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 ++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 npc/re/quests/skills/sage_skills.txt (limited to 'npc') 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; +} -- 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(-) (limited to 'npc') 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(-) (limited to 'npc') 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(-) (limited to 'npc') 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(-) (limited to 'npc') 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(-) (limited to 'npc') 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(-) (limited to 'npc') 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(-) (limited to 'npc') 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(-) (limited to 'npc') 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(-) (limited to 'npc') 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 (limited to 'npc') 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 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 (limited to 'npc') 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 11a90e148ed142c9bc39fc9e71ccc690b03fdb8f Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 30 May 2013 23:42:43 -0300 Subject: Mora / NPC Updates * Implemented all Mora quests (excluding instance-related quests and Mora Enchants). * Updated Mora town NPCs, Quiver Maker, and guides. * Updated Bifrost spawns and warps. All Credits to Euphy for sending those to us, Thank you~! Signed-off-by: shennetsind --- db/quest_db.txt | 12 +- npc/re/guides/guides_mora.txt | 215 ++ npc/re/merchants/quivers.txt | 121 + npc/re/mobs/fields/bifrost.txt | 25 +- npc/re/quests/quests_mora.txt | 5315 ++++++++++++++++++++++++++++++++++++++ npc/re/scripts.conf | 5 +- npc/re/warps/fields/bif_fild.txt | 42 +- src/common/mmo.h | 2 +- 8 files changed, 5711 insertions(+), 26 deletions(-) create mode 100644 npc/re/guides/guides_mora.txt create mode 100644 npc/re/merchants/quivers.txt create mode 100644 npc/re/quests/quests_mora.txt (limited to 'npc') diff --git a/db/quest_db.txt b/db/quest_db.txt index dc3b87d2d..298011a79 100644 --- a/db/quest_db.txt +++ b/db/quest_db.txt @@ -33,6 +33,7 @@ 1117,0,0,0,0,0,0,0,"Ropewa & Yuridi - Eternal Promise, Broken Ring" // Ropewa Clue Quest 1118,0,0,0,0,0,0,0,"Neighborhood Knight - I Need Clues" +1119,82800,0,0,0,0,0,0,"Neighborhood Knight - Cooldown" 1145,0,0,0,0,0,0,0,"Help the poor cat" 1146,0,0,0,0,0,0,0,"Help the poor cat" @@ -527,6 +528,11 @@ 5028,43200,0,0,0,0,0,0,"Inspection of the Sample" 5029,3600,0,0,0,0,0,0,"Unidentified Creature" +5030,0,0,0,0,0,0,0,"The creature's family" +5031,0,0,0,0,0,0,0,"The creature's family" +5032,0,0,0,0,0,0,0,"The creature's family" +5033,0,0,0,0,0,0,0,"The creature's family" +5034,0,0,0,0,0,0,0,"News from the family" 5035,0,0,0,0,0,0,0,"Help the old man!" 5036,0,0,0,0,0,0,0,"Help the old man!" 5037,0,0,0,0,0,0,0,"Help the old man!" @@ -854,7 +860,7 @@ // New Sapha's Honor Quest 7206,0,0,0,0,0,0,0,"New Day for Cheshire" 7207,0,0,0,0,0,0,0,"Cheshire's Box" -7208,82800,0,0,0,0,0,0,"Wait for Cheshire?" +7208,86400,0,0,0,0,0,0,"Wait for Cheshire?" // Misty Forest Labyrinth 7211,9000,0,0,0,0,0,0,"Misty Forest Labyrinth Exploration" @@ -1683,8 +1689,8 @@ //Mora Quests // == Roast Beef Quest -11182,180,0,0,0,0,0,0,"Teohre's Report" -11183,0,0,0,0,0,0,0,"Teohre's Favor" +11182,60,0,0,0,0,0,0,"Theore's Report" +11183,0,0,0,0,0,0,0,"Theore's Favor" // == Theo 11184,0,0,0,0,0,0,0,"Runaway Laphine" 11185,0,0,0,0,0,0,0,"Pouch" diff --git a/npc/re/guides/guides_mora.txt b/npc/re/guides/guides_mora.txt new file mode 100644 index 000000000..0cb0db35d --- /dev/null +++ b/npc/re/guides/guides_mora.txt @@ -0,0 +1,215 @@ +//===== rAthena Script ======================================= +//= Mora Guides +//===== By: ================================================== +//= Euphy +//===== Current Version: ===================================== +//= 1.0 +//===== Compatible With: ===================================== +//= rAthena SVN +//===== Description: ========================================= +//= Guides for the city of Mora. +//===== Additional Comments: ================================= +//= 1.0 First version. [Euphy] +//============================================================ + +mora,25,158,5 script Raffle Guide#north 516,{ + mes "[Raffoh]"; + mes "Laoh~!"; + mes "Welcome to the Village of Mora."; + mes "I can tell you whatever you want to know about the village~!"; + next; + switch(select("[ Inn ]:[ Residences ]:[ Stores ]:[ Warehouse ]:Remove markers from the mini-map:Quit")) { + case 1: + mes "[Raffoh]"; + mes "Laoh~!"; + mes "We have an inn but we can't make travelers sleep like Raffles..."; + mes "Get some rest!"; + viewpoint 1,44,134,0,0x0A82FF; + close; + case 2: + mes "[Raffoh]"; + mes "Laoh~!"; + mes "This is where Raffles' houses are..."; + mes "But keep the noise down because people are asleep~!"; + viewpoint 1,119,170,1,0xAAFF00; + close; + case 3: + mes "[Raffoh]"; + mes "Laoh~!"; + mes "If you are looking for souvenirs, you can buy some in this district."; + viewpoint 1,112,110,2,0xDA70D6; + close; + case 4: + mes "[Raffoh]"; + mes "Laoh~!"; + mes "This is where they keep all kinds of packages and groceries."; + mes "There are many things that don't belong to the Raffles, so be careful!"; + viewpoint 1,182,161,3,0xFF1493; + close; + case 5: + mes "[Raffoh]"; + mes "Laoh~! I'm removing them all~!"; + viewpoint 2,1,1,0,0xFFFF00; + viewpoint 2,1,1,1,0xFFFF00; + viewpoint 2,1,1,2,0xFFFF00; + viewpoint 2,1,1,3,0xFFFF00; + close; + case 6: + mes "[Raffoh]"; + mes "Laoh~!"; + mes "What kinds of sports are popular in your homeland?"; + close; + } +} + +mora,167,76,3 script Raffle Guide#east 522,{ + mes "[Raffuh]"; + mes "Uh..."; + mes "This, this is the Village of Mora."; + mes "Uh... which place do you want to know about?"; + next; + switch(select("[ Inn ]:[ Residences ]:[ Stores ]:[ Warehouse ]:Remove markers from the mini-map:Quit")) { + case 1: + mes "[Raffuh]"; + mes "Uh..."; + mes "Are, are you sleepy?"; + mes "You can sleep here uh!! Put your stuff down uh! And-- and---"; + viewpoint 1,44,134,0,0x0A82FF; + close; + case 2: + mes "[Raffuh]"; + mes "Uh..."; + mes "Why are you trying to find out where I live--?"; + mes "Uh, no... I'd like to live with my friends--"; + viewpoint 1,119,170,1,0xAAFF00; + close; + case 3: + mes "[Raffuh]"; + mes "Uh..."; + mes "There are a lot of things in those stores-- oh, there is a hot spring also uh!"; + viewpoint 1,112,110,2,0xDA70D6; + close; + case 4: + mes "[Raffuh]"; + mes "Uh..."; + mes "You can't just march into the warehouse, or you'll be in trouble--"; + mes "Many of the things there are from outside the village-- Raffuh has been in trouble several times--"; + viewpoint 1,182,161,3,0xFF1493; + close; + case 5: + mes "[Raffuh]"; + mes "Are you sure you want them removed?"; + viewpoint 2,1,1,0,0xFFFF00; + viewpoint 2,1,1,1,0xFFFF00; + viewpoint 2,1,1,2,0xFFFF00; + viewpoint 2,1,1,3,0xFFFF00; + close; + case 6: + mes "[Raffuh]"; + mes "Uh..."; + mes "Being a guide doesn't help much with my social phobia--"; + close; + } +} + +mora,115,138,5 script Raffle Guide#center 524,{ + mes "[Raffla]"; + mes "Lala!"; + mes "Welcome to the Village of Mora la!"; + mes "If you need to know anything about the village, just ask me la!"; + next; + switch(select("[ Inn ]:[ Residences ]:[ Stores ]:[ Warehouse ]:Remove markers from the mini-map:Quit.")) { + case 1: + mes "[Raffla]"; + mes "Lala!"; + mes "This is where travelers can rest la!"; + mes "The innkeeper is very kind, so try to talk to him a lot la!"; + viewpoint 1,44,134,0,0x0A82FF; + close; + case 2: + mes "[Raffla]"; + mes "Lala!"; + mes "This is where Raffles live la!"; + mes "Head over there la!"; + viewpoint 1,119,170,1,0xAAFF00; + close; + case 3: + mes "[Raffla]"; + mes "Lala!"; + mes "So you want to buy something la?"; + mes "There are a lot of stores and cafes, so check them out la!"; + viewpoint 1,112,110,2,0xDA70D6; + close; + case 4: + mes "[Raffla]"; + mes "Lala!"; + mes "The warehouse is where you keep your valuables la!"; + mes "Be careful so you don't get robbed la!"; + viewpoint 1,182,161,3,0xFF1493; + close; + case 5: + mes "[Raffla]"; + mes "Okay, I'll remove all the markers from the map la!"; + viewpoint 2,1,1,0,0xFFFF00; + viewpoint 2,1,1,1,0xFFFF00; + viewpoint 2,1,1,2,0xFFFF00; + viewpoint 2,1,1,3,0xFFFF00; + close; + case 6: + mes "[Raffla]"; + mes "Lala!"; + mes "I really don't know how my family ends up doing these things la!"; + close; + } +} + +mora,72,51,3 script Raffle Guide#south 518,{ + mes "[Raffli]"; + mes "Lali?"; + mes "Welcome to the Village of Mora."; + mes "If you need to know anything about the village, just ask me."; + next; + switch(select("[ Inn ]:[ Residences ]:[ Stores ]:[ Warehouse ]:Remove markers from the mini-map:Quit")) { + case 1: + mes "[Raffli]"; + mes "Lali?"; + mes "This is where travelers can rest."; + mes "The innkeeper is very kind, so get to know him."; + viewpoint 1,44,134,0,0x0A82FF; + close; + case 2: + mes "[Raffli]"; + mes "Lali?"; + mes "This is where Raffles live."; + mes "Are you coming to Raffli's house li? I'm so happy."; + viewpoint 1,119,170,1,0xAAFF00; + close; + case 3: + mes "[Raffli]"; + mes "Lali?"; + mes "There are a lot of things I want to buy."; + mes "You can find tons of places to eat and shop, and tons of things to buy."; + viewpoint 1,112,110,2,0xDA70D6; + close; + case 4: + mes "[Raffli]"; + mes "Lali?"; + mes "The warehouse is where you keep your valuables."; + mes "But don't get robbed."; + viewpoint 1,182,161,3,0xFF1493; + close; + case 5: + mes "[Raffli]"; + mes "I'll remove all the markers."; + viewpoint 2,1,1,0,0xFFFF00; + viewpoint 2,1,1,1,0xFFFF00; + viewpoint 2,1,1,2,0xFFFF00; + viewpoint 2,1,1,3,0xFFFF00; + close; + case 6: + mes "[Raffli]"; + mes "Lali?"; + mes "Brother seems to be upset today li. Did I do anything wrong?"; + close; + } +} diff --git a/npc/re/merchants/quivers.txt b/npc/re/merchants/quivers.txt new file mode 100644 index 000000000..45e44401a --- /dev/null +++ b/npc/re/merchants/quivers.txt @@ -0,0 +1,121 @@ +//===== rAthena Script ======================================= +//= Arrow Quivers +//===== By: ================================================== +//= Muad_Dib (Prometheus Project); L0ne_W0lf +//===== Current Version: ===================================== +//= 1.1 +//===== Compatible With: ===================================== +//= rAthena SVN +//===== Description: ========================================= +//= Turns arrows into Arrow Quivers. +// Breakdown of Subroutine "S_BuyQuiver" +// arg(0): Type of Arrow to be packaged (item ID). +// arg(1): How many of each 'getarg(0)' arrow per quiver. +// arg(2): The cost of making a 'getarg(0)' quiver. +// arg(3): The quiver given by the NPC (item ID). +//===== Additional Comments: ================================= +//= 1.0 Added Mora NPC. [Euphy] +//= 1.1 Updated to match the official scripts. [Euphy] +//============================================================ + +mora,106,117,3 script Quiver Maker#mora 516,{ + if (checkweight(1201,1) == 0) { + mes "[Quiver Maker]"; + mes "You have too many things with you."; + mes "Make some space in your inventory and come back. I'll tell you something interesting."; + close; + } + if (MaxWeight - Weight < 2000) { + mes "[Quiver Maker]"; + mes "You seem worn out with all that stuff."; + mes "Make some space in your inventory and come back. I'll tell you something interesting."; + close; + } + mes "[Quiver Maker]"; + mes "Mora villagers ask what good quivers are. They just don't know how the world works."; + mes "No wonder they don't know a thing about quivers - spreading jam over leaves all day long."; + next; + switch(select("Please make me a quiver.:What's a quiver?")) { + case 1: + mes "[Quiver Maker]"; + mes "At last someone appreciates a quiver!"; + mes "I can make Elven Quivers and Hunting Quivers."; + mes "Which do you need?"; + next; + switch(select("An Elven Quiver:A Hunting Quiver:I don't need a quiver.")) { + case 1: callsub S_BuyQuiver,1773,500,500,12575; //Arrow_Of_Elf_Cntr + case 2: callsub S_BuyQuiver,1774,500,500,12576; //Hunting_Arrow_Cntr + case 3: + mes "[Quiver Maker]"; + mes "You can buy arrows off the tool merchant next to me."; + close; + } + case 2: + mes "[Quiver Maker]"; + mes "An arrow may be thin and light, but carrying hundreds and thousands of arrows is like carrying a whole log."; + next; + mes "[Quiver Maker]"; + mes "But when you have quivers, you can put arrows in them and save weight and space."; + mes "If you're interested in one, I'll stitch one up for you."; + close; + } + end; + +S_BuyQuiver: + if (countitem(getarg(0)) < getarg(1)) { + mes "[Quiver Maker]"; + mes "Bring more than "+getarg(1)+" "+getitemname(getarg(0))+" and I'll make you a quiver."; + close; + } + mes "[Quiver Maker]"; + mes "Oh, I see you have "+getitemname(getarg(0))+" in your hand!"; + mes "Are you interested in using a quiver? It's really convenient!"; + mes "If you're interested, I can trade "+getarg(1)+" of those arrows for one of these quivers for ^FF3131"+getarg(2)+" zeny^000000."; + next; + switch(select("Trade all the arrows you have:Get only one quiver:Don't trade")) { + case 1: + set .@arrows, countitem(getarg(0)); + set .@quiver, .@arrows / getarg(1); + set .@arrows_used, .@quiver * getarg(1); + set .@arrow_zeny01, .@quiver * getarg(2); + mes "The number of arrows you have : ^3131FF"+.@arrows+"^000000"; + mes "The number of quivers available : ^3131FF"+.@quiver+"^000000"; + mes "Zeny needed for trade : ^3131FF"+.@arrow_zeny01+" zeny^000000"; + next; + mes "Trade?"; + next; + if(select("Trade:Don't trade") == 2) { + mes "[Quiver Maker]"; + mes "Hey, you don't doubt my skills, do you?"; + close; + } + break; + case 2: + set .@quiver, 1; + set .@arrows_used, getarg(1); + set .@arrow_zeny01, getarg(2); + set .@zeny_mes,1; + break; + case 3: + mes "[Quiver Maker]"; + mes "Hey, you don't doubt my skills, do you?"; + close; + } + if (Zeny < .@arrow_zeny01) { + mes "[Quiver Maker]"; + if (.@zeny_mes == 1) + mes "I said I'd accept human coins just for you, and you still don't want to spend the money?"; + else + mes "You really don't expect to get your hands on a masterpiece for nothing, do you?"; + close; + } + mes "[Quiver Maker]"; + mes "Hey, here you are."; + mes "There is ^3131FFsomething you need to know^000000 - try to remember it."; + mes "^FF0000You can't use quivers when your encumbrance is over 70%.^000000"; + mes "You'd better keep that in mind, or you might be in trouble later."; + set Zeny, Zeny-.@arrow_zeny01; + delitem getarg(0),.@arrows_used; + getitem getarg(3),.@quiver; + close; +} diff --git a/npc/re/mobs/fields/bifrost.txt b/npc/re/mobs/fields/bifrost.txt index b8c28bf49..04667acb0 100644 --- a/npc/re/mobs/fields/bifrost.txt +++ b/npc/re/mobs/fields/bifrost.txt @@ -9,27 +9,28 @@ //===== Additional Comments: ================================= //= 1.0 First Release //= 1.1 Added more accurate 1@mist monsters +//= 1.2 Renewal spawn update. [Euphy] //============================================================ //================================================== // bif_fild01 - Bifrost South //================================================== -bif_fild01,0,0,0,0 monster Luciola Vespa 1994,25,0,0,0 -bif_fild01,0,0,0,0 monster Cornus 1992,15,0,0,0 -bif_fild01,0,0,0,0 monster Pom Spider 2132,5,0,0,0 -bif_fild01,0,0,0,0 monster Angra Mantis 2133,5,0,0,0 -bif_fild01,0,0,0,0 monster Little Fatum 2136,30,0,0,0 -bif_fild01,0,0,0,0 monster Miming 2137,50,0,0,0 +bif_fild01,0,0,0,0 monster Luciola Vespa 1994,29,5000,0,0 +bif_fild01,0,0,0,0 monster Cornus 1992,17,5000,0,0 +bif_fild01,0,0,0,0 monster Miming 2137,58,5000,0,0 +bif_fild01,0,0,0,0 monster Little Fatum 2136,34,5000,0,0 +bif_fild01,0,0,0,0 monster Angra Mantis 2133,5,5000,0,0 +bif_fild01,0,0,0,0 monster Pom Spider 2132,5,5000,0,0 //================================================== // bif_fild02 - Bifrost North //================================================== -bif_fild02,0,0,0,0 monster Luciola Vespa 1994,25,0,0,0 -bif_fild02,0,0,0,0 monster Cornus 1992,15,0,0,0 -bif_fild02,0,0,0,0 monster Pom Spider 2132,5,0,0,0 -bif_fild02,0,0,0,0 monster Angra Mantis 2133,5,0,0,0 -bif_fild02,0,0,0,0 monster Little Fatum 2136,50,0,0,0 -bif_fild02,0,0,0,0 monster Miming 2137,30,0,0,0 +bif_fild02,0,0,0,0 monster Luciola Vespa 1994,27,5000,0,0 +bif_fild02,0,0,0,0 monster Cornus 1992,16,5000,0,0 +bif_fild02,0,0,0,0 monster Miming 2137,33,5000,0,0 +bif_fild02,0,0,0,0 monster Little Fatum 2136,55,5000,0,0 +bif_fild02,0,0,0,0 monster Angra Mantis 2133,5,5000,0,0 +bif_fild02,0,0,0,0 monster Pom Spider 2132,5,5000,0,0 //================================================== // 1@mist - Forest Maze of Mists diff --git a/npc/re/quests/quests_mora.txt b/npc/re/quests/quests_mora.txt new file mode 100644 index 000000000..f1d8e5784 --- /dev/null +++ b/npc/re/quests/quests_mora.txt @@ -0,0 +1,5315 @@ +//===== rAthena Script ======================================= +//= Mora Quest NPCs +//===== By: ================================================== +//= Euphy +//===== Current Version: ===================================== +//= 1.0 +//===== Compatible With: ===================================== +//= rAthena SVN +//===== Description: ========================================= +//= Quest NPCs related to Mora: +//== Theore's Request, Chesire's New Day, +//== Helping Lope and Euridi, Mora Daily Quests, +//== Find the Research Tools, Knights of the Neighborhood +//===== Additional Comments: ================================= +//= 0.1 NPCs are currently placeholders. [Euphy] +//= 1.0 Implemented all official quests. [Euphy] +//============================================================ + +// Theore's Request :: bs +//============================================================ +mid_camp,148,222,4 script Theore#ep14_1_bs 982,3,3,{ + if (BaseLevel < 100) { + mes "- A person with a white gown -"; + mes "- is pulling at his hair. -"; + close; + } + if (ep14_1_bs == 0) { + mes "[Theore]"; + mes "Aaaarrrggghh!!!"; + mes "Darn it!!!!"; + mes "I'm finished!!!"; + next; + mes "[Theore]"; + mes "How am I supposed to submit a report that's so bad!!! A 5-year-old could do better!!!"; + mes "Noooo!!!"; + set ep14_1_bs,1; + close; + } else if (ep14_1_bs == 1) { + mes "- A person with a white gown -"; + mes "- is pulling at his hair. -"; + next; + if(select("Try talking to him.:How noisy.") == 2) { + mes "[Theore]"; + mes "Oh, of course, I'm sorry."; + mes "I'll keep it down."; + close; + } + mes "["+strcharinfo(0)+"]"; + mes "Sir... Are you okay?"; + mes "You will lose all your hair like that."; + mes "Calm down."; + next; + mes "[Theore]"; + mes "Sob......."; + next; + mes "[Theore]"; + mes "......."; + next; + mes "[Theore]"; + mes "Odin!!!"; + mes "Freyja!!!!"; + mes "Sazarim!!!"; + mes "Thank you!!"; + mes "It's not all over!!"; + next; + mes "[Theore]"; + mes "There's always hope! I, Theore, will persevere and go on!!"; + next; + mes "[Theore]"; + mes "Dear Adventurer!!!"; + mes "No, no, dear Warrior!!!!"; + mes "Are you busy at the moment?"; + mes "If you spare me a little time, I will see to it that you're rewarded handsomely!"; + next; + switch(select("I'm busy.:Listen to him more.")) { + case 1: + mes "[Theore]"; + mes "......."; + mes "I see, I suppose it can't be helped."; + mes "I'll probably lose all my hair and be on the ad for hair growth solutions. But I won't hold it against you, Warrior."; + next; + mes "[Theore]"; + mes "Dear God! My luck ends here. *sob*"; + mes "Even though the world is turning its back on me, I won't blame anyone!!!"; + close; + case 2: + mes "[Theore]"; + mes "Ahhh!"; + mes "I feel like I was saved."; + mes "So the thing is......."; + next; + mes "[Theore]"; + mes "Oh! Oh dear!"; + mes "How rude of me, I haven't even introduced myself."; + mes "My name is Theore, and I work for 'Bazett Teablack's Institute of Culture of the Other World.' "; + next; + mes "[Theore]"; + mes "I'm currently working on researching Laphines in the Splendide Basecamp."; + mes "Might be because I've been working soooo hard, but these days the Laphines all run away as soon as they see me."; + next; + mes "[Theore]"; + mes "The deadline is approaching, and I still haven't figured out the most critical part. "; + mes "My professor will be very disappointed ......."; + next; + mes "[Theore]"; + mes "So won't you give me a hand?!"; + mes "Your help will be acknowledged fully - I will tell the professor myself!"; + next; + switch(select("Help.:Don't help.")) { + case 1: + mes "[Theore]"; + mes "Sob sob Warrior, you're the best!"; + mes "I will not forget this!!!"; + mes "I'm going to write about it in my diary!!"; + mes "And in the report!!!"; + mes "And in a letter I'm sending home!!"; + next; + mes "[Theore]"; + mes "I'll tell my buddies at the lab!!!"; + mes "I'll tell Lugen!!!"; + mes "I'll write it in the bulletin board!!!"; + mes "Let's see!!! Where else?"; + next; + mes "- The man seems to be in a manic state. -"; + mes "- Wait until he calms down -"; + mes "- and try speaking to him again. -"; + set ep14_1_bs,2; + setquest 11182; + close; + case 2: + mes "[Theore]"; + mes "......."; + mes "You bad person, making me all worked up."; + mes "*sob*"; + close; + } + } + } else if (ep14_1_bs == 2) { + if (checkquest(11182,PLAYTIME) < 2) { + mes "[Theore]"; + mes "......"; + switch(rand(1,4)) { + case 1: + mes "I must tell my next-door neighbor Pico!!!"; + mes "And Kachua!!!"; + break; + case 2: + mes "Tell the merchant across the street!!!"; + mes "And also tell the administrator!!!"; + break; + case 3: + mes "Tell Mr. Holgren!!!"; + mes "Write up a report for the King!!!"; + break; + case 4: + mes "Tell the people around here!!!"; + mes "Shout it out loud from the observatory so the whole world hears!!!"; + break; + } + next; + mes "- He is still manic. -"; + mes "- Wait until he calms down -"; + mes "- and try speaking to him again. -"; + close; + } + mes "[Theore]"; + mes "My apologies."; + mes "I got a little excited."; + mes "I do apologize."; + next; + mes "[Theore]"; + mes "I'm usually a calm and rational person, but it feels like I've been everywhere - heaven AND hell - today!"; + next; + mes "[Theore]"; + mes "To the point: what I would like to ask you is not a hard task."; + next; + mes "[Theore]"; + mes "As you probably know, the Laphines are at war with the Saphas."; + mes "Until recently, they attacked the Saphas mercilessly."; + next; + mes "[Theore]"; + mes "But lately, the frequency of attacks has decreased significantly."; + mes "I can't figure out why, they are single-minded creatures and it's not likely that they just took pity on the Saphas' situation."; + next; + mes "[Theore]"; + mes "Also, there are rumors of unarmed Laphines flying through the fields."; + next; + mes "[Theore]"; + mes "I have seen it once, but he ran away as soon as he spotted me and I didn't get a chance to ask him."; + mes "I'm sure that he went back to the village. But as desperately as I want to ask, I was banned from entering the Splendide Basecamp."; + next; + select("Banned?"); + mes "[Theore]"; + mes "Well..."; + mes "I got so excited after the professor assigned me to this research project......."; + mes "that I combed through Splendide night and day, and they finally kicked me out."; + mes "Ha ha ha!"; + next; + mes "[Theore]"; + mes "The Laphines may look cute, but they are combat specialists......."; + mes "So here I am, without the courage to sneak in, but with the report half-finished......."; + next; + mes "[Theore]"; + mes "Tell me, is there a life more unfortunate than mine?"; + mes "*chuckle*"; + next; + mes "[Theore]"; + mes "So Warrior, would you please find the Laphines who are coming to the Splendide field, and find out what they're up to?"; + next; + mes "[Theore]"; + mes "They may run away if you try to speak to them, so pay close attention when you find one."; + next; + mes "[Theore]"; + mes "The Laphines are such a rowdy crew, and it's very unsettling to see how quiet they've been - almost like a period of calm before a giant thunderstorm."; + set ep14_1_bs,3; + changequest 11182,11183; + close; + } else if (ep14_1_bs == 3) { + mes "[Theore]"; + mes "So Warrior, would you please find the Laphines who are coming to the Splendide field, and ask them what they're up to?"; + next; + mes "[Theore]"; + mes "They may run away if you try to speak to them, so pay close attention when you find one."; + next; + mes "[Theore]"; + mes "The Laphines are such a rowdy crew, and it's very unsettling to see how quiet they've been - almost like a period of calm before a giant thunderstorm."; + close; + } else if (ep14_1_bs < 10) { + if (ep14_1_bs2 == 0) { + mes "- He is in no state for conversations. You should take the pouch to Splendide and look for its owner. -"; + close; + } else if (ep14_1_bs2 < 4) { + mes "[Theore]"; + mes "Hmm...... They were rummaging through the bushes?"; + mes "Hmm... Hmm..."; + next; + mes "[Theore]"; + mes "They may have left a clue, can you please look around the area?"; + mes "If they were looking through the bushes, they may have been looking for something they've lost."; + mes "Or they may have left something behind."; + close; + } else if (ep14_1_bs2 < 7) { + if (countitem(6390) == 0) { + mes "[Theore]"; + mes "They may have left a clue, can you please look around the area?"; + mes "If they were looking through the bushes, they may have been looking for something they've lost."; + mes "Or they may have left something behind."; + close; + } + mes "[Theore]"; + mes "A pouch that a Laphine dropped as it fled?"; + mes "Hmm... Hmm... A soft leather pouch with a string made by soaking dried vines in oil.... too small for humans or Saphas to use..."; + next; + mes "[Theore]"; + mes "Could... Could it be??!!"; + mes "that object?!"; + mes "that I've only heard about, but never came across!!!"; + next; + mes "[Theore]"; + mes "In the ancient times, Laphines used to carry fairy dust - such as the flying dust, minimizing dust - in a small pouch like this."; + next; + mes "[Theore]"; + mes "They usually enjoy extravagant designs, but this 'fairy dust pouch' is something that they always carry around, and it is made simply without extravagant ornaments, keeping in line with tradition."; + next; + mes "[Theore]"; + mes "I'm not sure what it'll be like nowadays, but if this is the 'fairy dust pouch,' the owner should be anxious to find it."; + next; + mes "[Theore]"; + mes "We can't give it back for free though. In exchange for some information - that's a fair deal!"; + next; + mes "[Theore]"; + mes "And perhaps they won't be too upset if we look inside the pouch!"; + mes "Wooow!!"; + mes "I always believed when I was little that a fairy would come and sprinkle me with flying dust to make me fly!!!"; + next; + mes "- Before I can stop him, -"; + mes "- he opened the small pouch. -"; + next; + mes "[Theore]"; + mes "......."; + next; + mes "[Theore]"; + mes "Oh..."; + mes "Berries......and leaves?"; + mes "......."; + next; + mes "[Theore]"; + mes "......What about the flying dust?"; + mes "Noooo!"; + mes "My poor innocent imagination!!!!"; + next; + mes "- He is in no state for conversations. You should take the pouch to Splendide and look for its owner. -"; + set ep14_1_bs2, ep14_1_bs2+3; //4,5,6 -> 7,8,9 + changequest 11185,11186; + close; + } else { + mes "- He is in no state for conversations. You should take the pouch to Splendide and look for its owner. -"; + close; + } + } else if (ep14_1_bs < 18) { + mes "- He appears to be busy. You should finish the task at hand and come back. -"; + close; + } else if (ep14_1_bs == 18) { + mes "[Theore]"; + mes "At last, you're back!!!!"; + mes "How did the investigation go?!"; + next; + mes "[Theore]"; + mes "Wow!!!"; + mes "Incredible!!!!!!"; + mes "Unbelievable!!!"; + next; + mes "[Theore]"; + mes "The best!!!!"; + mes "This is surely enough to write an excellent report on!!"; + mes "All thanks to you, Warrior!!"; + next; + mes "[Theore]"; + mes "I'll never, EVER forget what you've done for me!"; + mes "No!!"; + mes "My grandchildren's grandchildren will remember!!!!"; + mes "*Sob*"; + next; + mes "[Theore]"; + mes "Then I'm off to put the finishing touches on the report!!!!!!!"; + mes "Oh yeah!!!!"; + set ep14_1_bs,19; + getexp 0,200000; + getitem 6380,5; //Mora_Coin + close; + } else if (ep14_1_bs > 18) { + mes "[Theore]"; + mes "I'll write the report with lightning speed!!!!!!!"; + mes "Oh yeah!!!!"; + close; + } + end; +OnTouch: + if (BaseLevel > 99) { + if (ep14_1_bs == 0) { + mes "[Theore]"; + mes "Aaaarrrggghh!!!"; + mes "Darn it!!!!"; + mes "I'm finished!!!"; + next; + mes "[Theore]"; + mes "How am I supposed to submit a report that's so bad!!! A 5-year-old could do better!!!"; + mes "Noooo!!!"; + set ep14_1_bs,1; + close; + } + } + end; +} + +- script #mora_bush -1,{ + if (ep14_1_bs != 3 || rand(5)) { + mes "- It's just an ordinary bush. -"; + close; + } + set .@i, atoi(charat(strnpcinfo(2),9)); + set .@rand, rand(1,3); + mes "[Unarmed Laphine]"; + mes "Aaaarrrrrggggghhhhh!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"; + donpcevent "Fairy#cmd"+.@i+.@rand+"::OnEnable"; + set ep14_1_bs, .@i+3; + set ep14_1_bs2, .@rand; + changequest 11183,11184; + next; + mes "- You try to talk to the Laphine, -"; + mes "- who is looking around the bushes, -"; + mes "- but it flew away -"; + mes "- while yelling fearfully. -"; + next; + mes "- What was the fairy doing? -"; + mes "- You decide to look around. -"; + donpcevent "Bush"+.@i+"Timer::OnEnable"; + close; +OnEnable: + enablenpc strnpcinfo(0); + donpcevent "Bush"+charat(strnpcinfo(2),9)+"Timer::OnDisable"; + end; +OnDisable: + disablenpc strnpcinfo(0); + end; +} + +- script #mora_pouch -1,{ + end; +OnTouch: + set .@i, atoi(charat(strnpcinfo(2),9)); + if (ep14_1_bs == .@i+3) { + if (countitem(6390) == 0) { + if (checkweight(1201,1) == 0) { + mes " - Hang on there !! -"; + mes " - You are carrying too many kinds of items - "; + mes " - to receive any more items. - "; + mes " - Please lighten your load - "; + mes " - and try again. - "; + close; + } + if (MaxWeight - Weight < 1000) { + mes " - Hang on there !! -"; + mes " - You are carrying too much weight - "; + mes " - Please lighten your load - "; + mes " - and try again. - "; + close; + } + mes "- Jumble Fumble -"; + mes "- Rustle Bustle -"; + next; + if (rand(1,5) == 4) { + mes "- You've found a Small pouch. -"; + if (ep14_1_bs2 > 0 && ep14_1_bs2 < 4) + set ep14_1_bs2, ep14_1_bs2+3; + changequest 11184,11185; + getitem 6390,1; //Small_Pocket + close; + } else { + mes "- You didn't find anything. -"; + close; + } + } + } + end; +} + +- script #mora_fairy -1,{ + end; +OnInit: + disablenpc strnpcinfo(0); + end; +OnEnable: + enablenpc strnpcinfo(0); + initnpctimer; + end; +OnDisable: + disablenpc strnpcinfo(0); + stopnpctimer; + end; +OnTimer5000: + donpcevent strnpcinfo(0)+"::OnDisable"; + stopnpctimer; + end; +} + +spl_fild02,79,104,0 duplicate(#mora_bush) Bush#ep14_1_bs1 111 +spl_fild02,79,104,0 duplicate(#mora_pouch) #ep14_1_bs1 139,2,2 +spl_fild02,79,104,6 duplicate(#mora_fairy) Fairy#cmd11 440 +spl_fild02,79,104,6 duplicate(#mora_fairy) Fairy#cmd12 445 +spl_fild02,79,104,6 duplicate(#mora_fairy) Fairy#cmd13 439 + +spl_fild02,103,344,0 duplicate(#mora_bush) Bush#ep14_1_bs2 111 +spl_fild02,103,344,0 duplicate(#mora_pouch) #ep14_1_bs2 139,2,2 +spl_fild02,103,344,6 duplicate(#mora_fairy) Fairy#cmd21 440 +spl_fild02,103,344,6 duplicate(#mora_fairy) Fairy#cmd22 445 +spl_fild02,103,344,6 duplicate(#mora_fairy) Fairy#cmd23 439 + +spl_fild02,261,323,0 duplicate(#mora_bush) Bush#ep14_1_bs3 111 +spl_fild02,261,323,0 duplicate(#mora_pouch) #ep14_1_bs3 139,2,2 +spl_fild02,261,323,6 duplicate(#mora_fairy) Fairy#cmd31 440 +spl_fild02,261,323,6 duplicate(#mora_fairy) Fairy#cmd32 445 +spl_fild02,261,323,6 duplicate(#mora_fairy) Fairy#cmd33 439 + +spl_fild02,137,305,0 duplicate(#mora_bush) Bush#ep14_1_bs4 111 +spl_fild02,137,305,0 duplicate(#mora_pouch) #ep14_1_bs4 139,2,2 +spl_fild02,137,305,6 duplicate(#mora_fairy) Fairy#cmd41 440 +spl_fild02,137,305,6 duplicate(#mora_fairy) Fairy#cmd42 445 +spl_fild02,137,305,6 duplicate(#mora_fairy) Fairy#cmd43 439 + +spl_fild02,23,196,0 duplicate(#mora_bush) Bush#ep14_1_bs5 111 +spl_fild02,23,196,0 duplicate(#mora_pouch) #ep14_1_bs5 139,2,2 +spl_fild02,23,196,6 duplicate(#mora_fairy) Fairy#cmd51 440 +spl_fild02,23,196,6 duplicate(#mora_fairy) Fairy#cmd52 445 +spl_fild02,23,196,6 duplicate(#mora_fairy) Fairy#cmd53 439 + +spl_fild02,186,260,0 duplicate(#mora_bush) Bush#ep14_1_bs6 111 +spl_fild02,186,260,0 duplicate(#mora_pouch) #ep14_1_bs6 139,2,2 +spl_fild02,186,260,6 duplicate(#mora_fairy) Fairy#cmd61 440 +spl_fild02,186,260,6 duplicate(#mora_fairy) Fairy#cmd62 445 +spl_fild02,186,260,6 duplicate(#mora_fairy) Fairy#cmd63 439 + +- script #mora_bush_timer -1,{ + end; +OnInit: + disablenpc strnpcinfo(0); + end; +OnEnable: + enablenpc strnpcinfo(0); + initnpctimer; + end; +OnDisable: + stopnpctimer; + disablenpc strnpcinfo(0); + end; +OnTimer1000: + donpcevent "Bush#ep14_1_bs"+charat(strnpcinfo(0),4)+"::OnDisable"; + end; +OnTimer600000: + donpcevent "Bush#ep14_1_bs"+charat(strnpcinfo(0),4)+"::OnEnable"; + donpcevent strnpcinfo(0)+"::OnDisable"; + end; +} +spl_fild02,180,1,0 duplicate(#mora_bush_timer) Bush1Timer 440 +spl_fild02,181,1,0 duplicate(#mora_bush_timer) Bush2Timer 440 +spl_fild02,182,1,0 duplicate(#mora_bush_timer) Bush3Timer 440 +spl_fild02,183,1,0 duplicate(#mora_bush_timer) Bush4Timer 440 +spl_fild02,184,1,0 duplicate(#mora_bush_timer) Bush5Timer 440 +spl_fild02,186,1,0 duplicate(#mora_bush_timer) Bush6Timer 440 + +/* +spl_fild02,187,1,0 script Field Bush Switch 440,{ + donpcevent "Bush#ep14_1_bs1::OnEnable"; + end; +} +*/ + +splendide,183,117,4 script Tired-looking Fairy 438,{ + if (!isequipped(2782)) { + mes "[Tired-looking Fairy]"; + mes "VeOsaRiveh No ModAsh"; + next; + mes "- You can't understand the fairy's words. -"; + mes "- You need something to help you interpret them. -"; + close; + } + if (ep14_1_bs < 4) { + mes "[Tired-looking Fairy]"; + mes "I'm tired, don't talk to me."; + close; + } else if (ep14_1_bs < 10) { + if (checkquest(11187) == -1) { + mes "[Tired-looking Fairy]"; + mes "I'm tired, don't talk to me."; + next; + select("Show the pouch."); + mes "[Tired-looking Fairy]"; + mes "Huh?!"; + mes "Where did you get this from?!"; + next; + select("I found it in the bushes."); + mes "[Tired-looking Fairy]"; + mes "It may not look like much, but it is an important object for us. I suppose I should say thanks."; + next; + mes "[Tired-looking Fairy]"; + mes "But it won't be easy to find its owner with just the pouch..."; + changequest 11186,11187; + next; + if(select("I think I saw a fairy that might be the owner.:I'll think about it.") == 2) { + mes "[Tired-looking Fairy]"; + mes "Then tell me if you remember anything."; + close; + } + } else if (checkquest(11187) == 2) { + mes "[Tired-looking Fairy]"; + mes "I hope you can find the owner."; + close; + } + mes "[Tired-looking Fairy]"; + mes "Do you remember how the fairy looked?"; + next; + + setarray .@Hair$[0],"blonde","grassy-green","woody-brown","sea-blue"; + setarray .@Skin$[0],"dark","light"; + setarray .@Clothing$[0],"snow-white","grape","sky-blue","grassy-green"; + setarray .@Wings$[0],"round","two pairs of","characteristic"; + + setarray .@i[1], + select("Blonde hair:Grassy-green hair:Woody-brown hair:Sea-blue hair"), + select("Dark-skinned:Light-skinned"), + select("Snow-white clothing:Grape clothing:Sky-blue clothing:Grassy-green clothing"), + select("Round wings:Two pairs of wings:Characteristic Wings"); + + set .@i[0], (1 << .@i[1]) | (1 << (.@i[2]+4)) | (1 << (.@i[3]+6)) | (1 << (.@i[4]+10)); + + mes "[Tired-looking Fairy]"; + mes "A "+.@Skin$[.@i[2]-1]+"-skinned fairy with "+.@Hair$[.@i[1]-1]+" hair and "+.@Wings$[.@i[4]-1]+" wings, dressed in "+.@Clothing$[.@i[3]-1]+" clothing......."; + switch(.@i[0]) { + case 4418: // Kusmi: blonde hair, light skin, grape clothing, two pairs of wings + mes "Hmm...... That must be Kusmi."; + next; + mes "[Tired-looking Fairy]"; + mes "Kusmi must be roaming the area southeast of the village."; + mes "Go see if she has lost her pouch."; + if (ep14_1_bs2 == 7) + set ep14_1_bs2,10; + close; + case 2212: // Theodore: grassy-green hair, dark skin, snow-white clothing, round wings + mes "Hmm......That must be Theodore."; + next; + mes "[Tired-looking Fairy]"; + mes "Theodore must be roaming the area northeast of the village."; + mes "Go see if he has lost his pouch."; + if (ep14_1_bs2 == 8) + set ep14_1_bs2,11; + close; + case 9264: // Pauchon: sea-blue hair, dark skin, grassy-green clothing, characteristic wings + mes "Hmm......That must be Pauchon."; + next; + mes "[Tired-looking Fairy]"; + mes "Pauchon must be roaming the area north of the village."; + mes "Go see if she has lost her pouch."; + if (ep14_1_bs2 == 9) + set ep14_1_bs2,12; + close; + default: + next; + mes "[Tired-looking Fairy]"; + mes "Hmm..."; + mes "I don't remember seeing such a fairy."; + mes "Are you sure you're not mistaken?"; + mes "Try to remember it again."; + close; + } + } + mes "[Tired-looking Fairy]"; + mes "What's up?"; + mes "Did you find the owner of the pouch?"; + close; +} + +splendide,119,138,4 script Kusmi#ep14_1_bs 440,{ + if (!isequipped(2782)) { + mes "[Kusmi]"; + mes "DimFusTal Mu Lars"; + mes "ModAnduLo"; + mes "Mod"; + mes "DorDuMe U NohLarsFulo Mu Fus"; + next; + mes "- You can't understand the fairy's words. -"; + mes "- You need something to help you interpret them. -"; + close; + } + if (ep14_1_bs > 3 && ep14_1_bs < 10) { + mes "[Kusmi]"; + mes "And who mayy you be?"; + next; + select("Show the pouch."); + if (countitem(6390) == 0) { + mes "[Kusmi]"; + mes "What is it that you want to show mee?"; + close; + } + if (ep14_1_bs2 == 10) { + mes "[Kusmi]"; + mes "Ahh!!"; + mes "My pouch!!!!!"; + mes "Thank you sirr!!!!!"; + mes "I've been looking for it all overr!"; + next; + select("Ask about the rumor."); + mes "[Kusmi]"; + mes "That's a difficult questionn!"; + mes "But you've returned my pouch, so I'll have to answerr......"; + next; + mes "[Kusmi]"; + mes "Promise me you won't tell anyonee!"; + mes "If you can promise, please talk to me againn."; + delitem 6390,1; //Small_Pocket + set ep14_1_bs,10; + changequest 11187,11188; + close; + } else { + mes "[Kusmi]"; + mes "Hmm I don't know who, but must be a slobb to be dropping his pouch like soo."; + mes "Huh? Mine??"; + mes "No, mine is right here safelyy?"; + next; + mes "[Kusmi]"; + mes "It's a precious object so I hope you'll find the owner itt."; + close; + } + } + if (ep14_1_bs2 == 10) { + if (ep14_1_bs == 10) { + mes "[Kusmi]"; + mes "You can't say this to anybody okayy~?"; + mes "Recently,"; + mes "the supplies from our the mainland have been cutt!"; + mes "Or rather, the supply route is being blocked and we can't get our suppliess?"; + next; + mes "[Kusmi]"; + mes "We need to find enough food before we run out of stored goods, that's why we've been rummaging the bushess."; + next; + mes "[Kusmi]"; + mes "But this cursed frozen land has no good foods."; + mes "We're barely keeping it green using magic, but it takes too much power to make fruit."; + next; + mes "[Kusmi]"; + mes "The energy spent in making food is probably twice as much as the energy gained from eatingg."; + mes "Those higher up don't want to admit it, but it's going to become a serious problem soonn."; + next; + mes "[Kusmi]"; + mes "We can't leave the battleground because we're in war, so we can't go checkk."; + mes "I am curiousss......."; + next; + mes "[Kusmi]"; + mes "Not just me, but many Laphines are worriedd."; + mes "Well that's the situation, so if you meet a Laphine in the bushes please don't talk to himm."; + mes "It's embarrassingg!!!"; + next; + mes "[Kusmi]"; + mes "Oh, and you must never ever tell anyone about what happened todayy!"; + mes "Unless that person wanted to help uss... spreading the word won't do Splendide any goood."; + set ep14_1_bs,11; + completequest 11188; + setquest 11189; + close; + } else if (ep14_1_bs == 11) { + mes "[Kusmi]"; + mes "Eh?"; + mes "You stilll want to talk?"; + next; + select("Supply route from the mainland?"); + mes "[Kusmi]"; + mes "Well if you hear that you'll have to helpp!"; + mes "Still want to knoww?!"; + next; + switch(select("Yes.:No.")) { + case 1: + mes "[Kusmi]"; + mes "It's not a special road or anythingg."; + mes "Just an old roadd."; + mes "Some say it connects different continents. It also connects the Splendide Basecamp and Alfheim through the backk."; + next; + mes "[Kusmi]"; + mes "If you're headed that way, please go see that all's okayy."; + set ep14_1_bs,12; + changequest 11189,11190; + close; + case 2: + mes "[Kusmi]"; + mes "Thank you for finding my pouchh."; + mes "I would give you some fairy dust, but there is none leftt."; + close; + } + } else if (ep14_1_bs == 12) { + mes "[Kusmi]"; + mes "It's not a special road or anythingg."; + mes "Just an old roadd."; + mes "Some say it connects different continents. It also connects the Splendide Basecamp and Alfheim through the backk."; + next; + mes "[Kusmi]"; + mes "If you're headed that way, please go see that all's okayy."; + close; + } else if (ep14_1_bs == 13) { + mes "[Kusmi]"; + mes "A crevicee?"; + mes "That's why we couldn't contact the mainland."; + mes "Urggg......."; + mes "It would be good to know what's going on up theree."; + next; + mes "[Kusmi]"; + mes "If you happen to go through Bifrost, please figure out what's going onn."; + mes "In the middle of Bifrost is a small village called 'Mora.' All the supplies from the mainland come through that villagee."; + next; + mes "[Kusmi]"; + mes "If you go to the warehouse in Mora Village, the manager will tell you moree."; + mes "Also, on the way back, will you check to see that my friend Rondo is in Mora Villagee?"; + next; + mes "[Kusmi]"; + mes "He always used to visit Splendide around this time, but the situation is no good now. I'll have to tell him to come another time."; + set ep14_1_bs,14; + changequest 11191,11192; + close; + } else if (ep14_1_bs == 14) { + mes "[Kusmi]"; + mes "If you happen to go through Bifrost, please figure out what's going onn."; + mes "In the middle of Bifrost is a small village called 'Mora.' All the supplies from the mainland come through that villagee."; + next; + mes "[Kusmi]"; + mes "If you go to the warehouse in Mora Village, the manager will tell you moree."; + if (checkquest(11193) > -1 && checkquest(11193) < 2) + close; + mes "Also, on the way back, will you check to see that my friend Rondo is in Mora Villagee?"; + next; + mes "[Kusmi]"; + mes "He always used to visit Splendide around this time, but the situation is no good now. I'll have to tell him to come another time."; + close; + } else if (ep14_1_bs > 14) { + if (checkquest(11193) == -1) { + mes "[Kusmi]"; + mes "Will you check to see that my friend Rondo is in Mora Villagee?"; + next; + mes "[Kusmi]"; + mes "He always used to visit Splendide around this time, but the situation is no good now. I'll have to tell him to come another time."; + close; + } + mes "[Kusmi]"; + mes "Heee!"; + mes "You really went through the fog of the Maze of the Hazy Forest?"; + mes "Wow!!!"; + mes "That's very impressivee."; + next; + mes "[Kusmi]"; + mes "Thank you soooo much."; + mes "I hope we'll be able to go through Bifrost againn."; + mes "I want to meet Rondo and talk to him againn."; + if (ep14_1_bs == 17) { + next; + mes "[Kusmi]"; + mes "Oh, And Daphrer is in northwest Splendide."; + } + if (checkquest(11193) < 2) { + completequest 11192; + completequest 11193; + } + close; + } + } + mes "[Kusmi]"; + mes "This place is always coldd."; + mes "So different from my heavenly hometownn."; + close; +} + +splendide,304,295,4 script Theodore#ep14_1_bs 445,{ + if (!isequipped(2782)) { + mes "[Theodore]"; + mes "DimFusTal Mu Lars"; + mes "ModAnduLo"; + mes "Mod"; + mes "DorDuMe U NohLarsFulo Mu Fus"; + next; + mes "- You can't understand the fairy's words. -"; + mes "- You need something to help you interpret them. -"; + close; + } + if (ep14_1_bs > 3 && ep14_1_bs < 10) { + mes "[Theodore]"; + mes "Who are you!"; + next; + select("Show the pouch."); + if (countitem(6390) == 0) { + mes "[Theodore]"; + mes "Hmm? What do you mean?"; + close; + } + if (ep14_1_bs2 == 11) { + mes "[Theodore]"; + mes "Ahh!!"; + mes "My pouch!!!!!"; + mes "I've been looking for it all over the place."; + mes "Thanks!"; + next; + select("Ask about the rumor."); + mes "[Theodore]"; + mes "Hrm!!"; + mes "What a penetrating question!"; + next; + mes "[Theodore]"; + mes "If you really want to hear the answer, talk to me again."; + mes "I need time to think."; + delitem 6390,1; //Small_Pocket + set ep14_1_bs,10; + changequest 11187,11194; + close; + } else { + mes "[Theodore]"; + mes "What is that dirty pouch!"; + mes "It is definitely not mine."; + next; + mes "[Theodore]"; + mes "But I hope you find its rightful owner."; + close; + } + } + if (ep14_1_bs2 == 11) { + if (ep14_1_bs == 10) { + mes "[Theodore]"; + mes "You are not to tell anyone what I'm about to tell you."; + next; + mes "[Theodore]"; + mes "Recently, there's a big problem in Splendide."; + mes "There is no communication with the mainland."; + mes "Not just communication, but supplies have been cut off also. People act indifferent but actually there is deep panic."; + next; + mes "[Theodore]"; + mes "This frozen land is no use for collecting food, but to farm it would be too much work."; + next; + mes "[Theodore]"; + mes "In fact, just maintaining the green is costing an incredible amount of magic power."; + mes "No word has come from higher up, but from the rumors it's not an easily fixable problem."; + next; + mes "[Theodore]"; + mes "And because there is no easy fix, everybody is worried sick."; + mes "By military law, our soldiers cannot leave the battlefield during war, so it's impossible to get more information."; + next; + mes "[Theodore]"; + mes "Therefore, if you happen to run into a Laphine, please don't mention any of this."; + mes "Everybody is trying as hard as they can, but we are still a proud race."; + next; + mes "[Theodore]"; + mes "And as I said before, what I told you is a secret and you must not tell anyone."; + mes "We do need help, but we are cornered and we don't want others to know."; + set ep14_1_bs,11; + completequest 11194; + setquest 11195; + close; + } else if (ep14_1_bs == 11) { + mes "[Theodore]"; + mes "You have further business with me?"; + next; + select("Supply route from the mainland?"); + mes "[Theodore]"; + mes "Hmm... if you hear that, you might just have to help us out?"; + mes "Do you still want to know?"; + next; + switch(select("Yes.:No.")) { + case 1: + mes "[Theodore]"; + mes "The supply route comes through Bifrost, and you can get to it from the back of the Splendide Basecamp."; + mes "That is why we set up the basecamp here."; + mes "The origin of the route is unclear, but it has been known for a long time to be a bridge that connects continents."; + next; + mes "[Theodore]"; + mes "If you happen to venture there, please ask a guard what things are like there."; + set ep14_1_bs,12; + changequest 11195,11196; + close; + case 2: + mes "[Theodore]"; + mes "Thank you for getting the pouch back to me."; + mes "Fairy dust? I don't carry around such a thing."; + close; + } + } else if (ep14_1_bs == 12) { + mes "[Theodore]"; + mes "The supply route comes through Bifrost, and you can get to it from the back of the Splendide Basecamp."; + mes "That is why we set up the basecamp here."; + mes "The origin of the route is unclear, but it has been known for a long time to be a bridge that connects continents."; + next; + mes "[Theodore]"; + mes "If you happen to venture there, please ask a guard what things are like there."; + close; + } else if (ep14_1_bs == 13) { + mes "[Theodore]"; + mes "A crevice?"; + mes "So that was why we couldn't reach the mainland."; + mes "It would be good to know what's going on up there."; + next; + mes "[Theodore]"; + mes "Hmm..."; + mes "I can't leave here, but you would be able to, no?"; + mes "The supplies from the mainland come through 'Mora' Village, which is located in the middle of Bifrost."; + next; + mes "[Theodore]"; + mes "If you speak to the Warehouse Manager of Mora Village, you'd be able to get more information."; + mes "If you're willing, will you go to Bifrost's 'Mora' Village and meet the Warehouse Manager?"; + next; + mes "[Theodore]"; + mes "And if it's not too much trouble, you could drop by my friend Lilitia's also..."; + set ep14_1_bs,14; + changequest 11197,11198; + close; + } else if (ep14_1_bs == 14) { + mes "[Theodore]"; + mes "If you speak to the Warehouse Manager of Mora Village, you'd be able to get more information."; + mes "If you're willing, will you go to Bifrost's 'Mora' Village and meet the Warehouse Manager?"; + if (checkquest(11199) > -1 && checkquest(11199) < 2) + close; + next; + mes "[Theodore]"; + mes "And if it's not too much trouble, you could drop by my friend Lilitia's also..."; + close; + } else if (ep14_1_bs > 14) { + if (checkquest(11199) == -1) { + mes "[Theodore]"; + mes "And if it's not too much trouble, you could drop by my friend Lilitia's also..."; + close; + } + mes "[Theodore]"; + mes "Wow!!!"; + mes "So you went through the Maze of the Hazy Forest and returned from Mora Village."; + mes "I made the right decision by asking you!"; + next; + mes "[Theodore]"; + mes "Thank you."; + mes "I hope this gets resolved soon..."; + mes "I don't want to further upset Lilitia..."; + if (ep14_1_bs == 17) { + next; + mes "[Theodore]"; + mes "Oh, And Daphrer is in northwest Splendide."; + } + if (checkquest(11199) < 2) { + completequest 11198; + completequest 11199; + } + close; + } + } + mes "[Theodore]"; + mes "Sometimes, I sense a painful beauty in this frozen earth, quite different from the beauty of my hometown."; + mes "But this is a difficult environment for us to live in, certainly."; + close; +} + +splendide,168,301,4 script Pauchon#ep14_1_bs 439,{ + if (!isequipped(2782)) { + mes "[Pauchon]"; + mes "DimFusTal Mu Lars"; + mes "ModAnduLo"; + mes "Mod"; + mes "DorDuMe U NohLarsFulo Mu Fus"; + next; + mes "- You can't understand the fairy's words. -"; + mes "- You need something to help you interpret them. -"; + close; + } + if (ep14_1_bs > 3 && ep14_1_bs < 10) { + mes "[Pauchon]"; + mes "What can I do for you, sir?"; + next; + select("Show the pouch."); + if (countitem(6390) == 0) { + mes "[Pauchon]"; + mes "Huh? Do you see something?"; + mes "I don't see anything..."; + close; + } + if (ep14_1_bs2 == 12) { + mes "[Pauchon]"; + mes "Good heavens...!"; + mes "I think this is mine!"; + mes "Thank you."; + mes "I've been worried since I lost it, you lifted a burden off of my mind."; + next; + select("Ask about the rumor."); + mes "[Pauchon]"; + mes "That's not easy for me to answer..."; + mes "I do appreciate you finding my pouch.... Hmm..."; + mes "Please give me some time to think.."; + delitem 6390,1; //Small_Pocket + set ep14_1_bs,10; + changequest 11187,11200; + close; + } else { + mes "[Pauchon]"; + mes "Oh dear. It's not mine."; + mes "But to carelessly drop such an important object!"; + mes "I don't know who it is, but that Laphine needs a lesson!"; + close; + } + } + if (ep14_1_bs2 == 12) { + if (ep14_1_bs == 10) { + mes "[Pauchon]"; + mes "What I'm about to tell you is top secret!"; + mes "We don't even talk about it amongst ourselves!"; + mes "How would we say that the supply from the mainland's been cut off like that!"; + next; + mes "[Pauchon]"; + mes "Ugh?!"; + mes "Oh boy... I've done it...."; + mes "It's really a top secret!!"; + mes "Don't tell anybody!"; + next; + mes "[Pauchon]"; + mes "Well since I spilled the beans already... oh well, too late."; + mes "So it's been a while since we received supplies from the mainland."; + next; + mes "[Pauchon]"; + mes "We're not starving, but we're receiving less and less food."; + mes "I was hungry so I went to go pick fruit, but in this cold climate there are no fruit trees."; + next; + mes "[Pauchon]"; + mes "And the people higher up only tell us to wait... I'm so tired of waiting!"; + mes "But the instant I leave this place, I'll end up going to prison...."; + next; + mes "[Pauchon]"; + mes "So I'm stuck here, and I'll be stuck here, suffering from hunger.... *sob*"; + next; + mes "[Pauchon]"; + mes "I'd eat the bark off of that tree if I could."; + mes "If only somebody could help. *sob*"; + set ep14_1_bs,11; + completequest 11200; + setquest 11201; + close; + } else if (ep14_1_bs == 11) { + mes "[Pauchon]"; + mes "What?"; + mes "What do you want... I'm hungry, don't have energy to talk..."; + next; + select("Supply route from the mainland?"); + mes "[Pauchon]"; + mes "Are you going to help me if I tell you?"; + mes "If not, I won't tell."; + next; + switch(select("Yes.:No.")) { + case 1: + mes "[Pauchon]"; + mes "A giant road leads away from the back of Splendide."; + mes "I don't know if it's related to legends and what not, but I've heard that the road's been there forever."; + next; + mes "[Pauchon]"; + mes "Oh! The guard there might know something."; + mes "If you're headed that way, please go find out what's up."; + set ep14_1_bs,12; + changequest 11201,11202; + close; + case 2: + mes "[Pauchon]"; + mes "Thank you for finding the pouch."; + mes "Ugh... I'm starving... I suppose I'll have to eat these bitter berries..."; + close; + } + } else if (ep14_1_bs == 12) { + mes "[Pauchon]"; + mes "A giant road leads away from the back of Splendide."; + mes "I don't know if it's related to legends and what not, but I've heard that the road's been there forever."; + next; + mes "[Pauchon]"; + mes "Oh! The guard there might know something."; + mes "If you're headed that way, please go find out what's up."; + close; + } else if (ep14_1_bs == 13) { + mes "[Pauchon]"; + mes "Crevice?!?"; + mes "Hmm I have heard that crevices are creeping up here and there, but it even infiltrated Bifrost...."; + mes "It appears to be more serious than I had imagined."; + next; + mes "[Pauchon]"; + mes "If you can, would you go to 'Mora' Village in Bifrost and figure out what's going on?"; + next; + mes "[Pauchon]"; + mes "The supplies from the mainland come through the Village. If you go speak to the Warehouse Manager, he'll be able to tell you something."; + mes "Also, please pay a visit to my friend Humming."; + next; + mes "[Pauchon]"; + mes "He's such a flighty guy, might have already left, but we were supposed to meet up in Mora Village."; + set ep14_1_bs,14; + changequest 11203,11204; + close; + } else if (ep14_1_bs == 14) { + mes "[Pauchon]"; + mes "If you can, would you go to 'Mora' Village in Bifrost and figure out what's going on?"; + next; + mes "[Pauchon]"; + mes "The supplies from the mainland come through the Village. If you go speak to the Warehouse Manager, he'll be able to tell you something."; + if (checkquest(11205) > -1 && checkquest(11205) < 2) + close; + mes "Also, please pay a visit to my friend Humming."; + next; + mes "[Pauchon]"; + mes "He's such a flighty guy, might have already left, but we were supposed to meet up in Mora Village."; + close; + } else if (ep14_1_bs > 14) { + if (checkquest(11205) == -1) { + mes "[Pauchon]"; + mes "Please pay a visit to my friend Humming."; + mes "He's such a flighty guy, might have already left, but we were supposed to meet up in Mora Village."; + close; + } + mes "[Pauchon]"; + mes "I had my doubts...But you really did cross the legendary Maze of the Hazy Forest..."; + mes "I'm very impressed."; + next; + mes "[Pauchon]"; + mes "I really appreciate your help."; + mes "I hope this gets resolved soon."; + mes "What I'm really afraid of... is hunger. More than war."; + if (ep14_1_bs == 17) { + next; + mes "[Pauchon]"; + mes "Oh, And Daphrer is in northwest Splendide."; + } + if (checkquest(11205) < 2) { + completequest 11204; + completequest 11205; + } + close; + } + } + mes "[Pauchon]"; + mes "Ah... I'm hungry."; + mes "When I get back to the mainland I'm going to stuff my belly until it bursts."; + close; +} + +splendide,262,376,4 script Laphine Soldier#ep14_1 447,{ + if (!isequipped(2782)) { + mes "[Laphine Soldier]"; + mes "DielFarmar Di RiniIyazser Ha mahAgolAsh U U "; + mes "TurNohnar Di DurNeiFar Ra AnuVerNoth Ha AshRivehDor Ha BurWehLars Ur RinimanMod"; + next; + mes "- You can't understand the fairy's words. -"; + mes "- You need something to help you interpret them. -"; + close; + } + mes "[Laphine Soldier]"; + mes "This is Bifrost, which leads to Alfheim."; + mes "Please note that entry is forbidden due to a crevice caused by an unidentified source."; + if (ep14_1_bs != 12) + close; + next; + mes "[Laphine Soldier]"; + mes "The other way leads to the Maze of the Hazy Forest."; + next; + mes "[Laphine Soldier]"; + mes "You can get to Alfheim by making it through the Maze of the Hazy Forest. However, nobody has ever come back from the Maze of the Hazy Forest."; + if (checkquest(11190) > -1 && checkquest(11190) < 2) { + set ep14_1_bs,13; + changequest 11190,11191; + } else if (checkquest(11196) > -1 && checkquest(11196) < 2) { + set ep14_1_bs,13; + changequest 11196,11197; + } else if (checkquest(11202) > -1 && checkquest(11202) < 2) { + set ep14_1_bs,13; + changequest 11202,11203; + } + close; +} + +mora,185,163,2 script Warehouse Manager#ep14_1 516,{ + if (ep14_1_bs < 15) { + mes "[Warehouse Manager]"; + mes "No, sir!"; + mes "You cannot enter at will."; + mes "This is a warehouse. If you need something, please ask the staff outside."; + if (ep14_1_bs < 14) + close; + next; + select("Supplies for Laphine?"); + mes "[Warehouse Manager]"; + mes "Ah!"; + mes "You're from Splendide?"; + mes "Let's see..."; + mes "All the supplies from over there to there are destined for Splendide."; + next; + mes "[Warehouse Manager]"; + mes "We are quite worried too because the crevice in Bifrost has made it impossible to deliver these goods."; + next; + mes "[Warehouse Manager]"; + mes "And the travelers who were heading down are also stuck here. The increasing number of customers is both a blessing and a curse.."; + next; + mes "[Warehouse Manager]"; + mes "If you plan to go back to Splendide, pay a visit to Jones at the Inn."; + mes "He has something that needs to be urgently delivered to the army of Splendide."; + set ep14_1_bs,15; + setquest 11206; + close; + } else if (ep14_1_bs == 15) { + mes "[Warehouse Manager]"; + mes "If you plan to go back to Splendide, pay a visit to Jones at the Inn."; + mes "He has something that needs to be urgently delivered to the army of Splendide."; + close; + } else { + mes "[Warehouse Manager]"; + mes "We are quite worried too because the crevice in Bifrost has made it impossible to deliver these goods."; + next; + mes "[Warehouse Manager]"; + mes "And the travelers who were heading down are also stuck here. The increasing number of customers is both a blessing and a curse..."; + close; + } + end; +} + +mora,35,119,4 script Rondo#ep14_1_bs 513,{ + mes "[Rondo]"; + mes "Mora is such a mysterious place."; + mes "You can understand any language."; + next; + mes "[Rondo]"; + mes "Of course, when we leave this area I won't be able to understand what you say, but I'll be able to remember the conversations we had. And I'll look forward to the day we meet again, here."; + if (ep14_1_bs > 13 && ep14_1_bs2 == 10) { + next; + mes "[Rondo]"; + mes "Please tell Kusmi"; + mes "that if he wants to meet, we can meet any time. There is nothing to worry about."; + if (checkquest(11193) == -1) + setquest 11193; + } + close; +} + +mora,98,66,4 script Lilitia#ep14_1_bs 518,{ + if (ep14_1_bs > 13 && ep14_1_bs2 == 11) { + mes "[Lilitia]"; + mes "Boo!!!"; + mes "He broke his promise again!!!"; + next; + mes "[Lilitia]"; + mes "He said he'd be here this time for sure!!!"; + mes "That place is too cold for me to visit!!!!!"; + mes "My precious leaves will wither there."; + next; + mes "[Lilitia]"; + mes "What? Theodore sent you?"; + mes "Please tell him that I'm so mad!!"; + if (checkquest(11199) == -1) + setquest 11199; + close; + } + mes "[Lilitia]"; + mes "I really hate the cold."; + mes "That's why Mora is a lovely place to live."; + next; + mes "[Lilitia]"; + mes "The leaves are always fresh here. And, the stress about languages just disappears."; + close; +} + +mora,139,102,2 script Humming#ep14_1_bs 515,{ + if (ep14_1_bs > 13 && ep14_1_bs2 == 12) { + mes "[Humming]"; + mes "Oh!"; + mes "You're here because Pauchon sent you?"; + next; + mes "[Humming]"; + mes "It must've been hard for you to get here. I'm impressed."; + mes "The Maze of the Hazy Forest~ It fuels my adventurous spirit!"; + next; + mes "[Humming]"; + mes "If you reach Splendide before me, please tell Pauchon"; + mes "that I'm going through the Maze of the Hazy Forest."; + if (checkquest(11205) == -1) + setquest 11205; + close; + } + mes "[Humming]"; + mes "I heard that a crevice crept in between Jotunheim and Midgard, so I wanted to check it out. But I got stuck here."; + mes "I was looking forward to seeing a new place."; + next; + mes "[Humming]"; + mes "Are you from Midgard?"; + mes "What is it like there?"; + mes "I've always wanted to see a creature called Poring."; + close; +} + +mora,55,124,2 script Jones#ep14_1_bs 495,{ + if (ep14_1_bs < 15) { + mes "[Jones]"; + mes "Oh.... Darn......."; + mes "I can't go down, and I can't go back. My credibility that I've worked so hard on is just crumbling into dust."; + close; + } else if (ep14_1_bs == 15) { + mes "[Jones]"; + mes "Ah, are you the traveler who came through the Maze of the Hazy Forest from Splendide?"; + mes "If you plan to go back, can you please deliver this to the Splendide army?"; + next; + mes "[Jones]"; + mes "A person high up requested it, but I can't cross Bifrost."; + next; + mes "[Jones]"; + mes "Deliveries to other places have all stopped also. Ah, my credibility is suffering...."; + next; + switch(select("Yes.:No.")) { + case 1: + mes "[Jones]"; + mes "Thank you."; + set ep14_1_bs,16; + changequest 11206,11207; + close; + case 2: + mes "[Jones]"; + mes "I'm a bit embarrassed to ask this of a stranger...... Ha ha!"; + close; + } + } else if (ep14_1_bs == 16) { + if (checkweight(1201,1) == 0) { + mes "[Jones]"; + mes "You have too many kinds of items. Please lighten your load and come back."; + close; + } + if (MaxWeight - Weight < 3500) { + mes "[Jones]"; + mes "You are carrying too much weight. Please lighten your load and come back."; + close; + } + mes "[Jones]"; + mes "Please take good care of it."; + mes "It's for Daphrer in Splendide."; + set ep14_1_bs,17; + getitem 6391,1; //Splendid_Supply_Kit + changequest 11207,11208; + close; + } else if (ep14_1_bs == 17) { + mes "[Jones]"; + mes "Please take good care of it."; + mes "It's for Daphrer in Splendide."; + close; + } else if (ep14_1_bs > 17) { + mes "[Jones]"; + mes "Thanks to you, the job is well done."; + mes "Hehe, I see potential in you as a delivery man."; + mes "Interested in the career of delivery?"; + close; + } else { + mes "[Jones]"; + mes "Hehe, I see potential in you as a delivery man."; + mes "Interested in the career of delivery?"; + close; + } + end; +} + +splendide,121,260,4 script Daphrer#ep14_1_bs 435,{ + if (!isequipped(2782)) { + mes "[Daphrer]"; + mes "DRHSfhsdfGSDH FGkkmvoifk DFG DFHshfeksmn fgg FDbbd fjnnvk n skncki dfgd F FHdfkdfjkmv"; + close; + } + if (countitem(6391)) { + mes "[Daphrer]"; + mes "Oh...."; + mes "I've been waiting for you."; + next; + mes "[Daphrer]"; + mes "This was urgently needed so thank you for bringing it here, I hope I haven't caused you too much trouble.."; + next; + mes "[Daphrer]"; + mes "This is probably too small to be a reward, but please accept this as a sign of my gratitude."; + delitem 6391,1; //Splendid_Supply_Kit + if (ep14_1_bs == 17) { + set ep14_1_bs,18; + completequest 11208; + getexp 0,500000; + getitem 6380,5; //Mora_Coin + } else + getitem 6380,2; //Mora_Coin + close; + } + if (ep14_1_bs == 17) { + mes "[Daphrer]"; + mes "Oh...."; + mes "So you lost the item on the way."; + next; + mes "[Daphrer]"; + mes "I knew that it was probably a stretch......"; + mes "Perhaps I've been unrealistic."; + mes "But I thank you for your trouble anyway. Please accept this as a sign of my gratitude."; + set ep14_1_bs,18; + completequest 11208; + getexp 0,200000; + getitem 6380,2; //Mora_Coin + close; + } + mes "[Daphrer]"; + mes "For me, a drop of water to make a flower blossom is more important than a sword for war."; + close; +} + +// Chesire's New Day :: cheshir2 +//============================================================ +dic_in01,262,191,0 script #ep14_1_xq02 139,0,3,{ + end; +OnTouch: + if (ep13_3_secret > 22 && checkquest(7206) == -1) { + enablenpc "Cheshire#ep14_1_xq01"; + cutin "ep13_cheshire_h",1; + mes "[Cheshire]"; + mes "Oh, wait!"; + mes "There's another thing I'd like you to do."; + mes "There's not enough time to go into details..."; + next; + mes "- Cheshire glanced at the guard standing close to you, and leaned close and whispered into your ear.-"; + next; + mes "[Cheshire]"; + mes "You'll find cat caravans in the middle of ^4d4dffKamidal Tunnel^000000."; + mes "There is ^4d4dffa marked box among the caravans' goods to the west of the entrance to the Scaraba Hole^000000."; + next; + mes "[Cheshire]"; + mes "I'd like you to bring it to me."; + mes "You'll see where you should bring it by looking at the box."; + mes "This is an important matter."; + next; + mes "[Cheshire]"; + mes "I have something to get done in advance..."; + mes "Good luck!"; + setquest 7206; + close2; + disablenpc "Cheshire#ep14_1_xq01"; + cutin "",255; + } + end; +} + +dic_in01,260,194,4 script Cheshire#ep14_1_xq01 498,{ + end; +OnInit: + disablenpc "Cheshire#ep14_1_xq01"; + end; +} + +dic_dun01,274,114,0 script Stacked Boxes of Goods 844,{ + if (checkweight(1201,1) == 0 || MaxWeight - Weight < 1000) { + mes "- You have too many items to do this quest. -"; + close; + } + set .@playtime, checkquest(7208,PLAYTIME); + if (.@playtime == 0 || .@playtime == 1) { + mes "Boxes with all kinds of goods in them are stacked to the ceiling."; + mes "The marked box Cheshire was talking about doesn't seem to be here yet."; + close; + } else if (.@playtime == 2) { + mes "Boxes with all kinds of goods in them are stacked to the ceiling."; + mes "Looking closely, you find a box with a small piece of paper stuck to it."; + mes "You've found the box of goods Cheshire was talking about."; + next; + switch(select("Move the box.:Give up.")) { + case 1: + mes "You promised to take the box of Bradium to Cheshire, who will be waiting for you near the Crevice of Bifrost."; + erasequest 7208; + setquest 7210; + getitem 6392,1; //Bradium_Box + close; + case 2: + mes "You decided to give up delivering the box."; + mes "You left the box as it is."; + erasequest 7208; + close; + } + } else { + if (checkquest(7207) == -1) { + if (checkquest(7206) > -1) { + mes "Boxes with all kinds of goods in them are stacked to the ceiling."; + mes "Looking closely, you find a box with a small piece of paper stuck to it."; + next; + mes "The piece of paper is marked with some mysterious symbol, and below it is written ^4d4dffTo: The Crevice of Bifrost^000000 in small letters."; + next; + mes "This must the box Cheshire was talking about."; + mes "You decide to take it to the location shown on the piece of paper."; + completequest 7206; + setquest 7207; + getitem 6392,1; //Bradium_Box + close; + } + } else if (checkquest(7207) < 2) { + mes "You've already obtained the box Cheshire was talking about."; + mes "Now you only have to take it to the Crevice of Bifrost."; + close; + } + mes "Boxes with all kinds of goods in them are stacked to the ceiling."; + close; + } + end; +} + +bif_fild01,335,168,3 script Cheshire#ep14_1_xq04 497,{ + if (checkweight(1201,1) == 0 || MaxWeight - Weight < 1000) { + mes "- You have too many items to do this quest. -"; + close; + } + cutin "ep13_cheshire",1; + if (checkquest(7209) > -1) { + if (countitem(6090) < 20) { + mes "[Cheshire]"; + mes "Bring me 20 pieces of refined Bradium."; + mes "In exchange for the box, which you carelessly and irresponsibly sold to somebody."; + mes "Have I made myself clear?!"; + close2; + cutin "",255; + end; + } + mes "[Cheshire]"; + mes "So you've brought it?"; + mes "The amount is less than it was, but I guess I can't help it."; + mes "Next time, you must bring the box to me intact."; + next; + mes "- Cheshire threw the Bradium into the Crevice. -"; + next; + mes "[Cheshire]"; + mes "You made a mistake of losing the box, you have to be content with this."; + mes "And starting tomorrow, get the box here intact."; + mes "Every day."; + delitem 6090,20; //Purified_Bradium + erasequest 7209; + setquest 7208; + getitem 6304,1; //Sapa_Feat_Cert + close2; + cutin "",255; + end; + } + callsub L_CheckPlaytime; + if (checkquest(7210) > -1) { + if (countitem(6392) == 0) + callsub L_LostQuest,7210; + else { + mes "[Cheshire]"; + mes "You've come at just the right time."; + mes "And I see the box is intact!"; + mes "Well done."; + next; + mes "[Cheshire]"; + mes "Well, I'll be counting on you, tomorrow as well."; + mes "Get it?"; + mes "Now, leave this place before the Laphines grow suspicious."; + erasequest 7210; + setquest 7208; + delitem 6392,1; //Bradium_Box + getitem 6304,1; //Sapa_Feat_Cert + getexp 50000,40000; + close2; + cutin "",255; + end; + } + } + if (ep13_3_secret > 22) { + if (checkquest(7207) == -1) { + if (checkquest(7206) == -1) { + mes "[Cheshire]"; + mes "...Hmm? Huh?"; + mes "It's "+strcharinfo(0)+"!"; + mes "What are you doing here?"; + next; + select("Huh? Cheshire?"); + mes "[Cheshire]"; + mes "What makes you so surprised?"; + mes "Does it surprise you to see me here?"; + next; + select("Nothing, it's just the hood..."); + mes "[Cheshire]"; + mes "Oh... This. Because it's bothersome."; + mes "And here, I don't have to mind others."; + mes "Oh, and well met!"; + mes "I was going to put you to work when you came to Diel."; + next; + mes "[Cheshire]"; + mes ".......What? Why are you staring at me like that?"; + mes "his is all for Ahat's good."; + next; + switch(select("I guess I have no choice.:I have a lot of things to do!")) { + case 1: + mes "["+strcharinfo(0)+"]"; + mes "(He will be suspicious if I refuse to do it... I guess I should play along for now.)"; + mes "Okay."; + mes "I'll do anything for Ahat's pleasure."; + mes "So, what do you need me for?"; + next; + break; + case 2: + mes "[Cheshire]"; + mes "Things to do?"; + mes "What things?"; + mes "This is one of the things you must do."; + mes "Don't forget you're are loyal to Ahat."; + next; + break; + } + mes "[Cheshire]"; + mes "Great! Now I will tell you what to do."; + mes "You know there is an entrance to Scaraba Hole in the middle of Kamidal Tunnel?"; + mes "You will find cat caravans around there who sell supplies and some simple tools."; + next; + mes "[Cheshire]"; + mes "There is a marked box among the goods stacked there."; + mes "I'd like you to bring the box to me."; + next; + mes "[Cheshire]"; + mes "It's a simple job of picking up and delivering a box."; + mes "Do it ^4d4dff quickly and quietly, without being noticed^000000."; + setquest 7206; + next; + mes "[Cheshire]"; + mes "Now, move!"; + close2; + cutin "",255; + end; + } else { + mes "[Cheshire]"; + mes "Bring the box from Kamidal Tunnel."; + mes "Quickly and quietly!"; + mes "No, get a move on!"; + close2; + cutin "",255; + end; + } + } else if (checkquest(7207) < 2) { + if (countitem(6392) == 0) + callsub L_LostQuest,7207; + else { + mes "[Cheshire]"; + mes "........That box!"; + mes "Oh, yes. It's the right one!"; + mes "You've done a good job."; + mes "This is very important."; + mes "Ahat will be pleased."; + next; + mes "[Cheshire]"; + mes "The boxes will be at the same place every day."; + mes "I'll leave the job to you."; + next; + select("Why don't you do it yourself?"); + mes "[Cheshire]"; + mes "........ Hmm..."; + mes "It's only you humans that have free access to any place."; + mes "Plus, this place is Laphine territory."; + next; + mes "[Cheshire]"; + mes "I don't attract their attention much, looking like this,"; + mes "but what would Saphas think?"; + mes "To see Ahat's man in a Laphine territory?"; + next; + mes "[Cheshire]"; + mes "They will grow suspicious."; + mes "But you humans are free from such troubles, so that's why you're the right one for the job."; + next; + mes "["+strcharinfo(0)+"]"; + mes "(... I don't buy his story, but he believes I'm on his side, so I guess I should play along.)"; + mes "What happens to this Bradium, then?"; + next; + mes "[Cheshire]"; + mes "That thing?"; + mes "Hand it to me."; + next; + mes "- Cheshire opened the box, checked the Bradium in it, threw them into the Crevice,"; + mes "and looked back, dusting his hands off, and with a triumphant look on his face. -"; + next; + mes "[Cheshire]"; + mes "This is what happens."; + mes "*laugh* Beyond the Crevice lies a path unknown to you."; + next; + mes "[Cheshire]"; + mes "Well, I'll leave the matter to you."; + mes "Try to bring the box to me every day."; + mes "Okay?"; + delitem 6392,1; //Bradium_Box + completequest 7207; + setquest 7208; + getitem 6304,1; //Sapa_Feat_Cert + getexp 50000,40000; + next; + mes "[Cheshire]"; + mes "In compensation for your efforts, I'll give you an Exploit Certification of Sapha and a little cash."; + mes "Now, leave this place before the Laphines grow suspicious."; + close2; + cutin "",255; + end; + } + } else { + callsub L_CheckPlaytime; + mes "[Cheshire]"; + mes "Huh? What's up?"; + mes "You haven't brought the box today?"; + next; + mes "[Cheshire]"; + mes "Hmm, this is unexpected..."; + mes "Well, I have no choice then."; + mes "I'll have another guy do it today."; + mes "But you must do it starting tomorrow, okay?"; + setquest 7208; + close2; + cutin "",255; + end; + } + } else if (ep13_3_secret > 15) { + mes "[Cheshire]"; + mes "... Huh? I think I've seen you somewhere..."; + mes "..........Oh!"; + mes strcharinfo(0)+"...?!"; + mes "What brings you here?"; + next; + mes "[Cheshire]"; + mes "You say you've forgotten what to do?"; + mes "You're not supposed to be here."; + mes "You're supposed to be at the crevice to the south of Dicastes."; + next; + mes "[Cheshire]"; + mes "Whoa."; + mes "What was Ahat thinking when he sent such an idiot to me?"; + mes "Now, get a move on and do your job."; + close2; + cutin "",255; + end; + } + mes "[Cheshire]"; + mes "...Why isn't this fellow showing up?"; + mes "Should be here by now..."; + mes "Lost the way back perhaps...?"; + mes "....? Eh? Who, who are you? How long have you been standing here?"; + next; + select("A cat?!"); + mes "[Cheshire]"; + mes "Who... who's a cat?!"; + mes "Get lost!"; + close2; + cutin "",255; + end; +L_LostQuest: + mes "[Cheshire]"; + mes "Oh, have you been there?"; + mes "What happened to the box?"; + mes "Why are you empty-handed?"; + next; + switch(select("I'll look for it again!:I lost it...")) { + case 1: + mes "[Cheshire]"; + mes "Make sure you do a good job!"; + mes "And keep looking for it."; + mes "You must not lose it."; + break; + case 2: + mes "[Cheshire]"; + mes "Where?"; + mes "Which merchant did you sell it to?"; + mes "Can't you distinguish between what to sell and what not to sell?"; + mes "Were you asleep when you made the deal?"; + next; + mes "[Cheshire]"; + mes "This is utterly ridiculous."; + mes "Make up for what you lost!"; + mes "^4d4dff20 pieces of refined Bradium^000000!!!"; + erasequest getarg(0); + setquest 7209; + break; + } + close2; + cutin "",255; + end; +L_CheckPlaytime: + set .@playtime, checkquest(7208,PLAYTIME); + if (.@playtime == 0 || .@playtime == 1) { + mes "[Cheshire]"; + mes "Each day, one of these boxes is sent to Kamidal Tunnel."; + mes "It's smuggled in among other items."; + next; + mes "[Cheshire]"; + mes "Sneak into the place on time, and bring the box to me. The boxes will be at the same place every day."; + mes "You'll be doing it every day."; + close2; + cutin "",255; + end; + } else if (.@playtime == 2) { + mes "[Cheshire]"; + mes "It's about time."; + mes "Now go get the box."; + mes "It should be lying near the entrance to Scaraba Hole in the Kamidal Tunnel."; + mes "You've done this before, so you must be familiar with it?"; + close2; + cutin "",255; + end; + } else + return; +} + +dicastes02,125,192,0 script #call_cheshir_ep14 139,0,3,{ + end; +OnTouch: + if (ep13_3_secret > 22) { + if (rand(2)) { + emotion e_ho,1; + mes "..........?"; + mes "You sense someone moving around."; + mes "There must be someone down there."; + if ($@cheshire_on == 0) { + donpcevent "Cheshire#ep14_extra::OnEnable"; + set $@cheshire_on,1; + } + close; + } + } + end; +} + +dicastes02,103,190,3 script Cheshire#ep14_extra 497,{ + if (ep13_3_secret > 22) { + cutin "ep13_cheshire",1; + mes "[Cheshire]"; + mes "...Eh?"; + mes "What a surprise. What are you doing here?"; + next; + switch(select("And what are YOU doing here?:Those ears...?")) { + case 1: + mes "[Cheshire]"; + mes "Out for a walk?"; + mes "I came out with Ahat, but he went back in to take care of an urgent matter."; + next; + mes "[Cheshire]"; + mes ".. .............."; + next; + select("....:Wha... What a pretty tree."); + mes "[Cheshire]"; + mes "This tree... it's white, transparent, and shiny."; + mes "It's a Sapha's body."; + next; + mes "[Cheshire]"; + mes "You know Saphas slowly turn to stone throughout their lives."; + mes "So when they die, they turn to stony trees."; + mes "This forest is... their cemetery, so to speak."; + next; + mes "[Cheshire]"; + mes "....... Look closely, and you can make out his arms and legs."; + mes "Interesting, isn't it?"; + next; + mes "[Cheshire]"; + mes "... .. ..."; + next; + mes "[Cheshire]"; + mes "Oh, this is so annoying."; + mes "I'm off!"; + next; + mes "- Cheshire stormed off... -"; + break; + case 2: + mes "[Cheshire]"; + mes "What? The ears?"; + mes "Well, it's no wonder because I'm a beastman."; + mes "... Why... Why are you staring me like that?"; + next; + select("Are you responsible for the report?!"); + mes "[Cheshire]"; + mes "What are you talking about?"; + mes "I don't know such a thing!"; + next; + mes "- Cheshire ran away... -"; + break; + } + disablenpc "Cheshire#ep14_extra"; + stopnpctimer; + close2; + cutin "",255; + end; + } + mes "A boy dressed in unusual clothing is standing, with a fierce look in his eyes."; + mes "You guess you'd better leave him alone."; + close; +OnInit: + disablenpc "Cheshire#ep14_extra"; + end; +OnEnable: + enablenpc "Cheshire#ep14_extra"; + initnpctimer; + end; +OnDisable: + disablenpc "Cheshire#ep14_extra"; + stopnpctimer; + end; +OnTimer600000: + disablenpc "Cheshire#ep14_extra"; + set $@cheshire_on,0; + stopnpctimer; + end; +} + +// Helping Lope and Euridi :: rofe +//============================================================ +mora,117,66,3 script Euridi#pa 521,{ + if (BaseLevel < 100) { + mes "[Euridi]"; + mes "You are very delicate."; + mes "It's true that I need help,"; + mes "but I don't think you can help."; + close; + } + if (ep14_1_rope == 0) { + mes "[Euridi]"; + mes "I hear you passed through the Hazy Forest."; + mes "Did you..."; + mes "Did you happen to see"; + mes "Lope, my fiance, there?"; + next; + switch(select("Yes, I did.:No, I didn't.")) { + case 1: + mes "[Euridi]"; + mes "Are you sure? Where did you see him?"; + mes "Take me there, quick!"; + mes "..."; + next; + mes "[Euridi]"; + mes "What?"; + mes "You're kidding...?"; + mes "How could you?"; + close; + case 2: + mes "[Euridi]"; + mes "Please find my Lope."; + mes "I came here to the Village of Mora"; + mes "after asking all around,"; + mes "but there is nothing more I can do."; + next; + mes "[Euridi]"; + mes "My heart aches at the thought of Lope..."; + mes "He will be desperately looking for me..."; + next; + switch(select("Sorry, I'm busy!:I'll help you!")) { + case 1: + mes "[Euridi]"; + mes "How heartless!"; + close; + case 2: + mes "[Euridi]"; + mes "I heard that he had gone into the Hazy Forest,"; + mes "while guiding tourists around the village."; + mes "One of the tourists who went with Lope"; + mes "must still be at the inn."; + next; + mes "[Euridi]"; + mes "He wouldn't see me and locked himself in the room."; + mes "But he might be willing to see you, because you've been to the Hazy Forest."; + setquest 1109; + set ep14_1_rope,1; + close; + } + } + } else if (ep14_1_rope == 1) { + mes "[Euridi]"; + mes "The tourist is at the inn,"; + mes "not in front of me!"; + close; + } else if (ep14_1_rope == 2) { + mes "[Euridi]"; + mes "So you've seen Pitt!"; + mes "I knew he would be willing to see you."; + mes "What did he say?"; + next; + mes "[Euridi]"; + mes "...No way....!"; + mes "That is utter nonsense."; + mes "To blame Lope for it!"; + mes "I found this piece of paper"; + mes "near the Hazy Forest."; + mes "I'm sure it's Lope's."; + next; + mes "[Euridi]"; + mes "If you find the rest of ^0000FFLope's Clues^000000,"; + mes "you'll be able to find out"; + mes "where he is."; + mes "I'm counting on you, "+strcharinfo(0)+"."; + changequest 1110,1111; + set ep14_1_rope,3; + close; + } else if (ep14_1_rope == 3) { + mes "[Euridi]"; + mes "If you come across a ^0000FFLope's Clue^000000, please show it to Pitt."; + mes "I hope he will tell the truth soon."; + close; + } else if (ep14_1_rope == 4) { + mes "[Euridi]"; + mes "I don't understand it."; + mes "I'm now suspicious of his motives."; + mes "Why is he trying so hard to accuse Lope?"; + mes "Wait... those clues..."; + next; + mes "[Euridi]"; + mes "Those seem to be more than simple notes."; + mes "Can I have a look at them?"; + mes "..."; + mes "These fit together like a puzzle."; + mes "... Oh!... This is..."; + next; + mes "[Lope's Letter]"; + mes "...We've been wandering around the Forest for days."; + mes "...So we're not protecting the tourists,"; + mes "I got sick from deadly poison, and became a burden to everyone."; + mes "How pathetic..."; + next; + mes "[Lope's Letter]"; + mes "No wonder I was kicked out of"; + mes "the Splendide Expedition."; + mes "...But I managed to protect at least one tourist."; + mes "He will deliver this letter and the ring to you."; + next; + mes "[Lope's Letter]"; + mes "...I wanted to propose to you"; + mes "as a proud member of the Expedition."; + mes "I'm sorry, Euridi."; + mes "See you soon."; + next; + mes "Having read the letter,"; + mes "Euridi is standing staring blankly like someone who wasn't all there."; + mes "Let's go show the letter to Pitt."; + changequest 1112,1113; + delitem 6383,30; //Clue_Of_Lope + set ep14_1_rope,5; + close; + } else if (ep14_1_rope == 5) { + mes "[Euridi]"; + mes "No, Lope must be safe."; + mes "He will come back no matter what..."; + close; + } else if (ep14_1_rope == 6) { + mes "[Euridi]"; + mes "......"; + next; + mes "You hear a song coming from the girl who is hanging her head low."; + mes "Her friend seems to have something to say."; + close; + } else if (ep14_1_rope == 7 || ep14_1_rope == 8) { + mes "You hear a quiet singing voice."; + mes "You can't make the words out."; + close; + } else if (ep14_1_rope == 9) { + mes "[Euridi]"; + mes "Have you found Lope?"; + mes "Is he safe?"; + next; + switch(select("Tell her you can't possibly find him.:Tell her he is dead.")) { + case 1: + mes "[Euridi]"; + mes "I'll go look for him myself."; + mes "Hopefully... it's not too late, yet."; + mes "Let me go, there's no time to lose!"; + close; + case 2: + mes "[Euridi]"; + mes "I don't believe it."; + mes "He told me he would come back soon..."; + mes "He told me to hang on."; + mes "It can't be... It just can't be..."; + next; + mes "You hand her Lope's Ring, which Pitt gave you."; + mes "With the ring in her hand, Euridi bursts into tears."; + mes "She starts to sing in a strained voice, still crying."; + changequest 1116,1117; + set ep14_1_rope,10; + delitem 6384,1; //Ring_Of_Lope + close; + } + } else if (ep14_1_rope > 9) { + mes "You stand frozen."; + mes "You hear a quiet singing voice."; + close; + } +} + +mora,115,68,3 script Euridi's Friend#pa 520,{ + if (ep14_1_rope < 2) { + mes "[Euridi's Friend]"; + mes "Please stop Euridi."; + mes "She is desperate to find her missing fiance."; + close; + } else if (ep14_1_rope == 2) { + mes "[Euridi's Friend]"; + mes "Pitt is definitely suspicious."; + mes "I think he is avoiding Euridi..."; + mes "He must be hiding something."; + close; + } else if (ep14_1_rope == 3) { + mes "[Euridi's Friend]"; + mes "To tell the truth, I don't think"; + mes "that Lope is alive."; + mes "I'm just worried about Euridi."; + next; + mes "[Euridi]"; + mes "Aaarrrggghhh!!!!!!!!"; + next; + mes "[Euridi's Friend]"; + mes "..."; + mes "To tell the truth, I really believe"; + mes "that Lope is alive."; + mes "..."; + mes "*sigh*"; + close; + } else if (ep14_1_rope == 4) { + mes "[Euridi's Friend]"; + mes "How's Pitt doing?"; + mes "I think I should go visit him"; + mes "and make him feel worse!"; + mes "He's so disgusting!"; + close; + } else if (ep14_1_rope == 5) { + mes "[Euridi's Friend]"; + mes "Go to Pitt, quick."; + close; + } else if (ep14_1_rope == 6) { + mes "[Euridi's Friend]"; + mes "Euridi is singing a song of healing"; + mes "to protect her weakened body and mind."; + mes "At this rate, something's going to happen to her too."; + next; + mes "[Euridi's Friend]"; + mes "Oh, I remember a traveler telling me"; + mes "that he had seen a suspicious man"; + mes "near the entrance to the Hazy Forest."; + next; + mes "[Euridi's Friend]"; + mes "The traveler says he looked creepy standing there staring blankly,"; + mes "but he couldn't see clearly"; + mes "because of the thick fog."; + mes "I think it's worth investigating."; + changequest 1114,1115; + set ep14_1_rope,7; + close; + } else if (ep14_1_rope == 7) { + mes "[Euridi's Friend]"; + mes "I hear that a suspicious man was seen"; + mes "near the entrance to the Hazy Forest."; + mes "The traveler says he looked creepy standing there staring blankly,"; + mes "but he couldn't see clearly"; + mes "because of the thick fog."; + mes "I think it's worth investigating."; + close; + } else if (ep14_1_rope == 8 || ep14_1_rope == 9) { + mes "[Euridi's Friend]"; + mes "Your face is dark."; + mes "Bad news?"; + close; + } else if (ep14_1_rope == 10) { + mes "[Euridi's Friend]"; + mes "There is a Laphine saying that"; + mes "desperation invites disaster."; + mes "Maybe we're responsible"; + mes "for what happened."; + next; + if (checkweight(6380,1) == 0) { + mes "[Euridi's Friend]"; + mes "You have too many things with you."; + mes "Can you throw out some of them?"; + close; + } + mes "[Euridi's Friend]"; + mes "Lope will be able to rest in peace now."; + mes "Thank you. I won't forget what you've done for me."; + completequest 1117; + set ep14_1_rope,11; + getexp 1000000,2000000; + getitem 6380,10; //Mora_Coin + close; + } else if (ep14_1_rope > 10) { + mes "[Euridi's Friend]"; + mes "Thank you. I won't forget your help."; + close; + } +} + +mora,65,145,3 script Pitt#pa 519,{ + if (ep14_1_rope == 0) { + mes "[Pitt]"; + mes "So you're quite good,"; + mes "since you passed through the Hazy Forest alive."; + mes "I'm completely messed up, you see,"; + mes "so I can't afford to listen to the tales of your exploits."; + mes "Now leave."; + close; + } else if (ep14_1_rope == 1) { + mes "[Pitt]"; + mes "You have a knack for pestering people, don't you?"; + mes "Euridi sent you, eh?"; + mes "The Laphine couple is"; + mes "anxious to kill me."; + next; + mes "[Pitt]"; + mes "Go and tell her!"; + mes "That the stupid guide"; + mes "pushed us reluctant tourists into the forest,"; + mes "and ran off to save his own skin!"; + next; + mes "[Pitt]"; + mes "So you're sorry that it's me, not him, that's here?"; + mes "He will be alive somewhere,"; + mes "so go and try to find him! Just stop bothering me!"; + changequest 1109,1110; + set ep14_1_rope,2; + close; + } else if (ep14_1_rope == 2) { + mes "[Pitt]"; + mes "This is all because of"; + mes "the stupid guide!"; + mes "I hate Laphines!"; + close; + } else if (ep14_1_rope == 3) { + if (countitem(6383) < 30) { + mes "[Pitt]"; + mes "This is all because of"; + mes "the stupid guide!"; + mes "I hate Laphines!"; + close; + } + mes "[Pitt]"; + mes "That thing you have in your hand..."; + mes "It looks very strange."; + mes "I've never seen such a thing before."; + mes "You'd better not keep that."; + mes "Can I have it?"; + next; + switch(select("Give it to him.:Don't give it to him.")) { + case 1: + mes "[Pitt]"; + mes "So I swallow it like this,"; + mes "and voila! Evidence gone!"; + mes "Now I can sleep soundly, thank you!"; + delitem 6383,5; //Clue_Of_Lope + close; + case 2: + mes "[Pitt]"; + mes "Why are you showing me such a thing?"; + mes "I don't know anything! I'm the victim here!"; + mes "I'm a victim of the schemes of the Laphine couple."; + mes "It's unfair..."; + next; + mes "It's no use trying to talk to him any more."; + mes "Try talking to Euridi."; + changequest 1111,1112; + set ep14_1_rope,4; + close; + } + } else if (ep14_1_rope == 4) { + mes "[Pitt]"; + mes "This is unfair!"; + mes "This is so totally unfair!"; + close; + } else if (ep14_1_rope == 5) { + if (checkweight(6384,1) == 0) { + mes "[Pitt]"; + mes "What are you, a professional mover?"; + mes "Stomping about with a ton of stuff on your back!"; + mes "I can't rest because of the noise!"; + mes "Throw away all that stuff!"; + close; + } + mes "[Pitt]"; + mes "I never imagined you'd find them all"; + mes "and piece them together."; + mes "Is this a divine punishment...?"; + mes "Or Laphines' curse?"; + mes "Whew..."; + next; + mes "[Pitt]"; + mes "That guide fellow,"; + mes "he opened the gate out"; + mes "when he was hit hard"; + mes "by the poison."; + next; + mes "[Pitt]"; + mes "When I was hesitating whether to take him with me,"; + mes "he handed me that letter and the ring."; + mes "Laphines' jewelry..."; + mes "It's rumored that nobody could ever have it except Laphines,"; + mes "including the Gods themselves."; + next; + mes "[Pitt]"; + mes "So I had in my hands"; + mes "a treasure among treasures!"; + mes "How...! Just how on earth"; + mes "could I have let it pass through!"; + next; + mes "[Pitt]"; + mes "I was going to leave this place"; + mes "as soon as I pulled myself together."; + mes "But now I'm stuck here,"; + mes "affected by the poison myself."; + next; + mes "[Pitt]"; + mes "I'll give you the ring back,"; + mes "so please leave me alone!"; + next; + mes "["+strcharinfo(0)+"]"; + mes "Then where could Lope...?"; + next; + mes "[Pitt]"; + mes "If he died near the exit of the forest,"; + mes "he must be somewhere around there,"; + mes "in whatever form he might be in."; + changequest 1113,1114; + set ep14_1_rope,6; + getitem 6384,1; //Ring_Of_Lope + close; + } else if (ep14_1_rope == 6 || ep14_1_rope == 7) { + mes "[Pitt]"; + mes "I'm a victim, too!"; + mes "So leave me alone! I beg you!"; + close; + } else if (ep14_1_rope == 8) { + mes "[Pitt]"; + mes "..."; + close; + } else if (ep14_1_rope > 8) { + mes "He's sleeping."; + mes "He seems to be in a very deep sleep."; + close; + } +} + +bif_fild01,132,338,3 script Lope#pa 461,2,2,{ + if (ep14_1_rope < 8) { + mes "[Suspicious Man]"; + mes "......"; + close; + } else if (ep14_1_rope == 8) { + donpcevent "Lope#pa::OnEnable"; + mes "[Suspicious Man]"; + mes "Aaaarrrrrggggghhhh!!!!!!"; + mes "I can't see anything."; + mes "Who's there?"; + mes "Answer, or I'll take you as an enemy and kill you."; + next; + mes "["+strcharinfo(0)+"]"; + mes "Euridi is looking for you."; + next; + mes "[Suspicious Man]"; + mes "......"; + next; + mes "[Lope]"; + mes "Wraith, how can you be so harsh to me?"; + mes "I asked you to wipe the name off my mind"; + mes "in return for bearing the curse!"; + next; + mes "["+strcharinfo(0)+"]"; + mes "Will you please calm down and listen to..."; + next; + mes "[Lope]"; + mes "My desire to help"; + mes "led me to my death,"; + mes "And my desire to survive and take revenge"; + mes "led me to my rebirth."; + mes "I will not side with life any more."; + next; + mes "[Lope]"; + mes "As soon as my transformation is over,"; + mes "I will punish you all with the bloody confusion of the Hazy Forest,"; + mes "which saved my life!"; + next; + mes "You put the letter Euridi pieced together in Lope's hands."; + next; + mes "[Lope]"; + mes "...This is!"; + mes "I feel Euridi's touch."; + mes "So the letter... was delivered to Euridi?"; + mes "This is unbelievable..."; + next; + mes "[Lope]"; + mes "Deformed as I am now,"; + mes "I'm not her love any more."; + mes "Go back, and tell her that Lope turned to dust"; + mes "on the ground of the Hazy Forest long ago."; + next; + mes "[Lope]"; + mes "Now go!"; + mes "This is my last request as a Laphine called Lope..."; + set ep14_1_rope,9; + changequest 1115,1116; + close; + } else { + mes "[Lope]"; + mes "Deformed as I am now,"; + mes "I'm not her love any more."; + mes "Go back, and tell her that Lope turned to dust"; + mes "on the ground of the Hazy Forest long ago."; + next; + mes "[Lope]"; + mes "Now go!"; + mes "This is my last request as a Laphine called Lope..."; + next; + mes "You see a ring glowing faintly on his left hand."; + close; + } + end; +OnEnable: + setnpcdisplay "Lope#pa",999; + end; +OnDisable: + disablenpc "Lope#pa"; + initnpctimer; + end; +OnReset: + setnpcdisplay "Lope#pa",461; + enablenpc "Lope#pa"; + end; +OnTimer2000: + donpcevent "Lope#pa::OnReset"; + stopnpctimer; + end; +OnTouch: + mes "I see a suspicious man. Should I try talking to him?"; + next; + switch(select("Leave him alone.:Talk to him.")) { + case 1: + donpcevent "Lope#pa::OnDisable"; + mes "[Suspicious Man]"; + mes "......"; + close; + case 2: + donpcevent "Lope#pa::OnDisable"; + if (ep14_1_rope == 7) { + mes "[Suspicious Man]"; + mes "."; + mes "..."; + mes "........!!!"; + next; + mes "[Suspicious Man]"; + mes "Aaaaarrrrrggghh!!!!!"; + set ep14_1_rope,8; + close; + } else { + mes "[Suspicious Man]"; + mes "......"; + close; + } + } +} + +// Find the Research Tools :: muk +//============================================================ +mora,31,138,6 script Raffle Researcher#ep14 522,{ + if (checkweight(1201,1) == 0 || MaxWeight - Weight < 500) { + mes "^FF0000- Warning message -"; + mes "- Hang on there!! -"; + mes "- You have too many items -"; + mes "- to receive any more items. -"; + mes "- Please lighten your load -"; + mes "- and try again. -^000000"; + close; + } + // NPC disabled from 12am ~ 5am. + if (gettime(3) >= 0 && gettime(3) < 5) { + if (ep14_1_muk > 0) { + mes "[Raffle Researcher]"; + mes "Don't humans sleep?"; + mes "People should be sleeping at this hour."; + mes "Why on earth are you bothering me?"; + next; + mes "[Raffle Researcher]"; + mes "I can't get any sleep because of you."; + mes "I have to sleep for my research tomorrow."; + mes "You should go sleep too."; + close; + } else { + mes "Z z Z z"; + next; + mes "^FF0000He appears to be asleep.^000000"; + close; + } + } + if (ep14_1_muk == 0) { + mes "[Raffle Researcher]"; + mes "Oh no~ My research tools..."; + mes "What...... What was it?"; + emotion e_sob; + next; + select("What is your business here?"); + mes "[Raffle Researcher]"; + mes "Hmm?"; + emotion e_what; + next; + mes "[Raffle Researcher]"; + mes "You're human...? Are you human...?"; + mes "You... came from the underworld?"; + next; + mes "[Raffle Researcher]"; + mes "Human beings are incredible..."; + mes "You survived the crevice and made it here."; + next; + mes "[Raffle Researcher]"; + mes "... ... ..."; + next; + mes "[Raffle Researcher]"; + mes "You, come here for a minute."; + mes "It's a simple experiment, so there's no need to be afraid."; + emotion e_gg; + next; + if(select("What a crazy Raffle. I must run away.:... ...") == 1) { + mes "[Raffle Researcher]"; + mes "You said you had made it up from the Crevice,"; + mes "so I was wondering what race you were,"; + mes "but a mere human? How did you get up here?"; + emotion e_lv; + close; + } + if (BaseLevel < 100) { + mes "[Raffle Researcher]"; + mes "What... I thought a human who made it up from the Crevice"; + mes "would be extraordinary,"; + mes "but you're no more than a kid."; + next; + mes "[Raffle Researcher]"; + mes "Go hunt more ^000000Porings^000000"; + mes "and come back when your level is in the triple digits kid!"; + close; + } + mes "[Raffle Researcher]"; + mes "... ... ..."; + emotion e_dots; + next; + mes "[Raffle Researcher]"; + mes "You... You're not like the other humans."; + mes "You're not running away..."; + next; + mes "[Raffle Researcher]"; + mes "You've got some serious guts..."; + mes "Now I really want to do some experiments on you..."; + next; + select("Well... that's... um..."); + mes "[Raffle Researcher]"; + mes "Ha ha... Just kidding..."; + mes "I'm a Raffle researcher,"; + mes "but I don't research humans."; + mes "Actually, I have no idea"; + mes "what to research"; + mes "about humans..."; + next; + select("Glad to hear that..."); + mes "[Raffle Researcher]"; + mes "That's that. You're not busy, are you?"; + mes "I'd like you to give me a hand..."; + next; + select("Help him.:Help willingly.:Although you feel a little embarrassed, help anyhow.:Help with conviction.:Help adorably.:You're suspicious, but help anyhow.:You have no choice. Help him."); + mes "[Raffle Researcher]"; + mes "I haven't met many humans"; + mes "but you clearly care about"; + mes "another person's hardship."; + mes "You must be an ^FF0000extremely^000000 nice human."; + emotion e_no1; + next; + mes "[Raffle Researcher]"; + mes "I'll save my thanks for time's sake."; + mes "It's important, so please take care of it quickly."; + mes "I can't proceed with the research because of it."; + next; + mes "[Raffle Researcher]"; + mes "Here at the Mora Inn,"; + mes "there's a very famous bath."; + mes "If anybody, not just us Raffles,"; + mes "goes into the bath water"; + mes "their wounds will be healed instantly..."; + next; + mes "[Raffle Researcher]"; + mes "So being a great researcher, I went into the bath"; + mes "to check it out further"; + mes "and... unfortunately..."; + next; + mes "[Raffle Researcher]"; + mes "I was attacked by a mysterious creature,"; + mes "and I lost consciousness."; + next; + mes "[Raffle Researcher]"; + mes "When I woke up, I realized that"; + mes "my important research tools were missing..."; + mes "So I was at a loss for what to do."; + next; + mes "[Raffle Researcher]"; + mes "And here you are, a human,"; + mes "a brave, heroic human that arrived at Mora Village from the Crevice."; + mes "Your willingness to help has really taken this load off of my mind."; + next; + select("... ... ..."); + mes "[Raffle Researcher]"; + mes "Please go to the bath house and retrieve my research tools."; + mes "The sooner you get them back,"; + mes "the sooner I can get back to my research."; + setquest 5016; + set ep14_1_muk,1; + next; + mes "[Raffle Researcher]"; + mes "Have a safe trip."; + emotion e_paper; + close; + } else if (ep14_1_muk == 1) { + if (checkquest(5016) > -1 && countitem(6385) == 0) { + mes "[Raffle Researcher]"; + mes "You're back? Where are my research tools?"; + emotion e_what; + next; + mes "[Raffle Researcher]"; + mes "You still haven't found the research tools?"; + mes "I'm disappointed. Get yourself to the bath"; + mes "and quickly retrieve my research tools"; + mes "taken away from me."; + close; + } + mes "[Raffle Researcher]"; + mes "Wow!! You found the research tools...?"; + mes "You're quite capable."; + mes "I really like how you handle your work."; + next; + mes "[Raffle Researcher]"; + mes "I like you."; + mes "Do you want to work on my research with me?"; + mes "I could use your help here and there,"; + mes "until I'm done with this research."; + next; + select("As you wish."); + mes "[Raffle Researcher]"; + mes "Great. Thanks, and when we're done,"; + mes "I'll pay you handsomely."; + mes "Also, for every research project that's completed,"; + mes "I'll also give you some pocket money."; + next; + mes "[Raffle Researcher]"; + mes "Young Raffles these days... they are just plain stupid."; + mes "I've always wanted a capable research assistant,"; + mes "but it hasn't been easy to find one."; + next; + if (checkweight(6380,1) == 0) { + mes "[Raffle Researcher]"; + mes "By the way... Was it that difficult to"; + mes "reclaim the research tools?"; + mes "You're carrying some very heavy looking equipment."; + mes "Go lighten your load, and I'll pay you for your work."; + close; + } + mes "[Raffle Researcher]"; + mes "It must've been hard work to retrieve the tools."; + mes "Why don't you take this and go to the inn"; + mes "and rest up? There's nothing for you to do right now."; + delitem 6385,1; //Research_Tool_Bag + set ep14_1_muk,2; + getitem 6380,1; //Mora_Coin + erasequest 5016; + close; + } else if (ep14_1_muk == 2) { + // Unofficial check, but it's needed here. + if (checkquest(5029,PLAYTIME) == 0 || checkquest(5029,PLAYTIME) == 1) { + mes "[Raffle Researcher]"; + mes "It must've been hard work to retrieve the tools."; + mes "Why don't you take this and go to the inn"; + mes "and rest up? There's nothing for you to do right now."; + close; + } + switch(rand(1,5)) { + case 1: + mes "[Raffle Researcher]"; + mes "I'm still preparing for the research."; + mes "Unfortunately a few research tools"; + mes "were damaged."; + emotion e_an; + close; + case 2: + mes "[Raffle Researcher]"; + mes "Come to think of it, I don't think"; + mes "I told you my name."; + next; + mes "[Raffle Researcher]"; + mes "My name is Inffle. If anybody"; + mes "asks you who you are working with,"; + mes "you can say ^0000FFI'm working with Researcher Inffle.^000000"; + mes "That's why I'm telling you my name."; + emotion e_ok; + close; + case 3: + mes "[Raffle Researcher]"; + mes "Why? The inn is closed?"; + mes "That's strange, it shouldn't be."; + mes "Why don't you go try again?"; + emotion e_what; + close; + case 4: + break; + case 5: + mes "[Raffle Researcher]"; + mes "Darn, I get more worked up the more I think about it."; + mes "It's not like I went with bad intentions..."; + mes "I just wanted to do some research..."; + mes "Can't believe I got attacked..."; + mes "I just can't believe it..."; + mes "What do you think?"; + emotion e_an; + close; + } + mes "[Raffle Researcher]"; + mes "Good thing you're here."; + next; + mes "[Raffle Researcher]"; + mes "I've been thinking about"; + mes "the unidentified creature in the bath."; + mes "He's quite the little devil, to take research tools,"; + mes "which are as important to a researcher as his life..."; + next; + mes "[Raffle Researcher]"; + mes "A research assistant's job"; + mes "is to make sure that the researcher can focus on his research"; + mes "And not have to worry about anything else... VERY! Important."; + next; + mes "[Raffle Researcher]"; + mes "I'd like you to take my revenge"; + mes "on the unidentified creature for me..."; + next; + mes "[Raffle Researcher]"; + mes "I don't even want anything that drastic."; + mes "3 times! Go bully him for just 3 times."; + mes "You can draw on his face,"; + mes "pinch him, tickle him,"; + mes "whatever you want. Just bully him 3 times."; + set ep14_1_muk,3; + setquest 5017; + close; + } else if (ep14_1_muk < 6) { + mes "[Raffle Researcher]"; + mes "How's the work going?"; + mes "An assistant has to work swiftly and effectively."; + mes "Could it be that you have forgotten"; + mes "what your task is?"; + next; + select("Exactly. What should I do?"); + mes "[Raffle Researcher]"; + mes "Go bully the unidentified creature"; + mes "just 3 times."; + mes "You can draw on his face,"; + mes "pinch him, tickle him, or whatever."; + mes "Bully him 3 times."; + emotion e_gg; + close; + } else if (ep14_1_muk == 6) { + mes "[Raffle Researcher]"; + mes "So you taught him a lesson? Great. I feel avenged!"; + emotion e_heh; + next; + mes "[Raffle Researcher]"; + mes "For a while, I couldn't sleep"; + mes "because I couldn't stop thinking about the lost research tools."; + next; + mes "[Raffle Researcher]"; + mes "That's that! We need to begin the bath research now."; + mes "I need to finish the research quickly,"; + mes "so that I can start on a new topic."; + next; + mes "[Raffle Researcher]"; + mes "Go to the bath water"; + mes "with the sample tube that I give you,"; + mes "and gather some samples."; + next; + mes "[Raffle Researcher]"; + mes "Look around the bath water,"; + mes "and you will find an area emitting a distinct aura."; + mes "You can collect the samples"; + mes "from that area."; + next; + if (MaxWeight - Weight < 100 || checkweight(1092,10) == 0) { + mes "[Raffle Researcher]"; + mes "You are carrying too much weight."; + mes "I can't give you the sample tube."; + mes "Why don't you lighten your load and come back?"; + close; + } + mes "[Raffle Researcher]"; + mes "Here is the sample tube for collecting."; + mes "Go and collect 10 samples!"; + set ep14_1_muk,7; + getitem 1092,10; //Empty_Cylinder + erasequest 5018; + setquest 5019; + close; + } else if (ep14_1_muk == 7) { + if (checkquest(5019) > -1 && countitem(6386) < 10) { + mes "[Raffle Researcher]"; + mes "Have you collected the samples yet?"; + mes "Please hurry up."; + next; + mes "[Raffle Researcher]"; + mes "Look around the bath water,"; + mes "and you will find an area emitting a distinct aura."; + mes "You can collect the samples"; + mes "from that area."; + close; + } + if (checkweight(6380,1) == 0) { + mes "[Raffle Researcher]"; + mes "I know that you've done a lot..."; + mes "but you are carrying too many things."; + mes "Even though I want to give you pocket money, I can't."; + mes "Could you lighten your load and come back?"; + close; + } + mes "[Raffle Researcher]"; + mes "You got the bath water sample. Great job."; + next; + mes "[Raffle Researcher]"; + mes "I'll have to run a few tests"; + mes "with the bath water samples."; + mes "It usually takes about 24 hours."; + mes "Why don't you come back then?"; + delitem 6386,10; //Bathtub_R_Sample + getitem 6380,1; //Mora_Coin + set ep14_1_muk,8; + erasequest 5019; + setquest 5020; + close; + } else if (ep14_1_muk == 8) { + if (checkquest(5020,PLAYTIME) == 0 || checkquest(5020,PLAYTIME) == 1) { + mes "[Raffle Researcher]"; + mes "The basic tests have not been completed yet."; + mes "There's nothing for you to do now."; + mes "Go for a walk."; + mes "Spend some money that I gave you."; + close; + } + mes "[Raffle Researcher]"; + mes "The basic tests are done."; + mes "As I thought..."; + mes "There were many interesting substances in the bath water."; + emotion e_ho; + next; + mes "[Raffle Researcher]"; + mes "The most notable is this unidentifiable DNA."; + mes "I didn't have a chance to compare it to a lot of DNA samples,"; + mes "but I'm pretty sure that this DNA"; + mes "has been transformed by the mysterious substances of the bath."; + next; + mes "[Raffle Researcher]"; + mes "After much thought,"; + mes "I concluded that this DNA probably belongs to"; + mes "the unidentified creature that attacked me."; + next; + if (rand(2)) { + set .@str$,"teeth"; + set .@quest,5021; + } else { + set .@str$,"scales"; + set .@quest,5022; + } + mes "[Raffle Researcher]"; + mes "I'd better compare the two."; + mes "Please return to the bath"; + mes "and look for the creature's "+.@str$+"."; + mes "If you can, please bring me 10 of them."; + set ep14_1_muk,9; + erasequest 5020; + setquest .@quest; + close; + } else if (ep14_1_muk == 9) { + if (checkquest(5021) > -1 || checkquest(5022) > -1) { + if (checkquest(5021) > -1) { + set .@quest,5021; + set .@item,6387; //Teeth_Sample + setarray .@str$[0],"tooth","teeth"; + } else { + set .@quest,5022; + set .@item,6388; //Scale_Sample + setarray .@str$[0],"scale","scales"; + } + if (countitem(.@item) < 10) { + mes "[Raffle Researcher]"; + mes "Haven't you found the unidentified creature's "+.@str$[1]+" yet?"; + mes "Look carefully!"; + mes "I'm certain that the creature"; + mes "dropped his "+.@str$[1]+" somewhere."; + close; + } + mes "[Raffle Researcher]"; + mes "You've collected all the "+.@str$[0]+" samples, finally."; + mes "As humans say,"; + mes "I've been waiting forever for them."; + next; + if (checkweight(6380,1) == 0) { + mes "[Raffle Researcher]"; + mes "I know that you've done a lot..."; + mes "but you are carrying too many things."; + mes "Even though I want to give you pocket money, I can't."; + mes "Could you lighten your load and come back?"; + close; + } + mes "[Raffle Researcher]"; + mes "OK, I'll get to work right away."; + mes "If you have any business to attend to, do so."; + mes "The DNA analysis takes about 6 hours."; + mes "Why don't you go for a walk"; + mes "and come back then?"; + delitem .@item,10; + getitem 6380,1; //Mora_Coin + erasequest .@quest; + setquest 5023; + close; + } else if (checkquest(5023,PLAYTIME) == 0 || checkquest(5023,PLAYTIME) == 1) { + mes "[Raffle Researcher]"; + mes "I'm still analyzing the DNA."; + mes "The DNA analysis takes about 6 hours."; + mes "Why don't you go for a walk and come back then?"; + close; + } else { + switch(rand(1,6)) { + case 1: + case 3: + set .@quest,5021; + set .@item,6387; //Teeth_Sample + setarray .@str$[0],"tooth","teeth"; + break; + case 2: + case 4: + set .@quest,5022; + set .@item,6388; //Scale_Sample + setarray .@str$[0],"scale","scales"; + break; + case 5: + case 6: + break; + } + if (.@quest) { + mes "[Raffle Researcher]"; + mes "This is not it."; + mes "The samples that you collected belonged to a normal species."; + emotion e_swt2; + next; + mes "[Raffle Researcher]"; + mes "Must be because so many species of creatures"; + mes "have been in the bath."; + next; + mes "[Raffle Researcher]"; + mes "I'm sorry, but please re-collect the samples."; + mes "This time, the "+.@str$[1]+"... Yes."; + mes "Please bring the "+.@str$[0]+" samples."; + erasequest 5023; + setquest .@quest; + close; + } + mes "[Raffle Researcher]"; + mes "Great! These samples are surely"; + mes "from the mysterious creature."; + next; + mes "[Raffle Researcher]"; + mes "According to the analysis,"; + mes "The DNA is a mutant form of fish DNA."; + mes "I'm not sure how long this creature"; + mes "has lived in the bath,"; + mes "but this DNA is 70% evolved"; + mes "from the original fish DNA."; + next; + mes "[Raffle Researcher]"; + mes "Where did this fish come from?"; + mes "How can it survive in the warm bath water?"; + mes "After the DNA analysis,"; + mes "my head is filled with even more questions."; + next; + mes "... ... ... ... ..."; + emotion e_dots; + emotion e_dots,1; + next; + mes "[Raffle Researcher]"; + mes "The village elders say"; + mes "that the bath water comes from"; + mes "the puddles around the village."; + next; + callsub L_CheckWeight; + mes "[Raffle Researcher]"; + mes "If you get me a sample from the puddle"; + mes "to the east, at 2 o'clock from here,"; + mes "I'll tell you what to do next."; + next; + mes "[Raffle Researcher]"; + mes "You probably don't need to run around"; + mes "like you did collecting"; + mes "the bath water samples."; + set ep14_1_muk,10; + getitem 1092,1; //Empty_Cylinder + erasequest 5023; + setquest 5024; + next; + mes "[Raffle Researcher]"; + mes "If you get all 4 puddle samples at once"; + mes "it may be more convenient. However,"; + mes "there's the risk of samples being damaged or mixed up."; + mes "Therefore, I'm going to send you one place at a time. Good luck."; + close; + } + } else if (ep14_1_muk == 10) { + if (countitem(6389) == 0) { + mes "[Raffle Researcher]"; + mes "You still haven't gone to collect the puddle sample?"; + mes "Go to the puddle to the east of the village,"; + mes "and collect a sample."; + mes "It's going to be at 2 o'clock from here."; + close; + } + mes "[Raffle Researcher]"; + mes "You have the sample from the puddle to the east?"; + mes "Great job, but it's no time to rest -"; + mes "the research is almost done."; + next; + callsub L_CheckWeight; + mes "[Raffle Researcher]"; + mes "Get me a sample from the puddle from the west."; + mes "It's not completely to the west..."; + mes "The puddle should be at 7 o'clock"; + mes "from the village."; + delitem 6389,1; //Puddle_R_Sample + set ep14_1_muk,11; + getitem 1092,1; //Empty_Cylinder + changequest 5024,5025; + next; + mes "[Raffle Researcher]"; + mes "Take care not to damage the sample."; + mes "Good luck!"; + close; + } else if (ep14_1_muk == 11) { + if (countitem(6389) == 0) { + mes "[Raffle Researcher]"; + mes "You still haven't gone to collect the puddle sample?"; + mes "Go to the puddle to the west of the village,"; + mes "and collect a sample."; + mes "It's going to be at 7 o'clock from here."; + close; + } + mes "[Raffle Researcher]"; + mes "You have the sample from the puddle to the west?"; + mes "Great job, but it's no time to rest -"; + mes "the research is almost done."; + next; + callsub L_CheckWeight; + mes "[Raffle Researcher]"; + mes "Get me a sample from the puddle from the south."; + mes "The puddle to the south"; + mes "should be... at 6 o'clock from here."; + delitem 6389,1; //Puddle_R_Sample + set ep14_1_muk,12; + getitem 1092,1; //Empty_Cylinder + changequest 5025,5026; + next; + mes "[Raffle Researcher]"; + mes "I can't emphasize this enough, even if I did it 1000000000000000000000 times."; + mes "Please take care that"; + mes "the sample is not damaged."; + close; + } else if (ep14_1_muk == 12) { + if (countitem(6389) == 0) { + mes "You still haven't gone to collect the puddle sample?"; + mes "Get me a sample from the puddle from the south."; + mes "The puddle to the south is located"; + mes "at 6 o'clock from here."; + next; + mes "[Raffle Researcher]"; + mes "You know what I'm going to say?"; + mes "Be careful."; + close; + } + mes "[Raffle Researcher]"; + mes "You have the sample from the puddle to the south?"; + mes "Now only the puddle to the north"; + mes "remains to be sampled."; + next; + callsub L_CheckWeight; + mes "[Raffle Researcher]"; + mes "Please get me the sample from the puddle to the north."; + mes "It's not completely to the north."; + mes "it's at 11 o'clock from the village."; + delitem 6389,1; //Puddle_R_Sample + set ep14_1_muk,13; + getitem 1092,1; //Empty_Cylinder + changequest 5026,5027; + next; + mes "[Raffle Researcher]"; + mes "You know what I'm going to say?"; + mes "Be careful."; + close; + } else if (ep14_1_muk == 13) { + if (countitem(6389) == 0) { + mes "[Raffle Researcher]"; + mes "You still haven't gone to collect the puddle sample?"; + mes "Please get me a sample from the puddle to the north."; + mes "It's not exactly north of the village."; + mes "The puddle should be located at 11 o'clock"; + mes "from the village."; + close; + } + mes "[Raffle Researcher]"; + mes "You brought the last sample from the puddle from the north."; + mes "Great work. You've done really well."; + next; + mes "[Raffle Researcher]"; + mes "Now, I'm going to do some research"; + mes "with these samples,"; + mes "looking at the relationship between"; + mes "these puddles and the bath."; + next; + if (checkweight(6380,4) == 0) { + mes "[Raffle Researcher]"; + mes "I know that you've done a lot..."; + mes "but you are carrying too many things."; + mes "Even though I want to give you pocket money, I can't."; + mes "Could you lighten your load and come back?"; + close; + } + mes "[Raffle Researcher]"; + mes "If I finish this experiment..."; + mes "There's probably nothing else to do. While I run the experiment,"; + mes "why don't you go and entertain yourself?"; + delitem 6389,1; //Puddle_R_Sample + set ep14_1_muk,14; + getitem 6380,4; //Mora_Coin + erasequest 5027; + setquest 5028; + next; + mes "[Raffle Researcher]"; + mes "Comparison of the samples and the bath water"; + mes "will take about 12 hours."; + close; + } else if (ep14_1_muk == 14) { + if (checkquest(5028,PLAYTIME) == 0 || checkquest(5028,PLAYTIME) == 1) { + mes "[Raffle Researcher]"; + mes "What? You're here? Well..."; + next; + mes "[Raffle Researcher]"; + mes "But the sample studies have not been finished."; + mes "This is an experiment for the final result,"; + mes "so don't be too hasty."; + mes "I think the research will take about 12 hours."; + next; + mes "[Raffle Researcher]"; + mes "Come back then."; + close; + } + mes "[Raffle Researcher]"; + mes "You're here? Finally,"; + mes "the experiment results are all in."; + mes "Do you want to look at the results?"; + next; + switch(select("Actually, I don't want to.:Look at the results.")) { + case 1: + mes "[Raffle Researcher]"; + mes "Good thinking. Actually, it may hurt"; + mes "regular people's brains to look at it."; + mes "I suppose it's time for your reward"; + mes "for helping me out so much."; + next; + mes "[Raffle Researcher]"; + mes "Did I talk to you about the reward before the experiment?"; + mes "That you won't be sorry that you helped out..."; + next; + break; + case 2: + mes "[Raffle Researcher]"; + mes "You're curious about the results? Really???"; + mes "OK, here it is."; + next; + callsub L_ShowReport; + mes "[Raffle Researcher]"; + mes "There are no volcanoes around the area"; + mes "and no record of volcanoes in the past,"; + mes "but the water temperature is that high..."; + mes "Isn't it surprising?"; + next; + mes "[Raffle Researcher]"; + mes "The ingredients are... yes."; + mes "There are certainly substances that are beneficial for you humans."; + mes "But, there are also substances"; + mes "that are fatal to us Raffles,"; + mes "or other races."; + next; + mes "[Raffle Researcher]"; + mes "And if you look at the electric conductivity,"; + mes "it is quite higher than that of the average water."; + mes "My theory is that"; + mes "this must be the cause of the mysterious power."; + mes "That's what I'm thinking about."; + mes "Anyhow."; + next; + mes "[Raffle Researcher]"; + mes "There is something at work that science cannot explain"; + mes "in the bath water..."; + mes "Take the unidentified creature, for instance."; + mes "How strange is it that a fish can live"; + mes "in such warm water?"; + next; + mes "[Raffle Researcher]"; + mes "I'm not satisfied with the research results and conclusions."; + mes "I guess in the end,"; + mes "it will remain a mystery..."; + next; + mes "[Raffle Researcher]"; + mes "I suppose it's time for your reward"; + mes "for helping me out so much."; + next; + mes "[Raffle Researcher]"; + mes "Did I talk to you about the reward before the experiment?"; + mes "That you won't be sorry that you helped out..."; + next; + break; + } + mes "[Raffle Researcher]"; + mes "I was thinking about what you would want"; + mes "for your reward... and I felt"; + mes "a little... sad."; + next; + mes "[Raffle Researcher]"; + mes "... ... ... ..."; + next; + mes "[Raffle Researcher]"; + mes "During our short time here together working on these projects,"; + mes "I sent you all over the place."; + mes "It must've been hard, but you didn't complain at all."; + mes "And unlike some of the other guys I've had,"; + mes "you never skipped work."; + next; + mes "[Raffle Researcher]"; + mes "I suppose I've grown fond of you,"; + mes "so that it saddens me to say goodbye..."; + next; + mes "[Raffle Researcher]"; + mes "But thank you anyhow. I've been researching for a while,"; + mes "but I've never met such an excellent research assistant as you."; + next; + if (MaxWeight - Weight < 100 || checkweight(1092,1) == 0) { + mes "[Raffle Researcher]"; + mes "Hmm? By the way..."; + mes "You are carrying too much weight."; + mes "Could it be because you are also sad"; + mes "about parting ways?"; + next; + mes "[Raffle Researcher]"; + mes "With this weight, I can't give you a reward!"; + close; + } + mes "[Raffle Researcher]"; + mes "The best research assistant in my life..."; + mes "is you, "+strcharinfo(0)+"!!!"; + set ep14_1_muk,15; + completequest 5028; + getexp 1000000,4000000; + getitem 6380,30; //Mora_Coin + next; + mes "[Raffle Researcher]"; + mes "If we happen to run into each other again,"; + mes "let's work on a research project once more."; + close; + } else if (ep14_1_muk == 15) { + mes "[Raffle Researcher]"; + mes "Hmm? No?... What are you doing here?"; + next; + mes "[Raffle Researcher]"; + mes "Could it be that you suddenly want to look at"; + mes "the research report???"; + next; + switch(select("Look at the report.:I came to say hello.")) { + case 1: + mes "[Raffle Researcher]"; + mes "Haven't I shown it to you before?"; + next; + mes "[Raffle Researcher]"; + mes "... ... ... ..."; + emotion e_dots; + next; + mes "[Raffle Researcher]"; + mes "Maybe I haven't shown you."; + mes "Sorry about that. So you wanted to see it so badly"; + mes "that you came back to see me?"; + mes "Great! Here it is."; + next; + while(1) { + callsub L_ShowReport; + mes "[Raffle Researcher]"; + mes "This concludes the report of"; + mes "Mora Village's mysterious bath."; + mes "You want to look again?"; + emotion e_what; + next; + switch(select("Look again.:Don't look again.")) { + case 1: + mes "[Raffle Researcher]"; + mes "Sure... As you wish!!"; + next; + break; + case 2: + mes "[Raffle Researcher]"; + mes "Goodbye. Come by any time,"; + mes "if you want to look at the results again."; + mes "You're always welcome here."; + close; + } + } + case 2: + mes "[Raffle Researcher]"; + mes "Oh, You came to say hi. I see."; + mes "Long time no see, "+strcharinfo(0)+"."; + next; + mes "[Raffle Researcher]"; + mes "I've been telling you that I lucked out in picking you as my research assistant."; + mes "Come by any time,"; + mes "if you want to look at the results again."; + mes "You're always welcome here."; + close; + } + } else { + mes "[Raffle Researcher]"; + mes "Hmm? I'm Researcher Inffle."; + mes "Who are you?"; + close; + } + end; +L_ShowReport: + mes "[Experimental Results]"; + mes "*** Researcher - Inffle"; + mes "*** Research Assistant - "+strcharinfo(0); + mes "””"; + mes ""; + mes "*** Bath of Mora Village"; + mes "””"; + mes ""; + mes "To investigate the mysterious power of the bath water"; + mes "and to find out ways to better utilize"; + mes "the water."; + mes "””"; + mes ""; + mes "1. Obtained an unidentified DNA sample."; + mes "Obtained a sample of an unidentified DNA,"; + mes "and collected more samples to look further into it."; + mes "””"; + mes "2. A comparison analysis on the unidentified DNA"; + mes "Concluded that the DNA belongs to"; + mes "an unidentified creature living in the bath water."; + mes "combine and result in"; + mes "from the swordfish DNA."; + mes "””"; + mes "3. Research on the puddles around the village"; + mes "From the four puddles around the village,"; + mes "confirmed that the testing substances were"; + mes "distributed evenly across the puddles."; + mes "It is thought that the four puddles"; + mes "combine and result in"; + mes "the mysterious power."; + mes "””"; + mes ""; + mes "*** Temperature ***** 33.5° "; + mes "*** PH ************ 9.8"; + mes "*** Solid residues *** 176"; + mes "*** K+ ************ 0,23"; + mes "*** Ca++ ********** 1.83"; + mes "*** Cl- *********** 26.2"; + mes "*** HCO3- ********* 31.0"; + mes "*** H2S *********** 1.7"; + mes "*** Na++ ********** 51.9"; + mes "*** Mg+ *********** 0.03"; + mes "*** SO4- ********** 5.0"; + mes "*** F ************* 12.8"; + mes "*** SiO2 ********** 23.9"; + mes "*** Li ************ 0.06"; + mes "*** CO3+ ********** 22.8"; + mes "*** Sr ************ 0.04"; + mes "*** Ge ************ 0.004"; + mes "*** T-solids ****** 165"; + mes "*** Electric conductivity **** 500"; + mes "*** Longitude ********** 4.6"; + next; + return; +L_CheckWeight: + if (MaxWeight - Weight < 100 || checkweight(1092,1) == 0) { + mes "[Raffle Researcher]"; + mes "You are carrying too much weight."; + mes "I can't give you the sample tube."; + mes "Why don't you lighten your load and come back?"; + close; + } + return; +} + +mora,114,79,0 script Black Shadow#ep14_muk 844,{ + if (checkweight(1201,1) == 0 || MaxWeight - Weight < 500) { + mes "^FF0000- Warning message -"; + mes "- Hang on there!! -"; + mes "- You have too many items -"; + mes "- to receive any more items. -"; + mes "- Please lighten your load -"; + mes "- and try again. -^000000"; + close; + } + if (BaseLevel < 100) { + mes "Something looks at you from head to toe, and disappears, mocking you."; + close2; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + end; + } + set .@playtime, checkquest(5029,PLAYTIME); + if (.@playtime == 0 || .@playtime == 1) { + mes "You see a dark hole. As you show interest, something disappears quickly into the dark hole."; + close2; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + end; + } else if (.@playtime == 2) + erasequest 5029; + if (ep14_1_goki == 30) { + if (checkquest(5030) == -1 && checkquest(5031) == -1 && checkquest(5032) == -1 && checkquest(5033) == -1 && checkquest(5034) == -1) { + mes "[Unidentified creature]"; + mes "Arrgghh!!!"; + mes "Why you bother me."; + mes "You stop bullying me."; + next; + if(select("Bully anyway.:I'll stop.") == 1) { + emotion e_sob; + set ep14_1_goki,0; + close2; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + end; + } + mes "[Unidentified creature]"; + mes "You... Good."; + mes "Everybody calls me monster."; + mes "Hit me. Bully. Me tired."; + next; + mes "[Fishee]"; + mes "My name Fishee."; + mes "Dad name me."; + next; + mes "... ... ... ... ..."; + next; + mes "He appears to be rambling."; + next; + mes "[Fishee]"; + mes "Bully. Fun. Every day."; + mes "I talk. Still bully."; + next; + mes "[Fishee]"; + mes "You... Good. Help Fishee?"; + next; + if(select("Don't help.:Help.") == 1) { + emotion e_sob; + set ep14_1_goki,0; + close2; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + end; + } + mes "[Fishee]"; + mes "You good. Good!"; + next; + mes "[Fishee]"; + mes "Me didn't live here."; + mes "Me lived puddle."; + mes "Puddle. Live there."; + next; + mes "[Fishee]"; + mes "Me sleep weird."; + mes "Wake up one day."; + mes "Here, bath."; + next; + mes "[Fishee]"; + mes "Don't know how go home."; + mes "Me just live here."; + mes "Grow big. Hole small."; + mes "Can't get in."; + next; + mes "[Fishee]"; + mes "Me miss family. Me want to see family."; + mes "You good. How my family do."; + mes "Bring me. Good."; + next; + select("How would I know who is your family?"); + mes "[Fishee]"; + mes "Us fish stupid."; + mes "Stupid. But know family name."; + next; + mes "[Fishee]"; + mes "Family know name Fishee. Family come."; + next; + mes "[Fishee]"; + mes "Please. In puddle."; + mes "You tell me my family do okay."; + setquest 5030+rand(4); //5030,5031,5032,5033 + close; + } else if (checkquest(5030) > -1 || checkquest(5031) > -1 || checkquest(5032) > -1 || checkquest(5033) > -1) { + mes "[Fishee]"; + mes "Please. In puddle."; + mes "You tell me my family do okay."; + next; + mes "[Fishee]"; + mes "You forgot me name?"; + next; + if(select("Please tell me your name again!:I know your name.") == 1) { + mes "[Fishee]"; + mes "Your memory, like fish."; + mes "Stupid. I talk."; + mes "My name Fishee, Fishee!!"; + next; + } + mes "[Fishee]"; + mes "Please. In puddle."; + mes "You tell me my family do okay."; + close; + } else if (checkquest(5034) > -1 && checkquest(5034) < 2) { + if (MaxWeight - Weight < 100 || checkweight(5792,1) == 0) { + mes "[Fishee]"; + mes "You have lots."; + mes "I give. To you."; + mes "Empty bag. Come back."; + close; + } + mes "[Fishee]"; + mes "You told me my family ok. Thank you."; + mes "I know thank you. Fish."; + mes "Re... Don't know word."; + next; + select("Perhaps... Reward??"); + mes "[Fishee]"; + mes "Yes. That. You good."; + mes "Smart. Give you reward."; + mes "I know thank you. Fish."; + next; + mes "[Fishee]"; + mes "This, I got from bath."; + mes "No. Someone left it."; + mes "... ... Good guy. I give you."; + completequest 5034; + getitem 5792,1; //Fish_Pin + close; + } else if (checkquest(5034) == 2) { + mes "[Fishee]"; + mes "You... I saw. Feeling. I saw. Feeling."; + mes "You... Name?"; + next; + input .@inputstr$; + mes "[Fishee]"; + mes .@inputstr$+" do."; + mes "No know. No remember.."; + mes "Who.. you... are?"; + close; + } + } + set .@weapon$, ((getequipisequiped(EQI_HAND_R))?getequipname(EQI_HAND_R):"Bare handed"); + set .@pc_hp, 200; + set .@npc_hp, 200; + setarray .@skills$[0],"Midsection punch","Headbutt","Wiggle wiggle","Screw punch","Mumble muble"; + mes "The unidentified creature is attacking. What will you do?"; + next; + while(1) { + switch(select("Attack with a weapon.:Attack using a skill.:Attack using teeth.:Run away in fear.")) { + case 1: // Weapon + set .@p_damage,10; + set .@pc_attack, rand(1,10); + mes "["+strcharinfo(0)+"'s Attack]"; + switch(.@pc_attack) { + // Miss. + case 3: + mes "You attempt to attack with your recent expensive purchase ^FF0000["+.@weapon$+"]^000000, but the unidentified creature rapidly dodged."; + break; + case 6: + mes "By mistake, you use ^FF0000["+.@weapon$+"]^000000 that Holgren has thrown your way to attack the unidentified creature, but the creature foresaw the attack and dodged."; + break; + case 9: + mes "You use your precious ^FF0000[+"+.@weapon$+"+]^000000 to attack the unidentified creature, but the creature pulled back and dodged your attack."; + break; + // Hit. + default: + specialeffect EF_HIT1; + set .@npc_hp, .@npc_hp - .@p_damage; + switch(.@pc_attack) { + case 1: set .@str$,"With your precious ^FF0000["+.@weapon$+"]^000000, you attacked the unidentified creature. The weapon pierced the creature's body."; break; + case 2: set .@str$,"By mistake, you use ^FF0000["+.@weapon$+"]^000000 that Holgren has thrown your way to attack the unidentified creature. With a thud, the unidentified creature's body is swaying."; break; + case 4: set .@str$,"You attempt to attack with your recent expensive purchase ^FF0000["+.@weapon$+"]^000000. You hit the unidentified creature's body with a thud."; break; + case 5: set .@str$,"You use a borrowed ^FF0000["+.@weapon$+"]^000000 to attack the unidentified creature, but the weapon slipped. But the weapon flies off and pierces the creature's body."; break; + case 7: set .@str$,"With your precious ^FF0000["+.@weapon$+"]^000000, you attacked the unidentified creature. It was as if the weapon was part of your body."; break; + case 8: set .@str$,"You use your lucky ^FF0000["+.@weapon$+"]^000000 to attack the unidentified creature."; break; + case 10: set .@str$,"You use a friend's ^FF0000["+.@weapon$+"]^000000 to attack the unidentified creature."; break; + } + mes .@str$+" ^FF0000["+.@p_damage+"]^000000 damage inflicted."; + break; + } + next; + break; + case 2: // Skill + set .@p_damage,20; + set .@pc_attack, rand(1,6); + set .@skillname$, .@skills$[rand(5)]; + mes "["+strcharinfo(0)+"'s Attack]"; + switch(.@pc_attack) { + // Miss. + case 2: + mes "You use skill ^0000FF["+.@skillname$+"]^000000 but you couldn't concentrate, and failed to use the skill properly."; + break; + case 4: + mes "You use skill ^0000FF["+.@skillname$+"]^000000 with all your might, but the unidentified creature dodged lightly and mocked you."; + break; + case 6: + mes "You use skill ^0000FF["+.@skillname$+"]^000000 to attack the creature, but he got out of sight and you failed to use the skill."; + break; + // Hit. + default: + specialeffect EF_BASH; + set .@npc_hp, .@npc_hp - .@p_damage; + switch(.@pc_attack) { + case 1: set .@str$, "With an attack so fast and furious, the creature is too stunned to move."; break; + case 3: set .@str$, "The creature dodged, but you foresaw his movements and targeted accurately."; break; + case 5: set .@str$, "Your skill flew in a perfect parabola and hit the creature exactly."; break; + } + mes "You use skill ^0000FF["+.@skillname$+"]^000000 to attack the unidentified creature. "+.@str$+" ^FF0000["+.@p_damage+"]^000000 damage inflicted."; + break; + } + next; + break; + case 3: // Tooth + set .@p_damage,50; + set .@pc_attack, rand(1,10); + mes "["+strcharinfo(0)+"'s Attack]"; + if (.@pc_attack == 4 || .@pc_attack == 7) { + specialeffect EF_HIT1; + set .@npc_hp, .@npc_hp - .@p_damage; + mes "You use your well-groomed teeth to bite the unidentified creature hard until your teeth sink into its flesh. ^FF0000["+.@p_damage+"]^000000 damage inflicted."; + } else + mes "You use your steel-like teeth to bite the unidentified creature, but the frightened creature dodged. He stares at you with strange eyes."; + next; + break; + case 4: // Run + mes "You get scared of the unidentified creature, and attempt to run."; + next; + mes "["+strcharinfo(0)+"'s Escape]"; + if (rand(1,2) == 1) { + mes "Fortunately, the unidentified creature did not come after you."; + close; + } else { + mes "When you attempt to run away, the unidentified creature sees you and attacks. You fail to escape."; + next; + specialeffect2 EF_HIT1; + mes "The creature slams you with its tail. It's so painful that a tear rolls out of your eyes. ^FF000010^000000 damaged received."; + set .@pc_hp, .@pc_hp - 10; + next; + // Unofficial check, but it's needed here. + callsub L_CheckPCAlive, .@pc_hp; + } + break; + } + if (.@npc_hp <= 0) { + mes "You won. The unidentified creature is unconscious."; + next; + if (checkquest(5016) > -1 && countitem(6385) == 0) { + mes "What will you do?"; + next; + select("Look for the research tools."); + if (checkweight(6385,1) == 0) { + mes "You attempted to look for the research tools,"; + mes "but you are carrying too many things."; + mes "You'd better lighten your load"; + mes "and come back."; + close2; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + end; + } + mes "Found Researcher Raffle's ^0000FF Research tool ^000000."; + set ep14_1_goki, ep14_1_goki+1; + getitem 6385,1; //Research_Tool_Bag + setquest 5029; + next; + mes "The creature wakes up and disappears into the dark hole."; + close2; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + end; + } else if (checkquest(5017) > -1) { + mes "How will you bully the creature?"; + next; + input .@inputstr$; + mes "You do ^0000FF"+.@inputstr$+"^000000 to bully the unidentified creature."; + next; + setquest 5029; + switch(ep14_1_muk) { + case 3: + mes "You bully the unidentified creature. This is kind of fun."; + break; + case 4: + mes "You bully the unidentified creature for the second time. It's definitely entertaining."; + break; + case 5: + mes "You bully the unidentified creature for the third time. It's fun, but now it is time to stop."; + changequest 5017,5018; + break; + } + set ep14_1_muk, ep14_1_muk+1; + set ep14_1_goki, ep14_1_goki+1; + close2; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + end; + } else { + mes "What will you do?"; + next; + if(select("Check the body of the unidentified creature.:Leave.") == 2) { + setquest 5029; + set ep14_1_goki, ep14_1_goki+1; + close2; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + end; + } + if (rand(1,30) == 7) { + if (checkweight(6380,1) == 0) { + mes "While you were checking the body of the unidentified creature, your fingers touch something. You got lucky, but due to your heavy load you failed to obtain a ^0000FF Mora Coin^000000."; + set ep14_1_goki, ep14_1_goki+1; + setquest 5029; + close2; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + end; + } + mes "While you were checking the body of the unidentified creature, your fingers touch something. Lucky. Obtained a ^0000FF Mora Coin^000000."; + set ep14_1_goki, ep14_1_goki+1; + getitem 6380,1; //Mora_Coin + setquest 5029; + next; + mes "The creature wakes up and disappears into the dark hole."; + } else { + mes "As soon as you touch the creature's body, it wakes up and disappears into the dark hole."; + set ep14_1_goki, ep14_1_goki+1; + setquest 5029; + } + close2; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + end; + } + } + mes "[ Current Progress ]"; + mes strcharinfo(0)+" HP = "+.@pc_hp; + mes "Unidentified Creature HP = "+.@npc_hp; + next; + mes "[Attack of the unidentified creature]"; + set .@npc_attack, rand(1,3); + switch(.@npc_attack) { + case 1: + set .@n_damage,10; + mes "The unidentified creature shoots a stream of bath water."; + break; + case 2: + set .@n_damage,20; + mes "The unidentified creature dashes at you with great speed. It appears to be attempting a headbutt."; + break; + case 3: + set .@n_damage,50; + mes "The unidentified creature runs at you with its teeth bared. It appears to be attempting to bite."; + break; + } + next; + mes "What will you do?"; + next; + switch(select("... ... ...:Dodge.:Block.:It's too much. Run away.")) { + case 1: + switch(.@npc_attack) { + case 1: + specialeffect2 EF_ICEARROW; + mes "You stand still. The stream of water hits your face squarely. Your mind is clear in an instant. ^FF0000["+.@n_damage+"]^000000 damage received."; + break; + case 2: + specialeffect2 EF_BASH; + mes "You stand still. The creature headbutts you squarely. Your mind is clear in an instant. ^FF0000["+.@n_damage+"]^000000 damage received."; + break; + case 3: + specialeffect2 EF_HIT1; + mes "You stand still. While you were standing stupidly, the creature comes near and bites you mercilessly. Your mind is clear in an instant. ^FF0000["+.@n_damage+"]^000000 damage received."; + break; + } + set .@pc_hp, .@pc_hp - .@n_damage; + next; + break; + case 2: + switch(.@npc_attack) { + case 1: + set .@miss, rand(1,5); + mes "[Attack of the unidentified creature]"; + switch(.@miss) { + // Miss. + case 1: + mes "The unidentified creature shoots a stream of water at you, but you dodge it easily by tilting your body."; + break; + case 3: + mes "The unidentified creature shoots a stream of water at you, but you dodge it while picking your nose."; + break; + // Hit. + default: + specialeffect2 EF_ICEARROW; + set .@pc_hp, .@pc_hp - .@n_damage; + switch(.@miss) { + case 2: set .@str$,"face"; break; + case 4: set .@str$,"stomach"; break; + case 5: set .@str$,"arm"; break; + } + mes "The stream of water hits your "+.@str$+" squarely. ^FF0000["+.@n_damage+"]^000000 damage received."; + break; + } + next; + break; + case 2: + set .@miss, rand(1,10); + mes "[Attack of the unidentified creature]"; + switch(.@miss) { + // Miss. + case 1: + mes "The unidentified creature dashes at you attempting a headbutt, but you are not the one to succumb to such an attack."; + break; + case 3: + mes "The unidentified creature dashes at you attempting a headbutt, but you move slightly to dodge the attack."; + break; + case 5: + mes "The unidentified creature dashes at you attempting a headbutt, but you dodge the attack while picking your nose."; + break; + case 7: + mes "The unidentified creature dashes at you attempting a headbutt, but you dodge the attack easily."; + break; + // Hit. + default: + specialeffect2 EF_BASH; + set .@pc_hp, .@pc_hp - .@n_damage; + switch(.@miss) { + case 2: set .@str$,"With a thud, you can feel intense pain."; break; + case 4: set .@str$,"*thud* Your back seems to give way."; break; + case 6: set .@str$,"The creature's attack hits you in the shoulder."; break; + case 8: set .@str$,"The attack is like an arrow."; break; + case 9: set .@str$,"The attack was fast and accurate."; break; + case 10: set .@str$,"It hits your hand with a thud."; break; + } + mes "The unidentified creature dashes at you and headbutts. "+.@str$+" ^FF0000["+.@n_damage+"]^000000 damage received."; + break; + } + next; + break; + case 3: + set .@miss, rand(1,10); + mes "[Attack of the unidentified creature]"; + switch(.@miss) { + // Miss. + case 1: + mes "The unidentified creature runs at you with its teeth bared, but you dodge the attack sneering."; + break; + case 3: + mes "The unidentified creature runs at you with its teeth bared, but you dodge the attack by moving slightly."; + break; + case 5: + mes "The unidentified creature runs at you with its teeth bared, but you dodge the attack while stretching."; + break; + case 7: + mes "The unidentified creature runs at you with its teeth bared, but you dodge the attack while counting Zenies."; + break; + case 8: + mes "The unidentified creature runs at you with its teeth bared, but you dodge the attack lightly."; + break; + case 9: + mes "The unidentified creature runs at you with its teeth bared, but you dodge the attack sneering."; + break; + // Hit. + default: + specialeffect2 EF_HIT1; + set .@pc_hp, .@pc_hp - .@n_damage; + switch(.@miss) { + case 2: set .@str$,"leg. Its sharp teeth penetrate your legs."; break; + case 4: set .@str$,"arm. Its sharp teeth penetrate your arm."; break; + case 6: set .@str$,"toe. You feel like your toe is being cut off."; break; + case 10: set .@str$,"finger. You feel like your finger is being cut off."; break; + } + mes "The unidentified creature runs at you with its teeth bared, and bites your "+.@str$+" ^FF0000["+.@n_damage+"]^000000 damage received."; + break; + } + next; + break; + } + break; + case 3: + set .@defend, rand(1,10); + switch(.@npc_attack) { + case 1: + if (.@defend == 3 || .@defend == 6) { + set .@n_damage, .@n_damage / 2; + specialeffect2 EF_GUARD; + } else + specialeffect2 EF_ICEARROW; + set .@pc_hp, .@pc_hp - .@n_damage; + mes "[Defense of "+strcharinfo(0)+"]"; + switch(.@defend) { + // Blocked. + case 3: set .@str$,"You block the stream of water with your strong butt. Feels refreshing. HP reduced only by half."; break; + case 6: set .@str$,"You block the stream of water with your strong hands. Your hands sting a little. HP reduced only by half."; break; + // Not blocked. + case 1: set .@str$,"You try to block the stream of water with your strong butt, but it's too late."; break; + case 2: set .@str$,"You try to block the stream of water with your big gut, but to no avail."; break; + case 4: set .@str$,"You try to block the stream of water with your gathered hands, but the creature targets a different place."; break; + case 5: set .@str$,"You try to block the stream of water with your strong hands, but you fail."; break; + case 7: set .@str$,"You try to block the stream of water with arms crossed, but you fold them wrong."; break; + case 8: set .@str$,"You try to block the stream of water with your rock-like head, but it was not possible."; break; + case 9: set .@str$,"You try to block the stream of water with your solid muscles, but it was not possible."; break; + case 10: set .@str$,"You try to block the stream of water with your strong feet, but your effort was wasted."; break; + } + mes .@str$+" ^FF0000["+.@n_damage+"]^000000 damage received."; + next; + break; + case 2: + if (.@defend == 1 || .@defend == 3 || .@defend == 5 || .@defend == 7) { + set .@n_damage, .@n_damage / 2; + specialeffect2 EF_GUARD; + } else + specialeffect2 EF_BASH; + set .@pc_hp, .@pc_hp - .@n_damage; + mes "[Defense of "+strcharinfo(0)+"]"; + switch(.@defend) { + // Blocked. + case 1: set .@str$,"You block the dash attack with your fat butt. Your butt is world class. HP reduced only by half."; break; + case 3: set .@str$,"You block the dash attack with your big gut. Your gut is world class. HP reduced only by half."; break; + case 5: set .@str$,"You block the dash attack with your strong hands. Your hands are world class. HP reduced only by half."; break; + case 7: set .@str$,"The unidentified creature dashed with lightning speed, but you easily block the attack with your big gut. Your gut is world class. HP reduced only by half."; break; + // Not blocked. + case 2: set .@str$,"You try to block the dash attack with your fat butt, but miss and get hit in an unmentionable place."; break; + case 4: set .@str$,"You try to block the dash attack with your big gut, but your gut isn't big enough to absorb the impact."; break; + case 6: set .@str$,"You try to block the dash attack with arms crossed, but you feel an incredible force."; break; + case 8: set .@str$,"You try to block the dash attack, to no avail."; break; + case 9: set .@str$,"You try to block the dash attack with your strong hands, to no avail."; break; + case 10: set .@str$,"You try to block the dash attack with your durable feet, but the pain woke you up."; break; + } + mes .@str$+" ^FF0000["+.@n_damage+"]^000000 damage received."; + next; + break; + case 3: + if (.@defend == 2 || .@defend == 4 || .@defend == 6 || .@defend == 8) { + set .@n_damage, .@n_damage / 2; + specialeffect2 EF_GUARD; + } + set .@pc_hp, .@pc_hp - .@n_damage; + mes "[Defense of "+strcharinfo(0)+"]"; + switch(.@defend) { + // Blocked. + case 2: set .@str$,"but you block its attack with a branch nearby. HP reduced only by half."; break; + case 4: set .@str$,"but you block its attack with a weapon. HP reduced only by half."; break; + case 6: set .@str$,"but you block its attack using skill ^0000FFFriend Shield^000000. HP reduced only by half."; break; + case 8: set .@str$,"but you block its attack using a book you always carry around. HP reduced only by half."; break; + // Not blocked. + case 1: set .@str$,"and bites your arm."; break; + case 3: set .@str$,"and bites your leg."; break; + case 5: set .@str$,"and bites your shoulder."; break; + case 7: set .@str$,"and bites your finger."; break; + case 9: set .@str$,"and bites your finger."; break; + case 10: set .@str$,"and bites your toe."; break; + } + mes "The unidentified creature runs at you with its teeth bared, "+.@str$+" ^FF0000["+.@n_damage+"]^000000 damage received."; + next; + break; + } + break; + case 4: + mes "You get scared of the unidentified creature, and attempt to run."; + next; + mes "["+strcharinfo(0)+"'s Escape]"; + if (rand(1,2) == 1) { + mes "Fortunately ^BF2C15Unidentified creature^000000"; + mes "did not come after you."; + close; + } else { + mes "When you attempt to run away, the unidentified creature sees you and attacks."; + mes "You fail to escape."; + next; + mes "The creature slams you with its tail. It's so painful that a tear rolls out of your eyes. ^FF000010^000000 damaged received."; + set .@pc_hp, .@pc_hp - 10; + next; + } + break; + } + callsub L_CheckPCAlive, .@pc_hp; + mes "[ Current Progress ]"; + mes strcharinfo(0)+" HP = "+.@pc_hp; + mes "Unidentified Creature HP = "+.@npc_hp; + next; + } + end; +L_CheckPCAlive: + if (getarg(0) <= 0) { + mes "You lost to the unidentified creature. Your mind goes blank and you faint."; + next; + mes "You leave the bath with somebody's help."; + percentheal -99,0; + donpcevent "Black Shadow#ep14_muk::OnDisable"; + warp "mora",31,132; + end; + } + return; +OnInit: + disablenpc "Black Shadow#ep14_muk"; + end; +OnEnable: + enablenpc "Black Shadow#ep14_muk"; + disablenpc "???#ep14_muk01"; + disablenpc "???#ep14_muk02"; + disablenpc "???#ep14_muk03"; + disablenpc "???#ep14_muk04"; + disablenpc "???#ep14_muk05"; + end; +OnDisable: + disablenpc "Black Shadow#ep14_muk"; + donpcevent "Black Shadow#ep14_muk::OnFullon"; + mapannounce "mora","You can now use the mysterious power of bath water.",bc_map,"0xFFFF00"; //FW_NORMAL 12 0 0 + end; +OnFullon: + donpcevent "???#ep14_muk01::OnReset"; + donpcevent "???#ep14_muk02::OnReset"; + donpcevent "???#ep14_muk03::OnReset"; + donpcevent "???#ep14_muk04::OnReset"; + donpcevent "???#ep14_muk05::OnReset"; + end; +} + +- script ???#mora -1,{ + if (checkquest(5019) > -1) { + mes "You find an area emitting a distinct aura."; + mes "You may be able to collect bath water samples."; + mes "What will you do?"; + next; + if(select("Collect samples.:Leave.") == 2) { + donpcevent strnpcinfo(0)+"::OnDisable"; + end; + } + if (countitem(6386) >= 10) { + mes "You will not need additional samples."; + close2; + donpcevent strnpcinfo(0)+"::OnDisable"; + end; + } + if (countitem(1092) == 0) { + mes "To obtain a sample, you need a sample tube."; + close2; + donpcevent strnpcinfo(0)+"::OnDisable"; + end; + } + mes "Collecting samples."; + next; + progressbar "ffff00",3; + if (!rand(3)) { + if (checkweight(6386,1) == 0) { + mes "You have so many items"; + mes "that it is difficult to collect samples."; + mes "You will have to lighten your load and come back."; + close2; + donpcevent strnpcinfo(0)+"::OnDisable"; + end; + } + mes "Bath water sample collection complete."; + delitem 1092,1; //Empty_Cylinder + getitem 6386,1; //Bathtub_R_Sample + } else { + mes "Bath water sample collection failed."; + percentheal 5,5; + } + close2; + donpcevent strnpcinfo(0)+"::OnDisable"; + end; + } else if (checkquest(5021) > -1 || checkquest(5022) > -1) { + if (checkquest(5021) > -1) { + set .@str$,"tooth"; + set .@item,6387; //Teeth_Sample + } else { + set .@str$,"scale"; + set .@item,6388; //Scale_Sample + } + mes "Something is shining in the water."; + mes "You may be able to collect the unidentified creature's "+.@str$+" samples."; + mes "What do you want to do?"; + next; + if(select("Look further.:Leave.") == 2) { + donpcevent strnpcinfo(0)+"::OnDisable"; + end; + } + if (countitem(.@item) >= 10) { + mes "You will not need additional samples."; + close2; + donpcevent strnpcinfo(0)+"::OnDisable"; + end; + } + progressbar "ffff00",3; + if (!rand(3)) { + if (checkweight(.@item,1) == 0) { + mes "You have so many items"; + mes "that it is difficult to collect samples."; + mes "You will have to lighten your load and come back."; + close; + } + mes "Obtained a "+.@str$+" sample"; + mes "of the unidentified creature."; + getitem .@item,1; + } else + mes "You thought you saw it on the ground, but it was an illusion."; + close2; + donpcevent strnpcinfo(0)+"::OnDisable"; + end; + } else { + mes "???"; + next; + select("???"); + mes "???"; + close; + } + end; +OnEnable: + enablenpc strnpcinfo(0); + stopnpctimer; + end; +OnDisable: + disablenpc strnpcinfo(0); + initnpctimer; + end; +OnReset: + if (rand(2)) + donpcevent strnpcinfo(0)+"::OnEnable"; + else + initnpctimer; + end; +OnTimer10000: +OnTimer20000: +OnTimer30000: +OnTimer40000: +OnTimer50000: + if (rand(2)) + donpcevent strnpcinfo(0)+"::OnEnable"; + end; +OnTimer60000: + donpcevent strnpcinfo(0)+"::OnEnable"; + end; +OnTouch: + if (checkquest(5034) == 2 || ep14_1_muk == 0 || rand(5)) { + percentheal 5,5; + end; + } + set .@playtime, checkquest(5029,PLAYTIME); + if (.@playtime == 0 || .@playtime == 1) { + percentheal 5,5; + end; + } else if (.@playtime == 2) { + erasequest 5029; + end; + } else { + mapannounce "mora","You can no longer use the mysterious power of the bath water.",bc_map,"0xFFFF00"; //FW_NORMAL 12 0 0 + mes "^FF0000Something appeared.^000000"; + mes "^FFFF00You cannot use the mysterious power of the bath water.^000000"; + close2; + donpcevent "Black Shadow#ep14_muk::OnEnable"; + end; + } +} +mora,108,86,0 duplicate(???#mora) ???#ep14_muk01 844,2,2 +mora,107,82,0 duplicate(???#mora) ???#ep14_muk02 844,2,2 +mora,113,84,0 duplicate(???#mora) ???#ep14_muk03 844,2,2 +mora,116,81,0 duplicate(???#mora) ???#ep14_muk04 844,2,2 +mora,118,86,0 duplicate(???#mora) ???#ep14_muk05 844,2,2 + +- script #mora_puddle -1,{ + set .@i, atoi(charat(strnpcinfo(2),9)); + + // This script has a lot of checks, + // so arrays are only set when used. + setarray .@quest1[1],5024,5025,5026,5027; + setarray .@dir$[1],"east","west","south","north"; + + if (checkquest(.@quest1[.@i]) > -1) { + if (countitem(6389) == 0) { + mes "This appears to be the puddle to the "+.@dir$[.@i]; + mes "that the researcher talked about."; + mes "Will you collect a sample?"; + next; + if(select("Collect a sample.:Don't collect a sample.") == 2) + close; + if (countitem(1092) == 0) { + mes "You have no empty sample tubes."; + close; + } + progressbar "ffff00",5; + if (checkweight(6389,1) == 0) { + mes "You have so many items"; + mes "that it is difficult to collect samples."; + mes "You will have to lighten your load and come back."; + close; + } + mes "You have collected a sample from the puddle to the "+.@dir$[.@i]+"."; + delitem 1092,1; //Empty_Cylinder + getitem 6389,1; //Puddle_R_Sample + close; + } else { + mes "You already have a sample."; + close; + } + } + + set .@quest1[0], .@quest1[.@i]; + set .@dir$[0], .@dir$[.@i]; + deletearray .@quest1[.@i],1; + deletearray .@dir$[.@i],1; + + if (checkquest(.@quest1[1]) > -1 || checkquest(.@quest1[2]) > -1 || checkquest(.@quest1[3]) > -1) { + for(set .@j,1; .@j<=3; set .@j,.@j+1) { + if (checkquest(.@quest1[.@j]) > -1) + break; + } + mes "This is not the puddle to the "+.@dir$[.@j]+"."; + close; + } + + setarray .@quest2[1],5030,5031,5032,5033; + set .@quest2[0], .@quest2[.@i]; + deletearray .@quest2[.@i],1; + + if (ep14_1_goki == 30 && checkquest(.@quest2[0]) > -1) { + mes "You arrived at the puddle to the "+.@dir$[0]+"."; + mes "You should look for the unidentified creature's family."; + next; + mes "["+strcharinfo(0)+"]"; + mes "Fish~ Fish~"; + next; + mes "When you called out, an answer came"; + mes "from the puddle."; + next; + mes "[???]"; + mes "Who? Fisher? Go!"; + next; + select("I'm looking for a particular fish's family."); + mes "[???]"; + mes "Family? What be that fish name?"; + next; + mes "What was the name of the unidentified creature?"; + next; + input .@inputstr$; + if (.@inputstr$ != "Fishee") { + mes "[???]"; + mes "No Family. "+.@inputstr$+" No."; + mes "You go."; + next; + mes "It appears that the unidentified creature's family is not here."; + close; + } + mes "[???]"; + mes .@inputstr$+"? Oh... How..."; + mes "Husband here come. Your son."; + mes "News here."; + next; + mes "Another creature from the puddle spoke to you."; + next; + mes "[????]"; + mes "What? Missing son news?"; + next; + mes "The two fish were very excited,"; + mes "and their conversation was hard to follow."; + mes "You waited for them to calm down"; + mes "and told them the full story."; + next; + mes "[Fishee's Dad]"; + mes "Yes... At night, son"; + mes "gone... Night fishers."; + mes "Son stupid. Caught. Dead. OK."; + next; + mes "[Fishee's Mom]"; + mes "Fishee alive. Great. Great."; + next; + mes "[Fishee's Dad]"; + mes "Yes... Human give son news."; + mes "Thanks. Son,"; + mes "We okay. Happy. Here. You tell son."; + changequest .@quest2[0],5034; + close; + } else if (checkquest(5034) > -1 && checkquest(5034) < 2) { + mes "[Fishee's Dad]"; + mes "Yes... Human give son news."; + mes "Thanks. Son,"; + mes "We okay. Happy. Here. You tell son."; + close; + } else if (checkquest(.@quest2[1]) > -1 || checkquest(.@quest2[2]) > -1 || checkquest(.@quest2[3]) > -1) { + mes "You arrived at the puddle to the "+.@dir$[0]+"."; + mes "You should look for the unidentified creature's family."; + next; + mes "["+strcharinfo(0)+"]"; + mes "Fish~ Fish~"; + next; + mes "You yelled out loud for fish,"; + mes "but there is no response."; + mes "I don't think anybody lives"; + mes "in this puddle."; + close; + } + mes "You see a puddle with a calm surface."; + close; +} +bif_fild02,315,285,0 duplicate(#mora_puddle) Puddle#ep14_muk01 844 +bif_fild02,65,109,0 duplicate(#mora_puddle) Puddle#ep14_muk02 844 +bif_fild02,223,71,0 duplicate(#mora_puddle) Puddle#ep14_muk03 844 +bif_fild02,113,340,0 duplicate(#mora_puddle) Puddle#ep14_muk04 844 + +// Mora Daily Quests :: dealer +//============================================================ +mora,133,80,6 script Elephantine#pa0829 509,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (ep14_1_mistwoods < 10) { + mes "[Elephantine]"; + mes "Hmm, you don't look reliable enough to perform tasks for me."; + close; + } + if (BaseLevel < 135) { + mes "[Elephantine]"; + mes "Why don't you come back when you've grown stronger? I can't give you tasks when you're in your current state."; + close; + } + set .@playtime, checkquest(12230,PLAYTIME); + if (.@playtime == 0 || .@playtime == 1) { + mes "[Elephantine]"; + mes "I have no additional tasks available now. If I get some, I'll let you know when you come back."; + close; + } else if (.@playtime == 2) { + mes "[Elephantine]"; + mes "Will you please check with ^990099Hotcha^000000"; + mes "on the details of the previous task?"; + close; + } + mes "[Elephantine]"; + mes "Welcome."; + mes "I have some tasks for you - will you take a look at them?"; + next; + if(select("What kind of tasks do you have for me?:Tell me about today's task.") == 1) { + mes "[Elephantine]"; + mes "I'm the Head of the Volunteer Patrol of the Village of Mora. It didn't used to be like this, he he."; + next; + mes "[Elephantine]"; + mes "Each day, I'll be giving you a quest to kill off monsters in the surrounding area."; + next; + mes "[Elephantine]"; + mes "You might get a task that's far too difficult for you to take care of alone - in that case, try to get help from your fellow adventurers."; + close; + } + mes "[Elephantine]"; + mes "Let me see what tasks we've got today... Hmm..."; + next; + mes "[Elephantine]"; + mes "How about this one?"; + next; + switch(rand(1,5)) { + case 1: + setquest 12225; + setquest 12230; + mes "[Elephantine]"; + mes "Strange insects that carry fruit on their backs roam this area - you must've seen them."; + next; + mes "[Elephantine]"; + mes "I'd like you to take them out as you see them, before they try to sell anything to the adventurers lost in the forest."; + set .@n$,"Fruit-Carrying Insects"; + break; + case 2: + setquest 12226; + setquest 12230; + mes "[Elephantine]"; + mes "There have been a lot of reports lately about mantises disguised as flowers attacking creatures passing by."; + next; + mes "[Elephantine]"; + mes "No casualties have been reported yet, but it wouldn't hurt to take precautions. Please deal with them appropriately."; + set .@n$,"Flowery Hunters"; + break; + case 3: + setquest 12227; + setquest 12230; + mes "[Elephantine]"; + mes "An adventurer was reported to have been attacked by little birds while gathering resources in the vicinity of Bifrost."; + next; + mes "[Elephantine]"; + mes "They didn't look so ferocious... but the adventurer has asked me to get rid of them, so you'll have to do it."; + set .@n$,"Small but Ferocious..."; + break; + case 4: + setquest 12228; + setquest 12230; + mes "[Elephantine]"; + mes "I have qualms about this one, but somebody anonymously asked me to hunt down the naughty fairies."; + next; + mes "[Elephantine]"; + mes "I don't know what grudge he has against the fairies, but a request is a request."; + set .@n$,"An Unknown Grudge"; + break; + case 5: + setquest 12229; + setquest 12230; + mes "[Elephantine]"; + mes "Would you believe it if I said there are balls of blonde hair rolling around? You wouldn't, would you?"; + next; + mes "[Elephantine]"; + mes "They don't seem so dangerous, but they are reported to steal books and sweets from adventurers. Please deal with them appropriately."; + set .@n$,"Blondie Ann"; + break; + } + next; + mes "You have received the task ^005500"+.@n$+"^000000. Open and see the quest window for the details."; + close; +} + +mora,115,98,8 script Hotcha#pa0829 509,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (ep14_1_mistwoods < 10) { + mes "[Hotcha]"; + mes "Hmm, you don't look reliable enough for Elephantine's tasks."; + close; + } + if (BaseLevel < 97) { + mes "[Hotcha]"; + mes "This place is like a paradise for adventurers. Not for weak ones like you, though."; + close; + } + set .@playtime, checkquest(12230,PLAYTIME); + if (.@playtime == -1) { + mes "[Hotcha]"; + mes "I see you haven't received"; + mes "any tasks yet."; + mes "Go talk to Elephantine,"; + mes "and Elephantine will give you"; + mes "one of the countless tasks."; + close; + } else if (.@playtime == 2) { + mes "[Hotcha]"; + mes "The time is up to complete the existing tasks."; + next; + mes "[Hotcha]"; + mes "If you have any unfinished tasks in your quest log, they are considered 'failed' and removed from the log."; + next; + mes "[Hotcha]"; + mes "Once they are removed, go talk to Elephantine and you can receive new tasks."; + for(set .@i,12225; .@i<=12229; set .@i,.@i+1) { + if (checkquest(.@i) > -1) + erasequest .@i; + } + erasequest 12230; + close; + } + mes "[Hotcha]"; + mes "Welcome."; + mes "How may I help you?"; + next; + select("I have completed a task."); + mes "Oh."; + mes "Have you?"; + mes "Please wait a minute while I check the documents."; + next; + + for(set .@i,12225; .@i<=12229; set .@i,.@i+1) { + if (checkquest(.@i,HUNTING) == 2) { + mes "[Hotcha]"; + mes "Yes, I see you've completed the task. It has been confirmed as completed."; + erasequest .@i; + specialeffect2 EF_STEAL; + if (BaseLevel > 99) + getexp 0, ((JobLevel < 50)?JobLevel * JobLevel * (110/100) * 50:0); + else + getexp 0, ((JobLevel < 70)?JobLevel * JobLevel * (110/100) * 10:0); + getitem 6380,3; //Mora_Coin + close; + } + } + + mes "[Hotcha]"; + mes "Hmm... "+strcharinfo(0)+"."; + mes "It may be a documentation error, but according to the documents, you have nothing to do with the tasks."; + close; +} + +mora,119,103,4 script Bow-wow#pa0829 513,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (ep14_1_mistwoods < 10) { + mes "[Bow-wow]"; + mes "I try to give tasks only to reliable people. You are......... no, never mind."; + close; + } + if (BaseLevel < 97) { + mes "[Bow-wow]"; + mes "You really have no clue. What could you do with such a weak body?"; + close; + } + set .@playtime, checkquest(12241,PLAYTIME); + if (.@playtime == 0 || .@playtime == 1) { + mes "[Bow-wow]"; + mes "I have no additional tasks available now. If I get some, I'll let you know when you come back."; + close; + } else if (.@playtime == 2) { + mes "[Bow-wow]"; + mes "Will you please check with the ^990099General Goods Dealer^000000"; + mes "on the details of the previous task?"; + close; + } + mes "[Bow-wow]"; + mes "Welcome."; + mes "I have some tasks for you - will you take a look at them?"; + next; + if(select("What kind of tasks do you have for me?:Tell me about today's task.") == 1) { + mes "[Bow-wow]"; + mes "Here, we make all kinds of supplies for adventurers."; + next; + mes "[Bow-wow]"; + mes "We accept raw materials for the supplies once a day."; + next; + mes "[Bow-wow]"; + mes "Sometimes, we might ask for materials that are very difficult to obtain. In that case, try to get help from your fellow adventurers."; + close; + } + mes "[Bow-wow]"; + mes "Let me see... what supplies are we making today...?"; + next; + mes "[Bow-wow]"; + mes "How about this one?"; + next; + switch(rand(1,5)) { + case 1: + setquest 12231; + setquest 12241; + mes "[Bow-wow]"; + mes "The adventurers here make sure to bring with them, on their exploration to dungeons, a preservative to keep their food fresh. Do you know what the preservative is made from?"; + next; + mes "[Bow-wow]"; + mes "*grin* None other than... Insect Feelers! The General Goods Dealer there asked me to get four of them. I personally would not eat it for all the world..."; + set .@n$,"Material for the Preservative"; + break; + case 2: + setquest 12232; + setquest 12241; + mes "[Bow-wow]"; + mes "These days, it's common for adventurers here to make talismans to protect themselves on their dangerous adventures. Like a kind of insurance."; + next; + mes "[Bow-wow]"; + mes "Immortal Hearts seem to be all the rage lately. The General Goods Merchant asked me to get five of them."; + set .@n$,"A Symbol of Resistance"; + break; + case 3: + setquest 12233; + setquest 12241; + mes "[Bow-wow]"; + mes "They need tons of Rotten Bandages for making first aid bandages. They must have run out of new materials."; + next; + mes "[Bow-wow]"; + mes "The client is the General Goods Merchant over there. Three bunches of them will be enough."; + set .@n$,"Material for First Aid Kits"; + break; + case 4: + setquest 12234; + setquest 12241; + mes "[Bow-wow]"; + mes "Symbols of strong warriors give adventurers great support on their journeys. That's why Orcish Vouchers sell like hotcakes."; + next; + mes "[Bow-wow]"; + mes "The General Goods Dealer asked me to get three Orcish Vouchers, which are to be used to make symbols of courage."; + set .@n$,"Symbols of Courage"; + break; + case 5: + setquest 12235; + setquest 12241; + mes "[Bow-wow]"; + mes "It seems to be rumored among adventurers that drinking powdered bones mixed with water helps boost their stamina."; + next; + mes "[Bow-wow]"; + mes "The General Goods Dealer asked me to get three Skel-Bones, which are to be used to make tonic."; + set .@n$,"Good for Stamina..."; + break; + } + next; + mes "You have received the task ^880088"+.@n$+"^000000. Open and see the quest window for the details."; + close; +} + +mora,119,118,4 script General Good Dealer#pa0 516,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (ep14_1_mistwoods < 10) { + mes "[General Good Dealer]"; + mes "Hmm, you don't look reliable enough for Bow-wow's tasks."; + close; + } + if (BaseLevel < 97) { + mes "[General Good Dealer]"; + mes "What could you do with that fragile body? Go get some exercise."; + close; + } + set .@playtime, checkquest(12241,PLAYTIME); + if (.@playtime == -1) { + mes "[General Good Dealer]"; + mes "I see you haven't received"; + mes "any tasks yet."; + mes "Go talk to Bow-wow,"; + mes "and Bow-wow will give you"; + mes "one of the countless tasks."; + close; + } else if (.@playtime == 2) { + mes "[General Good Dealer]"; + mes "The time is up to complete the existing tasks."; + next; + mes "[General Good Dealer]"; + mes "If you have any unfinished tasks in your quest log, they are considered 'failed' and removed from the log."; + next; + mes "[General Good Dealer]"; + mes "Once they are removed, go talk to Bow-wow and you can receive new tasks."; + for(set .@i,12231; .@i<=12235; set .@i,.@i+1) { + if (checkquest(.@i) > -1) + erasequest .@i; + } + erasequest 12241; + close; + } + mes "[General Good Dealer]"; + mes "Welcome."; + mes "How may I help you?"; + next; + select("I have completed a task."); + mes "[General Good Dealer]"; + mes "Oh."; + mes "Have you?"; + mes "Please wait a minute while I check the documents."; + next; + + callsub L_CheckQuest,12231,928,4; //Insect_Feeler + callsub L_CheckQuest,12232,929,5; //Immortal_Heart + callsub L_CheckQuest,12233,930,1; //Rotten_Bandage + callsub L_CheckQuest,12234,931,3; //Orcish_Voucher + callsub L_CheckQuest,12235,932,3; //Skel_Bone + + mes "[General Good Dealer]"; + mes "Hmm... "+strcharinfo(0)+"."; + mes "It may be a documentation error, but according to the documents, you have nothing to do with the tasks."; + close; + +L_CheckQuest: + if (checkquest(getarg(0)) > -1) { + if (countitem(getarg(1)) < getarg(2)) { + mes "[General Good Dealer]"; + mes "The amount is not enough..."; + close; + } + mes "[General Good Dealer]"; + mes "I've received the items all right. It will be some time before I have another task for you, so why don't you visit the hot spring and relax?"; + delitem getarg(1),getarg(2); + erasequest getarg(0); + specialeffect2 EF_STEAL; + if (BaseLevel > 99) + getexp 0, ((JobLevel < 50)?JobLevel * JobLevel * (110/100) * 50:0); + else + getexp 0, ((JobLevel < 70)?JobLevel * JobLevel * (110/100) * 10:0); + getitem 6380,1; //Mora_Coin + close; + } + return; +} + +mora,124,108,7 script Woof-grrr#pa0829 514,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (ep14_1_mistwoods < 10) { + mes "[Woof-grrr]"; + mes "Can you please keep away from me? You're getting in the way."; + close; + } + if (BaseLevel < 97) { + mes "[Woof-grrr]"; + mes "This place is not a nursery. Grow up and come back, and I'll gladly give you tasks."; + close; + } + set .@playtime, checkquest(12242,PLAYTIME); + if (.@playtime == 0 || .@playtime == 1) { + mes "[Woof-grrr]"; + mes "I have no additional tasks available now. If I get some, I'll let you know when you come back."; + close; + } else if (.@playtime == 2) { + mes "[Woof-grrr]"; + mes "Will you please check with the ^990099Commodities Dealer^000000, standing across from me,"; + mes "on the details of the previous task?"; + close; + } + mes "[Woof-grrr]"; + mes "Nice to see you."; + mes "I have some tasks for you - will you take a look at them?"; + next; + if(select("What kind of tasks do you have for me?:Tell me about today's task.") == 1) { + mes "[Woof-grrr]"; + mes "Bow-wow and I are in the same industry."; + next; + mes "[Woof-grrr]"; + mes "We are a manufacturer of adventurers' supplies."; + next; + mes "[Woof-grrr]"; + mes "My tasks won't be easy - you'd better prepare yourself."; + close; + } + mes "[Woof-grrr]"; + mes "Hmm... What tasks are at hand today?"; + next; + mes "[Woof-grrr]"; + mes "Oh. This one looks good."; + next; + switch(rand(1,5)) { + case 1: + setquest 12236; + setquest 12242; + mes "[Woof-grrr]"; + mes "Some people just hang their talismans around their necks, but more people choose to seal them in special cases and carry them on their bodies."; + next; + mes "[Woof-grrr]"; + mes "Mementos serve as inspirations for designers of those cases. The Commodities Dealer across from me asked me to get two of them."; + set .@n$,"The Latest Trend in Talismans"; + break; + case 2: + setquest 12237; + setquest 12242; + mes "[Woof-grrr]"; + mes "Adventurers make sure to keep their talismans safe, because they could save their lives."; + next; + mes "[Woof-grrr]"; + mes "The Commodities Dealer across from me seems to make protective cases out of Shells. I was asked to get three of them."; + set .@n$,"Keep Your Valuables Safe"; + break; + case 3: + setquest 12238; + setquest 12242; + mes "[Woof-grrr]"; + mes "Adventurers that go into the bushes of the Maze of the Hazy Forest always wear knee protectors."; + next; + mes "[Woof-grrr]"; + mes "The Commodities Dealer across from me asked me to get three Scale Shells, which are to be used to make knee protectors."; + set .@n$,"Material for Knee Protectors"; + break; + case 4: + setquest 12239; + setquest 12242; + mes "[Woof-grrr]"; + mes "I have a task for you at hand, making a vaccine for possible poisonous insects."; + next; + mes "[Woof-grrr]"; + mes "The Commodities Dealer across from me asked me to get two Venom Canines, which are to be used in the research of the substance."; + set .@n$,"Poison for Poison..."; + break; + case 5: + setquest 12240; + setquest 12242; + mes "[Woof-grrr]"; + mes "It seems they have run out of the material for adding non-slip soles to shoes."; + next; + mes "[Woof-grrr]"; + mes "The Commodities Dealer across from me commissioned me to get five globs of Sticky Mucus."; + set .@n$,"Don't Slip and Fall"; + break; + } + next; + mes "You have received the task ^880088"+.@n$+"^000000. Open and see the quest window for the details."; + close; +} + +mora,127,112,4 script Commodities Dealer#pa08 518,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (ep14_1_mistwoods < 10) { + mes "[Commodities Dealer]"; + mes "Well, Woof-grrr can't have given a weakling like you tasks."; + close; + } + if (BaseLevel < 97) { + mes "[Commodities Dealer]"; + mes "Go away! I can't concentrate on cataloging with you hanging around like that..."; + close; + } + set .@playtime, checkquest(12242,PLAYTIME); + if (.@playtime == -1) { + mes "[Commodities Dealer]"; + mes "I see you haven't received"; + mes "any tasks yet."; + mes "Go talk to Woof-grrr,"; + mes "and Woof-grrr will give you"; + mes "one of the countless tasks."; + close; + } else if (.@playtime == 2) { + mes "[Commodities Dealer]"; + mes "The time is up to complete the existing tasks."; + next; + mes "[Commodities Dealer]"; + mes "If you have any unfinished tasks in your quest log, they are considered 'failed' and removed from the log."; + next; + mes "[Commodities Dealer]"; + mes "Once they are removed, go talk to Woof-grrr and you can receive new tasks."; + for(set .@i,12236; .@i<=12240; set .@i,.@i+1) { + if (checkquest(.@i) > -1) + erasequest .@i; + } + erasequest 12242; + close; + } + mes "[Commodities Dealer]"; + mes "Welcome."; + mes "How may I help you?"; + next; + select("I have completed a task."); + mes "[Commodities Dealer]"; + mes "Oh."; + mes "Have you?"; + mes "Please wait a minute while I check the documents."; + next; + + callsub L_CheckQuest,12236,934,2; //Mementos + callsub L_CheckQuest,12237,935,3; //Shell + callsub L_CheckQuest,12238,936,3; //Scales_Shell + callsub L_CheckQuest,12239,937,2; //Posionous_Canine + callsub L_CheckQuest,12240,938,5; //Sticky_Mucus + + mes "[Commodities Dealer]"; + mes "Hmm... "+strcharinfo(0)+"."; + mes "It may be a documentation error, but according to the documents, you have nothing to do with the tasks."; + close; + +L_CheckQuest: + if (checkquest(getarg(0)) > -1) { + if (countitem(getarg(1)) < getarg(2)) { + mes "[Commodities Dealer]"; + mes "The amount is not enough..."; + close; + } + mes "[Commodities Dealer]"; + mes "I've received the items all right. I look forward to working with you again."; + delitem getarg(1),getarg(2); + erasequest getarg(0); + specialeffect2 EF_STEAL; + if (BaseLevel > 99) + getexp 0, ((JobLevel < 50)?JobLevel * JobLevel * (110/100) * 50:0); + else + getexp 0, ((JobLevel < 70)?JobLevel * JobLevel * (110/100) * 10:0); + getitem 6380,1; //Mora_Coin + close; + } + return; +} + +mora,170,101,4 script Soul Guide#pa0829 515,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (ep14_1_mistwoods < 10) { + mes "[Soul Guide]"; + mes "Reliability is the primary quality needed in looking for lost souls. You don't look so reliable to me."; + close; + } + if (BaseLevel < 97) { + mes "[Soul Guide]"; + mes "You need to have a strong spirit to do this task. I think you need a lot more discipline."; + close; + } + set .@playtime, checkquest(12253,PLAYTIME); + if (.@playtime == 0 || .@playtime == 1) { + mes "You still have marks of the haunting souls on your body."; + next; + mes "You'll have to come back when the marks have disappeared."; + close; + } else if (.@playtime == 2) { + mes "You feel your mind has calmed down once again. You now have enough energy to go look for other souls, so talk to the Guide again."; + for(set .@i,12243; .@i<=12252; set .@i,.@i+1) { + if (checkquest(.@i) > -1) + erasequest .@i; + } + erasequest 12253; + close; + } + mes "[Soul Guide]"; + mes "Welcome."; + mes "Are you ready?"; + next; + if(select("What kind of tasks do you have for me?:Tell me about today's task.") == 1) { + mes "[Soul Guide]"; + mes "My job is to gather the remains of the souls haunting the forest and put them to rest."; + next; + mes "[Soul Guide]"; + mes "There are countless souls trapped in the Maze."; + next; + mes "[Soul Guide]"; + mes "Help them get their long-deserved rest."; + close; + } + mes "[Soul Guide]"; + mes "I'll show you the details of one of the lost souls."; + next; + switch(rand(1,10)) { + case 1: + setquest 12243; + setquest 12253; + mes "^660066Age 32. Comes from Midgard. Has been missing for 3 months since he went to the Maze of the Hazy Forest in order to collect the native plants. Low chance of survival.^000000"; + set .@n$,"Tazar"; + break; + case 2: + setquest 12244; + setquest 12253; + mes "^660066Age 19. Adventurer who came from a far, unknown place by ship. Been missing for 2 months since he went to explore the Maze dressed in thin tights, despite dissuasion of all Mora residents."; + mes "Even if he's alive, he would cause trouble to the rescue team.^000000"; + set .@n$,"Niger"; + break; + case 3: + setquest 12245; + setquest 12253; + mes "^660066Age unknown. Has some mental illness. Went alone in order to purify the Maze of the Hazy forest. He insists that he has good ancestry but no one trusts him."; + mes "Disappearance period : 12 years. Not much chance of survival.^000000"; + set .@n$,"Messil"; + break; + case 4: + setquest 12246; + setquest 12253; + mes "^660066Age 51. Used to be a big thief who stole famous swords from all around the world."; + mes "Went missing in the Maze after being pursued for running an illegal casino house which caused massive casualties in his final years. Low chance of survival.^000000"; + set .@n$,"Noirit"; + break; + case 5: + setquest 12247; + setquest 12253; + mes "^660066Age 22. An apprentice of an airship pilot. He has gone missing while drinking in Mora town, where he went for a break."; + mes "Rumor has it that he fled after signing somewhere. Disappearance period : 4 months. Low chance of survival.^000000"; + set .@n$,"Pajama Sin"; + break; + case 6: + setquest 12248; + setquest 12253; + mes "^660066Age Unknown. A female with long hair, dressed in black. Went on an expedition to the forest of the Maze in search of eternal life. Disappearance period : 3 months. Low chance of survival.^000000"; + set .@n$,"Mendel"; + break; + case 7: + setquest 12249; + setquest 12253; + mes "^660066Age around 50. The current Mayor of the Mora village. He ran away to the Forest of Maze after being caught pocketing profits by cheating the residents. Survival uncertain.^000000"; + set .@n$,"Milebit"; + break; + case 8: + setquest 12250; + setquest 12253; + mes "^660066Age 29. A young man with an unknown background."; + mes "Fled to the forest of maze after scamming 1200 Mora coins from Mora residents while pretending to start a lot of business and adapting himself in Mora. Survival uncertain.^000000"; + set .@n$,"Kunmoon"; + break; + case 9: + setquest 12251; + setquest 12253; + mes "^660066Age 34. Flirted with several women in Mora. Fled from Mora villagers to the forest of maze. Survival uncertain.^000000"; + set .@n$,"Chaihokin"; + break; + case 10: + setquest 12252; + setquest 12253; + mes "^660066Age Unknown. Disappered with coins which were joint controlled by the villagers. Low chance of survival.^000000"; + set .@n$,"Tual"; + break; + } + next; + mes "^990099Information on missing person "+.@n$+"^000000 has been found. Check your Quest Window for further information."; + specialeffect2 EF_STEAL; + close; +} + +mora,131,165,7 script Wandering Customer#pa082 520,{ + mes "[Wandering Customer]"; + mes "I don't know whether to believe this art dealer... He made me stand here like this for days.... Ah... I feel dizzy."; + close; +} + +mora,125,174,2 script A Random Customer#pa0829 520,{ + mes "[Naive Customer]"; + mes "I don't know when carving my pendant will be completed. Since he is a reliable art dealer, I suppose he won't break my pendant."; + close; +} + +mora,104,172,7 script Victim#pa0829 520,{ + mes "[Victim]"; + mes "You Bastard! I want my rugged outwear! That was passed on to me by my father *SOB*"; + next; + mes "^990099 It seems that he has gotten a great deal of damage from the art dealer.^000000"; + close; +} + +// Mora Daily Quests - Souls :: md_cadaver_in +//============================================================ +// callfunc "mora_remains",,,,,; +function script mora_remains { + if (MaxWeight - Weight < 1000) { + mes "You have to make space in your inventory."; + close; + } + if (checkquest(getarg(0)) > -1) { + specialeffect2 EF_BLIND; + specialeffect2 EF_BEGINSPELL; + progressbar "ffff00",4; + erasequest getarg(0); + mes "These must be ["+getarg(1)+"]'s Remains. So carefully gather his remains."; + specialeffect2 EF_STEAL; + getitem getarg(3), rand(1,getarg(4)); + if (rand(10)) { + next; + mes "You picked up "+getarg(2)+" Mora Coins next to the remains."; + specialeffect2 EF_STEAL; + getitem 6380,getarg(2); //Mora_Coin + } + close; + } + mes "You see traces of recent digging."; + close; +} +1@mist,132,100,0 script Tazaar's Remains#33 844,{ callfunc "mora_remains",12243,"Tazaar",6,526,3; } //Royal_Jelly +1@mist,102,242,0 script Naizar's Remains#33 844,{ callfunc "mora_remains",12244,"Naizar",5,942,17; } //Yoyo_Tail +1@mist,145,245,0 script Meshir's Remains#33 844,{ callfunc "mora_remains",12245,"Meshir",5,943,4; } //Solid_Shell +1@mist,196,276,0 script Noirit's Remains#33 844,{ callfunc "mora_remains",12246,"Noirit",6,549,3; } //Nice_Sweet_Potato +1@mist,304,327,0 script Pajama God's Remains#33 844,{ callfunc "mora_remains",12247,"Pajama God",5,945,18; } //Raccoon_Leaf +1@mist,334,287,0 script Mendel's Remains#33 844,{ callfunc "mora_remains",12248,"Mendel",7,946,31; } //Snail's_Shell +1@mist,330,177,0 script Milebit's Remains#33 844,{ callfunc "mora_remains",12249,"Milebit",5,7008,17; } //Stiff_Horn +1@mist,284,84,0 script Kunmun's Remains#33 844,{ callfunc "mora_remains",12250,"Kunmun",4,6380,20; } //Mora_Coin +1@mist,170,54,0 script Tsaihokin's Remains#33 844,{ callfunc "mora_remains",12251,"Tsaihokin",2,929,5; } //Immortal_Heart +1@mist,118,43,0 script Tuar's Remains#33 844,{ callfunc "mora_remains",12252,"Tuar",3,6380,20; } //Mora_Coin + +// Knights of the Neighborhood :: mora_knight +//============================================================ +mora,118,166,6 script Knights Chief#mo 525,{ + mes "[Order of the Knights Chief]"; + mes "We are the legendary order of the Neighborhood Knights, founded just five minutes ago!"; + next; + mes "[Order of the Knights Chief]"; + mes "We have four chiefs but no foot soldiers..."; + mes "It's so frustrating!"; + next; + mes "[Other Leaders]"; + mes "Those other guys are all soldiers, but I'm the Boss!"; + mes "I, the Head, will tell you what to do!"; + mes "The Leader is the highest in the rank!"; + mes "You talked me into joining the order, and now look at this!"; + close; +} + +mora,116,165,5 script Knights Boss#mo 524,{ + set .@playtime, checkquest(1119,PLAYTIME); + if (.@playtime == 0 || .@playtime == 1) { + mes "[Order of the Knights Boss]"; + mes "We've run out of Mora Coins."; + mes "Come back tomorrow!"; + close; + } else if (.@playtime == 2) + erasequest 1119; + if (checkweight(6380,1) == 0) { + mes "[Order of the Knights Boss]"; + mes "You have a lot of things with you!"; + mes "Why not dump some of them in my pocket?"; + close; + } + if (countitem(12561) >= 200) { + mes "[Order of the Knights Boss]"; + mes "So you've brought back"; + mes "200 ^FF0000Mysterious Seeds^000000."; + mes "Are you working under my command?"; + mes "I'm so confused"; + mes "because I've been sending random people on errands."; + next; + mes "[Order of the Knights Boss]"; + mes "I'll reward you as I promised."; + mes "You made sure everyone knows"; + mes "it's the Order of the Neighborhood Knights's work, right?"; + setquest 1119; + delitem 12561,200; //Mysterious_Seed + getitem 6380,1; //Mora_Coin + close; + } + mes "[Order of the Knights Boss]"; + mes "You have courage to"; + mes "show up out of nowhere"; + mes "and demand Mora Coins... how impressive!"; + mes "You're more than qualified to be a soldier of the Order of the Neighborhood Knights."; + next; + mes "[Order of the Knights Boss]"; + mes "Soldier, I need you to do something for me."; + mes "Go to the Hazy Forest and gather 200 ^FF0000Mysterious Seeds^000000!"; + next; + switch(select("Yes, sir!:I challenge you to a duel!")) { + case 1: + mes "[Order of the Knights Boss]"; + mes "Good attitude, "+strcharinfo(0)+" Soldier!"; + mes "I'll reward you handsomely when you get back."; + next; + mes "[Other Bosses]"; + mes "This is from me, the Chief!"; + mes "Don't look down on the Head!"; + mes "It's from me, the Leader!"; + close; + case 2: + mes "[Order of the Knights Boss]"; + mes "See the Chief if you want to have a duel!"; + mes "I'm in charge of recruiting here."; + mes "Ahem..."; + close; + } +} + +mora,114,163,5 script Knights Head#mo 522,{ + if (checkweight(6380,1) == 0) { + mes "[Order of the Knights Head]"; + mes "You have a lot of things with you!"; + mes "Why not dump some of them in my pocket?"; + close; + } + if (ep14_1_rope < 11) { + mes "[Order of the Knights Head]"; + mes "I hear that a Laphine called 'Lope'"; + mes "went missing in the Hazy Forest."; + mes "I wish the Order of the Neighborhood Knights"; + next; + mes "[Order of the Knights Head]"; + mes "could help solve the case,"; + mes "but we can't now"; + mes "because we're not done cleaning the yard yet."; + mes "So, what I'm trying to say is"; + next; + mes "[Order of the Knights Head]"; + mes "why don't you go"; + mes "and deal with the problem"; + mes "on behalf of the Order of the Neighborhood Knights!"; + next; + mes "[Order of the Knights Head]"; + mes "I promise, as the Head of the Order,"; + mes "that I'll give you more work"; + mes "when you get back!"; + next; + mes "[Other Heads]"; + mes "I approve it, as the Chief."; + mes "You can thank me, the Boss."; + mes "You know the Leader is the boss here, right?"; + close; + } else if (ep14_1_rope == 11) { + mes "[Order of the Knights Head]"; + mes "So the missing Laphine"; + mes "is dead?"; + mes "I'm sorry to hear that."; + mes "I could have saved him."; + next; + mes "[Order of the Knights Head]"; + mes "I hear that there are more ^0000FFLope's Clues^000000"; + mes "in the Hazy Forest."; + mes "Go look for the rest of them"; + mes "and bring back about 30 of them."; + mes "They will make great souvenirs."; + next; + switch(select("Am I doing all the work here or what?:Yes, sir!")) { + case 1: + mes "[Order of the Knights Head]"; + mes "So you've noticed it?"; + mes "Darn! I should have given you work earlier!"; + close; + case 2: + mes "[Order of the Knights Head]"; + mes "It was worthwhile to have trained you after all."; + mes "I'm proud of you,"+strcharinfo(0)+" Soldier!"; + next; + mes "[Other Heads]"; + mes "I think you'll make a great right-hand man, the Chief."; + mes "I feel rewarded, as the Boss."; + mes "As the Leader, I'm so pleased to see you all improve."; + set ep14_1_rope,12; + setquest 1118; + close; + } + } else if (ep14_1_rope == 12) { + if (countitem(6383) < 30) { + mes "[Order of the Knights Head]"; + mes "You still haven't gathered"; + mes "^0000FFLope's Clues^000000?"; + mes "I feel somewhat good,"; + mes "because that's about what I expected out of you."; + close; + } + mes "[Order of the Knights Head]"; + mes "So you've brought back ^0000FFLope's Clues^000000."; + mes "Let's see ..."; + mes "Assemble, assemble"; + mes "Attach, attach"; + next; + mes "[Lope's Letter]"; + mes "...a traveler... attacked..."; + mes "...under disguise... deadly poison..."; + mes "...the Village... in danger..."; + next; + mes "[Order of the Knights Head]"; + mes "What on earth does this mean?"; + mes "Well done, anyway."; + mes "Cheer up, you will be a great head of the Knights like myself, someday."; + next; + mes "[Other Heads]"; + mes "I'm not so sure!"; + mes "It's too much for us."; + mes "It's no use trying to do it."; + completequest 1118; + delitem 6383,30; //Clue_Of_Lope + set ep14_1_rope,13; + getitem 6380,2; //Mora_Coin + getexp 1000000,1000000; + close; + } else if (ep14_1_rope > 12) { + mes "[Order of the Knights Head]"; + mes "We're in trouble."; + mes "We're sick of being knights."; + mes "We're thinking of forming"; + mes "a circus troupe instead."; + mes "Are you interested in trying tightrope walking?"; + next; + switch(select("Well, I could do a fire show.:This is so absurd.")) { + case 1: + mes "[Order of the Knights Head]"; + mes "No, it's impossible."; + mes "I burned down a few houses"; + mes "playing with fire."; + close; + case 2: + mes "[Order of the Knights Head]"; + mes "That's the answer I expected."; + mes "I'm proud of myself."; + close; + } + close; + } + end; +} + +mora,112,161,5 script Knights Leader#mo 523,{ + mes "[Order of the Knights Leader]"; + mes "I'm the Leader of the Order -"; + mes "you can tell me."; + mes "What brings you here? Do you have some work for us?"; + next; + mes "[Other Leaders]"; + mes "Huh! I said the Boss is the boss!"; + mes "No, the Chief is the best!"; + mes "How rude you all are! I'm the Head here!"; + emotion e_swt2,1; + close; +} diff --git a/npc/re/scripts.conf b/npc/re/scripts.conf index dfe698752..e4dcd94ac 100644 --- a/npc/re/scripts.conf +++ b/npc/re/scripts.conf @@ -34,6 +34,7 @@ npc: npc/re/guides/guides_juno.txt npc: npc/re/guides/guides_lighthalzen.txt npc: npc/re/guides/guides_louyang.txt npc: npc/re/guides/guides_lutie.txt +npc: npc/re/guides/guides_mora.txt npc: npc/re/guides/guides_morroc.txt npc: npc/re/guides/guides_moscovia.txt npc: npc/re/guides/guides_niflheim.txt @@ -51,6 +52,7 @@ npc: npc/re/merchants/3rd_trader.txt npc: npc/re/merchants/diamond.txt npc: npc/re/merchants/flute.txt npc: npc/re/merchants/inn.txt +npc: npc/re/merchants/quivers.txt npc: npc/re/merchants/refine.txt npc: npc/re/merchants/renters.txt npc: npc/re/merchants/shops.txt @@ -85,5 +87,6 @@ npc: npc/re/quests/quests_izlude.txt npc: npc/re/quests/quests_lighthalzen.txt npc: npc/re/quests/quests_malangdo.txt npc: npc/re/quests/quests_veins.txt +npc: npc/re/quests/quests_mora.txt npc: npc/re/quests/monstertamers.txt -npc: npc/re/quests/quests_13_1.txt +npc: npc/re/quests/quests_13_1.txt \ No newline at end of file diff --git a/npc/re/warps/fields/bif_fild.txt b/npc/re/warps/fields/bif_fild.txt index 3a32c3e75..ec9de1cf9 100644 --- a/npc/re/warps/fields/bif_fild.txt +++ b/npc/re/warps/fields/bif_fild.txt @@ -1,20 +1,44 @@ -//===== Hercules Script ====================================== +//===== rAthena Script ======================================= //= Bifrost Field Warp Script //===== By: ================================================== //= Chilly //===== Current Version: ===================================== -//= 1.0 +//= 1.2 +//===== Compatible With: ===================================== +//= rAthena SVN //===== Description: ========================================= //= Warp Points for Bifrost Field //===== Additional Comments: ================================= //= 1.0 First Version. +//= 1.1 Added official warp scripts. [Euphy] +//= 1.2 Updated to match the official script. [Euphy] //============================================================ splendide,275,390,0 warp bifrost_field0001 1,1,bif_fild01,316,50 -bif_fild01,318,48,0 warp bifrost_field0002 1,1,splendide,275,387 -bif_fild02,285,333,0 warp bifrost_field0003 1,1,mora,179,74 -mora,182,74,0 warp bifrost_field0004 1,1,bif_fild02,285,330 -bif_fild02,95,310,0 warp bifrost_field0005 1,1,mora,22,157 -mora,20,159,0 warp bifrost_field0006 1,1,bif_fild02,98,309 -bif_fild02,174,162,0 warp bifrost_field0007 1,1,mora,58,27 -mora,56,25,0 warp bifrost_field0008 1,1,bif_fild02,177,162 +bif_fild01,318,48,0 warp bifrost_field0002 1,1,splendide,271,382 +mora,182,74,0 warp bifrost_field0003 1,1,bif_fild02,286,327 +mora,20,159,0 warp bifrost_field0004 1,1,bif_fild02,99,308 +mora,56,25,0 warp bifrost_field0005 1,1,bif_fild02,176,162 + +- script bifrost_field0000 -1,{ + mes "At the end of the small path through the bright flower garden"; + mes "is an entrance to something that looks like a small hill."; + next; + if(select("Knock-knock:Is this a wormhole?") == 1) { + mes "When you knock on the door-like thing just for fun,"; + mes "the door clicks open and you feel some mysterious force pulling you inside."; + close2; + switch(atoi(charat(strnpcinfo(2),9))) { + case 1: warp "mora",179,74; end; + case 2: warp "mora",22,157; end; + case 3: warp "mora",58,27; end; + } + } + close; +OnTouch: + specialeffect EF_LEVEL99_4; + end; +} +bif_fild02,285,332,0 duplicate(bifrost_field0000) Small Hole#ep14_mora1 844 +bif_fild02,95,310,0 duplicate(bifrost_field0000) Small Hole#ep14_mora2 844 +bif_fild02,174,162,0 duplicate(bifrost_field0000) Small Hole#ep14_mora3 844 diff --git a/src/common/mmo.h b/src/common/mmo.h index fd157377b..c2fdfe43a 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -103,7 +103,7 @@ #define MAX_GUILDSKILL 15 // Increased max guild skills because of new skills [Sara-chan] #define MAX_GUILDLEVEL 50 #define MAX_GUARDIANS 8 // Local max per castle. [Skotlex] -#define MAX_QUEST_DB 2400 // Max quests that the server will load +#define MAX_QUEST_DB 2410 // Max quests that the server will load #define MAX_QUEST_OBJECTIVES 3 // Max quest objectives for a quest #define MAX_START_ITEMS 32 // Max number of items allowed to be given to a char whenever it's created. [mkbu95] -- cgit v1.2.3-70-g09d2 From bd396ce8238f2a4cc18f1889744acf45fa2d20d9 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Fri, 31 May 2013 02:04:47 -0300 Subject: Follow up 20bdc01fa687b174a732be4483ddea4982d67ce9 Debug leftover. Signed-off-by: shennetsind --- npc/instances/EndlessTower.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'npc') diff --git a/npc/instances/EndlessTower.txt b/npc/instances/EndlessTower.txt index a6c330e69..68cf25000 100644 --- a/npc/instances/EndlessTower.txt +++ b/npc/instances/EndlessTower.txt @@ -202,8 +202,7 @@ alberta,214,77,6 script Captain Janssen 709,{ } } -//e_tower,81,105,0 script Tower Protection Stone 406,{ -prontera,150,150,0 script Tower Protection Stone 952,{ +e_tower,81,105,0 script Tower Protection Stone 406,{ set .@party_id,getcharid(1); set .@ins_mas,getpartyleader(.@party_id,2); -- cgit v1.2.3-70-g09d2 From c7b746e44ea890b83811cdeab940c475a76f05be Mon Sep 17 00:00:00 2001 From: Streusel Date: Fri, 31 May 2013 01:01:59 -0600 Subject: Update izlude.txt Fixed Bug #7305 Disabled Captain Carew duplicate for now since it doesn't exist anymore as we've reverted the new novice ground update, until we get more information and add start_point_re. http://hercules.ws/board/tracker/issue-7305-captain-carew/ --- npc/re/cities/izlude.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'npc') diff --git a/npc/re/cities/izlude.txt b/npc/re/cities/izlude.txt index d2ac40e80..24390f070 100644 --- a/npc/re/cities/izlude.txt +++ b/npc/re/cities/izlude.txt @@ -26,7 +26,7 @@ izlude,58,156,2 duplicate(Cebalis_izlude) Cebalis#izlude 98 izlude,165,156,2 duplicate(Soldier_izlude) Soldier#izlude 105 izlude,158,130,3 duplicate(bdt) Bullet Dealer Tony#iz 86 izlude,155,132,3 duplicate(mdk) Magazine Dealer Kenny 83 -izlude,198,213,4 duplicate(Captain_Carew) Captain Carew#izlude 873 +//izlude,198,213,4 duplicate(Captain_Carew) Captain Carew#izlude 873 izlude_in,57,92,3 duplicate(Dorian) Dorian#izlude 878 izlude,147,131,6 script Blacksmith#izlude 726,{ end; @@ -95,4 +95,4 @@ izlude,146,205,7 script Magpies Adventurer#iz-02 706,{ izlude,120,254,0 script Siege Monument#izlude 111,{ end; -} \ No newline at end of file +} -- cgit v1.2.3-70-g09d2 From 59ae55518e2a5a2fc706ec4db3afa234c45c6707 Mon Sep 17 00:00:00 2001 From: Streusel Date: Fri, 31 May 2013 01:20:48 -0600 Subject: Update payg_cas02.txt Fixed Bug #7304 Part 1 Thanks to Xgear for spotting this. --- npc/guild/payg_cas02.txt | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'npc') diff --git a/npc/guild/payg_cas02.txt b/npc/guild/payg_cas02.txt index 4ada2da53..27e5fc4f0 100644 --- a/npc/guild/payg_cas02.txt +++ b/npc/guild/payg_cas02.txt @@ -3,20 +3,21 @@ //===== By: ================================================== //= L0ne_W0lf //===== Current Version: ===================================== -//= 1.3 +//= 1.4 //===== Description: ========================================= -//= NPCs that relate to Payon Guild Castle 1 +//= NPCs that relate to Payon Guild Castle 2 //===== Additional Comments: ================================= //= 1.0 First Version. No longer uses functions. [L0ne_W0lf] //= 1.1 Corrected flag-in spawn point. [L0ne_W0lf] //= 1.2 Removed dialog from interior flags. [L0ne_W0lf] //= Fixed position of Guild dungeon switch. //= 1.3 Partially rewrote Script. [Masao] +//= 1.4 Fixed names [Streusel] //============================================================ // Guild Flags (Outside Castle) //============================================================ -- script Sacred Palace#1::OutsideFlagsPA2 722,{ +- script Scarlet Palace#1::OutsideFlagsPA2 722,{ set .@GID, GetCastleData("payg_cas02",1); @@ -66,14 +67,14 @@ OnRecvCastlePy02: end; } -pay_gld,292,112,6 duplicate(OutsideFlagsPA2) Sacred Palace#1-2 722 -pay_gld,292,120,6 duplicate(OutsideFlagsPA2) Sacred Palace#2 722 -pay_gld,291,135,6 duplicate(OutsideFlagsPA2) Sacred Palace#3 722 -pay_gld,271,163,0 duplicate(OutsideFlagsPA2) Sacred Palace#4 722 +pay_gld,292,112,6 duplicate(OutsideFlagsPA2) Scarlet Palace#1-2 722 +pay_gld,292,120,6 duplicate(OutsideFlagsPA2) Scarlet Palace#2 722 +pay_gld,291,135,6 duplicate(OutsideFlagsPA2) Scarlet Palace#3 722 +pay_gld,271,163,0 duplicate(OutsideFlagsPA2) Scarlet Palace#4 722 // Guild Flags (Inside Castle) //============================================================ -- script Sacred Palace#5::InsideFlagsPA2 722,{ +- script Scarlet Palace#5::InsideFlagsPA2 722,{ end; OnRecvCastlePy02: @@ -81,17 +82,17 @@ OnRecvCastlePy02: end; } -payg_cas02,254,40,6 duplicate(InsideFlagsPA2) Sacred Palace#5-2 722 -payg_cas02,254,48,6 duplicate(InsideFlagsPA2) Sacred Palace#6 722 -payg_cas02,202,49,0 duplicate(InsideFlagsPA2) Sacred Palace#7 722 -payg_cas02,209,49,0 duplicate(InsideFlagsPA2) Sacred Palace#8 722 -payg_cas02,59,282,4 duplicate(InsideFlagsPA2) Sacred Palace#9 722 -payg_cas02,70,282,4 duplicate(InsideFlagsPA2) Sacred Palace#10 722 +payg_cas02,254,40,6 duplicate(InsideFlagsPA2) Scarlet Palace#5-2 722 +payg_cas02,254,48,6 duplicate(InsideFlagsPA2) Scarlet Palace#6 722 +payg_cas02,202,49,0 duplicate(InsideFlagsPA2) Scarlet Palace#7 722 +payg_cas02,209,49,0 duplicate(InsideFlagsPA2) Scarlet Palace#8 722 +payg_cas02,59,282,4 duplicate(InsideFlagsPA2) Scarlet Palace#9 722 +payg_cas02,70,282,4 duplicate(InsideFlagsPA2) Scarlet Palace#10 722 // Guild Flag (Town) //============================================================ -payon,97,322,4 duplicate(InsideFlagsPA2) Sacred Altar#11 722 -payon,166,173,3 duplicate(InsideFlagsPA2) Sacred Altar#12 722 +payon,97,322,4 duplicate(InsideFlagsPA2) Scarlet Palace#11 722 +payon,166,173,3 duplicate(InsideFlagsPA2) Scarlet Palace#12 722 // Kafra Employee //============================================================ -- cgit v1.2.3-70-g09d2 From ae7b1134fac67154c4868d123731342fb066e423 Mon Sep 17 00:00:00 2001 From: Streusel Date: Fri, 31 May 2013 01:25:21 -0600 Subject: Update payg_cas04.txt Fixed Bug #7304 Part 2 Thanks to Xgear for spotting this. --- npc/guild/payg_cas04.txt | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'npc') diff --git a/npc/guild/payg_cas04.txt b/npc/guild/payg_cas04.txt index b3ddce797..4f584e368 100644 --- a/npc/guild/payg_cas04.txt +++ b/npc/guild/payg_cas04.txt @@ -3,20 +3,21 @@ //===== By: ================================================== //= L0ne_W0lf //===== Current Version: ===================================== -//= 1.3 +//= 1.4 //===== Description: ========================================= -//= NPCs that relate to Payon Guild Castle 1 +//= NPCs that relate to Payon Guild Castle 4 //===== Additional Comments: ================================= //= 1.0 First Version. No longer uses functions. [L0ne_W0lf] //= 1.1 Corrected flag-in spawn point. [L0ne_W0lf] //= 1.2 Removed dialog from interior flags. [L0ne_W0lf] //= Fixed position of Guild dungeon switch. //= 1.3 Partially rewrote Script. [Masao] +//= 1.4 Fixed named [Streusel] //============================================================ // Guild Flags (Outside Castle) //============================================================ -- script Scarlet Palace#1::OutsideFlagsPA4 722,{ +- script Sacred Altar#1::OutsideFlagsPA4 722,{ set .@GID, GetCastleData("payg_cas04",1); @@ -66,14 +67,14 @@ OnRecvCastlePy04: end; } -pay_gld,137,160,0 duplicate(OutsideFlagsPA4) Scarlet Palace#1-2 722 -pay_gld,143,160,0 duplicate(OutsideFlagsPA4) Scarlet Palace#2 722 -pay_gld,133,151,2 duplicate(OutsideFlagsPA4) Scarlet Palace#3 722 -pay_gld,153,166,1 duplicate(OutsideFlagsPA4) Scarlet Palace#4 722 +pay_gld,137,160,0 duplicate(OutsideFlagsPA4) Sacred Altar#1-2 722 +pay_gld,143,160,0 duplicate(OutsideFlagsPA4) Sacred Altar#2 722 +pay_gld,133,151,2 duplicate(OutsideFlagsPA4) Sacred Altar#3 722 +pay_gld,153,166,1 duplicate(OutsideFlagsPA4) Sacred Altar#4 722 // Guild Flags (Inside Castle) //============================================================ -- script Scarlet Palace#5::InsideFlagsPA4 722,{ +- script Sacred Altar#5::InsideFlagsPA4 722,{ end; OnRecvCastlePy04: @@ -81,17 +82,17 @@ OnRecvCastlePy04: end; } -payg_cas04,255,259,0 duplicate(InsideFlagsPA4) Scarlet Palace#5-2 722 -payg_cas04,248,259,0 duplicate(InsideFlagsPA4) Scarlet Palace#6 722 -payg_cas04,248,168,6 duplicate(InsideFlagsPA4) Scarlet Palace#7 722 -payg_cas04,248,160,6 duplicate(InsideFlagsPA4) Scarlet Palace#8 722 -payg_cas04,232,181,4 duplicate(InsideFlagsPA4) Scarlet Palace#9 722 -payg_cas04,239,181,4 duplicate(InsideFlagsPA4) Scarlet Palace#10 722 +payg_cas04,255,259,0 duplicate(InsideFlagsPA4) Sacred Altar#5-2 722 +payg_cas04,248,259,0 duplicate(InsideFlagsPA4) Sacred Altar#6 722 +payg_cas04,248,168,6 duplicate(InsideFlagsPA4) Sacred Altar#7 722 +payg_cas04,248,160,6 duplicate(InsideFlagsPA4) Sacred Altar#8 722 +payg_cas04,232,181,4 duplicate(InsideFlagsPA4) Sacred Altar#9 722 +payg_cas04,239,181,4 duplicate(InsideFlagsPA4) Sacred Altar#10 722 // Guild Flag (Town) //============================================================ -payon,118,322,4 duplicate(InsideFlagsPA4) Scarlet Palace#11 722 -payon,166,165,3 duplicate(InsideFlagsPA4) Scarlet Palace#12 722 +payon,118,322,4 duplicate(InsideFlagsPA4) Sacred Altar#11 722 +payon,166,165,3 duplicate(InsideFlagsPA4) Sacred Altar#12 722 // Kafra Employee //============================================================ -- cgit v1.2.3-70-g09d2 From 8ec194289376af985d1c8a4de7adb33a27be1f99 Mon Sep 17 00:00:00 2001 From: Euphy Date: Sat, 1 Jun 2013 21:53:53 -0400 Subject: Implemented Mora Enchants. --- npc/re/merchants/enchan_mora.txt | 2356 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 2356 insertions(+) create mode 100644 npc/re/merchants/enchan_mora.txt (limited to 'npc') diff --git a/npc/re/merchants/enchan_mora.txt b/npc/re/merchants/enchan_mora.txt new file mode 100644 index 000000000..8ff8f758d --- /dev/null +++ b/npc/re/merchants/enchan_mora.txt @@ -0,0 +1,2356 @@ +//===== rAthena Script ======================================= +//= Mora Enchants +//===== By: ================================================== +//= Euphy +//===== Current Version: ===================================== +//= 1.0 +//===== Compatible With: ===================================== +//= rAthena SVN +//===== Description: ========================================= +//= [Official Conversion] +//= Adds enchantments to various items in exchange for +//= Mora coins. +//===== Additional Comments: ================================= +//= 1.0 First Version. [Euphy] +//============================================================ + +// Arch Bishop Enchants :: coin_arc +//============================================================ +mora,88,89,5 script Keeper of Secrets#pa082 495,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + disable_items; + if (countitem(6380) < 10) { + mes "[Artifice]"; + mes "Relics for Archbishops are meant for defense and support!"; + next; + mes "[Artifice]"; + mes "Like the other Guardians, they may trade coins for their relics, so collect Mora Coins!"; + next; + mes "[Artifice]"; + mes "If you collect more than 10 coins then come to me to trade!"; + close; + } + mes "[Artifice]"; + mes "By the light! You look like you are ready to gain access to our relics."; + next; + mes "[Artifice]"; + mes "Ring, Shoes, Shawl, Robe, Shield, or Weapon."; + mes "Select one of the six kinds of relics to receive."; + next; + mes "[Artifice]"; + mes "I'll randomly give you one of 2 types of the equipment, depending upon the weather and my mood."; + next; + mes "[Artifice]"; + mes "All I need is 10 Mora Coins of yours to grant you a relic!"; + next; + switch(select("I don't think I'm ready.:I'm ready to exchange my Mora Coins.:Exchange my Ring.")) { + case 1: + mes "[Artifice]"; + mes "See you next time!"; + close; + case 2: + mes "[Artifice]"; + // What does this even mean? (custom dialogue below) + //mes "You influence what part are you?"; + mes "What kind of relic do you want?"; + next; + switch(select("I'm not ready.:Ring:Shoes:Shawl:Robe:Shield:Weapon")) { + case 1: + mes "[Artifice]"; + mes "Go with the light."; + close; + case 2: + if (countitem(2864) || countitem(2865) || countitem(2866)) { + mes "[Artifice]"; + mes "You are already allowed access to our relics by your possession of a Ring!"; + close; + } + if (Class == Job_Arch_Bishop || Class == Job_Arch_Bishop_T || Class == Job_Baby_Bishop) { + setarray .@items[0],2864,2865,2866; //Light_Of_Cure,Seal_Of_Cathedral,Ring_Of_Archbishop + break; + } else { + mes "[Artifice]"; + mes "We prefer to only deal with Arch-Bishops."; + close; + } + case 3: + setarray .@items[0],2471,2472; //Shoes_Of_Affection,Shoes_Of_Judgement + break; + case 4: + setarray .@items[0],2569,2570; //Shawl_Of_Affection,Shawl_Of_Judgement + break; + case 5: + setarray .@items[0],15029,15030; //Robe_Of_Affection,Robe_Of_Judgement + break; + case 6: + setarray .@items[0],2156; //Bible_Of_Promise1 + break; + case 7: + setarray .@items[0],1657,16013; //Wand_Of_Affection,Mace_Of_Judgement + break; + } + set .@item, .@items[rand(getarraysize(.@items))]; + delitem 6380,10; //Mora_Coin + getitem .@item,1; + mes "[Artifice]"; + mes "You have obtained ^aa00aa"+getitemname(.@item)+"^000000. May the Blessing of the Light be with you."; + close; + case 3: + if (Class == Job_Arch_Bishop || Class == Job_Arch_Bishop_T || Class == Job_Baby_Bishop) { + mes "[Artifice]"; + mes "We exchange rings into coins for those who cannot control the ring."; + next; + mes "[Artifice]"; + mes "It seems that you have power to control the ring so I cannot exchange it into coins."; + close; + } + if (countitem(2864)) set .@item,2864; //Light_Of_Cure + else if (countitem(2865)) set .@item,2865; //Seal_Of_Cathedral + else if (countitem(2866)) set .@item,2866; //Ring_Of_Archbishop + else { + mes "[Artifice]"; + mes "Did you change something?"; + close; + } + mes "[Artifice]"; + mes "You have a "+getitemname(.@item)+". Do you really want to trade it for 10 Mora Coins?"; + next; + switch(select("I'm not ready:Exchange my "+getitemname(.@item))) { + case 1: + mes "[Artifice]"; + mes "If you change your mind, please stop by again."; + close; + case 2: + delitem .@item,1; + getitem 6380,10; //Mora_Coin + mes "[Artifice]"; + mes "I think that was an even trade."; + close; + } + } +} + +mora,96,74,5 script Master of Relics#pa0829 495,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + disable_items; + mes "[Relice]"; + mes "I enhance Relics that holy Arch-Bishops use, it will take 2 Mora Coins and the relic to allow me to attempt to enhance it."; + next; + switch(select("More details please.:Please Enhance my Relic.")) { + case 1: + mes "[Relice]"; + mes "Let me briefly explain, for 2 Mora Coins and the relic I can give you a single Enchantment on that relic."; + next; + mes "[Relice]"; + mes "Even though this relic was already enchanted, we will re-enchant it without checking its status."; + next; + mes "[Relice]"; + mes "So it you have already enchanted relic, please put it some place safe and come back."; + next; + mes "[Relice]"; + mes "Ah, one more thing! It is possible I can fail though and if that happens the relic is lost forever."; + close; + case 2: + mes "[Relice]"; + mes "Ok, you can get a new Relic from Artifice if it fails."; + next; + mes "[Relice]"; + mes "If you have a ritual for luck, you should use it now!"; + next; + set .@select, select("Wait a minute!:Light of Cure:Seal of Cathedral:Ring of Archbishop:Shoes of Affection:Shoes of Judgement:Shawl of Affection:Shawl of Judgement:Robe of Affection:Robe of Judgement:Bible of Promise 1st Vol:Wand of Affection:Mace of Judgement"); + switch(.@select) { + case 1: + mes "[Relice]"; + mes "Certainly. Go with the Light."; + close; + case 2: + case 3: + case 4: + setarray .@items[0],2864,2865,2866; //Light_Of_Cure,Seal_Of_Cathedral,Ring_Of_Archbishop + setarray .@special[0],4803,4804,4805; //Highness_Heal_3sec,Coluceo_Heal30,Heal_Amount2 + set .@item, .@items[.@select-2]; + set .@sp, .@special[.@select-2]; + set .@enchant_type,1; + break; + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + setarray .@items[0],2471,2472,2569,2570,15029,15030,2156; //Shoes_Of_Affection,Shoes_Of_Judgement,Shawl_Of_Affection,Shawl_Of_Judgement,Robe_Of_Affection,Robe_Of_Judgement,Bible_Of_Promise1 + set .@item, .@items[.@select-5]; + set .@enchant_type,2; + break; + case 12: + set .@item,1657; //Wand_Of_Affection + set .@enchant_type,3; + break; + case 13: + set .@item,16013; //Mace_Of_Judgement + set .@enchant_type,4; + break; + } + if (countitem(6380) < 2 || countitem(.@item) == 0) { + mes "[Relice]"; + mes "For 2 Mora Coins I can strengthen the relic you have in many ways!"; + close; + } + specialeffect2 EF_REPAIRWEAPON; + delitem 6380,2; //Mora_Coin + delitem .@item,1; + switch(.@enchant_type) { + case 1: + set .@i, rand(1,1487); + if (.@i <= 16) setarray .@enchants[2],4710,.@sp; //Inteligence2 [sp] + else if (.@i <= 32) setarray .@enchants[2],4710,4799; //Inteligence2 HP500 + else if (.@i <= 48) setarray .@enchants[2],4710,4766; //Inteligence2 Atk2 + else if (.@i <= 64) setarray .@enchants[2],4710,4788; //Inteligence2 Mdef6 + else if (.@i <= 80) setarray .@enchants[2],4720,.@sp; //Dexterity1 [sp] + else if (.@i <= 96) setarray .@enchants[2],4720,4799; //Dexterity1 HP500 + else if (.@i <= 112) setarray .@enchants[2],4720,4766; //Dexterity1 Atk2 + else if (.@i <= 128) setarray .@enchants[2],4720,4788; //Dexterity1 Mdef6 + else if (.@i <= 144) setarray .@enchants[2],4721,.@sp; //Dexterity2 [sp] + else if (.@i <= 160) setarray .@enchants[2],4721,4799; //Dexterity2 HP500 + else if (.@i <= 176) setarray .@enchants[2],4721,4766; //Dexterity2 Atk2 + else if (.@i <= 192) setarray .@enchants[2],4721,4788; //Dexterity2 Mdef6 + else if (.@i <= 208) setarray .@enchants[2],4740,.@sp; //Vitality1 [sp] + else if (.@i <= 224) setarray .@enchants[2],4740,4799; //Vitality1 HP500 + else if (.@i <= 240) setarray .@enchants[2],4740,4766; //Vitality1 Atk2 + else if (.@i <= 256) setarray .@enchants[2],4740,4788; //Vitality1 Mdef6 + else if (.@i <= 272) setarray .@enchants[2],4710,.@sp; //Inteligence2 [sp] + else if (.@i <= 288) setarray .@enchants[2],4710,4799; //Inteligence2 HP500 + else if (.@i <= 304) setarray .@enchants[2],4710,4766; //Inteligence2 Atk2 + else if (.@i <= 320) setarray .@enchants[2],4710,4788; //Inteligence2 Mdef6 + else if (.@i <= 336) setarray .@enchants[2],4720,.@sp; //Dexterity1 [sp] + else if (.@i <= 352) setarray .@enchants[2],4720,4799; //Dexterity1 HP500 + else if (.@i <= 368) setarray .@enchants[2],4720,4766; //Dexterity1 Atk2 + else if (.@i <= 384) setarray .@enchants[2],4720,4788; //Dexterity1 Mdef6 + else if (.@i <= 400) setarray .@enchants[2],4721,.@sp; //Dexterity2 [sp] + else if (.@i <= 416) setarray .@enchants[2],4721,4799; //Dexterity2 HP500 + else if (.@i <= 432) setarray .@enchants[2],4721,4766; //Dexterity2 Atk2 + else if (.@i <= 448) setarray .@enchants[2],4721,4788; //Dexterity2 Mdef6 + else if (.@i <= 464) setarray .@enchants[2],4740,.@sp; //Vitality1 [sp] + else if (.@i <= 480) setarray .@enchants[2],4740,4799; //Vitality1 HP500 + else if (.@i <= 496) setarray .@enchants[2],4740,4766; //Vitality1 Atk2 + else if (.@i <= 512) setarray .@enchants[2],4740,4788; //Vitality1 Mdef6 + else if (.@i <= 528) setarray .@enchants[2],4710,.@sp; //Inteligence2 [sp] + else if (.@i <= 544) setarray .@enchants[2],4710,4799; //Inteligence2 HP500 + else if (.@i <= 560) setarray .@enchants[2],4710,4766; //Inteligence2 Atk2 + else if (.@i <= 576) setarray .@enchants[2],4710,4788; //Inteligence2 Mdef6 + else if (.@i <= 592) setarray .@enchants[2],4720,.@sp; //Dexterity1 [sp] + else if (.@i <= 608) setarray .@enchants[2],4720,4799; //Dexterity1 HP500 + else if (.@i <= 624) setarray .@enchants[2],4720,4766; //Dexterity1 Atk2 + else if (.@i <= 640) setarray .@enchants[2],4720,4788; //Dexterity1 Mdef6 + else if (.@i <= 656) setarray .@enchants[2],4721,.@sp; //Dexterity2 [sp] + else if (.@i <= 672) setarray .@enchants[2],4721,4799; //Dexterity2 HP500 + else if (.@i <= 688) setarray .@enchants[2],4721,4766; //Dexterity2 Atk2 + else if (.@i <= 704) setarray .@enchants[2],4721,4788; //Dexterity2 Mdef6 + else if (.@i <= 720) setarray .@enchants[2],4740,.@sp; //Vitality1 [sp] + else if (.@i <= 736) setarray .@enchants[2],4740,4799; //Vitality1 HP500 + else if (.@i <= 752) setarray .@enchants[2],4740,4766; //Vitality1 Atk2 + else if (.@i <= 768) setarray .@enchants[2],4740,4788; //Vitality1 Mdef6 + else if (.@i <= 784) setarray .@enchants[2],4710,.@sp; //Inteligence2 [sp] + else if (.@i <= 800) setarray .@enchants[2],4710,4799; //Inteligence2 HP500 + else if (.@i <= 816) setarray .@enchants[2],4710,4766; //Inteligence2 Atk2 + else if (.@i <= 832) setarray .@enchants[2],4710,4788; //Inteligence2 Mdef6 + else if (.@i <= 848) setarray .@enchants[2],4720,.@sp; //Dexterity1 [sp] + else if (.@i <= 864) setarray .@enchants[2],4720,4799; //Dexterity1 HP500 + else if (.@i <= 880) setarray .@enchants[2],4720,4766; //Dexterity1 Atk2 + else if (.@i <= 896) setarray .@enchants[2],4720,4788; //Dexterity1 Mdef6 + else if (.@i <= 912) setarray .@enchants[2],4721,.@sp; //Dexterity2 [sp] + else if (.@i <= 928) setarray .@enchants[2],4721,4799; //Dexterity2 HP500 + else if (.@i <= 944) setarray .@enchants[2],4721,4766; //Dexterity2 Atk2 + else if (.@i <= 960) setarray .@enchants[2],4721,4788; //Dexterity2 Mdef6 + else if (.@i <= 976) setarray .@enchants[2],4740,.@sp; //Vitality1 [sp] + else if (.@i <= 992) setarray .@enchants[2],4740,4799; //Vitality1 HP500 + else if (.@i <= 1008) setarray .@enchants[2],4740,4766; //Vitality1 Atk2 + else if (.@i <= 1024) setarray .@enchants[2],4740,4788; //Vitality1 Mdef6 + else if (.@i <= 1040) setarray .@enchants[2],.@sp,.@sp; //[sp] [sp] + else if (.@i <= 1487) { + mes "[Relice]"; + mes "Sometimes things just don't work out the way you want. I hope next time things go better for you. Until then, good bye."; + close; + } + break; + case 2: + set .@i, rand(1,1487); + if (.@i <= 16) setarray .@enchants[1],4710,4711,4764; //Inteligence1 Inteligence2 Critical5 + else if (.@i <= 32) setarray .@enchants[1],4710,4711,4799; //Inteligence1 Inteligence2 HP500 + else if (.@i <= 48) setarray .@enchants[1],4710,4711,4766; //Inteligence1 Inteligence2 Atk2 + else if (.@i <= 64) setarray .@enchants[1],4710,4711,4788; //Inteligence1 Inteligence2 Mdef6 + else if (.@i <= 80) setarray .@enchants[1],4710,4720,4764; //Inteligence1 Dexterity1 Critical5 + else if (.@i <= 96) setarray .@enchants[1],4710,4720,4799; //Inteligence1 Dexterity1 HP500 + else if (.@i <= 112) setarray .@enchants[1],4710,4720,4766; //Inteligence1 Dexterity1 Atk2 + else if (.@i <= 128) setarray .@enchants[1],4710,4720,4788; //Inteligence1 Dexterity1 Mdef6 + else if (.@i <= 144) setarray .@enchants[1],4710,4721,4764; //Inteligence1 Dexterity2 Critical5 + else if (.@i <= 160) setarray .@enchants[1],4710,4721,4799; //Inteligence1 Dexterity2 HP500 + else if (.@i <= 176) setarray .@enchants[1],4710,4721,4766; //Inteligence1 Dexterity2 Atk2 + else if (.@i <= 192) setarray .@enchants[1],4710,4721,4788; //Inteligence1 Dexterity2 Mdef6 + else if (.@i <= 208) setarray .@enchants[1],4710,4740,4764; //Inteligence1 Vitality1 Critical5 + else if (.@i <= 224) setarray .@enchants[1],4710,4740,4799; //Inteligence1 Vitality1 HP500 + else if (.@i <= 240) setarray .@enchants[1],4710,4740,4766; //Inteligence1 Vitality1 Atk2 + else if (.@i <= 256) setarray .@enchants[1],4710,4740,4788; //Inteligence1 Vitality1 Mdef6 + else if (.@i <= 272) setarray .@enchants[1],4711,4711,4764; //Inteligence2 Inteligence2 Critical5 + else if (.@i <= 288) setarray .@enchants[1],4711,4711,4799; //Inteligence2 Inteligence2 HP500 + else if (.@i <= 304) setarray .@enchants[1],4711,4711,4766; //Inteligence2 Inteligence2 Atk2 + else if (.@i <= 320) setarray .@enchants[1],4711,4711,4788; //Inteligence2 Inteligence2 Mdef6 + else if (.@i <= 336) setarray .@enchants[1],4711,4720,4764; //Inteligence2 Dexterity1 Critical5 + else if (.@i <= 352) setarray .@enchants[1],4711,4720,4799; //Inteligence2 Dexterity1 HP500 + else if (.@i <= 368) setarray .@enchants[1],4711,4720,4766; //Inteligence2 Dexterity1 Atk2 + else if (.@i <= 384) setarray .@enchants[1],4711,4720,4788; //Inteligence2 Dexterity1 Mdef6 + else if (.@i <= 400) setarray .@enchants[1],4711,4721,4764; //Inteligence2 Dexterity2 Critical5 + else if (.@i <= 416) setarray .@enchants[1],4711,4721,4799; //Inteligence2 Dexterity2 HP500 + else if (.@i <= 432) setarray .@enchants[1],4711,4721,4766; //Inteligence2 Dexterity2 Atk2 + else if (.@i <= 448) setarray .@enchants[1],4711,4721,4788; //Inteligence2 Dexterity2 Mdef6 + else if (.@i <= 464) setarray .@enchants[1],4711,4740,4764; //Inteligence2 Vitality1 Critical5 + else if (.@i <= 480) setarray .@enchants[1],4711,4740,4799; //Inteligence2 Vitality1 HP500 + else if (.@i <= 496) setarray .@enchants[1],4711,4740,4766; //Inteligence2 Vitality1 Atk2 + else if (.@i <= 512) setarray .@enchants[1],4711,4740,4788; //Inteligence2 Vitality1 Mdef6 + else if (.@i <= 528) setarray .@enchants[1],4720,4711,4764; //Dexterity1 Inteligence2 Critical5 + else if (.@i <= 544) setarray .@enchants[1],4720,4711,4799; //Dexterity1 Inteligence2 HP500 + else if (.@i <= 560) setarray .@enchants[1],4720,4711,4766; //Dexterity1 Inteligence2 Atk2 + else if (.@i <= 576) setarray .@enchants[1],4720,4711,4788; //Dexterity1 Inteligence2 Mdef6 + else if (.@i <= 592) setarray .@enchants[1],4720,4720,4764; //Dexterity1 Dexterity1 Critical5 + else if (.@i <= 608) setarray .@enchants[1],4720,4720,4799; //Dexterity1 Dexterity1 HP500 + else if (.@i <= 624) setarray .@enchants[1],4720,4720,4766; //Dexterity1 Dexterity1 Atk2 + else if (.@i <= 640) setarray .@enchants[1],4720,4720,4788; //Dexterity1 Dexterity1 Mdef6 + else if (.@i <= 656) setarray .@enchants[1],4720,4721,4764; //Dexterity1 Dexterity2 Critical5 + else if (.@i <= 672) setarray .@enchants[1],4720,4721,4799; //Dexterity1 Dexterity2 HP500 + else if (.@i <= 688) setarray .@enchants[1],4720,4721,4766; //Dexterity1 Dexterity2 Atk2 + else if (.@i <= 704) setarray .@enchants[1],4720,4721,4788; //Dexterity1 Dexterity2 Mdef6 + else if (.@i <= 720) setarray .@enchants[1],4720,4740,4764; //Dexterity1 Vitality1 Critical5 + else if (.@i <= 736) setarray .@enchants[1],4720,4740,4799; //Dexterity1 Vitality1 HP500 + else if (.@i <= 752) setarray .@enchants[1],4720,4740,4766; //Dexterity1 Vitality1 Atk2 + else if (.@i <= 768) setarray .@enchants[1],4720,4740,4788; //Dexterity1 Vitality1 Mdef6 + else if (.@i <= 784) setarray .@enchants[1],4721,4711,4764; //Dexterity2 Inteligence2 Critical5 + else if (.@i <= 800) setarray .@enchants[1],4721,4711,4799; //Dexterity2 Inteligence2 HP500 + else if (.@i <= 816) setarray .@enchants[1],4721,4711,4766; //Dexterity2 Inteligence2 Atk2 + else if (.@i <= 832) setarray .@enchants[1],4721,4711,4788; //Dexterity2 Inteligence2 Mdef6 + else if (.@i <= 848) setarray .@enchants[1],4721,4720,4764; //Dexterity2 Dexterity1 Critical5 + else if (.@i <= 864) setarray .@enchants[1],4721,4720,4799; //Dexterity2 Dexterity1 HP500 + else if (.@i <= 880) setarray .@enchants[1],4721,4720,4766; //Dexterity2 Dexterity1 Atk2 + else if (.@i <= 896) setarray .@enchants[1],4721,4720,4788; //Dexterity2 Dexterity1 Mdef6 + else if (.@i <= 912) setarray .@enchants[1],4721,4721,4764; //Dexterity2 Dexterity2 Critical5 + else if (.@i <= 928) setarray .@enchants[1],4721,4721,4799; //Dexterity2 Dexterity2 HP500 + else if (.@i <= 944) setarray .@enchants[1],4721,4721,4766; //Dexterity2 Dexterity2 Atk2 + else if (.@i <= 960) setarray .@enchants[1],4721,4721,4788; //Dexterity2 Dexterity2 Mdef6 + else if (.@i <= 976) setarray .@enchants[1],4721,4740,4764; //Dexterity2 Vitality1 Critical5 + else if (.@i <= 992) setarray .@enchants[1],4721,4740,4799; //Dexterity2 Vitality1 HP500 + else if (.@i <= 1008) setarray .@enchants[1],4721,4740,4766; //Dexterity2 Vitality1 Atk2 + else if (.@i <= 1024) setarray .@enchants[1],4721,4740,4788; //Dexterity2 Vitality1 Mdef6 + else if (.@i <= 1026) setarray .@enchants[1],4761,4761,4761; //Matk2 Matk2 Matk2 + else if (.@i <= 1028) setarray .@enchants[1],4712,4713,4713; //Inteligence3 Inteligence4 Inteligence4 + else if (.@i <= 1030) setarray .@enchants[1],4712,4761,4761; //Inteligence3 Matk2 Matk2 + else if (.@i <= 1032) setarray .@enchants[1],4712,4713,4761; //Inteligence3 Inteligence4 Matk2 + else if (.@i <= 1034) setarray .@enchants[1],4722,4723,4723; //Dexterity3 Dexterity4 Dexterity4 + else if (.@i <= 1036) setarray .@enchants[1],4722,4703,4703; //Dexterity3 Strength4 Strength4 + else if (.@i <= 1038) setarray .@enchants[1],4722,4767,4767; //Dexterity3 Atk3 Atk3 + else if (.@i <= 1040) setarray .@enchants[1],4767,4767,4767; //Atk3 Atk3 Atk3 + else if (.@i <= 1487) { + mes "[Relice]"; + mes "Sometimes things just don't work out the way you want. I hope next time things go better for you. Until then, good bye."; + close; + } + break; + case 3: + set .@i, rand(1,2852); + if (.@i <= 31) setarray .@enchants[2],4720,4710; //Dexterity1 Inteligence1 + else if (.@i <= 62) setarray .@enchants[2],4720,4711; //Dexterity1 Inteligence2 + else if (.@i <= 93) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 124) setarray .@enchants[2],4720,4760; //Dexterity1 Matk1 + else if (.@i <= 155) setarray .@enchants[2],4740,4710; //Vitality1 Inteligence1 + else if (.@i <= 186) setarray .@enchants[2],4740,4711; //Vitality1 Inteligence2 + else if (.@i <= 217) setarray .@enchants[2],4740,4721; //Vitality1 Dexterity2 + else if (.@i <= 248) setarray .@enchants[2],4740,4760; //Vitality1 Matk1 + else if (.@i <= 279) setarray .@enchants[2],4741,4710; //Vitality2 Inteligence1 + else if (.@i <= 310) setarray .@enchants[2],4741,4711; //Vitality2 Inteligence2 + else if (.@i <= 341) setarray .@enchants[2],4741,4721; //Vitality2 Dexterity2 + else if (.@i <= 372) setarray .@enchants[2],4741,4760; //Vitality2 Matk1 + else if (.@i <= 403) setarray .@enchants[2],4801,4710; //SP100 Inteligence1 + else if (.@i <= 434) setarray .@enchants[2],4801,4711; //SP100 Inteligence2 + else if (.@i <= 465) setarray .@enchants[2],4801,4721; //SP100 Dexterity2 + else if (.@i <= 496) setarray .@enchants[2],4801,4760; //SP100 Matk1 + else if (.@i <= 527) setarray .@enchants[2],4720,4710; //Dexterity1 Inteligence1 + else if (.@i <= 558) setarray .@enchants[2],4720,4711; //Dexterity1 Inteligence2 + else if (.@i <= 589) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 620) setarray .@enchants[2],4720,4760; //Dexterity1 Matk1 + else if (.@i <= 651) setarray .@enchants[2],4740,4710; //Vitality1 Inteligence1 + else if (.@i <= 682) setarray .@enchants[2],4740,4711; //Vitality1 Inteligence2 + else if (.@i <= 713) setarray .@enchants[2],4740,4721; //Vitality1 Dexterity2 + else if (.@i <= 744) setarray .@enchants[2],4740,4760; //Vitality1 Matk1 + else if (.@i <= 775) setarray .@enchants[2],4741,4710; //Vitality2 Inteligence1 + else if (.@i <= 806) setarray .@enchants[2],4741,4711; //Vitality2 Inteligence2 + else if (.@i <= 837) setarray .@enchants[2],4741,4721; //Vitality2 Dexterity2 + else if (.@i <= 868) setarray .@enchants[2],4741,4760; //Vitality2 Matk1 + else if (.@i <= 899) setarray .@enchants[2],4801,4710; //SP100 Inteligence1 + else if (.@i <= 930) setarray .@enchants[2],4801,4711; //SP100 Inteligence2 + else if (.@i <= 961) setarray .@enchants[2],4801,4721; //SP100 Dexterity2 + else if (.@i <= 992) setarray .@enchants[2],4801,4760; //SP100 Matk1 + else if (.@i <= 1023) setarray .@enchants[2],4720,4710; //Dexterity1 Inteligence1 + else if (.@i <= 1054) setarray .@enchants[2],4720,4711; //Dexterity1 Inteligence2 + else if (.@i <= 1085) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 1116) setarray .@enchants[2],4720,4760; //Dexterity1 Matk1 + else if (.@i <= 1147) setarray .@enchants[2],4740,4710; //Vitality1 Inteligence1 + else if (.@i <= 1178) setarray .@enchants[2],4740,4711; //Vitality1 Inteligence2 + else if (.@i <= 1209) setarray .@enchants[2],4740,4721; //Vitality1 Dexterity2 + else if (.@i <= 1240) setarray .@enchants[2],4740,4760; //Vitality1 Matk1 + else if (.@i <= 1271) setarray .@enchants[2],4741,4710; //Vitality2 Inteligence1 + else if (.@i <= 1302) setarray .@enchants[2],4741,4711; //Vitality2 Inteligence2 + else if (.@i <= 1333) setarray .@enchants[2],4741,4721; //Vitality2 Dexterity2 + else if (.@i <= 1364) setarray .@enchants[2],4741,4760; //Vitality2 Matk1 + else if (.@i <= 1395) setarray .@enchants[2],4801,4710; //SP100 Inteligence1 + else if (.@i <= 1426) setarray .@enchants[2],4801,4711; //SP100 Inteligence2 + else if (.@i <= 1457) setarray .@enchants[2],4801,4721; //SP100 Dexterity2 + else if (.@i <= 1488) setarray .@enchants[2],4801,4760; //SP100 Matk1 + else if (.@i <= 1519) setarray .@enchants[2],4720,4710; //Dexterity1 Inteligence1 + else if (.@i <= 1550) setarray .@enchants[2],4720,4711; //Dexterity1 Inteligence2 + else if (.@i <= 1581) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 1612) setarray .@enchants[2],4720,4760; //Dexterity1 Matk1 + else if (.@i <= 1643) setarray .@enchants[2],4740,4710; //Vitality1 Inteligence1 + else if (.@i <= 1674) setarray .@enchants[2],4740,4711; //Vitality1 Inteligence2 + else if (.@i <= 1705) setarray .@enchants[2],4740,4721; //Vitality1 Dexterity2 + else if (.@i <= 1736) setarray .@enchants[2],4740,4760; //Vitality1 Matk1 + else if (.@i <= 1767) setarray .@enchants[2],4741,4710; //Vitality2 Inteligence1 + else if (.@i <= 1798) setarray .@enchants[2],4741,4711; //Vitality2 Inteligence2 + else if (.@i <= 1829) setarray .@enchants[2],4741,4721; //Vitality2 Dexterity2 + else if (.@i <= 1860) setarray .@enchants[2],4741,4760; //Vitality2 Matk1 + else if (.@i <= 1891) setarray .@enchants[2],4801,4710; //SP100 Inteligence1 + else if (.@i <= 1922) setarray .@enchants[2],4801,4711; //SP100 Inteligence2 + else if (.@i <= 1953) setarray .@enchants[2],4801,4721; //SP100 Dexterity2 + else if (.@i <= 1984) setarray .@enchants[2],4801,4760; //SP100 Matk1 + else if (.@i <= 1986) setarray .@enchants[2],4761,4761; //Matk2 Matk2 + else if (.@i <= 1988) setarray .@enchants[2],4761,4723; //Matk2 Dexterity4 + else if (.@i <= 1990) setarray .@enchants[2],4761,4714; //Matk2 Inteligence5 + else if (.@i <= 1992) setarray .@enchants[2],4714,4714; //Inteligence5 Inteligence5 + else if (.@i <= 1994) setarray .@enchants[2],4714,4723; //Inteligence5 Dexterity4 + else if (.@i <= 1996) setarray .@enchants[2],4723,4723; //Dexterity4 Dexterity4 + else if (.@i <= 2852) { + mes "[Relice]"; + mes "Sometimes things just don't work out the way you want. I hope next time things go better for you. Until then, good bye."; + close; + } + break; + case 4: + set .@i, rand(1,2852); + if (.@i <= 31) setarray .@enchants[2],4720,4700; //Dexterity1 Strength1 + else if (.@i <= 62) setarray .@enchants[2],4720,4701; //Dexterity1 Strength2 + else if (.@i <= 93) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 124) setarray .@enchants[2],4720,4767; //Dexterity1 Atk3 + else if (.@i <= 155) setarray .@enchants[2],4740,4700; //Vitality1 Strength1 + else if (.@i <= 186) setarray .@enchants[2],4740,4701; //Vitality1 Strength2 + else if (.@i <= 217) setarray .@enchants[2],4740,4721; //Vitality1 Dexterity2 + else if (.@i <= 248) setarray .@enchants[2],4740,4767; //Vitality1 Atk3 + else if (.@i <= 279) setarray .@enchants[2],4741,4700; //Vitality2 Strength1 + else if (.@i <= 310) setarray .@enchants[2],4741,4701; //Vitality2 Strength2 + else if (.@i <= 341) setarray .@enchants[2],4741,4721; //Vitality2 Dexterity2 + else if (.@i <= 372) setarray .@enchants[2],4741,4767; //Vitality2 Atk3 + else if (.@i <= 403) setarray .@enchants[2],4701,4700; //Strength2 Strength1 + else if (.@i <= 434) setarray .@enchants[2],4701,4701; //Strength2 Strength2 + else if (.@i <= 465) setarray .@enchants[2],4701,4721; //Strength2 Dexterity2 + else if (.@i <= 496) setarray .@enchants[2],4701,4767; //Strength2 Atk3 + else if (.@i <= 527) setarray .@enchants[2],4720,4700; //Dexterity1 Strength1 + else if (.@i <= 558) setarray .@enchants[2],4720,4701; //Dexterity1 Strength2 + else if (.@i <= 589) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 620) setarray .@enchants[2],4720,4767; //Dexterity1 Atk3 + else if (.@i <= 651) setarray .@enchants[2],4740,4700; //Vitality1 Strength1 + else if (.@i <= 682) setarray .@enchants[2],4740,4701; //Vitality1 Strength2 + else if (.@i <= 713) setarray .@enchants[2],4740,4721; //Vitality1 Dexterity2 + else if (.@i <= 744) setarray .@enchants[2],4740,4767; //Vitality1 Atk3 + else if (.@i <= 775) setarray .@enchants[2],4741,4700; //Vitality2 Strength1 + else if (.@i <= 806) setarray .@enchants[2],4741,4701; //Vitality2 Strength2 + else if (.@i <= 837) setarray .@enchants[2],4741,4721; //Vitality2 Dexterity2 + else if (.@i <= 868) setarray .@enchants[2],4741,4767; //Vitality2 Atk3 + else if (.@i <= 899) setarray .@enchants[2],4701,4700; //Strength2 Strength1 + else if (.@i <= 930) setarray .@enchants[2],4701,4701; //Strength2 Strength2 + else if (.@i <= 961) setarray .@enchants[2],4701,4721; //Strength2 Dexterity2 + else if (.@i <= 992) setarray .@enchants[2],4701,4767; //Strength2 Atk3 + else if (.@i <= 1023) setarray .@enchants[2],4720,4700; //Dexterity1 Strength1 + else if (.@i <= 1054) setarray .@enchants[2],4720,4701; //Dexterity1 Strength2 + else if (.@i <= 1085) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 1116) setarray .@enchants[2],4720,4767; //Dexterity1 Atk3 + else if (.@i <= 1147) setarray .@enchants[2],4740,4700; //Vitality1 Strength1 + else if (.@i <= 1178) setarray .@enchants[2],4740,4701; //Vitality1 Strength2 + else if (.@i <= 1209) setarray .@enchants[2],4740,4721; //Vitality1 Dexterity2 + else if (.@i <= 1240) setarray .@enchants[2],4740,4767; //Vitality1 Atk3 + else if (.@i <= 1271) setarray .@enchants[2],4741,4700; //Vitality2 Strength1 + else if (.@i <= 1302) setarray .@enchants[2],4741,4701; //Vitality2 Strength2 + else if (.@i <= 1333) setarray .@enchants[2],4741,4721; //Vitality2 Dexterity2 + else if (.@i <= 1364) setarray .@enchants[2],4741,4767; //Vitality2 Atk3 + else if (.@i <= 1395) setarray .@enchants[2],4701,4700; //Strength2 Strength1 + else if (.@i <= 1426) setarray .@enchants[2],4701,4701; //Strength2 Strength2 + else if (.@i <= 1457) setarray .@enchants[2],4701,4721; //Strength2 Dexterity2 + else if (.@i <= 1488) setarray .@enchants[2],4701,4767; //Strength2 Atk3 + else if (.@i <= 1519) setarray .@enchants[2],4720,4700; //Dexterity1 Strength1 + else if (.@i <= 1550) setarray .@enchants[2],4720,4701; //Dexterity1 Strength2 + else if (.@i <= 1581) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 1612) setarray .@enchants[2],4720,4767; //Dexterity1 Atk3 + else if (.@i <= 1643) setarray .@enchants[2],4740,4700; //Vitality1 Strength1 + else if (.@i <= 1674) setarray .@enchants[2],4740,4701; //Vitality1 Strength2 + else if (.@i <= 1705) setarray .@enchants[2],4740,4721; //Vitality1 Dexterity2 + else if (.@i <= 1736) setarray .@enchants[2],4740,4767; //Vitality1 Atk3 + else if (.@i <= 1767) setarray .@enchants[2],4741,4700; //Vitality2 Strength1 + else if (.@i <= 1798) setarray .@enchants[2],4741,4701; //Vitality2 Strength2 + else if (.@i <= 1829) setarray .@enchants[2],4741,4721; //Vitality2 Dexterity2 + else if (.@i <= 1860) setarray .@enchants[2],4741,4767; //Vitality2 Atk3 + else if (.@i <= 1891) setarray .@enchants[2],4701,4700; //Strength2 Strength1 + else if (.@i <= 1922) setarray .@enchants[2],4701,4701; //Strength2 Strength2 + else if (.@i <= 1953) setarray .@enchants[2],4701,4721; //Strength2 Dexterity2 + else if (.@i <= 1984) setarray .@enchants[2],4701,4767; //Strength2 Atk3 + else if (.@i <= 1986) setarray .@enchants[2],4767,4767; //Atk3 Atk3 + else if (.@i <= 1988) setarray .@enchants[2],4767,4723; //Atk3 Dexterity4 + else if (.@i <= 1990) setarray .@enchants[2],4767,4704; //Atk3 Strength5 + else if (.@i <= 1992) setarray .@enchants[2],4704,4704; //Strength5 Strength5 + else if (.@i <= 1994) setarray .@enchants[2],4704,4723; //Strength5 Dexterity4 + else if (.@i <= 1996) setarray .@enchants[2],4723,4723; //Dexterity4 Dexterity4 + else if (.@i <= 2852) { + mes "[Relice]"; + mes "Sometimes things just don't work out the way you want. I hope next time things go better for you. Until then, good bye."; + close; + } + break; + } + getitem2 .@item,1,1,0,0,0,.@enchants[1],.@enchants[2],.@enchants[3]; + mes "[Relice]"; + mes "The strengthening went well, lucky you!"; + close; + } +} + +// Warlock Enchants :: coin_warrock +//============================================================ +mora,104,76,4 script Guardian of Artifacts#p 495,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (countitem(6380) < 10) { + mes "[Guardian of Artifacts]"; + mes "My job is to guard the Warlock's ancient artifacts."; + next; + mes "[Guardian of Artifacts]"; + mes "Well, it's not a big deal actually. I give out artifacts to those who deserve them for the price of a few Mora Coins."; + next; + mes "[Guardian of Artifacts]"; + mes "You can trade with me when you have 10 or more Coins. See you later."; + close; + } + mes "[Guardian of Artifacts]"; + mes "Wow~ I see you're ready for the Warlock's Ancient Artifacts."; + next; + mes "[Guardian of Artifacts]"; + mes "You can choose from four types of items:"; + mes "staffs, orbs, shoes, and robes."; + next; + mes "[Guardian of Artifacts]"; + mes "There are four options available for each type, but the item available will change day to day, depending on my mood."; + next; + mes "[Guardian of Artifacts]"; + mes "Do you want to buy an artifact with your Mora Coins?"; + next; + if(select("Maybe later... I have things to do.:Yes, I do.") == 1) { + mes "[Guardian of Artifacts]"; + mes "Okay, see you later then."; + close; + } + mes "[Guardian of Artifacts]"; + mes "What type of item do you want to buy?"; + next; + switch(select("Quit:Shoes:Orbs:Robes:Staves")) { + case 1: + mes "[Guardian of Artifacts]"; + mes "Okay, see you later then."; + close; + case 2: + setarray .@items[0],2467,2468,2469,2470; //Golden_Rod_Shoes,Aqua_Shoes,Crimson_Shoes,Forest_Shoes + set .@plural,1; + break; + case 3: + setarray .@items[0],2859,2860,2861,2862; //Golden_Rod_Orb,Aqua_Orb,Crimson_Orb,Forest_Orb + break; + case 4: + setarray .@items[0],15025,15026,15027,15028; //Golden_Rod_Robe,Aqua_Robe,Crimson_Robe,Forest_Robe + break; + case 5: + setarray .@items[0],2007,2008,2009,2010; //Golden_Rod_Staff,Aqua_Staff,Crimson_Staff,Forest_Staff + break; + } + if (countitem(6380) < 10) { + mes "[Guardian of Artifacts]"; + mes "Would you please come back when you have enough Coins?"; + close; + } + set .@item, .@items[rand(getarraysize(.@items))]; + delitem 6380,10; //Mora_Coin + getitem .@item,1; + mes "[Guardian of Artifacts]"; + mes "I have ^aa00aa"+getitemname(.@item)+"^000000 available today. I hope "+((.@plural)?"they":"it")+" will come in handy..."; + close; +} + +mora,99,93,5 script Artifact Crafter#pa0829 495,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + disable_items; + mes "[Artifact Crafter]"; + mes "My job is to imbue artifacts with new power. If you have enough Coins, you can have one of the following items reinforced."; + next; + if(select("Tell me more.:I want to have my item reinforced.") == 1) { + mes "[Artifact Crafter]"; + mes "Let me explain. One reinforcement costs you two Coins."; + next; + set .@info_only,1; + } + mes "[Artifact Crafter]"; + mes "And, I'll work on the item whether it's been already reinforced or not."; + next; + mes "[Artifact Crafter]"; + mes "So if you have an artifact reinforced to your liking, put it in a safe place and come back."; + next; + mes "[Artifact Crafter]"; + mes "And another thing, the artifact will be destroyed if the reinforcement fails. Please keep that in mind."; + if (.@info_only) + close; + next; + set .@select, select("Maybe next time.:Golden Rod Staff:Aqua Staff:Crimson Staff:Forest Staff:Golden Rod Shoes:Aqua Shoes:Crimson Shoes:Forest Shoes:Golden Rod Orb:Aqua Orb:Crimson Orb:Forest Orb:Golden Rod Robe:Aqua Robe:Crimson Robe:Forest Robe"); + switch(.@select) { + case 1: + mes "[Artifact Crafter]"; + mes "As you wish."; + close; + case 2: + case 3: + case 4: + case 5: + setarray .@items[0],2007,2008,2009,2010; //Golden_Rod_Staff,Aqua_Staff,Crimson_Staff,Forest_Staff + set .@enchant_type,1; + break; + case 6: + case 7: + case 8: + case 9: + setarray .@items[0],2467,2468,2469,2470; //Golden_Rod_Shoes,Aqua_Shoes,Crimson_Shoes,Forest_Shoes + set .@enchant_type,2; + break; + case 10: + case 11: + case 12: + case 13: + setarray .@items[0],2859,2860,2861,2862; //Golden_Rod_Orb,Aqua_Orb,Crimson_Orb,Forest_Orb + set .@enchant_type,2; + break; + case 14: + case 15: + case 16: + case 17: + setarray .@items[0],15025,15026,15027,15028; //Golden_Rod_Robe,Aqua_Robe,Crimson_Robe,Forest_Robe + set .@enchant_type,2; + break; + } + set .@item, .@items[(.@select-2)%4]; + if (countitem(6380) == 0 || countitem(.@item) == 0) { + mes "[Artifact Crafter]"; + mes "You have to have 2 Mora Coins and an item to be reinforced before I can do my work."; + close; + } + specialeffect2 EF_REPAIRWEAPON; + delitem 6380,2; //Mora_Coin + delitem .@item,1; + switch(.@enchant_type) { + case 1: + set .@i, rand(1,2847); + if (.@i <= 31) setarray .@enchants[2],4720,4786; //Dexterity1 Mdef2 + else if (.@i <= 62) setarray .@enchants[2],4720,4760; //Dexterity1 Matk1 + else if (.@i <= 93) setarray .@enchants[2],4720,4711; //Dexterity1 Inteligence2 + else if (.@i <= 124) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 155) setarray .@enchants[2],4796,4786; //HP200 Mdef2 + else if (.@i <= 186) setarray .@enchants[2],4796,4760; //HP200 Matk1 + else if (.@i <= 217) setarray .@enchants[2],4796,4711; //HP200 Inteligence2 + else if (.@i <= 248) setarray .@enchants[2],4796,4721; //HP200 Dexterity2 + else if (.@i <= 279) setarray .@enchants[2],4710,4786; //Inteligence1 Mdef2 + else if (.@i <= 310) setarray .@enchants[2],4710,4760; //Inteligence1 Matk1 + else if (.@i <= 341) setarray .@enchants[2],4710,4711; //Inteligence1 Inteligence2 + else if (.@i <= 372) setarray .@enchants[2],4710,4721; //Inteligence1 Dexterity2 + else if (.@i <= 403) setarray .@enchants[2],4801,4786; //SP100 Mdef2 + else if (.@i <= 434) setarray .@enchants[2],4801,4760; //SP100 Matk1 + else if (.@i <= 465) setarray .@enchants[2],4801,4711; //SP100 Inteligence2 + else if (.@i <= 496) setarray .@enchants[2],4801,4721; //SP100 Dexterity2 + else if (.@i <= 527) setarray .@enchants[2],4720,4786; //Dexterity1 Mdef2 + else if (.@i <= 558) setarray .@enchants[2],4720,4760; //Dexterity1 Matk1 + else if (.@i <= 589) setarray .@enchants[2],4720,4711; //Dexterity1 Inteligence2 + else if (.@i <= 620) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 651) setarray .@enchants[2],4796,4786; //HP200 Mdef2 + else if (.@i <= 682) setarray .@enchants[2],4796,4760; //HP200 Matk1 + else if (.@i <= 713) setarray .@enchants[2],4796,4711; //HP200 Inteligence2 + else if (.@i <= 744) setarray .@enchants[2],4796,4721; //HP200 Dexterity2 + else if (.@i <= 775) setarray .@enchants[2],4710,4786; //Inteligence1 Mdef2 + else if (.@i <= 806) setarray .@enchants[2],4710,4760; //Inteligence1 Matk1 + else if (.@i <= 837) setarray .@enchants[2],4710,4711; //Inteligence1 Inteligence2 + else if (.@i <= 868) setarray .@enchants[2],4710,4721; //Inteligence1 Dexterity2 + else if (.@i <= 899) setarray .@enchants[2],4801,4786; //SP100 Mdef2 + else if (.@i <= 930) setarray .@enchants[2],4801,4760; //SP100 Matk1 + else if (.@i <= 961) setarray .@enchants[2],4801,4711; //SP100 Inteligence2 + else if (.@i <= 992) setarray .@enchants[2],4801,4721; //SP100 Dexterity2 + else if (.@i <= 1023) setarray .@enchants[2],4720,4786; //Dexterity1 Mdef2 + else if (.@i <= 1054) setarray .@enchants[2],4720,4760; //Dexterity1 Matk1 + else if (.@i <= 1085) setarray .@enchants[2],4720,4711; //Dexterity1 Inteligence2 + else if (.@i <= 1116) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 1147) setarray .@enchants[2],4796,4786; //HP200 Mdef2 + else if (.@i <= 1178) setarray .@enchants[2],4796,4760; //HP200 Matk1 + else if (.@i <= 1209) setarray .@enchants[2],4796,4711; //HP200 Inteligence2 + else if (.@i <= 1240) setarray .@enchants[2],4796,4721; //HP200 Dexterity2 + else if (.@i <= 1271) setarray .@enchants[2],4710,4786; //Inteligence1 Mdef2 + else if (.@i <= 1302) setarray .@enchants[2],4710,4760; //Inteligence1 Matk1 + else if (.@i <= 1333) setarray .@enchants[2],4710,4711; //Inteligence1 Inteligence2 + else if (.@i <= 1364) setarray .@enchants[2],4710,4721; //Inteligence1 Dexterity2 + else if (.@i <= 1395) setarray .@enchants[2],4801,4786; //SP100 Mdef2 + else if (.@i <= 1426) setarray .@enchants[2],4801,4760; //SP100 Matk1 + else if (.@i <= 1457) setarray .@enchants[2],4801,4711; //SP100 Inteligence2 + else if (.@i <= 1488) setarray .@enchants[2],4801,4721; //SP100 Dexterity2 + else if (.@i <= 1519) setarray .@enchants[2],4720,4786; //Dexterity1 Mdef2 + else if (.@i <= 1550) setarray .@enchants[2],4720,4760; //Dexterity1 Matk1 + else if (.@i <= 1581) setarray .@enchants[2],4720,4711; //Dexterity1 Inteligence2 + else if (.@i <= 1612) setarray .@enchants[2],4720,4721; //Dexterity1 Dexterity2 + else if (.@i <= 1643) setarray .@enchants[2],4796,4786; //HP200 Mdef2 + else if (.@i <= 1674) setarray .@enchants[2],4796,4760; //HP200 Matk1 + else if (.@i <= 1705) setarray .@enchants[2],4796,4711; //HP200 Inteligence2 + else if (.@i <= 1736) setarray .@enchants[2],4796,4721; //HP200 Dexterity2 + else if (.@i <= 1767) setarray .@enchants[2],4710,4786; //Inteligence1 Mdef2 + else if (.@i <= 1798) setarray .@enchants[2],4710,4760; //Inteligence1 Matk1 + else if (.@i <= 1829) setarray .@enchants[2],4710,4711; //Inteligence1 Inteligence2 + else if (.@i <= 1860) setarray .@enchants[2],4710,4721; //Inteligence1 Dexterity2 + else if (.@i <= 1891) setarray .@enchants[2],4801,4786; //SP100 Mdef2 + else if (.@i <= 1922) setarray .@enchants[2],4801,4760; //SP100 Matk1 + else if (.@i <= 1953) setarray .@enchants[2],4801,4711; //SP100 Inteligence2 + else if (.@i <= 1984) setarray .@enchants[2],4801,4721; //SP100 Dexterity2 + else if (.@i <= 1986) setarray .@enchants[2],4713,4761; //Inteligence4 Matk2 + else if (.@i <= 1988) setarray .@enchants[2],4713,4713; //Inteligence4 Inteligence4 + else if (.@i <= 1990) setarray .@enchants[2],4761,4761; //Matk2 Matk2 + else if (.@i <= 1992) setarray .@enchants[2],4761,4713; //Matk2 Inteligence4 + else if (.@i <= 2847) { + mes "[Artifact Crafter]"; + mes "Oh no... it broke... Well, it happens. Better luck next time."; + close; + } + break; + case 2: + set .@i, rand(1,2858); + if (.@i <= 31) setarray .@enchants[1],4710,4720,4786; //Inteligence1 Dexterity1 Mdef2 + else if (.@i <= 62) setarray .@enchants[1],4710,4720,4760; //Inteligence1 Dexterity1 Matk1 + else if (.@i <= 93) setarray .@enchants[1],4710,4720,4711; //Inteligence1 Dexterity1 Inteligence2 + else if (.@i <= 124) setarray .@enchants[1],4710,4720,4721; //Inteligence1 Dexterity1 Dexterity2 + else if (.@i <= 155) setarray .@enchants[1],4710,4796,4786; //Inteligence1 HP200 Mdef2 + else if (.@i <= 186) setarray .@enchants[1],4710,4796,4760; //Inteligence1 HP200 Matk1 + else if (.@i <= 217) setarray .@enchants[1],4710,4796,4711; //Inteligence1 HP200 Inteligence2 + else if (.@i <= 248) setarray .@enchants[1],4710,4796,4721; //Inteligence1 HP200 Dexterity2 + else if (.@i <= 279) setarray .@enchants[1],4710,4710,4786; //Inteligence1 Inteligence1 Mdef2 + else if (.@i <= 310) setarray .@enchants[1],4710,4710,4760; //Inteligence1 Inteligence1 Matk1 + else if (.@i <= 341) setarray .@enchants[1],4710,4710,4711; //Inteligence1 Inteligence1 Inteligence2 + else if (.@i <= 372) setarray .@enchants[1],4710,4710,4721; //Inteligence1 Inteligence1 Dexterity2 + else if (.@i <= 403) setarray .@enchants[1],4710,4801,4786; //Inteligence1 SP100 Mdef2 + else if (.@i <= 434) setarray .@enchants[1],4710,4801,4760; //Inteligence1 SP100 Matk1 + else if (.@i <= 465) setarray .@enchants[1],4710,4801,4711; //Inteligence1 SP100 Inteligence2 + else if (.@i <= 496) setarray .@enchants[1],4710,4801,4721; //Inteligence1 SP100 Dexterity2 + else if (.@i <= 527) setarray .@enchants[1],4711,4720,4786; //Inteligence2 Dexterity1 Mdef2 + else if (.@i <= 558) setarray .@enchants[1],4711,4720,4760; //Inteligence2 Dexterity1 Matk1 + else if (.@i <= 589) setarray .@enchants[1],4711,4720,4711; //Inteligence2 Dexterity1 Inteligence2 + else if (.@i <= 620) setarray .@enchants[1],4711,4720,4721; //Inteligence2 Dexterity1 Dexterity2 + else if (.@i <= 651) setarray .@enchants[1],4711,4796,4786; //Inteligence2 HP200 Mdef2 + else if (.@i <= 682) setarray .@enchants[1],4711,4796,4760; //Inteligence2 HP200 Matk1 + else if (.@i <= 713) setarray .@enchants[1],4711,4796,4711; //Inteligence2 HP200 Inteligence2 + else if (.@i <= 744) setarray .@enchants[1],4711,4796,4721; //Inteligence2 HP200 Dexterity2 + else if (.@i <= 775) setarray .@enchants[1],4711,4710,4786; //Inteligence2 Inteligence1 Mdef2 + else if (.@i <= 806) setarray .@enchants[1],4711,4710,4760; //Inteligence2 Inteligence1 Matk1 + else if (.@i <= 837) setarray .@enchants[1],4711,4710,4711; //Inteligence2 Inteligence1 Inteligence2 + else if (.@i <= 868) setarray .@enchants[1],4711,4710,4721; //Inteligence2 Inteligence1 Dexterity2 + else if (.@i <= 899) setarray .@enchants[1],4711,4801,4786; //Inteligence2 SP100 Mdef2 + else if (.@i <= 930) setarray .@enchants[1],4711,4801,4760; //Inteligence2 SP100 Matk1 + else if (.@i <= 961) setarray .@enchants[1],4711,4801,4711; //Inteligence2 SP100 Inteligence2 + else if (.@i <= 992) setarray .@enchants[1],4711,4801,4721; //Inteligence2 SP100 Dexterity2 + else if (.@i <= 1023) setarray .@enchants[1],4720,4720,4786; //Dexterity1 Dexterity1 Mdef2 + else if (.@i <= 1054) setarray .@enchants[1],4720,4720,4760; //Dexterity1 Dexterity1 Matk1 + else if (.@i <= 1085) setarray .@enchants[1],4720,4720,4711; //Dexterity1 Dexterity1 Inteligence2 + else if (.@i <= 1116) setarray .@enchants[1],4720,4720,4721; //Dexterity1 Dexterity1 Dexterity2 + else if (.@i <= 1147) setarray .@enchants[1],4720,4796,4786; //Dexterity1 HP200 Mdef2 + else if (.@i <= 1178) setarray .@enchants[1],4720,4796,4760; //Dexterity1 HP200 Matk1 + else if (.@i <= 1209) setarray .@enchants[1],4720,4796,4711; //Dexterity1 HP200 Inteligence2 + else if (.@i <= 1240) setarray .@enchants[1],4720,4796,4721; //Dexterity1 HP200 Dexterity2 + else if (.@i <= 1271) setarray .@enchants[1],4720,4710,4786; //Dexterity1 Inteligence1 Mdef2 + else if (.@i <= 1302) setarray .@enchants[1],4720,4710,4760; //Dexterity1 Inteligence1 Matk1 + else if (.@i <= 1333) setarray .@enchants[1],4720,4710,4711; //Dexterity1 Inteligence1 Inteligence2 + else if (.@i <= 1364) setarray .@enchants[1],4720,4710,4721; //Dexterity1 Inteligence1 Dexterity2 + else if (.@i <= 1395) setarray .@enchants[1],4720,4801,4786; //Dexterity1 SP100 Mdef2 + else if (.@i <= 1426) setarray .@enchants[1],4720,4801,4760; //Dexterity1 SP100 Matk1 + else if (.@i <= 1457) setarray .@enchants[1],4720,4801,4711; //Dexterity1 SP100 Inteligence2 + else if (.@i <= 1488) setarray .@enchants[1],4720,4801,4721; //Dexterity1 SP100 Dexterity2 + else if (.@i <= 1519) setarray .@enchants[1],4721,4720,4786; //Dexterity2 Dexterity1 Mdef2 + else if (.@i <= 1550) setarray .@enchants[1],4721,4720,4760; //Dexterity2 Dexterity1 Matk1 + else if (.@i <= 1581) setarray .@enchants[1],4721,4720,4711; //Dexterity2 Dexterity1 Inteligence2 + else if (.@i <= 1612) setarray .@enchants[1],4721,4720,4721; //Dexterity2 Dexterity1 Dexterity2 + else if (.@i <= 1643) setarray .@enchants[1],4721,4796,4786; //Dexterity2 HP200 Mdef2 + else if (.@i <= 1674) setarray .@enchants[1],4721,4796,4760; //Dexterity2 HP200 Matk1 + else if (.@i <= 1705) setarray .@enchants[1],4721,4796,4711; //Dexterity2 HP200 Inteligence2 + else if (.@i <= 1736) setarray .@enchants[1],4721,4796,4721; //Dexterity2 HP200 Dexterity2 + else if (.@i <= 1767) setarray .@enchants[1],4721,4710,4786; //Dexterity2 Inteligence1 Mdef2 + else if (.@i <= 1798) setarray .@enchants[1],4721,4710,4760; //Dexterity2 Inteligence1 Matk1 + else if (.@i <= 1829) setarray .@enchants[1],4721,4710,4711; //Dexterity2 Inteligence1 Inteligence2 + else if (.@i <= 1860) setarray .@enchants[1],4721,4710,4721; //Dexterity2 Inteligence1 Dexterity2 + else if (.@i <= 1891) setarray .@enchants[1],4721,4801,4786; //Dexterity2 SP100 Mdef2 + else if (.@i <= 1922) setarray .@enchants[1],4721,4801,4760; //Dexterity2 SP100 Matk1 + else if (.@i <= 1953) setarray .@enchants[1],4721,4801,4711; //Dexterity2 SP100 Inteligence2 + else if (.@i <= 1984) setarray .@enchants[1],4721,4801,4721; //Dexterity2 SP100 Dexterity2 + else if (.@i <= 1986) setarray .@enchants[1],4712,4713,4761; //Inteligence3 Inteligence4 Matk2 + else if (.@i <= 1988) setarray .@enchants[1],4712,4713,4713; //Inteligence3 Inteligence4 Inteligence4 + else if (.@i <= 1990) setarray .@enchants[1],4712,4761,4761; //Inteligence3 Matk2 Matk2 + else if (.@i <= 1992) setarray .@enchants[1],4712,4761,4713; //Inteligence3 Matk2 Inteligence4 + else if (.@i <= 1994) setarray .@enchants[1],4722,4713,4761; //Dexterity3 Inteligence4 Matk2 + else if (.@i <= 1996) setarray .@enchants[1],4722,4713,4713; //Dexterity3 Inteligence4 Inteligence4 + else if (.@i <= 1998) setarray .@enchants[1],4722,4761,4761; //Dexterity3 Matk2 Matk2 + else if (.@i <= 2000) setarray .@enchants[1],4722,4761,4713; //Dexterity3 Matk2 Inteligence4 + else if (.@i <= 2858) { + mes "[Artifact Crafter]"; + mes "Oh no... it broke... Well, it happens. Better luck next time."; + close; + } + break; + } + getitem2 .@item,1,1,0,0,0,.@enchants[1],.@enchants[2],.@enchants[3]; + mes "[Artifact Crafter]"; + mes "Looks like my effort was successful."; + close; +} + +// Rune Knight, Guillotine Cross, & Ranger Enchants :: new_artifact +//============================================================ +mora,152,97,5 script Guardian of Power#pa082 515,{ + if (checkweight(1201,1) == 0) { + mes "Reduce the amount of items that you have in your inventory before continuing."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much in your inventory."; + close; + } + if (countitem(6380) < 10) { + mes "[Guardian of Power]"; + mes "I give Rune Knights, Guillotine Crosses, and Rangers ancient artifacts to help them carry out their missions."; + next; + mes "[Guardian of Power]"; + mes "There are guardians that give Mora Village coins which you can use to exchange for these artifacts."; + next; + mes "[Guardian of Power]"; + mes "If you collect 10 or more Mora coins, then I can trade them for the artifacts."; + close; + } + mes "[Guardian of Power]"; + mes "I think that you're ready to receive the ancient artifacts."; + next; + mes "[Guardian of Power]"; + mes "Based on what class you specify, there are various artifacts available."; + next; + mes "[Guardian of Power]"; + mes "^ff0000Choose carefully because these artifacts aren't easy to come by^000000. So what class do you want it for?"; + next; + setarray .@jobs$[0],"Rune Knight","Guillotine Cross","Ranger"; + set .@job, select("Cancel:Rune Knight:Guillotine Cross:Ranger")-2; + if (.@job == -1) { + mes "[Guardian of Power]"; + mes "Talk to me later then."; + close; + } + mes "[Guardian of Power]"; + mes .@jobs$[.@job]+"~ which artifact do you want?"; + next; + switch(.@job) { + case 0: // Rune Knight + setarray .@items[0],2475,2476,2574,2575; + set .@i, select("Cancel:Ur's Greaves (Shoes):Peuz Greaves (Shoes):Ur's Manteau (Garment):Peuz Manteau (Garment)")-2; + break; + case 1: // Guillotine Cross + setarray .@items[0],2477,2478,2577,2578; + set .@i, select("Cancel:Sapha Shoes (Shoes):Nab Shoes (Shoes):Sapha Hood (Garment):Nab Hood (Garment)")-2; + break; + case 2: // Ranger + setarray .@items[0],2479,2480,2580,2581; + set .@i, select("Cancel:White Wing Boots (Shoes):Black Wing Boots (Shoes):White Wing Manteau (Garment):Black Wing Manteau (Garment)")-2; + break; + } + if (.@i == -1) { + mes "[Guardian of Power]"; + mes "Talk to me later then."; + close; + } + if (countitem(6380) < 10) { + mes "[Guardian of Power]"; + mes "Didn't I tell you to bring the correct amount of Mora Coins?"; + close; + } + delitem 6380,10; //Mora_Coin + getitem .@items[.@i],1; + mes "[Guardian of Power]"; + mes "Thank you for the 10 Mora Coins. Here is your artifact for the "+.@jobs$[.@job]+" job. Come back whenever you get more Mora Coins."; + close; +} + +mora,148,98,3 script Artifact Researcher#new 521,{ + if (checkweight(1201,1) == 0) { + mes "Reduce the amount of items that you have in your inventory before continuing."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much in your inventory."; + close; + } + disable_items; + mes "[Artifact Researcher]"; + mes "Nice to meet you."; + mes "I'm here in Mora studying ancient relics and artifacts. The new discoveries of Adventurers has made this village very exciting for me."; + next; + switch(select("Tell me more...:Give abilities to artifacts.:Reset Enhanced abilities.")) { + case 1: + mes "[Artifact Researcher]"; + mes "New artifacts have been found here in Mora village, haven't you heard the news?"; + next; + mes "[Artifact Researcher]"; + mes "If you come across any of these artifacts, there are hidden powers that can be extracted from them."; + next; + mes "[Artifact Researcher]"; + mes "I'm going to continue my research for these artifacts. We researchers are taking Mora Coins as payment for our services..."; + next; + mes "[Artifact Researcher]"; + mes "I'm offering my services to give abilities to the artifacts for 100,000 zeny and 1 Mora Coin."; + next; + mes "[Artifact Researcher]"; + mes "The best part of my service is that any enhancements that you have in these artifacts will not be harmed."; + close; + case 2: + set @mora_enchant_select,1; + break; + case 3: + set @mora_enchant_select,2; + break; + } + if (Zeny < 100000 || countitem(6380) == 0) { + mes "[Artifact Researcher]"; + mes "I'm not giving these services out for free pal. 100,000 zeny or 1 Mora Coin. Is that too much to ask?"; + close; + } + mes "[Artifact Researcher]"; + mes "Ok, so are you ready? Before I start working on this, what kind of equipment did you want me to enhance?"; + next; + set .@i, select("I'm not wearing the equipment:1. Weapon:2. Shoes:3. Garment:4. Armor:5. Accessory")-2; + if (.@i == -1) { + mes "[Artifact Researcher]"; + mes "Make sure you're wearing the equipment first."; + close; + } + setarray .@parts[0], EQI_HAND_R, EQI_SHOES, EQI_GARMENT, EQI_ARMOR, EQI_ACC_L; + set .@part, .@parts[.@i]; + if (!getequipisequiped(.@part)) { + mes "[Artifact Researcher]"; + mes "Make sure you're wearing the equipment first."; + close; + } + set .@equip_id, getequipid(.@part); + set @mora_equip_part, .@part; + + // @mora_equip_id = enc_type + //callsub L_Socket,,,<4-x enchants possible>; + // Enchant types: + // [1]ATK [2]CRIT [3]EVA [4]Healer [5]Spell 1 [6]Assist 1 [7]Assist 2 [8]STR [9]Range [10]Physical [11]Spell 2 + switch(.@part) { + case 4: //EQI_HAND_R + switch(.@equip_id) { + case 1660: callsub L_Socket,4,5,1; //Wand_Of_Affection2 + case 2011: callsub L_Socket,5,11,1; //Golden_Rod_Staff2 + case 2012: callsub L_Socket,5,11,1; //Aqua_Staff2 + case 2013: callsub L_Socket,5,11,1; //Crimson_Staff2 + case 2014: callsub L_Socket,5,11,1; //Forest_Staff2 + case 16018: callsub L_Socket,1,5,1; //Mace_Of_Judgement2 + } + break; + case 6: //EQI_SHOES + switch(.@equip_id) { + case 2475: callsub L_Socket,6,8,1; //Ur_Greave + case 2476: callsub L_Socket,6,10,1; //Peuz_Greave + case 2477: callsub L_Socket,6,2,1; //Sabah_Shoes + case 2478: callsub L_Socket,6,1,1; //Nab_Shoes + case 2479: callsub L_Socket,6,2,1; //White_Wing_Boots + case 2480: callsub L_Socket,6,1,1; //Black_Wing_Boots + } + break; + case 5: //EQI_GARMENT + switch(.@equip_id) { + case 2574: callsub L_Socket,3,8,1; //Ur_Manteau + case 2575: callsub L_Socket,3,2,1; //Peuz_Manteau + case 2577: callsub L_Socket,3,2,1; //Sabah_Hood + case 2578: callsub L_Socket,3,2,1; //Nab_Hood + case 2580: callsub L_Socket,3,1,1; //White_Wing_Manteau + case 2581: callsub L_Socket,3,1,1; //Black_Wing_Manteau + } + break; + case 2: //EQI_ARMOR + switch(.@equip_id) { + case 15036: callsub L_Socket,8,1,1; //Ur_Plate + case 15037: callsub L_Socket,10,2,1; //Peuz_Plate + case 15038: callsub L_Socket,2,10,1; //Sabah_Cloth + case 15039: callsub L_Socket,1,2,1; //Nab_Cloth + case 15042: callsub L_Socket,2,9,1; //White_Wing_Suits + case 15043: callsub L_Socket,1,9,1; //Black_Wing_Suits + } + break; + case 7: //EQI_ACC_L + switch(.@equip_id) { + case 2883: callsub L_Socket,6,0,2; //Ur_Seal + case 2884: callsub L_Socket,6,0,2; //Peuz_Seal + case 2886: callsub L_Socket,6,0,2; //Sabah_Ring + case 2887: callsub L_Socket,6,0,2; //Nab_Ring + case 2890: callsub L_Socket,6,0,2; //White_Wing_Brooch + case 2891: callsub L_Socket,6,0,2; //Black_wing_Brooch + } + break; + } + mes "[Artifact Researcher]"; + mes "^990099"+getequipname(.@part)+"^000000??"; + mes "I really want to study this equipment..."; + set @mora_equip_part,0; + close; + +L_Socket: + set .@select, @mora_enchant_select; + set .@enchant_type, getarg(0); + set .@part, @mora_equip_part; + set .@equip_id, getequipid(.@part); + set .@equip_name$, getitemname(.@equip_id); + set .@equip_refine, getequiprefinerycnt(.@part); + setarray .@equip_card[0], getequipcardid(.@part,0),getequipcardid(.@part,1),getequipcardid(.@part,2),getequipcardid(.@part,3); + set @mora_equip_part,0; + set @mora_enchant_select,0; + + if (.@select == 1) { + // If refine is +9 or higher, unlock bonus enchant type. + if (.@equip_refine >= 9 && getarg(1) > 0) { + if (.@enchant_type < 1 || .@enchant_type > 11 || getarg(1) > 11) { + mes "[Artifact Researcher]"; + mes "Mm-hmm something is wrong."; + close; + } + setarray .@enchant_type$[1],"ATK Type","Critical Type","Evasion Type","Healer Type","Spell Ability 1","Assist Ability 1","Assist Ability 2","Strength","Range Type","Physical Type","Spell Ability 2"; + mes "[Artifact Researcher]"; + mes "It's a considerable reinforcement to the equipment. In this case extended enhancements can be granted. Which stat do you want to enhance?"; + next; + switch(select(.@enchant_type$[.@enchant_type],.@enchant_type$[getarg(1)])) { + case 1: + break; + case 2: + set .@enchant_type, getarg(1); + break; + } + } + if (.@equip_card[3] == 0 && getarg(2) < 4) { + set .@slot,4; + mes "[Artifact Researcher]"; + mes "Attempting to strengthen the ability further. The previous enforcement won't be affected. Do you want to continue?"; + } else if (.@equip_card[2] == 0 && getarg(2) < 3) { + set .@slot,3; + mes "[Artifact Researcher]"; + mes "Attempting second enhancement. The previous enforcement won't be affected."; + next; + mes "[Artifact Researcher]"; + mes "I may have a chance to fail now with this attempt. Do you wish to continue?"; + } else if (.@equip_card[1] == 0 && getarg(2) < 2) { + set .@slot,2; + mes "[Artifact Researcher]"; + mes "Let's start the third enhancement. I can give the best stats at this stage but remember, ^990000there is now a chance for the artifact to be destroyed and previous enhancements will be erased^000000. Continue?"; + } else { + mes "[Artifact Researcher]"; + mes "This artifact has been strengthened to the limit. Further enhancement is impossible at its current state."; + close; + } + next; + if(select("I'll come back later.:Please continue!") == 1) { + mes "[Artifact Researcher]"; + mes "If you change your mind, please come back."; + close; + } + switch(.@enchant_type) { + case 1: //Attack + if (.@slot == 4) set .@i, rand(1,525); + else if (.@slot == 3) set .@i, rand(301,655); + else if (.@slot == 2) set .@i, rand(451,750); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 101) set .@enchant,4700; //Strength1 + else if (.@i < 201) set .@enchant,4811; //Fighting_Spirit1 + else if (.@i < 301) set .@enchant,4819; //Atk1 + else if (.@i < 351) set .@enchant,4701; //Strength2 + else if (.@i < 401) set .@enchant,4810; //Fighting_Spirit2 + else if (.@i < 451) set .@enchant,4766; //Atk2 + else if (.@i < 476) set .@enchant,4702; //Strength3 + else if (.@i < 501) set .@enchant,4809; //Fighting_Spirit3 + else if (.@i < 526) set .@enchant,4767; //Atk3 + else if (.@i < 626) set .@enchant,0; + else if (.@i < 641) set .@enchant,4703; //Strength4 + else if (.@i < 656) set .@enchant,4808; //Fighting_Spirit4 + else if (.@i < 661) set .@enchant,4704; //Strength5 + else if (.@i < 666) set .@enchant,4820; //Fighting_Spirit5 + else if (.@i < 668) set .@enchant,4705; //Strength6 + else if (.@i < 670) set .@enchant,4821; //Fighting_Spirit6 + else set .@enchant,9; + break; + case 2: //Critical + if (.@slot == 4) set .@i, rand(1,470); + else if (.@slot == 3) set .@i, rand(201,610); + else if (.@slot == 2) set .@i, rand(381,750); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 101) set .@enchant,4750; //Luck1 + else if (.@i < 201) set .@enchant,4700; //Strength1 + else if (.@i < 261) set .@enchant,4751; //Luck2 + else if (.@i < 321) set .@enchant,4701; //Strength2 + else if (.@i < 351) set .@enchant,4752; //Luck3 + else if (.@i < 381) set .@enchant,4702; //Strength3 + else if (.@i < 411) set .@enchant,4764; //Critical5 + else if (.@i < 441) set .@enchant,4818; //Sharp1 + else if (.@i < 471) set .@enchant,4752; //Luck3 + else if (.@i < 571) set .@enchant,0; + else if (.@i < 586) set .@enchant,4753; //Luck4 + else if (.@i < 601) set .@enchant,4754; //Luck5 + else if (.@i < 606) set .@enchant,4765; //Critical7 + else if (.@i < 611) set .@enchant,4817; //Sharp2 + else if (.@i < 616) set .@enchant,4703; //Strength4 + else if (.@i < 618) set .@enchant,4816; //Sharp3 + else set .@enchant,9; + break; + case 3: //Evasion + if (.@slot == 4) set .@i, rand(1,525); + else if (.@slot == 3) set .@i, rand(301,670); + else if (.@slot == 2) set .@i, rand(451,800); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 101) set .@enchant,4859; //Evasion1 + else if (.@i < 201) set .@enchant,4750; //Luck1 + else if (.@i < 301) set .@enchant,4730; //Agility1 + else if (.@i < 351) set .@enchant,4860; //Evasion3 + else if (.@i < 401) set .@enchant,4751; //Luck2 + else if (.@i < 451) set .@enchant,4731; //Agility2 + else if (.@i < 476) set .@enchant,4731; //Agility2 + else if (.@i < 501) set .@enchant,4752; //Luck3 + else if (.@i < 526) set .@enchant,4732; //Agility3 + else if (.@i < 626) set .@enchant,0; + else if (.@i < 641) set .@enchant,4762; //Evasion6 + else if (.@i < 656) set .@enchant,4753; //Luck4 + else if (.@i < 671) set .@enchant,4733; //Agility4 + else if (.@i < 676) set .@enchant,4763; //Evasion12 + else if (.@i < 681) set .@enchant,4754; //Luck5 + else if (.@i < 683) set .@enchant,4734; //Agility5 + else set .@enchant,9; + break; + case 4: //Healer + if (.@slot == 4) set .@i, rand(1,375); + else if (.@slot == 3) set .@i, rand(201,535); + else if (.@slot == 2) set .@i, rand(301,650); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 101) set .@enchant,4710; //Inteligence1 + else if (.@i < 201) set .@enchant,4720; //Dexterity1 + else if (.@i < 251) set .@enchant,4711; //Inteligence2 + else if (.@i < 301) set .@enchant,4721; //Dexterity2 + else if (.@i < 326) set .@enchant,4805; //Heal_Amount2 + else if (.@i < 351) set .@enchant,4712; //Inteligence3 + else if (.@i < 376) set .@enchant,4722; //Dexterity3 + else if (.@i < 476) set .@enchant,0; + else if (.@i < 491) set .@enchant,4760; //Matk1 + else if (.@i < 506) set .@enchant,4850; //Heal_Amount3 + else if (.@i < 521) set .@enchant,4713; //Inteligence4 + else if (.@i < 536) set .@enchant,4723; //Dexterity4 + else if (.@i < 541) set .@enchant,4761; //Matk2 + else if (.@i < 546) set .@enchant,4851; //Heal_Amount4 + else if (.@i < 548) set .@enchant,4806; //Matk3 + else if (.@i < 550) set .@enchant,4852; //Heal_Amount5 + else set .@enchant,9; + break; + case 5: //Spell 1 + if (.@slot == 4) set .@i, rand(1,600); + else if (.@slot == 3) set .@i, rand(401,760); + else if (.@slot == 2) set .@i, rand(401,766); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 101) set .@enchant,4710; //Inteligence1 + else if (.@i < 201) set .@enchant,4720; //Dexterity1 + else if (.@i < 301) set .@enchant,4795; //HP100 + else if (.@i < 401) set .@enchant,4815; //Spell1 + else if (.@i < 451) set .@enchant,4711; //Inteligence2 + else if (.@i < 501) set .@enchant,4721; //Dexterity2 + else if (.@i < 551) set .@enchant,4796; //HP200 + else if (.@i < 601) set .@enchant,4814; //Spell2 + else if (.@i < 701) set .@enchant,0; + else if (.@i < 716) set .@enchant,4712; //Inteligence3 + else if (.@i < 731) set .@enchant,4722; //Dexterity3 + else if (.@i < 746) set .@enchant,4797; //HP300 + else if (.@i < 761) set .@enchant,4813; //Spell3 + else if (.@i < 763) set .@enchant,4713; //Inteligence4 + else if (.@i < 765) set .@enchant,4723; //Dexterity4 + else if (.@i < 767) set .@enchant,4812; //Spell4 + else set .@enchant,9; + break; + case 6: //Assist 1 + if (.@slot == 4) set .@i, rand(1,520); + else if (.@slot == 3) set .@i, rand(321,720); + else if (.@slot == 2) set .@i, rand(521,850); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 81) set .@enchant,4792; //Def6 + else if (.@i < 161) set .@enchant,4787; //Mdef4 + else if (.@i < 241) set .@enchant,4801; //SP100 + else if (.@i < 321) set .@enchant,4796; //HP200 + else if (.@i < 371) set .@enchant,4700; //Strength1 + else if (.@i < 421) set .@enchant,4720; //Dexterity1 + else if (.@i < 471) set .@enchant,4730; //Agility1 + else if (.@i < 521) set .@enchant,4740; //Vitality1 + else if (.@i < 621) set .@enchant,0; + else if (.@i < 646) set .@enchant,4793; //Def9 + else if (.@i < 671) set .@enchant,4788; //Mdef6 + else if (.@i < 696) set .@enchant,4802; //SP150 + else if (.@i < 721) set .@enchant,4797; //HP300 + else if (.@i < 731) set .@enchant,4701; //Strength2 + else if (.@i < 741) set .@enchant,4721; //Dexterity2 + else if (.@i < 751) set .@enchant,4731; //Agility2 + else set .@enchant,9; + break; + case 7: //Assist 2 + if (.@slot == 4) set .@i, rand(1,520); + else if (.@slot == 3) set .@i, rand(321,720); + else if (.@slot == 2) set .@i, rand(521,850); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 81) set .@enchant,4792; //Def6 + else if (.@i < 161) set .@enchant,4787; //Mdef4 + else if (.@i < 241) set .@enchant,4801; //SP100 + else if (.@i < 321) set .@enchant,4796; //HP200 + else if (.@i < 371) set .@enchant,4710; //Inteligence1 + else if (.@i < 421) set .@enchant,4720; //Dexterity1 + else if (.@i < 471) set .@enchant,4730; //Agility1 + else if (.@i < 521) set .@enchant,4740; //Vitality1 + else if (.@i < 621) set .@enchant,0; + else if (.@i < 646) set .@enchant,4793; //Def9 + else if (.@i < 671) set .@enchant,4788; //Mdef6 + else if (.@i < 696) set .@enchant,4802; //SP150 + else if (.@i < 721) set .@enchant,4797; //HP300 + else if (.@i < 731) set .@enchant,4711; //Inteligence2 + else if (.@i < 741) set .@enchant,4721; //Dexterity2 + else if (.@i < 751) set .@enchant,4741; //Vitality2 + else set .@enchant,9; + break; + case 8: //Strength + if (.@slot == 4) set .@i, rand(1,525); + else if (.@slot == 3) set .@i, rand(301,685); + else if (.@slot == 2) set .@i, rand(451,800); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 101) set .@enchant,4740; //Vitality1 + else if (.@i < 201) set .@enchant,4797; //HP300 + else if (.@i < 301) set .@enchant,4791; //Def3 + else if (.@i < 351) set .@enchant,4741; //Vitality2 + else if (.@i < 401) set .@enchant,4798; //HP400 + else if (.@i < 451) set .@enchant,4792; //Def6 + else if (.@i < 476) set .@enchant,4742; //Vitality3 + else if (.@i < 501) set .@enchant,4793; //Def9 + else if (.@i < 526) set .@enchant,4799; //HP500 + else if (.@i < 626) set .@enchant,0; + else if (.@i < 641) set .@enchant,4742; //Vitality3 + else if (.@i < 656) set .@enchant,4743; //Vitality4 + else if (.@i < 671) set .@enchant,4794; //Def12 + //else if (.@i < 686) set .@enchant,01; // ?? + else if (.@i < 688) set .@enchant,4744; //Vitality5 + //else if (.@i < 690) set .@enchant,02; // ?? + else set .@enchant,9; + break; + case 9: //Range + if (.@slot == 4) set .@i, rand(1,470); + else if (.@slot == 3) set .@i, rand(201,610); + else if (.@slot == 2) set .@i, rand(321,750); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 101) set .@enchant,4750; //Luck1 + else if (.@i < 201) set .@enchant,4720; //Dexterity1 + else if (.@i < 261) set .@enchant,4751; //Luck2 + else if (.@i < 321) set .@enchant,4721; //Dexterity2 + else if (.@i < 351) set .@enchant,4752; //Luck3 + else if (.@i < 381) set .@enchant,4722; //Dexterity3 + else if (.@i < 411) set .@enchant,4764; //Critical5 + else if (.@i < 441) set .@enchant,4832; //Expert_Archer1 + else if (.@i < 471) set .@enchant,4753; //Luck4 + else if (.@i < 571) set .@enchant,0; + else if (.@i < 586) set .@enchant,4723; //Dexterity4 + else if (.@i < 601) set .@enchant,4833; //Expert_Archer2 + else if (.@i < 606) set .@enchant,4765; //Critical7 + else if (.@i < 611) set .@enchant,4834; //Expert_Archer3 + else if (.@i < 616) set .@enchant,4724; //Dexterity5 + else if (.@i < 618) set .@enchant,4835; //Expert_Archer4 + else set .@enchant,9; + break; + case 10: //Physical + if (.@slot == 4) set .@i, rand(1,600); + else if (.@slot == 3) set .@i, rand(401,800); + else if (.@slot == 2) set .@i, rand(601,930); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 101) set .@enchant,4791; //Def3 + else if (.@i < 201) set .@enchant,4730; //Agility1 + else if (.@i < 301) set .@enchant,4750; //Luck1 + else if (.@i < 401) set .@enchant,4795; //HP100 + else if (.@i < 451) set .@enchant,4792; //Def6 + else if (.@i < 501) set .@enchant,4731; //Agility2 + else if (.@i < 551) set .@enchant,4751; //Luck2 + else if (.@i < 601) set .@enchant,4796; //HP200 + else if (.@i < 701) set .@enchant,0; + else if (.@i < 726) set .@enchant,4793; //Def9 + else if (.@i < 751) set .@enchant,4732; //Agility3 + else if (.@i < 776) set .@enchant,4752; //Luck3 + else if (.@i < 801) set .@enchant,4797; //HP300 + else if (.@i < 816) set .@enchant,4733; //Agility4 + else if (.@i < 831) set .@enchant,4753; //Luck4 + else if (.@i < 833) set .@enchant,4807; //Atk_Speed1 + else set .@enchant,9; + break; + case 11: //Spell 2 + if (.@slot == 4) set .@i, rand(1,600); + else if (.@slot == 3) set .@i, rand(401,760); + else if (.@slot == 2) set .@i, rand(401,766); + else { + mes "[Artifact Researcher]"; + mes "An unknown error has occurred."; + close; + } + if (.@i < 101) set .@enchant,4711; //Inteligence2 + else if (.@i < 201) set .@enchant,4721; //Dexterity2 + else if (.@i < 301) set .@enchant,4796; //HP200 + else if (.@i < 401) set .@enchant,4814; //Spell2 + else if (.@i < 451) set .@enchant,4712; //Inteligence3 + else if (.@i < 501) set .@enchant,4722; //Dexterity3 + else if (.@i < 551) set .@enchant,4760; //Matk1 + else if (.@i < 601) set .@enchant,4813; //Spell3 + else if (.@i < 701) set .@enchant,0; + else if (.@i < 716) set .@enchant,4713; //Inteligence4 + else if (.@i < 731) set .@enchant,4723; //Dexterity4 + else if (.@i < 746) set .@enchant,4761; //Matk2 + else if (.@i < 761) set .@enchant,4812; //Spell4 + else if (.@i < 763) set .@enchant,4714; //Inteligence5 + else if (.@i < 765) set .@enchant,4724; //Dexterity5 + else if (.@i < 767) set .@enchant,4806; //Matk3 + else set .@enchant,9; + break; + default: + mes "[Artifact Researcher]"; + mes "Well I guess I was wrong..."; + close; + } + if (.@equip_card[3] == 0 && getarg(2) < 4) { + set .@equip_card[3],.@enchant; + } else if (.@equip_card[2] == 0 && getarg(2) < 3) { + set .@equip_card[2],.@enchant; + if (.@enchant == 0) { + set .@equip_card[3],0; + } + } else if (.@equip_card[1] == 0 && getarg(2) < 2) { + set .@equip_card[1],.@enchant; + if (.@enchant == 0) { + set .@equip_card[2],0; + set .@equip_card[3],0; + } + } else { + mes "[Artifact Researcher]"; + mes "I think there was an enhancing limit to the artifacts."; + close; + } + if (Zeny < 100000 || countitem(6380) == 0) { + mes "[Artifact Researcher]"; + mes "I'm not going to do the work unless you pay the fee."; + close; + } + delitem 6380,1; //Mora_Coin + set Zeny, Zeny-100000; + delequip .@part; + if (.@enchant == 9) { + specialeffect2 EF_SUI_EXPLOSION; + mes "[Artifact Researcher]"; + mes "This!"; + mes "I... I'm sorry but the equipment has been destroyed."; + close; + } + if (.@enchant == 0) { + specialeffect2 EF_SHIELDCHARGE; + mes "[Artifact Researcher]"; + mes "Since the balance of power does not match, the given existing ability has been destroyed. It is unfortunate but please try again next time."; + } else { + specialeffect2 EF_REPAIRWEAPON; + mes "[Artifact Researcher]"; + // Replacing original dialogue since it doesn't make sense. + //mes "The artifact ^990000"+.@slot+" will have the first enhancement retained."; + mes "I've successfully enhanced the artifact ^990000"+.@equip_name$+"^000000 at socket "+.@slot+"."; + } + +// GetNonSlotItemSock2 .@equip_refine .@equip_id .@equip_card[0] .@equip_card[1] .@equip_card[2] .@equip_card[3] + getitem2 .@equip_id,1,1,.@equip_refine,0,.@equip_card[0],.@equip_card[1],.@equip_card[2],.@equip_card[3]; + + close; + } else if (.@select == 2) { + if (Zeny < 100000 || countitem(6380) == 0) { + mes "[Artifact Researcher]"; + mes "You've got to pay if you want the services."; + close; + } + specialeffect2 EF_REPAIRWEAPON; + mes "[Artifact Researcher]"; + mes "The ability to enhance remains."; + delitem 6380,1; //Mora_Coin + set Zeny, Zeny-100000; + delequip .@part; + +// GetNonSlotItemSock2 .@equip_refine .@equip_id .@equip_card[0] .@equip_card[1] .@equip_card[2] .@equip_card[3] + for(set .@i,0; .@i<4; set .@i,.@i+1) { + if (.@equip_card[.@i] >= 4700) // Armor Enchant System + set .@equip_card[.@i],0; + } + getitem2 .@equip_id,1,1,.@equip_refine,0,.@equip_card[0],.@equip_card[1],.@equip_card[2],.@equip_card[3]; + + close; + } +} + +// Arch Bishop & Warlock Empowering :: relic_change +//============================================================ +mora,124,82,4 script Artifact Collector#blan 522,{ + if (checkweight(1201,1) == 0) { + mes "Reduce the amount of items that you have in your inventory before continuing."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much in your inventory."; + close; + } + disable_items; + emotion e_ho; + mes "Those Mora Artifacts look so perfect!"; + mes "But I know you want them to be even better!"; + next; + mes "[Artifact Collector]"; + mes "Greetings Adventurer. We will be great friends in a moment after I tell you how to Empower your Artifacts!"; + next; + switch(select("Let's do this!:Empower Artifacts?:Nope, not for me!")) { + case 1: + break; + case 2: + emotion e_ok; + mes "[Artifact Collector]"; + mes "You seem like a pretty good judge of character."; + next; + mes "[Artifact Collector]"; + mes "For over 200 years I've been working with Artifacts here in Mora. Toiling to get the perfect +9!"; + next; + select("Gulp... +9?!"); + emotion e_omg,1; + mes "[Artifact Collector]"; + mes "My business is collecting the old relics and refining them to their essence!"; + next; + emotion e_sob; + mes "[Artifact Collector]"; + mes "Finding the perfect Artifact for me to experiment on is my life's work."; + mes "Plus seeing the wonder of our ancestor's legacy is also gratifying."; + next; + select("I can see how that could be fun."); + emotion e_pat; + mes "[Artifact Collector]"; + mes "Thank you human."; + next; + mes "[Artifact Collector]"; + mes "I've been doing this for over 200 years, and honestly the readily available supply is gone, and Artificer and Artifact Crafter won't trade me anymore..."; + next; + emotion e_dots; + mes "[Artifact Collector]"; + mes "But maybe the Humans that are starting to visit can bring in some new stock!"; + next; + select("Humans... Stock?"); + emotion e_what,1; + mes "[Artifact Collector]"; + mes "Yes! If the humans can bring me new artifacts I can work on my ultimate achievement!"; + next; + select("Ultimate Achievement?"); + emotion e_what,1; + emotion e_ok; + mes "[Artifact Collector]"; + mes "Patience, we'll get to that..."; + next; + mes "[Artifact Collector]"; + mes "I am a collector, by trade, but my greatest achievement is empowering some artifacts with greater power!"; + mes "I have only perfected my ability on a few Artifact types so far."; + next; + mes "[Artifact Collector]"; + mes "You might just be the human to help me complete my plan."; + next; + emotion e_otl; + mes "[Artifact Collector]"; + mes "Oh how I love how fate works sometimes..."; + next; + mes "[Artifact Collector]"; + mes "+1, +2, +3, +4, +5, +6 those refinements are not strong enough to work on my craft."; + next; + emotion 57,0; + mes "[Artifact Collector]"; + mes "But +7! +7 is rare and just barely strong enough to work in my crafting attempts."; + next; + select("I'm gonna be abused again..."); + emotion e_hmm,1; + mes "[Artifact Collector]"; + mes "Right you are! I know it is natural for you Humans to help a friend, even without the friend asking..."; + next; + select("I'm not sure if..."); + emotion e_what,1; + mes "[Artifact Collector]"; + mes "Of course I'll accept your help! Find me..."; + next; + mes "- Golden Rod Staff -"; + mes "- Aqua Staff -"; + mes "- Crimson Staff -"; + mes "- Forest Staff -"; + mes "- Staff of Mercy -"; + mes "- Mace of Judgement -"; + next; + select("Anything else?"); + emotion e_what,1; + mes "[Artifact Collector]"; + mes "Well aside from the +7, there are very specific enchantments that need to be on the artifact that help catalyze the process."; + next; + mes "[Artifact Collector]"; + mes "If either the +7 or the specific enchantment is missing I can't do it."; + next; + select("So the Refining will be preserved?"); + emotion e_omg,1; + emotion e_an; + mes "[Artifact Collector]"; + mes "No, but what you'll get back is so much better!"; + next; + mes "[Artifact Collector]"; + mes "By now you are wondering more about the artifacts I'm looking for?"; + next; + emotion e_what; + mes "[Artifact Collector]"; + mes "Go ahead and ask!"; + next; + setarray .@artifacts[0],1657,16013,2007,2008,2009,2010; + setarray .@empowered[0],1660,16018,2011,2012,2013,2014; + while(1) { + set .@i, select("I don't think I'm interested:Staff of Mercy:Mace of Judgement:Golden Rod Staff:Aqua Staff:Crimson Staff:Forest Staff")-2; + if (.@i == -1) { + emotion e_what; + mes "[Artifact Collector]"; + mes "Ok, well maybe someday you will be."; + close; + } + mes "[Artifact Collector]"; + mes getitemname(.@artifacts[.@i])+" must of course be refined to +7 or higher for me to distill it to an enchantment."; + next; + switch(.@i) { + case 0: + setarray .@enchants[0],4761,4723,4714; + set .@str$, "MATK+2%, DEX+4, INT+5"; + break; + case 1: + setarray .@enchants[0],4767,4723,4704; + set .@str$, "ATK+3%, DEX+4, STR+5"; + break; + default: + setarray .@enchants[0],4761,4713; + set .@str$, "MATK+2%, INT+4"; + break; + } + mes "[Artifact Collector]"; + mes "It must also carry any of these enchantments: "+.@str$+" to be craftable by me."; + next; + select(getitemname(.@empowered[.@i])+" attributes?"); + callsub L_ShowInfo, .@empowered[.@i]; + mes "[Artifact Collector]"; + mes "But please if you do get one, please let me work on it, I'm begging you."; + next; + } + case 3: + mes "[Artifact Collector]"; + mes "Have yourself a great day. Bye~"; + close; + } + emotion e_flash; + mes "[Artifact Collector]"; + mes "Let me take a look at what you have brought me."; + next; + if (!getequipisequiped(EQI_HAND_R)) { + emotion e_an; + mes "[Artifact Collector]"; + mes "I don't know what you are trying to do... I can't enhance what you don't have."; + close; + } + set .@equip_id, getequipid(EQI_HAND_R); + setarray .@equip_card[2], getequipcardid(EQI_HAND_R,2),getequipcardid(EQI_HAND_R,3); + switch(.@equip_id) { + case 2007: //Golden_Rod_Staff + case 2008: //Aqua_Staff + case 2009: //Crimson_Staff + case 2010: //Forest_Staff + if (.@equip_card[2] == 4761 || .@equip_card[3] == 4761 || //Matk2 + .@equip_card[2] == 4713 || .@equip_card[3] == 4713) //Inteligence4 + set .@empowered,.@equip_id+4; //Golden_Rod_Staff2,Aqua_Staff2,Crimson_Staff2,Forest_Staff2 + break; + case 1657: //Wand_Of_Affection + if (.@equip_card[2] == 4761 || .@equip_card[3] == 4761 || //Matk2 + .@equip_card[2] == 4714 || .@equip_card[3] == 4714 || //Inteligence5 + .@equip_card[2] == 4723 || .@equip_card[3] == 4723) //Dexterity4 + set .@empowered,1660; //Wand_Of_Affection2 + break; + case 16013: //Mace_Of_Judgement + if (.@equip_card[2] == 4723 || .@equip_card[3] == 4723 || //Dexterity4 + .@equip_card[2] == 4704 || .@equip_card[3] == 4704 || //Strength5 + .@equip_card[2] == 4767 || .@equip_card[3] == 4767) //Atk3 + set .@empowered,16018; //Mace_Of_Judgement2 + break; + default: + emotion e_an; + mes "[Artifact Collector]"; + mes "The weapon you have isn't one of the Artifacts I can work with."; + close; + } + if (getequiprefinerycnt(EQI_HAND_R) < 7) { + emotion e_an; + mes "[Artifact Collector]"; + mes "I must insist that the refine level of the Artifact be at least +7!"; + close; + } + if (!.@empowered) { + emotion e_an; + mes "[Artifact Collector]"; + mes "These attributes just won't do for my research process, try re-randoming them."; + close; + } + emotion e_slur; + mes "[Artifact Collector]"; + mes "I'm tingling with excitement!"; + mes "You've brought me everything I need!!"; + next; + emotion e_ok; + mes "[Artifact Collector]"; + mes "If you are ready I am about to show you what I can do with your +"+getequiprefinerycnt(EQI_HAND_R)+" Artifact!"; + next; + mes "[Artifact Collector]"; + mes "I'm going to take your ^FF0000"+getequipname(EQI_HAND_R)+"^000000 and exchange it, are you ready?"; + next; + switch(select("NOOO!:Yes, I'm ready!:What will it be after?")) { + case 1: + emotion e_an; + mes "[Artifact Collector]"; + mes "You've got to be kidding... you got my hopes up..."; + close; + case 2: + break; + case 3: + callsub L_ShowInfo, .@empowered; + mes "[Artifact Collector]"; + mes "Surely you want to go on?"; + next; + if(select("No, I don't.:Yes, do it!") == 1) { + emotion e_an; + mes "[Artifact Collector]"; + mes "You've got to be kidding... you got my hopes up..."; + close; + } + break; + } + emotion e_heh; + delequip EQI_HAND_R; + getitem .@empowered,1; + mes "[Artifact Collector]"; + mes "It is perfectly done, you will be so happy! Good bye friend~"; + close; + +L_ShowInfo: + mes "[Artifact Collector]"; + mes getitemname(getarg(0)); + switch(getarg(0)) { + case 1660: //Wand_Of_Affection2 + mes "One handed Staff / Attack : 30"; + mes "Weight : 50 / Any Sex"; + mes "Archbishop only"; + mes "Weapon Level : 4 / ^ff0000Required Level: 130^000000"; + mes "MATK + 180, INT + 4."; + mes "Adds 20% Heal Bonus."; + mes "If worn with Robes, Shoes, and Robe of Mercy Increase Heal Bonus by an additional 45% and SP consumption of 'Heal' by 50."; + mes "When receives close physical attack, Lv.1 Silentium will be excuted at a certain rate."; + mes "Recuces 3 seconds of delay after excuting Clearance, Laudaramus, and Laudaagnus skills."; + break; + case 16018: //Mace_Of_Judgement2 + mes "Mace / Attack : 170"; + mes "Weight : 120 / Any Sex"; + mes "Archbishop only"; + mes "Weapon Level : 4 / ^ff0000Required Level: 130^000000"; + mes "MATK + 180, STR + 2, INT + 2."; + mes "Physical and Magical Attacks have a chance to increase damage by 40% to Demon monsters for 7 seconds."; + mes "If worn with Judgement Golves, Shoes and Shawl, increase Damage against Undead by 30%."; + mes "Increase damage of Adoramus by 200%, and increase SP cost of Adoramus by 30."; + break; + case 2011: //Golden_Rod_Staff2 + mes "Staff / Attack: 30"; + mes "Weight : 90 / Any Sex"; + mes "Warlock only"; + mes "Weapon Level : 4 / ^ff0000Required Level : 130^000000"; + mes "INT + 5, MATK + 270."; + mes "Increase Jupitel Thunder damage by 30%."; + mes "If worn with Golden Robe, Golden Shoes, and Golden Orb Increase Wind Magic damage by 60%."; + mes "Lower Earth Magic damage by 60% and resistance to Earth by 50%."; + break; + case 2012: //Aqua_Staff2 + mes "Staff / Attack : 30"; + mes "Weight : 90 / Any Sex"; + mes "Warlock only"; + mes "Weapon Level : 4 / ^ff0000Required Level: 130^000000"; + mes "INT + 5, MATK + 270."; + mes "Increase Cold Bolt and Frost Diver damage by 30%."; + mes "If worn with Aqua Robe, Shoes, and Orb Increase Water Magic damage by 60%."; + mes "Lower Wind Magic damage by 60% and resistance to Wind by 50%."; + break; + case 2013: //Crimson_Staff2 + mes "Staff / Attack : 30"; + mes "Weight : 90 / Any Sex"; + mes "Warlock only"; + mes "Weapon Level : 4 / ^ff0000Required Level: 130^000000"; + mes "INT + 5, MATK + 270."; + mes "Increase Fire Bolt and Fireball damage by 30%."; + mes "If worn with Crimson Robe, Shoes, and Orb Increase Fire Magic damage by 60%."; + mes "Lower Water Magic damage by 60% and resistance to Water by 50%."; + break; + case 2014: //Forest_Staff2 + mes "Staff / Attack : 30"; + mes "Weight : 90 / Any Sex"; + mes "Warlock only"; + mes "Weapon Level : 4 / ^ff0000Required Level: 130^000000"; + mes "INT + 5, MATK + 270."; + mes "Increase Earth Spike and Heaven's Drive damage by 30%."; + mes "If worn with Forest Robe, Shoes, and Orb Increase Earth Magic damage by 60%."; + mes "Lower Fire Magic damage by 60% and resistance to Fire by 50%."; + break; + } + next; + return; +} + +// Other Enchants :: sangjo +//============================================================ +function script F_Mora_Enchant { + specialeffect2 EF_REPAIRWEAPON; + progressbar "ffff00",3; + delitem 6380,5; //Mora_Coin + delitem getarg(0),1; + set .@i, rand(1,4568); + if (.@i <= 11) setarray .@enchants[1],4766,4720,4700; //Atk2 Dexterity1 Strength1 + else if (.@i <= 22) setarray .@enchants[1],4766,4720,4701; //Atk2 Dexterity1 Strength2 + else if (.@i <= 33) setarray .@enchants[1],4766,4720,4730; //Atk2 Dexterity1 Agility1 + else if (.@i <= 44) setarray .@enchants[1],4766,4720,4731; //Atk2 Dexterity1 Agility2 + else if (.@i <= 55) setarray .@enchants[1],4766,4720,4740; //Atk2 Dexterity1 Vitality1 + else if (.@i <= 66) setarray .@enchants[1],4766,4720,4741; //Atk2 Dexterity1 Vitality2 + else if (.@i <= 77) setarray .@enchants[1],4766,4721,4700; //Atk2 Dexterity2 Strength1 + else if (.@i <= 88) setarray .@enchants[1],4766,4721,4701; //Atk2 Dexterity2 Strength2 + else if (.@i <= 99) setarray .@enchants[1],4766,4721,4730; //Atk2 Dexterity2 Agility1 + else if (.@i <= 110) setarray .@enchants[1],4766,4721,4731; //Atk2 Dexterity2 Agility2 + else if (.@i <= 121) setarray .@enchants[1],4766,4721,4740; //Atk2 Dexterity2 Vitality1 + else if (.@i <= 132) setarray .@enchants[1],4766,4721,4741; //Atk2 Dexterity2 Vitality2 + else if (.@i <= 143) setarray .@enchants[1],4766,4710,4700; //Atk2 Inteligence1 Strength1 + else if (.@i <= 154) setarray .@enchants[1],4766,4710,4701; //Atk2 Inteligence1 Strength2 + else if (.@i <= 165) setarray .@enchants[1],4766,4710,4730; //Atk2 Inteligence1 Agility1 + else if (.@i <= 176) setarray .@enchants[1],4766,4710,4731; //Atk2 Inteligence1 Agility2 + else if (.@i <= 187) setarray .@enchants[1],4766,4710,4740; //Atk2 Inteligence1 Vitality1 + else if (.@i <= 198) setarray .@enchants[1],4766,4710,4741; //Atk2 Inteligence1 Vitality2 + else if (.@i <= 209) setarray .@enchants[1],4766,4711,4700; //Atk2 Inteligence2 Strength1 + else if (.@i <= 220) setarray .@enchants[1],4766,4711,4701; //Atk2 Inteligence2 Strength2 + else if (.@i <= 231) setarray .@enchants[1],4766,4711,4730; //Atk2 Inteligence2 Agility1 + else if (.@i <= 242) setarray .@enchants[1],4766,4711,4731; //Atk2 Inteligence2 Agility2 + else if (.@i <= 253) setarray .@enchants[1],4766,4711,4740; //Atk2 Inteligence2 Vitality1 + else if (.@i <= 264) setarray .@enchants[1],4766,4711,4741; //Atk2 Inteligence2 Vitality2 + else if (.@i <= 275) setarray .@enchants[1],4766,4750,4700; //Atk2 Luck1 Strength1 + else if (.@i <= 286) setarray .@enchants[1],4766,4750,4701; //Atk2 Luck1 Strength2 + else if (.@i <= 297) setarray .@enchants[1],4766,4750,4730; //Atk2 Luck1 Agility1 + else if (.@i <= 308) setarray .@enchants[1],4766,4750,4731; //Atk2 Luck1 Agility2 + else if (.@i <= 319) setarray .@enchants[1],4766,4750,4740; //Atk2 Luck1 Vitality1 + else if (.@i <= 330) setarray .@enchants[1],4766,4750,4741; //Atk2 Luck1 Vitality2 + else if (.@i <= 341) setarray .@enchants[1],4766,4751,4700; //Atk2 Luck2 Strength1 + else if (.@i <= 352) setarray .@enchants[1],4766,4751,4701; //Atk2 Luck2 Strength2 + else if (.@i <= 363) setarray .@enchants[1],4766,4751,4730; //Atk2 Luck2 Agility1 + else if (.@i <= 374) setarray .@enchants[1],4766,4751,4731; //Atk2 Luck2 Agility2 + else if (.@i <= 385) setarray .@enchants[1],4766,4751,4740; //Atk2 Luck2 Vitality1 + else if (.@i <= 396) setarray .@enchants[1],4766,4751,4741; //Atk2 Luck2 Vitality2 + else if (.@i <= 407) setarray .@enchants[1],4767,4720,4700; //Atk3 Dexterity1 Strength1 + else if (.@i <= 418) setarray .@enchants[1],4767,4720,4701; //Atk3 Dexterity1 Strength2 + else if (.@i <= 429) setarray .@enchants[1],4767,4720,4730; //Atk3 Dexterity1 Agility1 + else if (.@i <= 440) setarray .@enchants[1],4767,4720,4731; //Atk3 Dexterity1 Agility2 + else if (.@i <= 451) setarray .@enchants[1],4767,4720,4740; //Atk3 Dexterity1 Vitality1 + else if (.@i <= 462) setarray .@enchants[1],4767,4720,4741; //Atk3 Dexterity1 Vitality2 + else if (.@i <= 473) setarray .@enchants[1],4767,4721,4700; //Atk3 Dexterity2 Strength1 + else if (.@i <= 484) setarray .@enchants[1],4767,4721,4701; //Atk3 Dexterity2 Strength2 + else if (.@i <= 495) setarray .@enchants[1],4767,4721,4730; //Atk3 Dexterity2 Agility1 + else if (.@i <= 506) setarray .@enchants[1],4767,4721,4731; //Atk3 Dexterity2 Agility2 + else if (.@i <= 517) setarray .@enchants[1],4767,4721,4740; //Atk3 Dexterity2 Vitality1 + else if (.@i <= 528) setarray .@enchants[1],4767,4721,4741; //Atk3 Dexterity2 Vitality2 + else if (.@i <= 539) setarray .@enchants[1],4767,4710,4700; //Atk3 Inteligence1 Strength1 + else if (.@i <= 550) setarray .@enchants[1],4767,4710,4701; //Atk3 Inteligence1 Strength2 + else if (.@i <= 561) setarray .@enchants[1],4767,4710,4730; //Atk3 Inteligence1 Agility1 + else if (.@i <= 572) setarray .@enchants[1],4767,4710,4731; //Atk3 Inteligence1 Agility2 + else if (.@i <= 583) setarray .@enchants[1],4767,4710,4740; //Atk3 Inteligence1 Vitality1 + else if (.@i <= 594) setarray .@enchants[1],4767,4710,4741; //Atk3 Inteligence1 Vitality2 + else if (.@i <= 605) setarray .@enchants[1],4767,4711,4700; //Atk3 Inteligence2 Strength1 + else if (.@i <= 616) setarray .@enchants[1],4767,4711,4701; //Atk3 Inteligence2 Strength2 + else if (.@i <= 627) setarray .@enchants[1],4767,4711,4730; //Atk3 Inteligence2 Agility1 + else if (.@i <= 638) setarray .@enchants[1],4767,4711,4731; //Atk3 Inteligence2 Agility2 + else if (.@i <= 649) setarray .@enchants[1],4767,4711,4740; //Atk3 Inteligence2 Vitality1 + else if (.@i <= 660) setarray .@enchants[1],4767,4711,4741; //Atk3 Inteligence2 Vitality2 + else if (.@i <= 671) setarray .@enchants[1],4767,4750,4700; //Atk3 Luck1 Strength1 + else if (.@i <= 682) setarray .@enchants[1],4767,4750,4701; //Atk3 Luck1 Strength2 + else if (.@i <= 693) setarray .@enchants[1],4767,4750,4730; //Atk3 Luck1 Agility1 + else if (.@i <= 704) setarray .@enchants[1],4767,4750,4731; //Atk3 Luck1 Agility2 + else if (.@i <= 715) setarray .@enchants[1],4767,4750,4740; //Atk3 Luck1 Vitality1 + else if (.@i <= 726) setarray .@enchants[1],4767,4750,4741; //Atk3 Luck1 Vitality2 + else if (.@i <= 737) setarray .@enchants[1],4767,4751,4700; //Atk3 Luck2 Strength1 + else if (.@i <= 748) setarray .@enchants[1],4767,4751,4701; //Atk3 Luck2 Strength2 + else if (.@i <= 759) setarray .@enchants[1],4767,4751,4730; //Atk3 Luck2 Agility1 + else if (.@i <= 770) setarray .@enchants[1],4767,4751,4731; //Atk3 Luck2 Agility2 + else if (.@i <= 781) setarray .@enchants[1],4767,4751,4740; //Atk3 Luck2 Vitality1 + else if (.@i <= 792) setarray .@enchants[1],4767,4751,4741; //Atk3 Luck2 Vitality2 + else if (.@i <= 803) setarray .@enchants[1],4764,4720,4700; //Critical5 Dexterity1 Strength1 + else if (.@i <= 814) setarray .@enchants[1],4764,4720,4701; //Critical5 Dexterity1 Strength2 + else if (.@i <= 825) setarray .@enchants[1],4764,4720,4730; //Critical5 Dexterity1 Agility1 + else if (.@i <= 836) setarray .@enchants[1],4764,4720,4731; //Critical5 Dexterity1 Agility2 + else if (.@i <= 847) setarray .@enchants[1],4764,4720,4740; //Critical5 Dexterity1 Vitality1 + else if (.@i <= 858) setarray .@enchants[1],4764,4720,4741; //Critical5 Dexterity1 Vitality2 + else if (.@i <= 869) setarray .@enchants[1],4764,4721,4700; //Critical5 Dexterity2 Strength1 + else if (.@i <= 880) setarray .@enchants[1],4764,4721,4701; //Critical5 Dexterity2 Strength2 + else if (.@i <= 891) setarray .@enchants[1],4764,4721,4730; //Critical5 Dexterity2 Agility1 + else if (.@i <= 902) setarray .@enchants[1],4764,4721,4731; //Critical5 Dexterity2 Agility2 + else if (.@i <= 913) setarray .@enchants[1],4764,4721,4740; //Critical5 Dexterity2 Vitality1 + else if (.@i <= 924) setarray .@enchants[1],4764,4721,4741; //Critical5 Dexterity2 Vitality2 + else if (.@i <= 935) setarray .@enchants[1],4764,4710,4700; //Critical5 Inteligence1 Strength1 + else if (.@i <= 946) setarray .@enchants[1],4764,4710,4701; //Critical5 Inteligence1 Strength2 + else if (.@i <= 957) setarray .@enchants[1],4764,4710,4730; //Critical5 Inteligence1 Agility1 + else if (.@i <= 968) setarray .@enchants[1],4764,4710,4731; //Critical5 Inteligence1 Agility2 + else if (.@i <= 979) setarray .@enchants[1],4764,4710,4740; //Critical5 Inteligence1 Vitality1 + else if (.@i <= 990) setarray .@enchants[1],4764,4710,4741; //Critical5 Inteligence1 Vitality2 + else if (.@i <= 1001) setarray .@enchants[1],4764,4711,4700; //Critical5 Inteligence2 Strength1 + else if (.@i <= 1012) setarray .@enchants[1],4764,4711,4701; //Critical5 Inteligence2 Strength2 + else if (.@i <= 1023) setarray .@enchants[1],4764,4711,4730; //Critical5 Inteligence2 Agility1 + else if (.@i <= 1034) setarray .@enchants[1],4764,4711,4731; //Critical5 Inteligence2 Agility2 + else if (.@i <= 1045) setarray .@enchants[1],4764,4711,4740; //Critical5 Inteligence2 Vitality1 + else if (.@i <= 1056) setarray .@enchants[1],4764,4711,4741; //Critical5 Inteligence2 Vitality2 + else if (.@i <= 1067) setarray .@enchants[1],4764,4750,4700; //Critical5 Luck1 Strength1 + else if (.@i <= 1078) setarray .@enchants[1],4764,4750,4701; //Critical5 Luck1 Strength2 + else if (.@i <= 1089) setarray .@enchants[1],4764,4750,4730; //Critical5 Luck1 Agility1 + else if (.@i <= 1100) setarray .@enchants[1],4764,4750,4731; //Critical5 Luck1 Agility2 + else if (.@i <= 1111) setarray .@enchants[1],4764,4750,4740; //Critical5 Luck1 Vitality1 + else if (.@i <= 1122) setarray .@enchants[1],4764,4750,4741; //Critical5 Luck1 Vitality2 + else if (.@i <= 1133) setarray .@enchants[1],4764,4751,4700; //Critical5 Luck2 Strength1 + else if (.@i <= 1144) setarray .@enchants[1],4764,4751,4701; //Critical5 Luck2 Strength2 + else if (.@i <= 1155) setarray .@enchants[1],4764,4751,4730; //Critical5 Luck2 Agility1 + else if (.@i <= 1166) setarray .@enchants[1],4764,4751,4731; //Critical5 Luck2 Agility2 + else if (.@i <= 1177) setarray .@enchants[1],4764,4751,4740; //Critical5 Luck2 Vitality1 + else if (.@i <= 1188) setarray .@enchants[1],4764,4751,4741; //Critical5 Luck2 Vitality2 + else if (.@i <= 1199) setarray .@enchants[1],4765,4720,4700; //Critical7 Dexterity1 Strength1 + else if (.@i <= 1210) setarray .@enchants[1],4765,4720,4701; //Critical7 Dexterity1 Strength2 + else if (.@i <= 1221) setarray .@enchants[1],4765,4720,4730; //Critical7 Dexterity1 Agility1 + else if (.@i <= 1232) setarray .@enchants[1],4765,4720,4731; //Critical7 Dexterity1 Agility2 + else if (.@i <= 1243) setarray .@enchants[1],4765,4720,4740; //Critical7 Dexterity1 Vitality1 + else if (.@i <= 1254) setarray .@enchants[1],4765,4720,4741; //Critical7 Dexterity1 Vitality2 + else if (.@i <= 1265) setarray .@enchants[1],4765,4721,4700; //Critical7 Dexterity2 Strength1 + else if (.@i <= 1276) setarray .@enchants[1],4765,4721,4701; //Critical7 Dexterity2 Strength2 + else if (.@i <= 1287) setarray .@enchants[1],4765,4721,4730; //Critical7 Dexterity2 Agility1 + else if (.@i <= 1298) setarray .@enchants[1],4765,4721,4731; //Critical7 Dexterity2 Agility2 + else if (.@i <= 1309) setarray .@enchants[1],4765,4721,4740; //Critical7 Dexterity2 Vitality1 + else if (.@i <= 1320) setarray .@enchants[1],4765,4721,4741; //Critical7 Dexterity2 Vitality2 + else if (.@i <= 1331) setarray .@enchants[1],4765,4710,4700; //Critical7 Inteligence1 Strength1 + else if (.@i <= 1342) setarray .@enchants[1],4765,4710,4701; //Critical7 Inteligence1 Strength2 + else if (.@i <= 1353) setarray .@enchants[1],4765,4710,4730; //Critical7 Inteligence1 Agility1 + else if (.@i <= 1364) setarray .@enchants[1],4765,4710,4731; //Critical7 Inteligence1 Agility2 + else if (.@i <= 1375) setarray .@enchants[1],4765,4710,4740; //Critical7 Inteligence1 Vitality1 + else if (.@i <= 1386) setarray .@enchants[1],4765,4710,4741; //Critical7 Inteligence1 Vitality2 + else if (.@i <= 1397) setarray .@enchants[1],4765,4711,4700; //Critical7 Inteligence2 Strength1 + else if (.@i <= 1408) setarray .@enchants[1],4765,4711,4701; //Critical7 Inteligence2 Strength2 + else if (.@i <= 1419) setarray .@enchants[1],4765,4711,4730; //Critical7 Inteligence2 Agility1 + else if (.@i <= 1430) setarray .@enchants[1],4765,4711,4731; //Critical7 Inteligence2 Agility2 + else if (.@i <= 1441) setarray .@enchants[1],4765,4711,4740; //Critical7 Inteligence2 Vitality1 + else if (.@i <= 1452) setarray .@enchants[1],4765,4711,4741; //Critical7 Inteligence2 Vitality2 + else if (.@i <= 1463) setarray .@enchants[1],4765,4750,4700; //Critical7 Luck1 Strength1 + else if (.@i <= 1474) setarray .@enchants[1],4765,4750,4701; //Critical7 Luck1 Strength2 + else if (.@i <= 1485) setarray .@enchants[1],4765,4750,4730; //Critical7 Luck1 Agility1 + else if (.@i <= 1496) setarray .@enchants[1],4765,4750,4731; //Critical7 Luck1 Agility2 + else if (.@i <= 1507) setarray .@enchants[1],4765,4750,4740; //Critical7 Luck1 Vitality1 + else if (.@i <= 1518) setarray .@enchants[1],4765,4750,4741; //Critical7 Luck1 Vitality2 + else if (.@i <= 1529) setarray .@enchants[1],4765,4751,4700; //Critical7 Luck2 Strength1 + else if (.@i <= 1540) setarray .@enchants[1],4765,4751,4701; //Critical7 Luck2 Strength2 + else if (.@i <= 1551) setarray .@enchants[1],4765,4751,4730; //Critical7 Luck2 Agility1 + else if (.@i <= 1562) setarray .@enchants[1],4765,4751,4731; //Critical7 Luck2 Agility2 + else if (.@i <= 1573) setarray .@enchants[1],4765,4751,4740; //Critical7 Luck2 Vitality1 + else if (.@i <= 1584) setarray .@enchants[1],4765,4751,4741; //Critical7 Luck2 Vitality2 + else if (.@i <= 1595) setarray .@enchants[1],4762,4720,4700; //Evasion6 Dexterity1 Strength1 + else if (.@i <= 1606) setarray .@enchants[1],4762,4720,4701; //Evasion6 Dexterity1 Strength2 + else if (.@i <= 1617) setarray .@enchants[1],4762,4720,4730; //Evasion6 Dexterity1 Agility1 + else if (.@i <= 1628) setarray .@enchants[1],4762,4720,4731; //Evasion6 Dexterity1 Agility2 + else if (.@i <= 1639) setarray .@enchants[1],4762,4720,4740; //Evasion6 Dexterity1 Vitality1 + else if (.@i <= 1650) setarray .@enchants[1],4762,4720,4741; //Evasion6 Dexterity1 Vitality2 + else if (.@i <= 1661) setarray .@enchants[1],4762,4721,4700; //Evasion6 Dexterity2 Strength1 + else if (.@i <= 1672) setarray .@enchants[1],4762,4721,4701; //Evasion6 Dexterity2 Strength2 + else if (.@i <= 1683) setarray .@enchants[1],4762,4721,4730; //Evasion6 Dexterity2 Agility1 + else if (.@i <= 1694) setarray .@enchants[1],4762,4721,4731; //Evasion6 Dexterity2 Agility2 + else if (.@i <= 1705) setarray .@enchants[1],4762,4721,4740; //Evasion6 Dexterity2 Vitality1 + else if (.@i <= 1716) setarray .@enchants[1],4762,4721,4741; //Evasion6 Dexterity2 Vitality2 + else if (.@i <= 1727) setarray .@enchants[1],4762,4710,4700; //Evasion6 Inteligence1 Strength1 + else if (.@i <= 1738) setarray .@enchants[1],4762,4710,4701; //Evasion6 Inteligence1 Strength2 + else if (.@i <= 1749) setarray .@enchants[1],4762,4710,4730; //Evasion6 Inteligence1 Agility1 + else if (.@i <= 1760) setarray .@enchants[1],4762,4710,4731; //Evasion6 Inteligence1 Agility2 + else if (.@i <= 1771) setarray .@enchants[1],4762,4710,4740; //Evasion6 Inteligence1 Vitality1 + else if (.@i <= 1782) setarray .@enchants[1],4762,4710,4741; //Evasion6 Inteligence1 Vitality2 + else if (.@i <= 1793) setarray .@enchants[1],4762,4711,4700; //Evasion6 Inteligence2 Strength1 + else if (.@i <= 1804) setarray .@enchants[1],4762,4711,4701; //Evasion6 Inteligence2 Strength2 + else if (.@i <= 1815) setarray .@enchants[1],4762,4711,4730; //Evasion6 Inteligence2 Agility1 + else if (.@i <= 1826) setarray .@enchants[1],4762,4711,4731; //Evasion6 Inteligence2 Agility2 + else if (.@i <= 1837) setarray .@enchants[1],4762,4711,4740; //Evasion6 Inteligence2 Vitality1 + else if (.@i <= 1848) setarray .@enchants[1],4762,4711,4741; //Evasion6 Inteligence2 Vitality2 + else if (.@i <= 1859) setarray .@enchants[1],4762,4750,4700; //Evasion6 Luck1 Strength1 + else if (.@i <= 1870) setarray .@enchants[1],4762,4750,4701; //Evasion6 Luck1 Strength2 + else if (.@i <= 1881) setarray .@enchants[1],4762,4750,4730; //Evasion6 Luck1 Agility1 + else if (.@i <= 1892) setarray .@enchants[1],4762,4750,4731; //Evasion6 Luck1 Agility2 + else if (.@i <= 1903) setarray .@enchants[1],4762,4750,4740; //Evasion6 Luck1 Vitality1 + else if (.@i <= 1914) setarray .@enchants[1],4762,4750,4741; //Evasion6 Luck1 Vitality2 + else if (.@i <= 1925) setarray .@enchants[1],4762,4751,4700; //Evasion6 Luck2 Strength1 + else if (.@i <= 1936) setarray .@enchants[1],4762,4751,4701; //Evasion6 Luck2 Strength2 + else if (.@i <= 1947) setarray .@enchants[1],4762,4751,4730; //Evasion6 Luck2 Agility1 + else if (.@i <= 1958) setarray .@enchants[1],4762,4751,4731; //Evasion6 Luck2 Agility2 + else if (.@i <= 1969) setarray .@enchants[1],4762,4751,4740; //Evasion6 Luck2 Vitality1 + else if (.@i <= 1980) setarray .@enchants[1],4762,4751,4741; //Evasion6 Luck2 Vitality2 + else if (.@i <= 1991) setarray .@enchants[1],4763,4720,4700; //Evasion12 Dexterity1 Strength1 + else if (.@i <= 2002) setarray .@enchants[1],4763,4720,4701; //Evasion12 Dexterity1 Strength2 + else if (.@i <= 2013) setarray .@enchants[1],4763,4720,4730; //Evasion12 Dexterity1 Agility1 + else if (.@i <= 2024) setarray .@enchants[1],4763,4720,4731; //Evasion12 Dexterity1 Agility2 + else if (.@i <= 2035) setarray .@enchants[1],4763,4720,4740; //Evasion12 Dexterity1 Vitality1 + else if (.@i <= 2046) setarray .@enchants[1],4763,4720,4741; //Evasion12 Dexterity1 Vitality2 + else if (.@i <= 2057) setarray .@enchants[1],4763,4721,4700; //Evasion12 Dexterity2 Strength1 + else if (.@i <= 2068) setarray .@enchants[1],4763,4721,4701; //Evasion12 Dexterity2 Strength2 + else if (.@i <= 2079) setarray .@enchants[1],4763,4721,4730; //Evasion12 Dexterity2 Agility1 + else if (.@i <= 2090) setarray .@enchants[1],4763,4721,4731; //Evasion12 Dexterity2 Agility2 + else if (.@i <= 2101) setarray .@enchants[1],4763,4721,4740; //Evasion12 Dexterity2 Vitality1 + else if (.@i <= 2112) setarray .@enchants[1],4763,4721,4741; //Evasion12 Dexterity2 Vitality2 + else if (.@i <= 2123) setarray .@enchants[1],4763,4710,4700; //Evasion12 Inteligence1 Strength1 + else if (.@i <= 2134) setarray .@enchants[1],4763,4710,4701; //Evasion12 Inteligence1 Strength2 + else if (.@i <= 2145) setarray .@enchants[1],4763,4710,4730; //Evasion12 Inteligence1 Agility1 + else if (.@i <= 2156) setarray .@enchants[1],4763,4710,4731; //Evasion12 Inteligence1 Agility2 + else if (.@i <= 2167) setarray .@enchants[1],4763,4710,4740; //Evasion12 Inteligence1 Vitality1 + else if (.@i <= 2178) setarray .@enchants[1],4763,4710,4741; //Evasion12 Inteligence1 Vitality2 + else if (.@i <= 2189) setarray .@enchants[1],4763,4711,4700; //Evasion12 Inteligence2 Strength1 + else if (.@i <= 2200) setarray .@enchants[1],4763,4711,4701; //Evasion12 Inteligence2 Strength2 + else if (.@i <= 2211) setarray .@enchants[1],4763,4711,4730; //Evasion12 Inteligence2 Agility1 + else if (.@i <= 2222) setarray .@enchants[1],4763,4711,4731; //Evasion12 Inteligence2 Agility2 + else if (.@i <= 2233) setarray .@enchants[1],4763,4711,4740; //Evasion12 Inteligence2 Vitality1 + else if (.@i <= 2244) setarray .@enchants[1],4763,4711,4741; //Evasion12 Inteligence2 Vitality2 + else if (.@i <= 2255) setarray .@enchants[1],4763,4750,4700; //Evasion12 Luck1 Strength1 + else if (.@i <= 2266) setarray .@enchants[1],4763,4750,4701; //Evasion12 Luck1 Strength2 + else if (.@i <= 2277) setarray .@enchants[1],4763,4750,4730; //Evasion12 Luck1 Agility1 + else if (.@i <= 2288) setarray .@enchants[1],4763,4750,4731; //Evasion12 Luck1 Agility2 + else if (.@i <= 2299) setarray .@enchants[1],4763,4750,4740; //Evasion12 Luck1 Vitality1 + else if (.@i <= 2310) setarray .@enchants[1],4763,4750,4741; //Evasion12 Luck1 Vitality2 + else if (.@i <= 2321) setarray .@enchants[1],4763,4751,4700; //Evasion12 Luck2 Strength1 + else if (.@i <= 2332) setarray .@enchants[1],4763,4751,4701; //Evasion12 Luck2 Strength2 + else if (.@i <= 2343) setarray .@enchants[1],4763,4751,4730; //Evasion12 Luck2 Agility1 + else if (.@i <= 2354) setarray .@enchants[1],4763,4751,4731; //Evasion12 Luck2 Agility2 + else if (.@i <= 2365) setarray .@enchants[1],4763,4751,4740; //Evasion12 Luck2 Vitality1 + else if (.@i <= 2376) setarray .@enchants[1],4763,4751,4741; //Evasion12 Luck2 Vitality2 + else if (.@i <= 2387) setarray .@enchants[1],4760,4720,4700; //Matk1 Dexterity1 Strength1 + else if (.@i <= 2398) setarray .@enchants[1],4760,4720,4701; //Matk1 Dexterity1 Strength2 + else if (.@i <= 2409) setarray .@enchants[1],4760,4720,4730; //Matk1 Dexterity1 Agility1 + else if (.@i <= 2420) setarray .@enchants[1],4760,4720,4731; //Matk1 Dexterity1 Agility2 + else if (.@i <= 2431) setarray .@enchants[1],4760,4720,4740; //Matk1 Dexterity1 Vitality1 + else if (.@i <= 2442) setarray .@enchants[1],4760,4720,4741; //Matk1 Dexterity1 Vitality2 + else if (.@i <= 2453) setarray .@enchants[1],4760,4721,4700; //Matk1 Dexterity2 Strength1 + else if (.@i <= 2464) setarray .@enchants[1],4760,4721,4701; //Matk1 Dexterity2 Strength2 + else if (.@i <= 2475) setarray .@enchants[1],4760,4721,4730; //Matk1 Dexterity2 Agility1 + else if (.@i <= 2486) setarray .@enchants[1],4760,4721,4731; //Matk1 Dexterity2 Agility2 + else if (.@i <= 2497) setarray .@enchants[1],4760,4721,4740; //Matk1 Dexterity2 Vitality1 + else if (.@i <= 2508) setarray .@enchants[1],4760,4721,4741; //Matk1 Dexterity2 Vitality2 + else if (.@i <= 2519) setarray .@enchants[1],4760,4710,4700; //Matk1 Inteligence1 Strength1 + else if (.@i <= 2530) setarray .@enchants[1],4760,4710,4701; //Matk1 Inteligence1 Strength2 + else if (.@i <= 2541) setarray .@enchants[1],4760,4710,4730; //Matk1 Inteligence1 Agility1 + else if (.@i <= 2552) setarray .@enchants[1],4760,4710,4731; //Matk1 Inteligence1 Agility2 + else if (.@i <= 2563) setarray .@enchants[1],4760,4710,4740; //Matk1 Inteligence1 Vitality1 + else if (.@i <= 2574) setarray .@enchants[1],4760,4710,4741; //Matk1 Inteligence1 Vitality2 + else if (.@i <= 2585) setarray .@enchants[1],4760,4711,4700; //Matk1 Inteligence2 Strength1 + else if (.@i <= 2596) setarray .@enchants[1],4760,4711,4701; //Matk1 Inteligence2 Strength2 + else if (.@i <= 2607) setarray .@enchants[1],4760,4711,4730; //Matk1 Inteligence2 Agility1 + else if (.@i <= 2618) setarray .@enchants[1],4760,4711,4731; //Matk1 Inteligence2 Agility2 + else if (.@i <= 2629) setarray .@enchants[1],4760,4711,4740; //Matk1 Inteligence2 Vitality1 + else if (.@i <= 2640) setarray .@enchants[1],4760,4711,4741; //Matk1 Inteligence2 Vitality2 + else if (.@i <= 2651) setarray .@enchants[1],4760,4750,4700; //Matk1 Luck1 Strength1 + else if (.@i <= 2662) setarray .@enchants[1],4760,4750,4701; //Matk1 Luck1 Strength2 + else if (.@i <= 2673) setarray .@enchants[1],4760,4750,4730; //Matk1 Luck1 Agility1 + else if (.@i <= 2684) setarray .@enchants[1],4760,4750,4731; //Matk1 Luck1 Agility2 + else if (.@i <= 2695) setarray .@enchants[1],4760,4750,4740; //Matk1 Luck1 Vitality1 + else if (.@i <= 2706) setarray .@enchants[1],4760,4750,4741; //Matk1 Luck1 Vitality2 + else if (.@i <= 2717) setarray .@enchants[1],4760,4751,4700; //Matk1 Luck2 Strength1 + else if (.@i <= 2728) setarray .@enchants[1],4760,4751,4701; //Matk1 Luck2 Strength2 + else if (.@i <= 2739) setarray .@enchants[1],4760,4751,4730; //Matk1 Luck2 Agility1 + else if (.@i <= 2750) setarray .@enchants[1],4760,4751,4731; //Matk1 Luck2 Agility2 + else if (.@i <= 2761) setarray .@enchants[1],4760,4751,4740; //Matk1 Luck2 Vitality1 + else if (.@i <= 2772) setarray .@enchants[1],4760,4751,4741; //Matk1 Luck2 Vitality2 + else if (.@i <= 2783) setarray .@enchants[1],4761,4720,4700; //Matk2 Dexterity1 Strength1 + else if (.@i <= 2794) setarray .@enchants[1],4761,4720,4701; //Matk2 Dexterity1 Strength2 + else if (.@i <= 2805) setarray .@enchants[1],4761,4720,4730; //Matk2 Dexterity1 Agility1 + else if (.@i <= 2816) setarray .@enchants[1],4761,4720,4731; //Matk2 Dexterity1 Agility2 + else if (.@i <= 2827) setarray .@enchants[1],4761,4720,4740; //Matk2 Dexterity1 Vitality1 + else if (.@i <= 2838) setarray .@enchants[1],4761,4720,4741; //Matk2 Dexterity1 Vitality2 + else if (.@i <= 2849) setarray .@enchants[1],4761,4721,4700; //Matk2 Dexterity2 Strength1 + else if (.@i <= 2860) setarray .@enchants[1],4761,4721,4701; //Matk2 Dexterity2 Strength2 + else if (.@i <= 2871) setarray .@enchants[1],4761,4721,4730; //Matk2 Dexterity2 Agility1 + else if (.@i <= 2882) setarray .@enchants[1],4761,4721,4731; //Matk2 Dexterity2 Agility2 + else if (.@i <= 2893) setarray .@enchants[1],4761,4721,4740; //Matk2 Dexterity2 Vitality1 + else if (.@i <= 2904) setarray .@enchants[1],4761,4721,4741; //Matk2 Dexterity2 Vitality2 + else if (.@i <= 2915) setarray .@enchants[1],4761,4710,4700; //Matk2 Inteligence1 Strength1 + else if (.@i <= 2926) setarray .@enchants[1],4761,4710,4701; //Matk2 Inteligence1 Strength2 + else if (.@i <= 2937) setarray .@enchants[1],4761,4710,4730; //Matk2 Inteligence1 Agility1 + else if (.@i <= 2948) setarray .@enchants[1],4761,4710,4731; //Matk2 Inteligence1 Agility2 + else if (.@i <= 2959) setarray .@enchants[1],4761,4710,4740; //Matk2 Inteligence1 Vitality1 + else if (.@i <= 2970) setarray .@enchants[1],4761,4710,4741; //Matk2 Inteligence1 Vitality2 + else if (.@i <= 2981) setarray .@enchants[1],4761,4711,4700; //Matk2 Inteligence2 Strength1 + else if (.@i <= 2992) setarray .@enchants[1],4761,4711,4701; //Matk2 Inteligence2 Strength2 + else if (.@i <= 3003) setarray .@enchants[1],4761,4711,4730; //Matk2 Inteligence2 Agility1 + else if (.@i <= 3014) setarray .@enchants[1],4761,4711,4731; //Matk2 Inteligence2 Agility2 + else if (.@i <= 3025) setarray .@enchants[1],4761,4711,4740; //Matk2 Inteligence2 Vitality1 + else if (.@i <= 3036) setarray .@enchants[1],4761,4711,4741; //Matk2 Inteligence2 Vitality2 + else if (.@i <= 3047) setarray .@enchants[1],4761,4750,4700; //Matk2 Luck1 Strength1 + else if (.@i <= 3058) setarray .@enchants[1],4761,4750,4701; //Matk2 Luck1 Strength2 + else if (.@i <= 3069) setarray .@enchants[1],4761,4750,4730; //Matk2 Luck1 Agility1 + else if (.@i <= 3080) setarray .@enchants[1],4761,4750,4731; //Matk2 Luck1 Agility2 + else if (.@i <= 3091) setarray .@enchants[1],4761,4750,4740; //Matk2 Luck1 Vitality1 + else if (.@i <= 3102) setarray .@enchants[1],4761,4750,4741; //Matk2 Luck1 Vitality2 + else if (.@i <= 3113) setarray .@enchants[1],4761,4751,4700; //Matk2 Luck2 Strength1 + else if (.@i <= 3124) setarray .@enchants[1],4761,4751,4701; //Matk2 Luck2 Strength2 + else if (.@i <= 3135) setarray .@enchants[1],4761,4751,4730; //Matk2 Luck2 Agility1 + else if (.@i <= 3146) setarray .@enchants[1],4761,4751,4731; //Matk2 Luck2 Agility2 + else if (.@i <= 3157) setarray .@enchants[1],4761,4751,4740; //Matk2 Luck2 Vitality1 + else if (.@i <= 3168) setarray .@enchants[1],4761,4751,4741; //Matk2 Luck2 Vitality2 + else if (.@i <= 3179) setarray .@enchants[1],4761,4720,4700; //Matk2 Dexterity1 Strength1 + else if (.@i <= 3181) setarray .@enchants[1],4761,4712,4712; //Matk2 Inteligence3 Inteligence3 + else if (.@i <= 3183) setarray .@enchants[1],4765,4732,4732; //Critical7 Agility3 Agility3 + else if (.@i <= 3185) setarray .@enchants[1],4763,4752,4753; //Evasion12 Luck3 Luck4 + else if (.@i <= 3187) setarray .@enchants[1],4763,4742,4742; //Evasion12 Vitality3 Vitality3 + else if (.@i <= 3189) setarray .@enchants[1],4763,4722,4722; //Evasion12 Dexterity3 Dexterity3 + else if (.@i <= 3191) setarray .@enchants[1],4742,4742,4742; //Vitality3 Vitality3 Vitality3 + else if (.@i <= 3193) setarray .@enchants[1],4761,4722,4722; //Matk2 Dexterity3 Dexterity3 + else if (.@i <= 3195) setarray .@enchants[1],4767,4702,4702; //Atk3 Strength3 Strength3 + else if (.@i <= 3197) setarray .@enchants[1],4763,4732,4732; //Evasion12 Agility3 Agility3 + else if (.@i <= 4568) return 0; + + getitem2 getarg(0),1,1,0,0,0,.@enchants[1],.@enchants[2],.@enchants[3]; + return 1; +} +mora,105,176,4 script Master Tailor#pa0829 509,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (countitem(6380) < 5 || countitem(15024) < 1) { + mes "[Master Tailor]"; + mes "With my touch, I can turn a typical army padding into a piece of art. I'm Kay the Master Tailor, creating art with army paddings."; + next; + mes "[Master Tailor]"; + mes "Well, what's in a name? I can turn your army padding into a piece of art if you bring ^ff00005 Mora Coins and an Army Padding^000000."; + if (countitem(6380)) { + next; + mes "[Master Tailor]"; + mes "I happen to have a few army paddings in stock. Would you like to buy one? The price is 1 Mora Coin. So cheap."; + next; + switch(select("Maybe next time.:I'll buy one now.")) { + case 1: + mes "[Master Tailor]"; + mes "Okay, I understand."; + mes "Come back for one if you change your mind."; + close; + case 2: + delitem 6380,1; //Mora_Coin + getitem 15024,1; //Army_Padding + mes "[Master Tailor]"; + mes "Here it is."; + mes "It's very nice and fluffy. Please come back."; + close; + } + } + close; + } + mes "[Master Tailor]"; + mes "Have you come to add art to one of your army paddings?"; + next; + switch(select("Please tell me more.:Yes, I have.")) { + case 1: + mes "[Master Tailor]"; + mes "A typical army padding isn't warm enough. It feels rough on your skin and doesn't look good. And artistic value? It has next to none."; + next; + mes "[Master Tailor]"; + mes "However, I'll embroider it with velvet threads, and add three options to it."; + next; + mes "[Master Tailor]"; + mes "Bring me ^8888005 Mora Coins^000000 and an Army Padding, and we can add some art together!"; + close; + case 2: + mes "[Master Tailor]"; + mes "I'm telling you just in case - I'll do whatever I need to do with your army padding, whether it's brand-new or has been mended before."; + next; + mes "[Master Tailor]"; + mes "So if you have with you an army padding mended to your liking, put it in a safe place and come back."; + next; + mes "[Master Tailor]"; + mes "And another thing - once I fail to add art to it, it becomes unusable... you'll need to buy a new one in that case."; + next; + switch(select("Come on, what's the rush?:Okay! Let's do it!!")) { + case 1: + mes "[Master Tailor]"; + mes "What's wrong with you?"; + mes "The villagers keep me busy enough."; + close; + case 2: + if (countitem(6380) < 5 || countitem(15024) == 0) { + mes "[Master Tailor]"; + mes "It looks like you don't have everything you need."; + next; + mes "[Master Tailor]"; + mes "You have to have 5 Mora Coins and an Army Padding with you before I can do my work."; + close; + } + if (callfunc("F_Mora_Enchant",15024) == 0) { + mes "[Master Tailor]"; + mes "Oh......"; + mes "I can't believe I messed up."; + next; + mes "[Master Tailor]"; + mes "I want to be alone. Go away!"; + close; + } + mes "[Master Tailor]"; + mes "My art looks great."; + close; + } + } +} + +mora,123,177,6 script Pendant Crafter#pa0829 509,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (countitem(6380) < 5 || countitem(2858) == 0) { + mes "[Pendant Crafter]"; + mes "My job is to polish the stone in a Guardian's Pendant, and then carve a symbol with special power on it."; + next; + mes "[Pendant Crafter]"; + mes "The process gives the Guardian's Pendant more power than an ordinary accessory."; + next; + mes "[Pendant Crafter]"; + mes "If you're interested, I can work on your pendant for ^ff00005 Mora Coins^000000. Of course you need to have a Guardian's Pendant so I can work on with you."; + close; + } + mes "[Pendant Crafter]"; + mes "Have you come to have your Guardian's Pendant upgraded?"; + next; + switch(select("Please tell me more.:Yes, I have.")) { + case 1: + mes "[Pendant Crafter]"; + mes "My job is to polish the stone in a Guardian's Pendant, and then carve a symbol with special power on it."; + next; + mes "[Pendant Crafter]"; + mes "The process gives the Guardian's Pendant more power than an ordinary accessory."; + next; + mes "[Pendant Crafter]"; + mes "If you're interested, I can work on your pendant for ^ff00005 Mora Coins^000000. Of course you need to have a Guardian's Pendant so I can work on with you."; + close; + case 2: + mes "[Pendant Crafter]"; + mes "I'm telling you just in case - "; + mes "If I work on a Guardian's Pendant that's been upgraded before, it loses its original power."; + next; + mes "[Pendant Crafter]"; + mes "And worse, it can lose its power and become an ordinary pendant. Of course, stone is not as susceptible to damage as cloth, so you won't lose the pendant itself."; + next; + switch(select("Come on, what's the rush?:Okay! Let's do it!!")) { + case 1: + mes "[Pendant Crafter]"; + mes "Come back when you're not in a hurry. I always have a lot of time on my hands."; + close; + case 2: + if (countitem(6380) < 5 || countitem(2858) == 0) { + mes "[Pendant Crafter]"; + mes "It looks like you don't have everything you need."; + next; + mes "[Pendant Crafter]"; + mes "You must have 5 Mora Coins and a Guardian's Pendant with you before I can do my work."; + close; + } + if (callfunc("F_Mora_Enchant",2858) == 0) { + getitem 2858,1; //Pendant_Of_Guardian + mes "[Pendant Crafter]"; + mes "What~!!"; + mes "What on earth is wrong with it!!"; + close; + } + mes "[Pendant Crafter]"; + mes "Looks like I did it!"; + close; + } + } +} + +mora,134,166,4 script Bulberry Westhood#pa0829 509,{ + if (checkweight(1201,1) == 0) { + mes "You have too many kinds of things with you to do that. Throw out some of them and try again."; + close; + } + if (MaxWeight - Weight < 1000) { + mes "You are carrying too much weight to do that. Reduce the weight and try again."; + close; + } + if (countitem(6380) < 5 || countitem(2568) == 0) { + mes "[Bulberry Westhood]"; + mes "I'm Bulberry Westhood, keeping the tradition of quality hoods alive."; + next; + mes "[Bulberry Westhood]"; + mes "I only handle quality items - not random scarfs from a marketplace."; + next; + mes "[Bulberry Westhood]"; + mes "If you have anything that you think is of high enough quality, come find me with ^ff00005 Mora Coins^000000."; + next; + mes "[Bulberry Westhood]"; + mes "I can improve its high quality with my own hands."; + close; + } + mes "[Bulberry Westhood]"; + mes "So you have a Loki's Scarf 1042 Special Edition. You really have an eye for quality. Can I start working on it right away?"; + next; + switch(select("I don't get it.:Yes, please.")) { + case 1: + mes "[Bulberry Westhood]"; + mes "Like I said, I only handle quality items - not random scarfs from a marketplace."; + next; + mes "[Bulberry Westhood]"; + mes "This Loki's Scarf you have is awesome. It's a limited edition product with Loki's crest on it!"; + next; + mes "[Bulberry Westhood]"; + mes "My specialty is bringing out the hidden power at the small cost of... "; + mes "5 Mora Coins."; + next; + mes "[Bulberry Westhood]"; + mes "Come back if you change your mind."; + close; + case 2: + mes "[Bulberry Westhood]"; + mes "I'm telling you just in case - "; + mes "If I work on a Loki's Scarf that's been upgraded before, it loses its original power."; + next; + mes "[Bulberry Westhood]"; + mes "And worse, it can lose all its power becoming an ordinary scarf."; + next; + mes "[Bulberry Westhood]"; + mes "Of course, the Loki's Scarf is a quality item, so you won't lose the scarf itself in the process."; + next; + switch(select("Maybe later, sir...:I'd like to own a quality item!")) { + case 1: + mes "[Bulberry Westhood]"; + mes "Ha...!"; + mes "You say 'later' when you can have the best quality item right away? Well, have it your own way."; + close; + case 2: + if (countitem(6380) < 5 || countitem(2568) == 0) { + mes "[Bulberry Westhood]"; + mes "It looks like you don't everything you need."; + next; + mes "[Bulberry Westhood]"; + mes "You must have 5 Mora Coins and a Loki's Scarf with you before you can have the best quality item."; + close; + } + if (callfunc("F_Mora_Enchant",2568) == 0) { + getitem 2568,1; //Muffler_Of_Roki + mes "[Bulberry Westhood]"; + mes "Aaarrgghh, this is impossible!"; + mes "My! My Loki's Scarf!...."; + next; + mes "[Bulberry Westhood]"; + mes "Oh, I apologize for my disgraceful behavior. I was too upset."; + next; + mes "[Bulberry Westhood]"; + mes "Fortunately, it's still in its original state before I started working on it. It's not torn or stretched. It's a quality item after all. Oh ho ho~"; + close; + } + mes "[Bulberry Westhood]"; + mes "Wow~ mission complete!"; + close; + } + } +} -- cgit v1.2.3-70-g09d2 From 37e93bcf42def890ca79fa2645d518b8e94c2476 Mon Sep 17 00:00:00 2001 From: Streusel Date: Sun, 2 Jun 2013 12:46:44 -0600 Subject: Update scripts.conf --- npc/re/scripts.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'npc') diff --git a/npc/re/scripts.conf b/npc/re/scripts.conf index e4dcd94ac..c1e40dae6 100644 --- a/npc/re/scripts.conf +++ b/npc/re/scripts.conf @@ -57,6 +57,7 @@ npc: npc/re/merchants/refine.txt npc: npc/re/merchants/renters.txt npc: npc/re/merchants/shops.txt npc: npc/re/merchants/enchan_mal.txt +npc: npc/re/merchants/enchan_mora.txt npc: npc/re/merchants/coin_exchange.txt // --------------------------- Others --------------------------- @@ -89,4 +90,4 @@ npc: npc/re/quests/quests_malangdo.txt npc: npc/re/quests/quests_veins.txt npc: npc/re/quests/quests_mora.txt npc: npc/re/quests/monstertamers.txt -npc: npc/re/quests/quests_13_1.txt \ No newline at end of file +npc: npc/re/quests/quests_13_1.txt -- cgit v1.2.3-70-g09d2 From 8878cebb57c75d1a158743e8974067b68e7c2097 Mon Sep 17 00:00:00 2001 From: Euphy Date: Mon, 3 Jun 2013 02:39:34 -0400 Subject: Implemented Hazy Forest. --- npc/re/instances/HazyForest.txt | 1193 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 1193 insertions(+) create mode 100644 npc/re/instances/HazyForest.txt (limited to 'npc') diff --git a/npc/re/instances/HazyForest.txt b/npc/re/instances/HazyForest.txt new file mode 100644 index 000000000..cb65f11d7 --- /dev/null +++ b/npc/re/instances/HazyForest.txt @@ -0,0 +1,1193 @@ +//===== rAthena Script ======================================= +//= Hazy Forest +//===== By: ================================================== +//= Euphy +//===== Current Version: ===================================== +//= 1.0 +//===== Compatible With: ===================================== +//= rAthena SVN +//===== Description: ========================================= +//= [Official Conversion] +//= Cross through the Hazy Forest to reach the Bifrost. +//= Contains the Wandering Guardian quest. +//===== Additional Comments: ================================= +//= 1.0 First version. [Euphy] +//============================================================ + +// Instance Creation +//============================================================ +bif_fild01,158,340,5 script Laphine Soldier#mist 447,{ + + set .@party_id,getcharid(1); + set .@md_name$,"Mistwood Maze"; + + mes "[Laphine Soldier]"; + mes "Are you going into the forest?"; + next; + if (!.@party_id) { + mes "[Laphine Soldier]"; + mes "Well, well, well, aren't you being too rash?"; + mes "Why don't you at least organize a party?"; + close; + } + set .@playtime, checkquest(7211,PLAYTIME); + if (getcharid(0) == getpartyleader(.@party_id,2)) { + if (.@playtime == 0 || .@playtime == 1) { + mes "[Laphine Soldier]"; + mes "...Are you sure you're not doing too much?"; + mes "I think you'd better get some rest."; + mes "You'll only wear yourself out by trying to do too much"; + next; + mes "[Laphine Soldier]"; + mes "I don't think the authority will give you permission, either."; + mes "...Even a Sapha would be stopped from entering the forest."; + next; + select("You speak our language quite well, don't you?"); + mes "[Laphine Soldier]"; + mes "...Do I?"; + mes "Actually I'm not speaking your language."; + mes "I'm speaking Laphine language."; + next; + mes "[Laphine Soldier]"; + mes "But it's one of the mysteries of Bifrost."; + mes "That we can understand each other even if we speak different languages."; + next; + mes "[Laphine Soldier]"; + mes "To be able to talk with everybody..."; + mes "Perhaps that's the power of Bifrost."; + close; + } else if (.@playtime == 2) { + mes "[Laphine Soldier]"; + mes "Great, great."; + mes "Now the forest won't reject you."; + mes "What are you going to do now?"; + erasequest 7211; + } else { + mes "[Laphine Soldier]"; + mes "You human adventurers are incredible."; + mes "You're always going into the forest, where no one else dares to go."; + next; + mes "[Laphine Soldier]"; + mes "Phew. But I have to report to the authority"; + mes "everyone who goes into the forest, just in case."; + next; + mes "[Laphine Soldier]"; + mes "You'll get permission"; + mes "after you register."; + mes "Are you going to venture into the Hazy Forest?"; + } + next; + switch(select("Venture into the Hazy Forest.:Give up.")) { + case 1: + set .@instance, instance_create(.@md_name$,.@party_id); + if (.@instance >= 0) { + if (instance_attachmap("1@mist",.@instance) != "") { + + instance_attach(.@instance); + instance_set_timeout 7200,300,.@instance; + instance_init(.@instance); + + donpcevent instance_npcname("#Whisper_mist", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Tom's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Tomba's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Remi's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Tired Rem's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Ron's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Rover's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Mona's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Namon's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Sad Neoron's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Spyder's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Tito's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Pumba's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Tete's Garden Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("The Gardeners' Tree", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("#Dragon Herder", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Mysterious Young Man#mis", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Loki#mist", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("Collapsed Girl#mist", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("#Mist Mobs Respawn1", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("#Mist Mobs Respawn2", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("#Mist Mobs Respawn3", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("#Mist Mobs Respawn4", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("#Mist Mobs Respawn5", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("#Fragments of Memory", instance_id())+"::OnInstanceInit"; + donpcevent instance_npcname("#mist_warp_init", instance_id())+"::OnInstanceInit"; + + mes "[Laphine Soldier]"; + mes "Party Name "+getpartyname(.@party_id)+"..."; + mes "Party Leader "+strcharinfo(0)+"..."; + mes "I've got it. I've written them down on the report here."; + next; + mes "[Laphine Soldier]"; + mes "You'll get permission soon."; + mes "Now go to the log tunnel, the only way to get into the Hazy Forest."; + mes "You understand?"; + next; + mes "[Laphine Soldier]"; + mes "We can't go against the forest,"; + mes "but maybe you humans can."; + mes "Good luck!"; + close; + } else + instance_destroy(.@instance); + } + mes "[Laphine Soldier]"; + mes "Party Name "+getpartyname(.@party_id)+"..."; + mes "Party Leader "+strcharinfo(0)+"..."; + mes "Hmm..."; + next; + mes "[Laphine Soldier]"; + if (.@playtime == -1) + mes "It's dangerous in the forest."; + else + mes "The atmosphere is somewhat tense in the forest."; + mes "...Why don't you just go back today?"; + close; + case 2: + mes "[Laphine Soldier]"; + mes "Well, you've made the right decision."; + if (.@playtime == -1) + mes "That's what's good for you."; + close; + } + } else { + mes "[Laphine Soldier]"; + mes "Where's your party leader?"; + mes "It's dangerous in there."; + next; + if (.@playtime == 2) { + mes "[Laphine Soldier]"; + mes "I see you've been into the forest before."; + mes "Okay, at least the forest won't reject you."; + mes "However..."; + erasequest 7211; + next; + } + mes "[Laphine Soldier]"; + mes "Put yourself in my shoes, the entrance guard, and let me meet the representative of your party."; + mes "I have to discuss some things with him/her."; + close; + } +} + +bif_fild01,161,355,0 script Log Tunnel 844,{ + mes "I see the forest through the log tunnel."; + mes "It looks like I can enter the forest through the log tunnel."; + next; + if(select("Enter the tunnel.:Give up.") == 2) + close; + // TODO: Add official MD_Enter cases. + if (!getcharid(1)) { + mes "[Laphine Soldier]"; + mes "Hey, look!"; + mes "Are you going alone?"; + mes "That's impossible. Too rash."; + mes "Team up with some friends and go together!"; + close; + } + set .@playtime, checkquest(7211,PLAYTIME); + if (has_instance("1@mist") == "") { + if (.@playtime == 0 || .@playtime == 1) { + mes "You try to crawl into the log, but some mysterious power pushes you back with a gush of wind."; + mes "It seems like you can't force your way into the forest."; + close; + } + mes "The world beyond the log tunnel looks dark and suffocating."; + mes "Your instinct is screaming that this forest is dangerous."; + close; + } + if (.@playtime == 2) erasequest 7211; + if (checkquest(7211,PLAYTIME) == -1) setquest 7211; + mapannounce "bif_fild01",getpartyname(getcharid(1))+" party's "+strcharinfo(0)+" member is entering the Mistwood Maze.",bc_map,"0x00ff99"; //FW_NORMAL 12 0 0 + warp "1@mist",89,29; + close; +} + +// Instance Scripts +//============================================================ +1@mist,89,29,0 script #Whisper_mist 844,1,1,{ + end; +OnInstanceInit: + enablenpc instance_npcname("#Whisper_mist", instance_id()); + end; +OnTouch: + disablenpc instance_npcname("#Whisper_mist", instance_id()); + initnpctimer; + end; +OnTimer10000: +OnTimer20000: + instance_announce 0,"Whisper: Who's this? Who's this!? The forest is open! Tom, Tomba, Tired Rem, Remi! Wake up!",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + end; +OnTimer60000: + instance_announce 0,"Loud Whisper: What are the forest keepers doing? What are the gardeners doing??",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + end; +OnTimer120000: + instance_announce 0,"Loud Whisper: Don't go out, wander around forever, and play with us!",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + end; +OnTimer180000: + instance_announce 0,"Loud Whisper: Useless, useless. Wandering around and around, you'll meet your end!",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + stopnpctimer; + end; +} + +// callfunc "F_Mora_Mist",,,{,} +function script F_Mora_Mist { + if (mobcount("1@mist",instance_npcname(strnpcinfo(0), instance_id())+"::OnMyMobDead") == 0) { + mes "Obviously no one is taking care of it."; + mes "It seems like you can chop down the garden tree."; + next; + if(select("Chop down the garden tree.:Give up.") == 2) + close; + mes "You chop down the tree, which was blocking the path of the maze, "+((getarg(3,0))?"clearing the way out of the forest.":"so now you can continue."); + instance_announce 0,getarg(1),bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + enablenpc instance_npcname(getarg(0), instance_id()); + disablenpc instance_npcname(strnpcinfo(0), instance_id()); + close; + } else + instance_announce 0,((getarg(3,0))?getarg(2):getarg(2)+"'s Cry: Huh? Who's doing bad things to my tree?!"),bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + end; +} + +1@mist,251,121,3 script Tom's Garden 858,{ end; } +1@mist,247,123,0 script Tom's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "a25_a18-1", + "Roaring Cry: Tom's bolt is broken! Watch out, Tomba! Watch out, Tomba!", + "Tom"; + end; +OnInstanceInit: + monster "1@mist",249,120,"Tom",2136,1,instance_npcname("Tom's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,226,95,3 script Tomba's Garden 858,{ end; } +1@mist,225,98,0 script Tomba's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "a27-2_af1-2", + "Roaring Cry: Tomba's Garden Tree is gone with Tomba. Remi, what are you going to do now?", + "Tomba"; + end; +OnInstanceInit: + monster "1@mist",200,64,"Tomba",2136,1,instance_npcname("Tomba's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,157,183,3 script Remi's Garden 858,{ end; } +1@mist,159,184,0 script Remi's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "a15-2_a4-1", + "Roaring Cry: Remi, Remi's Garden Tree was chopped down- Rem, it's your turn next. Poor Rem!", + "Remi"; + end; +OnInstanceInit: + monster "1@mist",154,184,"Remi the Tired",2137,1,instance_npcname("Remi's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,58,39,3 script Tired Rem's Garden 858,{ end; } +1@mist,61,39,0 script Tired Rem's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "a4-2_a11", + "Rem's Desperate Cry: Argh... Rem will sleep. Rem will sleep now, and won't wake up forever!", + "Rem"; + end; +OnInstanceInit: + monster "1@mist",101,107,"Rem the Gardener",2136,1,instance_npcname("Tired Rem's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnTimer10000: + instance_announce 0,"Whisper of the Forest: So Tom's, Tomba's, Remi's, and Rem's garden trees were all chopped down?",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + end; +OnTimer15000: + instance_announce 0,"Whisper of the Forest: Trouble, trouble, we're in big trouble.",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + end; +OnTimer20000: + instance_announce 0,"Loud Whisper: They've come to the second deepest forest. Gardeners of the deep forest, watch out!",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + stopnpctimer; + end; +OnMyMobDead: + end; +} + +1@mist,227,179,3 script Ron's Garden 858,{ end; } +1@mist,230,179,0 script Ron's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "b4-2_b2", + "Ron the Gardener's Cry: I'm getting off work! Don't look for Ron, the second gardener, any more!!", + "Ron"; + end; +OnInstanceInit: + monster "1@mist",227,178,"Ron the Gardener",2134,1,instance_npcname("Ron's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,288,226,3 script Rover's Garden 858,{ end; } +1@mist,285,225,0 script Rover's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "b7_bf1-2", + "Roaring Whisper: Ron's, and Rover's trees were chopped down as well. Who is forcing his way into the forest? Who is it?", + "Rover"; + end; +OnInstanceInit: + monster "1@mist",304,237,"Rover the Strutter",2134,1,instance_npcname("Rover's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,159,318,3 script Mona's Garden 858,{ end; } +1@mist,161,316,0 script Mona's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "b31_b16", + "Clamoring Whisper: Mona the Seedseeker's garden tree is gone! Mona is gone too! Namon will be okay, because he is brave, right? Namon, are you okay?", + "Mona"; + end; +OnInstanceInit: + monster "1@mist",239,253,"Mona the Seedseeker",2133,1,instance_npcname("Mona's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,205,300,3 script Namon's Garden 858,{ end; } +1@mist,204,299,0 script Namon's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "b27-3_bN-1", + "Clamoring Whisper: Brave Namon met his fate not so bravely... *giggle*", + "Namon"; + end; +OnInstanceInit: + monster "1@mist",89,173,"Brave Namon",2134,1,instance_npcname("Namon's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,219,232,3 script Sad Neoron's Garden 858,{ end; } +1@mist,221,236,0 script Sad Neoron's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "b6-1_b33", + "Lamenting Whisper: Sad Neoron has become cheerful! Spyder the Superior Spider, what are you going to do? What are you going to do now?", + "Neoron"; + end; +OnInstanceInit: + monster "1@mist",143,265,"Sad Neoron",2137,1,instance_npcname("Sad Neoron's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,206,202,3 script Spyder's Garden 858,{ end; } +1@mist,206,200,0 script Spyder's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "b5_b14", + "Depressed Whisper: Now it's all over with the second deepest forest. Gardeners are dying out-", + "Spyder"; + end; +OnInstanceInit: + monster "1@mist",209,200,"Spyder the Eight-Legged",2132,1,instance_npcname("Spyder's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnTimer5000: + instance_announce 0,"Roaring Whisper: The path is about to open. The tight bolts have been removed!",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + end; +OnTimer9000: + instance_announce 0,"Roaring Whisper: A forest opened, another opened, and the other is going to open as well. Tito and Pumba, they are heading your way!",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + end; +OnTimer13000: + instance_announce 0,"Roaring Whisper: Where you get after wandering around, around and around, everybody you've met while wandering around, around and around,",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + end; +OnTimer17000: + instance_announce 0,"Roaring Whisper: all the gardeners will be waiting for you, with their clippers in their hands-!",bc_map,"0xccffcc"; //FW_NORMAL 12 0 0 + stopnpctimer; + end; +OnMyMobDead: + end; +} + +1@mist,96,288,3 script Tito's Garden 858,{ end; } +1@mist,95,287,0 script Tito's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "c1_c13-1", + "Tito's Cry: *sob* *sob* Tito's gone now! Tito's done for! Boo hoo!!", + "Tito"; + end; +OnInstanceInit: + monster "1@mist",264,291,"Tito the Flipper",2133,1,instance_npcname("Tito's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,326,325,3 script Pumba's Garden 858,{ end; } +1@mist,324,325,0 script Pumba's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "c13-3_c4", + "Roaring Whisper: Tito the Hard Worker was defeated! Stop playing and go to work, Tete! Start working!", + "Pumba"; + end; +OnInstanceInit: + monster "1@mist",309,165,"Diligent Pumba",2134,1,instance_npcname("Pumba's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,278,345,3 script Tete's Garden 858,{ end; } +1@mist,280,344,0 script Tete's Garden Tree 527,{ + callfunc "F_Mora_Mist", + "c19_c4", + "Whisper: They are strong, strong indeed. What are we going to do now? Are there any gardeners left? Are there any?", + "Tete"; + end; +OnInstanceInit: + monster "1@mist",277,343,"Carefree Tete",2136,1,instance_npcname("Tete's Garden Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,345,186,0 script The Gardeners' Tree 527,{ + callfunc "F_Mora_Mist", + "#to_bif02", + "Roaring Whisper: The forest will remember you! It will remember you, the one who broke the clippers of all the gardeners!", + "Gardeners: We're not dead, yet!!!!",1; + end; +OnInstanceInit: + monster "1@mist",318,137,"Baby Tom",2136,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",321,137,"Tomba the Baby",2136,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",324,137,"Exhausted Remi",2137,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",319,135,"Rem the Exhausted",2136,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",323,135,"Ron the Ex-Gardener",2134,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",320,133,"Rover the Strutter",2134,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",323,133,"Mona the Seedpicker",2133,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",317,132,"Timid Namon",2134,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",326,132,"Indifferent Neoron",2137,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",317,129,"Spyder the Seven-Legged",2132,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",320,129,"Tito the Flapper",2133,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",324,129,"Lazy Pumba",2134,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + monster "1@mist",327,129,"Careless Tete",2136,1,instance_npcname("The Gardeners' Tree", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + end; +} + +1@mist,73,290,0 script Mysterious Flower#1 844,{ + specialeffect EF_LEVEL99_4; + disablenpc instance_npcname(strnpcinfo(0), instance_id()); + getitem 12561,1; //Mysterious_Seed + end; +} +1@mist,69,295,0 duplicate(Mysterious Flower#1) Mysterious Flower#2 844 +1@mist,62,291,0 duplicate(Mysterious Flower#1) Mysterious Flower#3 844 +1@mist,54,293,0 duplicate(Mysterious Flower#1) Mysterious Flower#4 844 +1@mist,48,286,0 duplicate(Mysterious Flower#1) Mysterious Flower#5 844 +1@mist,54,277,0 duplicate(Mysterious Flower#1) Mysterious Flower#6 844 +1@mist,52,270,0 duplicate(Mysterious Flower#1) Mysterious Flower#7 844 +1@mist,62,268,0 duplicate(Mysterious Flower#1) Mysterious Flower#8 844 +1@mist,72,271,0 duplicate(Mysterious Flower#1) Mysterious Flower#9 844 +1@mist,72,276,0 duplicate(Mysterious Flower#1) Mysterious Flower#10 844 +1@mist,118,194,0 duplicate(Mysterious Flower#1) Mysterious Flower#11 844 +1@mist,122,204,0 duplicate(Mysterious Flower#1) Mysterious Flower#12 844 +1@mist,137,209,0 duplicate(Mysterious Flower#1) Mysterious Flower#13 844 +1@mist,144,203,0 duplicate(Mysterious Flower#1) Mysterious Flower#14 844 +1@mist,146,186,0 duplicate(Mysterious Flower#1) Mysterious Flower#15 844 +1@mist,142,182,0 duplicate(Mysterious Flower#1) Mysterious Flower#16 844 +1@mist,132,179,0 duplicate(Mysterious Flower#1) Mysterious Flower#17 844 +1@mist,123,184,0 duplicate(Mysterious Flower#1) Mysterious Flower#18 844 +1@mist,194,118,0 duplicate(Mysterious Flower#1) Mysterious Flower#19 844 +1@mist,188,109,0 duplicate(Mysterious Flower#1) Mysterious Flower#20 844 +1@mist,193,94,0 duplicate(Mysterious Flower#1) Mysterious Flower#21 844 +1@mist,205,92,0 duplicate(Mysterious Flower#1) Mysterious Flower#22 844 +1@mist,213,96,0 duplicate(Mysterious Flower#1) Mysterious Flower#23 844 +1@mist,216,103,0 duplicate(Mysterious Flower#1) Mysterious Flower#24 844 +1@mist,212,116,0 duplicate(Mysterious Flower#1) Mysterious Flower#25 844 +1@mist,207,120,0 duplicate(Mysterious Flower#1) Mysterious Flower#26 844 +1@mist,169,310,0 duplicate(Mysterious Flower#1) Mysterious Flower#27 844 +1@mist,172,296,0 duplicate(Mysterious Flower#1) Mysterious Flower#28 844 +1@mist,191,301,0 duplicate(Mysterious Flower#1) Mysterious Flower#30 844 +1@mist,195,301,0 duplicate(Mysterious Flower#1) Mysterious Flower#31 844 +1@mist,192,316,0 duplicate(Mysterious Flower#1) Mysterious Flower#32 844 +1@mist,187,320,0 duplicate(Mysterious Flower#1) Mysterious Flower#33 844 +1@mist,174,318,0 duplicate(Mysterious Flower#1) Mysterious Flower#34 844 +1@mist,308,136,0 duplicate(Mysterious Flower#1) Mysterious Flower#35 844 +1@mist,314,122,0 duplicate(Mysterious Flower#1) Mysterious Flower#36 844 +1@mist,321,118,0 duplicate(Mysterious Flower#1) Mysterious Flower#37 844 +1@mist,331,123,0 duplicate(Mysterious Flower#1) Mysterious Flower#38 844 +1@mist,335,126,0 duplicate(Mysterious Flower#1) Mysterious Flower#39 844 +1@mist,332,141,0 duplicate(Mysterious Flower#1) Mysterious Flower#40 844 +1@mist,328,144,0 duplicate(Mysterious Flower#1) Mysterious Flower#41 844 +1@mist,314,144,0 duplicate(Mysterious Flower#1) Mysterious Flower#42 844 +1@mist,238,224,0 duplicate(Mysterious Flower#1) Mysterious Flower#43 844 +1@mist,244,231,0 duplicate(Mysterious Flower#1) Mysterious Flower#44 844 +1@mist,257,232,0 duplicate(Mysterious Flower#1) Mysterious Flower#45 844 +1@mist,262,229,0 duplicate(Mysterious Flower#1) Mysterious Flower#46 844 +1@mist,265,216,0 duplicate(Mysterious Flower#1) Mysterious Flower#47 844 +1@mist,260,214,0 duplicate(Mysterious Flower#1) Mysterious Flower#48 844 +1@mist,252,206,0 duplicate(Mysterious Flower#1) Mysterious Flower#49 844 +1@mist,244,211,0 duplicate(Mysterious Flower#1) Mysterious Flower#50 844 + +// Wandering Guardian Quest +//============================================================ +1@mist,2,2,0 script #Dragon Herder 844,{ + end; +OnInstanceInit: + switch(rand(1,6)) { + case 1: setarray .@c[0],77,240; break; + case 2: setarray .@c[0],147,261; break; + case 3: setarray .@c[0],182,263; break; + case 4: setarray .@c[0],194,350; break; + case 5: setarray .@c[0],268,183; break; + case 6: setarray .@c[0],65,278; break; + } + monster "1@mist",.@c[0],.@c[1],"Wandering Purple Dragon",2131,1,instance_npcname("#Dragon Herder", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + if (mobcount("1@mist",instance_npcname("#Dragon Herder", instance_id())+"::OnMyMobDead") == 0) { + donpcevent instance_npcname("Collapsed Girl#mist", instance_id())+"::OnEnable"; + donpcevent instance_npcname("Mysterious Young Man#mis", instance_id())+"::OnEnable"; + donpcevent instance_npcname("Loki#mist", instance_id())+"::OnEnable"; + instance_announce 0,"The Dragon's Cry: Am I being punished... for abandoning the way... of the guardian...?",bc_map,"0xffff00"; //FW_NORMAL 12 0 0 + disablenpc instance_npcname("#Dragon Herder", instance_id()); + initnpctimer; + } + end; +OnTimer3000: + stopnpctimer; + instance_announce 0,"Voice in your head: ...Will you... save... me... please......?",bc_map,"0xffff00"; //FW_NORMAL 12 0 0 + end; +} + +1@mist,97,30,3 script Mysterious Young Man#mis 512,{ + if (BaseLevel < 98) { + mes "[Mysterious Young Man]"; + mes "Huh? Do you plan to pass through here?"; + mes ".....I'm afraid it's beyond your ability, but I won't meddle in your affairs."; + mes "We'll meet again, if you survive."; + close; + } + if (ep14_1_mistwoods == 0) { + if (ep13_3_secret > 23) { + mes "[Mysterious Young Man]"; + mes "You... I remember seeing you at the camp."; + mes "The information you gave on Ahat was useful."; + mes "Thanks!"; + next; + mes "[Mysterious Young Man]"; + mes "But do you plan to pass through here?"; + mes "What good is it to go across Bifrost?"; + next; + } else { + mes "[Mysterious Young Man]"; + mes "Do you plan to pass through here?"; + mes "I will advise against it if you're just curious."; + mes "It will only bring about your untimely death..."; + next; + } + mes "[Mysterious Young Man]"; + mes "If you are determined to pass through here,"; + mes "I will ask for your help with something."; + next; + select("Who are you?"); + mes "[Loki]"; + mes "Loki... from the Assassin's Guild."; + mes "That's my name."; + mes "And yours?"; + next; + mes "["+strcharinfo(0)+"]"; + mes "...."; + mes "...."+strcharinfo(0)+" sir."; + next; + mes "[Loki]"; + mes "I see. "+strcharinfo(0)+"."; + mes "I'm asking you again."; + mes "Do you plan to pass through this forest?"; + next; + switch(select("Yes, I do.:No, I don't.")) { + case 1: + mes "[Loki]"; + mes "Then I'll ask you a question."; + mes "Have you ever seen a guard... a girl with purple hair?"; + next; + switch(select("No, I haven't.:Yes, I might have...")) { + case 1: + mes "[Loki]"; + mes "So you haven't."; + mes "You're telling the truth."; + next; + break; + case 2: + mes "[Loki]"; + mes "Wait."; + mes "(Loki comes closer.)"; + mes "... No."; + mes "You're telling the truth."; + next; + break; + } + mes "[Loki]"; + mes "Now we have to say goodbye here."; + mes "If you survive this forest, of course."; + set ep14_1_mistwoods,2; + setquest 7212; + close; + case 2: + mes "[Loki]"; + mes "I understand."; + mes "Step back if you aren't ready."; + mes "This forest doesn't like strangers."; + set ep14_1_mistwoods,1; + close; + } + } else if (ep14_1_mistwoods == 1) { + mes "[Loki]"; + mes "I told you - step back if you don't want to die."; + mes "It's not easy going through the forest."; + mes "It may cost you your life."; + next; + switch(select("Okay.:What do you want?")) { + case 1: + mes "- When you step back,"; + mes "Loki nods slightly and then looks away. -"; + close; + case 2: + mes "[Loki]"; + mes "I'm looking for somebody."; + mes "Have you ever seen a guard... a girl with purple hair?"; + next; + switch(select("No, I haven't.:Yes, I might have...")) { + case 1: + mes "[Loki]"; + mes "So you haven't."; + mes "You're telling the truth."; + next; + break; + case 2: + mes "[Loki]"; + mes "Wait."; + mes "(Loki comes closer.)"; + mes "... No."; + mes "You're telling the truth."; + next; + break; + } + mes "[Loki]"; + mes "Now we have to say goodbye here."; + mes "Hopefully, we will see each other again in Mora."; + set ep14_1_mistwoods,2; + setquest 7212; + close; + } + } else if (ep14_1_mistwoods == 2) { + mes "[Loki]"; + mes "I don't want to go with you."; + mes "Hopefully, we will see each other again in Mora."; + close; + } else if (ep14_1_mistwoods == 3) { + mes "[Loki]"; + mes "So we meet again."; + mes "Are you used to this place?"; + mes "Come to the inn in Mora."; + mes "I have something to give to you."; + close; + } else { + mes "[Loki]"; + mes "We're seeing a lot of each other these days."; + mes "It seems you are completely comfortable with the place."; + mes "You'd better not be too proud of yourself."; + close; + } + end; +OnInstanceInit: +OnEnable: + enablenpc instance_npcname("Mysterious Young Man#mis", instance_id()); + end; +OnDisable: + disablenpc instance_npcname("Mysterious Young Man#mis", instance_id()); + end; +} + +1@mist,183,304,3 script Loki#mist 512,{ + if (ep14_1_mistwoods < 2) { + mes "[Loki]"; + mes "An adventurer in the forest."; + mes "....."; + mes "You can go to Mora through this forest."; + close; + } else if (ep14_1_mistwoods == 2) { + mes "[Loki]"; + mes "Is it you that took care of this unruly girl?"; + mes "I guess I have to thank you."; + mes "You've calmed her down."; + next; + select("What's happening?:This girl...?"); + mes "[Loki]"; + mes "You might be able to change your appearance, but you cannot change your unique, innate light."; + mes "A scent strong enough to burn your nose."; + next; + mes "[Loki]"; + mes "This is Nydhogg, the Guardian of Yggdrasil,"; + mes "whom I was looking for."; + mes "Now she won't wander around crazy any more."; + next; + select("What are you going to do now?"); + mes "[Loki]"; + mes "I'll wait for her to wake up and get out of this forest."; + mes "I can manage it on my own."; + mes "I'll see you in Mora."; + set ep14_1_mistwoods,3; + erasequest 7212; + setquest 7213; + close; + } else if (ep14_1_mistwoods == 3) { + mes "[Loki]"; + mes "I don't want to go with you."; + mes "I can manage her on my own."; + mes "If you have something to say, say it after we get out of the forest."; + close; + } else { + mes "[Loki]"; + mes "I don't want to go with you."; + mes "If you have something to say, say it after we get out of the forest."; + close; + } + end; +OnInstanceInit: +OnDisable: + disablenpc instance_npcname("Loki#mist", instance_id()); + end; +OnEnable: + enablenpc instance_npcname("Loki#mist", instance_id()); + end; +} + +1@mist,181,303,3 script Collapsed Girl#mist 511,{ + mes "You see a girl with mysterious hair collapsed on the ground."; + mes "As you approach her, you smell the scent of flowers so strong that it makes you dizzy."; + close; +OnInstanceInit: +OnDisable: + disablenpc instance_npcname("Collapsed Girl#mist", instance_id()); + end; +OnEnable: + enablenpc instance_npcname("Collapsed Girl#mist", instance_id()); + end; +} + +mora,46,152,5 script Flower Smelling Lady 510,{ + if (ep14_1_mistwoods < 3) { + mes "[Flower Smell Lady]"; + mes "I need rest."; + mes "I'm too tired to talk to you."; + mes "I'm sorry."; + close; + } else if (ep14_1_mistwoods == 3) { + mes "[Nydhogg the Guardian]"; + mes "I've been waiting for you."; + mes "I'm still confused, but I know what I did wrong."; + next; + mes "[Nydhogg the Guardian]"; + mes "If it weren't for you, I would still be wandering in the abyssal darkness."; + mes "I thank you, from the bottom of my heart."; + next; + mes "[Nydhogg the Guardian]"; + mes "I'm ashamed of myself, falling for the sweet but empty words that came to me in my loneliness."; + mes "...."; + next; + mes "[Nydhogg the Guardian]"; + mes "I don't deserve to be a guardian any more."; + mes "A dragon gone crazy is not a guardian any more."; + next; + mes "[Loki]"; + mes "Yggdrasil doesn't think so."; + mes "Nidi, don't forget your duties."; + next; + mes "[Nydhogg the Guardian]"; + mes "Are you...?"; + mes "I see..."; + mes "I thought I was forsaken..."; + next; + mes "The Guardian slowly looked away as if deep in thought."; + set ep14_1_mistwoods,4; + close2; + } else if (ep14_1_mistwoods == 4) { + mes "- He seems to be deep in thought. -"; + close; + } else { + mes "[Nydhogg the Guardian]"; + mes "I haven't gotten all of my powers back."; + mes "I'm sorry I can't protect you."; + next; + mes "[Nydhogg the Guardian]"; + mes "Loki said..."; + mes "that I won't cry from loneliness again,"; + mes "that I will always have new friends like you..."; + next; + mes "[Nydhogg the Guardian]"; + mes "...I've lost everything, but I'm happy now."; + close; + } +} + +mora,48,152,3 script Sharp Eyed Man 512,{ + if (checkweight(1201,1) == 0 || MaxWeight - Weight < 1000) { + mes "- You have too many items to do this quest. -"; + close; + } + if (ep14_1_mistwoods < 3) { + mes "He won't look at you. It's like he's not interested at all."; + close; + } else if (ep14_1_mistwoods == 3) { + mes "[Loki]"; + mes "So you've passed through the forest."; + mes "It seems Niddy has something to say to you."; + close; + } else if (ep14_1_mistwoods == 4) { + mes "[Loki]"; + mes "Nydhogg was one of the guardians of the World Tree."; + mes "But he abandoned his duties as a guardian when he gave in to Morroc's temptation."; + next; + mes "[Loki]"; + mes "Some fools performed a ritual to break the seal that held Morroc."; + mes "But the ritual didn't work right. The servant of Morroc failed to break the seal."; + next; + mes "[Loki]"; + mes "But the seal is so weak that it can break open any time."; + mes "It's Yggdrasil the World Tree's will that has kept the seal from breaking."; + next; + mes "[Nydhogg the Guardian]"; + mes "That's right. The power of the World Tree is linked to the whole world."; + mes "When the bond between the guardians and Yggdrasil broke, Yggdrasil became unstable."; + next; + mes "[Nydhogg the Guardian]"; + mes "That's why all those disasters happened to Yggdrasil."; + mes "As the World Tree became unstable, the influence it had on the seal grew weak."; + next; + mes "[Loki]"; + mes "And Morroc broke himself free from the seal."; + mes "Although it seems like he used most of his powers just to break the seal..."; + next; + mes "[Nydhogg the Guardian]"; + mes "It's all my fault."; + mes "I couldn't break free from Morroc's temptation."; + mes "For too... too long..."; + next; + mes "[Nydhogg the Guardian]"; + mes "...I wanted to be relieved of my thousands of years of loneliness."; + mes "I wasn't in my right mind then."; + mes "It was none other than I that broke my bond with Yggdrasil."; + next; + mes "[Nydhogg the Guardian]"; + mes "I lost control of myself, and did what I shouldn't have done."; + mes "The other side of me became a shadow and a reckless tyrant."; + next; + mes "[Nydhogg the Guardian]"; + mes "Facing the world, I realized..."; + mes "I felt too great a sense of loss... it was much more painful than the loneliness I had endured for thousands of years."; + next; + mes "[Nydhogg the Guardian]"; + mes "That's how I was left alone."; + mes "I felt too great a sense of loss... it was much more painful than the loneliness I had endured for thousands of years."; + next; + mes "[Nydhogg the Guardian]"; + mes "So I became a sinner, forgotten to the world."; + next; + mes "[Loki]"; + mes "It's not too late."; + mes "You're still a guardian."; + mes "You still have things to do."; + next; + mes "[Nydhogg the Guardian]"; + mes "... Oh, yes. It's late, but I have to fulfill my duties as a guardian."; + mes "Now I know. I'll destroy Morroc with my own hands."; + mes "I will fulfill my duties as a guardian."; + next; + switch(select("You're not alone.:Those are very important duties.")) { + case 1: + mes "[Nydhogg the Guardian]"; + mes "You're right."; + mes "It may be why I haven't been forsaken - to realize that I'm not alone."; + mes "You are a kind soul."; + next; + break; + case 2: + mes "[Nydhogg the Guardian]"; + mes "But this is my atonement."; + mes "I'm happy, though."; + mes "I don't have to fight the loneliness any more."; + next; + break; + } + mes "[Nydhogg the Guardian]"; + mes strcharinfo(0)+"..."; + mes "Thanks for listening to my long story."; + next; + mes "[Nydhogg the Guardian]"; + mes "It's what I always have with me."; + mes "I'm sure it will protect you someday."; + next; + mes "[Loki]"; + mes "(Removes his scarf from around his neck and hands it to you.)"; + next; + mes "[Nydhogg the Guardian]"; + mes "May the blessing of Mother Yggdrasil be with you..."; + set ep14_1_mistwoods,10; + completequest 7213; + getitem 2568,1; //Muffler_Of_Roki + getitem 2858,1; //Pendant_Of_Guardian + getexp 400000,400000; + close; + } else { + mes "[Loki]"; + mes "I'll be staying here for a while."; + mes "We may meet again."; + next; + mes "[Loki]"; + mes "The day when Morroc reveals his despicable nature..."; + mes "I will be waiting for him."; + close; + } +} + +// Monster Spawns +//============================================================ +1@mist,1,1,0 script #Mist Mobs Respawn1 844,{ + end; +OnInstanceInit: + monster "1@mist",0,0,"Miming",2137,15,instance_npcname("#Mist Mobs Respawn1", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + set .@num_mobs, 15 - mobcount("1@mist",instance_npcname("#Mist Mobs Respawn1", instance_id())+"::OnMyMobDead"); + if (.@num_mobs > 0) + monster "1@mist",0,0,"Miming",2137,.@num_mobs,instance_npcname("#Mist Mobs Respawn1", instance_id())+"::OnMyMobDead"; + end; +} + +1@mist,1,2,0 script #Mist Mobs Respawn2 844,{ + end; +OnInstanceInit: + monster "1@mist",0,0,"Pom Spider",2132,35,instance_npcname("#Mist Mobs Respawn2", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + set .@num_mobs, 35 - mobcount("1@mist",instance_npcname("#Mist Mobs Respawn2", instance_id())+"::OnMyMobDead"); + if (.@num_mobs > 0) + monster "1@mist",0,0,"Pom Spider",2132,.@num_mobs,instance_npcname("#Mist Mobs Respawn2", instance_id())+"::OnMyMobDead"; + end; +} + +1@mist,1,3,0 script #Mist Mobs Respawn3 844,{ + end; +OnInstanceInit: + monster "1@mist",0,0,"Angra Mantis",2133,35,instance_npcname("#Mist Mobs Respawn3", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + set .@num_mobs, 35 - mobcount("1@mist",instance_npcname("#Mist Mobs Respawn3", instance_id())+"::OnMyMobDead"); + if (.@num_mobs > 0) + monster "1@mist",0,0,"Angra Mantis",2133,.@num_mobs,instance_npcname("#Mist Mobs Respawn3", instance_id())+"::OnMyMobDead"; + end; +} + +1@mist,1,4,0 script #Mist Mobs Respawn4 844,{ + end; +OnInstanceInit: + monster "1@mist",0,0,"Parus",2134,35,instance_npcname("#Mist Mobs Respawn4", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + set .@num_mobs, 35 - mobcount("1@mist",instance_npcname("#Mist Mobs Respawn4", instance_id())+"::OnMyMobDead"); + if (.@num_mobs > 0) + monster "1@mist",0,0,"Parus",2134,.@num_mobs,instance_npcname("#Mist Mobs Respawn4", instance_id())+"::OnMyMobDead"; + end; +} + +1@mist,1,5,0 script #Mist Mobs Respawn5 844,{ + end; +OnInstanceInit: + monster "1@mist",0,0,"Little Fatum",2136,15,instance_npcname("#Mist Mobs Respawn5", instance_id())+"::OnMyMobDead"; + end; +OnMyMobDead: + set .@num_mobs, 15 - mobcount("1@mist",instance_npcname("#Mist Mobs Respawn5", instance_id())+"::OnMyMobDead"); + if (.@num_mobs > 0) + monster "1@mist",0,0,"Little Fatum",2136,.@num_mobs,instance_npcname("#Mist Mobs Respawn5", instance_id())+"::OnMyMobDead"; + end; +} + +1@mist,1,6,0 script #Fragments of Memory 844,{ + end; +OnInstanceInit: + disablenpc instance_npcname("#Fragments of Memory", instance_id()); + monster "1@mist",0,0,"Guardian's Fragments of Memory",2138,15; + end; +} + +// Warp Portals +//============================================================ +bif_fild01,38,374,0 script Mysterious Flower#ep14_1 844,{ + mes "It's a giant flower with mysterious energy."; + if (countitem(12561)) { + mes "It's reacting to the Mysterious Flower Seeds you have with you."; + next; + switch(select("Observe the reaction.:Stop the reaction.")) { + case 1: + mes "The flower started to shake violently"; + mes "and swing forward as if trying to send the seeds as far away as possible!!!"; + close2; + delitem 12561,1; //Mysterious_Seed + warp "bif_fild02",160,230; + end; + case 2: + mes "As you hold onto the Mysterious Flower Seeds tightly,"; + mes "the flower shook violently and then became calm again."; + close; + } + } + mes "It looks like it has some special use, but you're not sure what."; + close; +} + +1@mist,104,23,0 warp #to_bif01 1,1,bif_fild01,160,352 + +1@mist,109,70,0 script a1_a2 45,1,1,{ + end; +OnTouch: + if (checkquest(7211,PLAYTIME) == -1) + setquest 7211; + warp "1@mist",116,40; + end; +} + +1@mist,113,40,0 warp a2_a7 1,1,1@mist,90,81 +1@mist,93,81,0 warp a7_a14 1,1,1@mist,108,152 +1@mist,111,154,0 warp a14_a24 1,1,1@mist,236,108 +1@mist,236,110,0 warp a24_a1 1,1,1@mist,106,69 +1@mist,161,67,0 warp a18-1_a22 1,1,1@mist,159,85 +1@mist,180,116,0 warp a23_a18-1 1,1,1@mist,164,66 +1@mist,180,63,0 warp a18-2_a9 1,1,1@mist,141,90 +1@mist,116,84,0 warp a8_a26 1,1,1@mist,222,133 +1@mist,220,133,0 warp a26_a27-1 1,1,1@mist,200,64 +1@mist,197,64,0 warp a27-1_a23 1,1,1@mist,177,116 +1@mist,146,194,0 warp af1-2_a27-2 1,1,1@mist,225,96 +1@mist,133,195,0 warp af1-1_af2-1 1,1,1@mist,202,110 +1@mist,202,107,0 warp af2-1_af1-1 1,1,1@mist,134,189 +1@mist,217,110,0 warp af2-2_a20-1 1,1,1@mist,240,56 +1@mist,240,54,0 warp a20-1_af2-2 1,1,1@mist,214,110 +1@mist,234,67,0 warp a20-2_a21 1,1,1@mist,239,80 +1@mist,242,77,0 warp a21_a15-1 1,1,1@mist,153,137 +1@mist,156,139,0 warp a15-1_a3 1,1,1@mist,123,55 +1@mist,124,51,0 warp a3_a20-1 1,1,1@mist,240,56 +1@mist,48,41,0 warp a4-1_a17 1,1,1@mist,174,165 +1@mist,171,165,0 warp a17_a16 1,1,1@mist,168,143 +1@mist,169,141,0 warp a16_a10 1,1,1@mist,101,107 +1@mist,99,107,0 warp a10_a4-2 1,1,1@mist,57,38 +1@mist,65,113,0 warp a11_a28 1,1,1@mist,218,151 +1@mist,221,151,0 warp a28_a13 1,1,1@mist,117,126 +1@mist,114,126,0 warp a13_a5 1,1,1@mist,36,62 +1@mist,61,88,0 warp a6_a19 1,1,1@mist,189,139 +1@mist,186,140,0 warp a19_a12 1,1,1@mist,98,126 +1@mist,101,126,0 warp a12_a29-1 1,1,1@mist,238,151 +1@mist,235,152,0 warp a29-1_af1-2 1,1,1@mist,144,194 +1@mist,254,151,0 warp a29-2E_b1 1,1,1@mist,271,164 +1@mist,275,211,0 warp b1_b13 1,1,1@mist,277,112 +1@mist,301,141,0 warp b14_b24 1,1,1@mist,99,232 +1@mist,99,230,0 warp b24_b25 1,1,1@mist,103,255 +1@mist,102,253,0 warp b25_b4-1 1,1,1@mist,215,177 +1@mist,212,177,0 warp b4-1_b1 1,1,1@mist,276,208 +1@mist,289,167,0 warp b2_b19 1,1,1@mist,152,219 +1@mist,149,219,0 warp b19_b20 1,1,1@mist,119,227 +1@mist,115,227,0 warp b20_b23 1,1,1@mist,230,353 +1@mist,233,353,0 warp b23_b7 1,1,1@mist,289,225 +1@mist,76,273,0 warp bf1-2_b7 1,1,1@mist,289,225 +1@mist,61,282,0 warp bf1-1_bf2-1 1,1,1@mist,256,220 +1@mist,252,220,0 warp bf2-1_bf1-1 1,1,1@mist,65,282 +1@mist,267,213,0 warp bf2-2_b28 1,1,1@mist,214,268 +1@mist,212,265,0 warp b28_b12 1,1,1@mist,288,266 +1@mist,285,266,0 warp b12_b21 1,1,1@mist,143,234 +1@mist,143,231,0 warp b21_b29 1,1,1@mist,222,281 +1@mist,223,279,0 warp b29_b31 1,1,1@mist,158,317 +1@mist,134,287,0 warp b30_b3 1,1,1@mist,293,195 +1@mist,295,197,0 warp b3_b10 1,1,1@mist,239,253 +1@mist,236,253,0 warp b10_b12 1,1,1@mist,288,266 +1@mist,111,203,0 warp b16_b34 1,1,1@mist,202,333 +1@mist,199,333,0 warp b34_b27-1 1,1,1@mist,203,251 +1@mist,206,249,0 warp b27-1_b22 1,1,1@mist,168,239 +1@mist,165,239,0 warp b22_b15 1,1,1@mist,89,173 +1@mist,177,265,0 warp b27-2_a14 1,1,1@mist,108,152 +1@mist,166,314,0 warp bN-1_b27-3 1,1,1@mist,206,297 +1@mist,197,299,0 warp bN-2_b17 1,1,1@mist,167,200 +1@mist,165,200,0 warp b17_bN-2 1,1,1@mist,193,299 +1@mist,86,173,0 warp b15_b32 1,1,1@mist,218,313 +1@mist,215,313,0 warp b32_b28 1,1,1@mist,214,268 +1@mist,230,324,0 warp b33_b6-1 1,1,1@mist,221,233 +1@mist,230,230,0 warp b6-2_b11 1,1,1@mist,263,261 +1@mist,263,258,0 warp b11_b9 1,1,1@mist,272,246 +1@mist,269,246,0 warp b9_b26 1,1,1@mist,143,265 +1@mist,140,265,0 warp b26_b5 1,1,1@mist,209,200 +1@mist,195,206,0 warp b18_b35 1,1,1@mist,169,341 +1@mist,166,341,0 warp b35_b36 1,1,1@mist,198,354 +1@mist,201,354,0 warp b36_b37-1 1,1,1@mist,83,224 +1@mist,87,224,0 warp b37-1_b35 1,1,1@mist,169,341 +1@mist,84,273,0 warp b37-2_c1 1,1,1@mist,98,287 +1@mist,111,298,0 warp c2_c3 1,1,1@mist,82,307 +1@mist,79,307,0 warp c3_c7 1,1,1@mist,284,89 +1@mist,281,89,0 warp c7_c12 1,1,1@mist,264,291 +1@mist,261,291,0 warp c12_c2 1,1,1@mist,115,298 +1@mist,326,275,0 warp c13-1_b13 1,1,1@mist,277,112 +1@mist,294,293,0 warp c13-2_c5 1,1,1@mist,78,330 +1@mist,81,330,0 warp c5_c17 1,1,1@mist,308,330 +1@mist,308,327,0 warp c17_c10 1,1,1@mist,309,165 +1@mist,306,165,0 warp c10_c13-2 1,1,1@mist,298,293 +1@mist,46,316,0 warp c4_c6 1,1,1@mist,113,328 +1@mist,95,328,0 warp c6_c9 1,1,1@mist,342,157 +1@mist,339,157,0 warp c9_c16 1,1,1@mist,343,328 +1@mist,343,325,0 warp c16_c8-2 1,1,1@mist,346,120 +1@mist,344,123,0 warp c8-2_c19 1,1,1@mist,277,343 +1@mist,256,313,0 warp c18_c15 1,1,1@mist,343,307 +1@mist,342,305,0 warp c15_cKEY 1,1,1@mist,332,121 +1@mist,335,120,0 warp cKEY_c18 1,1,1@mist,259,313 +1@mist,317,89,0 warp c8-1_c14 1,1,1@mist,339,284 +1@mist,339,281,0 warp c14_c11-1 1,1,1@mist,332,172 +1@mist,329,171,0 warp c11-1_c8-2 1,1,1@mist,346,120 +1@mist,301,237,0 warp b8_b2 1,1,1@mist,289,170 + +// Disable Garden Tree warps. +// Custom, but saves processing and lines. +1@mist,1,1,0 script #mist_warp_init 844,{ + end; +OnInstanceInit: + disablenpc instance_npcname("a25_a18-1", instance_id()); + disablenpc instance_npcname("a27-2_af1-2", instance_id()); + disablenpc instance_npcname("a15-2_a4-1", instance_id()); + disablenpc instance_npcname("a4-2_a11", instance_id()); + disablenpc instance_npcname("b4-2_b2", instance_id()); + disablenpc instance_npcname("b7_bf1-2", instance_id()); + disablenpc instance_npcname("b31_b16", instance_id()); + disablenpc instance_npcname("b27-3_bN-1", instance_id()); + disablenpc instance_npcname("b6-1_b33", instance_id()); + disablenpc instance_npcname("b5_b14", instance_id()); + disablenpc instance_npcname("c1_c13-1", instance_id()); + disablenpc instance_npcname("c13-3_c4", instance_id()); + disablenpc instance_npcname("c19_c4", instance_id()); + disablenpc instance_npcname("#to_bif02", instance_id()); + disablenpc instance_npcname("#mist_warp_init", instance_id()); + end; +} +1@mist,247,123,0 warp a25_a18-1 1,1,1@mist,164,66 //Tom +1@mist,225,98,0 warp a27-2_af1-2 1,1,1@mist,144,194 //Tomba +1@mist,159,184,0 warp a15-2_a4-1 1,1,1@mist,49,37 //Remi +1@mist,61,39,0 warp a4-2_a11 1,1,1@mist,68,113 //Rem +1@mist,230,179,0 warp b4-2_b2 1,1,1@mist,289,170 //Ron +1@mist,285,225,0 warp b7_bf1-2 1,1,1@mist,72,274 //Rover +1@mist,161,316,0 warp b31_b16 1,1,1@mist,108,203 //Mona +1@mist,204,299,0 warp b27-3_bN-1 1,1,1@mist,169,314 //Namon +1@mist,221,236,0 warp b6-1_b33 1,1,1@mist,233,324 //Neoron +1@mist,206,200,0 warp b5_b14 1,1,1@mist,298,142 //Spyder +1@mist,95,287,0 warp c1_c13-1 1,1,1@mist,323,276 //Tito +1@mist,324,325,0 warp c13-3_c4 1,1,1@mist,49,316 //Pumba +1@mist,280,344,0 warp c19_c4 1,1,1@mist,49,316 //Tete +1@mist,345,186,0 warp #to_bif02 1,1,bif_fild02,151,121 //The Gardeners' Tree -- cgit v1.2.3-70-g09d2 From 240de5590ce83954574790406f64e3e64b5f1450 Mon Sep 17 00:00:00 2001 From: Mysteries Date: Sat, 8 Jun 2013 21:21:34 -0400 Subject: Fixed some spacings, typos, and sentences Thanks rAthena! --- npc/quests/quests_13_1.txt | 88 +++++++++++++++++++++++----------------------- src/map/script.c | 24 ++++++------- 2 files changed, 56 insertions(+), 56 deletions(-) (limited to 'npc') diff --git a/npc/quests/quests_13_1.txt b/npc/quests/quests_13_1.txt index 78c843ae5..627688922 100644 --- a/npc/quests/quests_13_1.txt +++ b/npc/quests/quests_13_1.txt @@ -8877,7 +8877,7 @@ mid_campin,90,121,5 script Hibba Agip 459,{ mes "What is it?"; next; mes "[Staff Officer Abidal]"; - mes "Err? Hey, aren't you that famous adventurer," + strcharinfo(0) + "? I've heard many good things about you."; + mes "Err? Hey, aren't you that famous adventurer, " + strcharinfo(0) + "? I've heard many good things about you."; next; mes "[Instructor Igrid]"; mes "I don't know what you're talking about. Boss, do you know this adventurer?"; @@ -8919,7 +8919,7 @@ mid_campin,90,121,5 script Hibba Agip 459,{ } else if (ep13_1_edq == 2) { mes "[Hibba Agip]"; - mes "Oh yes, right... You're" + strcharinfo(0) + ", right? Abidal has told me good things about you."; + mes "Oh yes, right... You're " + strcharinfo(0) + ", right? Abidal has told me good things about you."; next; mes "[Hibba Agip]"; mes "We're lucky to have you, my friend... I hope you're as good as the stories play you up to be."; @@ -10195,7 +10195,7 @@ mid_camp,206,286,3 script Expedition Messenger 997,{ if ((ep13_1_edq == 3) && (countitem(11012) > 0)) { mes "[Expedition Messenger]"; mes "Welcome, I've been waiting for you."; - mes "You must be" + strcharinfo(0) + ". Nice to meet you."; + mes "You must be " + strcharinfo(0) + ". Nice to meet you."; next; mes "[Expedition Messenger]"; mes "Let me check something quicly. You received the report directly from the commander, didn't you? May I see it?"; @@ -10205,7 +10205,7 @@ mid_camp,206,286,3 script Expedition Messenger 997,{ mes "........."; next; mes "[Expedition Messenger]"; - mes "Excellent. Thank you. Then we'll go back to the mainland and let the leaders know that you,"+ strcharinfo(0) + ", have departed."; + mes "Excellent. Thank you. Then we'll go back to the mainland and let the leaders know that you, "+ strcharinfo(0) + ", have departed."; next; mes "[Expedition Messenger]"; mes "Guys, it's time to go."; @@ -10255,7 +10255,7 @@ mid_camp,206,286,3 script Expedition Messenger 997,{ mes "Argh... You..."; next; mes "[Expedition Messenger]"; - mes "*Cough* Oh, thank god!" + strcharinfo(0) + ", please take the report and run!"; + mes "*Cough* Oh, thank god! " + strcharinfo(0) + ", please take the report and run!"; next; mes "[???]"; mes "No... Noooo!"; @@ -10263,7 +10263,7 @@ mid_camp,206,286,3 script Expedition Messenger 997,{ specialeffect2 EF_SOULBREAKER; specialeffect2 EF_SONICBLOWHIT; mes "[Expedition Messenger]"; - mes "Argh..." + strcharinfo(0) + ", are you alright? The report... The report..."; + mes "Argh... " + strcharinfo(0) + ", are you alright? The report... The report..."; next; delitem 11012,1; //Expedition_Report set ep13_1_edq,4; @@ -10308,7 +10308,7 @@ mid_camp,206,286,3 script Expedition Messenger 997,{ mes "Argh... You..."; next; mes "[Expedition Messenger]"; - mes "*Cough* Oh, thank god!" + strcharinfo(0) + ", please take the report and run!"; + mes "*Cough* Oh, thank god! " + strcharinfo(0) + ", please take the report and run!"; next; mes "[???]"; mes "No... Noooo!"; @@ -10316,7 +10316,7 @@ mid_camp,206,286,3 script Expedition Messenger 997,{ specialeffect2 EF_SOULBREAKER; specialeffect2 EF_SONICBLOWHIT; mes "[Expedition Messenger]"; - mes "Argh..." + strcharinfo(0) + ", are you alright? The report... The report..."; + mes "Argh... " + strcharinfo(0) + ", are you alright? The report... The report..."; next; mes "[Expedition Agent]"; mes "We lost the report. The pages are blowing away!"; @@ -10458,7 +10458,7 @@ man_fild01,315,95,3 script Expedition Scout#1 707,{ set .@ep13_search_lotto,rand(1,6); if (.@ep13_search_lotto == 4) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 5 pieces of paper that appear to be part of the report."; @@ -10473,7 +10473,7 @@ man_fild01,315,95,3 script Expedition Scout#1 707,{ } else if ((.@ep13_search_lotto == 1) || (.@ep13_search_lotto == 6)) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 2 pieces of paper that appear to be part of the report."; @@ -10488,7 +10488,7 @@ man_fild01,315,95,3 script Expedition Scout#1 707,{ } else if (.@ep13_search_lotto == 3) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 3 pieces of paper that appear to be part of the report."; @@ -10503,7 +10503,7 @@ man_fild01,315,95,3 script Expedition Scout#1 707,{ } else { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "I'm doing my best, but I haven't found any pages yet."; @@ -10518,7 +10518,7 @@ man_fild01,315,95,3 script Expedition Scout#1 707,{ } else if (((ep13_1_edq == 71) || (ep13_1_edq == 72)) && ((.@ep13_search_control == 0) || (.@ep13_search_control == 1))) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Searching for lost pages was tougher then I expected. Please come back later when I'm finished making one round."; @@ -10528,7 +10528,7 @@ man_fild01,315,95,3 script Expedition Scout#1 707,{ set .@ep13_search_lotto,rand(1,6); if (.@ep13_search_lotto == 4) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 5 pieces of paper that appear to be part of the report."; @@ -10542,7 +10542,7 @@ man_fild01,315,95,3 script Expedition Scout#1 707,{ } else if ((.@ep13_search_lotto == 1) || (.@ep13_search_lotto == 6)) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 2 pieces of paper that appear to be part of the report."; @@ -10556,7 +10556,7 @@ man_fild01,315,95,3 script Expedition Scout#1 707,{ } else if (.@ep13_search_lotto == 3) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 3 pieces of paper that appear to be part of the report."; @@ -10570,7 +10570,7 @@ man_fild01,315,95,3 script Expedition Scout#1 707,{ } else { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "I'm doing my best, but I haven't found any pages yet."; @@ -10633,7 +10633,7 @@ man_fild03,202,251,3 script Expedition Scout#2 707,{ set .@ep13_search_lotto,rand(1,6); if (.@ep13_search_lotto == 4) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 5 pieces of paper that appear to be part of the report."; @@ -10648,7 +10648,7 @@ man_fild03,202,251,3 script Expedition Scout#2 707,{ } else if ((.@ep13_search_lotto == 1) || (.@ep13_search_lotto == 6)) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 2 piece of paper that appear to be part of the report."; @@ -10663,7 +10663,7 @@ man_fild03,202,251,3 script Expedition Scout#2 707,{ } else if (.@ep13_search_lotto == 3) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 3 pieces of paper that appear to be part of the report."; @@ -10678,7 +10678,7 @@ man_fild03,202,251,3 script Expedition Scout#2 707,{ } else { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "I'm doing my best, but I haven't found any pages yet."; @@ -10693,7 +10693,7 @@ man_fild03,202,251,3 script Expedition Scout#2 707,{ } else if (((ep13_1_edq == 71) || (ep13_1_edq == 72)) && ((.@ep13_search_control == 0) || (.@ep13_search_control == 1))) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Searching for lost pages was tougher then I expected. Please come back later when I'm finished making one round."; @@ -10703,7 +10703,7 @@ man_fild03,202,251,3 script Expedition Scout#2 707,{ set .@ep13_search_lotto,rand(1,6); if (.@ep13_search_lotto == 4) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 5 pieces of paper that appear to be part of the report."; @@ -10717,7 +10717,7 @@ man_fild03,202,251,3 script Expedition Scout#2 707,{ } else if ((.@ep13_search_lotto == 1) || (.@ep13_search_lotto == 6)) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 2 pieces of paper that appear to be part of the report."; @@ -10731,7 +10731,7 @@ man_fild03,202,251,3 script Expedition Scout#2 707,{ } else if (.@ep13_search_lotto == 3) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 3 pieces of paper that appear to be part of the report."; @@ -10745,7 +10745,7 @@ man_fild03,202,251,3 script Expedition Scout#2 707,{ } else { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "I'm doing my best, but I haven't found any pages yet."; @@ -10798,7 +10798,7 @@ spl_fild02,295,368,3 script Expedition Scout#3 707,{ set .@ep13_search_lotto,rand(1,6); if (.@ep13_search_lotto == 4) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 5 pieces of paper that appear to be part of the report."; @@ -10813,7 +10813,7 @@ spl_fild02,295,368,3 script Expedition Scout#3 707,{ } else if ((.@ep13_search_lotto == 1) || (.@ep13_search_lotto == 6)) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 2 pieces of paper that appear to be part of the report."; @@ -10828,7 +10828,7 @@ spl_fild02,295,368,3 script Expedition Scout#3 707,{ } else if (.@ep13_search_lotto == 3) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 3 pieces of paper that appear to be part of the report."; @@ -10843,7 +10843,7 @@ spl_fild02,295,368,3 script Expedition Scout#3 707,{ } else { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "I'm doing my best, but I haven't found any pages yet."; @@ -10858,7 +10858,7 @@ spl_fild02,295,368,3 script Expedition Scout#3 707,{ } else if (((ep13_1_edq == 71) || (ep13_1_edq == 72)) && ((.@ep13_search_control == 0) || (.@ep13_search_control == 1))) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Searching for lost pages was tougher then I expected. Please come back later when I'm finished making one round."; @@ -10868,7 +10868,7 @@ spl_fild02,295,368,3 script Expedition Scout#3 707,{ set .@ep13_search_lotto,rand(1,6); if (.@ep13_search_lotto == 4) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 5 pieces of paper that appear to be part of the report."; @@ -10882,7 +10882,7 @@ spl_fild02,295,368,3 script Expedition Scout#3 707,{ } else if ((.@ep13_search_lotto == 1) || (.@ep13_search_lotto == 6)) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 2 piece of paper that appear to be part of the report."; @@ -10896,7 +10896,7 @@ spl_fild02,295,368,3 script Expedition Scout#3 707,{ } else if (.@ep13_search_lotto == 3) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 3 pieces of paper that appear to be part of the report."; @@ -10910,7 +10910,7 @@ spl_fild02,295,368,3 script Expedition Scout#3 707,{ } else { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "I'm doing my best, but I haven't found any pages yet."; @@ -10973,7 +10973,7 @@ spl_fild03,172,71,3 script Expedition Scout#4 707,{ set .@ep13_search_lotto,rand(1,6); if (.@ep13_search_lotto == 4) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 5 pieces of paper that appear to be part of the report."; @@ -10988,7 +10988,7 @@ spl_fild03,172,71,3 script Expedition Scout#4 707,{ } else if ((.@ep13_search_lotto == 1) || (.@ep13_search_lotto == 6)) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 2 pieces of paper that appear to be part of the report."; @@ -11003,7 +11003,7 @@ spl_fild03,172,71,3 script Expedition Scout#4 707,{ } else if (.@ep13_search_lotto == 3) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 3 pieces of paper that appear to be part of the report."; @@ -11018,7 +11018,7 @@ spl_fild03,172,71,3 script Expedition Scout#4 707,{ } else { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "I'm doing my best, but I haven't found any pages yet."; @@ -11033,7 +11033,7 @@ spl_fild03,172,71,3 script Expedition Scout#4 707,{ } else if (((ep13_1_edq == 71) || (ep13_1_edq == 72)) && ((.@ep13_search_control == 0) || (.@ep13_search_control == 1))) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Searching for lost pages was tougher then I expected. Please come back later when I'm finished making one round."; @@ -11043,7 +11043,7 @@ spl_fild03,172,71,3 script Expedition Scout#4 707,{ set .@ep13_search_lotto,rand(1,6); if (.@ep13_search_lotto == 4) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 5 pieces of paper that appear to be part of the report."; @@ -11057,7 +11057,7 @@ spl_fild03,172,71,3 script Expedition Scout#4 707,{ } else if ((.@ep13_search_lotto == 1) || (.@ep13_search_lotto == 6)) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 2 pieces of paper that appear to be part of the report."; @@ -11071,7 +11071,7 @@ spl_fild03,172,71,3 script Expedition Scout#4 707,{ } else if (.@ep13_search_lotto == 3) { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "Good news! I've found 3 pieces of paper that appear to be part of the report."; @@ -11085,7 +11085,7 @@ spl_fild03,172,71,3 script Expedition Scout#4 707,{ } else { mes "[Expedition Scout]"; - mes "Oh, you must be" + strcharinfo(0) + ". I heard that you'll be delivering the report."; + mes "Oh, you must be " + strcharinfo(0) + ". I heard that you'll be delivering the report."; next; mes "[Expedition Scout]"; mes "I'm doing my best, but I haven't found any pages yet."; diff --git a/src/map/script.c b/src/map/script.c index b36d86111..d58e3780e 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -728,7 +728,7 @@ const char* skip_space(const char* p) } /// Skips a word. -/// A word consists of undercores and/or alfanumeric characters, +/// A word consists of undercores and/or alphanumeric characters, /// and valid variable prefixes/postfixes. static const char* skip_word(const char* p) @@ -771,7 +771,7 @@ int add_word(const char* p) // Check for a word len = skip_word(p) - p; if( len == 0 ) - disp_error_message("script:add_word: invalid word. A word consists of undercores and/or alfanumeric characters, and valid variable prefixes/postfixes.", p); + disp_error_message("script:add_word: invalid word. A word consists of undercores and/or alphanumeric characters, and valid variable prefixes/postfixes.", p); // Duplicate the word word = (char*)aMalloc(len+1); @@ -809,7 +809,7 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) add_scriptl(func); arg = script->buildin[script->str_data[buildin_callsub_ref].val]; if( *arg == 0 ) - disp_error_message("parse_callfunc: callsub has no arguments, please review it's definition",p); + disp_error_message("parse_callfunc: callsub has no arguments, please review its definition",p); if( *arg != '*' ) ++arg; // count func as argument } else { @@ -1049,7 +1049,7 @@ const char* parse_simpleexpr(const char *p) p=skip_space(p); if(*p==';' || *p==',') - disp_error_message("parse_simpleexpr: unexpected expr end",p); + disp_error_message("parse_simpleexpr: unexpected end of expression",p); if(*p=='('){ if( (i=syntax.curly_count-1) >= 0 && syntax.curly[i].type == TYPE_ARGLIST ) ++syntax.curly[i].count; @@ -1065,7 +1065,7 @@ const char* parse_simpleexpr(const char *p) syntax.curly[i].flag = ARGLIST_NO_PAREN; } if( *p != ')' ) - disp_error_message("parse_simpleexpr: unmatch ')'",p); + disp_error_message("parse_simpleexpr: unmatched ')'",p); ++p; } else if(ISDIGIT(*p) || ((*p=='-' || *p=='+') && ISDIGIT(p[1]))){ char *np; @@ -1091,7 +1091,7 @@ const char* parse_simpleexpr(const char *p) add_scriptb(*p++); } if(!*p) - disp_error_message("parse_simpleexpr: unexpected eof @ string",p); + disp_error_message("parse_simpleexpr: unexpected end of file @ string",p); add_scriptb(0); p++; //'"' } else { @@ -1129,7 +1129,7 @@ const char* parse_simpleexpr(const char *p) p=parse_subexpr(p+1,-1); p=skip_space(p); if( *p != ']' ) - disp_error_message("parse_simpleexpr: unmatch ']'",p); + disp_error_message("parse_simpleexpr: unmatched ']'",p); ++p; add_scriptc(C_FUNC); }else @@ -1330,8 +1330,8 @@ const char* parse_curly_close(const char* p) } // Syntax-related processing -// break, case, continue, default, do, for, function, -// if, switch, while ? will handle this internally. +// break, case, continue, default, do, for, function, +// if, switch, while ? will handle this internally. const char* parse_syntax(const char* p) { const char *p2 = skip_word(p); @@ -1411,14 +1411,14 @@ const char* parse_syntax(const char* p) memcpy(label,p,v); label[v]='\0'; if( !script_get_constant(label, &v) ) - disp_error_message("parse_syntax: 'case' label not integer",p); + disp_error_message("parse_syntax: 'case' label is not an integer",p); p = skip_word(p); } else { //Numeric value if((*p == '-' || *p == '+') && ISDIGIT(p[1])) // pre-skip because '-' can not skip_word p++; p = skip_word(p); if(np != p) - disp_error_message("parse_syntax: 'case' label not integer",np); + disp_error_message("parse_syntax: 'case' label is not an integer",np); } p = skip_space(p); if(*p != ':') @@ -14007,7 +14007,7 @@ BUILDIN(setnpcdisplay) class_ = script->conv_num(st,data); else { - ShowError("script:setnpcdisplay: expected a string or number\n"); + ShowError("script:setnpcdisplay: expected string or number\n"); script_reportdata(data); return false; } -- cgit v1.2.3-70-g09d2 From 0395610469ffcd3b71c93ef90861f73e0ab8d16f Mon Sep 17 00:00:00 2001 From: malufett Date: Thu, 13 Jun 2013 01:56:21 +0800 Subject: Hercules Renewal Phase : Renewal Rename SC names to eagis standard. Implement SC Configuration.(see db/sc_config.txt) Skill updates and fixes. Some code optimization. Signed-off-by: malufett --- conf/battle/status.conf | 9 - conf/messages.conf | 3 - db/item_db2.txt | 8 +- db/item_delay.txt | 14 +- db/job_db2.txt | 9 +- db/pre-re/item_db.txt | 332 +- db/pre-re/skill_cast_db.txt | 140 +- db/pre-re/skill_db.txt | 145 +- db/pre-re/skill_require_db.txt | 20 + db/pre-re/skill_tree.txt | 99 + db/pre-re/skill_unit_db.txt | 11 +- db/re/item_combo_db.txt | 2 +- db/re/item_db.txt | 336 +- db/re/refine_db.txt | 7 +- db/re/skill_cast_db.txt | 91 +- db/re/skill_db.txt | 90 +- db/re/skill_require_db.txt | 24 +- db/re/skill_tree.txt | 99 + db/re/skill_unit_db.txt | 21 +- db/sc_config.txt | 407 ++ doc/script_commands.txt | 7 +- npc/cities/rachel.txt | 4 +- npc/custom/healer.txt | 2 +- npc/events/halloween_2009.txt | 42 +- npc/events/nguild/nguild_warper.txt | 6 +- npc/instances/NydhoggsNest.txt | 2 +- npc/mobs/citycleaners.txt | 2 + npc/quests/skills/assassin_skills.txt | 4 +- npc/re/cities/dewata.txt | 12 +- npc/re/jobs/3-1/rune_knight.txt | 4 +- npc/re/quests/quests_brasilis.txt | 22 +- src/char/char.c | 2 + src/common/mmo.h | 2 +- src/config/const.h | 4 +- src/map/atcommand.c | 8 +- src/map/battle.c | 7521 +++++++++++++------------- src/map/battle.h | 22 +- src/map/clif.c | 181 +- src/map/clif.h | 12 +- src/map/itemdb.h | 3 + src/map/map.c | 58 +- src/map/mercenary.c | 2 +- src/map/mob.c | 10 +- src/map/packets.h | 1 + src/map/party.c | 2 +- src/map/pc.c | 258 +- src/map/pc.h | 18 +- src/map/script.c | 4 +- src/map/skill.c | 9261 ++++++++++++++++----------------- src/map/skill.h | 25 +- src/map/status.c | 2787 +++++----- src/map/status.h | 770 +-- src/map/unit.c | 63 +- src/map/vending.c | 2 +- 54 files changed, 12206 insertions(+), 10784 deletions(-) create mode 100644 db/sc_config.txt (limited to 'npc') diff --git a/conf/battle/status.conf b/conf/battle/status.conf index 5341b606b..372619fd1 100644 --- a/conf/battle/status.conf +++ b/conf/battle/status.conf @@ -12,15 +12,6 @@ // Should skill casting be cancelled when inflicted by curse/stun/sleep/etc (includes silence) (Note 3)? status_cast_cancel: 0 -// Will certain skill status-changes be removed on logout? -// This mimics official servers, where Extremity Fist's no SP regen, -// Strip Equipment, and some other buffs are removed when you logout. Setting is: -// 0 = remove nothing. -// 1 = remove negative buffs (stripping, EF) -// 2 = remove positive buffs (maximize power, steel body...) -// 3 = remove both negative and positive buffs. -debuff_on_logout: 3 - // Adjustment for the natural rate of resistance from status changes. // If 50, status defense is halved, and you need twice as much stats to block // them (eg: 200 vit to completely block stun) diff --git a/conf/messages.conf b/conf/messages.conf index 5bff9a5af..e2886a57d 100644 --- a/conf/messages.conf +++ b/conf/messages.conf @@ -1505,8 +1505,5 @@ //src/map/pc.c::pc_isUseitem 1474: You cannot use this item while sitting -//src/map/clif.c::clif_parse_NpcClicked -1476: You cannot interact with NPCs while casting skills - //Custom translations import: conf/import/msg_conf.txt diff --git a/db/item_db2.txt b/db/item_db2.txt index 5ca7a825a..fe5a53d46 100644 --- a/db/item_db2.txt +++ b/db/item_db2.txt @@ -27,14 +27,14 @@ //5356,Pumpkin_Hat_H,Pumpkin Hat,5,20,,200,,2,,0,0xFFFFFFFF,7,2,256,,0,1,206,{ bonus bAllStats,2; bonus2 bSubRace,RC_Demon,5; bonus2 bMagicAddRace,RC_Demon,5; },{},{} //5811,Santa_Beard,Santa Beard,5,20,,100,,5,,0,0xFFFFFFFF,7,2,1,,0,0,25,{ bonus2 bSubRace,RC_Brute,5; },{},{} -//11702,Moon_Cookie,Moon Cookie,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; itemskill "AL_BLESSING",7; },{},{} -//12131,Lucky_Potion,Lucky Potion,0,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFood,180000,15; },{},{} +//11702,Moon_Cookie,Moon Cookie,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; itemskill "AL_BLESSING",7; },{},{} +//12131,Lucky_Potion,Lucky Potion,0,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,180000,15; },{},{} //12143,Red_Can,Red Can,2,50000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 25,25; },{},{} //Event effect: Summon monster? Probably Rice_Cake. x_x //12199,Rice_Scroll,Rice Scroll,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} //12200,Event_Cake,Event Cake,2,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "PR_MAGNIFICAT",3; },{},{} -//12238,New_Year_Rice_Cake_1,New Year Rice Cake,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 20,15; sc_start SC_STRFood,1200000,3; sc_start SC_INTFood,1200000,3; sc_start SC_LUKFood,1200000,3; sc_start SC_SpeedUp1,5000,0; },{},{} -//12239,New_Year_Rice_Cake_2,New Year Rice Cake,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 20,15; sc_start SC_DEXFood,1200000,3; sc_start SC_AGIFood,1200000,3; sc_start SC_VITFood,1200000,3; sc_start SC_SpeedUp1,5000,0; },{},{} +//12238,New_Year_Rice_Cake_1,New Year Rice Cake,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 20,15; sc_start SC_FOOD_STR,1200000,3; sc_start SC_FOOD_INT,1200000,3; sc_start SC_FOOD_LUK,1200000,3; sc_start SC_MOVHASTE_INFINITY,5000,0; },{},{} +//12239,New_Year_Rice_Cake_2,New Year Rice Cake,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 20,15; sc_start SC_FOOD_DEX,1200000,3; sc_start SC_FOOD_AGI,1200000,3; sc_start SC_FOOD_VIT,1200000,3; sc_start SC_MOVHASTE_INFINITY,5000,0; },{},{} // iRO St. Patrick's Day Event 2008 //============================================================= diff --git a/db/item_delay.txt b/db/item_delay.txt index ec9d9c020..afcb56f9e 100644 --- a/db/item_delay.txt +++ b/db/item_delay.txt @@ -21,4 +21,16 @@ 11522,1000 // Red_Raffle_Sap 11523,2000 // Yellow_Raffle_Sap 11524,3000 // White_Raffle_Sap -11525,5000 // Mora_Hip_Tea \ No newline at end of file +11525,5000 // Mora_Hip_Tea + +12622,3000 // Reins_Of_Mount + +//12580,0 // Vending_Search_Scroll +//12581,0 // Vending_Search_Scroll2 +//12591,0 // Vending_Search_Scroll3 + +12725,120000 // Runstone_Nosiege,Nauthiz Rune +12726,30000 // Runstone_Rhydo,Raido Rune +12727,60000 // Runstone_Verkana,Berkana Rune +12732,1000 // Runstone_Pertz,Wyrd Rune + diff --git a/db/job_db2.txt b/db/job_db2.txt index 1880808fa..a36cc3d88 100644 --- a/db/job_db2.txt +++ b/db/job_db2.txt @@ -212,7 +212,7 @@ // Sura (Regular) 4070,2,5,0,1,1,0,0,0,1,2,5,0,0,3,3,1,0,0,3,1,0,0,2,2,5,0,0,4,4,1,3,0,0,0,2,5,5,0,0,0,4,3,2,2,0,0,0,4,5,5 // Genetic (Regular) -4071,4,4,5,0,0,5,4,2,0,0,0,4,5,3,0,0,0,3,5,2,0,0,4,3,3,0,0,5,2,0,6,0,0,1,4,4,0,0,5,2,4,0,0,4,4,0,2,0,0,4 +4071,4,4,5,0,0,5,4,2,0,0,0,4,5,0,0,0,0,3,5,2,0,0,4,3,3,0,0,5,2,0,6,0,0,0,4,4,1,0,5,2,4,0,0,4,4,0,2,0,0,4 // Shadow Chaser (Regular) 4072,6,1,0,0,1,0,6,2,5,4,0,0,4,6,0,0,2,0,3,3,4,5,0,0,3,6,0,0,3,0,1,1,3,6,0,0,4,4,0,0,0,3,3,1,1,0,0,5,2,0 // Royal Guard (Trans) @@ -226,7 +226,7 @@ // Sura (Trans) 4077,2,5,0,1,1,0,0,0,1,2,5,0,0,3,3,1,0,0,3,1,0,0,2,2,5,0,0,4,4,1,3,0,0,0,2,5,5,0,0,0,4,3,2,2,0,0,0,4,5,5 // Genetic (Trans) -4078,4,4,5,0,0,5,4,2,0,0,0,4,5,3,0,0,0,3,5,2,0,0,4,3,3,0,0,5,2,0,6,0,0,1,4,4,0,0,5,2,4,0,0,4,4,0,2,0,0,4 +4078,4,4,5,0,0,5,4,2,0,0,0,4,5,0,0,0,0,3,5,2,0,0,4,3,3,0,0,5,2,0,6,0,0,0,4,4,1,0,5,2,4,0,0,4,4,0,2,0,0,4 // Shadow Chaser (Trans) 4079,6,1,0,0,1,0,6,2,5,4,0,0,4,6,0,0,2,0,3,3,4,5,0,0,3,6,0,0,3,0,1,1,3,6,0,0,4,4,0,0,0,3,3,1,1,0,0,5,2,0 // Rune Knight (Dragon) (Regular) @@ -268,7 +268,7 @@ // Baby Sura 4106,2,5,0,1,1,0,0,0,1,2,5,0,0,3,3,1,0,0,3,1,0,0,2,2,5,0,0,4,4,1,3,0,0,0,2,5,5,0,0,0,4,3,2,2,0,0,0,4,5,5 // Baby Genetic -4107,4,4,5,0,0,5,4,2,0,0,0,4,5,3,0,0,0,3,5,2,0,0,4,3,3,0,0,5,2,0,6,0,0,1,4,4,0,0,5,2,4,0,0,4,4,0,2,0,0,4 +4107,4,4,5,0,0,5,4,2,0,0,0,4,5,0,0,0,0,3,5,2,0,0,4,3,3,0,0,5,2,0,6,0,0,0,4,4,1,0,5,2,4,0,0,4,4,0,2,0,0,4 // Baby Shadow Chaser 4108,6,1,0,0,1,0,6,2,5,4,0,0,4,6,0,0,2,0,3,3,4,5,0,0,3,6,0,0,3,0,1,1,3,6,0,0,4,4,0,0,0,3,3,1,1,0,0,5,2,0 // Baby Rune Knight (Dragon) @@ -283,8 +283,7 @@ 4190,1,2,0,3,0,4,5,0,6,0,1,2,0,3,0,4,5,0,6,0,1,2,0,3,0,4,5,0,6,0,1,2,0,3,0,4,5,0,6,0,1,2,0,3,0,4,5,0,6,0 // Super Baby (Expanded) 4191,1,2,0,3,0,4,5,0,6,0,1,2,0,3,0,4,5,0,6,0,1,2,0,3,0,4,5,0,6,0,1,2,0,3,0,4,5,0,6,0,1,2,0,3,0,4,5,0,6,0 -// Note: Kagerou and Oboro will temporarly use Ninja stat bonuses until official ones are known. // Kagerou 4211,5,0,4,0,2,3,0,1,6,0,5,1,2,0,4,6,3,0,1,5,2,0,6,3,4,0,5,0,2,0,1,4,0,5,4,0,3,5,1,0,2,4,1,0,5,6,2,1,0,5 // Oboro -4212,5,0,4,0,2,3,0,1,6,0,5,1,2,0,4,6,3,0,1,5,2,0,6,3,4,0,5,0,2,0,1,4,0,5,4,0,3,5,1,0,2,4,1,0,5,6,2,1,0,5 \ No newline at end of file +4212,5,0,4,0,2,3,0,1,6,0,5,1,2,0,4,6,3,0,1,5,2,0,6,3,4,0,5,0,2,0,1,4,0,5,4,0,3,5,1,0,2,4,1,0,5,6,2,1,0,5 diff --git a/db/pre-re/item_db.txt b/db/pre-re/item_db.txt index 501e657cc..f632e582a 100644 --- a/db/pre-re/item_db.txt +++ b/db/pre-re/item_db.txt @@ -28,8 +28,8 @@ 521,Leaflet_Of_Aloe,Aloe Leaflet,0,360,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),0; },{},{} 522,Fruit_Of_Mastela,Mastela Fruit,0,8500,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(400,600),0; },{},{} 523,Holy_Water,Holy Water,0,20,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_Curse; },{},{} -525,Panacea,Panacea,0,500,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} -526,Royal_Jelly,Royal Jelly,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} +525,Panacea,Panacea,0,500,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} +526,Royal_Jelly,Royal Jelly,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} 528,Monster's_Feed,Monster's Feed,0,60,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(72,108),0; },{},{} 529,Candy,Candy,0,10,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(45,65),0; },{},{} 530,Candy_Striper,Candy Cane,0,20,,40,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(105,145),0; },{},{} @@ -68,14 +68,14 @@ 563,Pizza_01,Doublecrust Swiss Fondue,0,1200,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(375,445),0; },{},{} 564,Rice_Ball,Rice Ball,0,1,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal 200,0; },{},{} 565,Vita500_Bottle,Vita500,0,580,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(142,274),0; },{},{} -566,Tomyumkung,Tom Yum Goong,0,10000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(244,350),rand(10,30); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} +566,Tomyumkung,Tom Yum Goong,0,10000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(244,350),rand(10,30); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} 567,Prawn,Shrimp,0,500,,40,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(117,192),0; },{},{} 568,Lemon,Lemon,0,60,,40,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal 0,rand(10,20); },{},{} 569,Novice_Potion,Novice Potion,0,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(22,33),0; },{},{} 570,Lucky_Candy,Lucky Candy,0,10,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(45,65),0; },{},{} 571,Lucky_Candy_Cane,Lucky Candy Cane,0,20,,40,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(105,145),0; },{},{} 572,Lucky_Cookie,Lucky Cookie,0,1000,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(160,200),0; },{},{} -573,Chocolate_Drink,Chocolate Drink,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(330,410),rand(45,65); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} +573,Chocolate_Drink,Chocolate Drink,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(330,410),rand(45,65); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} 574,Egg,Egg,0,20,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(33,42),0; },{},{} 575,Piece_Of_Cake_,2nd Anniversary Cake,0,10,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(270,330),0; },{},{} 576,Prickly_Fruit,Prickly Fruit,0,540,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(150,300),rand(20,30); },{},{} @@ -85,7 +85,7 @@ 580,Bread,Bread,0,150,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(50,90),0; },{},{} 581,Mushroom,Edible Mushroom,0,40,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(20,30),0; },{},{} 582,Orange,Orange,0,300,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(10,20),rand(10,20); },{},{} -583,KETUPAT_,Ketupat Sayur,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} +583,KETUPAT_,Ketupat Sayur,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} 584,Fish_Ball_Soup,Fish Cake Soup,0,100,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(40,70),0; },{},{} 585,Wurst,Brusti,0,2,,40,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(15,20),0; },{},{} 586,Mother's_Cake,Mother's Cake,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),0; },{},{} @@ -93,11 +93,11 @@ 588,Spaghetti,Spaghetti,0,100,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(40,70),0; },{},{} 589,Pizza_02,Pizza,0,1200,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(375,445),0; },{},{} 590,Brezel_,Pretzel,0,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(50,90),0; },{},{} -591,Caviar_Pancake,Caviar Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} -592,Jam_Pancake,Jam Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} -593,Honey_Pancake,Honey Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} -594,Sour_Cream_Pancake,Sour-Cream Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} -595,Mushroom_Pancake,Mushroom Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} +591,Caviar_Pancake,Caviar Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} +592,Jam_Pancake,Jam Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} +593,Honey_Pancake,Honey Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} +594,Sour_Cream_Pancake,Sour-Cream Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} +595,Mushroom_Pancake,Mushroom Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} 596,Cute_Strawberry_Choco,Cute Strawberry-Choco,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal 0,rand(1,100); },{},{} 597,Lovely_Choco_Tart,Lovely Choco-Tart,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(10,400),0; },{},{} 598,Light_Red_Pot,Light Red Potion,0,50,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(45,65),0; },{},{} @@ -148,14 +148,14 @@ 642,Book_Of_Devil,Book of the Devil,2,1800,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1101; },{},{} 643,Pet_Incubator,Pet Incubator,2,3000,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ bpet; },{},{} 644,Gift_Box,Gift Box,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_GiftBox),1; },{},{} -645,Center_Potion,Concentration Potion,2,800,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ASPDPOTION0,1800000,0; },{},{} -656,Awakening_Potion,Awakening Potion,2,1500,,150,,,,,0xFFF7FEEF,7,2,,,40,,,{ sc_start SC_ASPDPOTION1,1800000,0; },{},{} -657,Berserk_Potion,Berserk Potion,2,3000,,200,,,,,0x01E646A6,7,2,,,85,,,{ sc_start SC_ASPDPOTION2,1800000,0; },{},{} +645,Center_Potion,Concentration Potion,2,800,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATTHASTE_POTION1,1800000,0; },{},{} +656,Awakening_Potion,Awakening Potion,2,1500,,150,,,,,0xFFF7FEEF,7,2,,,40,,,{ sc_start SC_ATTHASTE_POTION2,1800000,0; },{},{} +657,Berserk_Potion,Berserk Potion,2,3000,,200,,,,,0x01E646A6,7,2,,,85,,,{ sc_start SC_ATTHASTE_POTION3,1800000,0; },{},{} 658,Union_Of_Tribe,Union of Tribe,2,2,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ guildgetexp rand(600000,1200000); },{},{} 659,Heart_Of_Her,Her Heart,2,500,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1188; },{},{} 660,Prohibition_Red_Candle,Forbidden Red Candle,2,20000,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1200; },{},{} 661,Sway_Apron,Soft Apron,2,20000,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1275; },{},{} -662,Inspector_Certificate,Authoritative Badge,2,1450,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,180000,0; },{},{} +662,Inspector_Certificate,Authoritative Badge,2,1450,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,180000,0; },{},{} 663,Korea_Rice_Cake,Korean Rice Cake,0,1,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 10,0; },{},{} 664,Gift_Box_1,Gift Box,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_GiftBox_1),1; },{},{} 665,Gift_Box_2,Gift Box,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_GiftBox_2),1; },{},{} @@ -171,13 +171,13 @@ 675,Silver_Coin,Silver Coin,3,5000,,40,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 676,Silver_Coin_Moneybag,Bag of Silver Coins,3,50000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 677,White_Gold_Coin,Platinum Coin,3,2000,,40,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -678,Poison_Bottle,Poison Bottle,2,5000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ if(Class==Job_Assassin_Cross) { sc_start SC_DPoison,60000,0; sc_start SC_ASPDPOTION3,60000,0; } else percentheal -100,-100; },{},{} +678,Poison_Bottle,Poison Bottle,2,5000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ if(Class==Job_Assassin_Cross) { sc_start SC_DPoison,60000,0; sc_start SC_ATTHASTE_INFINITY,60000,0; } else percentheal -100,-100; },{},{} 679,Gold_Pill,Pilule,2,5000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ if(rand(1000)<100) sc_start SC_DPoison,10000,0; sc_start SC_Poison,50000,0; },{},{} 680,Magical_Carnation,Magic Carnation,0,0,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,20; },{},{} 681,Memory_Of_Wedding,Sweet Memory of Marriage,2,50000,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if(getpartnerid()) sc_start SC_WEDDING,600000,0; },{},{} -682,Realgar_Wine,Distilled Fighting Spirit,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,60000,30; },{},{} -683,Exorcize_Herb,Herb of Incantation,2,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MATKPOTION,60000,30; },{},{} -684,Durian,Durian,2,15000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,60000,10; sc_start SC_MATKPOTION,60000,10; },{},{} +682,Realgar_Wine,Distilled Fighting Spirit,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,60000,30; },{},{} +683,Exorcize_Herb,Herb of Incantation,2,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSMAGICPOWER,60000,30; },{},{} +684,Durian,Durian,2,15000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,60000,10; sc_start SC_PLUSMAGICPOWER,60000,10; },{},{} 685,RAMADAN,Ramadan,0,5000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,50; },{},{} 686,Earth_Scroll_1_3,Level 3 Earth Spike,11,1000,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_EARTHSPIKE",3; },{},{} 687,Earth_Scroll_1_5,Level 5 Earth Spike,11,2000,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_EARTHSPIKE",5; },{},{} @@ -4560,7 +4560,7 @@ 12013,Shadow_Arrow_Container,Shadow Arrow Quiver,2,2,,250,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 1767,500; },{},{} 12014,Imma_Arrow_Container,Immaterial Arrow Quiver,2,2,,250,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 1757,500; },{},{} 12015,Rusty_Arrow_Container,Rusty Arrow Quiver,2,2,,250,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 1762,500; },{},{} -12016,Speed_Up_Potion,Speed Potion,2,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp1,5000,0; },{},{} +12016,Speed_Up_Potion,Speed Potion,2,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_INFINITY,5000,0; },{},{} 12017,Slow_Down_Potion,Slow Potion,2,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SlowDown,5000,0; },{},{} 12018,Fire_Cracker,Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} 12019,Holy_Egg,Holy Egg,11,2,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "ALL_RESURRECTION",2; },{},{} @@ -4572,10 +4572,10 @@ 12025,Egg_Boy,Dano Festival Egg,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_EggBoy),1; },{},{} 12026,Egg_Girl,Dano Festival Egg,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_EggGirl),1; },{},{} 12027,Giggling_Box,Giggling Box,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 9,0; if(rand(1000)<300) sc_start SC_Curse,30000,0; },{},{} -12028,Box_Of_Thunder,Box of Thunder,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,20000,0; },{},{} +12028,Box_Of_Thunder,Box of Thunder,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,20000,0; },{},{} 12029,Gloomy_Box,Box of Gloom,11,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "AC_CONCENTRATION",1; },{},{} -12030,Box_Of_Grudge,Box of Resentment,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,60000,20; },{},{} -12031,Sleepy_Box,Box of Drowsiness,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MATKPOTION,60000,20; },{},{} +12030,Box_Of_Grudge,Box of Resentment,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,60000,20; },{},{} +12031,Sleepy_Box,Box of Drowsiness,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSMAGICPOWER,60000,20; },{},{} 12032,Box_Of_Storm,Box of Storms,11,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "ITEM_ENCHANTARMS",2; },{},{} 12033,Box_Of_Sunlight,Box of Sunlight,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_Intravision,30000,0; },{},{} 12034,Painting_Box,Box of Panting,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,9; if(rand(1000)<300) sc_start SC_Silence,30000,0; },{},{} @@ -4585,66 +4585,66 @@ 12038,Lotto_Box04,Lotto Box 04,2,0,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_LottoBox),1; },{},{} 12039,Lotto_Box05,Lotto Box 05,2,0,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem rand(7542,7546),1; },{},{} 12040,Stone_Of_Intelligence_,Stone of Sage,2,100000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ homevolution; },{},{} -12041,Str_Dish01,Fried Grasshopper Legs,0,2000,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,1; percentheal 5,0; },{},{} -12042,Str_Dish02,Seasoned Sticky Webfoot,0,4000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,2; percentheal 5,0; },{},{} -12043,Str_Dish03,Bomber Steak,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,3; percentheal 5,0; },{},{} -12044,Str_Dish04,Herb Marinade Beef,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,4; percentheal 5,0; },{},{} -12045,Str_Dish05,Lutie Lady's Pancake,0,10000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,5; percentheal 10,0; },{},{} -12046,Int_Dish01,Grape Juice Herbal Tea,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,1; percentheal 0,5; },{},{} -12047,Int_Dish02,Autumn Red Tea,0,4000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,2; percentheal 0,5; },{},{} -12048,Int_Dish03,Honey Herbal Tea,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,3; percentheal 0,5; },{},{} -12049,Int_Dish04,Morroc Fruit Wine,0,8000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,4; percentheal 0,5; },{},{} -12050,Int_Dish05,Mastela Fruit Wine,0,10000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,5; percentheal 0,10; },{},{} -12051,Vit_Dish01,Steamed Crab Nippers,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,1; percentheal 5,0; },{},{} -12052,Vit_Dish02,Assorted Seafood,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,2; percentheal 5,0; },{},{} -12053,Vit_Dish03,Clam Soup,0,6000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,3; percentheal 5,0; },{},{} -12054,Vit_Dish04,Seasoned Jellyfish,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,4; percentheal 5,0; },{},{} -12055,Vit_Dish05,Spicy Fried Bao,0,10000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,5; percentheal 10,0; },{},{} -12056,Agi_Dish01,Frog Egg Squid Ink Soup,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,1; percentheal 3,1; },{},{} -12057,Agi_Dish02,Smooth Noodle,0,4000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,2; percentheal 3,1; },{},{} -12058,Agi_Dish03,Tentacle Cheese Gratin,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,3; percentheal 3,1; },{},{} -12059,Agi_Dish04,Lutie Cold Noodle,0,8000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,4; percentheal 3,1; },{},{} -12060,Agi_Dish05,Steamed Bat Wing in Pumpkin,0,10000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,5; percentheal 6,2; },{},{} -12061,Dex_Dish01,Honey Grape Juice,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,1; percentheal 2,2; },{},{} -12062,Dex_Dish02,Chocolate Mousse Cake,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,2; percentheal 2,2; },{},{} -12063,Dex_Dish03,Fruit Mix,0,6000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,3; percentheal 2,2; },{},{} -12064,Dex_Dish04,Cream Sandwich,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,4; percentheal 2,2; },{},{} -12065,Dex_Dish05,Green Salad,0,10000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,5; percentheal 5,5; },{},{} -12066,Luk_Dish01,Fried Monkey Tails,0,2000,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,1; percentheal 3,2; },{},{} -12067,Luk_Dish02,Mixed Juice,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,2; percentheal 3,2; },{},{} -12068,Luk_Dish03,Fried Sweet Potato,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,3; percentheal 4,2; },{},{} -12069,Luk_Dish04,Steamed Ancient Lips,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,4; percentheal 4,2; },{},{} -12070,Luk_Dish05,Fried Scorpion Tails,0,10000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,5; percentheal 5,2; },{},{} -12071,Str_Dish06,Shiny Marinade Beef,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,6; percentheal 10,2; },{},{} -12072,Str_Dish07,Whole Roast,0,40000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,7; percentheal 10,4; },{},{} -12073,Str_Dish08,Bearfoot Special,0,60000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,8; percentheal 15,6; },{},{} -12074,Str_Dish09,Tendon Satay,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,9; percentheal 15,8; },{},{} -12075,Str_Dish10,Steamed Tongue,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,10; percentheal 20,20; },{},{} -12076,Int_Dish06,Red Mushroom Wine,0,20000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,6; percentheal 2,10; },{},{} -12077,Int_Dish07,Special Royal Jelly Herbal Tea,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,7; percentheal 4,10; },{},{} -12078,Int_Dish08,Royal Family Tea,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,8; percentheal 6,10; },{},{} -12079,Int_Dish09,Tristan XII,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,9; percentheal 8,15; },{},{} -12080,Int_Dish10,Dragon Breath Cocktail,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,10; percentheal 10,20; },{},{} -12081,Vit_Dish06,Awfully Bitter Bracer,0,20000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,6; percentheal 13,0; },{},{} -12082,Vit_Dish07,Sumptuous Feast,0,40000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,7; percentheal 16,0; },{},{} -12083,Vit_Dish08,Giant Burito,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,8; percentheal 19,0; },{},{} -12084,Vit_Dish09,Ascending Dragon Soup,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,9; percentheal 22,0; },{},{} -12085,Vit_Dish10,Immortal Stew,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,10; percentheal 25,0; },{},{} -12086,Agi_Dish06,Chile Shrimp Gratin,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,6; percentheal 7,2; },{},{} -12087,Agi_Dish07,Steamed Alligator with Vegetable,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,7; percentheal 8,2; },{},{} -12088,Agi_Dish08,Incredibly Spicy Curry,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,8; percentheal 9,2; },{},{} -12089,Agi_Dish09,Special Meat Stew,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,9; percentheal 10,2; },{},{} -12090,Agi_Dish10,Steamed Desert Scorpions,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,10; percentheal 15,5; },{},{} -12091,Dex_Dish06,Peach Cake,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,6; percentheal 5,6; },{},{} -12092,Dex_Dish07,Soul Haunted Bread,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,7; percentheal 5,7; },{},{} -12093,Dex_Dish08,Special Toast,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,8; percentheal 5,8; },{},{} -12094,Dex_Dish09,Heavenly Fruit Juice,0,80000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,9; percentheal 5,9; },{},{} -12095,Dex_Dish10,Hwergelmir's Tonic,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,10; percentheal 10,10; },{},{} -12096,Luk_Dish06,Lucky Soup,0,20000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,6; percentheal 6,3; },{},{} -12097,Luk_Dish07,Assorted Shish Kebob,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,7; percentheal 7,3; },{},{} -12098,Luk_Dish08,Strawberry Flavored Rice Ball,0,60000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,8; percentheal 9,3; },{},{} -12099,Luk_Dish09,Blood Flavored Soda,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,9; percentheal 10,4; },{},{} -12100,Luk_Dish10,Cooked Nine Tail's Tails,0,100000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,10; percentheal 14,8; },{},{} +12041,Str_Dish01,Fried Grasshopper Legs,0,2000,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,1; percentheal 5,0; },{},{} +12042,Str_Dish02,Seasoned Sticky Webfoot,0,4000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,2; percentheal 5,0; },{},{} +12043,Str_Dish03,Bomber Steak,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,3; percentheal 5,0; },{},{} +12044,Str_Dish04,Herb Marinade Beef,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,4; percentheal 5,0; },{},{} +12045,Str_Dish05,Lutie Lady's Pancake,0,10000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,5; percentheal 10,0; },{},{} +12046,Int_Dish01,Grape Juice Herbal Tea,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,1; percentheal 0,5; },{},{} +12047,Int_Dish02,Autumn Red Tea,0,4000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,2; percentheal 0,5; },{},{} +12048,Int_Dish03,Honey Herbal Tea,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,3; percentheal 0,5; },{},{} +12049,Int_Dish04,Morroc Fruit Wine,0,8000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,4; percentheal 0,5; },{},{} +12050,Int_Dish05,Mastela Fruit Wine,0,10000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,5; percentheal 0,10; },{},{} +12051,Vit_Dish01,Steamed Crab Nippers,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,1; percentheal 5,0; },{},{} +12052,Vit_Dish02,Assorted Seafood,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,2; percentheal 5,0; },{},{} +12053,Vit_Dish03,Clam Soup,0,6000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,3; percentheal 5,0; },{},{} +12054,Vit_Dish04,Seasoned Jellyfish,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,4; percentheal 5,0; },{},{} +12055,Vit_Dish05,Spicy Fried Bao,0,10000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,5; percentheal 10,0; },{},{} +12056,Agi_Dish01,Frog Egg Squid Ink Soup,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,1; percentheal 3,1; },{},{} +12057,Agi_Dish02,Smooth Noodle,0,4000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,2; percentheal 3,1; },{},{} +12058,Agi_Dish03,Tentacle Cheese Gratin,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,3; percentheal 3,1; },{},{} +12059,Agi_Dish04,Lutie Cold Noodle,0,8000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,4; percentheal 3,1; },{},{} +12060,Agi_Dish05,Steamed Bat Wing in Pumpkin,0,10000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,5; percentheal 6,2; },{},{} +12061,Dex_Dish01,Honey Grape Juice,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,1; percentheal 2,2; },{},{} +12062,Dex_Dish02,Chocolate Mousse Cake,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,2; percentheal 2,2; },{},{} +12063,Dex_Dish03,Fruit Mix,0,6000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,3; percentheal 2,2; },{},{} +12064,Dex_Dish04,Cream Sandwich,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,4; percentheal 2,2; },{},{} +12065,Dex_Dish05,Green Salad,0,10000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,5; percentheal 5,5; },{},{} +12066,Luk_Dish01,Fried Monkey Tails,0,2000,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,1; percentheal 3,2; },{},{} +12067,Luk_Dish02,Mixed Juice,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,2; percentheal 3,2; },{},{} +12068,Luk_Dish03,Fried Sweet Potato,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,3; percentheal 4,2; },{},{} +12069,Luk_Dish04,Steamed Ancient Lips,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,4; percentheal 4,2; },{},{} +12070,Luk_Dish05,Fried Scorpion Tails,0,10000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,5; percentheal 5,2; },{},{} +12071,Str_Dish06,Shiny Marinade Beef,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,6; percentheal 10,2; },{},{} +12072,Str_Dish07,Whole Roast,0,40000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,7; percentheal 10,4; },{},{} +12073,Str_Dish08,Bearfoot Special,0,60000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,8; percentheal 15,6; },{},{} +12074,Str_Dish09,Tendon Satay,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,9; percentheal 15,8; },{},{} +12075,Str_Dish10,Steamed Tongue,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,10; percentheal 20,20; },{},{} +12076,Int_Dish06,Red Mushroom Wine,0,20000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,6; percentheal 2,10; },{},{} +12077,Int_Dish07,Special Royal Jelly Herbal Tea,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,7; percentheal 4,10; },{},{} +12078,Int_Dish08,Royal Family Tea,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,8; percentheal 6,10; },{},{} +12079,Int_Dish09,Tristan XII,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,9; percentheal 8,15; },{},{} +12080,Int_Dish10,Dragon Breath Cocktail,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,10; percentheal 10,20; },{},{} +12081,Vit_Dish06,Awfully Bitter Bracer,0,20000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,6; percentheal 13,0; },{},{} +12082,Vit_Dish07,Sumptuous Feast,0,40000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,7; percentheal 16,0; },{},{} +12083,Vit_Dish08,Giant Burito,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,8; percentheal 19,0; },{},{} +12084,Vit_Dish09,Ascending Dragon Soup,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,9; percentheal 22,0; },{},{} +12085,Vit_Dish10,Immortal Stew,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,10; percentheal 25,0; },{},{} +12086,Agi_Dish06,Chile Shrimp Gratin,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,6; percentheal 7,2; },{},{} +12087,Agi_Dish07,Steamed Alligator with Vegetable,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,7; percentheal 8,2; },{},{} +12088,Agi_Dish08,Incredibly Spicy Curry,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,8; percentheal 9,2; },{},{} +12089,Agi_Dish09,Special Meat Stew,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,9; percentheal 10,2; },{},{} +12090,Agi_Dish10,Steamed Desert Scorpions,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,10; percentheal 15,5; },{},{} +12091,Dex_Dish06,Peach Cake,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,6; percentheal 5,6; },{},{} +12092,Dex_Dish07,Soul Haunted Bread,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,7; percentheal 5,7; },{},{} +12093,Dex_Dish08,Special Toast,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,8; percentheal 5,8; },{},{} +12094,Dex_Dish09,Heavenly Fruit Juice,0,80000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,9; percentheal 5,9; },{},{} +12095,Dex_Dish10,Hwergelmir's Tonic,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,10; percentheal 10,10; },{},{} +12096,Luk_Dish06,Lucky Soup,0,20000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,6; percentheal 6,3; },{},{} +12097,Luk_Dish07,Assorted Shish Kebob,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,7; percentheal 7,3; },{},{} +12098,Luk_Dish08,Strawberry Flavored Rice Ball,0,60000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,8; percentheal 9,3; },{},{} +12099,Luk_Dish09,Blood Flavored Soda,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,9; percentheal 10,4; },{},{} +12100,Luk_Dish10,Cooked Nine Tail's Tails,0,100000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,10; percentheal 14,8; },{},{} 12101,Citron,Citron,0,20,,300,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12102,Meat_Skewer,Grilled Skewer,0,20,,300,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12103,Bloody_Dead_Branch,Bloody Branch,2,10000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ monster "this",-1,-1,"--ja--",-3,1,""; },{},{} @@ -4666,8 +4666,8 @@ 12119,Resist_Water,Coldproof Potion,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start4 SC_ARMOR_ELEMENT,1200000,20,0,0,-15; },{},{} 12120,Resist_Earth,Earthproof Potion,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start4 SC_ARMOR_ELEMENT,1200000,0,20,-15,0; },{},{} 12121,Resist_Wind,Thunderproof Potion,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start4 SC_ARMOR_ELEMENT,1200000,0,-15,0,20; },{},{} -12122,Sesame_Pastry,Sesame Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_HITFOOD,1200000,30; },{},{} -12123,Honey_Pastry,Honey Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FLEEFOOD,1200000,30; },{},{} +12122,Sesame_Pastry,Sesame Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_BASICHIT,1200000,30; },{},{} +12123,Honey_Pastry,Honey Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_BASICAVOIDANCE,1200000,30; },{},{} 12124,Rainbow_Cake,Rainbow Cake,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_BATKFOOD,1200000,10; sc_start SC_MATKFOOD,120000,10; },{},{} 12125,Outdoor_Cooking_Kits,Outdoor Cooking Kit,2,500,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ cooking 11; },{},{} 12126,Indoor_Cooking_Kits,Home Cooking Kit,2,1000,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ cooking 12; },{},{} @@ -4686,7 +4686,7 @@ 12139,3rd_Stage_Prize,Third Stage Prize,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12140,4th_Stage_Prize,Fourth Stage Prize,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12141,5th_Stage_Prize,Fifth Stage Prize,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -12142,Magic_Book,Book of Magic,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1800000,10; },{},{} +12142,Magic_Book,Book of Magic,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1800000,10; },{},{} 12143,Red_Can,Red Can,2,50000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12144,Sphere_Case_Wind,Lightning Sphere Pack,2,2,,350,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 13204,500; },{},{} 12145,Sphere_Case_Darkness,Blind Sphere Pack,2,2,,350,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 13206,500; },{},{} @@ -4753,66 +4753,66 @@ 12205,Dex_Dish10_,Hwergelmir's Tonic,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX_CASH,1800000,10; percentheal 15,5; },{},{} 12206,Luk_Dish10_,Cooked Nine Tail's Tails,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK_CASH,1800000,10; percentheal 15,5; },{},{} 12207,Vit_Dish10_,Stew Of Immortality,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT_CASH,1800000,10; percentheal 15,5; },{},{} -12208,Battle_Manual,Battle Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,1800000,50; },{},{} -12209,Insurance,Life Insurance,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LIFEINSURANCE,1800000,0; },{},{} -12210,Bubble_Gum,Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMBOOST,1800000,200; },{},{} +12208,Battle_Manual,Battle Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,1800000,50; },{},{} +12209,Insurance,Life Insurance,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_DEATHPENALTY,1800000,0; },{},{} +12210,Bubble_Gum,Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_RECEIVEITEM,1800000,200; },{},{} 12211,Kafra_Card,Kafra Card,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashStore"; },{},{} 12212,Giant_Fly_Wing,Giant Fly Wing,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashPartyCall"; },{},{} 12213,Neuralizer,Neuralizer,11,2,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashReset"; },{},{} -12214,Convex_Mirror,Convex Mirror,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_BOSSMAPINFO,600000,0; },{},{} +12214,Convex_Mirror,Convex Mirror,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_BOSS_ALARM,600000,0; },{},{} 12215,Blessing_10_Scroll,LV10 Blessing Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ skilleffect "AL_BLESSING",0; sc_start SC_BLESSING,240000,10; },{},{} -12216,Inc_Agi_10_Scroll,LV10 Agil Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if(Hp>15) { skilleffect "AL_INCAGI",0; sc_start SC_INCREASEAGI,240000,10; heal -15,0; } },{},{} +12216,Inc_Agi_10_Scroll,LV10 Agil Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if(Hp>15) { skilleffect "AL_INCAGI",0; sc_start SC_INC_AGI,240000,10; heal -15,0; } },{},{} 12217,Aspersio_5_Scroll,LV5 Aspersio Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if(countitem(523)>0) { skilleffect "PR_ASPERSIO",0; sc_start SC_ASPERSIO,180000,5; delitem 523,1; } },{},{} 12218,Assumptio_5_Scroll,LV5 Assumptio Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ASSUMPTIO,100000,5; skilleffect "HP_ASSUMPTIO",0; },{},{} 12219,Wind_Walk_10_Scroll,LV10 Wind Walker Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ skilleffect "SN_WINDWALK",0; sc_start SC_WINDWALK,250000,5; },{},{} 12220,Adrenaline_Scroll,LV5 Adrenaline Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ set .@type,getiteminfo(getequipid(EQI_HAND_R),11); if (.@type==6||.@type==7||.@type==8) { skilleffect "BS_ADRENALINE",0; sc_start SC_ADRENALINE,150000,5; } },{},{} 12221,Megaphone_,Megaphone,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ input @megaphone$; announce strcharinfo(0) + ": " + @megaphone$,bc_all,0xFF0000; end; },{},{} 12225,Sweet_Candy_Striper,Sweet Candy Cane,2,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1245; },{},{} -12226,Examination1,Examination 1,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,5400000,0; percentheal 100,100; sc_start SC_STRFOOD,5400000,10; sc_start SC_DEXFOOD,5400000,5; sc_start SC_ATKPOTION,5400000,22; sc_start SC_MATKFOOD,5400000,15; },{},{} -12227,Examination2,Examination 2,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,5400000,0; percentheal 100,100; sc_start SC_INTFOOD,5400000,8; sc_start SC_VITFOOD,5400000,7; sc_start SC_LUKFOOD,5400000,7; sc_start SC_ATKPOTION,5400000,10; },{},{} -12228,Examination3,Examination 3,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,5400000,0; percentheal 100,100; sc_start SC_AGIFOOD,5400000,15; sc_start SC_ATKPOTION,5400000,52; sc_start SC_MATKFOOD,5400000,10; },{},{} -12229,Examination4,Examination 4,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,5400000,0; percentheal 100,100; sc_start SC_STRFOOD,5400000,3; sc_start SC_AGIFOOD,5400000,5; sc_start SC_VITFOOD,5400000,10; sc_start SC_MATKFOOD,5400000,52; },{},{} -12230,Examination5,Examination 5,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,5400000,0; percentheal 100,100; sc_start SC_INTFOOD,5400000,3; sc_start SC_DEXFOOD,5400000,12; sc_start SC_ATKPOTION,5400000,20; sc_start SC_MATKFOOD,5400000,20; },{},{} -12231,Examination6,Examination 6,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,100; sc_start SC_SpeedUp0,5400000,0; sc_start SC_STRFOOD,5400000,6; sc_start SC_DEXFOOD,5400000,6; sc_start SC_AGIFOOD,5400000,6; sc_start SC_INTFOOD,5400000,6; sc_start SC_VITFOOD,5400000,6; sc_start SC_LUKFOOD,5400000,6; sc_start SC_ATKPOTION,5400000,24; sc_start SC_MATKFOOD,5400000,24; },{},{} -12232,Gingerbread,Ginger Bread,2,20,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ASPDPOTION1,900000,0; sc_start SC_SpeedUp0,900000,0; },{},{} +12226,Examination1,Examination 1,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,5400000,0; percentheal 100,100; sc_start SC_FOOD_STR,5400000,10; sc_start SC_FOOD_DEX,5400000,5; sc_start SC_PLUSATTACKPOWER,5400000,22; sc_start SC_MATKFOOD,5400000,15; },{},{} +12227,Examination2,Examination 2,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,5400000,0; percentheal 100,100; sc_start SC_FOOD_INT,5400000,8; sc_start SC_FOOD_VIT,5400000,7; sc_start SC_FOOD_LUK,5400000,7; sc_start SC_PLUSATTACKPOWER,5400000,10; },{},{} +12228,Examination3,Examination 3,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,5400000,0; percentheal 100,100; sc_start SC_FOOD_AGI,5400000,15; sc_start SC_PLUSATTACKPOWER,5400000,52; sc_start SC_MATKFOOD,5400000,10; },{},{} +12229,Examination4,Examination 4,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,5400000,0; percentheal 100,100; sc_start SC_FOOD_STR,5400000,3; sc_start SC_FOOD_AGI,5400000,5; sc_start SC_FOOD_VIT,5400000,10; sc_start SC_MATKFOOD,5400000,52; },{},{} +12230,Examination5,Examination 5,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,5400000,0; percentheal 100,100; sc_start SC_FOOD_INT,5400000,3; sc_start SC_FOOD_DEX,5400000,12; sc_start SC_PLUSATTACKPOWER,5400000,20; sc_start SC_MATKFOOD,5400000,20; },{},{} +12231,Examination6,Examination 6,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,100; sc_start SC_MOVHASTE_HORSE,5400000,0; sc_start SC_FOOD_STR,5400000,6; sc_start SC_FOOD_DEX,5400000,6; sc_start SC_FOOD_AGI,5400000,6; sc_start SC_FOOD_INT,5400000,6; sc_start SC_FOOD_VIT,5400000,6; sc_start SC_FOOD_LUK,5400000,6; sc_start SC_PLUSATTACKPOWER,5400000,24; sc_start SC_MATKFOOD,5400000,24; },{},{} +12232,Gingerbread,Ginger Bread,2,20,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATTHASTE_POTION2,900000,0; sc_start SC_MOVHASTE_HORSE,900000,0; },{},{} 12233,Kvass,Kvass,0,20,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,100; },{},{} 12234,Cacao99,Fierce Cacao 99%,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 25,0; },{},{} 12235,Strawberry_Choco,Chocolate Strawberry,2,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,5; skilleffect "AL_BLESSING",0; sc_start SC_BLESSING,240000,10; },{},{} 12236,Choco_Tart,Chocolate Tart,11,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,0; itemskill "AL_ANGELUS",5; },{},{} -12237,Choco_Lump,Junky Chocolate,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,5; sc_start SC_Poison,18000,0; sc_start SC_Bleeding,18000,0; },{},{} +12237,Choco_Lump,Junky Chocolate,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,5; sc_start SC_Poison,18000,0; sc_start SC_BLOODING,18000,0; },{},{} 12238,New_Year_Rice_Cake_1,New Year Rice Cake,2,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ if(rand(1000)<100) sc_start SC_DPoison,10000,0; sc_start SC_Poison,50000,0; },{},{} 12239,New_Year_Rice_Cake_2,New Year Rice Cake,2,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ if(rand(1000)<100) sc_start SC_DPoison,10000,0; sc_start SC_Poison,50000,0; },{},{} 12240,Old_Yellow_Box,Old Yellow Box,2,20,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_YellowBox),1; },{},{} -12241,M_Center_Potion,Mercenary Concentration Potion,2,800,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ASPDPOTION0,1800000,0; },{},{} -12242,M_Awakening_Potion,Mercenary Awakening Potion,2,1500,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ASPDPOTION1,1800000,0; },{},{} -12243,M_Berserk_Potion,Mercenary Berserk Potion,2,3000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ASPDPOTION2,1800000,0; },{},{} +12241,M_Center_Potion,Mercenary Concentration Potion,2,800,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ATTHASTE_POTION1,1800000,0; },{},{} +12242,M_Awakening_Potion,Mercenary Awakening Potion,2,1500,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ATTHASTE_POTION2,1800000,0; },{},{} +12243,M_Berserk_Potion,Mercenary Berserk Potion,2,3000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ATTHASTE_POTION3,1800000,0; },{},{} 12244,Old_Gift_Box,Old Gift Box,2,20,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_OldGiftBox),1; },{},{} 12245,Green_Ale_US,Green Ale,0,5000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,0; },{},{} 12246,Magic_Card_Album,Mystical Card Album,2,10000,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_MagicCardAlbum),1; },{},{} 12247,Halohalo,Halo-Halo,2,2,,100,,,,,0xFFFFFFFF,7,2,,,20,,,{ sc_start SC_INCALLSTATUS,600000,3; },{},{} 12248,Masquerade_Ball_Box,Fancy Ball Box,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_Masquerade),1; },{},{} 12249,Payroll_Of_Kafra_,Payment Statement for Kafra Employee,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -12250,Str_Dish10_M,Steamed Tongue,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,3600000,10; percentheal 20,20; },{},{} -12251,Agi_Dish10_M,Steamed Desert Scorpions,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,3600000,10; percentheal 15,5; },{},{} -12252,Int_Dish10_M,Dragon Breath Cocktail,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,3600000,10; percentheal 10,20; },{},{} -12253,Dex_Dish10_M,Hwergelmir's Tonic,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,3600000,10; percentheal 10,10; },{},{} -12254,Luk_Dish10_M,Cooked Nine Tail,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,3600000,10; percentheal 14,8; },{},{} -12255,Vit_Dish10_M,Immortal Stew,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,3600000,10; percentheal 25,0; },{},{} +12250,Str_Dish10_M,Steamed Tongue,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,3600000,10; percentheal 20,20; },{},{} +12251,Agi_Dish10_M,Steamed Desert Scorpions,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,3600000,10; percentheal 15,5; },{},{} +12252,Int_Dish10_M,Dragon Breath Cocktail,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,3600000,10; percentheal 10,20; },{},{} +12253,Dex_Dish10_M,Hwergelmir's Tonic,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,3600000,10; percentheal 10,10; },{},{} +12254,Luk_Dish10_M,Cooked Nine Tail,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,3600000,10; percentheal 14,8; },{},{} +12255,Vit_Dish10_M,Immortal Stew,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,3600000,10; percentheal 25,0; },{},{} 12256,PRO_Gift_Box,PRO Gift Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12257,Cold_Medicine,Cold Medicine,0,20,,100,,,,,0xFFFFFFFF,7,2,,,50,,,{ percentheal 25,25; },{},{} 12258,Bombring_Box,Bomb Poring Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if(strcharinfo(3)=="job3_rang02") { monster "this",-1,-1,"--ja--",1904,1,""; } },{},{} 12259,Miracle_Medicine,Miracle Tonic,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ getexp 3000000,1500000; },{},{} 12260,Cool_Summer_Outfit,Cool Summer Outfit,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_Summer,600000,0; },{},{} 12261,Secret_Medicine,Leap of Fantasy,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ getexp 2000000,1000000; },{},{} -12262,Inspector_Certificate_,Authoritative Badge,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,180000,0; },{},{} -12263,Comp_Battle_Manual,Field Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,1800000,50; },{},{} -12264,Comp_Bubble_Gum,Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMBOOST,1800000,200; },{},{} -12265,Comp_Insurance,Life Insurrance,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LIFEINSURANCE,1800000,0; },{},{} -12266,Sesame_Pastry_,Sesame Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_HITFOOD,1200000,30; },{},{} -12267,Honey_Pastry_,Honey Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FLEEFOOD,1200000,30; },{},{} -12268,Rainbow_Cake_,Rainbow Cake,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,60000,10; sc_start SC_MATKFOOD,120000,10; },{},{} -12269,Tasty_Colonel,Tasty Pink Ration,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,600000,15; },{},{} -12270,Tasty_Major,Tasty White Ration,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MATKPOTION,600000,15; },{},{} +12262,Inspector_Certificate_,Authoritative Badge,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,180000,0; },{},{} +12263,Comp_Battle_Manual,Field Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,1800000,50; },{},{} +12264,Comp_Bubble_Gum,Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_RECEIVEITEM,1800000,200; },{},{} +12265,Comp_Insurance,Life Insurrance,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_DEATHPENALTY,1800000,0; },{},{} +12266,Sesame_Pastry_,Sesame Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_BASICHIT,1200000,30; },{},{} +12267,Honey_Pastry_,Honey Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_BASICAVOIDANCE,1200000,30; },{},{} +12268,Rainbow_Cake_,Rainbow Cake,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,60000,10; sc_start SC_MATKFOOD,120000,10; },{},{} +12269,Tasty_Colonel,Tasty Pink Ration,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,600000,15; },{},{} +12270,Tasty_Major,Tasty White Ration,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSMAGICPOWER,600000,15; },{},{} 12271,Mre_A,Military Ration A,0,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,0; },{},{} 12272,Mre_B,Military Ration B,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCHIT,600000,33; },{},{} 12273,Mre_C,Military Ration C,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCFLEE,600000,33; },{},{} @@ -4824,16 +4824,16 @@ 12279,Undead_Element_Scroll,Undead Elemental Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start4 SC_ARMOR_RESIST,300000,20,20,20,20; },{},{} 12280,Holy_Element_Scroll,Holy Elemental Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_BENEDICTIO; sc_start SC_BENEDICTIO,300000,1; },{},{} 12281,Tresure_Box_WoE,Event Treasure Box,2,20,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_Tresure_Box_WoE),1; },{},{} -12282,Internet_Cafe1,Internet Cafe1,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCALLSTATUS,5400000,3; sc_start SC_ATKPOTION,5400000,15; sc_start SC_MATKPOTION,5400000,15; },{},{} -12283,Internet_Cafe2,Internet Cafe2,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCSTR,5400000,8; sc_start SC_INCDEX,5400000,4; sc_start SC_INCAGI,5400000,6; sc_start SC_ATKPOTION,5400000,32; sc_start SC_INCFLEE,5400000,5; },{},{} -12284,Internet_Cafe3,Internet Cafe3,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCINT,5400000,8; sc_start SC_INCVIT,5400000,4; sc_start SC_INCDEX,5400000,6; sc_start SC_MATKPOTION,5400000,40; },{},{} -12285,Internet_Cafe4,Internet Cafe4,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCDEX,5400000,8; sc_start SC_INCLUK,5400000,4; sc_start SC_INCAGI,5400000,6; sc_start SC_ATKPOTION,5400000,24; sc_start SC_MATKPOTION,5400000,24; },{},{} +12282,Internet_Cafe1,Internet Cafe1,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCALLSTATUS,5400000,3; sc_start SC_PLUSATTACKPOWER,5400000,15; sc_start SC_PLUSMAGICPOWER,5400000,15; },{},{} +12283,Internet_Cafe2,Internet Cafe2,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCSTR,5400000,8; sc_start SC_INCDEX,5400000,4; sc_start SC_INCAGI,5400000,6; sc_start SC_PLUSATTACKPOWER,5400000,32; sc_start SC_INCFLEE,5400000,5; },{},{} +12284,Internet_Cafe3,Internet Cafe3,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCINT,5400000,8; sc_start SC_INCVIT,5400000,4; sc_start SC_INCDEX,5400000,6; sc_start SC_PLUSMAGICPOWER,5400000,40; },{},{} +12285,Internet_Cafe4,Internet Cafe4,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCDEX,5400000,8; sc_start SC_INCLUK,5400000,4; sc_start SC_INCAGI,5400000,6; sc_start SC_PLUSATTACKPOWER,5400000,24; sc_start SC_PLUSMAGICPOWER,5400000,24; },{},{} 12286,Masquerade_Ball_Box2,Masquerade Ball Box2,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_Masquerade_2),1; },{},{} 12287,Love_Angel,Love Angel Magic Powder,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ setfont 1; },{},{} 12288,Squirrel,Squirrel Magic Powder,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ setfont 2; },{},{} 12289,Gogo,Gogo Magic Powder,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ setfont 3; },{},{} 12290,Mysterious_Can,Mysterious Can Magic Powder,2,10,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,0; skilleffect "AL_BLESSING",0; sc_start SC_BLESSING,120000,5; },{},{} -12291,Mysterious_PET_Bottle,Mysterious PET Bottle,2,10,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,0; skilleffect "AL_INCAGI",0; sc_start SC_INCREASEAGI,120000,5; },{},{} +12291,Mysterious_PET_Bottle,Mysterious PET Bottle,2,10,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,0; skilleffect "AL_INCAGI",0; sc_start SC_INC_AGI,120000,5; },{},{} 12292,Unripe_Fruit,Unripe Fruit,0,500,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 20,0; },{},{} 12293,Dried_Yggdrasilberry,Dried Yggdrasilberry,0,500,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,20; },{},{} 12294,PC_Bang_Coin_Box1,PC-Room Coin Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 2740,1; },{},{} @@ -4854,7 +4854,7 @@ 12309,Bulging_Head,JJangu Magic Powder,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ setfont 9; },{},{} 12310,Spray_Of_Flowers,Spray Of Flowers,2,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCFLEE,600000,10; },{},{} 12311,Large_Spray_Of_Flowers,Huge Spray Of Flowers,11,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "ALL_PARTYFLEE",1; },{},{} -12312,Thick_Manual50,Thick Battle Manual,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,3600000,50; },{},{} +12312,Thick_Manual50,Thick Battle Manual,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,3600000,50; },{},{} 12313,Protection_Of_Angel,Guardian Angel,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12314,Noive_Box,Noive Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12315,Goddess_Bless,Goddess Of Blessing,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} @@ -4863,7 +4863,7 @@ 12318,Little_Heart,Small Hearts,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12319,Strawberry_Cake,Rune Strawberry Cake,2,0,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCATKRATE,600000,5; sc_start SC_INCMATKRATE,600000,5; },{},{} 12320,Pineapple_Juice,Schwartzwald Pine Jubilee,2,0,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCHIT,600000,10; sc_start SC_INCFLEE2,600000,20; },{},{} -12321,Spicy_Sandwich,Arunafeltz Desert Sandwich,2,0,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCCRI,600000,7; },{},{} +12321,Spicy_Sandwich,Arunafeltz Desert Sandwich,2,0,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CRITICALPERCENT,600000,7; },{},{} 12322,Chocolate_Pie,Chocolate Pie,0,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,5; },{},{} 12323,N_Fly_Wing,Novice Fly Wing,11,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "AL_TELEPORT",1; },{},{} 12324,N_Butterfly_Wing,Novice Butterfly Wing,11,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "AL_TELEPORT",3; },{},{} @@ -4896,7 +4896,7 @@ 12351,Shout_Megaphone,Scream Megaphone,11,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "MC_LOUD",1; },{},{} 12352,Dun_Tele_Scroll3,Dungeon Teleport Scroll 3,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12353,Tiny_Waterbottle,Small Bottle,2,800,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_WATERWEAPON,90000,1; },{},{} -12354,Buche_De_Noel,Buche De Noel,2,2,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_ANGELUS; sc_start SC_INCMHPRATE,600000,3; sc_start SC_INCMSPRATE,600000,3; sc_start SC_INCHITRATE,600000,3; sc_start SC_INCCRI,600000,7; },{},{} +12354,Buche_De_Noel,Buche De Noel,2,2,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_ANGELUS; sc_start SC_INCMHPRATE,600000,3; sc_start SC_INCMSPRATE,600000,3; sc_start SC_INCHITRATE,600000,3; sc_start SC_CRITICALPERCENT,600000,7; },{},{} 12355,Xmas_Gift,Xmas Gift,2,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_Xmas_Gift),1; },{},{} 12356,Louise_Costume_Box,Louise Costume Box,2,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_Louise_Costume_Box),1; },{},{} 12357,Shiny_Wing_Gown,Shiny Wing Gown,2,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1630; },{},{} @@ -4953,10 +4953,10 @@ 12408,Leaf_Cat_Ball,Leaf Cat Ball,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 2081; },{},{} 12409,Pork_Belly_H,Pork Belly H,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12410,Spareribs_H,Spareribs H,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -12411,HE_Battle_Manual,HE Battle Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,900000,200; },{},{} -12412,HE_Bubble_Gum,HE Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMBOOST,900000,300; },{},{} +12411,HE_Battle_Manual,HE Battle Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,900000,200; },{},{} +12412,HE_Bubble_Gum,HE Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_RECEIVEITEM,900000,300; },{},{} 12413,PCBang_Coupon_Box2,PCBang Coupon Box2,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -12414,Guarana_Candy,Guarana Candy,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ASPDPOTION0,1800000,0; sc_start SC_INCREASEAGI,140000,5; skilleffect "AL_INCAGI",0; },{},{} +12414,Guarana_Candy,Guarana Candy,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATTHASTE_POTION1,1800000,0; sc_start SC_INC_AGI,140000,5; skilleffect "AL_INCAGI",0; },{},{} 12415,Siege_Teleport_Scroll2,Siege Teleport Scroll2,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12416,Lucky_Egg_C3,Lucky Egg C3,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12417,Boost500,Boost500,2,100,,50,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} @@ -5015,7 +5015,7 @@ 12472,F_Convex_Mirror,F Convex Mirror,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12473,RWC_Parti_Box,RWC Parti Box,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12474,RWC_Final_Comp_Box,RWC Final Comp Box,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -12475,Cure_Free,Cure Free,2,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_SILENCE; sc_end SC_BLEEDING; sc_end SC_POISON; sc_end SC_CURSE; sc_end SC_ORCISH; sc_end SC_CHANGEUNDEAD; itemheal 500,0; },{},{} +12475,Cure_Free,Cure Free,2,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_SILENCE; sc_end SC_BLOODING; sc_end SC_POISON; sc_end SC_CURSE; sc_end SC_ORCISH; sc_end SC_CHANGEUNDEAD; itemheal 500,0; },{},{} 12476,PCBang_Coupon_Box3,PCBang Coupon Box3,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12477,Gift_Bundle,Gift Bundle,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12478,Chance_Box,Chance Box,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} @@ -5127,7 +5127,7 @@ 12702,Old_Bleu_Box,Old Navy Box,2,0,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_BleuBox),1; getrandgroupitem(IG_BleuBox),1; },{},{} 12703,Holy_Egg_2,Holy Egg,11,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12704,Elixir_Of_Life,Elixir of Life,0,0,,10,,,,,0xFFFFFFFF,7,2,,,85,,,{ percentheal 100,0; },{},{} -12705,Noble_Nameplate,Noble Nameplate,2,0,,100,,,,,0xFFFFFFFF,7,2,,,90,,,{ sc_start SC_EXPBOOST,1800000,100; },{},{} +12705,Noble_Nameplate,Noble Nameplate,2,0,,100,,,,,0xFFFFFFFF,7,2,,,90,,,{ sc_start SC_CASH_PLUSEXP,1800000,100; },{},{} 12706,Lucky_Cookie01,Lucky Cookie,11,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "PR_GLORIA",5; },{},{} 12707,Lucky_Cookie02,Lucky Cookie,11,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "PR_MAGNIFICAT",1; },{},{} 12708,Lucky_Cookie03,Lucky Cookie,11,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "PR_IMPOSITIO",3; },{},{} @@ -5436,7 +5436,7 @@ 13269,Boost500_To_Throw,Throwing Boost 500,10,100,,10,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_BOOST500,500000,10; },{},{} 13270,Full_SwingK_To_Throw,Throwing Full Swing K,10,100,,50,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_FULL_SWING_K,500000,50; },{},{} 13271,Mana_Plus_To_Throw,Throwing Mana Plus,10,100,,50,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_MANA_PLUS,500000,50; },{},{} -13272,Cure_Free_To_Throw,Throwing Cure Free,10,100,,50,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_end SC_Bleeding; sc_end SC_Curse; sc_end SC_Silence; itemheal rand(1000,1200),0; },{},{} +13272,Cure_Free_To_Throw,Throwing Cure Free,10,100,,50,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_end SC_BLOODING; sc_end SC_Curse; sc_end SC_Silence; itemheal rand(1000,1200),0; },{},{} 13273,Stamina_Up_M_To_Throw,Throwing Muramura M,10,100,,10,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_MUSTLE_M,500000,5; },{},{} 13274,Digestive_F_To_Throw,Throwing Falmons F,10,100,,10,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_LIFE_FORCE_F,500000,5; },{},{} 13275,HP_Inc_PotS_To_Throw,Throwing Increase HP Potion (Small),10,100,,20,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_INCMHPRATE,500000,1; percentheal 1,0; },{},{}//HP and SP pots need a recheck later to correct max increases. @@ -6319,11 +6319,11 @@ 14461,Asara_Fairy_Hat_Box,Ashura Fairy Hat Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 5505,1; },{},{} 14466,Valentine_Pledge_Box,Valentine's Emblem Box,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 14469,Ox_Tail_Scroll,Ox Tail Egg,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -14500,Insurance60,Life Insurrance Certificate,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LIFEINSURANCE,3600000,0; },{},{} +14500,Insurance60,Life Insurrance Certificate,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_DEATHPENALTY,3600000,0; },{},{} 14508,Zeny_Scroll,Zeny Pet Egg Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -14509,Light_Center_Pot,Light Concentration Potion,2,800,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ASPDPOTION0,1800000,0; },{},{} -14510,Light_Awakening_Pot,Light Awakening Potion,2,1500,,20,,,,,0xFFF7FEEF,7,2,,,40,,,{ sc_start SC_ASPDPOTION1,1800000,0; },{},{} -14511,Light_Berserk_Pot,Light Berserk Potion,2,3000,,20,,,,,0x01E646A6,7,2,,,85,,,{ sc_start SC_ASPDPOTION2,1800000,0; },{},{} +14509,Light_Center_Pot,Light Concentration Potion,2,800,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATTHASTE_POTION1,1800000,0; },{},{} +14510,Light_Awakening_Pot,Light Awakening Potion,2,1500,,20,,,,,0xFFF7FEEF,7,2,,,40,,,{ sc_start SC_ATTHASTE_POTION2,1800000,0; },{},{} +14511,Light_Berserk_Pot,Light Berserk Potion,2,3000,,20,,,,,0x01E646A6,7,2,,,85,,,{ sc_start SC_ATTHASTE_POTION3,1800000,0; },{},{} 14512,Meteor_10_Scroll,Meteor Storm Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_METEOR",10; },{},{} 14513,Storm_10_Scroll,Storm Gust Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_STORMGUST",10; },{},{} 14514,Vermilion_10_Scroll,Lord of Vermilion Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_VERMILION",10; },{},{} @@ -6337,18 +6337,18 @@ 14522,Big_Bun,Big Bun,0,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,0; },{},{} 14523,Pill_,Pill,0,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,100; },{},{} 14524,Superb_Fish_Slice,Superb Fish Slice,0,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,100; },{},{} -14525,Chewy_Ricecake,Chewy Ricecake,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,180000,10; },{},{} -14526,Oriental_Pastry,Oriental Pastry,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MATKPOTION,180000,10; },{},{} +14525,Chewy_Ricecake,Chewy Ricecake,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,180000,10; },{},{} +14526,Oriental_Pastry,Oriental Pastry,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSMAGICPOWER,180000,10; },{},{} 14527,Dun_Tele_Scroll1,Dungeon Teleport Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashDungeon"; },{},{} 14528,PVP_Tele_Scroll,PVP Teleport Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 14529,Greed_Scroll,Greed Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "BS_GREED",1; },{},{} 14530,Flee_30_Scroll,Evasion Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCFLEE,1800000,30; },{},{} 14531,Accuracy_30_Scroll,Concentration Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCHIT,1800000,30; },{},{} -14532,Battle_Manual25,Field Manual 25%,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,1800000,25; },{},{} -14533,Battle_Manual100,Field Manual 100%,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,1800000,100; },{},{} +14532,Battle_Manual25,Field Manual 25%,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,1800000,25; },{},{} +14533,Battle_Manual100,Field Manual 100%,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,1800000,100; },{},{} 14534,Small_Life_Potion,Small Life Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 320; sc_start4 SC_S_LIFEPOTION,600000,-5,5,0,0; },{},{} 14535,Med_Life_Potion,Medium Life Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 320; sc_start4 SC_L_LIFEPOTION,600000,-7,4,0,0; },{},{} -14536,Abrasive,Abrasive,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 182; sc_start SC_INCCRI,300000,30; },{},{} +14536,Abrasive,Abrasive,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 182; sc_start SC_CRITICALPERCENT,300000,30; },{},{} 14537,Regeneration_Potion,Regeneration Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 348; sc_start SC_INCHEALRATE,1800000,20; },{},{} 14538,Glass_Of_Illusion,Glass of Illusion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_STEAL; sc_start SC_INCFLEE2,60000,20; },{},{} 14539,Shadow_Armor_S,Shadow Armor Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_CLOAKING; sc_start4 SC_ELEMENTALCHANGE,1800000,1,Ele_Dark,1,0; },{},{} @@ -6357,42 +6357,42 @@ 14542,B_Def_Potion,Big Defense Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_GUARD; sc_start SC_DEF_RATE,180000,3; },{},{} 14543,S_Mdef_Potion,Small Magic Defense Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_SPELLBREAKER; sc_start SC_MDEF_RATE,60000,3; },{},{} 14544,B_Mdef_Potion,Big Magic Defense Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_SPELLBREAKER; sc_start SC_MDEF_RATE,180000,3; },{},{} -14545,Battle_Manual_X3,Field Manual 300%,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,1800000,300; },{},{} +14545,Battle_Manual_X3,Field Manual 300%,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,1800000,300; },{},{} 14546,Fire_Cracker_Love,I Love You Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} 14547,Fire_Cracker_Wday,Whiteday Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} 14548,Fire_Cracker_Valentine,Valentine's Day Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} 14549,Fire_Cracker_Bday,Birthday Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} 14550,Fire_Cracker_Xmas,Xmas Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} -14551,Str_Dish01_,Fried Grasshopper Legs,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,1; percentheal 5,0; },{},{} -14552,Str_Dish02_,Seasoned Sticky Webfoot,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,2; percentheal 5,0; },{},{} -14553,Str_Dish03_,Bomber Steak,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,3; percentheal 5,0; },{},{} -14554,Int_Dish01_,Grape Juice Herbal Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,1; percentheal 0,5; },{},{} -14555,Int_Dish02_,Autumn Red Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,2; percentheal 0,5; },{},{} -14556,Int_Dish03_,Honey Herbal Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,3; percentheal 0,5; },{},{} -14557,Vit_Dish01_,Steamed Crab Nippers,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,1; percentheal 5,0; },{},{} -14558,Vit_Dish02_,Assorted Seafood,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,2; percentheal 5,0; },{},{} -14559,Vit_Dish03_,Clam Soup,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,3; percentheal 5,0; },{},{} -14560,Agi_Dish01_,Frog Egg Squid Ink Soup,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,1; percentheal 3,1; },{},{} -14561,Agi_Dish02_,Smooth Noodle,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,2; percentheal 3,1; },{},{} -14562,Agi_Dish03_,Tentacle Cheese Gratin,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,3; percentheal 3,1; },{},{} -14563,Dex_Dish01_,Honey Grape Juice,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,1; percentheal 2,2; },{},{} -14564,Dex_Dish02_,Chocolate Mousse Cake,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,2; percentheal 2,2; },{},{} -14565,Dex_Dish03_,Fruit Mix,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,3; percentheal 2,2; },{},{} -14566,Luk_Dish01_,Fried Monkey Tails,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,1; percentheal 3,2; },{},{} -14567,Luk_Dish02_,Mixed Juice,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,2; percentheal 3,2; },{},{} -14568,Luk_Dish03_,Fried Sweet Potato,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,3; percentheal 4,2; },{},{} +14551,Str_Dish01_,Fried Grasshopper Legs,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,1; percentheal 5,0; },{},{} +14552,Str_Dish02_,Seasoned Sticky Webfoot,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,2; percentheal 5,0; },{},{} +14553,Str_Dish03_,Bomber Steak,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,3; percentheal 5,0; },{},{} +14554,Int_Dish01_,Grape Juice Herbal Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,1; percentheal 0,5; },{},{} +14555,Int_Dish02_,Autumn Red Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,2; percentheal 0,5; },{},{} +14556,Int_Dish03_,Honey Herbal Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,3; percentheal 0,5; },{},{} +14557,Vit_Dish01_,Steamed Crab Nippers,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,1; percentheal 5,0; },{},{} +14558,Vit_Dish02_,Assorted Seafood,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,2; percentheal 5,0; },{},{} +14559,Vit_Dish03_,Clam Soup,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,3; percentheal 5,0; },{},{} +14560,Agi_Dish01_,Frog Egg Squid Ink Soup,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,1; percentheal 3,1; },{},{} +14561,Agi_Dish02_,Smooth Noodle,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,2; percentheal 3,1; },{},{} +14562,Agi_Dish03_,Tentacle Cheese Gratin,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,3; percentheal 3,1; },{},{} +14563,Dex_Dish01_,Honey Grape Juice,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,1; percentheal 2,2; },{},{} +14564,Dex_Dish02_,Chocolate Mousse Cake,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,2; percentheal 2,2; },{},{} +14565,Dex_Dish03_,Fruit Mix,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,3; percentheal 2,2; },{},{} +14566,Luk_Dish01_,Fried Monkey Tails,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,1; percentheal 3,2; },{},{} +14567,Luk_Dish02_,Mixed Juice,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,2; percentheal 3,2; },{},{} +14568,Luk_Dish03_,Fried Sweet Potato,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,3; percentheal 4,2; },{},{} 14569,Knife_Goblin_Ring,Knife Goblin Ring,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1122; },{},{} 14570,Flail_Goblin_Ring,Flail Goblin Ring,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1123; },{},{} 14571,Hammer_Goblin_Ring,Hammer Goblin Ring,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1125; },{},{} 14572,Holy_Marble,Holy Marble,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1385; },{},{} 14573,Red_Burning_Stone,Red Burning Stone,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1382; },{},{} 14574,Skull_Of_Vagabond,Vagabond's Skull,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1208; },{},{} -14575,Str_Dish05_,Lutie Lady's Pancake,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,5; percentheal 10,0; },{},{} -14576,Int_Dish05_,Mastela Fruit Wine,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,5; percentheal 0,10; },{},{} -14577,Vit_Dish05_,Spicy Fried Bao,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,5; percentheal 10,0; },{},{} -14578,Agi_Dish05_,Steamed Bat Wing in Pumpkin,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,5; percentheal 6,2; },{},{} -14579,Dex_Dish05_,Green Salad,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,5; percentheal 5,5; },{},{} -14580,Luk_Dish05_,Fried Scorpion Tails,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,5; percentheal 5,2; },{},{} +14575,Str_Dish05_,Lutie Lady's Pancake,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,5; percentheal 10,0; },{},{} +14576,Int_Dish05_,Mastela Fruit Wine,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,5; percentheal 0,10; },{},{} +14577,Vit_Dish05_,Spicy Fried Bao,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,5; percentheal 10,0; },{},{} +14578,Agi_Dish05_,Steamed Bat Wing in Pumpkin,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,5; percentheal 6,2; },{},{} +14579,Dex_Dish05_,Green Salad,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,5; percentheal 5,5; },{},{} +14580,Luk_Dish05_,Fried Scorpion Tails,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,5; percentheal 5,2; },{},{} 14581,Dun_Tele_Scroll2,Dungeon Teleport Scroll II,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashDungeon"; },{},{} 14582,WOB_Rune,Yellow Butterfly Wing,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashCity",1; },{},{} 14583,WOB_Schwaltz,Green Butterfly Wing,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashCity",2; },{},{} @@ -6404,7 +6404,7 @@ 14589,Pty_Inc_Agi_Scroll,Party Increase Agi 10 Scroll,11,10,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "CASH_INCAGI",10; },{},{} 14590,Pty_Assumptio_Scroll,Party Assumptio 5 Scroll,11,10,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "CASH_ASSUMPTIO",5; },{},{} 14591,Siege_Teleport_Scroll,WoE Teleport Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashSeigeTele"; },{},{} -14592,Job_Manual50,JOB Battle Manual,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_JEXPBOOST,1800000,50; },{},{} +14592,Job_Manual50,JOB Battle Manual,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSONLYJOBEXP,1800000,50; },{},{} 14593,Magic_Power_Scroll,Mystical Amplification Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "HW_MAGICPOWER",10; },{},{} 14594,Quagmire_Scroll,Quagmire Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_QUAGMIRE",5; },{},{} 14595,Unsealed_Magic_Spell,Unsealed Magic Spell,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ warp "yuno_fild09",255,127; },{},{} @@ -6413,7 +6413,7 @@ 14598,GhostringS,Ghostring Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMSCRIPT,60000,4047; },{},{} 14599,Greed_Scroll_C,Greed Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 14600,Mental_Potion,Mental Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -14601,Tyr's_Blessing,Tyr's Blessing,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCFLEE,300000,30; sc_start SC_INCHIT,300000,30; sc_start SC_ATKPOTION,300000,20; sc_start SC_MATKPOTION,300000,20; },{},{} +14601,Tyr's_Blessing,Tyr's Blessing,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCFLEE,300000,30; sc_start SC_INCHIT,300000,30; sc_start SC_PLUSATTACKPOWER,300000,20; sc_start SC_PLUSMAGICPOWER,300000,20; },{},{} 14602,TaogunkaS,Tao Gunka Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMSCRIPT,180000,4302; },{},{} 14603,MistressS,Mistress Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMSCRIPT,180000,4132; },{},{} 14604,Orc_HeroS,Orc Hero Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMSCRIPT,60000,4143; },{},{} diff --git a/db/pre-re/skill_cast_db.txt b/db/pre-re/skill_cast_db.txt index fcd2e8ceb..9a2c4bafb 100644 --- a/db/pre-re/skill_cast_db.txt +++ b/db/pre-re/skill_cast_db.txt @@ -1086,16 +1086,16 @@ 2006,1000,0,0,0,0,2000 //-- RK_DRAGONBREATH -2008,0:0:0:1000:1000:1000:1500:1500:2000:2000,2000,0,10000,0,0 +2008,0:0:0:1000:1000:1000:1500:1500:2000:2000,2000,0,42000,0,0 //-- RK_DRAGONHOWLING 2009,0,0,0,15000,0,10000 //-- RK_MILLENNIUMSHIELD -2011,0,1000,0,180000,0,60000 +2011,0,1000,0,180000,60000,0 //-- RK_CRUSHSTRIKE -2012,0,0,0,30000,0,30000 +2012,0,0,0,180000,30000,0 //-- RK_REFRESH -2013,0,0,0,60000,0,120000 +2013,0,0,0,60000,120000,0 //-- RK_GIANTGROWTH 2014,0,0,0,180000,0,0 //-- RK_STONEHARDSKIN @@ -1108,6 +1108,8 @@ 2018,0,0,0,180000,0,0 //-- RK_ABUNDANCE 2019,0,0,0,180000,0,0 +//-- RK_DRAGONBREATH_WATER +5004,0:0:0:1000:1000:1000:1500:1500:2000:2000,2000,0,40000,0,0 //========================================== //===== Gillotine Cross ==================== @@ -1144,6 +1146,8 @@ 2036,0,200,0,3000,0,0 //-- GC_CROSSRIPPERSLASHER 2037,0,1000,0,0,0,0 +//-- GC_DARKCROW +5001,0,1500,0,5000,0,0 //========================================== //===== Arch Bishop ======================== @@ -1183,6 +1187,8 @@ //-- AB_SILENTIUM 2057,4000,0,0,20000:30000:40000:50000:60000,0,15000 +//-- AB_OFFERTORIUM +5011,4000,0,0,90000,0,0,-1 //========================================== //===== Warlock ============================ @@ -1208,17 +1214,15 @@ //-- WL_CRIMSONROCK 2211,5000,2000,0,3000:4000:5000:6000:7000,0,5000 //-- WL_HELLINFERNO -2212,3000,1000,0,15000,0,0 +2212,3000,1000,0,42000,0,0 //-- WL_COMET -2213,10000:11000:12000:13000:14000,0,0,15000,0,60000 +2213,10000:11000:12000:13000:14000,0,0,100,42000,60000 //-- WL_CHAINLIGHTNING 2214,3500:4000:4500:5000:5500,0,0,100,0,3000 - //-- WL_EARTHSTRAIN -2216,2000:3000:4000:5000:6000,1000,0,150,75000:90000:105000:120000:135000,10000 -//-- WL_TETRAVORTEX -2217,5000:6000:7000:8000:9000,2000,0,20000,0,15000 - +2216,2000:3000:4000:5000:6000,1000,0,100,75000:90000:105000:120000:135000,10000 +//-- WL_TETRAVORTEX +2217,5000:6000:7000:8000:9000,2000,0,15000:120000:40000:5000,0,15000 //-- WL_SUMMONFB 2222,2000,0,0,120000:160000:200000:240000:280000,0,0 //-- WL_SUMMONBL @@ -1230,6 +1234,8 @@ //-- WL_READING_SB 2231,5000,500,0,0,0,0 +//-- WL_TELEKINESIS_INTENSE +5012,1000,0,0,180000,0,0 //========================================== //===== Ranger ============================= @@ -1271,6 +1277,8 @@ 2253,0,0,0,20000,15000,0 //-- RA_ICEBOUNDTRAP 2254,0,0,0,20000,15000,0 +//-- RA_UNLIMIT +5002,0,0,0,60000,0,0 //========================================== //===== Mechanic =========================== @@ -1326,6 +1334,8 @@ 2282,0,0,0,20000:30000:40000:50000:60000,0,0 //-- NC_DISJOINT 2283,2000,0,0,0,0,0 +//-- NC_MAGMA_ERUPTION +5006,1000,0,0,10000,42000,0 //========================================== //===== Shadow Chaser ====================== @@ -1411,6 +1421,8 @@ 2324,1000,3000,0,0,0,20000 //-- LG_INSPIRATION 2325,2000,2000,0,30000:45000:60000:75000:90000,0,540000:480000:420000:360000:300000 +//-- LG_KINGS_GRACE +5013,1000,0,0,5000,0,0 //========================================== //===== Sura Skills ======================== @@ -1457,6 +1469,8 @@ 2347,1000,1000,0,240000,0,200000:180000:160000:140000:120000 //-- SR_GENTLETOUCH_REVITALIZE 2348,1000,1000,0,240000,0,200000:180000:160000:140000:120000 +//-- SR_FLASHCOMBO +2348,0,4000,0,0,0,0 //========================================== //==== Wanderer skills ===================== @@ -1519,6 +1533,8 @@ 2433,1000,1000,0,20000:30000:40000:50000:60000,0,180000 //-- WM_UNLIMITED_HUMMING_VOICE 2434,1000,1000,0,60000:90000:120000:150000:180000,0,110000:120000:130000:140000:150000 +//-- WM_FRIGG_SONG +5007,0,0,0,60000,0,0 //========================================== //==== Sorcerer skills ===================== @@ -1639,60 +1655,62 @@ //========================================== //==== Kagerou & Oboro skills ============== -//-- KO_YAMIKUMO +//-- KO_YAMIKUMO 3001,0,0,0,60000,0,0 -//-- KO_JYUMONJIKIRI -3004,0,2500,0,5000,0,0 -//-- KO_SETSUDAN -3005,0,2000,0,0,0,0 -//-- KO_BAKURETSU -3006,1000:1500:2000:2500:3000,1000,0,100,0,3000 -//-- KO_HAPPOKUNAI -3007,0,1000,0,0,0,0 -//-- KO_MUCHANAGE -3008,0,0,0,100,0,10000 -//-- KO_HUUMARANKA -3009,0,3000,0,500,0,0 -//-- KO_MAKIBISHI -3010,0,0,0,12000:14000:16000:18000:20000,10000,0 -//-- KO_MEIKYOUSISUI -3011,3000,0,0,10000,0,0 -//-- KO_ZANZOU -3012,0,0,0,27000:24000:21000:18000:15000,0,0 -//-- KO_KYOUGAKU -3013,1000,0,0,12000:14000:16000:18000:20000,0,0 -//-- KO_JYUSATSU -3014,1000,0,0,8000:10000:12000:14000:16000,0,0 -//-- KO_KAHU_ENTEN -3015,500,0,0,300000,0,0 -//-- KO_HYOUHU_HUBUKI -3016,500,0,0,300000,0,0 -//-- KO_KAZEHU_SEIRAN -3017,500,0,0,300000,0,0 -//-- KO_DOHU_KOUKAI -3018,500,0,0,300000,0,0 -//-- KO_KAIHOU -3019,1000,0,0,0,0,0 -//-- KO_ZENKAI -3020,1000,0,0,10000,10000,0 -//-- KO_GENWAKU -3021,500,0,0,5000,0,0 -//-- KO_IZAYOI +//-- KO_JYUMONJIKIRI +3004,0,500,0,3000,0,5000 +//-- KO_SETSUDAN +3005,0,0,0,0,0,3000 +//-- KO_BAKURETSU +3006,1000:1400:1800:2200:2600,1000,0,100,0,3000 +//-- KO_HAPPOKUNAI +3007,0,500,0,0,0,0 +//-- KO_MUCHANAGE +3008,1000,0,0,100,0,10000 +//-- KO_HUUMARANKA +3009,1000:1200:1400:1600:1800,1000,0,500,0,3000 +//-- KO_MAKIBISHI +3010,0,0,0,12000:14000:16000:18000:20000,10000,10000 +//-- KO_MEIKYOUSISUI +3011,3000,0,0,10000,0 +//-- KO_ZANZOU +3012,0,1000,0,30000:27000:24000:21000:18000,0,0 +//-- KO_KYOUGAKU +3013,3000:2500:2000:1500:1000,1000,0,12000:14000:16000:18000:20000,0,0 +//-- KO_JYUSATSU +3014,3000:2500:2000:1500:1000,1000,0,8000:10000:12000:14000:16000,0,10000 +//-- KO_KAHU_ENTEN +3015,2000,0,0,300000,0,0 +//-- KO_HYOUHU_HUBUKI +3016,2000,0,0,300000,0,0 +//-- KO_KAZEHU_SEIRAN +3017,2000,0,0,300000,0,0 +//-- KO_DOHU_KOUKAI +3018,2000,0,0,300000,0,0 +//-- KO_ZENKAI +3020,0,1000,0,10000,10000,0 +//-- KO_GENWAKU +3021,3000:2500:2000:1500:1000,1000,0,5000,0,10000 +//-- KO_IZAYOI 3022,0,0,0,30000:45000:60000:75000:90000,0,60000 -//-- KG_KAGEHUMI -3023,0,0,0,5000,0,5000 -//-- KG_KYOMU -3024,0,0,0,10000:15000:20000:25000:30000,0,0 -//-- KG_KAGEMUSYA -3025,0,0,0,60000:90000:120000:15000:180000,0,0 -//-- OB_ZANGETSU -3026,0,0,0,60000:75000:90000:105000:120000,0,0 -//-- OB_OBOROGENSOU -3027,0,0,0,10000:15000:20000:25000:30000,0,0 -//-- OB_AKAITSUKI -3029,0,0,0,10000:15000:20000:25000:30000,0,0 +//-- KG_KAGEHUMI +3023,0,0,0,5000:6000:7000:8000:9000,0,0 +//-- KG_KYOMU +3024,0,1000,0,10000:15000:20000:25000:30000,0,20000 +//-- KG_KAGEMUSYA +3025,0,0,0,60000:90000:120000:150000:180000,0,0 + +//-- OB_ZANGETSU +3026,1000:1500:2000:2500:3000,1000,0,60000:75000:90000:105000:120000,0,30000 +//-- OB_OBOROGENSOU +3027,1000,0,0,10000:15000:20000:25000:30000,0,15000 +//-- OB_AKAITSUKI +3029,1000:1500:2000:2500:3000,1000,0,10000:15000:20000:25000:30000,0,30000 //========================================== +//-- ALL_FULL_THROTTLE +5014,0,0,0,10000:15000:20000:25000:30000,10000,20000:25000:30000:35000:40000 + //===== Homunculus Skills ================== //-- HLIF_HEAL 8001,0,2000,0,0,0,0 diff --git a/db/pre-re/skill_db.txt b/db/pre-re/skill_db.txt index 3635bca65..26030c867 100644 --- a/db/pre-re/skill_db.txt +++ b/db/pre-re/skill_db.txt @@ -660,7 +660,7 @@ 1003,0,0,0,0,0,0,1,0,no,0,0x1,0,weapon,0, AS_SONICACCEL,Sonic Acceleration 1004,9,8,1,0,0x8,0,1,1,no,0,0x1,0,weapon,0, AS_VENOMKNIFE,Throw Venom Knife 1005,1,6,1,0,0x1,0,1,1,no,0,0x1,0,weapon,0, RG_CLOSECONFINE,Close Confine -1006,0,6,4,3,0,2,1,1,yes,0,0x1,0,magic,3, WZ_SIGHTBLASTER,Sight Blaster +1006,0,6,4,3,0,1,1,1,yes,0,0x1,0,magic,3, WZ_SIGHTBLASTER,Sight Blaster 1007,0,6,4,0,0x1,0,1,0,no,0,0x1,0,none,0, SA_CREATECON,Create Elemental Converter 1008,9,6,1,1,0x1,0,1,1,yes,0,0x1,0,magic,0, SA_ELEMENTWATER,Elemental Change Water 1009,-9,6,1,0,0,0,1,1,no,0,0x1,0,weapon,3, HT_PHANTASMIC,Phantasmic Arrow @@ -680,15 +680,15 @@ //**** 2001,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0, RK_ENCHANTBLADE,Enchant Blade 2002,7:8:9:10:11,6,1,-1,0,0,5,1,no,0,0,0,weapon,0, RK_SONICWAVE,Sonic Wave -2003,0,6,4,0,0x1,0,10,1,no,0,0,0,weapon,0, RK_DEATHBOUND,Death Bound -2004,5,8,1,-1,0,0,10,-5,no,0,0,0,weapon,0, RK_HUNDREDSPEAR,Hundred Spear +2003,0,6,4,0,0x1,0,10,1,no,0,0,0,weapon,3, RK_DEATHBOUND,Death Bound +2004,1,8,1,-1,0,0,10,-5,no,0,0,0,weapon,0, RK_HUNDREDSPEAR,Hundred Spear 2005,1,6,2,4,0x2,2,5,1,no,0,0,0,weapon,3, RK_WINDCUTTER,Wind Cutter 2006,0,6,4,-1,0x2,5,5,1,no,0,0,0,weapon,0, RK_IGNITIONBREAK,Ignition Break 2007,0,0,0,0,0,0,5,0,no,0,0,0,weapon,0, RK_DRAGONTRAINING,Dragon Training 2008,9,6,2,3,0xC2,1:1:1:2:2:2:3:3:4:4,10,1,no,0,0,0,misc,0, RK_DRAGONBREATH,Dragon Breath -2009,0,6,4,0,0x3,3:4:5:6:7,5,1,no,0,0,0,none,0, RK_DRAGONHOWLING,Dragon Howling +2009,0,6,4,0,0x3,3:4:5:6:7,5,1,yes,0,0,0,none,0, RK_DRAGONHOWLING,Dragon Howling 2010,0,0,0,0,0,0,10,0,no,0,0,0,none,0, RK_RUNEMASTERY,Rune Mastery -2011,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, RK_MILLENNIUMSHIELD,Millenium Shield +2011,0,6,4,0,0x1,0,1,1,yes,0,0,0,none,0, RK_MILLENNIUMSHIELD,Millenium Shield 2012,1,6,4,-1,0,0x8,1,1,yes,0,0,0,weapon,0, RK_CRUSHSTRIKE,Crush Strike 2013,0,6,4,0,0x1,0,1,1,yes,0,0,0,none,0, RK_REFRESH,Refresh 2014,0,6,4,0,0x1,0,1,1,yes,0,0,0,none,0, RK_GIANTGROWTH,Giant Growth @@ -697,43 +697,7 @@ 2017,0,6,4,-1,0x2,3,1,1,no,0,0,0,weapon,7, RK_STORMBLAST,Storm Blast 2018,0,6,4,0,0x3,-1,1,1,yes,0,0,0,none,0, RK_FIGHTINGSPIRIT,Fighting Spirit //CHECK Is this splash needed? 2019,9,6,4,6,0x1,0,1,1,yes,0,0,0,none,0, RK_ABUNDANCE,Abundance -2020,5:6:7:8:9,6,16,-1,0,0,5,1,no,0,0,0,weapon,0, RK_PHANTOMTHRUST,Phantom Thrust - -//**** -// WL Warlock -//**** -2201,11,6,16,0,0,0,5,1,yes,0,0,0,magic,0, WL_WHITEIMPRISON,White Imprison -2202,11,8,1,8,0x2,1:1:1:2:2,5,-2,yes,0,0,0,magic,0, WL_SOULEXPANSION,Soul Expansion -2203,0,8,4,1,0x2,13,5,-3:-4:-5:-6:-7,yes,0,0,0,magic,0, WL_FROSTMISTY,Frosty Misty -2204,0,8,4,1,0x2,13,5,-5,yes,0,0,0,magic,0, WL_JACKFROST,Jack Frost -2205,11,6,1,0,0x1,0,5,1,yes,0,0,0,magic,0, WL_MARSHOFABYSS,Marsh of Abyss -2206,0,6,4,0,0x1,0,5,1,yes,0,0,0,magic,0, WL_RECOGNIZEDSPELL,Recognized Spell -2207,7,6,1,2,0x3,1:2:2:3:3,5,1,yes,0,0,0,magic,0, WL_SIENNAEXECRATE,Sienna Execrate -2208,0,0,0,0,0,0,3,0,no,0,0,0,none,0, WL_RADIUS,Radius -2209,0,6,4,0,0x3,9:10:11:12:13,5,1,yes,0,0,0,magic,0, WL_STASIS,Stasis -2210,11,6,1,0,0,0,5,1,yes,0,0,0,magic,0, WL_DRAINLIFE,Drain Life -2211,11,8,1,3,0x2,3,5,-7,yes,0,0,0,magic,3, WL_CRIMSONROCK,Crimson Rock -2212,11,6,1,3,0,0,5,1,yes,0,0,0,magic,0, WL_HELLINFERNO,Hell Inferno -2213,11,8,2,0,0x2,7,5,-20,yes,0,0,0,magic,2, WL_COMET,Comet -2214,11,6,1,0,0,3,5,1,yes,0,0,0,magic,0, WL_CHAINLIGHTNING,Chain Lightning //CHECK Is the splash being used for the target search? -2215,11,6,1,4,0,0,5,1,no,0,0,0,magic,0, WL_CHAINLIGHTNING_ATK,Chain Lightning Attack -2216,3,8,2,2,0,0,5,-6:-7:-8:-9:-10,yes,0,0,0,magic,0, WL_EARTHSTRAIN,Earth Strain -2217,11,6,1,0,0,0,5,1,yes,0,0,0,magic,0, WL_TETRAVORTEX,Tetra Vortex -2218,11,6,1,3,0,0,5,1,no,0,0,0,magic,0, WL_TETRAVORTEX_FIRE,Tetra Vortex Fire -2219,11,6,1,1,0,0,5,1,no,0,0,0,magic,0, WL_TETRAVORTEX_WATER,Tetra Vortex Water -2220,11,6,1,4,0,0,5,1,no,0,0,0,magic,0, WL_TETRAVORTEX_WIND,Tetra Vortex Wind -2221,11,6,1,2,0,0,5,1,no,0,0,0,magic,0, WL_TETRAVORTEX_GROUND,Tetra Vortex Earth -2222,0,6,4,3,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONFB,Summon Fire Ball -2223,0,6,4,4,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONBL,Summon Lightning Ball -2224,0,6,4,1,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONWB,Summon Water Ball -2225,11,6,1,3,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_FIRE,Summon Attack Fire //CHECK Summon attack ID's dont appear to have a range. -2226,11,6,1,4,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_WIND,Summon Attack Wind -2227,11,6,1,1,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_WATER,Summon Attack Water -2228,11,6,1,2,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_GROUND,Summon Attack Earth -2229,0,6,4,2,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONSTONE,Summon Stone -2230,11,8,1,0,0,0,2,1,yes,0,0,0,magic,0, WL_RELEASE,Release //CHECK Should it be left to do multi hit or single hit? -2231,0,6,4,0,0x1,0,1,1,yes,0,0,0,magic,0, WL_READING_SB,Reading Spellbook -2232,0,0,0,0,0,0,5,0,no,0,0,0,none,0, WL_FREEZE_SP,Freeze Spell +2020,5:6:7:8:9,6,1,-1,0,0,5,1,yes,0,0,0,weapon,0, RK_PHANTOMTHRUST,Phantom Thrust //**** // GC Guillotine Cross @@ -750,7 +714,7 @@ 2030,-2,6,4,-1,0x1,0,5,1,no,0,0x200,0,weapon,0, GC_WEAPONCRUSH,Weapon Crush //CHECK SHould this and the above skill have INF2 0x200? 2031,1,6,1,-1,0,0,5,1,no,0,0,0,weapon,0, GC_VENOMPRESSURE,Venom Pressure 2032,5,6,2,0,0x1,0,5,1,yes,0,0,1,none,0, GC_POISONSMOKE,Poison Smoke -2033,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, GC_CLOAKINGEXCEED,Cloaking Exceed +2033,0,6,4,0,0x1,0,5,1,no,0,0,0,weapon,0, GC_CLOAKINGEXCEED,Cloaking Exceed 2034,0,6,4,-1,0x2,3,1,1,no,0,0,0,weapon,0, GC_PHANTOMMENACE,Phantom Menace 2035,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, GC_HALLUCINATIONWALK,Hallucination Walk 2036,0,6,4,-1,0x2,1:1:1:1:2,5,1,no,0,0,0,weapon,0, GC_ROLLINGCUTTER,Rolling Cutter @@ -780,7 +744,41 @@ 2056,-1,6,1,0,0,0,10,1,no,0,0,0,magic,0, AB_DUPLELIGHT_MAGIC,Duple Light Magic 2057,0,6,4,6,0x3,4:5:6:7:8,5,1,yes,0,0,0,magic,0, AB_SILENTIUM,Silentium //CHECk Marked magic attack as well. Hmmmm.... -2515,11,6,16,0,0x1,0,5,1,yes,0,0,0,magic,0, AB_SECRAMENT,Secrament +//**** +// WL Warlock +//**** +2201,11,6,16,0,0,0,5,1,yes,0,0,0,magic,0, WL_WHITEIMPRISON,White Imprison +2202,11,8,1,8,0x2,1:1:1:2:2,5,-2,yes,0,0,0,magic,0, WL_SOULEXPANSION,Soul Expansion +2203,0,8,4,1,0x2,13,5,-3:-4:-5:-6:-7,yes,0,0,0,magic,0, WL_FROSTMISTY,Frosty Misty +2204,0,8,4,1,0x2,13,5,-5,yes,0,0,0,magic,0, WL_JACKFROST,Jack Frost +2205,11,6,1,0,0x1,0,5,1,yes,0,0,0,magic,0, WL_MARSHOFABYSS,Marsh of Abyss +2206,0,6,4,0,0x1,0,5,1,yes,0,0,0,magic,0, WL_RECOGNIZEDSPELL,Recognized Spell +2207,7,6,1,2,0x3,1:2:2:3:3,5,1,yes,0,0,0,magic,0, WL_SIENNAEXECRATE,Sienna Execrate +2208,0,0,0,0,0,0,3,0,no,0,0,0,none,0, WL_RADIUS,Radius +2209,0,6,4,0,0x3,9:10:11:12:13,5,1,yes,0,0,0,magic,0, WL_STASIS,Stasis +2210,11,6,1,0,0,0,5,1,yes,0,0,0,magic,0, WL_DRAINLIFE,Drain Life +2211,11,8,1,3,0x2,3,5,-7,yes,0,0,0,magic,3, WL_CRIMSONROCK,Crimson Rock +2212,11,6,1,3,0,0,5,1,yes,0,0,0,magic,0, WL_HELLINFERNO,Hell Inferno +2213,11,8,2,0,0,0,5,-20,yes,0,0,0,magic,2, WL_COMET,Comet +2214,11,6,1,0,0,3,5,1,yes,0,0,0,magic,0, WL_CHAINLIGHTNING,Chain Lightning +2215,11,6,1,4,0,0,5,1,no,0,0,0,magic,0, WL_CHAINLIGHTNING_ATK,Chain Lightning Attack +2216,3,8,2,2,0,0,5,-6:-7:-8:-9:-10,yes,0,0,0,magic,0, WL_EARTHSTRAIN,Earth Strain +2217,11,6,1,0,0,0,5,1,yes,0,0,0,magic,0, WL_TETRAVORTEX,Tetra Vortex +2218,11,6,1,3,0,0,5,1,no,0,0,0,magic,0, WL_TETRAVORTEX_FIRE,Tetra Vortex Fire +2219,11,6,1,1,0,0,5,1,no,0,0,0,magic,0, WL_TETRAVORTEX_WATER,Tetra Vortex Water +2220,11,6,1,4,0,0,5,1,no,0,0,0,magic,0, WL_TETRAVORTEX_WIND,Tetra Vortex Wind +2221,11,6,1,2,0,0,5,1,no,0,0,0,magic,0, WL_TETRAVORTEX_GROUND,Tetra Vortex Earth +2222,0,6,4,3,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONFB,Summon Fire Ball +2223,0,6,4,4,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONBL,Summon Lightning Ball +2224,0,6,4,1,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONWB,Summon Water Ball +2225,11,6,1,3,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_FIRE,Summon Attack Fire +2226,11,6,1,4,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_WIND,Summon Attack Wind +2227,11,6,1,1,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_WATER,Summon Attack Water +2228,11,6,1,2,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_GROUND,Summon Attack Earth +2229,0,6,4,2,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONSTONE,Summon Stone +2230,11,6,1,0,0,0,2,1,yes,0,0,0,magic,0, WL_RELEASE,Release +2231,0,6,4,0,0x1,0,1,1,yes,0,0,0,magic,0, WL_READING_SB,Reading Spellbook +2232,0,0,0,0,0,0,5,0,no,0,0,0,none,0, WL_FREEZE_SP,Freeze Spell //**** // RA Ranger @@ -911,9 +909,6 @@ 2346,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0, SR_GENTLETOUCH_ENERGYGAIN,Gentle Touch - Energy Gain 2347,2,6,16,0,0x1,0,5,1,yes,0,0,0,none,0, SR_GENTLETOUCH_CHANGE,Gentle Touch - Change 2348,2,6,16,0,0x1,0,5,1,yes,0,0,0,none,0, SR_GENTLETOUCH_REVITALIZE,Gentle Touch - Revitalize -//More from Sura but not following ID order -2517,0,6,4,-1,0x2,3:4:5:6:7,5,1,no,0,0,0,weapon,0, SR_HOWLINGOFLION,Howling of Lion -2518,11,6,2,-1,0x2,2:2:3:3:4,5,1,no,0,0,0,weapon,0, SR_RIDEINLIGHTNING,Ride In Lightening //**** // WA Wanderer @@ -931,7 +926,7 @@ // WM Wanderer/Minstrel 2412,0,0,0,0,0,0,10,0,no,0,0,0,none,0, WM_LESSON,Lesson 2413,9,8,1,-1,0,0,5,-2:-2:-3:-3:-4,yes,0,0,0,magic,0, WM_METALICSOUND,Metallic Sound -2414,9,6,2,-1,0x3,1,5,1,yes,0,0x80,3,none,0, WM_REVERBERATION,Reverberation +2414,9,6,2,-1,0x3,1,5,1,yes,0,0x80,3,none,0, WM_REVERBERATION,Reverberation 2415,0,6,1,-1,0x6,1,5,1,no,0,0,0,weapon,0, WM_REVERBERATION_MELEE,Reverberation Melee 2416,0,6,1,0,0x6,1,5,1,no,0,0,0,magic,0, WM_REVERBERATION_MAGIC,Reverberation Magic 2417,11,6,2,0,0x3,5,1,1,no,0,0,0,none,0, WM_DOMINION_IMPULSE,Dominion Impulse @@ -952,7 +947,6 @@ 2432,0,6,4,0,0x3,5,5,1,yes,0,0x4000,0,none,0, WM_MELODYOFSINK,Melody of Sink 2433,0,6,4,0,0x3,5,5,1,yes,0,0x4000,0,none,0, WM_BEYOND_OF_WARCRY,Warcry of Beyond 2434,0,6,4,0,0x3,5,5,1,yes,0,0x4000,0,none,0, WM_UNLIMITED_HUMMING_VOICE,Unlimited Humming Voice -2516,11,6,1,-1,0x2,5,5,1,no,0,0,0,weapon,0, WM_SEVERE_RAINSTORM_MELEE,Severe Rainstorm Melee //**** // SO Sorcerer @@ -1011,12 +1005,17 @@ 2497,0,6,4,0,0x1,0,10,1,no,0,0,0,none,0, GN_S_PHARMACY,Special Pharmacy 2498,11,6,1,0,0,0,1,1,no,0,0,0,weapon,0, GN_SLINGITEM_RANGEMELEEATK,Sling Item Attack +2515,11,6,16,0,0x1,0,5,1,yes,0,0,0,magic,0, AB_SECRAMENT,Secrament +2516,11,6,1,-1,0x2,5,5,1,no,0,0,0,weapon,0, WM_SEVERE_RAINSTORM_MELEE,Severe Rainstorm Melee +2517,0,6,4,-1,0x2,3:4:5:6:7,5,1,no,0,0,0,weapon,0, SR_HOWLINGOFLION,Howling of Lion +2518,11,6,2,-1,0x2,2:2:3:3:4,5,1,no,0,0,0,weapon,0, SR_RIDEINLIGHTNING,Ride In Lightening + // Episode 13.3 //2533,0,0,4,0,0x1,0,1,0,no,0,0,0,none,0, ALL_ODINS_RECALL,Odin's Recall -2534,0,0,4,0,0x1,0,1,0,no,0,0,0,none,0, RETURN_TO_ELDICASTES,Return To Eldicastes +2534,0,0,4,0,0x1,0,1,0,no,0,0,0,none,0, RETURN_TO_ELDICASTES,Return To Eldicastes 2535,0,0,4,0,0x1,0,1,0,no,0,0x1,0,none,0, ALL_BUYING_STORE,Open Buying Store -2536,0,0,4,0,0x1,0,1,0,no,0,0,0,none,0, ALL_GUARDIAN_RECALL,Guardian's Recall -//2537,9,6,16,0,0x1,0,2,1,yes,0,0,0,magic,0, ALL_ODINS_POWER,Odin's Power +2536,0,0,4,0,0x1,0,1,0,no,0,0,0,none,0, ALL_GUARDIAN_RECALL,Guardian's Recall +2537,9,6,16,0,0x1,0,2,1,yes,0,0,0,magic,0, ALL_ODINS_POWER,Odin's Power //2538,0,0,0,0,0,0,??,0,no,0,0,0,none,0, BEER_BOTTLE_CAP,Beer Bottle Cap //2539,0,0,0,0,0,0,??,0,no,0,0,0,none,0, NPC_ASSASSINCROSS,Assassin Cross of Sunset 2 //2540,0,0,0,0,0,0,??,0,no,0,0,0,none,0, NPC_DISSONANCE,Dissonance 2 @@ -1024,8 +1023,11 @@ //2542,0,0,0,0,0,0,??,0,no,0,0,0,none,0, ALL_TETANY,Tetany //2543,0,0,0,0,0,0,??,0,no,0,0,0,none,0, ALL_RAY_OF_PROTECTION,Ray of Protection //2544,0,0,0,0,0,0,??,0,no,0,0,0,none,0, MC_CARTDECORATE,Decorate Cart +//2545,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GM_ITEM_ATKMAX#Maximum Attack# +//2546,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GM_ITEM_ATKMIN#Minimal Attack# +//2547,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GM_ITEM_MATKMAX#Maximum Magic Attack# +//2548,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GM_ITEM_MATKMIN#Minimal Magic Attack# -//**** // Kagerou & Oboro 3001,0,6,4,0,0,0,1,1,no,0,0,0,none,0, KO_YAMIKUMO,Yamikumo 3002,0,0,0,0,0,0,5,0,no,0,0,0,weapon,0, KO_RIGHT,Right Hand Mastery @@ -1034,18 +1036,18 @@ 3005,2,6,1,-1,0,0,5,1,no,0,0,0,weapon,0, KO_SETSUDAN,Soul Sever 3006,7:8:9:10:11,6,2,0,0x2,2,5,0,no,0,0,0,weapon,0, KO_BAKURETSU,Bakuretsu Kunai 3007,0,6,4,-1,0x42,4:4:4:4:5,5,0,no,0,0,0,misc,0, KO_HAPPOKUNAI,Happo Kunai -3008,9,8,2,0,0x52,2,10,-10,no,0,0,0,misc,0, KO_MUCHANAGE,Mucha Nage +3008,9,8,2,0,0x12,2,10,-10,no,0,0,0,misc,0, KO_MUCHANAGE,Mucha Nage 3009,9:10:11:12:13,8,2,-1,0x2,3,5,2,no,0,0,0,weapon,0, KO_HUUMARANKA,Huuma Shuriken Ranka -3010,3,6,4,0,0x43,0,5,1,no,0,0x80,0,misc,0, KO_MAKIBISHI,Makibishi +3010,3,6,4,0,0x42,0,5,1,no,0,0x80,0,weapon,0, KO_MAKIBISHI,Makibishi 3011,0,6,4,0,0x1,0,5,0,yes,0,0,0,none,0, KO_MEIKYOUSISUI,Meikyo Shisui -3012,0,6,4,0,0x1,0,5,0,no,0,0,1,none,7, KO_ZANZOU,Zanzou +3012,0,6,4,0,0x1,0,5,0,no,0,0,1,none,3:4:5:6:7, KO_ZANZOU,Zanzou 3013,5,6,1,0,0x1,0,5,0,no,0,0,0,none,0, KO_KYOUGAKU,Kyougaku 3014,5,6,1,0,0x1,0,5,0,no,0,0,0,none,0, KO_JYUSATSU,Jyusatsu 3015,0,6,4,3,0x1,0,1,1,no,0,0,0,none,0, KO_KAHU_ENTEN,Kahu Enten 3016,0,6,4,1,0x1,0,1,1,no,0,0,0,none,0, KO_HYOUHU_HUBUKI,Hyouhu Hubuki 3017,0,6,4,4,0x1,0,1,1,no,0,0,0,none,0, KO_KAZEHU_SEIRAN,Kazehu Seiran 3018,0,6,4,2,0x1,0,1,1,no,0,0,0,none,0, KO_DOHU_KOUKAI,Dohu Koukai -3019,11,6,1,0,0,0,5,0,no,0,0,0,weapon,0, KO_KAIHOU,Technique Kaihou +3019,11,6,1,0,0,0,5,0,no,0,0,0,magic,0, KO_KAIHOU,Technique Kaihou 3020,7,6,2,0,0,0,1,3,yes,0,0,0,magic,0, KO_ZENKAI,Zenkai 3021,5:6:7:8:9,6,16,0,0x1,0,5,1,no,0,0,0,none,0, KO_GENWAKU,Genwaku 3022,0,6,4,0,0x1,0,5,0,no,0,0,0,none,0, KO_IZAYOI,Izayoi @@ -1054,9 +1056,36 @@ 3025,7,6,16,0,0x1,0,5,1,no,0,0,0,none,0, KG_KAGEMUSYA,Kagemusha 3026,7,6,16,0,0x1,0,5,1,no,0,0,0,none,0, OB_ZANGETSU,Zangetsu 3027,7,6,16,0,0x1,0,5,1,no,0,0,0,none,0, OB_OBOROGENSOU,Oboro Gensou -3028,1,6,4,0,0x2,3,1,1,no,0,0,0,weapon,0, OB_OBOROGENSOU_TRANSITION_ATK, +3028,1,6,4,0,0x2,3,1,1,no,0,0,0,weapon,0, OB_OBOROGENSOU_TRANSITION_ATK,Hazy Moonlight Illusion Transition Attack 3029,7,6,1,0,0x1,0,5,0,no,0,0,0,none,0, OB_AKAITSUKI,Akaitsuki +// Eclage Skills +3031,7,6,16,0,0x1,0,1,1,no,0,0,0,none,0, ECL_SNOWFLIP,Snow Flip +3032,7,6,16,0,0x1,0,1,1,no,0,0,0,none,0, ECL_PEONYMAMY,Peony Mamy +3033,7,6,16,0,0x1,0,1,1,no,0,0,0,none,0, ECL_SADAGUI,Sadagui +3034,7,6,16,0,0x1,0,1,1,no,0,0,0,none,0, ECL_SEQUOIADUST,Sequoia Dust +3035,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, ECLAGE_RECALL,Return To Eclage + +// EP 14.3 Part 2 3rd Job Skills +5001,1,6,1,-1,0,0,5,1,no,0,0,0,weapon,0, GC_DARKCROW,Dark Claw +5002,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, RA_UNLIMIT,Unlimited +//5003,7,6,1,-1,0x2,4:5:6:7:8,5,1,no,0,0,0,weapon,0, GN_ILLUSIONDOPING,Illusion Doping +5004,9,6,2,1,0x2,1:1:1:2:2:2:3:3:4:4,10,1,no,0,0,0,misc,0, RK_DRAGONBREATH_WATER,Dragon Breath - Water +//5005,0,6,4,0,0x3,3,1,1,no,0,0,0,none,0, RK_LUXANIMA,Lux Anima +5006,1,6,2,3,0,0,5,1,no,0,0,3,misc,0, NC_MAGMA_ERUPTION,Magma Eruption +5007,0,6,4,0,0x3,5:6:7:8:9,5,1,no,0,0,0,none,0, WM_FRIGG_SONG,Frigg's Song +//5008,0,6,4,0,0x3,15,5,1,no,0,0,0,none,0, SO_ELEMENTAL_SHIELD,Elemental Shield +5009,1,6,1,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO,Flash Combo +//5010,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SC_ESCAPE,Emergency Escape +5011,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, AB_OFFERTORIUM,Offertorium +5012,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, WL_TELEKINESIS_INTENSE,Intense Telekinesis +5013,0,6,4,0,0x3,5,5,1,no,0,0,0,none,0, LG_KINGS_GRACE,King's Grace +5014,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, ALL_FULL_THROTTLE,Full Throttle +5015,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO_ATK_STEP1,Flash Combo Attack Step 1 +5016,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO_ATK_STEP2,Flash Combo Attack Step 2 +5017,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO_ATK_STEP3,Flash Combo Attack Step 3 +5018,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO_ATK_STEP4,Flash Combo Attack Step 4 + 8001,9,6,4,0,0x1,0,5,1,no,0,0,0,magic,0, HLIF_HEAL,Healing Touch 8002,0,6,4,0,0x3,-1,5,1,no,0,0,0,none,0, HLIF_AVOID,Avoid 8003,0,0,0,0,0,1,5,0,no,0,0,0,none,0, HLIF_BRAIN,Brain Surgery diff --git a/db/pre-re/skill_require_db.txt b/db/pre-re/skill_require_db.txt index b8e549b08..3eb00ff95 100644 --- a/db/pre-re/skill_require_db.txt +++ b/db/pre-re/skill_require_db.txt @@ -820,6 +820,26 @@ 3027,0,0,55:60:65:70:75 ,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //OB_OBOROGENSOU#Oboro Gensou# 3029,0,0,20:30:40:50:60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //OB_AKAITSUKI#Akaitsuki# +// EP 14.3 Part 2 3rd Job Skills +5001,0,0,22:34:46:58:70,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GC_DARKCROW#Dark Claw# +5002,0,0,100:120:140:160:180,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimited# +5003,0,0,60:70:80:90:100,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_ILLUSIONDOPING#Illusion Doping# +5004,0,0,30:35:40:45:50:55:60:65:70:75,0,0,0,99,0,0,dragon,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath - Water# +5005,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_LUXANIMA#Lux Anima# +5006,0,0,60:70:80:90:100,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# +5007,0,0,200:230:260:290:320,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG#Frigg's Song# +5008,0,0,120:120:120:120:120,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_ELEMENTAL_SHIELD#Elemental Shield# +5009,0,0,75:65:55:45:35,0,0,0,99,0,0,none,5:5:4:4:3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO#Flash Combo# +5010,0,0,30:26:22:18:14,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SC_ESCAPE#Emergency Escape# +5011,0,0,30:60:90:120:150,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AB_OFFERTORIUM#Offertorium# +5012,0,0,100:150:200:250:300,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WL_TELEKINESIS_INTENSE#Intense Telekinesis# +5013,0,0,200:180:160:140:120,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +5014,0,0,1:1:1:1:1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# +5015,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP1#Flash Combo Attack Step 1#//All 4 steps are using temp req SP values for now. +5016,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP2#Flash Combo Attack Step 2# +5017,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP3#Flash Combo Attack Step 3# +5018,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP4#Flash Combo Attack Step 4# + 10010,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_BATTLEORDER## 10011,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_REGENERATION## 10012,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_RESTORE## diff --git a/db/pre-re/skill_tree.txt b/db/pre-re/skill_tree.txt index f1954a2bc..f10c29dbb 100644 --- a/db/pre-re/skill_tree.txt +++ b/db/pre-re/skill_tree.txt @@ -2483,6 +2483,8 @@ 4054,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4054,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4054,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4054,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4054,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Warlock (Regular) 4055,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4055,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2539,6 +2541,8 @@ 4055,2230,2,0,0,0,0,0,0,0,0,0,0 //WL_RELEASE#Release# 4055,2231,1,0,0,0,0,0,0,0,0,0,0 //WL_READING_SB#Reading Spellbook# 4055,2232,5,0,0,0,0,0,0,0,0,0,0 //WL_FREEZE_SP#Freeze Spell# +4055,5012,5,2202,5,0,0,0,0,0,0,0,0 //WL_TELEKINESIS_INTENSE#Intense Telekinesis# +4055,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Ranger (Regular) 4056,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4056,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2592,6 +2596,8 @@ 4056,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4056,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4056,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4056,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4056,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Arch Bishop (Regular) 4057,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4057,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2650,6 +2656,8 @@ 4057,2054,10,68,1,0,0,0,0,0,0,0,0 //AB_DUPLELIGHT#Duple Light# 4057,2057,5,2052,1,0,0,0,0,0,0,0,0 //AB_SILENTIUM#Silentium# 4057,2515,5,2044,1,2053,1,0,0,0,0,0,0 //AB_SECRAMENT#Secrament# +4057,5011,5,2051,2,0,0,0,0,0,0,0,0 //AB_OFFERTORIUM#Offertorium# +4057,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Mechanic (Regular) 4058,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4058,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2718,7 +2726,9 @@ 4058,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4058,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4058,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4058,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4058,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4058,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Guillotine Cross (Regular) 4059,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4059,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2763,6 +2773,8 @@ 4059,2035,5,2034,1,0,0,0,0,0,0,0,0 //GC_HALLUCINATIONWALK#Hallucination Walk# 4059,2036,5,136,10,0,0,0,0,0,0,0,0 //GC_ROLLINGCUTTER#Rolling Cutter# 4059,2037,5,2036,1,0,0,0,0,0,0,0,0 //GC_CROSSRIPPERSLASHER#Cross Ripper Slasher# +4059,5001,5,2023,5,0,0,0,0,0,0,0,0 //GC_DARKCROW#Dark Claw# +4059,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Rune Knight (Trans) 4060,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4060,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2809,6 +2821,8 @@ 4060,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4060,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4060,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4060,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4060,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Warlock (Trans) 4061,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4061,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2871,6 +2885,8 @@ 4061,2230,2,0,0,0,0,0,0,0,0,0,0 //WL_RELEASE#Release# 4061,2231,1,0,0,0,0,0,0,0,0,0,0 //WL_READING_SB#Reading Spellbook# 4061,2232,5,0,0,0,0,0,0,0,0,0,0 //WL_FREEZE_SP#Freeze Spell# +4061,5012,5,2202,5,0,0,0,0,0,0,0,0 //WL_TELEKINESIS_INTENSE#Intense Telekinesis# +4061,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Ranger (Trans) 4062,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4062,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2928,6 +2944,8 @@ 4062,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4062,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4062,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4062,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4062,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Arch Bishop (Trans) 4063,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4063,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2990,6 +3008,8 @@ 4063,2054,10,68,1,0,0,0,0,0,0,0,0 //AB_DUPLELIGHT#Duple Light# 4063,2057,5,2052,1,0,0,0,0,0,0,0,0 //AB_SILENTIUM#Silentium# 4063,2515,5,2044,1,2053,1,0,0,0,0,0,0 //AB_SECRAMENT#Secrament# +4063,5011,5,2051,2,0,0,0,0,0,0,0,0 //AB_OFFERTORIUM#Offertorium# +4063,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Mechanic (Trans) 4064,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4064,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3063,7 +3083,9 @@ 4064,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4064,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4064,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4064,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4064,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4064,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Guillotine Cross (Trans) 4065,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4065,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3113,6 +3135,8 @@ 4065,2035,5,2034,1,0,0,0,0,0,0,0,0 //GC_HALLUCINATIONWALK#Hallucination Walk# 4065,2036,5,136,10,0,0,0,0,0,0,0,0 //GC_ROLLINGCUTTER#Rolling Cutter# 4065,2037,5,2036,1,0,0,0,0,0,0,0,0 //GC_CROSSRIPPERSLASHER#Cross Ripper Slasher# +4065,5001,5,2023,5,0,0,0,0,0,0,0,0 //GC_DARKCROW#Dark Claw# +4065,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Royal Guard (Regular) 4066,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4066,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3166,6 +3190,8 @@ 4066,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4066,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4066,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4066,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4066,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Sorcerer (Regular) 4067,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4067,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3236,6 +3262,7 @@ 4067,2466,3,2458,3,0,0,0,0,0,0,0,0 //SO_WATER_INSIGNIA#Water Insignia# 4067,2467,3,2459,3,0,0,0,0,0,0,0,0 //SO_WIND_INSIGNIA#Wind Insignia# 4067,2468,3,2460,3,0,0,0,0,0,0,0,0 //SO_EARTH_INSIGNIA#Earth Insignia# +4067,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Minstrel (Regular) 4068,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4068,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3291,6 +3318,8 @@ 4068,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4068,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4068,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4068,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4068,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Wanderer (Regular) 4069,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4069,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3346,6 +3375,8 @@ 4069,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4069,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4069,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4069,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4069,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Sura (Regular) 4070,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4070,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3405,6 +3436,8 @@ 4070,2348,5,2347,5,0,0,0,0,0,0,0,0 //SR_GENTLETOUCH_REVITALIZE#Gentle Touch - Revitalize# 4070,2517,5,2340,1,2518,3,0,0,0,0,0,0 //SR_HOWLINGOFLION#Howling Of Lion# 4070,2518,5,267,3,0,0,0,0,0,0,0,0 //SR_RIDEINLIGHTNING#Ride In Lightening# +4070,5009,5,2326,3,2329,3,2330,1,2327,1,0,0 //SR_FLASHCOMBO#Flash Combo# +4070,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Genetic (Regular) 4071,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4071,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3459,7 +3492,9 @@ 4071,2495,2,2497,1,0,0,0,0,0,0,0,0 //GN_MIX_COOKING#Mix Cooking# 4071,2496,2,2495,1,0,0,0,0,0,0,0,0 //GN_MAKEBOMB#Create Bomb# 4071,2497,10,0,0,0,0,0,0,0,0,0,0 //GN_S_PHARMACY#Special Pharmacy# +4071,5003,5,2497,1,0,0,0,0,0,0,0,0 //GN_ILLUSIONDOOPING#Hallucination Drug# 4071,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4071,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Shadow Chaser (Regular) 4072,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4072,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3517,6 +3552,8 @@ 4072,2302,3,2296,3,2301,3,0,0,0,0,0,0 //SC_MAELSTROM#Maelstrom# 4072,2303,3,2300,3,0,0,0,0,0,0,0,0 //SC_BLOODYLUST#Bloody Lust# 4072,2304,3,2300,3,0,0,0,0,0,0,0,0 //SC_FEINTBOMB#Feint Bomb# +4072,5010,5,2288,2,0,0,0,0,0,0,0,0 //SC_SCAPE#Scape# +4072,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Royal Guard (Trans) 4073,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4073,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3574,6 +3611,8 @@ 4073,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4073,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4073,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4073,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4073,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Sorcerer (Trans) 4074,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4074,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3652,6 +3691,7 @@ 4074,2466,3,2458,3,0,0,0,0,0,0,0,0 //SO_WATER_INSIGNIA#Water Insignia# 4074,2467,3,2459,3,0,0,0,0,0,0,0,0 //SO_WIND_INSIGNIA#Wind Insignia# 4074,2468,3,2460,3,0,0,0,0,0,0,0,0 //SO_EARTH_INSIGNIA#Earth Insignia# +4074,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Minstrel (Trans) 4075,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4075,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3713,6 +3753,8 @@ 4075,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4075,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4075,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4075,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4075,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Wanderer (Trans) 4076,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4076,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3774,6 +3816,8 @@ 4076,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4076,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4076,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4076,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4076,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Sura (Trans) 4077,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4077,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3837,6 +3881,8 @@ 4077,2348,5,2347,5,0,0,0,0,0,0,0,0 //SR_GENTLETOUCH_REVITALIZE#Gentle Touch - Revitalize# 4077,2517,5,2340,1,2518,3,0,0,0,0,0,0 //SR_HOWLINGOFLION#Howling Of Lion# 4077,2518,5,267,3,0,0,0,0,0,0,0,0 //SR_RIDEINLIGHTNING#Ride In Lightening# +4077,5009,5,2326,3,2329,3,2330,1,2327,1,0,0 //SR_FLASHCOMBO#Flash Combo# +4077,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Genetic (Trans) 4078,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4078,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3895,7 +3941,9 @@ 4078,2495,2,2497,1,0,0,0,0,0,0,0,0 //GN_MIX_COOKING#Mix Cooking# 4078,2496,2,2495,1,0,0,0,0,0,0,0,0 //GN_MAKEBOMB#Create Bomb# 4078,2497,10,0,0,0,0,0,0,0,0,0,0 //GN_S_PHARMACY#Special Pharmacy# +4078,5003,5,2497,1,0,0,0,0,0,0,0,0 //GN_ILLUSIONDOOPING#Hallucination Drug# 4078,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4078,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Shadow Chaser (Trans) 4079,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4079,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3941,6 +3989,7 @@ 4079,2286,10,2285,5,0,0,0,0,0,0,0,0 //SC_AUTOSHADOWSPELL#Auto Shadow Spell# 4079,2287,5,213,3,0,0,0,0,0,0,0,0 //SC_SHADOWFORM#Shadow Form# 4079,2288,10,46,7,0,0,0,0,0,0,0,0 //SC_TRIANGLESHOT#Triangle Shot# +4079,5010,5,2288,2,0,0,0,0,0,0,0,0 //SC_SCAPE#Scape# 4079,2289,5,0,0,0,0,0,0,0,0,0,0 //SC_BODYPAINT#Body Painting# 4079,2290,5,2286,7,2291,5,2296,3,0,0,0,0 //SC_INVISIBILITY#Invisibility# 4079,2291,5,2286,5,2287,3,0,0,0,0,0,0 //SC_DEADLYINFECT#Deadly Infect# @@ -3957,6 +4006,7 @@ 4079,2302,3,2296,3,2301,3,0,0,0,0,0,0 //SC_MAELSTROM#Maelstrom# 4079,2303,3,2300,3,0,0,0,0,0,0,0,0 //SC_BLOODYLUST#Bloody Lust# 4079,2304,3,2300,3,0,0,0,0,0,0,0,0 //SC_FEINTBOMB#Feint Bomb# +4079,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Rune Knight (Dragon) (Regular) 4080,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4080,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3995,6 +4045,8 @@ 4080,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4080,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4080,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4080,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4080,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Rune Knight (Dragon) (Trans) 4081,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4081,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4041,6 +4093,8 @@ 4081,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4081,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4081,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4081,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4081,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Royal Guard (Gryphon) (Regular) 4082,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4082,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4094,6 +4148,8 @@ 4082,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4082,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4082,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4082,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4082,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Royal Guard (Gryphon) (Trans) 4083,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4083,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4151,6 +4207,8 @@ 4083,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4083,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4083,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4083,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4083,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Ranger (Warg) (Regular) 4084,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4084,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4204,6 +4262,8 @@ 4084,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4084,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4084,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4084,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4084,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Ranger (Warg) (Trans) 4085,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4085,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4261,6 +4321,8 @@ 4085,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4085,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4085,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4085,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4085,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Mechanic (Mado) (Regular) 4086,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4086,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4329,7 +4391,9 @@ 4086,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4086,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4086,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4086,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4086,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4086,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Mechanic (Mado) (Trans) 4087,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4087,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4403,7 +4467,9 @@ 4087,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4087,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4087,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4087,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4087,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4087,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Rune Knight 4096,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4096,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4443,6 +4509,8 @@ 4096,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4096,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4096,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4096,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4096,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Warlock 4097,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4097,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4500,6 +4568,8 @@ 4097,2230,2,0,0,0,0,0,0,0,0,0,0 //WL_RELEASE#Release# 4097,2231,1,0,0,0,0,0,0,0,0,0,0 //WL_READING_SB#Reading Spellbook# 4097,2232,5,0,0,0,0,0,0,0,0,0,0 //WL_FREEZE_SP#Freeze Spell# +4097,5012,5,2202,5,0,0,0,0,0,0,0,0 //WL_TELEKINESIS_INTENSE#Intense Telekinesis# +4097,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Ranger 4098,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4098,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4554,6 +4624,8 @@ 4098,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4098,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4098,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4098,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4098,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Arch Bishop 4099,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4099,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4613,6 +4685,8 @@ 4099,2054,10,68,1,0,0,0,0,0,0,0,0 //AB_DUPLELIGHT#Duple Light# 4099,2057,5,2052,1,0,0,0,0,0,0,0,0 //AB_SILENTIUM#Silentium# 4099,2515,5,2044,1,2053,1,0,0,0,0,0,0 //AB_SECRAMENT#Secrament# +4099,5011,5,2051,2,0,0,0,0,0,0,0,0 //AB_OFFERTORIUM#Offertorium# +4099,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Mechanic 4100,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4100,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4682,7 +4756,9 @@ 4100,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4100,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4100,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4100,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4100,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4100,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Guillotine Cross 4101,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4101,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4728,6 +4804,8 @@ 4101,2035,5,2034,1,0,0,0,0,0,0,0,0 //GC_HALLUCINATIONWALK#Hallucination Walk# 4101,2036,5,136,10,0,0,0,0,0,0,0,0 //GC_ROLLINGCUTTER#Rolling Cutter# 4101,2037,5,2036,1,0,0,0,0,0,0,0,0 //GC_CROSSRIPPERSLASHER#Cross Ripper Slasher# +4101,5001,5,2023,5,0,0,0,0,0,0,0,0 //GC_DARKCROW#Dark Claw# +4101,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Royal Guard 4102,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4102,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4782,6 +4860,8 @@ 4102,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4102,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4102,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4102,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4102,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Sorcerer 4103,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4103,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4853,6 +4933,7 @@ 4103,2466,3,2458,3,0,0,0,0,0,0,0,0 //SO_WATER_INSIGNIA#Water Insignia# 4103,2467,3,2459,3,0,0,0,0,0,0,0,0 //SO_WIND_INSIGNIA#Wind Insignia# 4103,2468,3,2460,3,0,0,0,0,0,0,0,0 //SO_EARTH_INSIGNIA#Earth Insignia# +4103,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Minstrel 4104,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4104,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4909,6 +4990,8 @@ 4104,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4104,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4104,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4104,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4104,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Wanderer 4105,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4105,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4965,6 +5048,8 @@ 4105,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4105,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4105,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4105,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4105,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Sura 4106,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4106,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5025,6 +5110,8 @@ 4106,2348,5,2347,5,0,0,0,0,0,0,0,0 //SR_GENTLETOUCH_REVITALIZE#Gentle Touch - Revitalize# 4106,2517,5,2340,1,2518,3,0,0,0,0,0,0 //SR_HOWLINGOFLION#Howling Of Lion# 4106,2518,5,267,3,0,0,0,0,0,0,0,0 //SR_RIDEINLIGHTNING#Ride In Lightening# +4106,5009,5,2326,3,2329,3,2330,1,2327,1,0,0 //SR_FLASHCOMBO#Flash Combo# +4106,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Genetic 4107,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4107,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5080,7 +5167,9 @@ 4107,2495,2,2497,1,0,0,0,0,0,0,0,0 //GN_MIX_COOKING#Mix Cooking# 4107,2496,2,2495,1,0,0,0,0,0,0,0,0 //GN_MAKEBOMB#Create Bomb# 4107,2497,10,0,0,0,0,0,0,0,0,0,0 //GN_S_PHARMACY#Special Pharmacy# +4107,5003,5,2497,1,0,0,0,0,0,0,0,0 //GN_ILLUSIONDOOPING#Hallucination Drug# 4107,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4107,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Shadow Chaser 4108,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4108,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5139,6 +5228,8 @@ 4108,2302,3,2296,3,2301,3,0,0,0,0,0,0 //SC_MAELSTROM#Maelstrom# 4108,2303,3,2300,3,0,0,0,0,0,0,0,0 //SC_BLOODYLUST#Bloody Lust# 4108,2304,3,2300,3,0,0,0,0,0,0,0,0 //SC_FEINTBOMB#Feint Bomb# +4108,5010,5,2288,2,0,0,0,0,0,0,0,0 //SC_SCAPE#Scape# +4108,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Rune Knight (Dragon) 4109,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4109,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5178,6 +5269,8 @@ 4109,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4109,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4109,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4009,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4109,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Royal Guard (Gryphon) 4110,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4110,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5232,6 +5325,8 @@ 4110,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4110,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4110,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4110,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4110,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Ranger (Warg) 4111,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4111,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5286,6 +5381,8 @@ 4111,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4111,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4111,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4111,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4111,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Mechanic (Mado) 4112,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4112,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5355,7 +5452,9 @@ 4112,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4112,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4112,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4112,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4112,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4112,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Super Novice (Expanded) 4190,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4190,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# diff --git a/db/pre-re/skill_unit_db.txt b/db/pre-re/skill_unit_db.txt index 388bfd341..f02c3c231 100644 --- a/db/pre-re/skill_unit_db.txt +++ b/db/pre-re/skill_unit_db.txt @@ -103,8 +103,8 @@ 2032,0xe1, , 2, 0,1000,enemy, 0x018 //GC_POISONSMOKE -2214,0x86, , 0, 5, 100,enemy, 0x080 //WL_CHAINLIGHTNING -2216,0xcb, , -1, 0, 150,enemy, 0x018 //WL_EARTHSTRAIN +2213,0x86, , 0, 8, 100,enemy, 0x018 //WL_COMET +2216,0xcb, , -1, 0, 100,enemy, 0x018 //WL_EARTHSTRAIN 2238,0xd8, , 0, 1,1000,enemy, 0x006 //RA_ELECTRICSHOCKER 2239,0xd9, , 0, 1,1000,enemy, 0x006 //RA_CLUSTERBOMB @@ -156,7 +156,10 @@ 3008,0x86, , 0, 2, 100,enemy, 0x018 //KO_MUCHANAGE 3009,0x86, , 0, 3, 500,enemy, 0x018 //KO_HUUMARANKA 3020,0xf8, , 0, 3, 100,all, 0x018 //KO_ZENKAI -3010,0xfc, , 0, 1,1000,enemy, 0x020 //KO_MAKIBISHI +3010,0xfc, , 0, 0,5000,enemy, 0x018 //KO_MAKIBISHI + +5006,0x101, , 0, 3,2000,enemy, 0x018 //NC_MAGMA_ERUPTION +5010,0xfe, , 0, 2, -1,enemy, 0x000 //SC_SCAPE 8020,0xf5, , 0, 3,2300:2100:1900:1700:1500,enemy, 0x018 //MH_POISON_MIST 8033,0x7e, , 0, 0, -1,all, 0x003 //MH_STEINWAND @@ -172,7 +175,7 @@ 8403,0xed, , -1, 1,1000,enemy, 0x018 //EL_FIRE_MANTLE 8406,0xee, , 0, 1, -1,friend,0x018 //EL_WATER_BARRIER -8409,0xef, , 0, 1, -1,friend,0x018 //EL_ZEPHYR +8409,0xef, , 0, 1,1000,friend,0x018 //EL_ZEPHYR 8412,0xf0, , 0, 1, -1,friend,0x018 //EL_POWER_OF_GAIA 10006,0xc1, , 2, 0, -1,sameguild, 0x040 //GD_LEADERSHIP diff --git a/db/re/item_combo_db.txt b/db/re/item_combo_db.txt index 26b955d9b..71e544107 100644 --- a/db/re/item_combo_db.txt +++ b/db/re/item_combo_db.txt @@ -115,7 +115,7 @@ 2472:2570:15030:16013,{ bonus2 bAddRace,RC_Undead,15; bonus2 bMagicAddRace,RC_Undead,15; bonus2 bSkillAtk,"AB_ADORAMUS",100; } 2472:2570:15030:16018,{ bonus2 bAddRace,RC_Undead,30; bonus2 bMagicAddRace,RC_Undead,30; bonus2 bSkillAtk,"AB_ADORAMUS",200; bonus bVariableCastrate,-50; } 2475:2574:2883:15036,{ bonus bMaxHPRate,14; bonus2 bSkillAtk,"RK_HUNDREDSPEAR",50; skill "CR_AUTOGUARD",1; } -2476:2575:2884:15037,{ bonus2 bAddRace,RC_NonBoss,10; bonus2 bAddRace,RC_Boss,10; bonus2 bSkillAtk,"RK_SONICWAVE",100; bonus2 bSkillAtk,"RK_WINDCUTTER",100; autobonus "{ sc_start SC_CONCENTRATION,10000,getskilllv(\"LK_CONCENTRATION\")?getskilllv(\"LK_CONCENTRATION\"):1; bonus bAspd,2; }",1,10000,BF_WEAPON,"{}"; } +2476:2575:2884:15037,{ bonus2 bAddRace,RC_NonBoss,10; bonus2 bAddRace,RC_Boss,10; bonus2 bSkillAtk,"RK_SONICWAVE",100; bonus2 bSkillAtk,"RK_WINDCUTTER",100; autobonus "{ sc_start SC_LKCONCENTRATION,10000,getskilllv(\"LK_CONCENTRATION\")?getskilllv(\"LK_CONCENTRATION\"):1; bonus bAspd,2; }",1,10000,BF_WEAPON,"{}"; } 2477:2577:2886:15038,{ bonus bCritical,15; bonus bFlee,10; bonus bCritAtkRate,40; bonus2 bSkillAtk,"GC_CROSSIMPACT",20; } 2478:2578:2887:15039,{ bonus2 bAddRace,RC_NonBoss,10; bonus2 bAddRace,RC_Boss,10; bonus bMatk,10; if(readparam(bStr)>119) { bonus bBaseAtk,30; } bonus3 bAutoSpell,"ASC_BREAKER",getskilllv("ASC_BREAKER"),10; bonus bCritical,-20; } 2479:2580:2890:15042,{ bonus bAspd,2; bonus bLongAtkRate,30; bonus3 bAutoSpell,"AC_DOUBLE",3,10; bonus2 bSkillAtk,"RA_ARROWSTORM",50; } diff --git a/db/re/item_db.txt b/db/re/item_db.txt index 5dccc5442..52b872afc 100644 --- a/db/re/item_db.txt +++ b/db/re/item_db.txt @@ -31,8 +31,8 @@ 521,Leaflet_Of_Aloe,Aloe Leaflet,0,360,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),0; },{},{} 522,Fruit_Of_Mastela,Mastela Fruit,0,8500,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(400,600),0; },{},{} 523,Holy_Water,Holy Water,0,20,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_Curse; },{},{} -525,Panacea,Panacea,0,500,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} -526,Royal_Jelly,Royal Jelly,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} +525,Panacea,Panacea,0,500,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} +526,Royal_Jelly,Royal Jelly,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} 528,Monster's_Feed,Monster's Feed,0,60,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(72,108),0; },{},{} 529,Candy,Candy,0,10,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(45,65),0; },{},{} 530,Candy_Striper,Candy Cane,0,20,,40,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(105,145),0; },{},{} @@ -71,14 +71,14 @@ 563,Pizza_01,Doublecrust Swiss Fondue,0,1200,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(375,445),0; },{},{} 564,Rice_Ball,Rice Ball,0,1,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal 200,0; },{},{} 565,Vita500_Bottle,Vita500,0,580,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(142,274),0; },{},{} -566,Tomyumkung,Tom Yum Goong,0,10000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(244,350),rand(10,30); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} +566,Tomyumkung,Tom Yum Goong,0,10000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(244,350),rand(10,30); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} 567,Prawn,Shrimp,0,500,,40,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(117,192),0; },{},{} 568,Lemon,Lemon,0,60,,40,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal 0,rand(10,20); },{},{} 569,Novice_Potion,Novice Potion,0,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(44,66),0; },{},{} 570,Lucky_Candy,Lucky Candy,0,10,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(45,65),0; },{},{} 571,Lucky_Candy_Cane,Lucky Candy Cane,0,20,,40,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(105,145),0; },{},{} 572,Lucky_Cookie,Lucky Cookie,0,1000,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(160,200),0; },{},{} -573,Chocolate_Drink,Chocolate Drink,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(330,410),rand(45,65); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} +573,Chocolate_Drink,Chocolate Drink,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(330,410),rand(45,65); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} 574,Egg,Egg,0,20,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(33,42),0; },{},{} 575,Piece_Of_Cake_,2nd Anniversary Cake,0,10,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(270,330),0; },{},{} 576,Prickly_Fruit,Prickly Fruit,0,540,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(150,300),rand(20,30); },{},{} @@ -88,7 +88,7 @@ 580,Bread,Bread,0,150,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(50,90),0; },{},{} 581,Mushroom,Edible Mushroom,0,40,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(20,30),0; },{},{} 582,Orange,Orange,0,300,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(10,20),rand(10,20); },{},{} -583,KETUPAT_,Ketupat Sayur,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} +583,KETUPAT_,Ketupat Sayur,0,7000,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} 584,Fish_Ball_Soup,Fish Cake Soup,0,100,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(40,70),0; },{},{} 585,Wurst,Brusti,0,2,,40,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(15,20),0; },{},{} 586,Mother's_Cake,Mother's Cake,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),0; },{},{} @@ -96,11 +96,11 @@ 588,Spaghetti,Spaghetti,0,100,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(40,70),0; },{},{} 589,Pizza_02,Pizza,0,1200,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(375,445),0; },{},{} 590,Brezel_,Pretzel,0,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(50,90),0; },{},{} -591,Caviar_Pancake,Caviar Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} -592,Jam_Pancake,Jam Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} -593,Honey_Pancake,Honey Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} -594,Sour_Cream_Pancake,Sour-Cream Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} -595,Mushroom_Pancake,Mushroom Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_Hallucination; },{},{} +591,Caviar_Pancake,Caviar Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} +592,Jam_Pancake,Jam Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} +593,Honey_Pancake,Honey Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} +594,Sour_Cream_Pancake,Sour-Cream Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} +595,Mushroom_Pancake,Mushroom Pancake,0,0,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(325,405),rand(40,60); sc_end SC_Poison; sc_end SC_Silence; sc_end SC_Blind; sc_end SC_Confusion; sc_end SC_Curse; sc_end SC_ILLUSION; },{},{} 596,Cute_Strawberry_Choco,Cute Strawberry-Choco,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal 0,rand(1,100); },{},{} 597,Lovely_Choco_Tart,Lovely Choco-Tart,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(10,400),0; },{},{} 598,Light_Red_Pot,Light Red Potion,0,50,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemheal rand(45,65),0; },{},{} @@ -153,15 +153,15 @@ 644,Gift_Box,Gift Box,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_GiftBox),1; },{},{} //ASPD in RE they give a fixed +4/+6/+9 ASPD -645,Center_Potion,Concentration Potion,2,800,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ASPDPOTION0,1800000,4; },{},{} -656,Awakening_Potion,Awakening Potion,2,1500,,150,,,,,0xFFF7FEEF,7,2,,,40,,,{ sc_start SC_ASPDPOTION1,1800000,6; },{},{} -657,Berserk_Potion,Berserk Potion,2,3000,,200,,,,,0x01E646A6,7,2,,,85,,,{ sc_start SC_ASPDPOTION2,1800000,9; },{},{} +645,Center_Potion,Concentration Potion,2,800,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATTHASTE_POTION1,1800000,4; },{},{} +656,Awakening_Potion,Awakening Potion,2,1500,,150,,,,,0xFFF7FEEF,7,2,,,40,,,{ sc_start SC_ATTHASTE_POTION2,1800000,6; },{},{} +657,Berserk_Potion,Berserk Potion,2,3000,,200,,,,,0x01E646A6,7,2,,,85,,,{ sc_start SC_ATTHASTE_POTION3,1800000,9; },{},{} 658,Union_Of_Tribe,Union of Tribe,2,2,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ guildgetexp rand(600000,1200000); },{},{} 659,Heart_Of_Her,Her Heart,2,500,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1188; },{},{} 660,Prohibition_Red_Candle,Forbidden Red Candle,2,20000,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1200; },{},{} 661,Sway_Apron,Soft Apron,2,20000,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1275; },{},{} -662,Inspector_Certificate,Authoritative Badge,2,1450,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,180000,0; },{},{} +662,Inspector_Certificate,Authoritative Badge,2,1450,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,180000,0; },{},{} 663,Korea_Rice_Cake,Korean Rice Cake,0,1,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 10,0; },{},{} 664,Gift_Box_1,Gift Box,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_GiftBox_1),1; },{},{} 665,Gift_Box_2,Gift Box,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_GiftBox_2),1; },{},{} @@ -177,13 +177,13 @@ 675,Silver_Coin,Silver Coin,3,5000,,40,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 676,Silver_Coin_Moneybag,Bag of Silver Coins,3,50000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 677,White_Gold_Coin,Platinum Coin,3,2000,,40,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -678,Poison_Bottle,Poison Bottle,2,5000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ if(Class == Job_Assassin_Cross || Class == Job_Guillotine_Cross || Class == Job_Guillotine_Cross_T) { sc_start SC_DPoison,60000,0; sc_start SC_ASPDPOTION3,60000,9; } else percentheal -100,-100; },{},{} +678,Poison_Bottle,Poison Bottle,2,5000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ if(Class == Job_Assassin_Cross || Class == Job_Guillotine_Cross || Class == Job_Guillotine_Cross_T) { sc_start SC_DPoison,60000,0; sc_start SC_ATTHASTE_INFINITY,60000,9; } else percentheal -100,-100; },{},{} 679,Gold_Pill,Pilule,2,5000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ if(rand(1000)<100) sc_start SC_DPoison,10000,0; sc_start SC_Poison,50000,0; },{},{} 680,Magical_Carnation,Magic Carnation,0,0,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,20; },{},{} 681,Memory_Of_Wedding,Sweet Memory of Marriage,2,50000,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if (getpartnerid()) sc_start SC_WEDDING,600000,0; },{},{} -682,Realgar_Wine,Distilled Fighting Spirit,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,60000,30; },{},{} -683,Exorcize_Herb,Herb of Incantation,2,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MATKPOTION,60000,30; },{},{} -684,Durian,Durian,2,15000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,60000,10; sc_start SC_MATKPOTION,60000,10; },{},{} +682,Realgar_Wine,Distilled Fighting Spirit,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,60000,30; },{},{} +683,Exorcize_Herb,Herb of Incantation,2,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSMAGICPOWER,60000,30; },{},{} +684,Durian,Durian,2,15000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,60000,10; sc_start SC_PLUSMAGICPOWER,60000,10; },{},{} 685,RAMADAN,Ramadan,0,5000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,50; },{},{} 686,Earth_Scroll_1_3,Level 3 Earth Spike,11,1000,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_EARTHSPIKE",3; },{},{} 687,Earth_Scroll_1_5,Level 5 Earth Spike,11,2000,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_EARTHSPIKE",5; },{},{} @@ -1638,7 +1638,7 @@ 2603,Necklace,Necklace,5,30000,,100,,0,,0,0xFFFFFFFE,7,2,136,,20,0,0,{ bonus bVit,2; },{},{} 2604,Glove,Glove,5,30000,,100,,0,,0,0xFFFFFFFE,7,2,136,,20,0,0,{ bonus bDex,2; },{},{} 2605,Brooch,Brooch,5,30000,,100,,0,,0,0xFFFFFFFE,7,2,136,,20,0,0,{ bonus bAgi,2; },{},{} -2607,Clip,Clip,5,30000,,100,,0,,1,0xFFFFFFFF,7,2,136,,0,0,0,{ bonus bMaxSP,10; },{},{} +2607,Clip,Clip,5,30000,,100,,0,,1,0xFFFFFFFF,7,2,136,,0,0,0,{ bonus bMaxSP,10; bonus bMaxHP,2; },{},{} 2608,Rosary,Rosary,5,15000,,100,,0,,0,0xFFFFFFFE,7,2,136,,20,0,0,{ bonus bMdef,5; bonus bLuk,2; },{},{} 2609,Skul_Ring,Skull Ring,5,10000,,100,,0,,0,0xFFFFFFFF,7,2,136,,0,0,0,{},{},{} 2610,Gold_Ring,Gold Ring,5,30000,,100,,0,,0,0xFFFFFFFF,7,2,136,,0,0,0,{},{},{} @@ -5312,7 +5312,7 @@ 12013,Shadow_Arrow_Container,Shadow Arrow Quiver,2,2,,250,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 1767,500; },{},{} 12014,Imma_Arrow_Container,Immaterial Arrow Quiver,2,2,,250,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 1757,500; },{},{} 12015,Rusty_Arrow_Container,Rusty Arrow Quiver,2,2,,250,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 1762,500; },{},{} -12016,Speed_Up_Potion,Speed Potion,2,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp1,5000,0; },{},{} +12016,Speed_Up_Potion,Speed Potion,2,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_INFINITY,5000,0; },{},{} 12017,Slow_Down_Potion,Slow Potion,2,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SlowDown,5000,0; },{},{} 12018,Fire_Cracker,Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} 12019,Holy_Egg,Holy Egg,11,2,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "ALL_RESURRECTION",2; },{},{} @@ -5324,10 +5324,10 @@ 12025,Egg_Boy,Dano Festival Egg,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_EggBoy),1; },{},{} 12026,Egg_Girl,Dano Festival Egg,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_EggGirl),1; },{},{} 12027,Giggling_Box,Giggling Box,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 9,0; if(rand(1000)<300) sc_start SC_Curse,30000,0; },{},{} -12028,Box_Of_Thunder,Box of Thunder,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,20000,0; },{},{} +12028,Box_Of_Thunder,Box of Thunder,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,20000,0; },{},{} 12029,Gloomy_Box,Box of Gloom,11,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "AC_CONCENTRATION",1; },{},{} -12030,Box_Of_Grudge,Box of Resentment,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,60000,20; },{},{} -12031,Sleepy_Box,Box of Drowsiness,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MATKPOTION,60000,20; },{},{} +12030,Box_Of_Grudge,Box of Resentment,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,60000,20; },{},{} +12031,Sleepy_Box,Box of Drowsiness,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSMAGICPOWER,60000,20; },{},{} 12032,Box_Of_Storm,Box of Storms,11,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "ITEM_ENCHANTARMS",2; },{},{} 12033,Box_Of_Sunlight,Box of Sunlight,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_Intravision,30000,0; },{},{} 12034,Painting_Box,Box of Panting,2,1000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,9; if(rand(1000)<300) sc_start SC_Silence,30000,0; },{},{} @@ -5337,66 +5337,66 @@ 12038,Lotto_Box04,Lotto Box 04,2,0,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_LottoBox),1; },{},{} 12039,Lotto_Box05,Lotto Box 05,2,0,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem rand(7542,7546),1; },{},{} 12040,Stone_Of_Intelligence_,Stone of Sage,2,100000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ homevolution; },{},{} -12041,Str_Dish01,Fried Grasshopper Legs,0,2000,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,1; percentheal 5,0; },{},{} -12042,Str_Dish02,Seasoned Sticky Webfoot,0,4000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,2; percentheal 5,0; },{},{} -12043,Str_Dish03,Bomber Steak,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,3; percentheal 5,0; },{},{} -12044,Str_Dish04,Herb Marinade Beef,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,4; percentheal 5,0; },{},{} -12045,Str_Dish05,Lutie Lady's Pancake,0,10000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,5; percentheal 10,0; },{},{} -12046,Int_Dish01,Grape Juice Herbal Tea,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,1; percentheal 0,5; },{},{} -12047,Int_Dish02,Autumn Red Tea,0,4000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,2; percentheal 0,5; },{},{} -12048,Int_Dish03,Honey Herbal Tea,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,3; percentheal 0,5; },{},{} -12049,Int_Dish04,Morroc Fruit Wine,0,8000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,4; percentheal 0,5; },{},{} -12050,Int_Dish05,Mastela Fruit Wine,0,10000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,5; percentheal 0,10; },{},{} -12051,Vit_Dish01,Steamed Crab Nippers,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,1; percentheal 5,0; },{},{} -12052,Vit_Dish02,Assorted Seafood,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,2; percentheal 5,0; },{},{} -12053,Vit_Dish03,Clam Soup,0,6000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,3; percentheal 5,0; },{},{} -12054,Vit_Dish04,Seasoned Jellyfish,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,4; percentheal 5,0; },{},{} -12055,Vit_Dish05,Spicy Fried Bao,0,10000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,5; percentheal 10,0; },{},{} -12056,Agi_Dish01,Frog Egg Squid Ink Soup,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,1; percentheal 3,1; },{},{} -12057,Agi_Dish02,Smooth Noodle,0,4000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,2; percentheal 3,1; },{},{} -12058,Agi_Dish03,Tentacle Cheese Gratin,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,3; percentheal 3,1; },{},{} -12059,Agi_Dish04,Lutie Cold Noodle,0,8000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,4; percentheal 3,1; },{},{} -12060,Agi_Dish05,Steamed Bat Wing in Pumpkin,0,10000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,5; percentheal 6,2; },{},{} -12061,Dex_Dish01,Honey Grape Juice,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,1; percentheal 2,2; },{},{} -12062,Dex_Dish02,Chocolate Mousse Cake,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,2; percentheal 2,2; },{},{} -12063,Dex_Dish03,Fruit Mix,0,6000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,3; percentheal 2,2; },{},{} -12064,Dex_Dish04,Cream Sandwich,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,4; percentheal 2,2; },{},{} -12065,Dex_Dish05,Green Salad,0,10000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,5; percentheal 5,5; },{},{} -12066,Luk_Dish01,Fried Monkey Tails,0,2000,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,1; percentheal 3,2; },{},{} -12067,Luk_Dish02,Mixed Juice,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,2; percentheal 3,2; },{},{} -12068,Luk_Dish03,Fried Sweet Potato,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,3; percentheal 4,2; },{},{} -12069,Luk_Dish04,Steamed Ancient Lips,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,4; percentheal 4,2; },{},{} -12070,Luk_Dish05,Fried Scorpion Tails,0,10000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,5; percentheal 5,2; },{},{} -12071,Str_Dish06,Shiny Marinade Beef,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,6; percentheal 10,2; },{},{} -12072,Str_Dish07,Whole Roast,0,40000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,7; percentheal 10,4; },{},{} -12073,Str_Dish08,Bearfoot Special,0,60000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,8; percentheal 15,6; },{},{} -12074,Str_Dish09,Tendon Satay,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,9; percentheal 15,8; },{},{} -12075,Str_Dish10,Steamed Tongue,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,10; percentheal 20,20; },{},{} -12076,Int_Dish06,Red Mushroom Wine,0,20000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,6; percentheal 2,10; },{},{} -12077,Int_Dish07,Special Royal Jelly Herbal Tea,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,7; percentheal 4,10; },{},{} -12078,Int_Dish08,Royal Family Tea,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,8; percentheal 6,10; },{},{} -12079,Int_Dish09,Tristan XII,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,9; percentheal 8,15; },{},{} -12080,Int_Dish10,Dragon Breath Cocktail,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,10; percentheal 10,20; },{},{} -12081,Vit_Dish06,Awfully Bitter Bracer,0,20000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,6; percentheal 13,0; },{},{} -12082,Vit_Dish07,Sumptuous Feast,0,40000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,7; percentheal 16,0; },{},{} -12083,Vit_Dish08,Giant Burito,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,8; percentheal 19,0; },{},{} -12084,Vit_Dish09,Ascending Dragon Soup,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,9; percentheal 22,0; },{},{} -12085,Vit_Dish10,Immortal Stew,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,10; percentheal 25,0; },{},{} -12086,Agi_Dish06,Chile Shrimp Gratin,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,6; percentheal 7,2; },{},{} -12087,Agi_Dish07,Steamed Alligator with Vegetable,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,7; percentheal 8,2; },{},{} -12088,Agi_Dish08,Incredibly Spicy Curry,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,8; percentheal 9,2; },{},{} -12089,Agi_Dish09,Special Meat Stew,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,9; percentheal 10,2; },{},{} -12090,Agi_Dish10,Steamed Desert Scorpions,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,10; percentheal 15,5; },{},{} -12091,Dex_Dish06,Peach Cake,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,6; percentheal 5,6; },{},{} -12092,Dex_Dish07,Soul Haunted Bread,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,7; percentheal 5,7; },{},{} -12093,Dex_Dish08,Special Toast,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,8; percentheal 5,8; },{},{} -12094,Dex_Dish09,Heavenly Fruit Juice,0,80000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,9; percentheal 5,9; },{},{} -12095,Dex_Dish10,Hwergelmir's Tonic,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,10; percentheal 10,10; },{},{} -12096,Luk_Dish06,Lucky Soup,0,20000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,6; percentheal 6,3; },{},{} -12097,Luk_Dish07,Assorted Shish Kebob,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,7; percentheal 7,3; },{},{} -12098,Luk_Dish08,Strawberry Flavored Rice Ball,0,60000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,8; percentheal 9,3; },{},{} -12099,Luk_Dish09,Blood Flavored Soda,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,9; percentheal 10,4; },{},{} -12100,Luk_Dish10,Cooked Nine Tail's Tails,0,100000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,10; percentheal 14,8; },{},{} +12041,Str_Dish01,Fried Grasshopper Legs,0,2000,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,1; percentheal 5,0; },{},{} +12042,Str_Dish02,Seasoned Sticky Webfoot,0,4000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,2; percentheal 5,0; },{},{} +12043,Str_Dish03,Bomber Steak,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,3; percentheal 5,0; },{},{} +12044,Str_Dish04,Herb Marinade Beef,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,4; percentheal 5,0; },{},{} +12045,Str_Dish05,Lutie Lady's Pancake,0,10000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,5; percentheal 10,0; },{},{} +12046,Int_Dish01,Grape Juice Herbal Tea,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,1; percentheal 0,5; },{},{} +12047,Int_Dish02,Autumn Red Tea,0,4000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,2; percentheal 0,5; },{},{} +12048,Int_Dish03,Honey Herbal Tea,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,3; percentheal 0,5; },{},{} +12049,Int_Dish04,Morroc Fruit Wine,0,8000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,4; percentheal 0,5; },{},{} +12050,Int_Dish05,Mastela Fruit Wine,0,10000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,5; percentheal 0,10; },{},{} +12051,Vit_Dish01,Steamed Crab Nippers,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,1; percentheal 5,0; },{},{} +12052,Vit_Dish02,Assorted Seafood,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,2; percentheal 5,0; },{},{} +12053,Vit_Dish03,Clam Soup,0,6000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,3; percentheal 5,0; },{},{} +12054,Vit_Dish04,Seasoned Jellyfish,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,4; percentheal 5,0; },{},{} +12055,Vit_Dish05,Spicy Fried Bao,0,10000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,5; percentheal 10,0; },{},{} +12056,Agi_Dish01,Frog Egg Squid Ink Soup,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,1; percentheal 3,1; },{},{} +12057,Agi_Dish02,Smooth Noodle,0,4000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,2; percentheal 3,1; },{},{} +12058,Agi_Dish03,Tentacle Cheese Gratin,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,3; percentheal 3,1; },{},{} +12059,Agi_Dish04,Lutie Cold Noodle,0,8000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,4; percentheal 3,1; },{},{} +12060,Agi_Dish05,Steamed Bat Wing in Pumpkin,0,10000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,5; percentheal 6,2; },{},{} +12061,Dex_Dish01,Honey Grape Juice,0,2000,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,1; percentheal 2,2; },{},{} +12062,Dex_Dish02,Chocolate Mousse Cake,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,2; percentheal 2,2; },{},{} +12063,Dex_Dish03,Fruit Mix,0,6000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,3; percentheal 2,2; },{},{} +12064,Dex_Dish04,Cream Sandwich,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,4; percentheal 2,2; },{},{} +12065,Dex_Dish05,Green Salad,0,10000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,5; percentheal 5,5; },{},{} +12066,Luk_Dish01,Fried Monkey Tails,0,2000,,60,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,1; percentheal 3,2; },{},{} +12067,Luk_Dish02,Mixed Juice,0,4000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,2; percentheal 3,2; },{},{} +12068,Luk_Dish03,Fried Sweet Potato,0,6000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,3; percentheal 4,2; },{},{} +12069,Luk_Dish04,Steamed Ancient Lips,0,8000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,4; percentheal 4,2; },{},{} +12070,Luk_Dish05,Fried Scorpion Tails,0,10000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,5; percentheal 5,2; },{},{} +12071,Str_Dish06,Shiny Marinade Beef,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,6; percentheal 10,2; },{},{} +12072,Str_Dish07,Whole Roast,0,40000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,7; percentheal 10,4; },{},{} +12073,Str_Dish08,Bearfoot Special,0,60000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,8; percentheal 15,6; },{},{} +12074,Str_Dish09,Tendon Satay,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,9; percentheal 15,8; },{},{} +12075,Str_Dish10,Steamed Tongue,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,10; percentheal 20,20; },{},{} +12076,Int_Dish06,Red Mushroom Wine,0,20000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,6; percentheal 2,10; },{},{} +12077,Int_Dish07,Special Royal Jelly Herbal Tea,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,7; percentheal 4,10; },{},{} +12078,Int_Dish08,Royal Family Tea,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,8; percentheal 6,10; },{},{} +12079,Int_Dish09,Tristan XII,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,9; percentheal 8,15; },{},{} +12080,Int_Dish10,Dragon Breath Cocktail,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,10; percentheal 10,20; },{},{} +12081,Vit_Dish06,Awfully Bitter Bracer,0,20000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,6; percentheal 13,0; },{},{} +12082,Vit_Dish07,Sumptuous Feast,0,40000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,7; percentheal 16,0; },{},{} +12083,Vit_Dish08,Giant Burito,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,8; percentheal 19,0; },{},{} +12084,Vit_Dish09,Ascending Dragon Soup,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,9; percentheal 22,0; },{},{} +12085,Vit_Dish10,Immortal Stew,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,10; percentheal 25,0; },{},{} +12086,Agi_Dish06,Chile Shrimp Gratin,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,6; percentheal 7,2; },{},{} +12087,Agi_Dish07,Steamed Alligator with Vegetable,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,7; percentheal 8,2; },{},{} +12088,Agi_Dish08,Incredibly Spicy Curry,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,8; percentheal 9,2; },{},{} +12089,Agi_Dish09,Special Meat Stew,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,9; percentheal 10,2; },{},{} +12090,Agi_Dish10,Steamed Desert Scorpions,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,10; percentheal 15,5; },{},{} +12091,Dex_Dish06,Peach Cake,0,20000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,6; percentheal 5,6; },{},{} +12092,Dex_Dish07,Soul Haunted Bread,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,7; percentheal 5,7; },{},{} +12093,Dex_Dish08,Special Toast,0,60000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,8; percentheal 5,8; },{},{} +12094,Dex_Dish09,Heavenly Fruit Juice,0,80000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,9; percentheal 5,9; },{},{} +12095,Dex_Dish10,Hwergelmir's Tonic,0,100000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,10; percentheal 10,10; },{},{} +12096,Luk_Dish06,Lucky Soup,0,20000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,6; percentheal 6,3; },{},{} +12097,Luk_Dish07,Assorted Shish Kebob,0,40000,,800,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,7; percentheal 7,3; },{},{} +12098,Luk_Dish08,Strawberry Flavored Rice Ball,0,60000,,400,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,8; percentheal 9,3; },{},{} +12099,Luk_Dish09,Blood Flavored Soda,0,80000,,1000,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,9; percentheal 10,4; },{},{} +12100,Luk_Dish10,Cooked Nine Tail's Tails,0,100000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,10; percentheal 14,8; },{},{} 12101,Citron,Citron,0,20,,300,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12102,Meat_Skewer,Grilled Skewer,0,20,,300,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12103,Bloody_Dead_Branch,Bloody Branch,2,10000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ monster "this",-1,-1,"--ja--",-3,1,""; },{},{} @@ -5418,8 +5418,8 @@ 12119,Resist_Water,Coldproof Potion,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start4 SC_ARMOR_ELEMENT,1200000,20,0,0,-15; },{},{} 12120,Resist_Earth,Earthproof Potion,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start4 SC_ARMOR_ELEMENT,1200000,0,20,-15,0; },{},{} 12121,Resist_Wind,Thunderproof Potion,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start4 SC_ARMOR_ELEMENT,1200000,0,-15,0,20; },{},{} -12122,Sesame_Pastry,Sesame Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_HITFOOD,1200000,30; },{},{} -12123,Honey_Pastry,Honey Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FLEEFOOD,1200000,30; },{},{} +12122,Sesame_Pastry,Sesame Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_BASICHIT,1200000,30; },{},{} +12123,Honey_Pastry,Honey Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_BASICAVOIDANCE,1200000,30; },{},{} 12124,Rainbow_Cake,Rainbow Cake,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_BATKFOOD,1200000,10; sc_start SC_MATKFOOD,120000,10; },{},{} 12125,Outdoor_Cooking_Kits,Outdoor Cooking Kit,2,500,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ cooking 11; },{},{} 12126,Indoor_Cooking_Kits,Home Cooking Kit,2,1000,,30,,,,,0xFFFFFFFF,7,2,,,,,,{ cooking 12; },{},{} @@ -5438,7 +5438,7 @@ 12139,3rd_Stage_Prize,Third Stage Prize,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12140,4th_Stage_Prize,Fourth Stage Prize,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12141,5th_Stage_Prize,Fifth Stage Prize,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -12142,Magic_Book,Book of Magic,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1800000,10; },{},{} +12142,Magic_Book,Book of Magic,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1800000,10; },{},{} 12143,Red_Can,Red Can,2,50000,,300,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12144,Sphere_Case_Wind,Lightning Sphere Pack,2,2,,350,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 13204,500; },{},{} 12145,Sphere_Case_Darkness,Blind Sphere Pack,2,2,,350,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 13206,500; },{},{} @@ -5505,66 +5505,66 @@ 12205,Dex_Dish10_,Hwergelmir's Tonic,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX_CASH,1800000,10; percentheal 15,5; },{},{} 12206,Luk_Dish10_,Cooked Nine Tail's Tails,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK_CASH,1800000,10; percentheal 15,5; },{},{} 12207,Vit_Dish10_,Stew Of Immortality,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT_CASH,1800000,10; percentheal 15,5; },{},{} -12208,Battle_Manual,Battle Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,1800000,50; },{},{} -12209,Insurance,Life Insurance,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LIFEINSURANCE,1800000,0; },{},{} -12210,Bubble_Gum,Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMBOOST,1800000,200; },{},{} +12208,Battle_Manual,Battle Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,1800000,50; },{},{} +12209,Insurance,Life Insurance,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_DEATHPENALTY,1800000,0; },{},{} +12210,Bubble_Gum,Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_RECEIVEITEM,1800000,200; },{},{} 12211,Kafra_Card,Kafra Card,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashStore"; },{},{} 12212,Giant_Fly_Wing,Giant Fly Wing,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashPartyCall"; },{},{} 12213,Neuralizer,Neuralizer,11,2,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashReset"; },{},{} -12214,Convex_Mirror,Convex Mirror,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_BOSSMAPINFO,600000,0; },{},{} +12214,Convex_Mirror,Convex Mirror,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_BOSS_ALARM,600000,0; },{},{} 12215,Blessing_10_Scroll,LV10 Blessing Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ skilleffect "AL_BLESSING",0; sc_start SC_BLESSING,240000,10; },{},{} -12216,Inc_Agi_10_Scroll,LV10 Agil Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if(Hp>15) { skilleffect "AL_INCAGI",0; sc_start SC_INCREASEAGI,240000,10; heal -15,0; } },{},{} +12216,Inc_Agi_10_Scroll,LV10 Agil Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if(Hp>15) { skilleffect "AL_INCAGI",0; sc_start SC_INC_AGI,240000,10; heal -15,0; } },{},{} 12217,Aspersio_5_Scroll,LV5 Aspersio Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if(countitem(523)>0) { skilleffect "PR_ASPERSIO",0; sc_start SC_ASPERSIO,180000,5; delitem 523,1; } },{},{} 12218,Assumptio_5_Scroll,LV5 Assumptio Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ASSUMPTIO,100000,5; skilleffect "HP_ASSUMPTIO",0; },{},{} 12219,Wind_Walk_10_Scroll,LV10 Wind Walker Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ skilleffect "SN_WINDWALK",0; sc_start SC_WINDWALK,250000,5; },{},{} 12220,Adrenaline_Scroll,LV5 Adrenaline Scroll,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ set .@type,getiteminfo(getequipid(EQI_HAND_R),11); if (.@type==6||.@type==7||.@type==8) { skilleffect "BS_ADRENALINE",0; sc_start SC_ADRENALINE,150000,5; } },{},{} 12221,Megaphone_,Megaphone,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ input @megaphone$; announce strcharinfo(0) + ": " + @megaphone$,bc_all,0xFF0000; end; },{},{} 12225,Sweet_Candy_Striper,Sweet Candy Cane,2,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1245; },{},{} -12226,Examination1,Examination 1,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,5400000,0; percentheal 100,100; sc_start SC_STRFOOD,5400000,10; sc_start SC_DEXFOOD,5400000,5; sc_start SC_ATKPOTION,5400000,22; sc_start SC_MATKFOOD,5400000,15; },{},{} -12227,Examination2,Examination 2,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,5400000,0; percentheal 100,100; sc_start SC_INTFOOD,5400000,8; sc_start SC_VITFOOD,5400000,7; sc_start SC_LUKFOOD,5400000,7; sc_start SC_ATKPOTION,5400000,10; },{},{} -12228,Examination3,Examination 3,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,5400000,0; percentheal 100,100; sc_start SC_AGIFOOD,5400000,15; sc_start SC_ATKPOTION,5400000,52; sc_start SC_MATKFOOD,5400000,10; },{},{} -12229,Examination4,Examination 4,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,5400000,0; percentheal 100,100; sc_start SC_STRFOOD,5400000,3; sc_start SC_AGIFOOD,5400000,5; sc_start SC_VITFOOD,5400000,10; sc_start SC_MATKFOOD,5400000,52; },{},{} -12230,Examination5,Examination 5,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,5400000,0; percentheal 100,100; sc_start SC_INTFOOD,5400000,3; sc_start SC_DEXFOOD,5400000,12; sc_start SC_ATKPOTION,5400000,20; sc_start SC_MATKFOOD,5400000,20; },{},{} -12231,Examination6,Examination 6,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,100; sc_start SC_SpeedUp0,5400000,0; sc_start SC_STRFOOD,5400000,6; sc_start SC_DEXFOOD,5400000,6; sc_start SC_AGIFOOD,5400000,6; sc_start SC_INTFOOD,5400000,6; sc_start SC_VITFOOD,5400000,6; sc_start SC_LUKFOOD,5400000,6; sc_start SC_ATKPOTION,5400000,24; sc_start SC_MATKFOOD,5400000,24; },{},{} -12232,Gingerbread,Ginger Bread,2,20,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ASPDPOTION1,900000,0; sc_start SC_SpeedUp0,900000,0; },{},{} +12226,Examination1,Examination 1,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,5400000,0; percentheal 100,100; sc_start SC_FOOD_STR,5400000,10; sc_start SC_FOOD_DEX,5400000,5; sc_start SC_PLUSATTACKPOWER,5400000,22; sc_start SC_MATKFOOD,5400000,15; },{},{} +12227,Examination2,Examination 2,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,5400000,0; percentheal 100,100; sc_start SC_FOOD_INT,5400000,8; sc_start SC_FOOD_VIT,5400000,7; sc_start SC_FOOD_LUK,5400000,7; sc_start SC_PLUSATTACKPOWER,5400000,10; },{},{} +12228,Examination3,Examination 3,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,5400000,0; percentheal 100,100; sc_start SC_FOOD_AGI,5400000,15; sc_start SC_PLUSATTACKPOWER,5400000,52; sc_start SC_MATKFOOD,5400000,10; },{},{} +12229,Examination4,Examination 4,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,5400000,0; percentheal 100,100; sc_start SC_FOOD_STR,5400000,3; sc_start SC_FOOD_AGI,5400000,5; sc_start SC_FOOD_VIT,5400000,10; sc_start SC_MATKFOOD,5400000,52; },{},{} +12230,Examination5,Examination 5,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,5400000,0; percentheal 100,100; sc_start SC_FOOD_INT,5400000,3; sc_start SC_FOOD_DEX,5400000,12; sc_start SC_PLUSATTACKPOWER,5400000,20; sc_start SC_MATKFOOD,5400000,20; },{},{} +12231,Examination6,Examination 6,0,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,100; sc_start SC_MOVHASTE_HORSE,5400000,0; sc_start SC_FOOD_STR,5400000,6; sc_start SC_FOOD_DEX,5400000,6; sc_start SC_FOOD_AGI,5400000,6; sc_start SC_FOOD_INT,5400000,6; sc_start SC_FOOD_VIT,5400000,6; sc_start SC_FOOD_LUK,5400000,6; sc_start SC_PLUSATTACKPOWER,5400000,24; sc_start SC_MATKFOOD,5400000,24; },{},{} +12232,Gingerbread,Ginger Bread,2,20,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATTHASTE_POTION2,900000,0; sc_start SC_MOVHASTE_HORSE,900000,0; },{},{} 12233,Kvass,Kvass,0,20,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,100; },{},{} 12234,Cacao99,Fierce Cacao 99%,0,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 25,0; },{},{} 12235,Strawberry_Choco,Chocolate Strawberry,2,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,5; skilleffect "AL_BLESSING",0; sc_start SC_BLESSING,240000,10; },{},{} 12236,Choco_Tart,Chocolate Tart,11,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,0; itemskill "AL_ANGELUS",5; },{},{} -12237,Choco_Lump,Junky Chocolate,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,5; sc_start SC_Poison,18000,0; sc_start SC_Bleeding,18000,0; },{},{} +12237,Choco_Lump,Junky Chocolate,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,5; sc_start SC_Poison,18000,0; sc_start SC_BLOODING,18000,0; },{},{} 12238,New_Year_Rice_Cake_1,New Year Rice Cake,2,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ if(rand(1000)<100) sc_start SC_DPoison,10000,0; sc_start SC_Poison,50000,0; },{},{} 12239,New_Year_Rice_Cake_2,New Year Rice Cake,2,20,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ if(rand(1000)<100) sc_start SC_DPoison,10000,0; sc_start SC_Poison,50000,0; },{},{} 12240,Old_Yellow_Box,Old Yellow Box,2,20,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_YellowBox),1; },{},{} -12241,M_Center_Potion,Mercenary Concentration Potion,2,800,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ASPDPOTION0,1800000,0; },{},{} -12242,M_Awakening_Potion,Mercenary Awakening Potion,2,1500,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ASPDPOTION1,1800000,0; },{},{} -12243,M_Berserk_Potion,Mercenary Berserk Potion,2,3000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ASPDPOTION2,1800000,0; },{},{} +12241,M_Center_Potion,Mercenary Concentration Potion,2,800,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ATTHASTE_POTION1,1800000,0; },{},{} +12242,M_Awakening_Potion,Mercenary Awakening Potion,2,1500,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ATTHASTE_POTION2,1800000,0; },{},{} +12243,M_Berserk_Potion,Mercenary Berserk Potion,2,3000,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ mercenary_sc_start SC_ATTHASTE_POTION3,1800000,0; },{},{} 12244,Old_Gift_Box,Old Gift Box,2,20,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_OldGiftBox),1; },{},{} 12245,Green_Ale_US,Green Ale,0,5000,,500,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,0; },{},{} 12246,Magic_Card_Album,Mystical Card Album,2,10000,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_MagicCardAlbum),1; },{},{} 12247,Halohalo,Halo-Halo,2,2,,100,,,,,0xFFFFFFFF,7,2,,,20,,,{ sc_start SC_INCALLSTATUS,600000,3; },{},{} 12248,Masquerade_Ball_Box,Fancy Ball Box,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_Masquerade),1; },{},{} 12249,Payroll_Of_Kafra_,Payment Statement for Kafra Employee,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -12250,Str_Dish10_M,Steamed Tongue,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,3600000,10; percentheal 20,20; },{},{} -12251,Agi_Dish10_M,Steamed Desert Scorpions,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,3600000,10; percentheal 15,5; },{},{} -12252,Int_Dish10_M,Dragon Breath Cocktail,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,3600000,10; percentheal 10,20; },{},{} -12253,Dex_Dish10_M,Hwergelmir's Tonic,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,3600000,10; percentheal 10,10; },{},{} -12254,Luk_Dish10_M,Cooked Nine Tail,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,3600000,10; percentheal 14,8; },{},{} -12255,Vit_Dish10_M,Immortal Stew,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,3600000,10; percentheal 25,0; },{},{} +12250,Str_Dish10_M,Steamed Tongue,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,3600000,10; percentheal 20,20; },{},{} +12251,Agi_Dish10_M,Steamed Desert Scorpions,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,3600000,10; percentheal 15,5; },{},{} +12252,Int_Dish10_M,Dragon Breath Cocktail,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,3600000,10; percentheal 10,20; },{},{} +12253,Dex_Dish10_M,Hwergelmir's Tonic,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,3600000,10; percentheal 10,10; },{},{} +12254,Luk_Dish10_M,Cooked Nine Tail,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,3600000,10; percentheal 14,8; },{},{} +12255,Vit_Dish10_M,Immortal Stew,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,3600000,10; percentheal 25,0; },{},{} 12256,PRO_Gift_Box,PRO Gift Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12257,Cold_Medicine,Cold Medicine,0,20,,100,,,,,0xFFFFFFFF,7,2,,,50,,,{ percentheal 25,25; },{},{} 12258,Bombring_Box,Bomb Poring Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if(strcharinfo(3)=="job3_rang02") { monster "this",-1,-1,"--ja--",1904,1,""; } },{},{} 12259,Miracle_Medicine,Miracle Tonic,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ getexp 3000000,1500000; },{},{} 12260,Cool_Summer_Outfit,Cool Summer Outfit,2,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_Summer,600000,0; },{},{} 12261,Secret_Medicine,Leap of Fantasy,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ getexp 2000000,1000000; },{},{} -12262,Inspector_Certificate_,Authoritative Badge,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_SpeedUp0,180000,0; },{},{} -12263,Comp_Battle_Manual,Field Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,1800000,50; },{},{} -12264,Comp_Bubble_Gum,Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMBOOST,1800000,200; },{},{} -12265,Comp_Insurance,Life Insurrance,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LIFEINSURANCE,1800000,0; },{},{} -12266,Sesame_Pastry_,Sesame Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_HITFOOD,1200000,30; },{},{} -12267,Honey_Pastry_,Honey Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FLEEFOOD,1200000,30; },{},{} -12268,Rainbow_Cake_,Rainbow Cake,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,60000,10; sc_start SC_MATKFOOD,120000,10; },{},{} -12269,Tasty_Colonel,Tasty Pink Ration,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,600000,15; },{},{} -12270,Tasty_Major,Tasty White Ration,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MATKPOTION,600000,15; },{},{} +12262,Inspector_Certificate_,Authoritative Badge,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MOVHASTE_HORSE,180000,0; },{},{} +12263,Comp_Battle_Manual,Field Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,1800000,50; },{},{} +12264,Comp_Bubble_Gum,Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_RECEIVEITEM,1800000,200; },{},{} +12265,Comp_Insurance,Life Insurrance,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_DEATHPENALTY,1800000,0; },{},{} +12266,Sesame_Pastry_,Sesame Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_BASICHIT,1200000,30; },{},{} +12267,Honey_Pastry_,Honey Pastry,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_BASICAVOIDANCE,1200000,30; },{},{} +12268,Rainbow_Cake_,Rainbow Cake,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,60000,10; sc_start SC_MATKFOOD,120000,10; },{},{} +12269,Tasty_Colonel,Tasty Pink Ration,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,600000,15; },{},{} +12270,Tasty_Major,Tasty White Ration,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSMAGICPOWER,600000,15; },{},{} 12271,Mre_A,Military Ration A,0,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,0; },{},{} 12272,Mre_B,Military Ration B,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCHIT,600000,33; },{},{} 12273,Mre_C,Military Ration C,2,2,,70,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCFLEE,600000,33; },{},{} @@ -5576,16 +5576,16 @@ 12279,Undead_Element_Scroll,Undead Elemental Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start4 SC_ARMOR_RESIST,300000,20,20,20,20; },{},{} 12280,Holy_Element_Scroll,Holy Elemental Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_BENEDICTIO; sc_start SC_BENEDICTIO,300000,1; },{},{} 12281,Tresure_Box_WoE,Event Treasure Box,2,20,,150,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_Tresure_Box_WoE),1; },{},{} -12282,Internet_Cafe1,Internet Cafe1,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCALLSTATUS,5400000,3; sc_start SC_ATKPOTION,5400000,15; sc_start SC_MATKPOTION,5400000,15; },{},{} -12283,Internet_Cafe2,Internet Cafe2,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCSTR,5400000,8; sc_start SC_INCDEX,5400000,4; sc_start SC_INCAGI,5400000,6; sc_start SC_ATKPOTION,5400000,32; sc_start SC_INCFLEE,5400000,5; },{},{} -12284,Internet_Cafe3,Internet Cafe3,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCINT,5400000,8; sc_start SC_INCVIT,5400000,4; sc_start SC_INCDEX,5400000,6; sc_start SC_MATKPOTION,5400000,40; },{},{} -12285,Internet_Cafe4,Internet Cafe4,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCDEX,5400000,8; sc_start SC_INCLUK,5400000,4; sc_start SC_INCAGI,5400000,6; sc_start SC_ATKPOTION,5400000,24; sc_start SC_MATKPOTION,5400000,24; },{},{} +12282,Internet_Cafe1,Internet Cafe1,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCALLSTATUS,5400000,3; sc_start SC_PLUSATTACKPOWER,5400000,15; sc_start SC_PLUSMAGICPOWER,5400000,15; },{},{} +12283,Internet_Cafe2,Internet Cafe2,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCSTR,5400000,8; sc_start SC_INCDEX,5400000,4; sc_start SC_INCAGI,5400000,6; sc_start SC_PLUSATTACKPOWER,5400000,32; sc_start SC_INCFLEE,5400000,5; },{},{} +12284,Internet_Cafe3,Internet Cafe3,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCINT,5400000,8; sc_start SC_INCVIT,5400000,4; sc_start SC_INCDEX,5400000,6; sc_start SC_PLUSMAGICPOWER,5400000,40; },{},{} +12285,Internet_Cafe4,Internet Cafe4,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCDEX,5400000,8; sc_start SC_INCLUK,5400000,4; sc_start SC_INCAGI,5400000,6; sc_start SC_PLUSATTACKPOWER,5400000,24; sc_start SC_PLUSMAGICPOWER,5400000,24; },{},{} 12286,Masquerade_Ball_Box2,Masquerade Ball Box2,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_Masquerade_2),1; },{},{} 12287,Love_Angel,Love Angel Magic Powder,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ setfont 1; },{},{} 12288,Squirrel,Squirrel Magic Powder,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ setfont 2; },{},{} 12289,Gogo,Gogo Magic Powder,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ setfont 3; },{},{} 12290,Mysterious_Can,Mysterious Can Magic Powder,2,10,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,0; skilleffect "AL_BLESSING",0; sc_start SC_BLESSING,120000,5; },{},{} -12291,Mysterious_PET_Bottle,Mysterious PET Bottle,2,10,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,0; skilleffect "AL_INCAGI",0; sc_start SC_INCREASEAGI,120000,5; },{},{} +12291,Mysterious_PET_Bottle,Mysterious PET Bottle,2,10,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,0; skilleffect "AL_INCAGI",0; sc_start SC_INC_AGI,120000,5; },{},{} 12292,Unripe_Fruit,Unripe Fruit,0,500,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 20,0; },{},{} 12293,Dried_Yggdrasilberry,Dried Yggdrasilberry,0,500,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,20; },{},{} 12294,PC_Bang_Coin_Box1,PC-Room Coin Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 2740,1; },{},{} @@ -5606,7 +5606,7 @@ 12309,Bulging_Head,JJangu Magic Powder,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ setfont 9; },{},{} 12310,Spray_Of_Flowers,Spray Of Flowers,2,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCFLEE,600000,10; },{},{} 12311,Large_Spray_Of_Flowers,Huge Spray Of Flowers,11,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "ALL_PARTYFLEE",1; },{},{} -12312,Thick_Manual50,Thick Battle Manual,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,3600000,50; },{},{} +12312,Thick_Manual50,Thick Battle Manual,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,3600000,50; },{},{} 12313,Protection_Of_Angel,Guardian Angel,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12314,Noive_Box,Noive Box,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12315,Goddess_Bless,Goddess Of Blessing,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} @@ -5615,7 +5615,7 @@ 12318,Little_Heart,Small Hearts,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12319,Strawberry_Cake,Rune Strawberry Cake,2,0,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCATKRATE,600000,5; sc_start SC_INCMATKRATE,600000,5; },{},{} 12320,Pineapple_Juice,Schwartzwald Pine Jubilee,2,0,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCHIT,600000,10; sc_start SC_INCFLEE2,600000,20; },{},{} -12321,Spicy_Sandwich,Arunafeltz Desert Sandwich,2,0,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCCRI,600000,7; },{},{} +12321,Spicy_Sandwich,Arunafeltz Desert Sandwich,2,0,,300,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CRITICALPERCENT,600000,7; },{},{} 12322,Chocolate_Pie,Chocolate Pie,0,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 5,5; },{},{} 12323,N_Fly_Wing,Novice Fly Wing,11,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "AL_TELEPORT",1; },{},{} 12324,N_Butterfly_Wing,Novice Butterfly Wing,11,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "AL_TELEPORT",3; },{},{} @@ -5648,7 +5648,7 @@ 12351,Shout_Megaphone,Scream Megaphone,11,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "MC_LOUD",1; },{},{} 12352,Dun_Tele_Scroll3,Dungeon Teleport Scroll 3,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12353,Tiny_Waterbottle,Small Bottle,2,800,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_WATERWEAPON,90000,1; },{},{} -12354,Buche_De_Noel,Buche De Noel,2,2,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_ANGELUS; sc_start SC_INCMHPRATE,600000,3; sc_start SC_INCMSPRATE,600000,3; sc_start SC_INCHITRATE,600000,3; sc_start SC_INCCRI,600000,7; },{},{} +12354,Buche_De_Noel,Buche De Noel,2,2,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_ANGELUS; sc_start SC_INCMHPRATE,600000,3; sc_start SC_INCMSPRATE,600000,3; sc_start SC_INCHITRATE,600000,3; sc_start SC_CRITICALPERCENT,600000,7; },{},{} 12355,Xmas_Gift,Xmas Gift,2,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_Xmas_Gift),1; },{},{} 12356,Louise_Costume_Box,Louise Costume Box,2,2,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_Louise_Costume_Box),1; },{},{} 12357,Shiny_Wing_Gown,Shiny Wing Gown,2,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1630; },{},{} @@ -5705,10 +5705,10 @@ 12408,Hydra_Ball,Hydra Ball,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 2081; },{},{} 12409,Pork_Belly_H,Pork Belly H,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12410,Spareribs_H,Spareribs H,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -12411,HE_Battle_Manual,HE Battle Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,900000,200; },{},{} -12412,HE_Bubble_Gum,HE Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMBOOST,900000,300; },{},{} +12411,HE_Battle_Manual,HE Battle Manual,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,900000,200; },{},{} +12412,HE_Bubble_Gum,HE Bubble Gum,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_RECEIVEITEM,900000,300; },{},{} 12413,PCBang_Coupon_Box2,PCBang Coupon Box2,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -12414,Guarana_Candy,Guarana Candy,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ASPDPOTION0,1800000,0; sc_start SC_INCREASEAGI,140000,5; skilleffect "AL_INCAGI",0; },{},{} +12414,Guarana_Candy,Guarana Candy,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATTHASTE_POTION1,1800000,0; sc_start SC_INC_AGI,140000,5; skilleffect "AL_INCAGI",0; },{},{} 12415,Siege_Teleport_Scroll2,Siege Teleport Scroll2,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12416,Lucky_Egg_C3,Lucky Egg C3,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12417,Boost500,Boost500,2,100,,50,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} @@ -5767,7 +5767,7 @@ 12472,F_Convex_Mirror,F Convex Mirror,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12473,RWC_Parti_Box,RWC Parti Box,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12474,RWC_Final_Comp_Box,RWC Final Comp Box,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -12475,Cure_Free,Cure Free,2,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_SILENCE; sc_end SC_BLEEDING; sc_end SC_POISON; sc_end SC_CURSE; sc_end SC_ORCISH; sc_end SC_CHANGEUNDEAD; itemheal 500,0; },{},{} +12475,Cure_Free,Cure Free,2,20,,50,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_end SC_SILENCE; sc_end SC_BLOODING; sc_end SC_POISON; sc_end SC_CURSE; sc_end SC_ORCISH; sc_end SC_CHANGEUNDEAD; itemheal 500,0; },{},{} 12476,PCBang_Coupon_Box3,PCBang Coupon Box3,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12477,Gift_Bundle,Gift Bundle,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12478,Chance_Box,Chance Box,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} @@ -5905,7 +5905,7 @@ 12702,Old_Bleu_Box,Old Navy Box,2,0,,200,,,,,0xFFFFFFFF,7,2,,,,,,{ getrandgroupitem(IG_BleuBox),1; getrandgroupitem(IG_BleuBox),1; },{},{} 12703,Holy_Egg_2,Holy Egg,11,0,,50,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 12704,Elixir_Of_Life,Elixir of Life,0,0,,10,,,,,0xFFFFFFFF,7,2,,,85,,,{ percentheal 100,0; },{},{} -12705,Noble_Nameplate,Noble Nameplate,2,0,,100,,,,,0xFFFFFFFF,7,2,,,90,,,{ sc_start SC_EXPBOOST,1800000,100; },{},{} +12705,Noble_Nameplate,Noble Nameplate,2,0,,100,,,,,0xFFFFFFFF,7,2,,,90,,,{ sc_start SC_CASH_PLUSEXP,1800000,100; },{},{} 12706,Lucky_Cookie01,Lucky Cookie,11,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "PR_GLORIA",5; },{},{} 12707,Lucky_Cookie02,Lucky Cookie,11,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "PR_MAGNIFICAT",1; },{},{} 12708,Lucky_Cookie03,Lucky Cookie,11,0,,100,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "PR_IMPOSITIO",3; },{},{} @@ -5984,7 +5984,7 @@ 12775,Ancient_Spirit_Amulet,Ancient Spirit Amulet,2,20,,600,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} // 12786,Change_Slot_Card,Character Position Change Coupon,2,,,,,,,,0xFFFFFFFF,7,2,,,,,,{ set SlotChange, SlotChange + 1; },{},{} -12790,Change_Name_Card,Name Change Coupon,2,,,,,,,,0xFFFFFFFF,7,2,,,,,,{ set CharRename, CharRename + 1; },{},{} +12790,Char_Rename_Card,Character Name Change Coupon,2,,,,,,,,0xFFFFFFFF,7,2,,,,,,{ set CharRename, CharRename + 1; },{},{} // 12848,Falcon_Flute,Falcon Flute,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ if(getskilllv("HT_FALCON")) { if(checkoption(Option_Wug)||checkoption(Option_Wugrider)) end; if(checkfalcon()==1) { setfalcon 0; } else { setfalcon 1; } } },{},{} 12900,Battle_Manual_Box,Battle Manual Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 12208,10; },{},{} @@ -6257,7 +6257,7 @@ 13269,Boost500_To_Throw,Throwing Boost 500,10,100,,10,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_BOOST500,500000,10; },{},{} 13270,Full_SwingK_To_Throw,Throwing Full Swing K,10,100,,50,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_FULL_SWING_K,500000,50; },{},{} 13271,Mana_Plus_To_Throw,Throwing Mana Plus,10,100,,50,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_MANA_PLUS,500000,50; },{},{} -13272,Cure_Free_To_Throw,Throwing Cure Free,10,100,,50,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_end SC_Bleeding; sc_end SC_Curse; sc_end SC_Silence; itemheal rand(1000,1200),0; },{},{} +13272,Cure_Free_To_Throw,Throwing Cure Free,10,100,,50,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_end SC_BLOODING; sc_end SC_Curse; sc_end SC_Silence; itemheal rand(1000,1200),0; },{},{} 13273,Stamina_Up_M_To_Throw,Throwing Muramura M,10,100,,10,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_MUSTLE_M,500000,5; },{},{} 13274,Digestive_F_To_Throw,Throwing Falmons F,10,100,,10,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_LIFE_FORCE_F,500000,5; },{},{} 13275,HP_Inc_PotS_To_Throw,Throwing Increase HP Potion (Small),10,100,,20,0,,,,0x00040000,8,2,32768,,99,,9,{ sc_start SC_INCMHPRATE,500000,1; percentheal 1,0; },{},{}//HP and SP pots need a recheck later to correct max increases. @@ -7164,11 +7164,11 @@ 14461,Asara_Fairy_Hat_Box,Ashura Fairy Hat Box,18,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ getitem 5505,1; },{},{} 14466,Valentine_Pledge_Box,Valentine's Emblem Box,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 14469,Ox_Tail_Scroll,Ox Tail Egg,2,20,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -14500,Insurance60,Life Insurrance Certificate,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LIFEINSURANCE,3600000,0; },{},{} +14500,Insurance60,Life Insurrance Certificate,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_DEATHPENALTY,3600000,0; },{},{} 14508,Zeny_Scroll,Zeny Pet Egg Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -14509,Light_Center_Pot,Light Concentration Potion,2,800,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ASPDPOTION0,1800000,0; },{},{} -14510,Light_Awakening_Pot,Light Awakening Potion,2,1500,,20,,,,,0xFFF7FEEF,7,2,,,40,,,{ sc_start SC_ASPDPOTION1,1800000,0; },{},{} -14511,Light_Berserk_Pot,Light Berserk Potion,2,3000,,20,,,,,0x01E646A6,7,2,,,85,,,{ sc_start SC_ASPDPOTION2,1800000,0; },{},{} +14509,Light_Center_Pot,Light Concentration Potion,2,800,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATTHASTE_POTION1,1800000,0; },{},{} +14510,Light_Awakening_Pot,Light Awakening Potion,2,1500,,20,,,,,0xFFF7FEEF,7,2,,,40,,,{ sc_start SC_ATTHASTE_POTION2,1800000,0; },{},{} +14511,Light_Berserk_Pot,Light Berserk Potion,2,3000,,20,,,,,0x01E646A6,7,2,,,85,,,{ sc_start SC_ATTHASTE_POTION3,1800000,0; },{},{} 14512,Meteor_10_Scroll,Meteor Storm Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_METEOR",10; },{},{} 14513,Storm_10_Scroll,Storm Gust Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_STORMGUST",10; },{},{} 14514,Vermilion_10_Scroll,Lord of Vermilion Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_VERMILION",10; },{},{} @@ -7182,18 +7182,18 @@ 14522,Big_Bun,Big Bun,0,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,0; },{},{} 14523,Pill_,Pill,0,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 0,100; },{},{} 14524,Superb_Fish_Slice,Superb Fish Slice,0,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ percentheal 100,100; },{},{} -14525,Chewy_Ricecake,Chewy Ricecake,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ATKPOTION,180000,10; },{},{} -14526,Oriental_Pastry,Oriental Pastry,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_MATKPOTION,180000,10; },{},{} +14525,Chewy_Ricecake,Chewy Ricecake,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSATTACKPOWER,180000,10; },{},{} +14526,Oriental_Pastry,Oriental Pastry,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_PLUSMAGICPOWER,180000,10; },{},{} 14527,Dun_Tele_Scroll1,Dungeon Teleport Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashDungeon"; },{},{} 14528,PVP_Tele_Scroll,PVP Teleport Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 14529,Greed_Scroll,Greed Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "BS_GREED",1; },{},{} 14530,Flee_30_Scroll,Evasion Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCFLEE,1800000,30; },{},{} 14531,Accuracy_30_Scroll,Concentration Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCHIT,1800000,30; },{},{} -14532,Battle_Manual25,Field Manual 25%,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,1800000,25; },{},{} -14533,Battle_Manual100,Field Manual 100%,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,1800000,100; },{},{} +14532,Battle_Manual25,Field Manual 25%,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,1800000,25; },{},{} +14533,Battle_Manual100,Field Manual 100%,2,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,1800000,100; },{},{} 14534,Small_Life_Potion,Small Life Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 320; sc_start4 SC_S_LIFEPOTION,600000,-5,5,0,0; },{},{} 14535,Med_Life_Potion,Medium Life Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 320; sc_start4 SC_L_LIFEPOTION,600000,-7,4,0,0; },{},{} -14536,Abrasive,Abrasive,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 182; sc_start SC_INCCRI,300000,30; },{},{} +14536,Abrasive,Abrasive,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 182; sc_start SC_CRITICALPERCENT,300000,30; },{},{} 14537,Regeneration_Potion,Regeneration Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 348; sc_start SC_INCHEALRATE,1800000,20; },{},{} 14538,Glass_Of_Illusion,Glass of Illusion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_STEAL; sc_start SC_INCFLEE2,60000,20; },{},{} 14539,Shadow_Armor_S,Shadow Armor Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_CLOAKING; sc_start4 SC_ELEMENTALCHANGE,1800000,1,Ele_Dark,1,0; },{},{} @@ -7202,42 +7202,42 @@ 14542,B_Def_Potion,Big Defense Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_GUARD; sc_start SC_DEF_RATE,180000,3; },{},{} 14543,S_Mdef_Potion,Small Magic Defense Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_SPELLBREAKER; sc_start SC_MDEF_RATE,60000,3; },{},{} 14544,B_Mdef_Potion,Big Magic Defense Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ specialeffect2 EF_SPELLBREAKER; sc_start SC_MDEF_RATE,180000,3; },{},{} -14545,Battle_Manual_X3,Field Manual 300%,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_EXPBOOST,1800000,300; },{},{} +14545,Battle_Manual_X3,Field Manual 300%,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSEXP,1800000,300; },{},{} 14546,Fire_Cracker_Love,I Love You Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} 14547,Fire_Cracker_Wday,Whiteday Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} 14548,Fire_Cracker_Valentine,Valentine's Day Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} 14549,Fire_Cracker_Bday,Birthday Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} 14550,Fire_Cracker_Xmas,Xmas Firecracker,2,2,,20,,,,,0xFFFFFFFF,7,2,,,,,,{ end; },{},{} -14551,Str_Dish01_,Fried Grasshopper Legs,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,1; percentheal 5,0; },{},{} -14552,Str_Dish02_,Seasoned Sticky Webfoot,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,2; percentheal 5,0; },{},{} -14553,Str_Dish03_,Bomber Steak,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,3; percentheal 5,0; },{},{} -14554,Int_Dish01_,Grape Juice Herbal Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,1; percentheal 0,5; },{},{} -14555,Int_Dish02_,Autumn Red Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,2; percentheal 0,5; },{},{} -14556,Int_Dish03_,Honey Herbal Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,3; percentheal 0,5; },{},{} -14557,Vit_Dish01_,Steamed Crab Nippers,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,1; percentheal 5,0; },{},{} -14558,Vit_Dish02_,Assorted Seafood,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,2; percentheal 5,0; },{},{} -14559,Vit_Dish03_,Clam Soup,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,3; percentheal 5,0; },{},{} -14560,Agi_Dish01_,Frog Egg Squid Ink Soup,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,1; percentheal 3,1; },{},{} -14561,Agi_Dish02_,Smooth Noodle,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,2; percentheal 3,1; },{},{} -14562,Agi_Dish03_,Tentacle Cheese Gratin,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,3; percentheal 3,1; },{},{} -14563,Dex_Dish01_,Honey Grape Juice,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,1; percentheal 2,2; },{},{} -14564,Dex_Dish02_,Chocolate Mousse Cake,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,2; percentheal 2,2; },{},{} -14565,Dex_Dish03_,Fruit Mix,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,3; percentheal 2,2; },{},{} -14566,Luk_Dish01_,Fried Monkey Tails,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,1; percentheal 3,2; },{},{} -14567,Luk_Dish02_,Mixed Juice,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,2; percentheal 3,2; },{},{} -14568,Luk_Dish03_,Fried Sweet Potato,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,3; percentheal 4,2; },{},{} +14551,Str_Dish01_,Fried Grasshopper Legs,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,1; percentheal 5,0; },{},{} +14552,Str_Dish02_,Seasoned Sticky Webfoot,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,2; percentheal 5,0; },{},{} +14553,Str_Dish03_,Bomber Steak,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,3; percentheal 5,0; },{},{} +14554,Int_Dish01_,Grape Juice Herbal Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,1; percentheal 0,5; },{},{} +14555,Int_Dish02_,Autumn Red Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,2; percentheal 0,5; },{},{} +14556,Int_Dish03_,Honey Herbal Tea,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,3; percentheal 0,5; },{},{} +14557,Vit_Dish01_,Steamed Crab Nippers,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,1; percentheal 5,0; },{},{} +14558,Vit_Dish02_,Assorted Seafood,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,2; percentheal 5,0; },{},{} +14559,Vit_Dish03_,Clam Soup,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,3; percentheal 5,0; },{},{} +14560,Agi_Dish01_,Frog Egg Squid Ink Soup,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,1; percentheal 3,1; },{},{} +14561,Agi_Dish02_,Smooth Noodle,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,2; percentheal 3,1; },{},{} +14562,Agi_Dish03_,Tentacle Cheese Gratin,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,3; percentheal 3,1; },{},{} +14563,Dex_Dish01_,Honey Grape Juice,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,1; percentheal 2,2; },{},{} +14564,Dex_Dish02_,Chocolate Mousse Cake,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,2; percentheal 2,2; },{},{} +14565,Dex_Dish03_,Fruit Mix,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,3; percentheal 2,2; },{},{} +14566,Luk_Dish01_,Fried Monkey Tails,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,1; percentheal 3,2; },{},{} +14567,Luk_Dish02_,Mixed Juice,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,2; percentheal 3,2; },{},{} +14568,Luk_Dish03_,Fried Sweet Potato,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,3; percentheal 4,2; },{},{} 14569,Knife_Goblin_Ring,Knife Goblin Ring,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1122; },{},{} 14570,Flail_Goblin_Ring,Flail Goblin Ring,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1123; },{},{} 14571,Hammer_Goblin_Ring,Hammer Goblin Ring,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1125; },{},{} 14572,Holy_Marble,Holy Marble,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1385; },{},{} 14573,Red_Burning_Stone,Red Burning Stone,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1382; },{},{} 14574,Skull_Of_Vagabond,Vagabond's Skull,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ pet 1208; },{},{} -14575,Str_Dish05_,Lutie Lady's Pancake,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_STRFOOD,1200000,5; percentheal 10,0; },{},{} -14576,Int_Dish05_,Mastela Fruit Wine,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INTFOOD,1200000,5; percentheal 0,10; },{},{} -14577,Vit_Dish05_,Spicy Fried Bao,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_VITFOOD,1200000,5; percentheal 10,0; },{},{} -14578,Agi_Dish05_,Steamed Bat Wing in Pumpkin,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_AGIFOOD,1200000,5; percentheal 6,2; },{},{} -14579,Dex_Dish05_,Green Salad,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_DEXFOOD,1200000,5; percentheal 5,5; },{},{} -14580,Luk_Dish05_,Fried Scorpion Tails,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_LUKFOOD,1200000,5; percentheal 5,2; },{},{} +14575,Str_Dish05_,Lutie Lady's Pancake,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_STR,1200000,5; percentheal 10,0; },{},{} +14576,Int_Dish05_,Mastela Fruit Wine,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_INT,1200000,5; percentheal 0,10; },{},{} +14577,Vit_Dish05_,Spicy Fried Bao,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_VIT,1200000,5; percentheal 10,0; },{},{} +14578,Agi_Dish05_,Steamed Bat Wing in Pumpkin,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_AGI,1200000,5; percentheal 6,2; },{},{} +14579,Dex_Dish05_,Green Salad,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_DEX,1200000,5; percentheal 5,5; },{},{} +14580,Luk_Dish05_,Fried Scorpion Tails,0,2,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_FOOD_LUK,1200000,5; percentheal 5,2; },{},{} 14581,Dun_Tele_Scroll2,Dungeon Teleport Scroll II,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashDungeon"; },{},{} 14582,WOB_Rune,Yellow Butterfly Wing,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashCity",1; },{},{} 14583,WOB_Schwaltz,Green Butterfly Wing,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashCity",2; },{},{} @@ -7249,7 +7249,7 @@ 14589,Pty_Inc_Agi_Scroll,Party Increase Agi 10 Scroll,11,10,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "CASH_INCAGI",10; },{},{} 14590,Pty_Assumptio_Scroll,Party Assumptio 5 Scroll,11,10,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "CASH_ASSUMPTIO",5; },{},{} 14591,Siege_Teleport_Scroll,WoE Teleport Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ callfunc "F_CashSeigeTele"; },{},{} -14592,Job_Manual50,JOB Battle Manual,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_JEXPBOOST,1800000,50; },{},{} +14592,Job_Manual50,JOB Battle Manual,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_CASH_PLUSONLYJOBEXP,1800000,50; },{},{} 14593,Magic_Power_Scroll,Mystical Amplification Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "HW_MAGICPOWER",10; },{},{} 14594,Quagmire_Scroll,Quagmire Scroll,11,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ itemskill "WZ_QUAGMIRE",5; },{},{} 14595,Unsealed_Magic_Spell,Unsealed Magic Spell,2,0,,0,,,,,0xFFFFFFFF,7,2,,,,,,{ warp "yuno_fild09",255,127; },{},{} @@ -7258,7 +7258,7 @@ 14598,GhostringS,Ghostring Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMSCRIPT,60000,4047; },{},{} 14599,Greed_Scroll_C,Greed Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} 14600,Mental_Potion,Mental Potion,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{},{},{} -14601,Tyr's_Blessing,Tyr's Blessing,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCFLEE,300000,30; sc_start SC_INCHIT,300000,30; sc_start SC_ATKPOTION,300000,20; sc_start SC_MATKPOTION,300000,20; },{},{} +14601,Tyr's_Blessing,Tyr's Blessing,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_INCFLEE,300000,30; sc_start SC_INCHIT,300000,30; sc_start SC_PLUSATTACKPOWER,300000,20; sc_start SC_PLUSMAGICPOWER,300000,20; },{},{} 14602,TaogunkaS,Tao Gunka Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMSCRIPT,180000,4302; },{},{} 14603,MistressS,Mistress Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMSCRIPT,180000,4132; },{},{} 14604,Orc_HeroS,Orc Hero Scroll,2,0,,10,,,,,0xFFFFFFFF,7,2,,,,,,{ sc_start SC_ITEMSCRIPT,60000,4143; },{},{} diff --git a/db/re/refine_db.txt b/db/re/refine_db.txt index 421a1bdbc..3dad5be78 100644 --- a/db/re/refine_db.txt +++ b/db/re/refine_db.txt @@ -27,15 +27,14 @@ // Chance: // 100 = 100% // -// Note: Chances for +11 and higher are not verified - 10% is a rumor from iRO wiki. // A note about renewal Armors, there may or may not be another bonus, according to iRO wiki: Every upgrade gives floor[( 3 + current upgrade ) / 4] equipment DEF) 0,0,0,0,100:100,100:100,100:100,100:100,60:200,40:200,40:200,20:200,20:300,10:300,50:300,30:300,30:400,20:400,10:400,10:400,10:500,10:500,10:500,10:500 // Level 1 weapons -1,200,8,300,100:0,100:0,100:0,100:0,100:0,100:0,100:0,60:0,40:0,20:0,70:0,70:0,50:0,50:0,30:0,30:300,20:300,20:300,10:300,10:300 +1,200,8,300,100:0,100:0,100:0,100:0,100:0,100:0,100:0,60:0,40:0,20:0,90:0,80:0,80:0,70:0,70:0,60:300,60:300,40:300,20:300,20:300 // Level 2 weapons -2,300,7,500,100:0,100:0,100:0,100:0,100:0,100:0,60:0,40:0,20:0,20:0,70:0,50:0,50:0,30:0,30:0,20:600,20:600,10:600,10:600,10:600 +2,300,7,500,100:0,100:0,100:0,100:0,100:0,100:0,60:0,40:0,20:0,20:0,80:0,80:0,70:0,70:0,60:0,60:600,50:600,20:600,20:600,20:600 // Level 3 weapons -3,500,6,800,100:0,100:0,100:0,100:0,100:0,60:0,50:0,20:0,20:0,20:0,50:0,50:0,30:0,30:0,20:0,20:900,10:900,10:900,10:900,10:900 +3,500,6,800,100:0,100:0,100:0,100:0,100:0,60:0,50:0,20:0,20:0,20:0,80:0,70:0,70:0,60:0,60:0,40:900,40:900,20:900,20:900,10:900 // Level 4 weapons 4,700,5,1400,100:0,100:0,100:0,100:0,60:0,40:0,40:0,20:0,20:0,10:0,50:0,30:0,30:0,20:0,20:0,10:1200,10:1200,10:1200,10:1200,10:1200 diff --git a/db/re/skill_cast_db.txt b/db/re/skill_cast_db.txt index ef34d230a..5766f5217 100644 --- a/db/re/skill_cast_db.txt +++ b/db/re/skill_cast_db.txt @@ -1085,16 +1085,16 @@ 2006,1000,0,0,0,0,2000,-1 //-- RK_DRAGONBREATH -2008,0:0:0:1000:1000:1000:1500:1500:2000:2000,2000,0,10000,0,0,500 +2008,0:0:0:1000:1000:1000:1500:1500:2000:2000,2000,0,42000,0,0,500 //-- RK_DRAGONHOWLING 2009,0,0,0,15000,0,10000,-1 //-- RK_MILLENNIUMSHIELD -2011,0,1000,0,180000,0,60000,-1 +2011,0,1000,0,180000,60000,0,-1 //-- RK_CRUSHSTRIKE -2012,0,0,0,30000,0,30000,1000 +2012,0,0,0,180000,30000,0,1000 //-- RK_REFRESH -2013,0,0,0,60000,0,120000,1000 +2013,0,0,0,60000,120000,0,1000 //-- RK_GIANTGROWTH 2014,0,0,0,180000,0,0,1000 //-- RK_STONEHARDSKIN @@ -1107,6 +1107,8 @@ 2018,0,0,0,180000,0,0,-1 //-- RK_ABUNDANCE 2019,0,0,0,180000,0,0,-1 +//-- RK_DRAGONBREATH_WATER +5004,0:0:0:1000:1000:1000:1500:1500:2000:2000,2000,0,40000,0,0,500 //========================================== //===== Gillotine Cross ==================== @@ -1141,6 +1143,8 @@ 2036,0,200,0,3000,0,0,-1 //-- GC_CROSSRIPPERSLASHER 2037,0,1000,0,0,0,0,-1 +//-- GC_DARKCROW +5001,0,1500,0,5000,0,0,-1 //========================================== //===== Arch Bishop ======================== @@ -1180,6 +1184,8 @@ //-- AB_SILENTIUM 2057,4000,0,0,20000:30000:40000:50000:60000,0,15000,-1 +//-- AB_OFFERTORIUM +5011,4000,0,0,90000,0,0,-1 //========================================== //===== Warlock ============================ @@ -1197,7 +1203,6 @@ 2206,1000,1000,0,60000:90000:120000:150000:180000,0,50000:80000:110000:140000:170000,1000 //-- WL_SIENNAEXECRATE 2207,2000,2000,0,10000:12000:14000:16000:18000,0,0,-1 - //-- WL_STASIS 2209,3000,1000,0,10000:15000:20000:25000:30000,0,300000,1000 //-- WL_DRAINLIFE @@ -1205,17 +1210,15 @@ //-- WL_CRIMSONROCK 2211,5000,2000,0,3000:4000:5000:6000:7000,0,5000,2000 //-- WL_HELLINFERNO -2212,3000,1000,0,15000,0,0,1000 +2212,3000,1000,0,42000,0,0,1000 //-- WL_COMET -2213,10000:11000:12000:13000:14000,0,0,15000,0,60000,1000:1500:2000:2500:3000 +2213,10000:11000:12000:13000:14000,0,0,100,42000,60000,1000:1500:2000:2500:3000 //-- WL_CHAINLIGHTNING 2214,3500:4000:4500:5000:5500,0,0,100,0,3000,1000 - //-- WL_EARTHSTRAIN -2216,2000:3000:4000:5000:6000,1000,0,150,75000:90000:105000:120000:135000,10000,2000 +2216,2000:3000:4000:5000:6000,1000,0,100,75000:90000:105000:120000:135000,10000,2000 //-- WL_TETRAVORTEX -2217,5000:6000:7000:8000:9000,2000,0,20000,0,15000,2000 - +2217,5000:6000:7000:8000:9000,2000,0,15000:120000:40000:5000,0,15000,2000 //-- WL_SUMMONFB 2222,2000,0,0,120000:160000:200000:240000:280000,0,0,-1 //-- WL_SUMMONBL @@ -1224,9 +1227,10 @@ 2224,2000,0,0,120000:160000:200000:240000:280000,0,0,-1 //-- WL_SUMMONSTONE 2229,2000,0,0,120000:160000:200000:240000:280000,0,0,-1 - //-- WL_READING_SB 2231,5000,500,0,0,0,0,1000 +//-- WL_TELEKINESIS_INTENSE +5012,1000,0,0,180000,0,0,-1 //========================================== //===== Ranger ============================= @@ -1268,6 +1272,8 @@ 2253,0,0,0,20000,15000,0,-1 //-- RA_ICEBOUNDTRAP 2254,0,0,0,20000,15000,0,-1 +//-- RA_UNLIMIT +5002,0,0,0,60000,0,0,-1 //========================================== //===== Mechanic =========================== @@ -1323,6 +1329,8 @@ 2282,0,0,0,20000:30000:40000:50000:60000,0,0,1800:1600:1400:1200:1000 //-- NC_DISJOINT 2283,2000,0,0,0,0,0,-1 +//-- NC_MAGMA_ERUPTION +5006,1000,0,0,10000,42000,0,-1 //========================================== //===== Shadow Chaser ====================== @@ -1368,6 +1376,8 @@ 2303,2000,2000,0,10000:20000:30000,0,180000,-1 //-- SC_FEINTBOMB 2304,1000,0,0,1000,0,5000,-1 +//-- SC_SCAPE +5010,1000,0,0,1000,0,5000,-1 //========================================== //==== Royal Guard skills ================== @@ -1408,6 +1418,8 @@ 2324,1000,3000,0,0,0,20000,0 //-- LG_INSPIRATION 2325,2000,2000,0,30000:45000:60000:75000:90000,0,540000:480000:420000:360000:300000,1000 +//-- LG_KINGS_GRACE +5013,1000,0,0,5000,0,0,-1 //========================================== //===== Sura Skills ======================== @@ -1454,6 +1466,9 @@ 2347,1000,1000,0,240000,0,200000:180000:160000:140000:120000,1000 //-- SR_GENTLETOUCH_REVITALIZE 2348,1000,1000,0,240000,0,200000:180000:160000:140000:120000,1000 +//-- SR_FLASHCOMBO +2348,0,4000,0,0,0,0,-1 + //========================================== //==== Wanderer skills ===================== @@ -1516,6 +1531,8 @@ 2433,1000,1000,0,20000:30000:40000:50000:60000,0,180000,500 //-- WM_UNLIMITED_HUMMING_VOICE 2434,1000,1000,0,60000:90000:120000:150000:180000,0,110000:120000:130000:140000:150000,500 +//-- WM_FRIGG_SONG +5007,0,0,0,60000,0,0,0 //========================================== //==== Sorcerer skills ===================== @@ -1639,57 +1656,59 @@ //-- KO_YAMIKUMO 3001,0,0,0,60000,0,0,-1 //-- KO_JYUMONJIKIRI -3004,0,2500,0,5000,0,0,-1 +3004,0,500,0,3000,0,5000,-1 //-- KO_SETSUDAN -3005,0,2000,0,0,0,0,-1 +3005,0,0,0,0,0,3000,-1 //-- KO_BAKURETSU -3006,1000:1500:2000:2500:3000,1000,0,100,0,3000,0 +3006,1000:1400:1800:2200:2600,1000,0,100,0,3000,-1 //-- KO_HAPPOKUNAI -3007,0,1000,0,0,0,0,-1 +3007,0,500,0,0,0,0,-1 //-- KO_MUCHANAGE -3008,0,0,0,100,0,10000,-1 +3008,1000,0,0,100,0,10000,0 //-- KO_HUUMARANKA -3009,0,3000,0,500,0,0,-1 +3009,1000:1200:1400:1600:1800,1000,0,500,0,3000,-1 //-- KO_MAKIBISHI -3010,0,0,0,12000:14000:16000:18000:20000,10000,0,-1 +3010,0,0,0,12000:14000:16000:18000:20000,10000,10000,-1 //-- KO_MEIKYOUSISUI -3011,3000,0,0,10000,0,0,0 +3011,3000,0,0,10000,0,10000,-1 //-- KO_ZANZOU -3012,0,0,0,27000:24000:21000:18000:15000,0,0,-1 +3012,0,1000,0,30000:27000:24000:21000:18000,0,0,-1 //-- KO_KYOUGAKU -3013,1000,0,0,12000:14000:16000:18000:20000,0,0,0 +3013,3000:2500:2000:1500:1000,1000,0,12000:14000:16000:18000:20000,0,0,-1 //-- KO_JYUSATSU -3014,1000,0,0,8000:10000:12000:14000:16000,0,0,0 +3014,3000:2500:2000:1500:1000,1000,0,8000:10000:12000:14000:16000,0,10000,-1 //-- KO_KAHU_ENTEN -3015,500,0,0,300000,0,0,0 +3015,2000,0,0,300000,0,0,-1 //-- KO_HYOUHU_HUBUKI -3016,500,0,0,300000,0,0,0 +3016,2000,0,0,300000,0,0,-1 //-- KO_KAZEHU_SEIRAN -3017,500,0,0,300000,0,0,0 +3017,2000,0,0,300000,0,0,-1 //-- KO_DOHU_KOUKAI -3018,500,0,0,300000,0,0,0 -//-- KO_KAIHOU -3019,1000,0,0,0,0,0,0 +3018,2000,0,0,300000,0,0,-1 //-- KO_ZENKAI -3020,1000,0,0,10000,10000,0,0 +3020,0,1000,0,10000,10000,0,0 //-- KO_GENWAKU -3021,500,0,0,5000,0,0,0 +3021,3000:2500:2000:1500:1000,1000,0,5000,0,10000,-1 //-- KO_IZAYOI 3022,0,0,0,30000:45000:60000:75000:90000,0,60000,-1 //-- KG_KAGEHUMI -3023,0,0,0,5000,0,5000,-1 +3023,0,0,0,5000:6000:7000:8000:9000,0,0,-1 //-- KG_KYOMU -3024,0,0,0,10000:15000:20000:25000:30000,0,0,-1 +3024,0,1000,0,10000:15000:20000:25000:30000,0,20000,-1 //-- KG_KAGEMUSYA 3025,0,0,0,60000:90000:120000:150000:180000,0,0,-1 + //-- OB_ZANGETSU -3026,0,0,0,60000:75000:90000:105000:120000,0,0,-1 +3026,1000:1500:2000:2500:3000,1000,0,60000:75000:90000:105000:120000,0,30000,2000 //-- OB_OBOROGENSOU -3027,0,0,0,10000:15000:20000:25000:30000,0,0,-1 +3027,1000,0,0,10000:15000:20000:25000:30000,0,15000,0 //-- OB_AKAITSUKI -3029,0,0,0,10000:15000:20000:25000:30000,0,0,-1 +3029,1000:1500:2000:2500:3000,1000,0,10000:15000:20000:25000:30000,0,30000,2000 //========================================== +//-- ALL_FULL_THROTTLE +5014,0,0,0,10000:15000:20000:25000:30000,10000,20000:25000:30000:35000:40000,-1 + //===== Homunculus Skills ================== //-- HLIF_HEAL 8001,0,2000,0,0,0,0,-1 diff --git a/db/re/skill_db.txt b/db/re/skill_db.txt index f6da92528..e472626d4 100644 --- a/db/re/skill_db.txt +++ b/db/re/skill_db.txt @@ -9,8 +9,8 @@ // -2 - use endowed element, -3 - use random element.) // 06 nk (skill damage properties): // 0x01 - No damage skill -// 0x02 - Has splash area (requires source modification) -// 0x04 - Damage should be split among targets (requires 0x02 in order to work) +// 0x02 - Has splash area +// 0x04 - Damage should be split among targets // 0x08 - Skill ignores caster's % damage cards (misc type always ignores) // 0x10 - Skill ignores elemental adjustments // 0x20 - Skill ignores target's defense (misc type always ignores) @@ -91,7 +91,7 @@ 44,0,0,0,0,0,0,10,0,no,0,0,0,none,0, AC_VULTURE,Vulture's Eye 45,0,6,4,0,0x3,3,10,1,no,0,0,0,weapon,0, AC_CONCENTRATION,Improve Concentration 46,-9,8,1,-1,0,0,10,2,no,0,0,0,weapon,0, AC_DOUBLE,Double Strafe -47,-9,6,2,-1,0x2,2,10,1,no,0,0x2000,0,weapon,2, AC_SHOWER,Arrow Shower +47,-9,6,2,-1,0x2,2:2:2:2:2:3:3:3:3:3,10,1,no,0,0x2000,0,weapon,2, AC_SHOWER,Arrow Shower 48,-1,8,0,-1,0,0,10,2,no,0,0,0,weapon,0, TF_DOUBLE,Double Attack 49,0,0,0,0,0,0,10,0,no,0,0,0,weapon,0, TF_MISS,Improve Dodge 50,1,6,1,0,1,0,10,1,no,0,0,0,weapon,0, TF_STEAL,Steal @@ -422,7 +422,7 @@ 376,0,0,0,0,0x1,0,5,1,no,0,0,0,weapon,0, ASC_KATAR,Advanced Katar Mastery //377,0,0,4,0,0x1,0,10,1,no,0,0,0,misc,0, ASC_HALLUCINATION,Hallucination Walk 378,0,6,4,5,0x1,0,5,1,no,0,0,0,weapon,0, ASC_EDP,Enchant Deadly Poison -379,7,6,1,-1,0x8,0,10,1,yes,0,0,0,weapon,0, ASC_BREAKER,Soul Destroyer +379,7,6,1,-1,0x40,0,10,1,yes,0,0,0,misc,0, ASC_BREAKER,Soul Destroyer 380,0,6,4,0,0x1,0,10,1,no,0,0,0,weapon,0, SN_SIGHT,Falcon Eyes 381,5,8,1,0,0x40,0,5,1,yes,0,0,0,misc,0, SN_FALCONASSAULT,Falcon Assault 382,9,8,1,-1,0,2,5,1,yes,0,0,13,weapon,0, SN_SHARPSHOOTING,Focused Arrow Strike @@ -533,7 +533,7 @@ 487,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, CG_LONGINGFREEDOM,Longing for Freedom 488,0,6,4,0,0x1,1,5,1,no,0,0x40,0,misc,0, CG_HERMODE,Wand of Hermode 489,9,6,1,0,0x41,0,5,1,no,0,0,0,misc,0, CG_TAROTCARD,Tarot Card of Fate -490,9,8,1,0,0x40,0,10,1:2:3:4:5:6:7:8:9:10,yes,0,0,0,misc,0, CR_ACIDDEMONSTRATION,Acid Demonstration +490,9,8,1,0,0x40,0,10,-1:-2:-3:-4:-5:-6:-7:-8:-9:-10,yes,0,0,0,misc,0, CR_ACIDDEMONSTRATION,Acid Demonstration 491,1,6,2,0,0x1,0,2,1,no,0,0,0,none,0, CR_CULTIVATION,Plant Cultivation 492,0,6,4,0:1:2:3:4:5:6:7:8:9,0x1,0,10,1,no,0,0x2,0,none,0, ITEM_ENCHANTARMS,Weapon Enchantment 493,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, TK_MISSION,Taekwon Mission @@ -672,7 +672,7 @@ 1003,0,0,0,0,0,0,1,0,no,0,0x1,0,weapon,0, AS_SONICACCEL,Sonic Acceleration 1004,9,8,1,0,0x8,0,1,1,no,0,0x1,0,weapon,0, AS_VENOMKNIFE,Throw Venom Knife 1005,1,6,1,0,0x1,0,1,1,no,0,0x1,0,weapon,0, RG_CLOSECONFINE,Close Confine -1006,0,6,4,3,0,2,1,1,yes,0,0x1,0,magic,3, WZ_SIGHTBLASTER,Sight Blaster +1006,0,6,4,3,0,1,1,1,yes,0,0x1,0,magic,3, WZ_SIGHTBLASTER,Sight Blaster 1007,0,6,4,0,0x1,0,1,0,no,0,0x1,0,none,0, SA_CREATECON,Create Elemental Converter 1008,9,6,1,1,0x1,0,1,1,yes,0,0x1,0,magic,0, SA_ELEMENTWATER,Elemental Change Water 1009,-9,6,1,0,0,0,1,1,no,0,0x1,0,weapon,3, HT_PHANTASMIC,Phantasmic Arrow @@ -692,15 +692,15 @@ //**** 2001,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0, RK_ENCHANTBLADE,Enchant Blade 2002,7:8:9:10:11,6,1,-1,0,0,5,1,no,0,0,0,weapon,0, RK_SONICWAVE,Sonic Wave -2003,0,6,4,0,0x1,0,10,1,no,0,0,0,weapon,0, RK_DEATHBOUND,Death Bound +2003,0,6,4,0,0x1,0,10,1,no,0,0,0,weapon,3, RK_DEATHBOUND,Death Bound 2004,1,8,1,-1,0,0,10,-5,no,0,0,0,weapon,0, RK_HUNDREDSPEAR,Hundred Spear 2005,1,6,2,4,0x2,2,5,1,no,0,0,0,weapon,3, RK_WINDCUTTER,Wind Cutter 2006,0,6,4,-1,0x2,5,5,1,no,0,0,0,weapon,0, RK_IGNITIONBREAK,Ignition Break 2007,0,0,0,0,0,0,5,0,no,0,0,0,weapon,0, RK_DRAGONTRAINING,Dragon Training 2008,9,6,2,3,0xC2,1:1:1:2:2:2:3:3:4:4,10,1,no,0,0,0,misc,0, RK_DRAGONBREATH,Dragon Breath -2009,0,6,4,0,0x3,3:4:5:6:7,5,1,no,0,0,0,none,0, RK_DRAGONHOWLING,Dragon Howling +2009,0,6,4,0,0x3,3:4:5:6:7,5,1,yes,0,0,0,none,0, RK_DRAGONHOWLING,Dragon Howling 2010,0,0,0,0,0,0,10,0,no,0,0,0,none,0, RK_RUNEMASTERY,Rune Mastery -2011,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, RK_MILLENNIUMSHIELD,Millenium Shield +2011,0,6,4,0,0x1,0,1,1,yes,0,0,0,none,0, RK_MILLENNIUMSHIELD,Millenium Shield 2012,1,6,4,-1,0,0x8,1,1,yes,0,0,0,weapon,0, RK_CRUSHSTRIKE,Crush Strike 2013,0,6,4,0,0x1,0,1,1,yes,0,0,0,none,0, RK_REFRESH,Refresh 2014,0,6,4,0,0x1,0,1,1,yes,0,0,0,none,0, RK_GIANTGROWTH,Giant Growth @@ -709,7 +709,7 @@ 2017,0,6,4,-1,0x2,3,1,1,no,0,0,0,weapon,7, RK_STORMBLAST,Storm Blast 2018,0,6,4,0,0x3,-1,1,1,yes,0,0,0,none,0, RK_FIGHTINGSPIRIT,Fighting Spirit //CHECK Is this splash needed? 2019,9,6,4,6,0x1,0,1,1,yes,0,0,0,none,0, RK_ABUNDANCE,Abundance -2020,5:6:7:8:9,6,16,-1,0,0,5,1,no,0,0,0,weapon,0, RK_PHANTOMTHRUST,Phantom Thrust +2020,5:6:7:8:9,6,1,-1,0,0,5,1,yes,0,0,0,weapon,0, RK_PHANTOMTHRUST,Phantom Thrust //**** // GC Guillotine Cross @@ -771,8 +771,8 @@ 2210,11,6,1,0,0,0,5,1,yes,0,0,0,magic,0, WL_DRAINLIFE,Drain Life 2211,11,8,1,3,0x2,3,5,-7,yes,0,0,0,magic,3, WL_CRIMSONROCK,Crimson Rock 2212,11,6,1,3,0,0,5,1,yes,0,0,0,magic,0, WL_HELLINFERNO,Hell Inferno -2213,11,8,2,0,0x2,7,5,-20,yes,0,0,0,magic,2, WL_COMET,Comet -2214,11,6,1,0,0,3,5,1,yes,0,0,0,magic,0, WL_CHAINLIGHTNING,Chain Lightning //CHECK Is the splash being used for the target search? +2213,11,8,2,0,0,0,5,-20,yes,0,0,0,magic,2, WL_COMET,Comet +2214,11,6,1,0,0,3,5,1,yes,0,0,0,magic,0, WL_CHAINLIGHTNING,Chain Lightning 2215,11,6,1,4,0,0,5,1,no,0,0,0,magic,0, WL_CHAINLIGHTNING_ATK,Chain Lightning Attack 2216,3,8,2,2,0,0,5,-6:-7:-8:-9:-10,yes,0,0,0,magic,0, WL_EARTHSTRAIN,Earth Strain 2217,11,6,1,0,0,0,5,1,yes,0,0,0,magic,0, WL_TETRAVORTEX,Tetra Vortex @@ -783,12 +783,12 @@ 2222,0,6,4,3,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONFB,Summon Fire Ball 2223,0,6,4,4,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONBL,Summon Lightning Ball 2224,0,6,4,1,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONWB,Summon Water Ball -2225,11,6,1,3,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_FIRE,Summon Attack Fire //CHECK Summon attack ID's dont appear to have a range. +2225,11,6,1,3,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_FIRE,Summon Attack Fire 2226,11,6,1,4,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_WIND,Summon Attack Wind 2227,11,6,1,1,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_WATER,Summon Attack Water 2228,11,6,1,2,0,0,5,1,no,0,0,1,magic,0, WL_SUMMON_ATK_GROUND,Summon Attack Earth 2229,0,6,4,2,0x1,0,5,1,yes,0,0,0,magic,0, WL_SUMMONSTONE,Summon Stone -2230,11,8,1,0,0,0,2,1,yes,0,0,0,magic,0, WL_RELEASE,Release //CHECK Should it be left to do multi hit or single hit? +2230,11,6,1,0,0,0,2,1,yes,0,0,0,magic,0, WL_RELEASE,Release 2231,0,6,4,0,0x1,0,1,1,yes,0,0,0,magic,0, WL_READING_SB,Reading Spellbook 2232,0,0,0,0,0,0,5,0,no,0,0,0,none,0, WL_FREEZE_SP,Freeze Spell @@ -1048,18 +1048,18 @@ 3005,2,6,1,-1,0,0,5,1,no,0,0,0,weapon,0, KO_SETSUDAN,Soul Sever 3006,7:8:9:10:11,6,2,0,0x2,2,5,0,no,0,0,0,weapon,0, KO_BAKURETSU,Bakuretsu Kunai 3007,0,6,4,-1,0x42,4:4:4:4:5,5,0,no,0,0,0,misc,0, KO_HAPPOKUNAI,Happo Kunai -3008,9,8,2,0,0x52,2,10,-10,no,0,0,0,misc,0, KO_MUCHANAGE,Mucha Nage +3008,9,8,2,0,0x12,2,10,-10,no,0,0,0,misc,0, KO_MUCHANAGE,Mucha Nage 3009,9:10:11:12:13,8,2,-1,0x2,3,5,2,no,0,0,0,weapon,0, KO_HUUMARANKA,Huuma Shuriken Ranka -3010,3,6,4,0,0x43,0,5,1,no,0,0x80,0,misc,0, KO_MAKIBISHI,Makibishi +3010,3,6,4,0,0x42,0,5,1,no,0,0x80,0,weapon,0, KO_MAKIBISHI,Makibishi 3011,0,6,4,0,0x1,0,5,0,yes,0,0,0,none,0, KO_MEIKYOUSISUI,Meikyo Shisui -3012,0,6,4,0,0x1,0,5,0,no,0,0,1,none,7, KO_ZANZOU,Zanzou +3012,0,6,4,0,0x1,0,5,0,no,0,0,1,none,3:4:5:6:7, KO_ZANZOU,Zanzou 3013,5,6,1,0,0x1,0,5,0,no,0,0,0,none,0, KO_KYOUGAKU,Kyougaku 3014,5,6,1,0,0x1,0,5,0,no,0,0,0,none,0, KO_JYUSATSU,Jyusatsu 3015,0,6,4,3,0x1,0,1,1,no,0,0,0,none,0, KO_KAHU_ENTEN,Kahu Enten 3016,0,6,4,1,0x1,0,1,1,no,0,0,0,none,0, KO_HYOUHU_HUBUKI,Hyouhu Hubuki 3017,0,6,4,4,0x1,0,1,1,no,0,0,0,none,0, KO_KAZEHU_SEIRAN,Kazehu Seiran 3018,0,6,4,2,0x1,0,1,1,no,0,0,0,none,0, KO_DOHU_KOUKAI,Dohu Koukai -3019,11,6,1,0,0,0,5,0,no,0,0,0,weapon,0, KO_KAIHOU,Technique Kaihou +3019,11,6,1,0,0,0,5,0,no,0,0,0,magic,0, KO_KAIHOU,Technique Kaihou 3020,7,6,2,0,0,0,1,3,yes,0,0,0,magic,0, KO_ZENKAI,Zenkai 3021,5:6:7:8:9,6,16,0,0x1,0,5,1,no,0,0,0,none,0, KO_GENWAKU,Genwaku 3022,0,6,4,0,0x1,0,5,0,no,0,0,0,none,0, KO_IZAYOI,Izayoi @@ -1079,45 +1079,25 @@ 3035,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0, ECLAGE_RECALL,Return To Eclage // EP 14.3 Part 2 3rd Job Skills -//5001,0,0,22:34:46:58:70,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GC_DARKCROW#Dark Claw# -//5002,0,0,100:120:140:160:180,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimited# -//5003,0,0,60:70:80:90:100,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_ILLUSIONDOPING#Illusion Doping# -//5004,0,0,30:35:40:45:50:55:60:65:70:75,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath - Water# -//5005,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_LUXANIMA#Lux Anima# -//5006,0,0,60:70:80:90:100,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# -//5007,0,0,200:230:260:290:320,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG#Frigg's Song# -//5008,0,0,120:120:120:120:120,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_ELEMENTAL_SHIELD#Elemental Shield# -//5009,0,0,75:65:55:45:35,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO#Flash Combo# -//5010,0,0,30:26:22:18:14,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SC_ESCAPE#Emergency Escape# -//5011,0,0,30:60:90:120:150,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AB_OFFERTORIUM#Offertorium# -//5012,0,0,100:150:200:250:300,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WL_TELEKINESIS_INTENSE#Intense Telekinesis# -//5013,0,0,200:180:160:140:120,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# -//5014,0,0,1:1:1:1:1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# -//5015,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP1#Flash Combo Attack Step 1#//All 4 steps are using temp req SP values for now. -//5016,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP2#Flash Combo Attack Step 2# -//5017,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP3#Flash Combo Attack Step 3# -//5018,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP4#Flash Combo Attack Step 4# - - -// EP 14.3 Part 2 3rd Job Skills -//5001,1,6,1,-1,0,0,5,1,no,0,0,0,weapon,0, GC_DARKCROW,Dark Claw -//5002,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, RA_UNLIMIT,Unlimited -//5003,7,6,1,-1,0x2,4:5:6:7:8,5,1,no,0,0,0,weapon,0,GN_ILLUSIONDOPING,Illusion Doping -//5004,9,6,2,1,0x2,1:1:1:2:2:2:3:3:4:4,10,1,no,0,0,0,weapon,0, RK_DRAGONBREATH_WATER,Dragon Breath - Water +5001,1,6,1,-1,0,0,5,1,no,0,0,0,weapon,0, GC_DARKCROW,Dark Claw +5002,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, RA_UNLIMIT,Unlimited +//5003,7,6,1,-1,0x2,4:5:6:7:8,5,1,no,0,0,0,weapon,0, GN_ILLUSIONDOPING,Illusion Doping +5004,9,6,2,1,0x2,1:1:1:2:2:2:3:3:4:4,10,1,no,0,0,0,misc,0, RK_DRAGONBREATH_WATER,Dragon Breath - Water //5005,0,6,4,0,0x3,3,1,1,no,0,0,0,none,0, RK_LUXANIMA,Lux Anima -//5006,1,6,2,3,0,0,5,1,no,0,0,3,misc,0, NC_MAGMA_ERUPTION,Magma Eruption -//5007,0,6,4,0,0x3,5:6:7:8:9,5,1,no,0,0,0,none,0, WM_FRIGG_SONG,Frigg's Song +5006,1,6,2,3,0,0,5,1,no,0,0,3,misc,0, NC_MAGMA_ERUPTION,Magma Eruption +5007,0,6,4,0,0x3,5:6:7:8:9,5,1,no,0,0,0,none,0, WM_FRIGG_SONG,Frigg's Song //5008,0,6,4,0,0x3,15,5,1,no,0,0,0,none,0, SO_ELEMENTAL_SHIELD,Elemental Shield -//5009,1,6,1,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO,Flash Combo//I can mark this as a no damage skill right? -//5010,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SC_ESCAPE,Emergency Escape//Said places a ankle snare trap. Must confirm before I remove the no damage thing. -//5011,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, AB_OFFERTORIUM,Offertorium -//5012,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, WL_TELEKINESIS_INTENSE,Intense Telekinesis -//5013,0,6,4,0,0x3,5,5,1,no,0,0,0,none,0, LG_KINGS_GRACE,King's Grace//Need to know the splash AoE -//5014,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, ALL_FULL_THROTTLE,Full Throttle -//5015,-2,8,4,-1,0,0,10,-2,no,0,0x200,0,weapon,0, SR_FLASHCOMBO_ATK_STEP1,Flash Combo Attack Step 1//Dragon Combo -//5016,-2,8,4,-1,0,0,5,-2,no,0,0x200,0,weapon,0, SR_FLASHCOMBO_ATK_STEP2,Flash Combo Attack Step 2//Fallen Empire -//5017,-2,6,4,-1,0x42,1:1:1:1:1:2:2:2:2:2,10,1,no,0,0x200,0,weapon,0, SR_FLASHCOMBO_ATK_STEP3,Flash Combo Attack Step 3//Tiger Cannon -//5018,0,8,4,-1,0x2,2,5,-3,no,0,0,0,weapon,0, SR_FLASHCOMBO_ATK_STEP4,Flash Combo Attack Step 4//Skynet Blow +5009,1,6,1,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO,Flash Combo +//5010,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SC_ESCAPE,Emergency Escape +5011,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, AB_OFFERTORIUM,Offertorium +5012,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, WL_TELEKINESIS_INTENSE,Intense Telekinesis +5013,0,6,4,0,0x3,5,5,1,no,0,0,0,none,0, LG_KINGS_GRACE,King's Grace +5014,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, ALL_FULL_THROTTLE,Full Throttle +5015,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO_ATK_STEP1,Flash Combo Attack Step 1 +5016,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO_ATK_STEP2,Flash Combo Attack Step 2 +5017,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO_ATK_STEP3,Flash Combo Attack Step 3 +5018,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0, SR_FLASHCOMBO_ATK_STEP4,Flash Combo Attack Step 4 + 8001,9,6,4,0,0x1,0,5,1,no,0,0,0,magic,0, HLIF_HEAL,Healing Touch 8002,0,6,4,0,0x3,-1,5,1,no,0,0,0,none,0, HLIF_AVOID,Avoid diff --git a/db/re/skill_require_db.txt b/db/re/skill_require_db.txt index eccbbe456..6202ba94f 100644 --- a/db/re/skill_require_db.txt +++ b/db/re/skill_require_db.txt @@ -292,7 +292,7 @@ 374,0,0,5,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //PF_SOULCHANGE#ƒ\ƒEƒ‹ƒ`ƒFƒ“ƒW# 375,0,0,80:90:100:110:120,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //PF_SOULBURN#?ƒEƒ‹ƒo?ƒ“# -378,0,0,60:70:80:90:100,0,0,0,99,0,0,none,0,678,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ASC_EDP#ƒGƒ“ƒ`ƒƒƒ“ƒgƒfƒbƒhƒŠ?ƒ|ƒCƒYƒ“# +378,0,0,60:70:80:90:100,0,0,0,1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:22,0,0,none,0,678,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ASC_EDP#ƒGƒ“ƒ`ƒƒƒ“ƒgƒfƒbƒhƒŠ?ƒ|ƒCƒYƒ“# 379,0,0,20:20:20:20:20:30:30:30:30:30,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ASC_BREAKER#ƒ\ƒEƒ‹ƒuƒŒ?ƒJ?# 380,0,0,20:20:25:25:30:30:35:35:40:40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SN_SIGHT#ƒgƒDƒ‹?ƒTƒCƒg# 381,0,0,30:34:38:42:46,0,0,0,99,0,0,falcon,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SN_FALCONASSAULT#ƒtƒ@ƒ‹ƒRƒ“ƒAƒTƒ‹ƒg# @@ -475,7 +475,7 @@ 2008,0,0,30:35:40:45:50:55:60:65:70:75,0,0,0,99,0,0,dragon,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH#Dragon Breath# 2009,0,0,70,0,0,0,99,0,0,dragon,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 2011,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_MILLENNIUMSHIELD#Millenium Shield# -2012,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_CRUSHSTRIKE#Crush Strike# +2012,0,0,1,0,0,0,1:2:3:4:5:6:7:8,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_CRUSHSTRIKE#Crush Strike# 2013,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_REFRESH#Refresh# 2014,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_GIANTGROWTH#Giant Growth# 2015,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_STONEHARDSKIN#Stone Hard Skin# @@ -830,6 +830,26 @@ 3027,0,0,55:60:65:70:75 ,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //OB_OBOROGENSOU#Oboro Gensou# 3029,0,0,20:30:40:50:60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //OB_AKAITSUKI#Akaitsuki# +// EP 14.3 Part 2 3rd Job Skills +5001,0,0,22:34:46:58:70,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GC_DARKCROW#Dark Claw# +5002,0,0,100:120:140:160:180,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimited# +5003,0,0,60:70:80:90:100,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GN_ILLUSIONDOPING#Illusion Doping# +5004,0,0,30:35:40:45:50:55:60:65:70:75,0,0,0,99,0,0,dragon,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath - Water# +5005,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //RK_LUXANIMA#Lux Anima# +5006,0,0,60:70:80:90:100,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# +5007,0,0,200:230:260:290:320,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG#Frigg's Song# +5008,0,0,120:120:120:120:120,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SO_ELEMENTAL_SHIELD#Elemental Shield# +5009,0,0,75:65:55:45:35,0,0,0,99,0,0,none,5:5:4:4:3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO#Flash Combo# +5010,0,0,30:26:22:18:14,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SC_ESCAPE#Emergency Escape# +5011,0,0,30:60:90:120:150,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AB_OFFERTORIUM#Offertorium# +5012,0,0,100:150:200:250:300,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WL_TELEKINESIS_INTENSE#Intense Telekinesis# +5013,0,0,200:180:160:140:120,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +5014,0,0,1:1:1:1:1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# +5015,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP1#Flash Combo Attack Step 1#//All 4 steps are using temp req SP values for now. +5016,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP2#Flash Combo Attack Step 2# +5017,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP3#Flash Combo Attack Step 3# +5018,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //SR_FLASHCOMBO_ATK_STEP4#Flash Combo Attack Step 4# + 10010,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_BATTLEORDER## 10011,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_REGENERATION## 10012,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //GD_RESTORE## diff --git a/db/re/skill_tree.txt b/db/re/skill_tree.txt index b8b1cb86b..e7420dafe 100644 --- a/db/re/skill_tree.txt +++ b/db/re/skill_tree.txt @@ -2483,6 +2483,8 @@ 4054,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4054,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4054,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4054,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4054,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Warlock (Regular) 4055,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4055,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2539,6 +2541,8 @@ 4055,2230,2,0,0,0,0,0,0,0,0,0,0 //WL_RELEASE#Release# 4055,2231,1,0,0,0,0,0,0,0,0,0,0 //WL_READING_SB#Reading Spellbook# 4055,2232,5,0,0,0,0,0,0,0,0,0,0 //WL_FREEZE_SP#Freeze Spell# +4055,5012,5,2202,5,0,0,0,0,0,0,0,0 //WL_TELEKINESIS_INTENSE#Intense Telekinesis# +4055,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Ranger (Regular) 4056,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4056,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2592,6 +2596,8 @@ 4056,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4056,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4056,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4056,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4056,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Arch Bishop (Regular) 4057,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4057,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2650,6 +2656,8 @@ 4057,2054,10,68,1,0,0,0,0,0,0,0,0 //AB_DUPLELIGHT#Duple Light# 4057,2057,5,2052,1,0,0,0,0,0,0,0,0 //AB_SILENTIUM#Silentium# 4057,2515,5,2044,1,2053,1,0,0,0,0,0,0 //AB_SECRAMENT#Secrament# +4057,5011,5,2051,2,0,0,0,0,0,0,0,0 //AB_OFFERTORIUM#Offertorium# +4057,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Mechanic (Regular) 4058,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4058,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2718,7 +2726,9 @@ 4058,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4058,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4058,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4058,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4058,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4058,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Guillotine Cross (Regular) 4059,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4059,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2763,6 +2773,8 @@ 4059,2035,5,2034,1,0,0,0,0,0,0,0,0 //GC_HALLUCINATIONWALK#Hallucination Walk# 4059,2036,5,136,10,0,0,0,0,0,0,0,0 //GC_ROLLINGCUTTER#Rolling Cutter# 4059,2037,5,2036,1,0,0,0,0,0,0,0,0 //GC_CROSSRIPPERSLASHER#Cross Ripper Slasher# +4059,5001,5,2023,5,0,0,0,0,0,0,0,0 //GC_DARKCROW#Dark Claw# +4059,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Rune Knight (Trans) 4060,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4060,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2809,6 +2821,8 @@ 4060,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4060,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4060,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4060,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4060,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Warlock (Trans) 4061,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4061,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2871,6 +2885,8 @@ 4061,2230,2,0,0,0,0,0,0,0,0,0,0 //WL_RELEASE#Release# 4061,2231,1,0,0,0,0,0,0,0,0,0,0 //WL_READING_SB#Reading Spellbook# 4061,2232,5,0,0,0,0,0,0,0,0,0,0 //WL_FREEZE_SP#Freeze Spell# +4061,5012,5,2202,5,0,0,0,0,0,0,0,0 //WL_TELEKINESIS_INTENSE#Intense Telekinesis# +4061,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Ranger (Trans) 4062,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4062,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2928,6 +2944,8 @@ 4062,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4062,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4062,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4062,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4062,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Arch Bishop (Trans) 4063,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4063,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -2990,6 +3008,8 @@ 4063,2054,10,68,1,0,0,0,0,0,0,0,0 //AB_DUPLELIGHT#Duple Light# 4063,2057,5,2052,1,0,0,0,0,0,0,0,0 //AB_SILENTIUM#Silentium# 4063,2515,5,2044,1,2053,1,0,0,0,0,0,0 //AB_SECRAMENT#Secrament# +4063,5011,5,2051,2,0,0,0,0,0,0,0,0 //AB_OFFERTORIUM#Offertorium# +4063,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Mechanic (Trans) 4064,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4064,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3063,7 +3083,9 @@ 4064,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4064,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4064,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4064,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4064,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4064,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Guillotine Cross (Trans) 4065,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4065,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3113,6 +3135,8 @@ 4065,2035,5,2034,1,0,0,0,0,0,0,0,0 //GC_HALLUCINATIONWALK#Hallucination Walk# 4065,2036,5,136,10,0,0,0,0,0,0,0,0 //GC_ROLLINGCUTTER#Rolling Cutter# 4065,2037,5,2036,1,0,0,0,0,0,0,0,0 //GC_CROSSRIPPERSLASHER#Cross Ripper Slasher# +4065,5001,5,2023,5,0,0,0,0,0,0,0,0 //GC_DARKCROW#Dark Claw# +4065,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Royal Guard (Regular) 4066,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4066,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3166,6 +3190,8 @@ 4066,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4066,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4066,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4066,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4066,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Sorcerer (Regular) 4067,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4067,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3236,6 +3262,7 @@ 4067,2466,3,2458,3,0,0,0,0,0,0,0,0 //SO_WATER_INSIGNIA#Water Insignia# 4067,2467,3,2459,3,0,0,0,0,0,0,0,0 //SO_WIND_INSIGNIA#Wind Insignia# 4067,2468,3,2460,3,0,0,0,0,0,0,0,0 //SO_EARTH_INSIGNIA#Earth Insignia# +4067,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Minstrel (Regular) 4068,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4068,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3291,6 +3318,8 @@ 4068,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4068,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4068,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4068,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4068,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Wanderer (Regular) 4069,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4069,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3346,6 +3375,8 @@ 4069,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4069,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4069,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4069,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4069,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Sura (Regular) 4070,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4070,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3405,6 +3436,8 @@ 4070,2348,5,2347,5,0,0,0,0,0,0,0,0 //SR_GENTLETOUCH_REVITALIZE#Gentle Touch - Revitalize# 4070,2517,5,2340,1,2518,3,0,0,0,0,0,0 //SR_HOWLINGOFLION#Howling Of Lion# 4070,2518,5,267,3,0,0,0,0,0,0,0,0 //SR_RIDEINLIGHTNING#Ride In Lightening# +4070,5009,5,2326,3,2329,3,2330,1,2327,1,0,0 //SR_FLASHCOMBO#Flash Combo# +4070,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Genetic (Regular) 4071,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4071,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3459,7 +3492,9 @@ 4071,2495,2,2497,1,0,0,0,0,0,0,0,0 //GN_MIX_COOKING#Mix Cooking# 4071,2496,2,2495,1,0,0,0,0,0,0,0,0 //GN_MAKEBOMB#Create Bomb# 4071,2497,10,0,0,0,0,0,0,0,0,0,0 //GN_S_PHARMACY#Special Pharmacy# +4071,5003,5,2497,1,0,0,0,0,0,0,0,0 //GN_ILLUSIONDOOPING#Hallucination Drug# 4071,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4071,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Shadow Chaser (Regular) 4072,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4072,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3517,6 +3552,8 @@ 4072,2302,3,2296,3,2301,3,0,0,0,0,0,0 //SC_MAELSTROM#Maelstrom# 4072,2303,3,2300,3,0,0,0,0,0,0,0,0 //SC_BLOODYLUST#Bloody Lust# 4072,2304,3,2300,3,0,0,0,0,0,0,0,0 //SC_FEINTBOMB#Feint Bomb# +4072,5010,5,2288,2,0,0,0,0,0,0,0,0 //SC_SCAPE#Scape# +4072,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Royal Guard (Trans) 4073,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4073,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3574,6 +3611,8 @@ 4073,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4073,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4073,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4073,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4073,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Sorcerer (Trans) 4074,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4074,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3652,6 +3691,7 @@ 4074,2466,3,2458,3,0,0,0,0,0,0,0,0 //SO_WATER_INSIGNIA#Water Insignia# 4074,2467,3,2459,3,0,0,0,0,0,0,0,0 //SO_WIND_INSIGNIA#Wind Insignia# 4074,2468,3,2460,3,0,0,0,0,0,0,0,0 //SO_EARTH_INSIGNIA#Earth Insignia# +4074,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Minstrel (Trans) 4075,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4075,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3713,6 +3753,8 @@ 4075,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4075,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4075,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4075,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4075,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Wanderer (Trans) 4076,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4076,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3774,6 +3816,8 @@ 4076,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4076,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4076,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4076,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4076,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Sura (Trans) 4077,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4077,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3837,6 +3881,8 @@ 4077,2348,5,2347,5,0,0,0,0,0,0,0,0 //SR_GENTLETOUCH_REVITALIZE#Gentle Touch - Revitalize# 4077,2517,5,2340,1,2518,3,0,0,0,0,0,0 //SR_HOWLINGOFLION#Howling Of Lion# 4077,2518,5,267,3,0,0,0,0,0,0,0,0 //SR_RIDEINLIGHTNING#Ride In Lightening# +4077,5009,5,2326,3,2329,3,2330,1,2327,1,0,0 //SR_FLASHCOMBO#Flash Combo# +4077,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Genetic (Trans) 4078,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4078,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3895,7 +3941,9 @@ 4078,2495,2,2497,1,0,0,0,0,0,0,0,0 //GN_MIX_COOKING#Mix Cooking# 4078,2496,2,2495,1,0,0,0,0,0,0,0,0 //GN_MAKEBOMB#Create Bomb# 4078,2497,10,0,0,0,0,0,0,0,0,0,0 //GN_S_PHARMACY#Special Pharmacy# +4078,5003,5,2497,1,0,0,0,0,0,0,0,0 //GN_ILLUSIONDOOPING#Hallucination Drug# 4078,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4078,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Shadow Chaser (Trans) 4079,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4079,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3941,6 +3989,7 @@ 4079,2286,10,2285,5,0,0,0,0,0,0,0,0 //SC_AUTOSHADOWSPELL#Auto Shadow Spell# 4079,2287,5,213,3,0,0,0,0,0,0,0,0 //SC_SHADOWFORM#Shadow Form# 4079,2288,10,46,7,0,0,0,0,0,0,0,0 //SC_TRIANGLESHOT#Triangle Shot# +4079,5010,5,2288,2,0,0,0,0,0,0,0,0 //SC_SCAPE#Scape# 4079,2289,5,0,0,0,0,0,0,0,0,0,0 //SC_BODYPAINT#Body Painting# 4079,2290,5,2286,7,2291,5,2296,3,0,0,0,0 //SC_INVISIBILITY#Invisibility# 4079,2291,5,2286,5,2287,3,0,0,0,0,0,0 //SC_DEADLYINFECT#Deadly Infect# @@ -3957,6 +4006,7 @@ 4079,2302,3,2296,3,2301,3,0,0,0,0,0,0 //SC_MAELSTROM#Maelstrom# 4079,2303,3,2300,3,0,0,0,0,0,0,0,0 //SC_BLOODYLUST#Bloody Lust# 4079,2304,3,2300,3,0,0,0,0,0,0,0,0 //SC_FEINTBOMB#Feint Bomb# +4079,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Rune Knight (Dragon) (Regular) 4080,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4080,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -3995,6 +4045,8 @@ 4080,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4080,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4080,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4080,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4080,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Rune Knight (Dragon) (Trans) 4081,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4081,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4041,6 +4093,8 @@ 4081,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4081,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4081,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4081,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4081,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Royal Guard (Gryphon) (Regular) 4082,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4082,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4094,6 +4148,8 @@ 4082,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4082,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4082,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4082,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4082,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Royal Guard (Gryphon) (Trans) 4083,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4083,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4151,6 +4207,8 @@ 4083,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4083,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4083,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4083,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4083,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Ranger (Warg) (Regular) 4084,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4084,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4204,6 +4262,8 @@ 4084,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4084,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4084,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4084,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4084,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Ranger (Warg) (Trans) 4085,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4085,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4261,6 +4321,8 @@ 4085,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4085,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4085,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4085,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4085,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Mechanic (Mado) (Regular) 4086,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4086,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4329,7 +4391,9 @@ 4086,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4086,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4086,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4086,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4086,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4086,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Mechanic (Mado) (Trans) 4087,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4087,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4403,7 +4467,9 @@ 4087,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4087,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4087,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4087,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4087,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4087,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Rune Knight 4096,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4096,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4443,6 +4509,8 @@ 4096,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4096,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4096,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4096,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4096,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Warlock 4097,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4097,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4500,6 +4568,8 @@ 4097,2230,2,0,0,0,0,0,0,0,0,0,0 //WL_RELEASE#Release# 4097,2231,1,0,0,0,0,0,0,0,0,0,0 //WL_READING_SB#Reading Spellbook# 4097,2232,5,0,0,0,0,0,0,0,0,0,0 //WL_FREEZE_SP#Freeze Spell# +4097,5012,5,2202,5,0,0,0,0,0,0,0,0 //WL_TELEKINESIS_INTENSE#Intense Telekinesis# +4097,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Ranger 4098,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4098,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4554,6 +4624,8 @@ 4098,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4098,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4098,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4098,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4098,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Arch Bishop 4099,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4099,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4613,6 +4685,8 @@ 4099,2054,10,68,1,0,0,0,0,0,0,0,0 //AB_DUPLELIGHT#Duple Light# 4099,2057,5,2052,1,0,0,0,0,0,0,0,0 //AB_SILENTIUM#Silentium# 4099,2515,5,2044,1,2053,1,0,0,0,0,0,0 //AB_SECRAMENT#Secrament# +4099,5011,5,2051,2,0,0,0,0,0,0,0,0 //AB_OFFERTORIUM#Offertorium# +4099,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Mechanic 4100,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4100,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4682,7 +4756,9 @@ 4100,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4100,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4100,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4100,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4100,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4100,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Guillotine Cross 4101,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4101,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4728,6 +4804,8 @@ 4101,2035,5,2034,1,0,0,0,0,0,0,0,0 //GC_HALLUCINATIONWALK#Hallucination Walk# 4101,2036,5,136,10,0,0,0,0,0,0,0,0 //GC_ROLLINGCUTTER#Rolling Cutter# 4101,2037,5,2036,1,0,0,0,0,0,0,0,0 //GC_CROSSRIPPERSLASHER#Cross Ripper Slasher# +4101,5001,5,2023,5,0,0,0,0,0,0,0,0 //GC_DARKCROW#Dark Claw# +4101,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Royal Guard 4102,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4102,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4782,6 +4860,8 @@ 4102,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4102,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4102,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4102,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4102,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Sorcerer 4103,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4103,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4853,6 +4933,7 @@ 4103,2466,3,2458,3,0,0,0,0,0,0,0,0 //SO_WATER_INSIGNIA#Water Insignia# 4103,2467,3,2459,3,0,0,0,0,0,0,0,0 //SO_WIND_INSIGNIA#Wind Insignia# 4103,2468,3,2460,3,0,0,0,0,0,0,0,0 //SO_EARTH_INSIGNIA#Earth Insignia# +4103,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Minstrel 4104,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4104,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4909,6 +4990,8 @@ 4104,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4104,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4104,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4104,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4104,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Wanderer 4105,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4105,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -4965,6 +5048,8 @@ 4105,2432,5,2427,1,0,0,0,0,0,0,0,0 //WM_MELODYOFSINK#Melody Of Sink# 4105,2433,5,2431,1,0,0,0,0,0,0,0,0 //WM_BEYOND_OF_WARCRY#Warcry Of Beyond# 4105,2434,5,2429,1,2433,1,0,0,0,0,0,0 //WM_UNLIMITED_HUMMING_VOICE#Unlimited Humming Voice# +4105,5007,5,2412,1,0,0,0,0,0,0,0,0 //WM_FRIGG_SONG# +4105,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Sura 4106,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4106,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5025,6 +5110,8 @@ 4106,2348,5,2347,5,0,0,0,0,0,0,0,0 //SR_GENTLETOUCH_REVITALIZE#Gentle Touch - Revitalize# 4106,2517,5,2340,1,2518,3,0,0,0,0,0,0 //SR_HOWLINGOFLION#Howling Of Lion# 4106,2518,5,267,3,0,0,0,0,0,0,0,0 //SR_RIDEINLIGHTNING#Ride In Lightening# +4106,5009,5,2326,3,2329,3,2330,1,2327,1,0,0 //SR_FLASHCOMBO#Flash Combo# +4106,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Genetic 4107,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4107,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5080,7 +5167,9 @@ 4107,2495,2,2497,1,0,0,0,0,0,0,0,0 //GN_MIX_COOKING#Mix Cooking# 4107,2496,2,2495,1,0,0,0,0,0,0,0,0 //GN_MAKEBOMB#Create Bomb# 4107,2497,10,0,0,0,0,0,0,0,0,0,0 //GN_S_PHARMACY#Special Pharmacy# +4107,5003,5,2497,1,0,0,0,0,0,0,0,0 //GN_ILLUSIONDOOPING#Hallucination Drug# 4107,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4107,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Shadow Chaser 4108,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4108,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5139,6 +5228,8 @@ 4108,2302,3,2296,3,2301,3,0,0,0,0,0,0 //SC_MAELSTROM#Maelstrom# 4108,2303,3,2300,3,0,0,0,0,0,0,0,0 //SC_BLOODYLUST#Bloody Lust# 4108,2304,3,2300,3,0,0,0,0,0,0,0,0 //SC_FEINTBOMB#Feint Bomb# +4108,5010,5,2288,2,0,0,0,0,0,0,0,0 //SC_SCAPE#Scape# +4108,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Rune Knight (Dragon) 4109,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4109,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5178,6 +5269,8 @@ 4109,2009,5,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONHOWLING#Dragon Howling# 4109,2010,10,0,0,0,0,0,0,0,0,0,0 //RK_RUNEMASTERY#Rune Mastery# 4109,2020,5,57,2,0,0,0,0,0,0,0,0 //RK_PHANTOMTHRUST#Phantom Thrust# +4009,5004,10,2007,2,0,0,0,0,0,0,0,0 //RK_DRAGONBREATH_WATER#Dragon Breath(Water)# +4109,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Royal Guard (Gryphon) 4110,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4110,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5232,6 +5325,8 @@ 4110,2323,5,2311,3,0,0,0,0,0,0,0,0 //LG_EARTHDRIVE#Earth Drive# 4110,2324,5,2318,3,2319,3,0,0,0,0,0,0 //LG_HESPERUSLIT#Hesperus Lit# 4110,2325,5,2315,3,2321,4,2322,5,0,0,0,0 //LG_INSPIRATION#Inspiration# +4110,5013,5,2311,5,0,0,0,0,0,0,0,0 //LG_KINGS_GRACE#King's Grace# +4110,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Ranger (Warg) 4111,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4111,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5286,6 +5381,8 @@ 4111,2252,1,2248,1,0,0,0,0,0,0,0,0 //RA_VERDURETRAP#Verdure Trap# 4111,2253,5,2237,1,0,0,0,0,0,0,0,0 //RA_FIRINGTRAP#Firing Trap# 4111,2254,5,2237,1,0,0,0,0,0,0,0,0 //RA_ICEBOUNDTRAP#Icebound Trap# +4111,5002,5,2234,5,0,0,0,0,0,0,0,0 //RA_UNLIMIT#Unlimit# +4111,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Baby Mechanic (Mado) 4112,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4112,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# @@ -5355,7 +5452,9 @@ 4112,2281,5,2277,2,0,0,0,0,0,0,0,0 //NC_SILVERSNIPER#FAW - Silver Sniper# 4112,2282,5,2277,2,0,0,0,0,0,0,0,0 //NC_MAGICDECOY#FAW - Magic Decoy# 4112,2283,1,2281,1,0,0,0,0,0,0,0,0 //NC_DISJOINT#FAW Removal# +4112,5006,5,0,0,0,0,0,0,0,0,0,0 //NC_MAGMA_ERUPTION#Magma Eruption# 4112,2535,1,41,1,0,0,0,0,0,0,0,0 //ALL_BUYING_STORE#Open Buying Store# +4112,5014,5,0,0,0,0,0,0,0,0,0,0 //ALL_FULL_THROTTLE#Full Throttle# //Super Novice (Expanded) 4190,1,9,0,0,0,0,0,0,0,0,0,0 //NV_BASIC#Basic Skill# 4190,142,1,0,0,0,0,0,0,0,0,0,0 //NV_FIRSTAID#First Aid# diff --git a/db/re/skill_unit_db.txt b/db/re/skill_unit_db.txt index d8c19dbe9..7468c6cc3 100644 --- a/db/re/skill_unit_db.txt +++ b/db/re/skill_unit_db.txt @@ -2,7 +2,7 @@ // // layout = -1:special, 0:1*1, 1:3*3, 2:5*5, up to 5:11*11 // target = friend (party +guildmates +neutral players) / party / guild -// ally (party +guildmates) / all / sameguild (guild but no allies) / enemy +// ally (party +guildmates) / all / enemy // flag 0x001(UF_DEFNOTENEMY) If 'defunit_not_enemy' is set, the target is changed to 'friend' // 0x002(UF_NOREITERRATION) Spell cannot be stacked // 0x004(UF_NOFOOTSET) Spell cannot be cast near/on targets @@ -30,7 +30,7 @@ 21,0x86, , 0, 2,1000,enemy, 0x018 //MG_THUNDERSTORM 25,0x85, , 1, 0, -1,all, 0x003 //AL_PNEUMA 27,0x81,0x80, 0, 0, -1,all, 0x00E //AL_WARP - 47,0x86, , 0, 2,1000,enemy, 0x080 //AC_SHOWER + 47,0x86, , 0, 2:2:2:2:2:3:3:3:3:3,1000,enemy, 0x080 //AC_SHOWER 70,0x83, , -1, 1,1000,all, 0x018 //PR_SANCTUARY 79,0x84, , -1, 1,3000,enemy, 0x018 //PR_MAGNUS 80,0x87,0x88, 0, 1,2000,enemy, 0x006 //WZ_FIREPILLAR @@ -105,8 +105,8 @@ 2032,0xe1, , 2, 0,1000,enemy, 0x018 //GC_POISONSMOKE -2214,0x86, , 0, 5, 100,enemy, 0x080 //WL_CHAINLIGHTNING -2216,0xcb, , -1, 0, 150,enemy, 0x018 //WL_EARTHSTRAIN +2213,0x86, , 0, 8, 100,enemy, 0x018 //WL_COMET +2216,0xcb, , -1, 0, 100,enemy, 0x018 //WL_EARTHSTRAIN 2238,0xd8, , 0, 1,1000,enemy, 0x006 //RA_ELECTRICSHOCKER 2239,0xd9, , 0, 1,1000,enemy, 0x006 //RA_CLUSTERBOMB @@ -158,7 +158,10 @@ 3008,0x86, , 0, 2, 100,enemy, 0x018 //KO_MUCHANAGE 3009,0x86, , 0, 3, 500,enemy, 0x018 //KO_HUUMARANKA 3020,0xf8, , 0, 3, 100,all, 0x018 //KO_ZENKAI -3010,0xfc, , 0, 1,1000,enemy, 0x020 //KO_MAKIBISHI +3010,0xfc, , 0, 0,5000,enemy, 0x018 //KO_MAKIBISHI + +5006,0x101, , 0, 3,2000,enemy, 0x018 //NC_MAGMA_ERUPTION +5010,0xfe, , 0, 2, -1,enemy, 0x000 //SC_SCAPE 8020,0xf5, , 0, 3,2300:2100:1900:1700:1500,enemy, 0x018 //MH_POISON_MIST 8033,0x7e, , 0, 0, -1,all, 0x003 //MH_STEINWAND @@ -177,7 +180,7 @@ 8409,0xef, , 0, 1,1000,friend,0x018 //EL_ZEPHYR 8412,0xf0, , 0, 1, -1,friend,0x018 //EL_POWER_OF_GAIA -10006,0xc1, , 2, 0, -1,sameguild, 0x040 //GD_LEADERSHIP -10007,0xc2, , 2, 0, -1,sameguild, 0x040 //GD_GLORYWOUNDS -10008,0xc3, , 2, 0, -1,sameguild, 0x040 //GD_SOULCOLD -10009,0xc4, , 2, 0, -1,sameguild, 0x040 //GD_HAWKEYES +10006,0xc1, , 2, 0, -1,guild, 0x040 //GD_LEADERSHIP +10007,0xc2, , 2, 0, -1,guild, 0x040 //GD_GLORYWOUNDS +10008,0xc3, , 2, 0, -1,guild, 0x040 //GD_SOULCOLD +10009,0xc4, , 2, 0, -1,guild, 0x040 //GD_HAWKEYES diff --git a/db/sc_config.txt b/db/sc_config.txt new file mode 100644 index 000000000..2da6f3147 --- /dev/null +++ b/db/sc_config.txt @@ -0,0 +1,407 @@ +// Status Change configuration database +// +// Structure of Database: +// SC_NAME, flag +// +// flag 0x1 - SC cannot be removed by death. +// 0x2 - SC cannot be saved. +// 0x4 - SC cannot be reset by dispell. +// 0x8 - SC cannot be reset by clearance. +// 0x10 - SC considered as buff and be removed by Hermode and etc. +// 0x20 - SC considered as debuff and be removed by Gospel and etc. +// 0x40 - SC cannot be reset when MADO Gear is taken off. + +SC_PROVOKE, 0x20 +SC_ENDURE, 0x15 +SC_TWOHANDQUICKEN, 0x18 +SC_CONCENTRATION, 0x10 +SC_ENCHANTPOISON, 0x10 +SC_POISONREACT, 0x10 +SC_QUAGMIRE, 0x2A +SC_ANGELUS, 0x10 +SC_BLESSING, 0x50 +SC_INC_AGI, 0x50 +SC_DEC_AGI, 0x22 +SC_SLOWPOISON, 0x18 +SC_IMPOSITIO, 0x10 +SC_SUFFRAGIUM, 0x10 +SC_ASPERSIO, 0x50 +SC_BENEDICTIO, 0x1A +SC_KYRIE, 0x10 +SC_MAGNIFICAT, 0x12 +SC_GLORIA, 0x10 +SC_LEXAETERNA, 0x12 +SC_ADRENALINE, 0x10 +SC_WEAPONPERFECT, 0x10 +SC_OVERTHRUST, 0x10 +SC_MAXIMIZEPOWER, 0x10 +SC_TRICKDEAD, 0x1A +SC_SHOUT, 0x10 +SC_ENERGYCOAT, 0x10 +SC_ATTHASTE_POTION1, 0x18 +SC_ATTHASTE_POTION2, 0x18 +SC_ATTHASTE_POTION3, 0x10 +//SC_MOVHASTE_POTION, 0x1A +//SC_POSTDELAY, 0x1D +SC_BARRIER, 0x10 +SC_NOEQUIPWEAPON, 0x1E +SC_NOEQUIPSHIELD, 0x1E +SC_NOEQUIPARMOR, 0x1E +SC_NOEQUIPHELM, 0x1E +SC_PROTECTWEAPON, 0x1C +SC_PROTECTSHIELD, 0x1C +SC_PROTECTARMOR, 0x1C +SC_PROTECTHELM, 0x1C +SC_AUTOGUARD, 0x18 +SC_REFLECTSHIELD, 0x18 +SC_DEVOTION, 0x12 +SC_PROVIDENCE, 0x12 +SC_DEFENDER, 0x10 +SC_MAGICROD, 0x1A +//SC_WEAPONPROPERTY, 0x18 +SC_AUTOSPELL, 0x15 +//SC_SPECIALZONE, 0x1A +//SC_MASK, 0x1A +SC_SPEARQUICKEN, 0x10 +SC_BLADESTOP, 0x1A +SC_EXPLOSIONSPIRITS, 0x1A +SC_STEELBODY, 0x12 +SC_PROPERTYFIRE, 0x1D +SC_PROPERTYWATER, 0x1D +SC_PROPERTYWIND, 0x1D +SC_PROPERTYGROUND, 0x1D +SC_STOP, 0x1A +SC_PROPERTYUNDEAD, 0x1A +//SC_STATUSONE, 0x1A +SC_AURABLADE, 0x12 +SC_PARRYING, 0x1A +SC_LKCONCENTRATION, 0x12 +SC_TENSIONRELAX, 0x1A +SC_BERSERK, 0x12 +SC_SACRIFICE, 0x1A +SC_GOSPEL, 0x22 +SC_ASSUMPTIO, 0x10 +SC_BASILICA, 0x1A +//SC_GROUNDMAGIC, 0x1A //is divided to SC_VOLCANO, 0xSC_DELUGE, 0xSC_VIOLENTGALE +SC_VOLCANO, 0x1A +SC_DELUGE, 0x1A +SC_VIOLENTGALE, 0x1A +SC_MAGICPOWER, 0x12 +SC_EDP, 0x17 +SC_TRUESIGHT, 0x12 +SC_WINDWALK, 0x12 +SC_MELTDOWN, 0x17 +SC_CARTBOOST, 0x17 +SC_BLOODING, 0x1A +SC_JOINTBEAT, 0x2A +SC_MINDBREAKER, 0x12 +SC_MEMORIZE, 0x12 +SC_FOGWALL, 0x1A +SC_SPIDERWEB, 0x2F +//SC_SUB_WEAPONPROPERTY, 0x17 +SC_RUN, 0x1A +SC_STRUP, 0x1A +SC_PROPERTYDARK, 0x1A +SC_ADRENALINE2, 0x12 +SC_PROPERTYTELEKINESIS, 0x1A +SC_SOULLINK, 0x1A +SC_PLUSATTACKPOWER, 0x58 +SC_PLUSMAGICPOWER, 0x58 +SC_KAITE, 0x1A +SC_KAAHI, 0x1A +SC_KAUPE, 0x1A +SC_ONEHANDQUICKEN, 0x1A +//SC_GDSKILL_POSTDELAY, 0x1D +SC_PRESERVE, 0x12 +SC_CHASEWALK2, 0x1A +//SC_MOVESLOW_POTION, 0x1A +SC_DOUBLECASTING, 0x1A +SC_GRAVITATION, 0x1A +SC_OVERTHRUSTMAX, 0x12 +SC_TAROTCARD, 0x2A +SC_CR_SHRINK, 0x17 +SC_WZ_SIGHTBLASTER, 0x17 +SC_RG_CCONFINE_M, 0x1F +SC_RG_CCONFINE_S, 0x1F +SC_NJ_UTSUSEMI, 0x1A +SC_NJ_BUNSINJYUTSU, 0x1A +SC_NJ_SUITON, 0x2F +//SC_MENTAL, 0x1A +//SC_EXPMEMORY, 0x1A +//SC_PERFORMANCE, 0x1A +//SC_GAIN, 0x1A +//SC_DRIFT, 0x1A +//SC_WALLSHIFT, 0x1A +//SC_REINCARNATION, 0x1A +//SC_DENERGY, 0x1A +//SC_DAURA, 0x1A +//SC_DFREEZER, 0x1A +//SC_DPUNISH, 0x1A +//SC_DBARRIER, 0x1A +//SC_DWARNING, 0x1A +//SC_MOUSEWHEEL, 0x1E +//SC_DACCEL, 0x1A +//SC_DBLOCK, 0x1A +SC_FOOD_STR, 0x1C +SC_FOOD_AGI, 0x1C +SC_FOOD_VIT, 0x1C +SC_FOOD_DEX, 0x1C +SC_FOOD_INT, 0x1C +SC_FOOD_LUK, 0x1C +SC_FOOD_BASICAVOIDANCE, 0x58 +SC_FOOD_BASICHIT, 0x58 +//SC_FOOD_CRITICALSUCCESSVALUE, 0x18 +SC_CASH_PLUSEXP, 0x1D +SC_CASH_DEATHPENALTY, 0x1D +SC_CASH_RECEIVEITEM, 0x1D +SC_CASH_BOSS_ALARM, 0x1E +//SC_DA_ENERGY, 0x1A +//SC_DA_FIRSTSLOT, 0x1A +//SC_DA_HEADDEF, 0x1A +//SC_DA_SPACE, 0x1E +//SC_DA_ITEMREBUILD, 0x1E +//SC_DA_ILLUSION, 0x1A +//SC_DA_EARPLUG, 0x1E +//SC_DA_CONTRACT, 0x1D +//SC_DA_BLACK, 0x1E +//SC_DA_MAGICCART, 0x1A +//SC_CRYSTAL, 0x1E +//SC_DA_REBUILD, 0x1D +//SC_DA_EDARKNESS, 0x1A +//SC_DA_EGUARDIAN, 0x1A +//SC_DA_TIMEOUT, 0x1A +SC_FOOD_STR_CASH, 0x1D +SC_FOOD_AGI_CASH, 0x1D +SC_FOOD_VIT_CASH, 0x1D +SC_FOOD_DEX_CASH, 0x1D +SC_FOOD_INT_CASH, 0x1D +SC_FOOD_LUK_CASH, 0x1D +SC_MER_FLEE, 0x1C +SC_MER_ATK, 0x1C +SC_MER_HP, 0x1C +SC_MER_SP, 0x1C +SC_MER_HIT, 0x1C +SC_SLOWCAST, 0x1F +SC_CRITICALWOUND, 0x17 +SC_MOVHASTE_HORSE, 0x1F +SC_PROTECT_DEF, 0x1C +SC_PROTECT_MDEF, 0x1C +SC_HEALPLUS, 0x5C +SC_S_LIFEPOTION, 0x5C +SC_L_LIFEPOTION, 0x5C +SC_CRITICALPERCENT, 0x5C +SC_PLUSAVOIDVALUE, 0x5C +//SC_ATKER_ASPD, 0x1C +//SC_TARGET_ASPD, 0x5C +//SC_ATKER_MOVESPEED, 0x1C +SC_ATKER_BLOOD, 0x1C +SC_TARGET_BLOOD, 0x1E +SC_ARMOR_PROPERTY, 0x1D +//SC_REUSE_LIMIT_A, 0x1D +SC_HELLPOWER, 0x1D +//SC_STEAMPACK, 0x5C +//SC_REUSE_LIMIT_B, 0x1D +//SC_REUSE_LIMIT_C, 0x1D +//SC_REUSE_LIMIT_D, 0x1D +//SC_REUSE_LIMIT_E, 0x1D +//SC_REUSE_LIMIT_F, 0x1D +SC_CASH_PLUSONLYJOBEXP, 0x1D +SC_PARTYFLEE, 0x18 +//SC_ANGEL_PROTECT, 0x18 +//SC_ENDURE_MDEF, 0x15 +SC_ENCHANTBLADE, 0x10 +SC_DEATHBOUND, 0x1E +SC_REFRESH, 0x16 +SC_GIANTGROWTH, 0x14 +SC_STONEHARDSKIN, 0x17 +SC_VITALITYACTIVATION, 0x14 +SC_FIGHTINGSPIRIT, 0x14 +SC_ABUNDANCE, 0x14 +//SC_REUSE_MILLENNIUMSHIELD, 0x1D +//SC_REUSE_CRUSHSTRIKE, 0x1D +//SC_REUSE_REFRESH, 0x1D +//SC_REUSE_STORMBLAST, 0x1D +SC_EPICLESIS, 0x1D +SC_ORATIO, 0x14 +SC_LAUDAAGNUS, 0x14 +SC_LAUDARAMUS, 0x14 +SC_CLOAKINGEXCEED, 0x1E +SC_HALLUCINATIONWALK, 0x1C +SC_HALLUCINATIONWALK_POSTDELAY, 0x1F +SC_RENOVATIO, 0x14 +SC_WEAPONBLOCKING, 0x1C +//SC_WEAPONBLOCKING_POSTDELAY, 0x1F +SC_ROLLINGCUTTER, 0x1E +SC_EXPIATIO, 0x14 +SC_POISONINGWEAPON, 0x1C +SC_TOXIN, 0x14 +SC_PARALYSE, 0x14 +SC_VENOMBLEED, 0x14 +SC_MAGICMUSHROOM, 0x14 +SC_DEATHHURT, 0x14 +SC_PYREXIA, 0x14 +SC_OBLIVIONCURSE, 0x14 +SC_LEECHESEND, 0x14 +SC_DUPLELIGHT, 0x14 +SC_FEARBREEZE, 0x1C +SC_ELECTRICSHOCKER, 0x1E +SC_MARSHOFABYSS, 0x14 +SC_RECOGNIZEDSPELL, 0x14 +//SC_WUGRIDER, 0x1D +SC_WUGDASH, 0x1E +SC_WUGBITE, 0x1E +SC_CAMOUFLAGE, 0x1E +SC_ACCELERATION, 0x1C +SC_HOVERING, 0x1C +SC_SUMMON1, 0x18 +SC_SUMMON2, 0x18 +SC_SUMMON3, 0x18 +SC_SUMMON4, 0x18 +SC_SUMMON5, 0x18 +//SC_MVPCARD_TAOGUNKA, 0x1C +//SC_MVPCARD_MISTRESS, 0x1C +//SC_MVPCARD_ORCHERO, 0x1C +//SC_MVPCARD_ORCLORD, 0x1C +SC_OVERHEAT_LIMITPOINT, 0x1C +SC_OVERHEAT, 0x1C +SC_SHAPESHIFT, 0x1C +SC_INFRAREDSCAN, 0x1C +SC_MAGNETICFIELD, 0x1E +SC_NEUTRALBARRIER, 0x1E +SC_NEUTRALBARRIER_MASTER, 0x1E +SC_STEALTHFIELD_MASTER, 0x1E +SC_MANU_ATK, 0x1C +SC_MANU_DEF, 0x1C +SC_SPL_ATK, 0x1C +SC_SPL_DEF, 0x1C +SC__REPRODUCE, 0x1C +SC_MANU_MATK, 0x1C +SC_SPL_MATK, 0x1C +//SC_STR_SCROLL, 0x1D +//SC_INT_SCROLL, 0x1D +SC_FORCEOFVANGUARD, 0x1C +//SC_BUCHEDENOEL, 0x1C +SC__AUTOSHADOWSPELL, 0x10 +SC__SHADOWFORM, 0x1E +SC_RAID, 0x1C +SC_SHIELDSPELL_DEF, 0x10 +SC_SHIELDSPELL_MDEF, 0x10 +SC_SHIELDSPELL_REF, 0x10 +SC__BODYPAINT, 0x14 +SC_EXEEDBREAK, 0x1C +SC_ADORAMUS, 0x10 +SC_PRESTIGE, 0x10 +SC__INVISIBILITY, 0x1E +SC__DEADLYINFECT, 0x14 +SC_BANDING, 0x1C +SC_BANDING_DEFENCE, 0x1C +SC_EARTHDRIVE, 0x14 +SC_INSPIRATION, 0x1C +SC__ENERVATION, 0x10 +SC__GROOMY, 0x10 +SC_RAISINGDRAGON, 0x1E +SC__IGNORANCE, 0x10 +SC__LAZINESS, 0x10 +SC_LIGHTNINGWALK, 0x1C +//SC_ACARAJE, 0x18 +SC__UNLUCKY, 0x10 +SC_CURSEDCIRCLE_ATKER, 0x1C +SC_CURSEDCIRCLE_TARGET, 0x1C +SC__WEAKNESS, 0x10 +SC_CRESCENTELBOW, 0x1C +//SC_NOEQUIPACCESSARY, 0x1E +SC__STRIPACCESSARY, 0x1C +SC__MANHOLE, 0x5E +//SC_POPECOOKIE, 0x1C +SC__BLOODYLUST, 0x20 +SC_SWING, 0x1C +SC_SYMPHONY_LOVE, 0x1C +SC_PROPERTYWALK, 0x12 +SC_SPELLFIST, 0x10 +SC_NETHERWORLD, 0x10 +SC_SIREN, 0x10 +SC_DEEP_SLEEP, 0x22 +SC_SIRCLEOFNATURE, 0x10 +SC_GLOOMYDAY, 0x10 +SC_GLOOMYDAY_SK, 0x10 +SC_SONG_OF_MANA, 0x10 +SC_DANCE_WITH_WUG, 0x10 +SC_RUSH_WINDMILL, 0x1C +SC_ECHOSONG, 0x1C +SC_HARMONIZE, 0x10 +SC_MOONLIT_SERENADE, 0x1C +SC_SATURDAY_NIGHT_FEVER, 0x10 +SC_SITDOWN_FORCE, 0x1C +SC_ANALYZE, 0x1C +SC_LERADS_DEW, 0x1C +SC_MELODYOFSINK, 0x1C +SC_BEYOND_OF_WARCRY, 0x1C +SC_UNLIMITED_HUMMING_VOICE, 0x1C +SC_WARMER, 0x2 +SC_VENOMIMPRESS, 0x4 +SC_FROSTMISTY, 0x20 +//SC_ASSUMPTIO2, 0x10 +//SC_GN_TRAINING_SWORD, 0x1F +//SC_GN_REMODELING_CART, 0x1F +SC_STOMACHACHE, 0x20 +SC_MYSTERIOUS_POWDER, 0x20 +//SC_ELEMENTAL_AGGRESSIVE, 0x2 +//SC_ELEMENTAL_WAIT, 0x2 +//SC_ELEMENTAL_PASSIVE, 0x2 +//SC_ELEMENTAL_DEFENSIVE, 0x2 +SC_WATER_BARRIER, 0x2 +SC_ZEPHYR, 0x2 +SC_POWER_OF_GAIA, 0x2 +SC_FIRE_INSIGNIA, 0x2 +SC_WATER_INSIGNIA, 0x2 +SC_WIND_INSIGNIA, 0x2 +SC_EARTH_INSIGNIA, 0x2 +//SC_MORA_BUFF, 0x2 +//SC_REUSE_LIMIT_G, 0x1D +//SC_REUSE_LIMIT_H, 0x1D +SC_NEEDLE_OF_PARALYZE, 0x1 +SC_PAIN_KILLER, 0x1 +//SC_G_LIFEPOTION, 0x44 +//SC_VITALIZE_POTION, 0x4 +SC_LIGHT_OF_REGENE, 0x1 +//SC_SONIC_CLAW_POSTDELAY, 0x2 +//SC_SILVERVEIN_RUSH_POSTDELAY, 0x2 +//SC_MIDNIGHT_FRENZY_POSTDELAY, 0x2 +//SC_TINDER_BREAKER, 0x2 +//SC_TINDER_BREAKER_POSTDELAY, 0x2 +//SC_CBC, 0x2 +//SC_CBC_POSTDELAY, 0x2 +//SC_EQC, 0x2 +//SC_MAGIC_CANDY, 0x5C +//SC_ALL_RIDING_REUSE_LIMIT, 0x1 +//SC_HANDICAPSTATE_DEEP_SLEEP, 0x50 + +SC_FULL_THROTTLE, 0x12 +SC_REBOUND, 0x12 +SC_TELEKINESIS_INTENSE, 0x12 + +// Unremovable +SC_WEIGHTOVER50, 0x4F +SC_WEIGHTOVER90, 0x4F +SC_XMAS, 0x4D +SC_SUMMER, 0x4D +SC_NOCHAT, 0x4D +SC_FUSION, 0x4D +SC_EARTHSCROLL, 0x4D +SC_STORMKICK_READY, 0x4D +SC_DOWNKICK_READY, 0x4D +SC_COUNTERKICK_READY, 0x4D +SC_TURNKICK_READY, 0x4D +SC_DODGE_READY, 0x4D +SC_JAILED, 0x4D +SC_AUTOTRADE, 0x4D +SC_WHISTLE, 0x4F +SC_ASSNCROS, 0x4F +SC_POEMBRAGI, 0x4F +SC_APPLEIDUN, 0x4F +SC_HUMMING, 0x4F +SC_DONTFORGETME, 0x4F +SC_FORTUNE, 0x4F +SC_SERVICEFORYOU, 0x4F +SC_INCHIT, 0x4D +SC_PUSH_CART, 0x4D \ No newline at end of file diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 3bac278bb..0441d385a 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -1,4 +1,4 @@ -//===== Hercules Documentation =============================== +ļ»æ//===== Hercules Documentation =============================== //= Hercules Script Commands //===== By: ================================================== //= Hercules Dev Team @@ -183,9 +183,8 @@ There are two optional fields for monster size and AI. Size can be 0 (medium), 1 (small), or 2 (big). AI can be 0 (default), 1 (attack/friendly), 2 (sphere), 3 (flora), or 4 (zanzou). -Alternately, a monster spawned using 'boss_monster' instead of 'monster' -is able to be detected on the map with the SC_BOSSMAPINFO status (used by -Convex Mirror, item ID# 12214). +Alternately, a monster spawned using 'boss_monster' instead of 'monster' is able +to be detected on the map with the SC_CASH_BOSS_ALARM status (used by Convex Mirror, item ID# 12214). ** NPC names diff --git a/npc/cities/rachel.txt b/npc/cities/rachel.txt index db3c6816e..88eb359f1 100644 --- a/npc/cities/rachel.txt +++ b/npc/cities/rachel.txt @@ -308,8 +308,8 @@ rachel,206,30,3 script Freya's Priest#play 920,{ set .@play,rand(1,10); if (.@play == 1) warp "Random",0,0; else if (.@play == 2) warp "Random",0,0; - else if (.@play == 3) sc_start SC_SpeedUp1,5000,0; - else if (.@play == 4) sc_start SC_SpeedUp1,5000,0; + else if (.@play == 3) sc_start SC_MOVHASTE_INFINITY,5000,0; + else if (.@play == 4) sc_start SC_MOVHASTE_INFINITY,5000,0; else sc_start SC_SlowDown,5000,0; end; } diff --git a/npc/custom/healer.txt b/npc/custom/healer.txt index 31f247695..a6f028e8a 100644 --- a/npc/custom/healer.txt +++ b/npc/custom/healer.txt @@ -26,7 +26,7 @@ } specialeffect2 313; percentheal 100,100; if (.@Buffs) { - specialeffect2 EF_INCAGILITY; sc_start SC_INCREASEAGI,240000,10; + specialeffect2 EF_INCAGILITY; sc_start SC_INC_AGI,240000,10; specialeffect2 EF_BLESSING; sc_start SC_BLESSING,240000,10; } if (.@Delay) set @HD, gettimetick(2)+.@Delay; diff --git a/npc/events/halloween_2009.txt b/npc/events/halloween_2009.txt index 9dee31807..a5faf713e 100644 --- a/npc/events/halloween_2009.txt +++ b/npc/events/halloween_2009.txt @@ -118,13 +118,13 @@ OnTouch: mes "[Trick or Treater]"; mes "Yay thank you!"; mes "Here, take this for being so nice!"; - sc_start SC_STRFood, 1800000, 5; - sc_start SC_INTFood, 1800000, 5; - sc_start SC_VITFood, 1800000, 5; - sc_start SC_AGIFood, 1800000, 5; - sc_start SC_DEXFood, 1800000, 5; - sc_start SC_LUKFood, 1800000, 5; - sc_start SC_FLEEFOOD, 1800000, 15; + sc_start SC_FOOD_STR, 1800000, 5; + sc_start SC_FOOD_INT, 1800000, 5; + sc_start SC_FOOD_VIT, 1800000, 5; + sc_start SC_FOOD_AGI, 1800000, 5; + sc_start SC_FOOD_DEX, 1800000, 5; + sc_start SC_FOOD_LUK, 1800000, 5; + sc_start SC_FOOD_BASICAVOIDANCE, 1800000, 15; delitem 529,1; // Candy close; }else{ @@ -139,13 +139,13 @@ OnTouch: mes "[Trick or Treater]"; mes "Yay thank you!"; mes "Here, take this for being so nice!"; - sc_start SC_STRFood, 1800000, 5; - sc_start SC_INTFood, 1800000, 5; - sc_start SC_VITFood, 1800000, 5; - sc_start SC_AGIFood, 1800000, 5; - sc_start SC_DEXFood, 1800000, 5; - sc_start SC_LUKFood, 1800000, 5; - sc_start SC_FLEEFOOD, 1800000, 15; + sc_start SC_FOOD_STR, 1800000, 5; + sc_start SC_FOOD_INT, 1800000, 5; + sc_start SC_FOOD_VIT, 1800000, 5; + sc_start SC_FOOD_AGI, 1800000, 5; + sc_start SC_FOOD_DEX, 1800000, 5; + sc_start SC_FOOD_LUK, 1800000, 5; + sc_start SC_FOOD_BASICAVOIDANCE, 1800000, 15; delitem 530,1; // Candy Cane close; }else{ @@ -160,13 +160,13 @@ OnTouch: mes "[Trick or Treater]"; mes "Yay thank you!"; mes "Here, take this for being so nice!"; - sc_start SC_STRFood, 1800000, 5; - sc_start SC_INTFood, 1800000, 5; - sc_start SC_VITFood, 1800000, 5; - sc_start SC_AGIFood, 1800000, 5; - sc_start SC_DEXFood, 1800000, 5; - sc_start SC_LUKFood, 1800000, 5; - sc_start SC_FLEEFOOD, 1800000, 15; + sc_start SC_FOOD_STR, 1800000, 5; + sc_start SC_FOOD_INT, 1800000, 5; + sc_start SC_FOOD_VIT, 1800000, 5; + sc_start SC_FOOD_AGI, 1800000, 5; + sc_start SC_FOOD_DEX, 1800000, 5; + sc_start SC_FOOD_LUK, 1800000, 5; + sc_start SC_FOOD_BASICAVOIDANCE, 1800000, 15; delitem 538,1; // Well-baked Cookie close; }else{ diff --git a/npc/events/nguild/nguild_warper.txt b/npc/events/nguild/nguild_warper.txt index 57f5bc827..ac54c0716 100644 --- a/npc/events/nguild/nguild_warper.txt +++ b/npc/events/nguild/nguild_warper.txt @@ -64,7 +64,7 @@ prontera,146,163,6 script Novice Castles 729,{ sc_end SC_IMPOSITIO; sc_end SC_SUFFRAGIUM; sc_end SC_MAGNIFICAT; - sc_end SC_WEAPONPERFECTION; + sc_end SC_WEAPONPERFECT; sc_end SC_GOSPEL; sc_end SC_BASILICA; sc_end SC_MAGICPOWER; @@ -72,8 +72,8 @@ prontera,146,163,6 script Novice Castles 729,{ sc_end SC_MARIONETTE2; sc_end SC_DEVOTION; sc_end SC_SACRIFICE; - sc_end SC_MAXOVERTHRUST; - sc_end SC_SPIRIT; + sc_end SC_OVERTHRUSTMAX; + sc_end SC_SOULLINK; warp "n_castle",102,93+rand(14); } } diff --git a/npc/instances/NydhoggsNest.txt b/npc/instances/NydhoggsNest.txt index 2d48d0341..f2fe3fc68 100644 --- a/npc/instances/NydhoggsNest.txt +++ b/npc/instances/NydhoggsNest.txt @@ -2182,7 +2182,7 @@ OnDisable: OnTouch: percentheal -50,0; percentheal -30,0; - sc_start SC_BLEEDING,60000,0; + sc_start SC_BLOODING,60000,0; end; OnTimer10000: diff --git a/npc/mobs/citycleaners.txt b/npc/mobs/citycleaners.txt index 0e810ac5b..876017fd4 100644 --- a/npc/mobs/citycleaners.txt +++ b/npc/mobs/citycleaners.txt @@ -46,3 +46,5 @@ einbech,0,0,0,0 monster Tarou 1175,5,1800000,1500000,0 // payon_in02 - Inside Payon //================================================== payon_in02,23,68,5,5 monster Thief Bug Egg 1048,7,1200000,600000,0 + +job3_war01,19,33,5,5 monster Thief Bug Egg 1213,1,12,60,0 diff --git a/npc/quests/skills/assassin_skills.txt b/npc/quests/skills/assassin_skills.txt index 109d699d3..4fddf6b12 100644 --- a/npc/quests/skills/assassin_skills.txt +++ b/npc/quests/skills/assassin_skills.txt @@ -758,7 +758,7 @@ OnTouch: mes "the coffin bit your"; mes "hand really hard!^000000"; sc_start SC_Poison,30000,0; - sc_start SC_Bleeding,10000,0; + sc_start SC_BLOODING,10000,0; Emotion e_omg,1; close; case 2: @@ -830,7 +830,7 @@ OnTouch: mes "the coffin bit your"; mes "hand really hard!^000000"; sc_start SC_Poison,30000,0; - sc_start SC_Bleeding,10000,0; + sc_start SC_BLOODING,10000,0; Emotion e_omg,1; close; } diff --git a/npc/re/cities/dewata.txt b/npc/re/cities/dewata.txt index 6bbbfeb4e..3c5953adf 100644 --- a/npc/re/cities/dewata.txt +++ b/npc/re/cities/dewata.txt @@ -457,32 +457,32 @@ dewata,89,191,6 script Small Shrine#dew1 844,{ callsub L_Wish; set Zeny, Zeny - .@input; if (.@stat & 1 && .@bonus){ - sc_start SC_STRFOOD,1200000,3; + sc_start SC_FOOD_STR,1200000,3; percentheal 5,0; //consumeitem 12043; //Str_Dish03 } else if (.@stat & 2 && .@bonus){ - sc_start SC_AGIFOOD,1200000,3; + sc_start SC_FOOD_AGI,1200000,3; percentheal 5,0; //consumeitem 12058; //Agi_Dish03 } else if (.@stat & 4 && .@bonus){ - sc_start SC_DEXFOOD,1200000,3; + sc_start SC_FOOD_DEX,1200000,3; percentheal 5,0; //consumeitem 12063; //Dex_Dish03 } else if (.@stat & 8 && .@bonus){ - sc_start SC_VITFOOD,1200000,3; + sc_start SC_FOOD_VIT,1200000,3; percentheal 5,0; //consumeitem 12053; //Vit_Dish03 } else if (.@stat & 16 && .@bonus){ - sc_start SC_INTFOOD,1200000,3; + sc_start SC_FOOD_INT,1200000,3; percentheal 5,0; //consumeitem 12048; //Int_Dish03 } else if (.@stat & 32 && .@bonus){ - sc_start SC_LUKFOOD,1200000,3; + sc_start SC_FOOD_LUK,1200000,3; percentheal 5,0; //consumeitem 12068; //Luk_Dish03 } diff --git a/npc/re/jobs/3-1/rune_knight.txt b/npc/re/jobs/3-1/rune_knight.txt index 6dbfdaa3a..1255c355e 100644 --- a/npc/re/jobs/3-1/rune_knight.txt +++ b/npc/re/jobs/3-1/rune_knight.txt @@ -1826,7 +1826,7 @@ job3_rune02,34,46,5 script Captain Tigris#jrt1 470,2,2,{ break; case 5: mapannounce "job3_rune02","Captain Tigris : For a Rune Knight, this kind of ordeal is nothing!",bc_map,"0xFFFF00"; //FW_NORMAL 12 0 0 - sc_start SC_BLEEDING,10000,0; + sc_start SC_BLOODING,10000,0; break; } set $@job_rune_test2,1; @@ -2161,4 +2161,4 @@ sec_in02,34,167,3 script R.Knight Job Manager 470,1,1,{ close; } job3_rune01,1,1,3 duplicate(R.Knight Job Manager) #renshucheck 844 -*/ \ No newline at end of file +*/ diff --git a/npc/re/quests/quests_brasilis.txt b/npc/re/quests/quests_brasilis.txt index 2e1cbe75a..e9256047f 100644 --- a/npc/re/quests/quests_brasilis.txt +++ b/npc/re/quests/quests_brasilis.txt @@ -227,9 +227,9 @@ brasilis,192,133,6 script Lucia#brasilis 478,{ if (.@nQState2 > -1) erasequest 9029; setquest 9029; percentheal 100,100; - sc_start SC_LUKFOOD, 1200000, 5; percentheal 5,2; - sc_start SC_VITFOOD, 1200000, 5; percentheal 10,0; - sc_start SC_DEXFOOD, 1200000, 5; percentheal 5,5; + sc_start SC_FOOD_LUK, 1200000, 5; percentheal 5,2; + sc_start SC_FOOD_VIT, 1200000, 5; percentheal 10,0; + sc_start SC_FOOD_DEX, 1200000, 5; percentheal 5,5; getitem 11502,3; //Light_Blue_Pot close; } @@ -971,7 +971,7 @@ OnTouch_: set brazil_gua,8; changequest 2197,2198; close2; - sc_start SC_SpeedUp1,5000,0; + sc_start SC_MOVHASTE_INFINITY,5000,0; end; } else { @@ -3071,13 +3071,13 @@ bra_dun02,157,74,5 script Iara#nk 478,2,2,{ delitem 11517,1; //Puri_Potion percentheal 100,100; sc_start SC_INCFLEE,3600000,20; - sc_start SC_INCCRI,3600000,10; - sc_start SC_STRFOOD,1200000,3; - sc_start SC_DEXFOOD,1200000,3; - sc_start SC_AGIFOOD,1200000,3; - sc_start SC_VITFOOD,1200000,3; - sc_start SC_INTFOOD,1200000,3; - sc_start SC_LUKFOOD,1200000,3; + sc_start SC_CRITICALPERCENT,3600000,10; + sc_start SC_FOOD_STR,1200000,3; + sc_start SC_FOOD_DEX,1200000,3; + sc_start SC_FOOD_AGI,1200000,3; + sc_start SC_FOOD_VIT,1200000,3; + sc_start SC_FOOD_INT,1200000,3; + sc_start SC_FOOD_LUK,1200000,3; next; mes "[Iara]"; mes "Ahhh~..."; diff --git a/src/char/char.c b/src/char/char.c index f889c1a25..7dfb6861c 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -2027,6 +2027,8 @@ static void char_auth_ok(int fd, struct char_session_data *sd) mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); if (character->waiting_disconnect == INVALID_TIMER) character->waiting_disconnect = iTimer->add_timer(iTimer->gettick()+20000, chardb_waiting_disconnect, character->account_id, 0); + if (character) + character->pincode_enable = -1; WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 8; diff --git a/src/common/mmo.h b/src/common/mmo.h index c2fdfe43a..eaffdf7df 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -83,7 +83,7 @@ #define MAX_ZENY 1000000000 #define MAX_FAME 1000000000 #define MAX_CART 100 -#define MAX_SKILL 1477 +#define MAX_SKILL 1478 #define MAX_SKILL_ID 10015 // [Ind/Hercules] max used skill ID #define GLOBAL_REG_NUM 256 // Max permanent character variables per char #define ACCOUNT_REG_NUM 64 // Max permanent local account variables per account diff --git a/src/config/const.h b/src/config/const.h index 756c681c1..7acdea688 100644 --- a/src/config/const.h +++ b/src/config/const.h @@ -60,8 +60,8 @@ /* ATCMD_FUNC(mobinfo) HIT and FLEE calculations */ #ifdef RENEWAL - #define MOB_FLEE(mob) ( mob->lv + mob->status.agi + mob->status.luk/5 + 100 ) - #define MOB_HIT(mob) ( mob->lv + mob->status.dex + mob->status.luk/3 + 175 ) + #define MOB_FLEE(mob) ( mob->lv + mob->status.agi + 100 ) + #define MOB_HIT(mob) ( mob->lv + mob->status.dex + 150 ) #else #define MOB_FLEE(mob) ( mob->lv + mob->status.agi ) #define MOB_HIT(mob) ( mob->lv + mob->status.dex ) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index f96c7920a..d9810e77c 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -6148,7 +6148,7 @@ ACMD(npctalk) unsigned long color=0; if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEPSLEEP] || sd->sc.data[SC__BLOODYLUST] || + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return false; @@ -6199,7 +6199,7 @@ ACMD(pettalk) } if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEPSLEEP] || sd->sc.data[SC__BLOODYLUST] || + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return false; @@ -6965,7 +6965,7 @@ ACMD(homtalk) } if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEPSLEEP] || sd->sc.data[SC__BLOODYLUST] || + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return false; @@ -7348,7 +7348,7 @@ ACMD(me) memset(atcmd_output, '\0', sizeof(atcmd_output)); if (sd->sc.count && //no "chatting" while muted. - (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEPSLEEP] || sd->sc.data[SC__BLOODYLUST] || + (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEP_SLEEP] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) return false; diff --git a/src/map/battle.c b/src/map/battle.c index a2cc7692c..a4908982c 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -363,14 +363,14 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag if( tsc->data[SC_SPIDERWEB]->val2 == 0 ) status_change_end(target, SC_SPIDERWEB, INVALID_TIMER); } - if( tsc->data[SC_THORNSTRAP]) - status_change_end(target, SC_THORNSTRAP, INVALID_TIMER); + if( tsc->data[SC_THORNS_TRAP]) + status_change_end(target, SC_THORNS_TRAP, INVALID_TIMER); if( tsc->data[SC_FIRE_CLOAK_OPTION]) damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100; if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB) status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER); if( tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2; - if( tsc->data[SC_ASH]) damage += damage/2; //150% + if( tsc->data[SC_VOLCANIC_ASH]) damage += damage/2; //150% break; case ELE_HOLY: if( tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2; @@ -394,1833 +394,1365 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag struct map_session_data *sd = BL_CAST(BL_PC, src); int s; - ARR_FIND(1, 6, s, sd->talisman[s] > 0); + ARR_FIND(1, 6, s, sd->charm[s] > 0); if( s < 5 && atk_elem == s ) - ratio += sd->talisman[s] * 2; // +2% custom value + ratio += sd->charm[s] * 2; // +2% custom value } if( target && target->type == BL_PC ) { struct map_session_data *tsd = BL_CAST(BL_PC, target); int t; - ARR_FIND(1, 6, t, tsd->talisman[t] > 0); + ARR_FIND(1, 6, t, tsd->charm[t] > 0); if( t < 5 && atk_elem == t ) - damage -= damage * ( tsd->talisman[t] * 3 ) / 100;// -3% custom value + damage -= damage * ( tsd->charm[t] * 3 ) / 100;// -3% custom value } return damage*ratio/100; } -/*========================================== - * Calculates card bonuses damage adjustments. - *------------------------------------------*/ -int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag){ - struct map_session_data *sd, *tsd; - short cardfix = 1000, t_class, s_class, s_race2, t_race2; - struct status_data *sstatus, *tstatus; - int i; +int battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2){ // [malufett] + int damage, eatk = 0; + struct status_change *sc; + struct map_session_data *sd; - if( !damage ) + if( !src || !bl ) return 0; + sc = status_get_sc(src); sd = BL_CAST(BL_PC, src); - tsd = BL_CAST(BL_PC, target); - t_class = status_get_class(target); - s_class = status_get_class(src); - sstatus = status_get_status_data(src); - tstatus = status_get_status_data(target); - s_race2 = status_get_race2(src); - switch(attack_type){ - case BF_MAGIC: - if ( sd && !(nk&NK_NO_CARDFIX_ATK) ) { - cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) - cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100; - cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - cardfix=cardfix*(100+sd->magic_atk_ele[s_ele])/100; - for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate;i++) { - if(sd->add_mdmg[i].class_ == t_class) { - cardfix=cardfix*(100+sd->add_mdmg[i].rate)/100; - break; - } - } - if (cardfix != 1000) - damage = damage * cardfix / 1000; - } + damage = status_get_weapon_atk(src, watk, flag); + + if( sd ){ + if( type == EQI_HAND_R ) + damage = battle->calc_sizefix(sd, damage, EQI_HAND_R, size, flag&8); + else + damage = battle->calc_sizefix(sd, damage, EQI_HAND_L, size, flag&8); - if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) - { // Target cards. - if (!(nk&NK_NO_ELEFIX)) - { - int ele_fix = tsd->subele[s_ele]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele) continue; - if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && - tsd->subele2[i].flag&flag&BF_RANGEMASK && - tsd->subele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix)/100; - } - cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; - cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; - cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; - cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + if( sd->bonus.eatk > 0 ) + eatk = sd->bonus.eatk; + if( flag&2 && sd->bonus.arrow_atk ) + eatk += sd->bonus.arrow_atk; + } + + if( sc && sc->count ){ + if( sc->data[SC_ZENKAI] && watk->ele == sc->data[SC_ZENKAI]->val2 ) + eatk += 200; + #ifdef RENEWAL_EDP + if( sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE ){ + eatk = eatk * sc->data[SC_EDP]->val3 / 100; // 400% + damage = damage * sc->data[SC_EDP]->val4 / 100; // 500% + damage--; // temporary until we find the correct formula [malufett] + } + #endif + } - for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) { - if(tsd->add_mdef[i].class_ == s_class) { - cardfix=cardfix*(100-tsd->add_mdef[i].rate)/100; - break; - } - } - //It was discovered that ranged defense also counts vs magic! [Skotlex] - if ( flag&BF_SHORT ) - cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; - else - cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; + /* [malufett] + some unknown factors that needs to be discovered. PS: it's something related with ranged attacks + if( eatk ){ + eatk += unknown value; + eatk = eatk * (unknown value) / 100; + } + */ - cardfix = cardfix * ( 100 - tsd->bonus.magic_def_rate ) / 100; + if( sc && sc->data[SC_WATK_ELEMENT] ) + damage = damage + eatk; + else + damage = battle->calc_elefix(src, bl, skill_id, skill_lv, damage + eatk, nk, n_ele, s_ele, s_ele_, false, flag); + + /** + * In RE Shield Bommerang takes weapon element only for damage calculation, + * - resist calculation is always against neutral + **/ + if ( skill_id == CR_SHIELDBOOMERANG ) + s_ele = s_ele_ = ELE_NEUTRAL; + + if( type == EQI_HAND_R ) + damage = battle->calc_cardfix(BF_WEAPON, src, bl, nk, s_ele, s_ele_, damage, 2, flag2); + else + damage = battle->calc_cardfix(BF_WEAPON, src, bl, nk, s_ele, s_ele_, damage, 3, flag2); + + return damage; +} +/*========================================== + * Calculates the standard damage of a normal attack assuming it hits, + * it calculates nothing extra fancy, is needed for magnum break's WATK_ELEMENT bonus. [Skotlex] + *------------------------------------------ + * Pass damage2 as NULL to not calc it. + * Flag values: + * &1: Critical hit + * &2: Arrow attack + * &4: Skill is Magic Crasher + * &8: Skip target size adjustment (Extremity Fist?) + *&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX) + */ - if( tsd->sc.data[SC_MDEF_RATE] ) - cardfix = cardfix * ( 100 - tsd->sc.data[SC_MDEF_RATE]->val1 ) / 100; +#ifdef RENEWAL +int battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2) +{ + int damage, batk; + struct status_change *sc = status_get_sc(src); + struct status_data *status = status_get_status_data(src); + + if( sc && sc->data[SC_TK_SEVENWIND] && !sc->data[SC_WATK_ELEMENT] ) + batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->batk, nk, n_ele, s_ele, s_ele_, false, flag); + else + batk = status->batk; - if (cardfix != 1000) - damage = damage * cardfix / 1000; - } - break; - case BF_WEAPON: - t_race2 = status_get_race2(target); - if( sd && !(nk&NK_NO_CARDFIX_ATK) && (left&2) ) - { - short cardfix_ = 1000; - if(sd->state.arrow_atk) - { - cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) - { - int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele]; - for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { - if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; - if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK && - sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK && - sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += sd->right_weapon.addele2[i].rate; - } - cardfix=cardfix*(100+ele_fix)/100; - } - cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN])/100; - } - else - { // Melee attack - if( !battle_config.left_cardfix_to_right ) - { - cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) { - int ele_fix = sd->right_weapon.addele[tstatus->def_ele]; - for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { - if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; - if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK && - sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK && - sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += sd->right_weapon.addele2[i].rate; - } - cardfix=cardfix*(100+ele_fix)/100; - } - cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN])/100; + if( type == EQI_HAND_L ) + damage = batk + 3 * battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &status->lhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2) / 4; + else + damage = (batk << 1) + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &status->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2); +#else +static int battle_calc_base_damage(struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) +{ + unsigned int atkmin=0, atkmax=0; + short type = 0; + int damage = 0; - if( left&1 ) - { - cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; - if (!(nk&NK_NO_ELEFIX)) { - int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele]; - for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) { - if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue; - if(!(sd->left_weapon.addele2[i].flag&flag&BF_WEAPONMASK && - sd->left_weapon.addele2[i].flag&flag&BF_RANGEMASK && - sd->left_weapon.addele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix_lh += sd->left_weapon.addele2[i].rate; - } - cardfix=cardfix*(100+ele_fix_lh)/100; - } - cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100; - cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100; - cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix_=cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; - } - } - else - { - int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]; - for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { - if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; - if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK && - sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK && - sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += sd->right_weapon.addele2[i].rate; - } - for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) { - if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue; - if(!(sd->left_weapon.addele2[i].flag&flag&BF_WEAPONMASK && - sd->left_weapon.addele2[i].flag&flag&BF_RANGEMASK && - sd->left_weapon.addele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += sd->left_weapon.addele2[i].rate; - } + if (!sd) { //Mobs/Pets + if(flag&4) { + atkmin = status->matk_min; + atkmax = status->matk_max; + } else { + atkmin = wa->atk; + atkmax = wa->atk2; + } + if (atkmin > atkmax) + atkmin = atkmax; + } else { //PCs + atkmax = wa->atk; + type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R; - cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100; - cardfix=cardfix*(100+ele_fix)/100; - cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100; - cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; - } - } - for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ ) - { - if( sd->right_weapon.add_dmg[i].class_ == t_class ) - { - cardfix=cardfix*(100+sd->right_weapon.add_dmg[i].rate)/100; - break; - } - } + if (!(flag&1) || (flag&2)) { //Normal attacks + atkmin = status->dex; - if( left&1 ) - { - for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ ) - { - if( sd->left_weapon.add_dmg[i].class_ == t_class ) - { - cardfix_=cardfix_*(100+sd->left_weapon.add_dmg[i].rate)/100; - break; - } - } - } + if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]]) + atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100; - if( flag&BF_LONG ) - cardfix = cardfix * ( 100 + sd->bonus.long_attack_atk_rate ) / 100; -#ifdef RENEWAL_EDP - if( sd->sc.data[SC_EDP] ){ - cardfix = cardfix * (100 + sd->sc.data[SC_EDP]->val1 * 60 ) / 100; - cardfix_ = cardfix_ * (100 + sd->sc.data[SC_EDP]->val1 * 60 ) / 100; - } -#endif - if( (left&1) && cardfix_ != 1000 ) - damage = damage * cardfix_ / 1000; - else if( cardfix != 1000 ) - damage = damage * cardfix / 1000; + if (atkmin > atkmax) + atkmin = atkmax; - }else if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){ - if( !(nk&NK_NO_ELEFIX) ) - { - int ele_fix = tsd->subele[s_ele]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele) continue; - if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && - tsd->subele2[i].flag&flag&BF_RANGEMASK && - tsd->subele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix)/100; - if( left&1 && s_ele_ != s_ele ) - { - int ele_fix_lh = tsd->subele[s_ele_]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele_) continue; - if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && - tsd->subele2[i].flag&flag&BF_RANGEMASK && - tsd->subele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix_lh += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix_lh)/100; - } + if(flag&2 && !(flag&16)) { //Bows + atkmin = atkmin*atkmax/100; + if (atkmin > atkmax) + atkmax = atkmin; } - cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; - cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; - cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; - cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + } + } - for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ) { - if( tsd->add_def[i].class_ == s_class ) { - cardfix=cardfix*(100-tsd->add_def[i].rate)/100; - break; - } - } + if (sc && sc->data[SC_MAXIMIZEPOWER]) + atkmin = atkmax; - if( flag&BF_SHORT ) - cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; - else // BF_LONG (there's no other choice) - cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; + //Weapon Damage calculation + if (!(flag&1)) + damage = (atkmax>atkmin? rnd()%(atkmax-atkmin):0)+atkmin; + else + damage = atkmax; + + if (sd) { + //rodatazone says the range is 0~arrow_atk-1 for non crit + if (flag&2 && sd->bonus.arrow_atk) + damage += ( (flag&1) ? sd->bonus.arrow_atk : rnd()%sd->bonus.arrow_atk ); - if( tsd->sc.data[SC_DEF_RATE] ) - cardfix = cardfix * ( 100 - tsd->sc.data[SC_DEF_RATE]->val1 ) / 100; + //SizeFix only for players + if (!(sd->special_state.no_sizefix || (flag&8))) + DAMAGE_RATE(type==EQI_HAND_L? + sd->left_weapon.atkmods[t_size]: + sd->right_weapon.atkmods[t_size]) + } - if( cardfix != 1000 ) - damage = damage * cardfix / 1000; + //Finally, add baseatk + if(flag&4) + damage += status->matk_min; + else + damage += status->batk; + + //rodatazone says that Overrefine bonuses are part of baseatk + //Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands. + if(sd) { + if (type == EQI_HAND_L) { + if(sd->left_weapon.overrefine) + damage += rnd()%sd->left_weapon.overrefine+1; + if (sd->weapon_atk_rate[sd->weapontype2]) + DAMAGE_ADDRATE(sd->weapon_atk_rate[sd->weapontype2]) + } else { //Right hand + if(sd->right_weapon.overrefine) + damage += rnd()%sd->right_weapon.overrefine+1; + if (sd->weapon_atk_rate[sd->weapontype1]) + DAMAGE_ADDRATE(sd->weapon_atk_rate[sd->weapontype1]) } - break; - case BF_MISC: - if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){ - // misc damage reduction from equipment - if (!(nk&NK_NO_ELEFIX)) - { - int ele_fix = tsd->subele[s_ele]; - for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) - { - if(tsd->subele2[i].ele != s_ele) continue; - if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && - tsd->subele2[i].flag&flag&BF_RANGEMASK && - tsd->subele2[i].flag&flag&BF_SKILLMASK)) - continue; - ele_fix += tsd->subele2[i].rate; - } - cardfix=cardfix*(100-ele_fix)/100; - } - cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; - cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; - cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; - cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; + } +#endif + return damage; +} - cardfix = cardfix * ( 100 - tsd->bonus.misc_def_rate ) / 100; - if( flag&BF_SHORT ) - cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; - else // BF_LONG (there's no other choice) - cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; +int battle_calc_sizefix(struct map_session_data *sd, int damage, int type, int size, bool ignore){ + //SizeFix only for players + if (!(sd->special_state.no_sizefix || (ignore))) + damage = damage * ( type == EQI_HAND_L ? sd->left_weapon.atkmods[size] : sd->right_weapon.atkmods[size] ) / 100; + return damage; +} - if (cardfix != 10000) - damage = damage * cardfix / 1000; +/*========================================== + * Passive skill damages increases + *------------------------------------------*/ +int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type) +{ + int damage,skill; + struct status_data *status = status_get_status_data(target); + int weapon; + damage = dmg; + + nullpo_ret(sd); + + if((skill = pc->checkskill(sd,AL_DEMONBANE)) > 0 && + target->type == BL_MOB && //This bonus doesnt work against players. + (battle->check_undead(status->race,status->def_ele) || status->race==RC_DEMON) ) + damage += (int)(skill*(3+sd->status.base_level/20.0)); + //damage += (skill * 3); + if( (skill = pc->checkskill(sd, RA_RANGERMAIN)) > 0 && (status->race == RC_BRUTE || status->race == RC_PLANT || status->race == RC_FISH) ) + damage += (skill * 5); + if( (skill = pc->checkskill(sd,NC_RESEARCHFE)) > 0 && (status->def_ele == ELE_FIRE || status->def_ele == ELE_EARTH) ) + damage += (skill * 10); + if( pc_ismadogear(sd) ) + damage += 20 + 20 * pc->checkskill(sd, NC_MADOLICENCE); +#ifdef RENEWAL + if( (skill = pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0 ) + damage += (skill * 2); +#endif + if((skill = pc->checkskill(sd,HT_BEASTBANE)) > 0 && (status->race==RC_BRUTE || status->race==RC_INSECT) ) { + damage += (skill * 4); + if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_HUNTER) + damage += sd->status.str; + } + + if(type == 0) + weapon = sd->weapontype1; + else + weapon = sd->weapontype2; + switch(weapon) + { + case W_1HSWORD: + #ifdef RENEWAL + if((skill = pc->checkskill(sd,AM_AXEMASTERY)) > 0) + damage += (skill * 3); + #endif + case W_DAGGER: + if((skill = pc->checkskill(sd,SM_SWORD)) > 0) + damage += (skill * 4); + if((skill = pc->checkskill(sd,GN_TRAINING_SWORD)) > 0) + damage += skill * 10; + break; + case W_2HSWORD: + #ifdef RENEWAL + if((skill = pc->checkskill(sd,AM_AXEMASTERY)) > 0) + damage += (skill * 3); + #endif + if((skill = pc->checkskill(sd,SM_TWOHAND)) > 0) + damage += (skill * 4); + break; + case W_1HSPEAR: + case W_2HSPEAR: + if((skill = pc->checkskill(sd,KN_SPEARMASTERY)) > 0) { + + if(!pc_isriding(sd)) + damage += (skill * 4); + else if(pc_isridingdragon(sd)) + damage += (skill * 10); + else + damage += (skill * 5); } break; + case W_1HAXE: + case W_2HAXE: + if((skill = pc->checkskill(sd,AM_AXEMASTERY)) > 0) + damage += (skill * 3); + if((skill = pc->checkskill(sd,NC_TRAININGAXE)) > 0) + damage += (skill * 5); + break; + case W_MACE: + case W_2HMACE: + if((skill = pc->checkskill(sd,PR_MACEMASTERY)) > 0) + damage += (skill * 3); + if((skill = pc->checkskill(sd,NC_TRAININGAXE)) > 0) + damage += (skill * 5); + break; + case W_FIST: + if((skill = pc->checkskill(sd,TK_RUN)) > 0) + damage += (skill * 10); + // No break, fallthrough to Knuckles + case W_KNUCKLE: + if((skill = pc->checkskill(sd,MO_IRONHAND)) > 0) + damage += (skill * 3); + break; + case W_MUSICAL: + if((skill = pc->checkskill(sd,BA_MUSICALLESSON)) > 0) + damage += (skill * 3); + break; + case W_WHIP: + if((skill = pc->checkskill(sd,DC_DANCINGLESSON)) > 0) + damage += (skill * 3); + break; + case W_BOOK: + if((skill = pc->checkskill(sd,SA_ADVANCEDBOOK)) > 0) + damage += (skill * 3); + break; + case W_KATAR: + if((skill = pc->checkskill(sd,AS_KATAR)) > 0) + damage += (skill * 3); + break; } return damage; } /*========================================== - * Check dammage trough status. - * ATK may be MISS, BLOCKED FAIL, reduc, increase, end status... - * After this we apply bg/gvg reduction + * Calculates ATK masteries. *------------------------------------------*/ -int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int damage,uint16 skill_id,uint16 skill_lv) -{ - struct map_session_data *sd = NULL; +int battle_calc_masteryfix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int div, bool left, bool weapon){ + int skill, i; + struct map_session_data *sd; struct status_change *sc; - struct status_change_entry *sce; - int div_ = d->div_, flag = d->flag; - - nullpo_ret(bl); - if( !damage ) - return 0; - if( battle_config.ksprotection && mob_ksprotected(src, bl) ) - return 0; + nullpo_ret(src); + nullpo_ret(target); - if (bl->type == BL_PC) { - sd=(struct map_session_data *)bl; - //Special no damage states - if(flag&BF_WEAPON && sd->special_state.no_weapon_damage) - damage -= damage * sd->special_state.no_weapon_damage / 100; + sd = BL_CAST(BL_PC, src); + sc = status_get_sc(src); - if(flag&BF_MAGIC && sd->special_state.no_magic_damage) - damage -= damage * sd->special_state.no_magic_damage / 100; + if ( !sd ) + return damage; - if(flag&BF_MISC && sd->special_state.no_misc_damage) - damage -= damage * sd->special_state.no_misc_damage / 100; + switch( skill_id ){ // specific skill masteries + case MO_INVESTIGATE: + case MO_EXTREMITYFIST: + case CR_GRANDCROSS: + case NJ_ISSEN: + case CR_ACIDDEMONSTRATION: + return damage; + case NJ_SYURIKEN: + if( (skill = pc->checkskill(sd,NJ_TOBIDOUGU)) > 0 && weapon ) + damage += 3 * skill; + break; + case NJ_KUNAI: + if( weapon ) + damage += 60; + break; + case RA_WUGDASH: + case RA_WUGSTRIKE: + case RA_WUGBITE: + damage += 30*pc->checkskill(sd, RA_TOOTHOFWUG); + break; + } - if(!damage) return 0; + if ( sc && sc->data[SC_MIRACLE] ) i = 2; //Star anger + else + ARR_FIND(0, MAX_PC_FEELHATE, i, status_get_class(target) == sd->hate_mob[i]); + if ( i < MAX_PC_FEELHATE && (skill=pc->checkskill(sd,sg_info[i].anger_id)) && weapon ){ + int ratio = sd->status.base_level + status_get_dex(src) + status_get_luk(src); + if ( i == 2 ) ratio += status_get_str(src); //Star Anger + if (skill < 4 ) + ratio /= 12 - 3 * skill; + damage += damage * ratio; + } + + if( sc ){ + if(sc->data[SC_GN_CARTBOOST]) + damage += 10 * sc->data[SC_GN_CARTBOOST]->val1; + if(sc->data[SC_CAMOUFLAGE]) + damage += 30 * ( 10 - sc->data[SC_CAMOUFLAGE]->val4 ); } - sc = status_get_sc(bl); + // general skill masteries +#ifdef RENEWAL + if( skill_id == MO_FINGEROFFENSIVE )//The finger offensive spheres on moment of attack do count. [Skotlex] + damage += div * sd->spiritball_old * 3; + else + damage += div * sd->spiritball * 3; + if( skill_id != CR_SHIELDBOOMERANG ) // Only Shield boomerang doesn't takes the Star Crumbs bonus. + damage += div * (left ? sd->left_weapon.star : sd->right_weapon.star); +#else + if( skill_id != ASC_BREAKER && weapon ) // Adv Katar Mastery is does not applies to ASC_BREAKER, but other masteries DO apply >_> + if( sd->status.weapon == W_KATAR && (skill=pc->checkskill(sd,ASC_KATAR)) > 0 ) + damage += damage * (10 + 2 * skill) / 100; +#endif - if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) - return 1; - if (skill_id == PA_PRESSURE) - return damage; //This skill bypass everything else. - - if( sc && sc->count ) - { - //First, sc_*'s that reduce damage to 0. - if( sc->data[SC_BASILICA] && !(status_get_mode(src)&MD_BOSS) ) - { - d->dmg_lv = ATK_BLOCK; - return 0; - } - if( sc->data[SC_WHITEIMPRISON] && skill_id != HW_GRAVITATION ) { // Gravitation and Pressure do damage without removing the effect - if( skill_id == MG_NAPALMBEAT || - skill_id == MG_SOULSTRIKE || - skill_id == WL_SOULEXPANSION || - (skill_id && skill->get_ele(skill_id, skill_lv) == ELE_GHOST) || - (!skill_id && (status_get_status_data(src))->rhw.ele == ELE_GHOST) - ){ - if( skill_id == WL_SOULEXPANSION ) - damage <<= 1; // If used against a player in White Imprison, the skill deals double damage. - status_change_end(bl,SC_WHITEIMPRISON,INVALID_TIMER); // Those skills do damage and removes effect - }else{ - d->dmg_lv = ATK_BLOCK; - return 0; - } - } - - if(sc->data[SC_ZEPHYR] && - flag&(BF_LONG|BF_SHORT)){ - d->dmg_lv = ATK_BLOCK; - return 0; - } - - if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) - { - struct skill_unit_group* group = skill->id2group(sc->data[SC_SAFETYWALL]->val3); - uint16 skill_id = sc->data[SC_SAFETYWALL]->val2; - if (group) { - if(skill_id == MH_STEINWAND){ - if (--group->val2<=0) - skill->del_unitgroup(group,ALC_MARK); - d->dmg_lv = ATK_BLOCK; - return 0; - } - /** - * in RE, SW possesses a lifetime equal to 3 times the caster's health - **/ - #ifdef RENEWAL - d->dmg_lv = ATK_BLOCK; - if ( ( group->val2 - damage) > 0 ) { - group->val2 -= damage; - } else - skill->del_unitgroup(group,ALC_MARK); - return 0; - #else - if (--group->val2<=0) - skill->del_unitgroup(group,ALC_MARK); - d->dmg_lv = ATK_BLOCK; - return 0; - #endif - } - status_change_end(bl, SC_SAFETYWALL, INVALID_TIMER); - } - - if( ( sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG ) || sc->data[SC__MANHOLE] ) { - d->dmg_lv = ATK_BLOCK; - return 0; - } - if( sc->data[SC_WEAPONBLOCKING] && flag&(BF_SHORT|BF_WEAPON) && rnd()%100 < sc->data[SC_WEAPONBLOCKING]->val2 ) - { - clif->skill_nodamage(bl,src,GC_WEAPONBLOCKING,1,1); - d->dmg_lv = ATK_BLOCK; - sc_start2(bl,SC_COMBO,100,GC_WEAPONBLOCKING,src->id,2000); - return 0; - } - if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2 ) - { - int delay; - clif->skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1); - // different delay depending on skill level [celest] - if (sce->val1 <= 5) - delay = 300; - else if (sce->val1 > 5 && sce->val1 <= 9) - delay = 200; - else - delay = 100; - unit_set_walkdelay(bl, iTimer->gettick(), delay, 1); - - if(sc->data[SC_SHRINK] && rnd()%100<5*sce->val1) - skill->blown(bl,src,skill->get_blewcount(CR_SHRINK,1),-1,0); - return 0; - } - - if( (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 ) { - clif->skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1); - sce->val3 -= damage; // absorb damage - d->dmg_lv = ATK_BLOCK; - sc_start(bl,SC_STUN,15,0,skill->get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken. - if( sce->val3 <= 0 ) { // Shield Down - sce->val2--; - if( sce->val2 > 0 ) { - if( sd ) - clif->millenniumshield(sd,sce->val2); - sce->val3 = 1000; // Next Shield - } else - status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down - } - return 0; - } + damage = battle->add_mastery(sd, target, damage, left); + if((skill = pc->checkskill(sd,AB_EUCHARISTICA)) > 0 && + (status_get_status_data(target)->race == RC_DEMON || status_get_status_data(target)->def_ele == ELE_DARK) ) + damage += damage * skill / 100; - if( (sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON && skill_id != WS_CARTTERMINATION && rnd()%100 < sce->val2 ) - { // attack blocked by Parrying - clif->skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1); - return 0; - } + return damage; +} +/*========================================== + * Elemental attribute fix. + *------------------------------------------*/ +int battle_calc_elefix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag){ + struct status_data *sstatus, *tstatus; + struct status_change *sc; - if(sc->data[SC_DODGE] && ( !sc->opt1 || sc->opt1 == OPT1_BURNING ) && - (flag&BF_LONG || sc->data[SC_SPURT]) - && rnd()%100 < 20) { - if (sd && pc_issit(sd)) pc->setstand(sd); //Stand it to dodge. - clif->skill_nodamage(bl,bl,TK_DODGE,1,1); - if (!sc->data[SC_COMBO]) - sc_start4(bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000); - return 0; - } + nullpo_ret(src); + nullpo_ret(target); - if(sc->data[SC_HERMODE] && flag&BF_MAGIC) - return 0; + sstatus = status_get_status_data(src); + tstatus = status_get_status_data(target); + sc = status_get_sc(src); - if(sc->data[SC_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG) - return 0; + if( (nk&NK_NO_ELEFIX) && n_ele ) + return damage; - if( sc->data[SC_NEUTRALBARRIER] && (flag&(BF_MAGIC|BF_LONG)) == (BF_MAGIC|BF_LONG) ) { - d->dmg_lv = ATK_MISS; - return 0; + if( damage > 0 ) + { + if( left ) + damage = battle->attr_fix(src, target, damage, s_ele_, tstatus->def_ele, tstatus->ele_lv); + else{ + damage=battle->attr_fix(src, target, damage, s_ele, tstatus->def_ele, tstatus->ele_lv); + if( skill_id == MC_CARTREVOLUTION ) //Cart Revolution applies the element fix once more with neutral element + damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); + if( skill_id == GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage. + damage += battle_attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); } + } + if( sc && sc->data[SC_WATK_ELEMENT] ) + { // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex] + damage = +#ifndef RENEWAL + battle->calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, ((TBL_PC*)src), (flag?2:0)) +#else + battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (flag?2:0)|(sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), 0) +#endif + * sc->data[SC_WATK_ELEMENT]->val2 / 100; + + damage += battle->attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); + if( left ){ + damage = +#ifndef RENEWAL + battle->calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, ((TBL_PC*)src), (flag?2:0)) +#else + battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_L, (flag?2:0)|(sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), 0) +#endif + * sc->data[SC_WATK_ELEMENT]->val2 / 100; + damage += battle->attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); + } + } - if((sce=sc->data[SC_KAUPE]) && rnd()%100 < sce->val2) - { //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries. - clif->specialeffect(bl, 462, AREA); - //Shouldn't end until Breaker's non-weapon part connects. - if (skill_id != ASC_BREAKER || !(flag&BF_WEAPON)) - if (--(sce->val3) <= 0) //We make it work like Safety Wall, even though it only blocks 1 time. - status_change_end(bl, SC_KAUPE, INVALID_TIMER); - return 0; - } + return damage; +} +/*========================================== + * Calculates card bonuses damage adjustments. + *------------------------------------------*/ +int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag){ + struct map_session_data *sd, *tsd; + short cardfix = 1000, t_class, s_class, s_race2, t_race2; + struct status_data *sstatus, *tstatus; + int i; - if( flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) && rnd()%100 < sce->val2) { - clif->specialeffect(bl, 462, AREA); // Still need confirm it. - return 0; - } + if( !damage ) + return 0; + + nullpo_ret(src); + nullpo_ret(target); - if (((sce=sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU]) - && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK)) { + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, target); + t_class = status_get_class(target); + s_class = status_get_class(src); + sstatus = status_get_status_data(src); + tstatus = status_get_status_data(target); + s_race2 = status_get_race2(src); - skill->additional_effect (src, bl, skill_id, skill_lv, flag, ATK_BLOCK, iTimer->gettick() ); - if( !status_isdead(src) ) - skill->counter_additional_effect( src, bl, skill_id, skill_lv, flag, iTimer->gettick() ); - if (sce) { - clif->specialeffect(bl, 462, AREA); - skill->blown(src,bl,sce->val3,-1,0); + switch(attack_type){ + case BF_MAGIC: + if ( sd && !(nk&NK_NO_CARDFIX_ATK) ) { + cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) + cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100; + cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + cardfix=cardfix*(100+sd->magic_atk_ele[s_ele])/100; + for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate;i++) { + if(sd->add_mdmg[i].class_ == t_class) { + cardfix=cardfix*(100+sd->add_mdmg[i].rate)/100; + break; + } + } + if (cardfix != 1000) + damage = damage * cardfix / 1000; } - //Both need to be consumed if they are active. - if (sce && --(sce->val2) <= 0) - status_change_end(bl, SC_UTSUSEMI, INVALID_TIMER); - if ((sce=sc->data[SC_BUNSINJYUTSU]) && --(sce->val2) <= 0) - status_change_end(bl, SC_BUNSINJYUTSU, INVALID_TIMER); - return 0; - } + if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) + { // Target cards. + if (!(nk&NK_NO_ELEFIX)) + { + int ele_fix = tsd->subele[s_ele]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele) continue; + if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && + tsd->subele2[i].flag&flag&BF_RANGEMASK && + tsd->subele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix)/100; + } + cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; + cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; + cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; + cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; - //Now damage increasing effects - if( sc->data[SC_AETERNA] && skill_id != PF_SOULBURN ) - { - if( src->type != BL_MER || skill_id == 0 ) - damage <<= 1; // Lex Aeterna only doubles damage of regular attacks from mercenaries + for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) { + if(tsd->add_mdef[i].class_ == s_class) { + cardfix=cardfix*(100-tsd->add_mdef[i].rate)/100; + break; + } + } + //It was discovered that ranged defense also counts vs magic! [Skotlex] + if ( flag&BF_SHORT ) + cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; + else + cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; - if( skill_id != ASC_BREAKER || !(flag&BF_WEAPON) ) - status_change_end(bl, SC_AETERNA, INVALID_TIMER); //Shouldn't end until Breaker's non-weapon part connects. - } + cardfix = cardfix * ( 100 - tsd->bonus.magic_def_rate ) / 100; -#ifdef RENEWAL - if( sc->data[SC_RAID] ) { - damage += damage * 20 / 100; + if( tsd->sc.data[SC_PROTECT_MDEF] ) + cardfix = cardfix * ( 100 - tsd->sc.data[SC_PROTECT_MDEF]->val1 ) / 100; - if (--sc->data[SC_RAID]->val1 == 0) - status_change_end(bl, SC_RAID, INVALID_TIMER); - } -#endif - - if( damage ) { - struct map_session_data *tsd = BL_CAST(BL_PC, src); - if( sc->data[SC_DEEPSLEEP] ) { - damage += damage / 2; // 1.5 times more damage while in Deep Sleep. - status_change_end(bl,SC_DEEPSLEEP,INVALID_TIMER); + if (cardfix != 1000) + damage = damage * cardfix / 1000; } - if( tsd && sd && sc->data[SC_CRYSTALIZE] && flag&BF_WEAPON ){ - switch(tsd->status.weapon){ - case W_MACE: - case W_2HMACE: - case W_1HAXE: - case W_2HAXE: - damage = damage * 150/100; - break; - case W_MUSICAL: - case W_WHIP: - if(!sd->state.arrow_atk) - break; - case W_BOW: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - case W_DAGGER: - case W_1HSWORD: - case W_2HSWORD: - damage = damage * 50/100; - break; + break; + case BF_WEAPON: + t_race2 = status_get_race2(target); + if( sd && !(nk&NK_NO_CARDFIX_ATK) && (left&2) ) + { + short cardfix_ = 1000; + if(sd->state.arrow_atk) + { + cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) + { + int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele]; + for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { + if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; + if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK && + sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK && + sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix += sd->right_weapon.addele2[i].rate; + } + cardfix=cardfix*(100+ele_fix)/100; + } + cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN])/100; } - } - if( sc->data[SC_VOICEOFSIREN] ) - status_change_end(bl,SC_VOICEOFSIREN,INVALID_TIMER); - } + else + { // Melee attack + if( !battle_config.left_cardfix_to_right ) + { + cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) { + int ele_fix = sd->right_weapon.addele[tstatus->def_ele]; + for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { + if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; + if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK && + sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK && + sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix += sd->right_weapon.addele2[i].rate; + } + cardfix=cardfix*(100+ele_fix)/100; + } + cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN])/100; - //Finally damage reductions.... - // Assumptio doubles the def & mdef on RE mode, otherwise gives a reduction on the final damage. [Igniz] -#ifndef RENEWAL - if( sc->data[SC_ASSUMPTIO] ) { - if( map_flag_vs(bl->m) ) - damage = damage*2/3; //Receive 66% damage - else - damage >>= 1; //Receive 50% damage - } -#endif + if( left&1 ) + { + cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; + if (!(nk&NK_NO_ELEFIX)) { + int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele]; + for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) { + if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue; + if(!(sd->left_weapon.addele2[i].flag&flag&BF_WEAPONMASK && + sd->left_weapon.addele2[i].flag&flag&BF_RANGEMASK && + sd->left_weapon.addele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix_lh += sd->left_weapon.addele2[i].rate; + } + cardfix=cardfix*(100+ele_fix_lh)/100; + } + cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100; + cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100; + cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix_=cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; + } + } + else + { + int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]; + for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) { + if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue; + if(!(sd->right_weapon.addele2[i].flag&flag&BF_WEAPONMASK && + sd->right_weapon.addele2[i].flag&flag&BF_RANGEMASK && + sd->right_weapon.addele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix += sd->right_weapon.addele2[i].rate; + } + for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) { + if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue; + if(!(sd->left_weapon.addele2[i].flag&flag&BF_WEAPONMASK && + sd->left_weapon.addele2[i].flag&flag&BF_RANGEMASK && + sd->left_weapon.addele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix += sd->left_weapon.addele2[i].rate; + } - if(sc->data[SC_DEFENDER] && - (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) - damage = damage * ( 100 - sc->data[SC_DEFENDER]->val2 ) / 100; + cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100; + cardfix=cardfix*(100+ele_fix)/100; + cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100; + cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100; + if( tstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; + } + } + for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ ) + { + if( sd->right_weapon.add_dmg[i].class_ == t_class ) + { + cardfix=cardfix*(100+sd->right_weapon.add_dmg[i].rate)/100; + break; + } + } - if(sc->data[SC_ADJUSTMENT] && - (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) - damage -= damage * 20 / 100; + if( left&1 ) + { + for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ ) + { + if( sd->left_weapon.add_dmg[i].class_ == t_class ) + { + cardfix_=cardfix_*(100+sd->left_weapon.add_dmg[i].rate)/100; + break; + } + } + } - if(sc->data[SC_FOGWALL] && skill_id != RK_DRAGONBREATH) { - if(flag&BF_SKILL) //25% reduction - damage -= damage * 25 / 100; - else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) - damage >>= 2; //75% reduction - } + if( flag&BF_LONG ) + cardfix = cardfix * ( 100 + sd->bonus.long_attack_atk_rate ) / 100; + if( (left&1) && cardfix_ != 1000 ) + damage = damage * cardfix_ / 1000; + else if( cardfix != 1000 ) + damage = damage * cardfix / 1000; - // Compressed code, fixed by map.h [Epoque] - if (src->type == BL_MOB) { - int i; - if (sc->data[SC_MANU_DEF]) - for (i=0;ARRAYLENGTH(mob_manuk)>i;i++) - if (mob_manuk[i]==((TBL_MOB*)src)->class_) { - damage -= damage * sc->data[SC_MANU_DEF]->val1 / 100; - break; - } - if (sc->data[SC_SPL_DEF]) - for (i=0;ARRAYLENGTH(mob_splendide)>i;i++) - if (mob_splendide[i]==((TBL_MOB*)src)->class_) { - damage -= damage * sc->data[SC_SPL_DEF]->val1 / 100; - break; + }else if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){ + if( !(nk&NK_NO_ELEFIX) ) + { + int ele_fix = tsd->subele[s_ele]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele) continue; + if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && + tsd->subele2[i].flag&flag&BF_RANGEMASK && + tsd->subele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix)/100; + if( left&1 && s_ele_ != s_ele ) + { + int ele_fix_lh = tsd->subele[s_ele_]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele_) continue; + if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && + tsd->subele2[i].flag&flag&BF_RANGEMASK && + tsd->subele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix_lh += tsd->subele2[i].rate; } - } + cardfix=cardfix*(100-ele_fix_lh)/100; + } + } + cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; + cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; + cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; + cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; - if((sce=sc->data[SC_ARMOR]) && //NPC_DEFENDER - sce->val3&flag && sce->val4&flag) - damage -= damage * sc->data[SC_ARMOR]->val2 / 100; + for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ) { + if( tsd->add_def[i].class_ == s_class ) { + cardfix=cardfix*(100-tsd->add_def[i].rate)/100; + break; + } + } -#ifdef RENEWAL - if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON || flag&BF_MAGIC) && skill_id != WS_CARTTERMINATION) -#else - if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON && skill_id != WS_CARTTERMINATION)) -#endif - { - struct status_data *status = status_get_status_data(bl); - int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval - per /=20; //Uses 20% SP intervals. - //SP Cost: 1% + 0.5% per every 20% SP - if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000)) - status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER); - //Reduction: 6% + 6% every 20% - damage -= damage * (6 * (1+per)) / 100; - } - if(sc->data[SC_GRANITIC_ARMOR]){ - damage -= damage * sc->data[SC_GRANITIC_ARMOR]->val2 / 100; - } - if(sc->data[SC_PAIN_KILLER]){ - damage -= damage * sc->data[SC_PAIN_KILLER]->val3 / 100; - } - if((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ){ - skill->castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,iTimer->gettick(),0); + if( flag&BF_SHORT ) + cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; + else // BF_LONG (there's no other choice) + cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; + + if( tsd->sc.data[SC_PROTECT_DEF] ) + cardfix = cardfix * ( 100 - tsd->sc.data[SC_PROTECT_DEF]->val1 ) / 100; + + if( cardfix != 1000 ) + damage = damage * cardfix / 1000; } + break; + case BF_MISC: + if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){ + // misc damage reduction from equipment + if (!(nk&NK_NO_ELEFIX)) + { + int ele_fix = tsd->subele[s_ele]; + for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++) + { + if(tsd->subele2[i].ele != s_ele) continue; + if(!(tsd->subele2[i].flag&flag&BF_WEAPONMASK && + tsd->subele2[i].flag&flag&BF_RANGEMASK && + tsd->subele2[i].flag&flag&BF_SKILLMASK)) + continue; + ele_fix += tsd->subele2[i].rate; + } + cardfix=cardfix*(100-ele_fix)/100; + } + cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100; + cardfix=cardfix*(100-tsd->subrace2[s_race2])/100; + cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100; + cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100; + if( sstatus->race != RC_DEMIHUMAN ) + cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100; - if( (sce = sc->data[SC_STONEHARDSKIN]) && flag&BF_WEAPON && damage > 0 ) { - sce->val2 -= damage; - if( src->type == BL_PC ) { - TBL_PC *ssd = BL_CAST(BL_PC, src); - if (ssd && ssd->status.weapon != W_BOW) - skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF); - } else - skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF); - // 30% chance to reduce monster's ATK by 25% for 10 seconds. - if( src->type == BL_MOB ) - sc_start(src, SC_STRIPWEAPON, 30, 0, skill->get_time2(RK_STONEHARDSKIN, sce->val1)); - if( sce->val2 <= 0 ) - status_change_end(bl, SC_STONEHARDSKIN, INVALID_TIMER); - } + cardfix = cardfix * ( 100 - tsd->bonus.misc_def_rate ) / 100; + if( flag&BF_SHORT ) + cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; + else // BF_LONG (there's no other choice) + cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; -/** - * In renewal steel body reduces all incoming damage by 1/10 - **/ -#ifdef RENEWAL - if( sc->data[SC_STEELBODY] ) { - damage = damage > 10 ? damage / 10 : 1; - } -#endif + if (cardfix != 1000) + damage = damage * cardfix / 1000; + } + break; + } - //Finally added to remove the status of immobile when aimedbolt is used. [Jobbie] - if( skill_id == RA_AIMEDBOLT && (sc->data[SC_BITE] || sc->data[SC_ANKLE] || sc->data[SC_ELECTRICSHOCKER]) ) - { - status_change_end(bl, SC_BITE, INVALID_TIMER); - status_change_end(bl, SC_ANKLE, INVALID_TIMER); - status_change_end(bl, SC_ELECTRICSHOCKER, INVALID_TIMER); - } + return damage; +} - //Finally Kyrie because it may, or not, reduce damage to 0. - if((sce = sc->data[SC_KYRIE]) && damage > 0){ - sce->val2-=damage; - if(flag&BF_WEAPON || skill_id == TF_THROWSTONE){ - if(sce->val2>=0) - damage=0; - else - damage=-sce->val2; +/*========================================== + * Calculates defense reduction. [malufett] + * flag: + * &1 - idef/imdef(Ignore defense) + * &2 - pdef(Pierce defense) + * &4 - tdef(Total defense reduction) + *------------------------------------------*/ +int battle_calc_defense(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int flag, int pdef){ + struct status_data *sstatus, *tstatus; + struct map_session_data *sd, *tsd; + struct status_change *sc, *tsc; + int i; + + if( !damage ) + return 0; + + nullpo_ret(src); + nullpo_ret(target); + + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, target); + sstatus = status_get_status_data(src); + tstatus = status_get_status_data(target); + sc = status_get_sc(src); + tsc = status_get_sc(target); + + switch(attack_type){ + case BF_WEAPON: + { + /** Take note in RE + * def1 = equip def + * def2 = status def + **/ + defType def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions. + short def2 = tstatus->def2, vit_def; + + def1 = status_calc_def2(target, tsc, def1, false); // equip def(RE) + def2 = status_calc_def(target, tsc, def2, false); // status def(RE) + + if( sd ){ + i = sd->ignore_def[is_boss(target)?RC_BOSS:RC_NONBOSS]; + i += sd->ignore_def[tstatus->race]; + if( i ){ + if( i > 100 ) i = 100; + def1 -= def1 * i / 100; + def2 -= def2 * i / 100; + } } - if((--sce->val3)<=0 || (sce->val2<=0) || skill_id == AL_HOLYLIGHT) - status_change_end(bl, SC_KYRIE, INVALID_TIMER); - } - if( sc->data[SC_MEIKYOUSISUI] && rand()%100 < 40 ) // custom value - damage = 0; + if( sc && sc->data[SC_EXPIATIO] ){ + i = 5 * sc->data[SC_EXPIATIO]->val1; // 5% per level + def1 -= def1 * i / 100; + def2 -= def2 * i / 100; + } + + if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) { + unsigned char target_count; //256 max targets should be a sane max + target_count = unit_counttargeted(target); + if(target_count >= battle_config.vit_penalty_count) { + if(battle_config.vit_penalty_type == 1) { + if( !tsc || !tsc->data[SC_STEELBODY] ) + def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; + def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; + } else { //Assume type 2 + if( !tsc || !tsc->data[SC_STEELBODY] ) + def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; + def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; + } + } + if(skill_id == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex] + if(def2 < 1) def2 = 1; + } + //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def + if (tsd) //Sd vit-eq + { +#ifndef RENEWAL + //[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1)) + vit_def = def2*(def2-15)/150; + vit_def = def2/2 + (vit_def>0?rnd()%vit_def:0); +#else + vit_def = def2; +#endif + if((battle->check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesnt work vs players + src->type == BL_MOB && (i=pc->checkskill(tsd,AL_DP)) > 0) + vit_def += i*(int)(3 +(tsd->status.base_level+1)*0.04); // submitted by orn + if( src->type == BL_MOB && (i=pc->checkskill(tsd,RA_RANGERMAIN))>0 && + (sstatus->race == RC_BRUTE || sstatus->race == RC_FISH || sstatus->race == RC_PLANT) ) + vit_def += i*5; + } + else { //Mob-Pet vit-eq +#ifndef RENEWAL + //VIT + rnd(0,[VIT/20]^2-1) + vit_def = (def2/20)*(def2/20); + vit_def = def2 + (vit_def>0?rnd()%vit_def:0); +#else + vit_def = def2; +#endif + } + + if (battle_config.weapon_defense_type) { + vit_def += def1*battle_config.weapon_defense_type; + def1 = 0; + } + #ifdef RENEWAL + /** + * RE DEF Reduction + * Damage = Attack * (4000+eDEF)/(4000+eDEF*10) - sDEF + * Pierce defence gains 1 atk per def/2 + **/ + if( def1 == -400 ) /* being hit by a gazillion units, you hit the jackpot and got -400 which creates a division by 0 and subsequently crashes */ + def1 = -399; - if (!damage) return 0; + if( flag&2 ) + damage += def1 >> 1; - if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1 ) { - int dx[8]={0,-1,-1,-1,0,1,1,1}; - int dy[8]={1,1,0,-1,-1,-1,0,1}; - uint8 dir = iMap->calc_dir(bl, src->x, src->y); - if( unit_movepos(bl, src->x-dx[dir], src->y-dy[dir], 1, 1) ) { - clif->slide(bl,src->x-dx[dir],src->y-dy[dir]); - unit_setdir(bl, dir); + if( !(flag&1) && !(flag&2) ) + if( flag&4 ) + damage -= (def1 + vit_def); + else + damage = damage * (4000+def1) / (4000+10*def1) - vit_def; + + #else + if( def1 > 100 ) def1 = 100; + if( !(flag&1) ){ + if( flag&2 ) + damage = damage * pdef * (def1+vit_def) / 100; + else + damage = damage * (100-def1) / 100; + } + if( !(flag&1 || flag&2) ) + damage -= vit_def; + #endif } - d->dmg_lv = ATK_DEF; - status_change_end(bl, SC_LIGHTNINGWALK, INVALID_TIMER); - return 0; - } + break; - //Probably not the most correct place, but it'll do here - //(since battle_drain is strictly for players currently) - if ((sce=sc->data[SC_BLOODLUST]) && flag&BF_WEAPON && damage > 0 && - rnd()%100 < sce->val3) - status_heal(src, damage*sce->val4/100, 0, 3); + case BF_MAGIC: + { + defType mdef = tstatus->mdef; + short mdef2= tstatus->mdef2; - if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 ) - pc->addspiritball(sd,skill->get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3); - if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { - TBL_HOM *hd = BL_CAST(BL_HOM,bl); - if (hd) homun->addspiritball(hd, 10); //add a sphere - } + mdef2 = status_calc_mdef(target, tsc, mdef2, false); // status mdef(RE) + mdef = status_calc_mdef2(target, tsc, mdef, false); // equip mde(RE) - if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) - status_change_spread(bl, src); // Deadly infect attacked side + if( flag&1 ) + mdef = 0; - if( sc && sc->data[SC__SHADOWFORM] ) { - struct block_list *s_bl = iMap->id2bl(sc->data[SC__SHADOWFORM]->val2); - if( !s_bl || s_bl->m != bl->m ) { // If the shadow form target is not present remove the sc. - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - } else if( status_isdead(s_bl) || !battle->check_target(src,s_bl,BCT_ENEMY)) { // If the shadow form target is dead or not your enemy remove the sc in both. - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - if( s_bl->type == BL_PC ) - ((TBL_PC*)s_bl)->shadowform_id = 0; - } else { - if( (--sc->data[SC__SHADOWFORM]->val3) < 0 ) { // If you have exceded max hits supported, remove the sc in both. - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - if( s_bl->type == BL_PC ) - ((TBL_PC*)s_bl)->shadowform_id = 0; - } else { - status_damage(bl, s_bl, damage, 0, clif->damage(s_bl, s_bl, iTimer->gettick(), 500, 500, damage, -1, 0, 0), 0); - return ATK_NONE; + if(sd) { + i = sd->ignore_mdef[is_boss(target)?RC_BOSS:RC_NONBOSS]; + i += sd->ignore_mdef[tstatus->race]; + if (i) + { + if (i > 100) i = 100; + mdef -= mdef * i/100; + //mdef2-= mdef2* i/100; } } - } - + #ifdef RENEWAL + /** + * RE MDEF Reduction + * Damage = Magic Attack * (1000+eMDEF)/(1000+eMDEF) - sMDEF + **/ + damage = damage * (1000 + mdef) / (1000 + mdef * 10) - mdef2; + #else + if(battle_config.magic_defense_type) + damage = damage - mdef*battle_config.magic_defense_type - mdef2; + else + damage = damage * (100-mdef)/100 - mdef2; + #endif + } + break; } + return damage; +} - //SC effects from caster side. - sc = status_get_sc(src); +int battle_calc_skillratio(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag){ + int i, addedratio; + struct status_change *sc, *tsc; + struct map_session_data *sd, *tsd; + struct status_data *status, *tstatus; - if (sc && sc->count) { - if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) - damage += damage * 75 / 100; - // [Epoque] - if (bl->type == BL_MOB) { - int i; + nullpo_ret(src); + nullpo_ret(target); - if ( ((sce=sc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) || - ((sce=sc->data[SC_MANU_MATK]) && (flag&BF_MAGIC)) - ) - for (i=0;ARRAYLENGTH(mob_manuk)>i;i++) - if (((TBL_MOB*)bl)->class_==mob_manuk[i]) { - damage += damage * sce->val1 / 100; - break; + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, target); + sc = status_get_sc(src); + tsc = status_get_sc(target); + status = status_get_status_data(src); + tstatus = status_get_status_data(target); + + addedratio = skillratio - 100; + + switch(attack_type){ + case BF_MAGIC: + switch(skill_id){ + case MG_NAPALMBEAT: + skillratio += skill_lv * 10 - 30; + break; + case MG_FIREBALL: + #ifdef RENEWAL + skillratio += 20 * skill_lv; + #else + skillratio += skill_lv * 10 - 30; + #endif + break; + case MG_SOULSTRIKE: + if (battle->check_undead(tstatus->race,tstatus->def_ele)) + skillratio += 5*skill_lv; + break; + case MG_FIREWALL: + skillratio -= 50; + break; + case MG_THUNDERSTORM: + /** + * in Renewal Thunder Storm boost is 100% (in pre-re, 80%) + **/ + #ifndef RENEWAL + skillratio -= 20; + #endif + break; + case MG_FROSTDIVER: + skillratio += 10 * skill_lv; + break; + case AL_HOLYLIGHT: + skillratio += 25; + if (sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_PRIEST) + skillratio *= 5; //Does 5x damage include bonuses from other skills? + break; + case AL_RUWACH: + skillratio += 45; + break; + case WZ_FROSTNOVA: + skillratio += (100+skill_lv*10) * 2 / 3 - 100; + break; + case WZ_FIREPILLAR: + if (skill_lv > 10) + skillratio += 100; + else + skillratio -= 80; + break; + case WZ_SIGHTRASHER: + skillratio += 20 * skill_lv; + break; + case WZ_WATERBALL: + skillratio += 30 * skill_lv; + break; + case WZ_STORMGUST: + skillratio += 40 * skill_lv; + break; + case HW_NAPALMVULCAN: + skillratio += 10 * skill_lv - 30; + break; + case SL_STIN: + skillratio += (tstatus->size!=SZ_SMALL?-99:10*skill_lv); //target size must be small (0) for full damage. + break; + case SL_STUN: + skillratio += (tstatus->size!=SZ_BIG?5*skill_lv:-99); //Full damage is dealt on small/medium targets + break; + case SL_SMA: + skillratio += -60 + status_get_lv(src); //Base damage is 40% + lv% + break; + case NJ_KOUENKA: + skillratio -= 10; + break; + case NJ_KAENSIN: + skillratio -= 50; + break; + case NJ_BAKUENRYU: + skillratio += 50 * (skill_lv-1); + break; + case NJ_HYOUSYOURAKU: + skillratio += 50 * skill_lv; + break; + case NJ_RAIGEKISAI: + skillratio += 60 + 40 * skill_lv; + break; + case NJ_KAMAITACHI: + case NPC_ENERGYDRAIN: + skillratio += 100 * skill_lv; + break; + case NPC_EARTHQUAKE: + skillratio += 100 + 100 * skill_lv + 100 * (skill_lv/2); + break; + #ifdef RENEWAL + case WZ_HEAVENDRIVE: + case WZ_METEOR: + skillratio += 25; + break; + case WZ_VERMILION: + { + int interval = 0, per = interval, ratio = per; + while( (per++) < skill_lv ){ + ratio += interval; + if(per%3==0) interval += 20; + } + if( skill_lv > 9 ) + ratio -= 10; + skillratio += ratio; } - if ( ((sce=sc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) || - ((sce=sc->data[SC_SPL_MATK]) && (flag&BF_MAGIC)) - ) - for (i=0;ARRAYLENGTH(mob_splendide)>i;i++) - if (((TBL_MOB*)bl)->class_==mob_splendide[i]) { - damage += damage * sce->val1 / 100; - break; + break; + case NJ_HUUJIN: + skillratio += 50; + break; + #else + case WZ_VERMILION: + skillratio += 20*skill_lv-20; + break; + #endif + /** + * Arch Bishop + **/ + case AB_JUDEX: + skillratio += 180 + 20 * skill_lv; + if (skill_lv > 4) skillratio += 20; + RE_LVL_DMOD(100); + break; + case AB_ADORAMUS: + skillratio += 400 + 100 * skill_lv; + RE_LVL_DMOD(100); + break; + case AB_DUPLELIGHT_MAGIC: + skillratio += 100 + 20 * skill_lv; + break; + /** + * Warlock + **/ + case WL_SOULEXPANSION: // MATK [{( Skill Level + 4 ) x 100 ) + ( Caster?s INT )} x ( Caster?s Base Level / 100 )] % + skillratio += 300 + 100 * skill_lv + status_get_int(src); + RE_LVL_DMOD(100); + break; + case WL_FROSTMISTY: // MATK [{( Skill Level x 100 ) + 200 } x ( Caster’s Base Level / 100 )] % + skillratio += 100 + 100 * skill_lv; + RE_LVL_DMOD(100); + break; + case WL_JACKFROST: + if( tsc && tsc->data[SC_FROSTMISTY] ){ + skillratio += 900 + 300 * skill_lv; + RE_LVL_DMOD(100); + }else{ + skillratio += 400 + 100 * skill_lv; + RE_LVL_DMOD(150); } - } - if( sc->data[SC_POISONINGWEAPON] && skill_id != GC_VENOMPRESSURE && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < sc->data[SC_POISONINGWEAPON]->val3 ) - sc_start(bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON, 1)); - if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) - status_change_spread(src, bl); - if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { - TBL_HOM *hd = BL_CAST(BL_HOM,bl); - if (hd) homun->addspiritball(hd, 10); - } - } - /* no data claims these settings affect anything other than players */ - if( damage && sd && bl->type == BL_PC ) { - switch( skill_id ) { - //case PA_PRESSURE: /* pressure also belongs to this list but it doesn't reach this area -- so dont worry about it */ - case HW_GRAVITATION: - case NJ_ZENYNAGE: - case KO_MUCHANAGE: - break; - default: - if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] - if (flag&BF_WEAPON) - damage = damage * map[bl->m].weapon_damage_rate / 100; - if (flag&BF_MAGIC) - damage = damage * map[bl->m].magic_damage_rate / 100; - if (flag&BF_MISC) - damage = damage * map[bl->m].misc_damage_rate / 100; - } else { //Normal attacks get reductions based on range. - if (flag & BF_SHORT) - damage = damage * map[bl->m].short_damage_rate / 100; - if (flag & BF_LONG) - damage = damage * map[bl->m].long_damage_rate / 100; + break; + case WL_DRAINLIFE: + skillratio = 200 * skill_lv + status_get_int(src); + RE_LVL_DMOD(100); + break; + case WL_CRIMSONROCK: + skillratio = 300 * skill_lv; + RE_LVL_DMOD(100); + skillratio += 1300; + break; + case WL_HELLINFERNO: + skillratio = 300 * skill_lv; + RE_LVL_DMOD(100); + // Shadow: MATK [{( Skill Level x 300 ) x ( Caster Base Level / 100 ) x 4/5 }] % + // Fire : MATK [{( Skill Level x 300 ) x ( Caster Base Level / 100 ) /5 }] % + if( flag&ELE_DARK ) + skillratio *= 4; + skillratio /= 5; + break; + case WL_COMET: + i = ( sc ? distance_xy(target->x, target->y, sc->comet_x, sc->comet_y) : 8 ); + if( i <= 3 ) skillratio += 2400 + 500 * skill_lv; // 7 x 7 cell + else + if( i <= 5 ) skillratio += 1900 + 500 * skill_lv; // 11 x 11 cell + else + if( i <= 7 ) skillratio += 1400 + 500 * skill_lv; // 15 x 15 cell + else + skillratio += 900 + 500 * skill_lv; // 19 x 19 cell + + if( sd && sd->status.party_id ){ + struct map_session_data* psd; + int static p_sd[5] = {0, 0, 0, 0, 0}, c; // just limit it to 5 + + c = 0; + memset (p_sd, 0, sizeof(p_sd)); + party_foreachsamemap(skill->check_condition_char_sub, sd, 3, &sd->bl, &c, &p_sd, skill_id); + c = ( c > 1 ? rand()%c : 0 ); + + if( (psd = iMap->id2sd(p_sd[c])) && pc->checkskill(psd,WL_COMET) > 0 ){ + skillratio = skill_lv * 400; //MATK [{( Skill Level x 400 ) x ( Caster's Base Level / 120 )} + 2500 ] % + RE_LVL_DMOD(120); + skillratio += 2500; + status_zap(&psd->bl, 0, skill->get_sp(skill_id, skill_lv) / 2); + } + } + break; + case WL_CHAINLIGHTNING_ATK: + skillratio += 400 + 100 * skill_lv; + RE_LVL_DMOD(100); + if(flag > 0) + skillratio += 100 * flag; + break; + case WL_EARTHSTRAIN: + skillratio += 1900 + 100 * skill_lv; + RE_LVL_DMOD(100); + break; + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + skillratio += 400 + 500 * skill_lv; + break; + case WL_SUMMON_ATK_FIRE: + case WL_SUMMON_ATK_WATER: + case WL_SUMMON_ATK_WIND: + case WL_SUMMON_ATK_GROUND: + skillratio = skill_lv * (status_get_lv(src) + ( sd ? sd->status.job_level : 50 ));// This is close to official, but lacking a little info to finalize. [Rytech] + RE_LVL_DMOD(100); + break; + case LG_RAYOFGENESIS: + { + int16 lv = skill_lv; + int bandingBonus = 0; + if( sc && sc->data[SC_BANDING] ) + bandingBonus = 200 * (sd ? skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),0) : 1); + skillratio = ((300 * skill_lv) + bandingBonus) * (sd ? sd->status.job_level : 1) / 25; } - if(!damage) damage = 1; break; - } - } - - if(battle_config.skill_min_damage && damage > 0 && damage < div_) - { - if ((flag&BF_WEAPON && battle_config.skill_min_damage&1) - || (flag&BF_MAGIC && battle_config.skill_min_damage&2) - || (flag&BF_MISC && battle_config.skill_min_damage&4) - ) - damage = div_; - } + case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield MDEF x 100) + (Casters INT x 2)] % + if( sd ) { + skillratio = status_get_lv(src) * 4 + sd->bonus.shieldmdef * 100 + status_get_int(src) * 2; + } else + skillratio += 1900; //2000% + break; + case WM_METALICSOUND: + skillratio += 120 * skill_lv + 60 * ( sd? pc->checkskill(sd, WM_LESSON) : 10 ) - 100; + break; + /*case WM_SEVERE_RAINSTORM: + skillratio += 50 * skill_lv; + break; - if( bl->type == BL_MOB && !status_isdead(bl) && src != bl) { - if (damage > 0 ) - mobskill_event((TBL_MOB*)bl,src,iTimer->gettick(),flag); - if (skill_id) - mobskill_event((TBL_MOB*)bl,src,iTimer->gettick(),MSC_SKILLUSED|(skill_id<<16)); - } - if( sd ) { - if( pc_ismadogear(sd) && rnd()%100 < 50 ) { - short element = skill->get_ele(skill_id, skill_lv); - if( !skill_id || element == -1 ) { //Take weapon's element - struct status_data *sstatus = NULL; - if( src->type == BL_PC && ((TBL_PC*)src)->bonus.arrow_ele ) - element = ((TBL_PC*)src)->bonus.arrow_ele; - else if( (sstatus = status_get_status_data(src)) ) { - element = sstatus->rhw.ele; - } + WM_SEVERE_RAINSTORM just set a unit place, + refer to WM_SEVERE_RAINSTORM_MELEE to set the formula. + */ + case WM_REVERBERATION_MAGIC: + // MATK [{(Skill Level x 100) + 100} x Casters Base Level / 100] % + skillratio += 100 * (sd ? pc->checkskill(sd, WM_REVERBERATION) : 1); + RE_LVL_DMOD(100); + break; + case SO_FIREWALK: + skillratio = 300; + RE_LVL_DMOD(100); + if( sc && sc->data[SC_HEATER_OPTION] ) + skillratio += sc->data[SC_HEATER_OPTION]->val3; + break; + case SO_ELECTRICWALK: + skillratio = 300; + RE_LVL_DMOD(100); + if( sc && sc->data[SC_BLAST_OPTION] ) + skillratio += sd ? sd->status.job_level / 2 : 0; + break; + case SO_EARTHGRAVE: + skillratio = ( 200 * ( sd ? pc->checkskill(sd, SA_SEISMICWEAPON) : 10 ) + status_get_int(src) * skill_lv ); + RE_LVL_DMOD(100); + if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) + skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2; + break; + case SO_DIAMONDDUST: + skillratio = ( 200 * ( sd ? pc->checkskill(sd, SA_FROSTWEAPON) : 10 ) + status_get_int(src) * skill_lv ); + RE_LVL_DMOD(100); + if( sc && sc->data[SC_COOLER_OPTION] ) + skillratio += sc->data[SC_COOLER_OPTION]->val3; + break; + case SO_POISON_BUSTER: + skillratio += 1100 + 300 * skill_lv; + if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) + skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2; + break; + case SO_PSYCHIC_WAVE: + skillratio += -100 + skill_lv * 70 + (status_get_int(src) * 3); + RE_LVL_DMOD(100); + if( sc ){ + if( sc->data[SC_HEATER_OPTION] ) + skillratio += sc->data[SC_HEATER_OPTION]->val3; + else if(sc->data[SC_COOLER_OPTION] ) + skillratio += sc->data[SC_COOLER_OPTION]->val3; + else if(sc->data[SC_BLAST_OPTION] ) + skillratio += sc->data[SC_BLAST_OPTION]->val2; + else if(sc->data[SC_CURSED_SOIL_OPTION] ) + skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3; + } + break; + case SO_VARETYR_SPEAR: //MATK [{( Endow Tornado skill level x 50 ) + ( Caster INT x Varetyr Spear Skill level )} x Caster Base Level / 100 ] % + skillratio = status_get_int(src) * skill_lv + ( sd ? pc->checkskill(sd, SA_LIGHTNINGLOADER) * 50 : 0 ); + RE_LVL_DMOD(100); + if( sc && sc->data[SC_BLAST_OPTION] ) + skillratio += sd ? sd->status.job_level * 5 : 0; + break; + case SO_CLOUD_KILL: + skillratio += -100 + skill_lv * 40; + RE_LVL_DMOD(100); + if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) + skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2; + break; + case GN_DEMONIC_FIRE: + if( skill_lv > 20) + { // Fire expansion Lv.2 + skillratio += 110 + 20 * (skill_lv - 20) + status_get_int(src) * 3; // Need official INT bonus. [LimitLine] + } + else if( skill_lv > 10 ) + { // Fire expansion Lv.1 + skillratio += 110 + 20 * (skill_lv - 10) / 2; + } + else + skillratio += 110 + 20 * skill_lv; + break; + // Magical Elemental Spirits Attack Skills + case EL_FIRE_MANTLE: + case EL_WATER_SCREW: + skillratio += 900; + break; + case EL_FIRE_ARROW: + case EL_ROCK_CRUSHER_ATK: + skillratio += 200; + break; + case EL_FIRE_BOMB: + case EL_ICE_NEEDLE: + case EL_HURRICANE_ATK: + skillratio += 400; + break; + case EL_FIRE_WAVE: + case EL_TYPOON_MIS_ATK: + skillratio += 1100; + break; + case MH_ERASER_CUTTER: + if(skill_lv%2) skillratio += 400; //600:800:1000 + else skillratio += 700; //1000:1200 + skillratio += 100 * skill_lv; + break; + case MH_XENO_SLASHER: + if(skill_lv%2) skillratio += 350 + 50 * skill_lv; //500:600:700 + else skillratio += 400 + 100 * skill_lv; //700:900 + break; + case MH_HEILIGE_STANGE: + skillratio += 400 + 250 * skill_lv; + break; + case MH_POISON_MIST: + skillratio += 100 * skill_lv; + break; + case KO_KAIHOU: + if( sd ){ + ARR_FIND(1, 6, i, sd->charm[i] > 0); + if( i < 5 ){ + skillratio += -100 + 200 * sd->charm[i]; + RE_LVL_DMOD(100); + pc->del_charm(sd, sd->charm[i], i); + } + } + break; } - else if( element == -2 ) //Use enchantment's element - element = status_get_attack_sc_element(src,status_get_sc(src)); - else if( element == -3 ) //Use random element - element = rnd()%ELE_MAX; - if( element == ELE_FIRE || element == ELE_WATER ) - pc->overheat(sd,element == ELE_FIRE ? 1 : -1); - } - } - - return damage; -} - -/*========================================== - * Calculates BG related damage adjustments. - *------------------------------------------*/ -int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int damage, int div_, uint16 skill_id, uint16 skill_lv, int flag) -{ - if( !damage ) - return 0; - - if( bl->type == BL_MOB ) { - struct mob_data* md = BL_CAST(BL_MOB, bl); - - if( flag&BF_SKILL && (md->class_ == MOBID_BLUE_CRYST || md->class_ == MOBID_PINK_CRYST) ) - return 0; // Crystal cannot receive skill damage on battlegrounds - } - - return damage; -} - -/*========================================== - * Calculates GVG related damage adjustments. - *------------------------------------------*/ -int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,uint16 skill_id,uint16 skill_lv,int flag) -{ - struct mob_data* md = BL_CAST(BL_MOB, bl); - int class_ = status_get_class(bl); - - if (!damage) //No reductions to make. - return 0; - - if(md && md->guardian_data) { - if(class_ == MOBID_EMPERIUM && flag&BF_SKILL) { - //Skill immunity. - switch (skill_id) { -#ifndef RENEWAL - case MO_TRIPLEATTACK: -#endif - case HW_GRAVITATION: - break; - default: - return 0; - } - } - if(src->type != BL_MOB) { - struct guild *g = src->type == BL_PC ? ((TBL_PC *)src)->guild : guild->search(status_get_guild_id(src)); - - if (class_ == MOBID_EMPERIUM && (!g || guild->checkskill(g,GD_APPROVAL) <= 0 )) - return 0; - - if (g && battle_config.guild_max_castles && guild->checkcastles(g)>=battle_config.guild_max_castles) - return 0; // [MouseJstr] - } - } - - switch (skill_id) { - case PA_PRESSURE: - case HW_GRAVITATION: - case NJ_ZENYNAGE: - case KO_MUCHANAGE: - break; - default: - /* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka] - if (md && md->guardian_data) { - damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100; - } - */ - break; - } - - return damage; -} - -/*========================================== - * HP/SP drain calculation - *------------------------------------------*/ -int battle_calc_drain(int damage, int rate, int per) { - int diff = 0; - - if (per && rnd()%1000 < rate) { - diff = (damage * per) / 100; - if (diff == 0) { - if (per > 0) - diff = 1; - else - diff = -1; - } - } - return diff; -} - -/*========================================== - * Passif skill dammages increases - *------------------------------------------*/ -int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type) { - int damage,skill; - struct status_data *status = status_get_status_data(target); - int weapon; - damage = dmg; - - nullpo_ret(sd); - - if((skill = pc->checkskill(sd,AL_DEMONBANE)) > 0 && - target->type == BL_MOB && //This bonus doesnt work against players. - (battle->check_undead(status->race,status->def_ele) || status->race==RC_DEMON) ) - damage += (skill*(int)(3+(sd->status.base_level+1)*0.05)); // submitted by orn - //damage += (skill * 3); - if( (skill = pc->checkskill(sd, RA_RANGERMAIN)) > 0 && (status->race == RC_BRUTE || status->race == RC_PLANT || status->race == RC_FISH) ) - damage += (skill * 5); - if( (skill = pc->checkskill(sd,NC_RESEARCHFE)) > 0 && (status->def_ele == ELE_FIRE || status->def_ele == ELE_EARTH) ) - damage += (skill * 10); - if( pc_ismadogear(sd) ) - damage += 20 + 20 * pc->checkskill(sd, NC_MADOLICENCE); - - if((skill = pc->checkskill(sd,HT_BEASTBANE)) > 0 && (status->race==RC_BRUTE || status->race==RC_INSECT) ) { - damage += (skill * 4); - if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_HUNTER) - damage += sd->status.str; - } - - if(type == 0) - weapon = sd->weapontype1; - else - weapon = sd->weapontype2; - switch(weapon) - { - case W_1HSWORD: - #ifdef RENEWAL - if((skill = pc->checkskill(sd,AM_AXEMASTERY)) > 0) - damage += (skill * 3); - #endif - case W_DAGGER: - if((skill = pc->checkskill(sd,SM_SWORD)) > 0) - damage += (skill * 4); - if((skill = pc->checkskill(sd,GN_TRAINING_SWORD)) > 0) - damage += skill * 10; - break; - case W_2HSWORD: - #ifdef RENEWAL - if((skill = pc->checkskill(sd,AM_AXEMASTERY)) > 0) - damage += (skill * 3); - #endif - if((skill = pc->checkskill(sd,SM_TWOHAND)) > 0) - damage += (skill * 4); - break; - case W_1HSPEAR: - case W_2HSPEAR: - if((skill = pc->checkskill(sd,KN_SPEARMASTERY)) > 0) { - if(!pc_isriding(sd)) - damage += (skill * 4); - else - damage += (skill * 5); - } - break; - case W_1HAXE: - case W_2HAXE: - if((skill = pc->checkskill(sd,AM_AXEMASTERY)) > 0) - damage += (skill * 3); - if((skill = pc->checkskill(sd,NC_TRAININGAXE)) > 0) - damage += (skill * 5); - break; - case W_MACE: - case W_2HMACE: - if((skill = pc->checkskill(sd,PR_MACEMASTERY)) > 0) - damage += (skill * 3); - if((skill = pc->checkskill(sd,NC_TRAININGAXE)) > 0) - damage += (skill * 5); - break; - case W_FIST: - if((skill = pc->checkskill(sd,TK_RUN)) > 0) - damage += (skill * 10); - // No break, fallthrough to Knuckles - case W_KNUCKLE: - if((skill = pc->checkskill(sd,MO_IRONHAND)) > 0) - damage += (skill * 3); - break; - case W_MUSICAL: - if((skill = pc->checkskill(sd,BA_MUSICALLESSON)) > 0) - damage += (skill * 3); - break; - case W_WHIP: - if((skill = pc->checkskill(sd,DC_DANCINGLESSON)) > 0) - damage += (skill * 3); - break; - case W_BOOK: - if((skill = pc->checkskill(sd,SA_ADVANCEDBOOK)) > 0) - damage += (skill * 3); - break; - case W_KATAR: - if((skill = pc->checkskill(sd,AS_KATAR)) > 0) - damage += (skill * 3); - break; - } - - return damage; -} -/*========================================== - * Calculates the standard damage of a normal attack assuming it hits, - * it calculates nothing extra fancy, is needed for magnum break's WATK_ELEMENT bonus. [Skotlex] - *------------------------------------------ - * Pass damage2 as NULL to not calc it. - * Flag values: - * &1: Critical hit - * &2: Arrow attack - * &4: Skill is Magic Crasher - * &8: Skip target size adjustment (Extremity Fist?) - *&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX) - */ -int battle_calc_base_damage(struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) { - unsigned int atkmin=0, atkmax=0; - short type = 0; - int damage = 0; - - if (!sd) - { //Mobs/Pets - if(flag&4) - { - atkmin = status->matk_min; - atkmax = status->matk_max; - } else { - atkmin = wa->atk; - atkmax = wa->atk2; - } - if (atkmin > atkmax) - atkmin = atkmax; - } else { //PCs - atkmax = wa->atk; - type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R; - - if (!(flag&1) || (flag&2)) - { //Normal attacks - atkmin = status->dex; - - if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]]) - atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100; - - if (atkmin > atkmax) - atkmin = atkmax; - - if(flag&2 && !(flag&16)) - { //Bows - atkmin = atkmin*atkmax/100; - if (atkmin > atkmax) - atkmax = atkmin; - } - } - } - - if (sc && sc->data[SC_MAXIMIZEPOWER]) - atkmin = atkmax; - - //Weapon Damage calculation - if (!(flag&1)) - damage = (atkmax>atkmin? rnd()%(atkmax-atkmin):0)+atkmin; - else - damage = atkmax; - - if (sd) - { - //rodatazone says the range is 0~arrow_atk-1 for non crit - if (flag&2 && sd->bonus.arrow_atk) - damage += ( (flag&1) ? sd->bonus.arrow_atk : rnd()%sd->bonus.arrow_atk ); - - //SizeFix only for players - if (!(sd->special_state.no_sizefix || (flag&8))) - damage = damage * ( type == EQI_HAND_L ? sd->left_weapon.atkmods[t_size] : sd->right_weapon.atkmods[t_size] ) / 100; - } - - //Finally, add baseatk - if(flag&4) - damage += status->matk_min; - else - damage += status->batk; - - //rodatazone says that Overrefine bonuses are part of baseatk - //Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands. - if(sd) { - if (type == EQI_HAND_L) { - if(sd->left_weapon.overrefine) - damage += rnd()%sd->left_weapon.overrefine+1; - if (sd->weapon_atk_rate[sd->weapontype2]) - damage += damage * sd->weapon_atk_rate[sd->weapontype2] / 100; - } else { //Right hand - if(sd->right_weapon.overrefine) - damage += rnd()%sd->right_weapon.overrefine+1; - if (sd->weapon_atk_rate[sd->weapontype1]) - damage += damage * sd->weapon_atk_rate[sd->weapontype1] / 100; - } - } - return damage; -} - -/*========================================== - * Consumes ammo for the given skill. - *------------------------------------------*/ -void battle_consume_ammo(TBL_PC*sd, int skill_id, int lv) { - int qty=1; - if (!battle_config.arrow_decrement) - return; - - if (skill) { - qty = skill->get_ammo_qty(skill_id, lv); - if (!qty) qty = 1; - } - - if(sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition - pc->delitem(sd,sd->equip_index[EQI_AMMO],qty,0,1,LOG_TYPE_CONSUME); - - sd->state.arrow_atk = 0; -} -//Skill Range Criteria -int battle_range_type(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv) { - if (battle_config.skillrange_by_distance && - (src->type&battle_config.skillrange_by_distance) - ) { //based on distance between src/target [Skotlex] - if (check_distance_bl(src, target, 5)) - return BF_SHORT; - return BF_LONG; - } - //based on used skill's range - if (skill->get_range2(src, skill_id, skill_lv) < 5) - return BF_SHORT; - return BF_LONG; -} -int battle_adjust_skill_damage(int m, unsigned short skill_id) { - - if( map[m].skill_count ) { - int i; - ARR_FIND(0, map[m].skill_count, i, map[m].skills[i]->skill_id == skill_id ); - - if( i < map[m].skill_count ) { - return map[m].skills[i]->modifier; - } - - } - - return 0; -} -int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) { - int i; - if (!sd->skillblown[0].id) - return 0; - //Apply the bonus blewcount. [Skotlex] - for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) { - if (sd->skillblown[i].id == skill_id) - return sd->skillblown[i].val; - } - return 0; -} - -//For quick div adjustment. -#define damage_div_fix(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; } -/*========================================== - * battle_calc_weapon_attack (by Skotlex) - *------------------------------------------*/ -struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag) -{ - unsigned int skillratio = 100; //Skill dmg modifiers. - short temp=0; - short s_ele, s_ele_, t_class; - int i, nk; - bool n_ele = false; // non-elemental - - struct map_session_data *sd, *tsd; - struct Damage wd; - struct status_change *sc = status_get_sc(src); - struct status_change *tsc = status_get_sc(target); - struct status_data *sstatus = status_get_status_data(src); - struct status_data *tstatus = status_get_status_data(target); - struct { - unsigned hit : 1; //the attack Hit? (not a miss) - unsigned cri : 1; //Critical hit - unsigned idef : 1; //Ignore defense - unsigned idef2 : 1; //Ignore defense (left weapon) - unsigned pdef : 2; //Pierces defense (Investigate/Ice Pick) - unsigned pdef2 : 2; //1: Use def+def2/100, 2: Use def+def2/50 - unsigned infdef : 1; //Infinite defense (plants) - unsigned arrow : 1; //Attack is arrow-based - unsigned rh : 1; //Attack considers right hand (wd.damage) - unsigned lh : 1; //Attack considers left hand (wd.damage2) - unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that) - } flag; - - memset(&wd,0,sizeof(wd)); - memset(&flag,0,sizeof(flag)); - - if(src==NULL || target==NULL) - { - nullpo_info(NLP_MARK); - return wd; - } - //Initial flag - flag.rh=1; - flag.weapon=1; - flag.infdef=(tstatus->mode&MD_PLANT && skill_id != RA_CLUSTERBOMB -#ifdef RENEWAL - && skill_id != HT_FREEZINGTRAP -#endif - ?1:0); - if( target->type == BL_SKILL){ - TBL_SKILL *su = (TBL_SKILL*)target; - if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) - flag.infdef = 1; - } - - //Initial Values - wd.type=0; //Normal attack - wd.div_=skill_id?skill->get_num(skill_id,skill_lv):1; - wd.amotion=(skill_id && skill->get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. - if(skill_id == KN_AUTOCOUNTER) - wd.amotion >>= 1; - wd.dmotion=tstatus->dmotion; - wd.blewcount=skill->get_blewcount(skill_id,skill_lv); - wd.flag = BF_WEAPON; //Initial Flag - wd.flag |= (skill_id||wflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish] - wd.dmg_lv=ATK_DEF; //This assumption simplifies the assignation later - nk = skill->get_nk(skill_id); - if( !skill_id && wflag ) //If flag, this is splash damage from Baphomet Card and it always hits. - nk |= NK_NO_CARDFIX_ATK|NK_IGNORE_FLEE; - flag.hit = nk&NK_IGNORE_FLEE?1:0; - flag.idef = flag.idef2 = nk&NK_IGNORE_DEF?1:0; - - if (sc && !sc->count) - sc = NULL; //Skip checking as there are no status changes active. - if (tsc && !tsc->count) - tsc = NULL; //Skip checking as there are no status changes active. - - sd = BL_CAST(BL_PC, src); - tsd = BL_CAST(BL_PC, target); - - if(sd) - wd.blewcount += battle->blewcount_bonus(sd, skill_id); - - //Set miscellaneous data that needs be filled regardless of hit/miss - if( - (sd && sd->state.arrow_atk) || - (!sd && ((skill_id && skill->get_ammotype(skill_id)) || sstatus->rhw.range>3)) - ) - flag.arrow = 1; - - if(skill_id) { - wd.flag |= battle->range_type(src, target, skill_id, skill_lv); - switch(skill_id) { - case MO_FINGEROFFENSIVE: - if(sd) { - if (battle_config.finger_offensive_type) - wd.div_ = 1; - else - wd.div_ = sd->spiritball_old; - } - break; - case HT_PHANTASMIC: - //Since these do not consume ammo, they need to be explicitly set as arrow attacks. - flag.arrow = 1; - break; -#ifndef RENEWAL - case PA_SHIELDCHAIN: - case CR_SHIELDBOOMERANG: -#endif - case LG_SHIELDPRESS: - case LG_EARTHDRIVE: - flag.weapon = 0; - break; - - case KN_PIERCE: - case ML_PIERCE: - wd.div_= (wd.div_>0?tstatus->size+1:-(tstatus->size+1)); - break; - - case TF_DOUBLE: //For NPC used skill. - case GS_CHAINACTION: - wd.type = 0x08; - break; - - case GS_GROUNDDRIFT: - case KN_SPEARSTAB: - case KN_BOWLINGBASH: - case MS_BOWLINGBASH: - case MO_BALKYOUNG: - case TK_TURNKICK: - wd.blewcount=0; - break; - - case KN_AUTOCOUNTER: - wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL; - break; - - case NPC_CRITICALSLASH: - case LG_PINPOINTATTACK: - flag.cri = 1; //Always critical skill. - break; - - case LK_SPIRALPIERCE: - if (!sd) wd.flag=(wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC; - break; - } - } else //Range for normal attacks. - wd.flag |= flag.arrow?BF_LONG:BF_SHORT; - - if ( (!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2 ) - { //Check for Lucky Dodge - wd.type=0x0b; - wd.dmg_lv=ATK_LUCKY; - if (wd.div_ < 0) wd.div_*=-1; - return wd; - } - - t_class = status_get_class(target); - s_ele = s_ele_ = skill->get_ele(skill_id, skill_lv); - if( !skill_id || s_ele == -1 ) - { //Take weapon's element - s_ele = sstatus->rhw.ele; - s_ele_ = sstatus->lhw.ele; - if( sd ){ //Summoning 10 talisman will endow your weapon. - ARR_FIND(1, 6, i, sd->talisman[i] >= 10); - if( i < 5 ) s_ele = s_ele_ = i; - } - if( flag.arrow && sd && sd->bonus.arrow_ele ) - s_ele = sd->bonus.arrow_ele; - if( battle_config.attack_attr_none&src->type ) - n_ele = true; //Weapon's element is "not elemental" - } - else if( s_ele == -2 ) //Use enchantment's element - s_ele = s_ele_ = status_get_attack_sc_element(src,sc); - else if( s_ele == -3 ) //Use random element - s_ele = s_ele_ = rnd()%ELE_MAX; - switch( skill_id ) - { - case GS_GROUNDDRIFT: - s_ele = s_ele_ = wflag; //element comes in flag. - break; - case LK_SPIRALPIERCE: - if (!sd) n_ele = false; //forced neutral for monsters - break; - } - - if (!(nk & NK_NO_ELEFIX) && !n_ele) - if (src->type == BL_HOM) - n_ele = true; //skill is "not elemental" - if (sc && sc->data[SC_GOLDENE_FERSE] && ((!skill_id && (rnd() % 100 < sc->data[SC_GOLDENE_FERSE]->val4)) || skill_id == MH_STAHL_HORN)) { - s_ele = s_ele_ = ELE_HOLY; - n_ele = false; - } - - if(!skill_id) - { //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2) - if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0) - { - flag.rh=0; - flag.lh=1; - } - if (sstatus->lhw.atk) - flag.lh=1; - } - - if( sd && !skill_id ) { //Check for double attack. - if( ( ( skill_lv = pc->checkskill(sd,TF_DOUBLE) ) > 0 && sd->weapontype1 == W_DAGGER ) - || ( sd->bonus.double_rate > 0 && sd->weapontype1 != W_FIST ) //Will fail bare-handed - || ( sc && sc->data[SC_KAGEMUSYA] && sd->weapontype1 != W_FIST )) // Need confirmation - { //Success chance is not added, the higher one is used [Skotlex] - if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) ) - { - wd.div_ = skill->get_num(TF_DOUBLE,skill_lv?skill_lv:1); - wd.type = 0x08; - } - } - else if( sd->weapontype1 == W_REVOLVER && (skill_lv = pc->checkskill(sd,GS_CHAINACTION)) > 0 && rnd()%100 < 5*skill_lv ) - { - wd.div_ = skill->get_num(GS_CHAINACTION,skill_lv); - wd.type = 0x08; - } - else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW - && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1){ - int chance = rand()%100; - wd.type = 0x08; - switch(sc->data[SC_FEARBREEZE]->val1){ - case 5: - if( chance < 3){// 3 % chance to attack 5 times. - wd.div_ = 5; - break; - } - case 4: - if( chance < 7){// 6 % chance to attack 4 times. - wd.div_ = 4; - break; - } - case 3: - if( chance < 10){// 9 % chance to attack 3 times. - wd.div_ = 3; - break; - } - case 2: - case 1: - if( chance < 13){// 12 % chance to attack 2 times. - wd.div_ = 2; - break; - } - } - wd.div_ = min(wd.div_,sd->status.inventory[i].amount); - sc->data[SC_FEARBREEZE]->val4 = wd.div_-1; - } - } - - //Check for critical - if( !flag.cri && !(wd.type&0x08) && sstatus->cri && - (!skill_id || - skill_id == KN_AUTOCOUNTER || - skill_id == SN_SHARPSHOOTING || skill_id == MA_SHARPSHOOTING || - skill_id == NJ_KIRIKAGE)) - { - short cri = sstatus->cri; - if (sd) - { - cri+= sd->critaddrace[tstatus->race]; - if(flag.arrow) - cri += sd->bonus.arrow_cri; - } - if( sc && sc->data[SC_CAMOUFLAGE] ) - cri += 10 * (10-sc->data[SC_CAMOUFLAGE]->val4); - //The official equation is *2, but that only applies when sd's do critical. - //Therefore, we use the old value 3 on cases when an sd gets attacked by a mob - cri -= tstatus->luk*(!sd&&tsd?3:2); - - if( tsc && tsc->data[SC_SLEEP] ) { - cri <<= 1; - } - switch (skill_id) { - case KN_AUTOCOUNTER: - if(battle_config.auto_counter_type && - (battle_config.auto_counter_type&src->type)) - flag.cri = 1; - else - cri <<= 1; - break; - case SN_SHARPSHOOTING: - case MA_SHARPSHOOTING: - cri += 200; - break; - case NJ_KIRIKAGE: - cri += 250 + 50*skill_lv; - break; - } - if(tsd && tsd->bonus.critical_def) - cri = cri * ( 100 - tsd->bonus.critical_def ) / 100; - if (rnd()%1000 < cri) - flag.cri = 1; - } - if (flag.cri) { - wd.type = 0x0a; -#ifdef RENEWAL - flag.hit = 1; -#else - flag.idef = flag.idef2 = flag.hit = 1; -#endif - } else { //Check for Perfect Hit - if(sd && sd->bonus.perfect_hit > 0 && rnd()%100 < sd->bonus.perfect_hit) - flag.hit = 1; - if (sc && sc->data[SC_FUSION]) { - flag.hit = 1; //SG_FUSION always hit [Komurka] - flag.idef = flag.idef2 = 1; //def ignore [Komurka] - } - if( !flag.hit ) - switch(skill_id) - { - case AS_SPLASHER: - if( !wflag ) // Always hits the one exploding. - flag.hit = 1; - break; - case CR_SHIELDBOOMERANG: - if( sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_CRUSADER ) - flag.hit = 1; - break; - } - if (tsc && !flag.hit && tsc->opt1 && tsc->opt1 != OPT1_STONEWAIT && tsc->opt1 != OPT1_BURNING) - flag.hit = 1; - } - - if (!flag.hit) - { //Hit/Flee calculation - short - flee = tstatus->flee, -#ifdef RENEWAL - hitrate = 0; //Default hitrate -#else - hitrate = 80; //Default hitrate -#endif - - if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) { - unsigned char attacker_count; //256 max targets should be a sane max - attacker_count = unit_counttargeted(target); - if(attacker_count >= battle_config.agi_penalty_count) { - if (battle_config.agi_penalty_type == 1) - flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; - else //asume type 2: absolute reduction - flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; - if(flee < 1) flee = 1; - } - } - - hitrate+= sstatus->hit - flee; - - if(wd.flag&BF_LONG && !skill_id && //Fogwall's hit penalty is only for normal ranged attacks. - tsc && tsc->data[SC_FOGWALL]) - hitrate -= 50; - - if(sd && flag.arrow) - hitrate += sd->bonus.arrow_hit; -#ifdef RENEWAL - if( sd ) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window - hitrate += pc->checkskill(sd,AC_VULTURE); -#endif - if(skill_id) - switch(skill_id) - { //Hit skill modifiers - //It is proven that bonus is applied on final hitrate, not hit. - case SM_BASH: - case MS_BASH: - hitrate += hitrate * 5 * skill_lv / 100; - break; - case MS_MAGNUM: - case SM_MAGNUM: - hitrate += hitrate * 10 * skill_lv / 100; - break; - case KN_AUTOCOUNTER: - case PA_SHIELDCHAIN: - case NPC_WATERATTACK: - case NPC_GROUNDATTACK: - case NPC_FIREATTACK: - case NPC_WINDATTACK: - case NPC_POISONATTACK: - case NPC_HOLYATTACK: - case NPC_DARKNESSATTACK: - case NPC_UNDEADATTACK: - case NPC_TELEKINESISATTACK: - case NPC_BLEEDING: - hitrate += hitrate * 20 / 100; - break; - case KN_PIERCE: - case ML_PIERCE: - hitrate += hitrate * 5 * skill_lv / 100; - break; - case AS_SONICBLOW: - if(sd && pc->checkskill(sd,AS_SONICACCEL)>0) - hitrate += hitrate * 50 / 100; - break; - case MC_CARTREVOLUTION: - case GN_CART_TORNADO: - case GN_CARTCANNON: - if( sd && pc->checkskill(sd, GN_REMODELING_CART) ) - hitrate += pc->checkskill(sd, GN_REMODELING_CART) * 4; - break; - case GC_VENOMPRESSURE: - hitrate += 10 + 4 * skill_lv; - break; - } - - if( sd ) { - // Weaponry Research hidden bonus - if ((temp = pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0) - hitrate += hitrate * ( 2 * temp ) / 100; - - if( (sd->status.weapon == W_1HSWORD || sd->status.weapon == W_DAGGER) && - (temp = pc->checkskill(sd, GN_TRAINING_SWORD))>0 ) - hitrate += 3 * temp; - } - - hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); - - if(rnd()%100 >= hitrate) - wd.dmg_lv = ATK_FLEE; - else - flag.hit = 1; - } //End hit/miss calculation - - if (flag.hit && !flag.infdef) //No need to do the math for plants - { //Hitting attack - -//Assuming that 99% of the cases we will not need to check for the flag.rh... we don't. -//ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc -#define ATK_RATE( a ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(a)/100; } -#define ATK_RATE2( a , b ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; } -#define ATK_RATER(a){ wd.damage = wd.damage*(a)/100;} -#define ATK_RATEL(a){ wd.damage2 = wd.damage2*(a)/100;} -//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage -#define ATK_ADDRATE( a ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(a)/100; } -#define ATK_ADDRATE2( a , b ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; } -//Adds an absolute value to damage. 100 = +100 damage -#define ATK_ADD( a ) { wd.damage+= a; if (flag.lh) wd.damage2+= a; } -#define ATK_ADD2( a , b ) { wd.damage+= a; if (flag.lh) wd.damage2+= b; } - - switch (skill_id) - { //Calc base damage according to skill - case PA_SACRIFICE: - wd.damage = sstatus->max_hp* 9/100; - wd.damage2 = 0; - break; -#ifndef RENEWAL - case NJ_ISSEN: - wd.damage = 40*sstatus->str +skill_lv*(sstatus->hp/10 + 35); - wd.damage2 = 0; - break; - case LK_SPIRALPIERCE: - case ML_SPIRALPIERCE: - if (sd) { - short index = sd->equip_index[EQI_HAND_R]; - - if (index >= 0 && - sd->inventory_data[index] && - sd->inventory_data[index]->type == IT_WEAPON) - wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight - } else - wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2 - - ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only. - i = sstatus->str/10; - i*=i; - ATK_ADD(i); //Add str bonus. - switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection? - case SZ_SMALL: //Small: 125% - ATK_RATE(125); - break; - //case SZ_MEDIUM: //Medium: 100% - case SZ_BIG: //Large: 75% - ATK_RATE(75); - break; - } - break; -#endif - case CR_SHIELDBOOMERANG: - case PA_SHIELDCHAIN: - case LG_SHIELDPRESS: - case LG_EARTHDRIVE: - wd.damage = sstatus->batk; - if (sd) { - short index = sd->equip_index[EQI_HAND_L]; - - if (index >= 0 && - sd->inventory_data[index] && - sd->inventory_data[index]->type == IT_ARMOR) - ATK_ADD(sd->inventory_data[index]->weight/10); - } else - ATK_ADD(sstatus->rhw.atk2); //Else use Atk2 - break; - case HFLI_SBR44: //[orn] - if(src->type == BL_HOM) { - wd.damage = ((TBL_HOM*)src)->homunculus.intimacy ; - break; - } - default: - { - i = (flag.cri?1:0)| - (flag.arrow?2:0)| - (skill_id == HW_MAGICCRASHER?4:0)| - (!skill_id && sc && sc->data[SC_CHANGE]?4:0)| - (skill_id == MO_EXTREMITYFIST?8:0)| - (sc && sc->data[SC_WEAPONPERFECTION]?8:0); - if (flag.arrow && sd) - switch(sd->status.weapon) { - case W_BOW: - case W_REVOLVER: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - break; - default: - i |= 16; // for ex. shuriken must not be influenced by DEX - } - wd.damage = battle->calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i); - if (flag.lh) - wd.damage2 = battle->calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i); - - if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets - if(wflag>0) - wd.damage/= wflag; - else - ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); - } - - //Add any bonuses that modify the base baseatk+watk (pre-skills) - if(sd) { - if (sd->bonus.atk_rate) - ATK_ADDRATE(sd->bonus.atk_rate); - - if(flag.cri && sd->bonus.crit_atk_rate) - ATK_ADDRATE(sd->bonus.crit_atk_rate); - - if(sd->status.party_id && (temp=pc->checkskill(sd,TK_POWER)) > 0){ - if( (i = party_foreachsamemap(party->sub_count, sd, 0)) > 1 ) // exclude the player himself [Inkfish] - ATK_ADDRATE(2*temp*i); - } - } - break; - } //End default case - } //End switch(skill_id) - - //Skill damage modifiers that stack linearly - if(sc && skill_id != PA_SACRIFICE) - { - if(sc->data[SC_OVERTHRUST]) - skillratio += sc->data[SC_OVERTHRUST]->val3; - if(sc->data[SC_MAXOVERTHRUST]) - skillratio += sc->data[SC_MAXOVERTHRUST]->val2; - if (sc->data[SC_BERSERK] || sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST]) - skillratio += 100; - if(sc->data[SC_ZENKAI] && sstatus->rhw.ele == sc->data[SC_ZENKAI]->val2 ) - skillratio += sc->data[SC_ZENKAI]->val1 * 2; - } - if( !skill_id ) - { - ATK_RATE(skillratio); - } - else - { + break; + case BF_WEAPON: switch( skill_id ) { case SM_BASH: case MS_BASH: - skillratio += 30*skill_lv; + skillratio += 30 * skill_lv; break; case SM_MAGNUM: case MS_MAGNUM: - skillratio += 20*skill_lv; + skillratio += 20 * skill_lv; break; case MC_MAMMONITE: - skillratio += 50*skill_lv; + skillratio += 50 * skill_lv; break; case HT_POWER: - skillratio += -50+8*sstatus->str; + skillratio += -50 + 8 * status_get_str(src); break; case AC_DOUBLE: case MA_DOUBLE: - skillratio += 10*(skill_lv-1); + skillratio += 10 * (skill_lv-1); break; case AC_SHOWER: case MA_SHOWER: #ifdef RENEWAL - skillratio += 50+10*skill_lv; + skillratio += 50 + 10 * skill_lv; #else - skillratio += -25+5*skill_lv; + skillratio += -25 + 5 * skill_lv; #endif break; case AC_CHARGEARROW: case MA_CHARGEARROW: skillratio += 50; break; -#ifndef RENEWAL + #ifndef RENEWAL case HT_FREEZINGTRAP: case MA_FREEZINGTRAP: - skillratio += -50+10*skill_lv; + skillratio += -50 + 10 * skill_lv; break; -#endif + #endif case KN_PIERCE: case ML_PIERCE: - skillratio += 10*skill_lv; + skillratio += 10 * skill_lv; break; case MER_CRASH: - skillratio += 10*skill_lv; + skillratio += 10 * skill_lv; break; case KN_SPEARSTAB: - skillratio += 15*skill_lv; + skillratio += 15 * skill_lv; break; case KN_SPEARBOOMERANG: skillratio += 50*skill_lv; @@ -2228,41 +1760,41 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case KN_BRANDISHSPEAR: case ML_BRANDISH: { - int ratio = 100+20*skill_lv; - skillratio += ratio-100; - if(skill_lv>3 && wflag==1) skillratio += ratio/2; - if(skill_lv>6 && wflag==1) skillratio += ratio/4; - if(skill_lv>9 && wflag==1) skillratio += ratio/8; - if(skill_lv>6 && wflag==2) skillratio += ratio/2; - if(skill_lv>9 && wflag==2) skillratio += ratio/4; - if(skill_lv>9 && wflag==3) skillratio += ratio/2; + int ratio = 100 + 20 * skill_lv; + skillratio += ratio - 100; + if(skill_lv>3 && flag==1) skillratio += ratio / 2; + if(skill_lv>6 && flag==1) skillratio += ratio / 4; + if(skill_lv>9 && flag==1) skillratio += ratio / 8; + if(skill_lv>6 && flag==2) skillratio += ratio / 2; + if(skill_lv>9 && flag==2) skillratio += ratio / 4; + if(skill_lv>9 && flag==3) skillratio += ratio / 2; break; } case KN_BOWLINGBASH: case MS_BOWLINGBASH: - skillratio+= 40*skill_lv; + skillratio+= 40 * skill_lv; break; case AS_GRIMTOOTH: - skillratio += 20*skill_lv; + skillratio += 20 * skill_lv; break; case AS_POISONREACT: - skillratio += 30*skill_lv; + skillratio += 30 * skill_lv; break; case AS_SONICBLOW: - skillratio += -50+5*skill_lv; + skillratio += -50 + 5 * skill_lv; break; case TF_SPRINKLESAND: skillratio += 30; break; case MC_CARTREVOLUTION: skillratio += 50; - if(sd && sd->cart_weight) - skillratio += 100*sd->cart_weight/sd->cart_weight_max; // +1% every 1% weight + if( sd && sd->cart_weight ) + skillratio += 100 * sd->cart_weight / sd->cart_weight_max; // +1% every 1% weight else if (!sd) skillratio += 100; //Max damage for non players. break; case NPC_RANDOMATTACK: - skillratio += 100*skill_lv; + skillratio += 100 * skill_lv; break; case NPC_WATERATTACK: case NPC_GROUNDATTACK: @@ -2281,30 +1813,30 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case NPC_THUNDERBREATH: case NPC_HELLJUDGEMENT: case NPC_PULSESTRIKE: - skillratio += 100*(skill_lv-1); + skillratio += 100 * (skill_lv-1); break; case RG_BACKSTAP: - if(sd && sd->status.weapon == W_BOW && battle_config.backstab_bow_penalty) - skillratio += (200+40*skill_lv)/2; + if( sd && sd->status.weapon == W_BOW && battle_config.backstab_bow_penalty ) + skillratio += (200 + 40 * skill_lv) / 2; else - skillratio += 200+40*skill_lv; + skillratio += 200 + 40 * skill_lv; break; case RG_RAID: - skillratio += 40*skill_lv; + skillratio += 40 * skill_lv; break; case RG_INTIMIDATE: - skillratio += 30*skill_lv; + skillratio += 30 * skill_lv; break; case CR_SHIELDCHARGE: - skillratio += 20*skill_lv; + skillratio += 20 * skill_lv; break; case CR_SHIELDBOOMERANG: - skillratio += 30*skill_lv; + skillratio += 30 * skill_lv; break; case NPC_DARKCROSS: case CR_HOLYCROSS: { - int ratio = 35*skill_lv; + int ratio = 35 * skill_lv; #ifdef RENEWAL if(sd && sd->status.weapon == W_2HSPEAR) ratio *= 2; @@ -2313,18 +1845,18 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list break; } case AM_DEMONSTRATION: - skillratio += 20*skill_lv; + skillratio += 20 * skill_lv; break; case AM_ACIDTERROR: - skillratio += 40*skill_lv; + skillratio += 40 * skill_lv; break; case MO_FINGEROFFENSIVE: skillratio+= 50 * skill_lv; break; case MO_INVESTIGATE: - skillratio += 75*skill_lv; - flag.pdef = flag.pdef2 = 2; + skillratio += 75 * skill_lv; break; + #ifndef RENEWAL case MO_EXTREMITYFIST: { //Overflow check. [Skotlex] unsigned int ratio = skillratio + 100*(8 + sstatus->sp/10); @@ -2333,76 +1865,63 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list skillratio = (unsigned short)ratio; } break; + #endif case MO_TRIPLEATTACK: - skillratio += 20*skill_lv; + skillratio += 20 * skill_lv; break; case MO_CHAINCOMBO: - skillratio += 50+50*skill_lv; + skillratio += 50 + 50 * skill_lv; break; case MO_COMBOFINISH: - skillratio += 140+60*skill_lv; + skillratio += 140 + 60 * skill_lv; break; case BA_MUSICALSTRIKE: case DC_THROWARROW: - skillratio += 25+25*skill_lv; + skillratio += 25 + 25 * skill_lv; break; case CH_TIGERFIST: - skillratio += 100*skill_lv-60; + skillratio += 100 * skill_lv - 60; break; case CH_CHAINCRUSH: - skillratio += 300+100*skill_lv; + skillratio += 300 + 100 * skill_lv; break; case CH_PALMSTRIKE: - skillratio += 100+100*skill_lv; + skillratio += 100 + 100 * skill_lv; break; case LK_HEADCRUSH: - skillratio += 40*skill_lv; + skillratio += 40 * skill_lv; break; case LK_JOINTBEAT: - i = 10*skill_lv-50; + i = 10 * skill_lv - 50; // Although not clear, it's being assumed that the 2x damage is only for the break neck ailment. - if (wflag&BREAK_NECK) i*=2; + if (flag&BREAK_NECK) i*=2; skillratio += i; break; -#ifdef RENEWAL - case LK_SPIRALPIERCE: - case ML_SPIRALPIERCE: - {// Formula: Floor[Floor(Weapon Weight/2)*skill level + ATK ]*(100%+50%*s.lvl) * 5 multi-hits - short index = sd?sd->equip_index[EQI_HAND_R]:0; - int weight = 0; - - if (sd && index >= 0 && - sd->inventory_data[index] && - sd->inventory_data[index]->type == IT_WEAPON) - weight = sd->inventory_data[index]->weight/20; - ATK_ADD(weight * skill_lv) - skillratio += 50*skill_lv; - } - break; -#endif case ASC_METEORASSAULT: - skillratio += 40*skill_lv-60; + skillratio += 40 * skill_lv - 60; break; case SN_SHARPSHOOTING: case MA_SHARPSHOOTING: - skillratio += 100+50*skill_lv; + skillratio += 100 + 50 * skill_lv; break; case CG_ARROWVULCAN: - skillratio += 100+100*skill_lv; + skillratio += 100 + 100 * skill_lv; break; case AS_SPLASHER: - skillratio += 400+50*skill_lv; + skillratio += 400 + 50 * skill_lv; if(sd) skillratio += 20 * pc->checkskill(sd,AS_POISONREACT); break; + #ifndef RENEWAL case ASC_BREAKER: skillratio += 100*skill_lv-100; break; + #endif case PA_SACRIFICE: - skillratio += 10*skill_lv-10; + skillratio += 10 * skill_lv - 10; break; case PA_SHIELDCHAIN: - skillratio += 30*skill_lv; + skillratio += 30 * skill_lv; break; case WS_CARTTERMINATION: i = 10 * (16 - skill_lv); @@ -2414,30 +1933,30 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list skillratio += 80000 / i - 100; break; case TK_DOWNKICK: - skillratio += 60 + 20*skill_lv; + skillratio += 60 + 20 * skill_lv; break; case TK_STORMKICK: - skillratio += 60 + 20*skill_lv; + skillratio += 60 + 20 * skill_lv; break; case TK_TURNKICK: - skillratio += 90 + 30*skill_lv; + skillratio += 90 + 30 * skill_lv; break; case TK_COUNTER: - skillratio += 90 + 30*skill_lv; + skillratio += 90 + 30 * skill_lv; break; case TK_JUMPKICK: skillratio += -70 + 10*skill_lv; - if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_id) - skillratio += 10*status_get_lv(src)/3; //Tumble bonus - if (wflag) + if (sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == skill_id) + skillratio += 10 * status_get_lv(src) / 3; //Tumble bonus + if (flag) { - skillratio += 10*status_get_lv(src)/3; //Running bonus (TODO: What is the real bonus?) - if( sc && sc->data[SC_SPURT] ) // Spurt bonus + skillratio += 10 * status_get_lv(src) / 3; //Running bonus (TODO: What is the real bonus?) + if( sc && sc->data[SC_STRUP] ) // Spurt bonus skillratio *= 2; } break; case GS_TRIPLEACTION: - skillratio += 50*skill_lv; + skillratio += 50 * skill_lv; break; case GS_BULLSEYE: //Only works well against brute/demihumans non bosses. @@ -2446,55 +1965,47 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list skillratio += 400; break; case GS_TRACKING: - skillratio += 100 *(skill_lv+1); + skillratio += 100 * (skill_lv+1); break; case GS_PIERCINGSHOT: - skillratio += 20*skill_lv; + skillratio += 20 * skill_lv; break; case GS_RAPIDSHOWER: - skillratio += 10*skill_lv; + skillratio += 10 * skill_lv; break; case GS_DESPERADO: - skillratio += 50*(skill_lv-1); + skillratio += 50 * (skill_lv-1); break; case GS_DUST: - skillratio += 50*skill_lv; + skillratio += 50 * skill_lv; break; case GS_FULLBUSTER: - skillratio += 100*(skill_lv+2); + skillratio += 100 * (skill_lv+2); break; case GS_SPREADATTACK: #ifdef RENEWAL - skillratio += 20*(skill_lv); + skillratio += 20 * (skill_lv); #else - skillratio += 20*(skill_lv-1); + skillratio += 20 * (skill_lv-1); #endif break; -#ifdef RENEWAL - case NJ_ISSEN: - skillratio += 100 * (skill_lv-1); - break; -#endif case NJ_HUUMA: - skillratio += 50 + 150*skill_lv; + skillratio += 50 + 150 * skill_lv; break; case NJ_TATAMIGAESHI: -#ifdef RENEWAL - ATK_RATE(200); -#endif - skillratio += 10*skill_lv; + skillratio += 10 * skill_lv; break; case NJ_KASUMIKIRI: - skillratio += 10*skill_lv; + skillratio += 10 * skill_lv; break; case NJ_KIRIKAGE: - skillratio += 100*(skill_lv-1); + skillratio += 100 * (skill_lv-1); break; case KN_CHARGEATK: { - int k = (wflag-1)/3; //+100% every 3 cells of distance - if( k > 2 ) k = 2; // ...but hard-limited to 300%. - skillratio += 100 * k; + int k = (flag-1)/3; //+100% every 3 cells of distance + if( k > 2 ) k = 2; // ...but hard-limited to 300%. + skillratio += 100 * k; } break; case HT_PHANTASMIC: @@ -2504,66 +2015,63 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list skillratio += 200; break; case HFLI_MOON: //[orn] - skillratio += 10+110*skill_lv; + skillratio += 10 + 110 * skill_lv; break; case HFLI_SBR44: //[orn] - skillratio += 100 *(skill_lv-1); + skillratio += 100 * (skill_lv-1); break; case NPC_VAMPIRE_GIFT: - skillratio += ((skill_lv-1)%5+1)*100; + skillratio += ((skill_lv-1)%5+1) * 100; break; case RK_SONICWAVE: - skillratio += 400 + 100 * skill_lv; - RE_LVL_DMOD(100); + skillratio += -100 + 100 * (skill_lv + 5); + skillratio = skillratio * (100 + (status_get_lv(src)-100) / 2) / 100; break; case RK_HUNDREDSPEAR: skillratio += 500 + (80 * skill_lv); - if( sd ) - { + if( sd ){ short index = sd->equip_index[EQI_HAND_R]; if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON ) - skillratio += max(10000 - sd->inventory_data[index]->weight, 0) / 10; - skillratio += 50 * pc->checkskill(sd,LK_SPIRALPIERCE); - } // (1 + [(Casters Base Level - 100) / 200]) - skillratio = skillratio * (100 + (status_get_lv(src)-100) / 2) / 100; + skillratio += (10000 - min(10000, sd->inventory_data[index]->weight)) / 10; + skillratio = skillratio * (100 + (status_get_lv(src)-100) / 2) / 100 + 50 * pc->checkskill(sd,LK_SPIRALPIERCE); + } break; case RK_WINDCUTTER: - skillratio += 50 * skill_lv; + skillratio += -100 + 50 * (skill_lv + 2); RE_LVL_DMOD(100); break; case RK_IGNITIONBREAK: i = distance_bl(src,target); if( i < 2 ) - skillratio = 200 + 200 * skill_lv; + skillratio += 300 * skill_lv; else if( i < 4 ) - skillratio = 100 + 200 * skill_lv; + skillratio += 250 * skill_lv; else - skillratio = 100 + 100 * skill_lv; - RE_LVL_DMOD(100); - if( sstatus->rhw.ele == ELE_FIRE ) - skillratio += skillratio / 2; + skillratio += 200 * skill_lv; + skillratio = (skillratio - 100) * (100 + (status_get_lv(src)-100)) / 100; + if( status->rhw.ele == ELE_FIRE ) + skillratio += 100 * skill_lv; break; case RK_CRUSHSTRIKE: if( sd ) {//ATK [{Weapon Level * (Weapon Upgrade Level + 6) * 100} + (Weapon ATK) + (Weapon Weight)]% short index = sd->equip_index[EQI_HAND_R]; if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON ) - skillratio = sd->inventory_data[index]->weight/10 + sstatus->rhw.atk + + skillratio += -100 + sd->inventory_data[index]->weight/10 + status->rhw.atk + 100 * sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6); } break; case RK_STORMBLAST: - skillratio = 100 * (sd ? pc->checkskill(sd,RK_RUNEMASTERY) : 1) + 100 * (sstatus->int_ / 4); + skillratio += -100 + 100 * (sd ? pc->checkskill(sd,RK_RUNEMASTERY) : 1) + 100 * (status_get_int(src) / 4); break; case RK_PHANTOMTHRUST: - skillratio = 50 * skill_lv + 10 * ( sd ? pc->checkskill(sd,KN_SPEARMASTERY) : 10); - //if( s_level > 100 ) skillratio += skillratio * s_level / 150; // Base level bonus. This is official, but is disabled until I can confirm something with was changed or not. [Rytech] - //if( s_level > 100 ) skillratio += skillratio * (s_level - 100) / 200; // Base level bonus. + skillratio += -100 + 50 * skill_lv + 10 * ( sd ? pc->checkskill(sd,KN_SPEARMASTERY) : 10); + RE_LVL_DMOD(150); break; /** - * GC Guilotine Cross - **/ + * GC Guilotine Cross + **/ case GC_CROSSIMPACT: skillratio += 900 + 100 * skill_lv; RE_LVL_DMOD(120); @@ -2575,7 +2083,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list //ATK [{(Skill Level x 100) + 300} x Caster's Base Level / 120]% + ATK [(AGI x 2) + (Caster's Job Level x 4)]% skillratio += 200 + (100 * skill_lv); RE_LVL_DMOD(120); - skillratio += sstatus->agi + (sd?sd->status.job_level:0) * 4; + skillratio += status_get_agi(src) * 2 + (sd?sd->status.job_level:0) * 4; break; case GC_ROLLINGCUTTER: skillratio += -50 + 50 * skill_lv; @@ -2585,17 +2093,20 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list skillratio += 300 + 80 * skill_lv; RE_LVL_DMOD(100); if( sc && sc->data[SC_ROLLINGCUTTER] ) - skillratio += sc->data[SC_ROLLINGCUTTER]->val1 * sstatus->agi; + skillratio += sc->data[SC_ROLLINGCUTTER]->val1 * status_get_agi(src); + break; + case GC_DARKCROW: + skillratio += 100 * (skill_lv - 1); break; /** - * Arch Bishop - **/ + * Arch Bishop + **/ case AB_DUPLELIGHT_MELEE: skillratio += 10 * skill_lv; break; /** - * Ranger - **/ + * Ranger + **/ case RA_ARROWSTORM: skillratio += 900 + 80 * skill_lv; RE_LVL_DMOD(100); @@ -2603,8 +2114,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case RA_AIMEDBOLT: skillratio += 400 + 50 * skill_lv; RE_LVL_DMOD(100); - if( tsc && (tsc->data[SC_BITE] || tsc->data[SC_ANKLE] || tsc->data[SC_ELECTRICSHOCKER]) ) - wd.div_ = tstatus->size + 2 + ( (rnd()%100 < 50-tstatus->size*10) ? 1 : 0 ); break; case RA_CLUSTERBOMB: skillratio += 100 + 100 * skill_lv; @@ -2613,7 +2122,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list skillratio += 200; break; case RA_WUGSTRIKE: - skillratio = 200 * skill_lv; + skillratio += -100 + 200 * skill_lv; break; case RA_WUGBITE: skillratio += 300 + 200 * skill_lv; @@ -2623,18 +2132,18 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list skillratio += 50 * skill_lv; break; /** - * Mechanic - **/ + * Mechanic + **/ case NC_BOOSTKNUCKLE: - skillratio += 100 + 100 * skill_lv + sstatus->dex; + skillratio += 100 + 100 * skill_lv + status_get_dex(src); RE_LVL_DMOD(100); break; case NC_PILEBUNKER: - skillratio += 200 + 100 * skill_lv + sstatus->str; + skillratio += 200 + 100 * skill_lv + status_get_str(src); RE_LVL_DMOD(100); break; case NC_VULCANARM: - skillratio = 70 * skill_lv + sstatus->dex; + skillratio += -100 + 70 * skill_lv + status_get_dex(src); RE_LVL_DMOD(100); break; case NC_FLAMELAUNCHER: @@ -2661,11 +2170,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list RE_LVL_DMOD(100); break; case NC_POWERSWING: - skillratio += 80 + 20 * skill_lv + sstatus->str + sstatus->dex; + skillratio += 80 + 20 * skill_lv + status_get_str(src) + status_get_dex(src); RE_LVL_DMOD(100); break; case NC_AXETORNADO: - skillratio += 100 + 100 * skill_lv + sstatus->vit; + skillratio += 100 + 100 * skill_lv + status_get_vit(src); RE_LVL_DMOD(100); break; case SC_FATALMENACE: @@ -2678,7 +2187,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list skillratio += 100 + 100 * skill_lv; break; case LG_CANNONSPEAR:// Stimated formula. Still need confirm it. - skillratio += -100 + (50 + sstatus->str) * skill_lv; + skillratio += -100 + (50 + status_get_str(src)) * skill_lv; RE_LVL_DMOD(100); break; case LG_BANISHINGPOINT: @@ -2690,7 +2199,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list RE_LVL_DMOD(100); break; case LG_PINPOINTATTACK: - skillratio = ((100 * skill_lv) + (10 * status_get_agi(src)) ); + skillratio += -100 + ((100 * skill_lv) + (10 * status_get_agi(src)) ); RE_LVL_DMOD(100); break; case LG_RAGEBURST: @@ -2703,7 +2212,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield DEF x 10) + (Casters VIT x 2)] % if( sd ) { struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; - skillratio = status_get_lv(src) * 4 + status_get_vit(src) * 2; + skillratio += -100 + status_get_lv(src) * 4 + status_get_vit(src) * 2; if( shield_data ) skillratio += shield_data->def * 10; } else @@ -2714,668 +2223,1563 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list RE_LVL_DMOD(100); break; case LG_OVERBRAND: - skillratio = 400 * skill_lv + (pc->checkskill(sd,CR_SPEARQUICKEN) * 30); + skillratio += -100 + 400 * skill_lv + (pc->checkskill(sd,CR_SPEARQUICKEN) * 30); RE_LVL_DMOD(100); break; case LG_OVERBRAND_BRANDISH: - skillratio = 300 * skill_lv + (2 * (sstatus->str + sstatus->dex) / 3); + skillratio += -100 + 300 * skill_lv + (2 * (status_get_str(src) + status_get_dex(src)) / 3); RE_LVL_DMOD(100); break; case LG_OVERBRAND_PLUSATK: - skillratio = 150 * skill_lv; + skillratio += -100 + 150 * skill_lv; + RE_LVL_DMOD(100); + break; + case LG_RAYOFGENESIS: + skillratio += 200 + 300 * skill_lv; + RE_LVL_DMOD(100); + break; + case LG_EARTHDRIVE: + skillratio = (skillratio + 100) * skill_lv; + RE_LVL_DMOD(100); + break; + case LG_HESPERUSLIT: + skillratio += 120 * skill_lv - 100; + break; + case SR_DRAGONCOMBO: + skillratio += 40 * skill_lv; + RE_LVL_DMOD(100); + break; + case SR_SKYNETBLOW: + if( sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_DRAGONCOMBO )//ATK [{(Skill Level x 100) + (Caster AGI) + 150} x Caster Base Level / 100] % + skillratio += 100 * skill_lv + status_get_agi(src) + 50; + else //ATK [{(Skill Level x 80) + (Caster AGI)} x Caster Base Level / 100] % + skillratio += -100 + 80 * skill_lv + status_get_agi(src); + RE_LVL_DMOD(100); + break; + case SR_EARTHSHAKER: + if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || // [(Skill Level x 150) x (Caster Base Level / 100) + (Caster INT x 3)] % + tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || tsc->data[SC__INVISIBILITY]) ){ + skillratio += -100 + 150 * skill_lv; + RE_LVL_DMOD(100); + skillratio += status_get_int(src) * 3; + }else{ //[(Skill Level x 50) x (Caster Base Level / 100) + (Caster INT x 2)] % + skillratio += 50 * (skill_lv-2); + RE_LVL_DMOD(100); + skillratio += status_get_int(src) * 2; + } + break; + case SR_FALLENEMPIRE:// ATK [(Skill Level x 150 + 100) x Caster Base Level / 150] % + skillratio += 150 *skill_lv; + RE_LVL_DMOD(150); + break; + case SR_TIGERCANNON:// ATK [((Caster consumed HP + SP) / 4) x Caster Base Level / 100] % + { + int hp = status_get_max_hp(src) * (10 + 2 * skill_lv) / 100, + sp = status_get_max_sp(src) * (6 + skill_lv) / 100; + if( sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE ) // ATK [((Caster consumed HP + SP) / 2) x Caster Base Level / 100] % + skillratio += -100 + hp+sp / 2; + else + skillratio += -100 + (hp+sp) / 4; + RE_LVL_DMOD(100); + } + break; + case SR_RAMPAGEBLASTER: + skillratio += 20 * skill_lv * (sd?sd->spiritball_old:5) - 100; + if( sc && sc->data[SC_EXPLOSIONSPIRITS] ){ + skillratio += sc->data[SC_EXPLOSIONSPIRITS]->val1 * 20; + RE_LVL_DMOD(120); + }else + RE_LVL_DMOD(150); + break; + case SR_KNUCKLEARROW: + if( flag&4 ){ // ATK [(Skill Level x 150) + (1000 x Target current weight / Maximum weight) + (Target Base Level x 5) x (Caster Base Level / 150)] % + skillratio += -100 + 150 * skill_lv + status_get_lv(target) * 5 * (status_get_lv(src) / 100) ; + if( tsd && tsd->weight ) + skillratio += 100 * (tsd->weight / tsd->max_weight); + }else // ATK [(Skill Level x 100 + 500) x Caster Base Level / 100] % + skillratio += 400 + (100 * skill_lv); + RE_LVL_DMOD(100); + break; + case SR_WINDMILL: // ATK [(Caster Base Level + Caster DEX) x Caster Base Level / 100] % + skillratio += -100 + status_get_lv(src) + status_get_dex(src); + RE_LVL_DMOD(100); + break; + case SR_GATEOFHELL: + if( sc && sc->data[SC_COMBOATTACK] + && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE ) + skillratio += 800 * skill_lv -100; + else + skillratio += 500 * skill_lv -100; + RE_LVL_DMOD(100); + break; + case SR_GENTLETOUCH_QUIET: + skillratio += 100 * skill_lv - 100 + status_get_dex(src); + RE_LVL_DMOD(100); + break; + case SR_HOWLINGOFLION: + skillratio += 300 * skill_lv - 100; + RE_LVL_DMOD(150); + break; + case SR_RIDEINLIGHTNING: // ATK [{(Skill Level x 200) + Additional Damage} x Caster Base Level / 100] % + if( (status->rhw.ele) == ELE_WIND || (status->lhw.ele) == ELE_WIND ) + skillratio += skill_lv * 50; + skillratio += -100 + 200 * skill_lv; + RE_LVL_DMOD(100); + break; + case WM_REVERBERATION_MELEE: + // ATK [{(Skill Level x 100) + 300} x Caster Base Level / 100] + skillratio += 200 + 100 * pc->checkskill(sd, WM_REVERBERATION); RE_LVL_DMOD(100); break; - case LG_RAYOFGENESIS: - skillratio = 300 + 300 * skill_lv; + case WM_SEVERE_RAINSTORM_MELEE: + //ATK [{(Caster DEX + AGI) x (Skill Level / 5)} x Caster Base Level / 100] % + skillratio += -100 + (status_get_dex(src) + status_get_agi(src)) * (skill_lv * 2); + RE_LVL_DMOD(100); + skillratio /= 10; + break; + case WM_GREAT_ECHO: + skillratio += 800 + 100 * skill_lv; + if( sd ) { // Still need official value [pakpil] + short lv = (short)skill_lv; + skillratio += 100 * skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),0); + } + break; + case WM_SOUND_OF_DESTRUCTION: + skillratio += 400; + break; + case GN_CART_TORNADO: + // ATK [( Skill Level x 50 ) + ( Cart Weight / ( 150 - Caster Base STR ))] + ( Cart Remodeling Skill Level x 50 )] % + skillratio += -100 + 50 * skill_lv; + if( sd && sd->cart_weight) + skillratio += sd->cart_weight/10 / max(150-status_get_str(src),1) + pc->checkskill(sd, GN_REMODELING_CART) * 50; + break; + case GN_CARTCANNON: + // ATK [{( Cart Remodeling Skill Level x 50 ) x ( INT / 40 )} + ( Cart Cannon Skill Level x 60 )] % + skillratio += -100 + 60 * skill_lv; + if( sd ) skillratio += pc->checkskill(sd, GN_REMODELING_CART) * 50 * (status_get_int(src) / 40); + break; + case GN_SPORE_EXPLOSION: + skillratio += 200 + 100 * skill_lv; + break; + case GN_CRAZYWEED_ATK: + skillratio += 400 + 100 * skill_lv; + break; + case GN_SLINGITEM_RANGEMELEEATK: + if( sd ) { + switch( sd->itemid ) { + case 13260: // Apple Bomob + case 13261: // Coconut Bomb + case 13262: // Melon Bomb + case 13263: // Pinapple Bomb + skillratio += 400; // Unconfirded + break; + case 13264: // Banana Bomb 2000% + skillratio += 1900; + break; + case 13265: skillratio -= 75; break; // Black Lump 25% + case 13266: skillratio -= 25; break; // Hard Black Lump 75% + case 13267: skillratio += 100; break; // Extremely Hard Black Lump 200% + } + } else + skillratio += 300; // Bombs + break; + case SO_VARETYR_SPEAR://ATK [{( Striking Level x 50 ) + ( Varetyr Spear Skill Level x 50 )} x Caster Base Level / 100 ] % + skillratio += -100 + 50 * skill_lv + ( sd ? pc->checkskill(sd, SO_STRIKING) * 50 : 0 ); + if( sc && sc->data[SC_BLAST_OPTION] ) + skillratio += sd ? sd->status.job_level * 5 : 0; + break; + // Physical Elemantal Spirits Attack Skills + case EL_CIRCLE_OF_FIRE: + case EL_FIRE_BOMB_ATK: + case EL_STONE_RAIN: + skillratio += 200; + break; + case EL_FIRE_WAVE_ATK: + skillratio += 500; + break; + case EL_TIDAL_WEAPON: + skillratio += 1400; + break; + case EL_WIND_SLASH: + skillratio += 100; + break; + case EL_HURRICANE: + skillratio += 600; + break; + case EL_TYPOON_MIS: + case EL_WATER_SCREW_ATK: + skillratio += 900; + break; + case EL_STONE_HAMMER: + skillratio += 400; + break; + case EL_ROCK_CRUSHER: + skillratio += 700; + break; + case KO_JYUMONJIKIRI: + skillratio += -100 + 150 * skill_lv; + RE_LVL_DMOD(120); + if( tsc && tsc->data[SC_KO_JYUMONJIKIRI] ) + skillratio += status_get_lv(src) * skill_lv; + case KO_HUUMARANKA: + skillratio += -100 + 150 * skill_lv + status_get_agi(src) + status_get_dex(src) + 100 * (sd ? pc->checkskill(sd, NJ_HUUMA) : 0); + break; + case KO_SETSUDAN: + skillratio += -100 + 100 * skill_lv; RE_LVL_DMOD(100); break; - case LG_EARTHDRIVE: - skillratio = (skillratio + 100) * skill_lv; - RE_LVL_DMOD(100); + case KO_BAKURETSU: + skillratio += -100 + (50 + status_get_dex(src) / 4) * skill_lv * (sd?pc->checkskill(sd,NJ_TOBIDOUGU):10) * 4 / 100; + RE_LVL_DMOD(120); + skillratio += 10 * (sd ? sd->status.job_level : 0); break; - case LG_HESPERUSLIT: - skillratio += 120 * skill_lv - 100; + case MH_NEEDLE_OF_PARALYZE: + skillratio += 600 + 100 * skill_lv; break; - case SR_DRAGONCOMBO: - skillratio += 40 * skill_lv; - RE_LVL_DMOD(100); + case MH_STAHL_HORN: + skillratio += 400 + 100 * skill_lv; break; - case SR_SKYNETBLOW: - //ATK [{(Skill Level x 80) + (Caster AGI)} x Caster Base Level / 100] % - skillratio = 80 * skill_lv + sstatus->agi; - if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_DRAGONCOMBO )//ATK [{(Skill Level x 100) + (Caster AGI) + 150} x Caster Base Level / 100] % - skillratio = 100 * skill_lv + sstatus->agi + 150; - RE_LVL_DMOD(100); + case MH_LAVA_SLIDE: + skillratio += -100 + 70 * skill_lv; break; - case SR_EARTHSHAKER: - if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || // [(Skill Level x 150) x (Caster Base Level / 100) + (Caster INT x 3)] % - tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || tsc->data[SC__INVISIBILITY]) ){ - skillratio = 150 * skill_lv; - RE_LVL_DMOD(100); - skillratio += sstatus->int_ * 3; - }else{ //[(Skill Level x 50) x (Caster Base Level / 100) + (Caster INT x 2)] % - skillratio += 50 * (skill_lv-2); - RE_LVL_DMOD(100); - skillratio += sstatus->int_ * 2; - } + case MH_TINDER_BREAKER: + case MH_MAGMA_FLOW: + skillratio += -100 + 100 * skill_lv; break; - case SR_FALLENEMPIRE:// ATK [(Skill Level x 150 + 100) x Caster Base Level / 150] % - skillratio += 150 *skill_lv; - RE_LVL_DMOD(150); - break; - case SR_TIGERCANNON:// ATK [((Caster consumed HP + SP) / 4) x Caster Base Level / 100] % - { - int hp = sstatus->max_hp * (10 + 2 * skill_lv) / 100, - sp = sstatus->max_sp * (6 + skill_lv) / 100; - skillratio = (hp+sp) / 4; - if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) // ATK [((Caster consumed HP + SP) / 2) x Caster Base Level / 100] % - skillratio = hp+sp / 2; - RE_LVL_DMOD(100); + } + if( sc && sc->data[SC_EDP] ){ + skillratio -= addedratio; + if( skill_id == AS_SONICBLOW || + skill_id == GC_COUNTERSLASH || + skill_id == GC_CROSSIMPACT ) + skillratio >>= 1; + skillratio += addedratio; + } + } + if( skillratio < 1 ) + return 0; + return skillratio; +} +/*========================================== + * Check dammage trough status. + * ATK may be MISS, BLOCKED FAIL, reduc, increase, end status... + * After this we apply bg/gvg reduction + *------------------------------------------*/ +int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int damage,uint16 skill_id,uint16 skill_lv) +{ + struct map_session_data *sd = NULL; + struct status_change *sc; + struct status_change_entry *sce; + int div_ = d->div_, flag = d->flag; + + nullpo_ret(bl); + + if( !damage ) + return 0; + if( battle_config.ksprotection && mob_ksprotected(src, bl) ) + return 0; + + if (bl->type == BL_PC) { + sd=(struct map_session_data *)bl; + //Special no damage states + if(flag&BF_WEAPON && sd->special_state.no_weapon_damage) + damage -= damage * sd->special_state.no_weapon_damage / 100; + + if(flag&BF_MAGIC && sd->special_state.no_magic_damage) + damage -= damage * sd->special_state.no_magic_damage / 100; + + if(flag&BF_MISC && sd->special_state.no_misc_damage) + damage -= damage * sd->special_state.no_misc_damage / 100; + + if(!damage) return 0; + } + + sc = status_get_sc(bl); + + if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) + return 1; + + if (skill_id == PA_PRESSURE) + return damage; //This skill bypass everything else. + + if( sc && sc->count ) + { + //First, sc_*'s that reduce damage to 0. + if( sc->data[SC_BASILICA] && !(status_get_mode(src)&MD_BOSS) ) + { + d->dmg_lv = ATK_BLOCK; + return 0; + } + if( sc->data[SC_WHITEIMPRISON] && skill_id != HW_GRAVITATION ) { // Gravitation and Pressure do damage without removing the effect + if( skill_id == MG_NAPALMBEAT || + skill_id == MG_SOULSTRIKE || + skill_id == WL_SOULEXPANSION || + (skill_id && skill->get_ele(skill_id, skill_lv) == ELE_GHOST) || + (!skill_id && (status_get_status_data(src))->rhw.ele == ELE_GHOST) + ){ + if( skill_id == WL_SOULEXPANSION ) + damage <<= 1; // If used against a player in White Imprison, the skill deals double damage. + status_change_end(bl,SC_WHITEIMPRISON,INVALID_TIMER); // Those skills do damage and removes effect + }else{ + d->dmg_lv = ATK_BLOCK; + return 0; + } + } + + if(sc->data[SC_ZEPHYR] && + flag&(BF_LONG|BF_SHORT)){ + d->dmg_lv = ATK_BLOCK; + return 0; + } + + if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) + { + struct skill_unit_group* group = skill->id2group(sc->data[SC_SAFETYWALL]->val3); + uint16 skill_id = sc->data[SC_SAFETYWALL]->val2; + if (group) { + if(skill_id == MH_STEINWAND){ + if (--group->val2<=0) + skill->del_unitgroup(group,ALC_MARK); + d->dmg_lv = ATK_BLOCK; + return 0; + } + /** + * in RE, SW possesses a lifetime equal to 3 times the caster's health + **/ + #ifdef RENEWAL + d->dmg_lv = ATK_BLOCK; + if ( ( group->val2 - damage) > 0 ) { + group->val2 -= damage; + } else + skill->del_unitgroup(group,ALC_MARK); + return 0; + #else + if (--group->val2<=0) + skill->del_unitgroup(group,ALC_MARK); + d->dmg_lv = ATK_BLOCK; + return 0; + #endif + } + status_change_end(bl, SC_SAFETYWALL, INVALID_TIMER); + } + + if( ( sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG ) || sc->data[SC__MANHOLE] ) { + d->dmg_lv = ATK_BLOCK; + return 0; + } + if( sc->data[SC_WEAPONBLOCKING] && flag&(BF_SHORT|BF_WEAPON) && rnd()%100 < sc->data[SC_WEAPONBLOCKING]->val2 ) + { + clif->skill_nodamage(bl,src,GC_WEAPONBLOCKING,1,1); + d->dmg_lv = ATK_BLOCK; + sc_start2(bl,SC_COMBOATTACK,100,GC_WEAPONBLOCKING,src->id,2000); + return 0; + } + if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2 ) + { + int delay; + clif->skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1); + // different delay depending on skill level [celest] + if (sce->val1 <= 5) + delay = 300; + else if (sce->val1 > 5 && sce->val1 <= 9) + delay = 200; + else + delay = 100; + unit_set_walkdelay(bl, iTimer->gettick(), delay, 1); + + if(sc->data[SC_CR_SHRINK] && rnd()%100<5*sce->val1) + skill->blown(bl,src,skill->get_blewcount(CR_SHRINK,1),-1,0); + return 0; + } + + if( (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 ) { + clif->skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1); + sce->val3 -= damage; // absorb damage + d->dmg_lv = ATK_BLOCK; + sc_start(bl,SC_STUN,15,0,skill->get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken. + if( sce->val3 <= 0 ) { // Shield Down + sce->val2--; + if( sce->val2 > 0 ) { + if( sd ) + clif->millenniumshield(sd,sce->val2); + sce->val3 = 1000; // Next Shield + } else + status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down + } + return 0; + } + + + if( (sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON && skill_id != WS_CARTTERMINATION && rnd()%100 < sce->val2 ) + { // attack blocked by Parrying + clif->skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1); + return 0; + } + + if(sc->data[SC_DODGE_READY] && ( !sc->opt1 || sc->opt1 == OPT1_BURNING ) && + (flag&BF_LONG || sc->data[SC_STRUP]) + && rnd()%100 < 20) { + if (sd && pc_issit(sd)) pc->setstand(sd); //Stand it to dodge. + clif->skill_nodamage(bl,bl,TK_DODGE,1,1); + if (!sc->data[SC_COMBOATTACK]) + sc_start4(bl, SC_COMBOATTACK, 100, TK_JUMPKICK, src->id, 1, 0, 2000); + return 0; + } + + if(sc->data[SC_HERMODE] && flag&BF_MAGIC) + return 0; + + if(sc->data[SC_NJ_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG) + return 0; + + if( sc->data[SC_NEUTRALBARRIER] && (flag&(BF_MAGIC|BF_LONG)) == (BF_MAGIC|BF_LONG) ) { + d->dmg_lv = ATK_MISS; + return 0; + } + + if((sce=sc->data[SC_KAUPE]) && rnd()%100 < sce->val2) + { //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries. + clif->specialeffect(bl, 462, AREA); + //Shouldn't end until Breaker's non-weapon part connects. + if (skill_id != ASC_BREAKER || !(flag&BF_WEAPON)) + if (--(sce->val3) <= 0) //We make it work like Safety Wall, even though it only blocks 1 time. + status_change_end(bl, SC_KAUPE, INVALID_TIMER); + return 0; + } + + if( flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) && rnd()%100 < sce->val2) { + clif->specialeffect(bl, 462, AREA); // Still need confirm it. + return 0; + } + + if (((sce=sc->data[SC_NJ_UTSUSEMI]) || sc->data[SC_NJ_BUNSINJYUTSU]) + && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK)) { + + skill->additional_effect (src, bl, skill_id, skill_lv, flag, ATK_BLOCK, iTimer->gettick() ); + if( !status_isdead(src) ) + skill->counter_additional_effect( src, bl, skill_id, skill_lv, flag, iTimer->gettick() ); + if (sce) { + clif->specialeffect(bl, 462, AREA); + skill->blown(src,bl,sce->val3,-1,0); + } + //Both need to be consumed if they are active. + if (sce && --(sce->val2) <= 0) + status_change_end(bl, SC_NJ_UTSUSEMI, INVALID_TIMER); + if ((sce=sc->data[SC_NJ_BUNSINJYUTSU]) && --(sce->val2) <= 0) + status_change_end(bl, SC_NJ_BUNSINJYUTSU, INVALID_TIMER); + + return 0; + } + + //Now damage increasing effects + if( sc->data[SC_LEXAETERNA] && skill_id != PF_SOULBURN ) + { + if( src->type != BL_MER || skill_id == 0 ) + damage <<= 1; // Lex Aeterna only doubles damage of regular attacks from mercenaries + + if( skill_id != ASC_BREAKER || !(flag&BF_WEAPON) ) + status_change_end(bl, SC_LEXAETERNA, INVALID_TIMER); //Shouldn't end until Breaker's non-weapon part connects. + } + +#ifdef RENEWAL + if( sc->data[SC_RAID] ) { + damage += damage * 20 / 100; + + if (--sc->data[SC_RAID]->val1 == 0) + status_change_end(bl, SC_RAID, INVALID_TIMER); + } +#endif + + if( damage ) { + struct map_session_data *tsd = BL_CAST(BL_PC, src); + if( sc->data[SC_DEEP_SLEEP] ) { + damage += damage / 2; // 1.5 times more damage while in Deep Sleep. + status_change_end(bl,SC_DEEP_SLEEP,INVALID_TIMER); + } + if( tsd && sd && sc->data[SC_CRYSTALIZE] && flag&BF_WEAPON ){ + switch(tsd->status.weapon){ + case W_MACE: + case W_2HMACE: + case W_1HAXE: + case W_2HAXE: + damage = damage * 150/100; + break; + case W_MUSICAL: + case W_WHIP: + if(!sd->state.arrow_atk) + break; + case W_BOW: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + case W_DAGGER: + case W_1HSWORD: + case W_2HSWORD: + damage = damage * 50/100; + break; + } + } + if( sc->data[SC_SIREN] ) + status_change_end(bl,SC_SIREN,INVALID_TIMER); + } + + //Finally damage reductions.... + // Assumptio doubles the def & mdef on RE mode, otherwise gives a reduction on the final damage. [Igniz] +#ifndef RENEWAL + if( sc->data[SC_ASSUMPTIO] ) { + if( map_flag_vs(bl->m) ) + damage = damage*2/3; //Receive 66% damage + else + damage >>= 1; //Receive 50% damage + } +#endif + + if(sc->data[SC_DEFENDER] && + (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) + damage = damage * ( 100 - sc->data[SC_DEFENDER]->val2 ) / 100; + + if(sc->data[SC_GS_ADJUSTMENT] && + (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) + damage -= damage * 20 / 100; + + if(sc->data[SC_FOGWALL] && skill_id != RK_DRAGONBREATH && skill_id != RK_DRAGONBREATH_WATER) { + if(flag&BF_SKILL) //25% reduction + damage -= damage * 25 / 100; + else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) + damage >>= 2; //75% reduction + } + + // Compressed code, fixed by map.h [Epoque] + if (src->type == BL_MOB) { + int i; + if (sc->data[SC_MANU_DEF]) + for (i=0;ARRAYLENGTH(mob_manuk)>i;i++) + if (mob_manuk[i]==((TBL_MOB*)src)->class_) { + damage -= damage * sc->data[SC_MANU_DEF]->val1 / 100; + break; } + if (sc->data[SC_SPL_DEF]) + for (i=0;ARRAYLENGTH(mob_splendide)>i;i++) + if (mob_splendide[i]==((TBL_MOB*)src)->class_) { + damage -= damage * sc->data[SC_SPL_DEF]->val1 / 100; + break; + } + } + + if((sce=sc->data[SC_ARMOR]) && //NPC_DEFENDER + sce->val3&flag && sce->val4&flag) + damage -= damage * sc->data[SC_ARMOR]->val2 / 100; + +#ifdef RENEWAL + if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON || flag&BF_MAGIC) && skill_id != WS_CARTTERMINATION) +#else + if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON && skill_id != WS_CARTTERMINATION)) +#endif + { + struct status_data *status = status_get_status_data(bl); + int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval + per /=20; //Uses 20% SP intervals. + //SP Cost: 1% + 0.5% per every 20% SP + if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000)) + status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER); + //Reduction: 6% + 6% every 20% + damage -= damage * (6 * (1+per)) / 100; + } + if(sc->data[SC_GRANITIC_ARMOR]){ + damage -= damage * sc->data[SC_GRANITIC_ARMOR]->val2 / 100; + } + if(sc->data[SC_PAIN_KILLER]){ + damage -= damage * sc->data[SC_PAIN_KILLER]->val3 / 100; + } + if((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ){ + skill->castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,iTimer->gettick(),0); + } + + if( (sce = sc->data[SC_STONEHARDSKIN]) && flag&(BF_SHORT|BF_WEAPON) && damage > 0 ) { + sce->val2 -= damage; + if( src->type == BL_PC ) { + TBL_PC *ssd = BL_CAST(BL_PC, src); + if (ssd && ssd->status.weapon != W_BOW) + skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF); + } else + skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF); + // 30% chance to reduce monster's ATK by 25% for 10 seconds. + if( src->type == BL_MOB ) + sc_start(src, SC_NOEQUIPWEAPON, 30, 0, skill->get_time2(RK_STONEHARDSKIN, sce->val1)); + if( sce->val2 <= 0 ) + status_change_end(bl, SC_STONEHARDSKIN, INVALID_TIMER); + } + +/** + * In renewal steel body reduces all incoming damage by 1/10 + **/ +#ifdef RENEWAL + if( sc->data[SC_STEELBODY] ) { + damage = damage > 10 ? damage / 10 : 1; + } +#endif + + //Finally added to remove the status of immobile when aimedbolt is used. [Jobbie] + if( skill_id == RA_AIMEDBOLT && (sc->data[SC_WUGBITE] || sc->data[SC_ANKLESNARE] || sc->data[SC_ELECTRICSHOCKER]) ) + { + status_change_end(bl, SC_WUGBITE, INVALID_TIMER); + status_change_end(bl, SC_ANKLESNARE, INVALID_TIMER); + status_change_end(bl, SC_ELECTRICSHOCKER, INVALID_TIMER); + } + + //Finally Kyrie because it may, or not, reduce damage to 0. + if((sce = sc->data[SC_KYRIE]) && damage > 0){ + sce->val2-=damage; + if(flag&BF_WEAPON || skill_id == TF_THROWSTONE){ + if(sce->val2>=0) + damage=0; + else + damage=-sce->val2; + } + if((--sce->val3)<=0 || (sce->val2<=0) || skill_id == AL_HOLYLIGHT) + status_change_end(bl, SC_KYRIE, INVALID_TIMER); + } + + if( sc->data[SC_MEIKYOUSISUI] && rand()%100 < 40 ) // custom value + damage = 0; + + + if (!damage) return 0; + + if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1 ) { + int dx[8]={0,-1,-1,-1,0,1,1,1}; + int dy[8]={1,1,0,-1,-1,-1,0,1}; + uint8 dir = iMap->calc_dir(bl, src->x, src->y); + if( unit_movepos(bl, src->x-dx[dir], src->y-dy[dir], 1, 1) ) { + clif->slide(bl,src->x-dx[dir],src->y-dy[dir]); + unit_setdir(bl, dir); + } + d->dmg_lv = ATK_DEF; + status_change_end(bl, SC_LIGHTNINGWALK, INVALID_TIMER); + return 0; + } + + //Probably not the most correct place, but it'll do here + //(since battle_drain is strictly for players currently) + if ((sce=sc->data[SC_HAMI_BLOODLUST]) && flag&BF_WEAPON && damage > 0 && + rnd()%100 < sce->val3) + status_heal(src, damage*sce->val4/100, 0, 3); + + if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 ) + pc->addspiritball(sd,skill->get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3); + if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { + TBL_HOM *hd = BL_CAST(BL_HOM,bl); + if (hd) homun->addspiritball(hd, 10); //add a sphere + } + + if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) + status_change_spread(bl, src); // Deadly infect attacked side + + if( sc && sc->data[SC__SHADOWFORM] ) { + struct block_list *s_bl = iMap->id2bl(sc->data[SC__SHADOWFORM]->val2); + if( !s_bl || s_bl->m != bl->m ) { // If the shadow form target is not present remove the sc. + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + } else if( status_isdead(s_bl) || !battle->check_target(src,s_bl,BCT_ENEMY)) { // If the shadow form target is dead or not your enemy remove the sc in both. + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + if( s_bl->type == BL_PC ) + ((TBL_PC*)s_bl)->shadowform_id = 0; + } else { + if( (--sc->data[SC__SHADOWFORM]->val3) < 0 ) { // If you have exceded max hits supported, remove the sc in both. + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + if( s_bl->type == BL_PC ) + ((TBL_PC*)s_bl)->shadowform_id = 0; + } else { + status_damage(bl, s_bl, damage, 0, clif->damage(s_bl, s_bl, iTimer->gettick(), 500, 500, damage, -1, 0, 0), 0); + return ATK_NONE; + } + } + } + + } + + //SC effects from caster side. + sc = status_get_sc(src); + + if (sc && sc->count) { + if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) + damage += damage * 75 / 100; + // [Epoque] + if (bl->type == BL_MOB) { + int i; + + if ( ((sce=sc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) || + ((sce=sc->data[SC_MANU_MATK]) && (flag&BF_MAGIC)) + ) + for (i=0;ARRAYLENGTH(mob_manuk)>i;i++) + if (((TBL_MOB*)bl)->class_==mob_manuk[i]) { + damage += damage * sce->val1 / 100; break; - case SR_RAMPAGEBLASTER: - skillratio += 20 * skill_lv * (sd?sd->spiritball_old:5) - 100; - if( sc && sc->data[SC_EXPLOSIONSPIRITS] ){ - skillratio += sc->data[SC_EXPLOSIONSPIRITS]->val1 * 20; - RE_LVL_DMOD(120); - }else - RE_LVL_DMOD(150); - break; - case SR_KNUCKLEARROW: - if( wflag&4 ){ // ATK [(Skill Level x 150) + (1000 x Target current weight / Maximum weight) + (Target Base Level x 5) x (Caster Base Level / 150)] % - skillratio = 150 * skill_lv + status_get_lv(target) * 5 * (status_get_lv(src) / 100) ; - if( tsd && tsd->weight ) - skillratio += 100 * (tsd->weight / tsd->max_weight); - }else // ATK [(Skill Level x 100 + 500) x Caster Base Level / 100] % - skillratio += 400 + (100 * skill_lv); - RE_LVL_DMOD(100); - break; - case SR_WINDMILL: // ATK [(Caster Base Level + Caster DEX) x Caster Base Level / 100] % - skillratio = status_get_lv(src) + sstatus->dex; - RE_LVL_DMOD(100); - break; - case SR_GATEOFHELL: - if( sc && sc->data[SC_COMBO] - && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) - skillratio += 800 * skill_lv -100; - else - skillratio += 500 * skill_lv -100; - RE_LVL_DMOD(100); - break; - case SR_GENTLETOUCH_QUIET: - skillratio += 100 * skill_lv - 100 + sstatus->dex; - RE_LVL_DMOD(100); - break; - case SR_HOWLINGOFLION: - skillratio += 300 * skill_lv - 100; - RE_LVL_DMOD(150); - break; - case SR_RIDEINLIGHTNING: // ATK [{(Skill Level x 200) + Additional Damage} x Caster Base Level / 100] % - if( (sstatus->rhw.ele) == ELE_WIND || (sstatus->lhw.ele) == ELE_WIND ) - skillratio += skill_lv * 50; - skillratio += -100 + 200 * skill_lv; - RE_LVL_DMOD(100); - break; - case WM_REVERBERATION_MELEE: - // ATK [{(Skill Level x 100) + 300} x Caster Base Level / 100] - skillratio += 200 + 100 * pc->checkskill(sd, WM_REVERBERATION); - RE_LVL_DMOD(100); - break; - case WM_SEVERE_RAINSTORM_MELEE: - //ATK [{(Caster DEX + AGI) x (Skill Level / 5)} x Caster Base Level / 100] % - skillratio = (sstatus->dex + sstatus->agi) * (skill_lv * 2); - RE_LVL_DMOD(100); - skillratio /= 10; - break; - case WM_GREAT_ECHO: - skillratio += 800 + 100 * skill_lv; - if( sd ) { // Still need official value [pakpil] - short lv = (short)skill_lv; - skillratio += 100 * skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),0); } - break; - case WM_SOUND_OF_DESTRUCTION: - skillratio += 400; - break; - case GN_CART_TORNADO: - // ATK [( Skill Level x 50 ) + ( Cart Weight / ( 150 - Caster Base STR ))] + ( Cart Remodeling Skill Level x 50 )] % - skillratio = 50 * skill_lv; - if( sd && sd->cart_weight) - skillratio += sd->cart_weight/10 / max(150-sstatus->str,1) + pc->checkskill(sd, GN_REMODELING_CART) * 50; - break; - case GN_CARTCANNON: - // ATK [{( Cart Remodeling Skill Level x 50 ) x ( INT / 40 )} + ( Cart Cannon Skill Level x 60 )] % - skillratio = 60 * skill_lv; - if( sd ) skillratio += pc->checkskill(sd, GN_REMODELING_CART) * 50 * (sstatus->int_ / 40); - break; - case GN_SPORE_EXPLOSION: - skillratio += 200 + 100 * skill_lv; - break; - case GN_CRAZYWEED_ATK: - skillratio += 400 + 100 * skill_lv; - break; - case GN_SLINGITEM_RANGEMELEEATK: - if( sd ) { - switch( sd->itemid ) { - case 13260: // Apple Bomob - case 13261: // Coconut Bomb - case 13262: // Melon Bomb - case 13263: // Pinapple Bomb - skillratio += 400; // Unconfirded - break; - case 13264: // Banana Bomb 2000% - skillratio += 1900; - break; - case 13265: skillratio -= 75; break; // Black Lump 25% - case 13266: skillratio -= 25; break; // Hard Black Lump 75% - case 13267: skillratio += 100; break; // Extremely Hard Black Lump 200% - } - } else - skillratio += 300; // Bombs - break; - case SO_VARETYR_SPEAR://ATK [{( Striking Level x 50 ) + ( Varetyr Spear Skill Level x 50 )} x Caster Base Level / 100 ] % - skillratio = 50 * skill_lv + ( sd ? pc->checkskill(sd, SO_STRIKING) * 50 : 0 ); - if( sc && sc->data[SC_BLAST_OPTION] ) - skillratio += sd ? sd->status.job_level * 5 : 0; - break; - // Physical Elemantal Spirits Attack Skills - case EL_CIRCLE_OF_FIRE: - case EL_FIRE_BOMB_ATK: - case EL_STONE_RAIN: - skillratio += 200; - break; - case EL_FIRE_WAVE_ATK: - skillratio += 500; - break; - case EL_TIDAL_WEAPON: - skillratio += 1400; - break; - case EL_WIND_SLASH: - skillratio += 100; - break; - case EL_HURRICANE: - skillratio += 600; - break; - case EL_TYPOON_MIS: - case EL_WATER_SCREW_ATK: - skillratio += 900; - break; - case EL_STONE_HAMMER: - skillratio += 400; - break; - case EL_ROCK_CRUSHER: - skillratio += 700; - break; - case KO_JYUMONJIKIRI: - if( tsc && tsc->data[SC_JYUMONJIKIRI] ) - wd.div_ = wd.div_ * -1;// needs more info - skillratio += -100 + 150 * skill_lv; - case KO_HUUMARANKA: - skillratio += -100 + 150 * skill_lv + sstatus->dex/2 + sstatus->agi/2; // needs more info - break; - case KO_SETSUDAN: - skillratio += 100 * (skill_lv-1); - break; - case KO_BAKURETSU: - skillratio = 50 * skill_lv * (sd?pc->checkskill(sd,NJ_TOBIDOUGU):10); - break; - case MH_NEEDLE_OF_PARALYZE: - skillratio += 600 + 100 * skill_lv; - break; - case MH_STAHL_HORN: - skillratio += 400 + 100 * skill_lv; - break; - case MH_LAVA_SLIDE: - skillratio = 70 * skill_lv; - break; - case MH_TINDER_BREAKER: - case MH_MAGMA_FLOW: - skillratio += -100 + 100 * skill_lv; - break; + if ( ((sce=sc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) || + ((sce=sc->data[SC_SPL_MATK]) && (flag&BF_MAGIC)) + ) + for (i=0;ARRAYLENGTH(mob_splendide)>i;i++) + if (((TBL_MOB*)bl)->class_==mob_splendide[i]) { + damage += damage * sce->val1 / 100; + break; + } + } + if( sc->data[SC_POISONINGWEAPON] && skill_id != GC_VENOMPRESSURE && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < sc->data[SC_POISONINGWEAPON]->val3 ) + sc_start(bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON, 1)); + if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) + status_change_spread(src, bl); + if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { + TBL_HOM *hd = BL_CAST(BL_HOM,bl); + if (hd) homun->addspiritball(hd, 10); + } + } + /* no data claims these settings affect anything other than players */ + if( damage && sd && bl->type == BL_PC ) { + switch( skill_id ) { + //case PA_PRESSURE: /* pressure also belongs to this list but it doesn't reach this area -- so dont worry about it */ + case HW_GRAVITATION: + case NJ_ZENYNAGE: + case KO_MUCHANAGE: + break; + default: + if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] + if (flag&BF_WEAPON) + damage = damage * map[bl->m].weapon_damage_rate / 100; + if (flag&BF_MAGIC) + damage = damage * map[bl->m].magic_damage_rate / 100; + if (flag&BF_MISC) + damage = damage * map[bl->m].misc_damage_rate / 100; + } else { //Normal attacks get reductions based on range. + if (flag & BF_SHORT) + damage = damage * map[bl->m].short_damage_rate / 100; + if (flag & BF_LONG) + damage = damage * map[bl->m].long_damage_rate / 100; + } + if(!damage) damage = 1; + break; + } + } + + if(battle_config.skill_min_damage && damage > 0 && damage < div_) + { + if ((flag&BF_WEAPON && battle_config.skill_min_damage&1) + || (flag&BF_MAGIC && battle_config.skill_min_damage&2) + || (flag&BF_MISC && battle_config.skill_min_damage&4) + ) + damage = div_; + } + + if( bl->type == BL_MOB && !status_isdead(bl) && src != bl) { + if (damage > 0 ) + mobskill_event((TBL_MOB*)bl,src,iTimer->gettick(),flag); + if (skill_id) + mobskill_event((TBL_MOB*)bl,src,iTimer->gettick(),MSC_SKILLUSED|(skill_id<<16)); + } + if( sd ) { + if( pc_ismadogear(sd) && rnd()%100 < 50 ) { + short element = skill->get_ele(skill_id, skill_lv); + if( !skill_id || element == -1 ) { //Take weapon's element + struct status_data *sstatus = NULL; + if( src->type == BL_PC && ((TBL_PC*)src)->bonus.arrow_ele ) + element = ((TBL_PC*)src)->bonus.arrow_ele; + else if( (sstatus = status_get_status_data(src)) ) { + element = sstatus->rhw.ele; + } + } + else if( element == -2 ) //Use enchantment's element + element = status_get_attack_sc_element(src,status_get_sc(src)); + else if( element == -3 ) //Use random element + element = rnd()%ELE_MAX; + if( element == ELE_FIRE || element == ELE_WATER ) + pc->overheat(sd,element == ELE_FIRE ? 1 : -1); + } + } + + return damage; +} + +/*========================================== + * Calculates BG related damage adjustments. + *------------------------------------------*/ +int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int damage, int div_, uint16 skill_id, uint16 skill_lv, int flag) +{ + if( !damage ) + return 0; + + if( bl->type == BL_MOB ) { + struct mob_data* md = BL_CAST(BL_MOB, bl); + + if( flag&BF_SKILL && (md->class_ == MOBID_BLUE_CRYST || md->class_ == MOBID_PINK_CRYST) ) + return 0; // Crystal cannot receive skill damage on battlegrounds + } + + return damage; +} + +/*========================================== + * Calculates GVG related damage adjustments. + *------------------------------------------*/ +int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,uint16 skill_id,uint16 skill_lv,int flag) +{ + struct mob_data* md = BL_CAST(BL_MOB, bl); + int class_ = status_get_class(bl); + + if (!damage) //No reductions to make. + return 0; + + if(md && md->guardian_data) { + if(class_ == MOBID_EMPERIUM && flag&BF_SKILL) { + //Skill immunity. + switch (skill_id) { +#ifndef RENEWAL + case MO_TRIPLEATTACK: +#endif + case HW_GRAVITATION: + break; + default: + return 0; + } + } + if(src->type != BL_MOB) { + struct guild *g = src->type == BL_PC ? ((TBL_PC *)src)->guild : guild->search(status_get_guild_id(src)); + + if (class_ == MOBID_EMPERIUM && (!g || guild->checkskill(g,GD_APPROVAL) <= 0 )) + return 0; + + if (g && battle_config.guild_max_castles && guild->checkcastles(g)>=battle_config.guild_max_castles) + return 0; // [MouseJstr] + } + } + + switch (skill_id) { + case PA_PRESSURE: + case HW_GRAVITATION: + case NJ_ZENYNAGE: + case KO_MUCHANAGE: + break; + default: + /* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka] + if (md && md->guardian_data) { + damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100; + } + */ + break; + } + + return damage; +} + +/*========================================== + * HP/SP drain calculation + *------------------------------------------*/ +int battle_calc_drain(int damage, int rate, int per) { + int diff = 0; + + if (per && rnd()%1000 < rate) { + diff = (damage * per) / 100; + if (diff == 0) { + if (per > 0) + diff = 1; + else + diff = -1; + } + } + return diff; +} + +/*========================================== + * Consumes ammo for the given skill. + *------------------------------------------*/ +void battle_consume_ammo(TBL_PC*sd, int skill_id, int lv) { + int qty=1; + if (!battle_config.arrow_decrement) + return; + + if (skill) { + qty = skill->get_ammo_qty(skill_id, lv); + if (!qty) qty = 1; + } + + if(sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition + pc->delitem(sd,sd->equip_index[EQI_AMMO],qty,0,1,LOG_TYPE_CONSUME); + + sd->state.arrow_atk = 0; +} +//Skill Range Criteria +int battle_range_type(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv) { + if (battle_config.skillrange_by_distance && + (src->type&battle_config.skillrange_by_distance) + ) { //based on distance between src/target [Skotlex] + if (check_distance_bl(src, target, 5)) + return BF_SHORT; + return BF_LONG; + } + //based on used skill's range + if (skill->get_range2(src, skill_id, skill_lv) < 5) + return BF_SHORT; + return BF_LONG; +} +int battle_adjust_skill_damage(int m, unsigned short skill_id) { + + if( map[m].skill_count ) { + int i; + ARR_FIND(0, map[m].skill_count, i, map[m].skills[i]->skill_id == skill_id ); + + if( i < map[m].skill_count ) { + return map[m].skills[i]->modifier; + } + + } + + return 0; +} +int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) { + int i; + if (!sd->skillblown[0].id) + return 0; + //Apply the bonus blewcount. [Skotlex] + for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) { + if (sd->skillblown[i].id == skill_id) + return sd->skillblown[i].val; + } + return 0; +} +//For quick div adjustment. +#define damage_div_fix(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; } +/*========================================== + * battle_calc_magic_attack [DracoRPG] + *------------------------------------------*/ +struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { + int i, nk; + short s_ele = 0; + unsigned int skillratio = 100; //Skill dmg modifiers. + + TBL_PC *sd; +// TBL_PC *tsd; + struct status_change *sc, *tsc; + struct Damage ad; + struct status_data *sstatus = status_get_status_data(src); + struct status_data *tstatus = status_get_status_data(target); + struct { + unsigned imdef : 1; + unsigned infdef : 1; + } flag; + + memset(&ad,0,sizeof(ad)); + memset(&flag,0,sizeof(flag)); + + if(src==NULL || target==NULL) + { + nullpo_info(NLP_MARK); + return ad; + } + //Initial Values + ad.damage = 1; + ad.div_=skill->get_num(skill_id,skill_lv); + ad.amotion=skill->get_inf(skill_id)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills. + ad.dmotion=tstatus->dmotion; + ad.blewcount = skill->get_blewcount(skill_id,skill_lv); + ad.flag=BF_MAGIC|BF_SKILL; + ad.dmg_lv=ATK_DEF; + nk = skill->get_nk(skill_id); + flag.imdef = nk&NK_IGNORE_DEF?1:0; + + sd = BL_CAST(BL_PC, src); +// tsd = BL_CAST(BL_PC, target); + sc = status_get_sc(src); + tsc = status_get_sc(target); + + //Initialize variables that will be used afterwards + s_ele = skill->get_ele(skill_id, skill_lv); + + if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element + s_ele = sstatus->rhw.ele; + if( sd ){ //Summoning 10 charm will endow your weapon + ARR_FIND(1, 6, i, sd->charm[i] >= 10); + if( i < 5 ) s_ele = i; + } + }else if (s_ele == -2) //Use status element + s_ele = status_get_attack_sc_element(src,status_get_sc(src)); + else if( s_ele == -3 ) //Use random element + s_ele = rnd()%ELE_MAX; + + if( skill_id == SO_PSYCHIC_WAVE ) { + if( sc && sc->count ) { + if( sc->data[SC_HEATER_OPTION] ) s_ele = sc->data[SC_HEATER_OPTION]->val4; + else if( sc->data[SC_COOLER_OPTION] ) s_ele = sc->data[SC_COOLER_OPTION]->val4; + else if( sc->data[SC_BLAST_OPTION] ) s_ele = sc->data[SC_BLAST_OPTION]->val3; + else if( sc->data[SC_CURSED_SOIL_OPTION] ) s_ele = sc->data[SC_CURSED_SOIL_OPTION]->val4; + } + } + + //Set miscellaneous data that needs be filled + if(sd) { + sd->state.arrow_atk = 0; + ad.blewcount += battle->blewcount_bonus(sd, skill_id); + } + + //Skill Range Criteria + ad.flag |= battle->range_type(src, target, skill_id, skill_lv); + flag.infdef=(tstatus->mode&MD_PLANT?1:0); + if( target->type == BL_SKILL){ + TBL_SKILL *su = (TBL_SKILL*)target; + if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) + flag.infdef = 1; + } + + switch(skill_id) { + case MG_FIREWALL: + case NJ_KAENSIN: + ad.dmotion = 0; //No flinch animation. + if ( tstatus->def_ele == ELE_FIRE || battle->check_undead(tstatus->race, tstatus->def_ele) ) + ad.blewcount = 0; //No knockback + break; + case PR_SANCTUARY: + ad.dmotion = 0; //No flinch animation. + break; + case WL_HELLINFERNO: + if( mflag&ELE_DARK ) + s_ele = ELE_DARK; + break; + case KO_KAIHOU: + if( sd ){ + ARR_FIND(1, 6, i, sd->charm[i] > 0); + if( i < 5 ) + s_ele = i; } + break; #ifdef RENEWAL - if( sc && sc->data[SC_TRUESIGHT] ) - skillratio += 2*sc->data[SC_TRUESIGHT]->val1; + case CR_ACIDDEMONSTRATION: + case ASC_BREAKER: + case HW_MAGICCRASHER: + flag.imdef = 1; + break; #endif - ATK_RATE(skillratio); + } - //Constant/misc additions from skills - switch (skill_id) { - case MO_EXTREMITYFIST: - ATK_ADD(250 + 150*skill_lv); - break; - case TK_DOWNKICK: - case TK_STORMKICK: - case TK_TURNKICK: - case TK_COUNTER: - case TK_JUMPKICK: - //TK_RUN kick damage bonus. - if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST) - ATK_ADD(10*pc->checkskill(sd, TK_RUN)); - break; - case GS_MAGICALBULLET: - if(sstatus->matk_max>sstatus->matk_min) { - ATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); - } else { - ATK_ADD(sstatus->matk_min); - } - break; - case NJ_SYURIKEN: - ATK_ADD(4*skill_lv); - break; + if (!flag.infdef) //No need to do the math for plants + { #ifdef RENEWAL - case NJ_ISSEN: - // Damage = (current HP + atk * skill_lv) - (sdef+edef) - ATK_ADD(sstatus->hp); - wd.damage2 = 0;// needs more info if this really 0 for dual weilding KG/OB. [malufett] - if( sc && sc->data[SC_BUNSINJYUTSU] && (i=sc->data[SC_BUNSINJYUTSU]->val2) > 0){ - wd.div_ = -( i + 2 ); // mirror image number of hits + 2 - ATK_ADDRATE(20 + i*20); // (20 + 20 * mirror image) % - } - break; + ad.damage = 0; //reinitialize.. #endif - case HT_FREEZINGTRAP: - if(sd) - ATK_ADD( 40 * pc->checkskill(sd, RA_RESEARCHTRAP) ); - break; - case RA_WUGDASH ://(Caster Current Weight x 10 / 8) - if( sd && sd->weight ) - ATK_ADD( sd->weight / 8 ); - case RA_WUGSTRIKE: - case RA_WUGBITE: - if(sd) - ATK_ADD(30*pc->checkskill(sd, RA_TOOTHOFWUG)); - break; - case SR_GATEOFHELL: - ATK_ADD (sstatus->max_hp - status_get_hp(src)); - if(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE){ - ATK_ADD ( (sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status_get_lv(src) ); - }else{ - ATK_ADD ( (sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status_get_lv(src) ); - } - break; - case SR_TIGERCANNON: // (Tiger Cannon skill level x 240) + (Target Base Level x 40) - ATK_ADD( skill_lv * 240 + status_get_lv(target) * 40 ); - if( sc && sc->data[SC_COMBO] - && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) // (Tiger Cannon skill level x 500) + (Target Base Level x 40) - ATK_ADD( skill_lv * 500 + status_get_lv(target) * 40 ); - break; - case SR_FALLENEMPIRE:// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)] - ATK_ADD( ((tstatus->size+1)*2 + skill_lv - 1) * sstatus->str); - if( tsd && tsd->weight ){ - ATK_ADD( (tsd->weight/10) * sstatus->dex / 120 ); - }else{ - ATK_ADD( status_get_lv(target) * 50 ); //mobs - } - break; - case KO_SETSUDAN: - if( tsc && tsc->data[SC_SPIRIT] ){ - ATK_ADDRATE(10*tsc->data[SC_SPIRIT]->val1);// +10% custom value. - status_change_end(target,SC_SPIRIT,INVALID_TIMER); - } - break; - case KO_KAIHOU: - if( sd ){ - ARR_FIND(1, 6, i, sd->talisman[i] > 0); - if( i < 5 ){ - s_ele = i; - ATK_ADDRATE(100 * sd->talisman[i]);// +100% custom value. - pc->del_talisman(sd, sd->talisman[i], i); +//MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc +#define MATK_RATE( a ) { ad.damage= ad.damage*(a)/100; } +//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage +#define MATK_ADDRATE( a ) { ad.damage+= ad.damage*(a)/100; } +//Adds an absolute value to damage. 100 = +100 damage +#define MATK_ADD( a ) { ad.damage+= a; } + + switch (skill_id) + { //Calc base damage according to skill + case AL_HEAL: + case PR_BENEDICTIO: + case PR_SANCTUARY: + /** + * Arch Bishop + **/ + case AB_HIGHNESSHEAL: + ad.damage = skill->calc_heal(src, target, skill_id, skill_lv, false); + break; + case PR_ASPERSIO: + ad.damage = 40; + break; + case ALL_RESURRECTION: + case PR_TURNUNDEAD: + //Undead check is on skill_castend_damageid code. + i = 20*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src) + + 200 - 200*tstatus->hp/tstatus->max_hp; // there is no changed in success chance in renewal. [malufett] + if(i > 700) i = 700; + if(rnd()%1000 < i && !(tstatus->mode&MD_BOSS)) + ad.damage = tstatus->hp; + else { + #ifdef RENEWAL + MATK_ADD(status_get_matk(src, 2)); + #else + ad.damage = status_get_lv(src) + sstatus->int_ + skill_lv * 10; + #endif + } + break; + case PF_SOULBURN: + ad.damage = tstatus->sp * 2; + break; + /** + * Arch Bishop + **/ + case AB_RENOVATIO: + //Damage calculation from iRO wiki. [Jobbie] + ad.damage = (int)((15 * status_get_lv(src)) + (1.5 * sstatus->int_)); + break; + default: { + MATK_ADD( status_get_matk(src, 2) ); + + if (nk&NK_SPLASHSPLIT) { // Divide MATK in case of multiple targets skill + if(mflag>0) + ad.damage/= mflag; + else + ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); + } + + if (sc){ + if( sc->data[SC_TELEKINESIS_INTENSE] && s_ele == ELE_GHOST ) + skillratio += sc->data[SC_TELEKINESIS_INTENSE]->val3; + } + switch(skill_id){ + case MG_FIREBOLT: + case MG_COLDBOLT: + case MG_LIGHTNINGBOLT: + if ( sc && sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) { + skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech] + ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax] + ad.flag = BF_WEAPON|BF_SHORT; + ad.type = 0; } + break; + default: + MATK_RATE(battle->calc_skillratio(BF_MAGIC, src, target, skill_id, skill_lv, skillratio, mflag)); + } + //Constant/misc additions from skills + if (skill_id == WZ_FIREPILLAR) + MATK_ADD(50); + if( sd && (i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 && + (tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) ) + MATK_ADDRATE(i); + } + } +#ifndef HMAP_ZONE_DAMAGE_CAP_TYPE + if( target && skill_id ) { + for(i = 0; i < map[target->m].zone->capped_skills_count; i++) { + if( skill_id == map[target->m].zone->capped_skills[i]->nameid && (map[target->m].zone->capped_skills[i]->type & target->type) ) { + if( target->type == BL_MOB && map[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { + if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) ) + continue; + if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) ) + continue; } + if( ad.damage > map[target->m].zone->capped_skills[i]->cap ) + ad.damage = map[target->m].zone->capped_skills[i]->cap; + if( ad.damage2 > map[target->m].zone->capped_skills[i]->cap ) + ad.damage2 = map[target->m].zone->capped_skills[i]->cap; break; + } } } - //Div fix. - damage_div_fix(wd.damage, wd.div_); - - //The following are applied on top of current damage and are stackable. - if ( sc ) { -#ifndef RENEWAL - if( sc->data[SC_TRUESIGHT] ) - ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1); #endif - if( sc->data[SC_GLOOMYDAY_SK] && - ( skill_id == LK_SPIRALPIERCE || skill_id == KN_BRANDISHSPEAR || - skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN || - skill_id == LG_SHIELDPRESS ) ) - ATK_ADDRATE(sc->data[SC_GLOOMYDAY_SK]->val2); - if( sc->data[SC_EDP] ){ - switch(skill_id){ - case AS_SPLASHER: case AS_VENOMKNIFE: -#ifndef RENEWAL_EDP - case AS_GRIMTOOTH: +#ifdef RENEWAL + ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); #endif + if(sd) { + //Damage bonuses + if ((i = pc->skillatk_bonus(sd, skill_id))) + ad.damage += ad.damage*i/100; + + if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) + MATK_RATE(i); + + //Ignore Defense? + if (!flag.imdef && ( + sd->bonus.ignore_mdef_ele & ( 1 << tstatus->def_ele ) || + sd->bonus.ignore_mdef_race & ( 1 << tstatus->race ) || + sd->bonus.ignore_mdef_race & ( is_boss(target) ? 1 << RC_BOSS : 1 << RC_NONBOSS ) + )) + flag.imdef = 1; + } + + ad.damage = battle->calc_defense(BF_MAGIC, src, target, skill_id, skill_lv, ad.damage, (flag.imdef?1:0), 0); + + if (skill_id == NPC_EARTHQUAKE) + { //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex] + //Also divide the extra bonuses from atk2 based on the number in range [Kevin] + if(mflag>0) + ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag; + else + ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); + } + + if(ad.damage<1) + ad.damage=1; + else if(sc){//only applies when hit + // TODO: there is another factor that contribute with the damage and need to be formulated. [malufett] + switch(skill_id){ + case MG_LIGHTNINGBOLT: + case MG_THUNDERSTORM: + case MG_FIREBOLT: + case MG_FIREWALL: + case MG_COLDBOLT: + case MG_FROSTDIVER: + case WZ_EARTHSPIKE: + case WZ_HEAVENDRIVE: + if(sc->data[SC_GUST_OPTION] || sc->data[SC_PETROLOGY_OPTION] + || sc->data[SC_PYROTECHNIC_OPTION] || sc->data[SC_AQUAPLAY_OPTION]) + ad.damage += (6 + sstatus->int_/4) + max(sstatus->dex-10,0)/30; break; -#ifndef RENEWAL_EDP - case ASC_BREAKER: case ASC_METEORASSAULT: break; -#else - case AS_SONICBLOW: - case ASC_BREAKER: - case GC_COUNTERSLASH: - case GC_CROSSIMPACT: - ATK_RATE(50); // only modifier is halved but still benefit with the damage bonus -#endif - default: - ATK_ADDRATE(sc->data[SC_EDP]->val3); - } } - if(sc->data[SC_STYLE_CHANGE]){ - TBL_HOM *hd = BL_CAST(BL_HOM,src); - if (hd) ATK_ADD(hd->homunculus.spiritball * 3); - } } - switch (skill_id) { - case AS_SONICBLOW: - if (sc && sc->data[SC_SPIRIT] && - sc->data[SC_SPIRIT]->val2 == SL_ASSASIN) - ATK_ADDRATE(map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe + if (!(nk&NK_NO_ELEFIX)) + ad.damage=battle->attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); - if(sd && pc->checkskill(sd,AS_SONICACCEL)>0) - ATK_ADDRATE(10); - break; - case CR_SHIELDBOOMERANG: - if(sc && sc->data[SC_SPIRIT] && - sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) - ATK_ADDRATE(100); - break; - case NC_AXETORNADO: - if( (sstatus->rhw.ele) == ELE_WIND || (sstatus->lhw.ele) == ELE_WIND ) - ATK_ADDRATE(50); - break; + if( skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS ) + { //Apply the physical part of the skill's damage. [Skotlex] + struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); + ad.damage = battle->attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40*skill_lv)/100; + if( src == target ) + { + if( src->type == BL_PC ) + ad.damage = ad.damage/2; + else + ad.damage = 0; + } } - if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) - ATK_RATE(i); - - if( sd ) { - if (skill_id && (i = pc->skillatk_bonus(sd, skill_id))) - ATK_ADDRATE(i); - - if( skill_id != PA_SACRIFICE && skill_id != MO_INVESTIGATE && skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS && skill_id != PA_SHIELDCHAIN && !flag.cri ) - { //Elemental/Racial adjustments - if( sd->right_weapon.def_ratio_atk_ele & (1<def_ele) || - sd->right_weapon.def_ratio_atk_race & (1<race) || - sd->right_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) - ) - flag.pdef = 1; +#ifndef RENEWAL + ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); +#endif + } - if( sd->left_weapon.def_ratio_atk_ele & (1<def_ele) || - sd->left_weapon.def_ratio_atk_race & (1<race) || - sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) - ) - { //Pass effect onto right hand if configured so. [Skotlex] - if (battle_config.left_cardfix_to_right && flag.rh) - flag.pdef = 1; - else - flag.pdef2 = 1; - } - } + damage_div_fix(ad.damage, ad.div_); - if (skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS) - { //Ignore Defense? - if (!flag.idef && ( - sd->right_weapon.ignore_def_ele & (1<def_ele) || - sd->right_weapon.ignore_def_race & (1<race) || - sd->right_weapon.ignore_def_race & (is_boss(target)?1<0?1:-1; - if (!flag.idef2 && ( - sd->left_weapon.ignore_def_ele & (1<def_ele) || - sd->left_weapon.ignore_def_race & (1<race) || - sd->left_weapon.ignore_def_race & (is_boss(target)?1<calc_damage(src,target,&ad,ad.damage,skill_id,skill_lv); + if( map_flag_gvg2(target->m) ) + ad.damage=battle->calc_gvg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); + else if( map[target->m].flag.battleground ) + ad.damage=battle->calc_bg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); + + switch( skill_id ) { /* post-calc modifiers */ + case SO_VARETYR_SPEAR: { // Physical damage. + struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); + if(!flag.infdef && ad.damage > 1) + ad.damage += wd.damage; + break; } + //case HM_ERASER_CUTTER: + } + + return ad; +} + +/*========================================== + * Calculate Misc dammage for skill_id + *------------------------------------------*/ +struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { + int temp; + short i, nk; + short s_ele; + + struct map_session_data *sd, *tsd; + struct Damage md; //DO NOT CONFUSE with md of mob_data! + struct status_data *sstatus = status_get_status_data(src); + struct status_data *tstatus = status_get_status_data(target); + struct status_change *tsc = status_get_sc(target); + struct status_change *sc = status_get_sc(src); + + memset(&md,0,sizeof(md)); + + if( src == NULL || target == NULL ){ + nullpo_info(NLP_MARK); + return md; + } + + //Some initial values + md.amotion=skill->get_inf(skill_id)&INF_GROUND_SKILL?0:sstatus->amotion; + md.dmotion=tstatus->dmotion; + md.div_=skill->get_num( skill_id,skill_lv ); + md.blewcount=skill->get_blewcount(skill_id,skill_lv); + md.dmg_lv=ATK_DEF; + md.flag=BF_MISC|BF_SKILL; + + nk = skill->get_nk(skill_id); - if (!flag.idef || !flag.idef2) - { //Defense reduction - short vit_def; - defType def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions. - short def2 = tstatus->def2; -#ifdef RENEWAL - if( tsc && tsc->data[SC_ASSUMPTIO] ) - def1 <<= 1; // only eDEF is doubled -#endif - if( sd ) - { - i = sd->ignore_def[is_boss(target)?RC_BOSS:RC_NONBOSS]; - i += sd->ignore_def[tstatus->race]; - if( i ) - { - if( i > 100 ) i = 100; - def1 -= def1 * i / 100; - def2 -= def2 * i / 100; - } - } + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, target); - if( sc && sc->data[SC_EXPIATIO] ){ - i = 5 * sc->data[SC_EXPIATIO]->val1; // 5% per level - def1 -= def1 * i / 100; - def2 -= def2 * i / 100; - } + if(sd) { + sd->state.arrow_atk = 0; + md.blewcount += battle->blewcount_bonus(sd, skill_id); + } - if( tsc && tsc->data[SC_GT_REVITALIZE] && tsc->data[SC_GT_REVITALIZE]->val4 ) - def2 += 2 * tsc->data[SC_GT_REVITALIZE]->val4; + s_ele = skill->get_ele(skill_id, skill_lv); + if (s_ele < 0 && s_ele != -3) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex] + s_ele = ELE_NEUTRAL; + else if (s_ele == -3) //Use random element + s_ele = rnd()%ELE_MAX; - if( tsc && tsc->data[SC_CAMOUFLAGE] ){ - i = 5 * (10-tsc->data[SC_CAMOUFLAGE]->val4); - def1 -= def1 * i / 100; - def2 -= def2 * i / 100; - } + //Skill Range Criteria + md.flag |= battle->range_type(src, target, skill_id, skill_lv); - if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) { - unsigned char target_count; //256 max targets should be a sane max - target_count = unit_counttargeted(target); - if(target_count >= battle_config.vit_penalty_count) { - if(battle_config.vit_penalty_type == 1) { - if( !tsc || !tsc->data[SC_STEELBODY] ) - def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; - def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100; - } else { //Assume type 2 - if( !tsc || !tsc->data[SC_STEELBODY] ) - def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; - def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num; - } - } - if(skill_id == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex] - if(def2 < 1) def2 = 1; - } - //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def - if (tsd) //Sd vit-eq - { -#ifndef RENEWAL - //[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1)) - vit_def = def2*(def2-15)/150; - vit_def = def2/2 + (vit_def>0?rnd()%vit_def:0); -#else - vit_def = def2; -#endif - if((battle->check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesnt work vs players - src->type == BL_MOB && (temp=pc->checkskill(tsd,AL_DP)) > 0) - vit_def += temp*(int)(3 +(tsd->status.base_level+1)*0.04); // submitted by orn - if( src->type == BL_MOB && (temp=pc->checkskill(tsd,RA_RANGERMAIN))>0 && - (sstatus->race == RC_BRUTE || sstatus->race == RC_FISH || sstatus->race == RC_PLANT) ) - vit_def += temp*5; + switch( skill_id ) + { #ifdef RENEWAL - if( temp == NJ_ISSEN ){//TODO: do better implementation if other skills(same func) are found [malufett] - vit_def += def1; - def1 = 0; - } -#endif - } - else { //Mob-Pet vit-eq -#ifndef RENEWAL - //VIT + rnd(0,[VIT/20]^2-1) - vit_def = (def2/20)*(def2/20); - vit_def = def2 + (vit_def>0?rnd()%vit_def:0); + case HT_LANDMINE: + case MA_LANDMINE: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + md.damage = skill_lv * sstatus->dex * (3+status_get_lv(src)/100) * (1+sstatus->int_/35); + md.damage += md.damage * (rnd()%20-10) / 100; + md.damage += 40 * (sd?pc->checkskill(sd,RA_RESEARCHTRAP):0); + break; #else - vit_def = def2; + case HT_LANDMINE: + case MA_LANDMINE: + md.damage=skill_lv*(sstatus->dex+75)*(100+sstatus->int_)/100; + break; + case HT_BLASTMINE: + md.damage=skill_lv*(sstatus->dex/2+50)*(100+sstatus->int_)/100; + break; + case HT_CLAYMORETRAP: + md.damage=skill_lv*(sstatus->dex/2+75)*(100+sstatus->int_)/100; + break; #endif - } + case HT_BLITZBEAT: + case SN_FALCONASSAULT: + //Blitz-beat Damage. + if(!sd || (temp = pc->checkskill(sd,HT_STEELCROW)) <= 0) + temp=0; + md.damage=(sstatus->dex/10+sstatus->int_/2+temp*3+40)*2; + if(mflag > 1) //Autocasted Blitz. + nk|=NK_SPLASHSPLIT; + if (skill_id == SN_FALCONASSAULT) { + //Div fix of Blitzbeat + temp = skill->get_num(HT_BLITZBEAT, 5); + damage_div_fix(md.damage, temp); - if (battle_config.weapon_defense_type) { - vit_def += def1*battle_config.weapon_defense_type; - def1 = 0; + //Falcon Assault Modifier + md.damage=md.damage*(150+70*skill_lv)/100; + } + break; + case TF_THROWSTONE: + md.damage=50; + break; + case BA_DISSONANCE: + md.damage=30+skill_lv*10; + if (sd) + md.damage+= 3*pc->checkskill(sd,BA_MUSICALLESSON); + break; + case NPC_SELFDESTRUCTION: + md.damage = sstatus->hp; + break; + case NPC_SMOKING: + md.damage=3; + break; + case NPC_DARKBREATH: + md.damage = 500 + (skill_lv-1)*1000 + rnd()%1000; + if(md.damage > 9999) md.damage = 9999; + break; + case PA_PRESSURE: + md.damage=500+300*skill_lv; + break; + case PA_GOSPEL: + md.damage = 1+rnd()%9999; + break; + case CR_ACIDDEMONSTRATION: +#ifdef RENEWAL + {// [malufett] + int matk=0, atk; + short tdef = status_get_total_def(target); + short tmdef = status_get_total_mdef(target); + int targetVit = min(120, status_get_vit(target)); + short totaldef = (tmdef + tdef - ((unsigned _int64)(tmdef + tdef) >> 32)) >> 1; + + matk = battle->calc_magic_attack(src, target, skill_id, skill_lv, mflag).damage; + atk = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, false, s_ele, ELE_NEUTRAL, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), md.flag); + md.damage = matk + atk; + if( src->type == BL_MOB ){ + totaldef = (tdef + tmdef) >> 1; + md.damage = 7 * targetVit * skill_lv * (atk + matk) / 100; + /* + // Pending [malufett] + if( unknown condition ) + md.damage >>= 1; + if( unknown condition ){ + md.damage = 7 * md.damage % 20; + md.damage = 7 * md.damage / 20; + }*/ + }else{ + float vitfactor = 0.0f, temp; + + if( (vitfactor=(status_get_vit(target)-120.0f)) > 0) + vitfactor = (vitfactor * (matk + atk) / 10) / status_get_vit(target); + temp = max(0, vitfactor) + (targetVit * (matk + atk)) / 10; + md.damage = (int)(temp * 70 * skill_lv / 100); } - #ifdef RENEWAL - /** - * RE DEF Reduction - * Damage = Attack * (4000+eDEF)/(4000+eDEF) - sDEF - * Pierce defence gains 1 atk per def/2 - **/ - - if( def1 == -400 ) /* being hit by a gazillion units, you hit the jackpot and got -400 which creates a division by 0 and subsequently crashes */ - def1 = -399; - - ATK_ADD2( - flag.pdef ?(def1/2):0, - flag.pdef2?(def1/2):0 - ); - if( !flag.idef && !flag.pdef ) - wd.damage = wd.damage * (4000+def1) / (4000+10*def1) - vit_def; - if( flag.lh && !flag.idef2 && !flag.pdef2 ) - wd.damage2 = wd.damage2 * (4000+def1) / (4000+10*def1) - vit_def; - - #else - if (def1 > 100) def1 = 100; - ATK_RATE2( - flag.idef ?100:(flag.pdef ? flag.pdef*(def1+vit_def) : (100-def1)), - flag.idef2?100:(flag.pdef2? flag.pdef2*(def1+vit_def) : (100-def1)) - ); - ATK_ADD2( - flag.idef ||flag.pdef ?0:-vit_def, - flag.idef2||flag.pdef2?0:-vit_def - ); - #endif + md.damage -= totaldef; } +#else + // updated the formula based on a Japanese formula found to be exact [Reddozen] + if(tstatus->vit+sstatus->int_) //crash fix + md.damage = (int)(7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_))); + else + md.damage = 0; + if (tsd) md.damage>>=1; +#endif + if (md.damage < 0 || md.damage > INT_MAX>>1) + //Overflow prevention, will anyone whine if I cap it to a few billion? + //Not capped to INT_MAX to give some room for further damage increase. + md.damage = INT_MAX>>1; + break; - //Post skill/vit reduction damage increases - if( sc ) - { //SC skill damages - if(sc->data[SC_AURABLADE] + case KO_MUCHANAGE: + md.damage = skill->get_zeny(skill_id ,skill_lv); + md.damage = md.damage * (50 + rand()%50) / 100; + if ( is_boss(target) || (sd && !pc->checkskill(sd,NJ_TOBIDOUGU)) ) + md.damage >>= 1; + break; + case NJ_ZENYNAGE: + md.damage = skill->get_zeny(skill_id ,skill_lv); + if (!md.damage) md.damage = 2; + md.damage = rand()%md.damage + md.damage; + if (is_boss(target)) + md.damage=md.damage / 3; + else if (tsd) + md.damage=md.damage / 2; + break; + case GS_FLING: + md.damage = sd?sd->status.job_level:status_get_lv(src); + break; + case HVAN_EXPLOSION: //[orn] + md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100; + break ; + case ASC_BREAKER: + { #ifndef RENEWAL - && skill_id != LK_SPIRALPIERCE && skill_id != ML_SPIRALPIERCE -#endif - ){ - int lv = sc->data[SC_AURABLADE]->val1; -#ifdef RENEWAL - lv *= ((skill_id == LK_SPIRALPIERCE || skill_id == ML_SPIRALPIERCE)?wd.div_:1); // +100 per hit in lv 5 + md.damage = 500+rnd()%500 + 5*skill_lv * sstatus->int_; + nk|=NK_IGNORE_FLEE|NK_NO_ELEFIX; //These two are not properties of the weapon based part. +#else + int ratio = 300 + 50 * skill_lv; + int matk = battle->calc_magic_attack(src, target, skill_id, skill_lv, mflag).damage; + short totaldef = status_get_total_def(target) + status_get_total_mdef(target); + int atk = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, false, s_ele, ELE_NEUTRAL, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), md.flag); + + if( sc && sc->data[SC_EDP] ) + ratio >>= 1; + md.damage = (matk + atk) * ratio / 100; + md.damage -= totaldef; #endif - ATK_ADD(20*lv); - } - - if(sc->data[SC_GN_CARTBOOST]) - ATK_ADD(10*sc->data[SC_GN_CARTBOOST]->val1); - - if(sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val2){ - struct block_list *bl; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] - if( (bl = iMap->id2bl(sc->data[SC_GT_CHANGE]->val2)) ) - ATK_ADD( ( status_get_dex(bl)/4 + status_get_str(bl)/2 ) * sc->data[SC_GT_CHANGE]->val1 / 5 ); - } - - if(sc->data[SC_CAMOUFLAGE]) - ATK_ADD(30 * (10-sc->data[SC_CAMOUFLAGE]->val4) ); } + break; + case HW_GRAVITATION: + md.damage = 200+200*skill_lv; + md.dmotion = 0; //No flinch animation. + break; + case NPC_EVILLAND: + md.damage = skill->calc_heal(src,target,skill_id,skill_lv,false); + break; + case RK_DRAGONBREATH: + case RK_DRAGONBREATH_WATER: + md.damage = ((status_get_hp(src) / 50) + (status_get_max_sp(src) / 4)) * skill_lv; + RE_LVL_MDMOD(150); + if (sd) md.damage = md.damage * (100 + 5 * (pc->checkskill(sd,RK_DRAGONTRAINING) - 1)) / 100; + md.flag |= BF_LONG|BF_WEAPON; + break; + /** + * Ranger + **/ + case RA_CLUSTERBOMB: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + md.damage = skill_lv * sstatus->dex + sstatus->int_ * 5 ; + RE_LVL_TMDMOD(); + if(sd) + { + int researchskill_lv = pc->checkskill(sd,RA_RESEARCHTRAP); + if(researchskill_lv) + md.damage = md.damage * 20 * researchskill_lv / (skill_id == RA_CLUSTERBOMB?50:100); + else + md.damage = 0; + }else + md.damage = md.damage * 200 / (skill_id == RA_CLUSTERBOMB?50:100); - //Refine bonus - if( sd && flag.weapon && skill_id != MO_INVESTIGATE && skill_id != MO_EXTREMITYFIST ) - { // Counts refine bonus multiple times - if( skill_id == MO_FINGEROFFENSIVE ) - { - ATK_ADD2(wd.div_*sstatus->rhw.atk2, wd.div_*sstatus->lhw.atk2); - } else { - ATK_ADD2(sstatus->rhw.atk2, sstatus->lhw.atk2); - } + break; + /** + * Mechanic + **/ + case NC_SELFDESTRUCTION: + { + short totaldef = status_get_total_def(target); + md.damage = ( (sd?pc->checkskill(sd,NC_MAINFRAME):10) + 8 ) * ( skill_lv + 1 ) * ( status_get_sp(src) + sstatus->vit ); + RE_LVL_MDMOD(100); + md.damage += status_get_hp(src) - totaldef; + } + break; + case NC_MAGMA_ERUPTION: + md.damage = 1200 + 400 * skill_lv; + break; + case GN_THORNS_TRAP: + md.damage = 100 + 200 * skill_lv + sstatus->int_; + break; + case GN_HELLS_PLANT_ATK: + //[{( Hell Plant Skill Level x Casters Base Level ) x 10 } + {( Casters INT x 7 ) / 2 } x { 18 + ( Casters Job Level / 4 )] x ( 5 / ( 10 - Summon Flora Skill Level )) + md.damage = ( skill_lv * status_get_lv(src) * 10 ) + ( sstatus->int_ * 7 / 2 ) * ( 18 + (sd?sd->status.job_level:0) / 4 ) * ( 5 / (10 - (sd?pc->checkskill(sd,AM_CANNIBALIZE):0)) ); + break; + case KO_HAPPOKUNAI: + { + struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); + short totaldef = status_get_total_def(target); + md.damage = 3 * wd.damage * (5 + skill_lv) / 5; + md.damage -= totaldef; } + break; + } - //Set to min of 1 - if (flag.rh && wd.damage < 1) wd.damage = 1; - if (flag.lh && wd.damage2 < 1) wd.damage2 = 1; + if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets + if(mflag>0) + md.damage/= mflag; + else + ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); + } - if (sd && flag.weapon && - skill_id != MO_INVESTIGATE && - skill_id != MO_EXTREMITYFIST && - skill_id != CR_GRANDCROSS) - { //Add mastery damage - if(skill_id != ASC_BREAKER && sd->status.weapon == W_KATAR && - (temp=pc->checkskill(sd,ASC_KATAR)) > 0) - { //Adv Katar Mastery is does not applies to ASC_BREAKER, - // but other masteries DO apply >_> - ATK_ADDRATE(10+ 2*temp); - } + damage_div_fix(md.damage, md.div_); - wd.damage = battle->add_mastery(sd,target,wd.damage,0); - if (flag.lh) - wd.damage2 = battle->add_mastery(sd,target,wd.damage2,1); + if (!(nk&NK_IGNORE_FLEE)) + { + i = 0; //Temp for "hit or no hit" + if(tsc && tsc->opt1 && tsc->opt1 != OPT1_STONEWAIT && tsc->opt1 != OPT1_BURNING) + i = 1; + else { + short + flee = tstatus->flee, +#ifdef RENEWAL + hitrate = 0; //Default hitrate +#else + hitrate = 80; //Default hitrate +#endif - if (sc && sc->data[SC_MIRACLE]) i = 2; //Star anger - else - ARR_FIND(0, MAX_PC_FEELHATE, i, t_class == sd->hate_mob[i]); - if (i < MAX_PC_FEELHATE && (temp=pc->checkskill(sd,sg_info[i].anger_id))) { - skillratio = sd->status.base_level + sstatus->dex + sstatus->luk; - if (i == 2) skillratio += sstatus->str; //Star Anger - if (temp<4) - skillratio /= 12-3*temp; - ATK_ADDRATE(skillratio); + if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) { + unsigned char attacker_count; //256 max targets should be a sane max + attacker_count = unit_counttargeted(target); + if(attacker_count >= battle_config.agi_penalty_count) + { + if (battle_config.agi_penalty_type == 1) + flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; + else //asume type 2: absolute reduction + flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; + if(flee < 1) flee = 1; + } } - if (skill_id == NJ_SYURIKEN && (temp = pc->checkskill(sd,NJ_TOBIDOUGU)) > 0) { - ATK_ADD(3*temp); - } else if (skill_id == NJ_KUNAI) - ATK_ADD(60); - } - } //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks - else if(wd.div_ < 0) //Since the attack missed... - wd.div_ *= -1; - - if(sd && (temp=pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0) - ATK_ADD(temp*2); - if(skill_id==TF_POISON) - ATK_ADD(15*skill_lv); + hitrate+= sstatus->hit - flee; +#ifdef RENEWAL + if( sd ) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window + hitrate += pc->checkskill(sd,AC_VULTURE); +#endif + if( skill_id == KO_MUCHANAGE ) + hitrate = (int)((10 - ((float)1 / (status_get_dex(src) + status_get_luk(src))) * 500) * ((float)skill_lv / 2 + 5)); + + hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); - if( !(nk&NK_NO_ELEFIX) && !n_ele ) - { //Elemental attribute fix - if( wd.damage > 0 ) - { - wd.damage=battle->attr_fix(src,target,wd.damage,s_ele,tstatus->def_ele, tstatus->ele_lv); - if( skill_id == MC_CARTREVOLUTION ) //Cart Revolution applies the element fix once more with neutral element - wd.damage = battle->attr_fix(src,target,wd.damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); - if( skill_id== GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage. - wd.damage += battle->attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); - } - if( flag.lh && wd.damage2 > 0 ) - wd.damage2 = battle->attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); - if( sc && sc->data[SC_WATK_ELEMENT] ) - { // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex] - int damage = battle->calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; - wd.damage += battle->attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); - - if( flag.lh ) { - damage = battle->calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; - wd.damage2 += battle->attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); - } + if(rnd()%100 < hitrate) + i = 1; + } + if (!i) { + md.damage = 0; + md.dmg_lv=ATK_FLEE; } - #ifdef RENEWAL - /** - * In RE Shield Bommerang takes weapon element only for damage calculation, - * - resist calculation is always against neutral - **/ - if ( skill_id == CR_SHIELDBOOMERANG ) - s_ele = s_ele_ = ELE_NEUTRAL; - #endif } - - if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS) - return wd; //Enough, rest is not needed. #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE if( target && skill_id ) { for(i = 0; i < map[target->m].zone->capped_skills_count; i++) { @@ -3386,1107 +3790,970 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) ) continue; } - if( wd.damage > map[target->m].zone->capped_skills[i]->cap ) - wd.damage = map[target->m].zone->capped_skills[i]->cap; - if( wd.damage2 > map[target->m].zone->capped_skills[i]->cap ) - wd.damage2 = map[target->m].zone->capped_skills[i]->cap; + if( md.damage > map[target->m].zone->capped_skills[i]->cap ) + md.damage = map[target->m].zone->capped_skills[i]->cap; + if( md.damage2 > map[target->m].zone->capped_skills[i]->cap ) + md.damage2 = map[target->m].zone->capped_skills[i]->cap; break; } } } #endif - if (sd) { - if (skill_id != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus. - ATK_ADD2(wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star); - if (skill_id==MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex] - ATK_ADD(wd.div_*sd->spiritball_old*3); - } else { - ATK_ADD(wd.div_*sd->spiritball*3); - } + md.damage = battle->calc_cardfix(BF_MISC, src, target, nk, s_ele, 0, md.damage, 0, md.flag); - //Card Fix, sd side - wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag); - if( flag.lh ) - wd.damage2 = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag); + if (sd && (i = pc->skillatk_bonus(sd, skill_id))) + md.damage += md.damage*i/100; + + if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) + md.damage = md.damage * i / 100; + + if(md.damage < 0) + md.damage = 0; + else if(md.damage && tstatus->mode&MD_PLANT){ + switch(skill_id){ + case HT_LANDMINE: + case MA_LANDMINE: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + case RA_CLUSTERBOMB: #ifdef RENEWAL - if( flag.cri ) - ATK_ADDRATE(sd->bonus.crit_atk_rate>=100?sd->bonus.crit_atk_rate-60:40); + break; #endif - if( skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ) - { //Refine bonus applies after cards and elements. - short index= sd->equip_index[EQI_HAND_L]; - if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR ) - ATK_ADD(10*sd->status.inventory[index].refine); + default: + md.damage = 1; } + }else if( target->type == BL_SKILL ){ + TBL_SKILL *su = (TBL_SKILL*)target; + if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) + md.damage = 1; } - //Card Fix, tsd side - if(tsd) //if player on player then it was already measured above - wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, flag.lh, wd.flag); + if(!(nk&NK_NO_ELEFIX)) + md.damage=battle->attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); - if( flag.infdef ) { //Plants receive 1 damage when hit - short class_ = status_get_class(target); - if( flag.hit || wd.damage > 0 ) - wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage - if( flag.lh && (flag.hit || wd.damage2 > 0) ) - wd.damage2 = wd.div_; - if( flag.hit && class_ == MOBID_EMPERIUM ) { - if(wd.damage2 > 0) { - wd.damage2 = battle->attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); - wd.damage2 = battle->calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); - } - else if(wd.damage > 0) { - wd.damage = battle->attr_fix(src,target,wd.damage,s_ele_,tstatus->def_ele, tstatus->ele_lv); - wd.damage = battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); - } - return wd; - } - if( !(battle_config.skill_min_damage&1) ) - //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex] - return wd; - } + md.damage=battle->calc_damage(src,target,&md,md.damage,skill_id,skill_lv); + if( map_flag_gvg2(target->m) ) + md.damage=battle->calc_gvg_damage(src,target,md.damage,md.div_,skill_id,skill_lv,md.flag); + else if( map[target->m].flag.battleground ) + md.damage=battle->calc_bg_damage(src,target,md.damage,md.div_,skill_id,skill_lv,md.flag); - if (sd) { - if (!flag.rh && flag.lh) { //Move lh damage to the rh - wd.damage = wd.damage2; - wd.damage2 = 0; - flag.rh=1; - flag.lh=0; - } else if(flag.rh && flag.lh) { //Dual-wield - if (wd.damage) { - if( (temp = pc->checkskill(sd,AS_RIGHT)) ) - ATK_RATER(50 + (temp * 10)) - else if( (temp = pc->checkskill(sd,KO_RIGHT)) ) - ATK_RATER(70 + (temp * 10)) - if(wd.damage < 1) wd.damage = 1; - } - if (wd.damage2) { - if( (temp = pc->checkskill(sd,AS_LEFT)) ) - ATK_RATEL(30 + (temp * 10)) - else if( (temp = pc->checkskill(sd,KO_LEFT)) ) - ATK_RATEL(50 + (temp * 10)) - if(wd.damage2 < 1) wd.damage2 = 1; + switch( skill_id ) { + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + if( md.damage == 1 ) break; + case RA_CLUSTERBOMB: + { + struct Damage wd; + wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); + md.damage += wd.damage; } - } else if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2) - temp = pc->checkskill(sd,TF_DOUBLE); - wd.damage2 = wd.damage * (1 + (temp * 2))/100; - - if(wd.damage && !wd.damage2) wd.damage2 = 1; - flag.lh = 1; - } - } - - if(!flag.rh && wd.damage) - wd.damage=0; - - if(!flag.lh && wd.damage2) - wd.damage2=0; - - if( wd.damage + wd.damage2 ) - { //There is a total damage value - if(!wd.damage2) - { - wd.damage = battle->calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv); - if( map_flag_gvg2(target->m) ) - wd.damage=battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); - else if( map[target->m].flag.battleground ) - wd.damage=battle->calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); - } - else if(!wd.damage) - { - wd.damage2 = battle->calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv); - if( map_flag_gvg2(target->m) ) - wd.damage2 = battle->calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); - else if( map[target->m].flag.battleground ) - wd.damage = battle->calc_bg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); - } - else - { - int d1 = wd.damage + wd.damage2,d2 = wd.damage2; - wd.damage = battle->calc_damage(src,target,&wd,d1,skill_id,skill_lv); - if( map_flag_gvg2(target->m) ) - wd.damage = battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); - else if( map[target->m].flag.battleground ) - wd.damage = battle->calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); - wd.damage2 = d2*100/d1 * wd.damage/100; - if(wd.damage > 1 && wd.damage2 < 1) wd.damage2 = 1; - wd.damage-=wd.damage2; - } - } - //Reject Sword bugreport:4493 by Daegaladh - if(wd.damage && tsc && tsc->data[SC_REJECTSWORD] && - (src->type!=BL_PC || ( - ((TBL_PC *)src)->weapontype1 == W_DAGGER || - ((TBL_PC *)src)->weapontype1 == W_1HSWORD || - ((TBL_PC *)src)->status.weapon == W_2HSWORD - )) && - rnd()%100 < tsc->data[SC_REJECTSWORD]->val2 - ) { - ATK_RATER(50) - status_fix_damage(target,src,wd.damage,clif->damage(target,src,iTimer->gettick(),0,0,wd.damage,0,0,0)); - clif->skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_REJECTSWORD]->val1,1); - if( --(tsc->data[SC_REJECTSWORD]->val3) <= 0 ) - status_change_end(target, SC_REJECTSWORD, INVALID_TIMER); - } - if(skill_id == ASC_BREAKER) { //Breaker's int-based damage (a misc attack?) - struct Damage md = battle->calc_misc_attack(src, target, skill_id, skill_lv, wflag); - wd.damage += md.damage; - } - if( sc ) { - //SG_FUSION hp penalty [Komurka] - if (sc->data[SC_FUSION]) { - int hp= sstatus->max_hp; - if (sd && tsd) { - hp = 8*hp/100; - if ((sstatus->hp * 100) <= (sstatus->max_hp * 20)) - hp = sstatus->hp; - } else - hp = 2*hp/100; //2% hp loss per hit - status_zap(src, hp, 0); - } - /** - * affecting non-skills - **/ - if( !skill_id ) { - /** - * RK Enchant Blade - **/ - if( sc->data[SC_ENCHANTBLADE] && sd && ( (flag.rh && sd->weapontype1) || (flag.lh && sd->weapontype2) ) ) { - //[( ( Skill Lv x 20 ) + 100 ) x ( casterBaseLevel / 150 )] + casterInt - ATK_ADD( ( sc->data[SC_ENCHANTBLADE]->val1*20+100 ) * status_get_lv(src) / 150 + status_get_int(src) ); + break; + case NJ_ZENYNAGE: + if( sd ) { + if ( md.damage > sd->status.zeny ) + md.damage = sd->status.zeny; + pc->payzeny(sd, md.damage,LOG_TYPE_STEAL,NULL); } - } - status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); - } - if( skill_id == LG_RAYOFGENESIS ) { - struct Damage md = battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag); - wd.damage += md.damage; + break; } - return wd; + return md; } /*========================================== - * battle_calc_magic_attack [DracoRPG] + * battle_calc_weapon_attack (by Skotlex) *------------------------------------------*/ -struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { - int i, nk; - short s_ele = 0; +struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag) +{ unsigned int skillratio = 100; //Skill dmg modifiers. + short temp=0; + short s_ele, s_ele_, t_class; + int i, nk; + bool n_ele = false; // non-elemental - TBL_PC *sd; -// TBL_PC *tsd; - struct status_change *sc, *tsc; - struct Damage ad; + struct map_session_data *sd, *tsd; + struct Damage wd; + struct status_change *sc = status_get_sc(src); + struct status_change *tsc = status_get_sc(target); struct status_data *sstatus = status_get_status_data(src); struct status_data *tstatus = status_get_status_data(target); struct { - unsigned imdef : 1; - unsigned infdef : 1; + unsigned hit : 1; //the attack Hit? (not a miss) + unsigned cri : 1; //Critical hit + unsigned idef : 1; //Ignore defense + unsigned idef2 : 1; //Ignore defense (left weapon) + unsigned pdef : 2; //Pierces defense (Investigate/Ice Pick) + unsigned pdef2 : 2; //1: Use def+def2/100, 2: Use def+def2/50 + unsigned infdef : 1; //Infinite defense (plants) + unsigned arrow : 1; //Attack is arrow-based + unsigned rh : 1; //Attack considers right hand (wd.damage) + unsigned lh : 1; //Attack considers left hand (wd.damage2) + unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that) +#ifdef RENEWAL + unsigned tdef : 1; //Total defence reduction +#endif } flag; - memset(&ad,0,sizeof(ad)); + memset(&wd,0,sizeof(wd)); memset(&flag,0,sizeof(flag)); if(src==NULL || target==NULL) { nullpo_info(NLP_MARK); - return ad; - } - //Initial Values - ad.damage = 1; - ad.div_=skill->get_num(skill_id,skill_lv); - ad.amotion=skill->get_inf(skill_id)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills. - ad.dmotion=tstatus->dmotion; - ad.blewcount = skill->get_blewcount(skill_id,skill_lv); - ad.flag=BF_MAGIC|BF_SKILL; - ad.dmg_lv=ATK_DEF; - nk = skill->get_nk(skill_id); - flag.imdef = nk&NK_IGNORE_DEF?1:0; - - sd = BL_CAST(BL_PC, src); -// tsd = BL_CAST(BL_PC, target); - sc = status_get_sc(src); - tsc = status_get_sc(target); - - //Initialize variables that will be used afterwards - s_ele = skill->get_ele(skill_id, skill_lv); - - if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element - s_ele = sstatus->rhw.ele; - if( sd ){ //Summoning 10 talisman will endow your weapon - ARR_FIND(1, 6, i, sd->talisman[i] >= 10); - if( i < 5 ) s_ele = i; - } - }else if (s_ele == -2) //Use status element - s_ele = status_get_attack_sc_element(src,status_get_sc(src)); - else if( s_ele == -3 ) //Use random element - s_ele = rnd()%ELE_MAX; - - if( skill_id == SO_PSYCHIC_WAVE ) { - if( sc && sc->count ) { - if( sc->data[SC_HEATER_OPTION] ) s_ele = sc->data[SC_HEATER_OPTION]->val4; - else if( sc->data[SC_COOLER_OPTION] ) s_ele = sc->data[SC_COOLER_OPTION]->val4; - else if( sc->data[SC_BLAST_OPTION] ) s_ele = sc->data[SC_BLAST_OPTION]->val3; - else if( sc->data[SC_CURSED_SOIL_OPTION] ) s_ele = sc->data[SC_CURSED_SOIL_OPTION]->val4; - } - } - - //Set miscellaneous data that needs be filled - if(sd) { - sd->state.arrow_atk = 0; - ad.blewcount += battle->blewcount_bonus(sd, skill_id); - } - - //Skill Range Criteria - ad.flag |= battle->range_type(src, target, skill_id, skill_lv); - flag.infdef=(tstatus->mode&MD_PLANT?1:0); - if( target->type == BL_SKILL){ - TBL_SKILL *su = (TBL_SKILL*)target; - if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) - flag.infdef = 1; - } - - switch(skill_id) { - case MG_FIREWALL: - case NJ_KAENSIN: - ad.dmotion = 0; //No flinch animation. - if ( tstatus->def_ele == ELE_FIRE || battle->check_undead(tstatus->race, tstatus->def_ele) ) - ad.blewcount = 0; //No knockback - break; - case PR_SANCTUARY: - ad.dmotion = 0; //No flinch animation. - break; + return wd; + } + //Initial flag + flag.rh=1; + flag.weapon=1; + flag.infdef=(tstatus->mode&MD_PLANT && skill_id != RA_CLUSTERBOMB +#ifdef RENEWAL + && skill_id != HT_FREEZINGTRAP +#endif + ?1:0); + if( target->type == BL_SKILL){ + TBL_SKILL *su = (TBL_SKILL*)target; + if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) + flag.infdef = 1; } - if (!flag.infdef) //No need to do the math for plants - { -#ifdef RENEWAL - ad.damage = 0; //reinitialize.. -#endif -//MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc -#define MATK_RATE( a ) { ad.damage= ad.damage*(a)/100; } -//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage -#define MATK_ADDRATE( a ) { ad.damage+= ad.damage*(a)/100; } -//Adds an absolute value to damage. 100 = +100 damage -#define MATK_ADD( a ) { ad.damage+= a; } - - switch (skill_id) - { //Calc base damage according to skill - case AL_HEAL: - case PR_BENEDICTIO: - case PR_SANCTUARY: - /** - * Arch Bishop - **/ - case AB_HIGHNESSHEAL: - ad.damage = skill->calc_heal(src, target, skill_id, skill_lv, false); - break; - case PR_ASPERSIO: - ad.damage = 40; - break; - case ALL_RESURRECTION: - case PR_TURNUNDEAD: - //Undead check is on skill_castend_damageid code. - #ifdef RENEWAL - i = 10*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src) - + 300 - 300*tstatus->hp/tstatus->max_hp; - #else - i = 20*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src) - + 200 - 200*tstatus->hp/tstatus->max_hp; - #endif - if(i > 700) i = 700; - if(rnd()%1000 < i && !(tstatus->mode&MD_BOSS)) - ad.damage = tstatus->hp; - else { - #ifdef RENEWAL - if (sstatus->matk_max > sstatus->matk_min) { - MATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); - } else { - MATK_ADD(sstatus->matk_min); - } - MATK_RATE(skill_lv); - #else - ad.damage = status_get_lv(src) + sstatus->int_ + skill_lv * 10; - #endif - } - break; - case PF_SOULBURN: - ad.damage = tstatus->sp * 2; - break; - /** - * Arch Bishop - **/ - case AB_RENOVATIO: - //Damage calculation from iRO wiki. [Jobbie] - ad.damage = (int)((15 * status_get_lv(src)) + (1.5 * sstatus->int_)); - break; - default: { - if (sstatus->matk_max > sstatus->matk_min) { - MATK_ADD(sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min)); - } else { - MATK_ADD(sstatus->matk_min); - } - - if (nk&NK_SPLASHSPLIT) { // Divide MATK in case of multiple targets skill - if(mflag>0) - ad.damage/= mflag; - else - ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); - } - - switch(skill_id){ - case MG_NAPALMBEAT: - skillratio += skill_lv*10-30; - break; - case MG_FIREBALL: - #ifdef RENEWAL - skillratio += 20*skill_lv; - #else - skillratio += skill_lv*10-30; - #endif - break; - case MG_SOULSTRIKE: - if (battle->check_undead(tstatus->race,tstatus->def_ele)) - skillratio += 5*skill_lv; - break; - case MG_FIREWALL: - skillratio -= 50; - break; - case MG_FIREBOLT: - case MG_COLDBOLT: - case MG_LIGHTNINGBOLT: - if ( sc && sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) { - skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech] - ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax] - ad.flag = BF_WEAPON|BF_SHORT; - ad.type = 0; - } - break; - case MG_THUNDERSTORM: - /** - * in Renewal Thunder Storm boost is 100% (in pre-re, 80%) - **/ - #ifndef RENEWAL - skillratio -= 20; - #endif - break; - case MG_FROSTDIVER: - skillratio += 10*skill_lv; - break; - case AL_HOLYLIGHT: - skillratio += 25; - if (sd && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_PRIEST) - skillratio *= 5; //Does 5x damage include bonuses from other skills? - break; - case AL_RUWACH: - skillratio += 45; - break; - case WZ_FROSTNOVA: - skillratio += (100+skill_lv*10)*2/3-100; - break; - case WZ_FIREPILLAR: - if (skill_lv > 10) - skillratio += 100; - else - skillratio -= 80; - break; - case WZ_SIGHTRASHER: - skillratio += 20*skill_lv; - break; - case WZ_WATERBALL: - skillratio += 30*skill_lv; - break; - case WZ_STORMGUST: - skillratio += 40*skill_lv; - break; - case HW_NAPALMVULCAN: - skillratio += 10*skill_lv-30; - break; - case SL_STIN: - skillratio += (tstatus->size!=SZ_SMALL?-99:10*skill_lv); //target size must be small (0) for full damage. - break; - case SL_STUN: - skillratio += (tstatus->size!=SZ_BIG?5*skill_lv:-99); //Full damage is dealt on small/medium targets - break; - case SL_SMA: - skillratio += -60 + status_get_lv(src); //Base damage is 40% + lv% - break; - case NJ_KOUENKA: - skillratio -= 10; - break; - case NJ_KAENSIN: - skillratio -= 50; - break; - case NJ_BAKUENRYU: - skillratio += 50*(skill_lv-1); - break; - case NJ_HYOUSYOURAKU: - skillratio += 50*skill_lv; - break; - case NJ_RAIGEKISAI: - skillratio += 60 + 40*skill_lv; - break; - case NJ_KAMAITACHI: - case NPC_ENERGYDRAIN: - skillratio += 100*skill_lv; - break; - case NPC_EARTHQUAKE: - skillratio += 100 +100*skill_lv +100*(skill_lv/2); - break; - #ifdef RENEWAL - case WZ_HEAVENDRIVE: - case WZ_METEOR: - skillratio += 25; - break; - case WZ_VERMILION: - { - int interval = 0, per = interval, ratio = per; - while( (per++) < skill_lv ){ - ratio += interval; - if(per%3==0) interval += 20; - } - if( skill_lv > 9 ) - ratio -= 10; - skillratio += ratio; - } - break; - case NJ_HUUJIN: - skillratio += 50; - break; - #else - case WZ_VERMILION: - skillratio += 20*skill_lv-20; - break; - #endif - /** - * Arch Bishop - **/ - case AB_JUDEX: - skillratio += 180 + 20 * skill_lv; - if (skill_lv > 4) skillratio += 20; - RE_LVL_DMOD(100); - break; - case AB_ADORAMUS: - skillratio += 400 + 100 * skill_lv; - RE_LVL_DMOD(100); - break; - case AB_DUPLELIGHT_MAGIC: - skillratio += 100 + 20 * skill_lv; - break; - /** - * Warlock - **/ - case WL_SOULEXPANSION: - skillratio += 300 + 100 * skill_lv + sstatus->int_; - RE_LVL_DMOD(100); - break; - case WL_FROSTMISTY: - skillratio += 100 + 100 * skill_lv; - RE_LVL_DMOD(100); - break; - case WL_JACKFROST: - if( tsc && tsc->data[SC_FREEZING] ){ - skillratio += 900 + 300 * skill_lv; - RE_LVL_DMOD(100); - }else{ - skillratio += 400 + 100 * skill_lv; - RE_LVL_DMOD(150); - } - break; - case WL_DRAINLIFE: - skillratio = 200 * skill_lv + sstatus->int_; - RE_LVL_DMOD(100); - break; - case WL_CRIMSONROCK: - skillratio += 1200 + 300 * skill_lv; - RE_LVL_DMOD(100); - break; - case WL_HELLINFERNO: - skillratio = 300 * skill_lv; - RE_LVL_DMOD(100); - // Shadow: MATK [{( Skill Level x 300 ) x ( Caster Base Level / 100 ) x 4/5 }] % - // Fire : MATK [{( Skill Level x 300 ) x ( Caster Base Level / 100 ) /5 }] % - if( mflag&ELE_DARK ){ skillratio *= 4; s_ele = ELE_DARK; } - skillratio /= 5; - break; - case WL_COMET: { - struct status_change * sc = status_get_sc(src); - if( sc ) - i = distance_xy(target->x, target->y, sc->comet_x, sc->comet_y); - else - i = 8; - if( i < 2 ) skillratio = 2500 + 500 * skill_lv; - else - if( i < 4 ) skillratio = 1600 + 400 * skill_lv; - else - if( i < 6 ) skillratio = 1200 + 300 * skill_lv; - else - skillratio = 800 + 200 * skill_lv; - } - break; - case WL_CHAINLIGHTNING_ATK: - skillratio += 100 + 300 * skill_lv; - RE_LVL_DMOD(100); - break; - case WL_EARTHSTRAIN: - skillratio += 1900 + 100 * skill_lv; - RE_LVL_DMOD(100); - break; - case WL_TETRAVORTEX_FIRE: - case WL_TETRAVORTEX_WATER: - case WL_TETRAVORTEX_WIND: - case WL_TETRAVORTEX_GROUND: - skillratio += 400 + 500 * skill_lv; - break; - case WL_SUMMON_ATK_FIRE: - case WL_SUMMON_ATK_WATER: - case WL_SUMMON_ATK_WIND: - case WL_SUMMON_ATK_GROUND: - skillratio = skill_lv * (status_get_lv(src) + ( sd ? sd->status.job_level : 50 ));// This is close to official, but lacking a little info to finalize. [Rytech] - RE_LVL_DMOD(100); - break; - case LG_RAYOFGENESIS: - { - int16 lv = skill_lv; - int bandingBonus = 0; - if( sc && sc->data[SC_BANDING] ) - bandingBonus = 200 * (sd ? skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),0) : 1); - skillratio = ((300 * skill_lv) + bandingBonus) * (sd ? sd->status.job_level : 1) / 25; - } - break; - case LG_SHIELDSPELL:// [(Casters Base Level x 4) + (Shield MDEF x 100) + (Casters INT x 2)] % - if( sd ) { - skillratio = status_get_lv(src) * 4 + sd->bonus.shieldmdef * 100 + status_get_int(src) * 2; - } else - skillratio += 1900; //2000% - break; - case WM_METALICSOUND: - skillratio += 120 * skill_lv + 60 * ( sd? pc->checkskill(sd, WM_LESSON) : 10 ) - 100; - break; - /*case WM_SEVERE_RAINSTORM: - skillratio += 50 * skill_lv; - break; - - WM_SEVERE_RAINSTORM just set a unit place, - refer to WM_SEVERE_RAINSTORM_MELEE to set the formula. - */ - case WM_REVERBERATION_MAGIC: - // MATK [{(Skill Level x 100) + 100} x Casters Base Level / 100] % - skillratio += 100 * (sd ? pc->checkskill(sd, WM_REVERBERATION) : 1); - RE_LVL_DMOD(100); - break; - case SO_FIREWALK: - skillratio = 300; - RE_LVL_DMOD(100); - if( sc && sc->data[SC_HEATER_OPTION] ) - skillratio += sc->data[SC_HEATER_OPTION]->val3; - break; - case SO_ELECTRICWALK: - skillratio = 300; - RE_LVL_DMOD(100); - if( sc && sc->data[SC_BLAST_OPTION] ) - skillratio += sd ? sd->status.job_level / 2 : 0; - break; - case SO_EARTHGRAVE: - skillratio = ( 200 * ( sd ? pc->checkskill(sd, SA_SEISMICWEAPON) : 10 ) + sstatus->int_ * skill_lv ); - RE_LVL_DMOD(100); - if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) - skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2; - break; - case SO_DIAMONDDUST: - skillratio = ( 200 * ( sd ? pc->checkskill(sd, SA_FROSTWEAPON) : 10 ) + sstatus->int_ * skill_lv ); - RE_LVL_DMOD(100); - if( sc && sc->data[SC_COOLER_OPTION] ) - skillratio += sc->data[SC_COOLER_OPTION]->val3; - break; - case SO_POISON_BUSTER: - skillratio += 1100 + 300 * skill_lv; - if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) - skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2; - break; - case SO_PSYCHIC_WAVE: - skillratio += -100 + skill_lv * 70 + (sstatus->int_ * 3); - RE_LVL_DMOD(100); - if( sc ){ - if( sc->data[SC_HEATER_OPTION] ) - skillratio += sc->data[SC_HEATER_OPTION]->val3; - else if(sc->data[SC_COOLER_OPTION] ) - skillratio += sc->data[SC_COOLER_OPTION]->val3; - else if(sc->data[SC_BLAST_OPTION] ) - skillratio += sc->data[SC_BLAST_OPTION]->val2; - else if(sc->data[SC_CURSED_SOIL_OPTION] ) - skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3; - } - break; - case SO_VARETYR_SPEAR: //MATK [{( Endow Tornado skill level x 50 ) + ( Caster INT x Varetyr Spear Skill level )} x Caster Base Level / 100 ] % - skillratio = status_get_int(src) * skill_lv + ( sd ? pc->checkskill(sd, SA_LIGHTNINGLOADER) * 50 : 0 ); - RE_LVL_DMOD(100); - if( sc && sc->data[SC_BLAST_OPTION] ) - skillratio += sd ? sd->status.job_level * 5 : 0; - break; - case SO_CLOUD_KILL: - skillratio += -100 + skill_lv * 40; - RE_LVL_DMOD(100); - if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) - skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2; - break; - case GN_DEMONIC_FIRE: - if( skill_lv > 20) - { // Fire expansion Lv.2 - skillratio += 110 + 20 * (skill_lv - 20) + status_get_int(src) * 3; // Need official INT bonus. [LimitLine] - } - else if( skill_lv > 10 ) - { // Fire expansion Lv.1 - skillratio += 110 + 20 * (skill_lv - 10) / 2; - } - else - skillratio += 110 + 20 * skill_lv; - break; - // Magical Elemental Spirits Attack Skills - case EL_FIRE_MANTLE: - case EL_WATER_SCREW: - skillratio += 900; - break; - case EL_FIRE_ARROW: - case EL_ROCK_CRUSHER_ATK: - skillratio += 200; - break; - case EL_FIRE_BOMB: - case EL_ICE_NEEDLE: - case EL_HURRICANE_ATK: - skillratio += 400; - break; - case EL_FIRE_WAVE: - case EL_TYPOON_MIS_ATK: - skillratio += 1100; - break; - case MH_ERASER_CUTTER: - if(skill_lv%2) skillratio += 400; //600:800:1000 - else skillratio += 700; //1000:1200 - skillratio += 100 * skill_lv; - break; - case MH_XENO_SLASHER: - if(skill_lv%2) skillratio += 350 + 50 * skill_lv; //500:600:700 - else skillratio += 400 + 100 * skill_lv; //700:900 - break; - case MH_HEILIGE_STANGE: - skillratio += 400 + 250 * skill_lv; - break; - case MH_POISON_MIST: - skillratio += 100 * skill_lv; - break; - } + //Initial Values + wd.type=0; //Normal attack + wd.div_=skill_id?skill->get_num(skill_id,skill_lv):1; + wd.amotion=(skill_id && skill->get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. + if(skill_id == KN_AUTOCOUNTER) + wd.amotion >>= 1; + wd.dmotion=tstatus->dmotion; + wd.blewcount=skill->get_blewcount(skill_id,skill_lv); + wd.flag = BF_WEAPON; //Initial Flag + wd.flag |= (skill_id||wflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish] + wd.dmg_lv=ATK_DEF; //This assumption simplifies the assignation later + nk = skill->get_nk(skill_id); + if( !skill_id && wflag ) //If flag, this is splash damage from Baphomet Card and it always hits. + nk |= NK_NO_CARDFIX_ATK|NK_IGNORE_FLEE; + flag.hit = nk&NK_IGNORE_FLEE?1:0; + flag.idef = flag.idef2 = nk&NK_IGNORE_DEF?1:0; + flag.tdef = 0; - MATK_RATE(skillratio); + if (sc && !sc->count) + sc = NULL; //Skip checking as there are no status changes active. + if (tsc && !tsc->count) + tsc = NULL; //Skip checking as there are no status changes active. - //Constant/misc additions from skills - if (skill_id == WZ_FIREPILLAR) - MATK_ADD(50); - } - } -#ifndef HMAP_ZONE_DAMAGE_CAP_TYPE - if( target && skill_id ) { - for(i = 0; i < map[target->m].zone->capped_skills_count; i++) { - if( skill_id == map[target->m].zone->capped_skills[i]->nameid && (map[target->m].zone->capped_skills[i]->type & target->type) ) { - if( target->type == BL_MOB && map[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { - if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) ) - continue; - if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) ) - continue; - } - if( ad.damage > map[target->m].zone->capped_skills[i]->cap ) - ad.damage = map[target->m].zone->capped_skills[i]->cap; - if( ad.damage2 > map[target->m].zone->capped_skills[i]->cap ) - ad.damage2 = map[target->m].zone->capped_skills[i]->cap; - break; + sd = BL_CAST(BL_PC, src); + tsd = BL_CAST(BL_PC, target); + + if(sd) + wd.blewcount += battle->blewcount_bonus(sd, skill_id); + + //Set miscellaneous data that needs be filled regardless of hit/miss + if( + (sd && sd->state.arrow_atk) || + (!sd && ((skill_id && skill->get_ammotype(skill_id)) || sstatus->rhw.range>3)) + ) + flag.arrow = 1; + + if(skill_id) { + wd.flag |= battle->range_type(src, target, skill_id, skill_lv); + switch(skill_id) { + case MO_FINGEROFFENSIVE: + if(sd) { + if (battle_config.finger_offensive_type) + wd.div_ = 1; + else + wd.div_ = sd->spiritball_old; } - } - } + break; + case HT_PHANTASMIC: + //Since these do not consume ammo, they need to be explicitly set as arrow attacks. + flag.arrow = 1; + break; +#ifndef RENEWAL + case PA_SHIELDCHAIN: + case CR_SHIELDBOOMERANG: #endif + case LG_SHIELDPRESS: + case LG_EARTHDRIVE: + flag.weapon = 0; + break; + + case KN_PIERCE: + case ML_PIERCE: + wd.div_= (wd.div_>0?tstatus->size+1:-(tstatus->size+1)); + break; + + case TF_DOUBLE: //For NPC used skill. + case GS_CHAINACTION: + wd.type = 0x08; + break; + + case GS_GROUNDDRIFT: + case KN_SPEARSTAB: + case KN_BOWLINGBASH: + case MS_BOWLINGBASH: + case MO_BALKYOUNG: + case TK_TURNKICK: + wd.blewcount=0; + break; + + case KN_AUTOCOUNTER: + wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL; + break; + + case NPC_CRITICALSLASH: + case LG_PINPOINTATTACK: + flag.cri = 1; //Always critical skill. + break; + + case LK_SPIRALPIERCE: + if (!sd) wd.flag=(wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC; + break; + + case MO_INVESTIGATE: + flag.pdef = flag.pdef2 = 2; + break; + + case RA_AIMEDBOLT: + if( tsc && (tsc->data[SC_WUGBITE] || tsc->data[SC_ANKLESNARE] || tsc->data[SC_ELECTRICSHOCKER]) ) + wd.div_ = tstatus->size + 2 + ( (rnd()%100 < 50-tstatus->size*10) ? 1 : 0 ); + break; #ifdef RENEWAL - ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); + case HW_MAGICCRASHER: + flag.tdef = 1; + break; #endif - if(sd) { - //Damage bonuses - if ((i = pc->skillatk_bonus(sd, skill_id))) - ad.damage += ad.damage*i/100; - - if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) - MATK_RATE(i); + } + } else //Range for normal attacks. + wd.flag |= flag.arrow?BF_LONG:BF_SHORT; + if ( (!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2 ) + { //Check for Lucky Dodge + wd.type=0x0b; + wd.dmg_lv=ATK_LUCKY; + if (wd.div_ < 0) wd.div_*=-1; + return wd; + } - //Ignore Defense? - if (!flag.imdef && ( - sd->bonus.ignore_mdef_ele & ( 1 << tstatus->def_ele ) || - sd->bonus.ignore_mdef_race & ( 1 << tstatus->race ) || - sd->bonus.ignore_mdef_race & ( is_boss(target) ? 1 << RC_BOSS : 1 << RC_NONBOSS ) - )) - flag.imdef = 1; + t_class = status_get_class(target); + s_ele = s_ele_ = skill->get_ele(skill_id, skill_lv); + if( !skill_id || s_ele == -1 ) + { //Take weapon's element + s_ele = sstatus->rhw.ele; + s_ele_ = sstatus->lhw.ele; + if( sd ){ //Summoning 10 charm will endow your weapon. + ARR_FIND(1, 6, i, sd->charm[i] >= 10); + if( i < 5 ) s_ele = s_ele_ = i; + } + if( flag.arrow && sd && sd->bonus.arrow_ele ) + s_ele = sd->bonus.arrow_ele; + if( battle_config.attack_attr_none&src->type ) + n_ele = true; //Weapon's element is "not elemental" + } + else if( s_ele == -2 ) //Use enchantment's element + s_ele = s_ele_ = status_get_attack_sc_element(src,sc); + else if( s_ele == -3 ) //Use random element + s_ele = s_ele_ = rnd()%ELE_MAX; + switch( skill_id ) + { + case GS_GROUNDDRIFT: + s_ele = s_ele_ = wflag; //element comes in flag. + break; + case LK_SPIRALPIERCE: + if (!sd) n_ele = false; //forced neutral for monsters + break; + } + + if (!(nk & NK_NO_ELEFIX) && !n_ele) + if (src->type == BL_HOM) + n_ele = true; //skill is "not elemental" + if (sc && sc->data[SC_GOLDENE_FERSE] && ((!skill_id && (rnd() % 100 < sc->data[SC_GOLDENE_FERSE]->val4)) || skill_id == MH_STAHL_HORN)) { + s_ele = s_ele_ = ELE_HOLY; + n_ele = false; + } + + if(!skill_id) + { //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2) + if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0) + { + flag.rh=0; + flag.lh=1; } + if (sstatus->lhw.atk) + flag.lh=1; + } - if(!flag.imdef){ - defType mdef = tstatus->mdef; - int mdef2= tstatus->mdef2; -#ifdef RENEWAL - if(tsc && tsc->data[SC_ASSUMPTIO]) - mdef <<= 1; // only eMDEF is doubled -#endif - if(sd) { - i = sd->ignore_mdef[is_boss(target)?RC_BOSS:RC_NONBOSS]; - i+= sd->ignore_mdef[tstatus->race]; - if (i) - { - if (i > 100) i = 100; - mdef -= mdef * i/100; - //mdef2-= mdef2* i/100; + if( sd && !skill_id ) { //Check for double attack. + if( ( ( skill_lv = pc->checkskill(sd,TF_DOUBLE) ) > 0 && sd->weapontype1 == W_DAGGER ) + || ( sd->bonus.double_rate > 0 && sd->weapontype1 != W_FIST ) //Will fail bare-handed + || ( sc && sc->data[SC_KAGEMUSYA] && sd->weapontype1 != W_FIST )) // Need confirmation + { //Success chance is not added, the higher one is used [Skotlex] + if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) ) + { + wd.div_ = skill->get_num(TF_DOUBLE,skill_lv?skill_lv:1); + wd.type = 0x08; + } + } + else if( sd->weapontype1 == W_REVOLVER && (skill_lv = pc->checkskill(sd,GS_CHAINACTION)) > 0 && rnd()%100 < 5*skill_lv ) + { + wd.div_ = skill->get_num(GS_CHAINACTION,skill_lv); + wd.type = 0x08; + } + else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW + && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1){ + int chance = rand()%100; + wd.type = 0x08; + switch(sc->data[SC_FEARBREEZE]->val1){ + case 5: + if( chance < 3){// 3 % chance to attack 5 times. + wd.div_ = 5; + break; + } + case 4: + if( chance < 7){// 6 % chance to attack 4 times. + wd.div_ = 4; + break; + } + case 3: + if( chance < 10){// 9 % chance to attack 3 times. + wd.div_ = 3; + break; + } + case 2: + case 1: + if( chance < 13){// 12 % chance to attack 2 times. + wd.div_ = 2; + break; + } } - } - #ifdef RENEWAL - /** - * RE MDEF Reduction - * Damage = Magic Attack * (1000+eMDEF)/(1000+eMDEF) - sMDEF - **/ - ad.damage = ad.damage * (1000 + mdef) / (1000 + mdef * 10) - mdef2; - #else - if(battle_config.magic_defense_type) - ad.damage = ad.damage - mdef*battle_config.magic_defense_type - mdef2; - else - ad.damage = ad.damage * (100-mdef)/100 - mdef2; - #endif + wd.div_ = min(wd.div_,sd->status.inventory[i].amount); + sc->data[SC_FEARBREEZE]->val4 = wd.div_-1; } + } - if (skill_id == NPC_EARTHQUAKE) - { //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex] - //Also divide the extra bonuses from atk2 based on the number in range [Kevin] - if(mflag>0) - ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag; - else - ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); + //Check for critical + if( !flag.cri && !(wd.type&0x08) && sstatus->cri && + (!skill_id || + skill_id == KN_AUTOCOUNTER || + skill_id == SN_SHARPSHOOTING || skill_id == MA_SHARPSHOOTING || + skill_id == NJ_KIRIKAGE)) + { + short cri = sstatus->cri; + if (sd) + { + cri+= sd->critaddrace[tstatus->race]; + if(flag.arrow) + cri += sd->bonus.arrow_cri; } + if( sc && sc->data[SC_CAMOUFLAGE] ) + cri += 10 * (10-sc->data[SC_CAMOUFLAGE]->val4); +#ifndef RENEWAL + //The official equation is *2, but that only applies when sd's do critical. + //Therefore, we use the old value 3 on cases when an sd gets attacked by a mob + cri -= tstatus->luk*(!sd&&tsd?3:2); +#else + cri -= status_get_lv(target) / 15 + 2 * status_get_luk(target); +#endif - if(ad.damage<1) - ad.damage=1; - else if(sc){//only applies when hit - // TODO: there is another factor that contribute with the damage and need to be formulated. [malufett] - switch(skill_id){ - case MG_LIGHTNINGBOLT: - case MG_THUNDERSTORM: - case MG_FIREBOLT: - case MG_FIREWALL: - case MG_COLDBOLT: - case MG_FROSTDIVER: - case WZ_EARTHSPIKE: - case WZ_HEAVENDRIVE: - if(sc->data[SC_GUST_OPTION] || sc->data[SC_PETROLOGY_OPTION] - || sc->data[SC_PYROTECHNIC_OPTION] || sc->data[SC_AQUAPLAY_OPTION]) - ad.damage += (6 + sstatus->int_/4) + max(sstatus->dex-10,0)/30; - break; - } + if( tsc && tsc->data[SC_SLEEP] ) { + cri <<= 1; } - - if (!(nk&NK_NO_ELEFIX)) - ad.damage=battle->attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); - - if( skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS ) - { //Apply the physical part of the skill's damage. [Skotlex] - struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); - ad.damage = battle->attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40*skill_lv)/100; - if( src == target ) - { - if( src->type == BL_PC ) - ad.damage = ad.damage/2; + switch (skill_id) { + case KN_AUTOCOUNTER: + if(battle_config.auto_counter_type && + (battle_config.auto_counter_type&src->type)) + flag.cri = 1; else - ad.damage = 0; - } + cri <<= 1; + break; + case SN_SHARPSHOOTING: + case MA_SHARPSHOOTING: + cri += 200; + break; + case NJ_KIRIKAGE: + cri += 250 + 50*skill_lv; + break; } - + if(tsd && tsd->bonus.critical_def) + cri = cri * ( 100 - tsd->bonus.critical_def ) / 100; + if (rnd()%1000 < cri) + flag.cri = 1; + } + if (flag.cri) { + wd.type = 0x0a; #ifndef RENEWAL - ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); + flag.idef = flag.idef2 = #endif + flag.hit = 1; + } else { //Check for Perfect Hit + if(sd && sd->bonus.perfect_hit > 0 && rnd()%100 < sd->bonus.perfect_hit) + flag.hit = 1; + if (sc && sc->data[SC_FUSION]) { + flag.hit = 1; //SG_FUSION always hit [Komurka] + flag.idef = flag.idef2 = 1; //def ignore [Komurka] + } + if( !flag.hit ) + switch(skill_id) + { + case AS_SPLASHER: + if( !wflag ) // Always hits the one exploding. + flag.hit = 1; + break; + case CR_SHIELDBOOMERANG: + if( sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_CRUSADER ) + flag.hit = 1; + break; + } + if (tsc && !flag.hit && tsc->opt1 && tsc->opt1 != OPT1_STONEWAIT && tsc->opt1 != OPT1_BURNING) + flag.hit = 1; } - damage_div_fix(ad.damage, ad.div_); - - if (flag.infdef && ad.damage) - ad.damage = ad.damage>0?1:-1; - - ad.damage=battle->calc_damage(src,target,&ad,ad.damage,skill_id,skill_lv); - if( map_flag_gvg2(target->m) ) - ad.damage=battle->calc_gvg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); - else if( map[target->m].flag.battleground ) - ad.damage=battle->calc_bg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); + if (!flag.hit) + { //Hit/Flee calculation + short + flee = tstatus->flee, +#ifdef RENEWAL + hitrate = 0; //Default hitrate +#else + hitrate = 80; //Default hitrate +#endif - switch( skill_id ) { /* post-calc modifiers */ - case SO_VARETYR_SPEAR: { // Physical damage. - struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); - if(!flag.infdef && ad.damage > 1) - ad.damage += wd.damage; - break; + if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) { + unsigned char attacker_count; //256 max targets should be a sane max + attacker_count = unit_counttargeted(target); + if(attacker_count >= battle_config.agi_penalty_count) { + if (battle_config.agi_penalty_type == 1) + flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; + else //asume type 2: absolute reduction + flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; + if(flee < 1) flee = 1; + } } - //case HM_ERASER_CUTTER: - } - return ad; -} - -/*========================================== - * Calculate Misc dammage for skill_id - *------------------------------------------*/ -struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { - int temp; - short i, nk; - short s_ele; + hitrate+= sstatus->hit - flee; - struct map_session_data *sd, *tsd; - struct Damage md; //DO NOT CONFUSE with md of mob_data! - struct status_data *sstatus = status_get_status_data(src); - struct status_data *tstatus = status_get_status_data(target); + if(wd.flag&BF_LONG && !skill_id && //Fogwall's hit penalty is only for normal ranged attacks. + tsc && tsc->data[SC_FOGWALL]) + hitrate -= 50; - memset(&md,0,sizeof(md)); + if(sd && flag.arrow) + hitrate += sd->bonus.arrow_hit; +#ifdef RENEWAL + if( sd ) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window + hitrate += pc->checkskill(sd,AC_VULTURE); +#endif + if(skill_id) + switch(skill_id) + { //Hit skill modifiers + //It is proven that bonus is applied on final hitrate, not hit. + case SM_BASH: + case MS_BASH: + hitrate += hitrate * 5 * skill_lv / 100; + break; + case MS_MAGNUM: + case SM_MAGNUM: + hitrate += hitrate * 10 * skill_lv / 100; + break; + case KN_AUTOCOUNTER: + case PA_SHIELDCHAIN: + case NPC_WATERATTACK: + case NPC_GROUNDATTACK: + case NPC_FIREATTACK: + case NPC_WINDATTACK: + case NPC_POISONATTACK: + case NPC_HOLYATTACK: + case NPC_DARKNESSATTACK: + case NPC_UNDEADATTACK: + case NPC_TELEKINESISATTACK: + case NPC_BLEEDING: + hitrate += hitrate * 20 / 100; + break; + case KN_PIERCE: + case ML_PIERCE: + hitrate += hitrate * 5 * skill_lv / 100; + break; + case AS_SONICBLOW: + if(sd && pc->checkskill(sd,AS_SONICACCEL)>0) + hitrate += hitrate * 50 / 100; + break; + case MC_CARTREVOLUTION: + case GN_CART_TORNADO: + case GN_CARTCANNON: + if( sd && pc->checkskill(sd, GN_REMODELING_CART) ) + hitrate += pc->checkskill(sd, GN_REMODELING_CART) * 4; + break; + case GC_VENOMPRESSURE: + hitrate += 10 + 4 * skill_lv; + break; + } - if( src == NULL || target == NULL ){ - nullpo_info(NLP_MARK); - return md; - } + if( sd ) { + // Weaponry Research hidden bonus + if ((temp = pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0) + hitrate += hitrate * ( 2 * temp ) / 100; - //Some initial values - md.amotion=skill->get_inf(skill_id)&INF_GROUND_SKILL?0:sstatus->amotion; - md.dmotion=tstatus->dmotion; - md.div_=skill->get_num( skill_id,skill_lv ); - md.blewcount=skill->get_blewcount(skill_id,skill_lv); - md.dmg_lv=ATK_DEF; - md.flag=BF_MISC|BF_SKILL; + if( (sd->status.weapon == W_1HSWORD || sd->status.weapon == W_DAGGER) && + (temp = pc->checkskill(sd, GN_TRAINING_SWORD))>0 ) + hitrate += 3 * temp; + } - nk = skill->get_nk(skill_id); + hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); +#ifdef RENEWAL + if( !sd ) + hitrate = cap_value(hitrate, 5, 95); +#endif + if(rnd()%100 >= hitrate) + wd.dmg_lv = ATK_FLEE; + else + flag.hit = 1; + } //End hit/miss calculation - sd = BL_CAST(BL_PC, src); - tsd = BL_CAST(BL_PC, target); + if (flag.hit && !flag.infdef) //No need to do the math for plants + { //Hitting attack - if(sd) { - sd->state.arrow_atk = 0; - md.blewcount += battle->blewcount_bonus(sd, skill_id); - } +//Assuming that 99% of the cases we will not need to check for the flag.rh... we don't. +//ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc +#define ATK_RATE( a ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(a)/100; } +#define ATK_RATE2( a , b ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; } +#define ATK_RATER(a){ wd.damage = wd.damage*(a)/100;} +#define ATK_RATEL(a){ wd.damage2 = wd.damage2*(a)/100;} +//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage +#define ATK_ADDRATE( a ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(a)/100; } +#define ATK_ADDRATE2( a , b ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; } +//Adds an absolute value to damage. 100 = +100 damage +#define ATK_ADD( a ) { wd.damage+= a; if (flag.lh) wd.damage2+= a; } +#define ATK_ADD2( a , b ) { wd.damage+= a; if (flag.lh) wd.damage2+= b; } - s_ele = skill->get_ele(skill_id, skill_lv); - if (s_ele < 0 && s_ele != -3) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex] - s_ele = ELE_NEUTRAL; - else if (s_ele == -3) //Use random element - s_ele = rnd()%ELE_MAX; + switch (skill_id) + { //Calc base damage according to skill + case PA_SACRIFICE: + wd.damage = sstatus->max_hp* 9/100; + wd.damage2 = 0; + break; + +#ifdef RENEWAL + case MO_EXTREMITYFIST: // [malufett] + wd.damage = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|8, wd.flag); + // first value is still not confirm. + wd.damage = status_get_sp(src) + 10 * status_get_sp(src) * wd.damage / 100 + 8 * wd.damage; + flag.tdef = 1; + break; + case NJ_ISSEN: // [malufett] + { + short totaldef = status_get_total_def(target); + i = 0; + wd.damage = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), wd.flag); + if( sc && sc->data[SC_NJ_BUNSINJYUTSU] && (i=sc->data[SC_NJ_BUNSINJYUTSU]->val2) > 0 ) + wd.div_ = ~( i++ + 2 ) + 1; + wd.damage *= sstatus->hp * skill_lv; + wd.damage = wd.damage / sstatus->max_hp + sstatus->hp + i * (wd.damage / sstatus->max_hp + sstatus->hp) / 5; + ATK_ADD(-totaldef); + if( is_boss(target) ) + ATK_RATE(50); + flag.idef = 1; + } +#else + + wd.damage = 40*sstatus->str +skill_lv*(sstatus->hp/10 + 35); + wd.damage2 = 0; +#endif + break; +#ifndef RENEWAL + case LK_SPIRALPIERCE: + case ML_SPIRALPIERCE: + if (sd) { + short index = sd->equip_index[EQI_HAND_R]; - //Skill Range Criteria - md.flag |= battle->range_type(src, target, skill_id, skill_lv); + if (index >= 0 && + sd->inventory_data[index] && + sd->inventory_data[index]->type == IT_WEAPON) + wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight + } else + wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2 - switch( skill_id ) - { + ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only. + i = sstatus->str/10; + i*=i; + ATK_ADD(i); //Add str bonus. + switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection? + case SZ_SMALL: //Small: 125% + ATK_RATE(125); + break; + //case SZ_MEDIUM: //Medium: 100% + case SZ_BIG: //Large: 75% + ATK_RATE(75); + break; + } + break; +#endif + case CR_SHIELDBOOMERANG: + case PA_SHIELDCHAIN: + case LG_SHIELDPRESS: + case LG_EARTHDRIVE: + wd.damage = sstatus->batk; + if (sd) { + short index = sd->equip_index[EQI_HAND_L]; + + if (index >= 0 && + sd->inventory_data[index] && + sd->inventory_data[index]->type == IT_ARMOR) + ATK_ADD(sd->inventory_data[index]->weight/10); + } else + ATK_ADD(sstatus->rhw.atk2); //Else use Atk2 + break; + case HFLI_SBR44: //[orn] + if(src->type == BL_HOM) { + wd.damage = ((TBL_HOM*)src)->homunculus.intimacy ; + break; + } + default: + { + i = (flag.cri #ifdef RENEWAL - case HT_LANDMINE: - case MA_LANDMINE: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - md.damage = skill_lv * sstatus->dex * (3+status_get_lv(src)/100) * (1+sstatus->int_/35); - md.damage += md.damage * (rnd()%20-10) / 100; - md.damage += 40 * (sd?pc->checkskill(sd,RA_RESEARCHTRAP):0); - break; + || (sc && sc->data[SC_MAXIMIZEPOWER]) +#endif + ?1:0)| + (flag.arrow?2:0)| +#ifndef RENEWAL + (skill_id == HW_MAGICCRASHER?4:0)| + (skill_id == MO_EXTREMITYFIST?8:0)| +#endif + (!skill_id && sc && sc->data[SC_HLIF_CHANGE]?4:0)| + (sc && sc->data[SC_WEAPONPERFECT]?8:0); + if (flag.arrow && sd) + switch(sd->status.weapon) { + case W_BOW: + case W_REVOLVER: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + break; + default: + i |= 16; // for ex. shuriken must not be influenced by DEX + } +#ifdef RENEWAL + wd.damage = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, i, wd.flag); + wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon); + if (flag.lh){ + wd.damage2 = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_L, i, wd.flag); + wd.damage2 = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage2, wd.div_, 1, flag.weapon); + } #else - case HT_LANDMINE: - case MA_LANDMINE: - md.damage=skill_lv*(sstatus->dex+75)*(100+sstatus->int_)/100; - break; - case HT_BLASTMINE: - md.damage=skill_lv*(sstatus->dex/2+50)*(100+sstatus->int_)/100; - break; - case HT_CLAYMORETRAP: - md.damage=skill_lv*(sstatus->dex/2+75)*(100+sstatus->int_)/100; - break; + wd.damage = battle->calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i); + if (flag.lh) + wd.damage2 = battle->calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i); #endif - case HT_BLITZBEAT: - case SN_FALCONASSAULT: - //Blitz-beat Damage. - if(!sd || (temp = pc->checkskill(sd,HT_STEELCROW)) <= 0) - temp=0; - md.damage=(sstatus->dex/10+sstatus->int_/2+temp*3+40)*2; - if(mflag > 1) //Autocasted Blitz. - nk|=NK_SPLASHSPLIT; + if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets + if(wflag>0) + wd.damage/= wflag; + else + ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); + } - if (skill_id == SN_FALCONASSAULT) { - //Div fix of Blitzbeat - temp = skill->get_num(HT_BLITZBEAT, 5); - damage_div_fix(md.damage, temp); + //Add any bonuses that modify the base baseatk+watk (pre-skills) + if(sd) { + if (sd->bonus.atk_rate) + ATK_ADDRATE(sd->bonus.atk_rate); - //Falcon Assault Modifier - md.damage=md.damage*(150+70*skill_lv)/100; - } - break; - case TF_THROWSTONE: - md.damage=50; - break; - case BA_DISSONANCE: - md.damage=30+skill_lv*10; - if (sd) - md.damage+= 3*pc->checkskill(sd,BA_MUSICALLESSON); - break; - case NPC_SELFDESTRUCTION: - md.damage = sstatus->hp; - break; - case NPC_SMOKING: - md.damage=3; - break; - case NPC_DARKBREATH: - md.damage = 500 + (skill_lv-1)*1000 + rnd()%1000; - if(md.damage > 9999) md.damage = 9999; - break; - case PA_PRESSURE: - md.damage=500+300*skill_lv; - break; - case PA_GOSPEL: - md.damage = 1+rnd()%9999; - break; - case CR_ACIDDEMONSTRATION: // updated the formula based on a Japanese formula found to be exact [Reddozen] - if(tstatus->vit+sstatus->int_) //crash fix - md.damage = (int)(7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_))); - else - md.damage = 0; - if (tsd) md.damage>>=1; - if (md.damage < 0 || md.damage > INT_MAX>>1) - //Overflow prevention, will anyone whine if I cap it to a few billion? - //Not capped to INT_MAX to give some room for further damage increase. - md.damage = INT_MAX>>1; - break; - case NJ_ZENYNAGE: - case KO_MUCHANAGE: - md.damage = skill->get_zeny(skill_id ,skill_lv); - if (!md.damage) md.damage = 2; - md.damage = rand()%md.damage + md.damage / (skill_id==NJ_ZENYNAGE?1:2) ; - if (is_boss(target)) - md.damage=md.damage / (skill_id==NJ_ZENYNAGE?3:2); - else if (tsd) // need confirmation for KO_MUCHANAGE - md.damage=md.damage/2; - break; - case GS_FLING: - md.damage = sd?sd->status.job_level:status_get_lv(src); - break; - case HVAN_EXPLOSION: //[orn] - md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100; - break ; - case ASC_BREAKER: - md.damage = 500+rnd()%500 + 5*skill_lv * sstatus->int_; - nk|=NK_IGNORE_FLEE|NK_NO_ELEFIX; //These two are not properties of the weapon based part. - break; - case HW_GRAVITATION: - md.damage = 200+200*skill_lv; - md.dmotion = 0; //No flinch animation. - break; - case NPC_EVILLAND: - md.damage = skill->calc_heal(src,target,skill_id,skill_lv,false); - break; - case RK_DRAGONBREATH: - md.damage = ((status_get_hp(src) / 50) + (status_get_max_sp(src) / 4)) * skill_lv; - RE_LVL_MDMOD(150); - if (sd) md.damage = md.damage * (100 + 5 * (pc->checkskill(sd,RK_DRAGONTRAINING) - 1)) / 100; - md.flag |= BF_LONG|BF_WEAPON; - break; - /** - * Ranger - **/ - case RA_CLUSTERBOMB: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - md.damage = skill_lv * sstatus->dex + sstatus->int_ * 5 ; - RE_LVL_TMDMOD(); - if(sd) - { - int researchskill_lv = pc->checkskill(sd,RA_RESEARCHTRAP); - if(researchskill_lv) - md.damage = md.damage * 20 * researchskill_lv / (skill_id == RA_CLUSTERBOMB?50:100); - else - md.damage = 0; - }else - md.damage = md.damage * 200 / (skill_id == RA_CLUSTERBOMB?50:100); + if(flag.cri && sd->bonus.crit_atk_rate) + ATK_ADDRATE(sd->bonus.crit_atk_rate); + + if(sd->status.party_id && (temp=pc->checkskill(sd,TK_POWER)) > 0){ + if( (i = party_foreachsamemap(party->sub_count, sd, 0)) > 1 ) // exclude the player himself [Inkfish] + ATK_ADDRATE(2*temp*i); + } + } + break; + } //End default case + } //End switch(skill_id) - break; - /** - * Mechanic - **/ - case NC_SELFDESTRUCTION: + //Skill damage modifiers that stack linearly + if( sd && sd->status.weapon == W_KATAR && (i=pc->checkskill(sd,ASC_KATAR)) > 0 ) + skillratio += skillratio * (13 + 2 * i) / 100; + if(sc && skill_id != PA_SACRIFICE) { - short totaldef = tstatus->def2 + (short)status_get_def(target); - md.damage = ( (sd?pc->checkskill(sd,NC_MAINFRAME):10) + 8 ) * ( skill_lv + 1 ) * ( status_get_sp(src) + sstatus->vit ); - RE_LVL_MDMOD(100); - md.damage += status_get_hp(src) - totaldef; + if(sc->data[SC_OVERTHRUST]) + skillratio += sc->data[SC_OVERTHRUST]->val3; + if(sc->data[SC_OVERTHRUSTMAX]) + skillratio += sc->data[SC_OVERTHRUSTMAX]->val2; + if (sc->data[SC_BERSERK] || sc->data[SC_SATURDAY_NIGHT_FEVER] || sc->data[SC__BLOODYLUST]) + skillratio += 100; +#ifdef RENEWAL + if( sc->data[SC_TRUESIGHT] ) + skillratio += 2*sc->data[SC_TRUESIGHT]->val1; + if( sc->data[SC_LKCONCENTRATION] ) + skillratio += sc->data[SC_LKCONCENTRATION]->val2; +#endif + if( sc->data[SC_UNLIMIT] && wd.flag&BF_LONG ) + ATK_ADD( 50 * sc->data[SC_UNLIMIT]->val1 ); } - break; - case GN_THORNS_TRAP: - md.damage = 100 + 200 * skill_lv + sstatus->int_; - break; - case GN_HELLS_PLANT_ATK: - //[{( Hell Plant Skill Level x Casters Base Level ) x 10 } + {( Casters INT x 7 ) / 2 } x { 18 + ( Casters Job Level / 4 )] x ( 5 / ( 10 - Summon Flora Skill Level )) - md.damage = ( skill_lv * status_get_lv(src) * 10 ) + ( sstatus->int_ * 7 / 2 ) * ( 18 + (sd?sd->status.job_level:0) / 4 ) * ( 5 / (10 - (sd?pc->checkskill(sd,AM_CANNIBALIZE):0)) ); - break; - case KO_HAPPOKUNAI: - { - struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); - short totaldef = tstatus->def2 + (short)status_get_def(target); - md.damage = wd.damage * 60 * (5 + skill_lv) / 100; - md.damage -= totaldef; + if( tsc && skill_id != PA_SACRIFICE ){ + if( tsc->data[SC_DARKCROW] && wd.flag&BF_SHORT ) + ATK_ADD( 30 * tsc->data[SC_DARKCROW]->val1 ); } - break; - case KO_MAKIBISHI: - md.damage = 20 * skill_lv; - break; - } - if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets - if(mflag>0) - md.damage/= mflag; + if( !skill_id ) + { + ATK_RATE(skillratio); + } else - ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); - } + { + switch(skill_id){ + #ifdef RENEWAL + case LK_SPIRALPIERCE: + case ML_SPIRALPIERCE: + {// Formula: Floor[Floor(Weapon Weight/2)*skill level + ATK ]*(100%+50%*s.lvl) * 5 multi-hits + short index = sd?sd->equip_index[EQI_HAND_R]:0; + int weight = 0; - damage_div_fix(md.damage, md.div_); + if (sd && index >= 0 && + sd->inventory_data[index] && + sd->inventory_data[index]->type == IT_WEAPON) + weight = sd->inventory_data[index]->weight/20; + ATK_ADD(weight * skill_lv); + } + case NJ_TATAMIGAESHI: + if( skill_id != LK_SPIRALPIERCE && skill_id != ML_SPIRALPIERCE ) + ATK_RATE(200); + #endif + default: + ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag)); + } - if (!(nk&NK_IGNORE_FLEE)) - { - struct status_change *sc = status_get_sc(target); - i = 0; //Temp for "hit or no hit" - if(sc && sc->opt1 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING) - i = 1; - else { - short - flee = tstatus->flee, + //Constant/misc additions from skills + switch (skill_id) { + case MO_EXTREMITYFIST: + ATK_ADD(250 + 150*skill_lv); + break; #ifdef RENEWAL - hitrate = 0; //Default hitrate + case HW_MAGICCRASHER: + ATK_ADD(battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag).damage / 5); + break; +#endif + case TK_DOWNKICK: + case TK_STORMKICK: + case TK_TURNKICK: + case TK_COUNTER: + case TK_JUMPKICK: + //TK_RUN kick damage bonus. + if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST) + ATK_ADD(10*pc->checkskill(sd, TK_RUN)); + break; + case GS_MAGICALBULLET: +#ifndef RENEWAL + ATK_ADD( status_get_matk(src, 2) ); #else - hitrate = 80; //Default hitrate + ATK_ADD( battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag).damage ); + flag.tdef = 1; +#endif + case NJ_SYURIKEN: + ATK_ADD(4*skill_lv); + break; + case HT_FREEZINGTRAP: + if(sd) + ATK_ADD( 40 * pc->checkskill(sd, RA_RESEARCHTRAP) ); + break; + case RA_WUGDASH ://(Caster Current Weight x 10 / 8) + if( sd && sd->weight ) + ATK_ADD( sd->weight / 8 ); + break; + case SR_TIGERCANNON: // (Tiger Cannon skill level x 240) + (Target Base Level x 40) + ATK_ADD( skill_lv * 240 + status_get_lv(target) * 40 ); + if( sc && sc->data[SC_COMBOATTACK] + && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE ) // (Tiger Cannon skill level x 500) + (Target Base Level x 40) + ATK_ADD( skill_lv * 500 + status_get_lv(target) * 40 ); + break; + case SR_FALLENEMPIRE:// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)] + ATK_ADD( ((tstatus->size+1)*2 + skill_lv - 1) * sstatus->str); + if( tsd && tsd->weight ){ + ATK_ADD( (tsd->weight/10) * sstatus->dex / 120 ); + }else{ + ATK_ADD( status_get_lv(target) * 50 ); //mobs + } + break; + case KO_SETSUDAN: + if( tsc && tsc->data[SC_SOULLINK] ){ + ATK_ADDRATE(200*tsc->data[SC_SOULLINK]->val1); + status_change_end(target,SC_SOULLINK,INVALID_TIMER); + } + break; + case KO_MAKIBISHI: + wd.damage = 20 * skill_lv; + break; + } + } +#ifndef RENEWAL + //Div fix. + damage_div_fix(wd.damage, wd.div_); +#endif + //The following are applied on top of current damage and are stackable. + if ( sc ) { +#ifndef RENEWAL + if( sc->data[SC_TRUESIGHT] ) + ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1); +#endif + if( sc->data[SC_GLOOMYDAY_SK] && + ( skill_id == LK_SPIRALPIERCE || skill_id == KN_BRANDISHSPEAR || + skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN || + skill_id == LG_SHIELDPRESS || skill_id == RK_HUNDREDSPEAR || + skill_id == CR_SHIELDCHARGE ) ) + ATK_ADDRATE(sc->data[SC_GLOOMYDAY_SK]->val2); + if( sc->data[SC_EDP] ){ + switch(skill_id){ +#ifndef RENEWAL_EDP + case AS_SPLASHER: case AS_VENOMKNIFE: + case AS_GRIMTOOTH: + break; + case ASC_METEORASSAULT: break; + default: + ATK_ADDRATE(sc->data[SC_EDP]->val3); #endif + } + } + if(sc->data[SC_STYLE_CHANGE]){ + TBL_HOM *hd = BL_CAST(BL_HOM,src); + if (hd) ATK_ADD(hd->homunculus.spiritball * 3); + } + } - if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) { - unsigned char attacker_count; //256 max targets should be a sane max - attacker_count = unit_counttargeted(target); - if(attacker_count >= battle_config.agi_penalty_count) - { - if (battle_config.agi_penalty_type == 1) - flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; - else //asume type 2: absolute reduction - flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num; - if(flee < 1) flee = 1; + switch (skill_id) { + case AS_SONICBLOW: + if (sc && sc->data[SC_SOULLINK] && + sc->data[SC_SOULLINK]->val2 == SL_ASSASIN) + ATK_ADDRATE(map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe + + if(sd && pc->checkskill(sd,AS_SONICACCEL)>0) + ATK_ADDRATE(10); + break; + case CR_SHIELDBOOMERANG: + if(sc && sc->data[SC_SOULLINK] && + sc->data[SC_SOULLINK]->val2 == SL_CRUSADER) + ATK_ADDRATE(100); + break; + case NC_AXETORNADO: + if( (sstatus->rhw.ele) == ELE_WIND || (sstatus->lhw.ele) == ELE_WIND ) + ATK_ADDRATE(50); + break; + } + + if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) + ATK_RATE(i); + + if( sd ) { + if (skill_id && (i = pc->skillatk_bonus(sd, skill_id))) + ATK_ADDRATE(i); + if( (i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 && + (tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) ) + ATK_ADDRATE(-i); + if( skill_id != PA_SACRIFICE && skill_id != MO_INVESTIGATE && skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS && skill_id != PA_SHIELDCHAIN && !flag.cri ) + { //Elemental/Racial adjustments + if( sd->right_weapon.def_ratio_atk_ele & (1<def_ele) || + sd->right_weapon.def_ratio_atk_race & (1<race) || + sd->right_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) + ) + flag.pdef = 1; + + if( sd->left_weapon.def_ratio_atk_ele & (1<def_ele) || + sd->left_weapon.def_ratio_atk_race & (1<race) || + sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS)) + ) + { //Pass effect onto right hand if configured so. [Skotlex] + if (battle_config.left_cardfix_to_right && flag.rh) + flag.pdef = 1; + else + flag.pdef2 = 1; + } + } + + if (skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS) + { //Ignore Defense? + if (!flag.idef && ( + sd->right_weapon.ignore_def_ele & (1<def_ele) || + sd->right_weapon.ignore_def_race & (1<race) || + sd->right_weapon.ignore_def_race & (is_boss(target)?1<left_weapon.ignore_def_ele & (1<def_ele) || + sd->left_weapon.ignore_def_race & (1<race) || + sd->left_weapon.ignore_def_race & (is_boss(target)?1<calc_defense(BF_WEAPON, src, target, skill_id, skill_lv, wd.damage, (flag.idef?1:0)|(flag.pdef?2:0)|(flag.tdef?4:0), flag.pdef); + if( wd.damage2 ) + wd.damage2 = battle->calc_defense(BF_WEAPON, src, target, skill_id, skill_lv, wd.damage2, (flag.idef2?1:0)|(flag.pdef2?2:0)|(flag.tdef?4:0), flag.pdef2); + } + +#ifdef RENEWAL + //Div fix. + damage_div_fix(wd.damage, wd.div_); +#endif + //Post skill/vit reduction damage increases + if( sc ) + { //SC skill damages + if(sc->data[SC_AURABLADE] +#ifndef RENEWAL + && skill_id != LK_SPIRALPIERCE && skill_id != ML_SPIRALPIERCE +#endif + ){ + int lv = sc->data[SC_AURABLADE]->val1; +#ifdef RENEWAL + lv *= ((skill_id == LK_SPIRALPIERCE || skill_id == ML_SPIRALPIERCE)?wd.div_:1); // +100 per hit in lv 5 +#endif + ATK_ADD(20*lv); + } + } +#ifndef RENEWAL + //Refine bonus + if( sd && flag.weapon && skill_id != MO_INVESTIGATE && skill_id != MO_EXTREMITYFIST ) + { // Counts refine bonus multiple times + if( skill_id == MO_FINGEROFFENSIVE ) + { + ATK_ADD2(wd.div_*sstatus->rhw.atk2, wd.div_*sstatus->lhw.atk2); + } else { + ATK_ADD2(sstatus->rhw.atk2, sstatus->lhw.atk2); + } + } + //Set to min of 1 + if (flag.rh && wd.damage < 1) wd.damage = 1; + if (flag.lh && wd.damage2 < 1) wd.damage2 = 1; +#else + if (flag.rh && wd.damage < 1) wd.damage = 0; + if (flag.lh && wd.damage2 < 1) wd.damage2 = 0; +#endif + +#ifndef RENEWAL + wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon); + if( flag.lh) + wd.damage2 = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage2, wd.div_, 1, flag.weapon); +#else + if( flag.cri ) + ATK_ADDRATE(40); +#endif + } //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks + else if(wd.div_ < 0) //Since the attack missed... + wd.div_ *= -1; +#ifndef RENEWAL + if(sd && (temp=pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0) + ATK_ADD(temp*2); +#endif + if(skill_id==TF_POISON) + ATK_ADD(15*skill_lv); - hitrate+= sstatus->hit - flee; -#ifdef RENEWAL - if( sd ) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window - hitrate += pc->checkskill(sd,AC_VULTURE); +#ifndef RENEWAL + wd.damage = battle->calc_elefix(src, target, skill_id, skill_lv, wd.damage, nk, n_ele, s_ele, s_ele_, false, flag.arrow); + if( flag.lh ) + wd.damage2 = battle->calc_elefix(src, target, skill_id, skill_lv, wd.damage2, nk, n_ele, s_ele, s_ele_, true, flag.arrow); #endif - hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); - if(rnd()%100 < hitrate) - i = 1; - } - if (!i) { - md.damage = 0; - md.dmg_lv=ATK_FLEE; - } - } + if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS) + return wd; //Enough, rest is not needed. #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE if( target && skill_id ) { for(i = 0; i < map[target->m].zone->capped_skills_count; i++) { @@ -4497,75 +4764,251 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) ) continue; } - if( md.damage > map[target->m].zone->capped_skills[i]->cap ) - md.damage = map[target->m].zone->capped_skills[i]->cap; - if( md.damage2 > map[target->m].zone->capped_skills[i]->cap ) - md.damage2 = map[target->m].zone->capped_skills[i]->cap; + if( wd.damage > map[target->m].zone->capped_skills[i]->cap ) + wd.damage = map[target->m].zone->capped_skills[i]->cap; + if( wd.damage2 > map[target->m].zone->capped_skills[i]->cap ) + wd.damage2 = map[target->m].zone->capped_skills[i]->cap; break; } } } #endif - md.damage = battle->calc_cardfix(BF_MISC, src, target, nk, s_ele, 0, md.damage, 0, md.flag); - - if (sd && (i = pc->skillatk_bonus(sd, skill_id))) - md.damage += md.damage*i/100; +#ifndef RENEWAL + if (sd) { + if (skill_id != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus. + ATK_ADD2(wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star); + if (skill_id==MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex] + ATK_ADD(wd.div_*sd->spiritball_old*3); + } else { + ATK_ADD(wd.div_*sd->spiritball*3); + } + //Card Fix, sd side + wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag); + if( flag.lh ) + wd.damage2 = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag); +#ifdef RENEWAL + if( flag.cri ) + ATK_ADDRATE(sd->bonus.crit_atk_rate>=100?sd->bonus.crit_atk_rate-60:40); +#endif + if( skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ) + { //Refine bonus applies after cards and elements. + short index= sd->equip_index[EQI_HAND_L]; + if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR ) + ATK_ADD(10*sd->status.inventory[index].refine); + } + } + //Card Fix, tsd side + if(tsd){ //if player on player then it was already measured above + wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag); + if( flag.lh ) + wd.damage2 = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag); + } +#endif + if( flag.infdef ) { //Plants receive 1 damage when hit + short class_ = status_get_class(target); + if( flag.hit || wd.damage > 0 ) + wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage + if( flag.lh && (flag.hit || wd.damage2 > 0) ) + wd.damage2 = wd.div_; + if( flag.hit && class_ == MOBID_EMPERIUM ) { + if(wd.damage2 > 0) { + wd.damage2 = battle->attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); + wd.damage2 = battle->calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); + } + else if(wd.damage > 0) { + wd.damage = battle->attr_fix(src,target,wd.damage,s_ele_,tstatus->def_ele, tstatus->ele_lv); + wd.damage = battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); + } + return wd; + } + if( !(battle_config.skill_min_damage&1) ) + //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex] + return wd; + } - if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) - md.damage = md.damage * i / 100; + if (sd) { + if (!flag.rh && flag.lh) { //Move lh damage to the rh + wd.damage = wd.damage2; + wd.damage2 = 0; + flag.rh=1; + flag.lh=0; + } else if(flag.rh && flag.lh) { //Dual-wield + if (wd.damage) { + temp = pc->checkskill(sd,AS_RIGHT) * 10; + if( (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO ) + temp = pc->checkskill(sd,KO_RIGHT) * 10 + 20; + ATK_RATER( 50 + temp ); + } + if (wd.damage2) { + temp = pc->checkskill(sd,AS_LEFT) * 10; + if( (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO ) + temp = pc->checkskill(sd,KO_LEFT) * 10 + 20; + ATK_RATEL( 30 + temp ); + } +#ifdef RENEWAL + if(wd.damage < 0) wd.damage = 0; + if(wd.damage2 < 0) wd.damage2 = 0; +#else + if(wd.damage < 1) wd.damage = 1; + if(wd.damage2 < 1) wd.damage2 = 1; +#endif + } else if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2) + temp = pc->checkskill(sd,TF_DOUBLE); + wd.damage2 = wd.damage * (1 + (temp * 2))/100; - if(md.damage < 0) - md.damage = 0; - else if(md.damage && tstatus->mode&MD_PLANT){ - switch(skill_id){ - case HT_LANDMINE: - case MA_LANDMINE: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case RA_CLUSTERBOMB: + if(wd.damage && !wd.damage2) wd.damage2 = #ifdef RENEWAL - break; + 0; +#else + 1; #endif - default: - md.damage = 1; + flag.lh = 1; } - }else if( target->type == BL_SKILL ){ - TBL_SKILL *su = (TBL_SKILL*)target; - if( su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) - md.damage = 1; } - if(!(nk&NK_NO_ELEFIX)) - md.damage=battle->attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); + if(!flag.rh && wd.damage) + wd.damage=0; - md.damage=battle->calc_damage(src,target,&md,md.damage,skill_id,skill_lv); - if( map_flag_gvg2(target->m) ) - md.damage=battle->calc_gvg_damage(src,target,md.damage,md.div_,skill_id,skill_lv,md.flag); - else if( map[target->m].flag.battleground ) - md.damage=battle->calc_bg_damage(src,target,md.damage,md.div_,skill_id,skill_lv,md.flag); + if(!flag.lh && wd.damage2) + wd.damage2=0; - switch( skill_id ) { - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - if( md.damage == 1 ) break; - case RA_CLUSTERBOMB: - { - struct Damage wd; - wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); - md.damage += wd.damage; + if( sc ) { + //SG_FUSION hp penalty [Komurka] + if (sc->data[SC_FUSION]) { + int hp= sstatus->max_hp; + if (sd && tsd) { + hp = 8*hp/100; + if ((sstatus->hp * 100) <= (sstatus->max_hp * 20)) + hp = sstatus->hp; + } else + hp = 2*hp/100; //2% hp loss per hit + status_zap(src, hp, 0); + } + if( !skill_id ) { + if( sc->data[SC_ENCHANTBLADE] ) { // it also works with bear hands..intended in official + //[( ( Skill Lv x 20 ) + 100 ) x ( casterBaseLevel / 150 )] + casterInt + ATK_ADD(( sc->data[SC_ENCHANTBLADE]->val1 * 20 + 100 ) * status_get_lv(src) / 150 + status_get_int(src)); } + } + status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); + } + + switch(skill_id){ + case LG_RAYOFGENESIS: + { + struct Damage md = battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag); + wd.damage += md.damage; break; - case NJ_ZENYNAGE: - if( sd ) { - if ( md.damage > sd->status.zeny ) - md.damage = sd->status.zeny; - pc->payzeny(sd, md.damage,LOG_TYPE_STEAL,NULL); } - break; + case SR_GATEOFHELL: + ATK_ADD (sstatus->max_hp - status_get_hp(src)); + if(sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE){ + ATK_ADD ( (sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status_get_lv(src) ); + }else{ + ATK_ADD ( (sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status_get_lv(src) ); + } + break; } - return md; + if( wd.damage + wd.damage2 ) + { //There is a total damage value + int damage = wd.damage + wd.damage2, rdamage = 0, rdelay = 0; + + if( src != target && + (!skill_id || skill_id || + ( src->type == BL_SKILL && ( skill_id == SG_SUN_WARM || skill_id == SG_MOON_WARM || skill_id == SG_STAR_WARM ) )) ){ + + rdamage = battle->calc_return_damage(target, src, &damage, wd.flag, 0, &rdelay); + + if( tsc && tsc->count ) { + if( tsc && tsc->data[SC_DEATHBOUND] ){ + wd.damage = damage; + wd.damage2 = 0; + status_change_end(target,SC_DEATHBOUND,INVALID_TIMER); + } + } + if( rdamage > 0 ) { + if( tsc && tsc->data[SC_LG_REFLECTDAMAGE] ) { + if( src != target ) {// Don't reflect your own damage (Grand Cross) + bool change = false; + if( sd && !sd->state.autocast ) + change = true; + if( change ) + sd->state.autocast = 1; + iMap->foreachinshootrange(battle->damage_area,target,skill->get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,iTimer->gettick(),target,wd.amotion,sstatus->dmotion,rdamage,tstatus->race); + if( change ) + sd->state.autocast = 0; + } + } else { + //Use Reflect Shield to signal this kind of skill trigger. [Skotlex] + if( tsd && src != target ) + battle->drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); + battle->delay_damage(iTimer->gettick(), wd.amotion,target,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,rdelay,true); + skill->additional_effect(target, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,iTimer->gettick()); + } + } + } + if(!wd.damage2) + { + wd.damage = battle->calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv); + if( map_flag_gvg2(target->m) ) + wd.damage=battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); + else if( map[target->m].flag.battleground ) + wd.damage=battle->calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); + } + else if(!wd.damage) + { + wd.damage2 = battle->calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv); + if( map_flag_gvg2(target->m) ) + wd.damage2 = battle->calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); + else if( map[target->m].flag.battleground ) + wd.damage = battle->calc_bg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); + } + else + { +#ifdef RENEWAL + wd.damage = battle->calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv); + wd.damage2 = battle->calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv); +#else + int d1 = wd.damage + wd.damage2,d2 = wd.damage2; + wd.damage = battle->calc_damage(src,target,&wd,d1,skill_id,skill_lv); +#endif + if( map_flag_gvg2(target->m) ) + wd.damage = battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); + else if( map[target->m].flag.battleground ) + wd.damage = battle->calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); +#ifndef RENEWAL + wd.damage2 = d2*100/d1 * wd.damage/100; + if(wd.damage > 1 && wd.damage2 < 1) wd.damage2 = 1; + wd.damage-=wd.damage2; +#endif + } + } + //Reject Sword bugreport:4493 by Daegaladh + if(wd.damage && tsc && tsc->data[SC_SWORDREJECT] && + (src->type!=BL_PC || ( + ((TBL_PC *)src)->weapontype1 == W_DAGGER || + ((TBL_PC *)src)->weapontype1 == W_1HSWORD || + ((TBL_PC *)src)->status.weapon == W_2HSWORD + )) && + rnd()%100 < tsc->data[SC_SWORDREJECT]->val2 + ) { + ATK_RATER(50) + status_fix_damage(target,src,wd.damage,clif->damage(target,src,iTimer->gettick(),0,0,wd.damage,0,0,0)); + clif->skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_SWORDREJECT]->val1,1); + if( --(tsc->data[SC_SWORDREJECT]->val3) <= 0 ) + status_change_end(target, SC_SWORDREJECT, INVALID_TIMER); + } +#ifndef RENEWAL + if(skill_id == ASC_BREAKER) { //Breaker's int-based damage (a misc attack?) + struct Damage md = battle->calc_misc_attack(src, target, skill_id, skill_lv, wflag); + wd.damage += md.damage; + } +#endif + + return wd; } + /*========================================== * Battle main entry, from skill->attack *------------------------------------------*/ @@ -4614,19 +5057,19 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl } //Calculates BF_WEAPON returned damage. -int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int *dmg, int flag, uint16 skill_id){ +int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int *dmg, int flag, uint16 skill_id, int *delay){ + int rdamage = 0, damage = *dmg, rdelay = *delay, trdamage = 0; struct map_session_data* sd; - int rdamage = 0, damage = *dmg; struct status_change* sc; + int max_reflect_damage; sd = BL_CAST(BL_PC, bl); sc = status_get_sc(bl); + max_reflect_damage = max(status_get_max_hp(bl), status_get_max_hp(bl) * status_get_lv(bl) / 100); - if( sc && sc->data[SC_REFLECTDAMAGE] ) { - int max_damage = status_get_max_hp(bl) * status_get_lv(bl) / 100; - rdamage = (*dmg) * sc->data[SC_REFLECTDAMAGE]->val2 / 100; - if( rdamage > max_damage ) rdamage = max_damage; - }else if( sc && sc->data[SC_CRESCENTELBOW] && !is_boss(src) && rnd()%100 < sc->data[SC_CRESCENTELBOW]->val2 ){ +#define NORMALIZE_RDAMAGE(d){ trdamage += rdamage = max(1, min(max_reflect_damage, d)); } + + if( sc && sc->data[SC_CRESCENTELBOW] && !is_boss(src) && rnd()%100 < sc->data[SC_CRESCENTELBOW]->val2 ){ //ATK [{(Target HP / 100) x Skill Level} x Caster Base Level / 125] % + [Received damage x {1 + (Skill Level x 0.2)}] int ratio = (status_get_hp(src) / 100) * sc->data[SC_CRESCENTELBOW]->val1 * status_get_lv(bl) / 125; if (ratio > 5000) ratio = 5000; // Maximum of 5000% ATK @@ -4638,42 +5081,56 @@ int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int status_damage(src, bl, status_damage(bl, src, rdamage, 0, 0, 1)/10, 0, 0, 1); status_change_end(bl, SC_CRESCENTELBOW, INVALID_TIMER); return 0; // Just put here to minimize redundancy - }else if (flag & BF_SHORT) {//Bounces back part of the damage. - if ( sd && sd->bonus.short_weapon_damage_return ) { - rdamage += damage * sd->bonus.short_weapon_damage_return / 100; - if(rdamage < 1) rdamage = 1; + } + if( flag & BF_SHORT) {//Bounces back part of the damage. + if ( sd && sd->bonus.short_weapon_damage_return ){ + NORMALIZE_RDAMAGE(damage * sd->bonus.short_weapon_damage_return / 100); + rdelay = clif->damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4, 0); } if( sc && sc->count ) { - if ( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) { - rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100; - if (rdamage < 1) rdamage = 1; + if( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ){ + NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100); + rdelay = clif->skill_damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, 4); + } + if( sc->data[SC_LG_REFLECTDAMAGE] && rand()%100 < (30 + 10*sc->data[SC_LG_REFLECTDAMAGE]->val1) ) { + if( skill_id != HT_LANDMINE && skill_id != HT_CLAYMORETRAP + && skill_id != RA_CLUSTERBOMB && (skill_id <= RA_VERDURETRAP || skill_id > RA_ICEBOUNDTRAP && skill_id != MA_LANDMINE) ){ + NORMALIZE_RDAMAGE((*dmg) * sc->data[SC_LG_REFLECTDAMAGE]->val2 / 100); + rdelay = clif->damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4, 0); + } } - if(sc->data[SC_DEATHBOUND] && skill_id != WS_CARTTERMINATION && !(src->type == BL_MOB && is_boss(src)) ) { + if( sc->data[SC_DEATHBOUND] && skill_id != WS_CARTTERMINATION && !is_boss(src) ) { uint8 dir = iMap->calc_dir(bl,src->x,src->y), - t_dir = unit_getdir(bl); - - if( distance_bl(src,bl) <= 0 || !iMap->check_dir(dir,t_dir) ) { - int rd1 = 0; - rd1 = min(damage,status_get_max_hp(bl)) * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. - *dmg = rd1 * 30 / 100; // Received damage = 30% of amplifly damage. - clif->skill_damage(src,bl,iTimer->gettick(), status_get_amotion(src), 0, -30000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1,6); - status_change_end(bl,SC_DEATHBOUND,INVALID_TIMER); - rdamage += rd1; - if (rdamage < 1) rdamage = 1; + t_dir = unit_getdir(bl); + + if( !iMap->check_dir(dir,t_dir) ) { + int rd1 = damage * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. + trdamage += rdamage = rd1 - (*dmg = rd1 * 30 / 100); // not normalized as intended. + clif->skill_damage(src, bl, iTimer->gettick(), status_get_amotion(src), 0, -3000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, 6); + skill->blown(bl, src, skill->get_blewcount(RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1), unit_getdir(src), 0); + if( skill_id ) + status_change_end(bl, SC_DEATHBOUND, INVALID_TIMER); + rdelay = clif->damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4, 0); } } } + if( sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 2 && !is_boss(src) ){ + NORMALIZE_RDAMAGE(damage * sc->data[SC_SHIELDSPELL_DEF]->val2 / 100); + rdelay = clif->damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4, 0); + } } else { - if (sd && sd->bonus.long_weapon_damage_return) { - rdamage += damage * sd->bonus.long_weapon_damage_return / 100; - if (rdamage < 1) rdamage = 1; + if (sd && sd->bonus.long_weapon_damage_return){ + NORMALIZE_RDAMAGE(damage * sd->bonus.long_weapon_damage_return / 100); + rdelay = clif->damage(src, src, iTimer->gettick(), status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4, 0); } } + + if( !(sc && sc->data[SC_DEATHBOUND]) ){ + if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability + return 0; + } - if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability - rdamage = 0; - - return rdamage; + return max(0, trdamage); } void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss) @@ -4898,17 +5355,17 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t return ATK_DEF; return ATK_MISS; } - if( sc->data[SC_GT_ENERGYGAIN] ) { - if( sd && rnd()%100 < 10 + 5 * sc->data[SC_GT_ENERGYGAIN]->val1) + if( sc->data[SC_GENTLETOUCH_ENERGYGAIN] ) { + if( sd && rnd()%100 < 10 + 5 * sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1) pc->addspiritball(sd, - skill->get_time(MO_CALLSPIRITS, sc->data[SC_GT_ENERGYGAIN]->val1), - sc->data[SC_GT_ENERGYGAIN]->val1); + skill->get_time(MO_CALLSPIRITS, sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1), + sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1); } - if( tsc && tsc->data[SC_GT_ENERGYGAIN] ) { - if( tsd && rnd()%100 < 10 + 5 * tsc->data[SC_GT_ENERGYGAIN]->val1) + if( tsc && tsc->data[SC_GENTLETOUCH_ENERGYGAIN] ) { + if( tsd && rnd()%100 < 10 + 5 * tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1) pc->addspiritball(tsd, - skill->get_time(MO_CALLSPIRITS, tsc->data[SC_GT_ENERGYGAIN]->val1), - tsc->data[SC_GT_ENERGYGAIN]->val1); + skill->get_time(MO_CALLSPIRITS, tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1), + tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1); } if( sc && sc->data[SC_CRUSHSTRIKE] ){ uint16 skill_lv = sc->data[SC_CRUSHSTRIKE]->val1; @@ -4958,19 +5415,6 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t skill_id = AB_DUPLELIGHT_MAGIC; skill->attack(skill->get_type(skill_id), src, src, target, skill_id, sc->data[SC_DUPLELIGHT]->val1, tick, SD_LEVEL); } - - rdamage = battle->calc_return_damage(target,src, &damage, wd.flag, 0); - if( rdamage > 0 ) { - if( tsc && tsc->data[SC_REFLECTDAMAGE] ) { - if( src != target ) {// Don't reflect your own damage (Grand Cross) - iMap->foreachinshootrange(battle->damage_area,target,skill->get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd.amotion,wd.dmotion,rdamage,tstatus->race); - } - } else { - rdelay = clif->damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0); - //Use Reflect Shield to signal this kind of skill trigger. [Skotlex] - skill->additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); - } - } } wd.dmotion = clif->damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2); @@ -5023,7 +5467,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t uint16 skill_id = sc->data[SC_AUTOSPELL]->val2; uint16 skill_lv = sc->data[SC_AUTOSPELL]->val3; int i = rnd()%100; - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_SAGE) + if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_SAGE) i = 0; //Max chance, no skill_lv reduction. [Skotlex] if (i >= 50) skill_lv -= 2; else if (i >= 15) skill_lv--; @@ -5099,7 +5543,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t sd->state.autocast = 0; sd->ud.canact_tick = tick + skill->delay_fix(src, r_skill, r_lv); - clif->status_change(src, SI_ACTIONDELAY, 1, skill->delay_fix(src, r_skill, r_lv), 0, 0, 1); + clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, r_skill, r_lv), 0, 0, 1); } } @@ -5110,11 +5554,6 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t battle->drain(sd, target, wd.damage, wd.damage2, tstatus->race, is_boss(target)); } } - if (rdamage > 0 && !(tsc && tsc->data[SC_REFLECTDAMAGE])) { //By sending attack type "none" skill->additional_effect won't be invoked. [Skotlex] - if(tsd && src != target) - battle->drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); - battle->delay_damage(tick, wd.amotion, target, src, 0, CR_REFLECTSHIELD, 0, rdamage, ATK_DEF, rdelay, true); - } if (tsc) { if (tsc->data[SC_POISONREACT] && @@ -5243,7 +5682,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f if (((TBL_PC*)target)->invincible_timer != INVALID_TIMER || pc_isinvisible((TBL_PC*)target)) return -1; //Cannot be targeted yet. if( sc && sc->count ) { - if( sc->data[SC_VOICEOFSIREN] && sc->data[SC_VOICEOFSIREN]->val2 == target->id ) + if( sc->data[SC_SIREN] && sc->data[SC_SIREN]->val2 == target->id ) return -1; } } @@ -5265,6 +5704,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f if( skill->get_inf2(su->group->skill_id)&INF2_TRAP ) { //Only a few skills can target traps... switch( battle->get_current_skill(src) ) { case RK_DRAGONBREATH:// it can only hit traps in pvp/gvg maps + case RK_DRAGONBREATH_WATER: if( !map[m].flag.pvp && !map[m].flag.gvg ) break; case 0://you can hit them without skills @@ -5838,7 +6278,6 @@ static const struct _battle_data { { "ignore_items_gender", &battle_config.ignore_items_gender, 1, 0, 1, }, { "copyskill_restrict", &battle_config.copyskill_restrict, 2, 0, 2, }, { "berserk_cancels_buffs", &battle_config.berserk_cancels_buffs, 0, 0, 1, }, - { "debuff_on_logout", &battle_config.debuff_on_logout, 1|2, 0, 1|2, }, { "monster_ai", &battle_config.mob_ai, 0x000, 0x000, 0x77F, }, { "hom_setting", &battle_config.hom_setting, 0xFFFF, 0x0000, 0xFFFF, }, { "dynamic_mobs", &battle_config.dynamic_mobs, 1, 0, 1, }, @@ -6239,9 +6678,15 @@ void battle_defaults(void) { battle->drain = battle_drain; battle->calc_return_damage = battle_calc_return_damage; battle->calc_weapon_attack = battle_calc_weapon_attack; + battle->calc_weapon_damage = battle_calc_weapon_damage; + battle->calc_defense = battle_calc_defense; battle->attr_ratio = battle_attr_ratio; battle->attr_fix = battle_attr_fix; battle->calc_cardfix = battle_calc_cardfix; + battle->calc_elefix = battle_calc_elefix; + battle->calc_masteryfix = battle_calc_masteryfix; + battle->calc_skillratio = battle_calc_skillratio; + battle->calc_sizefix = battle_calc_sizefix; battle->get_master = battle_get_master; battle->get_targeted = battle_gettargeted; battle->get_enemy = battle_getenemy; diff --git a/src/map/battle.h b/src/map/battle.h index f2d870032..bbe723f36 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -348,7 +348,6 @@ struct Battle_Config { int copyskill_restrict; // [Aru] int berserk_cancels_buffs; // [Aru] - int debuff_on_logout; // Removes a few "official" negative Scs on logout. [Skotlex] int mob_ai; //Configures various mob_ai settings to make them smarter or dumber(official). [Skotlex] int hom_setting; //Configures various homunc settings which make them behave unlike normal characters.. [Skotlex] int dynamic_mobs; // Dynamic Mobs [Wizputer] - battle.conf flag implemented by [random] @@ -489,13 +488,25 @@ struct battle_interface { /* drain damage */ void (*drain) (struct map_session_data *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss); /* damage return/reflect */ - int (*calc_return_damage) (struct block_list *bl, struct block_list *src, int *, int flag, uint16 skill_id); + int (*calc_return_damage) (struct block_list *bl, struct block_list *src, int *, int flag, uint16 skill_id, int*); /* attribute rate */ int (*attr_ratio) (int atk_elem, int def_type, int def_lv); /* applies attribute modifiers */ int (*attr_fix) (struct block_list *src, struct block_list *target, int damage, int atk_elem, int def_type, int def_lv); /* applies card modifiers */ int (*calc_cardfix) (int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag); + /* applies element modifiers */ + int (*calc_elefix) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag); + /* applies mastery modifiers */ + int (*calc_masteryfix) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int div, bool left, bool weapon); + /* applies skill modifiers */ + int (*calc_skillratio) (int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag); + /* applies size modifiers */ + int (*calc_sizefix) (struct map_session_data *sd, int damage, int type, int size, bool ignore); + /* get weapon damage */ + int (*calc_weapon_damage) (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2); + /* applies defense reductions */ + int (*calc_defense) (int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int damage, int flag, int pdef); /* get master (who does this unit respond to?) */ struct block_list *(*get_master) (struct block_list *src); /* returns a random unit who is targeting this unit */ @@ -521,7 +532,12 @@ struct battle_interface { int (*blewcount_bonus) (struct map_session_data *sd, uint16 skill_id); /* skill range criteria */ int (*range_type) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv); - int (*calc_base_damage) (struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag); + int (*calc_base_damage) +#ifdef RENEWAL + (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2); +#else + (struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag); +#endif struct Damage (*calc_misc_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag); struct Damage (*calc_magic_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag); int (*adjust_skill_damage) (int m, unsigned short skill_id); diff --git a/src/map/clif.c b/src/map/clif.c index 202469605..2f8ecd6a4 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1259,12 +1259,12 @@ void clif_spiritball_single(int fd, struct map_session_data *sd) { /*========================================== * Kagerou/Oboro amulet spirit *------------------------------------------*/ -void clif_talisman_single(int fd, struct map_session_data *sd, short type) { +void clif_charm_single(int fd, struct map_session_data *sd, short type) { WFIFOHEAD(fd, packet_len(0x08cf)); WFIFOW(fd,0)=0x08cf; WFIFOL(fd,2)=sd->bl.id; WFIFOW(fd,6)=type; - WFIFOW(fd,8)=sd->talisman[type]; + WFIFOW(fd,8)=sd->charm[type]; WFIFOSET(fd, packet_len(0x08cf)); } @@ -1358,8 +1358,8 @@ int clif_spawn(struct block_list *bl) clif->sc_load(&sd->bl, sd->bl.id,AREA,StatusIconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3); } for(i = 1; i < 5; i++){ - if( sd->talisman[i] > 0 ) - clif->talisman(sd, i); + if( sd->charm[i] > 0 ) + clif->charm(sd, i); } if (sd->status.robe) clif->refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); @@ -3461,7 +3461,9 @@ void clif_arrowequip(struct map_session_data *sd,int val) nullpo_retv(sd); pc_stop_attack(sd); // [Valaris] - +#if PACKETVER >= 20121128 + clif->status_change(&sd->bl, SI_CLIENT_ONLY_EQUIP_ARROW, 1, INVALID_TIMER, 0, 0, 0); +#endif fd=sd->fd; WFIFOHEAD(fd, packet_len(0x013c)); WFIFOW(fd,0)=0x013c; @@ -4309,8 +4311,8 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds if(dstsd->spiritball > 0) clif->spiritball_single(sd->fd, dstsd); for(i = 1; i < 5; i++){ - if( dstsd->talisman[i] > 0 ) - clif->talisman_single(sd->fd, dstsd, i); + if( dstsd->charm[i] > 0 ) + clif->charm_single(sd->fd, dstsd, i); } for( i = 0; i < dstsd->sc_display_count; i++ ) { clif->sc_load(&sd->bl,dstsd->bl.id,SELF,StatusIconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3); @@ -4471,9 +4473,9 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic type = clif_calc_delay(type,div,damage+damage2,ddelay); sc = status_get_sc(dst); if(sc && sc->count) { - if(sc->data[SC_HALLUCINATION]) { - if(damage) damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; - if(damage2) damage2 = damage2*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; + if(sc->data[SC_ILLUSION]) { + if(damage) damage = damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100; + if(damage2) damage2 = damage2*(sc->data[SC_ILLUSION]->val2) + rnd()%100; } } @@ -4643,12 +4645,21 @@ void clif_getareachar_item(struct map_session_data* sd,struct flooritem_data* fi /// Notifies the client of a skill unit. /// 011f .L .L .W .W .B .B (ZC_SKILL_ENTRY) /// 01c9 .L .L .W .W .B .B .B .80B (ZC_SKILL_ENTRY2) +/// 08c7 .W L .L .W .W .B .W .B (ZC_SKILL_ENTRY3) +/// 099f .W L .L .W .W .L .W .B (ZC_SKILL_ENTRY4) void clif_getareachar_skillunit(struct map_session_data *sd, struct skill_unit *unit) { - int fd = sd->fd; + int fd = sd->fd, header = 0x11f, pos=0; if( unit->group->state.guildaura ) return; +#if PACKETVER >= 20130320 + if(unit->group->unit_id > UCHAR_MAX){ + header = 0x99f; + pos = 2; + } +#endif + #if PACKETVER >= 3 if(unit->group->unit_id==UNT_GRAFFITI) { // Graffiti [Valaris] WFIFOHEAD(fd,packet_len(0x1c9)); @@ -4665,20 +4676,26 @@ void clif_getareachar_skillunit(struct map_session_data *sd, struct skill_unit * return; } #endif - WFIFOHEAD(fd,packet_len(0x11f)); - WFIFOW(fd, 0)=0x11f; - WFIFOL(fd, 2)=unit->bl.id; - WFIFOL(fd, 6)=unit->group->src_id; - WFIFOW(fd,10)=unit->bl.x; - WFIFOW(fd,12)=unit->bl.y; + WFIFOHEAD(fd,packet_len(header)); + WFIFOW(fd, 0)=header; + if(pos > 0) + WFIFOL(fd, pos)=packet_len(header); + WFIFOL(fd, 2 + pos)=unit->bl.id; + WFIFOL(fd, 6 + pos)=unit->group->src_id; + WFIFOW(fd,10 + pos)=unit->bl.x; + WFIFOW(fd,12 + pos)=unit->bl.y; if (battle_config.traps_setting&1 && skill->get_inf2(unit->group->skill_id)&INF2_TRAP) WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps. else if (skill->get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT)) WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps. - else + else if(pos > 0){ + WFIFOL(fd,16)=unit->group->unit_id; + WFIFOW(fd,20)=unit->range; + pos += 5; + }else WFIFOB(fd,14)=unit->group->unit_id; - WFIFOB(fd,15)=1; // ignored by client (always gets set to 1) - WFIFOSET(fd,packet_len(0x11f)); + WFIFOB(fd,15 + pos)=1; // ignored by client (always gets set to 1) + WFIFOSET(fd,packet_len(header)); if(unit->group->skill_id == WZ_ICEWALL) clif->changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,5,SELF); @@ -5134,8 +5151,8 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int type = clif_calc_delay(type,div,damage,ddelay); sc = status_get_sc(dst); if(sc && sc->count) { - if(sc->data[SC_HALLUCINATION] && damage) - damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; + if(sc->data[SC_ILLUSION] && damage) + damage = damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100; } #if PACKETVER < 3 @@ -5223,8 +5240,8 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned in sc = status_get_sc(dst); if(sc && sc->count) { - if(sc->data[SC_HALLUCINATION] && damage) - damage = damage*(sc->data[SC_HALLUCINATION]->val2) + rnd()%100; + if(sc->data[SC_ILLUSION] && damage) + damage = damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100; } WBUFW(buf,0)=0x115; @@ -5330,12 +5347,20 @@ void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,i void clif_skill_setunit(struct skill_unit *unit) { unsigned char buf[128]; + int header = 0x11f, pos = 0; nullpo_retv(unit); if( unit->group->state.guildaura ) return; +#if PACKETVER >= 20130320 + if(unit->group->unit_id > UCHAR_MAX){ + header = 0x99f; + pos = 2; + } +#endif + #if PACKETVER >= 3 if(unit->group->unit_id==UNT_GRAFFITI) { // Graffiti [Valaris] WBUFW(buf, 0)=0x1c9; @@ -5351,19 +5376,25 @@ void clif_skill_setunit(struct skill_unit *unit) return; } #endif - WBUFW(buf, 0)=0x11f; - WBUFL(buf, 2)=unit->bl.id; - WBUFL(buf, 6)=unit->group->src_id; - WBUFW(buf,10)=unit->bl.x; - WBUFW(buf,12)=unit->bl.y; + WBUFW(buf, 0)=header; + if(pos > 0) + WBUFW(buf, pos)=packet_len(header); + WBUFL(buf, 2 + pos)=unit->bl.id; + WBUFL(buf, 6 + pos)=unit->group->src_id; + WBUFW(buf,10 + pos)=unit->bl.x; + WBUFW(buf,12 + pos)=unit->bl.y; if (unit->group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE) WBUFB(buf,14)=unit->val2&UF_SONG?UNT_DISSONANCE:UNT_UGLYDANCE; else if (skill->get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT)) WBUFB(buf, 14) = UNT_DUMMYSKILL; // Only display the unit at center. - else + else if(pos > 0){ + WBUFL(buf,16)=unit->group->unit_id; + WBUFW(buf,20)=unit->range; + pos += 5; + }else WBUFB(buf,14)=unit->group->unit_id; - WBUFB(buf,15)=1; // ignored by client (always gets set to 1) - clif->send(buf,packet_len(0x11f),&unit->bl,AREA); + WBUFB(buf,15 + pos)=1; // ignored by client (always gets set to 1) + clif->send(buf,packet_len(header),&unit->bl,AREA); } @@ -5388,9 +5419,10 @@ void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 s WFIFOSET(fd,packet_len(0x11c)); sd->menuskill_id = skill_id; - if (skill_id == AL_WARP) + if (skill_id == AL_WARP){ sd->menuskill_val = (sd->ud.skillx<<16)|sd->ud.skilly; //Store warp position here. - else + sd->state.workinprogress = 3; + }else sd->menuskill_val = skill_lv; } @@ -5423,10 +5455,11 @@ void clif_skill_memomessage(struct map_session_data* sd, int type) /// type: /// 0 = "Unable to Teleport in this area" in color 0xFFFF00 (cyan) /// 1 = "Saved point cannot be memorized." in color 0x0000FF (red) +/// 2 = "This skill cannot be used within this area." in color 0xFFFF00 (cyan) /// /// @param sd Who receives the message /// @param type What message -void clif_skill_teleportmessage(struct map_session_data *sd, int type) +void clif_skill_mapinfomessage(struct map_session_data *sd, int type) { int fd; @@ -5621,6 +5654,9 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val if (!(status_type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client return; + if ( tick < 0 ) + tick = 9999; + sd = BL_CAST(BL_PC, bl); p.PacketType = status_changeType; @@ -6061,6 +6097,7 @@ void clif_item_identify_list(struct map_session_data *sd) WFIFOSET(fd,WFIFOW(fd,2)); sd->menuskill_id = MC_IDENTIFY; sd->menuskill_val = c; + sd->state.workinprogress = 3; } } @@ -6163,25 +6200,20 @@ void clif_item_refine_list(struct map_session_data *sd) int fd; uint16 skill_lv; int wlv; - int refine_item[5]; nullpo_retv(sd); skill_lv = pc->checkskill(sd,WS_WEAPONREFINE); fd=sd->fd; - - refine_item[0] = -1; - refine_item[1] = pc->search_inventory(sd,1010); - refine_item[2] = pc->search_inventory(sd,1011); - refine_item[3] = refine_item[4] = pc->search_inventory(sd,984); - + WFIFOHEAD(fd, MAX_INVENTORY * 13 + 4); WFIFOW(fd,0)=0x221; for(i=c=0;istatus.inventory[i].nameid > 0 && sd->status.inventory[i].refine < skill_lv && - sd->status.inventory[i].identify && (wlv=itemdb_wlv(sd->status.inventory[i].nameid)) >=1 && - refine_item[wlv]!=-1 && !(sd->status.inventory[i].equip&EQP_ARMS)){ + if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify + && (wlv=itemdb_wlv(sd->status.inventory[i].nameid)) >=1 + && !sd->inventory_data[i]->flag.no_refine + && !(sd->status.inventory[i].equip&EQP_ARMS)){ WFIFOW(fd,c*13+ 4)=i+2; WFIFOW(fd,c*13+ 6)=sd->status.inventory[i].nameid; WFIFOB(fd,c*13+ 8)=sd->status.inventory[i].refine; @@ -8498,8 +8530,8 @@ void clif_refresh(struct map_session_data *sd) if (sd->spiritball) clif->spiritball_single(sd->fd, sd); for(i = 1; i < 5; i++){ - if( sd->talisman[i] > 0 ) - clif->talisman_single(sd->fd, sd, i); + if( sd->charm[i] > 0 ) + clif->charm_single(sd->fd, sd, i); } if (sd->vd.cloth_color) clif->refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); @@ -9499,7 +9531,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if (iMap->night_flag && map[sd->bl.m].flag.nightenabled) { sd->state.night = 1; - clif->status_change(&sd->bl, SI_NIGHT, 1, 0, 0, 0, 0); + clif->status_change(&sd->bl, SI_SKE, 1, 0, 0, 0, 0); } // Notify everyone that this char logged in [Skotlex]. @@ -9537,11 +9569,11 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if( iMap->night_flag && map[sd->bl.m].flag.nightenabled ) { //Display night. if( !sd->state.night ) { sd->state.night = 1; - clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_NIGHT); + clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_SKE); } } else if( sd->state.night ) { //Clear night display. sd->state.night = 0; - clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_NIGHT); + clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_SKE); } if( map[sd->bl.m].flag.battleground ) { @@ -9586,7 +9618,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) npc_script_event(sd, NPCE_LOADMAP); if (pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd)) //blindness [Komurka] - clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_DEVIL); + clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_DEVIL1); if (sd->sc.opt2) //Client loses these on warp. clif->changeoption(&sd->bl); @@ -9862,7 +9894,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) if( atcommand->parse(fd, sd, message, 1) ) return; - if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEPSLEEP] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) { //[Skotlex] @@ -10321,7 +10353,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) if ( atcommand->parse(fd, sd, message, 1) ) return; - if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEPSLEEP] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) + if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) return; if (battle_config.min_chat_delay) { //[Skotlex] @@ -10602,7 +10634,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) return; } else if ( sd->state.storage_flag || sd->sc.opt1 ) ; //You can equip/unequip stuff while storage is open/under status changes - else if ( pc_cant_act2(sd) ) + else if ( pc_cant_act2(sd) || sd->state.prerefining ) return; if(!sd->status.inventory[index].identify) { @@ -10730,7 +10762,7 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd) return; } else if ( sd->state.storage_flag || sd->sc.opt1 ) ; //You can equip/unequip stuff while storage is open/under status changes - else if ( pc_cant_act2(sd) ) + else if ( pc_cant_act2(sd) || sd->state.prerefining ) return; index = RFIFOW(fd,2)-2; @@ -10751,7 +10783,12 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) clif_clearunit_area(&sd->bl,CLR_DEAD); return; } - + if( sd->npc_id || sd->state.workinprogress&2 ){ +#ifdef RENEWAL + clif->msg(sd, 0x783); // TODO look for the client date that has this message. +#endif + return; + } if ( pc_cant_act2(sd) || !(bl = iMap->id2bl(RFIFOL(fd,2))) ) return; @@ -10761,8 +10798,10 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) clif->pActionRequest_sub(sd, 0x07, bl->id, iTimer->gettick()); break; case BL_NPC: - if( sd->ud.skilltimer != INVALID_TIMER ) { - clif->colormes(fd,COLOR_WHITE,msg_txt(1476)); + if( sd->ud.skill_id < RK_ENCHANTBLADE && sd->ud.skilltimer != INVALID_TIMER ) {// TODO: should only work with none 3rd job skills +#ifdef RENEWAL + clif->msg(sd, 0x783); +#endif break; } if( bl->m != -1 )// the user can't click floating npcs directly (hack attempt) @@ -11270,7 +11309,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) // Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] sd->idletime = last_tick; - if( sd->npc_id ){ + if( sd->npc_id || sd->state.workinprogress&1 ){ #ifdef RENEWAL clif->msg(sd, 0x783); // TODO look for the client date that has this message. #endif @@ -11563,6 +11602,8 @@ void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) { int idx; + sd->state.prerefining = 0; + if (sd->menuskill_id != WS_WEAPONREFINE) //Packet exploit? return; if (pc_istrading(sd)) { @@ -11664,6 +11705,8 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd) if (sd->menuskill_id != MC_IDENTIFY) return; if( idx == -1 ) {// cancel pressed + sd->state.workinprogress = 0; + clif->item_identified(sd,idx-2,1); clif_menuskill_clear(sd); return; } @@ -12096,7 +12139,7 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd) if( atcommand->parse(fd, sd, message, 1) ) return; - if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEPSLEEP] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) @@ -12658,7 +12701,7 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) const uint8* data = (uint8*)RFIFOP(fd,85); if( !flag ) - sd->state.prevend = 0; + sd->state.prevend = sd->state.workinprogress = 0; if( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM ) return; @@ -12937,7 +12980,7 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd) if( atcommand->parse(fd, sd, message, 1) ) return; - if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEPSLEEP] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) @@ -15790,7 +15833,7 @@ void clif_parse_BattleChat(int fd, struct map_session_data* sd) if( atcommand->parse(fd, sd, message, 1) ) return; - if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC_DEEPSLEEP] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) + if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || sd->sc.data[SC_DEEP_SLEEP] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; if( battle_config.min_chat_delay ) { @@ -16735,7 +16778,7 @@ int clif_spellbook_list(struct map_session_data *sd) if( itemdb_is_spellbook(sd->status.inventory[i].nameid) ) { WFIFOW(fd, c * 2 + 4) = sd->status.inventory[i].nameid; - c ++; + c++; } } @@ -16926,7 +16969,7 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) { /*========================================== * Kagerou/Oboro amulet spirit *------------------------------------------*/ -void clif_talisman(struct map_session_data *sd,short type) +void clif_charm(struct map_session_data *sd,short type) { unsigned char buf[10]; @@ -16935,7 +16978,7 @@ void clif_talisman(struct map_session_data *sd,short type) WBUFW(buf,0)=0x08cf; WBUFL(buf,2)=sd->bl.id; WBUFW(buf,6)=type; - WBUFW(buf,8)=sd->talisman[type]; + WBUFW(buf,8)=sd->charm[type]; clif->send(buf,packet_len(0x08cf),&sd->bl,AREA); } /// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE] @@ -17744,7 +17787,7 @@ void clif_defaults(void) { clif->skill_fail = clif_skill_fail; clif->skill_cooldown = clif_skill_cooldown; clif->skill_memomessage = clif_skill_memomessage; - clif->skill_teleportmessage = clif_skill_teleportmessage; + clif->skill_mapinfomessage = clif_skill_mapinfomessage; clif->skill_produce_mix_list = clif_skill_produce_mix_list; clif->cooking_list = clif_cooking_list; clif->autospell = clif_autospell; @@ -17845,8 +17888,8 @@ void clif_defaults(void) { clif->specialeffect_single = clif_specialeffect_single; clif->specialeffect_value = clif_specialeffect_value; clif->millenniumshield = clif_millenniumshield; - clif->talisman = clif_talisman; - clif->talisman_single = clif_talisman_single; + clif->charm = clif_charm; + clif->charm_single = clif_charm_single; clif->snap = clif_snap; clif->weather_check = clif_weather_check; /* sound effects client-side */ diff --git a/src/map/clif.h b/src/map/clif.h index 5393ef5b7..b447687ea 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -231,7 +231,7 @@ enum map_type { // clif_map_type MAPTYPE_UNUSED = 29, }; -enum useskill_fail_cause { // clif_skill_fail +typedef enum useskill_fail_cause { // clif_skill_fail USESKILL_FAIL_LEVEL = 0, USESKILL_FAIL_SP_INSUFFICIENT = 1, USESKILL_FAIL_HP_INSUFFICIENT = 2, @@ -272,7 +272,7 @@ enum useskill_fail_cause { // clif_skill_fail USESKILL_FAIL_CANONBALL = 37, //XXX_USESKILL_FAIL_II_MADOGEAR_ACCELERATION = 38, //XXX_USESKILL_FAIL_II_MADOGEAR_HOVERING_BOOSTER = 39, - USESKILL_FAIL_MADOGEAR_HOVERING = 40, + //XXX_USESKILL_FAIL_MADOGEAR_HOVERING = 40, //XXX_USESKILL_FAIL_II_MADOGEAR_SELFDESTRUCTION_DEVICE = 41, //XXX_USESKILL_FAIL_II_MADOGEAR_SHAPESHIFTER = 42, USESKILL_FAIL_GUILLONTINE_POISON = 43, @@ -316,7 +316,7 @@ enum useskill_fail_cause { // clif_skill_fail USESKILL_FAIL_STYLE_CHANGE_FIGHTER = 81, USESKILL_FAIL_STYLE_CHANGE_GRAPPLER = 82, USESKILL_FAIL_THERE_ARE_NPC_AROUND = 83, -}; +}useskill_fail_cause; enum clif_messages { SKILL_CANT_USE_AREA = 0x536, @@ -571,7 +571,7 @@ struct clif_interface { void (*skill_fail) (struct map_session_data *sd,uint16 skill_id,enum useskill_fail_cause cause,int btype); void (*skill_cooldown) (struct map_session_data *sd, uint16 skill_id, unsigned int tick); void (*skill_memomessage) (struct map_session_data* sd, int type); - void (*skill_teleportmessage) (struct map_session_data *sd, int type); + void (*skill_mapinfomessage) (struct map_session_data *sd, int type); void (*skill_produce_mix_list) (struct map_session_data *sd, int skill_id, int trigger); void (*cooking_list) (struct map_session_data *sd, int trigger, uint16 skill_id, int qty, int list_type); void (*autospell) (struct map_session_data *sd,uint16 skill_lv); @@ -672,8 +672,8 @@ struct clif_interface { void (*specialeffect_single) (struct block_list* bl, int type, int fd); void (*specialeffect_value) (struct block_list* bl, int effect_id, int num, send_target target); void (*millenniumshield) (struct map_session_data *sd, short shields ); - void (*talisman) (struct map_session_data *sd, short type); - void (*talisman_single) (int fd, struct map_session_data *sd, short type); + void (*charm) (struct map_session_data *sd, short type); + void (*charm_single) (int fd, struct map_session_data *sd, short type); void (*snap) ( struct block_list *bl, short x, short y ); void (*weather_check) (struct map_session_data *sd); /* sound effects client-side */ diff --git a/src/map/itemdb.h b/src/map/itemdb.h index c441de26a..ea478d135 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -22,11 +22,13 @@ #define MAX_ITEMS_PER_COMBO 6 enum item_itemid { + ITEMID_HOLY_WATER = 523, ITEMID_EMPERIUM = 714, ITEMID_YELLOW_GEMSTONE = 715, ITEMID_RED_GEMSTONE = 716, ITEMID_BLUE_GEMSTONE = 717, ITEMID_TRAP = 1065, + ITEMID_FACE_PAINT = 6120, ITEMID_STONE = 7049, ITEMID_SKULL_ = 7420, ITEMID_TOKEN_OF_SIEGFRIED = 7621, @@ -66,6 +68,7 @@ enum { ITEMID_CAMOUFLAGE_GENERATOR, ITEMID_HIGH_QUALITY_COOLER, ITEMID_SPECIAL_COOLER, + ITEMID_MONKEY_SPANNER = 6186, } mecha_item_list; enum { diff --git a/src/map/map.c b/src/map/map.c index 0dab56d21..510f36109 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -358,10 +358,10 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) sc = status_get_sc(bl); skill->unit_move(bl,tick,2); - status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); - status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); + status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER); + status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); // status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure... - status_change_end(bl, SC_TATAMIGAESHI, INVALID_TIMER); + status_change_end(bl, SC_NJ_TATAMIGAESHI, INVALID_TIMER); status_change_end(bl, SC_MAGICROD, INVALID_TIMER); if (sc->data[SC_PROPERTYWALK] && sc->data[SC_PROPERTYWALK]->val3 >= skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) @@ -1667,45 +1667,19 @@ int map_quit(struct map_session_data *sd) { //(changing map-servers invokes unit_free but bypasses iMap->quit) if( sd->sc.count ) { //Status that are not saved... - status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER); - status_change_end(&sd->bl, SC_AUTOTRADE, INVALID_TIMER); - status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER); - status_change_end(&sd->bl, SC_BERSERK, INVALID_TIMER); - status_change_end(&sd->bl, SC__BLOODYLUST, INVALID_TIMER); - status_change_end(&sd->bl, SC_TRICKDEAD, INVALID_TIMER); - status_change_end(&sd->bl, SC_LEADERSHIP, INVALID_TIMER); - status_change_end(&sd->bl, SC_GLORYWOUNDS, INVALID_TIMER); - status_change_end(&sd->bl, SC_SOULCOLD, INVALID_TIMER); - status_change_end(&sd->bl, SC_HAWKEYES, INVALID_TIMER); - if(sd->sc.data[SC_ENDURE] && sd->sc.data[SC_ENDURE]->val4) - status_change_end(&sd->bl, SC_ENDURE, INVALID_TIMER); //No need to save infinite endure. - status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER); - status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER); - status_change_end(&sd->bl, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); - status_change_end(&sd->bl, SC_KYOUGAKU, INVALID_TIMER); - if (battle_config.debuff_on_logout&1) { - status_change_end(&sd->bl, SC_ORCISH, INVALID_TIMER); - status_change_end(&sd->bl, SC_STRIPWEAPON, INVALID_TIMER); - status_change_end(&sd->bl, SC_STRIPARMOR, INVALID_TIMER); - status_change_end(&sd->bl, SC_STRIPSHIELD, INVALID_TIMER); - status_change_end(&sd->bl, SC_STRIPHELM, INVALID_TIMER); - status_change_end(&sd->bl, SC_EXTREMITYFIST, INVALID_TIMER); - status_change_end(&sd->bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER); - if(sd->sc.data[SC_REGENERATION] && sd->sc.data[SC_REGENERATION]->val4) - status_change_end(&sd->bl, SC_REGENERATION, INVALID_TIMER); - //TO-DO Probably there are way more NPC_type negative status that are removed - status_change_end(&sd->bl, SC_CHANGEUNDEAD, INVALID_TIMER); - // Both these statuses are removed on logout. [L0ne_W0lf] - status_change_end(&sd->bl, SC_SLOWCAST, INVALID_TIMER); - status_change_end(&sd->bl, SC_CRITICALWOUND, INVALID_TIMER); - } - if (battle_config.debuff_on_logout&2) { - status_change_end(&sd->bl, SC_MAXIMIZEPOWER, INVALID_TIMER); - status_change_end(&sd->bl, SC_MAXOVERTHRUST, INVALID_TIMER); - status_change_end(&sd->bl, SC_STEELBODY, INVALID_TIMER); - status_change_end(&sd->bl, SC_PRESERVE, INVALID_TIMER); - status_change_end(&sd->bl, SC_KAAHI, INVALID_TIMER); - status_change_end(&sd->bl, SC_SPIRIT, INVALID_TIMER); + for(i=0; i < SC_MAX; i++){ + if ( status_get_sc_type(i)&SC_NO_SAVE ){ + if ( !sd->sc.data[i] ) + continue; + switch( i ){ + case SC_ENDURE: + case SC_GDSKILL_REGENERATION: + if( !sd->sc.data[i]->val4 ) + break; + default: + status_change_end(&sd->bl, (sc_type)i, INVALID_TIMER); + } + } } } diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 91d685a49..566f68409 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -361,7 +361,7 @@ int mercenary_dead(struct mercenary_data *md) int mercenary_killbonus(struct mercenary_data *md) { - const enum sc_type scs[] = { SC_MERC_FLEEUP, SC_MERC_ATKUP, SC_MERC_HPUP, SC_MERC_SPUP, SC_MERC_HITUP }; + const enum sc_type scs[] = { SC_MER_FLEE, SC_MER_ATK, SC_MER_HP, SC_MER_SP, SC_MER_HIT }; int index = rnd() % ARRAYLENGTH(scs); sc_start(&md->bl, scs[index], 100, rnd() % 5, 600000); diff --git a/src/map/mob.c b/src/map/mob.c index 04c4bba38..6bb40478f 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1461,7 +1461,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) if( !battle->check_range(&md->bl, tbl, md->status.rhw.range) && ( //Can't attack back and can't reach back. (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) - || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNSTRAP] + || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP] || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target. || !mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) ) @@ -1484,7 +1484,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) || (!battle->check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ... && ( // Reach check (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) - || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNSTRAP] + || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP] || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target. || !mob_can_reach(md, abl, dist+md->db->range3, MSS_RUSH) ) @@ -2360,9 +2360,9 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) (int)(md->level - sd->status.base_level) >= 20) drop_rate = (int)(drop_rate*1.25); // pk_mode increase drops if 20 level difference [Valaris] - // Increase drop rate if user has SC_ITEMBOOST - if (sd && sd->sc.data[SC_ITEMBOOST]) // now rig the drop rate to never be over 90% unless it is originally >90%. - drop_rate = max(drop_rate,cap_value((int)(0.5+drop_rate*(sd->sc.data[SC_ITEMBOOST]->val1)/100.),0,9000)); + // Increase drop rate if user has SC_CASH_RECEIVEITEM + if (sd && sd->sc.data[SC_CASH_RECEIVEITEM]) // now rig the drop rate to never be over 90% unless it is originally >90%. + drop_rate = max(drop_rate,cap_value((int)(0.5+drop_rate*(sd->sc.data[SC_CASH_RECEIVEITEM]->val1)/100.),0,9000)); #ifdef RENEWAL_DROP if( drop_modifier != 100 ) { drop_rate = drop_rate * drop_modifier / 100; diff --git a/src/map/packets.h b/src/map/packets.h index 4f2b119fb..bcce36040 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -2091,6 +2091,7 @@ packet(0x020d,-1); // New Packets packet(0x0998,8,clif->pEquipItem,2,4); packet(0x0447,2); // PACKET_CZ_BLOCKING_PLAY_CANCEL + packet(0x099f,24); // New Packets End #endif diff --git a/src/map/party.c b/src/map/party.c index e30d16c07..adcb35c5a 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -840,7 +840,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id break; case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators if((p_sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR - && sd->sc.data[SC_READYCOUNTER] + && sd->sc.data[SC_COUNTERKICK_READY] && pc->checkskill(p_sd,SG_FRIEND)) { sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER, 50+50*pc->checkskill(p_sd,SG_FRIEND), //+100/150/200% rate diff --git a/src/map/pc.c b/src/map/pc.c index 170de63ff..155812836 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -868,20 +868,20 @@ int pc_isequip(struct map_session_data *sd,int n) if (sd->sc.count) { - if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_STRIPWEAPON]) // Also works with left-hand weapons [DracoRPG] + if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_NOEQUIPWEAPON]) // Also works with left-hand weapons [DracoRPG] return 0; - if(item->equip & EQP_SHIELD && item->type == IT_ARMOR && sd->sc.data[SC_STRIPSHIELD]) + if(item->equip & EQP_SHIELD && item->type == IT_ARMOR && sd->sc.data[SC_NOEQUIPSHIELD]) return 0; - if(item->equip & EQP_ARMOR && sd->sc.data[SC_STRIPARMOR]) + if(item->equip & EQP_ARMOR && sd->sc.data[SC_NOEQUIPARMOR]) return 0; - if(item->equip & EQP_HEAD_TOP && sd->sc.data[SC_STRIPHELM]) + if(item->equip & EQP_HEAD_TOP && sd->sc.data[SC_NOEQUIPHELM]) return 0; - if(item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSORY]) + if(item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSARY]) return 0; if(item->equip && sd->sc.data[SC_KYOUGAKU]) return 0; - if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SUPERNOVICE) { + if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_SUPERNOVICE) { //Spirit of Super Novice equip bonuses. [Skotlex] if (sd->status.base_level > 90 && item->equip & EQP_HELM) return 1; //Can equip all helms @@ -1338,7 +1338,7 @@ int pc_calc_skilltree(struct map_session_data *sd) sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; } - if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && skill_db[i].nameid >= DC_HUMMING && skill_db[i].nameid <= DC_SERVICEFORYOU ) + if( sd->sc.count && sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_BARDDANCER && skill_db[i].nameid >= DC_HUMMING && skill_db[i].nameid <= DC_SERVICEFORYOU ) { //Enable Bard/Dancer spirit linked skills. if( sd->status.sex ) { //Link dancer skills to bard. @@ -1427,7 +1427,7 @@ int pc_calc_skilltree(struct map_session_data *sd) if(!sd->status.skill[idx].lv && ( (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || inf2&INF2_WEDDING_SKILL || - (inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) + (inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SOULLINK]) )) continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills. @@ -1459,7 +1459,7 @@ int pc_calc_skilltree(struct map_session_data *sd) if( sd->status.skill[idx].id == 0 ) { sd->status.skill[idx].id = id; sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill. - } else if( id != NV_BASIC) { + } else if( id != NV_BASIC ) { sd->status.skill[idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[idx].lv; // Remember original level } @@ -1518,7 +1518,7 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill_id) if( !sd->status.skill[idx].lv && ( (j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || j&INF2_WEDDING_SKILL || - (j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) + (j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SOULLINK]) ) ) continue; //Cannot be learned via normal means. @@ -1620,7 +1620,7 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd) *------------------------------------------ * 1: overweight 50% * 2: overweight 90% - * It's assumed that SC_WEIGHT50 and SC_WEIGHT90 are only started/stopped here. + * It's assumed that SC_WEIGHTOVER50 and SC_WEIGHTOVER90 are only started/stopped here. */ int pc_updateweightstatus(struct map_session_data *sd) { @@ -1629,7 +1629,7 @@ int pc_updateweightstatus(struct map_session_data *sd) nullpo_retr(1, sd); - old_overweight = (sd->sc.data[SC_WEIGHT90]) ? 2 : (sd->sc.data[SC_WEIGHT50]) ? 1 : 0; + old_overweight = (sd->sc.data[SC_WEIGHTOVER90]) ? 2 : (sd->sc.data[SC_WEIGHTOVER50]) ? 1 : 0; new_overweight = (pc_is90overweight(sd)) ? 2 : (pc_is50overweight(sd)) ? 1 : 0; if( old_overweight == new_overweight ) @@ -1637,15 +1637,15 @@ int pc_updateweightstatus(struct map_session_data *sd) // stop old status change if( old_overweight == 1 ) - status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER); + status_change_end(&sd->bl, SC_WEIGHTOVER50, INVALID_TIMER); else if( old_overweight == 2 ) - status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER); + status_change_end(&sd->bl, SC_WEIGHTOVER90, INVALID_TIMER); // start new status change if( new_overweight == 1 ) - sc_start(&sd->bl, SC_WEIGHT50, 100, 0, 0); + sc_start(&sd->bl, SC_WEIGHTOVER50, 100, 0, 0); else if( new_overweight == 2 ) - sc_start(&sd->bl, SC_WEIGHT90, 100, 0, 0); + sc_start(&sd->bl, SC_WEIGHTOVER90, 100, 0, 0); // update overweight status sd->regen.state.overweight = new_overweight; @@ -2070,12 +2070,13 @@ int pc_bonus(struct map_session_data *sd,int type,int val) break; case SP_BASE_ATK: if(sd->state.lr_flag != 2) { - //#ifdef RENEWAL - // sd->bonus.eatk += val; - //#else +#ifdef RENEWAL + sd->bonus.eatk += val; + clif->updatestatus(sd,SP_ATK2); +#else bonus = status->batk + val; status->batk = cap_value(bonus, 0, USHRT_MAX); - //#endif +#endif } break; case SP_DEF1: @@ -2431,7 +2432,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG] if(sd->state.lr_flag != 2) { sd->special_state.intravision = 1; - clif->status_change(&sd->bl, SI_INTRAVISION, 1, 0, 0, 0, 0); + clif->status_change(&sd->bl, SI_CLAIRVOYANCE, 1, 0, 0, 0, 0); } break; case SP_NO_KNOCKBACK: @@ -4122,7 +4123,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) case 12212: // Giant Fly Wing if( map[sd->bl.m].flag.noteleport || map_flag_gvg(sd->bl.m) ) { - clif->skill_teleportmessage(sd,0); + clif->skill_mapinfomessage(sd,0); return 0; } case 602: // ButterFly Wing @@ -4150,7 +4151,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) break; case 12210: // Bubble Gum case 12264: // Comp Bubble Gum - if( sd->sc.data[SC_ITEMBOOST] ) + if( sd->sc.data[SC_CASH_RECEIVEITEM] ) return 0; break; case 12208: // Battle Manual @@ -4160,11 +4161,11 @@ int pc_isUseitem(struct map_session_data *sd,int n) case 14532: // Battle_Manual25 case 14533: // Battle_Manual100 case 14545: // Battle_Manual300 - if( sd->sc.data[SC_EXPBOOST] ) + if( sd->sc.data[SC_CASH_PLUSEXP] ) return 0; break; case 14592: // JOB_Battle_Manual - if( sd->sc.data[SC_JEXPBOOST] ) + if( sd->sc.data[SC_CASH_PLUSONLYJOBEXP] ) return 0; break; @@ -4177,7 +4178,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) case 12243: // Mercenary's Berserk Potion if( sd->md == NULL || sd->md->db == NULL ) return 0; - if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAYNIGHTFEVER] || sd->md->sc.data[SC__BLOODYLUST]) + if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAY_NIGHT_FEVER] || sd->md->sc.data[SC__BLOODYLUST]) return 0; if( nameid == 12242 && sd->md->db->lv < 40 ) return 0; @@ -4281,7 +4282,8 @@ int pc_useitem(struct map_session_data *sd,int n) sd->sc.data[SC_HIDING] || sd->sc.data[SC__SHADOWFORM] || sd->sc.data[SC__MANHOLE] || - sd->sc.data[SC_KAGEHUMI] || + sd->sc.data[SC_KG_KAGEHUMI] || + sd->sc.data[SC_WHITEIMPRISON] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) )) return 0; @@ -4315,16 +4317,7 @@ int pc_useitem(struct map_session_data *sd,int n) if( sd->item_delay[i].nameid ) {// found if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) { int e_tick = DIFF_TICK(sd->item_delay[i].tick, tick)/1000; - char e_msg[100]; - if( e_tick > 99 ) - sprintf(e_msg,"Item Failed. [%s] is cooling down. wait %.1f minutes.", - itemdb_jname(sd->status.inventory[n].nameid), - (double)e_tick / 60); - else - sprintf(e_msg,"Item Failed. [%s] is cooling down. wait %d seconds.", - itemdb_jname(sd->status.inventory[n].nameid), - e_tick+1); - clif->colormes(sd->fd,COLOR_RED,e_msg); + clif->msgtable_num(sd->fd, 0x746, e_tick + 1); // [%d] seconds left until you can use return 0; // Delay has not expired yet } } else {// not yet used item (all slots are initially empty) @@ -4375,7 +4368,7 @@ int pc_useitem(struct map_session_data *sd,int n) pc->famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST)) { potion_flag = 2; // Famous player's potions have 50% more efficiency - if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ROGUE) + if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ROGUE) potion_flag = 3; //Even more effective potions. } @@ -4781,7 +4774,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y if (sd->sc.count) { // Cancel some map related stuff. if (sd->sc.data[SC_JAILED]) return 1; //You may not get out! - status_change_end(&sd->bl, SC_BOSSMAPINFO, INVALID_TIMER); + status_change_end(&sd->bl, SC_CASH_BOSS_ALARM, INVALID_TIMER); status_change_end(&sd->bl, SC_WARM, INVALID_TIMER); status_change_end(&sd->bl, SC_SUN_COMFORT, INVALID_TIMER); status_change_end(&sd->bl, SC_MOON_COMFORT, INVALID_TIMER); @@ -4947,7 +4940,7 @@ int pc_memo(struct map_session_data* sd, int pos) // check mapflags if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) { - clif->skill_teleportmessage(sd, 1); // "Saved point cannot be memorized." + clif->skill_mapinfomessage(sd, 1); // "Saved point cannot be memorized." return 0; } @@ -5038,21 +5031,24 @@ int pc_checkallowskill(struct map_session_data *sd) { const enum sc_type scw_list[] = { SC_TWOHANDQUICKEN, - SC_ONEHAND, + SC_ONEHANDQUICKEN, SC_AURABLADE, SC_PARRYING, SC_SPEARQUICKEN, SC_ADRENALINE, SC_ADRENALINE2, SC_DANCING, - SC_GATLINGFEVER, + SC_GS_GATLINGFEVER, +#ifdef RENEWAL + SC_EDP, +#endif SC_FEARBREEZE }; const enum sc_type scs_list[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, - SC_REFLECTDAMAGE + SC_LG_REFLECTDAMAGE }; int i; nullpo_ret(sd); @@ -5069,9 +5065,9 @@ int pc_checkallowskill(struct map_session_data *sd) status_change_end(&sd->bl, scw_list[i], INVALID_TIMER); } - if(sd->sc.data[SC_SPURT] && sd->status.weapon) + if(sd->sc.data[SC_STRUP] && sd->status.weapon) // Spurt requires bare hands (feet, in fact xD) - status_change_end(&sd->bl, SC_SPURT, INVALID_TIMER); + status_change_end(&sd->bl, SC_STRUP, INVALID_TIMER); if(sd->status.shield <= 0) { // Skills requiring a shield for (i = 0; i < ARRAYLENGTH(scs_list); i++) @@ -5755,7 +5751,7 @@ int pc_checkjoblevelup(struct map_session_data *sd) status_calc_pc(sd,0); clif->misceffect(&sd->bl,1); if (pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd)) - clif->status_change(&sd->bl,SI_DEVIL, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL. + clif->status_change(&sd->bl,SI_DEVIL1, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL. npc_script_event(sd, NPCE_JOBLVUP); return 1; @@ -5777,13 +5773,13 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi (int)(status_get_lv(src) - sd->status.base_level) >= 20) bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris] - if (sd->sc.data[SC_EXPBOOST]) - bonus += sd->sc.data[SC_EXPBOOST]->val1; + if (sd->sc.data[SC_CASH_PLUSEXP]) + bonus += sd->sc.data[SC_CASH_PLUSEXP]->val1; *base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * bonus/100., 1, UINT_MAX); - if (sd->sc.data[SC_JEXPBOOST]) - bonus += sd->sc.data[SC_JEXPBOOST]->val1; + if (sd->sc.data[SC_CASH_PLUSONLYJOBEXP]) + bonus += sd->sc.data[SC_CASH_PLUSONLYJOBEXP]->val1; *job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * bonus/100., 1, UINT_MAX); @@ -6134,6 +6130,19 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) { clif->updatestatus(sd,SP_CARTINFO); if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown clif->skillinfoblock(sd); + }else if( battle_config.skillup_limit ){ + int pts = 0, i, id; + for(i = 0; i < MAX_SKILL_TREE && (id=skill_tree[pc_class2idx(sd->status.class_)][i].id) > 0 ; i++){ + int inf2 = skill->get_inf2(id); + if ( inf2&INF2_QUEST_SKILL || (inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) || id == NV_BASIC ) + continue; + if( sd->status.skill[id].id && sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) + pts += pc_checkskill(sd, id); + } + if( pts < sd->change_level_2nd ) + clif->msg_value(sd, 0x61E, sd->change_level_2nd-pts); + else if( pts < (sd->change_level_3rd + sd->change_level_2nd) ) + clif->msg_value(sd, 0x61F, sd->change_level_3rd - (pts - sd->change_level_2nd)); } return 0; @@ -6370,7 +6379,7 @@ int pc_resetskill(struct map_session_data* sd, int flag) return 0; if( pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd) ) //Remove perma blindness due to skill-reset. [Skotlex] - clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_DEVIL); + clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_DEVIL1); i = sd->sc.option; if( i&OPTION_RIDING && (!pc->checkskill(sd, KN_RIDING) || (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) ) i &= ~OPTION_RIDING; @@ -6691,7 +6700,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { pc->delspiritball(sd,sd->spiritball,0); for(i = 1; i < 5; i++) - pc->del_talisman(sd, sd->talisman[i], i); + pc->del_charm(sd, sd->charm[i], i); if (src) { switch (src->type) { @@ -6801,7 +6810,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { if(battle_config.death_penalty_type && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty && !map[sd->bl.m].flag.noexppenalty && !map_flag_gvg(sd->bl.m) - && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_LIFEINSURANCE]) + && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY]) { unsigned int base_penalty =0; if (battle_config.death_penalty_base > 0) { @@ -7304,8 +7313,8 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp) hp = hp * bonus / 100; // Recovery Potion - if( sd->sc.data[SC_INCHEALRATE] ) - hp += (int)(hp * sd->sc.data[SC_INCHEALRATE]->val1/100.); + if( sd->sc.data[SC_HEALPLUS] ) + hp += (int)(hp * sd->sc.data[SC_HEALPLUS]->val1/100.); } if(sp) { bonus = 100 + (sd->battle_status.int_<<1) @@ -7529,7 +7538,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) //Remove peco/cart/falcon i = sd->sc.option; - if( i&OPTION_RIDING && !pc->checkskill(sd, KN_RIDING) ) + if( i&OPTION_RIDING && (!pc->checkskill(sd, KN_RIDING) || (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) ) i&=~OPTION_RIDING; if( i&OPTION_FALCON && !pc->checkskill(sd, HT_FALCON) ) i&=~OPTION_FALCON; @@ -7715,22 +7724,23 @@ int pc_setoption(struct map_session_data *sd,int type) } } if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) { - if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) ) { + int i; + if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) ) status_calc_pc(sd, 0); - status_change_end(&sd->bl,SC_MAXIMIZEPOWER,INVALID_TIMER); - status_change_end(&sd->bl,SC_OVERTHRUST,INVALID_TIMER); - status_change_end(&sd->bl,SC_WEAPONPERFECTION,INVALID_TIMER); - status_change_end(&sd->bl,SC_ADRENALINE,INVALID_TIMER); - status_change_end(&sd->bl,SC_CARTBOOST,INVALID_TIMER); - status_change_end(&sd->bl,SC_MELTDOWN,INVALID_TIMER); - status_change_end(&sd->bl,SC_MAXOVERTHRUST,INVALID_TIMER); - } else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR ) { + else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR ) status_calc_pc(sd, 0); - status_change_end(&sd->bl,SC_SHAPESHIFT,INVALID_TIMER); - status_change_end(&sd->bl,SC_HOVERING,INVALID_TIMER); - status_change_end(&sd->bl,SC_ACCELERATION,INVALID_TIMER); - status_change_end(&sd->bl,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); - status_change_end(&sd->bl,SC_OVERHEAT,INVALID_TIMER); + for( i = 0; i < SC_MAX; i++ ){ + if ( !sd->sc.data[i] || !status_get_sc_type(i) ) + continue; + if ( status_get_sc_type(i)&SC_MADO_NO_RESET ) + continue; + switch (i) { + case SC_BERSERK: + case SC_SATURDAY_NIGHT_FEVER: + sd->sc.data[i]->val2 = 0; + break; + } + status_change_end(&sd->bl, (sc_type)i, INVALID_TIMER); } } @@ -8503,7 +8513,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) return 0; } - if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST]) + if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER] || sd->sc.data[SC__BLOODYLUST]) { clif->equipitemack(sd,n,0,0); // fail return 0; @@ -8699,7 +8709,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { } // if player is berserk then cannot unequip - if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST])) + if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER] || sd->sc.data[SC__BLOODYLUST])) { clif->unequipitemack(sd,n,0,0); return 0; @@ -8780,7 +8790,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { clif->unequipitemack(sd,n,sd->status.inventory[n].equip,1); if((sd->status.inventory[n].equip & EQP_ARMS) && - sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!) + sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_TK_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!) skill->enchant_elemental_end(&sd->bl,-1); if(sd->status.inventory[n].equip & EQP_ARMOR) { @@ -8822,8 +8832,8 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { status_calc_pc(sd,0); } - if(sd->sc.data[SC_SIGNUMCRUCIS] && !battle->check_undead(sd->battle_status.race,sd->battle_status.def_ele)) - status_change_end(&sd->bl, SC_SIGNUMCRUCIS, INVALID_TIMER); + if(sd->sc.data[SC_CRUCIS] && !battle->check_undead(sd->battle_status.race,sd->battle_status.def_ele)) + status_change_end(&sd->bl, SC_CRUCIS, INVALID_TIMER); //OnUnEquip script [Skotlex] if (sd->inventory_data[n]) { @@ -9209,7 +9219,7 @@ int pc_autosave(int tid, unsigned int tick, int id, intptr_t data) static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) { if (sd->state.night != iMap->night_flag && map[sd->bl.m].flag.nightenabled) { //Night/day state does not match. - clif->status_change(&sd->bl, SI_NIGHT, iMap->night_flag, 0, 0, 0, 0); //New night effect by dynamix [Skotlex] + clif->status_change(&sd->bl, SI_SKE, iMap->night_flag, 0, 0, 0, 0); //New night effect by dynamix [Skotlex] sd->state.night = iMap->night_flag; return 1; } @@ -9313,7 +9323,7 @@ bool pc_can_use_command(struct map_session_data *sd, const char *command) { return atcommand->can_use(sd,command); } -static int pc_talisman_timer(int tid, unsigned int tick, int id, intptr_t data) +static int pc_charm_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd; int i, type; @@ -9321,33 +9331,33 @@ static int pc_talisman_timer(int tid, unsigned int tick, int id, intptr_t data) if( (sd=(struct map_session_data *)iMap->id2sd(id)) == NULL || sd->bl.type!=BL_PC ) return 1; - ARR_FIND(1, 5, type, sd->talisman[type] > 0); + ARR_FIND(1, 5, type, sd->charm[type] > 0); - if( sd->talisman[type] <= 0 ) + if( sd->charm[type] <= 0 ) { - ShowError("pc_talisman_timer: %d talisman's available. (aid=%d cid=%d tid=%d)\n", sd->talisman[type], sd->status.account_id, sd->status.char_id, tid); - sd->talisman[type] = 0; + ShowError("pc_charm_timer: %d charm's available. (aid=%d cid=%d tid=%d)\n", sd->charm[type], sd->status.account_id, sd->status.char_id, tid); + sd->charm[type] = 0; return 0; } - ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == tid); - if( i == sd->talisman[type] ) + ARR_FIND(0, sd->charm[type], i, sd->charm_timer[type][i] == tid); + if( i == sd->charm[type] ) { - ShowError("pc_talisman_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid); + ShowError("pc_charm_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid); return 0; } - sd->talisman[type]--; - if( i != sd->talisman[type] ) - memmove(sd->talisman_timer[type]+i, sd->talisman_timer[type]+i+1, (sd->talisman[type]-i)*sizeof(int)); - sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER; + sd->charm[type]--; + if( i != sd->charm[type] ) + memmove(sd->charm_timer[type]+i, sd->charm_timer[type]+i+1, (sd->charm[type]-i)*sizeof(int)); + sd->charm_timer[type][sd->charm[type]] = INVALID_TIMER; - clif->talisman(sd, type); + clif->charm(sd, type); return 0; } -int pc_add_talisman(struct map_session_data *sd,int interval,int max,int type) +int pc_add_charm(struct map_session_data *sd,int interval,int max,int type) { int tid, i; @@ -9355,61 +9365,61 @@ int pc_add_talisman(struct map_session_data *sd,int interval,int max,int type) if(max > 10) max = 10; - if(sd->talisman[type] < 0) - sd->talisman[type] = 0; + if(sd->charm[type] < 0) + sd->charm[type] = 0; - if( sd->talisman[type] && sd->talisman[type] >= max ) + if( sd->charm[type] && sd->charm[type] >= max ) { - if(sd->talisman_timer[type][0] != INVALID_TIMER) - iTimer->delete_timer(sd->talisman_timer[type][0],pc_talisman_timer); - sd->talisman[type]--; - if( sd->talisman[type] != 0 ) - memmove(sd->talisman_timer[type]+0, sd->talisman_timer[type]+1, (sd->talisman[type])*sizeof(int)); - sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER; - } - - tid = iTimer->add_timer(iTimer->gettick()+interval, pc_talisman_timer, sd->bl.id, 0); - ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == INVALID_TIMER || DIFF_TICK(iTimer->get_timer(tid)->tick,iTimer->get_timer(sd->talisman_timer[type][i])->tick) < 0); - if( i != sd->talisman[type] ) - memmove(sd->talisman_timer[type]+i+1, sd->talisman_timer[type]+i, (sd->talisman[type]-i)*sizeof(int)); - sd->talisman_timer[type][i] = tid; - sd->talisman[type]++; - - clif->talisman(sd, type); + if(sd->charm_timer[type][0] != INVALID_TIMER) + iTimer->delete_timer(sd->charm_timer[type][0],pc_charm_timer); + sd->charm[type]--; + if( sd->charm[type] != 0 ) + memmove(sd->charm_timer[type]+0, sd->charm_timer[type]+1, (sd->charm[type])*sizeof(int)); + sd->charm_timer[type][sd->charm[type]] = INVALID_TIMER; + } + + tid = iTimer->add_timer(iTimer->gettick()+interval, pc_charm_timer, sd->bl.id, 0); + ARR_FIND(0, sd->charm[type], i, sd->charm_timer[type][i] == INVALID_TIMER || DIFF_TICK(iTimer->get_timer(tid)->tick, iTimer->get_timer(sd->charm_timer[type][i])->tick) < 0); + if( i != sd->charm[type] ) + memmove(sd->charm_timer[type]+i+1, sd->charm_timer[type]+i, (sd->charm[type]-i)*sizeof(int)); + sd->charm_timer[type][i] = tid; + sd->charm[type]++; + + clif->charm(sd, type); return 0; } -int pc_del_talisman(struct map_session_data *sd,int count,int type) +int pc_del_charm(struct map_session_data *sd,int count,int type) { int i; nullpo_ret(sd); - if( sd->talisman[type] <= 0 ) { - sd->talisman[type] = 0; + if( sd->charm[type] <= 0 ) { + sd->charm[type] = 0; return 0; } if( count <= 0 ) return 0; - if( count > sd->talisman[type] ) - count = sd->talisman[type]; - sd->talisman[type] -= count; + if( count > sd->charm[type] ) + count = sd->charm[type]; + sd->charm[type] -= count; if( count > 10 ) count = 10; for(i = 0; i < count; i++) { - if(sd->talisman_timer[type][i] != INVALID_TIMER) { - iTimer->delete_timer(sd->talisman_timer[type][i],pc_talisman_timer); - sd->talisman_timer[type][i] = INVALID_TIMER; + if(sd->charm_timer[type][i] != INVALID_TIMER) { + iTimer->delete_timer(sd->charm_timer[type][i],pc_charm_timer); + sd->charm_timer[type][i] = INVALID_TIMER; } } for(i = count; i < 10; i++) { - sd->talisman_timer[type][i-count] = sd->talisman_timer[type][i]; - sd->talisman_timer[type][i] = INVALID_TIMER; + sd->charm_timer[type][i-count] = sd->charm_timer[type][i]; + sd->charm_timer[type][i] = INVALID_TIMER; } - clif->talisman(sd, type); + clif->charm(sd, type); return 0; } #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) @@ -9854,7 +9864,7 @@ int do_init_pc(void) { iTimer->add_timer_func_list(pc_spiritball_timer, "pc_spiritball_timer"); iTimer->add_timer_func_list(pc_follow_timer, "pc_follow_timer"); iTimer->add_timer_func_list(pc->endautobonus, "pc->endautobonus"); - iTimer->add_timer_func_list(pc_talisman_timer, "pc_talisman_timer"); + iTimer->add_timer_func_list(pc_charm_timer, "pc_charm_timer"); iTimer->add_timer(iTimer->gettick() + iMap->autosave_interval, pc_autosave, 0, 0); @@ -10087,8 +10097,8 @@ void pc_defaults(void) { pc->load_combo = pc_load_combo; - pc->add_talisman = pc_add_talisman; - pc->del_talisman = pc_del_talisman; + pc->add_charm = pc_add_charm; + pc->del_charm = pc_del_charm; pc->baselevelchanged = pc_baselevelchanged; #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) diff --git a/src/map/pc.h b/src/map/pc.h index ebf474823..cd2a45a6b 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -160,6 +160,8 @@ struct map_session_data { unsigned int warping : 1;//states whether you're in the middle of a warp processing unsigned int permanent_speed : 1; // When 1, speed cannot be changed through status_calc_pc(). unsigned int dialog : 1; + unsigned int prerefining : 1; + unsigned int workinprogress : 3; // 1 = disable skill/item, 2 = disable npc interaction, 3 = disable both } state; struct { unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; @@ -190,7 +192,7 @@ struct map_session_data { unsigned char head_dir; //0: Look forward. 1: Look right, 2: Look left. unsigned int client_tick; int npc_id,areanpc_id,npc_shopid,touching_id; //for script follow scriptoid; ,npcid - int npc_item_flag; //Marks the npc_id with which you can use items during interactions with said npc (see script command enable_itemuse) + int npc_item_flag; //Marks the npc_id with which you can change equipments during interactions with said npc (see script command enable_itemuse) int npc_menu; // internal variable, used in npc menu handling int npc_amount; struct script_state *st; @@ -324,7 +326,7 @@ struct map_session_data { int fixcastrate,varcastrate; int add_fixcast,add_varcast; int ematk; // matk bonus from equipment -// int eatk; // atk bonus from equipment + int eatk; // atk bonus from equipment } bonus; // zeroed vars end here. int castrate,delayrate,hprate,sprate,dsprate; @@ -336,8 +338,8 @@ struct map_session_data { short catch_target_class; // pet catching, stores a pet class to catch (short now) [zzo] short spiritball, spiritball_old; int spirit_timer[MAX_SPIRITBALL]; - short talisman[ELE_POISON+1]; // There are actually 5 talisman Fire, Ice, Wind, Earth & Poison maybe because its color violet. - int talisman_timer[ELE_POISON+1][10]; + short charm[ELE_POISON+1]; // There are actually 5 charm Fire, Ice, Wind, Earth & Poison maybe because its color violet. + int charm_timer[ELE_POISON+1][10]; unsigned char potion_success_counter; //Potion successes in row counter unsigned char mission_count; //Stores the bounty kill count for TK_MISSION short mission_mobid; //Stores the target mob_id for TK_MISSION @@ -650,13 +652,13 @@ enum equip_pos { // clientside display macros (values to the left/right of the "+") #ifdef RENEWAL #define pc_leftside_atk(sd) ((sd)->battle_status.batk) - #define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk + (sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2) + #define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk + (sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2 + (sd)->bonus.eatk ) #define pc_leftside_def(sd) ((sd)->battle_status.def2) #define pc_rightside_def(sd) ((sd)->battle_status.def) #define pc_leftside_mdef(sd) ((sd)->battle_status.mdef2) #define pc_rightside_mdef(sd) ((sd)->battle_status.mdef) #define pc_leftside_matk(sd) (status_base_matk(status_get_status_data(&(sd)->bl), (sd)->status.base_level)) -#define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->bonus.ematk) +#define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->battle_status.lhw.matk+(sd)->bonus.ematk) #else #define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk) #define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2) @@ -940,8 +942,8 @@ struct pc_interface { int (*load_combo) (struct map_session_data *sd); - int (*add_talisman) (struct map_session_data *sd,int interval,int max,int type); - int (*del_talisman) (struct map_session_data *sd,int count,int type); + int (*add_charm) (struct map_session_data *sd,int interval,int max,int type); + int (*del_charm) (struct map_session_data *sd,int count,int type); void (*baselevelchanged) (struct map_session_data *sd); #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) diff --git a/src/map/script.c b/src/map/script.c index e1015a718..a01372385 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -9581,8 +9581,8 @@ BUILDIN(sc_end) switch (type) { - case SC_WEIGHT50: - case SC_WEIGHT90: + case SC_WEIGHTOVER50: + case SC_WEIGHTOVER90: case SC_NOCHAT: case SC_PUSH_CART: return true; diff --git a/src/map/skill.c b/src/map/skill.c index 15c133dc1..dcc422da5 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -346,7 +346,6 @@ int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { **/ case WL_WHITEIMPRISON: case WL_SOULEXPANSION: - case WL_FROSTMISTY: case WL_MARSHOFABYSS: case WL_SIENNAEXECRATE: case WL_DRAINLIFE: @@ -355,6 +354,7 @@ int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { case WL_COMET: case WL_CHAINLIGHTNING: case WL_TETRAVORTEX: + case WL_EARTHSTRAIN: case WL_RELEASE: if( bl->type == BL_PC ) range += pc->checkskill((TBL_PC*)bl, WL_RADIUS); @@ -385,13 +385,13 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk struct status_change* sc; switch( skill_id ) { - case BA_APPLEIDUN: + case BA_APPLEIDUN: #ifdef RENEWAL - hp = 100+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery + hp = 100+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery #else - hp = 30+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery + hp = 30+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery #endif - if( sd ) + if( sd ) hp += 5*pc->checkskill(sd,BA_MUSICALLESSON); break; case PR_SANCTUARY: @@ -406,7 +406,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk #ifdef RENEWAL /** * Renewal Heal Formula - * Formula: ( [(Base Level + INT) / 5] ļæ½ 30 ) ļæ½ (Heal Level / 10) ļæ½ (Modifiers) + MATK + * Formula: ( [(Base Level + INT) / 5] ? 30 ) ? (Heal Level / 10) ? (Modifiers) + MATK **/ hp = (status_get_lv(src) + status_get_int(src)) / 5 * 30 * skill_lv / 10; #else @@ -434,10 +434,12 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk hp -= hp * sc->data[SC_CRITICALWOUND]->val2/100; if( sc->data[SC_DEATHHURT] && heal ) hp -= hp * 20/100; - if( sc->data[SC_INCHEALRATE] && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN ) - hp += hp * sc->data[SC_INCHEALRATE]->val1/100; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish] + if( sc->data[SC_HEALPLUS] && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN ) + hp += hp * sc->data[SC_HEALPLUS]->val1/100; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish] if( sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) hp += hp / 10; + if( sc->data[SC_OFFERTORIUM] && (skill_id == AB_HIGHNESSHEAL || skill_id == AB_CHEAL || skill_id == PR_SANCTUARY || skill_id == AL_HEAL) ) + hp += hp * sc->data[SC_OFFERTORIUM]->val2 / 100; } #ifdef RENEWAL @@ -447,32 +449,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk case BA_APPLEIDUN: case PR_SANCTUARY: case NPC_EVILLAND: break; default: - { - struct status_data *status = status_get_status_data(src); - int min, max; - - min = max = status_base_matk(status, status_get_lv(src)); - if( status->rhw.matk > 0 ){ - int wMatk, variance; - wMatk = status->rhw.matk; - variance = wMatk * status->rhw.wlv / 10; - min += wMatk - variance; - max += wMatk + variance; - } - - if( sc && sc->data[SC_RECOGNIZEDSPELL] ) - min = max; - - if( sd && sd->right_weapon.overrefine > 0 ){ - min++; - max += sd->right_weapon.overrefine - 1; - } - - if(max > min) - hp += min+rnd()%(max-min); - else - hp += min; - } + hp += status_get_matk(src, 3); } #endif return hp; @@ -557,7 +534,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) case RETURN_TO_ELDICASTES: case ALL_GUARDIAN_RECALL: if(map[m].flag.nowarp) { - clif->skill_teleportmessage(sd,0); + clif->skill_mapinfomessage(sd,0); return 1; } return 0; @@ -565,7 +542,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) case SC_FATALMENACE: case SC_DIMENSIONDOOR: if(map[m].flag.noteleport) { - clif->skill_teleportmessage(sd,0); + clif->skill_mapinfomessage(sd,0); return 1; } return 0; // gonna be checked in 'skill->castend_nodamage_id' @@ -573,7 +550,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) case WE_CALLPARENT: case WE_CALLBABY: if (map[m].flag.nomemo) { - clif->skill_teleportmessage(sd,1); + clif->skill_mapinfomessage(sd,1); return 1; } break; @@ -625,7 +602,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) * These skills cannot be used while in mado gear (credits to Xantara) **/ if( pc_ismadogear(sd) ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR_RIDE,0); return 1; } break; @@ -636,7 +613,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) case WM_LULLABY_DEEPSLEEP: case WM_SATURDAY_NIGHT_FEVER: if( !map_flag_vs(m) ) { - clif->skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails. + clif->skill_mapinfomessage(sd,2); // This skill uses this msg instead of skill fails. return 1; } break; @@ -815,12 +792,12 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint if(sd) { // Automatic trigger of Blitz Beat if (pc_isfalcon(sd) && sd->status.weapon == W_BOW && (temp=pc->checkskill(sd,HT_BLITZBEAT))>0 && - rnd()%1000 <= sstatus->luk*10/3+1 ) { - rate=(sd->status.job_level+9)/10; + rnd()%1000 <= sstatus->luk*3 ) { + rate = sd->status.job_level / 10 + 1; skill->castend_damage_id(src,bl,HT_BLITZBEAT,(tempstatus.weapon == W_BOW || sd->status.weapon == W_FIST) && (temp=pc->checkskill(sd,RA_WUGSTRIKE)) > 0 && rnd()%1000 <= sstatus->luk*10/3+1 ) + if( pc_iswug(sd) && (temp=pc->checkskill(sd,RA_WUGSTRIKE)) > 0 && rnd()%1000 <= sstatus->luk*3 ) skill->castend_damage_id(src,bl,RA_WUGSTRIKE,temp,tick,0); // Gank if(dstmd && sd->status.weapon != W_BOW && @@ -832,26 +809,26 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint clif->skill_fail(sd,RG_SNATCHER,USESKILL_FAIL_LEVEL,0); } // Chance to trigger Taekwon kicks [Dralnu] - if(sc && !sc->data[SC_COMBO]) { - if(sc->data[SC_READYSTORM] && - sc_start(src,SC_COMBO, 15, TK_STORMKICK, + if(sc && !sc->data[SC_COMBOATTACK]) { + if(sc->data[SC_STORMKICK_READY] && + sc_start(src,SC_COMBOATTACK, 15, TK_STORMKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered - else if(sc->data[SC_READYDOWN] && - sc_start(src,SC_COMBO, 15, TK_DOWNKICK, + else if(sc->data[SC_DOWNKICK_READY] && + sc_start(src,SC_COMBOATTACK, 15, TK_DOWNKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered - else if(sc->data[SC_READYTURN] && - sc_start(src,SC_COMBO, 15, TK_TURNKICK, + else if(sc->data[SC_TURNKICK_READY] && + sc_start(src,SC_COMBOATTACK, 15, TK_TURNKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered - else if (sc->data[SC_READYCOUNTER]) { //additional chance from SG_FRIEND [Komurka] + else if (sc->data[SC_COUNTERKICK_READY]) { //additional chance from SG_FRIEND [Komurka] rate = 20; if (sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == TK_COUNTER) { rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100; status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); } - sc_start2(src, SC_COMBO, rate, TK_COUNTER, bl->id, + sc_start2(src, SC_COMBOATTACK, rate, TK_COUNTER, bl->id, (2000 - 4*sstatus->agi - 2*sstatus->dex)); } } @@ -862,7 +839,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint if (sc) { struct status_change_entry *sce; // Enchant Poison gives a chance to poison attacked enemies - if((sce=sc->data[SC_ENCPOISON])) //Don't use sc_start since chance comes in 1/10000 rate. + if((sce=sc->data[SC_ENCHANTPOISON])) //Don't use sc_start since chance comes in 1/10000 rate. status_change_start(bl,SC_POISON,sce->val2, sce->val1,src->id,0,0, skill->get_time2(AS_ENCHANTPOISON,sce->val1),0); // Enchant Deadly Poison gives a chance to deadly poison attacked enemies @@ -871,7 +848,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint skill->get_time2(ASC_EDP,sce->val1)); } } - break; + break; case SM_BASH: if( sd && skill_lv > 5 && pc->checkskill(sd,SM_FATALBLOW)>0 ){ @@ -990,7 +967,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint break; case AM_ACIDTERROR: - sc_start2(bl,SC_BLEEDING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + sc_start2(bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); if (skill->break_equip(bl, EQP_ARMOR, 100*skill->get_time(skill_id,skill_lv), BCT_ENEMY)) clif->emotion(bl,E_OMG); break; @@ -1062,14 +1039,12 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint sc_start(bl,status_skill2sc(skill_id),70,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case NPC_BLEEDING: - sc_start2(bl,SC_BLEEDING,(20*skill_lv),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + sc_start2(bl,SC_BLOODING,(20*skill_lv),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); break; case NPC_MENTALBREAKER: { //Based on observations by Tharis, Mental Breaker should do SP damage - //equal to Matk*skLevel. - rate = sstatus->matk_min; - if (rate < sstatus->matk_max) - rate += rnd()%(sstatus->matk_max - sstatus->matk_min); + //equal to Matk*skLevel. + rate = status_get_matk(src, 2); rate*=skill_lv; status_zap(bl, 0, rate); break; @@ -1108,7 +1083,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint case LK_HEADCRUSH: //Headcrush has chance of causing Bleeding status, except on demon and undead element if (!(battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON)) - sc_start2(bl, SC_BLEEDING,50, skill_lv, src->id, skill->get_time2(skill_id,skill_lv)); + sc_start2(bl, SC_BLOODING,50, skill_lv, src->id, skill->get_time2(skill_id,skill_lv)); break; case LK_JOINTBEAT: @@ -1128,8 +1103,8 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint sc_start(bl,SC_STUN,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,2)); break; default: - sc_start2(bl,SC_BLEEDING,(5+skill_lv*5),skill_lv,src->id,skill->get_time2(skill_id,3)); - } + sc_start2(bl,SC_BLOODING,(5+skill_lv*5),skill_lv,src->id,skill->get_time2(skill_id,3)); + } break; case HW_NAPALMVULCAN: @@ -1151,12 +1126,12 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint case TK_JUMPKICK: if( dstsd && dstsd->class_ != MAPID_SOUL_LINKER && !tsc->data[SC_PRESERVE] ) {// debuff the following statuses - status_change_end(bl, SC_SPIRIT, INVALID_TIMER); + status_change_end(bl, SC_SOULLINK, INVALID_TIMER); status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); status_change_end(bl, SC_KAITE, INVALID_TIMER); status_change_end(bl, SC_KAAHI, INVALID_TIMER); - status_change_end(bl, SC_ONEHAND, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); + status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); } break; case TK_TURNKICK: @@ -1169,7 +1144,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint status_change_start(bl,SC_COMA,10,skill_lv,0,src->id,0,0,0); break; case GS_PIERCINGSHOT: - sc_start2(bl,SC_BLEEDING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + sc_start2(bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); break; case NJ_HYOUSYOURAKU: sc_start(bl,SC_FREEZE,(10+10*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); @@ -1204,34 +1179,37 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint sc_start(bl,SC_FEAR,3+2*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); break; case RK_DRAGONBREATH: - sc_start4(bl,SC_BURNING,5+5*skill_lv,skill_lv,1000,src->id,0,skill->get_time(skill_id,skill_lv)); + sc_start4(bl,SC_BURNING,5+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv)); + break; + case RK_DRAGONBREATH_WATER: + sc_start4(bl,SC_FROSTMISTY,5+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv)); break; case AB_ADORAMUS: - if( tsc && !tsc->data[SC_DECREASEAGI] ) //Prevent duplicate agi-down effect. + if( tsc && !tsc->data[SC_DEC_AGI] ) //Prevent duplicate agi-down effect. sc_start(bl, SC_ADORAMUS, 100, skill_lv, skill->get_time(skill_id, skill_lv)); break; case WL_CRIMSONROCK: sc_start(bl, SC_STUN, 40, skill_lv, skill->get_time(skill_id, skill_lv)); break; case WL_COMET: - sc_start4(bl,SC_BURNING,100,skill_lv,1000,src->id,0,skill->get_time(skill_id,skill_lv)); + sc_start4(bl,SC_BURNING,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv)); break; case WL_EARTHSTRAIN: { - int rate = 0, i; - const int pos[5] = { EQP_WEAPON, EQP_HELM, EQP_SHIELD, EQP_ARMOR, EQP_ACC }; - rate = 6 * skill_lv + sstatus->dex / 10 + (sd? sd->status.job_level / 4 : 0) - tstatus->dex /5;// The tstatus->dex / 5 part is unofficial, but players gotta have some kind of way to have resistance. [Rytech] - //rate -= rate * tstatus->dex / 200; // Disabled until official resistance is found. - - for( i = 0; i < skill_lv; i++ ) - skill->strip_equip(bl,pos[i],rate,skill_lv,skill->get_time2(skill_id,skill_lv)); + // lv 1 & 2 = Strip Helm, lv 3 = Strip Armor, lv 4 = Strip Weapon and lv 5 = Strip Accessory. [malufett] + const int pos[5] = { EQP_HELM, EQP_HELM, EQP_ARMOR, EQP_WEAPON, EQP_ACC }; + skill->strip_equip(bl, pos[skill_lv], 6 * skill_lv + status_get_lv(src) / 4 + status_get_dex(src) / 10, + skill_lv, skill->get_time2(skill_id,skill_lv)); } break; case WL_JACKFROST: sc_start(bl,SC_FREEZE,100,skill_lv,skill->get_time(skill_id,skill_lv)); break; + case WL_FROSTMISTY: + sc_start(bl,SC_FROSTMISTY,25 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + break; case RA_WUGBITE: - sc_start(bl, SC_BITE, (sd ? pc->checkskill(sd,RA_TOOTHOFWUG)*2 : 0), skill_lv, (skill->get_time(skill_id,skill_lv) + (sd ? pc->checkskill(sd,RA_TOOTHOFWUG)*500 : 0)) ); + sc_start(bl, SC_WUGBITE, (sd ? pc->checkskill(sd,RA_TOOTHOFWUG)*2 : 0), skill_lv, (skill->get_time(skill_id,skill_lv) + (sd ? pc->checkskill(sd,RA_TOOTHOFWUG)*500 : 0)) ); break; case RA_SENSITIVEKEEN: if( rnd()%100 < 8 * skill_lv ) @@ -1239,7 +1217,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint break; case RA_FIRINGTRAP: case RA_ICEBOUNDTRAP: - sc_start(bl, (skill_id == RA_FIRINGTRAP) ? SC_BURNING:SC_FREEZING, 40 + 10 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv)); + sc_start4(bl, (skill_id == RA_FIRINGTRAP) ? SC_BURNING:SC_FROSTMISTY, 40 + 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv)); break; case NC_PILEBUNKER: if( rnd()%100 < 5 + 15*skill_lv ) @@ -1252,20 +1230,27 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint } break; case NC_FLAMELAUNCHER: - sc_start4(bl, SC_BURNING, 50 + 10 * skill_lv, skill_lv, 1000, src->id, 0, skill->get_time2(skill_id, skill_lv)); + sc_start4(bl, SC_BURNING, 50 + 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv)); break; case NC_COLDSLOWER: sc_start(bl, SC_FREEZE, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); - sc_start(bl, SC_FREEZING, 20 + 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(bl, SC_FROSTMISTY, 20 + 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); break; case NC_POWERSWING: sc_start(bl, SC_STUN, 5*skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); if( rnd()%100 < 5*skill_lv ) skill->castend_damage_id(src, bl, NC_AXEBOOMERANG, pc->checkskill(sd, NC_AXEBOOMERANG), tick, 1); break; + case NC_MAGMA_ERUPTION: + sc_start4(bl, SC_BURNING, 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time2(skill_id, skill_lv)); + sc_start(bl, SC_STUN, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + break; case GC_WEAPONCRUSH: skill->castend_nodamage_id(src,bl,skill_id,skill_lv,tick,BCT_ENEMY); break; + case GC_DARKCROW: + sc_start(bl, SC_DARKCROW, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + break; case LG_SHIELDPRESS: sc_start(bl, SC_STUN, 30 + 8 * skill_lv, skill_lv, skill->get_time(skill_id,skill_lv)); break; @@ -1273,7 +1258,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint rate = 30 + (((5 * (sd?pc->checkskill(sd,LG_PINPOINTATTACK):skill_lv)) + (sstatus->agi + status_get_lv(src))) / 10); switch( skill_lv ) { case 1: - sc_start2(bl,SC_BLEEDING,rate,skill_lv,src->id,skill->get_time(skill_id,skill_lv)); + sc_start2(bl,SC_BLOODING,rate,skill_lv,src->id,skill->get_time(skill_id,skill_lv)); break; case 2: if( dstsd && dstsd->spiritball && rnd()%100 < rate ) @@ -1335,25 +1320,25 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint status_change_end(bl, SC_APPLEIDUN, INVALID_TIMER); status_change_end(bl, SC_HUMMING, INVALID_TIMER); status_change_end(bl, SC_FORTUNE, INVALID_TIMER); - status_change_end(bl, SC_SERVICE4U, INVALID_TIMER); + status_change_end(bl, SC_SERVICEFORYOU, INVALID_TIMER); status_change_end(bl, SC_LONGING, INVALID_TIMER); - status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); - status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); - status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); - status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); + status_change_end(bl, SC_SWING, INVALID_TIMER); + status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER); + status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER); + status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER); status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - status_change_end(bl, SC_WINKCHARM, INVALID_TIMER); - status_change_end(bl, SC_SONGOFMANA, INVALID_TIMER); - status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); - status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); + status_change_end(bl, SC_DC_WINKCHARM, INVALID_TIMER); + status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER); + status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER); + status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER); status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); - status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); - status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); + status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER); + status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER); } break; case SO_EARTHGRAVE: - sc_start2(bl, SC_BLEEDING, 5 * skill_lv, skill_lv, src->id, skill->get_time2(skill_id, skill_lv)); // Need official rate. [LimitLine] + sc_start2(bl, SC_BLOODING, 5 * skill_lv, skill_lv, src->id, skill->get_time2(skill_id, skill_lv)); // Need official rate. [LimitLine] break; case SO_DIAMONDDUST: rate = 5 + 5 * skill_lv; @@ -1369,14 +1354,14 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint switch( sd->itemid ) { // Starting SCs here instead of do it in skill->additional_effect to simplify the code. case 13261: sc_start(bl, SC_STUN, 100, skill_lv, skill->get_time2(GN_SLINGITEM, skill_lv)); - sc_start2(bl, SC_BLEEDING, 100, skill_lv, src->id, skill->get_time2(GN_SLINGITEM, skill_lv)); + sc_start2(bl, SC_BLOODING, 100, skill_lv, src->id, skill->get_time2(GN_SLINGITEM, skill_lv)); break; case 13262: sc_start(bl, SC_MELON_BOMB, 100, skill_lv, skill->get_time(GN_SLINGITEM, skill_lv)); // Reduces ASPD and moviment speed break; case 13264: sc_start(bl, SC_BANANA_BOMB, 100, skill_lv, skill->get_time(GN_SLINGITEM, skill_lv)); // Reduces LUK ??Needed confirm it, may be it's bugged in kRORE? - sc_start(bl, SC_BANANA_BOMB_SITDOWN, 75, skill_lv, skill->get_time(GN_SLINGITEM_RANGEMELEEATK,skill_lv)); // Sitdown for 3 seconds. + sc_start(bl, SC_BANANA_BOMB_SITDOWN_POSTDELAY, 75, skill_lv, skill->get_time(GN_SLINGITEM_RANGEMELEEATK,skill_lv)); // Sitdown for 3 seconds. break; } sd->itemid = -1; @@ -1384,10 +1369,10 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint break; case GN_HELLS_PLANT_ATK: sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv)); - sc_start2(bl, SC_BLEEDING, 20 + 10 * skill_lv, skill_lv, src->id,skill->get_time2(skill_id, skill_lv)); + sc_start2(bl, SC_BLOODING, 20 + 10 * skill_lv, skill_lv, src->id,skill->get_time2(skill_id, skill_lv)); break; case EL_WIND_SLASH: // Non confirmed rate. - sc_start2(bl, SC_BLEEDING, 25, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); + sc_start2(bl, SC_BLOODING, 25, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); break; case EL_STONE_HAMMER: rate = 10 * skill_lv; @@ -1400,20 +1385,20 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint case EL_TYPOON_MIS: sc_start(bl,SC_SILENCE,10*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); break; - case KO_JYUMONJIKIRI: // needs more info - sc_start(bl,SC_JYUMONJIKIRI,25,skill_lv,skill->get_time(skill_id,skill_lv)); + case KO_JYUMONJIKIRI: + sc_start(bl,SC_KO_JYUMONJIKIRI,90,skill_lv,skill->get_time(skill_id,skill_lv)); break; case KO_MAKIBISHI: - sc_start(bl, SC_STUN, 100, skill_lv, skill->get_time2(skill_id,skill_lv)); + sc_start(bl, SC_STUN, 10 * skill_lv, skill_lv, 1000 * (skill_lv / 2 + 2)); break; case MH_LAVA_SLIDE: - if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skill_lv, skill_lv, 1000, src->id, 0, skill->get_time(skill_id, skill_lv)); + if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skill_lv, skill_lv, 0, src->id, 0, skill->get_time(skill_id, skill_lv)); break; case MH_STAHL_HORN: sc_start(bl, SC_STUN, (20 + 4 * (skill_lv-1)), skill_lv, skill->get_time(skill_id, skill_lv)); break; case MH_NEEDLE_OF_PARALYZE: - sc_start(bl, SC_PARALYSIS, 40 + (5*skill_lv), skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(bl, SC_NEEDLE_OF_PARALYZE, 40 + (5*skill_lv), skill_lv, skill->get_time(skill_id, skill_lv)); break; } @@ -1442,7 +1427,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint rate += 10; if(sc->data[SC_OVERTHRUST]) rate += 10; - if(sc->data[SC_MAXOVERTHRUST]) + if(sc->data[SC_OVERTHRUSTMAX]) rate += 10; } if( rate ) @@ -1492,7 +1477,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ ud->canact_tick = tick+rate; if ( battle_config.display_status_timers ) - clif->status_change(src, SI_ACTIONDELAY, 1, rate, 0, 0, 0); + clif->status_change(src, SI_POSTDELAY, 1, rate, 0, 0, 0); } } } @@ -1589,7 +1574,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ ud->canact_tick = tick+rate; if ( battle_config.display_status_timers && sd ) - clif->status_change(src, SI_ACTIONDELAY, 1, rate, 0, 0, 0); + clif->status_change(src, SI_POSTDELAY, 1, rate, 0, 0, 0); } } } @@ -1828,10 +1813,10 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * if( skill_id == WZ_WATERBALL ) {//(bugreport:5303) struct status_change *sc = NULL; if( ( sc = status_get_sc(src) ) ) { - if(sc->data[SC_SPIRIT] && - sc->data[SC_SPIRIT]->val2 == SL_WIZARD && - sc->data[SC_SPIRIT]->val3 == WZ_WATERBALL) - sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. + if(sc->data[SC_SOULLINK] && + sc->data[SC_SOULLINK]->val2 == SL_WIZARD && + sc->data[SC_SOULLINK]->val3 == WZ_WATERBALL) + sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check. } } } @@ -1925,7 +1910,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ ud->canact_tick = tick+rate; if ( battle_config.display_status_timers && dstsd ) - clif->status_change(bl, SI_ACTIONDELAY, 1, rate, 0, 0, 0); + clif->status_change(bl, SI_POSTDELAY, 1, rate, 0, 0, 0); } } } @@ -1957,8 +1942,8 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * --------------------------------------------------------------------------*/ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, int flag) { const int where_list[4] = {EQP_WEAPON, EQP_ARMOR, EQP_SHIELD, EQP_HELM}; - const enum sc_type scatk[4] = {SC_STRIPWEAPON, SC_STRIPARMOR, SC_STRIPSHIELD, SC_STRIPHELM}; - const enum sc_type scdef[4] = {SC_CP_WEAPON, SC_CP_ARMOR, SC_CP_SHIELD, SC_CP_HELM}; + const enum sc_type scatk[4] = {SC_NOEQUIPWEAPON, SC_NOEQUIPARMOR, SC_NOEQUIPSHIELD, SC_NOEQUIPHELM}; + const enum sc_type scdef[4] = {SC_PROTECTWEAPON, SC_PROTECTARMOR, SC_PROTECTSHIELD, SC_PROTECTHELM}; struct status_change *sc = status_get_sc(bl); int i,j; TBL_PC *sd; @@ -2048,8 +2033,8 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time) { struct status_change *sc; const int pos[5] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM, EQP_ACC}; - const enum sc_type sc_atk[5] = {SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC__STRIPACCESSORY}; - const enum sc_type sc_def[5] = {SC_CP_WEAPON, SC_CP_SHIELD, SC_CP_ARMOR, SC_CP_HELM, 0}; + const enum sc_type sc_atk[5] = {SC_NOEQUIPWEAPON, SC_NOEQUIPSHIELD, SC_NOEQUIPARMOR, SC_NOEQUIPHELM, SC__STRIPACCESSARY}; + const enum sc_type sc_def[5] = {SC_PROTECTWEAPON, SC_PROTECTSHIELD, SC_PROTECTARMOR, SC_PROTECTHELM, 0}; int i; if (rnd()%100 >= rate) @@ -2182,7 +2167,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds struct status_data *sstatus, *tstatus; struct status_change *sc; struct map_session_data *sd, *tsd; - int type,damage,rdamage=0; + int type,damage; int8 rmdamage=0;//magic reflected bool additional_effects = true; @@ -2253,15 +2238,15 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds flag |= 2; //Spirit of Wizard blocks Kaite's reflection - if( type == 2 && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_WIZARD ) + if( type == 2 && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_WIZARD ) { //Consume one Fragment per hit of the casted skill? [Skotlex] type = tsd?pc->search_inventory (tsd, 7321):0; if (type >= 0) { if ( tsd ) pc->delitem(tsd, type, 1, 0, 1, LOG_TYPE_CONSUME); dmg.damage = dmg.damage2 = 0; dmg.dmg_lv = ATK_MISS; - sc->data[SC_SPIRIT]->val3 = skill_id; - sc->data[SC_SPIRIT]->val4 = dsrc->id; + sc->data[SC_SOULLINK]->val3 = skill_id; + sc->data[SC_SOULLINK]->val4 = dsrc->id; } } else if( type != 2 ) /* Kaite bypasses */ additional_effects = false; @@ -2311,19 +2296,15 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if( (skill_id == AL_INCAGI || skill_id == AL_BLESSING || skill_id == CASH_BLESSING || skill_id == CASH_INCAGI || - skill_id == MER_INCAGI || skill_id == MER_BLESSING) && tsd->sc.data[SC_CHANGEUNDEAD] ) + skill_id == MER_INCAGI || skill_id == MER_BLESSING) && tsd->sc.data[SC_PROPERTYUNDEAD] ) damage = 1; - if( damage > 0 && (( dmg.flag&BF_WEAPON && src != bl && ( src == dsrc || ( dsrc->type == BL_SKILL && ( skill_id == SG_SUN_WARM || skill_id == SG_MOON_WARM || skill_id == SG_STAR_WARM ) ) )) - || (sc && sc->data[SC_REFLECTDAMAGE])) ) - rdamage = battle->calc_return_damage(bl,src, &damage, dmg.flag, skill_id); - if( damage && sc && sc->data[SC_GENSOU] && dmg.flag&BF_MAGIC ){ struct block_list *nbl; nbl = battle->get_enemy_area(bl,bl->x,bl->y,2,BL_CHAR,bl->id); if( nbl ){ // Only one target is chosen. - damage = damage / 2; // Deflect half of the damage to a target nearby - clif->skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,damage,0), dmg.div_, OB_OBOROGENSOU_TRANSITION_ATK, -1, 6); + int temp = (int)(damage / (float)(10 / skill_lv)); + clif->skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,temp,0), 1, OB_OBOROGENSOU_TRANSITION_ATK, -1, 6); } } @@ -2348,7 +2329,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if(sd) { int flag = 0; //Used to signal if this skill can be combo'ed later on. struct status_change_entry *sce; - if ((sce = sd->sc.data[SC_COMBO])) {//End combo state after skill is invoked. [Skotlex] + if ((sce = sd->sc.data[SC_COMBOATTACK])) {//End combo state after skill is invoked. [Skotlex] switch (skill_id) { case TK_TURNKICK: case TK_STORMKICK: @@ -2359,14 +2340,14 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds sce->val3 = skill_id; if( sce->timer != INVALID_TIMER ) iTimer->delete_timer(sce->timer, status_change_timer); - sce->timer = iTimer->add_timer(tick+sce->val4, status_change_timer, src->id, SC_COMBO); + sce->timer = iTimer->add_timer(tick+sce->val4, status_change_timer, src->id, SC_COMBOATTACK); break; } unit_cancel_combo(src); // Cancel combo wait break; default: if( src == dsrc ) // Ground skills are exceptions. [Inkfish] - status_change_end(src, SC_COMBO, INVALID_TIMER); + status_change_end(src, SC_COMBOATTACK, INVALID_TIMER); } } switch(skill_id) { @@ -2394,7 +2375,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if( (tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT) && pc->checkskill(sd, HT_POWER)) { //TODO: This code was taken from Triple Blows, is this even how it should be? [Skotlex] - sc_start2(src,SC_COMBO,100,HT_POWER,bl->id,2000); + sc_start2(src,SC_COMBOATTACK,100,HT_POWER,bl->id,2000); clif->combo_delay(src,2000); } break; @@ -2407,8 +2388,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds break; case SL_STIN: case SL_STUN: - if (skill_lv >= 7 && !sd->sc.data[SC_SMA]) - sc_start(src,SC_SMA,100,skill_lv,skill->get_time(SL_SMA, skill_lv)); + if (skill_lv >= 7 && !sd->sc.data[SC_SMA_READY]) + sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA, skill_lv)); break; case GS_FULLBUSTER: //Can't attack nor use items until skill's delay expires. [Skotlex] @@ -2425,7 +2406,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds } //Switch End if (flag) { //Possible to chain if ( (flag = DIFF_TICK(sd->ud.canact_tick, tick)) < 50 ) flag = 50;/* less is a waste. */ - sc_start2(src,SC_COMBO,100,skill_id,bl->id,flag); + sc_start2(src,SC_COMBOATTACK,100,skill_id,bl->id,flag); clif->combo_delay(src, flag); } } @@ -2459,9 +2440,11 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds case SR_EARTHSHAKER: dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,-2,6); break; + case KO_MUCHANAGE: + if( dmg.dmg_lv == ATK_FLEE ) + break; case WL_SOULEXPANSION: case WL_COMET: - case KO_MUCHANAGE: case NJ_HUUMA: dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,8); break; @@ -2488,6 +2471,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds case EL_HURRICANE_ATK: case KO_BAKURETSU: case GN_CRAZYWEED_ATK: + case NC_MAGMA_ERUPTION: dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5); break; case GN_SLINGITEM_RANGEMELEEATK: @@ -2503,6 +2487,12 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds case WM_REVERBERATION_MAGIC: dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,6); break; + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_, WL_TETRAVORTEX,-1,5); + break; case HT_CLAYMORETRAP: case HT_BLASTMINE: case HT_FLASHER: @@ -2518,7 +2508,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds break; case WZ_SIGHTBLASTER: dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, 5); - break; + break; case AB_DUPLELIGHT_MELEE: case AB_DUPLELIGHT_MAGIC: dmg.amotion = 300;/* makes the damage value not overlap with previous damage (when displayed by the client) */ @@ -2643,8 +2633,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds skill->counter_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,tick); } // Hell Inferno burning status only starts if Fire part hits. - if( skill_id == WL_HELLINFERNO && dmg.damage > 0 ) - sc_start4(bl,SC_BURNING,55+5*skill_lv,skill_lv,1000,src->id,0,skill->get_time(skill_id,skill_lv)); + if( skill_id == WL_HELLINFERNO && dmg.damage > 0 && !(flag&ELE_DARK) ) + sc_start4(bl,SC_BURNING,55+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv)); // Apply knock back chance in SC_TRIANGLESHOT skill. else if( skill_id == SC_TRIANGLESHOT && rnd()%100 > (1 + skill_lv) ) dmg.blewcount = 0; @@ -2753,7 +2743,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds dmg.flag |= BF_WEAPON; if( sd && src != bl && damage > 0 && ( dmg.flag&BF_WEAPON || - (dmg.flag&BF_MISC && (skill_id == RA_CLUSTERBOMB || skill_id == RA_FIRINGTRAP || skill_id == RA_ICEBOUNDTRAP || skill_id == RK_DRAGONBREATH)) ) ) + (dmg.flag&BF_MISC && (skill_id == RA_CLUSTERBOMB || skill_id == RA_FIRINGTRAP || skill_id == RA_ICEBOUNDTRAP || skill_id == RK_DRAGONBREATH || skill_id == RK_DRAGONBREATH_WATER)) ) ) { if (battle_config.left_cardfix_to_right) battle->drain(sd, bl, dmg.damage, dmg.damage, tstatus->race, tstatus->mode&MD_BOSS); @@ -2761,30 +2751,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds battle->drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->mode&MD_BOSS); } - if( rdamage > 0 ) { - if( sc && sc->data[SC_REFLECTDAMAGE] ) { - if( src != bl ) {// Don't reflect your own damage (Grand Cross) - bool change = false; - if( sd && !sd->state.autocast ) - change = true; - if( change ) - sd->state.autocast = 1; - iMap->foreachinshootrange(battle->damage_area,bl,skill->get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,bl,dmg.amotion,sstatus->dmotion,rdamage,tstatus->race); - if( change ) - sd->state.autocast = 0; - } - } else { - if( dmg.amotion ) - battle->delay_damage(tick, dmg.amotion,bl,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,0,additional_effects); - else - status_fix_damage(bl,src,rdamage,0); - clif->damage(src,src,tick, dmg.amotion,0,rdamage,1,4,0); // in aegis damage reflected is shown in single hit. - //Use Reflect Shield to signal this kind of skill trigger. [Skotlex] - if( tsd && src != bl ) - battle->drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); - skill->additional_effect(bl, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); - } - } + if( damage > 0 ) { /** * Post-damage effects @@ -2818,8 +2785,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds skill_id == MG_COLDBOLT || skill_id == MG_FIREBOLT || skill_id == MG_LIGHTNINGBOLT ) && (sc = status_get_sc(src)) && - sc->data[SC_DOUBLECAST] && - rnd() % 100 < sc->data[SC_DOUBLECAST]->val2) + sc->data[SC_DOUBLECASTING] && + rnd() % 100 < sc->data[SC_DOUBLECASTING]->val2) { // skill->addtimerskill(src, tick + dmg.div_*dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2); skill->addtimerskill(src, tick + dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2); @@ -3101,7 +3068,7 @@ int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, index[i] = pc->search_inventory(sd, itemid[i]); if( index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i] ) { - clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + clif->skill_fail(sd, skill_id, USESKILL_FAIL_NEED_ITEM, amount[i]|(itemid[i] << 16)); return 0; } } @@ -3193,10 +3160,10 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { } else { struct status_change *sc = status_get_sc(src); if(sc) { - if(sc->data[SC_SPIRIT] && - sc->data[SC_SPIRIT]->val2 == SL_WIZARD && - sc->data[SC_SPIRIT]->val3 == skl->skill_id) - sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. + if(sc->data[SC_SOULLINK] && + sc->data[SC_SOULLINK]->val2 == SL_WIZARD && + sc->data[SC_SOULLINK]->val3 == skl->skill_id) + sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check. } } break; @@ -3205,48 +3172,33 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { **/ case WL_CHAINLIGHTNING_ATK: { struct block_list *nbl = NULL; // Next Target of Chain - skill->attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); // Hit a Lightning on the current Target + skill->attack(BF_MAGIC, src, src, target, skl->skill_id, skl->skill_lv, tick, (9-skl->type)); // Hit a Lightning on the current Target skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify - if( skl->type > 1 ) { // Remaining Chains Hit - nbl = battle->get_enemy_area(src,target->x,target->y,2,BL_CHAR|BL_SKILL,target->id); // Search for a new Target around current one... - if( nbl == NULL && skl->x > 1 ) { - nbl = target; - skl->x--; - } else - skl->x = 3; + + if( skl->type < (4 + skl->skill_lv - 1) && skl->x < 3 ) + { // Remaining Chains Hit + nbl = battle->get_enemy_area(src, target->x, target->y, (skl->type>2)?2:3, // After 2 bounces, it will bounce to other targets in 7x7 range. + BL_CHAR|BL_SKILL, target->id); // Search for a new Target around current one... + if( nbl == NULL) + skl->x++; + else + skl->x = 0; + + skill->addtimerskill(src, tick + 651, (nbl?nbl:target)->id, skl->x, 0, WL_CHAINLIGHTNING_ATK, skl->skill_lv, skl->type + 1, skl->flag); } - - if( nbl ) - skill->addtimerskill(src,tick+status_get_adelay(src),nbl->id,skl->x,0,WL_CHAINLIGHTNING_ATK,skl->skill_lv,skl->type-1,skl->flag); } break; case WL_TETRAVORTEX_FIRE: case WL_TETRAVORTEX_WATER: case WL_TETRAVORTEX_WIND: case WL_TETRAVORTEX_GROUND: - skill->attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag|SD_ANIMATION); + clif->skill_nodamage(src, target, skl->skill_id, skl->skill_lv, 1); + skill_attack(BF_MAGIC, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag); skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify - if( skl->type >= 3 ) { // Final Hit - if( !status_isdead(target) ) { // Final Status Effect - int effects[4] = { SC_BURNING, SC_FREEZING, SC_BLEEDING, SC_STUN }, - applyeffects[4] = { 0, 0, 0, 0 }, - i, j = 0, k = 0; - for( i = 1; i <= 8; i = i + i ) { - if( skl->x&i ) - { - applyeffects[j] = effects[k]; - j++; - } - k++; - } - if( j ) { - i = applyeffects[rnd()%j]; - status_change_start(target, i, 10000, skl->skill_lv, - (i == SC_BURNING ? 1000 : (i == SC_BLEEDING ? src->id : 0)), - (i == SC_BURNING ? src->id : 0), - 0, skill->get_time(WL_TETRAVORTEX,skl->skill_lv), 0); - } - } + if( skl->type == 4 ){ + const enum sc_type scs[] = { SC_BURNING, SC_BLOODING, SC_FROSTMISTY, SC_STUN }; // status inflicts are depend on what summoned element is used. + int rate = skl->y, index = skl->x-1; + sc_start2(target, scs[index], rate, skl->skill_lv, src->id, skill->get_time(WL_TETRAVORTEX,index)); } break; case WM_REVERBERATION_MELEE: @@ -3282,6 +3234,19 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { iMap->foreachinrange(skill->area_sub, target, skill->get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, src, skl->skill_id, skl->skill_lv, 0, skl->flag|1|BCT_ENEMY, skill->castend_damage_id); break; + case SR_FLASHCOMBO_ATK_STEP1: + case SR_FLASHCOMBO_ATK_STEP2: + case SR_FLASHCOMBO_ATK_STEP3: + case SR_FLASHCOMBO_ATK_STEP4: + if( src->type == BL_PC ) { + struct map_session_data *sd = NULL; + const enum e_skill combos[] = {SR_DRAGONCOMBO, SR_FALLENEMPIRE, SR_TIGERCANNON, SR_SKYNETBLOW}; + if( (sd = ((TBL_PC*)src)) ){ + uint16 cid = combos[skl->skill_id-SR_FLASHCOMBO_ATK_STEP1]; + skill->castend_damage_id(src, target, cid, pc->checkskill(sd, cid), tick, 0); + } + } + break; case CH_PALMSTRIKE: { struct status_change* tsc = status_get_sc(target); @@ -3525,7 +3490,9 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case GS_FULLBUSTER: case NJ_SYURIKEN: case NJ_KUNAI: +#ifndef RENEWAL case ASC_BREAKER: +#endif case HFLI_MOON: //[orn] case HFLI_SBR44: //[orn] case NPC_BLEEDING: @@ -3533,6 +3500,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case NPC_HELLPOWER: case RK_SONICWAVE: case RK_HUNDREDSPEAR: + case RK_STORMBLAST: + case RK_CRUSHSTRIKE: case AB_DUPLELIGHT_MELEE: case RA_AIMEDBOLT: case NC_AXEBOOMERANG: @@ -3555,7 +3524,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case GN_SLINGITEM_RANGEMELEEATK: case KO_JYUMONJIKIRI: case KO_SETSUDAN: - case KO_KAIHOU: + case GC_DARKCROW: skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); break; @@ -3588,7 +3557,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint break; case MO_COMBOFINISH: - if (!(flag&1) && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) + if (!(flag&1) && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_MONK) { //Becomes a splash attack when Soul Linked. iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv),splash_target(src), @@ -3687,9 +3656,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint break; case NJ_ISSEN: - status_change_end(src, SC_NEN, INVALID_TIMER); - status_change_end(src, SC_HIDING, INVALID_TIMER); - // fall through case MO_EXTREMITYFIST: { short x, y, i = 2; // Move 2 cells for Issen(from target) @@ -3708,7 +3674,9 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint #ifdef RENEWAL sc_start(src,SC_EXTREMITYFIST2,100,skill_lv,skill->get_time(skill_id,skill_lv)); #endif - }else + }else{ + status_change_end(src, SC_NJ_NEN, INVALID_TIMER); + status_change_end(src, SC_HIDING, INVALID_TIMER); status_set_hp(src, #ifdef RENEWAL max(status_get_max_hp(src)/100, 1) @@ -3716,7 +3684,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint 1 #endif , 0); - + } dir = iMap->calc_dir(src,bl->x,bl->y); if( dir > 0 && dir < 4) x = -i; else if( dir > 4 ) x = i; @@ -3945,6 +3913,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case AB_DUPLELIGHT_MAGIC: case WM_METALICSOUND: case MH_ERASER_CUTTER: + case KO_KAIHOU: skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); break; @@ -4011,7 +3980,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint break; case SL_SMA: - status_change_end(src, SC_SMA, INVALID_TIMER); + status_change_end(src, SC_SMA_READY, INVALID_TIMER); case SL_STIN: case SL_STUN: if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { @@ -4033,11 +4002,15 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case NJ_ZENYNAGE: case GN_THORNS_TRAP: case GN_HELLS_PLANT_ATK: +#ifdef RENEWAL + case ASC_BREAKER: +#endif skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); break; /** * Rune Knight **/ + case RK_DRAGONBREATH_WATER: case RK_DRAGONBREATH: { struct status_change *tsc = NULL; if( (tsc = status_get_sc(bl)) && (tsc->data[SC_HIDING] )) { @@ -4112,16 +4085,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); break; - case RK_STORMBLAST: - case RK_CRUSHSTRIKE: - if( sd ) { - if( pc->checkskill(sd,RK_RUNEMASTERY) >= ( skill_id == RK_CRUSHSTRIKE ? 7 : 3 ) ) - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - else - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } else //non-sd support - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - break; case GC_DARKILLUSION: { short x, y; @@ -4145,9 +4108,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint } break; - case GC_WEAPONCRUSH: - if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == GC_WEAPONBLOCKING ) + if( sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == GC_WEAPONBLOCKING ) skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); else if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_WEAPONBLOCKING,0); @@ -4173,7 +4135,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint break; case WL_CHAINLIGHTNING: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - skill->addtimerskill(src,tick + 150,bl->id,3,0,WL_CHAINLIGHTNING_ATK,skill_lv,4+skill_lv,flag); + skill->addtimerskill(src,tick+status_get_amotion(src),bl->id,0,0,WL_CHAINLIGHTNING_ATK,skill_lv,0,flag); break; case WL_DRAINLIFE: { @@ -4182,7 +4144,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint heal = heal * (5 + 5 * skill_lv) / 100; - if( bl->type == BL_SKILL ) + if( bl->type == BL_SKILL || status_get_hp(src) == status_get_max_hp(src)) // Don't absorb when caster was in full HP heal = 0; // Don't absorb heal from Ice Walls or other skill units. if( heal && rnd()%100 < rate ) @@ -4194,61 +4156,43 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint break; case WL_TETRAVORTEX: - if( sd ) { - int spheres[5] = { 0, 0, 0, 0, 0 }, - positions[5] = {-1,-1,-1,-1,-1 }, - i, j = 0, k, subskill = 0; - - for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) - if( sc && sc->data[i] ) - { - spheres[j] = i; - positions[j] = sc->data[i]->val2; - j++; // - } - - if( j < 4 ) - { // Need 4 spheres minimum - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - - // Sphere Sort, this time from new to old - for( i = 0; i <= j - 2; i++ ) - for( k = i + 1; k <= j - 1; k++ ) - if( positions[i] < positions[k] ) - { - swap(positions[i],positions[k]); - swap(spheres[i],spheres[k]); + if( sc ){ + int i = SC_SUMMON5, x = 0; + int types[][2] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}}; + for(; i >= SC_SUMMON1; i--){ + if( sc->data[i] ){ + int skillid = WL_TETRAVORTEX_FIRE + (sc->data[i]->val1 - WLS_FIRE) + (sc->data[i]->val1 == WLS_WIND) - (sc->data[i]->val1 == WLS_WATER), sc_index = 0, rate = 0; + if( x < 4 ){ + types[x][0] = (sc->data[i]->val1 - WLS_FIRE) + 1; + types[x][1] = 25; // 25% each for equal sharing + if( x == 3 ){ + x = 0; + sc_index = types[rand()%4][0]; + for(; x < 4; x++) + if(types[x][0] == sc_index) + rate += types[x][1]; + } + skill->addtimerskill(src, tick + (SC_SUMMON5-i) * 206, bl->id, sc_index, rate, skillid, skill_lv, x, flag); } - - k = 0; - for( i = 0; i < 4; i++ ) - { - switch( sc->data[spheres[i]]->val1 ) - { - case WLS_FIRE: subskill = WL_TETRAVORTEX_FIRE; k |= 1; break; - case WLS_WIND: subskill = WL_TETRAVORTEX_WIND; k |= 4; break; - case WLS_WATER: subskill = WL_TETRAVORTEX_WATER; k |= 2; break; - case WLS_STONE: subskill = WL_TETRAVORTEX_GROUND; k |= 8; break; + status_change_end(src, (sc_type)i, INVALID_TIMER); + x++; } - skill->addtimerskill(src, tick + i * 200, bl->id, k, 0, subskill, skill_lv, i, flag); - clif->skill_nodamage(src, bl, subskill, skill_lv, 1); - status_change_end(src, spheres[i], INVALID_TIMER); } } break; case WL_RELEASE: if( sd ) { - int i; + int i, cooldown; + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + skill->toggle_magicpower(src, skill_id); // Priority is to release SpellBook if( sc && sc->data[SC_READING_SB] ) { // SpellBook uint16 skill_id, skill_lv, point, s = 0; - int spell[SC_MAXSPELLBOOK-SC_SPELLBOOK1 + 1]; + int spell[SC_SPELLBOOK7-SC_SPELLBOOK1 + 1]; - for(i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) // List all available spell to be released - if( sc->data[i] ) spell[s++] = i; + for(i = SC_SPELLBOOK7; i >= SC_SPELLBOOK1; i--) // List all available spell to be released + if( sc->data[i] ) spell[s++] = i; if ( s == 0 ) break; @@ -4261,13 +4205,12 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint status_change_end(src, (sc_type)i, INVALID_TIMER); }else //something went wrong :( break; - + if( sc->data[SC_READING_SB]->val2 > point ) sc->data[SC_READING_SB]->val2 -= point; else // Last spell to be released status_change_end(src, SC_READING_SB, INVALID_TIMER); - if( bl->type != BL_SKILL ) /* skill types will crash the client */ - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + if( !skill->check_condition_castbegin(sd, skill_id, skill_lv) ) break; @@ -4284,47 +4227,32 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint } sd->ud.canact_tick = tick + skill->delay_fix(src, skill_id, skill_lv); - clif->status_change(src, SI_ACTIONDELAY, 1, skill->delay_fix(src, skill_id, skill_lv), 0, 0, 0); - } else { // Summon Balls - int j = 0, k, skele; - int spheres[5] = { 0, 0, 0, 0, 0 }, - positions[5] = {-1,-1,-1,-1,-1 }; - - for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) - if( sc && sc->data[i] ) { - spheres[j] = i; - positions[j] = sc->data[i]->val2; - sc->data[i]->val2--; // Prepares for next position - j++; - } + clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, skill_id, skill_lv), 0, 0, 0); - if( j == 0 ) { // No Spheres - clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON_NONE,0); - break; + cooldown = skill_get_cooldown(skill_id, skill_lv); + for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { + if (sd->skillcooldown[i].id == skill_id){ + cooldown += sd->skillcooldown[i].val; + break; + } } - - // Sphere Sort - for( i = 0; i <= j - 2; i++ ) - for( k = i + 1; k <= j - 1; k++ ) - if( positions[i] > positions[k] ) { - swap(positions[i],positions[k]); - swap(spheres[i],spheres[k]); - } - - if( skill_lv == 1 ) j = 1; // Limit only to one ball - for( i = 0; i < j; i++ ) { - skele = WL_RELEASE - 5 + sc->data[spheres[i]]->val1 - WLS_FIRE; // Convert Ball Element into Skill ATK for balls - // WL_SUMMON_ATK_FIRE, WL_SUMMON_ATK_WIND, WL_SUMMON_ATK_WATER, WL_SUMMON_ATK_GROUND - skill->addtimerskill(src,tick+status_get_adelay(src)*i,bl->id,0,0,skele,sc->data[spheres[i]]->val3,BF_MAGIC,flag|SD_LEVEL); - status_change_end(src, spheres[i], INVALID_TIMER); // Eliminate ball + if(cooldown) + skill->blockpc_start(sd, skill_id, cooldown, false); + }else if( sc ){ // Summon Balls + int i = SC_SUMMON5; + for(; i >= SC_SUMMON1; i--){ + if( sc->data[i] ){ + int skillid = WL_SUMMON_ATK_FIRE + (sc->data[i]->val1 - WLS_FIRE); + skill->addtimerskill(src, tick + status_get_adelay(src) * (SC_SUMMON5 - i), bl->id, 0, 0, skillid, skill_lv, BF_MAGIC, flag); + status_change_end(src, (sc_type)i, INVALID_TIMER); + if(skill_lv == 1) + break; + } } - clif->skill_nodamage(src,bl,skill_id,0,1); } } break; case WL_FROSTMISTY: - // Causes Freezing status through walls. - sc_start(bl,status_skill2sc(skill_id),20+12*skill_lv+(sd ? sd->status.job_level : 50)/5,skill_lv,skill->get_time(skill_id,skill_lv)); // Doesn't deal damage through non-shootable walls. if( path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKWALL) ) skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); @@ -4453,19 +4381,19 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint break; case SR_HOWLINGOFLION: - status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); - status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); - status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); - status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); + status_change_end(bl, SC_SWING, INVALID_TIMER); + status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER); + status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER); + status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER); status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); - status_change_end(bl, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); - status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); - status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); + status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER); + status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER); + status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER); status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); - status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); - status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); + status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER); + status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER); skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION); break; @@ -4573,7 +4501,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint } break; - //recursive homon skill case MH_MAGMA_FLOW: case MH_XENO_SLASHER: @@ -4589,8 +4516,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint case MH_NEEDLE_OF_PARALYZE: skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); break; - case MH_TINDER_BREAKER: - if (unit_movepos(src, bl->x, bl->y, 1, 1)) { + case MH_TINDER_BREAKER: + if (unit_movepos(src, bl->x, bl->y, 1, 1)) { #if PACKETVER >= 20111005 clif->snap(src, bl->x, bl->y); #else @@ -4598,7 +4525,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint #endif } clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,SC_CLOSECONFINE2,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv))); + sc_start4(bl,SC_RG_CCONFINE_S,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv))); skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); break; @@ -4651,4760 +4578,4697 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint /*========================================== * *------------------------------------------*/ -int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) +int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd, *dstsd; - struct mob_data *md, *dstmd; - struct homun_data *hd; - struct mercenary_data *mer; - struct status_data *sstatus, *tstatus; - struct status_change *tsc; - struct status_change_entry *tsce; - - int i = 0; - enum sc_type type; - - if(skill_id > 0 && !skill_lv) return 0; // celest + struct block_list *target, *src; + struct map_session_data *sd; + struct mob_data *md; + struct unit_data *ud; + struct status_change *sc = NULL; + int inf,inf2,flag = 0; - nullpo_retr(1, src); - nullpo_retr(1, bl); + src = iMap->id2bl(id); + if( src == NULL ) + { + ShowDebug("skill_castend_id: src == NULL (tid=%d, id=%d)\n", tid, id); + return 0;// not found + } - if (src->m != bl->m) - return 1; + ud = unit_bl2ud(src); + if( ud == NULL ) + { + ShowDebug("skill_castend_id: ud == NULL (tid=%d, id=%d)\n", tid, id); + return 0;// ??? + } - sd = BL_CAST(BL_PC, src); - hd = BL_CAST(BL_HOM, src); + sd = BL_CAST(BL_PC, src); md = BL_CAST(BL_MOB, src); - mer = BL_CAST(BL_MER, src); - - dstsd = BL_CAST(BL_PC, bl); - dstmd = BL_CAST(BL_MOB, bl); - if(bl->prev == NULL) - return 1; - if(status_isdead(src)) - return 1; + if( src->prev == NULL ) { + ud->skilltimer = INVALID_TIMER; + return 0; + } - if( src != bl && status_isdead(bl) ) { - /** - * Skills that may be cast on dead targets - **/ - switch( skill_id ) { - case NPC_WIDESOULDRAIN: - case PR_REDEMPTIO: - case ALL_RESURRECTION: - case WM_DEADHILLHERE: - break; - default: - return 1; + if(ud->skill_id != SA_CASTCANCEL && ud->skill_id != SO_SPELLFIST) {// otherwise handled in unit_skillcastcancel() + if( ud->skilltimer != tid ) { + ShowError("skill_castend_id: Timer mismatch %d!=%d!\n", ud->skilltimer, tid); + ud->skilltimer = INVALID_TIMER; + return 0; } - } - tstatus = status_get_status_data(bl); - sstatus = status_get_status_data(src); + if( sd && ud->skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK) ) + {// restore original walk speed + ud->skilltimer = INVALID_TIMER; + status_calc_bl(&sd->bl, SCB_SPEED); + } - //Check for undead skills that convert a no-damage skill into a damage one. [Skotlex] - switch (skill_id) { - case HLIF_HEAL: //[orn] - if (bl->type != BL_HOM) { - if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0) ; - break ; - } - case AL_HEAL: - case ALL_RESURRECTION: - case PR_ASPERSIO: - /** - * Arch Bishop - **/ - case AB_RENOVATIO: - case AB_HIGHNESSHEAL: - //Apparently only player casted skills can be offensive like this. - if (sd && battle->check_undead(tstatus->race,tstatus->def_ele)) { - if (battle->check_target(src, bl, BCT_ENEMY) < 1) { - //Offensive heal does not works on non-enemies. [Skotlex] - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - return skill->castend_damage_id (src, bl, skill_id, skill_lv, tick, flag); - } - break; - case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex] - return skill->castend_damage_id (src, bl, skill_id, skill_lv, tick, flag); - case MH_STEINWAND: { - struct block_list *s_src = battle->get_master(src); - short ret = 0; - if(!skill->check_unit_range(src, src->x, src->y, skill_id, skill_lv)) //prevent reiteration - ret = skill->castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag); //cast on homon - if(s_src && !skill->check_unit_range(s_src, s_src->x, s_src->y, skill_id, skill_lv)) - ret |= skill->castend_pos2(s_src,s_src->x,s_src->y,skill_id,skill_lv,tick,flag); //cast on master - if (hd) - skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); - return ret; - } - break; - default: - //Skill is actually ground placed. - if (src == bl && skill->get_unit_id(skill_id,0)) - return skill->castend_pos2(src,bl->x,bl->y,skill_id,skill_lv,tick,0); + ud->skilltimer = INVALID_TIMER; } - type = status_skill2sc(skill_id); - tsc = status_get_sc(bl); - tsce = (tsc && type != -1)?tsc->data[type]:NULL; + if (ud->skilltarget == id) + target = src; + else + target = iMap->id2bl(ud->skilltarget); - if (src!=bl && type > -1 && - (i = skill->get_ele(skill_id, skill_lv)) > ELE_NEUTRAL && - skill->get_inf(skill_id) != INF_SUPPORT_SKILL && - battle->attr_fix(NULL, NULL, 100, i, tstatus->def_ele, tstatus->ele_lv) <= 0) - return 1; //Skills that cause an status should be blocked if the target element blocks its element. + // Use a do so that you can break out of it when the skill fails. + do { + if(!target || target->prev==NULL) break; - iMap->freeblock_lock(); - switch(skill_id) { - case HLIF_HEAL: //[orn] - case AL_HEAL: - /** - * Arch Bishop - **/ - case AB_HIGHNESSHEAL: - { - int heal = skill->calc_heal(src, bl, (skill_id == AB_HIGHNESSHEAL)?AL_HEAL:skill_id, (skill_id == AB_HIGHNESSHEAL)?10:skill_lv, true); - int heal_get_jobexp; - //Highness Heal: starts at 1.5 boost + 0.5 for each level - if( skill_id == AB_HIGHNESSHEAL ) { - heal = heal * ( 15 + 5 * skill_lv ) / 10; - } - if( status_isimmune(bl) || - (dstmd && (dstmd->class_ == MOBID_EMPERIUM || mob_is_battleground(dstmd))) || - (dstsd && pc_ismadogear(dstsd)) )//Mado is immune to heal - heal=0; + if(src->m != target->m || status_isdead(src)) break; - if( sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0 ) - heal = heal*2; - - if( tsc && tsc->count ) - { - if( tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS) ) - { //Bounce back heal - if (--tsc->data[SC_KAITE]->val2 <= 0) - status_change_end(bl, SC_KAITE, INVALID_TIMER); - if (src == bl) - heal=0; //When you try to heal yourself under Kaite, the heal is voided. - else { - bl = src; - dstsd = sd; - } - } - else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAYNIGHTFEVER] || tsc->data[SC__BLOODYLUST]) - heal = 0; //Needed so that it actually displays 0 when healing. + switch (ud->skill_id) { + //These should become skill_castend_pos + case WE_CALLPARTNER: + if(sd) clif->callpartner(sd); + case WE_CALLPARENT: + case WE_CALLBABY: + case AM_RESURRECTHOMUN: + case PF_SPIDERWEB: + //Find a random spot to place the skill. [Skotlex] + inf2 = skill->get_splash(ud->skill_id, ud->skill_lv); + ud->skillx = target->x + inf2; + ud->skilly = target->y + inf2; + if (inf2 && !iMap->random_dir(target, &ud->skillx, &ud->skilly)) { + ud->skillx = target->x; + ud->skilly = target->y; } - clif->skill_nodamage (src, bl, skill_id, heal, 1); - if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL ) - heal = ~heal + 1; - heal_get_jobexp = status_heal(bl,heal,0,0); + ud->skilltimer=tid; + return skill->castend_pos(tid,tick,id,data); + case GN_WALLOFTHORN: + ud->skillx = target->x; + ud->skilly = target->y; + ud->skilltimer = tid; + return skill->castend_pos(tid,tick,id,data); + } - if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){ - heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100; - if (heal_get_jobexp <= 0) - heal_get_jobexp = 1; - pc->gainexp (sd, bl, 0, heal_get_jobexp, false); - } + if(ud->skill_id == RG_BACKSTAP) { + uint8 dir = iMap->calc_dir(src,target->x,target->y),t_dir = unit_getdir(target); + if(check_distance_bl(src, target, 0) || iMap->check_dir(dir,t_dir)) { + break; } - break; + } - case PR_REDEMPTIO: - if (sd && !(flag&1)) { - if (sd->status.party_id == 0) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - skill_area_temp[0] = 0; - party_foreachsamemap(skill->area_sub, - sd,skill->get_splash(skill_id, skill_lv), - src,skill_id,skill_lv,tick, flag|BCT_PARTY|1, - skill->castend_nodamage_id); - if (skill_area_temp[0] == 0) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty... - if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty) { //Apply penalty - sd->status.base_exp -= min(sd->status.base_exp, pc->nextbaseexp(sd) * skill_area_temp[0] * 2/1000); //0.2% penalty per each. - sd->status.job_exp -= min(sd->status.job_exp, pc->nextjobexp(sd) * skill_area_temp[0] * 2/1000); - clif->updatestatus(sd,SP_BASEEXP); - clif->updatestatus(sd,SP_JOBEXP); - } - status_set_hp(src, 1, 0); - status_set_sp(src, 0, 0); + if( ud->skill_id == PR_TURNUNDEAD ) { + struct status_data *tstatus = status_get_status_data(target); + if( !battle->check_undead(tstatus->race, tstatus->def_ele) ) break; - } else if (status_isdead(bl) && flag&1) { //Revive - skill_area_temp[0]++; //Count it in, then fall-through to the Resurrection code. - skill_lv = 3; //Resurrection level 3 is used - } else //Invalid target, skip resurrection. + } + + if( ud->skill_id == RA_WUGSTRIKE ){ + if( !path_search(NULL,src->m,src->x,src->y,target->x,target->y,1,CELL_CHKNOREACH)) break; + } - case ALL_RESURRECTION: - if(sd && (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)) - { //No reviving in WoE grounds! - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if( ud->skill_id == PR_LEXDIVINA || ud->skill_id == MER_LEXDIVINA ) + { + sc = status_get_sc(target); + if( battle->check_target(src,target, BCT_ENEMY) <= 0 && (!sc || !sc->data[SC_SILENCE]) ) + { //If it's not an enemy, and not silenced, you can't use the skill on them. [Skotlex] + clif->skill_nodamage (src, target, ud->skill_id, ud->skill_lv, 0); break; } - if (!status_isdead(bl)) - break; + } + else + { // Check target validity. + inf = skill->get_inf(ud->skill_id); + inf2 = skill->get_inf2(ud->skill_id); + + if(inf&INF_ATTACK_SKILL || + (inf&INF_SELF_SKILL && inf2&INF2_NO_TARGET_SELF) //Combo skills + ) // Casted through combo. + inf = BCT_ENEMY; //Offensive skill. + else if(inf2&INF2_NO_ENEMY) + inf = BCT_NOENEMY; + else + inf = 0; + + if(inf2 & (INF2_PARTY_ONLY|INF2_GUILD_ONLY) && src != target) { - int per = 0, sper = 0; - if (tsc && tsc->data[SC_HELLPOWER]) - break; + inf |= + (inf2&INF2_PARTY_ONLY?BCT_PARTY:0)| + (inf2&INF2_GUILD_ONLY?BCT_GUILD:0); + //Remove neutral targets (but allow enemy if skill is designed to be so) + inf &= ~BCT_NEUTRAL; + } - if (map[bl->m].flag.pvp && dstsd && dstsd->pvp_point < 0) + if( sd && (inf2&INF2_CHORUS_SKILL) && skill->check_pc_partner(sd, ud->skill_id, &ud->skill_lv, 1, 0) < 1 ) { + clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_NEED_HELPER, 0); + break; + } + + if( ud->skill_id >= SL_SKE && ud->skill_id <= SL_SKA && target->type == BL_MOB ) + { + if( ((TBL_MOB*)target)->class_ == MOBID_EMPERIUM ) break; + } + else if (inf && battle->check_target(src, target, inf) <= 0){ + if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + break; + } - switch(skill_lv){ - case 1: per=10; break; - case 2: per=30; break; - case 3: per=50; break; - case 4: per=80; break; - } - if(dstsd && dstsd->special_state.restart_full_recover) - per = sper = 100; - if (status_revive(bl, per, sper)) - { - clif->skill_nodamage(src,bl,ALL_RESURRECTION,skill_lv,1); //Both Redemptio and Res show this skill-animation. - if(sd && dstsd && battle_config.resurrection_exp > 0) - { - int exp = 0,jexp = 0; - int lv = dstsd->status.base_level - sd->status.base_level, jlv = dstsd->status.job_level - sd->status.job_level; - if(lv > 0 && pc->nextbaseexp(dstsd)) { - exp = (int)((double)dstsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); - if (exp < 1) exp = 1; - } - if(jlv > 0 && pc->nextjobexp(dstsd)) { - jexp = (int)((double)dstsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); - if (jexp < 1) jexp = 1; - } - if(exp > 0 || jexp > 0) - pc->gainexp (sd, bl, exp, jexp, false); - } - } + if(inf&BCT_ENEMY && (sc = status_get_sc(target)) && + sc->data[SC_FOGWALL] && + rnd() % 100 < 75) { //Fogwall makes all offensive-type targetted skills fail at 75% + if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0); + break; } - break; + } - case AL_DECAGI: - case MER_DECAGI: - clif->skill_nodamage (src, bl, skill_id, skill_lv, - sc_start(bl, type, (40 + skill_lv * 2 + (status_get_lv(src) + sstatus->int_)/5), skill_lv, skill->get_time(skill_id,skill_lv))); + //Avoid doing double checks for instant-cast skills. + if (tid != INVALID_TIMER && !status_check_skilluse(src, target, ud->skill_id, 1)) break; - case AL_CRUCIS: - if (flag&1) - sc_start(bl,type, 23+skill_lv*4 +status_get_lv(src) -status_get_lv(bl), skill_lv,skill->get_time(skill_id,skill_lv)); - else { - iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + if(md) { + md->last_thinktime=tick +MIN_MOBTHINKTIME; + if(md->skill_idx >= 0 && md->db->skill[md->skill_idx].emotion >= 0) + clif->emotion(src, md->db->skill[md->skill_idx].emotion); + } + + if(src != target && battle_config.skill_add_range && + !check_distance_bl(src, target, skill->get_range2(src,ud->skill_id,ud->skill_lv)+battle_config.skill_add_range)) + { + if (sd) { + clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + if(battle_config.skill_out_range_consume) //Consume items anyway. [Skotlex] + skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,3); } break; + } - case PR_LEXDIVINA: - case MER_LEXDIVINA: - if( tsce ) - status_change_end(bl,type, INVALID_TIMER); + if( sd ) + { + if( !skill->check_condition_castend(sd, ud->skill_id, ud->skill_lv) ) + break; else - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); + skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,1); + } +#ifdef OFFICIAL_WALKPATH + if( !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) ) + break; +#endif + if( (src->type == BL_MER || src->type == BL_HOM) && !skill->check_condition_mercenary(src, ud->skill_id, ud->skill_lv, 1) ) break; - case SA_ABRACADABRA: - { - int abra_skill_id = 0, abra_skill_lv; - do { - i = rnd() % MAX_SKILL_ABRA_DB; - abra_skill_id = skill_abra_db[i].skill_id; - } while (abra_skill_id == 0 || - skill_abra_db[i].req_lv > skill_lv || //Required lv for it to appear - rnd()%10000 >= skill_abra_db[i].per - ); - abra_skill_lv = min(skill_lv, skill->get_max(abra_skill_id)); - clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); + if (ud->state.running && ud->skill_id == TK_JUMPKICK) { + ud->state.running = 0; + status_change_end(src, SC_RUN, INVALID_TIMER); + flag = 1; + } - if( sd ) - {// player-casted - sd->state.abra_flag = 1; - sd->skillitem = abra_skill_id; - sd->skillitemlv = abra_skill_lv; - clif->item_skill(sd, abra_skill_id, abra_skill_lv); - } - else - {// mob-casted - struct unit_data *ud = unit_bl2ud(src); - int inf = skill->get_inf(abra_skill_id); - if (!ud) break; - if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { - if (src->type == BL_PET) - bl = (struct block_list*)((TBL_PET*)src)->msd; - if (!bl) bl = src; - unit_skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv); - } else { //Assume offensive skills - int target_id = 0; - if (ud->target) - target_id = ud->target; - else switch (src->type) { - case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; - case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; - } - if (!target_id) - break; - if (skill->get_casttype(abra_skill_id) == CAST_GROUND) { - bl = iMap->id2bl(target_id); - if (!bl) bl = src; - unit_skilluse_pos(src, bl->x, bl->y, abra_skill_id, abra_skill_lv); - } else - unit_skilluse_id(src, target_id, abra_skill_id, abra_skill_lv); - } - } - } - break; - - case SA_COMA: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv))); - break; - case SA_FULLRECOVERY: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if (status_isimmune(bl)) - break; - status_percent_heal(bl, 100, 100); - break; - case NPC_ALLHEAL: - { - int heal; - if( status_isimmune(bl) ) - break; - heal = status_percent_heal(bl, 100, 0); - clif->skill_nodamage(NULL, bl, AL_HEAL, heal, 1); - if( dstmd ) - { // Reset Damage Logs - memset(dstmd->dmglog, 0, sizeof(dstmd->dmglog)); - dstmd->tdmg = 0; + if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH) + unit_stop_walking(src,1); + + if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) + ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); //Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish] + if (sd) { //Cooldown application + int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv); + for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses. + if (sd->skillcooldown[i].id == ud->skill_id){ + cooldown += sd->skillcooldown[i].val; + break; } } - break; - case SA_SUMMONMONSTER: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if (sd) mob_once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_SMALL, AI_NONE); - break; - case SA_LEVELUP: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if (sd && pc->nextbaseexp(sd)) pc->gainexp(sd, NULL, pc->nextbaseexp(sd) * 10 / 100, 0, false); - break; - case SA_INSTANTDEATH: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - status_set_hp(bl,1,0); - break; - case SA_QUESTION: - case SA_GRAVITY: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - case SA_CLASSCHANGE: - case SA_MONOCELL: - if (dstmd) + if(cooldown) + skill->blockpc_start(sd, ud->skill_id, cooldown, false); + } + if( battle_config.display_status_timers && sd ) + clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); + if( sd ) + { + switch( ud->skill_id ) { - int class_; - if ( sd && dstmd->status.mode&MD_BOSS ) - { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - class_ = skill_id==SA_MONOCELL?1002:mob_get_random_id(4, 1, 0); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - mob_class_change(dstmd,class_); - if( tsc && dstmd->status.mode&MD_BOSS ) + case GS_DESPERADO: + sd->canequip_tick = tick + skill->get_time(ud->skill_id, ud->skill_lv); + break; + case CR_GRANDCROSS: + case NPC_GRANDDARKNESS: + if( (sc = status_get_sc(src)) && sc->data[SC_NOEQUIPSHIELD] ) { - const enum sc_type scs[] = { SC_QUAGMIRE, SC_PROVOKE, SC_ROKISWEIL, SC_GRAVITATION, SC_SUITON, SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC_BLADESTOP }; - for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) - if (tsc->data[i]) status_change_end(bl, (sc_type)i, INVALID_TIMER); - for (i = 0; i < ARRAYLENGTH(scs); i++) - if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); + const struct TimerData *timer = iTimer->get_timer(sc->data[SC_NOEQUIPSHIELD]->timer); + if( timer && timer->func == status_change_timer && DIFF_TICK(timer->tick,iTimer->gettick()+skill->get_time(ud->skill_id, ud->skill_lv)) > 0 ) + break; } - } - break; - case SA_DEATH: - if ( sd && dstmd && dstmd->status.mode&MD_BOSS ) - { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + sc_start2(src, SC_NOEQUIPSHIELD, 100, 0, 1, skill->get_time(ud->skill_id, ud->skill_lv)); break; } - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - status_kill(bl); - break; - case SA_REVERSEORCISH: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv))); - break; - case SA_FORTUNE: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if(sd) pc->getzeny(sd,status_get_lv(bl)*100,LOG_TYPE_STEAL,NULL); - break; - case SA_TAMINGMONSTER: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if (sd && dstmd) { - ARR_FIND( 0, MAX_PET_DB, i, dstmd->class_ == pet_db[i].class_ ); - if( i < MAX_PET_DB ) - pet_catch_process1(sd, dstmd->class_); - } - break; - - case CR_PROVIDENCE: - if(sd && dstsd){ //Check they are not another crusader [Skotlex] - if ((dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 1; - } - } - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - break; - - case CG_MARIONETTE: - { - struct status_change* sc = status_get_sc(src); - - if( sd && dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex ) - {// Cannot cast on another bard/dancer-type class of the same gender as caster - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 1; - } + } + if (skill->get_state(ud->skill_id) != ST_MOVE_ENABLE) + unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill->get_walkdelay(ud->skill_id, ud->skill_lv), 1); - if( sc && tsc ) - { - if( !sc->data[SC_MARIONETTE] && !tsc->data[SC_MARIONETTE2] ) - { - sc_start(src,SC_MARIONETTE,100,bl->id,skill->get_time(skill_id,skill_lv)); - sc_start(bl,SC_MARIONETTE2,100,src->id,skill->get_time(skill_id,skill_lv)); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - } - else - if( sc->data[SC_MARIONETTE ] && sc->data[SC_MARIONETTE ]->val1 == bl->id && - tsc->data[SC_MARIONETTE2] && tsc->data[SC_MARIONETTE2]->val1 == src->id ) - { - status_change_end(src, SC_MARIONETTE, INVALID_TIMER); - status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER); - } - else - { - if( sd ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if(battle_config.skill_log && battle_config.skill_log&src->type) + ShowInfo("Type %d, ID %d skill castend id [id =%d, lv=%d, target ID %d]\n", + src->type, src->id, ud->skill_id, ud->skill_lv, target->id); - iMap->freeblock_unlock(); - return 1; - } - } - } - break; + iMap->freeblock_lock(); - case RG_CLOSECONFINE: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv))); - break; - case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris] - case SA_FROSTWEAPON: - case SA_LIGHTNINGLOADER: - case SA_SEISMICWEAPON: - if (dstsd) { - if(dstsd->status.weapon == W_FIST || - (dstsd->sc.count && !dstsd->sc.data[type] && - ( //Allow re-enchanting to lenghten time. [Skotlex] - dstsd->sc.data[SC_FIREWEAPON] || - dstsd->sc.data[SC_WATERWEAPON] || - dstsd->sc.data[SC_WINDWEAPON] || - dstsd->sc.data[SC_EARTHWEAPON] || - dstsd->sc.data[SC_SHADOWWEAPON] || - dstsd->sc.data[SC_GHOSTWEAPON] || - dstsd->sc.data[SC_ENCPOISON] - )) - ) { - if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - clif->skill_nodamage(src,bl,skill_id,skill_lv,0); - break; - } - } - // 100% success rate at lv4 & 5, but lasts longer at lv5 - if(!clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,type,(60+skill_lv*10),skill_lv, skill->get_time(skill_id,skill_lv)))) { - if (sd) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - if (skill->break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) && sd && sd != dstsd) - clif->message(sd->fd, msg_txt(669)); - } - break; + // SC_MAGICPOWER needs to switch states before any damage is actually dealt + skill->toggle_magicpower(src, ud->skill_id); + if( ud->skill_id != RA_CAMOUFLAGE ) // only normal attack and auto cast skills benefit from its bonuses + status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); - case PR_ASPERSIO: - if (sd && dstmd) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,0); - break; - } - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - break; + if (skill->get_casttype(ud->skill_id) == CAST_NODAMAGE) + skill->castend_nodamage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag); + else + skill->castend_damage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag); - case ITEM_ENCHANTARMS: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv, - skill->get_ele(skill_id,skill_lv), skill->get_time(skill_id,skill_lv))); - break; + sc = status_get_sc(src); + if(sc && sc->count) { + if(sc->data[SC_SOULLINK] && + sc->data[SC_SOULLINK]->val2 == SL_WIZARD && + sc->data[SC_SOULLINK]->val3 == ud->skill_id && + ud->skill_id != WZ_WATERBALL) + sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check. - case TK_SEVENWIND: - switch(skill->get_ele(skill_id,skill_lv)) { - case ELE_EARTH : type = SC_EARTHWEAPON; break; - case ELE_WIND : type = SC_WINDWEAPON; break; - case ELE_WATER : type = SC_WATERWEAPON; break; - case ELE_FIRE : type = SC_FIREWEAPON; break; - case ELE_GHOST : type = SC_GHOSTWEAPON; break; - case ELE_DARK : type = SC_SHADOWWEAPON; break; - case ELE_HOLY : type = SC_ASPERSIO; break; - } - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if( sc->data[SC_DANCING] && skill->get_inf2(ud->skill_id)&INF2_SONG_DANCE && sd ) + skill->blockpc_start(sd,BD_ADAPTATION,3000, false); + } - sc_start(bl,SC_SEVENWIND,100,skill_lv,skill->get_time(skill_id,skill_lv)); + if( sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish] + sd->skillitem = sd->skillitemlv = 0; - break; + if (ud->skilltimer == INVALID_TIMER) { + if(md) md->skill_idx = -1; + else ud->skill_id = 0; //mobs can't clear this one as it is used for skill condition 'afterskill' + ud->skill_lv = ud->skilltarget = 0; + } + iMap->freeblock_unlock(); + return 1; + } while(0); - case PR_KYRIE: - case MER_KYRIE: - clif->skill_nodamage(bl,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - break; - //Passive Magnum, should had been casted on yourself. - case SM_MAGNUM: - case MS_MAGNUM: - skill_area_temp[1] = 0; - iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_SKILL|BL_CHAR, - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, skill->castend_damage_id); - clif->skill_nodamage (src,src,skill_id,skill_lv,1); - // Initiate 10% of your damage becomes fire element. - sc_start4(src,SC_WATK_ELEMENT,100,3,20,0,0,skill->get_time2(skill_id, skill_lv)); - if( sd ) - skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv), false); - else if( bl->type == BL_MER ) - skill->blockmerc_start((TBL_MER*)bl, skill_id, skill->get_time(skill_id, skill_lv)); + //Skill failed. + if (ud->skill_id == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL])) + { //When Asura fails... (except when it fails from Fog of Wall) + //Consume SP/spheres + skill->consume_requirement(sd,ud->skill_id, ud->skill_lv,1); + status_set_sp(src, 0, 0); + sc = &sd->sc; + if (sc->count) + { //End states + status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); +#ifdef RENEWAL + sc_start(src, SC_EXTREMITYFIST2, 100, ud->skill_lv, skill->get_time(ud->skill_id, ud->skill_lv)); +#endif + } + if (target && target->m == src->m) + { //Move character to target anyway. + int dir, x, y; + dir = iMap->calc_dir(src,target->x,target->y); + if( dir > 0 && dir < 4) x = -2; + else if( dir > 4 ) x = 2; + else x = 0; + if( dir > 2 && dir < 6 ) y = -2; + else if( dir == 7 || dir < 2 ) y = 2; + else y = 0; + if (unit_movepos(src, src->x+x, src->y+y, 1, 1)) + { //Display movement + animation. + clif->slide(src,src->x,src->y); + clif->skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skill_id, ud->skill_lv, 5); + } + clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + } + } + + ud->skill_id = ud->skill_lv = ud->skilltarget = 0; + if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) + ud->canact_tick = tick; + //You can't place a skill failed packet here because it would be + //sent in ALL cases, even cases where skill_check_condition fails + //which would lead to double 'skill failed' messages u.u [Skotlex] + if(sd) + sd->skillitem = sd->skillitemlv = 0; + else if(md) + md->skill_idx = -1; + return 0; +} + +/*========================================== + * + *------------------------------------------*/ +int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) +{ + struct map_session_data *sd, *dstsd; + struct mob_data *md, *dstmd; + struct homun_data *hd; + struct mercenary_data *mer; + struct status_data *sstatus, *tstatus; + struct status_change *tsc; + struct status_change_entry *tsce; + + int i = 0; + enum sc_type type; + + if(skill_id > 0 && !skill_lv) return 0; // celest + + nullpo_retr(1, src); + nullpo_retr(1, bl); + + if (src->m != bl->m) + return 1; + + sd = BL_CAST(BL_PC, src); + hd = BL_CAST(BL_HOM, src); + md = BL_CAST(BL_MOB, src); + mer = BL_CAST(BL_MER, src); + + dstsd = BL_CAST(BL_PC, bl); + dstmd = BL_CAST(BL_MOB, bl); + + if(bl->prev == NULL) + return 1; + if(status_isdead(src)) + return 1; + + if( src != bl && status_isdead(bl) ) { + /** + * Skills that may be cast on dead targets + **/ + switch( skill_id ) { + case NPC_WIDESOULDRAIN: + case PR_REDEMPTIO: + case ALL_RESURRECTION: + case WM_DEADHILLHERE: + break; + default: + return 1; + } + } + + tstatus = status_get_status_data(bl); + sstatus = status_get_status_data(src); + + //Check for undead skills that convert a no-damage skill into a damage one. [Skotlex] + switch (skill_id) { + case HLIF_HEAL: //[orn] + if (bl->type != BL_HOM) { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0) ; + break ; + } + case AL_HEAL: + case ALL_RESURRECTION: + case PR_ASPERSIO: + /** + * Arch Bishop + **/ + case AB_RENOVATIO: + case AB_HIGHNESSHEAL: + //Apparently only player casted skills can be offensive like this. + if (sd && battle->check_undead(tstatus->race,tstatus->def_ele)) { + if (battle->check_target(src, bl, BCT_ENEMY) < 1) { + //Offensive heal does not works on non-enemies. [Skotlex] + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + return skill->castend_damage_id (src, bl, skill_id, skill_lv, tick, flag); + } break; + case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex] + return skill->castend_damage_id (src, bl, skill_id, skill_lv, tick, flag); + case MH_STEINWAND: { + struct block_list *s_src = battle->get_master(src); + short ret = 0; + if(!skill->check_unit_range(src, src->x, src->y, skill_id, skill_lv)) //prevent reiteration + ret = skill->castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag); //cast on homon + if(s_src && !skill->check_unit_range(s_src, s_src->x, s_src->y, skill_id, skill_lv)) + ret |= skill->castend_pos2(s_src,s_src->x,s_src->y,skill_id,skill_lv,tick,flag); //cast on master + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + return ret; + } + break; + case RK_MILLENNIUMSHIELD: + case RK_CRUSHSTRIKE: + case RK_REFRESH: + case RK_GIANTGROWTH: + case RK_STONEHARDSKIN: + case RK_VITALITYACTIVATION: + case RK_STORMBLAST: + case RK_FIGHTINGSPIRIT: + case RK_ABUNDANCE: + if( sd && !pc->checkskill(sd, RK_RUNEMASTERY) ){ + if( status_change_start(&sd->bl, (sc_type)(rnd()%SC_CONFUSION), 1000, 1, 0, 0, 0, skill->get_time2(skill_id,skill_lv),8) ){ + skill->consume_requirement(sd,skill_id,skill_lv,2); + iMap->freeblock_unlock(); + return 0; + } + } + break; + default: + //Skill is actually ground placed. + if (src == bl && skill->get_unit_id(skill_id,0)) + return skill->castend_pos2(src,bl->x,bl->y,skill_id,skill_lv,tick,0); + } - case TK_JUMPKICK: - /* Check if the target is an enemy; if not, skill should fail so the character doesn't unit_movepos (exploitable) */ - if( battle->check_target(src, bl, BCT_ENEMY) > 0 ) + type = status_skill2sc(skill_id); + tsc = status_get_sc(bl); + tsce = (tsc && type != -1)?tsc->data[type]:NULL; + + if (src!=bl && type > -1 && + (i = skill->get_ele(skill_id, skill_lv)) > ELE_NEUTRAL && + skill->get_inf(skill_id) != INF_SUPPORT_SKILL && + battle->attr_fix(NULL, NULL, 100, i, tstatus->def_ele, tstatus->ele_lv) <= 0) + return 1; //Skills that cause an status should be blocked if the target element blocks its element. + + iMap->freeblock_lock(); + switch(skill_id) { + case HLIF_HEAL: //[orn] + case AL_HEAL: + /** + * Arch Bishop + **/ + case AB_HIGHNESSHEAL: { - if( unit_movepos(src, bl->x, bl->y, 1, 1) ) + int heal = skill->calc_heal(src, bl, (skill_id == AB_HIGHNESSHEAL)?AL_HEAL:skill_id, (skill_id == AB_HIGHNESSHEAL)?10:skill_lv, true); + int heal_get_jobexp; + //Highness Heal: starts at 1.5 boost + 0.5 for each level + if( skill_id == AB_HIGHNESSHEAL ) { + heal = heal * ( 15 + 5 * skill_lv ) / 10; + } + if( status_isimmune(bl) || + (dstmd && (dstmd->class_ == MOBID_EMPERIUM || mob_is_battleground(dstmd))) || + (dstsd && pc_ismadogear(dstsd)) )//Mado is immune to heal + heal=0; + + if( sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0 ) + heal = heal*2; + + if( tsc && tsc->count ) { - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - clif->slide(src,bl->x,bl->y); + if( tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS) ) + { //Bounce back heal + if (--tsc->data[SC_KAITE]->val2 <= 0) + status_change_end(bl, SC_KAITE, INVALID_TIMER); + if (src == bl) + heal=0; //When you try to heal yourself under Kaite, the heal is voided. + else { + bl = src; + dstsd = sd; + } + } + else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAY_NIGHT_FEVER] || tsc->data[SC__BLOODYLUST]) + heal = 0; //Needed so that it actually displays 0 when healing. + } + clif->skill_nodamage (src, bl, skill_id, heal, 1); + if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL ) + heal = ~heal + 1; + heal_get_jobexp = status_heal(bl,heal,0,0); + + if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){ + heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100; + if (heal_get_jobexp <= 0) + heal_get_jobexp = 1; + pc->gainexp (sd, bl, 0, heal_get_jobexp, false); } } - else - clif->skill_fail(sd,skill_id,USESKILL_FAIL,0); break; - case AL_INCAGI: - case AL_BLESSING: - case MER_INCAGI: - case MER_BLESSING: - if (dstsd != NULL && tsc->data[SC_CHANGEUNDEAD]) { - skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); + case PR_REDEMPTIO: + if (sd && !(flag&1)) { + if (sd->status.party_id == 0) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + skill_area_temp[0] = 0; + party_foreachsamemap(skill->area_sub, + sd,skill->get_splash(skill_id, skill_lv), + src,skill_id,skill_lv,tick, flag|BCT_PARTY|1, + skill->castend_nodamage_id); + if (skill_area_temp[0] == 0) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty... + if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty) { //Apply penalty + sd->status.base_exp -= min(sd->status.base_exp, pc->nextbaseexp(sd) * skill_area_temp[0] * 2/1000); //0.2% penalty per each. + sd->status.job_exp -= min(sd->status.job_exp, pc->nextjobexp(sd) * skill_area_temp[0] * 2/1000); + clif->updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd,SP_JOBEXP); + } + status_set_hp(src, 1, 0); + status_set_sp(src, 0, 0); + break; + } else if (status_isdead(bl) && flag&1) { //Revive + skill_area_temp[0]++; //Count it in, then fall-through to the Resurrection code. + skill_lv = 3; //Resurrection level 3 is used + } else //Invalid target, skip resurrection. break; - } - case PR_SLOWPOISON: - case PR_IMPOSITIO: - case PR_LEXAETERNA: - case PR_SUFFRAGIUM: - case PR_BENEDICTIO: - case LK_BERSERK: - case MS_BERSERK: - case KN_AUTOCOUNTER: - case KN_TWOHANDQUICKEN: - case KN_ONEHAND: - case MER_QUICKEN: - case CR_SPEARQUICKEN: - case CR_REFLECTSHIELD: - case MS_REFLECTSHIELD: - case AS_POISONREACT: - case MC_LOUD: - case MG_ENERGYCOAT: - case MO_EXPLOSIONSPIRITS: - case MO_STEELBODY: - case MO_BLADESTOP: - case LK_AURABLADE: - case LK_PARRYING: - case MS_PARRYING: - case LK_CONCENTRATION: - case WS_CARTBOOST: - case SN_SIGHT: - case WS_MELTDOWN: - case WS_OVERTHRUSTMAX: - case ST_REJECTSWORD: - case HW_MAGICPOWER: - case PF_MEMORIZE: - case PA_SACRIFICE: - case ASC_EDP: - case PF_DOUBLECASTING: - case SG_SUN_COMFORT: - case SG_MOON_COMFORT: - case SG_STAR_COMFORT: - case NPC_HALLUCINATION: - case GS_MADNESSCANCEL: - case GS_ADJUSTMENT: - case GS_INCREASING: - case NJ_KASUMIKIRI: - case NJ_UTSUSEMI: - case NJ_NEN: - case NPC_DEFENDER: - case NPC_MAGICMIRROR: - case ST_PRESERVE: - case NPC_INVINCIBLE: - case NPC_INVINCIBLEOFF: - case RK_DEATHBOUND: - case AB_RENOVATIO: - case AB_EXPIATIO: - case AB_DUPLELIGHT: - case AB_SECRAMENT: - case NC_ACCELERATION: - case NC_HOVERING: - case NC_SHAPESHIFT: - case WL_RECOGNIZEDSPELL: - case GC_VENOMIMPRESS: - case SC_DEADLYINFECT: - case LG_EXEEDBREAK: - case LG_PRESTIGE: - case SR_CRESCENTELBOW: - case SR_LIGHTNINGWALK: - case SR_GENTLETOUCH_ENERGYGAIN: - case GN_CARTBOOST: - case KO_MEIKYOUSISUI: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - break; - case SO_STRIKING: - if (sd) { - int bonus = 25 + 10 * skill_lv; - bonus += (pc->checkskill(sd, SA_FLAMELAUNCHER)+pc->checkskill(sd, SA_FROSTWEAPON)+pc->checkskill(sd, SA_LIGHTNINGLOADER)+pc->checkskill(sd, SA_SEISMICWEAPON))*5; - clif->skill_nodamage( src, bl, skill_id, skill_lv, - battle->check_target(src,bl,BCT_PARTY) > 0 ? - sc_start2(bl, type, 100, skill_lv, bonus, skill->get_time(skill_id,skill_lv)) : - 0 - ); + case ALL_RESURRECTION: + if(sd && (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)) + { //No reviving in WoE grounds! + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; } - break; + if (!status_isdead(bl)) + break; + { + int per = 0, sper = 0; + if (tsc && tsc->data[SC_HELLPOWER]) + break; - case NPC_STOP: - if( clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)) ) ) - sc_start2(src,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv)); - break; - case HP_ASSUMPTIO: - if( sd && dstmd ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - else - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - break; - case MG_SIGHT: - case MER_SIGHT: - case AL_RUWACH: - case WZ_SIGHTBLASTER: - case NPC_WIDESIGHT: - case NPC_STONESKIN: - case NPC_ANTIMAGIC: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,skill_id,skill->get_time(skill_id,skill_lv))); - break; - case HLIF_AVOID: - case HAMI_DEFENCE: - i = skill->get_time(skill_id,skill_lv); - clif->skill_nodamage(bl,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,i)); // Master - clif->skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,type,100,skill_lv,i)); // Homunc + if (map[bl->m].flag.pvp && dstsd && dstsd->pvp_point < 0) + break; + + switch(skill_lv){ + case 1: per=10; break; + case 2: per=30; break; + case 3: per=50; break; + case 4: per=80; break; + } + if(dstsd && dstsd->special_state.restart_full_recover) + per = sper = 100; + if (status_revive(bl, per, sper)) + { + clif->skill_nodamage(src,bl,ALL_RESURRECTION,skill_lv,1); //Both Redemptio and Res show this skill-animation. + if(sd && dstsd && battle_config.resurrection_exp > 0) + { + int exp = 0,jexp = 0; + int lv = dstsd->status.base_level - sd->status.base_level, jlv = dstsd->status.job_level - sd->status.job_level; + if(lv > 0 && pc->nextbaseexp(dstsd)) { + exp = (int)((double)dstsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); + if (exp < 1) exp = 1; + } + if(jlv > 0 && pc->nextjobexp(dstsd)) { + jexp = (int)((double)dstsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); + if (jexp < 1) jexp = 1; + } + if(exp > 0 || jexp > 0) + pc->gainexp (sd, bl, exp, jexp, false); + } + } + } break; - case NJ_BUNSINJYUTSU: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - status_change_end(bl, SC_NEN, INVALID_TIMER); + + case AL_DECAGI: + case MER_DECAGI: + clif->skill_nodamage (src, bl, skill_id, skill_lv, + sc_start(bl, type, (40 + skill_lv * 2 + (status_get_lv(src) + sstatus->int_)/5), skill_lv, skill->get_time(skill_id,skill_lv))); break; - /* Was modified to only affect targetted char. [Skotlex] - case HP_ASSUMPTIO: + + case AL_CRUCIS: if (flag&1) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - else - { - iMap->foreachinrange(skill->area_sub, bl, - skill->get_splash(skill_id, skill_lv), BL_PC, - src, skill_id, skill_lv, tick, flag|BCT_ALL|1, - skill->castend_nodamage_id); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + sc_start(bl,type, 23+skill_lv*4 +status_get_lv(src) -status_get_lv(bl), skill_lv,skill->get_time(skill_id,skill_lv)); + else { + iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); } break; - */ - case SM_ENDURE: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - if (sd) - skill->blockpc_start (sd, skill_id, skill->get_time2(skill_id,skill_lv), false); + + case PR_LEXDIVINA: + case MER_LEXDIVINA: + if( tsce ) + status_change_end(bl,type, INVALID_TIMER); + else + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); break; - case AS_ENCHANTPOISON: // Prevent spamming [Valaris] - if (sd && dstsd && dstsd->sc.count) { - if (dstsd->sc.data[SC_FIREWEAPON] || - dstsd->sc.data[SC_WATERWEAPON] || - dstsd->sc.data[SC_WINDWEAPON] || - dstsd->sc.data[SC_EARTHWEAPON] || - dstsd->sc.data[SC_SHADOWWEAPON] || - dstsd->sc.data[SC_GHOSTWEAPON] - // dstsd->sc.data[SC_ENCPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex] - ) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,0); - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + case SA_ABRACADABRA: + { + int abra_skill_id = 0, abra_skill_lv; + do { + i = rnd() % MAX_SKILL_ABRA_DB; + abra_skill_id = skill_abra_db[i].skill_id; + } while (abra_skill_id == 0 || + skill_abra_db[i].req_lv > skill_lv || //Required lv for it to appear + rnd()%10000 >= skill_abra_db[i].per + ); + abra_skill_lv = min(skill_lv, skill->get_max(abra_skill_id)); + clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); + + if( sd ) + {// player-casted + sd->state.abra_flag = 1; + sd->skillitem = abra_skill_id; + sd->skillitemlv = abra_skill_lv; + clif->item_skill(sd, abra_skill_id, abra_skill_lv); + } + else + {// mob-casted + struct unit_data *ud = unit_bl2ud(src); + int inf = skill->get_inf(abra_skill_id); + if (!ud) break; + if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { + if (src->type == BL_PET) + bl = (struct block_list*)((TBL_PET*)src)->msd; + if (!bl) bl = src; + unit_skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv); + } else { //Assume offensive skills + int target_id = 0; + if (ud->target) + target_id = ud->target; + else switch (src->type) { + case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; + case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; + } + if (!target_id) + break; + if (skill->get_casttype(abra_skill_id) == CAST_GROUND) { + bl = iMap->id2bl(target_id); + if (!bl) bl = src; + unit_skilluse_pos(src, bl->x, bl->y, abra_skill_id, abra_skill_lv); + } else + unit_skilluse_id(src, target_id, abra_skill_id, abra_skill_lv); + } } } - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; - case LK_TENSIONRELAX: + case SA_COMA: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,0,0,skill->get_time2(skill_id,skill_lv), - skill->get_time(skill_id,skill_lv))); + sc_start(bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv))); break; - - case MC_CHANGECART: + case SA_FULLRECOVERY: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (status_isimmune(bl)) + break; + status_percent_heal(bl, 100, 100); break; - - case TK_MISSION: - if (sd) { - int id; - if (sd->mission_mobid && (sd->mission_count || rnd()%100)) { //Cannot change target when already have one - clif->mission_info(sd, sd->mission_mobid, sd->mission_count); - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + case NPC_ALLHEAL: + { + int heal; + if( status_isimmune(bl) ) break; + heal = status_percent_heal(bl, 100, 0); + clif->skill_nodamage(NULL, bl, AL_HEAL, heal, 1); + if( dstmd ) + { // Reset Damage Logs + memset(dstmd->dmglog, 0, sizeof(dstmd->dmglog)); + dstmd->tdmg = 0; } - id = mob_get_random_id(0,0xF, sd->status.base_level); - if (!id) { + } + break; + case SA_SUMMONMONSTER: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (sd) mob_once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_SMALL, AI_NONE); + break; + case SA_LEVELUP: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (sd && pc->nextbaseexp(sd)) pc->gainexp(sd, NULL, pc->nextbaseexp(sd) * 10 / 100, 0, false); + break; + case SA_INSTANTDEATH: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_set_hp(bl,1,0); + break; + case SA_QUESTION: + case SA_GRAVITY: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case SA_CLASSCHANGE: + case SA_MONOCELL: + if (dstmd) + { + int class_; + if ( sd && dstmd->status.mode&MD_BOSS ) + { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } - sd->mission_mobid = id; - sd->mission_count = 0; - pc_setglobalreg(sd,"TK_MISSION_ID", id); - clif->mission_info(sd, id, 0); + class_ = skill_id==SA_MONOCELL?1002:mob_get_random_id(4, 1, 0); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + mob_class_change(dstmd,class_); + if( tsc && dstmd->status.mode&MD_BOSS ) + { + const enum sc_type scs[] = { SC_QUAGMIRE, SC_PROVOKE, SC_ROKISWEIL, SC_GRAVITATION, SC_NJ_SUITON, SC_NOEQUIPWEAPON, SC_NOEQUIPSHIELD, SC_NOEQUIPARMOR, SC_NOEQUIPHELM, SC_BLADESTOP }; + for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) + if (tsc->data[i]) status_change_end(bl, (sc_type)i, INVALID_TIMER); + for (i = 0; i < ARRAYLENGTH(scs); i++) + if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); + } } break; - - case AC_CONCENTRATION: + case SA_DEATH: + if ( sd && dstmd && dstmd->status.mode&MD_BOSS ) { - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - iMap->foreachinrange( status_change_timer_sub, src, - skill->get_splash(skill_id, skill_lv), BL_CHAR, - src,NULL,type,tick); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_kill(bl); break; - - case SM_PROVOKE: - case SM_SELFPROVOKE: - case MER_PROVOKE: - if( (tstatus->mode&MD_BOSS) || battle->check_undead(tstatus->race,tstatus->def_ele) ) - { - iMap->freeblock_unlock(); - return 1; - } - //TODO: How much does base level affects? Dummy value of 1% per level difference used. [Skotlex] - clif->skill_nodamage(src,bl,skill_id == SM_SELFPROVOKE ? SM_PROVOKE : skill_id,skill_lv, - (i = sc_start(bl,type, skill_id == SM_SELFPROVOKE ? 100:( 50 + 3*skill_lv + status_get_lv(src) - status_get_lv(bl)), skill_lv, skill->get_time(skill_id,skill_lv)))); - if( !i ) - { - if( sd ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 0; - } - unit_skillcastcancel(bl, 2); - - if( tsc && tsc->count ) - { - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - if( tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE ) - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER); + case SA_REVERSEORCISH: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv))); + break; + case SA_FORTUNE: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if(sd) pc->getzeny(sd,status_get_lv(bl)*100,LOG_TYPE_STEAL,NULL); + break; + case SA_TAMINGMONSTER: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (sd && dstmd) { + ARR_FIND( 0, MAX_PET_DB, i, dstmd->class_ == pet_db[i].class_ ); + if( i < MAX_PET_DB ) + pet_catch_process1(sd, dstmd->class_); } + break; - if( dstmd ) - { - dstmd->state.provoke_flag = src->id; - mob_target(dstmd, src, skill->get_range2(src,skill_id,skill_lv)); + case CR_PROVIDENCE: + if(sd && dstsd){ //Check they are not another crusader [Skotlex] + if ((dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 1; + } } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; - case ML_DEVOTION: - case CR_DEVOTION: - { - int count, lv; - if( !dstsd || (!sd && !mer) ) - { // Only players can be devoted - if( sd ) - clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - break; - } + case CG_MARIONETTE: + { + struct status_change* sc = status_get_sc(src); - if( (lv = status_get_lv(src) - dstsd->status.base_level) < 0 ) - lv = -lv; - if( lv > battle_config.devotion_level_difference || // Level difference requeriments - (dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || // Cannot Devote a player devoted from another source - (skill_id == ML_DEVOTION && (!mer || mer != dstsd->md)) || // Mercenary only can devote owner - (dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER || // Crusader Cannot be devoted - (dstsd->sc.data[SC_HELLPOWER])) // Players affected by SC_HELLPOWERR cannot be devoted. - { - if( sd ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if( sd && dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex ) + {// Cannot cast on another bard/dancer-type class of the same gender as caster + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); iMap->freeblock_unlock(); return 1; } - i = 0; - count = (sd)? min(skill_lv,5) : 1; // Mercenary only can Devote owner - if( sd ) - { // Player Devoting Player - ARR_FIND(0, count, i, sd->devotion[i] == bl->id ); - if( i == count ) + if( sc && tsc ) + { + if( !sc->data[SC_MARIONETTE_MASTER] && !tsc->data[SC_MARIONETTE] ) { - ARR_FIND(0, count, i, sd->devotion[i] == 0 ); - if( i == count ) - { // No free slots, skill Fail - clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - iMap->freeblock_unlock(); - return 1; - } + sc_start(src,SC_MARIONETTE_MASTER,100,bl->id,skill->get_time(skill_id,skill_lv)); + sc_start(bl,SC_MARIONETTE,100,src->id,skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + else + if( sc->data[SC_MARIONETTE_MASTER ] && sc->data[SC_MARIONETTE_MASTER ]->val1 == bl->id && + tsc->data[SC_MARIONETTE] && tsc->data[SC_MARIONETTE]->val1 == src->id ) + { + status_change_end(src, SC_MARIONETTE_MASTER, INVALID_TIMER); + status_change_end(bl, SC_MARIONETTE, INVALID_TIMER); } + else + { + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - sd->devotion[i] = bl->id; + iMap->freeblock_unlock(); + return 1; + } } - else - mer->devotion_flag = 1; // Mercenary Devoting Owner - - clif->skill_nodamage(src, bl, skill_id, skill_lv, - sc_start4(bl, type, 100, src->id, i, skill->get_range2(src,skill_id,skill_lv),0, skill->get_time2(skill_id, skill_lv))); - clif->devotion(src, NULL); - } - break; - - case MO_CALLSPIRITS: - if(sd) { - int limit = skill_lv; - if( sd->sc.data[SC_RAISINGDRAGON] ) - limit += sd->sc.data[SC_RAISINGDRAGON]->val1; - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),limit); - } - break; - - case CH_SOULCOLLECT: - if(sd) { - int limit = 5; - if( sd->sc.data[SC_RAISINGDRAGON] ) - limit += sd->sc.data[SC_RAISINGDRAGON]->val1; - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - for (i = 0; i < limit; i++) - pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),limit); } break; - case MO_KITRANSLATION: - if(dstsd && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) { - pc->addspiritball(dstsd,skill->get_time(skill_id,skill_lv),5); - } + case RG_CLOSECONFINE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,type,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv))); break; - - case TK_TURNKICK: - case MO_BALKYOUNG: //Passive part of the attack. Splash knock-back+stun. [Skotlex] - if (skill_area_temp[1] != bl->id) { - skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),-1,0); - skill->additional_effect(src,bl,skill_id,skill_lv,BF_MISC,ATK_DEF,tick); //Use Misc rather than weapon to signal passive pushback + case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris] + case SA_FROSTWEAPON: + case SA_LIGHTNINGLOADER: + case SA_SEISMICWEAPON: + if (dstsd) { + if(dstsd->status.weapon == W_FIST || + (dstsd->sc.count && !dstsd->sc.data[type] && + ( //Allow re-enchanting to lenghten time. [Skotlex] + dstsd->sc.data[SC_PROPERTYFIRE] || + dstsd->sc.data[SC_PROPERTYWATER] || + dstsd->sc.data[SC_PROPERTYWIND] || + dstsd->sc.data[SC_PROPERTYGROUND] || + dstsd->sc.data[SC_PROPERTYDARK] || + dstsd->sc.data[SC_PROPERTYTELEKINESIS] || + dstsd->sc.data[SC_ENCHANTPOISON] + )) + ) { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + break; + } } - break; - - case MO_ABSORBSPIRITS: - i = 0; - if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) - { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen] - i = dstsd->spiritball * 7; - pc->delspiritball(dstsd,dstsd->spiritball,0); - } else if (dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20) - { // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen] - i = 2 * dstmd->level; - mob_target(dstmd,src,0); + // 100% success rate at lv4 & 5, but lasts longer at lv5 + if(!clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,type,(60+skill_lv*10),skill_lv, skill->get_time(skill_id,skill_lv)))) { + if (sd) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if (skill->break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) && sd && sd != dstsd) + clif->message(sd->fd, msg_txt(669)); } - if (i) status_heal(src, 0, i, 3); - clif->skill_nodamage(src,bl,skill_id,skill_lv,i?1:0); break; - case AC_MAKINGARROW: - if(sd) { - clif->arrow_create_list(sd); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + case PR_ASPERSIO: + if (sd && dstmd) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + break; } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; - case AM_PHARMACY: - if(sd) { - clif->skill_produce_mix_list(sd,skill_id,22); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - } + case ITEM_ENCHANTARMS: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl,type,100,skill_lv, + skill->get_ele(skill_id,skill_lv), skill->get_time(skill_id,skill_lv))); break; - case SA_CREATECON: - if(sd) { - clif->elementalconverter_list(sd); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + case TK_SEVENWIND: + switch(skill->get_ele(skill_id,skill_lv)) { + case ELE_EARTH : type = SC_PROPERTYGROUND; break; + case ELE_WIND : type = SC_PROPERTYWIND; break; + case ELE_WATER : type = SC_PROPERTYWATER; break; + case ELE_FIRE : type = SC_PROPERTYFIRE; break; + case ELE_GHOST : type = SC_PROPERTYTELEKINESIS; break; + case ELE_DARK : type = SC_PROPERTYDARK; break; + case ELE_HOLY : type = SC_ASPERSIO; break; } - break; - - case BS_HAMMERFALL: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,SC_STUN,(20 + 10 * skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv))); - break; - case RG_RAID: - skill_area_temp[1] = 0; - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->area_sub, bl, - skill->get_splash(skill_id, skill_lv), splash_target(src), - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, - skill->castend_damage_id); - status_change_end(src, SC_HIDING, INVALID_TIMER); - break; - - case ASC_METEORASSAULT: - case GS_SPREADATTACK: - case RK_STORMBLAST: - case NC_AXETORNADO: - case GC_COUNTERSLASH: - case SR_SKYNETBLOW: - case SR_RAMPAGEBLASTER: - case SR_HOWLINGOFLION: - case KO_HAPPOKUNAI: - skill_area_temp[1] = 0; - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - i = iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); - if( !i && ( skill_id == NC_AXETORNADO || skill_id == SR_SKYNETBLOW || skill_id == KO_HAPPOKUNAI ) ) - clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - break; + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - case NC_EMERGENCYCOOL: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - status_change_end(src,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); - status_change_end(src,SC_OVERHEAT,INVALID_TIMER); - break; - case SR_WINDMILL: - case GN_CART_TORNADO: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - case SR_EARTHSHAKER: - case NC_INFRAREDSCAN: - case NPC_EARTHQUAKE: - case NPC_VAMPIRE_GIFT: - case NPC_HELLJUDGEMENT: - case NPC_PULSESTRIKE: - case LG_MOONSLASHER: - skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag); - break; + sc_start2(bl,SC_TK_SEVENWIND,100,skill_lv,skill->get_ele(skill_id,skill_lv),skill->get_time(skill_id,skill_lv)); - case KN_BRANDISHSPEAR: - case ML_BRANDISH: - skill->brandishspear(src, bl, skill_id, skill_lv, tick, flag); break; - case WZ_SIGHTRASHER: - //Passive side of the attack. - status_change_end(src, SC_SIGHT, INVALID_TIMER); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->area_sub,src, - skill->get_splash(skill_id, skill_lv),BL_CHAR|BL_SKILL, - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, - skill->castend_damage_id); + case PR_KYRIE: + case MER_KYRIE: + clif->skill_nodamage(bl,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; - - case NJ_HYOUSYOURAKU: - case NJ_RAIGEKISAI: - case WZ_FROSTNOVA: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + //Passive Magnum, should had been casted on yourself. + case SM_MAGNUM: + case MS_MAGNUM: skill_area_temp[1] = 0; - iMap->foreachinrange(skill->attack_area, src, - skill->get_splash(skill_id, skill_lv), splash_target(src), - BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY); - break; - - case HVAN_EXPLOSION: //[orn] - case NPC_SELFDESTRUCTION: - //Self Destruction hits everyone in range (allies+enemies) - //Except for Summoned Marine spheres on non-versus maps, where it's just enemy. - i = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))? - BCT_ENEMY:BCT_ALL; - clif->skill_nodamage(src, src, skill_id, -1, 1); - iMap->delblock(src); //Required to prevent chain-self-destructions hitting back. - iMap->foreachinrange(skill->area_sub, bl, - skill->get_splash(skill_id, skill_lv), splash_target(src), - src, skill_id, skill_lv, tick, flag|i, - skill->castend_damage_id); - iMap->addblock(src); - status_damage(src, src, sstatus->max_hp,0,0,1); - break; - - case AL_ANGELUS: - case PR_MAGNIFICAT: - case PR_GLORIA: - case SN_WINDWALK: - case CASH_BLESSING: - case CASH_INCAGI: - case CASH_ASSUMPTIO: - if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) - clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - else if( sd ) - party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_SKILL|BL_CHAR, + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, skill->castend_damage_id); + clif->skill_nodamage (src,src,skill_id,skill_lv,1); + // Initiate 10% of your damage becomes fire element. + sc_start4(src,SC_WATK_ELEMENT,100,3,20,0,0,skill->get_time2(skill_id, skill_lv)); + if( sd ) + skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv), false); + else if( bl->type == BL_MER ) + skill->blockmerc_start((TBL_MER*)bl, skill_id, skill->get_time(skill_id, skill_lv)); break; - case MER_MAGNIFICAT: - if( mer != NULL ) + + case TK_JUMPKICK: + /* Check if the target is an enemy; if not, skill should fail so the character doesn't unit_movepos (exploitable) */ + if( battle->check_target(src, bl, BCT_ENEMY) > 0 ) { - clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - if( mer->master && mer->master->status.party_id != 0 && !(flag&1) ) - party_foreachsamemap(skill->area_sub, mer->master, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); - else if( mer->master && !(flag&1) ) - clif->skill_nodamage(src, &mer->master->bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if( unit_movepos(src, bl->x, bl->y, 1, 1) ) + { + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + clif->slide(src,bl->x,bl->y); + } } + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL,0); break; - case BS_ADRENALINE: - case BS_ADRENALINE2: - case BS_WEAPONPERFECT: - case BS_OVERTHRUST: - if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) { - clif->skill_nodamage(bl,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,(src == bl)? 1:0,skill->get_time(skill_id,skill_lv))); - } else if (sd) { - party_foreachsamemap(skill->area_sub, - sd,skill->get_splash(skill_id, skill_lv), - src,skill_id,skill_lv,tick, flag|BCT_PARTY|1, - skill->castend_nodamage_id); + case AL_INCAGI: + case AL_BLESSING: + case MER_INCAGI: + case MER_BLESSING: + if (dstsd != NULL && tsc->data[SC_PROPERTYUNDEAD]) { + skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); + break; } + case PR_SLOWPOISON: + case PR_IMPOSITIO: + case PR_LEXAETERNA: + case PR_SUFFRAGIUM: + case PR_BENEDICTIO: + case LK_BERSERK: + case MS_BERSERK: + case KN_AUTOCOUNTER: + case KN_TWOHANDQUICKEN: + case KN_ONEHAND: + case MER_QUICKEN: + case CR_SPEARQUICKEN: + case CR_REFLECTSHIELD: + case MS_REFLECTSHIELD: + case AS_POISONREACT: + case MC_LOUD: + case MG_ENERGYCOAT: + case MO_EXPLOSIONSPIRITS: + case MO_STEELBODY: + case MO_BLADESTOP: + case LK_AURABLADE: + case LK_PARRYING: + case MS_PARRYING: + case LK_CONCENTRATION: + case WS_CARTBOOST: + case SN_SIGHT: + case WS_MELTDOWN: + case WS_OVERTHRUSTMAX: + case ST_REJECTSWORD: + case HW_MAGICPOWER: + case PF_MEMORIZE: + case PA_SACRIFICE: + case ASC_EDP: + case PF_DOUBLECASTING: + case SG_SUN_COMFORT: + case SG_MOON_COMFORT: + case SG_STAR_COMFORT: + case NPC_HALLUCINATION: + case GS_MADNESSCANCEL: + case GS_ADJUSTMENT: + case GS_INCREASING: + case NJ_KASUMIKIRI: + case NJ_UTSUSEMI: + case NJ_NEN: + case NPC_DEFENDER: + case NPC_MAGICMIRROR: + case ST_PRESERVE: + case NPC_INVINCIBLE: + case NPC_INVINCIBLEOFF: + case RK_DEATHBOUND: + case AB_RENOVATIO: + case AB_EXPIATIO: + case AB_DUPLELIGHT: + case AB_SECRAMENT: + case NC_ACCELERATION: + case NC_HOVERING: + case NC_SHAPESHIFT: + case WL_RECOGNIZEDSPELL: + case GC_VENOMIMPRESS: + case SC_DEADLYINFECT: + case LG_EXEEDBREAK: + case LG_PRESTIGE: + case SR_CRESCENTELBOW: + case SR_LIGHTNINGWALK: + case SR_GENTLETOUCH_ENERGYGAIN: + case GN_CARTBOOST: + case KO_MEIKYOUSISUI: + case ALL_FULL_THROTTLE: + case RA_UNLIMIT: + case WL_TELEKINESIS_INTENSE: + case AB_OFFERTORIUM: + case RK_GIANTGROWTH: + case RK_VITALITYACTIVATION: + case RK_ABUNDANCE: + case RK_CRUSHSTRIKE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; - case BS_MAXIMIZE: - case NV_TRICKDEAD: - case CR_DEFENDER: - case ML_DEFENDER: - case CR_AUTOGUARD: - case ML_AUTOGUARD: - case TK_READYSTORM: - case TK_READYDOWN: - case TK_READYTURN: - case TK_READYCOUNTER: - case TK_DODGE: - case CR_SHRINK: - case SG_FUSION: - case GS_GATLINGFEVER: - if( tsce ) - { - clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); - iMap->freeblock_unlock(); - return 0; - } - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - break; - case SL_KAITE: - case SL_KAAHI: - case SL_KAIZEL: - case SL_KAUPE: + case SO_STRIKING: if (sd) { - if (!dstsd || !( - (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SOULLINKER) || - (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER || - dstsd->status.char_id == sd->status.char_id || - dstsd->status.char_id == sd->status.partner_id || - dstsd->status.char_id == sd->status.child - )) { - status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,8); - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } + int bonus = 25 + 10 * skill_lv; + bonus += (pc->checkskill(sd, SA_FLAMELAUNCHER)+pc->checkskill(sd, SA_FROSTWEAPON)+pc->checkskill(sd, SA_LIGHTNINGLOADER)+pc->checkskill(sd, SA_SEISMICWEAPON))*5; + clif->skill_nodamage( src, bl, skill_id, skill_lv, + battle->check_target(src,bl,BCT_PARTY) > 0 ? + sc_start2(bl, type, 100, skill_lv, bonus, skill->get_time(skill_id,skill_lv)) : + 0 + ); } - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv))); break; - case SM_AUTOBERSERK: - case MER_AUTOBERSERK: - if( tsce ) - i = status_change_end(bl, type, INVALID_TIMER); + + case NPC_STOP: + if( clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)) ) ) + sc_start2(src,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv)); + break; + case HP_ASSUMPTIO: + if( sd && dstmd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); else - i = sc_start(bl,type,100,skill_lv,60000); - clif->skill_nodamage(src,bl,skill_id,skill_lv,i); + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; - case TF_HIDING: - case ST_CHASEWALK: - case KO_YAMIKUMO: - if (tsce) - { - clif->skill_nodamage(src,bl,skill_id,-1,status_change_end(bl, type, INVALID_TIMER)); //Hide skill-scream animation. - iMap->freeblock_unlock(); - return 0; - } else if( tsc && tsc->option&OPTION_MADOGEAR ) { - //Mado Gear cannot hide - if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 0; - } - clif->skill_nodamage(src,bl,skill_id,-1,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + case MG_SIGHT: + case MER_SIGHT: + case AL_RUWACH: + case WZ_SIGHTBLASTER: + case NPC_WIDESIGHT: + case NPC_STONESKIN: + case NPC_ANTIMAGIC: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl,type,100,skill_lv,skill_id,skill->get_time(skill_id,skill_lv))); break; - case TK_RUN: - if (tsce) + case HLIF_AVOID: + case HAMI_DEFENCE: + i = skill->get_time(skill_id,skill_lv); + clif->skill_nodamage(bl,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,i)); // Master + clif->skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,type,100,skill_lv,i)); // Homunc + break; + case NJ_BUNSINJYUTSU: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + status_change_end(bl, SC_NJ_NEN, INVALID_TIMER); + break; + /* Was modified to only affect targetted char. [Skotlex] + case HP_ASSUMPTIO: + if (flag&1) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + else { - clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); - iMap->freeblock_unlock(); - return 0; + iMap->foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv), BL_PC, + src, skill_id, skill_lv, tick, flag|BCT_ALL|1, + skill->castend_nodamage_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit_getdir(bl),0,0,0)); - if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex] - clif->walkok(sd); // So aegis has to resend the walk ok. break; - case AS_CLOAKING: - case GC_CLOAKINGEXCEED: - case LG_FORCEOFVANGUARD: - case SC_REPRODUCE: - case SC_INVISIBILITY: - if (tsce) { - i = status_change_end(bl, type, INVALID_TIMER); - if( i ) - clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,i); - else if( sd ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 0; - } - case RA_CAMOUFLAGE: - i = sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - if( i ) - clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,i); - else if( sd ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + */ + case SM_ENDURE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if (sd) + skill->blockpc_start (sd, skill_id, skill->get_time2(skill_id,skill_lv), false); + break; + + case AS_ENCHANTPOISON: // Prevent spamming [Valaris] + if (sd && dstsd && dstsd->sc.count) { + if (dstsd->sc.data[SC_PROPERTYFIRE] || + dstsd->sc.data[SC_PROPERTYWATER] || + dstsd->sc.data[SC_PROPERTYWIND] || + dstsd->sc.data[SC_PROPERTYGROUND] || + dstsd->sc.data[SC_PROPERTYDARK] || + dstsd->sc.data[SC_PROPERTYTELEKINESIS] + // dstsd->sc.data[SC_ENCHANTPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex] + ) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; - case BD_ADAPTATION: - if(tsc && tsc->data[SC_DANCING]){ - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - status_change_end(bl, SC_DANCING, INVALID_TIMER); - } + case LK_TENSIONRELAX: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,type,100,skill_lv,0,0,skill->get_time2(skill_id,skill_lv), + skill->get_time(skill_id,skill_lv))); break; - case BA_FROSTJOKER: - case DC_SCREAM: + case MC_CHANGECART: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - skill->addtimerskill(src,tick+2000,bl->id,src->x,src->y,skill_id,skill_lv,0,flag); - - if (md) { - // custom hack to make the mob display the skill, because these skills don't show the skill use text themselves - //NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches) - char temp[70]; - snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill_db[skill_id].desc); - clif->disp_overhead(&md->bl,temp); - } break; - case BA_PANGVOICE: - clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,50,7,skill->get_time(skill_id,skill_lv))); + case TK_MISSION: + if (sd) { + int id; + if (sd->mission_mobid && (sd->mission_count || rnd()%100)) { //Cannot change target when already have one + clif->mission_info(sd, sd->mission_mobid, sd->mission_count); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + id = mob_get_random_id(0,0xF, sd->status.base_level); + if (!id) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + sd->mission_mobid = id; + sd->mission_count = 0; + pc_setglobalreg(sd,"TK_MISSION_ID", id); + clif->mission_info(sd, id, 0); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } break; - case DC_WINKCHARM: - if( dstsd ) - clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,30,7,skill->get_time2(skill_id,skill_lv))); - else - if( dstmd ) + case AC_CONCENTRATION: { - if( status_get_lv(src) > status_get_lv(bl) - && (tstatus->race == RC_DEMON || tstatus->race == RC_DEMIHUMAN || tstatus->race == RC_ANGEL) - && !(tstatus->mode&MD_BOSS) ) - clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start2(bl,type,70,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); - else - { - clif->skill_nodamage(src,bl,skill_id,skill_lv,0); - if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + iMap->foreachinrange( status_change_timer_sub, src, + skill->get_splash(skill_id, skill_lv), BL_CHAR, + src,NULL,type,tick); } break; - case TF_STEAL: - if(sd) { - if(pc->steal_item(sd,bl,skill_lv)) - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - else - clif->skill_fail(sd,skill_id,USESKILL_FAIL,0); + case SM_PROVOKE: + case SM_SELFPROVOKE: + case MER_PROVOKE: + if( (tstatus->mode&MD_BOSS) || battle->check_undead(tstatus->race,tstatus->def_ele) ) + { + iMap->freeblock_unlock(); + return 1; } - break; + //TODO: How much does base level affects? Dummy value of 1% per level difference used. [Skotlex] + clif->skill_nodamage(src,bl,skill_id == SM_SELFPROVOKE ? SM_PROVOKE : skill_id,skill_lv, + (i = sc_start(bl,type, skill_id == SM_SELFPROVOKE ? 100:( 50 + 3*skill_lv + status_get_lv(src) - status_get_lv(bl)), skill_lv, skill->get_time(skill_id,skill_lv)))); + if( !i ) + { + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 0; + } + unit_skillcastcancel(bl, 2); - case RG_STEALCOIN: - if(sd) { - if(pc->steal_coin(sd,bl)) - { - dstmd->state.provoke_flag = src->id; - mob_target(dstmd, src, skill->get_range2(src,skill_id,skill_lv)); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if( tsc && tsc->count ) + { + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + if( tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE ) + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER); + } - } - else - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if( dstmd ) + { + dstmd->state.provoke_flag = src->id; + mob_target(dstmd, src, skill->get_range2(src,skill_id,skill_lv)); } break; - case MG_STONECURSE: + case ML_DEVOTION: + case CR_DEVOTION: { - int brate = 0; - if (tstatus->mode&MD_BOSS) { - if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + int count, lv; + if( !dstsd || (!sd && !mer) ) + { // Only players can be devoted + if( sd ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); break; } - if(status_isimmune(bl) || !tsc) - break; - if (sd && sd->sc.data[SC_PETROLOGY_OPTION]) - brate = sd->sc.data[SC_PETROLOGY_OPTION]->val3; - - if (tsc->data[SC_STONE]) { - status_change_end(bl, SC_STONE, INVALID_TIMER); - if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + if( (lv = status_get_lv(src) - dstsd->status.base_level) < 0 ) + lv = -lv; + if( lv > battle_config.devotion_level_difference || // Level difference requeriments + (dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || // Cannot Devote a player devoted from another source + (skill_id == ML_DEVOTION && (!mer || mer != dstsd->md)) || // Mercenary only can devote owner + (dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER || // Crusader Cannot be devoted + (dstsd->sc.data[SC_HELLPOWER])) // Players affected by SC_HELLPOWERR cannot be devoted. + { + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 1; } - if (sc_start4(bl,SC_STONE,(skill_lv*4+20)+brate, - skill_lv, 0, 0, skill->get_time(skill_id, skill_lv), - skill->get_time2(skill_id,skill_lv))) - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - else if(sd) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - // Level 6-10 doesn't consume a red gem if it fails [celest] - if (skill_lv > 5) - { // not to consume items - iMap->freeblock_unlock(); - return 0; + + i = 0; + count = (sd)? min(skill_lv,5) : 1; // Mercenary only can Devote owner + if( sd ) + { // Player Devoting Player + ARR_FIND(0, count, i, sd->devotion[i] == bl->id ); + if( i == count ) + { + ARR_FIND(0, count, i, sd->devotion[i] == 0 ); + if( i == count ) + { // No free slots, skill Fail + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + iMap->freeblock_unlock(); + return 1; + } } + + sd->devotion[i] = bl->id; } + else + mer->devotion_flag = 1; // Mercenary Devoting Owner + + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start4(bl, type, 100, src->id, i, skill->get_range2(src,skill_id,skill_lv),0, skill->get_time2(skill_id, skill_lv))); + clif->devotion(src, NULL); } break; - case NV_FIRSTAID: - clif->skill_nodamage(src,bl,skill_id,5,1); - status_heal(bl,5,0,0); + case MO_CALLSPIRITS: + if(sd) { + int limit = skill_lv; + if( sd->sc.data[SC_RAISINGDRAGON] ) + limit += sd->sc.data[SC_RAISINGDRAGON]->val1; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),limit); + } break; - case AL_CURE: - if(status_isimmune(bl)) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,0); - break; + case CH_SOULCOLLECT: + if(sd) { + int limit = 5; + if( sd->sc.data[SC_RAISINGDRAGON] ) + limit += sd->sc.data[SC_RAISINGDRAGON]->val1; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + for (i = 0; i < limit; i++) + pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),limit); } - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - status_change_end(bl, SC_CONFUSION, INVALID_TIMER); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; - case TF_DETOXIFY: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - status_change_end(bl, SC_POISON, INVALID_TIMER); - status_change_end(bl, SC_DPOISON, INVALID_TIMER); + case MO_KITRANSLATION: + if(dstsd && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) { + pc->addspiritball(dstsd,skill->get_time(skill_id,skill_lv),5); + } break; - case PR_STRECOVERY: - if(status_isimmune(bl)) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,0); - break; + case TK_TURNKICK: + case MO_BALKYOUNG: //Passive part of the attack. Splash knock-back+stun. [Skotlex] + if (skill_area_temp[1] != bl->id) { + skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),-1,0); + skill->additional_effect(src,bl,skill_id,skill_lv,BF_MISC,ATK_DEF,tick); //Use Misc rather than weapon to signal passive pushback } - if (tsc && tsc->opt1) { - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); - status_change_end(bl, SC_WHITEIMPRISON, INVALID_TIMER); + break; + + case MO_ABSORBSPIRITS: + i = 0; + if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) + { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen] + i = dstsd->spiritball * 7; + pc->delspiritball(dstsd,dstsd->spiritball,0); + } else if (dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20) + { // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen] + i = 2 * dstmd->level; + mob_target(dstmd,src,0); } - //Is this equation really right? It looks so... special. - if( battle->check_undead(tstatus->race,tstatus->def_ele) ) { - status_change_start(bl, SC_BLIND, - 100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), - 1,0,0,0, - skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0); + if (i) status_heal(src, 0, i, 3); + clif->skill_nodamage(src,bl,skill_id,skill_lv,i?1:0); + break; + + case AC_MAKINGARROW: + if(sd) { + clif->arrow_create_list(sd); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if(dstmd) - mob_unlocktarget(dstmd,tick); break; - // Mercenary Supportive Skills - case MER_BENEDICTION: - status_change_end(bl, SC_CURSE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + case AM_PHARMACY: + if(sd) { + clif->skill_produce_mix_list(sd,skill_id,22); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } break; - case MER_COMPRESS: - status_change_end(bl, SC_BLEEDING, INVALID_TIMER); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + + case SA_CREATECON: + if(sd) { + clif->elementalconverter_list(sd); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } break; - case MER_MENTALCURE: - status_change_end(bl, SC_CONFUSION, INVALID_TIMER); + + case BS_HAMMERFALL: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,SC_STUN,(20 + 10 * skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv))); + break; + case RG_RAID: + skill_area_temp[1] = 0; clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv), splash_target(src), + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, + skill->castend_damage_id); + status_change_end(src, SC_HIDING, INVALID_TIMER); break; - case MER_RECUPERATE: - status_change_end(bl, SC_POISON, INVALID_TIMER); - status_change_end(bl, SC_SILENCE, INVALID_TIMER); + + case ASC_METEORASSAULT: + case GS_SPREADATTACK: + case RK_STORMBLAST: + case NC_AXETORNADO: + case GC_COUNTERSLASH: + case SR_SKYNETBLOW: + case SR_RAMPAGEBLASTER: + case SR_HOWLINGOFLION: + case KO_HAPPOKUNAI: + skill_area_temp[1] = 0; clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + i = iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); + if( !i && ( skill_id == NC_AXETORNADO || skill_id == SR_SKYNETBLOW || skill_id == KO_HAPPOKUNAI ) ) + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); break; - case MER_REGAIN: - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); + + case NC_EMERGENCYCOOL: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_change_end(src,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); + status_change_end(src,SC_OVERHEAT,INVALID_TIMER); break; - case MER_TENDER: - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); + case SR_WINDMILL: + case GN_CART_TORNADO: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + case SR_EARTHSHAKER: + case NC_INFRAREDSCAN: + case NPC_EARTHQUAKE: + case NPC_VAMPIRE_GIFT: + case NPC_HELLJUDGEMENT: + case NPC_PULSESTRIKE: + case LG_MOONSLASHER: + skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag); break; - case MER_SCAPEGOAT: - if( mer && mer->master ) - { - status_heal(&mer->master->bl, mer->battle_status.hp, 0, 2); - status_damage(src, src, mer->battle_status.max_hp, 0, 0, 1); - } + case KN_BRANDISHSPEAR: + case ML_BRANDISH: + skill->brandishspear(src, bl, skill_id, skill_lv, tick, flag); break; - case MER_ESTIMATION: - if( !mer ) - break; - sd = mer->master; - case WZ_ESTIMATION: - if( sd == NULL ) - break; - if( dstsd ) - { // Fail on Players - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) - break; // Cannot be Used on Emperium - - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - clif->skill_estimation(sd, bl); - if( skill_id == MER_ESTIMATION ) - sd = NULL; + case WZ_SIGHTRASHER: + //Passive side of the attack. + status_change_end(src, SC_SIGHT, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->area_sub,src, + skill->get_splash(skill_id, skill_lv),BL_CHAR|BL_SKILL, + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, + skill->castend_damage_id); break; - case BS_REPAIRWEAPON: - if(sd && dstsd) - clif->item_repair_list(sd,dstsd,skill_lv); + case NJ_HYOUSYOURAKU: + case NJ_RAIGEKISAI: + case WZ_FROSTNOVA: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill_area_temp[1] = 0; + iMap->foreachinrange(skill->attack_area, src, + skill->get_splash(skill_id, skill_lv), splash_target(src), + BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY); break; - case MC_IDENTIFY: - if(sd) { - clif->item_identify_list(sd); - if( sd->menuskill_id != MC_IDENTIFY ) {/* failed, dont consume anything, return */ - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->freeblock_unlock(); - return 1; - } - status_zap(src,0,skill_db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded - } + case HVAN_EXPLOSION: //[orn] + case NPC_SELFDESTRUCTION: + //Self Destruction hits everyone in range (allies+enemies) + //Except for Summoned Marine spheres on non-versus maps, where it's just enemy. + i = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))? + BCT_ENEMY:BCT_ALL; + clif->skill_nodamage(src, src, skill_id, -1, 1); + iMap->delblock(src); //Required to prevent chain-self-destructions hitting back. + iMap->foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv), splash_target(src), + src, skill_id, skill_lv, tick, flag|i, + skill->castend_damage_id); + iMap->addblock(src); + status_damage(src, src, sstatus->max_hp,0,0,1); break; - // Weapon Refining [Celest] - case WS_WEAPONREFINE: - if(sd) - clif->item_refine_list(sd); + case AL_ANGELUS: + case PR_MAGNIFICAT: + case PR_GLORIA: + case SN_WINDWALK: + case CASH_BLESSING: + case CASH_INCAGI: + case CASH_ASSUMPTIO: + case WM_FRIGG_SONG: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + else if( sd ) + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); break; - - case MC_VENDING: - if(sd) - { //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex] - if ( !pc->can_give_items(sd) ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - else { - sd->state.prevend = 1; - clif->openvendingreq(sd,2+skill_lv); - } + case MER_MAGNIFICAT: + if( mer != NULL ) + { + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if( mer->master && mer->master->status.party_id != 0 && !(flag&1) ) + party_foreachsamemap(skill->area_sub, mer->master, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + else if( mer->master && !(flag&1) ) + clif->skill_nodamage(src, &mer->master->bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); } break; - case AL_TELEPORT: - if(sd) - { - if (map[bl->m].flag.noteleport && skill_lv <= 2) { - clif->skill_teleportmessage(sd,0); - break; - } - if(!battle_config.duel_allow_teleport && sd->duel_group && skill_lv <= 2) { // duel restriction [LuzZza] - char output[128]; sprintf(output, msg_txt(365), skill->get_name(AL_TELEPORT)); - clif->message(sd->fd, output); //"Duel: Can't use %s in duel." - break; - } - - if( sd->state.autocast || ( (sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1 ) || skill_lv == 3 ) - { - if( skill_lv == 1 ) - pc->randomwarp(sd,CLR_TELEPORT); - else - pc->setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - break; - } - - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if( skill_lv == 1 ) - clif->skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,0,0,0); - else - clif->skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,sd->status.save_point.map,0,0); - } else - unit_warp(bl,-1,-1,-1,CLR_TELEPORT); + case BS_ADRENALINE: + case BS_ADRENALINE2: + case BS_WEAPONPERFECT: + case BS_OVERTHRUST: + if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) { + clif->skill_nodamage(bl,bl,skill_id,skill_lv, + sc_start2(bl,type,100,skill_lv,(src == bl)? 1:0,skill->get_time(skill_id,skill_lv))); + } else if (sd) { + party_foreachsamemap(skill->area_sub, + sd,skill->get_splash(skill_id, skill_lv), + src,skill_id,skill_lv,tick, flag|BCT_PARTY|1, + skill->castend_nodamage_id); + } break; - case NPC_EXPULSION: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - unit_warp(bl,-1,-1,-1,CLR_TELEPORT); + case BS_MAXIMIZE: + case NV_TRICKDEAD: + case CR_DEFENDER: + case ML_DEFENDER: + case CR_AUTOGUARD: + case ML_AUTOGUARD: + case TK_READYSTORM: + case TK_READYDOWN: + case TK_READYTURN: + case TK_READYCOUNTER: + case TK_DODGE: + case CR_SHRINK: + case SG_FUSION: + case GS_GATLINGFEVER: + if( tsce ) + { + clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); + iMap->freeblock_unlock(); + return 0; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; - - case AL_HOLYWATER: - if(sd) { - if (skill->produce_mix(sd, skill_id, 523, 0, 0, 0, 1)) - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - else + case SL_KAITE: + case SL_KAAHI: + case SL_KAIZEL: + case SL_KAUPE: + if (sd) { + if (!dstsd || !( + (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_SOULLINKER) || + (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER || + dstsd->status.char_id == sd->status.char_id || + dstsd->status.char_id == sd->status.partner_id || + dstsd->status.char_id == sd->status.child + )) { + status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,8); clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - break; - - case TF_PICKSTONE: - if(sd) { - int eflag; - struct item item_tmp; - struct block_list tbl; - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - memset(&item_tmp,0,sizeof(item_tmp)); - memset(&tbl,0,sizeof(tbl)); // [MouseJstr] - item_tmp.nameid = ITEMID_STONE; - item_tmp.identify = 1; - tbl.id = 0; - clif->takeitem(&sd->bl,&tbl); - eflag = pc->additem(sd,&item_tmp,1,LOG_TYPE_PRODUCE); - if(eflag) { - clif->additem(sd,0,0,eflag); - iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + break; } } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv))); break; - case ASC_CDP: - if(sd) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - skill->produce_mix(sd, skill_id, 678, 0, 0, 0, 1); //Produce a Deadly Poison Bottle. - } + case SM_AUTOBERSERK: + case MER_AUTOBERSERK: + if( tsce ) + i = status_change_end(bl, type, INVALID_TIMER); + else + i = sc_start(bl,type,100,skill_lv,60000); + clif->skill_nodamage(src,bl,skill_id,skill_lv,i); break; - - case RG_STRIPWEAPON: - case RG_STRIPSHIELD: - case RG_STRIPARMOR: - case RG_STRIPHELM: - case ST_FULLSTRIP: - case GC_WEAPONCRUSH: - case SC_STRIPACCESSARY: { - unsigned short location = 0; - int d = 0; - - //Rate in percent - if ( skill_id == ST_FULLSTRIP ) { - i = 5 + 2*skill_lv + (sstatus->dex - tstatus->dex)/5; - } else if( skill_id == SC_STRIPACCESSARY ) { - i = 12 + 2 * skill_lv + (sstatus->dex - tstatus->dex)/5; - } else { - i = 5 + 5*skill_lv + (sstatus->dex - tstatus->dex)/5; - } - - if (i < 5) i = 5; //Minimum rate 5% - - //Duration in ms - if( skill_id == GC_WEAPONCRUSH){ - d = skill->get_time(skill_id,skill_lv); - if(bl->type == BL_PC) - d += skill_lv * 15 + (sstatus->dex - tstatus->dex); - else - d += skill_lv * 30 + (sstatus->dex - tstatus->dex) / 2; - }else - d = skill->get_time(skill_id,skill_lv) + (sstatus->dex - tstatus->dex)*500; - - if (d < 0) d = 0; //Minimum duration 0ms - - switch (skill_id) { - case RG_STRIPWEAPON: - case GC_WEAPONCRUSH: - location = EQP_WEAPON; - break; - case RG_STRIPSHIELD: - location = EQP_SHIELD; - break; - case RG_STRIPARMOR: - location = EQP_ARMOR; - break; - case RG_STRIPHELM: - location = EQP_HELM; - break; - case ST_FULLSTRIP: - location = EQP_WEAPON|EQP_SHIELD|EQP_ARMOR|EQP_HELM; - break; - case SC_STRIPACCESSARY: - location = EQP_ACC; - break; + case TF_HIDING: + case ST_CHASEWALK: + case KO_YAMIKUMO: + if (tsce) + { + clif->skill_nodamage(src,bl,skill_id,-1,status_change_end(bl, type, INVALID_TIMER)); //Hide skill-scream animation. + iMap->freeblock_unlock(); + return 0; + } else if( tsc && tsc->option&OPTION_MADOGEAR ) { + //Mado Gear cannot hide + if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 0; } - - //Special message when trying to use strip on FCP [Jobbie] - if( sd && skill_id == ST_FULLSTRIP && tsc && tsc->data[SC_CP_WEAPON] && tsc->data[SC_CP_HELM] && tsc->data[SC_CP_ARMOR] && tsc->data[SC_CP_SHIELD]) + clif->skill_nodamage(src,bl,skill_id,-1,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + break; + case TK_RUN: + if (tsce) { - clif->gospel_info(sd, 0x28); - break; + clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); + iMap->freeblock_unlock(); + return 0; } - - //Attempts to strip at rate i and duration d - if( (i = skill->strip_equip(bl, location, i, skill_lv, d)) || (skill_id != ST_FULLSTRIP && skill_id != GC_WEAPONCRUSH ) ) - clif->skill_nodamage(src,bl,skill_id,skill_lv,i); - - //Nothing stripped. - if( sd && !i ) + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit_getdir(bl),0,0,0)); + if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex] + clif->walkok(sd); // So aegis has to resend the walk ok. + break; + case AS_CLOAKING: + case GC_CLOAKINGEXCEED: + case LG_FORCEOFVANGUARD: + case SC_REPRODUCE: + case SC_INVISIBILITY: + if (tsce) { + i = status_change_end(bl, type, INVALID_TIMER); + if( i ) + clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,i); + else if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 0; + } + case RA_CAMOUFLAGE: + i = sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + if( i ) + clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,i); + else if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; - } - - case AM_BERSERKPITCHER: - case AM_POTIONPITCHER: { - int i,sp = 0; - int64 hp = 0; - if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) { - iMap->freeblock_unlock(); - return 1; - } - if( sd ) { - int x,bonus=100; - x = skill_lv%11 - 1; - i = pc->search_inventory(sd,skill_db[skill_id].itemid[x]); - if( i < 0 || skill_db[skill_id].itemid[x] <= 0 ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 1; - } - if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skill_id].amount[x]) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 1; - } - if( skill_id == AM_BERSERKPITCHER ) { - if( dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 1; - } - } - potion_flag = 1; - potion_hp = potion_sp = potion_per_hp = potion_per_sp = 0; - potion_target = bl->id; - run_script(sd->inventory_data[i]->script,0,sd->bl.id,0); - potion_flag = potion_target = 0; - if( sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ALCHEMIST ) - bonus += sd->status.base_level; - if( potion_per_hp > 0 || potion_per_sp > 0 ) { - hp = tstatus->max_hp * potion_per_hp / 100; - hp = hp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - if( dstsd ) { - sp = dstsd->status.max_sp * potion_per_sp / 100; - sp = sp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - } - } else { - if( potion_hp > 0 ) { - hp = potion_hp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - hp = hp * (100 + (tstatus->vit<<1)) / 100; - if( dstsd ) - hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10) / 100; - } - if( potion_sp > 0 ) { - sp = potion_sp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - sp = sp * (100 + (tstatus->int_<<1)) / 100; - if( dstsd ) - sp = sp * (100 + pc->checkskill(dstsd,MG_SRECOVERY)*10) / 100; - } - } - - if (sd->itemgrouphealrate[IG_POTION]>0) { - hp += hp * sd->itemgrouphealrate[IG_POTION] / 100; - sp += sp * sd->itemgrouphealrate[IG_POTION] / 100; - } - if( (i = pc->skillheal_bonus(sd, skill_id)) ) { - hp += hp * i / 100; - sp += sp * i / 100; - } - } else { - hp = (1 + rnd()%400) * (100 + skill_lv*10) / 100; - hp = hp * (100 + (tstatus->vit<<1)) / 100; - if( dstsd ) - hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10) / 100; - } - if( dstsd && (i = pc->skillheal2_bonus(dstsd, skill_id)) ) { - hp += hp * i / 100; - sp += sp * i / 100; - } - if( tsc && tsc->count ) { - if( tsc->data[SC_CRITICALWOUND] ) { - hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - } - if( tsc->data[SC_DEATHHURT] ) { - hp -= hp * 20 / 100; - sp -= sp * 20 / 100; - } - if( tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2 ) { - hp += hp / 10; - sp += sp / 10; - } - } + case BD_ADAPTATION: + if(tsc && tsc->data[SC_DANCING]){ clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if( hp > 0 || (skill_id == AM_POTIONPITCHER && sp <= 0) ) - clif->skill_nodamage(NULL,bl,AL_HEAL,(int)hp,1); - if( sp > 0 ) - clif->skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); - #ifdef RENEWAL - if( tsc && tsc->data[SC_EXTREMITYFIST2] ) - sp = 0; - #endif - status_heal(bl,(int)hp,sp,0); + status_change_end(bl, SC_DANCING, INVALID_TIMER); } - break; - case AM_CP_WEAPON: - case AM_CP_SHIELD: - case AM_CP_ARMOR: - case AM_CP_HELM: - { - unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; + break; - if( sd && ( bl->type != BL_PC || ( dstsd && pc->checkequip(dstsd,equip[skill_id - AM_CP_WEAPON]) < 0 ) ) ){ - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); // Don't consume item requirements - return 0; - } + case BA_FROSTJOKER: + case DC_SCREAM: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->addtimerskill(src,tick+2000,bl->id,src->x,src->y,skill_id,skill_lv,0,flag); - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if (md) { + // custom hack to make the mob display the skill, because these skills don't show the skill use text themselves + //NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches) + char temp[70]; + snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill_db[skill_id].desc); + clif->disp_overhead(&md->bl,temp); } break; - case AM_TWILIGHT1: - if (sd) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - //Prepare 200 White Potions. - if (!skill->produce_mix(sd, skill_id, 504, 0, 0, 0, 200)) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + + case BA_PANGVOICE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,50,7,skill->get_time(skill_id,skill_lv))); + break; + + case DC_WINKCHARM: + if( dstsd ) + clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,30,7,skill->get_time2(skill_id,skill_lv))); + else + if( dstmd ) + { + if( status_get_lv(src) > status_get_lv(bl) + && (tstatus->race == RC_DEMON || tstatus->race == RC_DEMIHUMAN || tstatus->race == RC_ANGEL) + && !(tstatus->mode&MD_BOSS) ) + clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start2(bl,type,70,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); + else + { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } } break; - case AM_TWILIGHT2: - if (sd) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - //Prepare 200 Slim White Potions. - if (!skill->produce_mix(sd, skill_id, 547, 0, 0, 0, 200)) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + + case TF_STEAL: + if(sd) { + if(pc->steal_item(sd,bl,skill_lv)) + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL,0); } break; - case AM_TWILIGHT3: - if (sd) { - int ebottle = pc->search_inventory(sd,713); - if( ebottle >= 0 ) - ebottle = sd->status.inventory[ebottle].amount; - //check if you can produce all three, if not, then fail: - if (!skill->can_produce_mix(sd,970,-1, 100) //100 Alcohol - || !skill->can_produce_mix(sd,7136,-1, 50) //50 Acid Bottle - || !skill->can_produce_mix(sd,7135,-1, 50) //50 Flame Bottle - || ebottle < 200 //200 empty bottle are required at total. - ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + + case RG_STEALCOIN: + if(sd) { + if(pc->steal_coin(sd,bl)) + { + dstmd->state.provoke_flag = src->id; + mob_target(dstmd, src, skill->get_range2(src,skill_id,skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - skill->produce_mix(sd, skill_id, 970, 0, 0, 0, 100); - skill->produce_mix(sd, skill_id, 7136, 0, 0, 0, 50); - skill->produce_mix(sd, skill_id, 7135, 0, 0, 0, 50); + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } break; - case SA_DISPELL: - if (flag&1 || (i = skill->get_splash(skill_id, skill_lv)) < 1) + + case MG_STONECURSE: { - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) - || (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_ROGUE) //Rogue's spirit defends againt dispel. - || rnd()%100 >= 50+10*skill_lv - || ( tsc && tsc->option&OPTION_MADOGEAR ) )//Mado Gear is immune to dispell according to bug report 49 [Ind] - { - if (sd) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + int brate = 0; + if (tstatus->mode&MD_BOSS) { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } - if(status_isimmune(bl) || !tsc || !tsc->count) + if(status_isimmune(bl) || !tsc) break; - - if( sd && dstsd && !map_flag_vs(sd->bl.m) && sd->status.guild_id == dstsd->status.guild_id ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + + if (sd && sd->sc.data[SC_PETROLOGY_OPTION]) + brate = sd->sc.data[SC_PETROLOGY_OPTION]->val3; + + if (tsc->data[SC_STONE]) { + status_change_end(bl, SC_STONE, INVALID_TIMER); + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } - - for(i=0;idata[i]) - continue; - switch (i) { - case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION: - case SC_STRIPWEAPON: case SC_STRIPSHIELD: case SC_STRIPARMOR: - case SC_STRIPHELM: case SC_CP_WEAPON: case SC_CP_SHIELD: - case SC_CP_ARMOR: case SC_CP_HELM: case SC_COMBO: - case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD: - case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD: - case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD: - case SC_WATKFOOD: case SC_MATKFOOD: case SC_DANCING: - case SC_EDP: case SC_AUTOBERSERK: - case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL: - case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT: - case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED: - case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE: - case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL: - case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN: - case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN: - case SC_READYCOUNTER: case SC_DODGE: case SC_WARM: - case SC_SPEEDUP1: case SC_AUTOTRADE: case SC_CRITICALWOUND: - case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF: - case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF: - case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK: - case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS: - case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL: - case SC_INTOABYSS: case SC_SIEGFRIED: case SC_FOOD_STR_CASH: - case SC_FOOD_AGI_CASH: case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: - case SC_FOOD_INT_CASH: case SC_FOOD_LUK_CASH: case SC_SEVENWIND: - case SC_MIRACLE: case SC_S_LIFEPOTION: case SC_L_LIFEPOTION: - case SC_INCHEALRATE: case SC_ELECTRICSHOCKER: case SC__STRIPACCESSORY: - //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: case SC_MINOR_BBQ: - //case SC_SIROMA_ICE_TEA: case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: - case SC_NEUTRALBARRIER_MASTER: case SC_NEUTRALBARRIER: case SC_STEALTHFIELD_MASTER: - case SC_STEALTHFIELD: case SC_GIANTGROWTH: case SC_MILLENNIUMSHIELD: - case SC_REFRESH: case SC_STONEHARDSKIN: case SC_VITALITYACTIVATION: - case SC_FIGHTINGSPIRIT: case SC_ABUNDANCE: case SC__SHADOWFORM: - case SC_LEADERSHIP: case SC_GLORYWOUNDS: case SC_SOULCOLD: - case SC_HAWKEYES: case SC_GUILDAURA: case SC_PUSH_CART: - case SC_RAISINGDRAGON: case SC_GT_ENERGYGAIN: case SC_GT_CHANGE: - case SC_GT_REVITALIZE: case SC_REFLECTDAMAGE: case SC_INSPIRATION: - case SC_EXEEDBREAK: case SC_FORCEOFVANGUARD: case SC_BANDING: - case SC_DUPLELIGHT: case SC_EXPIATIO: case SC_LAUDAAGNUS: - case SC_LAUDARAMUS: case SC_GATLINGFEVER: case SC_INCREASING: - case SC_ADJUSTMENT: case SC_MADNESSCANCEL: case SC_ALL_RIDING: - #ifdef RENEWAL - case SC_EXTREMITYFIST2: - #endif - continue; - /** - * bugreport:4888 these songs may only be dispelled if you're not in their song area anymore - **/ - case SC_WHISTLE: - case SC_ASSNCROS: - case SC_POEMBRAGI: - case SC_APPLEIDUN: - case SC_HUMMING: - case SC_DONTFORGETME: - case SC_FORTUNE: - case SC_SERVICE4U: - if( !tsc->data[i]->val4 ) //val4 = out-of-song-area - continue; - break; - case SC_ASSUMPTIO: - if( bl->type == BL_MOB ) - continue; - break; + if (sc_start4(bl,SC_STONE,(skill_lv*4+20)+brate, + skill_lv, 0, 0, skill->get_time(skill_id, skill_lv), + skill->get_time2(skill_id,skill_lv))) + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + else if(sd) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + // Level 6-10 doesn't consume a red gem if it fails [celest] + if (skill_lv > 5) + { // not to consume items + iMap->freeblock_unlock(); + return 0; } - if(i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. - status_change_end(bl, (sc_type)i, INVALID_TIMER); } + } + break; + + case NV_FIRSTAID: + clif->skill_nodamage(src,bl,skill_id,5,1); + status_heal(bl,5,0,0); + break; + + case AL_CURE: + if(status_isimmune(bl)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + break; + } + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + status_change_end(bl, SC_CONFUSION, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + + case TF_DETOXIFY: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_change_end(bl, SC_POISON, INVALID_TIMER); + status_change_end(bl, SC_DPOISON, INVALID_TIMER); + break; + + case PR_STRECOVERY: + if(status_isimmune(bl)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + break; + } + if (tsc && tsc->opt1) { + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + status_change_end(bl, SC_WHITEIMPRISON, INVALID_TIMER); + } + //Is this equation really right? It looks so... special. + if( battle->check_undead(tstatus->race,tstatus->def_ele) ) { + status_change_start(bl, SC_BLIND, + 100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), + 1,0,0,0, + skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0); + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if(dstmd) + mob_unlocktarget(dstmd,tick); + break; + + // Mercenary Supportive Skills + case MER_BENEDICTION: + status_change_end(bl, SC_CURSE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case MER_COMPRESS: + status_change_end(bl, SC_BLOODING, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case MER_MENTALCURE: + status_change_end(bl, SC_CONFUSION, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case MER_RECUPERATE: + status_change_end(bl, SC_POISON, INVALID_TIMER); + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case MER_REGAIN: + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case MER_TENDER: + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + + case MER_SCAPEGOAT: + if( mer && mer->master ) + { + status_heal(&mer->master->bl, mer->battle_status.hp, 0, 2); + status_damage(src, src, mer->battle_status.max_hp, 0, 0, 1); + } + break; + + case MER_ESTIMATION: + if( !mer ) + break; + sd = mer->master; + case WZ_ESTIMATION: + if( sd == NULL ) + break; + if( dstsd ) + { // Fail on Players + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } - //Affect all targets on splash area. - iMap->foreachinrange(skill->area_sub, bl, i, BL_CHAR, - src, skill_id, skill_lv, tick, flag|1, - skill->castend_damage_id); + if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) + break; // Cannot be Used on Emperium + + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + clif->skill_estimation(sd, bl); + if( skill_id == MER_ESTIMATION ) + sd = NULL; + break; + + case BS_REPAIRWEAPON: + if(sd && dstsd) + clif->item_repair_list(sd,dstsd,skill_lv); + break; + + case MC_IDENTIFY: + if(sd) { + clif->item_identify_list(sd); + if( sd->menuskill_id != MC_IDENTIFY ) {/* failed, dont consume anything, return */ + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->freeblock_unlock(); + return 1; + } + status_zap(src,0,skill_db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded + } + break; + + // Weapon Refining [Celest] + case WS_WEAPONREFINE: + if(sd){ + sd->state.prerefining = 1; + clif->item_refine_list(sd); + } break; - case TF_BACKSLIDING: //This is the correct implementation as per packet logging information. [Skotlex] - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),unit_getdir(bl),0); + case MC_VENDING: + if(sd) + { //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex] + if ( !pc->can_give_items(sd) ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + else { + sd->state.prevend = sd->state.workinprogress = 3; + clif->openvendingreq(sd,2+skill_lv); + } + } break; - case TK_HIGHJUMP: + case AL_TELEPORT: + if(sd) { - int x,y, dir = unit_getdir(src); - - //Fails on noteleport maps, except for GvG and BG maps [Skotlex] - if( map[src->m].flag.noteleport && - !(map[src->m].flag.battleground || map_flag_gvg2(src->m) ) - ) { - x = src->x; - y = src->y; - } else { - x = src->x + dirx[dir]*skill_lv*2; - y = src->y + diry[dir]*skill_lv*2; + if (map[bl->m].flag.noteleport && skill_lv <= 2) { + clif->skill_mapinfomessage(sd,0); + break; + } + if(!battle_config.duel_allow_teleport && sd->duel_group && skill_lv <= 2) { // duel restriction [LuzZza] + char output[128]; sprintf(output, msg_txt(365), skill->get_name(AL_TELEPORT)); + clif->message(sd->fd, output); //"Duel: Can't use %s in duel." + break; } - clif->skill_nodamage(src,bl,TK_HIGHJUMP,skill_lv,1); - if(!iMap->count_oncell(src->m,x,y,BL_PC|BL_NPC|BL_MOB) && iMap->getcell(src->m,x,y,CELL_CHKREACH)) { - clif->slide(src,x,y); - unit_movepos(src, x, y, 1, 0); + if( sd->state.autocast || ( (sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1 ) || skill_lv == 3 ) + { + if( skill_lv == 1 ) + pc->randomwarp(sd,CLR_TELEPORT); + else + pc->setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + break; } - } + + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if( skill_lv == 1 ) + clif->skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,0,0,0); + else + clif->skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,sd->status.save_point.map,0,0); + } else + unit_warp(bl,-1,-1,-1,CLR_TELEPORT); break; - case SA_CASTCANCEL: - case SO_SPELLFIST: + case NPC_EXPULSION: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - unit_skillcastcancel(src,1); - if(sd) { - int sp = skill->get_sp(sd->skill_id_old,sd->skill_lv_old); - if( skill_id == SO_SPELLFIST ){ - sc_start4(src,type,100,skill_lv+1,skill_lv,sd->skill_id_old,sd->skill_lv_old,skill->get_time(skill_id,skill_lv)); - sd->skill_id_old = sd->skill_lv_old = 0; - break; - } - sp = sp * (90 - (skill_lv-1)*20) / 100; - if(sp < 0) sp = 0; - status_zap(src, 0, sp); - } + unit_warp(bl,-1,-1,-1,CLR_TELEPORT); break; - case SA_SPELLBREAKER: - { - int sp; - if(tsc && tsc->data[SC_MAGICROD]) { - sp = skill->get_sp(skill_id,skill_lv); - sp = sp * tsc->data[SC_MAGICROD]->val2 / 100; - if(sp < 1) sp = 1; - status_heal(bl,0,sp,2); - status_percent_damage(bl, src, 0, -20, false); //20% max SP damage. - } else { - struct unit_data *ud = unit_bl2ud(bl); - int bl_skill_id=0,bl_skill_lv=0,hp = 0; - if (!ud || ud->skilltimer == INVALID_TIMER) - break; //Nothing to cancel. - bl_skill_id = ud->skill_id; - bl_skill_lv = ud->skill_lv; - if (tstatus->mode & MD_BOSS) - { //Only 10% success chance against bosses. [Skotlex] - if (rnd()%100 < 90) - { - if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - } else if (!dstsd || map_flag_vs(bl->m)) //HP damage only on pvp-maps when against players. - hp = tstatus->max_hp/50; //Recover 2% HP [Skotlex] + case AL_HOLYWATER: + if(sd) { + if (skill->produce_mix(sd, skill_id, 523, 0, 0, 0, 1)) clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - unit_skillcastcancel(bl,0); - sp = skill->get_sp(bl_skill_id,bl_skill_lv); - status_zap(bl, hp, sp); - - if (hp && skill_lv >= 5) - hp>>=1; //Recover half damaged HP at level 5 [Skotlex] - else - hp = 0; - - if (sp) //Recover some of the SP used - sp = sp*(25*(skill_lv-1))/100; - - if(hp || sp) - status_heal(src, hp, sp, 2); - } + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } break; - case SA_MAGICROD: - clif->skill_nodamage(src,src,SA_MAGICROD,skill_lv,1); - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - break; - case SA_AUTOSPELL: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if(sd) - clif->autospell(sd,skill_lv); - else { - int maxlv=1,spellid=0; - static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT }; - if(skill_lv >= 10) { - spellid = MG_FROSTDIVER; - // if (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SA_SAGE) - // maxlv = 10; - // else - maxlv = skill_lv - 9; - } - else if(skill_lv >=8) { - spellid = MG_FIREBALL; - maxlv = skill_lv - 7; - } - else if(skill_lv >=5) { - spellid = MG_SOULSTRIKE; - maxlv = skill_lv - 4; - } - else if(skill_lv >=2) { - int i = rnd()%3; - spellid = spellarray[i]; - maxlv = skill_lv - 1; - } - else if(skill_lv > 0) { - spellid = MG_NAPALMBEAT; - maxlv = 3; + + case TF_PICKSTONE: + if(sd) { + int eflag; + struct item item_tmp; + struct block_list tbl; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + memset(&item_tmp,0,sizeof(item_tmp)); + memset(&tbl,0,sizeof(tbl)); // [MouseJstr] + item_tmp.nameid = ITEMID_STONE; + item_tmp.identify = 1; + tbl.id = 0; + clif->takeitem(&sd->bl,&tbl); + eflag = pc->additem(sd,&item_tmp,1,LOG_TYPE_PRODUCE); + if(eflag) { + clif->additem(sd,0,0,eflag); + iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } - if(spellid > 0) - sc_start4(src,SC_AUTOSPELL,100,skill_lv,spellid,maxlv,0, - skill->get_time(SA_AUTOSPELL,skill_lv)); } break; - - case BS_GREED: - if(sd){ + case ASC_CDP: + if(sd) { clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->greed,bl, - skill->get_splash(skill_id, skill_lv),BL_ITEM,bl); + skill->produce_mix(sd, skill_id, 678, 0, 0, 0, 1); //Produce a Deadly Poison Bottle. } break; - case SA_ELEMENTWATER: - case SA_ELEMENTFIRE: - case SA_ELEMENTGROUND: - case SA_ELEMENTWIND: - if(sd && !dstmd) //Only works on monsters. + case RG_STRIPWEAPON: + case RG_STRIPSHIELD: + case RG_STRIPARMOR: + case RG_STRIPHELM: + case ST_FULLSTRIP: + case GC_WEAPONCRUSH: + case SC_STRIPACCESSARY: { + unsigned short location = 0; + int d = 0; + + //Rate in percent + if ( skill_id == ST_FULLSTRIP ) { + i = 5 + 2*skill_lv + (sstatus->dex - tstatus->dex)/5; + } else if( skill_id == SC_STRIPACCESSARY ) { + i = 12 + 2 * skill_lv + (sstatus->dex - tstatus->dex)/5; + } else { + i = 5 + 5*skill_lv + (sstatus->dex - tstatus->dex)/5; + } + + if (i < 5) i = 5; //Minimum rate 5% + + //Duration in ms + if( skill_id == GC_WEAPONCRUSH){ + d = skill->get_time(skill_id,skill_lv); + if(bl->type == BL_PC) + d += skill_lv * 15 + (sstatus->dex - tstatus->dex); + else + d += skill_lv * 30 + (sstatus->dex - tstatus->dex) / 2; + }else + d = skill->get_time(skill_id,skill_lv) + (sstatus->dex - tstatus->dex)*500; + + if (d < 0) d = 0; //Minimum duration 0ms + + switch (skill_id) { + case RG_STRIPWEAPON: + case GC_WEAPONCRUSH: + location = EQP_WEAPON; break; - if(tstatus->mode&MD_BOSS) + case RG_STRIPSHIELD: + location = EQP_SHIELD; break; - case NPC_ATTRICHANGE: - case NPC_CHANGEWATER: - case NPC_CHANGEGROUND: - case NPC_CHANGEFIRE: - case NPC_CHANGEWIND: - case NPC_CHANGEPOISON: - case NPC_CHANGEHOLY: - case NPC_CHANGEDARKNESS: - case NPC_CHANGETELEKINESIS: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv), - skill->get_time(skill_id, skill_lv))); - break; - case NPC_CHANGEUNDEAD: - //This skill should fail if target is wearing bathory/evil druid card [Brainstorm] - //TO-DO This is ugly, fix it - if(tstatus->def_ele==ELE_UNDEAD || tstatus->def_ele==ELE_DARK) break; - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv), - skill->get_time(skill_id, skill_lv))); - break; - - case NPC_PROVOCATION: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if (md) mob_unlocktarget(md, tick); - break; + case RG_STRIPARMOR: + location = EQP_ARMOR; + break; + case RG_STRIPHELM: + location = EQP_HELM; + break; + case ST_FULLSTRIP: + location = EQP_WEAPON|EQP_SHIELD|EQP_ARMOR|EQP_HELM; + break; + case SC_STRIPACCESSARY: + location = EQP_ACC; + break; + } - case NPC_KEEPING: - case NPC_BARRIER: + //Special message when trying to use strip on FCP [Jobbie] + if( sd && skill_id == ST_FULLSTRIP && tsc && tsc->data[SC_PROTECTWEAPON] && tsc->data[SC_PROTECTHELM] && tsc->data[SC_PROTECTARMOR] && tsc->data[SC_PROTECTSHIELD]) { - int skill_time = skill->get_time(skill_id,skill_lv); - struct unit_data *ud = unit_bl2ud(bl); - if (clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_time)) - && ud) { //Disable attacking/acting/moving for skill's duration. - ud->attackabletime = - ud->canact_tick = - ud->canmove_tick = tick + skill_time; - } + clif->gospel_info(sd, 0x28); + break; } - break; - case NPC_REBIRTH: - if( md && md->state.rebirth ) - break; // only works once - sc_start(bl,type,100,skill_lv,-1); - break; + //Attempts to strip at rate i and duration d + if( (i = skill->strip_equip(bl, location, i, skill_lv, d)) || (skill_id != ST_FULLSTRIP && skill_id != GC_WEAPONCRUSH ) ) + clif->skill_nodamage(src,bl,skill_id,skill_lv,i); - case NPC_DARKBLESSING: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,(50+skill_lv*5),skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv))); + //Nothing stripped. + if( sd && !i ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; + } - case NPC_LICK: - status_zap(bl, 0, 100); - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,(skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv))); - break; + case AM_BERSERKPITCHER: + case AM_POTIONPITCHER: { + int i,sp = 0; + int64 hp = 0; + if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) { + iMap->freeblock_unlock(); + return 1; + } + if( sd ) { + int x,bonus=100; + x = skill_lv%11 - 1; + i = pc->search_inventory(sd,skill_db[skill_id].itemid[x]); + if( i < 0 || skill_db[skill_id].itemid[x] <= 0 ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 1; + } + if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skill_id].amount[x]) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 1; + } + if( skill_id == AM_BERSERKPITCHER ) { + if( dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 1; + } + } + potion_flag = 1; + potion_hp = potion_sp = potion_per_hp = potion_per_sp = 0; + potion_target = bl->id; + run_script(sd->inventory_data[i]->script,0,sd->bl.id,0); + potion_flag = potion_target = 0; + if( sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ALCHEMIST ) + bonus += sd->status.base_level; + if( potion_per_hp > 0 || potion_per_sp > 0 ) { + hp = tstatus->max_hp * potion_per_hp / 100; + hp = hp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + if( dstsd ) { + sp = dstsd->status.max_sp * potion_per_sp / 100; + sp = sp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + } + } else { + if( potion_hp > 0 ) { + hp = potion_hp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + hp = hp * (100 + (tstatus->vit<<1)) / 100; + if( dstsd ) + hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10) / 100; + } + if( potion_sp > 0 ) { + sp = potion_sp * (100 + pc->checkskill(sd,AM_POTIONPITCHER)*10 + pc->checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + sp = sp * (100 + (tstatus->int_<<1)) / 100; + if( dstsd ) + sp = sp * (100 + pc->checkskill(dstsd,MG_SRECOVERY)*10) / 100; + } + } - case NPC_SUICIDE: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - status_kill(src); //When suiciding, neither exp nor drops is given. - break; + if (sd->itemgrouphealrate[IG_POTION]>0) { + hp += hp * sd->itemgrouphealrate[IG_POTION] / 100; + sp += sp * sd->itemgrouphealrate[IG_POTION] / 100; + } - case NPC_SUMMONSLAVE: - case NPC_SUMMONMONSTER: - if(md && md->skill_idx >= 0) - mob_summonslave(md,md->db->skill[md->skill_idx].val,skill_lv,skill_id); + if( (i = pc->skillheal_bonus(sd, skill_id)) ) { + hp += hp * i / 100; + sp += sp * i / 100; + } + } else { + hp = (1 + rnd()%400) * (100 + skill_lv*10) / 100; + hp = hp * (100 + (tstatus->vit<<1)) / 100; + if( dstsd ) + hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10) / 100; + } + if( dstsd && (i = pc->skillheal2_bonus(dstsd, skill_id)) ) { + hp += hp * i / 100; + sp += sp * i / 100; + } + if( tsc && tsc->count ) { + if( tsc->data[SC_CRITICALWOUND] ) { + hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + } + if( tsc->data[SC_DEATHHURT] ) { + hp -= hp * 20 / 100; + sp -= sp * 20 / 100; + } + if( tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2 ) { + hp += hp / 10; + sp += sp / 10; + } + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if( hp > 0 || (skill_id == AM_POTIONPITCHER && sp <= 0) ) + clif->skill_nodamage(NULL,bl,AL_HEAL,(int)hp,1); + if( sp > 0 ) + clif->skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); + #ifdef RENEWAL + if( tsc && tsc->data[SC_EXTREMITYFIST2] ) + sp = 0; + #endif + status_heal(bl,(int)hp,sp,0); + } break; + case AM_CP_WEAPON: + case AM_CP_SHIELD: + case AM_CP_ARMOR: + case AM_CP_HELM: + { + unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; - case NPC_CALLSLAVE: - mob_warpslave(src,MOB_SLAVEDISTANCE); - break; + if( sd && ( bl->type != BL_PC || ( dstsd && pc->checkequip(dstsd,equip[skill_id - AM_CP_WEAPON]) < 0 ) ) ){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); // Don't consume item requirements + return 0; + } - case NPC_RANDOMMOVE: - if (md) { - md->next_walktime = tick - 1; - mob_randomwalk(md,tick); + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); } break; - - case NPC_SPEEDUP: - { - // or does it increase casting rate? just a guess xD - int i = SC_ASPDPOTION0 + skill_lv - 1; - if (i > SC_ASPDPOTION3) - i = SC_ASPDPOTION3; - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,(sc_type)i,100,skill_lv,skill_lv * 60000)); + case AM_TWILIGHT1: + if (sd) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + //Prepare 200 White Potions. + if (!skill->produce_mix(sd, skill_id, 504, 0, 0, 0, 200)) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } break; - - case NPC_REVENGE: - // not really needed... but adding here anyway ^^ - if (md && md->master_id > 0) { - struct block_list *mbl, *tbl; - if ((mbl = iMap->id2bl(md->master_id)) == NULL || - (tbl = battle->get_targeted(mbl)) == NULL) + case AM_TWILIGHT2: + if (sd) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + //Prepare 200 Slim White Potions. + if (!skill->produce_mix(sd, skill_id, 547, 0, 0, 0, 200)) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } + break; + case AM_TWILIGHT3: + if (sd) { + int ebottle = pc->search_inventory(sd,713); + if( ebottle >= 0 ) + ebottle = sd->status.inventory[ebottle].amount; + //check if you can produce all three, if not, then fail: + if (!skill->can_produce_mix(sd,970,-1, 100) //100 Alcohol + || !skill->can_produce_mix(sd,7136,-1, 50) //50 Acid Bottle + || !skill->can_produce_mix(sd,7135,-1, 50) //50 Flame Bottle + || ebottle < 200 //200 empty bottle are required at total. + ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; - md->state.provoke_flag = tbl->id; - mob_target(md, tbl, sstatus->rhw.range); + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->produce_mix(sd, skill_id, 970, 0, 0, 0, 100); + skill->produce_mix(sd, skill_id, 7136, 0, 0, 0, 50); + skill->produce_mix(sd, skill_id, 7135, 0, 0, 0, 50); } break; - - case NPC_RUN: + case SA_DISPELL: + if (flag&1 || (i = skill->get_splash(skill_id, skill_lv)) < 1) { - const int mask[8][2] = {{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}}; - uint8 dir = (bl == src)?unit_getdir(src):iMap->calc_dir(src,bl->x,bl->y); //If cast on self, run forward, else run away. - unit_stop_attack(src); - //Run skillv tiles overriding the can-move check. - if (unit_walktoxy(src, src->x + skill_lv * mask[dir][0], src->y + skill_lv * mask[dir][1], 2) && md) - md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the ai. + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) + || (tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_ROGUE) //Rogue's spirit defends againt dispel. + || rnd()%100 >= 50+10*skill_lv ) + { + if (sd) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + if(status_isimmune(bl) || !tsc || !tsc->count) + break; + + if( sd && dstsd && !map_flag_vs(sd->bl.m) && sd->status.guild_id == dstsd->status.guild_id ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + + for(i = 0; i < SC_MAX; i++) + { + if ( !tsc->data[i] ) + continue; + if( SC_COMMON_MAX < i ){ + if ( status_get_sc_type(i)&SC_NO_DISPELL ) + continue; + } + switch (i) { + /** + * bugreport:4888 these songs may only be dispelled if you're not in their song area anymore + **/ + case SC_WHISTLE: + case SC_ASSNCROS: + case SC_POEMBRAGI: + case SC_APPLEIDUN: + case SC_HUMMING: + case SC_DONTFORGETME: + case SC_FORTUNE: + case SC_SERVICEFORYOU: + if( tsc->data[i]->val4 ) //val4 = out-of-song-area + continue; + break; + case SC_ASSUMPTIO: + if( bl->type == BL_MOB ) + continue; + break; + case SC_BERSERK: + case SC_SATURDAY_NIGHT_FEVER: + tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. + break; + } + status_change_end(bl, (sc_type)i, INVALID_TIMER); + } + break; } + //Affect all targets on splash area. + iMap->foreachinrange(skill->area_sub, bl, i, BL_CHAR, + src, skill_id, skill_lv, tick, flag|1, + skill->castend_damage_id); break; - case NPC_TRANSFORMATION: - case NPC_METAMORPHOSIS: - if(md && md->skill_idx >= 0) { - int class_ = mob_random_class (md->db->skill[md->skill_idx].val,0); - if (skill_lv > 1) //Multiply the rest of mobs. [Skotlex] - mob_summonslave(md,md->db->skill[md->skill_idx].val,skill_lv-1,skill_id); - if (class_) mob_class_change(md, class_); - } + case TF_BACKSLIDING: //This is the correct implementation as per packet logging information. [Skotlex] + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),unit_getdir(bl),0); break; - case NPC_EMOTION_ON: - case NPC_EMOTION: - //val[0] is the emotion to use. - //NPC_EMOTION & NPC_EMOTION_ON can change a mob's mode 'permanently' [Skotlex] - //val[1] 'sets' the mode - //val[2] adds to the current mode - //val[3] removes from the current mode - //val[4] if set, asks to delete the previous mode change. - if(md && md->skill_idx >= 0 && tsc) { - clif->emotion(bl, md->db->skill[md->skill_idx].val[0]); - if(md->db->skill[md->skill_idx].val[4] && tsce) - status_change_end(bl, type, INVALID_TIMER); + case TK_HIGHJUMP: + { + int x,y, dir = unit_getdir(src); - //If mode gets set by NPC_EMOTION then the target should be reset [Playtester] - if(skill_id == NPC_EMOTION && md->db->skill[md->skill_idx].val[1]) - mob_unlocktarget(md,tick); - - if(md->db->skill[md->skill_idx].val[1] || md->db->skill[md->skill_idx].val[2]) - sc_start4(src, type, 100, skill_lv, - md->db->skill[md->skill_idx].val[1], - md->db->skill[md->skill_idx].val[2], - md->db->skill[md->skill_idx].val[3], - skill->get_time(skill_id, skill_lv)); + //Fails on noteleport maps, except for GvG and BG maps [Skotlex] + if( map[src->m].flag.noteleport && + !(map[src->m].flag.battleground || map_flag_gvg2(src->m) ) + ) { + x = src->x; + y = src->y; + } else { + x = src->x + dirx[dir]*skill_lv*2; + y = src->y + diry[dir]*skill_lv*2; + } + + clif->skill_nodamage(src,bl,TK_HIGHJUMP,skill_lv,1); + if(!iMap->count_oncell(src->m,x,y,BL_PC|BL_NPC|BL_MOB) && iMap->getcell(src->m,x,y,CELL_CHKREACH)) { + clif->slide(src,x,y); + unit_movepos(src, x, y, 1, 0); + } } break; - case NPC_POWERUP: - sc_start(bl,SC_INCATKRATE,100,200,skill->get_time(skill_id, skill_lv)); - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,100,skill->get_time(skill_id, skill_lv))); + case SA_CASTCANCEL: + case SO_SPELLFIST: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + unit_skillcastcancel(src,1); + if(sd) { + int sp = skill->get_sp(sd->skill_id_old,sd->skill_lv_old); + if( skill_id == SO_SPELLFIST ){ + sc_start4(src,type,100,skill_lv+1,skill_lv,sd->skill_id_old,sd->skill_lv_old,skill->get_time(skill_id,skill_lv)); + sd->skill_id_old = sd->skill_lv_old = 0; + break; + } + sp = sp * (90 - (skill_lv-1)*20) / 100; + if(sp < 0) sp = 0; + status_zap(src, 0, sp); + } break; + case SA_SPELLBREAKER: + { + int sp; + if(tsc && tsc->data[SC_MAGICROD]) { + sp = skill->get_sp(skill_id,skill_lv); + sp = sp * tsc->data[SC_MAGICROD]->val2 / 100; + if(sp < 1) sp = 1; + status_heal(bl,0,sp,2); + status_percent_damage(bl, src, 0, -20, false); //20% max SP damage. + } else { + struct unit_data *ud = unit_bl2ud(bl); + int bl_skill_id=0,bl_skill_lv=0,hp = 0; + if (!ud || ud->skilltimer == INVALID_TIMER) + break; //Nothing to cancel. + bl_skill_id = ud->skill_id; + bl_skill_lv = ud->skill_lv; + if (tstatus->mode & MD_BOSS) + { //Only 10% success chance against bosses. [Skotlex] + if (rnd()%100 < 90) + { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + } else if (!dstsd || map_flag_vs(bl->m)) //HP damage only on pvp-maps when against players. + hp = tstatus->max_hp/50; //Recover 2% HP [Skotlex] - case NPC_AGIUP: - sc_start(bl,SC_SPEEDUP1,100,skill_lv,skill->get_time(skill_id, skill_lv)); - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,100,skill->get_time(skill_id, skill_lv))); - break; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + unit_skillcastcancel(bl,0); + sp = skill->get_sp(bl_skill_id,bl_skill_lv); + status_zap(bl, hp, sp); - case NPC_INVISIBLE: - //Have val4 passed as 6 is for "infinite cloak" (do not end on attack/skill use). - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,0,0,6,skill->get_time(skill_id,skill_lv))); - break; + if (hp && skill_lv >= 5) + hp>>=1; //Recover half damaged HP at level 5 [Skotlex] + else + hp = 0; - case NPC_SIEGEMODE: - // not sure what it does - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - break; + if (sp) //Recover some of the SP used + sp = sp*(25*(skill_lv-1))/100; - case WE_MALE: - { - int hp_rate=(!skill_lv)? 0:skill_db[skill_id].hp_rate[skill_lv-1]; - int gain_hp= tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it costed the caster. [Skotlex] - clif->skill_nodamage(src,bl,skill_id,status_heal(bl, gain_hp, 0, 0),1); + if(hp || sp) + status_heal(src, hp, sp, 2); + } } break; - case WE_FEMALE: - { - int sp_rate=(!skill_lv)? 0:skill_db[skill_id].sp_rate[skill_lv-1]; - int gain_sp=tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it costed the caster. [Skotlex] - clif->skill_nodamage(src,bl,skill_id,status_heal(bl, 0, gain_sp, 0),1); - } + case SA_MAGICROD: + clif->skill_nodamage(src,src,SA_MAGICROD,skill_lv,1); + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); break; - - // parent-baby skills - case WE_BABY: - if(sd){ - struct map_session_data *f_sd = pc->get_father(sd); - struct map_session_data *m_sd = pc->get_mother(sd); - // if neither was found - if(!f_sd && !m_sd){ - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 0; + case SA_AUTOSPELL: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if(sd) + clif->autospell(sd,skill_lv); + else { + int maxlv=1,spellid=0; + static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT }; + if(skill_lv >= 10) { + spellid = MG_FROSTDIVER; + // if (tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SA_SAGE) + // maxlv = 10; + // else + maxlv = skill_lv - 9; } - status_change_start(bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8); - if (f_sd) sc_start(&f_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - if (m_sd) sc_start(&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - } - break; - - case PF_HPCONVERSION: - { - int hp, sp; - hp = sstatus->max_hp/10; - sp = hp * 10 * skill_lv / 100; - if (!status_charge(src,hp,0)) { - if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + else if(skill_lv >=8) { + spellid = MG_FIREBALL; + maxlv = skill_lv - 7; } - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - status_heal(bl,0,sp,2); + else if(skill_lv >=5) { + spellid = MG_SOULSTRIKE; + maxlv = skill_lv - 4; + } + else if(skill_lv >=2) { + int i = rnd()%3; + spellid = spellarray[i]; + maxlv = skill_lv - 1; + } + else if(skill_lv > 0) { + spellid = MG_NAPALMBEAT; + maxlv = 3; + } + if(spellid > 0) + sc_start4(src,SC_AUTOSPELL,100,skill_lv,spellid,maxlv,0, + skill->get_time(SA_AUTOSPELL,skill_lv)); } break; - case MA_REMOVETRAP: - case HT_REMOVETRAP: - { - struct skill_unit* su; - struct skill_unit_group* sg; - su = BL_CAST(BL_SKILL, bl); - - // Mercenaries can remove any trap - // Players can only remove their own traps or traps on Vs maps. - if( su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && (skill->get_inf2(sg->skill_id)&INF2_TRAP) ) - { - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) - { // prevent picking up expired traps - if( battle_config.skill_removetrap_type ) - { // get back all items used to deploy the trap - for( i = 0; i < 10; i++ ) - { - if( skill_db[su->group->skill_id].itemid[i] > 0 ) - { - int flag; - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = skill_db[su->group->skill_id].itemid[i]; - item_tmp.identify = 1; - if( item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) ) - { - clif->additem(sd,0,0,flag); - iMap->addflooritem(&item_tmp,skill_db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - } - } - else - { // get back 1 trap - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP; - item_tmp.identify = 1; - if( item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) ) - { - clif->additem(sd,0,0,flag); - iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); - } - } - } - skill->delunit(su); - }else if(sd) - clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - + case BS_GREED: + if(sd){ + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->greed,bl, + skill->get_splash(skill_id, skill_lv),BL_ITEM,bl); } break; - case HT_SPRINGTRAP: + + case SA_ELEMENTWATER: + case SA_ELEMENTFIRE: + case SA_ELEMENTGROUND: + case SA_ELEMENTWIND: + if(sd && !dstmd) //Only works on monsters. + break; + if(tstatus->mode&MD_BOSS) + break; + case NPC_ATTRICHANGE: + case NPC_CHANGEWATER: + case NPC_CHANGEGROUND: + case NPC_CHANGEFIRE: + case NPC_CHANGEWIND: + case NPC_CHANGEPOISON: + case NPC_CHANGEHOLY: + case NPC_CHANGEDARKNESS: + case NPC_CHANGETELEKINESIS: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv), + skill->get_time(skill_id, skill_lv))); + break; + case NPC_CHANGEUNDEAD: + //This skill should fail if target is wearing bathory/evil druid card [Brainstorm] + //TO-DO This is ugly, fix it + if(tstatus->def_ele==ELE_UNDEAD || tstatus->def_ele==ELE_DARK) break; + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv), + skill->get_time(skill_id, skill_lv))); + break; + + case NPC_PROVOCATION: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (md) mob_unlocktarget(md, tick); + break; + + case NPC_KEEPING: + case NPC_BARRIER: { - struct skill_unit *su=NULL; - if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){ - switch(su->group->unit_id){ - case UNT_ANKLESNARE: // ankle snare - if (su->group->val2 != 0) - // if it is already trapping something don't spring it, - // remove trap should be used instead - break; - // otherwise fallthrough to below - case UNT_BLASTMINE: - case UNT_SKIDTRAP: - case UNT_LANDMINE: - case UNT_SHOCKWAVE: - case UNT_SANDMAN: - case UNT_FLASHER: - case UNT_FREEZINGTRAP: - case UNT_CLAYMORETRAP: - case UNT_TALKIEBOX: - su->group->unit_id = UNT_USED_TRAPS; - clif->changetraplook(bl, UNT_USED_TRAPS); - su->group->limit=DIFF_TICK(tick+1500,su->group->tick); - su->limit=DIFF_TICK(tick+1500,su->group->tick); - } + int skill_time = skill->get_time(skill_id,skill_lv); + struct unit_data *ud = unit_bl2ud(bl); + if (clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill_time)) + && ud) { //Disable attacking/acting/moving for skill's duration. + ud->attackabletime = + ud->canact_tick = + ud->canmove_tick = tick + skill_time; } } break; - case BD_ENCORE: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if(sd) - unit_skilluse_id(src,src->id,sd->skill_id_dance,sd->skill_lv_dance); + + case NPC_REBIRTH: + if( md && md->state.rebirth ) + break; // only works once + sc_start(bl,type,100,skill_lv,-1); break; - case AS_SPLASHER: - if(tstatus->mode&MD_BOSS - /** - * Renewal dropped the 3/4 hp requirement - **/ - #ifndef RENEWAL - || tstatus-> hp > tstatus->max_hp*3/4 - #endif - ) { - if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 1; - } + case NPC_DARKBLESSING: clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000)); - #ifndef RENEWAL - if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000, false); - #endif + sc_start2(bl,type,(50+skill_lv*5),skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv))); break; - case PF_MINDBREAKER: - { - if(tstatus->mode&MD_BOSS || battle->check_undead(tstatus->race,tstatus->def_ele) ) { - iMap->freeblock_unlock(); - return 1; - } - - if (tsce) - { //HelloKitty2 (?) explained that this silently fails when target is - //already inflicted. [Skotlex] - iMap->freeblock_unlock(); - return 1; - } + case NPC_LICK: + status_zap(bl, 0, 100); + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,(skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv))); + break; - //Has a 55% + skill_lv*5% success chance. - if (!clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,55+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)))) - { - if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); - return 0; - } + case NPC_SUICIDE: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_kill(src); //When suiciding, neither exp nor drops is given. + break; - unit_skillcastcancel(bl,0); + case NPC_SUMMONSLAVE: + case NPC_SUMMONMONSTER: + if(md && md->skill_idx >= 0) + mob_summonslave(md,md->db->skill[md->skill_idx].val,skill_lv,skill_id); + break; - if(tsc && tsc->count){ - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - if(tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE) - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - } + case NPC_CALLSLAVE: + mob_warpslave(src,MOB_SLAVEDISTANCE); + break; - if(dstmd) - mob_target(dstmd,src,skill->get_range2(src,skill_id,skill_lv)); + case NPC_RANDOMMOVE: + if (md) { + md->next_walktime = tick - 1; + mob_randomwalk(md,tick); } break; - case PF_SOULCHANGE: + case NPC_SPEEDUP: { - unsigned int sp1 = 0, sp2 = 0; - if (dstmd) { - if (dstmd->state.soul_change_flag) { - if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - dstmd->state.soul_change_flag = 1; - sp2 = sstatus->max_sp * 3 /100; - status_heal(src, 0, sp2, 2); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - } - sp1 = sstatus->sp; - sp2 = tstatus->sp; - #ifdef RENEWAL - sp1 = sp1 / 2; - sp2 = sp2 / 2; - if( tsc && tsc->data[SC_EXTREMITYFIST2] ) - sp1 = tstatus->sp; - #endif - status_set_sp(src, sp2, 3); - status_set_sp(bl, sp1, 3); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + // or does it increase casting rate? just a guess xD + int i = SC_ATTHASTE_POTION1 + skill_lv - 1; + if (i > SC_ATTHASTE_INFINITY) + i = SC_ATTHASTE_INFINITY; + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,(sc_type)i,100,skill_lv,skill_lv * 60000)); } break; - // Slim Pitcher - case CR_SLIMPITCHER: - // Updated to block Slim Pitcher from working on barricades and guardian stones. - if( dstmd && (dstmd->class_ == MOBID_EMPERIUM || (dstmd->class_ >= MOBID_BARRICADE1 && dstmd->class_ <= MOBID_GUARIDAN_STONE2)) ) - break; - if (potion_hp || potion_sp) { - int hp = potion_hp, sp = potion_sp; - hp = hp * (100 + (tstatus->vit<<1))/100; - sp = sp * (100 + (tstatus->int_<<1))/100; - if (dstsd) { - if (hp) - hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10 + pc->skillheal2_bonus(dstsd, skill_id))/100; - if (sp) - sp = sp * (100 + pc->checkskill(dstsd,MG_SRECOVERY)*10 + pc->skillheal2_bonus(dstsd, skill_id))/100; - } - if( tsc && tsc->count ) { - if (tsc->data[SC_CRITICALWOUND]) { - hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - } - if (tsc->data[SC_DEATHHURT]) { - hp -= hp * 20 / 100; - sp -= sp * 20 / 100; - } - if( tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2) { - hp += hp / 10; - sp += sp / 10; - } - } - if(hp > 0) - clif->skill_nodamage(NULL,bl,AL_HEAL,hp,1); - if(sp > 0) - clif->skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); - status_heal(bl,hp,sp,0); + case NPC_REVENGE: + // not really needed... but adding here anyway ^^ + if (md && md->master_id > 0) { + struct block_list *mbl, *tbl; + if ((mbl = iMap->id2bl(md->master_id)) == NULL || + (tbl = battle->get_targeted(mbl)) == NULL) + break; + md->state.provoke_flag = tbl->id; + mob_target(md, tbl, sstatus->rhw.range); } break; - // Full Chemical Protection - case CR_FULLPROTECTION: - { - unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; - int i, s = 0, skilltime = skill->get_time(skill_id,skill_lv); - for (i=0 ; i<4; i++) { - if( bl->type != BL_PC || ( dstsd && pc->checkequip(dstsd,equip[i]) < 0 ) ) - continue; - sc_start(bl,(sc_type)(SC_CP_WEAPON + i),100,skill_lv,skilltime); - s++; - } - if( sd && !s ){ - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - iMap->freeblock_unlock(); // Don't consume item requirements - return 0; - } - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + case NPC_RUN: + { + const int mask[8][2] = {{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}}; + uint8 dir = (bl == src)?unit_getdir(src):iMap->calc_dir(src,bl->x,bl->y); //If cast on self, run forward, else run away. + unit_stop_attack(src); + //Run skillv tiles overriding the can-move check. + if (unit_walktoxy(src, src->x + skill_lv * mask[dir][0], src->y + skill_lv * mask[dir][1], 2) && md) + md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the ai. } break; - case RG_CLEANER: //AppleGirl - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - - case CG_LONGINGFREEDOM: - { - if (tsc && !tsce && (tsce=tsc->data[SC_DANCING]) && tsce->val4 - && (tsce->val1&0xFFFF) != CG_MOONLIT) //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex] - { - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - } + case NPC_TRANSFORMATION: + case NPC_METAMORPHOSIS: + if(md && md->skill_idx >= 0) { + int class_ = mob_random_class (md->db->skill[md->skill_idx].val,0); + if (skill_lv > 1) //Multiply the rest of mobs. [Skotlex] + mob_summonslave(md,md->db->skill[md->skill_idx].val,skill_lv-1,skill_id); + if (class_) mob_class_change(md, class_); } break; - case CG_TAROTCARD: - { - int eff, count = -1; - if( rnd() % 100 > skill_lv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPERIUM) || mob_is_battleground(dstmd))) ) - { - if( sd ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + case NPC_EMOTION_ON: + case NPC_EMOTION: + //val[0] is the emotion to use. + //NPC_EMOTION & NPC_EMOTION_ON can change a mob's mode 'permanently' [Skotlex] + //val[1] 'sets' the mode + //val[2] adds to the current mode + //val[3] removes from the current mode + //val[4] if set, asks to delete the previous mode change. + if(md && md->skill_idx >= 0 && tsc) { + clif->emotion(bl, md->db->skill[md->skill_idx].val[0]); + if(md->db->skill[md->skill_idx].val[4] && tsce) + status_change_end(bl, type, INVALID_TIMER); - iMap->freeblock_unlock(); - return 0; - } - status_zap(src,0,skill_db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish] - do { - eff = rnd() % 14; - clif->specialeffect(bl, 523 + eff, AREA); - switch (eff) - { - case 0: // heals SP to 0 - status_percent_damage(src, bl, 0, 100, false); - break; - case 1: // matk halved - sc_start(bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); - break; - case 2: // all buffs removed - status_change_clear_buffs(bl,1); - break; - case 3: // 1000 damage, random armor destroyed - { - status_fix_damage(src, bl, 1000, 0); - clif->damage(src,bl,tick,0,0,1000,0,0,0); - if( !status_isdead(bl) ) { - int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; - skill->break_equip(bl, where[rnd()%5], 10000, BCT_ENEMY); - } - } - break; - case 4: // atk halved - sc_start(bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); - break; - case 5: // 2000HP heal, random teleported - status_heal(src, 2000, 0, 0); - if( !map_flag_vs(bl->m) ) - unit_warp(bl, -1,-1,-1, CLR_TELEPORT); - break; - case 6: // random 2 other effects - if (count == -1) - count = 3; - else - count++; //Should not retrigger this one. - break; - case 7: // stop freeze or stoned - { - enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE }; - sc_start(bl,sc[rnd()%3],100,skill_lv,skill->get_time2(skill_id,skill_lv)); - } - break; - case 8: // curse coma and poison - sc_start(bl,SC_COMA,100,skill_lv,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_POISON,100,skill_lv,skill->get_time2(skill_id,skill_lv)); - break; - case 9: // confusion - sc_start(bl,SC_CONFUSION,100,skill_lv,skill->get_time2(skill_id,skill_lv)); - break; - case 10: // 6666 damage, atk matk halved, cursed - status_fix_damage(src, bl, 6666, 0); - clif->damage(src,bl,tick,0,0,6666,0,0,0); - sc_start(bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_CURSE,skill_lv,100,skill->get_time2(skill_id,skill_lv)); - break; - case 11: // 4444 damage - status_fix_damage(src, bl, 4444, 0); - clif->damage(src,bl,tick,0,0,4444,0,0,0); - break; - case 12: // stun - sc_start(bl,SC_STUN,100,skill_lv,5000); - break; - case 13: // atk,matk,hit,flee,def reduced - sc_start(bl,SC_INCATKRATE,100,-20,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCMATKRATE,100,-20,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCHITRATE,100,-20,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCFLEERATE,100,-20,skill->get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCDEFRATE,100,-20,skill->get_time2(skill_id,skill_lv)); - break; - default: - break; - } - } while ((--count) > 0); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + //If mode gets set by NPC_EMOTION then the target should be reset [Playtester] + if(skill_id == NPC_EMOTION && md->db->skill[md->skill_idx].val[1]) + mob_unlocktarget(md,tick); + + if(md->db->skill[md->skill_idx].val[1] || md->db->skill[md->skill_idx].val[2]) + sc_start4(src, type, 100, skill_lv, + md->db->skill[md->skill_idx].val[1], + md->db->skill[md->skill_idx].val[2], + md->db->skill[md->skill_idx].val[3], + skill->get_time(skill_id, skill_lv)); } break; - case SL_ALCHEMIST: - case SL_ASSASIN: - case SL_BARDDANCER: - case SL_BLACKSMITH: - case SL_CRUSADER: - case SL_HUNTER: - case SL_KNIGHT: - case SL_MONK: - case SL_PRIEST: - case SL_ROGUE: - case SL_SAGE: - case SL_SOULLINKER: - case SL_STAR: - case SL_SUPERNOVICE: - case SL_WIZARD: - //NOTE: here, 'type' has the value of the associated MAPID, not of the SC_SPIRIT constant. - if (sd && !(dstsd && (dstsd->class_&MAPID_UPPERMASK) == type)) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - if (skill_id == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rnd()%100)) - { //Erase death count 1% of the casts - dstsd->die_counter = 0; - pc_setglobalreg(dstsd,"PC_DIE_COUNTER", 0); - clif->specialeffect(bl, 0x152, AREA); - //SC_SPIRIT invokes status_calc_pc for us. - } + case NPC_POWERUP: + sc_start(bl,SC_INCATKRATE,100,200,skill->get_time(skill_id, skill_lv)); clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,SC_SPIRIT,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv))); - sc_start(src,SC_SMA,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); + sc_start(bl,type,100,100,skill->get_time(skill_id, skill_lv))); break; - case SL_HIGH: - if (sd && !(dstsd && (dstsd->class_&JOBL_UPPER) && !(dstsd->class_&JOBL_2) && dstsd->status.base_level < 70)) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } + + case NPC_AGIUP: + sc_start(bl,SC_MOVHASTE_INFINITY,100,skill_lv,skill->get_time(skill_id, skill_lv)); clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv))); - sc_start(src,SC_SMA,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); + sc_start(bl,type,100,100,skill->get_time(skill_id, skill_lv))); break; - case SL_SWOO: - if (tsce) { - if(sd) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,10000,8); - status_change_end(bl, SC_SWOO, INVALID_TIMER); - break; - } - case SL_SKA: // [marquis007] - case SL_SKE: - if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,10); - break; - } - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - if (skill_id == SL_SKE) - sc_start(src,SC_SMA,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); + case NPC_INVISIBLE: + //Have val4 passed as 6 is for "infinite cloak" (do not end on attack/skill use). + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,type,100,skill_lv,0,0,6,skill->get_time(skill_id,skill_lv))); break; - // New guild skills [Celest] - case GD_BATTLEORDER: - if(flag&1) { - if (status_get_guild_id(src) == status_get_guild_id(bl)) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)); - } else if (status_get_guild_id(src)) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->area_sub, src, - skill->get_splash(skill_id, skill_lv), BL_PC, - src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, - skill->castend_nodamage_id); - if (sd) - guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); + case NPC_SIEGEMODE: + // not sure what it does + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + + case WE_MALE: + { + int hp_rate=(!skill_lv)? 0:skill_db[skill_id].hp_rate[skill_lv-1]; + int gain_hp= tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it costed the caster. [Skotlex] + clif->skill_nodamage(src,bl,skill_id,status_heal(bl, gain_hp, 0, 0),1); } break; - case GD_REGENERATION: - if(flag&1) { - if (status_get_guild_id(src) == status_get_guild_id(bl)) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)); - } else if (status_get_guild_id(src)) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->area_sub, src, - skill->get_splash(skill_id, skill_lv), BL_PC, - src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, - skill->castend_nodamage_id); - if (sd) - guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); + case WE_FEMALE: + { + int sp_rate=(!skill_lv)? 0:skill_db[skill_id].sp_rate[skill_lv-1]; + int gain_sp=tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it costed the caster. [Skotlex] + clif->skill_nodamage(src,bl,skill_id,status_heal(bl, 0, gain_sp, 0),1); } break; - case GD_RESTORE: - if(flag&1) { - if (status_get_guild_id(src) == status_get_guild_id(bl)) - clif->skill_nodamage(src,bl,AL_HEAL,status_percent_heal(bl,90,90),1); - } else if (status_get_guild_id(src)) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->area_sub, src, - skill->get_splash(skill_id, skill_lv), BL_PC, - src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, - skill->castend_nodamage_id); - if (sd) - guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); + + // parent-baby skills + case WE_BABY: + if(sd){ + struct map_session_data *f_sd = pc->get_father(sd); + struct map_session_data *m_sd = pc->get_mother(sd); + // if neither was found + if(!f_sd && !m_sd){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 0; + } + status_change_start(bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8); + if (f_sd) sc_start(&f_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + if (m_sd) sc_start(&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); } break; - case GD_EMERGENCYCALL: + + case PF_HPCONVERSION: { - int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0}; - int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0}; - int j = 0; - struct guild *g; - // i don't know if it actually summons in a circle, but oh well. ;P - g = sd?sd->state.gmaster_flag:guild->search(status_get_guild_id(src)); - if (!g) + int hp, sp; + hp = sstatus->max_hp/10; + sp = hp * 10 * skill_lv / 100; + if (!status_charge(src,hp,0)) { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - for(i = 0; i < g->max_member; i++, j++) { - if (j>8) j=0; - if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) { - if (map[dstsd->bl.m].flag.nowarp && !map_flag_gvg2(dstsd->bl.m)) - continue; - if(iMap->getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH)) - dx[j] = dy[j] = 0; - pc->setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN); - } } - if (sd) - guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + status_heal(bl,0,sp,2); } break; - case SG_FEEL: - //AuronX reported you CAN memorize the same map as all three. [Skotlex] - if (sd) { - if(!sd->feel_map[skill_lv-1].index) - clif->feel_req(sd->fd,sd, skill_lv); - else - clif->feel_info(sd, skill_lv-1, 1); + case MA_REMOVETRAP: + case HT_REMOVETRAP: + { + struct skill_unit* su; + struct skill_unit_group* sg; + su = BL_CAST(BL_SKILL, bl); + + // Mercenaries can remove any trap + // Players can only remove their own traps or traps on Vs maps. + if( su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && (skill->get_inf2(sg->skill_id)&INF2_TRAP) ) + { + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) + { // prevent picking up expired traps + if( battle_config.skill_removetrap_type ) + { // get back all items used to deploy the trap + for( i = 0; i < 10; i++ ) + { + if( skill_db[su->group->skill_id].itemid[i] > 0 ) + { + int flag; + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = skill_db[su->group->skill_id].itemid[i]; + item_tmp.identify = 1; + if( item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) ) + { + clif->additem(sd,0,0,flag); + iMap->addflooritem(&item_tmp,skill_db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + } + } + else + { // get back 1 trap + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP; + item_tmp.identify = 1; + if( item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) ) + { + clif->additem(sd,0,0,flag); + iMap->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + } + skill->delunit(su); + }else if(sd) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + } break; - - case SG_HATE: - if (sd) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if (!pc->set_hate_mob(sd, skill_lv-1, bl)) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + case HT_SPRINGTRAP: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + { + struct skill_unit *su=NULL; + if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){ + switch(su->group->unit_id){ + case UNT_ANKLESNARE: // ankle snare + if (su->group->val2 != 0) + // if it is already trapping something don't spring it, + // remove trap should be used instead + break; + // otherwise fallthrough to below + case UNT_BLASTMINE: + case UNT_SKIDTRAP: + case UNT_LANDMINE: + case UNT_SHOCKWAVE: + case UNT_SANDMAN: + case UNT_FLASHER: + case UNT_FREEZINGTRAP: + case UNT_CLAYMORETRAP: + case UNT_TALKIEBOX: + su->group->unit_id = UNT_USED_TRAPS; + clif->changetraplook(bl, UNT_USED_TRAPS); + su->group->limit=DIFF_TICK(tick+1500,su->group->tick); + su->limit=DIFF_TICK(tick+1500,su->group->tick); + } + } } break; + case BD_ENCORE: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if(sd) + unit_skilluse_id(src,src->id,sd->skill_id_dance,sd->skill_lv_dance); + break; - case GS_GLITTERING: - if(sd) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if(rnd()%100 < (20+10*skill_lv)) - pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),10); - else if(sd->spiritball > 0) - pc->delspiritball(sd,1,0); + case AS_SPLASHER: + if(tstatus->mode&MD_BOSS + /** + * Renewal dropped the 3/4 hp requirement + **/ + #ifndef RENEWAL + || tstatus-> hp > tstatus->max_hp*3/4 + #endif + ) { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 1; } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000)); + #ifndef RENEWAL + if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000, false); + #endif break; - case GS_CRACKER: - /* per official standards, this skill works on players and mobs. */ - if (sd && (dstsd || dstmd)) + case PF_MINDBREAKER: { - i =65 -5*distance_bl(src,bl); //Base rate - if (i < 30) i = 30; - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - sc_start(bl,SC_STUN, i,skill_lv,skill->get_time2(skill_id,skill_lv)); - } - break; + if(tstatus->mode&MD_BOSS || battle->check_undead(tstatus->race,tstatus->def_ele) ) { + iMap->freeblock_unlock(); + return 1; + } - case AM_CALLHOMUN: //[orn] - if (sd && homun->call(sd)) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + if (tsce) + { //HelloKitty2 (?) explained that this silently fails when target is + //already inflicted. [Skotlex] + iMap->freeblock_unlock(); + return 1; + } - case AM_REST: - if (sd) { - if (homun->vaporize(sd,1)) - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - else - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + //Has a 55% + skill_lv*5% success chance. + if (!clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,55+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)))) + { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 0; + } + + unit_skillcastcancel(bl,0); + + if(tsc && tsc->count){ + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + if(tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE) + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + } + + if(dstmd) + mob_target(dstmd,src,skill->get_range2(src,skill_id,skill_lv)); } break; - case HAMI_CASTLE: //[orn] - if(rnd()%100 < 20*skill_lv && src != bl) + case PF_SOULCHANGE: { - int x,y; - x = src->x; - y = src->y; - if (hd) - skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv)); - - if (unit_movepos(src,bl->x,bl->y,0,0)) { - clif->skill_nodamage(src,src,skill_id,skill_lv,1); // Homunc - clif->slide(src,bl->x,bl->y) ; - if (unit_movepos(bl,x,y,0,0)) - { - clif->skill_nodamage(bl,bl,skill_id,skill_lv,1); // Master - clif->slide(bl,x,y) ; + unsigned int sp1 = 0, sp2 = 0; + if (dstmd) { + if (dstmd->state.soul_change_flag) { + if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; } + dstmd->state.soul_change_flag = 1; + sp2 = sstatus->max_sp * 3 /100; + status_heal(src, 0, sp2, 2); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + } + sp1 = sstatus->sp; + sp2 = tstatus->sp; + #ifdef RENEWAL + sp1 = sp1 / 2; + sp2 = sp2 / 2; + if( tsc && tsc->data[SC_EXTREMITYFIST2] ) + sp1 = tstatus->sp; + #endif + status_set_sp(src, sp2, 3); + status_set_sp(bl, sp1, 3); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - //TODO: Shouldn't also players and the like switch targets? - iMap->foreachinrange(skill->chastle_mob_changetarget,src, - AREA_SIZE, BL_MOB, bl, src); + // Slim Pitcher + case CR_SLIMPITCHER: + // Updated to block Slim Pitcher from working on barricades and guardian stones. + if( dstmd && (dstmd->class_ == MOBID_EMPERIUM || (dstmd->class_ >= MOBID_BARRICADE1 && dstmd->class_ <= MOBID_GUARIDAN_STONE2)) ) + break; + if (potion_hp || potion_sp) { + int hp = potion_hp, sp = potion_sp; + hp = hp * (100 + (tstatus->vit<<1))/100; + sp = sp * (100 + (tstatus->int_<<1))/100; + if (dstsd) { + if (hp) + hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10 + pc->skillheal2_bonus(dstsd, skill_id))/100; + if (sp) + sp = sp * (100 + pc->checkskill(dstsd,MG_SRECOVERY)*10 + pc->skillheal2_bonus(dstsd, skill_id))/100; + } + if( tsc && tsc->count ) { + if (tsc->data[SC_CRITICALWOUND]) { + hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + } + if (tsc->data[SC_DEATHHURT]) { + hp -= hp * 20 / 100; + sp -= sp * 20 / 100; + } + if( tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2) { + hp += hp / 10; + sp += sp / 10; + } } + if(hp > 0) + clif->skill_nodamage(NULL,bl,AL_HEAL,hp,1); + if(sp > 0) + clif->skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); + status_heal(bl,hp,sp,0); } - // Failed - else if (hd && hd->master) - clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_LEVEL, 0); - else if (sd) - clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); break; - case HVAN_CHAOTIC: //[orn] + // Full Chemical Protection + case CR_FULLPROTECTION: { - static const int per[5][2]={{20,50},{50,60},{25,75},{60,64},{34,67}}; - int r = rnd()%100; - i = (skill_lv-1)%5; - if(rget_master(src); - else //Enemy - bl = iMap->id2bl(battle->get_target(src)); + unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; + int i, s = 0, skilltime = skill->get_time(skill_id,skill_lv); - if (!bl) bl = src; - i = skill->calc_heal(src, bl, skill_id, 1+rnd()%skill_lv, true); - //Eh? why double skill packet? - clif->skill_nodamage(src,bl,AL_HEAL,i,1); - clif->skill_nodamage(src,bl,skill_id,i,1); - status_heal(bl, i, 0, 0); + for (i=0 ; i<4; i++) { + if( bl->type != BL_PC || ( dstsd && pc->checkequip(dstsd,equip[i]) < 0 ) ) + continue; + sc_start(bl,(sc_type)(SC_PROTECTWEAPON + i),100,skill_lv,skilltime); + s++; + } + if( sd && !s ){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); // Don't consume item requirements + return 0; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } break; - //Homun single-target support skills [orn] - case HAMI_BLOODLUST: - case HFLI_FLEET: - case HFLI_SPEED: - case HLIF_CHANGE: - case MH_ANGRIFFS_MODUS: - case MH_GOLDENE_FERSE: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - if (hd) - skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv)); + + case RG_CLEANER: //AppleGirl + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; - case NPC_DRAGONFEAR: - if (flag&1) { - const enum sc_type sc[] = { SC_STUN, SC_SILENCE, SC_CONFUSION, SC_BLEEDING }; - int j; - j = i = rnd()%ARRAYLENGTH(sc); - while ( !sc_start2(bl,sc[i],100,skill_lv,src->id,skill->get_time2(skill_id,i+1)) ) { - i++; - if ( i == ARRAYLENGTH(sc) ) - i = 0; - if (i == j) - break; + case CG_LONGINGFREEDOM: + { + if (tsc && !tsce && (tsce=tsc->data[SC_DANCING]) && tsce->val4 + && (tsce->val1&0xFFFF) != CG_MOONLIT) //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex] + { + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); } - break; - } - case NPC_WIDEBLEEDING: - case NPC_WIDECONFUSE: - case NPC_WIDECURSE: - case NPC_WIDEFREEZE: - case NPC_WIDESLEEP: - case NPC_WIDESILENCE: - case NPC_WIDESTONE: - case NPC_WIDESTUN: - case NPC_SLOWCAST: - case NPC_WIDEHELLDIGNITY: - if (flag&1) - sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); - else { - skill_area_temp[2] = 0; //For SD_PREAMBLE - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->area_sub, bl, - skill->get_splash(skill_id, skill_lv),BL_CHAR, - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, - skill->castend_nodamage_id); - } - break; - case NPC_WIDESOULDRAIN: - if (flag&1) - status_percent_damage(src,bl,0,((skill_lv-1)%5+1)*20,false); - else { - skill_area_temp[2] = 0; //For SD_PREAMBLE - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->area_sub, bl, - skill->get_splash(skill_id, skill_lv),BL_CHAR, - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, - skill->castend_nodamage_id); } break; - case ALL_PARTYFLEE: - if( sd && !(flag&1) ) + + case CG_TAROTCARD: { - if( !sd->status.party_id ) + int eff, count = -1; + if( tsc && tsc->data[type] ){ + iMap->freeblock_unlock(); + return 0; + } + if( rnd() % 100 > skill_lv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPERIUM) || mob_is_battleground(dstmd))) ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + + iMap->freeblock_unlock(); + return 0; } - party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + status_zap(src,0,skill_db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish] + do { + eff = rnd() % 14; + if( eff == 5 ) + clif->specialeffect(src, 528, AREA); + else + clif->specialeffect(bl, 523 + eff, AREA); + switch (eff) + { + case 0: // heals SP to 0 + status_percent_damage(src, bl, 0, 100, false); + break; + case 1: // matk halved + sc_start(bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + break; + case 2: // all buffs removed + status_change_clear_buffs(bl,1); + break; + case 3: // 1000 damage, random armor destroyed + { + status_fix_damage(src, bl, 1000, 0); + clif->damage(src,bl,tick,0,0,1000,0,0,0); + if( !status_isdead(bl) ) { + int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; + skill->break_equip(bl, where[rnd()%5], 10000, BCT_ENEMY); + } + } + break; + case 4: // atk halved + sc_start(bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + break; + case 5: // 2000HP heal, random teleported + status_heal(src, 2000, 0, 0); + if( !map_flag_vs(bl->m) ) + unit_warp(bl, -1,-1,-1, CLR_TELEPORT); + break; + case 6: // random 2 other effects + if (count == -1) + count = 3; + else + count++; //Should not retrigger this one. + break; + case 7: // stop freeze or stoned + { + enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE }; + sc_start(bl,sc[rnd()%3],100,skill_lv,skill->get_time2(skill_id,skill_lv)); + } + break; + case 8: // curse coma and poison + sc_start(bl,SC_COMA,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_POISON,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case 9: // confusion + sc_start(bl,SC_CONFUSION,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case 10: // 6666 damage, atk matk halved, cursed + status_fix_damage(src, bl, 6666, 0); + clif->damage(src,bl,tick,0,0,6666,0,0,0); + sc_start(bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_CURSE,skill_lv,100,skill->get_time2(skill_id,skill_lv)); + break; + case 11: // 4444 damage + status_fix_damage(src, bl, 4444, 0); + clif->damage(src,bl,tick,0,0,4444,0,0,0); + break; + case 12: // stun + sc_start(bl,SC_STUN,100,skill_lv,5000); + break; + case 13: // atk,matk,hit,flee,def reduced + sc_start(bl,SC_INCATKRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_INCMATKRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_INCHITRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_INCFLEERATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_INCDEFRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + default: + break; + } + } while ((--count) > 0); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - else - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - break; - case NPC_TALK: - case ALL_WEWISH: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; - case ALL_BUYING_STORE: - if( sd ) - {// players only, skill allows 5 buying slots - clif->skill_nodamage(src, bl, skill_id, skill_lv, buyingstore->setup(sd, MAX_BUYINGSTORE_SLOTS)); + + case SL_ALCHEMIST: + case SL_ASSASIN: + case SL_BARDDANCER: + case SL_BLACKSMITH: + case SL_CRUSADER: + case SL_HUNTER: + case SL_KNIGHT: + case SL_MONK: + case SL_PRIEST: + case SL_ROGUE: + case SL_SAGE: + case SL_SOULLINKER: + case SL_STAR: + case SL_SUPERNOVICE: + case SL_WIZARD: + //NOTE: here, 'type' has the value of the associated MAPID, not of the SC_SOULLINK constant. + if (sd && !(dstsd && (dstsd->class_&MAPID_UPPERMASK) == type)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; } + if (skill_id == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rnd()%100)) + { //Erase death count 1% of the casts + dstsd->die_counter = 0; + pc_setglobalreg(dstsd,"PC_DIE_COUNTER", 0); + clif->specialeffect(bl, 0x152, AREA); + //SC_SOULLINK invokes status_calc_pc for us. + } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,SC_SOULLINK,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv))); + sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); break; - case RK_ENCHANTBLADE: - clif->skill_nodamage(src,bl,skill_id,skill_lv,// formula not confirmed - sc_start2(bl,type,100,skill_lv,100+20*skill_lv/*+sstatus->int_/2+status_get_lv(bl)/10*/,skill->get_time(skill_id,skill_lv))); - break; - case RK_DRAGONHOWLING: - if( flag&1) - sc_start(bl,type,50 + 6 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); - else - { - skill_area_temp[2] = 0; - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->area_sub, src, - skill->get_splash(skill_id,skill_lv),BL_CHAR, - src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|1, - skill->castend_nodamage_id); + case SL_HIGH: + if (sd && !(dstsd && (dstsd->class_&JOBL_UPPER) && !(dstsd->class_&JOBL_2) && dstsd->status.base_level < 70)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,type,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv))); + sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); break; - case RK_IGNITIONBREAK: - case LG_EARTHDRIVE: - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - i = skill->get_splash(skill_id,skill_lv); - if( skill_id == LG_EARTHDRIVE ) { - int dummy = 1; - iMap->foreachinarea(skill->cell_overlap, src->m, src->x-i, src->y-i, src->x+i, src->y+i, BL_SKILL, LG_EARTHDRIVE, &dummy, src); - } - iMap->foreachinrange(skill->area_sub, bl,i,BL_CHAR, - src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); - break; - case RK_STONEHARDSKIN: - if( sd && pc->checkskill(sd,RK_RUNEMASTERY) >= 4 ) - { - int heal = sstatus->hp / 4; // 25% HP - if( status_charge(bl,heal,0) ) - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(bl,type,100,skill_lv,heal,skill->get_time(skill_id,skill_lv))); - else + + case SL_SWOO: + if (tsce) { + if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,10000,8); + status_change_end(bl, SC_SWOO, INVALID_TIMER); + break; } - break; - case RK_REFRESH: - if( sd && pc->checkskill(sd,RK_RUNEMASTERY) >= 8 ) - { - int heal = status_get_max_hp(bl) * 25 / 100; - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - status_heal(bl,heal,0,1); - status_change_clear_buffs(bl,4); + case SL_SKA: // [marquis007] + case SL_SKE: + if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,10); + break; } + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if (skill_id == SL_SKE) + sc_start(src,SC_SMA_READY,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); break; - case RK_MILLENNIUMSHIELD: - if( sd && pc->checkskill(sd,RK_RUNEMASTERY) >= 9 ) - { - short shields = (rnd()%100<50) ? 4 : ((rnd()%100<80) ? 3 : 2); - sc_start4(bl,type,100,skill_lv,shields,1000,0,skill->get_time(skill_id,skill_lv)); - clif->millenniumshield(sd,shields); - clif->skill_nodamage(src,bl,skill_id,1,1); + // New guild skills [Celest] + case GD_BATTLEORDER: + if(flag&1) { + if (status_get_guild_id(src) == status_get_guild_id(bl)) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)); + } else if (status_get_guild_id(src)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->area_sub, src, + skill->get_splash(skill_id, skill_lv), BL_PC, + src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, + skill->castend_nodamage_id); + if (sd) + guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); } break; - - case RK_GIANTGROWTH: - case RK_VITALITYACTIVATION: - case RK_ABUNDANCE: - case RK_CRUSHSTRIKE: - if( sd ) - { - int lv = 1; // RK_GIANTGROWTH - if( skill_id == RK_VITALITYACTIVATION ) - lv = 2; - else if( skill_id == RK_ABUNDANCE ) - lv = 6; - else if( skill_id == RK_CRUSHSTRIKE ) - lv = 7; - if( pc->checkskill(sd,RK_RUNEMASTERY) >= lv ) - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + case GD_REGENERATION: + if(flag&1) { + if (status_get_guild_id(src) == status_get_guild_id(bl)) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)); + } else if (status_get_guild_id(src)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->area_sub, src, + skill->get_splash(skill_id, skill_lv), BL_PC, + src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, + skill->castend_nodamage_id); + if (sd) + guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); } break; - - case RK_FIGHTINGSPIRIT: - if( flag&1 ) { - if( src == bl ) - sc_start2(bl,type,100,skill_area_temp[5],10*(sd?pc->checkskill(sd,RK_RUNEMASTERY):10),skill->get_time(skill_id,skill_lv)); - else - sc_start(bl,type,100,skill_area_temp[5]/4,skill->get_time(skill_id,skill_lv)); - } else if( sd && pc->checkskill(sd,RK_RUNEMASTERY) >= 5 ) { - if( sd->status.party_id ) { - i = party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,BCT_PARTY,skill->area_sub_count); - skill_area_temp[5] = 7 * i; // ATK - party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id); - } else - sc_start2(bl,type,100,7,5,skill->get_time(skill_id,skill_lv)); + case GD_RESTORE: + if(flag&1) { + if (status_get_guild_id(src) == status_get_guild_id(bl)) + clif->skill_nodamage(src,bl,AL_HEAL,status_percent_heal(bl,90,90),1); + } else if (status_get_guild_id(src)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->area_sub, src, + skill->get_splash(skill_id, skill_lv), BL_PC, + src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, + skill->castend_nodamage_id); + if (sd) + guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); } - clif->skill_nodamage(src,bl,skill_id,1,1); break; - /** - * Guilotine Cross - **/ - case GC_ROLLINGCUTTER: + case GD_EMERGENCYCALL: { - short count = 1; - skill_area_temp[2] = 0; - iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|SD_SPLASH|1,skill->castend_damage_id); - if( tsc && tsc->data[SC_ROLLINGCUTTER] ) - { // Every time the skill is casted the status change is reseted adding a counter. - count += (short)tsc->data[SC_ROLLINGCUTTER]->val1; - if( count > 10 ) - count = 10; // Max coounter - status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); + int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0}; + int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0}; + int j = 0; + struct guild *g; + // i don't know if it actually summons in a circle, but oh well. ;P + g = sd?sd->state.gmaster_flag:guild->search(status_get_guild_id(src)); + if (!g) + break; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + for(i = 0; i < g->max_member; i++, j++) { + if (j>8) j=0; + if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) { + if (map[dstsd->bl.m].flag.nowarp && !map_flag_gvg2(dstsd->bl.m)) + continue; + if(iMap->getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH)) + dx[j] = dy[j] = 0; + pc->setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN); + } } - sc_start(bl,SC_ROLLINGCUTTER,100,count,skill->get_time(skill_id,skill_lv)); - clif->skill_nodamage(src,src,skill_id,skill_lv,1); + if (sd) + guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); } break; - case GC_WEAPONBLOCKING: - if( tsc && tsc->data[SC_WEAPONBLOCKING] ) - status_change_end(bl, SC_WEAPONBLOCKING, INVALID_TIMER); - else - sc_start(bl,SC_WEAPONBLOCKING,100,skill_lv,skill->get_time(skill_id,skill_lv)); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - - case GC_CREATENEWPOISON: - if( sd ) - { - clif->skill_produce_mix_list(sd,skill_id,25); - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + case SG_FEEL: + //AuronX reported you CAN memorize the same map as all three. [Skotlex] + if (sd) { + if(!sd->feel_map[skill_lv-1].index) + clif->feel_req(sd->fd,sd, skill_lv); + else + clif->feel_info(sd, skill_lv-1, 1); } break; - case GC_POISONINGWEAPON: - if( sd ) { - clif->poison_list(sd,skill_lv); + case SG_HATE: + if (sd) { clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (!pc->set_hate_mob(sd, skill_lv-1, bl)) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } break; - case GC_ANTIDOTE: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if( tsc ) - { - status_change_end(bl, SC_PARALYSE, INVALID_TIMER); - status_change_end(bl, SC_PYREXIA, INVALID_TIMER); - status_change_end(bl, SC_DEATHHURT, INVALID_TIMER); - status_change_end(bl, SC_LEECHESEND, INVALID_TIMER); - status_change_end(bl, SC_VENOMBLEED, INVALID_TIMER); - status_change_end(bl, SC_MAGICMUSHROOM, INVALID_TIMER); - status_change_end(bl, SC_TOXIN, INVALID_TIMER); - status_change_end(bl, SC_OBLIVIONCURSE, INVALID_TIMER); - } - break; - - case GC_PHANTOMMENACE: - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR, - src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); - break; - - case GC_HALLUCINATIONWALK: - { - int heal = status_get_max_hp(bl) / 10; - if( status_get_hp(bl) < heal ) { // if you haven't enough HP skill fails. - if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); - break; - } - if( !status_charge(bl,heal,0) ) - { - if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); - break; - } - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - } - break; - /** - * Arch Bishop - **/ - case AB_ANCILLA: - if( sd ) { + case GS_GLITTERING: + if(sd) { clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - skill->produce_mix(sd, skill_id, ITEMID_ANCILLA, 0, 0, 0, 1); + if(rnd()%100 < (20+10*skill_lv)) + pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),10); + else if(sd->spiritball > 0) + pc->delspiritball(sd,1,0); } break; - case AB_CLEMENTIA: - case AB_CANTO: + case GS_CRACKER: + /* per official standards, this skill works on players and mobs. */ + if (sd && (dstsd || dstmd)) { - int bless_lv = pc->checkskill(sd,AL_BLESSING) + (sd->status.job_level / 10); - int agi_lv = pc->checkskill(sd,AL_INCAGI) + (sd->status.job_level / 10); - if( sd == NULL || sd->status.party_id == 0 || flag&1 ) - clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100, - (skill_id == AB_CLEMENTIA)? bless_lv : (skill_id == AB_CANTO)? agi_lv : skill_lv, skill->get_time(skill_id,skill_lv))); - else if( sd ) - party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + i =65 -5*distance_bl(src,bl); //Base rate + if (i < 30) i = 30; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + sc_start(bl,SC_STUN, i,skill_lv,skill->get_time2(skill_id,skill_lv)); } break; - case AB_PRAEFATIO: - if( sd == NULL || sd->status.party_id == 0 || flag&1 ) - clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start4(bl, type, 100, skill_lv, 0, 0, 1, skill->get_time(skill_id, skill_lv))); - else if( sd ) - party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + case AM_CALLHOMUN: //[orn] + if (sd && homun->call(sd)) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; - - case AB_CHEAL: - if( sd == NULL || sd->status.party_id == 0 || flag&1 ) { - if( sd && tstatus && !battle->check_undead(tstatus->race, tstatus->def_ele) ) { - i = skill->calc_heal(src, bl, AL_HEAL, pc->checkskill(sd, AL_HEAL), true); - - if( (dstsd && pc_ismadogear(dstsd)) || status_isimmune(bl)) - i = 0; // Should heal by 0 or won't do anything?? in iRO it breaks the healing to members.. [malufett] - - clif->skill_nodamage(bl, bl, skill_id, i, 1); - if( tsc && tsc->data[SC_AKAITSUKI] && i ) - i = ~i + 1; - status_heal(bl, i, 0, 0); - } + + case AM_REST: + if (sd) { + if (homun->vaporize(sd,1)) + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } - else if( sd ) - party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); break; - case AB_ORATIO: - if( flag&1 ) - sc_start(bl, type, 40 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); - else + case HAMI_CASTLE: //[orn] + if(rnd()%100 < 20*skill_lv && src != bl) { - iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + int x,y; + x = src->x; + y = src->y; + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv)); + + if (unit_movepos(src,bl->x,bl->y,0,0)) { + clif->skill_nodamage(src,src,skill_id,skill_lv,1); // Homunc + clif->slide(src,bl->x,bl->y) ; + if (unit_movepos(bl,x,y,0,0)) + { + clif->skill_nodamage(bl,bl,skill_id,skill_lv,1); // Master + clif->slide(bl,x,y) ; + } + + //TODO: Shouldn't also players and the like switch targets? + iMap->foreachinrange(skill->chastle_mob_changetarget,src, + AREA_SIZE, BL_MOB, bl, src); + } } + // Failed + else if (hd && hd->master) + clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_LEVEL, 0); + else if (sd) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); break; + case HVAN_CHAOTIC: //[orn] + { + static const int per[5][2]={{20,50},{50,60},{25,75},{60,64},{34,67}}; + int r = rnd()%100; + i = (skill_lv-1)%5; + if(rget_master(src); + else //Enemy + bl = iMap->id2bl(battle->get_target(src)); - case AB_LAUDAAGNUS: - if( flag&1 || sd == NULL ) { - if( tsc && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE] || tsc->data[SC_BLIND] || - tsc->data[SC_BURNING] || tsc->data[SC_FREEZING] || tsc->data[SC_CRYSTALIZE])) { - // Success Chance: (40 + 10 * Skill Level) % - if( rnd()%100 > 40+10*skill_lv ) break; - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - status_change_end(bl, SC_BURNING, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); - status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); - }else //Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets - clif->skill_nodamage(bl, bl, skill_id, skill_lv, - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); - } else if( sd ) - party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), - src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + if (!bl) bl = src; + i = skill->calc_heal(src, bl, skill_id, 1+rnd()%skill_lv, true); + //Eh? why double skill packet? + clif->skill_nodamage(src,bl,AL_HEAL,i,1); + clif->skill_nodamage(src,bl,skill_id,i,1); + status_heal(bl, i, 0, 0); + } break; - - case AB_LAUDARAMUS: - if( flag&1 || sd == NULL ) { - if( tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] || tsc->data[SC_SILENCE]) ){ - // Success Chance: (40 + 10 * Skill Level) % - if( rnd()%100 > 40+10*skill_lv ) break; - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); - status_change_end(bl, SC_MANDRAGORA, INVALID_TIMER); - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - }else // Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets - clif->skill_nodamage(bl, bl, skill_id, skill_lv, - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); - } else if( sd ) - party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), - src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + //Homun single-target support skills [orn] + case HAMI_BLOODLUST: + case HFLI_FLEET: + case HFLI_SPEED: + case HLIF_CHANGE: + case MH_ANGRIFFS_MODUS: + case MH_GOLDENE_FERSE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv)); break; - case AB_CLEARANCE: - if( flag&1 || (i = skill->get_splash(skill_id, skill_lv)) < 1 ) - { //As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie] - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) || rnd()%100 >= 30 + 10 * skill_lv) - { - if (sd) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - if(status_isimmune(bl) || !tsc || !tsc->count) - break; - for(i=0;idata[i]) - continue; - switch (i) { - case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION: - case SC_STRIPWEAPON: case SC_STRIPSHIELD: case SC_STRIPARMOR: - case SC_STRIPHELM: case SC_CP_WEAPON: case SC_CP_SHIELD: - case SC_CP_ARMOR: case SC_CP_HELM: case SC_COMBO: - case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD: - case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD: - case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD: - case SC_WATKFOOD: case SC_MATKFOOD: case SC_DANCING: - case SC_SPIRIT: case SC_AUTOBERSERK: - case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL: - case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT: - case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED: - case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE: - case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL: - case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN: - case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN: - case SC_READYCOUNTER:case SC_DODGE: case SC_WARM: - case SC_SPEEDUP1: case SC_AUTOTRADE: case SC_CRITICALWOUND: - case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF: - case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF: - case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK: - case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS: - case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL: - case SC_INTOABYSS: case SC_SIEGFRIED: case SC_WHISTLE: - case SC_ASSNCROS: case SC_POEMBRAGI: case SC_APPLEIDUN: - case SC_HUMMING: case SC_DONTFORGETME: case SC_FORTUNE: - case SC_SERVICE4U: case SC_FOOD_STR_CASH: case SC_FOOD_AGI_CASH: - case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: case SC_FOOD_INT_CASH: - case SC_FOOD_LUK_CASH: case SC_ELECTRICSHOCKER: case SC_BITE: - case SC__STRIPACCESSORY: case SC__ENERVATION: case SC__GROOMY: - case SC__IGNORANCE: case SC__LAZINESS: case SC__UNLUCKY: - case SC__WEAKNESS: //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: - case SC_MAGNETICFIELD://case SC_MINOR_BBQ: case SC_SIROMA_ICE_TEA: - //case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: - case SC_NEUTRALBARRIER_MASTER: case SC_NEUTRALBARRIER: - case SC_STEALTHFIELD_MASTER: case SC_STEALTHFIELD: - case SC_LEADERSHIP: case SC_GLORYWOUNDS: case SC_SOULCOLD: - case SC_HAWKEYES: case SC_GUILDAURA: case SC_PUSH_CART: - case SC_PARTYFLEE: case SC_GT_REVITALIZE: - case SC_RAISINGDRAGON: case SC_GT_ENERGYGAIN: case SC_GT_CHANGE: - #ifdef RENEWAL - case SC_EXTREMITYFIST2: - #endif - continue; - case SC_ASSUMPTIO: - if( bl->type == BL_MOB ) - continue; + case NPC_DRAGONFEAR: + if (flag&1) { + const enum sc_type sc[] = { SC_STUN, SC_SILENCE, SC_CONFUSION, SC_BLOODING }; + int j; + j = i = rnd()%ARRAYLENGTH(sc); + while ( !sc_start2(bl,sc[i],100,skill_lv,src->id,skill->get_time2(skill_id,i+1)) ) { + i++; + if ( i == ARRAYLENGTH(sc) ) + i = 0; + if (i == j) break; - } - if(i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. - status_change_end(bl,(sc_type)i,INVALID_TIMER); } break; } - iMap->foreachinrange(skill->area_sub, bl, i, BL_CHAR, src, skill_id, skill_lv, tick, flag|1, skill->castend_damage_id); - break; - - case AB_SILENTIUM: - // Should the level of Lex Divina be equivalent to the level of Silentium or should the highest level learned be used? [LimitLine] - iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR, - src, PR_LEXDIVINA, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + case NPC_WIDEBLEEDING: + case NPC_WIDECONFUSE: + case NPC_WIDECURSE: + case NPC_WIDEFREEZE: + case NPC_WIDESLEEP: + case NPC_WIDESILENCE: + case NPC_WIDESTONE: + case NPC_WIDESTUN: + case NPC_SLOWCAST: + case NPC_WIDEHELLDIGNITY: + if (flag&1) + sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + else { + skill_area_temp[2] = 0; //For SD_PREAMBLE + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv),BL_CHAR, + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, + skill->castend_nodamage_id); + } break; - /** - * Warlock - **/ - case WL_STASIS: - if( flag&1 ) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - else - { - iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id, skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill->castend_nodamage_id); - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + case NPC_WIDESOULDRAIN: + if (flag&1) + status_percent_damage(src,bl,0,((skill_lv-1)%5+1)*20,false); + else { + skill_area_temp[2] = 0; //For SD_PREAMBLE + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv),BL_CHAR, + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, + skill->castend_nodamage_id); } break; - - case WL_WHITEIMPRISON: - if( (src == bl || battle->check_target(src, bl, BCT_ENEMY) > 0 ) && !is_boss(bl) )// Should not work with bosses. + case ALL_PARTYFLEE: + if( sd && !(flag&1) ) { - int rate = ( sd? sd->status.job_level : 50 ) / 4; - - if( src == bl ) rate = 100; // Success Chance: On self, 100% - else if(bl->type == BL_PC) rate += 20 + 10 * skill_lv; // On Players, (20 + 10 * Skill Level) % - else rate += 40 + 10 * skill_lv; // On Monsters, (40 + 10 * Skill Level) % - - if( sd ) - skill->blockpc_start(sd,skill_id,4000, false); - - if( !(tsc && tsc->data[type]) ){ - i = sc_start2(bl,type,rate,skill_lv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill->get_time(skill_id,skill_lv):skill->get_time2(skill_id, skill_lv)); - clif->skill_nodamage(src,bl,skill_id,skill_lv,i); - if( !i ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if( !sd->status.party_id ) + { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; } - }else - if( sd ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0); + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + } + else + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; - - case WL_FROSTMISTY: + case NPC_TALK: + case ALL_WEWISH: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id); break; - - case WL_JACKFROST: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->foreachinshootrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + case ALL_BUYING_STORE: + if( sd ) + {// players only, skill allows 5 buying slots + clif->skill_nodamage(src, bl, skill_id, skill_lv, buyingstore->setup(sd, MAX_BUYINGSTORE_SLOTS)); + } break; - - case WL_MARSHOFABYSS: - // Should marsh of abyss still apply half reduction to players after the 28/10 patch? [LimitLine] - clif->skill_nodamage(src, bl, skill_id, skill_lv, - sc_start4(bl, type, 100, skill_lv, status_get_int(src), sd ? sd->status.job_level : 50, 0, - skill->get_time(skill_id, skill_lv))); + case RK_ENCHANTBLADE: + clif->skill_nodamage(src,bl,skill_id,skill_lv,// formula not confirmed + sc_start2(bl,type,100,skill_lv,100+20*skill_lv/*+sstatus->int_/2+status_get_lv(bl)/10*/,skill->get_time(skill_id,skill_lv))); break; - - case WL_SIENNAEXECRATE: - if( status_isimmune(bl) || !tsc ) - break; - - if( flag&1 ) { - if( bl->id == skill_area_temp[1] ) - break; // Already work on this target - - if( tsc && tsc->data[SC_STONE] ) - status_change_end(bl,SC_STONE,INVALID_TIMER); - else - status_change_start(bl,SC_STONE,10000,skill_lv,0,0,1000,skill->get_time(skill_id, skill_lv),2); - } else { - int rate = 40 + 8 * skill_lv + ( sd? sd->status.job_level : 50 ) / 4; - // IroWiki says Rate should be reduced by target stats, but currently unknown - if( rnd()%100 < rate ) { // Success on First Target - if( !tsc->data[SC_STONE] ) - rate = status_change_start(bl,SC_STONE,10000,skill_lv,0,0,1000,skill->get_time(skill_id, skill_lv),2); - else { - rate = 1; - status_change_end(bl,SC_STONE,INVALID_TIMER); - } - - if( rate ) { - skill_area_temp[1] = bl->id; - iMap->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id); - } - // Doesn't send failure packet if it fails on defense. + case RK_DRAGONHOWLING: + if( flag&1) + sc_start(bl,type,50 + 6 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + else + { + skill_area_temp[2] = 0; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->area_sub, src, + skill->get_splash(skill_id,skill_lv),BL_CHAR, + src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|1, + skill->castend_nodamage_id); + } + break; + case RK_IGNITIONBREAK: + case LG_EARTHDRIVE: + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + i = skill->get_splash(skill_id,skill_lv); + if( skill_id == LG_EARTHDRIVE ) { + int dummy = 1; + iMap->foreachinarea(skill->cell_overlap, src->m, src->x-i, src->y-i, src->x+i, src->y+i, BL_SKILL, LG_EARTHDRIVE, &dummy, src); } - else if( sd ) // Failure on Rate + iMap->foreachinrange(skill->area_sub, bl,i,BL_CHAR, + src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + break; + case RK_STONEHARDSKIN: + if( sd ) + { + int heal = sstatus->hp / 4; // 25% HP + if( status_charge(bl,heal,0) ) + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(bl,type,100,skill_lv,heal,skill->get_time(skill_id,skill_lv))); + else clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } break; - - case WL_SUMMONFB: - case WL_SUMMONBL: - case WL_SUMMONWB: - case WL_SUMMONSTONE: + case RK_REFRESH: { - short element = 0, sctype = 0, pos = -1; - struct status_change *sc = status_get_sc(src); - if( !sc ) break; - - for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) - { - if( !sctype && !sc->data[i] ) - sctype = i; // Take the free SC - if( sc->data[i] ) - pos = max(sc->data[i]->val2,pos); - } - - if( !sctype ) - { - if( sd ) // No free slots to put SC - clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); - break; - } - - pos++; // Used in val2 for SC. Indicates the order of this ball - switch( skill_id ) { // Set val1. The SC element for this ball - case WL_SUMMONFB: element = WLS_FIRE; break; - case WL_SUMMONBL: element = WLS_WIND; break; - case WL_SUMMONWB: element = WLS_WATER; break; - case WL_SUMMONSTONE: element = WLS_STONE; break; - } - - sc_start4(src,sctype,100,element,pos,skill_lv,0,skill->get_time(skill_id,skill_lv)); - clif->skill_nodamage(src,bl,skill_id,0,0); + int heal = status_get_max_hp(bl) * 25 / 100; + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + status_heal(bl,heal,0,1); + status_change_clear_buffs(bl,4); } break; - case WL_READING_SB: - if( sd ) { - struct status_change *sc = status_get_sc(bl); - - for( i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) - if( sc && !sc->data[i] ) - break; - if( i == SC_MAXSPELLBOOK ) { - clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); - break; - } - - sc_start(bl, SC_STOP, 100, skill_lv, INVALID_TIMER); //Can't move while selecting a spellbook. - clif->spellbook_list(sd); - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + case RK_MILLENNIUMSHIELD: + if( sd ){ + short shields = (rnd()%100<50) ? 4 : ((rnd()%100<80) ? 3 : 2); + sc_start4(bl,type,100,skill_lv,shields,1000,0,skill->get_time(skill_id,skill_lv)); + clif->millenniumshield(sd,shields); + clif->skill_nodamage(src,bl,skill_id,1,1); } break; - /** - * Ranger - **/ - case RA_FEARBREEZE: - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); - break; - case RA_WUGMASTERY: - if( sd ) { - if( !pc_iswug(sd) ) - pc->setoption(sd,sd->sc.option|OPTION_WUG); + case RK_FIGHTINGSPIRIT: + if( flag&1 ) { + if( src == bl ) + sc_start2(bl,type,100,skill_area_temp[5],10*(sd?pc->checkskill(sd,RK_RUNEMASTERY):10),skill->get_time(skill_id,skill_lv)); else - pc->setoption(sd,sd->sc.option&~OPTION_WUG); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + sc_start(bl,type,100,skill_area_temp[5]/4,skill->get_time(skill_id,skill_lv)); + } else if( sd ) { + if( sd->status.party_id ) { + i = party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,BCT_PARTY,skill->area_sub_count); + skill_area_temp[5] = 7 * i; // ATK + party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id); + } else + sc_start2(bl,type,100,7,5,skill->get_time(skill_id,skill_lv)); } + clif->skill_nodamage(src,bl,skill_id,1,1); break; - - case RA_WUGRIDER: - if( sd ) { - if( !pc_isridingwug(sd) && pc_iswug(sd) ) { - pc->setoption(sd,sd->sc.option&~OPTION_WUG); - pc->setoption(sd,sd->sc.option|OPTION_WUGRIDER); - } else if( pc_isridingwug(sd) ) { - pc->setoption(sd,sd->sc.option&~OPTION_WUGRIDER); - pc->setoption(sd,sd->sc.option|OPTION_WUG); + /** + * Guilotine Cross + **/ + case GC_ROLLINGCUTTER: + { + short count = 1; + skill_area_temp[2] = 0; + iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|SD_SPLASH|1,skill->castend_damage_id); + if( tsc && tsc->data[SC_ROLLINGCUTTER] ) + { // Every time the skill is casted the status change is reseted adding a counter. + count += (short)tsc->data[SC_ROLLINGCUTTER]->val1; + if( count > 10 ) + count = 10; // Max coounter + status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); } - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; - - case RA_WUGDASH: - if( tsce ) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); - iMap->freeblock_unlock(); - return 0; - } - if( sd && pc_isridingwug(sd) ) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit_getdir(bl),0,0,1)); - clif->walkok(sd); + sc_start(bl,SC_ROLLINGCUTTER,100,count,skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage(src,src,skill_id,skill_lv,1); } break; - case RA_SENSITIVEKEEN: + case GC_WEAPONBLOCKING: + if( tsc && tsc->data[SC_WEAPONBLOCKING] ) + status_change_end(bl, SC_WEAPONBLOCKING, INVALID_TIMER); + else + sc_start(bl,SC_WEAPONBLOCKING,100,skill_lv,skill->get_time(skill_id,skill_lv)); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id); break; - /** - * Mechanic - **/ - case NC_F_SIDESLIDE: - case NC_B_SIDESLIDE: + + case GC_CREATENEWPOISON: + if( sd ) { - uint8 dir = (skill_id == NC_F_SIDESLIDE) ? (unit_getdir(src)+4)%8 : unit_getdir(src); - skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),dir,0x1); - clif->slide(src,src->x,src->y); - clif->fixpos(src); //Aegis sent this packet - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + clif->skill_produce_mix_list(sd,skill_id,25); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); } break; - case NC_SELFDESTRUCTION: + case GC_POISONINGWEAPON: if( sd ) { - if( pc_ismadogear(sd) ) - pc->setmadogear(sd, 0); - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag); - status_set_sp(src, 0, 0); + clif->poison_list(sd,skill_lv); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } break; - case NC_ANALYZE: - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - clif->skill_nodamage(src, bl, skill_id, skill_lv, - sc_start(bl,type, 30 + 12 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv))); - if( sd ) pc->overheat(sd,1); - break; - - case NC_MAGNETICFIELD: - if( (i = sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) ) + case GC_ANTIDOTE: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if( tsc ) { - iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);; - clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); - if (sd) pc->overheat(sd,1); + status_change_end(bl, SC_PARALYSE, INVALID_TIMER); + status_change_end(bl, SC_PYREXIA, INVALID_TIMER); + status_change_end(bl, SC_DEATHHURT, INVALID_TIMER); + status_change_end(bl, SC_LEECHESEND, INVALID_TIMER); + status_change_end(bl, SC_VENOMBLEED, INVALID_TIMER); + status_change_end(bl, SC_MAGICMUSHROOM, INVALID_TIMER); + status_change_end(bl, SC_TOXIN, INVALID_TIMER); + status_change_end(bl, SC_OBLIVIONCURSE, INVALID_TIMER); } - clif->skill_nodamage(src,src,skill_id,skill_lv,i); break; - case NC_REPAIR: - if( sd ) + case GC_PHANTOMMENACE: + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR, + src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + break; + + case GC_HALLUCINATIONWALK: { - int heal; - if( dstsd && pc_ismadogear(dstsd) ) + int heal = status_get_max_hp(bl) / 10; + if( status_get_hp(bl) < heal ) { // if you haven't enough HP skill fails. + if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); + break; + } + if( !status_charge(bl,heal,0) ) { - heal = dstsd->status.max_hp * (3+3*skill_lv) / 100; - status_heal(bl,heal,0,2); - } else { - heal = sd->status.max_hp * (3+3*skill_lv) / 100; - status_heal(src,heal,0,2); + if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); + break; } - - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - clif->skill_nodamage(src, bl, skill_id, skill_lv, heal); + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + } + break; + /** + * Arch Bishop + **/ + case AB_ANCILLA: + if( sd ) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->produce_mix(sd, skill_id, ITEMID_ANCILLA, 0, 0, 0, 1); } break; - case NC_DISJOINT: + case AB_CLEMENTIA: + case AB_CANTO: { - if( bl->type != BL_MOB ) break; - md = iMap->id2md(bl->id); - if( md && md->class_ >= MOBID_SILVERSNIPER && md->class_ <= MOBID_MAGICDECOY_WIND ) - status_kill(bl); - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + int bless_lv = pc->checkskill(sd,AL_BLESSING) + (sd->status.job_level / 10); + int agi_lv = pc->checkskill(sd,AL_INCAGI) + (sd->status.job_level / 10); + if( sd == NULL || sd->status.party_id == 0 || flag&1 ) + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100, + (skill_id == AB_CLEMENTIA)? bless_lv : (skill_id == AB_CANTO)? agi_lv : skill_lv, skill->get_time(skill_id,skill_lv))); + else if( sd ) + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); } break; - case SC_AUTOSHADOWSPELL: - if( sd ) { - int idx1 = skill->get_index(sd->reproduceskill_id), idx2 = skill->get_index(sd->cloneskill_id); - if( sd->status.skill[idx1].id || sd->status.skill[idx2].id ) { - sc_start(src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] - clif->autoshadowspell_list(sd); - clif->skill_nodamage(src,bl,skill_id,1,1); - } - else - clif->skill_fail(sd,skill_id,USESKILL_FAIL_IMITATION_SKILL_NONE,0); - } + + case AB_PRAEFATIO: + if( sd == NULL || sd->status.party_id == 0 || flag&1 ) + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start4(bl, type, 100, skill_lv, 0, 0, 1, skill->get_time(skill_id, skill_lv))); + else if( sd ) + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); break; - case SC_SHADOWFORM: - if( sd && dstsd && src != bl && !dstsd->shadowform_id ) { - if( clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,type,100,skill_lv,bl->id,4+skill_lv,0,skill->get_time(skill_id, skill_lv))) ) - dstsd->shadowform_id = src->id; + case AB_CHEAL: + if( sd == NULL || sd->status.party_id == 0 || flag&1 ) { + if( sd && tstatus && !battle->check_undead(tstatus->race, tstatus->def_ele) ) { + i = skill->calc_heal(src, bl, AL_HEAL, pc->checkskill(sd, AL_HEAL), true); + + if( (dstsd && pc_ismadogear(dstsd)) || status_isimmune(bl)) + i = 0; // Should heal by 0 or won't do anything?? in iRO it breaks the healing to members.. [malufett] + + clif->skill_nodamage(bl, bl, skill_id, i, 1); + if( tsc && tsc->data[SC_AKAITSUKI] && i ) + i = ~i + 1; + status_heal(bl, i, 0, 0); + } } else if( sd ) - clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); break; - case SC_BODYPAINT: - if( flag&1 ) { - if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || - tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || - tsc->data[SC__INVISIBILITY]) ) { - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CHASEWALK, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); - - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - sc_start(bl,SC_BLIND,53 + 2 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); - } - } else { - clif->skill_nodamage(src, bl, skill_id, 0, 1); - iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, + case AB_ORATIO: + if( flag&1 ) + sc_start(bl, type, 40 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + else + { + iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); } break; - case SC_ENERVATION: - case SC_GROOMY: - case SC_LAZINESS: - case SC_UNLUCKY: - case SC_WEAKNESS: - if( !(tsc && tsc->data[type]) ) { - //((rand(myDEX / 12, myDEX / 4) + myJobLevel + 10 * skLevel) + myLevel / 10) - (targetLevel / 10 + targetLUK / 10 + (targetMaxWeight - targetWeight) / 1000 + rand(targetAGI / 6, targetAGI / 3)) - int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 - - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); - rate = cap_value(rate, skill_lv+sstatus->dex/20, 100); - clif->skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv))); + case AB_LAUDAAGNUS: + if( flag&1 || sd == NULL ) { + if( tsc && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE] || tsc->data[SC_BLIND] || + tsc->data[SC_BURNING] || tsc->data[SC_FROSTMISTY] || tsc->data[SC_CRYSTALIZE])) { + // Success Chance: (40 + 10 * Skill Level) % + if( rnd()%100 > 40+10*skill_lv ) break; + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + status_change_end(bl, SC_BURNING, INVALID_TIMER); + status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER); + status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); + }else //Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets + clif->skill_nodamage(bl, bl, skill_id, skill_lv, + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); } else if( sd ) - clif->skill_fail(sd,skill_id,0,0); + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), + src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); break; - case SC_IGNORANCE: - if( !(tsc && tsc->data[type]) ) { - int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 - - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); - rate = cap_value(rate, skill_lv+sstatus->dex/20, 100); - if (clif->skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)))) { - int sp = 200 * skill_lv; - if( dstmd ) sp = dstmd->level * 2; - if( status_zap(bl,0,sp) ) - status_heal(src,0,sp/2,3); - } - else if( sd ) clif->skill_fail(sd,skill_id,0,0); + case AB_LAUDARAMUS: + if( flag&1 || sd == NULL ) { + if( tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] || tsc->data[SC_SILENCE]) ){ + // Success Chance: (40 + 10 * Skill Level) % + if( rnd()%100 > 40+10*skill_lv ) break; + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + status_change_end(bl, SC_MANDRAGORA, INVALID_TIMER); + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + }else // Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets + clif->skill_nodamage(bl, bl, skill_id, skill_lv, + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); } else if( sd ) - clif->skill_fail(sd,skill_id,0,0); + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), + src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); break; - case LG_TRAMPLE: - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - iMap->foreachinrange(skill->destroy_trap,bl,skill->get_splash(skill_id,skill_lv),BL_SKILL,tick); + case AB_CLEARANCE: + if( flag&1 || (i = skill->get_splash(skill_id, skill_lv)) < 1 ) + { //As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie] + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) || rnd()%100 >= 30 + 10 * skill_lv) + { + if (sd) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + if(status_isimmune(bl) || !tsc || !tsc->count) + break; + for(i = 0; i < SC_MAX; i++) + { + if( SC_COMMON_MAX > i ){ + if ( !tsc->data[i] || !status_get_sc_type(i) ) + continue; + if ( status_get_sc_type(i)&SC_NO_CLEARANCE ) + continue; + } + switch (i) { + case SC_ASSUMPTIO: + if( bl->type == BL_MOB ) + continue; + break; + case SC_BERSERK: + case SC_SATURDAY_NIGHT_FEVER: + tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. + break; + } + status_change_end(bl,(sc_type)i,INVALID_TIMER); + } + break; + } + iMap->foreachinrange(skill->area_sub, bl, i, BL_CHAR, src, skill_id, skill_lv, tick, flag|1, skill->castend_damage_id); break; - case LG_REFLECTDAMAGE: - if( tsc && tsc->data[type] ) - status_change_end(bl,type,INVALID_TIMER); - else + case AB_SILENTIUM: + // Should the level of Lex Divina be equivalent to the level of Silentium or should the highest level learned be used? [LimitLine] + iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, PR_LEXDIVINA, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + break; + /** + * Warlock + **/ + case WL_STASIS: + if( flag&1 ) sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + else + { + iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id, skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill->castend_nodamage_id); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + } break; - case LG_SHIELDSPELL: - if( flag&1 ) { - int duration = (sd) ? sd->bonus.shieldmdef * 2000 : 10000; - sc_start(bl,SC_SILENCE,100,skill_lv,duration); - } else if( sd ) { - int opt = skill_lv; - int rate = rnd()%100; - int val, brate; - switch( skill_lv ) { - case 1: - { - struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; - if( !shield_data || shield_data->type != IT_ARMOR ) { // No shield? - clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - break; - } - brate = shield_data->def * 10; - if( rate < 50 ) - opt = 1; - else if( rate < 75 ) - opt = 2; - else - opt = 3; + case WL_WHITEIMPRISON: + if( (src == bl || battle->check_target(src, bl, BCT_ENEMY) > 0 ) && !is_boss(bl) )// Should not work with bosses. + { + int rate = ( sd? sd->status.job_level : 50 ) / 4; - switch( opt ) { - case 1: - sc_start(bl,SC_SHIELDSPELL_DEF,100,opt,-1); - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( rate < brate ) - iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); - status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER); - break; - case 2: - val = shield_data->def / 10; // % Reflected damage. - sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 1000); - break; - case 3: - val = shield_data->def; // Attack increase. - sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 3000); - break; - } - } - break; + if( src == bl ) rate = 100; // Success Chance: On self, 100% + else if(bl->type == BL_PC) rate += 20 + 10 * skill_lv; // On Players, (20 + 10 * Skill Level) % + else rate += 40 + 10 * skill_lv; // On Monsters, (40 + 10 * Skill Level) % - case 2: - brate = sd->bonus.shieldmdef * 20; - if( rate < 30 ) - opt = 1; - else if( rate < 60 ) - opt = 2; - else - opt = 3; - switch( opt ) { - case 1: - sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( rate < brate ) - iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|2,skill->castend_damage_id); - status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER); - break; - case 2: - sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( rate < brate ) - iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id); - break; - case 3: - if( sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->bonus.shieldmdef * 30000) ) - clif->skill_nodamage(src,bl,PR_MAGNIFICAT,skill_lv, - sc_start(bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000)); - break; - } - break; + if( sd ) + skill->blockpc_start(sd,skill_id,4000, false); - case 3: - { - struct item *it = &sd->status.inventory[sd->equip_index[EQI_HAND_L]]; - if( !it ) { // No shield? - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - brate = it->refine * 5; - if( rate < 25 ) - opt = 1; - else if( rate < 50 ) - opt = 2; - else - opt = 3; - switch( opt ) { - case 1: - val = 105 * it->refine / 10; - sc_start2(bl,SC_SHIELDSPELL_REF,brate,opt,val,skill->get_time(skill_id,skill_lv)); - break; - case 2: case 3: - if( rate < brate ) - { - val = sstatus->max_hp * (11 + it->refine) / 100; - status_heal(bl, val, 0, 3); - } - break; - /*case 3: - // Full protection. I need confirm what effect should be here. Moved to case 2 to until we got it. - break;*/ - } - } - break; + if( !(tsc && tsc->data[type]) ){ + i = sc_start2(bl,type,rate,skill_lv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill->get_time(skill_id,skill_lv):skill->get_time2(skill_id, skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,i); + if( sd && !i ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - } + }else + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0); break; - case LG_PIETY: - if( flag&1 ) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - else { - skill_area_temp[2] = 0; - iMap->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill->castend_nodamage_id); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - } + case WL_FROSTMISTY: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id); break; - case LG_INSPIRATION: - if( sd && !map[sd->bl.m].flag.noexppenalty && sd->status.base_level != MAX_LEVEL ) { - sd->status.base_exp -= min(sd->status.base_exp, pc->nextbaseexp(sd) * 1 / 100); // 1% penalty. - sd->status.job_exp -= min(sd->status.job_exp, pc->nextjobexp(sd) * 1 / 100); - clif->updatestatus(sd,SP_BASEEXP); - clif->updatestatus(sd,SP_JOBEXP); - } - clif->skill_nodamage(bl,src,skill_id,skill_lv, - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); - break; - case SR_CURSEDCIRCLE: - if( flag&1 ) { - if( is_boss(bl) ) break; - if( sc_start2(bl, type, 100, skill_lv, src->id, skill->get_time(skill_id, skill_lv))) { - if( bl->type == BL_MOB ) - mob_unlocktarget((TBL_MOB*)bl,iTimer->gettick()); - unit_stop_attack(bl); - clif->bladestop(src, bl->id, 1); - iMap->freeblock_unlock(); - return 1; - } - } else { - int count = 0; - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - count = iMap->forcountinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-charactors - BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); - if( sd ) pc->delspiritball(sd, count, 0); - clif->skill_nodamage(src, src, skill_id, skill_lv, - sc_start2(src, SC_CURSEDCIRCLE_ATKER, 100, skill_lv, count, skill->get_time(skill_id,skill_lv))); - } + case WL_JACKFROST: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->foreachinshootrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); break; - case SR_RAISINGDRAGON: - if( sd ) { - short max = 5 + skill_lv; - sc_start(bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill->get_time(skill_id, skill_lv)); - for( i = 0; i < max; i++ ) // Don't call more than max available spheres. - pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), max); - clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv))); - } + case WL_MARSHOFABYSS: + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); break; - case SR_ASSIMILATEPOWER: + case WL_SIENNAEXECRATE: if( flag&1 ) { - i = 0; - if( dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER ) - { - i = dstsd->spiritball; //1%sp per spiritball. - pc->delspiritball(dstsd, dstsd->spiritball, 0); - } - if( i ) status_percent_heal(src, 0, i); - clif->skill_nodamage(src, bl, skill_id, skill_lv, i ? 1:0); + if( status_isimmune(bl) || !tsc ) + break; + if( tsc && tsc->data[SC_STONE] ) + status_change_end(bl,SC_STONE,INVALID_TIMER); + else + status_change_start(bl,SC_STONE,10000,skill_lv,0,0,500,skill->get_time(skill_id, skill_lv),2); } else { - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id); + int rate = 45 + 5 * skill_lv; + if( rnd()%100 < rate ){ + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + iMap->foreachinrange(skill_area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id); + }else if( sd ) // Failure on Rate + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } break; - case SR_POWERVELOCITY: - if( !dstsd ) - break; - if( sd && dstsd->spiritball <= 5 ) { - for(i = 0; i <= 5; i++) { - pc->addspiritball(dstsd, skill->get_time(MO_CALLSPIRITS, pc->checkskill(sd,MO_CALLSPIRITS)), i); - pc->delspiritball(sd, sd->spiritball, 0); + case WL_SUMMONFB: + case WL_SUMMONBL: + case WL_SUMMONWB: + case WL_SUMMONSTONE: + for( i = SC_SUMMON1; i <= SC_SUMMON5; i++ ){ + if( tsc && !tsc->data[i] ){ // officially it doesn't work like a stack + int ele = WLS_FIRE + (skill_id - WL_SUMMONFB) - (skill_id == WL_SUMMONSTONE ? 4 : 0); + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start(bl, (sc_type)i, 100, ele, skill->get_time(skill_id, skill_lv))); + break; } } - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); break; - case SR_GENTLETOUCH_CURE: - { - int heal; + case WL_READING_SB: + if( sd ) { + struct status_change *sc = status_get_sc(bl); - if( status_isimmune(bl) ) - { - clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + for( i = SC_SPELLBOOK1; i <= SC_SPELLBOOK7; i++) + if( sc && !sc->data[i] ) + break; + if( i == SC_SPELLBOOK7 ) { + clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); break; } - heal = 120 * skill_lv + status_get_max_hp(bl) * (2 + skill_lv) / 100; - status_heal(bl, heal, 0, 0); + sc_start(bl, SC_STOP, 100, skill_lv, INVALID_TIMER); //Can't move while selecting a spellbook. + clif->spellbook_list(sd); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + } + break; + /** + * Ranger + **/ + case RA_FEARBREEZE: + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + break; - if( (tsc && tsc->opt1) && (rnd()%100 < ((skill_lv * 5) + (status_get_dex(src) + status_get_lv(src)) / 4) - (1 + (rnd() % 10))) ) - { - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); - status_change_end(bl, SC_POISON, INVALID_TIMER); - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - status_change_end(bl, SC_HALLUCINATION, INVALID_TIMER); - status_change_end(bl, SC_BURNING, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); - } + case RA_WUGMASTERY: + if( sd ) { + if( !pc_iswug(sd) ) + pc->setoption(sd,sd->sc.option|OPTION_WUG); + else + pc->setoption(sd,sd->sc.option&~OPTION_WUG); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; + case RA_WUGRIDER: + if( sd ) { + if( !pc_isridingwug(sd) && pc_iswug(sd) ) { + pc->setoption(sd,sd->sc.option&~OPTION_WUG); + pc->setoption(sd,sd->sc.option|OPTION_WUGRIDER); + } else if( pc_isridingwug(sd) ) { + pc->setoption(sd,sd->sc.option&~OPTION_WUGRIDER); + pc->setoption(sd,sd->sc.option|OPTION_WUG); + } clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } break; - case SR_GENTLETOUCH_CHANGE: - case SR_GENTLETOUCH_REVITALIZE: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); + + case RA_WUGDASH: + if( tsce ) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); + iMap->freeblock_unlock(); + return 0; + } + if( sd && pc_isridingwug(sd) ) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit_getdir(bl),0,0,1)); + clif->walkok(sd); + } break; - case WA_SWING_DANCE: - case WA_MOONLIT_SERENADE: - if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - else if( sd ) { // Only shows effects on caster. + + case RA_SENSITIVEKEEN: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id); + break; + /** + * Mechanic + **/ + case NC_F_SIDESLIDE: + case NC_B_SIDESLIDE: + { + uint8 dir = (skill_id == NC_F_SIDESLIDE) ? (unit_getdir(src)+4)%8 : unit_getdir(src); + skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),dir,0); + clif->slide(src,src->x,src->y); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); } break; - case WA_SYMPHONY_OF_LOVER: - case MI_RUSH_WINDMILL: - case MI_ECHOSONG: - if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) - sc_start4(bl,type,100,skill_lv,6*skill_lv,(sd?pc->checkskill(sd,WM_LESSON):0),(sd?sd->status.job_level:0),skill->get_time(skill_id,skill_lv)); - else if( sd ) { // Only shows effects on caster. - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + case NC_SELFDESTRUCTION: + if( sd ) { + if( pc_ismadogear(sd) ) + pc->setmadogear(sd, 0); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag); + status_set_sp(src, 0, 0); } break; - case MI_HARMONIZE: - if( src != bl ) - clif->skill_nodamage(src, src, skill_id, skill_lv, sc_start(src, type, 100, skill_lv, skill->get_time(skill_id,skill_lv))); - clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id,skill_lv))); + case NC_ANALYZE: + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start(bl,type, 30 + 12 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv))); + if( sd ) pc->overheat(sd,1); break; - case WM_DEADHILLHERE: - if( bl->type == BL_PC ) { - if( !status_isdead(bl) ) - break; + case NC_MAGNETICFIELD: + if( (i = sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) ) + { + iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);; + clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + if (sd) pc->overheat(sd,1); + } + clif->skill_nodamage(src,src,skill_id,skill_lv,i); + break; - if( rnd()%100 < 88 + 2 * skill_lv ) { - int heal = tstatus->sp; - if( heal <= 0 ) - heal = 1; - tstatus->hp = heal; - tstatus->sp -= tstatus->sp * ( 120 - 20 * skill_lv ) / 100; - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - pc->revive((TBL_PC*)bl,heal,0); - clif->resurrection(bl,1); + case NC_REPAIR: + if( sd ) + { + int heal; + if( dstsd && pc_ismadogear(dstsd) ) + { + heal = dstsd->status.max_hp * (3+3*skill_lv) / 100; + status_heal(bl,heal,0,2); + } else { + heal = sd->status.max_hp * (3+3*skill_lv) / 100; + status_heal(src,heal,0,2); + } + + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_nodamage(src, bl, skill_id, skill_lv, heal); + } + break; + + case NC_DISJOINT: + { + if( bl->type != BL_MOB ) break; + md = iMap->id2md(bl->id); + if( md && md->class_ >= MOBID_SILVERSNIPER && md->class_ <= MOBID_MAGICDECOY_WIND ) + status_kill(bl); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + } + break; + case SC_AUTOSHADOWSPELL: + if( sd ) { + int idx1 = skill->get_index(sd->reproduceskill_id), idx2 = skill->get_index(sd->cloneskill_id); + if( sd->status.skill[idx1].id || sd->status.skill[idx2].id ) { + sc_start(src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] + clif->autoshadowspell_list(sd); + clif->skill_nodamage(src,bl,skill_id,1,1); } + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL_IMITATION_SKILL_NONE,0); } break; - case WM_SIRCLEOFNATURE: - flag |= BCT_SELF|BCT_PARTY|BCT_GUILD; - case WM_VOICEOFSIREN: - if( skill_id != WM_SIRCLEOFNATURE ) - flag &= ~BCT_SELF; + case SC_SHADOWFORM: + if( sd && dstsd && src != bl && !dstsd->shadowform_id ) { + if( clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,type,100,skill_lv,bl->id,4+skill_lv,0,skill->get_time(skill_id, skill_lv))) ) + dstsd->shadowform_id = src->id; + } + else if( sd ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + break; + + case SC_BODYPAINT: if( flag&1 ) { - sc_start2(bl,type,(skill_id==WM_VOICEOFSIREN)?20+10*skill_lv:100,skill_lv,(skill_id==WM_VOICEOFSIREN)?src->id:0,skill->get_time(skill_id,skill_lv)); + if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || + tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || + tsc->data[SC__INVISIBILITY]) ) { + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CHASEWALK, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); + + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(bl,SC_BLIND,53 + 2 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + } } else { - iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),(skill_id==WM_VOICEOFSIREN)?BL_CHAR|BL_SKILL:BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + clif->skill_nodamage(src, bl, skill_id, 0, 1); + iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); } break; - case WM_GLOOMYDAY: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if( dstsd && ( pc->checkskill(dstsd,KN_BRANDISHSPEAR) || pc->checkskill(dstsd,LK_SPIRALPIERCE) || - pc->checkskill(dstsd,CR_SHIELDCHARGE) || pc->checkskill(dstsd,CR_SHIELDBOOMERANG) || - pc->checkskill(dstsd,PA_SHIELDCHAIN) || pc->checkskill(dstsd,LG_SHIELDPRESS) ) ) - { - sc_start(bl,SC_GLOOMYDAY_SK,100,skill_lv,skill->get_time(skill_id,skill_lv)); - break; - } - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + case SC_ENERVATION: + case SC_GROOMY: + case SC_LAZINESS: + case SC_UNLUCKY: + case SC_WEAKNESS: + if( !(tsc && tsc->data[type]) ) { + //((rand(myDEX / 12, myDEX / 4) + myJobLevel + 10 * skLevel) + myLevel / 10) - (targetLevel / 10 + targetLUK / 10 + (targetMaxWeight - targetWeight) / 1000 + rand(targetAGI / 6, targetAGI / 3)) + int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 + - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); + rate = cap_value(rate, skill_lv+sstatus->dex/20, 100); + clif->skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv))); + } else if( sd ) + clif->skill_fail(sd,skill_id,0,0); break; - case WM_SATURDAY_NIGHT_FEVER: - if( flag&1 ) { // Affect to all targets arround the caster and caster too. - if( !(tsc && tsc->data[type]) ) - sc_start(bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv)); - } else if( flag&2 ) { - if( src->id != bl->id && battle->check_target(src,bl,BCT_ENEMY) > 0 ) - status_fix_damage(src,bl,9999,clif->damage(src,bl,tick,0,0,9999,0,0,0)); - } else if( sd ) { - short chance = sstatus->int_/6 + sd->status.job_level/5 + skill_lv*4; - if( !sd->status.party_id || (rnd()%100 > chance)) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0); - break; + case SC_IGNORANCE: + if( !(tsc && tsc->data[type]) ) { + int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 + - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); + rate = cap_value(rate, skill_lv+sstatus->dex/20, 100); + if (clif->skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)))) { + int sp = 200 * skill_lv; + if( dstmd ) sp = dstmd->level * 2; + if( status_zap(bl,0,sp) ) + status_heal(src,0,sp/2,3); } - if( iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id,skill_lv), - BL_PC, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count) > 7 ) - flag |= 2; - else - flag |= 1; - iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF, skill->castend_nodamage_id); - clif->skill_nodamage(src, bl, skill_id, skill_lv, - sc_start(src,SC_STOP,100,skill_lv,skill->get_time2(skill_id,skill_lv))); - if( flag&2 ) // Dealed here to prevent conflicts - status_fix_damage(src,bl,9999,clif->damage(src,bl,tick,0,0,9999,0,0,0)); - } + else if( sd ) clif->skill_fail(sd,skill_id,0,0); + } else if( sd ) + clif->skill_fail(sd,skill_id,0,0); break; - case WM_SONG_OF_MANA: - case WM_DANCE_WITH_WUG: - case WM_LERADS_DEW: - if( flag&1 ) { // These affect to to all party members near the caster. - struct status_change *sc = status_get_sc(src); - if( sc && sc->data[type] ) { - sc_start2(bl,type,100,skill_lv,sc->data[type]->val2,skill->get_time(skill_id,skill_lv)); - } - } else if( sd ) { - short lv = (short)skill_lv; - int count = skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),1); - if( sc_start2(bl,type,100,skill_lv,count,skill->get_time(skill_id,skill_lv)) ) - party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + case LG_TRAMPLE: + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + iMap->foreachinrange(skill->destroy_trap,bl,skill->get_splash(skill_id,skill_lv),BL_SKILL,tick); + break; - } + case LG_REFLECTDAMAGE: + if( tsc && tsc->data[type] ) + status_change_end(bl,type,INVALID_TIMER); + else + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; - case WM_MELODYOFSINK: - case WM_BEYOND_OF_WARCRY: - case WM_UNLIMITED_HUMMING_VOICE: + case LG_SHIELDSPELL: if( flag&1 ) { - sc_start2(bl,type,100,skill_lv,skill_area_temp[0],skill->get_time(skill_id,skill_lv)); - } else { // These affect to all targets arround the caster. - short lv = (short)skill_lv; - skill_area_temp[0] = (sd) ? skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),1) : 50; // 50% chance in non BL_PC (clones). - iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + int duration = (sd) ? sd->bonus.shieldmdef * 2000 : 10000; + sc_start(bl,SC_SILENCE,100,skill_lv,duration); + } else if( sd ) { + int opt = skill_lv; + int rate = rnd()%100; + int val, brate; + switch( skill_lv ) { + case 1: + { + struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; + if( !shield_data || shield_data->type != IT_ARMOR ) { // No shield? + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + break; + } + brate = shield_data->def * 10; + if( rate < 50 ) + opt = 1; + else if( rate < 75 ) + opt = 2; + else + opt = 3; - case WM_RANDOMIZESPELL: { - int improv_skill_id = 0, improv_skill_lv; - do { - i = rnd() % MAX_SKILL_IMPROVISE_DB; - improv_skill_id = skill_improvise_db[i].skill_id; - } while( improv_skill_id == 0 || rnd()%10000 >= skill_improvise_db[i].per ); - improv_skill_lv = 4 + skill_lv; - clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); + switch( opt ) { + case 1: + sc_start(bl,SC_SHIELDSPELL_DEF,100,opt,-1); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( rate < brate ) + iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER); + break; + case 2: + val = shield_data->def / 10; // % Reflected damage. + sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 1000); + break; + case 3: + val = shield_data->def; // Attack increase. + sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 3000); + break; + } + } + break; - if( sd ) { - sd->state.abra_flag = 2; - sd->skillitem = improv_skill_id; - sd->skillitemlv = improv_skill_lv; - clif->item_skill(sd, improv_skill_id, improv_skill_lv); - } else { - struct unit_data *ud = unit_bl2ud(src); - int inf = skill->get_inf(improv_skill_id); - if (!ud) break; - if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { - if (src->type == BL_PET) - bl = (struct block_list*)((TBL_PET*)src)->msd; - if (!bl) bl = src; - unit_skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv); - } else { - int target_id = 0; - if (ud->target) - target_id = ud->target; - else switch (src->type) { - case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; - case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; + case 2: + brate = sd->bonus.shieldmdef * 20; + if( rate < 30 ) + opt = 1; + else if( rate < 60 ) + opt = 2; + else + opt = 3; + switch( opt ) { + case 1: + sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( rate < brate ) + iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|2,skill->castend_damage_id); + status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER); + break; + case 2: + sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( rate < brate ) + iMap->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id); + break; + case 3: + if( sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->bonus.shieldmdef * 30000) ) + clif->skill_nodamage(src,bl,PR_MAGNIFICAT,skill_lv, + sc_start(bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000)); + break; + } + break; + + case 3: + { + struct item *it = &sd->status.inventory[sd->equip_index[EQI_HAND_L]]; + if( !it ) { // No shield? + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + brate = it->refine * 5; + if( rate < 25 ) + opt = 1; + else if( rate < 50 ) + opt = 2; + else + opt = 3; + switch( opt ) { + case 1: + val = 105 * it->refine / 10; + sc_start2(bl,SC_SHIELDSPELL_REF,brate,opt,val,skill->get_time(skill_id,skill_lv)); + break; + case 2: case 3: + if( rate < brate ) + { + val = sstatus->max_hp * (11 + it->refine) / 100; + status_heal(bl, val, 0, 3); + } + break; + /*case 3: + // Full protection. I need confirm what effect should be here. Moved to case 2 to until we got it. + break;*/ } - if (!target_id) - break; - if (skill->get_casttype(improv_skill_id) == CAST_GROUND) { - bl = iMap->id2bl(target_id); - if (!bl) bl = src; - unit_skilluse_pos(src, bl->x, bl->y, improv_skill_id, improv_skill_lv); - } else - unit_skilluse_id(src, target_id, improv_skill_id, improv_skill_lv); } + break; } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } break; - - case RETURN_TO_ELDICASTES: - case ALL_GUARDIAN_RECALL: - if( sd ) - { - short x, y; // Destiny position. - unsigned short mapindex; - - if( skill_id == RETURN_TO_ELDICASTES) - { - x = 198; - y = 187; - mapindex = mapindex_name2id(MAP_DICASTES); - } - else + case LG_PIETY: + if( flag&1 ) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + else { + skill_area_temp[2] = 0; + iMap->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill->castend_nodamage_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; + case LG_KINGS_GRACE: + if( flag&1 ){ + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + for(i=0; idata[i]) + continue; + switch(i){ + case SC_POISON: case SC_BLIND: + case SC_FREEZE: case SC_STONE: + case SC_STUN: case SC_SLEEP: + case SC_BLOODING: case SC_CURSE: + case SC_CONFUSION: case SC_ILLUSION: + case SC_SILENCE: case SC_BURNING: + case SC_CRYSTALIZE: case SC_FROSTMISTY: + case SC_DEEP_SLEEP: case SC_FEAR: + case SC_MANDRAGORA: + status_change_end(bl, (sc_type)i, INVALID_TIMER); + } } - - if(!mapindex) - { //Given map not found? - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + }else { + skill_area_temp[2] = 0; + if( !map_flag_vs(src->m) && !map_flag_gvg(src->m) ) + flag |= BCT_GUILD; + iMap->foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill->castend_nodamage_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; + case LG_INSPIRATION: + if( sd && !map[sd->bl.m].flag.noexppenalty && sd->status.base_level != MAX_LEVEL ) { + sd->status.base_exp -= min(sd->status.base_exp, pc->nextbaseexp(sd) * 1 / 100); // 1% penalty. + sd->status.job_exp -= min(sd->status.job_exp, pc->nextjobexp(sd) * 1 / 100); + clif->updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd,SP_JOBEXP); + } + clif->skill_nodamage(bl,src,skill_id,skill_lv, + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + break; + case SR_CURSEDCIRCLE: + if( flag&1 ) { + if( is_boss(bl) ) break; + if( sc_start2(bl, type, 100, skill_lv, src->id, skill->get_time(skill_id, skill_lv))) { + if( bl->type == BL_MOB ) + mob_unlocktarget((TBL_MOB*)bl,iTimer->gettick()); + unit_stop_attack(bl); + clif->bladestop(src, bl->id, 1); iMap->freeblock_unlock(); - return 0; + return 1; } - pc->setpos(sd, mapindex, x, y, CLR_TELEPORT); + } else { + int count = 0; + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + count = iMap->forcountinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-charactors + BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + if( sd ) pc->delspiritball(sd, count, 0); + clif->skill_nodamage(src, src, skill_id, skill_lv, + sc_start2(src, SC_CURSEDCIRCLE_ATKER, 100, skill_lv, count, skill->get_time(skill_id,skill_lv))); } break; - case GM_SANDMAN: - if( tsc ) { - if( tsc->opt1 == OPT1_SLEEP ) - tsc->opt1 = 0; - else - tsc->opt1 = OPT1_SLEEP; - clif->changeoption(bl); - clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); + case SR_RAISINGDRAGON: + if( sd ) { + short max = 5 + skill_lv; + sc_start(bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + for( i = 0; i < max; i++ ) // Don't call more than max available spheres. + pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), max); + clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv))); } break; - case SO_ARRULLO: - { - // [(15 + 5 * Skill Level) + ( Casterļæ½s INT / 5 ) + ( Casterļæ½s Job Level / 5 ) - ( Targetļæ½s INT / 6 ) - ( Targetļæ½s LUK / 10 )] % - int rate = (15 + 5 * skill_lv) + status_get_int(src)/5 + (sd ? sd->status.job_level : 0); - rate -= status_get_int(bl)/6 - status_get_luk(bl)/10; - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - sc_start2(bl, type, rate, skill_lv, 1, skill->get_time(skill_id, skill_lv)); + case SR_ASSIMILATEPOWER: + if( flag&1 ) { + i = 0; + if( dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER ) + { + i = dstsd->spiritball; //1%sp per spiritball. + pc->delspiritball(dstsd, dstsd->spiritball, 0); + } + if( i ) status_percent_heal(src, 0, i); + clif->skill_nodamage(src, bl, skill_id, skill_lv, i ? 1:0); + } else { + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id); } break; - case WM_LULLABY_DEEPSLEEP: - if( flag&1 ){ - //[(Skill Level x 4) + (Voice Lessons Skill Level x 2) + (Casterļæ½s Base Level / 15) + (Casterļæ½s Job Level / 5)] % - int rate = (4 * skill_lv) + ( (sd) ? pc->checkskill(sd,WM_LESSON)*2 + sd->status.job_level/5 : 0 ) + status_get_lv(src) / 15; - if( bl != src ) - sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)); - }else { - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ALL|1, skill->castend_nodamage_id); + case SR_POWERVELOCITY: + if( !dstsd ) + break; + if( sd && dstsd->spiritball <= 5 ) { + for(i = 0; i <= 5; i++) { + pc->addspiritball(dstsd, skill->get_time(MO_CALLSPIRITS, pc->checkskill(sd,MO_CALLSPIRITS)), i); + pc->delspiritball(sd, sd->spiritball, 0); + } } + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); break; - case SO_SUMMON_AGNI: - case SO_SUMMON_AQUA: - case SO_SUMMON_VENTUS: - case SO_SUMMON_TERA: - if( sd ) { - int elemental_class = skill->get_elemental_type(skill_id,skill_lv); - - // Remove previous elemental fisrt. - if( sd->ed ) - elemental_delete(sd->ed,0); + case SR_GENTLETOUCH_CURE: + { + int heal; - // Summoning the new one. - if( !elemental_create(sd,elemental_class,skill->get_time(skill_id,skill_lv)) ) { - clif->skill_fail(sd,skill_id,0,0); + if( status_isimmune(bl) ) + { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); break; } - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; - - case SO_EL_CONTROL: - if( sd ) { - int mode = EL_MODE_PASSIVE; // Standard mode. - if( !sd->ed ) break; + heal = 120 * skill_lv + status_get_max_hp(bl) * (2 + skill_lv) / 100; + status_heal(bl, heal, 0, 0); - if( skill_lv == 4 ) {// At level 4 delete elementals. - elemental_delete(sd->ed, 0); - break; - } - switch( skill_lv ) {// Select mode bassed on skill level used. - case 2: mode = EL_MODE_ASSIST; break; - case 3: mode = EL_MODE_AGGRESSIVE; break; - } - if( !elemental_change_mode(sd->ed,mode) ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + if( (tsc && tsc->opt1) && (rnd()%100 < ((skill_lv * 5) + (status_get_dex(src) + status_get_lv(src)) / 4) - (1 + (rnd() % 10))) ) + { + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + status_change_end(bl, SC_POISON, INVALID_TIMER); + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + status_change_end(bl, SC_ILLUSION, INVALID_TIMER); + status_change_end(bl, SC_BURNING, INVALID_TIMER); + status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER); } - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; - case SO_EL_ACTION: - if( sd ) { - int duration = 3000; - if( !sd->ed ) break; - sd->skill_id_old = skill_id; - elemental_action(sd->ed, bl, tick); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - switch(sd->ed->db->class_){ - case 2115:case 2124: - case 2118:case 2121: - duration = 6000; - break; - case 2116:case 2119: - case 2122:case 2125: - duration = 9000; - break; - } - skill->blockpc_start(sd, skill_id, duration, false); } break; - - case SO_EL_CURE: - if( sd ) { - struct elemental_data *ed = sd->ed; - int s_hp = sd->battle_status.hp * 10 / 100, s_sp = sd->battle_status.sp * 10 / 100; - int e_hp, e_sp; - - if( !ed ) break; - if( !status_charge(&sd->bl,s_hp,s_sp) ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - e_hp = ed->battle_status.max_hp * 10 / 100; - e_sp = ed->battle_status.max_sp * 10 / 100; - status_heal(&ed->bl,e_hp,e_sp,3); - clif->skill_nodamage(src,&ed->bl,skill_id,skill_lv,1); - } + case SR_GENTLETOUCH_CHANGE: + case SR_GENTLETOUCH_REVITALIZE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); break; - - case GN_CHANGEMATERIAL: - case SO_EL_ANALYSIS: - if( sd ) { - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - clif->skill_itemlistwindow(sd,skill_id,skill_lv); - } + case SR_FLASHCOMBO: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + for(i = SR_FLASHCOMBO_ATK_STEP1; i <= SR_FLASHCOMBO_ATK_STEP4; i++) + skill->addtimerskill(src, tick + 600 * (i - SR_FLASHCOMBO_ATK_STEP1), bl->id, 0, 0, i, skill_lv, BF_WEAPON, flag|SD_LEVEL); break; - - case GN_BLOOD_SUCKER: - { - struct status_change *sc = status_get_sc(src); - - if( sc && sc->bs_counter < skill->get_maxcount( skill_id , skill_lv) ) { - if( tsc && tsc->data[type] ){ - (sc->bs_counter)--; - status_change_end(src, type, INVALID_TIMER); // the first one cancels and the last one will take effect resetting the timer - } - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - sc_start2(bl, type, 100, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); - (sc->bs_counter)++; - } else if( sd ) { - clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - break; - } + case WA_SWING_DANCE: + case WA_MOONLIT_SERENADE: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + else if( sd ) { // Only shows effects on caster. + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); } break; - case GN_MANDRAGORA: - if( flag&1 ) { - if ( clif->skill_nodamage(bl, src, skill_id, skill_lv, - sc_start(bl, type, 25 + 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv))) ) - status_zap(bl, 0, status_get_max_sp(bl) * (25 + 5 * skill_lv) / 100); - } else - iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + case WA_SYMPHONY_OF_LOVER: + case MI_RUSH_WINDMILL: + case MI_ECHOSONG: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + sc_start4(bl,type,100,skill_lv,6*skill_lv,(sd?pc->checkskill(sd,WM_LESSON):0),(sd?sd->status.job_level:0),skill->get_time(skill_id,skill_lv)); + else if( sd ) { // Only shows effects on caster. + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + } break; - case GN_SLINGITEM: - if( sd ) { - short ammo_id; - i = sd->equip_index[EQI_AMMO]; - if( i <= 0 ) - break; // No ammo. - ammo_id = sd->inventory_data[i]->nameid; - if( ammo_id <= 0 ) + case MI_HARMONIZE: + if( src != bl ) + clif->skill_nodamage(src, src, skill_id, skill_lv, sc_start(src, type, 100, skill_lv, skill->get_time(skill_id,skill_lv))); + clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id,skill_lv))); + break; + + case WM_DEADHILLHERE: + if( bl->type == BL_PC ) { + if( !status_isdead(bl) ) break; - sd->itemid = ammo_id; - if( itemdb_is_GNbomb(ammo_id) ) { - if(battle->check_target(src,bl,BCT_ENEMY) > 0) {// Only attack if the target is an enemy. - if( ammo_id == 13263 ) - iMap->foreachincell(skill->area_sub,bl->m,bl->x,bl->y,BL_CHAR,src,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); - else - skill->attack(BF_WEAPON,src,src,bl,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag); - } else //Otherwise, it fails, shows animation and removes items. - clif->skill_fail(sd,GN_SLINGITEM_RANGEMELEEATK,0xa,0); - } else if( itemdb_is_GNthrowable(ammo_id) ){ - struct script_code *script = sd->inventory_data[i]->script; - if( !script ) - break; - if( dstsd ) - run_script(script,0,dstsd->bl.id,fake_nd->bl.id); - else - run_script(script,0,src->id,0); + + if( rnd()%100 < 88 + 2 * skill_lv ) { + int heal = tstatus->sp; + if( heal <= 0 ) + heal = 1; + tstatus->hp = heal; + tstatus->sp -= tstatus->sp * ( 120 - 20 * skill_lv ) / 100; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + pc->revive((TBL_PC*)bl,heal,0); + clif->resurrection(bl,1); } } - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1);// This packet is received twice actually, I think it is to show the animation. break; - case GN_MIX_COOKING: - case GN_MAKEBOMB: - case GN_S_PHARMACY: - if( sd ) { - int qty = 1; - sd->skill_id_old = skill_id; - sd->skill_lv_old = skill_lv; - if( skill_id != GN_S_PHARMACY && skill_lv > 1 ) - qty = 10; - clif->cooking_list(sd,(skill_id - GN_MIX_COOKING) + 27,skill_id,qty,skill_id==GN_MAKEBOMB?5:6); + case WM_SIRCLEOFNATURE: + flag |= BCT_SELF|BCT_PARTY|BCT_GUILD; + case WM_VOICEOFSIREN: + if( skill_id != WM_SIRCLEOFNATURE ) + flag &= ~BCT_SELF; + if( flag&1 ) { + sc_start2(bl,type,(skill_id==WM_VOICEOFSIREN)?20+10*skill_lv:100,skill_lv,(skill_id==WM_VOICEOFSIREN)?src->id:0,skill->get_time(skill_id,skill_lv)); + } else { + iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),(skill_id==WM_VOICEOFSIREN)?BL_CHAR|BL_SKILL:BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } break; - case EL_CIRCLE_OF_FIRE: - case EL_PYROTECHNIC: - case EL_HEATER: - case EL_TROPIC: - case EL_AQUAPLAY: - case EL_COOLER: - case EL_CHILLY_AIR: - case EL_GUST: - case EL_BLAST: - case EL_WILD_STORM: - case EL_PETROLOGY: - case EL_CURSED_SOIL: - case EL_UPHEAVAL: - case EL_FIRE_CLOAK: - case EL_WATER_DROP: - case EL_WIND_CURTAIN: - case EL_SOLID_SKIN: - case EL_STONE_SHIELD: - case EL_WIND_STEP: { - struct elemental_data *ele = BL_CAST(BL_ELEM, src); - if( ele ) { - sc_type type2 = type-1; - struct status_change *sc = status_get_sc(&ele->bl); - if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { - elemental_clean_single_effect(ele, skill_id); - } else { - clif->skill_nodamage(src,src,skill_id,skill_lv,1); - clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away. - skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rand()%8,0); - sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); - } + case WM_GLOOMYDAY: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if( dstsd && ( pc->checkskill(dstsd,KN_BRANDISHSPEAR) || pc->checkskill(dstsd,LK_SPIRALPIERCE) || + pc->checkskill(dstsd,CR_SHIELDCHARGE) || pc->checkskill(dstsd,CR_SHIELDBOOMERANG) || + pc->checkskill(dstsd,PA_SHIELDCHAIN) || pc->checkskill(dstsd,LG_SHIELDPRESS) ) ) + { + sc_start(bl,SC_GLOOMYDAY_SK,100,skill_lv,skill->get_time(skill_id,skill_lv)); + break; } - } + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); break; - case EL_FIRE_MANTLE: - case EL_WATER_BARRIER: - case EL_ZEPHYR: - case EL_POWER_OF_GAIA: - clif->skill_nodamage(src,src,skill_id,skill_lv,1); - clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - skill->unitsetting(src,skill_id,skill_lv,bl->x,bl->y,0); + case WM_SATURDAY_NIGHT_FEVER: + if( flag&1 ) { // Affect to all targets arround the caster and caster too. + if( !(tsc && tsc->data[type]) ) + sc_start(bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv)); + } else if( flag&2 ) { + if( src->id != bl->id && battle->check_target(src,bl,BCT_ENEMY) > 0 ) + status_fix_damage(src,bl,9999,clif->damage(src,bl,tick,0,0,9999,0,0,0)); + } else if( sd ) { + short chance = sstatus->int_/6 + sd->status.job_level/5 + skill_lv*4; + if( !sd->status.party_id || (rnd()%100 > chance)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0); + break; + } + if( iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id,skill_lv), + BL_PC, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count) > 7 ) + flag |= 2; + else + flag |= 1; + iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF, skill->castend_nodamage_id); + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start(src,SC_STOP,100,skill_lv,skill->get_time2(skill_id,skill_lv))); + if( flag&2 ) // Dealed here to prevent conflicts + status_fix_damage(src,bl,9999,clif->damage(src,bl,tick,0,0,9999,0,0,0)); + } break; - case EL_WATER_SCREEN: { - struct elemental_data *ele = BL_CAST(BL_ELEM, src); - if( ele ) { - struct status_change *sc = status_get_sc(&ele->bl); - sc_type type2 = type-1; - - clif->skill_nodamage(src,src,skill_id,skill_lv,1); - if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { - elemental_clean_single_effect(ele, skill_id); - } else { - // This not heals at the end. - clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); - sc_start(bl,type,100,src->id,skill->get_time(skill_id,skill_lv)); - } + case WM_SONG_OF_MANA: + case WM_DANCE_WITH_WUG: + case WM_LERADS_DEW: + if( flag&1 ) { // These affect to to all party members near the caster. + struct status_change *sc = status_get_sc(src); + if( sc && sc->data[type] ) { + sc_start2(bl,type,100,skill_lv,sc->data[type]->val2,skill->get_time(skill_id,skill_lv)); } + } else if( sd ) { + short lv = (short)skill_lv; + int count = skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),1); + if( sc_start2(bl,type,100,skill_lv,count,skill->get_time(skill_id,skill_lv)) ) + party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } break; - case KO_KAHU_ENTEN: - case KO_HYOUHU_HUBUKI: - case KO_KAZEHU_SEIRAN: - case KO_DOHU_KOUKAI: - if(sd) { - int ttype = skill->get_ele(skill_id, skill_lv); - clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - pc->add_talisman(sd, skill->get_time(skill_id, skill_lv), 10, ttype); + case WM_MELODYOFSINK: + case WM_BEYOND_OF_WARCRY: + case WM_UNLIMITED_HUMMING_VOICE: + if( flag&1 ) { + sc_start2(bl,type,100,skill_lv,skill_area_temp[0],skill->get_time(skill_id,skill_lv)); + } else { // These affect to all targets arround the caster. + short lv = (short)skill_lv; + skill_area_temp[0] = (sd) ? skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),1) : 50; // 50% chance in non BL_PC (clones). + iMap->foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } break; - case KO_ZANZOU: - if(sd){ - struct mob_data *md; + case WM_RANDOMIZESPELL: { + int improv_skill_id = 0, improv_skill_lv; + do { + i = rnd() % MAX_SKILL_IMPROVISE_DB; + improv_skill_id = skill_improvise_db[i].skill_id; + } while( improv_skill_id == 0 || rnd()%10000 >= skill_improvise_db[i].per ); + improv_skill_lv = 4 + skill_lv; + clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); - md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), 2308, "", SZ_SMALL, AI_NONE); - if( md ) - { - md->master_id = src->id; - md->special_state.ai = AI_ZANZOU; - if( md->deletetimer != INVALID_TIMER ) - iTimer->delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = iTimer->add_timer (iTimer->gettick() + skill->get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0); - mob_spawn( md ); - pc->setinvincibletimer(sd,500);// unlock target lock - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),unit_getdir(bl),0); + if( sd ) { + sd->state.abra_flag = 2; + sd->skillitem = improv_skill_id; + sd->skillitemlv = improv_skill_lv; + clif->item_skill(sd, improv_skill_id, improv_skill_lv); + } else { + struct unit_data *ud = unit_bl2ud(src); + int inf = skill->get_inf(improv_skill_id); + if (!ud) break; + if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { + if (src->type == BL_PET) + bl = (struct block_list*)((TBL_PET*)src)->msd; + if (!bl) bl = src; + unit_skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv); + } else { + int target_id = 0; + if (ud->target) + target_id = ud->target; + else switch (src->type) { + case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; + case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; + } + if (!target_id) + break; + if (skill->get_casttype(improv_skill_id) == CAST_GROUND) { + bl = iMap->id2bl(target_id); + if (!bl) bl = src; + unit_skilluse_pos(src, bl->x, bl->y, improv_skill_id, improv_skill_lv); + } else + unit_skilluse_id(src, target_id, improv_skill_id, improv_skill_lv); + } } } break; - case KO_KYOUGAKU: - if( dstsd && tsc && !tsc->data[type] && rand()%100 < tstatus->int_/2 ){ - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - }else if( sd ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - - case KO_JYUSATSU: - if( dstsd && tsc && !tsc->data[type] && - rand()%100 < ((45+5*skill_lv) + skill_lv*5 - status_get_int(bl)/2) ){//[(Base chance of success) + (Skill Level x 5) - (int / 2)]%. - clif->skill_nodamage(src,bl,skill_id,skill_lv, - status_change_start(bl,type,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),1)); - status_zap(bl, tstatus->max_hp*skill_lv*5/100 , 0); - if( status_get_lv(bl) <= status_get_lv(src) ) - status_change_start(bl,SC_COMA,10,skill_lv,0,src->id,0,0,0); - }else if( sd ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - case KO_GENWAKU: - if ( !map_flag_gvg(src->m) && ( dstsd || dstmd ) && battle->check_target(src,bl,BCT_ENEMY) > 0 ) { - int x = src->x, y = src->y; + case RETURN_TO_ELDICASTES: + case ALL_GUARDIAN_RECALL: + if( sd ) + { + short x, y; // Destiny position. + unsigned short mapindex; - if( sd && rnd()%100 > ((45+5*skill_lv) - status_get_int(bl)/10) ){//[(Base chance of success) - (Intelligence Objectives / 10)]%. - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + if( skill_id == RETURN_TO_ELDICASTES) + { + x = 198; + y = 187; + mapindex = mapindex_name2id(MAP_DICASTES); + } + else + { + x = 44; + y = 151; + mapindex = mapindex_name2id(MAP_MORA); } - if (unit_movepos(src,bl->x,bl->y,0,0)) { - clif->skill_nodamage(src,src,skill_id,skill_lv,1); - clif->slide(src,bl->x,bl->y) ; - sc_start(src,SC_CONFUSION,80,skill_lv,skill->get_time(skill_id,skill_lv)); - if (unit_movepos(bl,x,y,0,0)) - { - clif->skill_damage(bl,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, -1, 6); - if( bl->type == BL_PC && pc_issit((TBL_PC*)bl)) - clif->sitting(bl); //Avoid sitting sync problem - clif->slide(bl,x,y) ; - sc_start(bl,SC_CONFUSION,80,skill_lv,skill->get_time(skill_id,skill_lv)); - } + if(!mapindex) + { //Given map not found? + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + iMap->freeblock_unlock(); + return 0; } + pc->setpos(sd, mapindex, x, y, CLR_TELEPORT); } break; - case OB_AKAITSUKI: - case OB_OBOROGENSOU: - if( sd && ( (skill_id == OB_OBOROGENSOU && bl->type == BL_MOB) // This skill does not work on monsters. - || is_boss(bl) ) ){ // Does not work on Boss monsters. - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + case GM_SANDMAN: + if( tsc ) { + if( tsc->opt1 == OPT1_SLEEP ) + tsc->opt1 = 0; + else + tsc->opt1 = OPT1_SLEEP; + clif->changeoption(bl); + clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); } - case KO_IZAYOI: - case OB_ZANGETSU: - case KG_KYOMU: - case KG_KAGEMUSYA: - clif->skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); break; - case KG_KAGEHUMI: - if( flag&1 ){ - if(tsc && ( tsc->option&(OPTION_CLOAK|OPTION_HIDE) || - tsc->data[SC_CAMOUFLAGE] || tsc->data[SC__SHADOWFORM] || - tsc->data[SC_MARIONETTE] || tsc->data[SC_HARMONIZE])){ - sc_start(src, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - status_change_end(bl, SC_MARIONETTE, INVALID_TIMER); - status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - } - if( skill_area_temp[2] == 1 ){ - clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - sc_start(src, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); - } - }else{ - skill_area_temp[2] = 0; - iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_nodamage_id); + case SO_ARRULLO: + { + // [(15 + 5 * Skill Level) + ( Caster?s INT / 5 ) + ( Caster?s Job Level / 5 ) - ( Target?s INT / 6 ) - ( Target?s LUK / 10 )] % + int rate = (15 + 5 * skill_lv) + status_get_int(src)/5 + (sd ? sd->status.job_level : 0); + rate -= status_get_int(bl)/6 - status_get_luk(bl)/10; + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + sc_start2(bl, type, rate, skill_lv, 1, skill->get_time(skill_id, skill_lv)); } break; - case MH_SILENT_BREEZE: { - struct status_change *ssc = status_get_sc(src); - struct block_list *m_bl = battle->get_master(src); - const enum sc_type scs[] = { - SC_MANDRAGORA, SC_HARMONIZE, SC_DEEPSLEEP, SC_VOICEOFSIREN, SC_SLEEP, SC_CONFUSION, SC_HALLUCINATION - }; - int heal; - if(tsc){ - for (i = 0; i < ARRAYLENGTH(scs); i++) { - if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); - } - if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target - status_change_start(bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); - } - heal = status_get_matk_min(src)*4; - status_heal(bl, heal, 0, 7); - - //now inflict silence on everyone - if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun - status_change_start(src, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); - if(m_bl){ - struct status_change *msc = status_get_sc(m_bl); - if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master - status_change_start(m_bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); - } - if (hd) - skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); - } - break; - case MH_OVERED_BOOST: - if (hd){ - struct block_list *s_bl = battle->get_master(src); - if(hd->homunculus.hunger>50) //reduce hunger - hd->homunculus.hunger = hd->homunculus.hunger/2; - else - hd->homunculus.hunger = min(1,hd->homunculus.hunger); - if(s_bl && s_bl->type==BL_PC){ - status_set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp - clif->send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info - sc_start(s_bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); //gene bonus - } - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); - skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); - } - break; - case MH_GRANITIC_ARMOR: - case MH_PYROCLASTIC: { - struct block_list *s_bl = battle->get_master(src); - if(s_bl) - sc_start2(s_bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); //start on master - sc_start2(bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); - if (hd) - skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); - } - break; - - case MH_LIGHT_OF_REGENE: - if(hd){ - hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750) - if(sd) clif->send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info + case WM_LULLABY_DEEPSLEEP: + if( flag&1 ){ + //[(Skill Level x 4) + (Voice Lessons Skill Level x 2) + (Caster?s Base Level / 15) + (Caster?s Job Level / 5)] % + int rate = (4 * skill_lv) + ( (sd) ? pc->checkskill(sd,WM_LESSON)*2 + sd->status.job_level/5 : 0 ) + status_get_lv(src) / 15; + if( bl != src ) + sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)); + }else { + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ALL|1, skill->castend_nodamage_id); } - //don't break need to start status and start block timer - case MH_STYLE_CHANGE: - case MH_MAGMA_FLOW: - case MH_PAIN_KILLER: - sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); - if (hd) - skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); - break; - case MH_SUMMON_LEGION: - { - int summons[5] = {1004, 1303, 1303, 1994, 1994}; - int qty[5] = {3 , 3 , 4 , 4 , 5}; - struct mob_data *md; - int i, dummy = 0; - - i = iMap->foreachinmap(skill->check_condition_mob_master_sub ,hd->bl.m, BL_MOB, hd->bl.id, summons[skill_lv-1], skill_id, &dummy); - if(i >= qty[skill_lv-1]) - break; - - for(i=0; im, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK); - if (md) { - md->master_id = src->id; - if (md->deletetimer != INVALID_TIMER) - iTimer->delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = iTimer->add_timer(iTimer->gettick() + skill->get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0); - mob_spawn(md); //Now it is ready for spawning. - sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_CANATTACK|MD_AGGRESSIVE, 0, 60000); - } - } - if (hd) - skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); - } - break; - default: - ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skill_id); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - iMap->freeblock_unlock(); - return 1; - } - - if(skill_id != SR_CURSEDCIRCLE){ - struct status_change *sc = status_get_sc(src); - if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] )//Should only remove after the skill had been casted. - status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); - } - - if (dstmd) { //Mob skill event for no damage skills (damage ones are handled in battle_calc_damage) [Skotlex] - mob_log_damage(dstmd, src, 0); //Log interaction (counts as 'attacker' for the exp bonus) - mobskill_event(dstmd, src, tick, MSC_SKILLUSED|(skill_id<<16)); - } - - if( sd && !(flag&1) ) { // ensure that the skill last-cast tick is recorded - sd->canskill_tick = iTimer->gettick(); + break; - if( sd->state.arrow_atk ) { // consume arrow on last invocation to this skill. - battle->consume_ammo(sd, skill_id, skill_lv); - } - skill->onskillusage(sd, bl, skill_id, tick); - // perform skill requirement consumption - skill->consume_requirement(sd,skill_id,skill_lv,2); - } + case SO_SUMMON_AGNI: + case SO_SUMMON_AQUA: + case SO_SUMMON_VENTUS: + case SO_SUMMON_TERA: + if( sd ) { + int elemental_class = skill->get_elemental_type(skill_id,skill_lv); - iMap->freeblock_unlock(); - return 0; -} + // Remove previous elemental fisrt. + if( sd->ed ) + elemental_delete(sd->ed,0); -/*========================================== - * - *------------------------------------------*/ -int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) -{ - struct block_list *target, *src; - struct map_session_data *sd; - struct mob_data *md; - struct unit_data *ud; - struct status_change *sc = NULL; - int inf,inf2,flag = 0; + // Summoning the new one. + if( !elemental_create(sd,elemental_class,skill->get_time(skill_id,skill_lv)) ) { + clif->skill_fail(sd,skill_id,0,0); + break; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - src = iMap->id2bl(id); - if( src == NULL ) - { - ShowDebug("skill_castend_id: src == NULL (tid=%d, id=%d)\n", tid, id); - return 0;// not found - } + case SO_EL_CONTROL: + if( sd ) { + int mode = EL_MODE_PASSIVE; // Standard mode. - ud = unit_bl2ud(src); - if( ud == NULL ) - { - ShowDebug("skill_castend_id: ud == NULL (tid=%d, id=%d)\n", tid, id); - return 0;// ??? - } + if( !sd->ed ) break; - sd = BL_CAST(BL_PC, src); - md = BL_CAST(BL_MOB, src); + if( skill_lv == 4 ) {// At level 4 delete elementals. + elemental_delete(sd->ed, 0); + break; + } + switch( skill_lv ) {// Select mode bassed on skill level used. + case 2: mode = EL_MODE_ASSIST; break; + case 3: mode = EL_MODE_AGGRESSIVE; break; + } + if( !elemental_change_mode(sd->ed,mode) ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - if( src->prev == NULL ) { - ud->skilltimer = INVALID_TIMER; - return 0; - } + case SO_EL_ACTION: + if( sd ) { + int duration = 3000; + if( !sd->ed ) break; + sd->skill_id_old = skill_id; + elemental_action(sd->ed, bl, tick); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + switch(sd->ed->db->class_){ + case 2115:case 2124: + case 2118:case 2121: + duration = 6000; + break; + case 2116:case 2119: + case 2122:case 2125: + duration = 9000; + break; + } + skill->blockpc_start(sd, skill_id, duration, false); + } + break; - if(ud->skill_id != SA_CASTCANCEL && ud->skill_id != SO_SPELLFIST) {// otherwise handled in unit_skillcastcancel() - if( ud->skilltimer != tid ) { - ShowError("skill_castend_id: Timer mismatch %d!=%d!\n", ud->skilltimer, tid); - ud->skilltimer = INVALID_TIMER; - return 0; - } + case SO_EL_CURE: + if( sd ) { + struct elemental_data *ed = sd->ed; + int s_hp = sd->battle_status.hp * 10 / 100, s_sp = sd->battle_status.sp * 10 / 100; + int e_hp, e_sp; - if( sd && ud->skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || ud->skill_id == LG_EXEEDBREAK) ) - {// restore original walk speed - ud->skilltimer = INVALID_TIMER; - status_calc_bl(&sd->bl, SCB_SPEED); - } + if( !ed ) break; + if( !status_charge(&sd->bl,s_hp,s_sp) ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + e_hp = ed->battle_status.max_hp * 10 / 100; + e_sp = ed->battle_status.max_sp * 10 / 100; + status_heal(&ed->bl,e_hp,e_sp,3); + clif->skill_nodamage(src,&ed->bl,skill_id,skill_lv,1); + } + break; - ud->skilltimer = INVALID_TIMER; - } + case GN_CHANGEMATERIAL: + case SO_EL_ANALYSIS: + if( sd ) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + clif->skill_itemlistwindow(sd,skill_id,skill_lv); + } + break; - if (ud->skilltarget == id) - target = src; - else - target = iMap->id2bl(ud->skilltarget); + case GN_BLOOD_SUCKER: + { + struct status_change *sc = status_get_sc(src); - // Use a do so that you can break out of it when the skill fails. - do { - if(!target || target->prev==NULL) break; + if( sc && sc->bs_counter < skill->get_maxcount( skill_id , skill_lv) ) { + if( tsc && tsc->data[type] ){ + (sc->bs_counter)--; + status_change_end(src, type, INVALID_TIMER); // the first one cancels and the last one will take effect resetting the timer + } + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + sc_start2(bl, type, 100, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); + (sc->bs_counter)++; + } else if( sd ) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + break; + } + } + break; - if(src->m != target->m || status_isdead(src)) break; + case GN_MANDRAGORA: + if( flag&1 ) { + if ( clif->skill_nodamage(bl, src, skill_id, skill_lv, + sc_start(bl, type, 25 + 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv))) ) + status_zap(bl, 0, status_get_max_sp(bl) * (25 + 5 * skill_lv) / 100); + } else + iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + break; - switch (ud->skill_id) { - //These should become skill_castend_pos - case WE_CALLPARTNER: - if(sd) clif->callpartner(sd); - case WE_CALLPARENT: - case WE_CALLBABY: - case AM_RESURRECTHOMUN: - case PF_SPIDERWEB: - //Find a random spot to place the skill. [Skotlex] - inf2 = skill->get_splash(ud->skill_id, ud->skill_lv); - ud->skillx = target->x + inf2; - ud->skilly = target->y + inf2; - if (inf2 && !iMap->random_dir(target, &ud->skillx, &ud->skilly)) { - ud->skillx = target->x; - ud->skilly = target->y; + case GN_SLINGITEM: + if( sd ) { + short ammo_id; + i = sd->equip_index[EQI_AMMO]; + if( i <= 0 ) + break; // No ammo. + ammo_id = sd->inventory_data[i]->nameid; + if( ammo_id <= 0 ) + break; + sd->itemid = ammo_id; + if( itemdb_is_GNbomb(ammo_id) ) { + if(battle->check_target(src,bl,BCT_ENEMY) > 0) {// Only attack if the target is an enemy. + if( ammo_id == 13263 ) + iMap->foreachincell(skill->area_sub,bl->m,bl->x,bl->y,BL_CHAR,src,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + else + skill->attack(BF_WEAPON,src,src,bl,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag); + } else //Otherwise, it fails, shows animation and removes items. + clif->skill_fail(sd,GN_SLINGITEM_RANGEMELEEATK,0xa,0); + } else if( itemdb_is_GNthrowable(ammo_id) ){ + struct script_code *script = sd->inventory_data[i]->script; + if( !script ) + break; + if( dstsd ) + run_script(script,0,dstsd->bl.id,fake_nd->bl.id); + else + run_script(script,0,src->id,0); } - ud->skilltimer=tid; - return skill->castend_pos(tid,tick,id,data); - case GN_WALLOFTHORN: - ud->skillx = target->x; - ud->skilly = target->y; - ud->skilltimer = tid; - return skill->castend_pos(tid,tick,id,data); - } + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1);// This packet is received twice actually, I think it is to show the animation. + break; - if(ud->skill_id == RG_BACKSTAP) { - uint8 dir = iMap->calc_dir(src,target->x,target->y),t_dir = unit_getdir(target); - if(check_distance_bl(src, target, 0) || iMap->check_dir(dir,t_dir)) { - break; + case GN_MIX_COOKING: + case GN_MAKEBOMB: + case GN_S_PHARMACY: + if( sd ) { + int qty = 1; + sd->skill_id_old = skill_id; + sd->skill_lv_old = skill_lv; + if( skill_id != GN_S_PHARMACY && skill_lv > 1 ) + qty = 10; + clif->cooking_list(sd,(skill_id - GN_MIX_COOKING) + 27,skill_id,qty,skill_id==GN_MAKEBOMB?5:6); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - } + break; + case EL_CIRCLE_OF_FIRE: + case EL_PYROTECHNIC: + case EL_HEATER: + case EL_TROPIC: + case EL_AQUAPLAY: + case EL_COOLER: + case EL_CHILLY_AIR: + case EL_GUST: + case EL_BLAST: + case EL_WILD_STORM: + case EL_PETROLOGY: + case EL_CURSED_SOIL: + case EL_UPHEAVAL: + case EL_FIRE_CLOAK: + case EL_WATER_DROP: + case EL_WIND_CURTAIN: + case EL_SOLID_SKIN: + case EL_STONE_SHIELD: + case EL_WIND_STEP: { + struct elemental_data *ele = BL_CAST(BL_ELEM, src); + if( ele ) { + sc_type type2 = type-1; + struct status_change *sc = status_get_sc(&ele->bl); - if( ud->skill_id == PR_TURNUNDEAD ) { - struct status_data *tstatus = status_get_status_data(target); - if( !battle->check_undead(tstatus->race, tstatus->def_ele) ) - break; - } + if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { + elemental_clean_single_effect(ele, skill_id); + } else { + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away. + skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rand()%8,0); + sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + } + } + } + break; - if( ud->skill_id == RA_WUGSTRIKE ){ - if( !path_search(NULL,src->m,src->x,src->y,target->x,target->y,1,CELL_CHKNOREACH)) - break; - } + case EL_FIRE_MANTLE: + case EL_WATER_BARRIER: + case EL_ZEPHYR: + case EL_POWER_OF_GAIA: + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + skill->unitsetting(src,skill_id,skill_lv,bl->x,bl->y,0); + break; + + case EL_WATER_SCREEN: { + struct elemental_data *ele = BL_CAST(BL_ELEM, src); + if( ele ) { + struct status_change *sc = status_get_sc(&ele->bl); + sc_type type2 = type-1; - if( ud->skill_id == PR_LEXDIVINA || ud->skill_id == MER_LEXDIVINA ) - { - sc = status_get_sc(target); - if( battle->check_target(src,target, BCT_ENEMY) <= 0 && (!sc || !sc->data[SC_SILENCE]) ) - { //If it's not an enemy, and not silenced, you can't use the skill on them. [Skotlex] - clif->skill_nodamage (src, target, ud->skill_id, ud->skill_lv, 0); - break; + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { + elemental_clean_single_effect(ele, skill_id); + } else { + // This not heals at the end. + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(bl,type,100,src->id,skill->get_time(skill_id,skill_lv)); + } + } } - } - else - { // Check target validity. - inf = skill->get_inf(ud->skill_id); - inf2 = skill->get_inf2(ud->skill_id); - - if(inf&INF_ATTACK_SKILL || - (inf&INF_SELF_SKILL && inf2&INF2_NO_TARGET_SELF) //Combo skills - ) // Casted through combo. - inf = BCT_ENEMY; //Offensive skill. - else if(inf2&INF2_NO_ENEMY) - inf = BCT_NOENEMY; - else - inf = 0; + break; - if(inf2 & (INF2_PARTY_ONLY|INF2_GUILD_ONLY) && src != target) - { - inf |= - (inf2&INF2_PARTY_ONLY?BCT_PARTY:0)| - (inf2&INF2_GUILD_ONLY?BCT_GUILD:0); - //Remove neutral targets (but allow enemy if skill is designed to be so) - inf &= ~BCT_NEUTRAL; + case KO_KAHU_ENTEN: + case KO_HYOUHU_HUBUKI: + case KO_KAZEHU_SEIRAN: + case KO_DOHU_KOUKAI: + if(sd) { + int ttype = skill->get_ele(skill_id, skill_lv); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + ARR_FIND(1, 6, i, sd->charm[i] > 0 && ttype != i); + if( i < 6 ) + pc->del_charm(sd, sd->charm[i], i); // replace with a new one. + pc->add_charm(sd, skill->get_time(skill_id, skill_lv), 10, ttype); } + break; - if( sd && (inf2&INF2_CHORUS_SKILL) && skill->check_pc_partner(sd, ud->skill_id, &ud->skill_lv, 1, 0) < 1 ) { - clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_NEED_HELPER, 0); - break; - } + case KO_ZANZOU: + if(sd){ + struct mob_data *md; - if( ud->skill_id >= SL_SKE && ud->skill_id <= SL_SKA && target->type == BL_MOB ) - { - if( ((TBL_MOB*)target)->class_ == MOBID_EMPERIUM ) - break; - } - else if (inf && battle->check_target(src, target, inf) <= 0){ - if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); - break; + md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), 2308, "", SZ_SMALL, AI_NONE); + if( md ) + { + md->master_id = src->id; + md->special_state.ai = AI_ZANZOU; + if( md->deletetimer != INVALID_TIMER ) + iTimer->delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = iTimer->add_timer (iTimer->gettick() + skill->get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0); + mob_spawn( md ); + pc->setinvincibletimer(sd,500);// unlock target lock + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),unit_getdir(bl),0); + } } + break; - if(inf&BCT_ENEMY && (sc = status_get_sc(target)) && - sc->data[SC_FOGWALL] && - rnd() % 100 < 75) { //Fogwall makes all offensive-type targetted skills fail at 75% - if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0); + case KO_KYOUGAKU: + { + int rate = max(5, (45 + 5 * skill_lv - status_get_int(bl) / 10)); + if( sd && !map_flag_gvg(src->m) ){ + clif->skill_fail(sd, skill_id, USESKILL_FAIL_SIZE, 0); break; + } + if( dstsd && tsc && !tsc->data[type] && rand()%100 < rate ){ + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + }else if( sd ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); } - } + break; - //Avoid doing double checks for instant-cast skills. - if (tid != INVALID_TIMER && !status_check_skilluse(src, target, ud->skill_id, 1)) + case KO_JYUSATSU: + if( dstsd && tsc && !tsc->data[type] && + rand()%100 < (10 * (5 * skill_lv - status_get_int(bl) / 2 + 45 + 5 * skill_lv)) ){ + clif->skill_nodamage(src, bl, skill_id, skill_lv, + status_change_start(bl, type, 10000, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 1)); + status_zap(bl, tstatus->max_hp * skill_lv * 5 / 100 , 0); + if( status_get_lv(bl) <= status_get_lv(src) ) + status_change_start(bl, SC_COMA, skill_lv, skill_lv, 0, src->id, 0, 0, 0); + }else if( sd ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); break; - if(md) { - md->last_thinktime=tick +MIN_MOBTHINKTIME; - if(md->skill_idx >= 0 && md->db->skill[md->skill_idx].emotion >= 0) - clif->emotion(src, md->db->skill[md->skill_idx].emotion); - } + case KO_GENWAKU: + if ( !map_flag_gvg(src->m) && ( dstsd || dstmd ) && !(tstatus->mode&MD_PLANT) && battle->check_target(src,bl,BCT_ENEMY) > 0 ) { + int x = src->x, y = src->y; + if( sd && rnd()%100 > max(5, (45 + 5 * skill_lv) - status_get_int(bl) / 10) ){//[(Base chance of success) - ( target's int / 10)]%. + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + break; + } - if(src != target && battle_config.skill_add_range && - !check_distance_bl(src, target, skill->get_range2(src,ud->skill_id,ud->skill_lv)+battle_config.skill_add_range)) - { - if (sd) { - clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); - if(battle_config.skill_out_range_consume) //Consume items anyway. [Skotlex] - skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,3); + if (unit_movepos(src, bl->x, bl->y, 0, 0)) { + clif->skill_nodamage(src, src, skill_id, skill_lv, 1); + clif->slide(src, bl->x, bl->y) ; + sc_start(src, SC_CONFUSION, 25, skill_lv, skill->get_time(skill_id, skill_lv)); + if ( !is_boss(bl) && unit_stop_walking(&sd->bl, 1) && unit_movepos(bl, x, y, 0, 0) ) + { + if( dstsd && pc_issit(dstsd) ) + pc->setstand(dstsd); + clif->slide(bl, x, y) ; + sc_start(bl, SC_CONFUSION, 75, skill_lv, skill->get_time(skill_id, skill_lv)); + } + } } break; - } - if( sd ) - { - if( !skill->check_condition_castend(sd, ud->skill_id, ud->skill_lv) ) + case OB_AKAITSUKI: + case OB_OBOROGENSOU: + if( sd && ( (skill_id == OB_OBOROGENSOU && bl->type == BL_MOB) // This skill does not work on monsters. + || is_boss(bl) ) ){ // Does not work on Boss monsters. + clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET_PLAYER, 0); break; - else - skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,1); - } -#ifdef OFFICIAL_WALKPATH - if( !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) ) - break; -#endif - if( (src->type == BL_MER || src->type == BL_HOM) && !skill->check_condition_mercenary(src, ud->skill_id, ud->skill_lv, 1) ) + } + case KO_IZAYOI: + case OB_ZANGETSU: + case KG_KYOMU: + case KG_KAGEMUSYA: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); break; - if (ud->state.running && ud->skill_id == TK_JUMPKICK) { - ud->state.running = 0; - status_change_end(src, SC_RUN, INVALID_TIMER); - flag = 1; - } + case KG_KAGEHUMI: + if( flag&1 ){ + if(tsc && ( tsc->option&(OPTION_CLOAK|OPTION_HIDE) || + tsc->data[SC_CAMOUFLAGE] || tsc->data[SC__SHADOWFORM] || + tsc->data[SC_MARIONETTE_MASTER] || tsc->data[SC_HARMONIZE])){ + sc_start(src, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + status_change_end(bl, SC_MARIONETTE_MASTER, INVALID_TIMER); + status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + } + if( skill_area_temp[2] == 1 ){ + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + sc_start(src, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + } + }else{ + skill_area_temp[2] = 0; + iMap->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_nodamage_id); + } + break; - if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH) - unit_stop_walking(src,1); + case MH_SILENT_BREEZE: { + struct status_change *ssc = status_get_sc(src); + struct block_list *m_bl = battle->get_master(src); + const enum sc_type scs[] = { + SC_MANDRAGORA, SC_HARMONIZE, SC_DEEP_SLEEP, SC_SIREN, SC_SLEEP, SC_CONFUSION, SC_ILLUSION + }; + int heal; + if(tsc){ + for (i = 0; i < ARRAYLENGTH(scs); i++) { + if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); + } + if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target + status_change_start(bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); + } + heal = status_get_matk_min(src)*4; + status_heal(bl, heal, 0, 7); - if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) - ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); //Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish] - if (sd) { //Cooldown application - int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv); - for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses. - if (sd->skillcooldown[i].id == ud->skill_id){ - cooldown += sd->skillcooldown[i].val; - break; - } + //now inflict silence on everyone + if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun + status_change_start(src, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); + if(m_bl){ + struct status_change *msc = status_get_sc(m_bl); + if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master + status_change_start(m_bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); } - if(cooldown) - skill->blockpc_start(sd, ud->skill_id, cooldown, false); - } - if( battle_config.display_status_timers && sd ) - clif->status_change(src, SI_ACTIONDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); - if( sd ) - { - switch( ud->skill_id ) - { - case GS_DESPERADO: - sd->canequip_tick = tick + skill->get_time(ud->skill_id, ud->skill_lv); + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + } + break; + case MH_OVERED_BOOST: + if (hd){ + struct block_list *s_bl = battle->get_master(src); + if(hd->homunculus.hunger>50) //reduce hunger + hd->homunculus.hunger = hd->homunculus.hunger/2; + else + hd->homunculus.hunger = min(1,hd->homunculus.hunger); + if(s_bl && s_bl->type==BL_PC){ + status_set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp + clif->send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info + sc_start(s_bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); //gene bonus + } + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + } break; - case CR_GRANDCROSS: - case NPC_GRANDDARKNESS: - if( (sc = status_get_sc(src)) && sc->data[SC_STRIPSHIELD] ) + case MH_GRANITIC_ARMOR: + case MH_PYROCLASTIC: { + struct block_list *s_bl = battle->get_master(src); + if(s_bl) + sc_start2(s_bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); //start on master + sc_start2(bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + } + break; + + case MH_LIGHT_OF_REGENE: + if(hd){ + hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750) + if(sd) clif->send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info + } + //don't break need to start status and start block timer + case MH_STYLE_CHANGE: + case MH_MAGMA_FLOW: + case MH_PAIN_KILLER: + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + break; + case MH_SUMMON_LEGION: { - const struct TimerData *timer = iTimer->get_timer(sc->data[SC_STRIPSHIELD]->timer); - if( timer && timer->func == status_change_timer && DIFF_TICK(timer->tick,iTimer->gettick()+skill->get_time(ud->skill_id, ud->skill_lv)) > 0 ) + int summons[5] = {1004, 1303, 1303, 1994, 1994}; + int qty[5] = {3 , 3 , 4 , 4 , 5}; + struct mob_data *md; + int i, dummy = 0; + + i = iMap->foreachinmap(skill->check_condition_mob_master_sub ,hd->bl.m, BL_MOB, hd->bl.id, summons[skill_lv-1], skill_id, &dummy); + if(i >= qty[skill_lv-1]) break; + + for(i=0; im, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK); + if (md) { + md->master_id = src->id; + if (md->deletetimer != INVALID_TIMER) + iTimer->delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = iTimer->add_timer(iTimer->gettick() + skill->get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0); + mob_spawn(md); //Now it is ready for spawning. + sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_CANATTACK|MD_AGGRESSIVE, 0, 60000); + } + } + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); } - sc_start2(src, SC_STRIPSHIELD, 100, 0, 1, skill->get_time(ud->skill_id, ud->skill_lv)); break; - } - } - if (skill->get_state(ud->skill_id) != ST_MOVE_ENABLE) - unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill->get_walkdelay(ud->skill_id, ud->skill_lv), 1); - - if(battle_config.skill_log && battle_config.skill_log&src->type) - ShowInfo("Type %d, ID %d skill castend id [id =%d, lv=%d, target ID %d]\n", - src->type, src->id, ud->skill_id, ud->skill_lv, target->id); - - iMap->freeblock_lock(); - - // SC_MAGICPOWER needs to switch states before any damage is actually dealt - skill->toggle_magicpower(src, ud->skill_id); - if( ud->skill_id != RA_CAMOUFLAGE ) // only normal attack and auto cast skills benefit from its bonuses - status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); - - if (skill->get_casttype(ud->skill_id) == CAST_NODAMAGE) - skill->castend_nodamage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag); - else - skill->castend_damage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag); - - sc = status_get_sc(src); - if(sc && sc->count) { - if(sc->data[SC_SPIRIT] && - sc->data[SC_SPIRIT]->val2 == SL_WIZARD && - sc->data[SC_SPIRIT]->val3 == ud->skill_id && - ud->skill_id != WZ_WATERBALL) - sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. + default: + ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skill_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + iMap->freeblock_unlock(); + return 1; + } - if( sc->data[SC_DANCING] && skill->get_inf2(ud->skill_id)&INF2_SONG_DANCE && sd ) - skill->blockpc_start(sd,BD_ADAPTATION,3000, false); - } + if(skill_id != SR_CURSEDCIRCLE){ + struct status_change *sc = status_get_sc(src); + if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] )//Should only remove after the skill had been casted. + status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); + } - if( sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish] - sd->skillitem = sd->skillitemlv = 0; + if (dstmd) { //Mob skill event for no damage skills (damage ones are handled in battle_calc_damage) [Skotlex] + mob_log_damage(dstmd, src, 0); //Log interaction (counts as 'attacker' for the exp bonus) + mobskill_event(dstmd, src, tick, MSC_SKILLUSED|(skill_id<<16)); + } - if (ud->skilltimer == INVALID_TIMER) { - if(md) md->skill_idx = -1; - else ud->skill_id = 0; //mobs can't clear this one as it is used for skill condition 'afterskill' - ud->skill_lv = ud->skilltarget = 0; - } - iMap->freeblock_unlock(); - return 1; - } while(0); + if( sd && !(flag&1) ) { // ensure that the skill last-cast tick is recorded + sd->canskill_tick = iTimer->gettick(); - //Skill failed. - if (ud->skill_id == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL])) - { //When Asura fails... (except when it fails from Fog of Wall) - //Consume SP/spheres - skill->consume_requirement(sd,ud->skill_id, ud->skill_lv,1); - status_set_sp(src, 0, 0); - sc = &sd->sc; - if (sc->count) - { //End states - status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); -#ifdef RENEWAL - sc_start(src, SC_EXTREMITYFIST2, 100, ud->skill_lv, skill->get_time(ud->skill_id, ud->skill_lv)); -#endif - } - if (target && target->m == src->m) - { //Move character to target anyway. - int dir, x, y; - dir = iMap->calc_dir(src,target->x,target->y); - if( dir > 0 && dir < 4) x = -2; - else if( dir > 4 ) x = 2; - else x = 0; - if( dir > 2 && dir < 6 ) y = -2; - else if( dir == 7 || dir < 2 ) y = 2; - else y = 0; - if (unit_movepos(src, src->x+x, src->y+y, 1, 1)) - { //Display movement + animation. - clif->slide(src,src->x,src->y); - clif->skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skill_id, ud->skill_lv, 5); - } - clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + if( sd->state.arrow_atk ) { // consume arrow on last invocation to this skill. + battle->consume_ammo(sd, skill_id, skill_lv); } + skill->onskillusage(sd, bl, skill_id, tick); + // perform skill requirement consumption + skill->consume_requirement(sd,skill_id,skill_lv,2); } - ud->skill_id = ud->skill_lv = ud->skilltarget = 0; - if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) - ud->canact_tick = tick; - //You can't place a skill failed packet here because it would be - //sent in ALL cases, even cases where skill_check_condition fails - //which would lead to double 'skill failed' messages u.u [Skotlex] - if(sd) - sd->skillitem = sd->skillitemlv = 0; - else if(md) - md->skill_idx = -1; + iMap->freeblock_unlock(); return 0; } @@ -9528,7 +9392,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) skill->blockpc_start(sd, ud->skill_id, cooldown, false); } if( battle_config.display_status_timers && sd ) - clif->status_change(src, SI_ACTIONDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); + clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); // if( sd ) // { // switch( ud->skill_id ) @@ -9574,6 +9438,143 @@ static int skill_count_wos(struct block_list *bl,va_list ap) { } return 0; } + +/*========================================== + * + *------------------------------------------*/ +int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char *map) +{ + nullpo_ret(sd); + +//Simplify skill_failed code. +#define skill_failed(sd) { sd->menuskill_id = sd->menuskill_val = 0; } + if(skill_id != sd->menuskill_id) + return 0; + + if( sd->bl.prev == NULL || pc_isdead(sd) ) { + skill_failed(sd); + return 0; + } + + if( ( sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING ) || sd->sc.option&OPTION_HIDE ) { + skill_failed(sd); + return 0; + } + if(sd->sc.count && ( + sd->sc.data[SC_SILENCE] || + sd->sc.data[SC_ROKISWEIL] || + sd->sc.data[SC_AUTOCOUNTER] || + sd->sc.data[SC_STEELBODY] || + (sd->sc.data[SC_DANCING] && skill_id < RK_ENCHANTBLADE && !pc->checkskill(sd, WM_LESSON)) || + sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || + sd->sc.data[SC_BASILICA] || + sd->sc.data[SC_MARIONETTE_MASTER] || + sd->sc.data[SC_WHITEIMPRISON] || + (sd->sc.data[SC_STASIS] && skill->block_check(&sd->bl, SC_STASIS, skill_id)) || + (sd->sc.data[SC_KG_KAGEHUMI] && skill->block_check(&sd->bl, SC_KG_KAGEHUMI, skill_id)) || + sd->sc.data[SC_OBLIVIONCURSE] || + sd->sc.data[SC__MANHOLE] || + (sd->sc.data[SC_VOLCANIC_ASH] && rnd()%2) //50% fail chance under ASH + )) { + skill_failed(sd); + return 0; + } + + pc_stop_attack(sd); + pc_stop_walking(sd,0); + + if(battle_config.skill_log && battle_config.skill_log&BL_PC) + ShowInfo("PC %d skill castend skill =%d map=%s\n",sd->bl.id,skill_id,map); + + if(strcmp(map,"cancel")==0) { + skill_failed(sd); + return 0; + } + + switch(skill_id) { + case AL_TELEPORT: + if(strcmp(map,"Random")==0) + pc->randomwarp(sd,CLR_TELEPORT); + else if (sd->menuskill_val > 1) //Need lv2 to be able to warp here. + pc->setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + break; + + case AL_WARP: + { + const struct point *p[4]; + struct skill_unit_group *group; + int i, lv, wx, wy; + int maxcount=0; + int x,y; + unsigned short mapindex; + + mapindex = mapindex_name2id((char*)map); + sd->state.workinprogress = 0; + if(!mapindex) { //Given map not found? + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + skill_failed(sd); + return 0; + } + p[0] = &sd->status.save_point; + p[1] = &sd->status.memo_point[0]; + p[2] = &sd->status.memo_point[1]; + p[3] = &sd->status.memo_point[2]; + + if((maxcount = skill->get_maxcount(skill_id, sd->menuskill_val)) > 0) { + for(i=0;iud.skillunit[i] && maxcount;i++) { + if(sd->ud.skillunit[i]->skill_id == skill_id) + maxcount--; + } + if(!maxcount) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + skill_failed(sd); + return 0; + } + } + + lv = sd->skillitem==skill_id?sd->skillitemlv:pc->checkskill(sd,skill_id); + wx = sd->menuskill_val>>16; + wy = sd->menuskill_val&0xffff; + + if( lv <= 0 ) return 0; + if( lv > 4 ) lv = 4; // crash prevention + + // check if the chosen map exists in the memo list + ARR_FIND( 0, lv, i, mapindex == p[i]->map ); + if( i < lv ) { + x=p[i]->x; + y=p[i]->y; + } else { + skill_failed(sd); + return 0; + } + + if(!skill->check_condition_castend(sd, sd->menuskill_id, lv)) { // This checks versus skill_id/skill_lv... + skill_failed(sd); + return 0; + } + + skill->consume_requirement(sd,sd->menuskill_id,lv,2); + sd->skillitem = sd->skillitemlv = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish] + + if((group=skill->unitsetting(&sd->bl,skill_id,lv,wx,wy,0))==NULL) { + skill_failed(sd); + return 0; + } + + group->val1 = (group->val1<<16)|(short)0; + // record the destination coordinates + group->val2 = (x<<16)|y; + group->val3 = mapindex; + } + break; + } + + sd->menuskill_id = sd->menuskill_val = 0; + return 0; +#undef skill_failed +} + /*========================================== * *------------------------------------------*/ @@ -9740,6 +9741,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case NJ_HUUMA: #endif case NPC_EVILLAND: + case WL_COMET: case RA_ELECTRICSHOCKER: case RA_CLUSTERBOMB: case RA_MAGENTATRAP: @@ -9776,6 +9778,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case MH_POISON_MIST: case MH_STEINWAND: case MH_XENO_SLASHER: + case NC_MAGMA_ERUPTION: flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). case GS_GROUNDDRIFT: //Ammo should be deleted right away. skill->unitsetting(src,skill_id,skill_lv,x,y,0); @@ -10038,6 +10041,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case NC_COLDSLOWER: case NC_ARMSCANNON: case RK_DRAGONBREATH: + case RK_DRAGONBREATH_WATER: i = skill->get_splash(skill_id,skill_lv); iMap->foreachinarea(skill->area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); @@ -10070,17 +10074,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui iMap->foreachinarea(skill->area_sub, src->m, x - i, y - i, x + i, y + i, BL_CHAR, src, ALL_RESURRECTION, 1, tick, flag|BCT_NOENEMY|1,skill->castend_nodamage_id); } break; - /** - * Warlock - **/ - case WL_COMET: - if( sc ) { - sc->comet_x = x; - sc->comet_y = y; - } - i = skill->get_splash(skill_id,skill_lv); - iMap->foreachinarea(skill->area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); - break; case WL_EARTHSTRAIN: { @@ -10095,7 +10088,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case 2: sx = x - i; break; case 6: sx = x + i; break; } - skill->addtimerskill(src,iTimer->gettick() + (150 * i),0,sx,sy,skill_id,skill_lv,dir,flag&2); + skill->addtimerskill(src,iTimer->gettick() + (50 * i),0,sx,sy,skill_id,skill_lv,dir,flag&2); } } break; @@ -10142,10 +10135,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui break; case SC_FEINTBOMB: - clif->skill_nodamage(src,src,skill_id,skill_lv,1); skill->unitsetting(src,skill_id,skill_lv,x,y,0); // Set bomb on current Position + clif->skill_nodamage(src,src,skill_id,skill_lv,1); if( skill->blown(src,src,6,unit_getdir(src),0) ) - skill->castend_nodamage_id(src,src,TF_HIDING,1,tick,0); + skill->castend_nodamage_id(src,src,TF_HIDING,1,tick,0x2); break; case LG_OVERBRAND: @@ -10279,141 +10272,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui return 0; } -/*========================================== - * - *------------------------------------------*/ -int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char *map) -{ - nullpo_ret(sd); - -//Simplify skill_failed code. -#define skill_failed(sd) { sd->menuskill_id = sd->menuskill_val = 0; } - if(skill_id != sd->menuskill_id) - return 0; - - if( sd->bl.prev == NULL || pc_isdead(sd) ) { - skill_failed(sd); - return 0; - } - - if( ( sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING ) || sd->sc.option&OPTION_HIDE ) { - skill_failed(sd); - return 0; - } - if(sd->sc.count && ( - sd->sc.data[SC_SILENCE] || - sd->sc.data[SC_ROKISWEIL] || - sd->sc.data[SC_AUTOCOUNTER] || - sd->sc.data[SC_STEELBODY] || - (sd->sc.data[SC_DANCING] && skill_id < RK_ENCHANTBLADE && !pc->checkskill(sd, WM_LESSON)) || - sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - sd->sc.data[SC_BASILICA] || - sd->sc.data[SC_MARIONETTE] || - sd->sc.data[SC_WHITEIMPRISON] || - (sd->sc.data[SC_STASIS] && skill->block_check(&sd->bl, SC_STASIS, skill_id)) || - (sd->sc.data[SC_KAGEHUMI] && skill->block_check(&sd->bl, SC_KAGEHUMI, skill_id)) || - sd->sc.data[SC_OBLIVIONCURSE] || - sd->sc.data[SC__MANHOLE] || - (sd->sc.data[SC_ASH] && rnd()%2) //50% fail chance under ASH - )) { - skill_failed(sd); - return 0; - } - - pc_stop_attack(sd); - pc_stop_walking(sd,0); - - if(battle_config.skill_log && battle_config.skill_log&BL_PC) - ShowInfo("PC %d skill castend skill =%d map=%s\n",sd->bl.id,skill_id,map); - - if(strcmp(map,"cancel")==0) { - skill_failed(sd); - return 0; - } - - switch(skill_id) { - case AL_TELEPORT: - if(strcmp(map,"Random")==0) - pc->randomwarp(sd,CLR_TELEPORT); - else if (sd->menuskill_val > 1) //Need lv2 to be able to warp here. - pc->setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - break; - - case AL_WARP: - { - const struct point *p[4]; - struct skill_unit_group *group; - int i, lv, wx, wy; - int maxcount=0; - int x,y; - unsigned short mapindex; - - mapindex = mapindex_name2id((char*)map); - if(!mapindex) { //Given map not found? - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - skill_failed(sd); - return 0; - } - p[0] = &sd->status.save_point; - p[1] = &sd->status.memo_point[0]; - p[2] = &sd->status.memo_point[1]; - p[3] = &sd->status.memo_point[2]; - - if((maxcount = skill->get_maxcount(skill_id, sd->menuskill_val)) > 0) { - for(i=0;iud.skillunit[i] && maxcount;i++) { - if(sd->ud.skillunit[i]->skill_id == skill_id) - maxcount--; - } - if(!maxcount) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - skill_failed(sd); - return 0; - } - } - - lv = sd->skillitem==skill_id?sd->skillitemlv:pc->checkskill(sd,skill_id); - wx = sd->menuskill_val>>16; - wy = sd->menuskill_val&0xffff; - - if( lv <= 0 ) return 0; - if( lv > 4 ) lv = 4; // crash prevention - - // check if the chosen map exists in the memo list - ARR_FIND( 0, lv, i, mapindex == p[i]->map ); - if( i < lv ) { - x=p[i]->x; - y=p[i]->y; - } else { - skill_failed(sd); - return 0; - } - - if(!skill->check_condition_castend(sd, sd->menuskill_id, lv)) { // This checks versus skill_id/skill_lv... - skill_failed(sd); - return 0; - } - - skill->consume_requirement(sd,sd->menuskill_id,lv,2); - sd->skillitem = sd->skillitemlv = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish] - - if((group=skill->unitsetting(&sd->bl,skill_id,lv,wx,wy,0))==NULL) { - skill_failed(sd); - return 0; - } - - group->val1 = (group->val1<<16)|(short)0; - // record the destination coordinates - group->val2 = (x<<16)|y; - group->val3 = mapindex; - } - break; - } - - sd->menuskill_id = sd->menuskill_val = 0; - return 0; -#undef skill_failed -} - /// transforms 'target' skill unit into dissonance (if conditions are met) int skill_dance_overlap_sub(struct block_list* bl, va_list ap) { struct skill_unit* target = (struct skill_unit*)bl; @@ -10713,8 +10571,13 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill } break; case DC_DONTFORGETME: +#ifdef RENEWAL + val1 = status->dex/10 + 3*skill_lv; // ASPD decrease + val2 = status->agi/10 + 2*skill_lv; // Movement speed adjustment. +#else val1 = status->dex/10 + 3*skill_lv + 5; // ASPD decrease val2 = status->agi/10 + 3*skill_lv + 5; // Movement speed adjustment. +#endif if(sd){ val1 += pc->checkskill(sd,DC_DANCINGLESSON); val2 += pc->checkskill(sd,DC_DANCINGLESSON); @@ -10734,9 +10597,15 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill } break; case BA_ASSASSINCROSS: +#ifdef RENEWAL + val1 = 10 + skill_lv + (status->agi/10); // ASPD increase + if(sd) + val1 += 4*pc->checkskill(sd,BA_MUSICALLESSON); +#else val1 = 100+(10*skill_lv)+(status->agi/10); // ASPD increase if(sd) val1 += 5*pc->checkskill(sd,BA_MUSICALLESSON); +#endif break; case DC_FORTUNEKISS: val1 = 10+skill_lv+(status->luk/10); // Critical increase @@ -10823,6 +10692,12 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill case GD_HAWKEYES: limit = 1000000;//it doesn't matter break; + case WL_COMET: + if( sc ) { + sc->comet_x = x; + sc->comet_y = y; + } + break; case LG_BANDING: limit = -1; break; @@ -10841,7 +10716,6 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill break; case SO_VACUUM_EXTREME: range++; - break; case SC_BLOODYLUST: skill->clear_group(src, 32); @@ -10853,13 +10727,13 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill break; case KO_ZENKAI: if( sd ){ - ARR_FIND(1, 6, i, sd->talisman[i] > 0); + ARR_FIND(1, 6, i, sd->charm[i] > 0); if( i < 5 ){ - val1 = sd->talisman[i]; // no. of aura + val1 = sd->charm[i]; // no. of aura val2 = i; // aura type limit += val1 * 1000; subunt = i - 1; - pc->del_talisman(sd, sd->talisman[i], i); + pc->del_charm(sd, sd->charm[i], i); } } break; @@ -11151,7 +11025,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned case UNT_INTOABYSS: case UNT_SIEGFRIED: //Needed to check when a dancer/bard leaves their ensemble area. - if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) + if (sg->src_id==bl->id && !(sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) return skill_id; if (!sce) sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); @@ -11164,7 +11038,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned case UNT_DONTFORGETME: case UNT_FORTUNEKISS: case UNT_SERVICEFORYOU: - if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) + if (sg->src_id==bl->id && !(sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) return 0; if (!sc) return 0; @@ -11217,7 +11091,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned case UNT_VOLCANIC_ASH: if (!sce) - sc_start(bl, SC_ASH, 100, sg->skill_lv, skill->get_time(MH_VOLCANIC_ASH, sg->skill_lv)); + sc_start(bl, SC_VOLCANIC_ASH, 100, sg->skill_lv, skill->get_time(MH_VOLCANIC_ASH, sg->skill_lv)); break; case UNT_GD_LEADERSHIP: @@ -11543,7 +11417,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( md && md->class_ == MOBID_EMPERIUM ) break; #endif - if( sg->src_id == bl->id && !(tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_BARDDANCER) ) + if( sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER) ) break; // affects self only when soullinked heal = skill->calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true); if( tsc->data[SC_AKAITSUKI] && heal ) @@ -11574,7 +11448,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns status_heal(bl,heal,0,0); break; case 1: // End all negative status - status_change_clear_buffs(bl,6); + status_change_clear_buffs(bl,2); if (tsd) clif->gospel_info(tsd, 0x15); break; case 2: // Immunity to all status @@ -11597,7 +11471,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns sc_start(bl,SC_BLESSING,100,10,time); break; case 7: // Level 10 Increase AGI - sc_start(bl,SC_INCREASEAGI,100,10,time); + sc_start(bl,SC_INC_AGI,100,10,time); break; case 8: // Enchant weapon with Holy element sc_start(bl,SC_ASPERSIO,100,1,time); @@ -11678,6 +11552,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_FIREWALK: case UNT_ELECTRICWALK: case UNT_PSYCHIC_WAVE: + case UNT_MAGMA_ERUPTION: + case UNT_MAKIBISHI: skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; @@ -11723,7 +11599,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns } } /* Enable this if kRO fix the current skill. Currently no damage on undead and demon monster. [Jobbie] - else if( battle->check_target(ss, bl, BCT_ENEMY) > 0 && battle_check_undead(tstatus->race, tstatus->def_ele) ) + else if( battle->check_target(ss, bl, BCT_ENEMY) > 0 && battle->check_undead(tstatus->race, tstatus->def_ele) ) skill->castend_damage_id(&src->bl, bl, sg->skill_id, sg->skill_lv, 0, 0);*/ break; @@ -11775,7 +11651,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns } else sec = 3000; // Couldn't trap it? sg->limit = DIFF_TICK(tick, sg->tick) + sec; - } else if( tsc->data[SC_THORNSTRAP] && bl->id == sg->val2 ) + } else if( tsc->data[SC_THORNS_TRAP] && bl->id == sg->val2 ) skill->attack(skill->get_type(GN_THORNS_TRAP), ss, ss, bl, sg->skill_id, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION); } break; @@ -11786,7 +11662,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case 1: case 2: default: - sc_start(bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, + sc_start4(bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, 0, ss->id, 0, skill->get_time2(sg->skill_id, sg->skill_lv)); skill->attack(skill->get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0); @@ -11903,36 +11779,31 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_ZENKAI_WATER: sc_start(bl, SC_CRYSTALIZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); sc_start(bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_FREEZING, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_FROSTMISTY, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_ZENKAI_LAND: sc_start(bl, SC_STONE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); sc_start(bl, SC_POISON, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_ZENKAI_FIRE: - sc_start(bl, SC_BURNING, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start4(bl, SC_BURNING, sg->val1*5, sg->skill_lv, 0, ss->id, 0, skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_ZENKAI_WIND: sc_start(bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); sc_start(bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_DEEPSLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_DEEP_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; } }else sc_start2(bl,type,100,sg->val1,sg->val2,skill->get_time2(sg->skill_id, sg->skill_lv)); break; - case UNT_MAKIBISHI: - skill->attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - sg->limit = DIFF_TICK(tick, sg->tick); - sg->unit_id = UNT_USED_TRAPS; - break; - case UNT_LAVA_SLIDE: skill->attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); if(++sg->val1 > 4) //after 5 stop hit and destroy me sg->limit = DIFF_TICK(tick, sg->tick); break; + case UNT_POISON_MIST: skill->attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); status_change_start(bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill->get_time2(sg->skill_id, sg->skill_lv), 2|8); @@ -12234,7 +12105,7 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap) { return 1; case WL_COMET: // Comet does not consume Red Gemstones when there is at least 1 Warlock class next to the caster - if( ( sd->class_&MAPID_THIRDMASK ) == MAPID_WARLOCK ) + if( ( tsd->class_&MAPID_THIRDMASK ) == MAPID_WARLOCK ) p_sd[(*c)++] = tsd->bl.id; return 1; case LG_RAYOFGENESIS: @@ -12469,11 +12340,11 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case BS_ADRENALINE: case WS_WEAPONREFINE: case BS_WEAPONPERFECT: case WS_CARTTERMINATION: case BS_OVERTHRUST: case WS_OVERTHRUSTMAX: - case BS_MAXIMIZE: case NC_AXEBOOMERANG: - case BS_ADRENALINE2: case NC_POWERSWING: - case BS_UNFAIRLYTRICK: case NC_AXETORNADO: + case BS_MAXIMIZE: + case BS_ADRENALINE2: + case BS_UNFAIRLYTRICK: case BS_GREED: - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR,0); return 0; default: //Only Mechanic exlcusive skill can be used. break; @@ -12529,30 +12400,43 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id return 0; if(sc->data[SC_BLADESTOP]) break; - if(sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_TRIPLEATTACK) + if( (i=(sc && sc->data[SC_COMBOATTACK])) && sc->data[SC_COMBOATTACK]->val1 == MO_TRIPLEATTACK ) break; + if( i ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_TRIPLEATTACK); return 0; case MO_COMBOFINISH: - if(!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_CHAINCOMBO)) + if(!sc) return 0; - break; + if( (i=(sc && sc->data[SC_COMBOATTACK])) && sc->data[SC_COMBOATTACK]->val1 == MO_CHAINCOMBO ) + break; + if( i ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_CHAINCOMBO); + return 0; case CH_TIGERFIST: - if(!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == MO_COMBOFINISH)) + if(!sc) return 0; - break; + if( (i=(sc && sc->data[SC_COMBOATTACK])) && sc->data[SC_COMBOATTACK]->val1 == MO_COMBOFINISH ) + break; + if( i ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, MO_COMBOFINISH); + return 0; case CH_CHAINCRUSH: - if(!(sc && sc->data[SC_COMBO])) - return 0; - if(sc->data[SC_COMBO]->val1 != MO_COMBOFINISH && sc->data[SC_COMBO]->val1 != CH_TIGERFIST) + if(!sc) return 0; - break; + if( (i=(sc && sc->data[SC_COMBOATTACK])) && sc->data[SC_COMBOATTACK]->val1 == CH_TIGERFIST ) + break; + if( i ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, CH_TIGERFIST); + return 0; case MO_EXTREMITYFIST: // if(sc && sc->data[SC_EXTREMITYFIST]) //To disable Asura during the 5 min skill block uncomment this... // return 0; if( sc && (sc->data[SC_BLADESTOP] || sc->data[SC_CURSEDCIRCLE_ATKER]) ) break; - if( sc && sc->data[SC_COMBO] ) { - switch(sc->data[SC_COMBO]->val1) { + if( sc && sc->data[SC_COMBOATTACK] ) + { + switch(sc->data[SC_COMBOATTACK]->val1) { case MO_COMBOFINISH: case CH_TIGERFIST: case CH_CHAINCRUSH: @@ -12594,17 +12478,17 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case TK_COUNTER: if ((sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) return 0; //Anti-Soul Linker check in case you job-changed with Stances active. - if(!(sc && sc->data[SC_COMBO]) || sc->data[SC_COMBO]->val1 == TK_JUMPKICK) + if(!(sc && sc->data[SC_COMBOATTACK]) || sc->data[SC_COMBOATTACK]->val1 == TK_JUMPKICK) return 0; //Combo needs to be ready - if (sc->data[SC_COMBO]->val3) { //Kick chain + if (sc->data[SC_COMBOATTACK]->val3) { //Kick chain //Do not repeat a kick. - if (sc->data[SC_COMBO]->val3 != skill_id) + if (sc->data[SC_COMBOATTACK]->val3 != skill_id) break; - status_change_end(&sd->bl, SC_COMBO, INVALID_TIMER); + status_change_end(&sd->bl, SC_COMBOATTACK, INVALID_TIMER); return 0; } - if(sc->data[SC_COMBO]->val1 != skill_id && !( sd && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )) { //Cancel combo wait. + if(sc->data[SC_COMBOATTACK]->val1 != skill_id && !( sd && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )) { //Cancel combo wait. unit_cancel_combo(&sd->bl); return 0; } @@ -12638,12 +12522,12 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id break; case SL_SMA: - if(!(sc && sc->data[SC_SMA])) + if(!(sc && sc->data[SC_SMA_READY])) return 0; break; case HT_POWER: - if(!(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_id)) + if(!(sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == skill_id)) return 0; break; @@ -12709,7 +12593,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; case SG_FUSION: - if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_STAR) + if (sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_STAR) break; //Auron insists we should implement SP consumption when you are not Soul Linked. [Skotlex] //Only invoke on skill begin cast (instant cast skill). [Kevin] @@ -12751,7 +12635,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id return 0; } case NJ_BUNSINJYUTSU: - if (!(sc && sc->data[SC_NEN])) { + if (!(sc && sc->data[SC_NJ_NEN])) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } @@ -12824,13 +12708,36 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case WL_SUMMONBL: case WL_SUMMONWB: case WL_SUMMONSTONE: - if( sc ) + case WL_TETRAVORTEX: + case WL_RELEASE: { - ARR_FIND(SC_SPHERE_1,SC_SPHERE_5+1,i,!sc->data[i]); - if( i == SC_SPHERE_5+1 ) - { // No more free slots - clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); - return 0; + int x = SC_SUMMON1; + i = 0; + for(; x <= SC_SUMMON5; x++) + if( sc && sc->data[x] ) + i++; + + switch(skill_id){ + case WL_TETRAVORTEX: + if( i < 4 ){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0); + return 0; + } + break; + case WL_RELEASE: + for(x = SC_SPELLBOOK7; x >= SC_SPELLBOOK1; x--) + if( sc && sc->data[x] ) + i++; + if( i == 0 ){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON_NONE,0); + return 0; + } + break; + default: + if( i == 5 ){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); + return 0; + } } } break; @@ -12845,7 +12752,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id break; case GC_COUNTERSLASH: case GC_WEAPONCRUSH: - if( !(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == GC_WEAPONBLOCKING) ) { + if( !(sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == GC_WEAPONBLOCKING) ) { clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_WEAPONBLOCKING, 0); return 0; } @@ -12854,26 +12761,26 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id * Ranger **/ case RA_WUGMASTERY: - if( pc_isfalcon(sd) || pc_isridingwug(sd) || sd->sc.data[SC__GROOMY]) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if( pc_isfalcon(sd) || pc_isridingwug(sd) || sd->sc.data[SC__GROOMY] ) { + clif->skill_fail(sd,skill_id,sd->sc.data[SC__GROOMY]?USESKILL_FAIL_MANUAL_NOTIFY:USESKILL_FAIL_CONDITION,0); return 0; } break; case RA_WUGSTRIKE: if( !pc_iswug(sd) && !pc_isridingwug(sd) ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0); return 0; } break; case RA_WUGRIDER: if( pc_isfalcon(sd) || ( !pc_isridingwug(sd) && !pc_iswug(sd) ) ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0); return 0; } break; case RA_WUGDASH: if(!pc_isridingwug(sd)) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0); return 0; } break; @@ -12915,10 +12822,13 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id } break; case SR_FALLENEMPIRE: - if( !(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_DRAGONCOMBO) ) + if( !sc ) return 0; - break; - + if( (i=(sc && sc->data[SC_COMBOATTACK])) && sc->data[SC_COMBOATTACK]->val1 == SR_DRAGONCOMBO ) + break; + if( i ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_COMBOSKILL, SR_DRAGONCOMBO); + return 0; case SR_CRESCENTELBOW: if( sc && sc->data[SC_CRESCENTELBOW] ) { clif->skill_fail(sd, skill_id, USESKILL_FAIL_DUPLICATE, 0); @@ -12973,7 +12883,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id break; case SO_EL_CONTROL: if( !sd->status.ele_id || !sd->ed ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_EL_SUMMON,0); return 0; } break; @@ -12985,7 +12895,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id break; case LG_REFLECTDAMAGE: case CR_REFLECTSHIELD: - if( sc && sc->data[SC_KYOMU] && rand()%100 < 30){ + if( sc && sc->data[SC_KYOMU] && rand()%100 < 5 * sc->data[SC_KYOMU]->val1 ){ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } @@ -12996,18 +12906,17 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case KO_DOHU_KOUKAI: { int ttype = skill->get_ele(skill_id, skill_lv); - ARR_FIND(1, 5, i, sd->talisman[i] > 0 && i != ttype); - if( (i < 5 && i != ttype) || sd->talisman[ttype] >= 10 ){ - clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + if( sd->charm[ttype] >= 10 ){ + clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0); return 0; } } break; case KO_KAIHOU: case KO_ZENKAI: - ARR_FIND(1, 6, i, sd->talisman[i] > 0); + ARR_FIND(1, 6, i, sd->charm[i] > 0); if( i > 4 ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); return 0; } break; @@ -13051,7 +12960,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id } case ST_CART: if(!pc_iscarton(sd)) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_CART,0); return 0; } break; @@ -13069,7 +12978,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id break; case ST_EXPLOSIONSPIRITS: if(!(sc && sc->data[SC_EXPLOSIONSPIRITS])) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_EXPLOSIONSPIRITS,0); return 0; } break; @@ -13080,7 +12989,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id } break; case ST_MOVE_ENABLE: - if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_id) + if (sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == skill_id) sd->ud.canmove_tick = iTimer->gettick(); //When using a combo, cancel the can't move delay to enable the skill. [Skotlex] if (!unit_can_move(&sd->bl)) { @@ -13089,7 +12998,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id } break; case ST_WATER: - if (sc && (sc->data[SC_DELUGE] || sc->data[SC_SUITON])) + if (sc && (sc->data[SC_DELUGE] || sc->data[SC_NJ_SUITON])) break; if (iMap->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER)) break; @@ -13097,7 +13006,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id return 0; case ST_RIDINGDRAGON: if( !pc_isridingdragon(sd) ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_DRAGON,0); return 0; } break; @@ -13115,7 +13024,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id break; case ST_MADO: if( !pc_ismadogear(sd) ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR,0); return 0; } break; @@ -13182,7 +13091,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id return 0; } - if( sd->sc.data[SC_COMBO] ) { + if( sd->sc.data[SC_COMBOATTACK] ) { switch( skill_id ) { case MO_CHAINCOMBO: case MO_COMBOFINISH: @@ -13329,7 +13238,10 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, if( require.ammo ) { //Skill requires stuff equipped in the arrow slot. if((i=sd->equip_index[EQI_AMMO]) < 0 || !sd->inventory_data[i] ) { - clif->arrow_fail(sd,0); + if( require.ammo&1<<8 ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_CANONBALL,0); + else + clif->arrow_fail(sd,0); return 0; } else if( sd->status.inventory[i].amount < require.ammo_qty ) { char e_msg[100]; @@ -13353,12 +13265,39 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, continue; index[i] = pc->search_inventory(sd,require.itemid[i]); if( index[i] < 0 || sd->status.inventory[index[i]].amount < require.amount[i] ) { - if( require.itemid[i] == ITEMID_RED_GEMSTONE ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_REDJAMSTONE,0);// red gemstone required - else if( require.itemid[i] == ITEMID_BLUE_GEMSTONE ) - clif->skill_fail(sd,skill_id,USESKILL_FAIL_BLUEJAMSTONE,0);// blue gemstone required - else - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + useskill_fail_cause cause = USESKILL_FAIL_NEED_ITEM; + switch( skill_id ){ + case NC_SILVERSNIPER: + case NC_MAGICDECOY: + cause = USESKILL_FAIL_STUFF_INSUFFICIENT; + break; + default: + switch(require.itemid[i]){ + case ITEMID_RED_GEMSTONE: + cause = USESKILL_FAIL_REDJAMSTONE; break; + case ITEMID_BLUE_GEMSTONE: + cause = USESKILL_FAIL_BLUEJAMSTONE; break; + case ITEMID_HOLY_WATER: + cause = USESKILL_FAIL_HOLYWATER; break; + case ITEMID_ANCILLA: + cause = USESKILL_FAIL_ANCILLA; break; + case ITEMID_ACCELERATOR: + case ITEMID_HOVERING_BOOSTER: + case ITEMID_SUICIDAL_DEVICE: + case ITEMID_SHAPE_SHIFTER: + case ITEMID_COOLING_DEVICE: + case ITEMID_MAGNETIC_FIELD_GENERATOR: + case ITEMID_BARRIER_BUILDER: + case ITEMID_CAMOUFLAGE_GENERATOR: + case ITEMID_REPAIR_KIT: + case ITEMID_MONKEY_SPANNER: + cause = USESKILL_FAIL_NEED_EQUIPMENT; + default: + clif->skill_fail(sd, skill_id, cause, max(1,require.amount[i])|(require.itemid[i] << 16)); + return 0; + } + } + clif->skill_fail(sd, skill_id, cause, 0); return 0; } } @@ -13417,7 +13356,7 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin if( !req.itemid[i] ) continue; - if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_WIZARD ) + if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_WIZARD ) continue; //Gemstones are checked, but not substracted from inventory. switch( skill_id ){ @@ -13521,10 +13460,12 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 if( sc ) { if( sc->data[SC__LAZINESS] ) req.sp += req.sp + sc->data[SC__LAZINESS]->val1 * 10; - if (sc->data[SC_UNLIMITEDHUMMINGVOICE]) - req.sp += req.sp * sc->data[SC_UNLIMITEDHUMMINGVOICE]->val2 / 100; + if( sc->data[SC_UNLIMITED_HUMMING_VOICE] ) + req.sp += req.sp * sc->data[SC_UNLIMITED_HUMMING_VOICE]->val2 / 100; if( sc->data[SC_RECOGNIZEDSPELL] ) req.sp += req.sp / 4; + if( sc->data[SC_TELEKINESIS_INTENSE] && skill->get_ele(skill_id, skill_lv) == ELE_GHOST) + req.sp -= req.sp * sc->data[SC_TELEKINESIS_INTENSE]->val2 / 100; } req.zeny = skill_db[idx].zeny[skill_lv-1]; @@ -13644,7 +13585,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 req.zeny -= req.zeny*10/100; break; case AL_HOLYLIGHT: - if(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_PRIEST) + if(sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_PRIEST) req.sp *= 5; break; case SL_SMA: @@ -13668,7 +13609,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 case MO_COMBOFINISH: case CH_TIGERFIST: case CH_CHAINCRUSH: - if(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) + if(sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_MONK) req.sp -= req.sp*25/100; //FIXME: Need real data. this is a custom value. break; case MO_BODYRELOCATION: @@ -13680,9 +13621,9 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 { if( sc->data[SC_BLADESTOP] ) req.spiritball--; - else if( sc->data[SC_COMBO] ) + else if( sc->data[SC_COMBOATTACK] ) { - switch( sc->data[SC_COMBO]->val1 ) + switch( sc->data[SC_COMBOATTACK]->val1 ) { case MO_COMBOFINISH: req.spiritball = 4; @@ -13702,7 +13643,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 req.spiritball = sd->spiritball?sd->spiritball:15; break; case SR_GATEOFHELL: - if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) + if( sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE ) req.sp -= req.sp * 10 / 100; break; case SO_SUMMON_AGNI: @@ -13779,15 +13720,15 @@ int skill_castfix_sc (struct block_list *bl, int time) if( time < 0 ) return 0; - + if( bl->type == BL_MOB ) // mobs casttime is fixed nothing to alter. return time; if (sc && sc->count) { if (sc->data[SC_SLOWCAST]) time += time * sc->data[SC_SLOWCAST]->val2 / 100; - if (sc->data[SC_PARALYSIS]) - time += sc->data[SC_PARALYSIS]->val3; + if (sc->data[SC_NEEDLE_OF_PARALYZE]) + time += sc->data[SC_NEEDLE_OF_PARALYZE]->val3; if (sc->data[SC_SUFFRAGIUM]) { time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100; status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER); @@ -13859,8 +13800,12 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16 if (sc && sc->count && !(skill->get_castnodex(skill_id, skill_lv)&2) ) { // All variable cast additive bonuses must come first + if (sc->data[SC_MAGICPOWER] ) + time += 700; if (sc->data[SC_SLOWCAST]) VARCAST_REDUCTION(-sc->data[SC_SLOWCAST]->val2); + if (sc->data[SC_FROSTMISTY]) + VARCAST_REDUCTION(-15); // Variable cast reduction bonuses if (sc->data[SC_SUFFRAGIUM]) { @@ -13878,17 +13823,33 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16 VARCAST_REDUCTION(50); if (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3 && (skill->get_ele(skill_id, skill_lv) == ELE_WATER)) VARCAST_REDUCTION(30); //Reduces 30% Variable Cast Time of Water spells. + if (sc->data[SC_TELEKINESIS_INTENSE]) + VARCAST_REDUCTION(sc->data[SC_TELEKINESIS_INTENSE]->val2); + if (sc->data[SC_SOULLINK]){ + if(sc->data[SC_SOULLINK]->val2 == SL_WIZARD || sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER) + switch(skill_id){ + case WZ_FIREPILLAR: + if(skill_lv < 5) + break; + case HW_GRAVITATION: + case MG_SAFETYWALL: + case MG_STONECURSE: + case BA_MUSICALSTRIKE: + case DC_THROWARROW: + VARCAST_REDUCTION(50); + } + } // Fixed cast reduction bonuses if( sc->data[SC__LAZINESS] ) fixcast_r = max(fixcast_r, sc->data[SC__LAZINESS]->val2); if( sc->data[SC_SECRAMENT] ) fixcast_r = max(fixcast_r, sc->data[SC_SECRAMENT]->val2); - if( sd && ( skill_lv = pc->checkskill(sd, WL_RADIUS) ) && skill_id >= WL_WHITEIMPRISON && skill_id <= WL_FREEZE_SP ) - fixcast_r = max(fixcast_r, 5 + skill_lv * 5); + if( sd && ( skill_lv = pc->checkskill(sd, WL_RADIUS) ) && (skill_id >= WL_WHITEIMPRISON && skill_id < WL_FREEZE_SP) ) + fixcast_r = max(fixcast_r, (status_get_int(bl) + status_get_lv(bl)) / 15 + skill_lv * 5); // [{(Caster?s INT / 15) + (Caster?s Base Level / 15) + (Radius Skill Level x 5)}] % // Fixed cast non percentage bonuses if( sc->data[SC_MANDRAGORA] ) fixed += sc->data[SC_MANDRAGORA]->val1 * 1000 / 2; - if (sc->data[SC_IZAYOI] && (skill_id >= NJ_TOBIDOUGU && skill_id <= NJ_ISSEN)) + if( sc->data[SC_IZAYOI] ) fixed = 0; if( sc->data[SC_GUST_OPTION] || sc->data[SC_BLAST_OPTION] || sc->data[SC_WILD_STORM_OPTION] ) fixed -= 1000; @@ -13966,14 +13927,14 @@ int skill_delay_fix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) } } - if ( sc && sc->data[SC_SPIRIT] ) { + if ( sc && sc->data[SC_SOULLINK] ) { switch (skill_id) { case CR_SHIELDBOOMERANG: - if (sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) + if (sc->data[SC_SOULLINK]->val2 == SL_CRUSADER) time /= 2; break; case AS_SONICBLOW: - if (!map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && sc->data[SC_SPIRIT]->val2 == SL_ASSASIN) + if (!map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && sc->data[SC_SOULLINK]->val2 == SL_ASSASIN) time /= 2; break; } @@ -14231,7 +14192,7 @@ void skill_identify (struct map_session_data *sd, int idx) int flag=1; nullpo_retv(sd); - + sd->state.workinprogress = 0; if(idx >= 0 && idx < MAX_INVENTORY) { if(sd->status.inventory[idx].nameid > 0 && sd->status.inventory[idx].identify == 0 ){ flag=0; @@ -14258,20 +14219,29 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) if(item->nameid > 0 && ditem->type == IT_WEAPON) { - if( item->refine >= sd->menuskill_val - || item->refine >= 10 // if it's no longer refineable - || ditem->flag.no_refine // if the item isn't refinable - || (i = pc->search_inventory(sd, material [ditem->wlv])) < 0 ) - { + if( ditem->flag.no_refine ){ // if the item isn't refinable clif->skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0); return; } + if( item->refine >= sd->menuskill_val || item->refine >= 10 ){ + clif->upgrademessage(sd->fd, 2, item->nameid); + return; + } + if( (i = pc->search_inventory(sd, material [ditem->wlv])) < 0 ){ + clif->upgrademessage(sd->fd, 3, material [ditem->wlv]); + return; + } - per = status_get_refine_chance(ditem->wlv, (int)item->refine); - per += (((signed int)sd->status.job_level)-50)/2; //Updated per the new kro descriptions. [Skotlex] - + per = status_get_refine_chance(ditem->wlv, (int)item->refine) * 10; + + // Aegis leaked formula. [malufett] + if( sd->status.class_ == JOB_MECHANIC_T ) + per += 100; + else + per += 5 * ((signed int)sd->status.job_level - 50); + pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); - if (per > rnd() % 100) { + if (per > rnd() % 1000) { logs->pick_pc(sd, LOG_TYPE_OTHER, -1, item, ditem); item->refine++; logs->pick_pc(sd, LOG_TYPE_OTHER, 1, item, ditem); @@ -14279,9 +14249,10 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) ep = item->equip; pc->unequipitem(sd,idx,3); } + clif->delitem(sd,idx,1,0); + clif->upgrademessage(sd->fd, 0,item->nameid); + clif->inventorylist(sd); clif->refine(sd->fd,0,idx,item->refine); - clif->delitem(sd,idx,1,3); - clif->additem(sd,idx,1,0); if (ep) pc->equipitem(sd,idx,ep); clif->misceffect(&sd->bl,3); @@ -14306,7 +14277,7 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) if(item->equip) pc->unequipitem(sd,idx,3); clif->refine(sd->fd,1,idx,item->refine); - pc->delitem(sd,idx,1,0,2, LOG_TYPE_OTHER); + pc->delitem(sd,idx,1,0,0, LOG_TYPE_OTHER); clif->misceffect(&sd->bl,2); clif->emotion(&sd->bl, E_OMG); } @@ -14331,7 +14302,7 @@ int skill_autospell (struct map_session_data *sd, uint16 skill_id) if(skill_id==MG_NAPALMBEAT) maxlv=3; else if(skill_id==MG_COLDBOLT || skill_id==MG_FIREBOLT || skill_id==MG_LIGHTNINGBOLT){ - if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SAGE) + if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_SAGE) maxlv =10; //Soul Linker bonus. [Skotlex] else if(skill_lv==2) maxlv=1; else if(skill_lv==3) maxlv=2; @@ -14862,7 +14833,7 @@ int skill_trap_splash (struct block_list *bl, va_list ap) { case UNT_MAIZETRAP: case UNT_VERDURETRAP: if( bl->type != BL_PC && !is_boss(bl) ) - sc_start2(bl,SC_ELEMENTALCHANGE,100,sg->skill_lv,skill->get_ele(sg->skill_id,sg->skill_lv),skill->get_time2(sg->skill_id,sg->skill_lv)); + sc_start2(bl,SC_ARMOR_PROPERTY,100,sg->skill_lv,skill->get_ele(sg->skill_id,sg->skill_lv),skill->get_time2(sg->skill_id,sg->skill_lv)); break; case UNT_REVERBERATION: skill->addtimerskill(ss,tick+50,bl->id,0,0,WM_REVERBERATION_MELEE,sg->skill_lv,BF_WEAPON,0); // for proper skill delay animation when use with Dominion Impulse @@ -14881,7 +14852,7 @@ int skill_trap_splash (struct block_list *bl, va_list ap) { int skill_enchant_elemental_end (struct block_list *bl, int type) { struct status_change *sc; - const enum sc_type scs[] = { SC_ENCPOISON, SC_ASPERSIO, SC_FIREWEAPON, SC_WATERWEAPON, SC_WINDWEAPON, SC_EARTHWEAPON, SC_SHADOWWEAPON, SC_GHOSTWEAPON, SC_ENCHANTARMS, SC_EXEEDBREAK }; + const enum sc_type scs[] = { SC_ENCHANTPOISON, SC_ASPERSIO, SC_PROPERTYFIRE, SC_PROPERTYWATER, SC_PROPERTYWIND, SC_PROPERTYGROUND, SC_PROPERTYDARK, SC_PROPERTYTELEKINESIS, SC_ENCHANTARMS, SC_EXEEDBREAK }; int i; nullpo_ret(bl); nullpo_ret(sc= status_get_sc(bl)); @@ -15036,7 +15007,7 @@ int skill_delunit (struct skill_unit* unit) { case HT_ANKLESNARE: { struct block_list* target = iMap->id2bl(group->val2); if( target ) - status_change_end(target, SC_ANKLE, INVALID_TIMER); + status_change_end(target, SC_ANKLESNARE, INVALID_TIMER); } break; case WZ_ICEWALL: @@ -16083,40 +16054,39 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, **/ case RK_RUNEMASTERY: { - int A = 100 * (51 + 2 * pc->checkskill(sd, skill_id)); - int B = 100 * status->dex / 30 + 10 * (status->luk + sd->status.job_level); + int A = 5100 + 200 * pc->checkskill(sd, skill_id); + int B = 10 * status->dex / 3 + (status->luk + sd->status.job_level); int C = 100 * cap_value(sd->itemid,0,100); //itemid depend on makerune() - int D = 0; + int D = 2500; switch (nameid) { //rune rank it_diff 9 craftable rune - case ITEMID_BERKANA: - D = -2000; - break; //Rank S - case ITEMID_NAUTHIZ: - case ITEMID_URUZ: - D = -1500; - break; //Rank A - case ITEMID_ISA: - case ITEMID_WYRD: - D = -1000; - break; //Rank B case ITEMID_RAIDO: case ITEMID_THURISAZ: case ITEMID_HAGALAZ: case ITEMID_OTHILA: - D = -500; - break; //Rank C - default: D = -1500; - break; //not specified =-15% + D -= 500; //Rank C + case ITEMID_ISA: + case ITEMID_WYRD: + D -= 500; //Rank B + case ITEMID_NAUTHIZ: + case ITEMID_URUZ: + D -= 500; //Rank A + case ITEMID_BERKANA: + D -= 500; //Rank S } - make_per = A + B + C + D; + make_per = A + B + C - D; break; } /** * Guilotine Cross **/ case GC_CREATENEWPOISON: - make_per = 3000 + 500 * pc->checkskill(sd,GC_RESEARCHNEWPOISON); - qty = 1+rnd()%pc->checkskill(sd,GC_RESEARCHNEWPOISON); + { + const int min[] = {2, 2, 3, 3, 4, 4, 5, 5, 6, 6}; + const int max[] = {4, 5, 5, 6, 6, 7, 7, 8, 8, 9}; + uint16 lv = pc->checkskill(sd,GC_RESEARCHNEWPOISON); + make_per = 3000 + 500 * lv ; + qty = min[lv] + rand()%(max[lv] - min[lv]); + } break; case GN_CHANGEMATERIAL: for(i=0; ibl); status_change_end(&sd->bl, SC_STOP, INVALID_TIMER); - for(i=SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) if( sc && !sc->data[i] ) break; - if( i > SC_MAXSPELLBOOK ) + for(i=SC_SPELLBOOK1; i <= SC_SPELLBOOK7; i++) if( sc && !sc->data[i] ) break; + if( i > SC_SPELLBOOK7 ) { clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); return 0; @@ -16637,7 +16607,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { return 0; } - max_preserve = 4 * pc->checkskill(sd, WL_FREEZE_SP) + status_get_int(&sd->bl) / 10 + sd->status.base_level / 10; + max_preserve = 4 * pc->checkskill(sd, WL_FREEZE_SP) + (status_get_int(&sd->bl) + sd->status.base_level) / 10; point = skill_spellbook_db[i].point; if( sc && sc->data[SC_READING_SB] ) { @@ -16645,7 +16615,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT, 0); return 0; } - for(i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--){ // This is how official saves spellbook. [malufett] + for(i = SC_SPELLBOOK7; i >= SC_SPELLBOOK1; i--){ // This is how official saves spellbook. [malufett] if( !sc->data[i] ){ sc->data[SC_READING_SB]->val2 += point; // increase points sc_start4(&sd->bl, (sc_type)i, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER); @@ -16654,7 +16624,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { } }else{ sc_start2(&sd->bl, SC_READING_SB, 100, 0, point, INVALID_TIMER); - sc_start4(&sd->bl, SC_MAXSPELLBOOK, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER); + sc_start4(&sd->bl, SC_SPELLBOOK7, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER); } return 1; @@ -17365,7 +17335,7 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) { return 1; // Can't do it. } break; - case SC_KAGEHUMI: + case SC_KG_KAGEHUMI: switch(skill_id) { case TF_HIDING: case AS_CLOAKING: case GC_CLOAKINGEXCEED: case SC_SHADOWFORM: case MI_HARMONIZE: case CG_MARIONETTE: case AL_TELEPORT: case TF_BACKSLIDING: @@ -17995,6 +17965,7 @@ void skill_defaults(void) { skill->delay_fix = skill_delay_fix; skill->check_condition_castbegin = skill_check_condition_castbegin; skill->check_condition_castend = skill_check_condition_castend; + skill->check_condition_char_sub = skill_check_condition_char_sub; skill->get_requirement = skill_get_requirement; skill->check_pc_partner = skill_check_pc_partner; skill->consume_requirement = skill_consume_requirement; diff --git a/src/map/skill.h b/src/map/skill.h index c585bbb3a..cc9ac4bfc 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -1281,7 +1281,26 @@ enum e_skill { ECL_SADAGUI, ECL_SEQUOIADUST, ECLAGE_RECALL, - + + GC_DARKCROW = 5001, + RA_UNLIMIT, + GN_ILLUSIONDOPING, + RK_DRAGONBREATH_WATER, + RK_LUXANIMA, + NC_MAGMA_ERUPTION, + WM_FRIGG_SONG, + SO_ELEMENTAL_SHIELD, + SR_FLASHCOMBO, + SC_ESCAPE, + AB_OFFERTORIUM, + WL_TELEKINESIS_INTENSE, + LG_KINGS_GRACE, + ALL_FULL_THROTTLE, + SR_FLASHCOMBO_ATK_STEP1, + SR_FLASHCOMBO_ATK_STEP2, + SR_FLASHCOMBO_ATK_STEP3, + SR_FLASHCOMBO_ATK_STEP4, + HLIF_HEAL = 8001, HLIF_AVOID, HLIF_BRAIN, @@ -1541,6 +1560,10 @@ enum { UNT_ZENKAI_WIND, UNT_MAKIBISHI, UNT_VENOMFOG, + UNT_ICEMINE, + UNT_FLAMECROSS, + UNT_HELLBURNING, + UNT_MAGMA_ERUPTION, /** * Guild Auras diff --git a/src/map/status.c b/src/map/status.c index c163135d8..0e1661728 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -69,6 +69,7 @@ static struct { static int atkmods[3][MAX_WEAPON_TYPE]; //ATK weapon modification for size (size_fix.txt) static char job_bonus[CLASS_COUNT][MAX_LEVEL]; +static sc_conf_type sc_conf[SC_MAX]; static struct eri *sc_data_ers; //For sc_data entries static struct status_data dummy_status; @@ -189,7 +190,7 @@ void initChangeTables(void) { set_sc( NPC_SILENCEATTACK , SC_SILENCE , SI_BLANK , SCB_NONE ); set_sc( NPC_WIDECONFUSE , SC_CONFUSION , SI_BLANK , SCB_NONE ); set_sc( NPC_BLINDATTACK , SC_BLIND , SI_BLANK , SCB_HIT|SCB_FLEE ); - set_sc( NPC_BLEEDING , SC_BLEEDING , SI_BLEEDING , SCB_REGEN ); + set_sc( NPC_BLEEDING , SC_BLOODING , SI_BLOODING , SCB_REGEN ); set_sc( NPC_POISON , SC_DPOISON , SI_BLANK , SCB_DEF2|SCB_REGEN ); //The main status definitions @@ -203,12 +204,12 @@ void initChangeTables(void) { add_sc( MG_STONECURSE , SC_STONE ); add_sc( AL_RUWACH , SC_RUWACH ); add_sc( AL_PNEUMA , SC_PNEUMA ); - set_sc( AL_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED ); - set_sc( AL_DECAGI , SC_DECREASEAGI , SI_DECREASEAGI , SCB_AGI|SCB_SPEED ); - set_sc( AL_CRUCIS , SC_SIGNUMCRUCIS , SI_SIGNUMCRUCIS , SCB_DEF ); + set_sc( AL_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED ); + set_sc( AL_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED ); + set_sc( AL_CRUCIS , SC_CRUCIS , SI_CRUCIS , SCB_DEF ); set_sc( AL_ANGELUS , SC_ANGELUS , SI_ANGELUS , SCB_DEF2 ); set_sc( AL_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); - set_sc( AC_CONCENTRATION , SC_CONCENTRATE , SI_CONCENTRATE , SCB_AGI|SCB_DEX ); + set_sc( AC_CONCENTRATION , SC_CONCENTRATION , SI_CONCENTRATION , SCB_AGI|SCB_DEX ); set_sc( TF_HIDING , SC_HIDING , SI_HIDING , SCB_SPEED ); add_sc( TF_POISON , SC_POISON ); set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD ); @@ -222,44 +223,44 @@ void initChangeTables(void) { set_sc( PR_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN ); set_sc( PR_GLORIA , SC_GLORIA , SI_GLORIA , SCB_LUK ); add_sc( PR_LEXDIVINA , SC_SILENCE ); - set_sc( PR_LEXAETERNA , SC_AETERNA , SI_AETERNA , SCB_NONE ); + set_sc( PR_LEXAETERNA , SC_LEXAETERNA , SI_LEXAETERNA , SCB_NONE ); add_sc( WZ_METEOR , SC_STUN ); add_sc( WZ_VERMILION , SC_BLIND ); add_sc( WZ_FROSTNOVA , SC_FREEZE ); add_sc( WZ_STORMGUST , SC_FREEZE ); - set_sc( WZ_QUAGMIRE , SC_QUAGMIRE , SI_QUAGMIRE , SCB_AGI|SCB_DEX|SCB_ASPD|SCB_SPEED ); - set_sc( BS_ADRENALINE , SC_ADRENALINE , SI_ADRENALINE , SCB_ASPD ); - set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECTION, SI_WEAPONPERFECTION, SCB_NONE ); - set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SI_OVERTHRUST , SCB_NONE ); - set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZEPOWER , SCB_REGEN ); - add_sc( HT_LANDMINE , SC_STUN ); - add_sc( HT_ANKLESNARE , SC_ANKLE ); + set_sc( WZ_QUAGMIRE , SC_QUAGMIRE , SI_QUAGMIRE , SCB_AGI|SCB_DEX|SCB_ASPD|SCB_SPEED ); + set_sc( BS_ADRENALINE , SC_ADRENALINE , SI_ADRENALINE , SCB_ASPD ); + set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECT , SI_WEAPONPERFECT, SCB_NONE ); + set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SI_OVERTHRUST , SCB_NONE ); + set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZE , SCB_REGEN ); + add_sc( HT_LANDMINE , SC_STUN ); + set_sc( HT_ANKLESNARE , SC_ANKLESNARE , SI_ANKLESNARE , SCB_NONE ); add_sc( HT_SANDMAN , SC_SLEEP ); add_sc( HT_FLASHER , SC_BLIND ); add_sc( HT_FREEZINGTRAP , SC_FREEZE ); - set_sc( AS_CLOAKING , SC_CLOAKING , SI_CLOAKING , SCB_CRI|SCB_SPEED ); + set_sc( AS_CLOAKING , SC_CLOAKING , SI_CLOAKING , SCB_CRI|SCB_SPEED ); add_sc( AS_SONICBLOW , SC_STUN ); - set_sc( AS_ENCHANTPOISON , SC_ENCPOISON , SI_ENCPOISON , SCB_ATK_ELE ); - set_sc( AS_POISONREACT , SC_POISONREACT , SI_POISONREACT , SCB_NONE ); + set_sc( AS_ENCHANTPOISON , SC_ENCHANTPOISON , SI_ENCHANTPOISON, SCB_ATK_ELE ); + set_sc( AS_POISONREACT , SC_POISONREACT , SI_POISONREACT , SCB_NONE ); add_sc( AS_VENOMDUST , SC_POISON ); add_sc( AS_SPLASHER , SC_SPLASHER ); - set_sc( NV_TRICKDEAD , SC_TRICKDEAD , SI_TRICKDEAD , SCB_REGEN ); - set_sc( SM_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE ); + set_sc( NV_TRICKDEAD , SC_TRICKDEAD , SI_TRICKDEAD , SCB_REGEN ); + set_sc( SM_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE ); add_sc( TF_SPRINKLESAND , SC_BLIND ); add_sc( TF_THROWSTONE , SC_STUN ); - set_sc( MC_LOUD , SC_LOUD , SI_LOUD , SCB_STR ); - set_sc( MG_ENERGYCOAT , SC_ENERGYCOAT , SI_ENERGYCOAT , SCB_NONE ); - set_sc( NPC_EMOTION , SC_MODECHANGE , SI_BLANK , SCB_MODE ); - add_sc( NPC_EMOTION_ON , SC_MODECHANGE ); - set_sc( NPC_ATTRICHANGE , SC_ELEMENTALCHANGE , SI_ARMOR_PROPERTY , SCB_DEF_ELE ); - add_sc( NPC_CHANGEWATER , SC_ELEMENTALCHANGE ); - add_sc( NPC_CHANGEGROUND , SC_ELEMENTALCHANGE ); - add_sc( NPC_CHANGEFIRE , SC_ELEMENTALCHANGE ); - add_sc( NPC_CHANGEWIND , SC_ELEMENTALCHANGE ); - add_sc( NPC_CHANGEPOISON , SC_ELEMENTALCHANGE ); - add_sc( NPC_CHANGEHOLY , SC_ELEMENTALCHANGE ); - add_sc( NPC_CHANGEDARKNESS , SC_ELEMENTALCHANGE ); - add_sc( NPC_CHANGETELEKINESIS, SC_ELEMENTALCHANGE ); + set_sc( MC_LOUD , SC_SHOUT , SI_SHOUT , SCB_STR ); + set_sc( MG_ENERGYCOAT , SC_ENERGYCOAT , SI_ENERGYCOAT , SCB_NONE ); + set_sc( NPC_EMOTION , SC_MODECHANGE , SI_BLANK , SCB_MODE ); + add_sc( NPC_EMOTION_ON , SC_MODECHANGE ); + set_sc( NPC_ATTRICHANGE , SC_ARMOR_PROPERTY , SI_ARMOR_PROPERTY , SCB_DEF_ELE ); + add_sc( NPC_CHANGEWATER , SC_ARMOR_PROPERTY ); + add_sc( NPC_CHANGEGROUND , SC_ARMOR_PROPERTY ); + add_sc( NPC_CHANGEFIRE , SC_ARMOR_PROPERTY ); + add_sc( NPC_CHANGEWIND , SC_ARMOR_PROPERTY ); + add_sc( NPC_CHANGEPOISON , SC_ARMOR_PROPERTY ); + add_sc( NPC_CHANGEHOLY , SC_ARMOR_PROPERTY ); + add_sc( NPC_CHANGEDARKNESS , SC_ARMOR_PROPERTY ); + add_sc( NPC_CHANGETELEKINESIS, SC_ARMOR_PROPERTY ); add_sc( NPC_POISON , SC_POISON ); add_sc( NPC_BLINDATTACK , SC_BLIND ); add_sc( NPC_SILENCEATTACK , SC_SILENCE ); @@ -273,25 +274,25 @@ void initChangeTables(void) { set_sc( NPC_BARRIER , SC_BARRIER , SI_BLANK , SCB_MDEF|SCB_DEF ); add_sc( NPC_DEFENDER , SC_ARMOR ); add_sc( NPC_LICK , SC_STUN ); - set_sc( NPC_HALLUCINATION , SC_HALLUCINATION , SI_HALLUCINATION , SCB_NONE ); + set_sc( NPC_HALLUCINATION , SC_ILLUSION , SI_ILLUSION , SCB_NONE ); add_sc( NPC_REBIRTH , SC_REBIRTH ); add_sc( RG_RAID , SC_STUN ); #ifdef RENEWAL add_sc( RG_RAID , SC_RAID ); add_sc( RG_BACKSTAP , SC_STUN ); #endif - set_sc( RG_STRIPWEAPON , SC_STRIPWEAPON , SI_STRIPWEAPON , SCB_WATK ); - set_sc( RG_STRIPSHIELD , SC_STRIPSHIELD , SI_STRIPSHIELD , SCB_DEF ); - set_sc( RG_STRIPARMOR , SC_STRIPARMOR , SI_STRIPARMOR , SCB_VIT ); - set_sc( RG_STRIPHELM , SC_STRIPHELM , SI_STRIPHELM , SCB_INT ); - add_sc( AM_ACIDTERROR , SC_BLEEDING ); - set_sc( AM_CP_WEAPON , SC_CP_WEAPON , SI_CP_WEAPON , SCB_NONE ); - set_sc( AM_CP_SHIELD , SC_CP_SHIELD , SI_CP_SHIELD , SCB_NONE ); - set_sc( AM_CP_ARMOR , SC_CP_ARMOR , SI_CP_ARMOR , SCB_NONE ); - set_sc( AM_CP_HELM , SC_CP_HELM , SI_CP_HELM , SCB_NONE ); - set_sc( CR_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE ); + set_sc( RG_STRIPWEAPON , SC_NOEQUIPWEAPON , SI_NOEQUIPWEAPON , SCB_WATK ); + set_sc( RG_STRIPSHIELD , SC_NOEQUIPSHIELD , SI_NOEQUIPSHIELD , SCB_DEF ); + set_sc( RG_STRIPARMOR , SC_NOEQUIPARMOR , SI_NOEQUIPARMOR , SCB_VIT ); + set_sc( RG_STRIPHELM , SC_NOEQUIPHELM , SI_NOEQUIPHELM , SCB_INT ); + add_sc( AM_ACIDTERROR , SC_BLOODING ); + set_sc( AM_CP_WEAPON , SC_PROTECTWEAPON , SI_PROTECTWEAPON , SCB_NONE ); + set_sc( AM_CP_SHIELD , SC_PROTECTSHIELD , SI_PROTECTSHIELD , SCB_NONE ); + set_sc( AM_CP_ARMOR , SC_PROTECTARMOR , SI_PROTECTARMOR , SCB_NONE ); + set_sc( AM_CP_HELM , SC_PROTECTHELM , SI_PROTECTHELM , SCB_NONE ); + set_sc( CR_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE ); add_sc( CR_SHIELDCHARGE , SC_STUN ); - set_sc( CR_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE ); + set_sc( CR_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE ); add_sc( CR_HOLYCROSS , SC_BLIND ); add_sc( CR_GRANDCROSS , SC_BLIND ); add_sc( CR_DEVOTION , SC_DEVOTION ); @@ -304,17 +305,17 @@ void initChangeTables(void) { set_sc( MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS, SI_EXPLOSIONSPIRITS, SCB_CRI|SCB_REGEN ); set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST , SI_BLANK , SCB_REGEN ); #ifdef RENEWAL - set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SI_EXTREMITYFIST , SCB_NONE ); + set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SI_EXTREMITYFIST , SCB_NONE ); #endif add_sc( SA_MAGICROD , SC_MAGICROD ); set_sc( SA_AUTOSPELL , SC_AUTOSPELL , SI_AUTOSPELL , SCB_NONE ); - set_sc( SA_FLAMELAUNCHER , SC_FIREWEAPON , SI_FIREWEAPON , SCB_ATK_ELE ); - set_sc( SA_FROSTWEAPON , SC_WATERWEAPON , SI_WATERWEAPON , SCB_ATK_ELE ); - set_sc( SA_LIGHTNINGLOADER , SC_WINDWEAPON , SI_WINDWEAPON , SCB_ATK_ELE ); - set_sc( SA_SEISMICWEAPON , SC_EARTHWEAPON , SI_EARTHWEAPON , SCB_ATK_ELE ); - set_sc( SA_VOLCANO , SC_VOLCANO , SI_LANDENDOW , SCB_WATK ); - set_sc( SA_DELUGE , SC_DELUGE , SI_LANDENDOW , SCB_MAXHP ); - set_sc( SA_VIOLENTGALE , SC_VIOLENTGALE , SI_LANDENDOW , SCB_FLEE ); + set_sc( SA_FLAMELAUNCHER , SC_PROPERTYFIRE , SI_PROPERTYFIRE , SCB_ATK_ELE ); + set_sc( SA_FROSTWEAPON , SC_PROPERTYWATER , SI_PROPERTYWATER , SCB_ATK_ELE ); + set_sc( SA_LIGHTNINGLOADER , SC_PROPERTYWIND , SI_PROPERTYWIND , SCB_ATK_ELE ); + set_sc( SA_SEISMICWEAPON , SC_PROPERTYGROUND , SI_PROPERTYGROUND , SCB_ATK_ELE ); + set_sc( SA_VOLCANO , SC_VOLCANO , SI_GROUNDMAGIC , SCB_WATK ); + set_sc( SA_DELUGE , SC_DELUGE , SI_GROUNDMAGIC , SCB_MAXHP ); + set_sc( SA_VIOLENTGALE , SC_VIOLENTGALE , SI_GROUNDMAGIC , SCB_FLEE ); add_sc( SA_REVERSEORCISH , SC_ORCISH ); add_sc( SA_COMA , SC_COMA ); set_sc( BD_ENCORE , SC_DANCING , SI_BLANK , SCB_SPEED|SCB_REGEN ); @@ -334,19 +335,23 @@ void initChangeTables(void) { set_sc( DC_HUMMING , SC_HUMMING , SI_BLANK , SCB_HIT ); set_sc( DC_DONTFORGETME , SC_DONTFORGETME , SI_BLANK , SCB_SPEED|SCB_ASPD ); set_sc( DC_FORTUNEKISS , SC_FORTUNE , SI_BLANK , SCB_CRI ); - set_sc( DC_SERVICEFORYOU , SC_SERVICE4U , SI_BLANK , SCB_ALL ); + set_sc( DC_SERVICEFORYOU , SC_SERVICEFORYOU , SI_BLANK , SCB_ALL ); add_sc( NPC_DARKCROSS , SC_BLIND ); add_sc( NPC_GRANDDARKNESS , SC_BLIND ); set_sc( NPC_STOP , SC_STOP , SI_STOP , SCB_NONE ); set_sc( NPC_WEAPONBRAKER , SC_BROKENWEAPON , SI_BROKENWEAPON , SCB_NONE ); set_sc( NPC_ARMORBRAKE , SC_BROKENARMOR , SI_BROKENARMOR , SCB_NONE ); - set_sc( NPC_CHANGEUNDEAD , SC_CHANGEUNDEAD , SI_UNDEAD , SCB_DEF_ELE ); + set_sc( NPC_CHANGEUNDEAD , SC_PROPERTYUNDEAD , SI_PROPERTYUNDEAD , SCB_DEF_ELE ); set_sc( NPC_POWERUP , SC_INCHITRATE , SI_BLANK , SCB_HIT ); set_sc( NPC_AGIUP , SC_INCFLEERATE , SI_BLANK , SCB_FLEE ); add_sc( NPC_INVISIBLE , SC_CLOAKING ); set_sc( LK_AURABLADE , SC_AURABLADE , SI_AURABLADE , SCB_NONE ); set_sc( LK_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE ); - set_sc( LK_CONCENTRATION , SC_CONCENTRATION , SI_CONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_DSPD ); +#ifndef RENEWAL + set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_CONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2); +#else + set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_CONCENTRATION , SCB_HIT|SCB_DEF); +#endif set_sc( LK_TENSIONRELAX , SC_TENSIONRELAX , SI_TENSIONRELAX , SCB_REGEN ); set_sc( LK_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN ); set_sc( HP_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE ); @@ -362,32 +367,32 @@ void initChangeTables(void) { set_sc( WS_MELTDOWN , SC_MELTDOWN , SI_MELTDOWN , SCB_NONE ); set_sc( WS_CARTBOOST , SC_CARTBOOST , SI_CARTBOOST , SCB_SPEED ); set_sc( ST_CHASEWALK , SC_CHASEWALK , SI_BLANK , SCB_SPEED ); - set_sc( ST_REJECTSWORD , SC_REJECTSWORD , SI_REJECTSWORD , SCB_NONE ); + set_sc( ST_REJECTSWORD , SC_SWORDREJECT , SI_SWORDREJECT , SCB_NONE ); add_sc( ST_REJECTSWORD , SC_AUTOCOUNTER ); - set_sc( CG_MARIONETTE , SC_MARIONETTE , SI_MARIONETTE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); - set_sc( CG_MARIONETTE , SC_MARIONETTE2 , SI_MARIONETTE2 , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + set_sc( CG_MARIONETTE , SC_MARIONETTE_MASTER , SI_MARIONETTE_MASTER , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + set_sc( CG_MARIONETTE , SC_MARIONETTE , SI_MARIONETTE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); add_sc( LK_SPIRALPIERCE , SC_STOP ); - add_sc( LK_HEADCRUSH , SC_BLEEDING ); + add_sc( LK_HEADCRUSH , SC_BLOODING ); set_sc( LK_JOINTBEAT , SC_JOINTBEAT , SI_JOINTBEAT , SCB_BATK|SCB_DEF2|SCB_SPEED|SCB_ASPD ); add_sc( HW_NAPALMVULCAN , SC_CURSE ); set_sc( PF_MINDBREAKER , SC_MINDBREAKER , SI_BLANK , SCB_MATK|SCB_MDEF2 ); add_sc( PF_MEMORIZE , SC_MEMORIZE ); add_sc( PF_FOGWALL , SC_FOGWALL ); set_sc( PF_SPIDERWEB , SC_SPIDERWEB , SI_BLANK , SCB_FLEE ); - set_sc( WE_BABY , SC_BABY , SI_BABY , SCB_NONE ); + set_sc( WE_BABY , SC_BABY , SI_PROTECTEXP , SCB_NONE ); set_sc( TK_RUN , SC_RUN , SI_RUN , SCB_SPEED|SCB_DSPD ); - set_sc( TK_RUN , SC_SPURT , SI_SPURT , SCB_STR ); - set_sc( TK_READYSTORM , SC_READYSTORM , SI_READYSTORM , SCB_NONE ); - set_sc( TK_READYDOWN , SC_READYDOWN , SI_READYDOWN , SCB_NONE ); + set_sc( TK_RUN , SC_STRUP , SI_STRUP , SCB_STR ); + set_sc( TK_READYSTORM , SC_STORMKICK_READY , SI_STORMKICK_ON , SCB_NONE ); + set_sc( TK_READYDOWN , SC_DOWNKICK_READY , SI_DOWNKICK_ON , SCB_NONE ); add_sc( TK_DOWNKICK , SC_STUN ); - set_sc( TK_READYTURN , SC_READYTURN , SI_READYTURN , SCB_NONE ); - set_sc( TK_READYCOUNTER , SC_READYCOUNTER , SI_READYCOUNTER , SCB_NONE ); - set_sc( TK_DODGE , SC_DODGE , SI_DODGE , SCB_NONE ); + set_sc( TK_READYTURN , SC_TURNKICK_READY , SI_TURNKICK_ON , SCB_NONE ); + set_sc( TK_READYCOUNTER , SC_COUNTERKICK_READY , SI_COUNTER_ON , SCB_NONE ); + set_sc( TK_DODGE , SC_DODGE_READY , SI_DODGE_ON , SCB_NONE ); set_sc( TK_SPTIME , SC_EARTHSCROLL , SI_EARTHSCROLL , SCB_NONE ); - add_sc( TK_SEVENWIND , SC_SEVENWIND ); - set_sc( TK_SEVENWIND , SC_GHOSTWEAPON , SI_GHOSTWEAPON , SCB_ATK_ELE ); - set_sc( TK_SEVENWIND , SC_SHADOWWEAPON , SI_SHADOWWEAPON , SCB_ATK_ELE ); - set_sc( SG_SUN_WARM , SC_WARM , SI_WARM , SCB_NONE ); + add_sc( TK_SEVENWIND , SC_TK_SEVENWIND ); + set_sc( TK_SEVENWIND , SC_PROPERTYTELEKINESIS , SI_PROPERTYTELEKINESIS , SCB_ATK_ELE ); + set_sc( TK_SEVENWIND , SC_PROPERTYDARK , SI_PROPERTYDARK , SCB_ATK_ELE ); + set_sc( SG_SUN_WARM , SC_WARM , SI_SG_SUN_WARM , SCB_NONE ); add_sc( SG_MOON_WARM , SC_WARM ); add_sc( SG_STAR_WARM , SC_WARM ); set_sc( SG_SUN_COMFORT , SC_SUN_COMFORT , SI_SUN_COMFORT , SCB_DEF2 ); @@ -405,39 +410,40 @@ void initChangeTables(void) { set_sc( SL_SWOO , SC_SWOO , SI_BLANK , SCB_SPEED ); set_sc( SL_SKE , SC_SKE , SI_BLANK , SCB_BATK|SCB_WATK|SCB_DEF|SCB_DEF2 ); set_sc( SL_SKA , SC_SKA , SI_BLANK , SCB_DEF|SCB_MDEF|SCB_ASPD ); - set_sc( SL_SMA , SC_SMA , SI_SMA , SCB_NONE ); + set_sc( SL_SMA , SC_SMA_READY , SI_SMA_READY , SCB_NONE ); set_sc( SM_SELFPROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); set_sc( ST_PRESERVE , SC_PRESERVE , SI_PRESERVE , SCB_NONE ); - set_sc( PF_DOUBLECASTING , SC_DOUBLECAST , SI_DOUBLECAST , SCB_NONE ); + set_sc( PF_DOUBLECASTING , SC_DOUBLECASTING , SI_DOUBLECASTING , SCB_NONE ); set_sc( HW_GRAVITATION , SC_GRAVITATION , SI_BLANK , SCB_ASPD ); add_sc( WS_CARTTERMINATION , SC_STUN ); - set_sc( WS_OVERTHRUSTMAX , SC_MAXOVERTHRUST , SI_MAXOVERTHRUST , SCB_NONE ); + set_sc( WS_OVERTHRUSTMAX , SC_OVERTHRUSTMAX , SI_OVERTHRUSTMAX , SCB_NONE ); set_sc( CG_LONGINGFREEDOM , SC_LONGING , SI_BLANK , SCB_SPEED|SCB_ASPD ); add_sc( CG_HERMODE , SC_HERMODE ); + set_sc( CG_TAROTCARD , SC_TAROTCARD , SI_TAROTCARD , SCB_NONE ); set_sc( ITEM_ENCHANTARMS , SC_ENCHANTARMS , SI_BLANK , SCB_ATK_ELE ); - set_sc( SL_HIGH , SC_SPIRIT , SI_SPIRIT , SCB_ALL ); - set_sc( KN_ONEHAND , SC_ONEHAND , SI_ONEHAND , SCB_ASPD ); + set_sc( SL_HIGH , SC_SOULLINK , SI_SOULLINK , SCB_ALL ); + set_sc( KN_ONEHAND , SC_ONEHANDQUICKEN , SI_ONEHANDQUICKEN , SCB_ASPD ); set_sc( GS_FLING , SC_FLING , SI_BLANK , SCB_DEF|SCB_DEF2 ); add_sc( GS_CRACKER , SC_STUN ); - add_sc( GS_DISARM , SC_STRIPWEAPON ); - add_sc( GS_PIERCINGSHOT , SC_BLEEDING ); - set_sc( GS_MADNESSCANCEL , SC_MADNESSCANCEL , SI_MADNESSCANCEL , SCB_BATK|SCB_ASPD ); - set_sc( GS_ADJUSTMENT , SC_ADJUSTMENT , SI_ADJUSTMENT , SCB_HIT|SCB_FLEE ); - set_sc( GS_INCREASING , SC_INCREASING , SI_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT ); - set_sc( GS_GATLINGFEVER , SC_GATLINGFEVER , SI_GATLINGFEVER , SCB_BATK|SCB_FLEE|SCB_SPEED|SCB_ASPD ); - set_sc( NJ_TATAMIGAESHI , SC_TATAMIGAESHI , SI_BLANK , SCB_NONE ); - set_sc( NJ_SUITON , SC_SUITON , SI_BLANK , SCB_AGI|SCB_SPEED ); + add_sc( GS_DISARM , SC_NOEQUIPWEAPON ); + add_sc( GS_PIERCINGSHOT , SC_BLOODING ); + set_sc( GS_MADNESSCANCEL , SC_GS_MADNESSCANCEL , SI_GS_MADNESSCANCEL , SCB_BATK|SCB_ASPD ); + set_sc( GS_ADJUSTMENT , SC_GS_ADJUSTMENT , SI_GS_ADJUSTMENT , SCB_HIT|SCB_FLEE ); + set_sc( GS_INCREASING , SC_GS_ACCURACY , SI_GS_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT ); + set_sc( GS_GATLINGFEVER , SC_GS_GATLINGFEVER , SI_GS_GATLINGFEVER , SCB_BATK|SCB_FLEE|SCB_SPEED|SCB_ASPD ); + set_sc( NJ_TATAMIGAESHI , SC_NJ_TATAMIGAESHI , SI_BLANK , SCB_NONE ); + set_sc( NJ_SUITON , SC_NJ_SUITON , SI_NJ_SUITON , SCB_AGI|SCB_SPEED ); add_sc( NJ_HYOUSYOURAKU , SC_FREEZE ); - set_sc( NJ_NEN , SC_NEN , SI_NEN , SCB_STR|SCB_INT ); - set_sc( NJ_UTSUSEMI , SC_UTSUSEMI , SI_UTSUSEMI , SCB_NONE ); - set_sc( NJ_BUNSINJYUTSU , SC_BUNSINJYUTSU , SI_BUNSINJYUTSU , SCB_DYE ); + set_sc( NJ_NEN , SC_NJ_NEN , SI_NJ_NEN , SCB_STR|SCB_INT ); + set_sc( NJ_UTSUSEMI , SC_NJ_UTSUSEMI , SI_NJ_UTSUSEMI , SCB_NONE ); + set_sc( NJ_BUNSINJYUTSU , SC_NJ_BUNSINJYUTSU , SI_NJ_BUNSINJYUTSU , SCB_DYE ); add_sc( NPC_ICEBREATH , SC_FREEZE ); add_sc( NPC_ACIDBREATH , SC_POISON ); add_sc( NPC_HELLJUDGEMENT , SC_CURSE ); add_sc( NPC_WIDESILENCE , SC_SILENCE ); add_sc( NPC_WIDEFREEZE , SC_FREEZE ); - add_sc( NPC_WIDEBLEEDING , SC_BLEEDING ); + add_sc( NPC_WIDEBLEEDING , SC_BLOODING ); add_sc( NPC_WIDESTONE , SC_STONE ); add_sc( NPC_WIDECONFUSE , SC_CONFUSION ); add_sc( NPC_WIDESLEEP , SC_SLEEP ); @@ -446,8 +452,8 @@ void initChangeTables(void) { add_sc( NPC_MAGICMIRROR , SC_MAGICMIRROR ); set_sc( NPC_SLOWCAST , SC_SLOWCAST , SI_SLOWCAST , SCB_NONE ); set_sc( NPC_CRITICALWOUND , SC_CRITICALWOUND , SI_CRITICALWOUND , SCB_NONE ); - set_sc( NPC_STONESKIN , SC_ARMORCHANGE , SI_BLANK , SCB_DEF|SCB_MDEF ); - add_sc( NPC_ANTIMAGIC , SC_ARMORCHANGE ); + set_sc( NPC_STONESKIN , SC_STONESKIN , SI_BLANK , SCB_DEF|SCB_MDEF ); + add_sc( NPC_ANTIMAGIC , SC_STONESKIN ); add_sc( NPC_WIDECURSE , SC_CURSE ); add_sc( NPC_WIDESTUN , SC_STUN ); @@ -457,29 +463,29 @@ void initChangeTables(void) { set_sc( NPC_INVINCIBLEOFF , SC_INVINCIBLEOFF , SI_BLANK , SCB_SPEED ); set_sc( CASH_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); - set_sc( CASH_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED ); + set_sc( CASH_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED ); set_sc( CASH_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE ); set_sc( ALL_PARTYFLEE , SC_PARTYFLEE , SI_PARTYFLEE , SCB_NONE ); set_sc( ALL_ODINS_POWER , SC_ODINS_POWER , SI_ODINS_POWER , SCB_MATK|SCB_BATK|SCB_MDEF|SCB_DEF ); - set_sc( CR_SHRINK , SC_SHRINK , SI_SHRINK , SCB_NONE ); - set_sc( RG_CLOSECONFINE , SC_CLOSECONFINE2 , SI_CLOSECONFINE2 , SCB_NONE ); - set_sc( RG_CLOSECONFINE , SC_CLOSECONFINE , SI_CLOSECONFINE , SCB_FLEE ); - set_sc( WZ_SIGHTBLASTER , SC_SIGHTBLASTER , SI_SIGHTBLASTER , SCB_NONE ); - set_sc( DC_WINKCHARM , SC_WINKCHARM , SI_WINKCHARM , SCB_NONE ); + set_sc( CR_SHRINK , SC_CR_SHRINK , SI_CR_SHRINK , SCB_NONE ); + set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE ); + set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE ); + set_sc( WZ_SIGHTBLASTER , SC_WZ_SIGHTBLASTER , SI_WZ_SIGHTBLASTER , SCB_NONE ); + set_sc( DC_WINKCHARM , SC_DC_WINKCHARM , SI_DC_WINKCHARM , SCB_NONE ); add_sc( MO_BALKYOUNG , SC_STUN ); - add_sc( SA_ELEMENTWATER , SC_ELEMENTALCHANGE ); - add_sc( SA_ELEMENTFIRE , SC_ELEMENTALCHANGE ); - add_sc( SA_ELEMENTGROUND , SC_ELEMENTALCHANGE ); - add_sc( SA_ELEMENTWIND , SC_ELEMENTALCHANGE ); - - set_sc( HLIF_AVOID , SC_AVOID , SI_BLANK , SCB_SPEED ); - set_sc( HLIF_CHANGE , SC_CHANGE , SI_BLANK , SCB_VIT|SCB_INT ); - set_sc( HFLI_FLEET , SC_FLEET , SI_BLANK , SCB_ASPD|SCB_BATK|SCB_WATK ); - set_sc( HFLI_SPEED , SC_SPEED , SI_BLANK , SCB_FLEE ); - set_sc( HAMI_DEFENCE , SC_DEFENCE , SI_BLANK , SCB_DEF ); - set_sc( HAMI_BLOODLUST , SC_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK ); + add_sc( SA_ELEMENTWATER , SC_ARMOR_PROPERTY ); + add_sc( SA_ELEMENTFIRE , SC_ARMOR_PROPERTY ); + add_sc( SA_ELEMENTGROUND , SC_ARMOR_PROPERTY ); + add_sc( SA_ELEMENTWIND , SC_ARMOR_PROPERTY ); + + set_sc( HLIF_AVOID , SC_HLIF_AVOID , SI_BLANK , SCB_SPEED ); + set_sc( HLIF_CHANGE , SC_HLIF_CHANGE , SI_BLANK , SCB_VIT|SCB_INT ); + set_sc( HFLI_FLEET , SC_HLIF_FLEET , SI_BLANK , SCB_ASPD|SCB_BATK|SCB_WATK ); + set_sc( HFLI_SPEED , SC_HLIF_SPEED , SI_BLANK , SCB_FLEE ); + set_sc( HAMI_DEFENCE , SC_HAMI_DEFENCE , SI_BLANK , SCB_DEF ); + set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK ); // Homunculus S add_sc(MH_STAHL_HORN, SC_STUN); @@ -489,25 +495,25 @@ void initChangeTables(void) { add_sc(MH_ERASER_CUTTER, SC_ERASER_CUTTER); set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD); add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE); - set_sc(MH_VOLCANIC_ASH, SC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE); + set_sc(MH_VOLCANIC_ASH, SC_VOLCANIC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE); set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE); set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE); set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SI_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE); add_sc(MH_LAVA_SLIDE, SC_BURNING); - set_sc(MH_NEEDLE_OF_PARALYZE, SC_PARALYSIS, SI_NEEDLE_OF_PARALYZE, SCB_DEF2); + set_sc(MH_NEEDLE_OF_PARALYZE, SC_NEEDLE_OF_PARALYZE, SI_NEEDLE_OF_PARALYZE, SCB_DEF2); add_sc(MH_POISON_MIST, SC_BLIND); set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD); add_sc(MH_STYLE_CHANGE, SC_STYLE_CHANGE); - set_sc( MH_TINDER_BREAKER , SC_CLOSECONFINE2 , SI_CLOSECONFINE2 , SCB_NONE ); - set_sc( MH_TINDER_BREAKER , SC_CLOSECONFINE , SI_CLOSECONFINE , SCB_FLEE ); + set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE ); + set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE ); add_sc( MER_CRASH , SC_STUN ); set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); add_sc( MS_MAGNUM , SC_WATK_ELEMENT ); add_sc( MER_SIGHT , SC_SIGHT ); - set_sc( MER_DECAGI , SC_DECREASEAGI , SI_DECREASEAGI , SCB_AGI|SCB_SPEED ); + set_sc( MER_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED ); set_sc( MER_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN ); add_sc( MER_LEXDIVINA , SC_SILENCE ); add_sc( MA_LANDMINE , SC_STUN ); @@ -520,19 +526,19 @@ void initChangeTables(void) { set_sc( MS_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE ); set_sc( MS_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN ); add_sc( ML_SPIRALPIERCE , SC_STOP ); - set_sc( MER_QUICKEN , SC_MERC_QUICKEN , SI_BLANK , SCB_ASPD ); + set_sc( MER_QUICKEN , SC_MER_QUICKEN , SI_BLANK , SCB_ASPD ); add_sc( ML_DEVOTION , SC_DEVOTION ); set_sc( MER_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE ); set_sc( MER_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); - set_sc( MER_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED ); + set_sc( MER_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED ); set_sc( GD_LEADERSHIP , SC_LEADERSHIP , SI_BLANK , SCB_STR ); set_sc( GD_GLORYWOUNDS , SC_GLORYWOUNDS , SI_BLANK , SCB_VIT ); set_sc( GD_SOULCOLD , SC_SOULCOLD , SI_BLANK , SCB_AGI ); set_sc( GD_HAWKEYES , SC_HAWKEYES , SI_BLANK , SCB_DEX ); - set_sc( GD_BATTLEORDER , SC_BATTLEORDERS , SI_BLANK , SCB_STR|SCB_INT|SCB_DEX ); - set_sc( GD_REGENERATION , SC_REGENERATION , SI_BLANK , SCB_REGEN ); + set_sc( GD_BATTLEORDER , SC_GDSKILL_BATTLEORDER , SI_BLANK , SCB_STR|SCB_INT|SCB_DEX ); + set_sc( GD_REGENERATION , SC_GDSKILL_REGENERATION , SI_BLANK , SCB_REGEN ); /** * Rune Knight @@ -541,15 +547,16 @@ void initChangeTables(void) { set_sc( RK_DRAGONHOWLING , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT ); set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SI_DEATHBOUND , SCB_NONE ); set_sc( RK_WINDCUTTER , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT ); - add_sc( RK_DRAGONBREATH , SC_BURNING ); - set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_REUSE_MILLENNIUMSHIELD , SCB_NONE ); + set_sc( RK_DRAGONBREATH , SC_BURNING , SI_BLANK , SCB_MDEF ); + set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_BLANK , SCB_NONE ); set_sc( RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE ); set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR ); - set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_DEF|SCB_MDEF ); + set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_NONE ); set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SI_VITALITYACTIVATION, SCB_REGEN ); set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD ); set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE ); set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SI_CRUSHSTRIKE , SCB_NONE ); + add_sc( RK_DRAGONBREATH_WATER, SC_FROSTMISTY ); /** * GC Guillotine Cross **/ @@ -559,12 +566,13 @@ void initChangeTables(void) { set_sc( GC_CLOAKINGEXCEED , SC_CLOAKINGEXCEED , SI_CLOAKINGEXCEED , SCB_SPEED ); set_sc( GC_HALLUCINATIONWALK , SC_HALLUCINATIONWALK, SI_HALLUCINATIONWALK, SCB_FLEE ); set_sc( GC_ROLLINGCUTTER , SC_ROLLINGCUTTER , SI_ROLLINGCUTTER , SCB_NONE ); + set_sc_with_vfx( GC_DARKCROW , SC_DARKCROW , SI_DARKCROW , SCB_NONE ); /** * Arch Bishop **/ set_sc( AB_ADORAMUS , SC_ADORAMUS , SI_ADORAMUS , SCB_AGI|SCB_SPEED ); add_sc( AB_CLEMENTIA , SC_BLESSING ); - add_sc( AB_CANTO , SC_INCREASEAGI ); + add_sc( AB_CANTO , SC_INC_AGI ); set_sc( AB_EPICLESIS , SC_EPICLESIS , SI_EPICLESIS , SCB_MAXHP ); add_sc( AB_PRAEFATIO , SC_KYRIE ); set_sc_with_vfx( AB_ORATIO , SC_ORATIO , SI_ORATIO , SCB_NONE ); @@ -574,14 +582,16 @@ void initChangeTables(void) { set_sc( AB_EXPIATIO , SC_EXPIATIO , SI_EXPIATIO , SCB_ATK_ELE ); set_sc( AB_DUPLELIGHT , SC_DUPLELIGHT , SI_DUPLELIGHT , SCB_NONE ); set_sc( AB_SECRAMENT , SC_SECRAMENT , SI_SECRAMENT , SCB_NONE ); + set_sc( AB_OFFERTORIUM , SC_OFFERTORIUM , SI_OFFERTORIUM , SCB_NONE ); /** * Warlock **/ add_sc( WL_WHITEIMPRISON , SC_WHITEIMPRISON ); - set_sc_with_vfx( WL_FROSTMISTY , SC_FREEZING , SI_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF|SCB_DEF2 ); - set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SI_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_DEF|SCB_MDEF ); + set_sc_with_vfx( WL_FROSTMISTY , SC_FROSTMISTY , SI_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF ); + set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SI_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_AGI|SCB_DEX ); set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_MATK); set_sc( WL_STASIS , SC_STASIS , SI_STASIS , SCB_NONE ); + set_sc( WL_TELEKINESIS_INTENSE, SC_TELEKINESIS_INTENSE , SI_TELEKINESIS_INTENSE , SCB_MATK ); /** * Ranger **/ @@ -589,12 +599,13 @@ void initChangeTables(void) { set_sc( RA_ELECTRICSHOCKER , SC_ELECTRICSHOCKER , SI_ELECTRICSHOCKER , SCB_NONE ); set_sc( RA_WUGDASH , SC_WUGDASH , SI_WUGDASH , SCB_SPEED ); set_sc( RA_CAMOUFLAGE , SC_CAMOUFLAGE , SI_CAMOUFLAGE , SCB_SPEED ); - add_sc( RA_MAGENTATRAP , SC_ELEMENTALCHANGE ); - add_sc( RA_COBALTTRAP , SC_ELEMENTALCHANGE ); - add_sc( RA_MAIZETRAP , SC_ELEMENTALCHANGE ); - add_sc( RA_VERDURETRAP , SC_ELEMENTALCHANGE ); - add_sc( RA_FIRINGTRAP , SC_BURNING ); - set_sc_with_vfx( RA_ICEBOUNDTRAP , SC_FREEZING , SI_FROSTMISTY , SCB_NONE ); + add_sc( RA_MAGENTATRAP , SC_ARMOR_PROPERTY ); + add_sc( RA_COBALTTRAP , SC_ARMOR_PROPERTY ); + add_sc( RA_MAIZETRAP , SC_ARMOR_PROPERTY ); + add_sc( RA_VERDURETRAP , SC_ARMOR_PROPERTY ); + add_sc( RA_FIRINGTRAP , SC_BURNING ); + add_sc( RA_ICEBOUNDTRAP , SC_FROSTMISTY ); + set_sc( RA_UNLIMIT , SC_UNLIMIT , SI_UNLIMIT , SCB_NONE ); /** * Mechanic **/ @@ -609,7 +620,7 @@ void initChangeTables(void) { /** * Royal Guard **/ - set_sc( LG_REFLECTDAMAGE , SC_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE ); + set_sc( LG_REFLECTDAMAGE , SC_LG_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE ); set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP|SCB_DEF ); set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE ); set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF ); @@ -619,6 +630,7 @@ void initChangeTables(void) { set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK); set_sc( LG_SHIELDSPELL , SC_SHIELDSPELL_DEF , SI_SHIELDSPELL_DEF , SCB_WATK ); set_sc( LG_SHIELDSPELL , SC_SHIELDSPELL_REF , SI_SHIELDSPELL_REF , SCB_DEF ); + set_sc( LG_KINGS_GRACE , SC_KINGS_GRACE , SI_KINGS_GRACE , SCB_NONE ); /** * Shadow Chaser **/ @@ -634,7 +646,7 @@ void initChangeTables(void) { set_sc( SC_LAZINESS , SC__LAZINESS , SI_LAZINESS , SCB_FLEE ); set_sc( SC_UNLUCKY , SC__UNLUCKY , SI_UNLUCKY , SCB_CRI|SCB_FLEE2 ); set_sc( SC_WEAKNESS , SC__WEAKNESS , SI_WEAKNESS , SCB_FLEE2|SCB_MAXHP ); - set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSORY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK ); + set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSARY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK ); set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SI_MANHOLE , SCB_NONE ); add_sc( SC_CHAOSPANIC , SC_CONFUSION ); set_sc_with_vfx( SC_BLOODYLUST , SC__BLOODYLUST , SI_BLOODYLUST , SCB_DEF | SCB_DEF2 | SCB_MDEF | SCB_MDEF2 | SCB_FLEE | SCB_SPEED | SCB_ASPD | SCB_MAXHP | SCB_REGEN ); @@ -647,30 +659,32 @@ void initChangeTables(void) { set_sc_with_vfx( SR_CURSEDCIRCLE , SC_CURSEDCIRCLE_TARGET, SI_CURSEDCIRCLE_TARGET , SCB_NONE ); set_sc( SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SI_LIGHTNINGWALK , SCB_NONE ); set_sc( SR_RAISINGDRAGON , SC_RAISINGDRAGON , SI_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP ); - set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GT_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE ); - set_sc( SR_GENTLETOUCH_CHANGE , SC_GT_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP ); - set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GT_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_REGEN ); + set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GENTLETOUCH_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE ); + set_sc( SR_GENTLETOUCH_CHANGE , SC_GENTLETOUCH_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP ); + set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GENTLETOUCH_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_REGEN ); /** * Wanderer / Minstrel **/ - set_sc( WA_SWING_DANCE , SC_SWINGDANCE , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD ); - set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONYOFLOVER , SI_SYMPHONYOFLOVERS , SCB_MDEF ); - set_sc( WA_MOONLIT_SERENADE , SC_MOONLITSERENADE , SI_MOONLITSERENADE , SCB_MATK ); - set_sc( MI_RUSH_WINDMILL , SC_RUSHWINDMILL , SI_RUSHWINDMILL , SCB_BATK ); - set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 ); - set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); - set_sc_with_vfx( WM_POEMOFNETHERWORLD , SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE ); - set_sc_with_vfx( WM_VOICEOFSIREN , SC_VOICEOFSIREN , SI_VOICEOFSIREN , SCB_NONE ); - set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEPSLEEP , SI_DEEPSLEEP , SCB_NONE ); - set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE ); - set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_ASPD ); - set_sc( WM_SONG_OF_MANA , SC_SONGOFMANA , SI_SONGOFMANA , SCB_NONE ); - set_sc( WM_DANCE_WITH_WUG , SC_DANCEWITHWUG , SI_DANCEWITHWUG , SCB_ASPD ); - set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAYNIGHTFEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN ); - set_sc( WM_LERADS_DEW , SC_LERADSDEW , SI_LERADSDEW , SCB_MAXHP ); - set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_BATK|SCB_MATK ); - set_sc( WM_BEYOND_OF_WARCRY , SC_BEYONDOFWARCRY , SI_WARCRYOFBEYOND , SCB_BATK|SCB_MATK ); - set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITEDHUMMINGVOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE ); + set_sc( WA_SWING_DANCE , SC_SWING , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD ); + set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONY_LOVE , SI_SYMPHONYOFLOVERS , SCB_MDEF ); + set_sc( WA_MOONLIT_SERENADE , SC_MOONLIT_SERENADE , SI_MOONLITSERENADE , SCB_MATK ); + set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SI_RUSHWINDMILL , SCB_BATK ); + set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 ); + set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + set_sc_with_vfx( WM_POEMOFNETHERWORLD , SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE ); + set_sc_with_vfx( WM_VOICEOFSIREN , SC_SIREN , SI_SIREN , SCB_NONE ); + set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE ); + set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE ); + set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_ASPD ); + set_sc( WM_SONG_OF_MANA , SC_SONG_OF_MANA , SI_SONG_OF_MANA , SCB_NONE ); + set_sc( WM_DANCE_WITH_WUG , SC_DANCE_WITH_WUG , SI_DANCEWITHWUG , SCB_ASPD ); + set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAY_NIGHT_FEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN ); + set_sc( WM_LERADS_DEW , SC_LERADS_DEW , SI_LERADSDEW , SCB_MAXHP ); + set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_BATK|SCB_MATK ); + set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SI_WARCRYOFBEYOND , SCB_BATK|SCB_MATK ); + set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE ); + set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SI_FRIGG_SONG , SCB_MAXHP ); + /** * Sorcerer **/ @@ -682,7 +696,7 @@ void initChangeTables(void) { set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI ); set_sc( SO_WARMER , SC_WARMER , SI_WARMER , SCB_NONE ); set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE ); - set_sc( SO_ARRULLO , SC_DEEPSLEEP , SI_DEEPSLEEP , SCB_NONE ); + set_sc( SO_ARRULLO , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE ); set_sc( SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SI_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); set_sc( SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SI_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); set_sc( SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SI_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); @@ -691,11 +705,11 @@ void initChangeTables(void) { * Genetic **/ set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SI_CARTSBOOST , SCB_SPEED ); - set_sc( GN_THORNS_TRAP , SC_THORNSTRAP , SI_THORNTRAP , SCB_NONE ); - set_sc_with_vfx( GN_BLOOD_SUCKER , SC_BLOODSUCKER , SI_BLOODSUCKER , SCB_NONE ); + set_sc( GN_THORNS_TRAP , SC_THORNS_TRAP , SI_THORNTRAP , SCB_NONE ); + set_sc_with_vfx( GN_BLOOD_SUCKER , SC_BLOOD_SUCKER , SI_BLOODSUCKER , SCB_NONE ); set_sc( GN_WALLOFTHORN , SC_STOP , SI_BLANK , SCB_NONE ); - set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_SMOKEPOWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_NONE ); - set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_TEARGAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE ); + set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_FIRE_EXPANSION_SMOKE_POWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_NONE ); + set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_FIRE_EXPANSION_TEAR_GAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE ); set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT ); // Elemental Spirit summoner's 'side' status changes. @@ -727,7 +741,7 @@ void initChangeTables(void) { set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED ); add_sc( KO_YAMIKUMO , SC_HIDING ); - set_sc_with_vfx( KO_JYUMONJIKIRI , SC_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE ); + set_sc_with_vfx( KO_JYUMONJIKIRI , SC_KO_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE ); add_sc( KO_MAKIBISHI , SC_STUN ); set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE ); set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); @@ -736,12 +750,14 @@ void initChangeTables(void) { set_sc( KO_IZAYOI , SC_IZAYOI , SI_IZAYOI , SCB_MATK ); set_sc( KG_KYOMU , SC_KYOMU , SI_KYOMU , SCB_NONE ); set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SI_KAGEMUSYA , SCB_NONE ); - set_sc( KG_KAGEHUMI , SC_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE ); + set_sc( KG_KAGEHUMI , SC_KG_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE ); set_sc( OB_ZANGETSU , SC_ZANGETSU , SI_ZANGETSU , SCB_MATK|SCB_BATK ); set_sc_with_vfx( OB_AKAITSUKI , SC_AKAITSUKI , SI_AKAITSUKI , SCB_NONE ); set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE ); - // Storing the target job rather than simply SC_SPIRIT simplifies code later on. + set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SI_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + + // Storing the target job rather than simply SC_SOULLINK simplifies code later on. SkillStatusChangeTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST, SkillStatusChangeTable[SL_MONK] = (sc_type)MAPID_MONK, SkillStatusChangeTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR, @@ -759,33 +775,33 @@ void initChangeTables(void) { SkillStatusChangeTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER, //Status that don't have a skill associated. - StatusIconChangeTable[SC_WEIGHT50] = SI_WEIGHT50; - StatusIconChangeTable[SC_WEIGHT90] = SI_WEIGHT90; - StatusIconChangeTable[SC_ASPDPOTION0] = SI_ASPDPOTION0; - StatusIconChangeTable[SC_ASPDPOTION1] = SI_ASPDPOTION1; - StatusIconChangeTable[SC_ASPDPOTION2] = SI_ASPDPOTION2; - StatusIconChangeTable[SC_ASPDPOTION3] = SI_ASPDPOTIONINFINITY; - StatusIconChangeTable[SC_SPEEDUP0] = SI_MOVHASTE_HORSE; - StatusIconChangeTable[SC_SPEEDUP1] = SI_SPEEDPOTION1; - StatusIconChangeTable[SC_INCSTR] = SI_INCSTR; - StatusIconChangeTable[SC_MIRACLE] = SI_SPIRIT; - StatusIconChangeTable[SC_INTRAVISION] = SI_INTRAVISION; - StatusIconChangeTable[SC_STRFOOD] = SI_FOODSTR; - StatusIconChangeTable[SC_AGIFOOD] = SI_FOODAGI; - StatusIconChangeTable[SC_VITFOOD] = SI_FOODVIT; - StatusIconChangeTable[SC_INTFOOD] = SI_FOODINT; - StatusIconChangeTable[SC_DEXFOOD] = SI_FOODDEX; - StatusIconChangeTable[SC_LUKFOOD] = SI_FOODLUK; - StatusIconChangeTable[SC_FLEEFOOD]= SI_FOODFLEE; - StatusIconChangeTable[SC_HITFOOD] = SI_FOODHIT; + StatusIconChangeTable[SC_WEIGHTOVER50] = SI_WEIGHTOVER50; + StatusIconChangeTable[SC_WEIGHTOVER90] = SI_WEIGHTOVER90; + StatusIconChangeTable[SC_ATTHASTE_POTION1] = SI_ATTHASTE_POTION1; + StatusIconChangeTable[SC_ATTHASTE_POTION2] = SI_ATTHASTE_POTION2; + StatusIconChangeTable[SC_ATTHASTE_POTION3] = SI_ATTHASTE_POTION3; + StatusIconChangeTable[SC_ATTHASTE_INFINITY] = SI_ATTHASTE_INFINITY; + StatusIconChangeTable[SC_MOVHASTE_HORSE] = SI_MOVHASTE_HORSE; + StatusIconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY; + StatusIconChangeTable[SC_CHASEWALK2] = SI_INCSTR; + StatusIconChangeTable[SC_MIRACLE] = SI_SOULLINK; + StatusIconChangeTable[SC_CLAIRVOYANCE] = SI_CLAIRVOYANCE; + StatusIconChangeTable[SC_FOOD_STR] = SI_FOOD_STR; + StatusIconChangeTable[SC_FOOD_AGI] = SI_FOOD_AGI; + StatusIconChangeTable[SC_FOOD_VIT] = SI_FOOD_VIT; + StatusIconChangeTable[SC_FOOD_INT] = SI_FOOD_INT; + StatusIconChangeTable[SC_FOOD_DEX] = SI_FOOD_DEX; + StatusIconChangeTable[SC_FOOD_LUK] = SI_FOOD_LUK; + StatusIconChangeTable[SC_FOOD_BASICAVOIDANCE]= SI_FOOD_BASICAVOIDANCE; + StatusIconChangeTable[SC_FOOD_BASICHIT] = SI_FOOD_BASICHIT; StatusIconChangeTable[SC_MANU_ATK] = SI_MANU_ATK; StatusIconChangeTable[SC_MANU_DEF] = SI_MANU_DEF; StatusIconChangeTable[SC_SPL_ATK] = SI_SPL_ATK; StatusIconChangeTable[SC_SPL_DEF] = SI_SPL_DEF; StatusIconChangeTable[SC_MANU_MATK] = SI_MANU_MATK; StatusIconChangeTable[SC_SPL_MATK] = SI_SPL_MATK; - StatusIconChangeTable[SC_ATKPOTION] = SI_PLUSATTACKPOWER; - StatusIconChangeTable[SC_MATKPOTION] = SI_PLUSMAGICPOWER; + StatusIconChangeTable[SC_PLUSATTACKPOWER] = SI_PLUSATTACKPOWER; + StatusIconChangeTable[SC_PLUSMAGICPOWER] = SI_PLUSMAGICPOWER; //Cash Items StatusIconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH; StatusIconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH; @@ -793,32 +809,32 @@ void initChangeTables(void) { StatusIconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH; StatusIconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH; StatusIconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH; - StatusIconChangeTable[SC_EXPBOOST] = SI_EXPBOOST; - StatusIconChangeTable[SC_ITEMBOOST] = SI_ITEMBOOST; - StatusIconChangeTable[SC_JEXPBOOST] = SI_CASH_PLUSONLYJOBEXP; - StatusIconChangeTable[SC_LIFEINSURANCE] = SI_LIFEINSURANCE; - StatusIconChangeTable[SC_BOSSMAPINFO] = SI_BOSSMAPINFO; - StatusIconChangeTable[SC_DEF_RATE] = SI_DEF_RATE; - StatusIconChangeTable[SC_MDEF_RATE] = SI_MDEF_RATE; - StatusIconChangeTable[SC_INCCRI] = SI_INCCRI; - StatusIconChangeTable[SC_INCFLEE2] = SI_PLUSAVOIDVALUE; - StatusIconChangeTable[SC_INCHEALRATE] = SI_INCHEALRATE; + StatusIconChangeTable[SC_CASH_PLUSEXP] = SI_CASH_PLUSEXP; + StatusIconChangeTable[SC_CASH_RECEIVEITEM] = SI_CASH_RECEIVEITEM; + StatusIconChangeTable[SC_CASH_PLUSONLYJOBEXP] = SI_CASH_PLUSONLYJOBEXP; + StatusIconChangeTable[SC_CASH_DEATHPENALTY] = SI_CASH_DEATHPENALTY; + StatusIconChangeTable[SC_CASH_BOSS_ALARM] = SI_CASH_BOSS_ALARM; + StatusIconChangeTable[SC_PROTECT_DEF] = SI_PROTECT_DEF; + StatusIconChangeTable[SC_PROTECT_MDEF] = SI_PROTECT_MDEF; + StatusIconChangeTable[SC_CRITICALPERCENT] = SI_CRITICALPERCENT; + StatusIconChangeTable[SC_PLUSAVOIDVALUE] = SI_PLUSAVOIDVALUE; + StatusIconChangeTable[SC_HEALPLUS] = SI_HEALPLUS; StatusIconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION; StatusIconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION; - StatusIconChangeTable[SC_SPCOST_RATE] = SI_ATKER_BLOOD; - StatusIconChangeTable[SC_COMMONSC_RESIST] = SI_TARGET_BLOOD; + StatusIconChangeTable[SC_ATKER_BLOOD] = SI_ATKER_BLOOD; + StatusIconChangeTable[SC_TARGET_BLOOD] = SI_TARGET_BLOOD; // Mercenary Bonus Effects - StatusIconChangeTable[SC_MERC_FLEEUP] = SI_MERC_FLEEUP; - StatusIconChangeTable[SC_MERC_ATKUP] = SI_MERC_ATKUP; - StatusIconChangeTable[SC_MERC_HPUP] = SI_MERC_HPUP; - StatusIconChangeTable[SC_MERC_SPUP] = SI_MERC_SPUP; - StatusIconChangeTable[SC_MERC_HITUP] = SI_MERC_HITUP; + StatusIconChangeTable[SC_MER_FLEE] = SI_MER_FLEE; + StatusIconChangeTable[SC_MER_ATK] = SI_MER_ATK; + StatusIconChangeTable[SC_MER_HP] = SI_MER_HP; + StatusIconChangeTable[SC_MER_SP] = SI_MER_SP; + StatusIconChangeTable[SC_MER_HIT] = SI_MER_HIT; // Warlock Spheres - StatusIconChangeTable[SC_SPHERE_1] = SI_SPHERE_1; - StatusIconChangeTable[SC_SPHERE_2] = SI_SPHERE_2; - StatusIconChangeTable[SC_SPHERE_3] = SI_SPHERE_3; - StatusIconChangeTable[SC_SPHERE_4] = SI_SPHERE_4; - StatusIconChangeTable[SC_SPHERE_5] = SI_SPHERE_5; + StatusIconChangeTable[SC_SUMMON1] = SI_SPHERE_1; + StatusIconChangeTable[SC_SUMMON2] = SI_SPHERE_2; + StatusIconChangeTable[SC_SUMMON3] = SI_SPHERE_3; + StatusIconChangeTable[SC_SUMMON4] = SI_SPHERE_4; + StatusIconChangeTable[SC_SUMMON5] = SI_SPHERE_5; // Warlock Preserved spells StatusIconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1; StatusIconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2; @@ -826,7 +842,7 @@ void initChangeTables(void) { StatusIconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4; StatusIconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5; StatusIconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6; - StatusIconChangeTable[SC_MAXSPELLBOOK] = SI_SPELLBOOK7; + StatusIconChangeTable[SC_SPELLBOOK7] = SI_SPELLBOOK7; StatusIconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER; StatusIconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER; @@ -856,7 +872,7 @@ void initChangeTables(void) { StatusIconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER; StatusIconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB; StatusIconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB; - StatusIconChangeTable[SC_BANANA_BOMB_SITDOWN] = SI_BANANA_BOMB_SITDOWN_POSTDELAY; + StatusIconChangeTable[SC_BANANA_BOMB_SITDOWN_POSTDELAY] = SI_BANANA_BOMB_SITDOWN_POSTDELAY; //Genetics New Food Items Status Icons StatusIconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK; @@ -897,19 +913,20 @@ void initChangeTables(void) { StatusIconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL; StatusIconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL; StatusIconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART; + StatusIconChangeTable[SC_REBOUND] = SI_REBOUND; StatusIconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING; //Other SC which are not necessarily associated to skills. - StatusChangeFlagTable[SC_ASPDPOTION0] = SCB_ASPD; - StatusChangeFlagTable[SC_ASPDPOTION1] = SCB_ASPD; - StatusChangeFlagTable[SC_ASPDPOTION2] = SCB_ASPD; - StatusChangeFlagTable[SC_ASPDPOTION3] = SCB_ASPD; - StatusChangeFlagTable[SC_SPEEDUP0] = SCB_SPEED; - StatusChangeFlagTable[SC_SPEEDUP1] = SCB_SPEED; - StatusChangeFlagTable[SC_ATKPOTION] = SCB_BATK; - StatusChangeFlagTable[SC_MATKPOTION] = SCB_MATK; + StatusChangeFlagTable[SC_ATTHASTE_POTION1] = SCB_ASPD; + StatusChangeFlagTable[SC_ATTHASTE_POTION2] = SCB_ASPD; + StatusChangeFlagTable[SC_ATTHASTE_POTION3] = SCB_ASPD; + StatusChangeFlagTable[SC_ATTHASTE_INFINITY] = SCB_ASPD; + StatusChangeFlagTable[SC_MOVHASTE_HORSE] = SCB_SPEED; + StatusChangeFlagTable[SC_MOVHASTE_INFINITY] = SCB_SPEED; + StatusChangeFlagTable[SC_PLUSATTACKPOWER] = SCB_BATK; + StatusChangeFlagTable[SC_PLUSMAGICPOWER] = SCB_MATK; StatusChangeFlagTable[SC_INCALLSTATUS] |= SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK; - StatusChangeFlagTable[SC_INCSTR] |= SCB_STR; + StatusChangeFlagTable[SC_CHASEWALK2] |= SCB_STR; StatusChangeFlagTable[SC_INCAGI] |= SCB_AGI; StatusChangeFlagTable[SC_INCVIT] |= SCB_VIT; StatusChangeFlagTable[SC_INCINT] |= SCB_INT; @@ -919,9 +936,9 @@ void initChangeTables(void) { StatusChangeFlagTable[SC_INCHITRATE] |= SCB_HIT; StatusChangeFlagTable[SC_INCFLEE] |= SCB_FLEE; StatusChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE; - StatusChangeFlagTable[SC_INCCRI] |= SCB_CRI; + StatusChangeFlagTable[SC_CRITICALPERCENT] |= SCB_CRI; StatusChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD; - StatusChangeFlagTable[SC_INCFLEE2] |= SCB_FLEE2; + StatusChangeFlagTable[SC_PLUSAVOIDVALUE] |= SCB_FLEE2; StatusChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP; StatusChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP; StatusChangeFlagTable[SC_INCMHP] |= SCB_MAXHP; @@ -929,20 +946,20 @@ void initChangeTables(void) { StatusChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK; StatusChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK; StatusChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF; - StatusChangeFlagTable[SC_STRFOOD] |= SCB_STR; - StatusChangeFlagTable[SC_AGIFOOD] |= SCB_AGI; - StatusChangeFlagTable[SC_VITFOOD] |= SCB_VIT; - StatusChangeFlagTable[SC_INTFOOD] |= SCB_INT; - StatusChangeFlagTable[SC_DEXFOOD] |= SCB_DEX; - StatusChangeFlagTable[SC_LUKFOOD] |= SCB_LUK; - StatusChangeFlagTable[SC_HITFOOD] |= SCB_HIT; - StatusChangeFlagTable[SC_FLEEFOOD] |= SCB_FLEE; + StatusChangeFlagTable[SC_FOOD_STR] |= SCB_STR; + StatusChangeFlagTable[SC_FOOD_AGI] |= SCB_AGI; + StatusChangeFlagTable[SC_FOOD_VIT] |= SCB_VIT; + StatusChangeFlagTable[SC_FOOD_INT] |= SCB_INT; + StatusChangeFlagTable[SC_FOOD_DEX] |= SCB_DEX; + StatusChangeFlagTable[SC_FOOD_LUK] |= SCB_LUK; + StatusChangeFlagTable[SC_FOOD_BASICHIT] |= SCB_HIT; + StatusChangeFlagTable[SC_FOOD_BASICAVOIDANCE] |= SCB_FLEE; StatusChangeFlagTable[SC_BATKFOOD] |= SCB_BATK; StatusChangeFlagTable[SC_WATKFOOD] |= SCB_WATK; StatusChangeFlagTable[SC_MATKFOOD] |= SCB_MATK; - StatusChangeFlagTable[SC_ARMOR_ELEMENT] |= SCB_ALL; + StatusChangeFlagTable[SC_ARMORPROPERTY] |= SCB_ALL; StatusChangeFlagTable[SC_ARMOR_RESIST] |= SCB_ALL; - StatusChangeFlagTable[SC_SPCOST_RATE] |= SCB_ALL; + StatusChangeFlagTable[SC_ATKER_BLOOD] |= SCB_ALL; StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; StatusChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL; // Cash Items @@ -953,11 +970,11 @@ void initChangeTables(void) { StatusChangeFlagTable[SC_FOOD_INT_CASH] = SCB_INT; StatusChangeFlagTable[SC_FOOD_LUK_CASH] = SCB_LUK; // Mercenary Bonus Effects - StatusChangeFlagTable[SC_MERC_FLEEUP] |= SCB_FLEE; - StatusChangeFlagTable[SC_MERC_ATKUP] |= SCB_WATK; - StatusChangeFlagTable[SC_MERC_HPUP] |= SCB_MAXHP; - StatusChangeFlagTable[SC_MERC_SPUP] |= SCB_MAXSP; - StatusChangeFlagTable[SC_MERC_HITUP] |= SCB_HIT; + StatusChangeFlagTable[SC_MER_FLEE] |= SCB_FLEE; + StatusChangeFlagTable[SC_MER_ATK] |= SCB_WATK; + StatusChangeFlagTable[SC_MER_HP] |= SCB_MAXHP; + StatusChangeFlagTable[SC_MER_SP] |= SCB_MAXSP; + StatusChangeFlagTable[SC_MER_HIT] |= SCB_HIT; // Guillotine Cross Poison Effects StatusChangeFlagTable[SC_PARALYSE] |= SCB_ASPD|SCB_FLEE|SCB_SPEED; StatusChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN; @@ -978,30 +995,31 @@ void initChangeTables(void) { StatusChangeFlagTable[SC_EXTRACT_WHITE_POTION_Z] |= SCB_REGEN; StatusChangeFlagTable[SC_VITATA_500] |= SCB_REGEN; StatusChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD; + StatusChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN; StatusChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED; /* StatusDisplayType Table [Ind/Hercules] */ StatusDisplayType[SC_ALL_RIDING] = true; StatusDisplayType[SC_PUSH_CART] = true; - StatusDisplayType[SC_SPHERE_1] = true; - StatusDisplayType[SC_SPHERE_2] = true; - StatusDisplayType[SC_SPHERE_3] = true; - StatusDisplayType[SC_SPHERE_4] = true; - StatusDisplayType[SC_SPHERE_5] = true; + StatusDisplayType[SC_SUMMON1] = true; + StatusDisplayType[SC_SUMMON2] = true; + StatusDisplayType[SC_SUMMON3] = true; + StatusDisplayType[SC_SUMMON4] = true; + StatusDisplayType[SC_SUMMON5] = true; StatusDisplayType[SC_CAMOUFLAGE] = true; StatusDisplayType[SC_DUPLELIGHT] = true; StatusDisplayType[SC_ORATIO] = true; - StatusDisplayType[SC_FREEZING] = true; + StatusDisplayType[SC_FROSTMISTY] = true; StatusDisplayType[SC_VENOMIMPRESS] = true; StatusDisplayType[SC_HALLUCINATIONWALK] = true; StatusDisplayType[SC_ROLLINGCUTTER] = true; StatusDisplayType[SC_BANDING] = true; StatusDisplayType[SC_CRYSTALIZE] = true; - StatusDisplayType[SC_DEEPSLEEP] = true; + StatusDisplayType[SC_DEEP_SLEEP] = true; StatusDisplayType[SC_CURSEDCIRCLE_ATKER]= true; StatusDisplayType[SC_CURSEDCIRCLE_TARGET]= true; - StatusDisplayType[SC_BLOODSUCKER] = true; + StatusDisplayType[SC_BLOOD_SUCKER] = true; StatusDisplayType[SC__SHADOWFORM] = true; StatusDisplayType[SC__MANHOLE] = true; @@ -1011,7 +1029,7 @@ void initChangeTables(void) { #endif if( !battle_config.display_hallucination ) //Disable Hallucination. - StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK; + StatusIconChangeTable[SC_ILLUSION] = SI_BLANK; } static void initDummyData(void) @@ -1147,7 +1165,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status_change_end(target, SC_STONE, INVALID_TIMER); status_change_end(target, SC_FREEZE, INVALID_TIMER); status_change_end(target, SC_SLEEP, INVALID_TIMER); - status_change_end(target, SC_WINKCHARM, INVALID_TIMER); + status_change_end(target, SC_DC_WINKCHARM, INVALID_TIMER); status_change_end(target, SC_CONFUSION, INVALID_TIMER); status_change_end(target, SC_TRICKDEAD, INVALID_TIMER); status_change_end(target, SC_HIDING, INVALID_TIMER); @@ -1155,8 +1173,8 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status_change_end(target, SC_CHASEWALK, INVALID_TIMER); status_change_end(target, SC_CAMOUFLAGE, INVALID_TIMER); status_change_end(target, SC__INVISIBILITY, INVALID_TIMER); - status_change_end(target, SC_DEEPSLEEP, INVALID_TIMER); - if ((sce=sc->data[SC_ENDURE]) && !sce->val4) { + status_change_end(target, SC_DEEP_SLEEP, INVALID_TIMER); + if ((sce=sc->data[SC_ENDURE]) && !sce->val4 && !sc->data[SC_LKCONCENTRATION]) { //Endure count is only reduced by non-players on non-gvg maps. //val4 signals infinite endure. [Skotlex] if (src && src->type != BL_PC && !map_flag_gvg(target->m) && !map[target->m].flag.battleground && --(sce->val2) < 0) @@ -1192,8 +1210,8 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status_change_end(target, SC_BERSERK, INVALID_TIMER); if( sc->data[SC_RAISINGDRAGON] && status->hp <= 1000 ) status_change_end(target, SC_RAISINGDRAGON, INVALID_TIMER); - if (sc->data[SC_SATURDAYNIGHTFEVER] && status->hp <= 100) - status_change_end(target, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); + if (sc->data[SC_SATURDAY_NIGHT_FEVER] && status->hp <= 100) + status_change_end(target, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER); if (sc->data[SC__BLOODYLUST] && status->hp <= 100) status_change_end(target, SC__BLOODYLUST, INVALID_TIMER); } @@ -1576,9 +1594,9 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin ) return 0; - if (sc->data[SC_WINKCHARM] && target && !flag) { //Prevents skill usage + if (sc->data[SC_DC_WINKCHARM] && target && !flag) { //Prevents skill usage if( unit_bl2ud(src) && (unit_bl2ud(src))->walktimer == INVALID_TIMER ) - unit_walktobl(src, iMap->id2bl(sc->data[SC_WINKCHARM]->val2), 3, 1); + unit_walktobl(src, iMap->id2bl(sc->data[SC_DC_WINKCHARM]->val2), 3, 1); clif->emotion(src, E_LV); return 0; } @@ -1632,13 +1650,13 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin sc->data[SC__INVISIBILITY] || (sc->data[SC_CRYSTALIZE] && src->type != BL_MOB) || sc->data[SC__IGNORANCE] || - sc->data[SC_DEEPSLEEP] || - sc->data[SC_SATURDAYNIGHTFEVER] || + sc->data[SC_DEEP_SLEEP] || + sc->data[SC_SATURDAY_NIGHT_FEVER] || sc->data[SC_CURSEDCIRCLE_TARGET] || - (sc->data[SC_MARIONETTE] && skill_id != CG_MARIONETTE) || //Only skill you can use is marionette again to cancel it - (sc->data[SC_MARIONETTE2] && skill_id == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another + (sc->data[SC_MARIONETTE_MASTER] && skill_id != CG_MARIONETTE) || //Only skill you can use is marionette again to cancel it + (sc->data[SC_MARIONETTE] && skill_id == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another (sc->data[SC_STASIS] && skill->block_check(src, SC_STASIS, skill_id)) || - (sc->data[SC_KAGEHUMI] && skill->block_check(src, SC_KAGEHUMI, skill_id)) + (sc->data[SC_KG_KAGEHUMI] && skill->block_check(src, SC_KG_KAGEHUMI, skill_id)) )) return 0; @@ -1882,17 +1900,18 @@ static unsigned short status_base_atk(const struct block_list *bl, const struct str += dstr*dstr; if (bl->type == BL_PC) #ifdef RENEWAL - str = (rstr*10 + dex*10/5 + status->luk*10/3 + ((TBL_PC*)bl)->status.base_level*10/4)/10; + str = (int)(rstr + (float)dex/5 + (float)status->luk/3 + (float)((TBL_PC*)bl)->status.base_level/4); + else if(bl->type == BL_MOB) + str = rstr + ((TBL_MOB*)bl)->level; #else str+= dex/5 + status->luk/5; #endif return cap_value(str, 0, USHRT_MAX); } -#ifndef RENEWAL static inline unsigned short status_base_matk_min(const struct status_data* status){ return status->int_+(status->int_/7)*(status->int_/7); } static inline unsigned short status_base_matk_max(const struct status_data* status){ return status->int_+(status->int_/5)*(status->int_/5); } -#else +#ifdef RENEWAL unsigned short status_base_matk(const struct status_data* status, int level){ return status->int_+(status->int_/2)+(status->dex/5)+(status->luk/3)+(level/4); } #endif @@ -1907,11 +1926,11 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev status->cri = status->flee2 = 0; #ifdef RENEWAL // renewal formulas - status->matk_min = status->matk_max = status_base_matk(status, level); - status->hit += level + status->dex + status->luk/3 + 175; //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175 - status->flee += level + status->agi + status->luk/5 + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 - status->def2 += (int)(((float)level + status->vit)/2 + ((float)status->agi/5)); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def) - status->mdef2 += (int)(status->int_ + ((float)level/4) + ((float)status->dex/5) + ((float)status->vit/5)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef) + status->matk_min = status->matk_max = bl->type == BL_PC ? status_base_matk(status, level) : level + status->int_; + status->hit += level + status->dex + (bl->type == BL_PC ? status->luk/3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175 + status->flee += level + status->agi + (bl->type == BL_PC ? status->luk/5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 + status->def2 += (int)(((float)level + status->vit)/2 + ( bl->type == BL_PC ? ((float)status->agi/5) : 0 )); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def) + status->mdef2 += (int)( bl->type == BL_PC ?(status->int_ + ((float)level/4) + ((float)(status->dex+status->vit)/5)):((float)(status->int_ + level)/4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef) #else status->matk_min = status_base_matk_min(status); status->matk_max = status_base_matk_max(status); @@ -1947,6 +1966,13 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev case BL_PC: //Players don't have a critical adjustment setting as of yet. break; + case BL_MER: +#ifdef RENEWAL + status->matk_min = status->matk_max = status_base_matk_max(status); + status->def2 = status->vit + level / 10 + status->vit / 5; + status->mdef2 = level / 10 + status->int_ / 5; +#endif + break; default: if(battle_config.critical_rate != 100) status->cri = status->cri*battle_config.critical_rate/100; @@ -2030,7 +2056,7 @@ int status_calc_mob_(struct mob_data* md, bool first) if (ud->skill_id == AM_SPHEREMINE) { status->max_hp = 2000 + 400*ud->skill_lv; } else if(ud->skill_id == KO_ZANZOU){ - status->max_hp = 3000 + 3000 * ud->skill_lv; + status->max_hp = 3000 + 3000 * ud->skill_lv + status_get_max_sp(battle->get_master(mbl)); } else { //AM_CANNIBALIZE status->max_hp = 1500 + 200*ud->skill_lv + 10*status_get_lv(mbl); status->mode|= MD_CANATTACK|MD_AGGRESSIVE; @@ -2352,8 +2378,8 @@ int status_calc_pc_(struct map_session_data* sd, bool first) memset (&sd->right_weapon.overrefine, 0, sizeof(sd->right_weapon) - sizeof(sd->right_weapon.atkmods)); memset (&sd->left_weapon.overrefine, 0, sizeof(sd->left_weapon) - sizeof(sd->left_weapon.atkmods)); - if (sd->special_state.intravision && !sd->sc.data[SC_INTRAVISION]) //Clear intravision as long as nothing else is using it - clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_INTRAVISION); + if (sd->special_state.intravision && !sd->sc.data[SC_CLAIRVOYANCE]) //Clear intravision as long as nothing else is using it + clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_CLAIRVOYANCE); memset(&sd->special_state,0,sizeof(sd->special_state)); memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp))); @@ -2365,7 +2391,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) status->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK); status->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM; - if (battle_config.character_size && pc_isriding(sd)) { //[Lupus] + if (battle_config.character_size && (pc_isriding(sd) || pc_isridingdragon(sd)) ) { //[Lupus] if (sd->class_&JOBL_BABY) { if (battle_config.character_size&SZ_BIG) status->size++; @@ -2638,7 +2664,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) sd->left_weapon.atkmods[1] = atkmods[1][sd->weapontype2]; sd->left_weapon.atkmods[2] = atkmods[2][sd->weapontype2]; - if(pc_isriding(sd) && + if( (pc_isriding(sd) || pc_isridingdragon(sd)) && (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR)) { //When Riding with spear, damage modifier to mid-class becomes //same as versus large size. @@ -2704,8 +2730,10 @@ int status_calc_pc_(struct map_session_data* sd, bool first) if (sd->status.weapon < MAX_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon]) status->batk += sd->weapon_atk[sd->status.weapon]; // Absolute modifiers from passive skills - if((skill=pc->checkskill(sd,BS_HILTBINDING))>0) +#ifndef RENEWAL + if((skill=pc->checkskill(sd,BS_HILTBINDING))>0) // it doesn't work in RE. status->batk += 4; +#endif // ----- HP MAX CALCULATION ----- @@ -2964,11 +2992,11 @@ int status_calc_pc_(struct map_session_data* sd, bool first) if((skill=pc->checkskill(sd,HP_MANARECHARGE))>0 ) sd->dsprate -= 4*skill; - if(sc->data[SC_SERVICE4U]) - sd->dsprate -= sc->data[SC_SERVICE4U]->val3; + if(sc->data[SC_SERVICEFORYOU]) + sd->dsprate -= sc->data[SC_SERVICEFORYOU]->val3; - if(sc->data[SC_SPCOST_RATE]) - sd->dsprate -= sc->data[SC_SPCOST_RATE]->val1; + if(sc->data[SC_ATKER_BLOOD]) + sd->dsprate -= sc->data[SC_ATKER_BLOOD]->val1; //Underflow protections. if(sd->dsprate < 0) @@ -3002,9 +3030,9 @@ int status_calc_pc_(struct map_session_data* sd, bool first) } if(sc->count){ - if(sc->data[SC_CONCENTRATE]) { //Update the card-bonus data - sc->data[SC_CONCENTRATE]->val3 = sd->param_bonus[1]; //Agi - sc->data[SC_CONCENTRATE]->val4 = sd->param_bonus[4]; //Dex + if(sc->data[SC_CONCENTRATION]) { //Update the card-bonus data + sc->data[SC_CONCENTRATION]->val3 = sd->param_bonus[1]; //Agi + sc->data[SC_CONCENTRATION]->val4 = sd->param_bonus[4]; //Dex } if(sc->data[SC_SIEGFRIED]){ i = sc->data[SC_SIEGFRIED]->val2; @@ -3022,11 +3050,11 @@ int status_calc_pc_(struct map_session_data* sd, bool first) sd->subele[ELE_HOLY] += sc->data[SC_PROVIDENCE]->val2; sd->subrace[RC_DEMON] += sc->data[SC_PROVIDENCE]->val2; } - if(sc->data[SC_ARMOR_ELEMENT]) { //This status change should grant card-type elemental resist. - sd->subele[ELE_WATER] += sc->data[SC_ARMOR_ELEMENT]->val1; - sd->subele[ELE_EARTH] += sc->data[SC_ARMOR_ELEMENT]->val2; - sd->subele[ELE_FIRE] += sc->data[SC_ARMOR_ELEMENT]->val3; - sd->subele[ELE_WIND] += sc->data[SC_ARMOR_ELEMENT]->val4; + if(sc->data[SC_ARMORPROPERTY]) { //This status change should grant card-type elemental resist. + sd->subele[ELE_WATER] += sc->data[SC_ARMORPROPERTY]->val1; + sd->subele[ELE_EARTH] += sc->data[SC_ARMORPROPERTY]->val2; + sd->subele[ELE_FIRE] += sc->data[SC_ARMORPROPERTY]->val3; + sd->subele[ELE_WIND] += sc->data[SC_ARMORPROPERTY]->val4; } if(sc->data[SC_ARMOR_RESIST]) { // Undead Scroll sd->subele[ELE_WATER] += sc->data[SC_ARMOR_RESIST]->val1; @@ -3266,17 +3294,13 @@ static unsigned short status_calc_vit(struct block_list *,struct status_change * static unsigned short status_calc_int(struct block_list *,struct status_change *,int); static unsigned short status_calc_dex(struct block_list *,struct status_change *,int); static unsigned short status_calc_luk(struct block_list *,struct status_change *,int); -static unsigned short status_calc_batk(struct block_list *,struct status_change *,int); -static unsigned short status_calc_watk(struct block_list *,struct status_change *,int); -static unsigned short status_calc_matk(struct block_list *,struct status_change *,int); -static signed short status_calc_hit(struct block_list *,struct status_change *,int); -static signed short status_calc_critical(struct block_list *,struct status_change *,int); -static signed short status_calc_flee(struct block_list *,struct status_change *,int); -static signed short status_calc_flee2(struct block_list *,struct status_change *,int); -static defType status_calc_def(struct block_list *bl, struct status_change *sc, int); -static signed short status_calc_def2(struct block_list *,struct status_change *,int); -static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int); -static signed short status_calc_mdef2(struct block_list *,struct status_change *,int); +static unsigned short status_calc_batk(struct block_list *,struct status_change *,int,bool); +static unsigned short status_calc_watk(struct block_list *,struct status_change *,int,bool); +static unsigned short status_calc_matk(struct block_list *,struct status_change *,int,bool); +static signed short status_calc_hit(struct block_list *,struct status_change *,int,bool); +static signed short status_calc_critical(struct block_list *,struct status_change *,int,bool); +static signed short status_calc_flee(struct block_list *,struct status_change *,int,bool); +static signed short status_calc_flee2(struct block_list *,struct status_change *,int,bool); static unsigned short status_calc_speed(struct block_list *,struct status_change *,int); static short status_calc_aspd_rate(struct block_list *,struct status_change *,int); static unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion); @@ -3430,18 +3454,18 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str || (sc->data[SC_DPOISON] && !sc->data[SC_SLOWPOISON]) || sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST] || sc->data[SC_TRICKDEAD] - || sc->data[SC_BLEEDING] + || sc->data[SC_BLOODING] || sc->data[SC_MAGICMUSHROOM] || sc->data[SC_RAISINGDRAGON] - || sc->data[SC_SATURDAYNIGHTFEVER] + || sc->data[SC_SATURDAY_NIGHT_FEVER] ) //No regen regen->flag = 0; if ( - sc->data[SC_DANCING] || sc->data[SC_OBLIVIONCURSE] || sc->data[SC_MAXIMIZEPOWER] + sc->data[SC_DANCING] || sc->data[SC_OBLIVIONCURSE] || sc->data[SC_MAXIMIZEPOWER] || sc->data[SC_REBOUND] || ( (bl->type == BL_PC && ((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK && - (sc->data[SC_EXTREMITYFIST] || (sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SPIRIT] || sc->data[SC_SPIRIT]->val2 != SL_MONK))) + (sc->data[SC_EXTREMITYFIST] || (sc->data[SC_EXPLOSIONSPIRITS] && (!sc->data[SC_SOULLINK] || sc->data[SC_SOULLINK]->val2 != SL_MONK))) ) ) //No natural SP regen regen->flag &=~RGN_SP; @@ -3458,9 +3482,9 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str regen->rate.hp += 1; regen->rate.sp += 1; } - if (sc->data[SC_REGENERATION]) + if (sc->data[SC_GDSKILL_REGENERATION]) { - const struct status_change_entry *sce = sc->data[SC_REGENERATION]; + const struct status_change_entry *sce = sc->data[SC_GDSKILL_REGENERATION]; if (!sce->val4) { regen->rate.hp += sce->val2; @@ -3468,8 +3492,8 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str } else regen->flag&=~sce->val4; //Remove regen as specified by val4 } - if(sc->data[SC_GT_REVITALIZE]){ - regen->hp = cap_value(regen->hp*sc->data[SC_GT_REVITALIZE]->val3/100, 1, SHRT_MAX); + if(sc->data[SC_GENTLETOUCH_REVITALIZE]){ + regen->hp = cap_value(regen->hp*sc->data[SC_GENTLETOUCH_REVITALIZE]->val3/100, 1, SHRT_MAX); regen->state.walk= 1; } if ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) //if insignia lvl 1 @@ -3563,23 +3587,22 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) temp += status->batk; status->batk = cap_value(temp, 0, USHRT_MAX); } - status->batk = status_calc_batk(bl, sc, status->batk); + status->batk = status_calc_batk(bl, sc, status->batk, true); } - if(flag&SCB_WATK) { - - status->rhw.atk = status_calc_watk(bl, sc, b_status->rhw.atk); + if(flag&SCB_WATK) { + status->rhw.atk = status_calc_watk(bl, sc, b_status->rhw.atk, true); if (!sd) //Should not affect weapon refine bonus - status->rhw.atk2 = status_calc_watk(bl, sc, b_status->rhw.atk2); + status->rhw.atk2 = status_calc_watk(bl, sc, b_status->rhw.atk2, true); if(b_status->lhw.atk) { if (sd) { sd->state.lr_flag = 1; - status->lhw.atk = status_calc_watk(bl, sc, b_status->lhw.atk); + status->lhw.atk = status_calc_watk(bl, sc, b_status->lhw.atk, true); sd->state.lr_flag = 0; } else { - status->lhw.atk = status_calc_watk(bl, sc, b_status->lhw.atk); - status->lhw.atk2= status_calc_watk(bl, sc, b_status->lhw.atk2); + status->lhw.atk = status_calc_watk(bl, sc, b_status->lhw.atk, true); + status->lhw.atk2 = status_calc_watk(bl, sc, b_status->lhw.atk2, true); } } @@ -3598,13 +3621,13 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) && status->luk == b_status->luk #endif ) - status->hit = status_calc_hit(bl, sc, b_status->hit); + status->hit = status_calc_hit(bl, sc, b_status->hit, true); else status->hit = status_calc_hit(bl, sc, b_status->hit + (status->dex - b_status->dex) #ifdef RENEWAL + (status->luk/3 - b_status->luk/3) #endif - ); + , true); } if(flag&SCB_FLEE) { @@ -3613,18 +3636,18 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) && status->luk == b_status->luk #endif ) - status->flee = status_calc_flee(bl, sc, b_status->flee); + status->flee = status_calc_flee(bl, sc, b_status->flee, true); else status->flee = status_calc_flee(bl, sc, b_status->flee +(status->agi - b_status->agi) #ifdef RENEWAL + (status->luk/5 - b_status->luk/5) #endif - ); + , true); } if(flag&SCB_DEF) { - status->def = status_calc_def(bl, sc, b_status->def); + status->def = status_calc_def(bl, sc, b_status->def, true); if( bl->type&BL_HOM ) status->def += (status->vit/5 - b_status->vit/5); @@ -3636,7 +3659,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) && status->agi == b_status->agi #endif ) - status->def2 = status_calc_def2(bl, sc, b_status->def2); + status->def2 = status_calc_def2(bl, sc, b_status->def2, true); else status->def2 = status_calc_def2(bl, sc, b_status->def2 #ifdef RENEWAL @@ -3644,12 +3667,12 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) #else + (status->vit - b_status->vit) #endif - ); + , true); } if(flag&SCB_MDEF) { - status->mdef = status_calc_mdef(bl, sc, b_status->mdef); + status->mdef = status_calc_mdef(bl, sc, b_status->mdef, true); if( bl->type&BL_HOM ) status->mdef += (status->int_/5 - b_status->int_/5); @@ -3661,7 +3684,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) && status->dex == b_status->dex #endif ) - status->mdef2 = status_calc_mdef2(bl, sc, b_status->mdef2); + status->mdef2 = status_calc_mdef2(bl, sc, b_status->mdef2, true); else status->mdef2 = status_calc_mdef2(bl, sc, b_status->mdef2 +(status->int_ - b_status->int_) #ifdef RENEWAL @@ -3669,7 +3692,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) #else + ((status->vit - b_status->vit)>>1) #endif - ); + , true); } if(flag&SCB_SPEED) { @@ -3693,9 +3716,9 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if(flag&SCB_CRI && b_status->cri) { if (status->luk == b_status->luk) - status->cri = status_calc_critical(bl, sc, b_status->cri); + status->cri = status_calc_critical(bl, sc, b_status->cri, true); else - status->cri = status_calc_critical(bl, sc, b_status->cri + 3*(status->luk - b_status->luk)); + status->cri = status_calc_critical(bl, sc, b_status->cri + 3*(status->luk - b_status->luk), true); /** * after status_calc_critical so the bonus is applied despite if you have or not a sc bugreport:5240 **/ @@ -3706,9 +3729,9 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if(flag&SCB_FLEE2 && b_status->flee2) { if (status->luk == b_status->luk) - status->flee2 = status_calc_flee2(bl, sc, b_status->flee2); + status->flee2 = status_calc_flee2(bl, sc, b_status->flee2, true); else - status->flee2 = status_calc_flee2(bl, sc, b_status->flee2 +(status->luk - b_status->luk)); + status->flee2 = status_calc_flee2(bl, sc, b_status->flee2 +(status->luk - b_status->luk), true); } if(flag&SCB_ATK_ELE) { @@ -3784,52 +3807,8 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) } } - if(flag&SCB_MATK) { -#ifndef RENEWAL - status->matk_min = status_base_matk_min(status) + (sd?sd->bonus.ematk:0); - status->matk_max = status_base_matk_max(status) + (sd?sd->bonus.ematk:0); -#else - /** - * RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK) - * MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers - **/ - status->matk_min = status->matk_max = status_base_matk(status, status_get_lv(bl)); - if( bl->type&BL_PC ){ - // Any +MATK you get from skills and cards, including cards in weapon, is added here. - if( sd->bonus.ematk > 0 ){ - status->matk_max += sd->bonus.ematk; - status->matk_min += sd->bonus.ematk; - } - status->matk_min = status_calc_ematk(bl, sc, status->matk_min); - status->matk_max = status_calc_ematk(bl, sc, status->matk_max); - //This is the only portion in MATK that varies depending on the weapon level and refinement rate. - if( status->rhw.matk > 0 ){ - int wMatk = status->rhw.matk; - int variance = wMatk * status->rhw.wlv / 10; - status->matk_min += wMatk - variance; - status->matk_max += wMatk + variance; - } - } -#endif - if (bl->type&BL_PC && sd->matk_rate != 100) { - status->matk_max = status->matk_max * sd->matk_rate/100; - status->matk_min = status->matk_min * sd->matk_rate/100; - } - - status->matk_min = status_calc_matk(bl, sc, status->matk_min); - status->matk_max = status_calc_matk(bl, sc, status->matk_max); - - if ((bl->type&BL_HOM && battle_config.hom_setting&0x20) //Hom Min Matk is always the same as Max Matk - || sc->data[SC_RECOGNIZEDSPELL]) - status->matk_min = status->matk_max; - -#ifdef RENEWAL - if( sd && sd->right_weapon.overrefine > 0){ - status->matk_min++; - status->matk_max += sd->right_weapon.overrefine - 1; - } -#endif - + if(flag&SCB_MATK) { + status_get_matk(bl, 0); } if(flag&SCB_ASPD) { @@ -3844,11 +3823,11 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) amotion = amotion*status->aspd_rate/1000; #else // aspd = baseaspd + floor(sqrt((agi^2/2) + (dex^2/5))/4 + (potskillbonus*agi/200)) - amotion -= (int)(sqrt( (pow(status->agi, 2) / 2) + (pow(status->dex, 2) / 5) ) / 4 + (status_calc_aspd(bl, sc, 1) * status->agi / 200)) * 10; + amotion -= (int)(sqrt( (pow(status->agi, 2) / 2) + (pow(status->dex, 2) / 5) ) / 4 + ((float)status_calc_aspd(bl, sc, 1) * status->agi / 200)) * 10; if( (status_calc_aspd(bl, sc, 2) + status->aspd_rate2) != 0 ) // RE ASPD percertage modifier - amotion -= ( amotion - ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd) ) - * (status_calc_aspd(bl, sc, 2) + status->aspd_rate2) / 100; + amotion -= (( amotion - ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd) ) + * (status_calc_aspd(bl, sc, 2) + status->aspd_rate2) / 10 + 5) / 10; if(status->aspd_rate != 1000) // absolute percentage modifier amotion = ( 200 - (200-amotion/10) * status->aspd_rate / 1000 ) * 10; @@ -4102,38 +4081,38 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang str -= sc->data[SC_HARMONIZE]->val2; return (unsigned short)cap_value(str,0,USHRT_MAX); } - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && str < 50) + if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && str < 50) return 50; if(sc->data[SC_INCALLSTATUS]) str += sc->data[SC_INCALLSTATUS]->val1; - if(sc->data[SC_INCSTR]) - str += sc->data[SC_INCSTR]->val1; - if(sc->data[SC_STRFOOD]) - str += sc->data[SC_STRFOOD]->val1; + if(sc->data[SC_CHASEWALK2]) + str += sc->data[SC_CHASEWALK2]->val1; + if(sc->data[SC_FOOD_STR]) + str += sc->data[SC_FOOD_STR]->val1; if(sc->data[SC_FOOD_STR_CASH]) str += sc->data[SC_FOOD_STR_CASH]->val1; - if(sc->data[SC_BATTLEORDERS]) + if(sc->data[SC_GDSKILL_BATTLEORDER]) str += 5; if(sc->data[SC_LEADERSHIP]) str += sc->data[SC_LEADERSHIP]->val1; - if(sc->data[SC_LOUD]) + if(sc->data[SC_SHOUT]) str += 4; if(sc->data[SC_TRUESIGHT]) str += 5; - if(sc->data[SC_SPURT]) + if(sc->data[SC_STRUP]) str += 10; - if(sc->data[SC_NEN]) - str += sc->data[SC_NEN]->val1; + if(sc->data[SC_NJ_NEN]) + str += sc->data[SC_NJ_NEN]->val1; if(sc->data[SC_BLESSING]){ if(sc->data[SC_BLESSING]->val2) str += sc->data[SC_BLESSING]->val2; else str >>= 1; } + if(sc->data[SC_MARIONETTE_MASTER]) + str -= ((sc->data[SC_MARIONETTE_MASTER]->val3)>>16)&0xFF; if(sc->data[SC_MARIONETTE]) - str -= ((sc->data[SC_MARIONETTE]->val3)>>16)&0xFF; - if(sc->data[SC_MARIONETTE2]) - str += ((sc->data[SC_MARIONETTE2]->val3)>>16)&0xFF; + str += ((sc->data[SC_MARIONETTE]->val3)>>16)&0xFF; if(sc->data[SC_GIANTGROWTH]) str += 30; if(sc->data[SC_SAVAGE_STEAK]) @@ -4144,6 +4123,8 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang str -= sc->data[SC_STOMACHACHE]->val1; if(sc->data[SC_KYOUGAKU]) str -= sc->data[SC_KYOUGAKU]->val2; + if(sc->data[SC_FULL_THROTTLE]) + str += str * 20 / 100; return (unsigned short)cap_value(str,0,USHRT_MAX); } @@ -4157,36 +4138,36 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang agi -= sc->data[SC_HARMONIZE]->val2; return (unsigned short)cap_value(agi,0,USHRT_MAX); } - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && agi < 50) + if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && agi < 50) return 50; - if(sc->data[SC_CONCENTRATE] && !sc->data[SC_QUAGMIRE]) - agi += (agi-sc->data[SC_CONCENTRATE]->val3)*sc->data[SC_CONCENTRATE]->val2/100; + if(sc->data[SC_CONCENTRATION] && !sc->data[SC_QUAGMIRE]) + agi += (agi-sc->data[SC_CONCENTRATION]->val3)*sc->data[SC_CONCENTRATION]->val2/100; if(sc->data[SC_INCALLSTATUS]) agi += sc->data[SC_INCALLSTATUS]->val1; if(sc->data[SC_INCAGI]) agi += sc->data[SC_INCAGI]->val1; - if(sc->data[SC_AGIFOOD]) - agi += sc->data[SC_AGIFOOD]->val1; + if(sc->data[SC_FOOD_AGI]) + agi += sc->data[SC_FOOD_AGI]->val1; if(sc->data[SC_FOOD_AGI_CASH]) agi += sc->data[SC_FOOD_AGI_CASH]->val1; if(sc->data[SC_SOULCOLD]) agi += sc->data[SC_SOULCOLD]->val1; if(sc->data[SC_TRUESIGHT]) agi += 5; - if(sc->data[SC_INCREASEAGI]) - agi += sc->data[SC_INCREASEAGI]->val2; - if(sc->data[SC_INCREASING]) + if(sc->data[SC_INC_AGI]) + agi += sc->data[SC_INC_AGI]->val2; + if(sc->data[SC_GS_ACCURACY]) agi += 4; // added based on skill updates [Reddozen] - if(sc->data[SC_DECREASEAGI]) - agi -= sc->data[SC_DECREASEAGI]->val2; + if(sc->data[SC_DEC_AGI]) + agi -= sc->data[SC_DEC_AGI]->val2; if(sc->data[SC_QUAGMIRE]) agi -= sc->data[SC_QUAGMIRE]->val2; - if(sc->data[SC_SUITON] && sc->data[SC_SUITON]->val3) - agi -= sc->data[SC_SUITON]->val2; + if(sc->data[SC_NJ_SUITON] && sc->data[SC_NJ_SUITON]->val3) + agi -= sc->data[SC_NJ_SUITON]->val2; + if(sc->data[SC_MARIONETTE_MASTER]) + agi -= ((sc->data[SC_MARIONETTE_MASTER]->val3)>>8)&0xFF; if(sc->data[SC_MARIONETTE]) - agi -= ((sc->data[SC_MARIONETTE]->val3)>>8)&0xFF; - if(sc->data[SC_MARIONETTE2]) - agi += ((sc->data[SC_MARIONETTE2]->val3)>>8)&0xFF; + agi += ((sc->data[SC_MARIONETTE]->val3)>>8)&0xFF; if(sc->data[SC_ADORAMUS]) agi -= sc->data[SC_ADORAMUS]->val2; if(sc->data[SC_DROCERA_HERB_STEAMED]) @@ -4198,6 +4179,11 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang if(sc->data[SC_KYOUGAKU]) agi -= sc->data[SC_KYOUGAKU]->val2; + if(sc->data[SC_MARSHOFABYSS]) + agi -= agi * sc->data[SC_MARSHOFABYSS]->val2 / 100; + if(sc->data[SC_FULL_THROTTLE]) + agi += agi * 20 / 100; + return (unsigned short)cap_value(agi,0,USHRT_MAX); } @@ -4210,26 +4196,26 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang vit -= sc->data[SC_HARMONIZE]->val2; return (unsigned short)cap_value(vit,0,USHRT_MAX); } - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && vit < 50) + if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && vit < 50) return 50; if(sc->data[SC_INCALLSTATUS]) vit += sc->data[SC_INCALLSTATUS]->val1; if(sc->data[SC_INCVIT]) vit += sc->data[SC_INCVIT]->val1; - if(sc->data[SC_VITFOOD]) - vit += sc->data[SC_VITFOOD]->val1; + if(sc->data[SC_FOOD_VIT]) + vit += sc->data[SC_FOOD_VIT]->val1; if(sc->data[SC_FOOD_VIT_CASH]) vit += sc->data[SC_FOOD_VIT_CASH]->val1; - if(sc->data[SC_CHANGE]) - vit += sc->data[SC_CHANGE]->val2; + if(sc->data[SC_HLIF_CHANGE]) + vit += sc->data[SC_HLIF_CHANGE]->val2; if(sc->data[SC_GLORYWOUNDS]) vit += sc->data[SC_GLORYWOUNDS]->val1; if(sc->data[SC_TRUESIGHT]) vit += 5; + if(sc->data[SC_MARIONETTE_MASTER]) + vit -= sc->data[SC_MARIONETTE_MASTER]->val3&0xFF; if(sc->data[SC_MARIONETTE]) - vit -= sc->data[SC_MARIONETTE]->val3&0xFF; - if(sc->data[SC_MARIONETTE2]) - vit += sc->data[SC_MARIONETTE2]->val3&0xFF; + vit += sc->data[SC_MARIONETTE]->val3&0xFF; if(sc->data[SC_LAUDAAGNUS]) vit += 4 + sc->data[SC_LAUDAAGNUS]->val1; if(sc->data[SC_MINOR_BBQ]) @@ -4241,8 +4227,10 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang if(sc->data[SC_KYOUGAKU]) vit -= sc->data[SC_KYOUGAKU]->val2; - if(sc->data[SC_STRIPARMOR]) - vit -= vit * sc->data[SC_STRIPARMOR]->val2/100; + if(sc->data[SC_NOEQUIPARMOR]) + vit -= vit * sc->data[SC_NOEQUIPARMOR]->val2/100; + if(sc->data[SC_FULL_THROTTLE]) + vit += vit * 20 / 100; return (unsigned short)cap_value(vit,0,USHRT_MAX); } @@ -4256,19 +4244,19 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang int_ -= sc->data[SC_HARMONIZE]->val2; return (unsigned short)cap_value(int_,0,USHRT_MAX); } - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && int_ < 50) + if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && int_ < 50) return 50; if(sc->data[SC_INCALLSTATUS]) int_ += sc->data[SC_INCALLSTATUS]->val1; if(sc->data[SC_INCINT]) int_ += sc->data[SC_INCINT]->val1; - if(sc->data[SC_INTFOOD]) - int_ += sc->data[SC_INTFOOD]->val1; + if(sc->data[SC_FOOD_INT]) + int_ += sc->data[SC_FOOD_INT]->val1; if(sc->data[SC_FOOD_INT_CASH]) int_ += sc->data[SC_FOOD_INT_CASH]->val1; - if(sc->data[SC_CHANGE]) - int_ += sc->data[SC_CHANGE]->val3; - if(sc->data[SC_BATTLEORDERS]) + if(sc->data[SC_HLIF_CHANGE]) + int_ += sc->data[SC_HLIF_CHANGE]->val3; + if(sc->data[SC_GDSKILL_BATTLEORDER]) int_ += 5; if(sc->data[SC_TRUESIGHT]) int_ += 5; @@ -4278,12 +4266,12 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang else int_ >>= 1; } - if(sc->data[SC_NEN]) - int_ += sc->data[SC_NEN]->val1; + if(sc->data[SC_NJ_NEN]) + int_ += sc->data[SC_NJ_NEN]->val1; + if(sc->data[SC_MARIONETTE_MASTER]) + int_ -= ((sc->data[SC_MARIONETTE_MASTER]->val4)>>16)&0xFF; if(sc->data[SC_MARIONETTE]) - int_ -= ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF; - if(sc->data[SC_MARIONETTE2]) - int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF; + int_ += ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF; if(sc->data[SC_MANDRAGORA]) int_ -= 5 + 5 * sc->data[SC_MANDRAGORA]->val1; if(sc->data[SC_COCKTAIL_WARG_BLOOD]) @@ -4295,10 +4283,12 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang if(sc->data[SC_KYOUGAKU]) int_ -= sc->data[SC_KYOUGAKU]->val2; - if(sc->data[SC_STRIPHELM]) - int_ -= int_ * sc->data[SC_STRIPHELM]->val2/100; - if(sc->data[SC__STRIPACCESSORY]) - int_ -= int_ * sc->data[SC__STRIPACCESSORY]->val2 / 100; + if(sc->data[SC_NOEQUIPHELM]) + int_ -= int_ * sc->data[SC_NOEQUIPHELM]->val2/100; + if(sc->data[SC__STRIPACCESSARY]) + int_ -= int_ * sc->data[SC__STRIPACCESSARY]->val2 / 100; + if(sc->data[SC_FULL_THROTTLE]) + int_ += int_ * 20 / 100; return (unsigned short)cap_value(int_,0,USHRT_MAX); } @@ -4312,19 +4302,19 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang dex -= sc->data[SC_HARMONIZE]->val2; return (unsigned short)cap_value(dex,0,USHRT_MAX); } - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && dex < 50) + if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && dex < 50) return 50; - if(sc->data[SC_CONCENTRATE] && !sc->data[SC_QUAGMIRE]) - dex += (dex-sc->data[SC_CONCENTRATE]->val4)*sc->data[SC_CONCENTRATE]->val2/100; + if(sc->data[SC_CONCENTRATION] && !sc->data[SC_QUAGMIRE]) + dex += (dex-sc->data[SC_CONCENTRATION]->val4)*sc->data[SC_CONCENTRATION]->val2/100; if(sc->data[SC_INCALLSTATUS]) dex += sc->data[SC_INCALLSTATUS]->val1; if(sc->data[SC_INCDEX]) dex += sc->data[SC_INCDEX]->val1; - if(sc->data[SC_DEXFOOD]) - dex += sc->data[SC_DEXFOOD]->val1; + if(sc->data[SC_FOOD_DEX]) + dex += sc->data[SC_FOOD_DEX]->val1; if(sc->data[SC_FOOD_DEX_CASH]) dex += sc->data[SC_FOOD_DEX_CASH]->val1; - if(sc->data[SC_BATTLEORDERS]) + if(sc->data[SC_GDSKILL_BATTLEORDER]) dex += 5; if(sc->data[SC_HAWKEYES]) dex += sc->data[SC_HAWKEYES]->val1; @@ -4338,12 +4328,12 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang else dex >>= 1; } - if(sc->data[SC_INCREASING]) + if(sc->data[SC_GS_ACCURACY]) dex += 4; // added based on skill updates [Reddozen] + if(sc->data[SC_MARIONETTE_MASTER]) + dex -= ((sc->data[SC_MARIONETTE_MASTER]->val4)>>8)&0xFF; if(sc->data[SC_MARIONETTE]) - dex -= ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF; - if(sc->data[SC_MARIONETTE2]) - dex += ((sc->data[SC_MARIONETTE2]->val4)>>8)&0xFF; + dex += ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF; if(sc->data[SC_SIROMA_ICE_TEA]) dex += sc->data[SC_SIROMA_ICE_TEA]->val1; if(sc->data[SC_INSPIRATION]) @@ -4353,8 +4343,12 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang if(sc->data[SC_KYOUGAKU]) dex -= sc->data[SC_KYOUGAKU]->val2; - if(sc->data[SC__STRIPACCESSORY]) - dex -= dex * sc->data[SC__STRIPACCESSORY]->val2 / 100; + if(sc->data[SC_MARSHOFABYSS]) + dex -= dex * sc->data[SC_MARSHOFABYSS]->val2 / 100; + if(sc->data[SC__STRIPACCESSARY]) + dex -= dex * sc->data[SC__STRIPACCESSARY]->val2 / 100; + if(sc->data[SC_FULL_THROTTLE]) + dex += dex * 20 / 100; return (unsigned short)cap_value(dex,0,USHRT_MAX); } @@ -4370,24 +4364,24 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang } if(sc->data[SC_CURSE]) return 0; - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && luk < 50) + if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && luk < 50) return 50; if(sc->data[SC_INCALLSTATUS]) luk += sc->data[SC_INCALLSTATUS]->val1; if(sc->data[SC_INCLUK]) luk += sc->data[SC_INCLUK]->val1; - if(sc->data[SC_LUKFOOD]) - luk += sc->data[SC_LUKFOOD]->val1; + if(sc->data[SC_FOOD_LUK]) + luk += sc->data[SC_FOOD_LUK]->val1; if(sc->data[SC_FOOD_LUK_CASH]) luk += sc->data[SC_FOOD_LUK_CASH]->val1; if(sc->data[SC_TRUESIGHT]) luk += 5; if(sc->data[SC_GLORIA]) luk += 30; + if(sc->data[SC_MARIONETTE_MASTER]) + luk -= sc->data[SC_MARIONETTE_MASTER]->val4&0xFF; if(sc->data[SC_MARIONETTE]) - luk -= sc->data[SC_MARIONETTE]->val4&0xFF; - if(sc->data[SC_MARIONETTE2]) - luk += sc->data[SC_MARIONETTE2]->val4&0xFF; + luk += sc->data[SC_MARIONETTE]->val4&0xFF; if(sc->data[SC_PUTTI_TAILS_NOODLES]) luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1; if(sc->data[SC_INSPIRATION]) @@ -4399,26 +4393,33 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang if(sc->data[SC_LAUDARAMUS]) luk += 4 + sc->data[SC_LAUDARAMUS]->val1; - if(sc->data[SC__STRIPACCESSORY]) - luk -= luk * sc->data[SC__STRIPACCESSORY]->val2 / 100; + if(sc->data[SC__STRIPACCESSARY]) + luk -= luk * sc->data[SC__STRIPACCESSARY]->val2 / 100; if(sc->data[SC_BANANA_BOMB]) luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100; + if(sc->data[SC_FULL_THROTTLE]) + luk += luk * 20 / 100; return (unsigned short)cap_value(luk,0,USHRT_MAX); } -static unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, int batk) +static unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, int batk, bool viewable) { if(!sc || !sc->count) return cap_value(batk,0,USHRT_MAX); + + if( !viewable ){ + /* some statuses that are hidden in the status window */ + return (unsigned short)cap_value(batk,0,USHRT_MAX); + } - if(sc->data[SC_ATKPOTION]) - batk += sc->data[SC_ATKPOTION]->val1; + if(sc->data[SC_PLUSATTACKPOWER]) + batk += sc->data[SC_PLUSATTACKPOWER]->val1; if(sc->data[SC_BATKFOOD]) batk += sc->data[SC_BATKFOOD]->val1; - if(sc->data[SC_GATLINGFEVER]) - batk += sc->data[SC_GATLINGFEVER]->val3; - if(sc->data[SC_MADNESSCANCEL]) + if(sc->data[SC_GS_GATLINGFEVER]) + batk += sc->data[SC_GS_GATLINGFEVER]->val3; + if(sc->data[SC_GS_MADNESSCANCEL]) batk += 100; if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) batk += 50; @@ -4433,7 +4434,7 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan batk += sc->data[SC_FULL_SWING_K]->val1; if(sc->data[SC_ODINS_POWER]) batk += 70; - if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ + if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){ if(status_get_element(bl) == ELE_WATER) //water type batk /= 2; } @@ -4446,42 +4447,53 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan batk += batk * sc->data[SC_INCATKRATE]->val1/100; if(sc->data[SC_PROVOKE]) batk += batk * sc->data[SC_PROVOKE]->val3/100; - if(sc->data[SC_CONCENTRATION]) - batk += batk * sc->data[SC_CONCENTRATION]->val2/100; +#ifndef RENEWAL + if(sc->data[SC_LKCONCENTRATION]) + batk += batk * sc->data[SC_LKCONCENTRATION]->val2/100; +#endif if(sc->data[SC_SKE]) batk += batk * 3; - if(sc->data[SC_BLOODLUST]) - batk += batk * sc->data[SC_BLOODLUST]->val2/100; + if(sc->data[SC_HAMI_BLOODLUST]) + batk += batk * sc->data[SC_HAMI_BLOODLUST]->val2/100; if(sc->data[SC_JOINTBEAT] && sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST) batk -= batk * 25/100; if(sc->data[SC_CURSE]) batk -= batk * 25/100; + if( sc->data[SC_ZANGETSU] ) + batk += sc->data[SC_ZANGETSU]->val2; //Curse shouldn't effect on this? <- Curse OR Bleeding?? -// if(sc->data[SC_BLEEDING]) +// if(sc->data[SC_BLOODING]) // batk -= batk * 25/100; - if(sc->data[SC_FLEET]) - batk += batk * sc->data[SC_FLEET]->val3/100; + if(sc->data[SC_HLIF_FLEET]) + batk += batk * sc->data[SC_HLIF_FLEET]->val3/100; if(sc->data[SC__ENERVATION]) batk -= batk * sc->data[SC__ENERVATION]->val2 / 100; - if(sc->data[SC_RUSHWINDMILL]) - batk += batk * sc->data[SC_RUSHWINDMILL]->val2/100; - if(sc->data[SC_SATURDAYNIGHTFEVER]) - batk += 100 * sc->data[SC_SATURDAYNIGHTFEVER]->val1; + if(sc->data[SC_RUSH_WINDMILL]) + batk += batk * sc->data[SC_RUSH_WINDMILL]->val2/100; + if(sc->data[SC_SATURDAY_NIGHT_FEVER]) + batk += 100 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1; if(sc->data[SC_MELODYOFSINK]) batk -= batk * sc->data[SC_MELODYOFSINK]->val3/100; - if(sc->data[SC_BEYONDOFWARCRY]) - batk += batk * sc->data[SC_BEYONDOFWARCRY]->val3/100; - if( sc->data[SC_ZANGETSU] ) - batk += batk * sc->data[SC_ZANGETSU]->val2 / 100; + if(sc->data[SC_BEYOND_OF_WARCRY]) + batk += batk * sc->data[SC_BEYOND_OF_WARCRY]->val3/100; return (unsigned short)cap_value(batk,0,USHRT_MAX); } -static unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, int watk) +static unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, int watk, bool viewable) { if(!sc || !sc->count) return cap_value(watk,0,USHRT_MAX); + if( !viewable ){ + /* some statuses that are hidden in the status window */ + if(sc->data[SC_STRIKING]) + watk += sc->data[SC_STRIKING]->val2; + if(sc->data[SC_GENTLETOUCH_CHANGE] && sc->data[SC_GENTLETOUCH_CHANGE]->val2) + watk += sc->data[SC_GENTLETOUCH_CHANGE]->val2; + return (unsigned short)cap_value(watk,0,USHRT_MAX); + } + if(sc->data[SC_IMPOSITIO]) watk += sc->data[SC_IMPOSITIO]->val2; if(sc->data[SC_WATKFOOD]) @@ -4490,12 +4502,10 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan watk += sc->data[SC_DRUMBATTLE]->val2; if(sc->data[SC_VOLCANO]) watk += sc->data[SC_VOLCANO]->val2; - if(sc->data[SC_MERC_ATKUP]) - watk += sc->data[SC_MERC_ATKUP]->val2; + if(sc->data[SC_MER_ATK]) + watk += sc->data[SC_MER_ATK]->val2; if(sc->data[SC_FIGHTINGSPIRIT]) watk += sc->data[SC_FIGHTINGSPIRIT]->val1; - if(sc->data[SC_STRIKING]) - watk += sc->data[SC_STRIKING]->val2; if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3) watk += sc->data[SC_SHIELDSPELL_DEF]->val2; if(sc->data[SC_INSPIRATION]) @@ -4522,23 +4532,28 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan watk += sc->data[SC_NIBELUNGEN]->val2; } } - +#ifndef RENEWAL + if(sc->data[SC_STRIKING]) + watk += sc->data[SC_STRIKING]->val2; + if(sc->data[SC_GENTLETOUCH_CHANGE] && sc->data[SC_GENTLETOUCH_CHANGE]->val2) + watk += sc->data[SC_GENTLETOUCH_CHANGE]->val2; + if(sc->data[SC_LKCONCENTRATION]) + watk += watk * sc->data[SC_LKCONCENTRATION]->val2/100; +#endif if(sc->data[SC_INCATKRATE]) watk += watk * sc->data[SC_INCATKRATE]->val1/100; if(sc->data[SC_PROVOKE]) watk += watk * sc->data[SC_PROVOKE]->val3/100; - if(sc->data[SC_CONCENTRATION]) - watk += watk * sc->data[SC_CONCENTRATION]->val2/100; if(sc->data[SC_SKE]) watk += watk * 3; if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; - if(sc->data[SC_FLEET]) - watk += watk * sc->data[SC_FLEET]->val3/100; + if(sc->data[SC_HLIF_FLEET]) + watk += watk * sc->data[SC_HLIF_FLEET]->val3/100; if(sc->data[SC_CURSE]) watk -= watk * 25/100; - if(sc->data[SC_STRIPWEAPON]) - watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100; + if(sc->data[SC_NOEQUIPWEAPON]) + watk -= watk * sc->data[SC_NOEQUIPWEAPON]->val2/100; if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; if((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) @@ -4551,10 +4566,6 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan watk += watk * sc->data[SC_TIDAL_WEAPON]->val2 / 100; if(sc->data[SC_ANGRIFFS_MODUS]) watk += watk * sc->data[SC_ANGRIFFS_MODUS]->val2/100; -#ifdef RENEWAL_EDP - if( sc->data[SC_EDP] ) - watk = watk * (100 + sc->data[SC_EDP]->val1 * 80) / 100; -#endif return (unsigned short)cap_value(watk,0,USHRT_MAX); } @@ -4564,8 +4575,8 @@ static unsigned short status_calc_ematk(struct block_list *bl, struct status_cha if (!sc || !sc->count) return cap_value(matk,0,USHRT_MAX); - if (sc->data[SC_MATKPOTION]) - matk += sc->data[SC_MATKPOTION]->val1; + if (sc->data[SC_PLUSMAGICPOWER]) + matk += sc->data[SC_PLUSMAGICPOWER]->val1; if (sc->data[SC_MATKFOOD]) matk += sc->data[SC_MATKFOOD]->val1; if(sc->data[SC_MANA_PLUS]) @@ -4581,18 +4592,24 @@ static unsigned short status_calc_ematk(struct block_list *bl, struct status_cha if(sc->data[SC_ODINS_POWER]) matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2 if(sc->data[SC_IZAYOI]) - matk += 50 * sc->data[SC_IZAYOI]->val1; + matk += 25 * sc->data[SC_IZAYOI]->val1; return (unsigned short)cap_value(matk,0,USHRT_MAX); } #endif -static unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk) +static unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk, bool viewable) { if(!sc || !sc->count) return cap_value(matk,0,USHRT_MAX); + + if( !viewable ){ + /* some statuses that are hidden in the status window */ + return (unsigned short)cap_value(matk,0,USHRT_MAX); + } + #ifndef RENEWAL // take note fixed value first before % modifiers - if (sc->data[SC_MATKPOTION]) - matk += sc->data[SC_MATKPOTION]->val1; + if (sc->data[SC_PLUSMAGICPOWER]) + matk += sc->data[SC_PLUSMAGICPOWER]->val1; if (sc->data[SC_MATKFOOD]) matk += sc->data[SC_MATKFOOD]->val1; if (sc->data[SC_MANA_PLUS]) @@ -4608,33 +4625,38 @@ static unsigned short status_calc_matk(struct block_list *bl, struct status_chan if (sc->data[SC_ODINS_POWER]) matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2 if (sc->data[SC_IZAYOI]) - matk += 50 * sc->data[SC_IZAYOI]->val1; + matk += 25 * sc->data[SC_IZAYOI]->val1; #endif + if( sc->data[SC_ZANGETSU] ) + matk += sc->data[SC_ZANGETSU]->val3; if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4) matk += matk * sc->data[SC_MAGICPOWER]->val3/100; if (sc->data[SC_MINDBREAKER]) matk += matk * sc->data[SC_MINDBREAKER]->val2/100; if (sc->data[SC_INCMATKRATE]) matk += matk * sc->data[SC_INCMATKRATE]->val1/100; - if (sc->data[SC_MOONLITSERENADE]) - matk += matk * sc->data[SC_MOONLITSERENADE]->val2/100; + if (sc->data[SC_MOONLIT_SERENADE]) + matk += matk * sc->data[SC_MOONLIT_SERENADE]->val2/100; if (sc->data[SC_MELODYOFSINK]) matk += matk * sc->data[SC_MELODYOFSINK]->val3/100; - if (sc->data[SC_BEYONDOFWARCRY]) - matk -= matk * sc->data[SC_BEYONDOFWARCRY]->val3/100; - if( sc->data[SC_ZANGETSU] ) - matk += matk * sc->data[SC_ZANGETSU]->val2 / 100; + if (sc->data[SC_BEYOND_OF_WARCRY]) + matk -= matk * sc->data[SC_BEYOND_OF_WARCRY]->val3/100; return (unsigned short)cap_value(matk,0,USHRT_MAX); } -static signed short status_calc_critical(struct block_list *bl, struct status_change *sc, int critical) { +static signed short status_calc_critical(struct block_list *bl, struct status_change *sc, int critical, bool viewable) { if(!sc || !sc->count) return cap_value(critical,10,SHRT_MAX); - if (sc->data[SC_INCCRI]) - critical += sc->data[SC_INCCRI]->val2; + if( !viewable ){ + /* some statuses that are hidden in the status window */ + return (short)cap_value(critical,10,SHRT_MAX); + } + + if (sc->data[SC_CRITICALPERCENT]) + critical += sc->data[SC_CRITICALPERCENT]->val2; if (sc->data[SC_EXPLOSIONSPIRITS]) critical += sc->data[SC_EXPLOSIONSPIRITS]->val2; if (sc->data[SC_FORTUNE]) @@ -4658,30 +4680,35 @@ static signed short status_calc_critical(struct block_list *bl, struct status_ch return (short)cap_value(critical,10,SHRT_MAX); } -static signed short status_calc_hit(struct block_list *bl, struct status_change *sc, int hit) +static signed short status_calc_hit(struct block_list *bl, struct status_change *sc, int hit, bool viewable) { if(!sc || !sc->count) return cap_value(hit,1,SHRT_MAX); + if( !viewable ){ + /* some statuses that are hidden in the status window */ + return (short)cap_value(hit,1,SHRT_MAX); + } + if(sc->data[SC_INCHIT]) hit += sc->data[SC_INCHIT]->val1; - if(sc->data[SC_HITFOOD]) - hit += sc->data[SC_HITFOOD]->val1; + if(sc->data[SC_FOOD_BASICHIT]) + hit += sc->data[SC_FOOD_BASICHIT]->val1; if(sc->data[SC_TRUESIGHT]) hit += sc->data[SC_TRUESIGHT]->val3; if(sc->data[SC_HUMMING]) hit += sc->data[SC_HUMMING]->val2; - if(sc->data[SC_CONCENTRATION]) - hit += sc->data[SC_CONCENTRATION]->val3; + if(sc->data[SC_LKCONCENTRATION]) + hit += sc->data[SC_LKCONCENTRATION]->val3; if(sc->data[SC_INSPIRATION]) hit += 5 * sc->data[SC_INSPIRATION]->val1; - if(sc->data[SC_ADJUSTMENT]) + if(sc->data[SC_GS_ADJUSTMENT]) hit -= 30; - if(sc->data[SC_INCREASING]) + if(sc->data[SC_GS_ACCURACY]) hit += 20; // RockmanEXE; changed based on updated [Reddozen] - if(sc->data[SC_MERC_HITUP]) - hit += sc->data[SC_MERC_HITUP]->val2; + if(sc->data[SC_MER_HIT]) + hit += sc->data[SC_MER_HIT]->val2; if(sc->data[SC_INCHITRATE]) hit += hit * sc->data[SC_INCHITRATE]->val1/100; @@ -4691,13 +4718,13 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change hit -= hit * sc->data[SC__GROOMY]->val3 / 100; if(sc->data[SC_FEAR]) hit -= hit * 20 / 100; - if (sc->data[SC_ASH]) + if (sc->data[SC_VOLCANIC_ASH]) hit /= 2; return (short)cap_value(hit,1,SHRT_MAX); } -static signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee) +static signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee, bool viewable) { if( bl->type == BL_PC ) { @@ -4710,10 +4737,15 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change if(!sc || !sc->count) return cap_value(flee,1,SHRT_MAX); + if( !viewable ){ + /* some statuses that are hidden in the status window */ + return (short)cap_value(flee,1,SHRT_MAX); + } + if(sc->data[SC_INCFLEE]) flee += sc->data[SC_INCFLEE]->val1; - if(sc->data[SC_FLEEFOOD]) - flee += sc->data[SC_FLEEFOOD]->val1; + if(sc->data[SC_FOOD_BASICAVOIDANCE]) + flee += sc->data[SC_FOOD_BASICAVOIDANCE]->val1; if(sc->data[SC_WHISTLE]) flee += sc->data[SC_WHISTLE]->val2; if(sc->data[SC_WINDWALK]) @@ -4722,28 +4754,26 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change flee += sc->data[SC_VIOLENTGALE]->val2; if(sc->data[SC_MOON_COMFORT]) //SG skill [Komurka] flee += sc->data[SC_MOON_COMFORT]->val2; - if(sc->data[SC_CLOSECONFINE]) + if(sc->data[SC_RG_CCONFINE_M]) flee += 10; if (sc->data[SC_ANGRIFFS_MODUS]) flee -= sc->data[SC_ANGRIFFS_MODUS]->val3; if (sc->data[SC_OVERED_BOOST]) flee = max(flee,sc->data[SC_OVERED_BOOST]->val2); - if(sc->data[SC_ADJUSTMENT]) + if(sc->data[SC_GS_ADJUSTMENT]) flee += 30; - if(sc->data[SC_SPEED]) - flee += 10 + sc->data[SC_SPEED]->val1 * 10; - if(sc->data[SC_GATLINGFEVER]) - flee -= sc->data[SC_GATLINGFEVER]->val4; + if(sc->data[SC_HLIF_SPEED]) + flee += 10 + sc->data[SC_HLIF_SPEED]->val1 * 10; + if(sc->data[SC_GS_GATLINGFEVER]) + flee -= sc->data[SC_GS_GATLINGFEVER]->val4; if(sc->data[SC_PARTYFLEE]) flee += sc->data[SC_PARTYFLEE]->val1 * 10; - if(sc->data[SC_MERC_FLEEUP]) - flee += sc->data[SC_MERC_FLEEUP]->val2; + if(sc->data[SC_MER_FLEE]) + flee += sc->data[SC_MER_FLEE]->val2; if( sc->data[SC_HALLUCINATIONWALK] ) flee += sc->data[SC_HALLUCINATIONWALK]->val2; if( sc->data[SC_WATER_BARRIER] ) flee -= sc->data[SC_WATER_BARRIER]->val3; - if( sc->data[SC_MARSHOFABYSS] ) - flee -= (9 * sc->data[SC_MARSHOFABYSS]->val3 / 10 + sc->data[SC_MARSHOFABYSS]->val2 / 10) * (bl->type == BL_MOB ? 2 : 1); #ifdef RENEWAL if( sc->data[SC_SPEARQUICKEN] ) flee += 2 * sc->data[SC_SPEARQUICKEN]->val1; @@ -4767,13 +4797,13 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change flee -= flee * sc->data[SC__LAZINESS]->val3 / 100; if( sc->data[SC_GLOOMYDAY] ) flee -= flee * sc->data[SC_GLOOMYDAY]->val2 / 100; - if( sc->data[SC_SATURDAYNIGHTFEVER] ) - flee -= flee * (40 + 10 * sc->data[SC_SATURDAYNIGHTFEVER]->val1) / 100; + if( sc->data[SC_SATURDAY_NIGHT_FEVER] ) + flee -= flee * (40 + 10 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1) / 100; if( sc->data[SC_WIND_STEP_OPTION] ) flee += flee * sc->data[SC_WIND_STEP_OPTION]->val2 / 100; if( sc->data[SC_ZEPHYR] ) flee += flee * sc->data[SC_ZEPHYR]->val2 / 100; - if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ //mob + if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){ //mob if(status_get_element(bl) == ELE_WATER) //water type flee /= 2; } @@ -4781,13 +4811,18 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change return (short)cap_value(flee,1,SHRT_MAX); } -static signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2) +static signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2, bool viewable) { if(!sc || !sc->count) return cap_value(flee2,10,SHRT_MAX); - if(sc->data[SC_INCFLEE2]) - flee2 += sc->data[SC_INCFLEE2]->val2; + if( !viewable ){ + /* some statuses that are hidden in the status window */ + return (short)cap_value(flee2,10,SHRT_MAX); + } + + if(sc->data[SC_PLUSAVOIDVALUE]) + flee2 += sc->data[SC_PLUSAVOIDVALUE]->val2; if(sc->data[SC_WHISTLE]) flee2 += sc->data[SC_WHISTLE]->val3*10; if(sc->data[SC__UNLUCKY]) @@ -4795,11 +4830,20 @@ static signed short status_calc_flee2(struct block_list *bl, struct status_chang return (short)cap_value(flee2,10,SHRT_MAX); } -static defType status_calc_def(struct block_list *bl, struct status_change *sc, int def) { +defType status_calc_def(struct block_list *bl, struct status_change *sc, int def, bool viewable) { if(!sc || !sc->count) return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); + if( !viewable ){ + /* some statuses that are hidden in the status window */ + if( sc && sc->data[SC_CAMOUFLAGE] ) + def -= def * 5 * (10-sc->data[SC_CAMOUFLAGE]->val4) / 100; + if( sc && sc->data[SC_GENTLETOUCH_REVITALIZE] && sc->data[SC_GENTLETOUCH_REVITALIZE]->val4 ) + def += 2 * sc->data[SC_GENTLETOUCH_REVITALIZE]->val4; + return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); + } + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) return 0; if(sc->data[SC_SKA]) @@ -4813,12 +4857,12 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc, return 90; #endif - if(sc->data[SC_ARMORCHANGE]) - def += sc->data[SC_ARMORCHANGE]->val2; + if(sc->data[SC_STONESKIN]) + def += sc->data[SC_STONESKIN]->val2; if(sc->data[SC_DRUMBATTLE]) def += sc->data[SC_DRUMBATTLE]->val3; - if(sc->data[SC_DEFENCE]) //[orn] - def += sc->data[SC_DEFENCE]->val2 ; + if(sc->data[SC_HAMI_DEFENCE]) //[orn] + def += sc->data[SC_HAMI_DEFENCE]->val2 ; if(sc->data[SC_INCDEFRATE]) def += def * sc->data[SC_INCDEFRATE]->val1/100; if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) @@ -4833,28 +4877,24 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc, def >>=1; if(sc->data[SC_FREEZE]) def >>=1; - if(sc->data[SC_SIGNUMCRUCIS]) - def -= def * sc->data[SC_SIGNUMCRUCIS]->val2/100; - if(sc->data[SC_CONCENTRATION]) - def -= def * sc->data[SC_CONCENTRATION]->val4/100; + if(sc->data[SC_CRUCIS]) + def -= def * sc->data[SC_CRUCIS]->val2/100; + if(sc->data[SC_LKCONCENTRATION]) + def -= def * sc->data[SC_LKCONCENTRATION]->val4/100; if(sc->data[SC_SKE]) def >>=1; if(sc->data[SC_PROVOKE] && bl->type != BL_PC) // Provoke doesn't alter player defense-> def -= def * sc->data[SC_PROVOKE]->val4/100; - if(sc->data[SC_STRIPSHIELD]) - def -= def * sc->data[SC_STRIPSHIELD]->val2/100; + if(sc->data[SC_NOEQUIPSHIELD]) + def -= def * sc->data[SC_NOEQUIPSHIELD]->val2/100; if (sc->data[SC_FLING]) def -= def * (sc->data[SC_FLING]->val2)/100; - if( sc->data[SC_FREEZING] ) - def -= def * 10 / 100; - if( sc->data[SC_MARSHOFABYSS] ) - def -= def * ( 6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36 ) / 100; if( sc->data[SC_ANALYZE] ) def -= def * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; if( sc->data[SC_FORCEOFVANGUARD] ) def += def * 2 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100; - if(sc->data[SC_SATURDAYNIGHTFEVER]) - def -= def * (10 + 10 * sc->data[SC_SATURDAYNIGHTFEVER]->val1) / 100; + if(sc->data[SC_SATURDAY_NIGHT_FEVER]) + def -= def * (10 + 10 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1) / 100; if(sc->data[SC_EARTHDRIVE]) def -= def * 25 / 100; if( sc->data[SC_ROCK_CRUSHER] ) @@ -4863,15 +4903,17 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc, def += def * sc->data[SC_POWER_OF_GAIA]->val2 / 100; if( sc->data[SC_PRESTIGE] ) def += def * sc->data[SC_PRESTIGE]->val1 / 100; - if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ + if( sc->data[SC_FROSTMISTY] ) + def -= def * 10 / 100; + if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){ if(status_get_race(bl)==RC_PLANT) def /= 2; } - return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);; + return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); } -static signed short status_calc_def2(struct block_list *bl, struct status_change *sc, int def2) +signed short status_calc_def2(struct block_list *bl, struct status_change *sc, int def2, bool viewable) { if(!sc || !sc->count) #ifdef RENEWAL @@ -4880,6 +4922,21 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change return (short)cap_value(def2,1,SHRT_MAX); #endif + if( !viewable ){ + /* some statuses that are hidden in the status window */ +#ifdef RENEWAL + if( sc && sc->data[SC_ASSUMPTIO] ) + def2 <<= 1; +#endif + if( sc && sc->data[SC_CAMOUFLAGE] ) + def2 -= def2 * 5 * (10-sc->data[SC_CAMOUFLAGE]->val4) / 100; +#ifdef RENEWAL + return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); +#else + return (short)cap_value(def2,1,SHRT_MAX); +#endif + } + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) return 0; if(sc->data[SC_ETERNALCHAOS]) @@ -4896,9 +4953,9 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100; #else def2 += def2 * sc->data[SC_ANGELUS]->val2/100; + if(sc->data[SC_LKCONCENTRATION]) + def2 -= def2 * sc->data[SC_LKCONCENTRATION]->val4/100; #endif - if(sc->data[SC_CONCENTRATION]) - def2 -= def2 * sc->data[SC_CONCENTRATION]->val4/100; if(sc->data[SC_POISON]) def2 -= def2 * 25/100; if(sc->data[SC_DPOISON]) @@ -4912,18 +4969,16 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change + def2 * ( sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST ? 25 : 0 ) / 100; if(sc->data[SC_FLING]) def2 -= def2 * (sc->data[SC_FLING]->val3)/100; - if( sc->data[SC_FREEZING] ) - def2 -= def2 * 3 / 10; if(sc->data[SC_ANALYZE]) def2 -= def2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; if( sc->data[SC_ECHOSONG] ) def2 += def2 * sc->data[SC_ECHOSONG]->val2/100; - if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ + if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){ if(status_get_race(bl)==RC_PLANT) def2 /= 2; } - if (sc->data[SC_PARALYSIS]) - def2 -= def2 * sc->data[SC_PARALYSIS]->val2 / 100; + if (sc->data[SC_NEEDLE_OF_PARALYZE]) + def2 -= def2 * sc->data[SC_NEEDLE_OF_PARALYZE]->val2 / 100; #ifdef RENEWAL return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); @@ -4933,11 +4988,16 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change } -static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef) { +defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef, bool viewable) { if(!sc || !sc->count) return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); + if( !viewable ){ + /* some statuses that are hidden in the status window */ + return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); + } + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) return 0; if(sc->data[SC_BARRIER]) @@ -4948,15 +5008,13 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, return 90; #endif - if(sc->data[SC_ARMORCHANGE]) - mdef += sc->data[SC_ARMORCHANGE]->val3; + if(sc->data[SC_STONESKIN]) + mdef += sc->data[SC_STONESKIN]->val3; if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3) mdef += 50; if(sc->data[SC_ENDURE])// It has been confirmed that eddga card grants 1 MDEF, not 0, not 10, but 1. mdef += (sc->data[SC_ENDURE]->val4 == 0) ? sc->data[SC_ENDURE]->val1 : 1; - if(sc->data[SC_CONCENTRATION]) - mdef += 1; //Skill info says it adds a fixed 1 Mdef point. - if(sc->data[SC_STONEHARDSKIN]) + if(sc->data[SC_STONEHARDSKIN])// Final MDEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] mdef += sc->data[SC_STONEHARDSKIN]->val1; if(sc->data[SC_WATER_BARRIER]) mdef += sc->data[SC_WATER_BARRIER]->val2; @@ -4964,21 +5022,21 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, mdef += 25*mdef/100; if(sc->data[SC_FREEZE]) mdef += 25*mdef/100; - if( sc->data[SC_MARSHOFABYSS] ) - mdef -= mdef * ( 6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36 ) / 100; if(sc->data[SC_ANALYZE]) mdef -= mdef * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; - if(sc->data[SC_SYMPHONYOFLOVER]) - mdef += mdef * sc->data[SC_SYMPHONYOFLOVER]->val2 / 100; - if(sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val4) - mdef -= mdef * sc->data[SC_GT_CHANGE]->val4 / 100; + if(sc->data[SC_SYMPHONY_LOVE]) + mdef += mdef * sc->data[SC_SYMPHONY_LOVE]->val2 / 100; + if(sc->data[SC_GENTLETOUCH_CHANGE] && sc->data[SC_GENTLETOUCH_CHANGE]->val4) + mdef -= mdef * sc->data[SC_GENTLETOUCH_CHANGE]->val4 / 100; if (sc->data[SC_ODINS_POWER]) mdef -= 20 * sc->data[SC_ODINS_POWER]->val1; + if(sc->data[SC_BURNING]) + mdef -= mdef *25 / 100; return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); } -static signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, int mdef2) +signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, int mdef2, bool viewable) { if(!sc || !sc->count) #ifdef RENEWAL @@ -4987,6 +5045,16 @@ static signed short status_calc_mdef2(struct block_list *bl, struct status_chang return (short)cap_value(mdef2,1,SHRT_MAX); #endif + if( !viewable ){ + /* some statuses that are hidden in the status window */ +#ifdef RENEWAL + if(sc && sc->data[SC_ASSUMPTIO]) + mdef2 <<= 1; + return (short)cap_value(mdef2,SHRT_MIN,SHRT_MAX); +#else + return (short)cap_value(mdef2,1,SHRT_MAX); +#endif + } if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) return 0; @@ -5063,9 +5131,9 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha val = max( val, 50 - 10 * sc->data[SC_LONGING]->val1 ); else if( sd && sc->data[SC_DANCING] ) - val = max( val, 500 - (40 + 10 * (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) * pc->checkskill(sd,(sd->status.sex?BA_MUSICALLESSON:DC_DANCINGLESSON)) ); + val = max( val, 500 - (40 + 10 * (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) * pc->checkskill(sd,(sd->status.sex?BA_MUSICALLESSON:DC_DANCINGLESSON)) ); - if( sc->data[SC_DECREASEAGI] ) + if( sc->data[SC_DEC_AGI] ) val = max( val, 25 ); if( sc->data[SC_QUAGMIRE] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY] || (sc->data[SC_GLOOMYDAY] && sc->data[SC_GLOOMYDAY]->val4) ) val = max( val, 50 ); @@ -5085,16 +5153,14 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha val = max( val, 75 ); if( sc->data[SC_SLOWDOWN] ) // Slow Potion val = max( val, 100 ); - if( sc->data[SC_GATLINGFEVER] ) + if( sc->data[SC_GS_GATLINGFEVER] ) val = max( val, 100 ); - if( sc->data[SC_SUITON] ) - val = max( val, sc->data[SC_SUITON]->val3 ); + if( sc->data[SC_NJ_SUITON] ) + val = max( val, sc->data[SC_NJ_SUITON]->val3 ); if( sc->data[SC_SWOO] ) val = max( val, 300 ); - if( sc->data[SC_FREEZING] ) - val = max( val, 70 ); - if( sc->data[SC_MARSHOFABYSS] ) - val = max( val, 40 + 10 * sc->data[SC_MARSHOFABYSS]->val1 ); + if( sc->data[SC_FROSTMISTY] ) + val = max( val, 50 ); if( sc->data[SC_CAMOUFLAGE] && (sc->data[SC_CAMOUFLAGE]->val3&1) == 0 ) val = max( val, sc->data[SC_CAMOUFLAGE]->val1 < 3 ? 0 : 25 * (5 - sc->data[SC_CAMOUFLAGE]->val1) ); if( sc->data[SC__GROOMY] ) @@ -5109,6 +5175,9 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha val = max( val, sc->data[SC_POWER_OF_GAIA]->val2 ); if( sc->data[SC_MELON_BOMB] ) val = max( val, sc->data[SC_MELON_BOMB]->val1 ); + + if( sc->data[SC_MARSHOFABYSS] ) // It stacks to other statuses so always put this at the end. + val = max( 50, val + 10 * sc->data[SC_MARSHOFABYSS]->val1 ); if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0 ) // permanent item-based speedup val = max( val, sd->bonus.speed_rate + sd->bonus.speed_add_rate ); @@ -5121,9 +5190,9 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha { int val = 0; - if( sc->data[SC_SPEEDUP1] ) //FIXME: used both by NPC_AGIUP and Speed Potion script + if( sc->data[SC_MOVHASTE_INFINITY] ) //FIXME: used both by NPC_AGIUP and Speed Potion script val = max( val, 50 ); - if( sc->data[SC_INCREASEAGI] ) + if( sc->data[SC_INC_AGI] ) val = max( val, 25 ); if( sc->data[SC_WINDWALK] ) val = max( val, 2 * sc->data[SC_WINDWALK]->val1 ); @@ -5137,8 +5206,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha val = max( val, 25 ); if( sc->data[SC_RUN] ) val = max( val, 55 ); - if( sc->data[SC_AVOID] ) - val = max( val, 10 * sc->data[SC_AVOID]->val1 ); + if( sc->data[SC_HLIF_AVOID] ) + val = max( val, 10 * sc->data[SC_HLIF_AVOID]->val1 ); if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) val = max( val, 75 ); if( sc->data[SC_CLOAKINGEXCEED] ) @@ -5147,13 +5216,14 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha val = max( val, 10 ); if( sc->data[SC_GN_CARTBOOST] ) val = max( val, sc->data[SC_GN_CARTBOOST]->val2 ); - if( sc->data[SC_SWINGDANCE] ) - val = max( val, sc->data[SC_SWINGDANCE]->val2 ); + if( sc->data[SC_SWING] ) + val = max( val, sc->data[SC_SWING]->val2 ); if( sc->data[SC_WIND_STEP_OPTION] ) val = max( val, sc->data[SC_WIND_STEP_OPTION]->val2 ); - + if( sc->data[SC_FULL_THROTTLE] ) + val = max( val, 30); //FIXME: official items use a single bonus for this [ultramage] - if( sc->data[SC_SPEEDUP0] ) // temporary item-based speedup + if( sc->data[SC_MOVHASTE_HORSE] ) // temporary item-based speedup val = max( val, 25 ); if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate < 0 ) // permanent item-based speedup val = max( val, -(sd->bonus.speed_rate + sd->bonus.speed_add_rate) ); @@ -5171,6 +5241,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha speed += speed * (50 - 5 * pc->checkskill(sd,MC_PUSHCART)) / 100; if( sc->data[SC_PARALYSE] ) speed += speed * 50 / 100; + if( sc->data[SC_REBOUND] ) + speed += max(speed, 100); if( speed_rate != 100 ) speed = speed * speed_rate / 100; if( sc->data[SC_STEELBODY] ) @@ -5179,6 +5251,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha speed = max(speed, 200); if( sc->data[SC_WALKSPEED] && sc->data[SC_WALKSPEED]->val1 > 0 ) // ChangeSpeed speed = speed * 100 / sc->data[SC_WALKSPEED]->val1; + } return (short)cap_value(speed,10,USHRT_MAX); @@ -5194,22 +5267,19 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s if(!sc || !sc->count) return 0; - if(sc->data[i=SC_ASPDPOTION3] || - sc->data[i=SC_ASPDPOTION2] || - sc->data[i=SC_ASPDPOTION1] || - sc->data[i=SC_ASPDPOTION0]) + if(sc->data[i=SC_ATTHASTE_INFINITY] || + sc->data[i=SC_ATTHASTE_POTION3] || + sc->data[i=SC_ATTHASTE_POTION2] || + sc->data[i=SC_ATTHASTE_POTION1]) pots += sc->data[i]->val1; if( !sc->data[SC_QUAGMIRE] ){ - if(sc->data[SC_STAR_COMFORT]) - skills1 = 5; // needs more info - if(sc->data[SC_TWOHANDQUICKEN] && skills1 < 7) skills1 = 7; - if(sc->data[SC_ONEHAND] && skills1 < 7) skills1 = 7; + if(sc->data[SC_ONEHANDQUICKEN] && skills1 < 7) skills1 = 7; - if(sc->data[SC_MERC_QUICKEN] && skills1 < 7) // needs more info + if(sc->data[SC_MER_QUICKEN] && skills1 < 7) // needs more info skills1 = 7; if(sc->data[SC_ADRENALINE2] && skills1 < 6) @@ -5221,48 +5291,25 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s if(sc->data[SC_SPEARQUICKEN] && skills1 < 7) skills1 = 7; - if(sc->data[SC_GATLINGFEVER] && skills1 < 9) // needs more info - skills1 = 9; - - if(sc->data[SC_FLEET] && skills1 < 5) + if(sc->data[SC_HLIF_FLEET] && skills1 < 5) skills1 = 5; - - if(sc->data[SC_ASSNCROS] && - skills1 < 5+1*sc->data[SC_ASSNCROS]->val1) // needs more info - { - if (bl->type!=BL_PC) - skills1 = 4+1*sc->data[SC_ASSNCROS]->val1; - else - switch(((TBL_PC*)bl)->status.weapon) - { - case W_BOW: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - break; - default: - skills1 = 5+1*sc->data[SC_ASSNCROS]->val1; - } - } } if((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) && skills1 < 15) skills1 = 15; - else if(sc->data[SC_MADNESSCANCEL] && skills1 < 15) // needs more info - skills1 = 15; + else if(sc->data[SC_GS_MADNESSCANCEL] && skills1 < 20) + skills1 = 20; if(sc->data[SC_DONTFORGETME]) - skills2 -= sc->data[SC_DONTFORGETME]->val2; // needs more info + skills2 -= sc->data[SC_DONTFORGETME]->val2; if(sc->data[SC_LONGING]) - skills2 -= sc->data[SC_LONGING]->val2; // needs more info + skills2 -= sc->data[SC_LONGING]->val2; if(sc->data[SC_STEELBODY]) skills2 -= 25; if(sc->data[SC_SKA]) skills2 -= 25; if(sc->data[SC_DEFENDER]) - skills2 -= sc->data[SC_DEFENDER]->val4; // needs more info + skills2 -= sc->data[SC_DEFENDER]->val4 / 10; if(sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) // needs more info skills2 -= 25; if(sc->data[SC_GRAVITATION]) @@ -5273,8 +5320,8 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s if( sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE ) skills2 -= 10; } - if( sc->data[SC_FREEZING] ) - skills2 -= 30; + if( sc->data[SC_FROSTMISTY] ) + skills2 -= 15; if( sc->data[SC_HALLUCINATIONWALK_POSTDELAY] ) skills2 -= 50; if( sc->data[SC_PARALYSE] ) @@ -5285,25 +5332,46 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s skills2 -= sc->data[SC__INVISIBILITY]->val2 ; if( sc->data[SC__GROOMY] ) skills2 -= sc->data[SC__GROOMY]->val2; - if( sc->data[SC_SWINGDANCE] ) - skills2 += sc->data[SC_SWINGDANCE]->val2; - if( sc->data[SC_DANCEWITHWUG] ) - skills2 += sc->data[SC_DANCEWITHWUG]->val3; if( sc->data[SC_GLOOMYDAY] ) skills2 -= sc->data[SC_GLOOMYDAY]->val3; if( sc->data[SC_EARTHDRIVE] ) skills2 -= 25; - if( sc->data[SC_GT_CHANGE] ) - skills2 += sc->data[SC_GT_CHANGE]->val3; if( sc->data[SC_MELON_BOMB] ) skills2 -= sc->data[SC_MELON_BOMB]->val1; + + if( sc->data[SC_SWING] ) + skills2 += sc->data[SC_SWING]->val2; + if( sc->data[SC_DANCE_WITH_WUG] ) + skills2 += sc->data[SC_DANCE_WITH_WUG]->val3; + if( sc->data[SC_GENTLETOUCH_CHANGE] ) + skills2 += sc->data[SC_GENTLETOUCH_CHANGE]->val3; if( sc->data[SC_BOOST500] ) skills2 += sc->data[SC_BOOST500]->val1; if( sc->data[SC_EXTRACT_SALAMINE_JUICE] ) skills2 += sc->data[SC_EXTRACT_SALAMINE_JUICE]->val1; if( sc->data[SC_INCASPDRATE] ) skills2 += sc->data[SC_INCASPDRATE]->val1; - + if( sc->data[SC_GS_GATLINGFEVER] ) + skills2 += sc->data[SC_GS_GATLINGFEVER]->val1; + if( sc->data[SC_STAR_COMFORT] ) + skills2 += 3 * sc->data[SC_STAR_COMFORT]->val1; + if( sc->data[SC_ASSNCROS] && !skills1){ + if (bl->type!=BL_PC) + skills2 += sc->data[SC_ASSNCROS]->val2; + else + switch(((TBL_PC*)bl)->status.weapon) + { + case W_BOW: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + break; + default: + skills2 += sc->data[SC_ASSNCROS]->val2; + } + } return ( flag&1? (skills1 + pots) : skills2 ); } #endif @@ -5344,13 +5412,13 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * max < sc->data[SC_TWOHANDQUICKEN]->val2) max = sc->data[SC_TWOHANDQUICKEN]->val2; - if(sc->data[SC_ONEHAND] && - max < sc->data[SC_ONEHAND]->val2) - max = sc->data[SC_ONEHAND]->val2; + if(sc->data[SC_ONEHANDQUICKEN] && + max < sc->data[SC_ONEHANDQUICKEN]->val2) + max = sc->data[SC_ONEHANDQUICKEN]->val2; - if(sc->data[SC_MERC_QUICKEN] && - max < sc->data[SC_MERC_QUICKEN]->val2) - max = sc->data[SC_MERC_QUICKEN]->val2; + if(sc->data[SC_MER_QUICKEN] && + max < sc->data[SC_MER_QUICKEN]->val2) + max = sc->data[SC_MER_QUICKEN]->val2; if(sc->data[SC_ADRENALINE2] && max < sc->data[SC_ADRENALINE2]->val3) @@ -5364,13 +5432,13 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * max < sc->data[SC_SPEARQUICKEN]->val2) max = sc->data[SC_SPEARQUICKEN]->val2; - if(sc->data[SC_GATLINGFEVER] && - max < sc->data[SC_GATLINGFEVER]->val2) - max = sc->data[SC_GATLINGFEVER]->val2; + if(sc->data[SC_GS_GATLINGFEVER] && + max < sc->data[SC_GS_GATLINGFEVER]->val2) + max = sc->data[SC_GS_GATLINGFEVER]->val2; - if(sc->data[SC_FLEET] && - max < sc->data[SC_FLEET]->val2) - max = sc->data[SC_FLEET]->val2; + if(sc->data[SC_HLIF_FLEET] && + max < sc->data[SC_HLIF_FLEET]->val2) + max = sc->data[SC_HLIF_FLEET]->val2; if(sc->data[SC_ASSNCROS] && max < sc->data[SC_ASSNCROS]->val2) @@ -5395,14 +5463,14 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * if((sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])) aspd_rate -= 300; - else if(sc->data[SC_MADNESSCANCEL]) + else if(sc->data[SC_GS_MADNESSCANCEL]) aspd_rate -= 200; } - if( sc->data[i=SC_ASPDPOTION3] || - sc->data[i=SC_ASPDPOTION2] || - sc->data[i=SC_ASPDPOTION1] || - sc->data[i=SC_ASPDPOTION0] ) + if( sc->data[i=SC_ATTHASTE_INFINITY] || + sc->data[i=SC_ATTHASTE_POTION3] || + sc->data[i=SC_ATTHASTE_POTION2] || + sc->data[i=SC_ATTHASTE_POTION1] ) aspd_rate -= sc->data[i]->val2; if(sc->data[SC_DONTFORGETME]) @@ -5425,8 +5493,8 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * if( sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE ) aspd_rate += 100; } - if( sc->data[SC_FREEZING] ) - aspd_rate += 300; + if( sc->data[SC_FROSTMISTY] ) + aspd_rate += 150; if( sc->data[SC_HALLUCINATIONWALK_POSTDELAY] ) aspd_rate += 500; if( sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 ) @@ -5439,16 +5507,16 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * aspd_rate += sc->data[SC__INVISIBILITY]->val2 * 10 ; if( sc->data[SC__GROOMY] ) aspd_rate += sc->data[SC__GROOMY]->val2 * 10; - if( sc->data[SC_SWINGDANCE] ) - aspd_rate -= sc->data[SC_SWINGDANCE]->val2 * 10; - if( sc->data[SC_DANCEWITHWUG] ) - aspd_rate -= sc->data[SC_DANCEWITHWUG]->val3 * 10; + if( sc->data[SC_SWING] ) + aspd_rate -= sc->data[SC_SWING]->val2 * 10; + if( sc->data[SC_DANCE_WITH_WUG] ) + aspd_rate -= sc->data[SC_DANCE_WITH_WUG]->val3 * 10; if( sc->data[SC_GLOOMYDAY] ) aspd_rate += sc->data[SC_GLOOMYDAY]->val3 * 10; if( sc->data[SC_EARTHDRIVE] ) aspd_rate += 250; - if( sc->data[SC_GT_CHANGE] ) - aspd_rate -= sc->data[SC_GT_CHANGE]->val3 * 10; + if( sc->data[SC_GENTLETOUCH_CHANGE] ) + aspd_rate -= sc->data[SC_GENTLETOUCH_CHANGE]->val3 * 10; if( sc->data[SC_MELON_BOMB] ) aspd_rate += sc->data[SC_MELON_BOMB]->val1 * 10; if( sc->data[SC_BOOST500] ) @@ -5474,8 +5542,6 @@ static unsigned short status_calc_dmotion(struct block_list *bl, struct status_c **/ if( sc->data[SC_ENDURE] || ( bl->type == BL_MOB && (((TBL_MOB*)bl)->status.mode&MD_BOSS) ) ) return 0; - if( sc->data[SC_CONCENTRATION] ) - return 0; if( sc->data[SC_RUN] || sc->data[SC_WUGDASH] ) return 0; @@ -5497,7 +5563,7 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang maxhp += maxhp * sc->data[SC_DELUGE]->val2/100; if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) maxhp += maxhp * 2; - if(sc->data[SC_MARIONETTE]) + if(sc->data[SC_MARIONETTE_MASTER]) maxhp -= 1000; if(sc->data[SC_SOLID_SKIN_OPTION]) maxhp += 2000;// Fix amount. @@ -5506,8 +5572,8 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) maxhp += 500; - if(sc->data[SC_MERC_HPUP]) - maxhp += maxhp * sc->data[SC_MERC_HPUP]->val2/100; + if(sc->data[SC_MER_HP]) + maxhp += maxhp * sc->data[SC_MER_HP]->val2/100; if(sc->data[SC_EPICLESIS]) maxhp += maxhp * 5 * sc->data[SC_EPICLESIS]->val1 / 100; @@ -5515,18 +5581,18 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang maxhp -= maxhp * 15 / 100; if(sc->data[SC__WEAKNESS]) maxhp -= maxhp * sc->data[SC__WEAKNESS]->val2 / 100; - if(sc->data[SC_LERADSDEW]) - maxhp += maxhp * sc->data[SC_LERADSDEW]->val3 / 100; + if(sc->data[SC_LERADS_DEW]) + maxhp += maxhp * sc->data[SC_LERADS_DEW]->val3 / 100; if(sc->data[SC_FORCEOFVANGUARD]) maxhp += maxhp * 3 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100; if(sc->data[SC_INSPIRATION]) //Custom value. maxhp += maxhp * 3 * sc->data[SC_INSPIRATION]->val1 / 100; if(sc->data[SC_RAISINGDRAGON]) maxhp += maxhp * (2 + sc->data[SC_RAISINGDRAGON]->val1) / 100; - if(sc->data[SC_GT_CHANGE]) // Max HP decrease: [Skill Level x 4] % - maxhp -= maxhp * (4 * sc->data[SC_GT_CHANGE]->val1) / 100; - if(sc->data[SC_GT_REVITALIZE])// Max HP increase: [Skill Level x 2] % - maxhp += maxhp * (2 * sc->data[SC_GT_REVITALIZE]->val1) / 100; + if(sc->data[SC_GENTLETOUCH_CHANGE]) // Max HP decrease: [Skill Level x 4] % + maxhp -= maxhp * (4 * sc->data[SC_GENTLETOUCH_CHANGE]->val1) / 100; + if(sc->data[SC_GENTLETOUCH_REVITALIZE])// Max HP increase: [Skill Level x 2] % + maxhp += maxhp * (2 * sc->data[SC_GENTLETOUCH_REVITALIZE]->val1) / 100; if(sc->data[SC_MUSTLE_M]) maxhp += maxhp * sc->data[SC_MUSTLE_M]->val1/100; if(sc->data[SC_MYSTERIOUS_POWDER]) @@ -5537,6 +5603,8 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100; if (sc->data[SC_GOLDENE_FERSE]) maxhp += maxhp * sc->data[SC_GOLDENE_FERSE]->val2 / 100; + if(sc->data[SC_FRIGG_SONG]) + maxhp += maxhp * sc->data[SC_FRIGG_SONG]->val2 / 100; return (unsigned int)cap_value(maxhp,1,UINT_MAX); } @@ -5550,10 +5618,10 @@ static unsigned int status_calc_maxsp(struct block_list *bl, struct status_chang maxsp += maxsp * sc->data[SC_INCMSPRATE]->val1/100; if(sc->data[SC_INCMSP]) maxsp += (sc->data[SC_INCMSP]->val1); - if(sc->data[SC_SERVICE4U]) - maxsp += maxsp * sc->data[SC_SERVICE4U]->val2/100; - if(sc->data[SC_MERC_SPUP]) - maxsp += maxsp * sc->data[SC_MERC_SPUP]->val2/100; + if(sc->data[SC_SERVICEFORYOU]) + maxsp += maxsp * sc->data[SC_SERVICEFORYOU]->val2/100; + if(sc->data[SC_MER_SP]) + maxsp += maxsp * sc->data[SC_MER_SP]->val2/100; if(sc->data[SC_RAISINGDRAGON]) maxsp += maxsp * (2 + sc->data[SC_RAISINGDRAGON]->val1) / 100; if(sc->data[SC_LIFE_FORCE_F]) @@ -5575,10 +5643,10 @@ static unsigned char status_calc_element(struct block_list *bl, struct status_ch return ELE_EARTH; if(sc->data[SC_BENEDICTIO]) return ELE_HOLY; - if(sc->data[SC_CHANGEUNDEAD]) + if(sc->data[SC_PROPERTYUNDEAD]) return ELE_UNDEAD; - if(sc->data[SC_ELEMENTALCHANGE]) - return sc->data[SC_ELEMENTALCHANGE]->val2; + if(sc->data[SC_ARMOR_PROPERTY]) + return sc->data[SC_ARMOR_PROPERTY]->val2; if(sc->data[SC_SHAPESHIFT]) return sc->data[SC_SHAPESHIFT]->val2; @@ -5596,10 +5664,10 @@ static unsigned char status_calc_element_lv(struct block_list *bl, struct status return 1; if(sc->data[SC_BENEDICTIO]) return 1; - if(sc->data[SC_CHANGEUNDEAD]) + if(sc->data[SC_PROPERTYUNDEAD]) return 1; - if(sc->data[SC_ELEMENTALCHANGE]) - return sc->data[SC_ELEMENTALCHANGE]->val1; + if(sc->data[SC_ARMOR_PROPERTY]) + return sc->data[SC_ARMOR_PROPERTY]->val1; if(sc->data[SC_SHAPESHIFT]) return 1; if(sc->data[SC__INVISIBILITY]) @@ -5615,25 +5683,25 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch return element; if(sc->data[SC_ENCHANTARMS]) return sc->data[SC_ENCHANTARMS]->val2; - if(sc->data[SC_WATERWEAPON] + if(sc->data[SC_PROPERTYWATER] || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) ) return ELE_WATER; - if(sc->data[SC_EARTHWEAPON] + if(sc->data[SC_PROPERTYGROUND] || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) ) return ELE_EARTH; - if(sc->data[SC_FIREWEAPON] + if(sc->data[SC_PROPERTYFIRE] || (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) ) return ELE_FIRE; - if(sc->data[SC_WINDWEAPON] + if(sc->data[SC_PROPERTYWIND] || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2) ) return ELE_WIND; - if(sc->data[SC_ENCPOISON]) + if(sc->data[SC_ENCHANTPOISON]) return ELE_POISON; if(sc->data[SC_ASPERSIO]) return ELE_HOLY; - if(sc->data[SC_SHADOWWEAPON]) + if(sc->data[SC_PROPERTYDARK]) return ELE_DARK; - if(sc->data[SC_GHOSTWEAPON] || sc->data[SC__INVISIBILITY]) + if(sc->data[SC_PROPERTYTELEKINESIS] || sc->data[SC__INVISIBILITY]) return ELE_GHOST; if(sc->data[SC_TIDAL_WEAPON_OPTION] || sc->data[SC_TIDAL_WEAPON] ) return ELE_WATER; @@ -6119,14 +6187,14 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti //Status that are blocked by Golden Thief Bug card or Wand of Hermod if (status_isimmune(bl)) switch (type) { - case SC_DECREASEAGI: + case SC_DEC_AGI: case SC_SILENCE: case SC_COMA: - case SC_INCREASEAGI: + case SC_INC_AGI: case SC_BLESSING: case SC_SLOWPOISON: case SC_IMPOSITIO: - case SC_AETERNA: + case SC_LEXAETERNA: case SC_SUFFRAGIUM: case SC_BENEDICTIO: case SC_PROVIDENCE: @@ -6137,11 +6205,11 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti case SC_GLORIA: case SC_WINDWALK: case SC_MAGICROD: - case SC_HALLUCINATION: + case SC_ILLUSION: case SC_STONE: case SC_QUAGMIRE: - case SC_SUITON: - case SC_SWINGDANCE: + case SC_NJ_SUITON: + case SC_SWING: case SC__ENERVATION: case SC__GROOMY: case SC__IGNORANCE: @@ -6164,7 +6232,7 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti return tick; case SC_DPOISON: case SC_SILENCE: - case SC_BLEEDING: + case SC_BLOODING: sc_def = status->vit*100; sc_def2 = status->luk*10; break; @@ -6172,11 +6240,11 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti sc_def = status->int_*100; sc_def2 = status->luk*10; break; - case SC_DEEPSLEEP: + case SC_DEEP_SLEEP: sc_def = status->int_*50; tick_def = status->int_*10 + status_get_lv(bl) * 65 / 10; //Seems to be -1 sec every 10 int and -5% chance every 10 int. break; - case SC_DECREASEAGI: + case SC_DEC_AGI: case SC_ADORAMUS: //Arch Bishop if (sd) tick>>=1; //Half duration for players. case SC_STONE: @@ -6205,13 +6273,13 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti sc_def = (status->str + status->int_)*50; sc_def2 = status->luk*10; break; - case SC_ANKLE: + case SC_ANKLESNARE: if(status->mode&MD_BOSS) // Lasts 5 times less on bosses tick /= 5; sc_def = status->agi*50; break; case SC_MAGICMIRROR: - case SC_ARMORCHANGE: + case SC_STONESKIN: if (sd) //Duration greatly reduced for players. tick /= 15; sc_def2 = status_get_lv(bl)*20 + status->vit*25 + status->agi*10; // Lineal Reduction of Rate @@ -6231,21 +6299,20 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti tick -= (status->vit + status->luk) / 20 * 1000; break; case SC_BURNING: - // From iROwiki : http://forums.irowiki.org/showpost.php?p=577240&postcount=583 - tick -= 50*status->luk + 60*status->int_ + 170*status->vit; - tick = max(tick,10000); // Minimum Duration 10s. + tick -= 75 * status->luk + 125 * status->agi; + tick = max(tick,5000); // Minimum Duration 5s. break; - case SC_FREEZING: + case SC_FROSTMISTY: tick -= 1000 * ((status->vit + status->dex) / 20); - tick = max(tick,10000); // Minimum Duration 10s. + tick = max(tick,6000); // Minimum Duration 10s. break; case SC_OBLIVIONCURSE: // 100% - (100 - 0.8 x INT) sc_def = 100 - ( 100 - status->int_* 8 / 10 ); sc_def = max(sc_def, 5); // minimum of 5% break; - case SC_BITE: // {(Base Success chance) - (Target's AGI / 4)} - rate -= status->agi*1000/4; - rate = max(rate,50000); // minimum of 50% + case SC_WUGBITE: // {(Base Success chance) - (Target's AGI / 4)} + rate -= status->agi*100/4; + rate = max(rate,5000); // minimum of 50% break; case SC_ELECTRICSHOCKER: if( bl->type == BL_MOB ) @@ -6258,11 +6325,11 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti sc_def = (status->vit+status->luk)/5; break; case SC_KYOUGAKU: - tick -= 30*status->int_; + tick -= 1000 * status_get_int(bl) / 20; break; - case SC_PARALYSIS: - tick -= 50 * (status->vit + status->luk); //(1000/20); - break; + case SC_NEEDLE_OF_PARALYZE: + tick -= 50 * (status->vit + status->luk); //(1000/20); + break; default: //Effect that cannot be reduced? Likely a buff. if (!(rnd()%10000 < rate)) @@ -6320,7 +6387,7 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti //Minimum chances switch (type) { - case SC_BITE: + case SC_WUGBITE: rate = max(rate, 5000); //Minimum of 50% break; } @@ -6330,8 +6397,8 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti { if( sd->reseff[type-SC_COMMON_MIN] > 0 ) rate -= rate*sd->reseff[type-SC_COMMON_MIN]/10000; - if( sd->sc.data[SC_COMMONSC_RESIST] ) - rate -= rate*sd->sc.data[SC_COMMONSC_RESIST]->val1/100; + if( sd->sc.data[SC_TARGET_BLOOD] ) + rate -= rate*sd->sc.data[SC_TARGET_BLOOD]->val1/100; } } @@ -6350,13 +6417,13 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti //Minimum durations switch (type) { - case SC_ANKLE: + case SC_ANKLESNARE: case SC_MARSHOFABYSS: case SC_STASIS: tick = max(tick, 5000); //Minimum duration 5s break; case SC_BURNING: - case SC_FREEZING: + case SC_FROSTMISTY: tick = max(tick, 10000); //Minimum duration 10s break; default: @@ -6460,9 +6527,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val return 0; // Immune to status ailements switch( type ) { case SC_QUAGMIRE://Tester said it protects against this and decrease agi. - case SC_DECREASEAGI: + case SC_DEC_AGI: case SC_BURNING: - case SC_FREEZING: + case SC_FROSTMISTY: //case SC_WHITEIMPRISON://Need confirm. Protected against this in the past. [Rytech] case SC_MARSHOFABYSS: case SC_TOXIN: @@ -6474,7 +6541,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_OBLIVIONCURSE: case SC_LEECHESEND: case SC_CRYSTALIZE: ////08/31/2011 - Class Balance Changes - case SC_DEEPSLEEP: + case SC_DEEP_SLEEP: case SC_MANDRAGORA: return 0; } @@ -6483,8 +6550,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX ) return 0; // Immune to status ailements switch( type ) { - case SC_DEEPSLEEP: - case SC_SATURDAYNIGHTFEVER: + case SC_DEEP_SLEEP: + case SC_SATURDAY_NIGHT_FEVER: case SC_PYREXIA: case SC_DEATHHURT: case SC_MAGICMUSHROOM: @@ -6528,14 +6595,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val //Undead are immune to Freeze/Stone if (undead_flag && !(flag&1)) return 0; - case SC_DEEPSLEEP: + case SC_DEEP_SLEEP: case SC_SLEEP: case SC_STUN: - case SC_FREEZING: + case SC_FROSTMISTY: case SC_CRYSTALIZE: if (sc->opt1) return 0; //Cannot override other opt1 status changes. [Skotlex] - if((type == SC_FREEZE || type == SC_FREEZING || type == SC_CRYSTALIZE) && sc->data[SC_WARMER]) + if((type == SC_FREEZE || type == SC_FROSTMISTY || type == SC_CRYSTALIZE) && sc->data[SC_WARMER]) return 0; //Immune to Frozen and Freezing status if under Warmer status. [Jobbie] break; @@ -6543,23 +6610,23 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC__BLOODYLUST: if(!sd) return 0; //should only affect player case SC_BERSERK: - if (((type == SC_BERSERK) && (sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST])) - || ((type == SC__BLOODYLUST) && (sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC_BERSERK])) + if (((type == SC_BERSERK) && (sc->data[SC_SATURDAY_NIGHT_FEVER] || sc->data[SC__BLOODYLUST])) + || ((type == SC__BLOODYLUST) && (sc->data[SC_SATURDAY_NIGHT_FEVER] || sc->data[SC_BERSERK])) ) return 0; break; case SC_BURNING: - if(sc->opt1 || sc->data[SC_FREEZING]) + if(sc->opt1 || sc->data[SC_FROSTMISTY]) return 0; break; - case SC_SIGNUMCRUCIS: + case SC_CRUCIS: //Only affects demons and undead element (but not players) if((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) return 0; break; - case SC_AETERNA: + case SC_LEXAETERNA: if( (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) || sc->data[SC_FREEZE] ) return 0; break; @@ -6568,9 +6635,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val return 0; break; case SC_OVERTHRUST: - if (sc->data[SC_MAXOVERTHRUST]) + if (sc->data[SC_OVERTHRUSTMAX]) return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex] - case SC_MAXOVERTHRUST: + case SC_OVERTHRUSTMAX: if( sc->option&OPTION_MADOGEAR ) return 0;//Overthrust and Overthrust Max cannot be used on Mado Gear [Ind] break; @@ -6578,7 +6645,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE))) return 0; if (sc->data[SC_QUAGMIRE] || - sc->data[SC_DECREASEAGI] || + sc->data[SC_DEC_AGI] || sc->option&OPTION_MADOGEAR //Adrenaline doesn't affect Mado Gear [Ind] ) return 0; @@ -6587,27 +6654,27 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE2))) return 0; if (sc->data[SC_QUAGMIRE] || - sc->data[SC_DECREASEAGI] + sc->data[SC_DEC_AGI] ) return 0; break; case SC_MAGNIFICAT: - if( sc->option&OPTION_MADOGEAR ) //Mado is immune to magnificat + if( sc->data[SC_OFFERTORIUM] || sc->option&OPTION_MADOGEAR ) //Mado is immune to magnificat return 0; break; - case SC_ONEHAND: - case SC_MERC_QUICKEN: + case SC_ONEHANDQUICKEN: + case SC_MER_QUICKEN: case SC_TWOHANDQUICKEN: - if(sc->data[SC_DECREASEAGI]) + if(sc->data[SC_DEC_AGI]) return 0; - case SC_INCREASEAGI: + case SC_INC_AGI: if(sd && pc_issit(sd)){ pc->setstand(sd); clif->standing(&sd->bl); } - case SC_CONCENTRATE: + case SC_CONCENTRATION: case SC_SPEARQUICKEN: case SC_TRUESIGHT: case SC_WINDWALK: @@ -6648,7 +6715,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } break; //Strip skills, need to divest something or it fails. - case SC_STRIPWEAPON: + case SC_NOEQUIPWEAPON: if (sd && !(flag&4)) { //apply sc anyway if loading saved sc_data int i; opt_flag = 0; //Reuse to check success condition. @@ -6664,7 +6731,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; - case SC_STRIPSHIELD: + case SC_NOEQUIPSHIELD: if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off.. else if (sd && !(flag&4)) { @@ -6678,7 +6745,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; - case SC_STRIPARMOR: + case SC_NOEQUIPARMOR: if (sd && !(flag&4)) { int i; if(sd->bonus.unstripable_equip&EQP_ARMOR) @@ -6690,7 +6757,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; - case SC_STRIPHELM: + case SC_NOEQUIPHELM: if (sd && !(flag&4)) { int i; if(sd->bonus.unstripable_equip&EQP_HELM) @@ -6702,67 +6769,67 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; - case SC_MERC_FLEEUP: - case SC_MERC_ATKUP: - case SC_MERC_HPUP: - case SC_MERC_SPUP: - case SC_MERC_HITUP: + case SC_MER_FLEE: + case SC_MER_ATK: + case SC_MER_HP: + case SC_MER_SP: + case SC_MER_HIT: if( bl->type != BL_MER ) return 0; // Stats only for Mercenaries break; - case SC_STRFOOD: + case SC_FOOD_STR: if (sc->data[SC_FOOD_STR_CASH] && sc->data[SC_FOOD_STR_CASH]->val1 > val1) return 0; break; - case SC_AGIFOOD: + case SC_FOOD_AGI: if (sc->data[SC_FOOD_AGI_CASH] && sc->data[SC_FOOD_AGI_CASH]->val1 > val1) return 0; break; - case SC_VITFOOD: + case SC_FOOD_VIT: if (sc->data[SC_FOOD_VIT_CASH] && sc->data[SC_FOOD_VIT_CASH]->val1 > val1) return 0; break; - case SC_INTFOOD: + case SC_FOOD_INT: if (sc->data[SC_FOOD_INT_CASH] && sc->data[SC_FOOD_INT_CASH]->val1 > val1) return 0; break; - case SC_DEXFOOD: + case SC_FOOD_DEX: if (sc->data[SC_FOOD_DEX_CASH] && sc->data[SC_FOOD_DEX_CASH]->val1 > val1) return 0; break; - case SC_LUKFOOD: + case SC_FOOD_LUK: if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1) return 0; break; case SC_FOOD_STR_CASH: - if (sc->data[SC_STRFOOD] && sc->data[SC_STRFOOD]->val1 > val1) + if (sc->data[SC_FOOD_STR] && sc->data[SC_FOOD_STR]->val1 > val1) return 0; break; case SC_FOOD_AGI_CASH: - if (sc->data[SC_AGIFOOD] && sc->data[SC_AGIFOOD]->val1 > val1) + if (sc->data[SC_FOOD_AGI] && sc->data[SC_FOOD_AGI]->val1 > val1) return 0; break; case SC_FOOD_VIT_CASH: - if (sc->data[SC_VITFOOD] && sc->data[SC_VITFOOD]->val1 > val1) + if (sc->data[SC_FOOD_VIT] && sc->data[SC_FOOD_VIT]->val1 > val1) return 0; break; case SC_FOOD_INT_CASH: - if (sc->data[SC_INTFOOD] && sc->data[SC_INTFOOD]->val1 > val1) + if (sc->data[SC_FOOD_INT] && sc->data[SC_FOOD_INT]->val1 > val1) return 0; break; case SC_FOOD_DEX_CASH: - if (sc->data[SC_DEXFOOD] && sc->data[SC_DEXFOOD]->val1 > val1) + if (sc->data[SC_FOOD_DEX] && sc->data[SC_FOOD_DEX]->val1 > val1) return 0; break; case SC_FOOD_LUK_CASH: - if (sc->data[SC_LUKFOOD] && sc->data[SC_LUKFOOD]->val1 > val1) + if (sc->data[SC_FOOD_LUK] && sc->data[SC_FOOD_LUK]->val1 > val1) return 0; break; case SC_CAMOUFLAGE: if( sd && pc->checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill->check_camouflage(bl,NULL) ) return 0; break; - case SC__STRIPACCESSORY: + case SC__STRIPACCESSARY: if( sd ) { int i = -1; if( !(sd->bonus.unstripable_equip&EQI_ACC_L) ) { @@ -6793,10 +6860,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if(sc->data[i]) return 0; } break; - case SC_SATURDAYNIGHTFEVER: + case SC_SATURDAY_NIGHT_FEVER: if (sc->data[SC_BERSERK] || sc->data[SC_INSPIRATION] || sc->data[SC__BLOODYLUST]) return 0; break; + case SC_OFFERTORIUM: + if (sc->data[SC_MAGNIFICAT]) + return 0; + break; } //Check for BOSS resistances @@ -6805,20 +6876,20 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val return 0; switch (type) { case SC_BLESSING: - case SC_DECREASEAGI: + case SC_DEC_AGI: case SC_PROVOKE: case SC_COMA: case SC_GRAVITATION: - case SC_SUITON: + case SC_NJ_SUITON: case SC_RICHMANKIM: case SC_ROKISWEIL: case SC_FOGWALL: - case SC_FREEZING: + case SC_FROSTMISTY: case SC_BURNING: case SC_MARSHOFABYSS: case SC_ADORAMUS: - case SC_PARALYSIS: - case SC_DEEPSLEEP: + case SC_NEEDLE_OF_PARALYZE: + case SC_DEEP_SLEEP: case SC_CRYSTALIZE: // Exploit prevention - kRO Fix @@ -6832,7 +6903,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_LEECHESEND: // Ranger Effects - case SC_BITE: + case SC_WUGBITE: case SC_ELECTRICSHOCKER: case SC_MAGNETICFIELD: @@ -6851,35 +6922,35 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val status_change_end(bl, SC_STONE, INVALID_TIMER); } break; - case SC_INCREASEAGI: - status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER); + case SC_INC_AGI: + status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); break; case SC_QUAGMIRE: - status_change_end(bl, SC_CONCENTRATE, INVALID_TIMER); + status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER); status_change_end(bl, SC_WINDWALK, INVALID_TIMER); //Also blocks the ones below... - case SC_DECREASEAGI: + case SC_DEC_AGI: status_change_end(bl, SC_CARTBOOST, INVALID_TIMER); //Also blocks the ones below... case SC_DONTFORGETME: - status_change_end(bl, SC_INCREASEAGI, INVALID_TIMER); + status_change_end(bl, SC_INC_AGI, INVALID_TIMER); status_change_end(bl, SC_ADRENALINE, INVALID_TIMER); status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER); status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_ONEHAND, INVALID_TIMER); - status_change_end(bl, SC_MERC_QUICKEN, INVALID_TIMER); + status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); status_change_end(bl, SC_ACCELERATION, INVALID_TIMER); break; - case SC_ONEHAND: + case SC_ONEHANDQUICKEN: //Removes the Aspd potion effect, as reported by Vicious. [Skotlex] - status_change_end(bl, SC_ASPDPOTION0, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION1, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION3, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); break; - case SC_MAXOVERTHRUST: + case SC_OVERTHRUSTMAX: //Cancels Normal Overthrust. [Skotlex] status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER); break; @@ -6896,18 +6967,18 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val status_change_end(bl, SC_GOSPEL, INVALID_TIMER); break; case SC_HIDING: - status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); - status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); + status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER); + status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); break; case SC__BLOODYLUST: case SC_BERSERK: if(battle_config.berserk_cancels_buffs) { - status_change_end(bl, SC_ONEHAND, INVALID_TIMER); + status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); + status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); status_change_end(bl, SC_PARRYING, INVALID_TIMER); status_change_end(bl, SC_AURABLADE, INVALID_TIMER); - status_change_end(bl, SC_MERC_QUICKEN, INVALID_TIMER); + status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); } #ifdef RENEWAL else { @@ -6923,61 +6994,65 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); break; case SC_CARTBOOST: - if(sc->data[SC_DECREASEAGI]) + if(sc->data[SC_DEC_AGI]) { //Cancel Decrease Agi, but take no further effect [Skotlex] - status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER); + status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); return 0; } break; case SC_FUSION: - status_change_end(bl, SC_SPIRIT, INVALID_TIMER); + status_change_end(bl, SC_SOULLINK, INVALID_TIMER); break; - case SC_ADJUSTMENT: - status_change_end(bl, SC_MADNESSCANCEL, INVALID_TIMER); + case SC_GS_ADJUSTMENT: + status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER); break; - case SC_MADNESSCANCEL: - status_change_end(bl, SC_ADJUSTMENT, INVALID_TIMER); + case SC_GS_MADNESSCANCEL: + status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER); break; //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up - case SC_CHANGEUNDEAD: + case SC_PROPERTYUNDEAD: status_change_end(bl, SC_BLESSING, INVALID_TIMER); - status_change_end(bl, SC_INCREASEAGI, INVALID_TIMER); + status_change_end(bl, SC_INC_AGI, INVALID_TIMER); break; - case SC_STRFOOD: + case SC_FOOD_STR: status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER); break; - case SC_AGIFOOD: + case SC_FOOD_AGI: status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER); break; - case SC_VITFOOD: + case SC_FOOD_VIT: status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER); break; - case SC_INTFOOD: + case SC_FOOD_INT: status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER); break; - case SC_DEXFOOD: + case SC_FOOD_DEX: status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER); break; - case SC_LUKFOOD: + case SC_FOOD_LUK: status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER); break; case SC_FOOD_STR_CASH: - status_change_end(bl, SC_STRFOOD, INVALID_TIMER); + status_change_end(bl, SC_FOOD_STR, INVALID_TIMER); break; case SC_FOOD_AGI_CASH: - status_change_end(bl, SC_AGIFOOD, INVALID_TIMER); + status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER); break; case SC_FOOD_VIT_CASH: - status_change_end(bl, SC_VITFOOD, INVALID_TIMER); + status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER); break; case SC_FOOD_INT_CASH: - status_change_end(bl, SC_INTFOOD, INVALID_TIMER); + status_change_end(bl, SC_FOOD_INT, INVALID_TIMER); break; case SC_FOOD_DEX_CASH: - status_change_end(bl, SC_DEXFOOD, INVALID_TIMER); + status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER); break; case SC_FOOD_LUK_CASH: - status_change_end(bl, SC_LUKFOOD, INVALID_TIMER); + status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); + break; + case SC_ENDURE: + if( val4 ) + status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); break; case SC_FIGHTINGSPIRIT: status_change_end(bl, type, INVALID_TIMER); // Remove previous one. @@ -6985,57 +7060,57 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_MARSHOFABYSS: status_change_end(bl, SC_INCAGI, INVALID_TIMER); status_change_end(bl, SC_WINDWALK, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION0, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION1, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION3, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); break; - case SC_SWINGDANCE: - case SC_SYMPHONYOFLOVER: - case SC_MOONLITSERENADE: - case SC_RUSHWINDMILL: + case SC_SWING: + case SC_SYMPHONY_LOVE: + case SC_MOONLIT_SERENADE: + case SC_RUSH_WINDMILL: case SC_ECHOSONG: case SC_HARMONIZE: //group A doesn't overlap - if (type != SC_SWINGDANCE) status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); - if (type != SC_SYMPHONYOFLOVER) status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); - if (type != SC_MOONLITSERENADE) status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); - if (type != SC_RUSHWINDMILL) status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); + if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER); + if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER); + if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER); + if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER); if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); break; - case SC_VOICEOFSIREN: - case SC_DEEPSLEEP: + case SC_SIREN: + case SC_DEEP_SLEEP: case SC_GLOOMYDAY: - case SC_SONGOFMANA: - case SC_DANCEWITHWUG: - case SC_SATURDAYNIGHTFEVER: - case SC_LERADSDEW: + case SC_SONG_OF_MANA: + case SC_DANCE_WITH_WUG: + case SC_SATURDAY_NIGHT_FEVER: + case SC_LERADS_DEW: case SC_MELODYOFSINK: - case SC_BEYONDOFWARCRY: - case SC_UNLIMITEDHUMMINGVOICE: //group B - if (type != SC_VOICEOFSIREN) status_change_end(bl, SC_VOICEOFSIREN, INVALID_TIMER); - if (type != SC_DEEPSLEEP) status_change_end(bl, SC_DEEPSLEEP, INVALID_TIMER); - if (type != SC_LERADSDEW) status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); + case SC_BEYOND_OF_WARCRY: + case SC_UNLIMITED_HUMMING_VOICE: //group B + if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER); + if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER); + if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER); if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); - if (type != SC_BEYONDOFWARCRY) status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); - if (type != SC_UNLIMITEDHUMMINGVOICE) status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); + if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER); + if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER); if (type != SC_GLOOMYDAY) { status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER); status_change_end(bl, SC_GLOOMYDAY_SK, INVALID_TIMER); } - if (type != SC_SONGOFMANA) status_change_end(bl, SC_SONGOFMANA, INVALID_TIMER); - if (type != SC_DANCEWITHWUG) status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); - if (type != SC_SATURDAYNIGHTFEVER) { - if (sc->data[SC_SATURDAYNIGHTFEVER]) { - sc->data[SC_SATURDAYNIGHTFEVER]->val2 = 0; //mark to not lose hp - status_change_end(bl, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); + if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER); + if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER); + if (type != SC_SATURDAY_NIGHT_FEVER) { + if (sc->data[SC_SATURDAY_NIGHT_FEVER]) { + sc->data[SC_SATURDAY_NIGHT_FEVER]->val2 = 0; //mark to not lose hp + status_change_end(bl, SC_SATURDAY_NIGHT_FEVER, INVALID_TIMER); } } break; case SC_REFLECTSHIELD: - status_change_end(bl, SC_REFLECTDAMAGE, INVALID_TIMER); + status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER); break; - case SC_REFLECTDAMAGE: + case SC_LG_REFLECTDAMAGE: status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); break; case SC_SHIELDSPELL_DEF: @@ -7049,15 +7124,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if( type != SC_SHIELDSPELL_REF ) status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER); break; - case SC_GT_ENERGYGAIN: - case SC_GT_CHANGE: - case SC_GT_REVITALIZE: - if( type != SC_GT_REVITALIZE ) - status_change_end(bl, SC_GT_REVITALIZE, INVALID_TIMER); - if( type != SC_GT_ENERGYGAIN ) - status_change_end(bl, SC_GT_ENERGYGAIN, INVALID_TIMER); - if( type != SC_GT_CHANGE ) - status_change_end(bl, SC_GT_CHANGE, INVALID_TIMER); + case SC_GENTLETOUCH_ENERGYGAIN: + case SC_GENTLETOUCH_CHANGE: + case SC_GENTLETOUCH_REVITALIZE: + if( type != SC_GENTLETOUCH_REVITALIZE ) + status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER); + if( type != SC_GENTLETOUCH_ENERGYGAIN ) + status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER); + if( type != SC_GENTLETOUCH_CHANGE ) + status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER); break; case SC_INVINCIBLE: status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER); @@ -7073,24 +7148,24 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val //Check for overlapping fails if( (sce = sc->data[type]) ) { switch( type ) { - case SC_MERC_FLEEUP: - case SC_MERC_ATKUP: - case SC_MERC_HPUP: - case SC_MERC_SPUP: - case SC_MERC_HITUP: + case SC_MER_FLEE: + case SC_MER_ATK: + case SC_MER_HP: + case SC_MER_SP: + case SC_MER_HIT: if( sce->val1 > val1 ) val1 = sce->val1; break; case SC_ADRENALINE: case SC_ADRENALINE2: - case SC_WEAPONPERFECTION: + case SC_WEAPONPERFECT: case SC_OVERTHRUST: if (sce->val2 > val2) return 0; break; case SC_S_LIFEPOTION: case SC_L_LIFEPOTION: - case SC_BOSSMAPINFO: + case SC_CASH_BOSS_ALARM: case SC_STUN: case SC_SLEEP: case SC_POISON: @@ -7098,13 +7173,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_SILENCE: case SC_CONFUSION: case SC_BLIND: - case SC_BLEEDING: + case SC_BLOODING: case SC_DPOISON: - case SC_CLOSECONFINE2: //Can't be re-closed in. + case SC_RG_CCONFINE_S: //Can't be re-closed in. + case SC_MARIONETTE_MASTER: case SC_MARIONETTE: - case SC_MARIONETTE2: case SC_NOCHAT: - case SC_CHANGE: //Otherwise your Hp/Sp would get refilled while still within effect of the last invocation. + case SC_HLIF_CHANGE: //Otherwise your Hp/Sp would get refilled while still within effect of the last invocation. case SC__INVISIBILITY: case SC__ENERVATION: case SC__GROOMY: @@ -7113,17 +7188,17 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC__WEAKNESS: case SC__UNLUCKY: return 0; - case SC_COMBO: + case SC_COMBOATTACK: case SC_DANCING: case SC_DEVOTION: - case SC_ASPDPOTION0: - case SC_ASPDPOTION1: - case SC_ASPDPOTION2: - case SC_ASPDPOTION3: - case SC_ATKPOTION: - case SC_MATKPOTION: + case SC_ATTHASTE_POTION1: + case SC_ATTHASTE_POTION2: + case SC_ATTHASTE_POTION3: + case SC_ATTHASTE_INFINITY: + case SC_PLUSATTACKPOWER: + case SC_PLUSMAGICPOWER: case SC_ENCHANTARMS: - case SC_ARMOR_ELEMENT: + case SC_ARMORPROPERTY: case SC_ARMOR_RESIST: break; case SC_GOSPEL: @@ -7153,7 +7228,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = sce->val3; val4 = sce->val4; break; - case SC_LERADSDEW: + case SC_LERADS_DEW: if (sc && (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])) return 0; case SC_SHAPESHIFT: @@ -7178,8 +7253,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val calc_flag = StatusChangeFlagTable[type]; if(!(flag&4)) { //&4 - Do not parse val settings when loading SCs switch(type) { - case SC_DECREASEAGI: - case SC_INCREASEAGI: + case SC_DEC_AGI: + case SC_INC_AGI: val2 = 2 + val1; //Agi change break; case SC_ENDURE: @@ -7209,7 +7284,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val sc_start4(bl,SC_PROVOKE,100,10,1,0,0,60000); tick = -1; break; - case SC_SIGNUMCRUCIS: + case SC_CRUCIS: val2 = 10 + 4*val1; //Def reduction tick = -1; clif->emotion(bl,E_SWT); @@ -7220,7 +7295,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_EDP: // [Celest] val2 = val1 + 2; //Chance to Poison enemies. - #ifndef RENEWAL_EDP + #ifdef RENEWAL_EDP + val3 = 50*(val1+3); + val4 = 100 * ((val1 + 1)/2 + 2); + #else val3 = 50*(val1+1); //Damage increase (+50 +50*lv%) #endif if( sd )//[Ind] - iROwiki says each level increases its duration by 3 seconds @@ -7247,18 +7325,18 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2 = 5; //Lasts 5 hits tick = -1; break; - case SC_ENCPOISON: + case SC_ENCHANTPOISON: val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate case SC_ASPERSIO: - case SC_FIREWEAPON: - case SC_WATERWEAPON: - case SC_WINDWEAPON: - case SC_EARTHWEAPON: - case SC_SHADOWWEAPON: - case SC_GHOSTWEAPON: + case SC_PROPERTYFIRE: + case SC_PROPERTYWATER: + case SC_PROPERTYWIND: + case SC_PROPERTYGROUND: + case SC_PROPERTYDARK: + case SC_PROPERTYTELEKINESIS: skill->enchant_elemental_end(bl,type); break; - case SC_ELEMENTALCHANGE: + case SC_ARMOR_PROPERTY: // val1 : Element Lvl (if called by skill lvl 1, takes random value between 1 and 4) // val2 : Element (When no element, random one is picked) // val3 : 0 = called by skill 1 = called by script (fixed level) @@ -7291,19 +7369,19 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } break; - case SC_STRIPWEAPON: + case SC_NOEQUIPWEAPON: if (!sd) //Watk reduction val2 = 25; break; - case SC_STRIPSHIELD: + case SC_NOEQUIPSHIELD: if (!sd) //Def reduction val2 = 15; break; - case SC_STRIPARMOR: + case SC_NOEQUIPARMOR: if (!sd) //Vit reduction val2 = 40; break; - case SC_STRIPHELM: + case SC_NOEQUIPHELM: if (!sd) //Int reduction val2 = 40; break; @@ -7334,7 +7412,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2 = 0; #endif break; - case SC_SUITON: + case SC_NJ_SUITON: if (!val2 || (sd && (sd->class_&MAPID_BASEMASK) == MAPID_NINJA)) { //No penalties. val2 = 0; //Agi penalty @@ -7345,13 +7423,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2 = 3*((val1+1)/3); if (val1 > 4) val2--; break; - case SC_ONEHAND: + case SC_ONEHANDQUICKEN: case SC_TWOHANDQUICKEN: val2 = 300; if (val1 > 10) //For boss casted skills [Skotlex] val2 += 20*(val1-10); break; - case SC_MERC_QUICKEN: + case SC_MER_QUICKEN: val2 = 300; break; #ifndef RENEWAL_ASPD @@ -7365,24 +7443,28 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val //val3 : Brings the skill_lv (merged into val1 here) //val4 : Partner if (val1 == CG_MOONLIT) - clif->status_change(bl,SI_MOONLIT,1,tick,0, 0, 0); + clif->status_change(bl,SI_MOON,1,tick,0, 0, 0); val1|= (val3<<16); val3 = tick/1000; //Tick duration tick_time = 1000; // [GodLesZ] tick time break; case SC_LONGING: + #ifdef RENEWAL + val2 = 50 + 10 * val1; + #else val2 = 500-100*val1; //Aspd penalty. + #endif break; case SC_EXPLOSIONSPIRITS: val2 = 75 + 25*val1; //Cri bonus break; - case SC_ASPDPOTION0: - case SC_ASPDPOTION1: - case SC_ASPDPOTION2: - case SC_ASPDPOTION3: - val2 = 50*(2+type-SC_ASPDPOTION0); - break; + case SC_ATTHASTE_POTION1: + case SC_ATTHASTE_POTION2: + case SC_ATTHASTE_POTION3: + case SC_ATTHASTE_INFINITY: + val2 = 50*(2+type-SC_ATTHASTE_POTION1); + break; case SC_WEDDING: case SC_XMAS: @@ -7407,7 +7489,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = tick/1000; //Petrified HP-damage iterations. if(val3 < 1) val3 = 1; tick = val4; //Petrifying time. - tick = max(tick, 1000); //Min time + if(val4 > 500) // not with WL_SIENNAEXECRATE + tick = max(tick, 1000); //Min time calc_flag = 0; //Actual status changes take effect on petrified state. break; @@ -7439,7 +7522,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_CONFUSION: clif->emotion(bl,E_WHAT); break; - case SC_BLEEDING: + case SC_BLOODING: val4 = tick/10000; if (!val4) val4 = 1; tick_time = 10000; // [GodLesZ] tick time @@ -7455,7 +7538,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val4 = 1; tick_time = val2 * 1000; // [GodLesZ] tick time break; - case SC_BOSSMAPINFO: + case SC_CASH_BOSS_ALARM: if( sd != NULL ) { struct mob_data *boss_md = iMap->getmob_boss(bl->m); // Search for Boss on this Map @@ -7479,7 +7562,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_CHASEWALK: val2 = tick>0?tick:10000; //Interval at which SP is drained. val3 = 35 - 5 * val1; //Speed adjustment. - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE) + if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_ROGUE) val3 -= 40; val4 = 10+val1*2; //SP cost. if (map_flag_gvg(bl->m) || map[bl->m].flag.battleground) val4 *= 5; @@ -7500,24 +7583,24 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_SIGHT: /* splash status */ case SC_RUWACH: - case SC_SIGHTBLASTER: + case SC_WZ_SIGHTBLASTER: val3 = skill->get_splash(val2, val1); //Val2 should bring the skill-id. val2 = tick/250; tick_time = 10; // [GodLesZ] tick time break; //Permanent effects. - case SC_AETERNA: + case SC_LEXAETERNA: case SC_MODECHANGE: - case SC_WEIGHT50: - case SC_WEIGHT90: + case SC_WEIGHTOVER50: + case SC_WEIGHTOVER90: case SC_BROKENWEAPON: case SC_BROKENARMOR: - case SC_READYSTORM: - case SC_READYDOWN: - case SC_READYCOUNTER: - case SC_READYTURN: - case SC_DODGE: + case SC_STORMKICK_READY: + case SC_DOWNKICK_READY: + case SC_COUNTERKICK_READY: + case SC_TURNKICK_READY: + case SC_DODGE_READY: case SC_PUSH_CART: case SC_ALL_RIDING: tick = -1; @@ -7591,7 +7674,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_JOINTBEAT: if( val2&BREAK_NECK ) - sc_start2(bl,SC_BLEEDING,100,val1,val3,skill->get_time2(status_sc2skill(type),val1)); + sc_start2(bl,SC_BLOODING,100,val1,val3,skill->get_time2(status_sc2skill(type),val1)); break; case SC_BERSERK: @@ -7614,7 +7697,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } break; - case SC_MARIONETTE: + case SC_MARIONETTE_MASTER: { int stat; @@ -7628,13 +7711,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val stat = ( sd ? sd->status.luk : status_get_base_status(bl)->luk ) / 2; val4 |= cap_value(stat,0,0xFF); break; } - case SC_MARIONETTE2: + case SC_MARIONETTE: { int stat,max_stat; // fetch caster information struct block_list *pbl = iMap->id2bl(val1); struct status_change *psc = pbl?status_get_sc(pbl):NULL; - struct status_change_entry *psce = psc?psc->data[SC_MARIONETTE]:NULL; + struct status_change_entry *psce = psc?psc->data[SC_MARIONETTE_MASTER]:NULL; // fetch target's stats struct status_data* status = status_get_status_data(bl); // battle status @@ -7652,7 +7735,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - status->luk ); val4 |= cap_value(stat,0,0xFF); break; } - case SC_REJECTSWORD: + case SC_SWORDREJECT: val2 = 15*val1; //Reflect chance val3 = 3; //Reflections tick = -1; @@ -7667,7 +7750,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2 = 50*val1; //aspd reduction break; - case SC_REGENERATION: + case SC_GDSKILL_REGENERATION: if (val1 == 1) val2 = 2; else @@ -7706,18 +7789,18 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val status_zap(bl, status->hp-1, val2?0:status->sp); return 1; break; - case SC_CLOSECONFINE2: + case SC_RG_CCONFINE_S: { struct block_list *src = val2?iMap->id2bl(val2):NULL; struct status_change *sc2 = src?status_get_sc(src):NULL; - struct status_change_entry *sce2 = sc2?sc2->data[SC_CLOSECONFINE]:NULL; + struct status_change_entry *sce2 = sc2?sc2->data[SC_RG_CCONFINE_M]:NULL; if (src && sc2) { if (!sce2) //Start lock on caster. - sc_start4(src,SC_CLOSECONFINE,100,val1,1,0,0,tick+1000); + sc_start4(src,SC_RG_CCONFINE_M,100,val1,1,0,0,tick+1000); else { //Increase count of locked enemies and refresh time. (sce2->val2)++; iTimer->delete_timer(sce2->timer, status_change_timer); - sce2->timer = iTimer->add_timer(iTimer->gettick()+tick+1000, status_change_timer, src->id, SC_CLOSECONFINE); + sce2->timer = iTimer->add_timer(iTimer->gettick()+tick+1000, status_change_timer, src->id, SC_RG_CCONFINE_M); } } else //Status failed. return 0; @@ -7742,7 +7825,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } break; - case SC_COMBO: { + case SC_COMBOATTACK: { //val1: Skill ID //val2: When given, target (for autotargetting skills) //val3: When set, this combo time should NOT delay attack/movement @@ -7780,7 +7863,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if (vd) vd->dead_sit = 1; tick = -1; break; - case SC_CONCENTRATE: + case SC_CONCENTRATION: val2 = 2 + val1; if (sd) { //Store the card-bonus data that should not count in the % val3 = sd->param_bonus[1]; //Agi @@ -7789,7 +7872,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = val4 = 0; } break; - case SC_MAXOVERTHRUST: + case SC_OVERTHRUSTMAX: val2 = 20*val1; //Power increase break; case SC_OVERTHRUST: @@ -7801,14 +7884,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_ADRENALINE2: case SC_ADRENALINE: val3 = (val2) ? 300 : 200; // aspd increase - case SC_WEAPONPERFECTION: + case SC_WEAPONPERFECT: if(sd && pc->checkskill(sd,BS_HILTBINDING)>0) tick += tick / 10; break; - case SC_CONCENTRATION: + case SC_LKCONCENTRATION: val2 = 5*val1; //Batk/Watk Increase val3 = 10*val1; //Hit Increase val4 = 5*val1; //Def reduction + sc_start(bl, SC_ENDURE, 100, 1, tick); //Endure effect break; case SC_ANGELUS: val2 = 5*val1; //def increase @@ -7838,7 +7922,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; // gs_something1 [Vicious] - case SC_GATLINGFEVER: + case SC_GS_GATLINGFEVER: val2 = 20*val1; //Aspd increase val3 = 20+10*val1; //Batk increase val4 = 5*val1; //Flee decrease @@ -7856,18 +7940,18 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = 2+3*val1; //Atk increase val4 = 5+5*val1; //Def reduction. break; - case SC_AVOID: + case SC_HLIF_AVOID: //val2 = 10*val1; //Speed change rate. break; - case SC_DEFENCE: + case SC_HAMI_DEFENCE: val2 = 2*val1; //Def bonus break; - case SC_BLOODLUST: + case SC_HAMI_BLOODLUST: val2 = 20+10*val1; //Atk rate change. val3 = 3*val1; //Leech chance val4 = 20; //Leech percent break; - case SC_FLEET: + case SC_HLIF_FLEET: val2 = 30*val1; //Aspd change val3 = 5+5*val1; //bAtk/wAtk rate change break; @@ -7901,14 +7985,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } } break; - case SC_UTSUSEMI: + case SC_NJ_UTSUSEMI: val2=(val1+1)/2; // number of hits blocked val3=skill->get_blewcount(NJ_UTSUSEMI, val1); //knockback value. break; - case SC_BUNSINJYUTSU: + case SC_NJ_BUNSINJYUTSU: val2=(val1+1)/2; // number of hits blocked break; - case SC_CHANGE: + case SC_HLIF_CHANGE: val2= 30*val1; //Vit increase val3= 20*val1; //Int increase break; @@ -7944,7 +8028,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2 = 20*val1; //Magic reflection/cast rate break; - case SC_ARMORCHANGE: + case SC_STONESKIN: if (val2 == NPC_ANTIMAGIC) { //Boost mdef val2 =-20; @@ -7956,32 +8040,32 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2*=val1; //20% per level val3*=val1; break; - case SC_EXPBOOST: - case SC_JEXPBOOST: + case SC_CASH_PLUSEXP: + case SC_CASH_PLUSONLYJOBEXP: if (val1 < 0) val1 = 0; break; - case SC_INCFLEE2: - case SC_INCCRI: + case SC_PLUSAVOIDVALUE: + case SC_CRITICALPERCENT: val2 = val1*10; //Actual boost (since 100% = 1000) break; case SC_SUFFRAGIUM: val2 = 15 * val1; //Speed cast decrease break; - case SC_INCHEALRATE: + case SC_HEALPLUS: if (val1 < 1) val1 = 1; break; - case SC_HALLUCINATION: + case SC_ILLUSION: val2 = 5+val1; //Factor by which displayed damage is increased by break; - case SC_DOUBLECAST: + case SC_DOUBLECASTING: val2 = 30+10*val1; //Trigger rate break; case SC_KAIZEL: val2 = 10*val1; //% of life to be revived with break; - // case SC_ARMOR_ELEMENT: + // case SC_ARMORPROPERTY: // case SC_ARMOR_RESIST: // Mod your resistance against elements: // val1 = water | val2 = earth | val3 = fire | val4 = wind @@ -7991,13 +8075,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val //associated, and yet are not wrong/unknown. [Skotlex] //break; - case SC_MERC_FLEEUP: - case SC_MERC_ATKUP: - case SC_MERC_HITUP: + case SC_MER_FLEE: + case SC_MER_ATK: + case SC_MER_HIT: val2 = 15 * val1; break; - case SC_MERC_HPUP: - case SC_MERC_SPUP: + case SC_MER_HP: + case SC_MER_SP: val2 = 5 * val1; break; case SC_REBIRTH: @@ -8023,8 +8107,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val tick_time = 1000; // [GodLesZ] tick time break; case SC_BURNING: - val4 = tick / 2000; // Total Ticks to Burn!! - tick_time = 2000; // [GodLesZ] tick time + val4 = tick / 3000; // Total Ticks to Burn!! + tick_time = 3000; // [GodLesZ] tick time break; /** * Rune Knight @@ -8110,24 +8194,27 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_WHITEIMPRISON: status_change_end(bl, SC_BURNING, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); + status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER); status_change_end(bl, SC_FREEZE, INVALID_TIMER); status_change_end(bl, SC_STONE, INVALID_TIMER); break; - case SC_FREEZING: + case SC_MARSHOFABYSS: + val2 = 6 * val1; + if( sd ) // half on players + val2 >>= 1; + break; + case SC_FROSTMISTY: status_change_end(bl, SC_BURNING, INVALID_TIMER); break; case SC_READING_SB: // val2 = sp reduction per second tick_time = 5000; // [GodLesZ] tick time break; - case SC_SPHERE_1: - case SC_SPHERE_2: - case SC_SPHERE_3: - case SC_SPHERE_4: - case SC_SPHERE_5: - if( !sd ) - return 0; // Should only work on players. + case SC_SUMMON1: + case SC_SUMMON2: + case SC_SUMMON3: + case SC_SUMMON4: + case SC_SUMMON5: val4 = tick / 1000; if( val4 < 1 ) val4 = 1; @@ -8168,7 +8255,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val tick_time = 1000; // [GodLesZ] tick time } break; - case SC__STRIPACCESSORY: + case SC__STRIPACCESSARY: if (!sd) val2 = 20; break; @@ -8212,8 +8299,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2 = 10 * val1; val_flag |= 1|2; // bypasses coating protection and MADO - sc_start(bl,SC_STRIPWEAPON,100,val1,tick); - sc_start(bl,SC_STRIPSHIELD,100,val1,tick); + sc_start(bl,SC_NOEQUIPWEAPON,100,val1,tick); + sc_start(bl,SC_NOEQUIPSHIELD,100,val1,tick); break; break; case SC_GN_CARTBOOST: @@ -8230,7 +8317,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_WARMER: status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); + status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER); status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); break; case SC_STRIKING: @@ -8238,36 +8325,42 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val4 = tick / 1000; tick_time = 1000; // [GodLesZ] tick time break; - case SC_BLOODSUCKER: - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time + case SC_BLOOD_SUCKER: + { + struct block_list *src = iMap->id2bl(sce->val2); + val3 = 1; + if(src) + val3 = 200 + 100 * sce->val1 + status_get_int(src); + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + } break; case SC_VACUUM_EXTREME: tick -= (status->str / 20) * 1000; val4 = val3 = tick / 100; tick_time = 100; // [GodLesZ] tick time break; - case SC_SWINGDANCE: + case SC_SWING: val2 = 4 * val1; // Walk speed and aspd reduction. break; - case SC_SYMPHONYOFLOVER: - case SC_RUSHWINDMILL: + case SC_SYMPHONY_LOVE: + case SC_RUSH_WINDMILL: case SC_ECHOSONG: val2 = 6 * val1; val2 += val3; //Adding 1% * Lesson Bonus val2 += (int)(val4*2/10); //Adding 0.2% per JobLevel break; - case SC_MOONLITSERENADE: + case SC_MOONLIT_SERENADE: val2 = 10 * val1; break; case SC_HARMONIZE: val2 = 5 + 5 * val1; break; - case SC_VOICEOFSIREN: + case SC_SIREN: val4 = tick / 2000; tick_time = 2000; // [GodLesZ] tick time break; - case SC_DEEPSLEEP: + case SC_DEEP_SLEEP: val4 = tick / 2000; tick_time = 2000; // [GodLesZ] tick time break; @@ -8277,12 +8370,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val4 = tick / 1000; tick_time = 1000; // [GodLesZ] tick time break; - case SC_SONGOFMANA: + case SC_SONG_OF_MANA: val3 = 10 + (2 * val2); val4 = tick/3000; tick_time = 3000; // [GodLesZ] tick time break; - case SC_SATURDAYNIGHTFEVER: + case SC_SATURDAY_NIGHT_FEVER: if (!val4) val4 = skill->get_time2(status_sc2skill(type),val1); if (!val4) val4 = 3000; val3 = tick/val4; @@ -8302,7 +8395,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val2 = 15 + rand()%( (sd?pc->checkskill(sd, WM_LESSON)*5:0) + val1*10 ); break; case SC_SITDOWN_FORCE: - case SC_BANANA_BOMB_SITDOWN: + case SC_BANANA_BOMB_SITDOWN_POSTDELAY: if( sd && !pc_issit(sd) ) { pc_setsit(sd); @@ -8310,19 +8403,19 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val clif->sitting(bl); } break; - case SC_DANCEWITHWUG: + case SC_DANCE_WITH_WUG: val3 = (5 * val1) + (1 * val2); //Still need official value. break; - case SC_LERADSDEW: + case SC_LERADS_DEW: val3 = (5 * val1) + (1 * val2); break; case SC_MELODYOFSINK: val3 = (5 * val1) + (1 * val2); break; - case SC_BEYONDOFWARCRY: + case SC_BEYOND_OF_WARCRY: val3 = (5 * val1) + (1 * val2); break; - case SC_UNLIMITEDHUMMINGVOICE: + case SC_UNLIMITED_HUMMING_VOICE: { struct unit_data *ud = unit_bl2ud(bl); if( ud == NULL ) return 0; @@ -8330,7 +8423,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = 15 - (2 * val2); } break; - case SC_REFLECTDAMAGE: + case SC_LG_REFLECTDAMAGE: val2 = 15 + 5 * val1; val3 = (val1==5)?20:(val1+4)*2; // SP consumption val4 = tick/10000; @@ -8398,15 +8491,17 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = tick / 5000; tick_time = 5000; // [GodLesZ] tick time break; - case SC_GT_CHANGE: + case SC_GENTLETOUCH_CHANGE: {// take note there is no def increase as skill desc says. [malufett] struct block_list * src; val3 = status->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] % - if( (src = iMap->id2bl(val2)) ) + if( (src = iMap->id2bl(val2)) ){ val4 = ( 200/status_get_int(src) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] + val2 = ( status_get_dex(src)/4 + status_get_str(src)/2 ) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5] + } } break; - case SC_GT_REVITALIZE: + case SC_GENTLETOUCH_REVITALIZE: {// take note there is no vit,aspd,speed increase as skill desc says. [malufett] struct block_list * src; val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] % @@ -8519,8 +8614,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val tick_time = 10000; // [GodLesZ] tick time break; case SC_KYOUGAKU: - val2 = 2*val1 + rand()%val1; - clif->status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); + val2 = 2*val1 + rand()%(3 * val1); + clif->status_change(bl, SI_ACTIVE_MONSTER_TRANSFORM, 1, 0, 1002, 0, 0); // Poring in disguise break; case SC_KAGEMUSYA: val3 = val1 * 2; @@ -8529,80 +8624,100 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val tick_time = 1000; break; case SC_ZANGETSU: - if( (status_get_hp(bl)+status_get_sp(bl)) % 2 == 0) - val2 = status_get_lv(bl) / 2 + 50; - else - val2 -= 50; + val2 = status_get_lv(bl) / 3 + 20 * val1; + val3 = status_get_lv(bl) / 2 + 30 * val1; + val2 = (!(status_get_hp(bl)%2) ? val2 : -val3); + val3 = (!(status_get_sp(bl)%2) ? val2 : -val3); break; case SC_GENSOU: { - int hp = status_get_hp(bl), lv = 5; - short per = 100 / (status_get_max_hp(bl) / hp); - - if( per <= 15 ) - lv = 1; - else if( per <= 30 ) - lv = 2; - else if( per <= 50 ) - lv = 3; - else if( per <= 75 ) - lv = 4; - if( hp % 2 == 0) - status_heal(bl, hp * (6-lv) * 4 / 100, status_get_sp(bl) * (6-lv) * 3 / 100, 1); - else - status_zap(bl, hp * (lv*4) / 100, status_get_sp(bl) * (lv*3) / 100); + int hp = status_get_hp(bl), sp = status_get_sp(bl), lv = 5; + #define PER( a ) { if( a <= 15 )lv = 1;else if( a <= 30 )lv = 2;else if( a <= 50 )lv = 3;else if( a <= 75 )lv = 4;} + + if( rand()%100 > (25 + 10 * val1) - status_get_int(bl) / 2) + return 0; + + PER( 100 / (status_get_max_hp(bl) / hp) ); + status_heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, 1); + + PER( 100 / (status_get_max_sp(bl) / sp) ); + status_heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), 1); } break; - case SC_ANGRIFFS_MODUS: - val2 = 50 + 20 * val1; //atk bonus - val3 = 40 + 20 * val1; // Flee reduction. - val4 = tick/1000; // hp/sp reduction timer - tick_time = 1000; - break; - case SC_NEUTRALBARRIER: - tick_time = tick; - tick = -1; - break; - case SC_GOLDENE_FERSE: - val2 = 10 + 10*val1; //max hp bonus - val3 = 6 + 4 * val1; // Aspd Bonus - val4 = 2 + 2 * val1; // Chance of holy attack - break; - case SC_OVERED_BOOST: - val2 = 300 + 40*val1; //flee bonus - val3 = 179 + 2*val1; //aspd bonus - break; - case SC_GRANITIC_ARMOR: - val2 = 2*val1; //dmg reduction - val3 = 6*val1; //dmg on status end - break; - case SC_MAGMA_FLOW: - val2 = 3*val1; //activation chance - break; - case SC_PYROCLASTIC: - val2 += 10*val1; //atk bonus - break; - case SC_PARALYSIS: //[Lighta] need real info - val2 = 2*val1; //def reduction - val3 = 500*val1; //varcast augmentation - break; - case SC_PAIN_KILLER: //[Lighta] need real info - val2 = 2*val1; //aspd reduction % - val3 = 2*val1; //dmg reduction % - if(sc->data[SC_PARALYSIS]) - sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration - break; - case SC_STYLE_CHANGE: //[Lighta] need real info - tick = -1; - if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING; - else val2 = MH_MD_FIGHTING; - break; - default: - if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 ) - { //Status change with no calc, no icon, and no skill associated...? - ShowError("UnknownStatusChange [%d]\n", type); - return 0; - } + case SC_ANGRIFFS_MODUS: + val2 = 50 + 20 * val1; //atk bonus + val3 = 40 + 20 * val1; // Flee reduction. + val4 = tick/1000; // hp/sp reduction timer + tick_time = 1000; + break; + case SC_NEUTRALBARRIER: + tick_time = tick; + tick = -1; + break; + case SC_GOLDENE_FERSE: + val2 = 10 + 10*val1; //max hp bonus + val3 = 6 + 4 * val1; // Aspd Bonus + val4 = 2 + 2 * val1; // Chance of holy attack + break; + case SC_OVERED_BOOST: + val2 = 300 + 40*val1; //flee bonus + val3 = 179 + 2*val1; //aspd bonus + break; + case SC_GRANITIC_ARMOR: + val2 = 2*val1; //dmg reduction + val3 = 6*val1; //dmg on status end + break; + case SC_MAGMA_FLOW: + val2 = 3*val1; //activation chance + break; + case SC_PYROCLASTIC: + val2 += 10*val1; //atk bonus + break; + case SC_NEEDLE_OF_PARALYZE: //[Lighta] need real info + val2 = 2*val1; //def reduction + val3 = 500*val1; //varcast augmentation + break; + case SC_PAIN_KILLER: //[Lighta] need real info + val2 = 2*val1; //aspd reduction % + val3 = 2*val1; //dmg reduction % + if(sc->data[SC_NEEDLE_OF_PARALYZE]) + sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration + break; + case SC_STYLE_CHANGE: //[Lighta] need real info + tick = -1; + if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING; + else val2 = MH_MD_FIGHTING; + break; + case SC_FULL_THROTTLE: + status_percent_heal(bl,100,0); + val2 = 7 - val1; + tick_time = 1000; + val4 = tick / tick_time; + break; + case SC_KINGS_GRACE: + val2 = 3 + val1; + tick_time = 1000; + val4 = tick / tick_time; + break; + case SC_TELEKINESIS_INTENSE: + val2 = 10 * val1; + val3 = 40 * val1; + break; + case SC_OFFERTORIUM: + val2 = 30 * val1; + break; + case SC_FRIGG_SONG: + val2 = 5 * val1; + val3 = 1000 + 100 * val1; + tick_time = 10000; + val4 = tick / tick_time; + break; + default: + if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 ) + { //Status change with no calc, no icon, and no skill associated...? + ShowError("UnknownStatusChange [%d]\n", type); + return 0; + } } } else { //Special considerations when loading SC data. switch( type ) { @@ -8619,6 +8734,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_KAAHI: val4 = INVALID_TIMER; break; + case SC_SUMMON1: + case SC_SUMMON2: + case SC_SUMMON3: + case SC_SUMMON4: + case SC_SUMMON5: + val_flag |= 1; + break; } } @@ -8642,7 +8764,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_STUN: case SC_SLEEP: case SC_STONE: - case SC_DEEPSLEEP: + case SC_DEEP_SLEEP: if (sd && pc_issit(sd)) //Avoid sprite sync problems. pc->setstand(sd); case SC_TRICKDEAD: @@ -8654,12 +8776,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val unit_stop_attack(bl); case SC_STOP: case SC_CONFUSION: - case SC_CLOSECONFINE: - case SC_CLOSECONFINE2: + case SC_RG_CCONFINE_M: + case SC_RG_CCONFINE_S: case SC_SPIDERWEB: case SC_ELECTRICSHOCKER: - case SC_BITE: - case SC_THORNSTRAP: + case SC_WUGBITE: + case SC_THORNS_TRAP: case SC__MANHOLE: case SC_CRYSTALIZE: case SC_CURSEDCIRCLE_ATKER: @@ -8668,10 +8790,11 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_NETHERWORLD: case SC_MEIKYOUSISUI: case SC_KYOUGAKU: - case SC_PARALYSIS: + case SC_NEEDLE_OF_PARALYZE: + case SC_DEATHBOUND: unit_stop_walking(bl,1); break; - case SC_ANKLE: + case SC_ANKLESNARE: if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) ) unit_stop_walking(bl,1); break; @@ -8679,9 +8802,9 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_CLOAKING: case SC_CLOAKINGEXCEED: case SC_CHASEWALK: - case SC_WEIGHT90: + case SC_WEIGHTOVER90: case SC_CAMOUFLAGE: - case SC_VOICEOFSIREN: + case SC_SIREN: unit_stop_attack(bl); break; case SC_SILENCE: @@ -8697,7 +8820,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break; case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break; case SC_STUN: sc->opt1 = OPT1_STUN; break; - case SC_DEEPSLEEP: opt_flag = 0; + case SC_DEEP_SLEEP: opt_flag = 0; case SC_SLEEP: sc->opt1 = OPT1_SLEEP; break; case SC_BURNING: sc->opt1 = OPT1_BURNING; break; // Burning need this to be showed correctly. [pakpil] case SC_WHITEIMPRISON: sc->opt1 = OPT1_IMPRISON; break; @@ -8707,24 +8830,24 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_CURSE: sc->opt2 |= OPT2_CURSE; break; case SC_SILENCE: sc->opt2 |= OPT2_SILENCE; break; - case SC_SIGNUMCRUCIS: + case SC_CRUCIS: sc->opt2 |= OPT2_SIGNUMCRUCIS; break; case SC_BLIND: sc->opt2 |= OPT2_BLIND; break; case SC_ANGELUS: sc->opt2 |= OPT2_ANGELUS; break; - case SC_BLEEDING: sc->opt2 |= OPT2_BLEEDING; break; + case SC_BLOODING: sc->opt2 |= OPT2_BLEEDING; break; case SC_DPOISON: sc->opt2 |= OPT2_DPOISON; break; //OPT3 case SC_TWOHANDQUICKEN: - case SC_ONEHAND: + case SC_ONEHANDQUICKEN: case SC_SPEARQUICKEN: - case SC_CONCENTRATION: - case SC_MERC_QUICKEN: + case SC_LKCONCENTRATION: + case SC_MER_QUICKEN: sc->opt3 |= OPT3_QUICKEN; opt_flag = 0; break; - case SC_MAXOVERTHRUST: + case SC_OVERTHRUSTMAX: case SC_OVERTHRUST: case SC_SWOO: //Why does it shares the same opt as Overthrust? Perhaps we'll never know... sc->opt3 |= OPT3_OVERTHRUST; @@ -8772,8 +8895,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val sc->opt3 |= OPT3_MOONLIT; opt_flag = 0; break; + case SC_MARIONETTE_MASTER: case SC_MARIONETTE: - case SC_MARIONETTE2: sc->opt3 |= OPT3_MARIONETTE; opt_flag = 0; break; @@ -8789,15 +8912,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val sc->opt3 |= OPT3_KAITE; opt_flag = 0; break; - case SC_BUNSINJYUTSU: + case SC_NJ_BUNSINJYUTSU: sc->opt3 |= OPT3_BUNSIN; opt_flag = 0; break; - case SC_SPIRIT: + case SC_SOULLINK: sc->opt3 |= OPT3_SOULLINK; opt_flag = 0; break; - case SC_CHANGEUNDEAD: + case SC_PROPERTYUNDEAD: sc->opt3 |= OPT3_UNDEAD; opt_flag = 0; break; @@ -8911,7 +9034,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } sce->val2 = 5 * status->max_hp / 100; break; - case SC_CHANGE: + case SC_HLIF_CHANGE: status_percent_heal(bl, 100, 100); break; case SC_RUN: @@ -8921,13 +9044,13 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val ud->state.running = unit_run(bl); } break; - case SC_BOSSMAPINFO: + case SC_CASH_BOSS_ALARM: clif->bossmapinfo(sd->fd, iMap->id2boss(sce->val1), 0); // First Message break; - case SC_MERC_HPUP: + case SC_MER_HP: status_percent_heal(bl, 100, 0); // Recover Full HP break; - case SC_MERC_SPUP: + case SC_MER_SP: status_percent_heal(bl, 0, 100); // Recover Full SP break; /** @@ -8940,7 +9063,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val ud->state.running = unit_wugdash(bl, sd); } break; - case SC_COMBO: + case SC_COMBOATTACK: switch (sce->val1) { case TK_STORMKICK: clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1); @@ -9008,68 +9131,25 @@ int status_change_clear(struct block_list* bl, int type) { for(i = 0; i < SC_MAX; i++) { if(!sc->data[i]) continue; - - if(type == 0) { - switch (i) { //Type 0: PC killed -> Place here statuses that do not dispel on death. - case SC_ELEMENTALCHANGE://Only when its Holy or Dark that it doesn't dispell on death - if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK ) - break; - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_EDP: - case SC_MELTDOWN: - case SC_XMAS: - case SC_SUMMER: - case SC_HANBOK: - case SC_NOCHAT: - case SC_FUSION: - case SC_EARTHSCROLL: - case SC_READYSTORM: - case SC_READYDOWN: - case SC_READYCOUNTER: - case SC_READYTURN: - case SC_DODGE: - case SC_JAILED: - case SC_EXPBOOST: - case SC_ITEMBOOST: - case SC_HELLPOWER: - case SC_JEXPBOOST: - case SC_AUTOTRADE: - case SC_WHISTLE: - case SC_ASSNCROS: - case SC_POEMBRAGI: - case SC_APPLEIDUN: - case SC_HUMMING: - case SC_DONTFORGETME: - case SC_FORTUNE: - case SC_SERVICE4U: - case SC_FOOD_STR_CASH: - case SC_FOOD_AGI_CASH: - case SC_FOOD_VIT_CASH: - case SC_FOOD_DEX_CASH: - case SC_FOOD_INT_CASH: - case SC_FOOD_LUK_CASH: - case SC_DEF_RATE: - case SC_MDEF_RATE: - case SC_INCHEALRATE: - case SC_INCFLEE2: - case SC_INCHIT: - case SC_ATKPOTION: - case SC_MATKPOTION: - case SC_S_LIFEPOTION: - case SC_L_LIFEPOTION: - case SC_PUSH_CART: - case SC_ALL_RIDING: - continue; + + if(type == 0){ + if( status_get_sc_type(i)&SC_NO_REM_DEATH ){ + switch (i) { + case SC_ARMOR_PROPERTY://Only when its Holy or Dark that it doesn't dispell on death + if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK ) + break; + default: + continue; + } } } - if( type == 3 ) { switch (i) {// TODO: This list may be incomplete - case SC_WEIGHT50: - case SC_WEIGHT90: + case SC_WEIGHTOVER50: + case SC_WEIGHTOVER90: case SC_NOCHAT: case SC_PUSH_CART: + case SC_JAILED: case SC_ALL_RIDING: continue; } @@ -9094,6 +9174,7 @@ int status_change_clear(struct block_list* bl, int type) { #ifndef RENEWAL sc->sg_counter = 0; #endif + if( type == 0 || type == 2 ) clif->changeoption(bl); @@ -9188,7 +9269,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const DIFF_TICK(iTimer->gettick(), sce->val4) <= 1000 && (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0)) ) - sc_start(bl,SC_SPURT,100,sce->val1,skill->get_time2(status_sc2skill(type), sce->val1)); + sc_start(bl,SC_STRUP,100,sce->val1,skill->get_time2(status_sc2skill(type), sce->val1)); } break; case SC_AUTOBERSERK: @@ -9307,7 +9388,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } if((sce->val1&0xFFFF) == CG_MOONLIT) - clif->sc_end(bl,bl->id,AREA,SI_MOONLIT); + clif->sc_end(bl,bl->id,AREA,SI_MOON); status_change_end(bl, SC_LONGING, INVALID_TIMER); } @@ -9328,18 +9409,18 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const skill->castend_damage_id(src, bl, sce->val2, sce->val1, iTimer->gettick(), SD_LEVEL ); } break; - case SC_CLOSECONFINE2: + case SC_RG_CCONFINE_S: { struct block_list *src = sce->val2?iMap->id2bl(sce->val2):NULL; struct status_change *sc2 = src?status_get_sc(src):NULL; - if (src && sc2 && sc2->data[SC_CLOSECONFINE]) { + if (src && sc2 && sc2->data[SC_RG_CCONFINE_M]) { //If status was already ended, do nothing. //Decrease count - if (--(sc2->data[SC_CLOSECONFINE]->val1) <= 0) //No more holds, free him up. - status_change_end(src, SC_CLOSECONFINE, INVALID_TIMER); + if (--(sc2->data[SC_RG_CCONFINE_M]->val1) <= 0) //No more holds, free him up. + status_change_end(src, SC_RG_CCONFINE_M, INVALID_TIMER); } } - case SC_CLOSECONFINE: + case SC_RG_CCONFINE_M: if (sce->val2 > 0) { //Caster has been unlocked... nearby chars need to be unlocked. int range = 1 @@ -9349,7 +9430,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sce,type,iTimer->gettick()); } break; - case SC_COMBO: + case SC_COMBOATTACK: if( sd ) switch (sce->val1) { case MO_COMBOFINISH: @@ -9371,11 +9452,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } break; - case SC_MARIONETTE: - case SC_MARIONETTE2: /// Marionette target + case SC_MARIONETTE_MASTER: + case SC_MARIONETTE: /// Marionette target if (sce->val1) { // check for partner and end their marionette status as well - enum sc_type type2 = (type == SC_MARIONETTE) ? SC_MARIONETTE2 : SC_MARIONETTE; + enum sc_type type2 = (type == SC_MARIONETTE_MASTER) ? SC_MARIONETTE : SC_MARIONETTE_MASTER; struct block_list *pbl = iMap->id2bl(sce->val1); struct status_change* sc2 = pbl?status_get_sc(pbl):NULL; @@ -9388,7 +9469,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const break; case SC_BERSERK: - case SC_SATURDAYNIGHTFEVER: + case SC_SATURDAY_NIGHT_FEVER: //If val2 is removed, no HP penalty (dispelled?) [Skotlex] if (status->hp > 100 && sce->val2) status_set_hp(bl, 100, 0); @@ -9398,8 +9479,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const status_change_end(bl, SC_ENDURE, INVALID_TIMER); } case SC__BLOODYLUST: - sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill->get_time(LK_BERSERK, sce->val1)); - if( type == SC_SATURDAYNIGHTFEVER ) //Sit down force of Saturday Night Fever has the duration of only 3 seconds. + sc_start4(bl, SC_GDSKILL_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill->get_time(LK_BERSERK, sce->val1)); + if( type == SC_SATURDAY_NIGHT_FEVER ) //Sit down force of Saturday Night Fever has the duration of only 3 seconds. sc_start(bl,SC_SITDOWN_FORCE,100,sce->val1,skill->get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1)); break; case SC_GOSPEL: @@ -9440,7 +9521,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if(sd && sd->mapindex == sce->val2) pc->setpos(sd,(unsigned short)sce->val3,sce->val4&0xFFFF, sce->val4>>16, CLR_TELEPORT); break; //guess hes not in jail :P - case SC_CHANGE: + case SC_HLIF_CHANGE: if (tid == INVALID_TIMER) break; // "lose almost all their HP and SP" on natural expiration. @@ -9466,6 +9547,9 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const status_change_end(tbl, SC_STOP, INVALID_TIMER); } break; + case SC_LKCONCENTRATION: + status_change_end(bl, SC_ENDURE, INVALID_TIMER); + break; /** * 3rd Stuff **/ @@ -9552,7 +9636,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } } break; - case SC_BLOODSUCKER: + case SC_BLOOD_SUCKER: if( sce->val2 ){ struct block_list *src = iMap->id2bl(sce->val2); if(src){ @@ -9565,10 +9649,13 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_KYOUGAKU); clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_ACTIVE_MONSTER_TRANSFORM); break; - case SC_INTRAVISION: + case SC_CLAIRVOYANCE: calc_flag = SCB_ALL;/* required for overlapping */ break; - } + case SC_FULL_THROTTLE: + sc_start(bl,SC_REBOUND,100,sce->val1,skill->get_time2(ALL_FULL_THROTTLE,sce->val1)); + break; + } opt_flag = 1; switch(type){ @@ -9576,7 +9663,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const case SC_FREEZE: case SC_STUN: case SC_SLEEP: - case SC_DEEPSLEEP: + case SC_DEEP_SLEEP: case SC_BURNING: case SC_WHITEIMPRISON: case SC_CRYSTALIZE: @@ -9592,7 +9679,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const case SC_DPOISON: sc->opt2 &= ~OPT2_DPOISON; break; - case SC_SIGNUMCRUCIS: + case SC_CRUCIS: sc->opt2 &= ~OPT2_SIGNUMCRUCIS; break; @@ -9641,15 +9728,15 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const break; //opt3 case SC_TWOHANDQUICKEN: - case SC_ONEHAND: + case SC_ONEHANDQUICKEN: case SC_SPEARQUICKEN: case SC_CONCENTRATION: - case SC_MERC_QUICKEN: + case SC_MER_QUICKEN: sc->opt3 &= ~OPT3_QUICKEN; opt_flag = 0; break; case SC_OVERTHRUST: - case SC_MAXOVERTHRUST: + case SC_OVERTHRUSTMAX: case SC_SWOO: sc->opt3 &= ~OPT3_OVERTHRUST; if( type == SC_SWOO ) @@ -9700,7 +9787,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const opt_flag = 0; break; case SC_MARIONETTE: - case SC_MARIONETTE2: + case SC_MARIONETTE_MASTER: sc->opt3 &= ~OPT3_MARIONETTE; opt_flag = 0; break; @@ -9716,15 +9803,15 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const sc->opt3 &= ~OPT3_KAITE; opt_flag = 0; break; - case SC_BUNSINJYUTSU: + case SC_NJ_BUNSINJYUTSU: sc->opt3 &= ~OPT3_BUNSIN; opt_flag = 0; break; - case SC_SPIRIT: + case SC_SOULLINK: sc->opt3 &= ~OPT3_SOULLINK; opt_flag = 0; break; - case SC_CHANGEUNDEAD: + case SC_PROPERTYUNDEAD: sc->opt3 &= ~OPT3_UNDEAD; opt_flag = 0; break; @@ -9861,9 +9948,9 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) if(!status_charge(bl, 0, sce->val4)) break; //Not enough SP to continue. - if (!sc->data[SC_INCSTR]) { - sc_start(bl, SC_INCSTR,100,1<<(sce->val1-1), - (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration + if (!sc->data[SC_CHASEWALK2]) { + sc_start(bl, SC_CHASEWALK2,100,1<<(sce->val1-1), + (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration *skill->get_time2(status_sc2skill(type),sce->val1)); } sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data); @@ -9891,8 +9978,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) case SC_SIGHT: case SC_RUWACH: - case SC_SIGHTBLASTER: - if(type == SC_SIGHTBLASTER) + case SC_WZ_SIGHTBLASTER: + if(type == SC_WZ_SIGHTBLASTER) iMap->foreachinrange( status_change_timer_sub, bl, sce->val3, BL_CHAR|BL_SKILL, bl, sce, type, tick); else iMap->foreachinrange( status_change_timer_sub, bl, sce->val3, BL_CHAR, bl, sce, type, tick); @@ -9970,7 +10057,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } break; - case SC_BLEEDING: + case SC_BLOODING: if (--(sce->val4) >= 0) { int hp = rnd()%600 + 200; struct block_list* src = iMap->id2bl(sce->val2); @@ -10005,7 +10092,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } break; - case SC_BOSSMAPINFO: + case SC_CASH_BOSS_ALARM: if( sd && --(sce->val4) >= 0 ) { struct mob_data *boss_md = iMap->id2boss(sce->val1); @@ -10112,8 +10199,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } break; + case SC_MARIONETTE_MASTER: case SC_MARIONETTE: - case SC_MARIONETTE2: { struct block_list *pbl = iMap->id2bl(sce->val1); if( pbl && check_distance_bl(bl, pbl, 7) ) @@ -10160,7 +10247,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_PYREXIA: - if( --(sce->val4) >= 0 ) { + if( --(sce->val4) > 0 ) { iMap->freeblock_lock(); clif->damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,0,0); status_fix_damage(NULL,bl,100,0); @@ -10173,7 +10260,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_LEECHESEND: - if( --(sce->val4) >= 0 ) { + if( --(sce->val4) > 0 ) { int damage = status->max_hp/100; // {Target VIT x (New Poison Research Skill Level - 3)} + (Target HP/100) damage += status->vit * (sce->val1 - 3); unit_skillcastcancel(bl,2); @@ -10188,7 +10275,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_MAGICMUSHROOM: - if( --(sce->val4) >= 0 ) { + if( --(sce->val4) > 0 ) { bool flag = 0; int damage = status->max_hp * 3 / 100; if( status->hp <= damage ) @@ -10233,7 +10320,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_TOXIN: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { //Damage is every 10 seconds including 3%sp drain. iMap->freeblock_lock(); clif->damage(bl,bl,tick,status_get_amotion(bl),1,1,0,0,0); @@ -10247,7 +10334,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_OBLIVIONCURSE: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { clif->emotion(bl,E_WHAT); sc_timer_next(3000 + tick, status_change_timer, bl->id, data ); @@ -10256,7 +10343,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_WEAPONBLOCKING: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { if( !status_charge(bl,0,3) ) break; @@ -10272,7 +10359,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) return 0; case SC_RENOVATIO: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { int heal = status->max_hp * 3 / 100; if( sc && sc->data[SC_AKAITSUKI] && heal ) @@ -10284,7 +10371,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_BURNING: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { struct block_list *src = iMap->id2bl(sce->val3); int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP) @@ -10294,7 +10381,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) status_damage(src, bl, damage, 0, 0, 1); if( sc->data[type]){ // Target still lives. [LimitLine] - sc_timer_next(2000 + tick, status_change_timer, bl->id, data); + sc_timer_next(3000 + tick, status_change_timer, bl->id, data); } iMap->freeblock_unlock(); return 0; @@ -10302,7 +10389,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_FEAR: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { if( sce->val2 > 0 ) sce->val2--; @@ -10311,12 +10398,12 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } break; - case SC_SPHERE_1: - case SC_SPHERE_2: - case SC_SPHERE_3: - case SC_SPHERE_4: - case SC_SPHERE_5: - if( --(sce->val4) >= 0 ) + case SC_SUMMON1: + case SC_SUMMON2: + case SC_SUMMON3: + case SC_SUMMON4: + case SC_SUMMON5: + if( --(sce->val4) > 0 ) { if( !status_charge(bl, 0, 1) ) break; @@ -10328,7 +10415,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) case SC_READING_SB: if( !status_charge(bl, 0, sce->val2) ){ int i; - for(i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) // Also remove stored spell as well. + for(i = SC_SPELLBOOK1; i <= SC_SPELLBOOK7; i++) // Also remove stored spell as well. status_change_end(bl, (sc_type)i, INVALID_TIMER); break; } @@ -10336,7 +10423,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) return 0; case SC_ELECTRICSHOCKER: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { status_charge(bl, 0, status->max_sp / 100 * sce->val1 ); sc_timer_next(1000 + tick, status_change_timer, bl->id, data); @@ -10359,7 +10446,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) return 0; case SC__SHADOWFORM: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { if( !status_charge(bl, 0, sce->val1 - (sce->val1 - 1)) ) break; @@ -10369,7 +10456,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC__INVISIBILITY: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { if( !status_charge(bl, 0, (status->sp * 6 - sce->val1) / 100) )// 6% - skill_lv. break; @@ -10379,7 +10466,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_STRIKING: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { if( !status_charge(bl,0, sce->val1 ) ) break; @@ -10388,19 +10475,19 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } break; case SC_VACUUM_EXTREME: - if( --(sce->val4) >= 0 ){ + if( --(sce->val4) > 0 ){ sc_timer_next(100 + tick, status_change_timer, bl->id, data); return 0; } break; - case SC_BLOODSUCKER: - if( --(sce->val4) >= 0 ) { + case SC_BLOOD_SUCKER: + if( --(sce->val4) > 0 ) { struct block_list *src = iMap->id2bl(sce->val2); int damage; if( !src || (src && (status_isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12)) ) break; iMap->freeblock_lock(); - damage = 200 + 100 * sce->val1 + status_get_int(src); + damage = sce->val3; status_damage(src, bl, damage, 0, clif->damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,0,0), 1); unit_skillcastcancel(bl,1); if ( sc->data[type] ) { @@ -10412,8 +10499,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } break; - case SC_VOICEOFSIREN: - if( --(sce->val4) >= 0 ) + case SC_SIREN: + if( --(sce->val4) > 0 ) { clif->emotion(bl,E_LV); sc_timer_next(2000 + tick, status_change_timer, bl->id, data); @@ -10421,8 +10508,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } break; - case SC_DEEPSLEEP: - if( --(sce->val4) >= 0 ) + case SC_DEEP_SLEEP: + if( --(sce->val4) > 0 ) { // Recovers 1% HP/SP every 2 seconds. status_heal(bl, status->max_hp / 100, status->max_sp / 100, 2); sc_timer_next(2000 + tick, status_change_timer, bl->id, data); @@ -10431,7 +10518,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_SIRCLEOFNATURE: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { if( !status_charge(bl,0,sce->val2) ) break; @@ -10441,8 +10528,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } break; - case SC_SONGOFMANA: - if( --(sce->val4) >= 0 ) + case SC_SONG_OF_MANA: + if( --(sce->val4) > 0 ) { status_heal(bl,0,sce->val3,3); sc_timer_next(3000 + tick, status_change_timer, bl->id, data); @@ -10451,9 +10538,9 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; - case SC_SATURDAYNIGHTFEVER: + case SC_SATURDAY_NIGHT_FEVER: // 1% HP/SP drain every val4 seconds [Jobbie] - if( --(sce->val3) >= 0 ) + if( --(sce->val3) > 0 ) { int hp = status->hp / 100; int sp = status->sp / 100; @@ -10465,7 +10552,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_CRYSTALIZE: - if( --(sce->val4) >= 0 ) + if( --(sce->val4) > 0 ) { // Drains 2% of HP and 1% of SP every seconds. if( bl->type != BL_MOB) // doesn't work on mobs status_charge(bl, status->max_hp * 2 / 100, status->max_sp / 100); @@ -10489,8 +10576,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } break; - case SC_REFLECTDAMAGE: - if( --(sce->val4) >= 0 ) { + case SC_LG_REFLECTDAMAGE: + if( --(sce->val4) > 0 ) { if( !status_charge(bl,0,sce->val3) ) break; sc_timer_next(10000 + tick, status_change_timer, bl->id, data); @@ -10538,7 +10625,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_INSPIRATION: - if(--(sce->val4) >= 0) + if(--(sce->val4) > 0) { int hp = status->max_hp * (7-sce->val1) / 100; int sp = status->max_sp * (9-sce->val1) / 100; @@ -10615,12 +10702,36 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } break; case SC_ANGRIFFS_MODUS: - if(--(sce->val4) >= 0) { //drain hp/sp + if(--(sce->val4) > 0) { //drain hp/sp if( !status_charge(bl,100,20) ) break; sc_timer_next(1000+tick,status_change_timer,bl->id, data); return 0; } break; + case SC_FULL_THROTTLE: + if( --(sce->val4) > 0 ) + { + status_percent_damage(bl, bl, sce->val2, 0, false); + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + case SC_KINGS_GRACE: + if( --(sce->val4) > 0 ) + { + status_percent_heal(bl, sce->val2, 0); + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; + case SC_FRIGG_SONG: + if( --(sce->val4) > 0 ) + { + status_heal(bl, sce->val3, 0, 0); + sc_timer_next(10000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; } // default for all non-handled control paths is to end the status @@ -10650,7 +10761,7 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] % status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - case SC_CONCENTRATE: + case SC_CONCENTRATION: status_change_end(bl, SC_HIDING, INVALID_TIMER); status_change_end(bl, SC_CLOAKING, INVALID_TIMER); status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); @@ -10673,7 +10784,7 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] % status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); break; - case SC_SIGHTBLASTER: + case SC_WZ_SIGHTBLASTER: if (battle->check_target( src, bl, BCT_ENEMY ) > 0 && status_check_skilluse(src, bl, WZ_SIGHTBLASTER, 2)) { @@ -10683,11 +10794,11 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) } } break; - case SC_CLOSECONFINE: + case SC_RG_CCONFINE_M: //Lock char has released the hold on everyone... - if (tsc && tsc->data[SC_CLOSECONFINE2] && tsc->data[SC_CLOSECONFINE2]->val2 == src->id) { - tsc->data[SC_CLOSECONFINE2]->val2 = 0; - status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); + if (tsc && tsc->data[SC_RG_CCONFINE_S] && tsc->data[SC_RG_CCONFINE_S]->val2 == src->id) { + tsc->data[SC_RG_CCONFINE_S]->val2 = 0; + status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); } break; case SC_CURSEDCIRCLE_TARGET: @@ -10700,6 +10811,131 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) return 0; } +#ifdef RENEWAL +int status_get_total_def(struct block_list *src){ return status_get_status_data(src)->def2 + (short)status_get_def(src); } +int status_get_total_mdef(struct block_list *src){ return status_get_status_data(src)->mdef2 + (short)status_get_mdef(src); } +int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int flag){ + int min = 0, max = 0, dstr; + float strdex_bonus, variance; + struct status_change *sc = status_get_sc(bl); + struct status_data *status = status_get_status_data(bl); + + if ( bl->type == BL_PC && watk->atk ){ + if ( flag&16 ) + dstr = status_get_dex(bl); + else + dstr = status_get_str(bl); + + variance = 5.0f * watk->atk * watk->wlv / 100.0f; + strdex_bonus = watk->atk * dstr / 200.0f; + + min = (watk->atk - (int)(variance + strdex_bonus)) + watk->atk2; + max = (watk->atk + (int)(variance + strdex_bonus)) + watk->atk2; + }else if( watk->atk ){ + min = watk->atk * 80 / 100; + max = watk->atk * 120 / 100; + } + + if( !(flag&1) ){ + if( max > min ) + max = min + rnd()%(max - min); + else + max = min; + } + + if( bl->type == BL_PC && ((TBL_PC*)bl)->right_weapon.overrefine > 0) + max += rnd()%((TBL_PC*)bl)->right_weapon.overrefine + 1; + + max = status_calc_watk(bl, sc, max, false); + + return max; +} +#endif + +#define GETRANDMATK(){\ + if( status->matk_max > status->matk_min )\ + return status->matk_min + rnd()%(status->matk_max - status->matk_min);\ + else\ + return status->matk_min;\ +} + +/*========================================== + * flag [malufett] + * 0 - update matk values + * 1 - get matk w/o SC bonuses + * 2 - get modified matk + * 3 - get matk w/o eatk & SC bonuses + *------------------------------------------*/ +int status_get_matk(struct block_list *bl, int flag){ + struct status_data *status; + struct status_change *sc; + struct map_session_data *sd; + + if( bl == NULL ) + return 1; + + status = status_get_status_data(bl); + sc = status_get_sc(bl); + sd = BL_CAST(BL_PC, bl); + + if( flag == 2 ) // just get matk + GETRANDMATK(); + +#ifndef RENEWAL + status->matk_min = status_base_matk_min(status) + (sd?sd->bonus.ematk:0); + status->matk_max = status_base_matk_max(status) + (sd?sd->bonus.ematk:0); +#else + /** + * RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK) + * MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers + **/ + status->matk_min = status_base_matk(status, status_get_lv(bl)); + + // Any +MATK you get from skills and cards, including cards in weapon, is added here. + if( sd && sd->bonus.ematk > 0 && flag != 3 ) + status->matk_min += sd->bonus.ematk; + if( flag != 3 ) + status->matk_min = status_calc_ematk(bl, sc, status->matk_min); + + status->matk_max = status->matk_min; + + //This is the only portion in MATK that varies depending on the weapon level and refinement rate. + if( bl->type&BL_PC && (status->rhw.matk + status->lhw.matk) > 0 ){ + int wMatk = status->rhw.matk + status->lhw.matk; // Left and right matk stacks + int variance = wMatk * status->rhw.wlv / 10; // Only use right hand weapon level + status->matk_min += wMatk - variance; + status->matk_max += wMatk + variance; + }else if( bl->type&BL_MOB ){ + status->matk_min = status->matk_max = status_get_int(bl) + status_get_lv(bl); + status->matk_min += 70 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100; + status->matk_max += 130 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100; + } +#endif + if (bl->type&BL_PC && sd->matk_rate != 100) { + status->matk_max = status->matk_max * sd->matk_rate/100; + status->matk_min = status->matk_min * sd->matk_rate/100; + } + + if ((bl->type&BL_HOM && battle_config.hom_setting&0x20) //Hom Min Matk is always the same as Max Matk + || sc->data[SC_RECOGNIZEDSPELL]) + status->matk_min = status->matk_max; + +#ifdef RENEWAL + if( sd && sd->right_weapon.overrefine > 0){ + status->matk_min++; + status->matk_max += sd->right_weapon.overrefine - 1; + } +#endif + + if( flag ) // get unmodified from sc matk + GETRANDMATK(); + + status->matk_min = status_calc_matk(bl, sc, status->matk_min, true); + status->matk_max = status_calc_matk(bl, sc, status->matk_max, true); + + return 0; +} + /*========================================== * Clears buffs/debuffs of a character. * type&1 -> buffs, type&2 -> debuffs @@ -10719,70 +10955,18 @@ int status_change_clear_buffs (struct block_list* bl, int type) for( i = SC_COMMON_MAX+1; i < SC_MAX; i++ ) { - if(!sc->data[i]) + if( !sc->data[i] || !status_get_sc_type(i) ) continue; - switch (i) { - //Stuff that cannot be removed - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_COMBO: - case SC_SMA: - case SC_DANCING: - case SC_LEADERSHIP: - case SC_GLORYWOUNDS: - case SC_SOULCOLD: - case SC_HAWKEYES: - case SC_GUILDAURA: - case SC_SAFETYWALL: - case SC_PNEUMA: - case SC_NOCHAT: - case SC_JAILED: - case SC_ANKLE: - case SC_BLADESTOP: - case SC_CP_WEAPON: - case SC_CP_SHIELD: - case SC_CP_ARMOR: - case SC_CP_HELM: - case SC_STRFOOD: - case SC_AGIFOOD: - case SC_VITFOOD: - case SC_INTFOOD: - case SC_DEXFOOD: - case SC_LUKFOOD: - case SC_HITFOOD: - case SC_FLEEFOOD: - case SC_BATKFOOD: - case SC_WATKFOOD: - case SC_MATKFOOD: - case SC_FOOD_STR_CASH: - case SC_FOOD_AGI_CASH: - case SC_FOOD_VIT_CASH: - case SC_FOOD_DEX_CASH: - case SC_FOOD_INT_CASH: - case SC_FOOD_LUK_CASH: - case SC_EXPBOOST: - case SC_JEXPBOOST: - case SC_ITEMBOOST: - case SC_ELECTRICSHOCKER: - case SC__MANHOLE: - case SC_GIANTGROWTH: - case SC_MILLENNIUMSHIELD: - case SC_REFRESH: - case SC_STONEHARDSKIN: - case SC_VITALITYACTIVATION: - case SC_FIGHTINGSPIRIT: - case SC_ABUNDANCE: - case SC_CURSEDCIRCLE_ATKER: - case SC_CURSEDCIRCLE_TARGET: - case SC_PUSH_CART: - case SC_ALL_RIDING: - continue; + if( type&1 && !(status_get_sc_type(i)&SC_BUFF) ) + continue; - //Debuffs that can be removed. - case SC_DEEPSLEEP: - case SC_BURNING: - case SC_FREEZING: + if( type&2 && !(status_get_sc_type(i)&SC_DEBUFF) ) + continue; + + switch (i) { + case SC_DEEP_SLEEP: + case SC_FROSTMISTY: case SC_CRYSTALIZE: case SC_TOXIN: case SC_PARALYSE: @@ -10797,40 +10981,13 @@ int status_change_clear_buffs (struct block_list* bl, int type) if(!(type&4)) continue; break; - case SC_HALLUCINATION: - case SC_QUAGMIRE: - case SC_SIGNUMCRUCIS: - case SC_DECREASEAGI: - case SC_SLOWDOWN: - case SC_MINDBREAKER: - case SC_WINKCHARM: - case SC_STOP: - case SC_ORCISH: - case SC_STRIPWEAPON: - case SC_STRIPSHIELD: - case SC_STRIPARMOR: - case SC_STRIPHELM: - case SC_BITE: - case SC_ADORAMUS: - case SC_VACUUM_EXTREME: - case SC_FEAR: - case SC_MAGNETICFIELD: - case SC_NETHERWORLD: - if (!(type&2)) - continue; - break; - //The rest are buffs that can be removed. case SC__BLOODYLUST: case SC_BERSERK: - case SC_SATURDAYNIGHTFEVER: - if (!(type&1)) + case SC_SATURDAY_NIGHT_FEVER: + if(type&4) continue; sc->data[i]->val2 = 0; break; - default: - if (!(type&1)) - continue; - break; } status_change_end(bl, (sc_type)i, INVALID_TIMER); } @@ -10861,21 +11018,21 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) { case SC_CONFUSION: case SC_BLIND: case SC_NOCHAT: - case SC_HALLUCINATION: - case SC_SIGNUMCRUCIS: - case SC_DECREASEAGI: + case SC_ILLUSION: + case SC_CRUCIS: + case SC_DEC_AGI: case SC_SLOWDOWN: case SC_MINDBREAKER: - case SC_WINKCHARM: + case SC_DC_WINKCHARM: case SC_STOP: case SC_ORCISH: - //case SC_STRIPWEAPON://Omg I got infected and had the urge to strip myself physically. - //case SC_STRIPSHIELD://No this is stupid and shouldnt be spreadable at all. - //case SC_STRIPARMOR:// Disabled until I can confirm if it does or not. [Rytech] - //case SC_STRIPHELM: - //case SC__STRIPACCESSORY: - case SC_BITE: - case SC_FREEZING: + //case SC_NOEQUIPWEAPON://Omg I got infected and had the urge to strip myself physically. + //case SC_NOEQUIPSHIELD://No this is stupid and shouldnt be spreadable at all. + //case SC_NOEQUIPARMOR:// Disabled until I can confirm if it does or not. [Rytech] + //case SC_NOEQUIPHELM: + //case SC__STRIPACCESSARY: + case SC_WUGBITE: + case SC_FROSTMISTY: case SC_VENOMBLEED: case SC_DEATHHURT: case SC_PARALYSE: @@ -10907,7 +11064,7 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) { data.tick = sc->data[i]->val4 * 4000; break; case SC_TOXIN: - case SC_BLEEDING: + case SC_BLOODING: data.tick = sc->data[i]->val4 * 10000; break; default: @@ -11142,6 +11299,13 @@ int status_get_refine_chance(enum refine_type wlv, int refine) { return refine_info[wlv].chance[refine]; } +int status_get_sc_type(sc_type type) { + + if( type <= SC_NONE || type >= SC_MAX ) + return 0; + + return sc_conf[type]; +} /*------------------------------------------ * DB reading. @@ -11244,6 +11408,20 @@ static bool status_readdb_refine(char* fields[], int columns, int current) return true; } +static bool status_readdb_scconfig(char* fields[], int columns, int current) +{ + int val = 0; + char* type = fields[0]; + + if( !script_get_constant(type, &val) ){ + ShowWarning("status_readdb_sc_conf: Invalid status type %s specified.\n", type); + return false; + } + + sc_conf[val] = (int)strtol(fields[1], NULL, 0); + + return true; +} /* * Read status db * job1.txt @@ -11295,6 +11473,7 @@ int status_readdb(void) sv->readdb(iMap->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, &status_readdb_job2); sv->readdb(iMap->db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(atkmods), &status_readdb_sizefix); sv->readdb(iMap->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine); + sv->readdb(iMap->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, &status_readdb_scconfig); return 0; } diff --git a/src/map/status.h b/src/map/status.h index 4a7af884e..617cd9572 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -31,6 +31,16 @@ enum refine_type { REFINE_TYPE_MAX = 5 }; +typedef enum sc_conf_type { + SC_NO_REM_DEATH = 0x1, + SC_NO_SAVE = 0x2, + SC_NO_DISPELL = 0x4, + SC_NO_CLEARANCE = 0x8, + SC_BUFF = 0x10, + SC_DEBUFF = 0x20, + SC_MADO_NO_RESET = 0x40 +} sc_conf_type; + int status_get_refine_chance(enum refine_type wlv, int refine); // Status changes listing. These code are for use by the server. @@ -48,25 +58,26 @@ typedef enum sc_type { SC_SILENCE, SC_CONFUSION, SC_BLIND, - SC_BLEEDING, - SC_DPOISON, //10 - SC_COMMON_MAX = 10, // end + SC_BLOODING, + SC_DPOISON, + SC_BURNING, //11 + SC_COMMON_MAX = 11, // end //Next up, we continue on 20, to leave enough room for additional "common" ailments in the future. SC_PROVOKE = 20, SC_ENDURE, SC_TWOHANDQUICKEN, - SC_CONCENTRATE, + SC_CONCENTRATION, SC_HIDING, SC_CLOAKING, - SC_ENCPOISON, + SC_ENCHANTPOISON, SC_POISONREACT, SC_QUAGMIRE, SC_ANGELUS, SC_BLESSING, //30 - SC_SIGNUMCRUCIS, - SC_INCREASEAGI, - SC_DECREASEAGI, + SC_CRUCIS, + SC_INC_AGI, + SC_DEC_AGI, SC_SLOWPOISON, SC_IMPOSITIO , SC_SUFFRAGIUM, @@ -75,40 +86,40 @@ typedef enum sc_type { SC_KYRIE, SC_MAGNIFICAT, //40 SC_GLORIA, - SC_AETERNA, + SC_LEXAETERNA, SC_ADRENALINE, - SC_WEAPONPERFECTION, + SC_WEAPONPERFECT, SC_OVERTHRUST, SC_MAXIMIZEPOWER, SC_TRICKDEAD, - SC_LOUD, + SC_SHOUT, SC_ENERGYCOAT, SC_BROKENARMOR, //50 - NOTE: These two aren't used anywhere, and they have an icon... SC_BROKENWEAPON, - SC_HALLUCINATION, - SC_WEIGHT50, - SC_WEIGHT90, - SC_ASPDPOTION0, - SC_ASPDPOTION1, - SC_ASPDPOTION2, - SC_ASPDPOTION3, - SC_SPEEDUP0, - SC_SPEEDUP1, //60 - SC_ATKPOTION, - SC_MATKPOTION, + SC_ILLUSION, + SC_WEIGHTOVER50, + SC_WEIGHTOVER90, + SC_ATTHASTE_POTION1, + SC_ATTHASTE_POTION2, + SC_ATTHASTE_POTION3, + SC_ATTHASTE_INFINITY, + SC_MOVHASTE_HORSE, + SC_MOVHASTE_INFINITY, //60 + SC_PLUSATTACKPOWER, + SC_PLUSMAGICPOWER, SC_WEDDING, SC_SLOWDOWN, - SC_ANKLE, + SC_ANKLESNARE, SC_KEEPING, SC_BARRIER, - SC_STRIPWEAPON, - SC_STRIPSHIELD, - SC_STRIPARMOR, //70 - SC_STRIPHELM, - SC_CP_WEAPON, - SC_CP_SHIELD, - SC_CP_ARMOR, - SC_CP_HELM, + SC_NOEQUIPWEAPON, + SC_NOEQUIPSHIELD, + SC_NOEQUIPARMOR, //70 + SC_NOEQUIPHELM, + SC_PROTECTWEAPON, + SC_PROTECTSHIELD, + SC_PROTECTARMOR, + SC_PROTECTHELM, SC_AUTOGUARD, SC_REFLECTSHIELD, SC_SPLASHER, @@ -126,24 +137,24 @@ typedef enum sc_type { SC_RUWACH, //90 SC_EXTREMITYFIST, SC_EXPLOSIONSPIRITS, - SC_COMBO, + SC_COMBOATTACK, SC_BLADESTOP_WAIT, SC_BLADESTOP, - SC_FIREWEAPON, - SC_WATERWEAPON, - SC_WINDWEAPON, - SC_EARTHWEAPON, + SC_PROPERTYFIRE, + SC_PROPERTYWATER, + SC_PROPERTYWIND, + SC_PROPERTYGROUND, SC_VOLCANO, //100, SC_DELUGE, SC_VIOLENTGALE, SC_WATK_ELEMENT, SC_ARMOR, - SC_ARMOR_ELEMENT, + SC_ARMORPROPERTY, SC_NOCHAT, SC_BABY, SC_AURABLADE, SC_PARRYING, - SC_CONCENTRATION, //110 + SC_LKCONCENTRATION, //110 SC_TENSIONRELAX, SC_BERSERK, SC_FURY, @@ -158,10 +169,10 @@ typedef enum sc_type { SC_MELTDOWN, SC_CARTBOOST, SC_CHASEWALK, - SC_REJECTSWORD, + SC_SWORDREJECT, + SC_MARIONETTE_MASTER, SC_MARIONETTE, - SC_MARIONETTE2, - SC_CHANGEUNDEAD, + SC_PROPERTYUNDEAD, SC_JOINTBEAT, SC_MINDBREAKER, //130 SC_MEMORIZE, @@ -171,39 +182,40 @@ typedef enum sc_type { SC_SACRIFICE, SC_STEELBODY, SC_ORCISH, - SC_READYSTORM, - SC_READYDOWN, - SC_READYTURN, //140 - SC_READYCOUNTER, - SC_DODGE, + SC_STORMKICK_READY, + SC_DOWNKICK_READY, + SC_TURNKICK_READY, //140 + SC_COUNTERKICK_READY, + SC_DODGE_READY, SC_RUN, - SC_SHADOWWEAPON, + SC_PROPERTYDARK, SC_ADRENALINE2, - SC_GHOSTWEAPON, + SC_PROPERTYTELEKINESIS, SC_KAIZEL, SC_KAAHI, SC_KAUPE, - SC_ONEHAND, //150 + SC_ONEHANDQUICKEN, //150 SC_PRESERVE, - SC_BATTLEORDERS, - SC_REGENERATION, - SC_DOUBLECAST, + SC_GDSKILL_BATTLEORDER, + SC_GDSKILL_REGENERATION, + SC_DOUBLECASTING, SC_GRAVITATION, - SC_MAXOVERTHRUST, + SC_OVERTHRUSTMAX, SC_LONGING, SC_HERMODE, - SC_SHRINK, - SC_SIGHTBLASTER, //160 - SC_WINKCHARM, - SC_CLOSECONFINE, - SC_CLOSECONFINE2, + SC_TAROTCARD, + SC_CR_SHRINK, //160 + SC_WZ_SIGHTBLASTER, + SC_DC_WINKCHARM, + SC_RG_CCONFINE_M, + SC_RG_CCONFINE_S, SC_DANCING, - SC_ELEMENTALCHANGE, + SC_ARMOR_PROPERTY, SC_RICHMANKIM, SC_ETERNALCHAOS, SC_DRUMBATTLE, - SC_NIBELUNGEN, - SC_ROKISWEIL, //170 + SC_NIBELUNGEN, //170 + SC_ROKISWEIL, SC_INTOABYSS, SC_SIEGFRIED, SC_WHISTLE, @@ -212,18 +224,18 @@ typedef enum sc_type { SC_APPLEIDUN, SC_MODECHANGE, SC_HUMMING, - SC_DONTFORGETME, - SC_FORTUNE, //180 - SC_SERVICE4U, + SC_DONTFORGETME, //180 + SC_FORTUNE, + SC_SERVICEFORYOU, SC_STOP, //Prevents inflicted chars from walking. [Skotlex] - SC_SPURT, - SC_SPIRIT, + SC_STRUP, + SC_SOULLINK, SC_COMA, //Not a real SC_, it makes a char's HP/SP hit 1. - SC_INTRAVISION, + SC_CLAIRVOYANCE, SC_INCALLSTATUS, - SC_INCSTR, - SC_INCAGI, - SC_INCVIT, //190 + SC_CHASEWALK2, + SC_INCAGI, //190 + SC_INCVIT, SC_INCINT, SC_INCDEX, SC_INCLUK, @@ -232,18 +244,18 @@ typedef enum sc_type { SC_INCFLEE, SC_INCFLEERATE, SC_INCMHPRATE, - SC_INCMSPRATE, - SC_INCATKRATE, //200 + SC_INCMSPRATE, //200 + SC_INCATKRATE, SC_INCMATKRATE, SC_INCDEFRATE, - SC_STRFOOD, - SC_AGIFOOD, - SC_VITFOOD, - SC_INTFOOD, - SC_DEXFOOD, - SC_LUKFOOD, - SC_HITFOOD, - SC_FLEEFOOD, //210 + SC_FOOD_STR, + SC_FOOD_AGI, + SC_FOOD_VIT, + SC_FOOD_INT, + SC_FOOD_DEX, + SC_FOOD_LUK, + SC_FOOD_BASICHIT, //210 + SC_FOOD_BASICAVOIDANCE, SC_BATKFOOD, SC_WATKFOOD, SC_MATKFOOD, @@ -252,8 +264,8 @@ typedef enum sc_type { SC_WARM, //SG skills [Komurka] SC_SUN_COMFORT, SC_MOON_COMFORT, - SC_STAR_COMFORT, - SC_FUSION, //220 + SC_STAR_COMFORT, //220 + SC_FUSION, SC_SKILLRATE_UP, SC_SKE, SC_KAITE, @@ -261,82 +273,82 @@ typedef enum sc_type { SC_SKA, // [marquis007] SC_EARTHSCROLL, SC_MIRACLE, //SG 'hidden' skill [Komurka] - SC_MADNESSCANCEL, - SC_ADJUSTMENT, - SC_INCREASING, //230 - SC_GATLINGFEVER, - SC_TATAMIGAESHI, - SC_UTSUSEMI, - SC_BUNSINJYUTSU, - SC_KAENSIN, - SC_SUITON, - SC_NEN, + SC_GS_MADNESSCANCEL, + SC_GS_ADJUSTMENT, //230 + SC_GS_ACCURACY, + SC_GS_GATLINGFEVER, + SC_NJ_TATAMIGAESHI, + SC_NJ_UTSUSEMI, + SC_NJ_BUNSINJYUTSU, + SC_NJ_KAENSIN, + SC_NJ_SUITON, + SC_NJ_NEN, SC_KNOWLEDGE, - SC_SMA, - SC_FLING, //240 - SC_AVOID, - SC_CHANGE, - SC_BLOODLUST, - SC_FLEET, - SC_SPEED, - SC_DEFENCE, + SC_SMA_READY, //240 + SC_FLING, + SC_HLIF_AVOID, + SC_HLIF_CHANGE, + SC_HAMI_BLOODLUST, + SC_HLIF_FLEET, + SC_HLIF_SPEED, + SC_HAMI_DEFENCE, SC_INCASPDRATE, - SC_INCFLEE2 = 248, - SC_JAILED, - SC_ENCHANTARMS, //250 + SC_PLUSAVOIDVALUE, + SC_JAILED, //250 + SC_ENCHANTARMS, SC_MAGICALATTACK, - SC_ARMORCHANGE, + SC_STONESKIN, SC_CRITICALWOUND, SC_MAGICMIRROR, SC_SLOWCAST, SC_SUMMER, - SC_EXPBOOST, - SC_ITEMBOOST, - SC_BOSSMAPINFO, - SC_LIFEINSURANCE, //260 - SC_INCCRI, + SC_CASH_PLUSEXP, + SC_CASH_RECEIVEITEM, + SC_CASH_BOSS_ALARM, //260 + SC_CASH_DEATHPENALTY, + SC_CRITICALPERCENT, //SC_INCDEF, - //SC_INCBASEATK = 263, + //SC_INCBASEATK = 264, //SC_FASTCAST, - SC_MDEF_RATE = 265, + SC_PROTECT_MDEF = 266, //SC_HPREGEN, - SC_INCHEALRATE = 267, + SC_HEALPLUS = 268, SC_PNEUMA, - SC_AUTOTRADE, - SC_KSPROTECTED, //270 - SC_ARMOR_RESIST = 271, - SC_SPCOST_RATE, - SC_COMMONSC_RESIST, - SC_SEVENWIND, - SC_DEF_RATE, + SC_AUTOTRADE, //270 + SC_KSPROTECTED, + SC_ARMOR_RESIST, + SC_ATKER_BLOOD, + SC_TARGET_BLOOD, + SC_TK_SEVENWIND, + SC_PROTECT_DEF, //SC_SPREGEN, - SC_WALKSPEED = 277, + SC_WALKSPEED = 278, // Mercenary Only Bonus Effects - SC_MERC_FLEEUP, - SC_MERC_ATKUP, - SC_MERC_HPUP, //280 - SC_MERC_SPUP, - SC_MERC_HITUP, - SC_MERC_QUICKEN, + SC_MER_FLEE, + SC_MER_ATK, //280 + SC_MER_HP, + SC_MER_SP, + SC_MER_HIT, + SC_MER_QUICKEN, SC_REBIRTH, - //SC_SKILLCASTRATE, //285 + //SC_SKILLCASTRATE, //286 //SC_DEFRATIOATK, //SC_HPDRAIN, //SC_SKILLATKBONUS, - SC_ITEMSCRIPT = 289, - SC_S_LIFEPOTION, //290 + SC_ITEMSCRIPT = 290, + SC_S_LIFEPOTION, SC_L_LIFEPOTION, - SC_JEXPBOOST, + SC_CASH_PLUSONLYJOBEXP, //SC_IGNOREDEF, - SC_HELLPOWER = 294, - SC_INVINCIBLE, //295 + SC_HELLPOWER = 295, + SC_INVINCIBLE, SC_INVINCIBLEOFF, SC_MANU_ATK, SC_MANU_DEF, - SC_SPL_ATK, - SC_SPL_DEF, //300 + SC_SPL_ATK, //300 + SC_SPL_DEF, SC_MANU_MATK, SC_SPL_MATK, SC_FOOD_STR_CASH, @@ -344,25 +356,24 @@ typedef enum sc_type { SC_FOOD_VIT_CASH, SC_FOOD_DEX_CASH, SC_FOOD_INT_CASH, - SC_FOOD_LUK_CASH,//308 + SC_FOOD_LUK_CASH, /** * 3rd **/ - SC_FEAR,//309 - SC_BURNING,//310 - SC_FREEZING,//311 + SC_FEAR, + SC_FROSTMISTY, /** * Rune Knight **/ - SC_ENCHANTBLADE,//312 - SC_DEATHBOUND,//313 + SC_ENCHANTBLADE, + SC_DEATHBOUND, SC_MILLENNIUMSHIELD, - SC_CRUSHSTRIKE,//315 + SC_CRUSHSTRIKE, SC_REFRESH, SC_REUSE_REFRESH, SC_GIANTGROWTH, SC_STONEHARDSKIN, - SC_VITALITYACTIVATION,//320 + SC_VITALITYACTIVATION, SC_STORMBLAST, SC_FIGHTINGSPIRIT, SC_ABUNDANCE, @@ -370,12 +381,12 @@ typedef enum sc_type { * Arch Bishop **/ SC_ADORAMUS, - SC_EPICLESIS,//325 + SC_EPICLESIS, SC_ORATIO, SC_LAUDAAGNUS, SC_LAUDARAMUS, SC_RENOVATIO, - SC_EXPIATIO,//330 + SC_EXPIATIO, SC_DUPLELIGHT, SC_SECRAMENT, /** @@ -383,38 +394,38 @@ typedef enum sc_type { **/ SC_WHITEIMPRISON, SC_MARSHOFABYSS, - SC_RECOGNIZEDSPELL,//335 + SC_RECOGNIZEDSPELL, SC_STASIS, - SC_SPHERE_1, - SC_SPHERE_2, - SC_SPHERE_3, - SC_SPHERE_4,//340 - SC_SPHERE_5, + SC_SUMMON1, + SC_SUMMON2, + SC_SUMMON3, + SC_SUMMON4, + SC_SUMMON5, SC_READING_SB, - SC_FREEZINGSPELL, + SC_FREEZINGSP, /** * Ranger **/ SC_FEARBREEZE, - SC_ELECTRICSHOCKER,//345 + SC_ELECTRICSHOCKER, SC_WUGDASH, - SC_BITE, + SC_WUGBITE, SC_CAMOUFLAGE, /** * Mechanic **/ SC_ACCELERATION, - SC_HOVERING,//350 + SC_HOVERING, SC_SHAPESHIFT, SC_INFRAREDSCAN, SC_ANALYZE, SC_MAGNETICFIELD, - SC_NEUTRALBARRIER,//355 + SC_NEUTRALBARRIER, SC_NEUTRALBARRIER_MASTER, SC_STEALTHFIELD, SC_STEALTHFIELD_MASTER, SC_OVERHEAT, - SC_OVERHEAT_LIMITPOINT,//360 + SC_OVERHEAT_LIMITPOINT, /** * Guillotine Cross **/ @@ -422,30 +433,30 @@ typedef enum sc_type { SC_POISONINGWEAPON, SC_WEAPONBLOCKING, SC_CLOAKINGEXCEED, - SC_HALLUCINATIONWALK,//365 + SC_HALLUCINATIONWALK, SC_HALLUCINATIONWALK_POSTDELAY, SC_ROLLINGCUTTER, SC_TOXIN, SC_PARALYSE, - SC_VENOMBLEED,//370 + SC_VENOMBLEED, SC_MAGICMUSHROOM, SC_DEATHHURT, SC_PYREXIA, SC_OBLIVIONCURSE, - SC_LEECHESEND,//375 + SC_LEECHESEND, /** * Royal Guard **/ - SC_REFLECTDAMAGE, + SC_LG_REFLECTDAMAGE, SC_FORCEOFVANGUARD, SC_SHIELDSPELL_DEF, SC_SHIELDSPELL_MDEF, - SC_SHIELDSPELL_REF,//380 + SC_SHIELDSPELL_REF, SC_EXEEDBREAK, SC_PRESTIGE, SC_BANDING, SC_BANDING_DEFENCE, - SC_EARTHDRIVE,//385 + SC_EARTHDRIVE, SC_INSPIRATION, /** * Sorcerer @@ -453,30 +464,30 @@ typedef enum sc_type { SC_SPELLFIST, SC_CRYSTALIZE, SC_STRIKING, - SC_WARMER,//390 + SC_WARMER, SC_VACUUM_EXTREME, SC_PROPERTYWALK, /** * Minstrel / Wanderer **/ - SC_SWINGDANCE, - SC_SYMPHONYOFLOVER, - SC_MOONLITSERENADE,//395 - SC_RUSHWINDMILL, + SC_SWING, + SC_SYMPHONY_LOVE, + SC_MOONLIT_SERENADE, + SC_RUSH_WINDMILL, SC_ECHOSONG, SC_HARMONIZE, - SC_VOICEOFSIREN, - SC_DEEPSLEEP,//400 + SC_SIREN, + SC_DEEP_SLEEP, SC_SIRCLEOFNATURE, SC_GLOOMYDAY, SC_GLOOMYDAY_SK, - SC_SONGOFMANA, - SC_DANCEWITHWUG,//405 - SC_SATURDAYNIGHTFEVER, - SC_LERADSDEW, + SC_SONG_OF_MANA, + SC_DANCE_WITH_WUG, + SC_SATURDAY_NIGHT_FEVER, + SC_LERADS_DEW, SC_MELODYOFSINK, - SC_BEYONDOFWARCRY, - SC_UNLIMITEDHUMMINGVOICE,//410 + SC_BEYOND_OF_WARCRY, + SC_UNLIMITED_HUMMING_VOICE, SC_SITDOWN_FORCE, SC_NETHERWORLD, /** @@ -485,35 +496,35 @@ typedef enum sc_type { SC_CRESCENTELBOW, SC_CURSEDCIRCLE_ATKER, SC_CURSEDCIRCLE_TARGET, - SC_LIGHTNINGWALK,//416 + SC_LIGHTNINGWALK, SC_RAISINGDRAGON, - SC_GT_ENERGYGAIN, - SC_GT_CHANGE, - SC_GT_REVITALIZE, + SC_GENTLETOUCH_ENERGYGAIN, + SC_GENTLETOUCH_CHANGE, + SC_GENTLETOUCH_REVITALIZE, /** * Genetic **/ - SC_GN_CARTBOOST,//427 - SC_THORNSTRAP, - SC_BLOODSUCKER, - SC_SMOKEPOWDER, - SC_TEARGAS, - SC_MANDRAGORA,//426 + SC_GN_CARTBOOST, + SC_THORNS_TRAP, + SC_BLOOD_SUCKER, + SC_FIRE_EXPANSION_SMOKE_POWDER, + SC_FIRE_EXPANSION_TEAR_GAS, + SC_MANDRAGORA, SC_STOMACHACHE, SC_MYSTERIOUS_POWDER, SC_MELON_BOMB, SC_BANANA_BOMB, - SC_BANANA_BOMB_SITDOWN,//431 + SC_BANANA_BOMB_SITDOWN_POSTDELAY, SC_SAVAGE_STEAK, SC_COCKTAIL_WARG_BLOOD, SC_MINOR_BBQ, SC_SIROMA_ICE_TEA, - SC_DROCERA_HERB_STEAMED,//436 + SC_DROCERA_HERB_STEAMED, SC_PUTTI_TAILS_NOODLES, SC_BOOST500, SC_FULL_SWING_K, SC_MANA_PLUS, - SC_MUSTLE_M,//441 + SC_MUSTLE_M, SC_LIFE_FORCE_F, SC_EXTRACT_WHITE_POTION_Z, SC_VITATA_500, @@ -521,21 +532,21 @@ typedef enum sc_type { /** * Shadow Chaser **/ - SC__REPRODUCE,//446 + SC__REPRODUCE, SC__AUTOSHADOWSPELL, SC__SHADOWFORM, SC__BODYPAINT, SC__INVISIBILITY, - SC__DEADLYINFECT,//451 + SC__DEADLYINFECT, SC__ENERVATION, SC__GROOMY, SC__IGNORANCE, SC__LAZINESS, - SC__UNLUCKY,//456 + SC__UNLUCKY, SC__WEAKNESS, - SC__STRIPACCESSORY, + SC__STRIPACCESSARY, SC__MANHOLE, - SC__BLOODYLUST,//460 + SC__BLOODYLUST, /** * Elemental Spirits **/ @@ -543,61 +554,60 @@ typedef enum sc_type { SC_CIRCLE_OF_FIRE_OPTION, SC_FIRE_CLOAK, SC_FIRE_CLOAK_OPTION, - SC_WATER_SCREEN,//465 + SC_WATER_SCREEN, SC_WATER_SCREEN_OPTION, SC_WATER_DROP, SC_WATER_DROP_OPTION, SC_WATER_BARRIER, - SC_WIND_STEP,//470 + SC_WIND_STEP, SC_WIND_STEP_OPTION, SC_WIND_CURTAIN, SC_WIND_CURTAIN_OPTION, SC_ZEPHYR, - SC_SOLID_SKIN,//475 + SC_SOLID_SKIN, SC_SOLID_SKIN_OPTION, SC_STONE_SHIELD, SC_STONE_SHIELD_OPTION, SC_POWER_OF_GAIA, - SC_PYROTECHNIC,//480 + SC_PYROTECHNIC, SC_PYROTECHNIC_OPTION, SC_HEATER, SC_HEATER_OPTION, SC_TROPIC, - SC_TROPIC_OPTION,//485 + SC_TROPIC_OPTION, SC_AQUAPLAY, SC_AQUAPLAY_OPTION, SC_COOLER, SC_COOLER_OPTION, - SC_CHILLY_AIR,//490 + SC_CHILLY_AIR, SC_CHILLY_AIR_OPTION, SC_GUST, SC_GUST_OPTION, SC_BLAST, - SC_BLAST_OPTION,//495 + SC_BLAST_OPTION, SC_WILD_STORM, SC_WILD_STORM_OPTION, SC_PETROLOGY, SC_PETROLOGY_OPTION, - SC_CURSED_SOIL,//500 + SC_CURSED_SOIL, SC_CURSED_SOIL_OPTION, SC_UPHEAVAL, SC_UPHEAVAL_OPTION, SC_TIDAL_WEAPON, - SC_TIDAL_WEAPON_OPTION,//505 + SC_TIDAL_WEAPON_OPTION, SC_ROCK_CRUSHER, SC_ROCK_CRUSHER_ATK, /* Guild Aura */ SC_LEADERSHIP, SC_GLORYWOUNDS, - SC_SOULCOLD, //508 + SC_SOULCOLD, SC_HAWKEYES, /* ... */ SC_ODINS_POWER, - SC_RAID, /* Sorcerer .extra */ SC_FIRE_INSIGNIA, SC_WATER_INSIGNIA, - SC_WIND_INSIGNIA, //516 + SC_WIND_INSIGNIA, SC_EARTH_INSIGNIA, /* new pushcart */ SC_PUSH_CART, @@ -610,22 +620,22 @@ typedef enum sc_type { SC_SPELLBOOK6, /** * In official server there are only 7 maximum number of spell books that can be memorized - * To increase the maximum value just add another status type before SC_MAXSPELLBOOK (ex. SC_SPELLBOOK7, SC_SPELLBOOK8 and so on) + * To increase the maximum value just add another status type before SC_SPELLBOOK7 (ex. SC_SPELLBOOK8, SC_SPELLBOOK9 and so on) **/ - SC_MAXSPELLBOOK, + SC_SPELLBOOK7, /* Max HP & SP */ SC_INCMHP, SC_INCMSP, - SC_PARTYFLEE, // 531 + SC_PARTYFLEE, /** * Kagerou & Oboro [malufett] **/ SC_MEIKYOUSISUI, - SC_JYUMONJIKIRI, + SC_KO_JYUMONJIKIRI, SC_KYOUGAKU, SC_IZAYOI, SC_ZENKAI, - SC_KAGEHUMI, + SC_KG_KAGEHUMI, SC_KYOMU, SC_KAGEMUSYA, SC_ZANGETSU, @@ -639,17 +649,24 @@ typedef enum sc_type { SC_ERASER_CUTTER, SC_OVERED_BOOST, SC_LIGHT_OF_REGENE, - SC_ASH, + SC_VOLCANIC_ASH, SC_GRANITIC_ARMOR, SC_MAGMA_FLOW, SC_PYROCLASTIC, - SC_PARALYSIS, + SC_NEEDLE_OF_PARALYZE, SC_PAIN_KILLER, - - #ifdef RENEWAL SC_EXTREMITYFIST2, + SC_RAID, #endif + SC_DARKCROW = 553, + SC_FULL_THROTTLE, + SC_REBOUND, + SC_UNLIMIT, + SC_KINGS_GRACE, + SC_TELEKINESIS_INTENSE, + SC_OFFERTORIUM, + SC_FRIGG_SONG, SC_ALL_RIDING, SC_HANBOK, @@ -660,66 +677,66 @@ typedef enum sc_type { // Official status change ids, used to display status icons on the client. enum si_type { SI_BLANK = -1, - SI_PROVOKE = 0, - SI_ENDURE = 1, - SI_TWOHANDQUICKEN = 2, - SI_CONCENTRATE = 3, - SI_HIDING = 4, - SI_CLOAKING = 5, - SI_ENCPOISON = 6, - SI_POISONREACT = 7, - SI_QUAGMIRE = 8, - SI_ANGELUS = 9, - SI_BLESSING = 10, - SI_SIGNUMCRUCIS = 11, - SI_INCREASEAGI = 12, - SI_DECREASEAGI = 13, - SI_SLOWPOISON = 14, - SI_IMPOSITIO = 15, - SI_SUFFRAGIUM = 16, - SI_ASPERSIO = 17, - SI_BENEDICTIO = 18, - SI_KYRIE = 19, - SI_MAGNIFICAT = 20, - SI_GLORIA = 21, - SI_AETERNA = 22, - SI_ADRENALINE = 23, - SI_WEAPONPERFECTION = 24, - SI_OVERTHRUST = 25, - SI_MAXIMIZEPOWER = 26, - SI_RIDING = 27, - SI_FALCON = 28, - SI_TRICKDEAD = 29, - SI_LOUD = 30, - SI_ENERGYCOAT = 31, - SI_BROKENARMOR = 32, - SI_BROKENWEAPON = 33, - SI_HALLUCINATION = 34, - SI_WEIGHT50 = 35, - SI_WEIGHT90 = 36, - SI_ASPDPOTION0 = 37, - SI_ASPDPOTION1 = 38, - SI_ASPDPOTION2 = 39, - SI_ASPDPOTIONINFINITY = 40, - SI_SPEEDPOTION1 = 41, -// SI_MOVHASTE_INFINITY = 42, + SI_PROVOKE = 0, + SI_ENDURE = 1, + SI_TWOHANDQUICKEN = 2, + SI_CONCENTRATION = 3, + SI_HIDING = 4, + SI_CLOAKING = 5, + SI_ENCHANTPOISON = 6, + SI_POISONREACT = 7, + SI_QUAGMIRE = 8, + SI_ANGELUS = 9, + SI_BLESSING = 10, + SI_CRUCIS = 11, + SI_INC_AGI = 12, + SI_DEC_AGI = 13, + SI_SLOWPOISON = 14, + SI_IMPOSITIO = 15, + SI_SUFFRAGIUM = 16, + SI_ASPERSIO = 17, + SI_BENEDICTIO = 18, + SI_KYRIE = 19, + SI_MAGNIFICAT = 20, + SI_GLORIA = 21, + SI_LEXAETERNA = 22, + SI_ADRENALINE = 23, + SI_WEAPONPERFECT = 24, + SI_OVERTHRUST = 25, + SI_MAXIMIZE = 26, + SI_RIDING = 27, + SI_FALCON = 28, + SI_TRICKDEAD = 29, + SI_SHOUT = 30, + SI_ENERGYCOAT = 31, + SI_BROKENARMOR = 32, + SI_BROKENWEAPON = 33, + SI_ILLUSION = 34, + SI_WEIGHTOVER50 = 35, + SI_WEIGHTOVER90 = 36, + SI_ATTHASTE_POTION1 = 37, + SI_ATTHASTE_POTION2 = 38, + SI_ATTHASTE_POTION3 = 39, + SI_ATTHASTE_INFINITY = 40, + SI_MOVHASTE_POTION = 41, + SI_MOVHASTE_INFINITY = 42, // SI_AUTOCOUNTER = 43, // SI_SPLASHER = 44, -// SI_ANKLESNARE = 45, - SI_ACTIONDELAY = 46, + SI_ANKLESNARE = 45, + SI_POSTDELAY = 46, // SI_NOACTION = 47, // SI_IMPOSSIBLEPICKUP = 48, // SI_BARRIER = 49, - SI_STRIPWEAPON = 50, - SI_STRIPSHIELD = 51, - SI_STRIPARMOR = 52, - SI_STRIPHELM = 53, - SI_CP_WEAPON = 54, - SI_CP_SHIELD = 55, - SI_CP_ARMOR = 56, - SI_CP_HELM = 57, - SI_AUTOGUARD = 58, - SI_REFLECTSHIELD = 59, + SI_NOEQUIPWEAPON = 50, + SI_NOEQUIPSHIELD = 51, + SI_NOEQUIPARMOR = 52, + SI_NOEQUIPHELM = 53, + SI_PROTECTWEAPON = 54, + SI_PROTECTSHIELD = 55, + SI_PROTECTARMOR = 56, + SI_PROTECTHELM = 57, + SI_AUTOGUARD = 58, + SI_REFLECTSHIELD = 59, // SI_DEVOTION = 60, SI_PROVIDENCE = 61, SI_DEFENDER = 62, @@ -750,29 +767,29 @@ enum si_type { SI_STEELBODY = 87, SI_EXTREMITYFIST = 88, // SI_COMBOATTACK = 89, - SI_FIREWEAPON = 90, - SI_WATERWEAPON = 91, - SI_WINDWEAPON = 92, - SI_EARTHWEAPON = 93, + SI_PROPERTYFIRE = 90, + SI_PROPERTYWATER = 91, + SI_PROPERTYWIND = 92, + SI_PROPERTYGROUND = 93, // SI_MAGICATTACK = 94, SI_STOP = 95, // SI_WEAPONBRAKER = 96, - SI_UNDEAD = 97, + SI_PROPERTYUNDEAD = 97, // SI_POWERUP = 98, // SI_AGIUP = 99, // SI_SIEGEMODE = 100, // SI_INVISIBLE = 101, // SI_STATUSONE = 102, - SI_AURABLADE = 103, - SI_PARRYING = 104, - SI_CONCENTRATION = 105, - SI_TENSIONRELAX = 106, + SI_AURABLADE = 103, + SI_PARRYING = 104, + SI_LKCONCENTRATION = 105, + SI_TENSIONRELAX = 106, SI_BERSERK = 107, // SI_SACRIFICE = 108, // SI_GOSPEL = 109, SI_ASSUMPTIO = 110, // SI_BASILICA = 111, - SI_LANDENDOW = 112, + SI_GROUNDMAGIC = 112, SI_MAGICPOWER = 113, SI_EDP = 114, SI_TRUESIGHT = 115, @@ -780,52 +797,52 @@ enum si_type { SI_MELTDOWN = 117, SI_CARTBOOST = 118, // SI_CHASEWALK = 119, - SI_REJECTSWORD = 120, - SI_MARIONETTE = 121, - SI_MARIONETTE2 = 122, - SI_MOONLIT = 123, - SI_BLEEDING = 124, + SI_SWORDREJECT = 120, + SI_MARIONETTE_MASTER = 121, + SI_MARIONETTE = 122, + SI_MOON = 123, + SI_BLOODING = 124, SI_JOINTBEAT = 125, // SI_MINDBREAKER = 126, // SI_MEMORIZE = 127, // SI_FOGWALL = 128, // SI_SPIDERWEB = 129, - SI_BABY = 130, + SI_PROTECTEXP = 130, // SI_SUB_WEAPONPROPERTY = 131, SI_AUTOBERSERK = 132, SI_RUN = 133, - SI_BUMP = 134, - SI_READYSTORM = 135, -// SI_STORMKICK_READY = 136, - SI_READYDOWN = 137, -// SI_DOWNKICK_READY = 138, - SI_READYTURN = 139, -// SI_TURNKICK_READY = 140, - SI_READYCOUNTER = 141, -// SI_COUNTER_READY = 142, - SI_DODGE = 143, -// SI_DODGE_READY = 144, - SI_SPURT = 145, - SI_SHADOWWEAPON = 146, - SI_ADRENALINE2 = 147, - SI_GHOSTWEAPON = 148, - SI_SPIRIT = 149, - SI_PLUSATTACKPOWER = 150, - SI_PLUSMAGICPOWER = 151, - SI_DEVIL = 152, + SI_TING = 134, + SI_STORMKICK_ON = 135, + SI_STORMKICK_READY = 136, + SI_DOWNKICK_ON = 137, + SI_DOWNKICK_READY = 138, + SI_TURNKICK_ON = 139, + SI_TURNKICK_READY = 140, + SI_COUNTER_ON = 141, + SI_COUNTER_READY = 142, + SI_DODGE_ON = 143, + SI_DODGE_READY = 144, + SI_STRUP = 145, + SI_PROPERTYDARK = 146, + SI_ADRENALINE2 = 147, + SI_PROPERTYTELEKINESIS = 148, + SI_SOULLINK = 149, + SI_PLUSATTACKPOWER = 150, + SI_PLUSMAGICPOWER = 151, + SI_DEVIL1 = 152, SI_KAITE = 153, // SI_SWOO = 154, // SI_STAR2 = 155, SI_KAIZEL = 156, SI_KAAHI = 157, SI_KAUPE = 158, - SI_SMA = 159, - SI_NIGHT = 160, - SI_ONEHAND = 161, + SI_SMA_READY = 159, + SI_SKE = 160, + SI_ONEHANDQUICKEN = 161, // SI_FRIEND = 162, // SI_FRIENDUP = 163, // SI_SG_WARM = 164, - SI_WARM = 165, + SI_SG_SUN_WARM = 165, // 166 | The three show the exact same display: ultra red character (165, 166, 167) // 167 | Their names would be SI_SG_SUN_WARM, SI_SG_MOON_WARM, SI_SG_STAR_WARM // SI_EMOTION = 168, @@ -844,34 +861,34 @@ enum si_type { SI_PRESERVE = 181, SI_INCSTR = 182, // SI_NOT_EXTREMITYFIST = 183, - SI_INTRAVISION = 184, + SI_CLAIRVOYANCE = 184, // SI_MOVESLOW_POTION = 185, - SI_DOUBLECAST = 186, + SI_DOUBLECASTING = 186, // SI_GRAVITATION = 187, - SI_MAXOVERTHRUST = 188, + SI_OVERTHRUSTMAX = 188, // SI_LONGING = 189, // SI_HERMODE = 190, - SI_TAROT = 191, // the icon allows no doubt... but what is it really used for ?? [DracoRPG] + SI_TAROTCARD = 191, // the icon allows no doubt... but what is it really used for ?? [DracoRPG] // SI_HLIF_AVOID = 192, // SI_HFLI_FLEET = 193, // SI_HFLI_SPEED = 194, // SI_HLIF_CHANGE = 195, // SI_HAMI_BLOODLUST = 196, - SI_SHRINK = 197, - SI_SIGHTBLASTER = 198, - SI_WINKCHARM = 199, - SI_CLOSECONFINE = 200, - SI_CLOSECONFINE2 = 201, + SI_CR_SHRINK = 197, + SI_WZ_SIGHTBLASTER = 198, + SI_DC_WINKCHARM = 199, + SI_RG_CCONFINE_M = 200, + SI_RG_CCONFINE_S = 201, // SI_DISABLEMOVE = 202, - SI_MADNESSCANCEL = 203, //[blackhole89] - SI_GATLINGFEVER = 204, - SI_EARTHSCROLL = 205, - SI_UTSUSEMI = 206, - SI_BUNSINJYUTSU = 207, - SI_NEN = 208, - SI_ADJUSTMENT = 209, - SI_ACCURACY = 210, -// SI_NJ_SUITON = 211, + SI_GS_MADNESSCANCEL = 203, //[blackhole89] + SI_GS_GATLINGFEVER = 204, + SI_EARTHSCROLL = 205, + SI_NJ_UTSUSEMI = 206, + SI_NJ_BUNSINJYUTSU = 207, + SI_NJ_NEN = 208, + SI_GS_ADJUSTMENT = 209, + SI_GS_ACCURACY = 210, + SI_NJ_SUITON = 211, // SI_PET = 212, // SI_MENTAL = 213, // SI_EXPMEMORY = 214, @@ -901,19 +918,19 @@ enum si_type { // SI_DGAUGE = 238, // SI_DACCEL = 239, // SI_DBLOCK = 240, - SI_FOODSTR = 241, - SI_FOODAGI = 242, - SI_FOODVIT = 243, - SI_FOODDEX = 244, - SI_FOODINT = 245, - SI_FOODLUK = 246, - SI_FOODFLEE = 247, - SI_FOODHIT = 248, - SI_FOODCRI = 249, - SI_EXPBOOST = 250, - SI_LIFEINSURANCE = 251, - SI_ITEMBOOST = 252, - SI_BOSSMAPINFO = 253, + SI_FOOD_STR = 241, + SI_FOOD_AGI = 242, + SI_FOOD_VIT = 243, + SI_FOOD_DEX = 244, + SI_FOOD_INT = 245, + SI_FOOD_LUK = 246, + SI_FOOD_BASICAVOIDANCE = 247, + SI_FOOD_BASICHIT = 248, + SI_FOOD_CRITICALSUCCESSVALUE = 249, + SI_CASH_PLUSEXP = 250, + SI_CASH_DEATHPENALTY = 251, + SI_CASH_RECEIVEITEM = 252, + SI_CASH_BOSS_ALARM = 253, // SI_DA_ENERGY = 254, // SI_DA_FIRSTSLOT = 255, // SI_DA_HEADDEF = 256, @@ -937,11 +954,11 @@ enum si_type { SI_FOOD_DEX_CASH = 274, SI_FOOD_INT_CASH = 275, SI_FOOD_LUK_CASH = 276, - SI_MERC_FLEEUP = 277, - SI_MERC_ATKUP = 278, - SI_MERC_HPUP = 279, - SI_MERC_SPUP = 280, - SI_MERC_HITUP = 281, + SI_MER_FLEE = 277, + SI_MER_ATK = 278, + SI_MER_HP = 279, + SI_MER_SP = 280, + SI_MER_HIT = 281, SI_SLOWCAST = 282, // SI_MAGICMIRROR = 283, // SI_STONESKIN = 284, @@ -949,14 +966,14 @@ enum si_type { SI_CRITICALWOUND = 286, // SI_NPC_DEFENDER = 287, // SI_NOACTION_WAIT = 288, - SI_MOVHASTE_HORSE = 289, - SI_DEF_RATE = 290, - SI_MDEF_RATE = 291, - SI_INCHEALRATE = 292, - SI_S_LIFEPOTION = 293, - SI_L_LIFEPOTION = 294, - SI_INCCRI = 295, - SI_PLUSAVOIDVALUE = 296, + SI_MOVHASTE_HORSE = 289, + SI_PROTECT_DEF = 290, + SI_PROTECT_MDEF = 291, + SI_HEALPLUS = 292, + SI_S_LIFEPOTION = 293, + SI_L_LIFEPOTION = 294, + SI_CRITICALPERCENT = 295, + SI_PLUSAVOIDVALUE = 296, // SI_ATKER_ASPD = 297, // SI_TARGET_ASPD = 298, // SI_ATKER_MOVESPEED = 299, @@ -975,7 +992,7 @@ enum si_type { SI_CASH_PLUSONLYJOBEXP = 312, SI_PARTYFLEE = 313, // SI_ANGEL_PROTECT = 314, - SI_ENDURE_MDEF = 315, +// SI_ENDURE_MDEF = 315, SI_ENCHANTBLADE = 316, SI_DEATHBOUND = 317, SI_REFRESH = 318, @@ -1094,12 +1111,12 @@ enum si_type { SI_PROPERTYWALK = 431, SI_SPELLFIST = 432, SI_NETHERWORLD = 433, - SI_VOICEOFSIREN = 434, + SI_SIREN = 434, SI_DEEPSLEEP = 435, SI_SIRCLEOFNATURE = 436, SI_COLD = 437, SI_GLOOMYDAY = 438, - SI_SONGOFMANA = 439, + SI_SONG_OF_MANA = 439, SI_CLOUDKILL = 440, SI_DANCEWITHWUG = 441, SI_RUSHWINDMILL = 442, @@ -1361,6 +1378,34 @@ enum si_type { SI_QUEST_BUFF3 = 707, SI_REUSE_LIMIT_RECALL = 708, SI_SAVEPOSITION = 709, + SI_HANDICAPSTATE_ICEEXPLO = 710, + SI_FENRIR_CARD = 711, + SI_REUSE_LIMIT_ASPD_POTION = 712, + SI_MAXPAIN = 713, + SI_PC_STOP = 714, + SI_FRIGG_SONG = 715, + SI_OFFERTORIUM = 716, + SI_TELEKINESIS_INTENSE = 717, + SI_MOONSTAR = 718, + SI_STRANGELIGHTS = 719, + SI_FULL_THROTTLE = 720, + SI_REBOUND = 721, + SI_UNLIMIT = 722, + SI_KINGS_GRACE = 723, + SI_ITEM_ATKMAX = 724, + SI_ITEM_ATKMIN = 725, + SI_ITEM_MATKMAX = 726, + SI_ITEM_MATKMIN = 727, + SI_SUPER_STAR = 728, + SI_HIGH_RANKER = 729, + SI_DARKCROW = 730, + SI_2013_VALENTINE1 = 731, + SI_2013_VALENTINE2 = 732, + SI_2013_VALENTINE3 = 733, + //SI_ = 734, + //SI_ = 735, + SI_CHILL = 736, + SI_BURNT = 737, SI_MAX, }; @@ -1553,7 +1598,7 @@ enum scb_flag //Basic damage info of a weapon //Required because players have two of these, one in status_data //and another for their left hand weapon. -struct weapon_atk { +typedef struct weapon_atk { unsigned short atk, atk2; unsigned short range; unsigned char ele; @@ -1561,7 +1606,7 @@ struct weapon_atk { unsigned short matk; unsigned char wlv; #endif -}; +}weapon_atk; sc_type SkillStatusChangeTable[MAX_SKILL]; // skill -> status int StatusIconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated) @@ -1681,6 +1726,7 @@ sc_type status_skill2sc(int skill); int status_sc2skill(sc_type sc); unsigned int status_sc2scb_flag(sc_type sc); int status_type2relevant_bl_types(int type); +int status_get_sc_type(sc_type idx); int status_damage(struct block_list *src,struct block_list *target,int hp,int sp, int walkdelay, int flag); //Define for standard HP damage attacks. @@ -1801,10 +1847,20 @@ int status_check_visibility(struct block_list *src, struct block_list *target); int status_change_spread( struct block_list *src, struct block_list *bl ); +defType status_calc_def(struct block_list *bl, struct status_change *sc, int, bool); +signed short status_calc_def2(struct block_list *,struct status_change *, int, bool); +defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int, bool); +signed short status_calc_mdef2(struct block_list *,struct status_change *, int, bool); + #ifdef RENEWAL unsigned short status_base_matk(const struct status_data* status, int level); +int status_get_weapon_atk(struct block_list *src, struct weapon_atk *watk, int flag); +int status_get_total_mdef(struct block_list *src); +int status_get_total_def(struct block_list *src); #endif +int status_get_matk(struct block_list *src, int flag); + int status_readdb(void); int do_init_status(void); void do_final_status(void); diff --git a/src/map/unit.c b/src/map/unit.c index 153ef5eda..371a75ac7 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -491,7 +491,7 @@ int unit_run(struct block_list *bl) if( (to_x == bl->x && to_y == bl->y ) || (to_x == (bl->x+1) || to_y == (bl->y+1)) || (to_x == (bl->x-1) || to_y == (bl->y-1))) { //If you can't run forward, you must be next to a wall, so bounce back. [Skotlex] - clif->sc_load(bl,bl->id,AREA,SI_BUMP,0,0,0); + clif->sc_load(bl,bl->id,AREA,SI_TING,0,0,0); //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] unit_bl2ud(bl)->state.running = 0; @@ -499,7 +499,7 @@ int unit_run(struct block_list *bl) skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit_getdir(bl),0); clif->fixpos(bl); //Why is a clif->slide (skill->blown) AND a fixpos needed? Ask Aegis. - clif->sc_end(bl,bl->id,AREA,SI_BUMP); + clif->sc_end(bl,bl->id,AREA,SI_TING); return 0; } if (unit_walktoxy(bl, to_x, to_y, 1)) @@ -511,7 +511,7 @@ int unit_run(struct block_list *bl) } while (--i > 0 && !unit_walktoxy(bl, to_x, to_y, 1)); if ( i == 0 ) { // copy-paste from above - clif->sc_load(bl,bl->id,AREA,SI_BUMP,0,0,0); + clif->sc_load(bl,bl->id,AREA,SI_TING,0,0,0); //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] unit_bl2ud(bl)->state.running = 0; @@ -519,7 +519,7 @@ int unit_run(struct block_list *bl) skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit_getdir(bl),0); clif->fixpos(bl); - clif->sc_end(bl,bl->id,AREA,SI_BUMP); + clif->sc_end(bl,bl->id,AREA,SI_TING); return 0; } return 1; @@ -924,7 +924,7 @@ int unit_can_move(struct block_list *bl) { if (sc) { if( sc->count && ( - sc->data[SC_ANKLE] + sc->data[SC_ANKLESNARE] || sc->data[SC_AUTOCOUNTER] || sc->data[SC_TRICKDEAD] || sc->data[SC_BLADESTOP] @@ -932,14 +932,14 @@ int unit_can_move(struct block_list *bl) { || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move || sc->data[SC_STOP] - || sc->data[SC_CLOSECONFINE] - || sc->data[SC_CLOSECONFINE2] - || sc->data[SC_MADNESSCANCEL] + || sc->data[SC_RG_CCONFINE_M] + || sc->data[SC_RG_CCONFINE_S] + || sc->data[SC_GS_MADNESSCANCEL] || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF) || sc->data[SC_WHITEIMPRISON] || sc->data[SC_ELECTRICSHOCKER] - || sc->data[SC_BITE] - || sc->data[SC_THORNSTRAP] + || sc->data[SC_WUGBITE] + || sc->data[SC_THORNS_TRAP] || sc->data[SC_MAGNETICFIELD] || sc->data[SC__MANHOLE] || sc->data[SC_CURSEDCIRCLE_ATKER] @@ -948,9 +948,9 @@ int unit_can_move(struct block_list *bl) { || sc->data[SC_NETHERWORLD] || (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 && !(sc->data[SC_CAMOUFLAGE]->val3&1)) || sc->data[SC_MEIKYOUSISUI] - || sc->data[SC_KAGEHUMI] + || sc->data[SC_KG_KAGEHUMI] || sc->data[SC_KYOUGAKU] - || sc->data[SC_PARALYSIS] + || sc->data[SC_NEEDLE_OF_PARALYZE] || sc->data[SC_VACUUM_EXTREME] || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) @@ -1069,10 +1069,10 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui sc = NULL; //Unneeded //temp: used to signal combo-skills right now. - if (sc && sc->data[SC_COMBO] && (sc->data[SC_COMBO]->val1 == skill_id || + if (sc && sc->data[SC_COMBOATTACK] && (sc->data[SC_COMBOATTACK]->val1 == skill_id || (sd?skill->check_condition_castbegin(sd,skill_id,skill_lv):0) )) { - if (sc->data[SC_COMBO]->val2) - target_id = sc->data[SC_COMBO]->val2; + if (sc->data[SC_COMBOATTACK]->val2) + target_id = sc->data[SC_COMBOATTACK]->val2; else target_id = ud->target; @@ -1240,17 +1240,17 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui casttime += casttime * min(skill_lv, sd->spiritball); break; case MO_EXTREMITYFIST: - if (sc && sc->data[SC_COMBO] && - (sc->data[SC_COMBO]->val1 == MO_COMBOFINISH || - sc->data[SC_COMBO]->val1 == CH_TIGERFIST || - sc->data[SC_COMBO]->val1 == CH_CHAINCRUSH)) + if (sc && sc->data[SC_COMBOATTACK] && + (sc->data[SC_COMBOATTACK]->val1 == MO_COMBOFINISH || + sc->data[SC_COMBOATTACK]->val1 == CH_TIGERFIST || + sc->data[SC_COMBOATTACK]->val1 == CH_CHAINCRUSH)) casttime = -1; temp = 1; break; case SR_GATEOFHELL: case SR_TIGERCANNON: - if (sc && sc->data[SC_COMBO] && - sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) + if (sc && sc->data[SC_COMBOATTACK] && + sc->data[SC_COMBOATTACK]->val1 == SR_FALLENEMPIRE) casttime = -1; temp = 1; break; @@ -1317,10 +1317,11 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui if(!ud->state.running) //need TK_RUN or WUGDASH handler to be done before that, see bugreport:6026 unit_stop_walking(src,1);// eventhough this is not how official works but this will do the trick. bugreport:6829 + // in official this is triggered even if no cast time. clif->skillcasting(src, src->id, target_id, 0,0, skill_id, skill->get_ele(skill_id, skill_lv), casttime); if( casttime > 0 || temp ) - { + { if (sd && target->type == BL_MOB) { TBL_MOB *md = (TBL_MOB*)target; @@ -1518,7 +1519,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui if( casttime > 0 ) { ud->skilltimer = iTimer->add_timer( tick+casttime, skill->castend_pos, src->id, 0 ); if( (sd && pc->checkskill(sd,SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK) - status_calc_bl(&sd->bl, SCB_SPEED); + status_calc_bl(&sd->bl, SCB_SPEED); } else { ud->skilltimer = INVALID_TIMER; skill->castend_pos(ud->skilltimer,tick,src->id,0); @@ -1638,7 +1639,7 @@ int unit_cancel_combo(struct block_list *bl) { struct unit_data *ud; - if (!status_change_end(bl, SC_COMBO, INVALID_TIMER)) + if (!status_change_end(bl, SC_COMBOATTACK, INVALID_TIMER)) return 0; //Combo wasn't active. ud = unit_bl2ud(bl); @@ -1925,7 +1926,7 @@ int unit_skillcastcancel(struct block_list *bl,int type) return 0; if (sd && (sd->special_state.no_castcancel2 || - ((sd->sc.data[SC_UNLIMITEDHUMMINGVOICE] || sd->special_state.no_castcancel) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89] + ((sd->sc.data[SC_UNLIMITED_HUMMING_VOICE] || sd->special_state.no_castcancel) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89] return 0; } @@ -2053,17 +2054,17 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, if(sc && sc->count ) { //map-change/warp dispells. status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); status_change_end(bl, SC_BASILICA, INVALID_TIMER); - status_change_end(bl, SC_ANKLE, INVALID_TIMER); + status_change_end(bl, SC_ANKLESNARE, INVALID_TIMER); status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER); status_change_end(bl, SC_BLADESTOP_WAIT, INVALID_TIMER); status_change_end(bl, SC_RUN, INVALID_TIMER); status_change_end(bl, SC_DANCING, INVALID_TIMER); status_change_end(bl, SC_WARM, INVALID_TIMER); status_change_end(bl, SC_DEVOTION, INVALID_TIMER); + status_change_end(bl, SC_MARIONETTE_MASTER, INVALID_TIMER); status_change_end(bl, SC_MARIONETTE, INVALID_TIMER); - status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER); - status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); - status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); + status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER); + status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); status_change_end(bl, SC_HIDING, INVALID_TIMER); // Ensure the bl is a PC; if so, we'll handle the removal of cloaking and cloaking exceed later if ( bl->type != BL_PC ) @@ -2074,7 +2075,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, status_change_end(bl, SC_CHASEWALK, INVALID_TIMER); if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) status_change_end(bl, SC_GOSPEL, INVALID_TIMER); - status_change_end(bl, SC_CHANGE, INVALID_TIMER); + status_change_end(bl, SC_HLIF_CHANGE, INVALID_TIMER); status_change_end(bl, SC_STOP, INVALID_TIMER); status_change_end(bl, SC_WUGDASH, INVALID_TIMER); status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); @@ -2322,7 +2323,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) pc->inventory_rental_clear(sd); pc->delspiritball(sd,sd->spiritball,1); for(i = 1; i < 5; i++) - pc->del_talisman(sd, sd->talisman[i], i); + pc->del_charm(sd, sd->charm[i], i); if( sd->reg ) { //Double logout already freed pointer fix... [Skotlex] aFree(sd->reg); diff --git a/src/map/vending.c b/src/map/vending.c index e0dd844e1..b9575c8dd 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -272,7 +272,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, const clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet return; } - sd->state.prevend = 0; + sd->state.prevend = sd->state.workinprogress = 0; sd->state.vending = true; sd->vender_id = getid(); sd->vend_num = i; -- cgit v1.2.3-70-g09d2 From 9cab748f1b4e41e57336f8537c643ca40d5ad5e0 Mon Sep 17 00:00:00 2001 From: Euphy Date: Sat, 15 Jun 2013 02:30:36 -0400 Subject: Implemented Hall of Abyss. --- db/quest_db.txt | 3 + npc/re/guild/invest_main.txt | 1678 ++++++++++++++++++++++++++++++++++++++ npc/re/guild/invest_npc.txt | 66 ++ npc/re/mobs/dungeons/gld_dun.txt | 52 -- npc/re/mobs/dungeons/gld_re.txt | 100 +++ npc/re/warps/guildcastles.txt | 43 + 6 files changed, 1890 insertions(+), 52 deletions(-) create mode 100644 npc/re/guild/invest_main.txt create mode 100644 npc/re/guild/invest_npc.txt delete mode 100644 npc/re/mobs/dungeons/gld_dun.txt create mode 100644 npc/re/mobs/dungeons/gld_re.txt create mode 100644 npc/re/warps/guildcastles.txt (limited to 'npc') diff --git a/db/quest_db.txt b/db/quest_db.txt index 025a9e6ec..6b4108ad6 100644 --- a/db/quest_db.txt +++ b/db/quest_db.txt @@ -997,6 +997,9 @@ 7345,0,0,0,0,0,0,0,"List of Errands" 7346,0,0,0,0,0,0,0,"List of Errands" +// Hall of Abyss +7349,1800,0,0,0,0,0,0,"Vote" + // Port Malaya 7350,0,0,0,0,0,0,0,"Cautious Village" 7351,0,0,0,0,0,0,0,"Better than My Old Button" diff --git a/npc/re/guild/invest_main.txt b/npc/re/guild/invest_main.txt new file mode 100644 index 000000000..e8c2a011a --- /dev/null +++ b/npc/re/guild/invest_main.txt @@ -0,0 +1,1678 @@ +//===== rAthena Script ======================================= +//= Hall of Abyss - Core Scripts +//===== By: ================================================== +//= Euphy +//===== Current Version: ===================================== +//= 1.0 +//===== Compatible With: ===================================== +//= rAthena SVN +//===== Description: ========================================= +//= Expansion for War of Emperium FE. +//= Invest in each realm to unlock new maps: +//= - Guild Dungeon F2, total 20,000,000z. +//= - Hall of Abyss, total 70,000,000z. +//===== Additional Comments: ================================= +//= 1.0 First version. Missing official times. [Euphy] +//============================================================ + +// Global Variables +//============================================================ +// Note: an asterisk (*) represents any realm (prt, pay, gef, alde). +/* +$2011_agit_invest +-- 0: Inactive. +-- 1: Investment in progress. +-- 2: Investment results calculating. +-- 4: Investment calculations complete (only when at least one $*_invest_result is 3). +-- 11-21: Tie, revote required. + +$agit_result_notice +-- 0: Inactive. +-- 1-12: Interim statements (displaying $@vfund_*x) available. + +$agit_result_timer +-- 0: Inactive. +-- 0-59: Time elapsed during investment (in hours). + +$agit_revoting_timer +-- 0: Inactive. +-- 0-29: Time elapsed during revote (in minutes). +-- 30: Revote closed. +-- 31: Revote results calculating. + +$*_invest_result +-- 0: No data. +-- 1: Realm not connected. +-- 2: Guild Dungeon F2 open. +-- 3: Abyss Gate (Hall of Abyss and Gulid Dungeon F2) open. + +$fund_*[01-05] +-- Investment units per guild castle. +$fund_*_extra +-- Investment units per realm. + +$@vfund_*[01-05] +$@vfund_*_extra +-- Investment units, used in interim statements only. +*/ + +// Investment Functions & Controller +//============================================================ +// Note: The time in this section are almost entirely custom. + +- script #invest_timer -1,{ +OnClock0000: // Open investments on Wed (1 hour after WoE) + if (gettime(4) == 3 && !agitcheck()) { + set $2011_agit_invest,1; + donpcevent "#fund_master::OnInvest_start"; + } + end; +OnClock1200: // Close investments on Fri (60 hours after investments open) + if (gettime(4) == 5 && !agitcheck()) { + set $2011_agit_invest,2; + donpcevent "#fund_master::OnInvest_stop"; + } + end; +OnClock1235: // Open dungeons on Fri (at least 31 minutes after investments close) + if (gettime(4) == 5 && !agitcheck()) + donpcevent "#fund_master::OnResult"; + end; +OnClock2000: // Close dungeons on Tues (1 hour before WoE) + if (gettime(4) == 2) + donpcevent "#fund_master::OnReset"; + end; +} + +function script F_Invest_Status { + set .@day, gettime(4); + set .@hour, gettime(3); + set .@minute, gettime(2); + + // Inactive. + if (agitcheck()) + return 0; + + // Open for investments. + if (.@day >= 3 && (.@day < 5 || (.@day == 5 && .@hour <= 12))) + return 1; + + // Investments closed, calculating results. + if (.@day == 5 && .@hour == 12 && .@minute < 35) + return 2; + + // Calculations complete, dungeons open. + if ((.@day == 5 && (.@hour > 12 || (.@hour == 12 && .@minute >= 35))) || .@day > 5 || + .@day < 2 || (.@day == 2 && .@hour < 20)) + return 3; + + // Dungeons closed. + return 0; +} + +//callfunc "F_Invest_Abyss","",""{,""}; +function script F_Invest_Abyss { + mes "There are 2 ways to invest, by Zeny or the Investment Certificate given out by the Cat Paw Merchant Guild."; + mes "Which way would you like to make your investment?"; + next; + switch(select("Invest with Zeny.:Invest with Investment Certificates.:Cancel")) { + case 1: + mes getarg(1); + mes "So you've decided to invest in Zeny."; + mes "Minimum investment unit is ^4d4dff10,000 Zeny^000000."; + mes "You can invest a maximum of 50 units which is ^4d4dff500,000 Zeny^000000."; + next; + switch(select("1 unit 10,000 Zeny:10 units 100,000 Zeny:50 units 500,000 Zeny:Another amount:Cancel")) { + case 1: + set .@units,1; + break; + case 2: + set .@units,10; + break; + case 3: + set .@units,50; + break; + case 4: + mes getarg(1); + mes "Please enter the amount you want to invest."; + mes "Please choose between 1 to 200."; + mes "Please enter 0 to cancel."; + next; + input .@units; + if (.@units < 0 || .@units > 200) { + mes getarg(1); + mes "You've exceeded the amount per investment."; + mes "Please try again."; + close; + } else if (.@units == 0) { + mes getarg(1); + mes "Canceled."; + close; + } else + break; + case 5: + mes getarg(1); + mes "Canceled."; + close; + } + set .@zeny, .@units * 10000; + if (Zeny < .@zeny) { + mes getarg(1); + mes "You do not have enough money."; + close; + } + mes getarg(1); + mes "You've invested "+.@units+" unit"+((.@units == 1)?"":"s")+" "+((.@units < 100)?.@units:insertchar(""+.@units,",",1))+"0,000 Zeny"+getarg(2,"")+"."; + mes "Not much but this is a small gift. You can exchange it with items in Malangdo."; + set Zeny, Zeny-.@zeny; + setd getarg(0), getd(getarg(0)) + .@units; + getitem 6488,.@units; //Thanks_Invest_Ticket + close; + case 2: + mes getarg(1); + mes "Wow, you've brought Investment Certificates."; + mes "How many certificates will you submit?"; + next; + switch(select("1 Investment Certificate:5 Investment Certificates:Another amount:Cancel")) { + case 1: + set .@tickets,1; + break; + case 2: + set .@tickets,5; + break; + case 3: + mes getarg(1); + mes "Please enter the number of Investment Certificates you want to submit."; + mes "Please choose between 1 to 20."; + mes "Please enter 0 to cancel."; + next; + input .@tickets; + if (.@tickets < 0 || .@tickets > 20) { + mes getarg(1); + mes "You've exceeded the amount per investment."; + mes "Please try again."; + close; + } else if (.@tickets == 0) { + mes getarg(1); + mes "Canceled."; + close; + } else + break; + case 4: + mes getarg(1); + mes "Canceled."; + close; + } + if (countitem(6489) < .@tickets) { + mes getarg(1); + mes "Looks like you have fewer Investment Certificates than you want to submit."; + close; + } + set .@units, .@tickets * 10; + mes getarg(1); + mes .@tickets+" Investment Certificate"+((.@tickets == 1)?" is":"s are")+" the same as an investment of "+.@units+" units ("+((.@units < 100)?.@units:insertchar(""+.@units,",",1))+"0,000z)"+getarg(2,"")+"."; + mes "Not much but this is a small gift. You can exchange it with items in Malangdo."; + delitem 6489,.@tickets; //Cats_Invest_Certif + setd getarg(0), getd(getarg(0)) + .@units; + getitem 6488,.@units; //Thanks_Invest_Ticket + close; + case 3: + mes getarg(1); + mes "Canceled."; + close; + } +} + +// Script Core +//============================================================ +prt_gld,1,1,0 script #fund_master 844,{ + end; +OnInit: + set .@invest_status, callfunc("F_Invest_Status"); + if (.@invest_status == 1) { + set $2011_agit_invest,1; + end; + } + if ((.@invest_status == 2 && $2011_agit_invest == 1) || + (.@invest_status == 3 && ($2011_agit_invest == 1 || $2011_agit_invest == 2))) { + donpcevent "#fund_master::OnCalculate"; + end; + } + end; +OnCalculate_Election: + set .@force_vote,1; +OnCalculate: + setarray .@cas$[0],"prt","pay","gef","alde"; + for(set .@i,0; .@i<4; set .@i,.@i+1) { + // All funds per realm are summed. + set .@funds[.@i], getd("$fund_"+.@cas$[.@i]+"01")+getd("$fund_"+.@cas$[.@i]+"02")+getd("$fund_"+.@cas$[.@i]+"03")+getd("$fund_"+.@cas$[.@i]+"04")+getd("$fund_"+.@cas$[.@i]+"05")+getd("$fund_"+.@cas$[.@i]+"_extra"); + + // 70,000,000z opens Hall of Abyss and F2. + if (.@funds[.@i] >= 7000) { + setd "$"+.@cas$[.@i]+"_invest_result",3; + set .@total_7000,1; + } + // 20,000,000z opens F2 and a chance for Hall of Abyss. + else if (.@funds[.@i] >= 2000) { + setd "$"+.@cas$[.@i]+"_invest_result",2; + set .@total_2000,1; + } + // Anything below that opens nothing. + else + setd "$"+.@cas$[.@i]+"_invest_result",1; + } + // No further actions if 20,000,000z isn't reached. + if (!.@total_2000) + end; + // No further actions if any realm hits 70,000,000z. + if (.@total_7000) { + set $2011_agit_invest,4; + end; + } + // Otherwise, highest investment above 20,000,000z opens Hall of Abyss. + set .@max, .@funds[0]; + for(set .@i,1; .@i<4; set .@i,.@i+1) { + if (.@funds[.@i] > .@max) { + set .@max, .@funds[.@i]; + set .@ele, .@i; + deletearray .@rand$[0], getarraysize(.@rand$); + } else if (.@funds[.@i] == .@max && .@funds[.@i] >= 2000) { + if (!getarraysize(.@rand$)) + set .@rand$[0], .@cas$[.@ele]; + set .@rand$[getarraysize(.@rand$)], .@cas$[.@i]; + } + } + if (.@max < 2000) + end; + if (getarraysize(.@rand$)) { + + // Tie: declare a random winner. + if (!.@force_vote) { + set .@i, rand(getarraysize(.@rand$)); + setd "$"+.@rand$[.@i]+"_invest_result",3; + set $2011_agit_invest,4; + end; + } + + // Tie: initiate a 30-minute election. + set .@str$, implode(.@rand$,"|"); + for(set .@i,0; .@i<4; set .@i,.@i+1) { + if (compare(.@str$,.@cas$[.@i])) + set .@election, .@election | (1<<.@i); + } + switch(.@election) { + case 3: set $2011_agit_invest,11; break; //Prontera|Payon + case 9: set $2011_agit_invest,12; break; //Prontera|Al De Baran + case 5: set $2011_agit_invest,13; break; //Prontera|Geffen + case 10: set $2011_agit_invest,14; break; //Al De Baran|Payon + case 6: set $2011_agit_invest,15; break; //Geffen|Payon + case 12: set $2011_agit_invest,16; break; //Al De Baran|Geffen + case 11: set $2011_agit_invest,17; break; //Prontera|Payon|Al De Baran + case 7: set $2011_agit_invest,18; break; //Prontera|Payon|Geffen + case 13: set $2011_agit_invest,19; break; //Prontera|Al De Baran|Geffen + case 14: set $2011_agit_invest,20; break; //Al De Baran|Payon|Geffen + case 15: set $2011_agit_invest,21; break; //Prontera|Payon|Al De Baran|Geffen + } + if ($2011_agit_invest >= 11) + donpcevent "Revoting Manager#Invest1::OnStart"; + end; + } else { + setd "$"+.@cas$[.@ele]+"_invest_result",3; + set $2011_agit_invest,4; + end; + } + end; +OnInvest_start: + announce "From now on, we are going to start the investments to connect the 'Abyss Gate' in the WOE areas: Valkyrie Realm, Greenwood Lake, Luina, Britoniah.",bc_all,0xFF0000; //FW_NORMAL 10 + set $fund_prt01,0; + set $fund_prt02,0; + set $fund_prt03,0; + set $fund_prt04,0; + set $fund_prt05,0; + set $fund_pay01,0; + set $fund_pay02,0; + set $fund_pay03,0; + set $fund_pay04,0; + set $fund_pay05,0; + set $fund_gef01,0; + set $fund_gef02,0; + set $fund_gef03,0; + set $fund_gef04,0; + set $fund_gef05,0; + set $fund_alde01,0; + set $fund_alde02,0; + set $fund_alde03,0; + set $fund_alde04,0; + set $fund_alde05,0; + donpcevent "Investment_total#fund00::OnEnable"; + end; +OnInvest_stop: + announce "We've finished the investments to connect the 'Abyss Gate'.",bc_all,0xFF0000; //FW_NORMAL 10 + donpcevent "Investment_total#fund00::OnReset"; + donpcevent "#fund_master::OnCalculate_Election"; + end; +OnResult: + announce "We've got the results of the investments for the 'Abyss Gate'. You can check through the Investment Status Board in each WOE area.",bc_all,0xFF0000; //FW_NORMAL 10 + if ($2011_agit_invest == 4) { + set $fund_prt01,0; + set $fund_prt02,0; + set $fund_prt03,0; + set $fund_prt04,0; + set $fund_prt05,0; + set $fund_prt_extra,0; + set $fund_pay01,0; + set $fund_pay02,0; + set $fund_pay03,0; + set $fund_pay04,0; + set $fund_pay05,0; + set $fund_pay_extra,0; + set $fund_gef01,0; + set $fund_gef02,0; + set $fund_gef03,0; + set $fund_gef04,0; + set $fund_gef05,0; + set $fund_gef_extra,0; + set $fund_alde01,0; + set $fund_alde02,0; + set $fund_alde03,0; + set $fund_alde04,0; + set $fund_alde05,0; + set $fund_alde_extra,0; + } else if ($2011_agit_invest == 2) + donpcevent "#fund_master::OnCalculate"; + end; +OnReset: + set $2011_agit_invest,0; + donpcevent "Investment_total#fund00::OnReset"; + end; +} + +prt_gld,2,2,0 script Investment_total#fund00 844,{ +/* + mes "Is this not working properly?"; + next; + input .@input; + if (.@input == 1854) { + mes "If you think the investment timer is dead, please adjust the timer."; + next; + switch(select("Turn on the timer:Cancel")) { + case 1: + donpcevent "Investment_total#fund00::OnTimerReset"; + mes "You've turned on the timer."; + close; + case 2: + mes "Canceled."; + close; + } + } else { + mes "I don't need to adjust anything now."; + close; + } +*/ + end; +OnInit: + if (callfunc("F_Invest_Status") == 1) { + initnpctimer; + donpcevent "Investment_total#fund00::OnVarInit"; + } else { + set $agit_result_timer,0; + set $agit_result_notice,0; + } + end; +OnVarInit: + setarray .@cas$[0],"prt","pay","gef","alde"; + for(set .@i,0; .@i<4; set .@i,.@i+1) { + setd "$@vfund_"+.@cas$[.@i]+"01", getd("$fund_"+.@cas$[.@i]+"01"); + setd "$@vfund_"+.@cas$[.@i]+"02", getd("$fund_"+.@cas$[.@i]+"02"); + setd "$@vfund_"+.@cas$[.@i]+"03", getd("$fund_"+.@cas$[.@i]+"03"); + setd "$@vfund_"+.@cas$[.@i]+"04", getd("$fund_"+.@cas$[.@i]+"04"); + setd "$@vfund_"+.@cas$[.@i]+"05", getd("$fund_"+.@cas$[.@i]+"05"); + setd "$@vfund_"+.@cas$[.@i]+"_extra", getd("$fund_"+.@cas$[.@i]+"_extra"); + } + end; +OnEnable: + set $agit_result_timer,0; + set $agit_result_notice,0; + initnpctimer; + end; +OnReset: + set $agit_result_timer,0; + set $agit_result_notice,0; + stopnpctimer; + end; +OnTimerReset: + initnpctimer; + end; +OnTimer3600000: + if (callfunc("F_Invest_Status") == 1) { + if ($agit_result_timer < 59) { + set $agit_result_timer, $agit_result_timer+1; + + // Trigger on multiples of 5 up to 55, and 58. + if ($agit_result_timer % 10 == 5 || $agit_result_timer % 10 == 0 || $agit_result_timer == 58) { + set $agit_result_notice, $agit_result_notice+1; + donpcevent "Investment_total#fund00::OnVarInit"; + announce "No. "+$agit_result_notice+" Interim statement is now available. You can check through the Investment Status Board in each WOE area.",bc_all,0xFF0000; //FW_NORMAL 10 + } + + donpcevent "Investment_total#fund00::OnTimerReset"; + } else + stopnpctimer; + end; + } else { + donpcevent "Investment_total#fund00::OnReset"; + end; + } +} + +prt_gld,164,98,3 script Revoting Manager#Invest1 421,{ + mes "[Revoting Manager]"; + mes "We are not accepting additional votes."; + mes "Please wait for our results announcement."; + close; +OnInit: + set .@invest_status, callfunc("F_Invest_Status"); + if (.@invest_status == 2 && $2011_agit_invest >= 11 && $agit_revoting_timer < 30) { + donpcevent "Revoting Manager#Invest2::OnEnable"; + initnpctimer; + } else if (.@invest_status == 3 && $2011_agit_invest >= 11) + donpcevent "Revoting Manager#Invest1::OnCalculate"; + donpcevent "Revoting Manager#Invest1::OnDisable"; + end; +OnCalculate: + switch($2011_agit_invest) { + case 11: setarray.@cas$[0],"prt","pay"; break; + case 12: setarray.@cas$[0],"prt","alde"; break; + case 13: setarray.@cas$[0],"prt","gef"; break; + case 14: setarray.@cas$[0],"alde","pay"; break; + case 15: setarray.@cas$[0],"gef","pay"; break; + case 16: setarray.@cas$[0],"alde","gef"; break; + case 17: setarray.@cas$[0],"prt","pay","alde"; break; + case 18: setarray.@cas$[0],"prt","pay","gef"; break; + case 19: setarray.@cas$[0],"prt","alde","gef"; break; + case 20: setarray.@cas$[0],"alde","pay","gef"; break; + case 21: setarray.@cas$[0],"prt","pay","alde","gef"; break; + default: end; + } + set .@max, getd("$fund_"+.@cas$[0]+"_extra"); + for(set .@i,1; .@i .@max) { + set .@max, .@funds; + set .@ele, .@i; + deletearray .@rand$[0], getarraysize(.@rand$); + } else if (.@funds == .@max) { + if (!getarraysize(.@rand$)) + set .@rand$[0], .@cas$[.@ele]; + set .@rand$[getarraysize(.@rand$)], .@cas$[.@i]; + } + } + if (getarraysize(.@rand$)) { + set .@i, rand(getarraysize(.@rand$)); + setd "$"+.@rand$[.@i]+"_invest_result",3; + } else + setd "$"+.@cas$[.@ele]+"_invest_result",3; + set $2011_agit_invest,4; + set $agit_revoting_timer,0; + end; +OnEnable: + enablenpc "Revoting Manager#Invest1"; + end; +OnDisable: + disablenpc "Revoting Manager#Invest1"; + end; +OnStart: + initnpctimer; + donpcevent "Revoting Manager#Invest2::OnNotice_on"; + end; +OnEnd: + stopnpctimer; + disablenpc "Revoting Manager#Invest1"; + end; +OnTimerReset: + initnpctimer; + end; +OnTimer60000: + set .@revote, $agit_revoting_timer; + if (.@revote < 30) { + set $agit_revoting_timer, $agit_revoting_timer+1; + donpcevent "Revoting Manager#Invest1::OnTimerReset"; + } else if (.@revote == 30) { + announce "Cat Paw Merchant Guild: Now we are going to close the additional vote. We will announce the results soon.",bc_all,0xFF0000; //FW_NORMAL 10 + donpcevent "Revoting Manager#Invest2::OnDisable"; + donpcevent "Revoting Manager#Invest1::OnEnable"; + set $agit_revoting_timer, $agit_revoting_timer+1; + donpcevent "Revoting Manager#Invest1::OnTimerReset"; + } else if (.@revote == 31) { + donpcevent "Revoting Manager#Invest1::OnCalculate"; + donpcevent "Revoting Manager#Invest1::OnDisable"; + stopnpctimer; + end; + } else { + donpcevent "Revoting Manager#Invest1::OnDisable"; + stopnpctimer; + } + end; +} + +prt_gld,164,98,3 script Revoting Manager#Invest2 421,{ + set .@invest, $2011_agit_invest; + if (.@invest < 11) { + mes "[Revoting Manager]"; + mes "No! This is not the time to take a revote."; + close2; + disablenpc "Revoting Manager#Invest2"; + end; + } + set .@playtime, checkquest(7349,PLAYTIME); + if (.@playtime == 0 || .@playtime == 1) { + mes "[Revoting Manager]"; + mes "You've already participated in the vote."; + mes "Please relax and wait for the results."; + close; + } else if (.@playtime == 2) + erasequest 7349; + mes "[Revoting Manager]"; + mes "Would you like to participate in the vote for choosing where to connect the 'Abyss Gate'?"; + next; + if(select("Participate in the vote.:Skip for now.") == 2) { + mes "[Revoting Manager]"; + mes "You've canceled the vote."; + close; + } + mes "[Revoting Manager]"; + mes "You can vote once and won't need to invest for your choice."; + mes "Plesae choose one WOE area."; + next; + + // Create menu. + explode(.@candidates$, callsub(OnGetCandidates, .@invest),"|"); + for(set .@i,0; .@i= 4800) { + mes .@n$; + mes "You have too many Thank You Tickets to receive any more."; + mes "Cannot give you any more tickets. Please use your ticket and come back."; + mes "The ticket can be exchanged with various items in Malangdo."; + close; + } + if (callfunc("F_Invest_Status") != 1) { + mes .@n$; + mes "We do not receive investments now."; + mes "Please come back during the investment duration."; + close; + } + set .@guild, getcharid(2); + for(set .@i,1; .@i<=5; set .@i,.@i+1) { + set .@castle_name$[.@i], getcastlename(.@npc$+"g_cas0"+.@i); + set .@owner_id[.@i], getcastledata(.@npc$+"g_cas0"+.@i,1); + set .@owner_name$[.@i], getguildname(.@owner_id[.@i]); + if (.@guild == .@owner_id[.@i]) { + set .@menu$, .@menu$+.@castle_name$[.@i]+" ["+.@owner_name$[.@i]+"] Guild:"; + set .@castles_owned, .@castles_owned | (1<<.@i); + } else + set .@menu$, .@menu$+"^aaaaaaNot the guild that claimed "+.@castle_name$[.@i]+"^000000:"; + } + mes .@n$; + mes "Would you like to invest in the ^4d4dff"+.@realm$+"^000000 region?"; + mes "If there is a castle occupied already, you will invest in the castle and the guild that is occupying it."; + next; + if (.@castles_owned) { + set .@i, select(.@menu$+"Cancel"); + if (.@i == 6) { + mes .@n$; + mes "Canceled."; + close; + } + if (.@guild != .@owner_id[.@i]) { + mes .@n$; + mes "The guild that is occupying "+.@castle_name$[.@i]+" is "+.@owner_name$[.@i]+"."; + mes "Doesn't look like your guild."; + close; + } + mes .@n$; + mes "Invest under "+.@castle_name$[.@i]+"'s"+.@owner_name$[.@i]+" guild name."; + callfunc "F_Invest_Abyss","$fund_"+.@npc$+"0"+.@i,.@n$; + end; + } else { + mes .@n$; + callfunc "F_Invest_Abyss","$fund_"+.@npc$+"_extra",.@n$," for "+.@realm$; + end; + } + case 4: + mes .@n$; + mes "Is that so?"; + mes "Please come back whenever you are interested in investing in the Abyss Gate development."; + close; + } +} + +- script Gate Manager#realm -1,{ + + if (compare(strnpcinfo(4),"alde")) { + set .@npc$,"alde"; + set .@name$,"Alkor"; + set .@gate$,"Hero's Tears"; + set .@realm$,"Luina"; + } else if (compare(strnpcinfo(4),"gef")) { + set .@npc$,"gef"; + set .@name$,"Mizar"; + set .@gate$,"Hill of the Dead"; + set .@realm$,"Britoniah"; + } else if (compare(strnpcinfo(4),"pay")) { + set .@npc$,"pay"; + set .@name$,"Alkaid"; + set .@gate$,"Winds of the Ancient"; + set .@realm$,"Greenwood Lake"; + } else if (compare(strnpcinfo(4),"prt")) { + set .@npc$,"prt"; + set .@name$,"Arios"; + set .@gate$,"Way of the Warrior"; + set .@realm$,"Valkyrie Realm"; + } + set .@n$,"["+.@name$+"]"; + + if (callfunc("F_Invest_Status") != 3) { + mes .@n$; + mes "There are currently no connected dungeon gates."; + close; + } + set .@status, getd("$"+.@npc$+"_invest_result"); + if (.@status == 3) { + mes .@n$; + mes "We've successfully connected the Abyss Gate ["+.@gate$+"] with the help from your investment."; + mes "The Agit dungeon will be open to everyone with a small entrance fee in "+.@realm$+"."; + next; + mes .@n$; + mes "Please visit as often as possible since the entrance fee is saved as an investment for the region."; + mes "Do you want to enter the Agit dungeon?"; + next; + set .@i, select(.@realm$+" Dungeon 1F - 10000z:"+.@realm$+" Dungeon 2F - 10000z:Cancel"); + if (.@i == 3) { + mes .@n$; + mes "Canceled."; + close; + } + if (Zeny < 10000) { + mes .@n$; + mes "I'm collecting a small entrance fee."; + mes "Your contribution will be saved for the next investment."; + mes "Entrance fee is 10000z."; + close; + } + mes .@n$; + mes "I'm sending you to the "+.@realm$+" Agit Dungeon "+.@i+"F."; + set Zeny, Zeny-10000; + setd "$fund_"+.@npc$+"_extra", getd("$fund_"+.@npc$+"_extra") + 1; + close2; + if (compare(strnpcinfo(2),"alde")) + warp "gld_dun02"+((.@i == 2)?"_2":""),32,122; + else if (compare(strnpcinfo(2),"gef")) + warp "gld_dun04"+((.@i == 2)?"_2":""),39,258; + else if (compare(strnpcinfo(2),"pay")) + warp "gld_dun01"+((.@i == 2)?"_2":""),186,165; + else if (compare(strnpcinfo(2),"prt")) + warp "gld_dun03"+((.@i == 2)?"_2":""),164,268; + end; + } else if (.@status == 2) { + mes .@n$; + mes "The "+.@realm$+" Agit Dungeon 2F is now available but since it is not connected with the Abyss Gate,"; + mes "the Agit dungeon is only accessible to the Agit guild."; + close; + } else { + mes .@n$; + mes .@realm$+" was not chosen to be connected with a gate this time."; + mes "Please wait for the next investment duration."; + close; + } + end; +} + +- script Investment Status Board -1,{ + set .@invest_status, callfunc("F_Invest_Status"); + if (.@invest_status == 1) { + if (compare(strnpcinfo(4),"alde")) { + set .@npc$,"alde"; + set .@realm$,"Luina"; + } else if (compare(strnpcinfo(4),"gef")) { + set .@npc$,"gef"; + set .@realm$,"Britoniah"; + } else if (compare(strnpcinfo(4),"pay")) { + set .@npc$,"pay"; + set .@realm$,"Greenwood Lake"; + } else if (compare(strnpcinfo(4),"prt")) { + set .@npc$,"prt"; + set .@realm$,"Valkyrie Realm"; + } + set .@notice, $agit_result_notice; + if (.@notice < 1 || .@notice > 12) { + mes "There are currently no investment sums available."; + close; + } else if (.@notice == 1) + set .@str$,"1st"; + else if (.@notice == 2) + set .@str$,"2nd"; + else if (.@notice == 3) + set .@str$,"3rd"; + else + set .@str$,.@notice+"th"; + mes .@str$+" total (unit in 10,000z)"; + for(set .@i,1; .@i<=5; set .@i,.@i+1) { + set .@map$, .@npc$+"g_cas0"+.@i; + set .@fund[.@i], getd("$@vfund_"+.@npc$+"0"+.@i); + mes getcastlename(.@map$)+" "+getguildname(getcastledata(.@map$,1))+" Guild: "+.@fund[.@i]; + } + set .@fund[0], getd("$@vfund_"+.@npc$+"_extra"); + mes .@realm$+" normal: "+.@fund[0]; + mes .@realm$+" Investment Grand Total: "+(.@fund[0]+.@fund[1]+.@fund[2]+.@fund[3]+.@fund[4]+.@fund[5]); + close; + } else if (.@invest_status == 2) { + mes "!- Notice -!"; + mes "No sums are available because the total investment amount is currently being calculated."; + mes "Please wait for the announcement of the results."; + close; + } else if (.@invest_status == 3) { + setarray .@invest_result[0], $prt_invest_result,$pay_invest_result,$gef_invest_result,$alde_invest_result; + setarray .@invest_region$[0], "Valkyrie Realm", "Greenwood Lake", "Britoniah", "Luina"; + mes "!- Investment Results of All Agit Regions -!"; + for(set .@i,0; .@i<4; set .@i,.@i+1) { + if (.@invest_result[.@i] == 1) + mes "^aaaaaa["+.@invest_region$[.@i]+"] below minimum^000000"; + else if (.@invest_result[.@i] == 2) { + mes "["+.@invest_region$[.@i]+"] minimum achieved"; + mes "-> Guild Dungeon Deepest Layer (2F) available"; + } else if (.@invest_result[.@i] == 3) { + mes "^4d4dff["+.@invest_region$[.@i]+"] maximum achieved^000000"; + mes "-> Abyss Gate available"; + } else + mes "No data for ["+.@invest_region$[.@i]+"]."; + } + close; + } else { + mes "!- Notice -!"; + mes "No investment information will be announced now."; + close; + } +} + +// Inside Castles - Gate Managers +//============================================================ +- script Gate Manager#castle -1,{ + + set .@id, atoi(charat(strnpcinfo(2),getstrlen(strnpcinfo(2))-1)); + if (compare(strnpcinfo(2),"alde")) { + set .@npc$,"alde"; + set .@realm$,"Luina"; + } else if (compare(strnpcinfo(2),"gef")) { + set .@npc$,"gef"; + set .@realm$,"Britoniah"; + } else if (compare(strnpcinfo(2),"pay")) { + set .@npc$,"pay"; + set .@realm$,"Greenwood Lake"; + } else if (compare(strnpcinfo(2),"prt")) { + set .@npc$,"prt"; + set .@realm$,"Valkyrie Realm"; + } + + set .@GID, getcastledata(strnpcinfo(4),1); + if (getcharid(2) != .@GID) { + mes "[Gate Manager]"; + mes "You don't seem to be the member of guild owning this castle."; + mes "If you need any help, please visit any of our guild members at "+.@realm$+" Square."; + close; + } + mes "[Gate Manager]"; + mes "Hello, I am the Gate Manager from Cat Paw Merchant Guild warp department."; + mes "How may I help you today?"; + next; + switch(select("Invest for gate connection:Deepest Layer Dungeon Access:Abyss Gate Access:Cancel")) { + case 1: + if (checkweight(1201,1) == 0 || MaxWeight - Weight < 1000) { + mes "[Gate Manager]"; + mes "You have too many items to receive the Thank You Ticket as a small gift for your investment."; + mes "Please come back after making room in your inventory."; + close; + } + if (countitem(6488) >= 4800) { + mes "[Gate Manager]"; + mes "You have too many Thank You Tickets to receive any more."; + mes "Cannot give you any more tickets. Please use your ticket and come back."; + mes "The ticket can be exchanged with various items in Malangdo."; + close; + } + if (callfunc("F_Invest_Status") != 1) { + mes "[Gate Manager]"; + mes "We do not receive investments now."; + mes "Please come back during the investment duration."; + close; + } + if (getcharid(2) != .@GID) { + mes "[Gate Manager]"; + mes "You don't seem to be the member of the guild owning this castle."; + mes "Please use the normal investment from "+.@realm$+" Square."; + close; + } + mes "[Gate Manager]"; + mes "Proceed investing under your guild name."; + callfunc "F_Invest_Abyss","$fund_"+.@npc$+"0"+.@id,"[Gate Manager]"; + end; + case 2: + callsub L_Enter,1,.@realm$; + mes "[Gate Manager]"; + mes "You are interested in exploring the "+.@realm$+" Guild Dungeon Deepest Layer (2F)."; + mes "Let me guide you. Good luck."; + close2; + if (compare(strnpcinfo(2),"alde")) { + switch(.@id) { + case 1: warp "gld_dun02_2",32,122; end; + case 2: warp "gld_dun02_2",79,30; end; + case 3: warp "gld_dun02_2",165,38; end; + case 4: warp "gld_dun02_2",160,148; end; + case 5: warp "gld_dun02_2",103,169; end; + } + } else if (compare(strnpcinfo(2),"gef")) { + switch(.@id) { + case 1: warp "gld_dun04_2",39,258; end; + case 2: warp "gld_dun04_2",125,270; end; + case 3: warp "gld_dun04_2",268,251; end; + case 4: warp "gld_dun04_2",268,108; end; + case 5: warp "gld_dun04_2",230,35; end; + } + } else if (compare(strnpcinfo(2),"pay")) { + switch(.@id) { + case 1: warp "gld_dun01_2",186,165; end; + case 2: warp "gld_dun01_2",54,165; end; + case 3: warp "gld_dun01_2",54,39; end; + case 4: warp "gld_dun01_2",186,39; end; + case 5: warp "gld_dun01_2",223,202; end; + } + } else if (compare(strnpcinfo(2),"prt")) { + switch(.@id) { + case 1: warp "gld_dun03_2",28,251; end; + case 2: warp "gld_dun03_2",164,268; end; + case 3: warp "gld_dun03_2",164,179; end; + case 4: warp "gld_dun03_2",268,203; end; + case 5: warp "gld_dun03_2",199,28; end; + } + } + end; + case 3: + callsub L_Enter,2,.@realm$; + mes "[Gate Manager]"; + mes "Let me guide you to the Abyss Gap connected with "+.@realm$+", the Abyss Gate 'Way of the Warrior'."; + close2; + if (compare(strnpcinfo(2),"alde")) { + switch(.@id) { + case 1: warp "gld2_ald",175,41; end; + case 2: warp "gld2_ald",77,64; end; + case 3: warp "gld2_ald",46,127; end; + case 4: warp "gld2_ald",104,246; end; + case 5: warp "gld2_ald",241,156; end; + } + } else if (compare(strnpcinfo(2),"gef")) { + switch(.@id) { + case 1: warp "gld2_gef",28,199; end; + case 2: warp "gld2_gef",217,46; end; + case 3: warp "gld2_gef",171,195; end; + case 4: warp "gld2_gef",30,67; end; + case 5: warp "gld2_gef",115,40; end; + } + } else if (compare(strnpcinfo(2),"pay")) { + switch(.@id) { + case 1: warp "gld2_pay",33,112; end; + case 2: warp "gld2_pay",119,27; end; + case 3: warp "gld2_pay",205,111; end; + case 4: warp "gld2_pay",175,221; end; + case 5: warp "gld2_pay",61,221; end; + } + } else if (compare(strnpcinfo(2),"prt")) { + switch(.@id) { + case 1: warp "gld2_prt",10,27; end; + case 2: warp "gld2_prt",14,247; end; + case 3: warp "gld2_prt",259,236; end; + case 4: warp "gld2_prt",226,25; end; + case 5: warp "gld2_prt",97,11; end; + } + } + end; + case 4: + mes "[Gate Manager]"; + mes "Canceled."; + close; + } + end; + +L_Enter: + set .@invest_status, callfunc("F_Invest_Status"); + if (.@invest_status == 3) { + set .@status, getd("$"+.@npc$+"_invest_result"); + if ((getarg(0) == 1 && .@status == 2) || .@status == 3) + return; + else { + mes "[Gate Manager]"; + mes getarg(1)+" was not chosen to be connected with a gate this time."; + mes "Please wait for the next investment duration."; + close; + } + } else if (.@invest_status < 3) { + mes "[Gate Manager]"; + mes "There are currently no connected dungeon gates."; + mes "A gate will be connected as soon as the investment results are available."; + mes "Please wait."; + close; + } else { + mes "[Gate Manager]"; + mes "The gate will disappear soon."; + mes "The dungeon is no longer accessible."; + mes "Please try again next time."; + close; + } +} + +// Item Investments +//============================================================ +malangdo,218,126,4 script Cat Paw Merchants Notice 857,{ + mes "<< Cat Paw Merchants Notice >>"; + mes "'^C379CEInvest Unused Items for Prizes!^000000'"; + next; + switch(select("Read Notice:Check Event 1:Check Event 2")) { + case 1: + mes "- Notice -"; + mes "Hello all Cat Paw Merchants customers! With your love, we Cat Paw Merchants are growing every day. All executives and staff members promise to do our best to further our frontier and development."; + next; + mes "- Event Notice! -"; + mes " An Event called '^C379CEInvest Unused Items for Prizes!^000000' is under way, where you could exchange unused items in your storage for Investment Certificate of the Cat Paw Merchants."; + next; + mes "Exchangeable items will be announced on a separate sheet. Thank you for your time."; + mes "- From all the employees of Cat Paw Merchants -"; + next; + mes "There is a small warning at the bottom."; + mes " "; + mes "^FF0000This event could be changed or repealed due to the Merchants' situation.^000000"; + close; + case 2: + mes "'^C379CEInvest Unused Items for Prizes!^000000'"; + mes "There are details of Event 1."; + next; + setarray .@event1$[0], + "Wings of the Insect Queen","Crown of the Fly King","I hear Dragon Scales are tough 01","The Meaning of the Mother's Nightmare", + "To refine ore","Hekekek Orcs, Orcs!!","Study of Yin-Yang","Secrets of the Pyramid King","Tick-tock the time goes", + "Planting trees on Mellow Island","Ancient language research","Weapons made of sharp teeth","Toy boss doll 01", + "A tiger is just a cat after all","The shattered spear and shield?","Toy boss doll 02","Best in summer! Cold scales", + "Piece of Thanatos' armor","I hear Dragon Scales are tough 02","The identity of the creepy eye","If only I could see!"; + set .@menu$, "Quit:"+implode(.@event1$[0],":"); + while(1) { + set .@i, select(.@menu$)-1; + switch(.@i) { + case 0: close; + case 1: set .@str$,"2 Pieces of Queen's Wing"; break; + case 2: set .@str$,"2 Broken Crowns"; break; + case 3: set .@str$,"2 Fire Dragon Scales"; break; + case 4: set .@str$,"3 Mother's Nightmares"; break; + case 5: set .@str$,"5 Gemstones"; break; + case 6: set .@str$,"5 Heroic Emblems"; break; + case 7: set .@str$,"3 Taeguk Plates"; break; + case 8: set .@str$,"3 Broken Pharaoh Symbols and 3 Tutankhamen's Masks"; break; + case 9: set .@str$,"2 Pocket Watches"; break; + case 10: set .@str$,"3 Young Twigs"; break; + case 11: set .@str$,"5 Rossata Pieces"; break; + case 12: set .@str$,"5 Fangs of Garm"; break; + case 13: set .@str$,"3 Baphomet Dolls"; break; + case 14: set .@str$,"1 Tiger's Footskin and 5 Tiger Skins"; break; + case 15: set .@str$,"3 Broken Shield Pieces and 3 Shining Spear Blades"; break; + case 16: set .@str$,"3 Osiris Dolls"; break; + case 17: set .@str$,"1 Ice Scale"; break; + case 18: set .@str$,"1 Skeletal Armor Piece"; break; + case 19: set .@str$,"1 Darkred Scale Piece"; break; + case 20: set .@str$,"2 Wills of Red Darkness"; break; + case 21: set .@str$,"2 Foolishness of the Blind"; break; + } + mes "["+.@event1$[.@i-1]+"]"; + mes .@str$+" for one Cat Paw Merchants Investment Certificate."; + next; + } + case 3: + mes "Look out for the next '^C379CEInvest Unused Items for Prizes!^000000' Event 2!! Coming up real soon!"; + close; + } +} + +malangdo,218,123,1 script Namis#invest 545,4,4,{ + if (checkweight(1201,1) == 0 || MaxWeight - Weight < 1000) { + mes "- Currently you're carrying -"; + mes "- too many items with you. -"; + mes "- Please try again after you -"; + mes "- lose some weight. -"; + close; + } + emotion e_omg; + emotion e_an; + emotion e_ag; + mes "[Namis]"; + mes "Purr-Purr-Purrr-Purrrr-Pur~ Meow!!"; + mes "Wh-- What? How rude. You scared me."; + next; + switch(select("What do you need? I'll invest!:What's the purpose of this event?:Were you asleep?")) { + case 1: + break; + case 2: + mes "[Namis]"; + mes "So, another pushover in contract with the Cat Paw Merchants?"; + next; + select("Huh? What! You calling me a pushover?"); + mes "[Namis]"; + mes "I'll say this just once, so you listen good!"; + mes "We, the Cat Paw Merchants have planned an event for loyal workers like yourself."; + next; + mes "[Namis]"; + mes "Run along to your storage and bring back rotting antiques to us and we'll exchange them for the oh-so valuable 'Cat Paw Merchants Investment Certificate'."; + next; + mes "[Namis]"; + mes "It will be wise for you to do so because the Cat Paw Merchants are doing this at a loss!"; + next; + mes "[Namis]"; + mes "Details are on the notice."; + close; + case 3: + mes "[Namis]"; + mes "Hick- Slurp-"; + mes "Remember, human! There's no other cat who works as hard as I do."; + close; + } + mes "[Namis]"; + mes "You must be here to participate in the '^C379CEInvest Unused Items for Prizes!^000000' event of the Cat Paw Merchants."; + next; + mes "[Namis]"; + mes "So, which event do you wish to participate in?"; + next; + switch(select("Not interested:Event 1 Items:Event 2 Items")) { + case 1: + mes "[Namis]"; + mes "Don't you mess with a busy cat!"; + close; + case 2: + mes "[Namis]"; + mes "So you're in for Event 1."; + mes "Choose from the shown list."; + next; + setarray .@event1$[0], + "Wings of the Insect Queen","Crown of the Fly King","I hear Dragon Scales are tough 01","The Meaning of the Mother's Nightmare", + "To refine ore","Hekekek Orcs, Orcs!!","Study of Yin-Yang","Secrets of the Pyramid King","Tick-tock the time goes", + "Planting trees on Mellow Island","Ancient language research","Weapons made of sharp teeth","Toy boss doll 01", + "A tiger is just a cat after all","The shattered spear and shield?","Toy boss doll 02","Best in summer! Cold scales", + "Piece of Thanatos' armor","I hear Dragon Scales are tough 02","The identity of the creepy eye","If only I could see!"; + set .@i, select(implode(.@event1$[0],":"))-1; + switch(.@i+1) { + case 1: callsub L_Check,"2 Pieces of Queen's Wing",6326,2,"Wings of the Insect Queen? What a pitiful name. I would've given some cool names!",.@event1$[.@i]; + case 2: callsub L_Check,"2 Broken Crowns",7754,2,"For crying out loud! Those cats working on these events must be playing around. Can't they think of a better name?",.@event1$[.@i]; + case 3: callsub L_Check,"2 Fire Dragon Scales",7451,2,"Dragon scales? Well... I guess they are tough. But what are they going to use them for?",.@event1$[.@i]; + case 4: callsub L_Check,"3 Mother's Nightmares",7020,3,"Even though I don't have the authority to find out, I wonder what they're doing with the collected items?",.@event1$[.@i]; + case 5: callsub L_Check,"5 Gemstones",7300,5,"Something useful for a change. The ore will end up as nice pieces of jewelry.",.@event1$[.@i]; + case 6: callsub L_Check,"5 Heroic Emblems",968,5,"Good, good. This is the kind of name I wanted!",.@event1$[.@i]; + case 7: callsub L_Check,"3 Taeguk Plates",7169,3,"Taking in something like this, maybe they're up to something dangerous.",.@event1$[.@i]; + case 8: callsub L_Check,"3 Broken Pharaoh Symbols and 3 Tutankhamen's Masks",7113,3,"I hear the pyramids are in Morroc, but I've never been there. Some humans call it Morco.",.@event1$[.@i],7114,3; + case 9: callsub L_Check,"2 Pocket Watches",7513,2,"Those lazy merchants, why do they need pocket watches they don't even use?",.@event1$[.@i]; + case 10: callsub L_Check,"3 Young Twigs",7018,3,"Mellow Island has a climate like with where we cats used to live. But the trees die out sometimes due to it being an island.",.@event1$[.@i]; + case 11: callsub L_Check,"5 Rossata Pieces",7211,5,"I guess they collect these because humans have them, but what's the use of researching ancient languages?",.@event1$[.@i]; + case 12: callsub L_Check,"5 Fangs of Garm",7036,5,"Weak humans need sharp weapons, but cats already have nice and sharp claws, so why are we collecting these!!",.@event1$[.@i]; + case 13: callsub L_Check,"3 Baphomet Dolls",750,3,"Baphomet dolls are great for playing around with.",.@event1$[.@i]; + case 14: callsub L_Check,"1 Tiger's Footskin and 5 Tiger Skins",1030,1,"Did you know that tigers are cats too? Therefore, cats are better than tigers.",.@event1$[.@i],1029,5; + case 15: callsub L_Check,"3 Broken Shield Pieces and 3 Shining Spear Blades",7108,3,"I don't know what they want with these.",.@event1$[.@i],7109,3; + case 16: callsub L_Check,"3 Osiris Dolls",751,3,"Shame~ I never got to play with an Osiris doll.",.@event1$[.@i]; + case 17: callsub L_Check,"1 Ice Scale",7562,1,"Mellow Island is a fabulous place to live. But the ships are too hot.",.@event1$[.@i]; + case 18: callsub L_Check,"1 Skeletal Armor Piece",7450,1,"Ewww... Why would they collect something so creepy?",.@event1$[.@i]; + case 19: callsub L_Check,"1 Darkred Scale Piece",6091,1,"Dragon scales? Well... I guess they are tough. But what are they going to use them for?",.@event1$[.@i]; + case 20: callsub L_Check,"2 Wills of Red Darkness",7566,2,"Interesting! Does it scream or something when I poke it in the eye?",.@event1$[.@i]; + case 21: callsub L_Check,"2 Foolishness of the Blind",7021,2,"This blind man is foolish in not knowing that gathering 300 cats cures blindness...",.@event1$[.@i]; + } + case 3: + mes "[Namis]"; + mes "Participate in Event 2?"; + mes "It is not yet in motion. Wait for it!"; + close; + } + end; +L_Check: + set .@args, getargcount(); + if (.@args > 5) { + if (countitem(getarg(5)) < getarg(6)) + set .@items,1; //incomplete + else + set .@items,2; //complete + } + if (countitem(getarg(1)) < getarg(2) || .@items == 1) { + mes "[Namis]"; + mes "You don't have the items?"; + mes getarg(0)+" exchange for one Cat Paw Merchants Investment Certificate."; + next; + mes "[Namis]"; + mes "Don't bother me and look up the details on the board over there!"; + close; + } + mes "[Namis]"; + mes "'^8E5601"+getarg(4)+" Event^000000'"; + mes "Seems to be the right items."; + mes getarg(3); + mes "Oh! Almost forgot. Will you invest?"; + next; + if(select("Invest:Don't Invest") == 2) { + mes "[Namis]"; + mes "Don't you mess with a busy cat!"; + close; + } + delitem getarg(1),getarg(2); + if (.@items == 2) + delitem getarg(5),getarg(6); + getitem 6489,1; //Cats_Invest_Certif + mes "[Namis]"; + mes "Here's your Certificate. Always be grateful to the Merchants for these events!"; + close; +OnTouch: + if (rand(2)) + emotion e_yawn; + else + specialeffect EF_SLEEPATTACK; + end; +} + +// Investment Rewards +//============================================================ +malangdo,215,119,4 script Thanks Ticket Machine 564,{ + if (MaxWeight - Weight < 4500 || checkweight(1201,1) == 0) { + mes "- Currently you're carrying -"; + mes "- too many items with you. -"; + mes "- Please try again after you -"; + mes "- lose some weight. -"; + close; + } + mes "[Vending Machine Notice]"; + mes "^6815EA1. Don't kick the machine please. @_@"; + mes "2. You can only insert Invest Thanks Ticket."; + mes "3. About the Jelly Box, if you open it, it gives you a random item."; + mes "4. Hope you enjoy~^000000"; + mes "- Mr. Cat, the Machine Owner -"; + next; + switch(select("Finish:Purchase:Red Paw Jelly Bag (5 Tickets):Black Paw Jelly Bag (50 Tickets)")) { + case 1: + close; + case 2: + mes "The Vending Machine is selling items in the following list."; + next; + switch(select("Finish:1 Siege Arrow Quiver A (2 Tickets):1 Siege Arrow Quiver S (2 Tickets):30 White Potion (12 Tickets):30 White Slim Potion (14 Tickets):10 Dark Water (20 Tickets):20 Siege_Violet_Potion (30 Tickets):10 Coldproof Potion (30 Tickets):10 Thunderproof Potion (30 Tickets):10 Earthproof Potion (30 Tickets):10 Fireproof Potion (30 Tickets):10 Elemental Converter[Fire] (30 Tickets)")) { + case 1: close; + case 2: callsub L_Purchase,2,12678,1; //Siege_Arrow_Quiver_A + case 3: callsub L_Purchase,2,12677,1; //Siege_Arrow_Quiver_S + case 4: callsub L_Purchase,12,504,30; //White_Potion + case 5: callsub L_Purchase,14,547,30; //White_Slim_Potion + case 6: callsub L_Purchase,20,12020,10; //Water_Of_Darkness + case 7: callsub L_Purchase,30,11547,20; //Woe_Violet_Potion + case 8: callsub L_Purchase,30,12119,10; //Resist_Water + case 9: callsub L_Purchase,30,12121,10; //Resist_Wind + case 10: callsub L_Purchase,30,12120,10; //Resist_Earth + case 11: callsub L_Purchase,30,12118,10; //Resist_Fire + case 12: callsub L_Purchase,30,12114,10,"Elemental Converter[Fire]"; //Elemental_Fire + case 13: callsub L_Purchase,30,12115,10,"Elemental Converter[Water]"; //Elemental_Water + case 14: callsub L_Purchase,30,12117,10,"Elemental Converter[Wind]"; //Elemental_Wind + case 15: callsub L_Purchase,30,12116,10,"Elemental Converter[Earth]"; //Elemental_Earth + } + end; + case 3: + mes "Red Paw Jelly Bag Button chosen. Need to insert 5 ^FF0000Invest Thanks Ticket^000000 and a random item will appear."; + next; + if (countitem(6488) < 5) { + mes "You don't have enough ^FF0000Invest Thanks Ticket^000000 to proceed."; + close; + } + delitem 6488,5; //Thanks_Invest_Ticket + set .@i, rand(1,10000); + if (.@i <= 100) callsub L_Bag,12531,1; //White_Potion_Box + else if (.@i <= 200) callsub L_Bag,12549,1; //White_Slim_Pot_Box2 + else if (.@i <= 250) callsub L_Bag,11549,10; //Woe_Blue_Potion + else if (.@i <= 660) callsub L_Bag,617,1; //Old_Violet_Box + else if (.@i <= 710) callsub L_Bag,12532,1; //Royal_Jelly_Box2 + else if (.@i <= 760) callsub L_Bag,12533,1; //Blue_Herb_Box2 + else if (.@i <= 810) callsub L_Bag,505,5; //Blue_Potion + else if (.@i <= 1110) callsub L_Bag,644,1; //Gift_Box + else if (.@i <= 1120) callsub L_Bag,607,1; //Yggdrasilberry + else if (.@i <= 1130) callsub L_Bag,608,2; //Seed_Of_Yggdrasil + else if (.@i <= 1140) callsub L_Bag,12292,5; //Unripe_Fruit + else if (.@i <= 1150) callsub L_Bag,12293,5; //Dried_Yggdrasilberry + else if (.@i <= 1250) callsub L_Bag,12679,1; //Sg_White_Potion_Box + else if (.@i <= 1471) callsub L_Bag,603,1; //Old_Blue_Box + else if (.@i <= 1571) callsub L_Bag,12550,1,"Poison Bottle Box(30)"; //Poison_Bottle_Box2 + else if (.@i <= 1671) callsub L_Bag,12020,10; //Water_Of_Darkness + else if (.@i <= 1871) callsub L_Bag,12030,5; //Box_Of_Grudge + else if (.@i <= 2071) callsub L_Bag,12031,5; //Sleepy_Box + else if (.@i <= 2371) callsub L_Bag,12033,2; //Box_Of_Sunlight + else if (.@i <= 2571) callsub L_Bag,12114,5,"Elemental Converter[Fire]"; //Elemental_Fire + else if (.@i <= 2771) callsub L_Bag,12115,5,"Elemental Converter[Water]"; //Elemental_Water + else if (.@i <= 2971) callsub L_Bag,12117,5,"Elemental Converter[Wind]"; //Elemental_Wind + else if (.@i <= 3171) callsub L_Bag,12116,5,"Elemental Converter[Earth]"; //Elemental_Earth + else if (.@i <= 3271) callsub L_Bag,12680,1; //Sg_Blue_Potion_Box + else if (.@i <= 3471) callsub L_Bag,12118,5; //Resist_Fire + else if (.@i <= 3671) callsub L_Bag,12119,5; //Resist_Water + else if (.@i <= 3871) callsub L_Bag,12121,5; //Resist_Wind + else if (.@i <= 4071) callsub L_Bag,12120,5; //Resist_Earth + else if (.@i <= 4271) callsub L_Bag,929,20; //Immortal_Heart + else if (.@i <= 4471) callsub L_Bag,1059,20; //Transparent_Cloth + else if (.@i <= 4671) callsub L_Bag,905,20; //Stem + else if (.@i <= 4871) callsub L_Bag,606,10; //Aloebera + else if (.@i <= 5071) callsub L_Bag,609,10; //Amulet + else if (.@i <= 5271) callsub L_Bag,710,2; //Illusion_Flower + else if (.@i <= 5471) callsub L_Bag,576,20; //Prickly_Fruit + else if (.@i <= 5671) callsub L_Bag,621,10; //Bitter_Herb + else if (.@i <= 5871) callsub L_Bag,709,10; //Izidor + else if (.@i <= 6071) callsub L_Bag,605,10; //Anodyne + else if (.@i <= 6171) callsub L_Bag,11548,10; //Woe_White_Potion + else if (.@i <= 6371) callsub L_Bag,706,10; //Four_Leaf_Clover + else if (.@i <= 6571) callsub L_Bag,521,10; //Leaflet_Of_Aloe + else if (.@i <= 6771) callsub L_Bag,707,10; //Singing_Plant + else if (.@i <= 6971) callsub L_Bag,610,10; //Leaf_Of_Yggdrasil + else if (.@i <= 7021) callsub L_Bag,12676,1; //Sg_Violet_Potion_Box + else if (.@i <= 7171) callsub L_Bag,6249,10; //Savage_Meat + else if (.@i <= 7321) callsub L_Bag,6252,10; //Wolf_Blood + else if (.@i <= 7471) callsub L_Bag,6254,10; //Beef_Head_Meat + else if (.@i <= 7621) callsub L_Bag,6253,10; //Cold_Ice + else if (.@i <= 7771) callsub L_Bag,6256,10; //Ice_Fragment + else if (.@i <= 7921) callsub L_Bag,6257,10; //Ice_Crystal + else if (.@i <= 8071) callsub L_Bag,6260,10; //Petti_Tail + else if (.@i <= 8309) callsub L_Bag,7932,20; //Poison_Herb_Nerium + else if (.@i <= 8547) callsub L_Bag,7933,20; //Poison_Herb_Rantana + else if (.@i <= 8785) callsub L_Bag,7934,20; //Poison_Herb_Makulata + else if (.@i <= 9023) callsub L_Bag,7935,20; //Poison_Herb_Seratum + else if (.@i <= 9261) callsub L_Bag,7936,20; //Poison_Herb_Scopolia + else if (.@i <= 9499) callsub L_Bag,7937,20; //Poison_Herb_Amoena + else if (.@i <= 9699) callsub L_Bag,6217,20; //Mandragora_Flowerpot + else callsub L_Bag,12016,10; //Speed_Up_Potion + end; + case 4: + mes "Black Paw Jelly Bag Button chosen. Need to insert 50 ^FF0000Invest Thanks Ticket^000000 and a random item will appear."; + next; + if (countitem(6488) < 50) { + mes "You don't have enough ^FF0000Invest Thanks Ticket^000000 to proceed."; + close; + } + delitem 6488,50; //Thanks_Invest_Ticket + set .@i, rand(1,10000); + if (.@i <= 100) callsub L_Bag,12531,1; //White_Potion_Box + else if (.@i <= 200) callsub L_Bag,12549,1; //White_Slim_Pot_Box2 + else if (.@i <= 250) callsub L_Bag,11549,20; //Woe_Blue_Potion + else if (.@i <= 450) callsub L_Bag,617,1; //Old_Violet_Box + else if (.@i <= 500) callsub L_Bag,12532,1; //Royal_Jelly_Box2 + else if (.@i <= 550) callsub L_Bag,12533,1; //Blue_Herb_Box2 + else if (.@i <= 600) callsub L_Bag,505,10; //Blue_Potion + else if (.@i <= 800) callsub L_Bag,644,1; //Gift_Box + else if (.@i <= 810) callsub L_Bag,607,2; //Yggdrasilberry + else if (.@i <= 820) callsub L_Bag,608,3; //Seed_Of_Yggdrasil + else if (.@i <= 830) callsub L_Bag,12292,10; //Unripe_Fruit + else if (.@i <= 840) callsub L_Bag,12293,10; //Dried_Yggdrasilberry + else if (.@i <= 940) callsub L_Bag,12679,1; //Sg_White_Potion_Box + else if (.@i <= 1140) callsub L_Bag,603,1; //Old_Blue_Box + else if (.@i <= 1240) callsub L_Bag,12550,1,"Poison Bottle Box(30)"; //Poison_Bottle_Box2 + else if (.@i <= 1340) callsub L_Bag,12020,20; //Water_Of_Darkness + else if (.@i <= 1440) callsub L_Bag,12030,10; //Box_Of_Grudge + else if (.@i <= 1540) callsub L_Bag,12031,10; //Sleepy_Box + else if (.@i <= 1690) callsub L_Bag,12033,4; //Box_Of_Sunlight + else if (.@i <= 1790) callsub L_Bag,12114,10,"Elemental Converter[Fire]"; //Elemental_Fire + else if (.@i <= 1890) callsub L_Bag,12115,10,"Elemental Converter[Water]"; //Elemental_Water + else if (.@i <= 1990) callsub L_Bag,12117,10,"Elemental Converter[Wind]"; //Elemental_Wind + else if (.@i <= 2090) callsub L_Bag,12116,10,"Elemental Converter[Earth]"; //Elemental_Earth + else if (.@i <= 2190) callsub L_Bag,12680,1; //Sg_Blue_Potion_Box + else if (.@i <= 2290) callsub L_Bag,12118,10; //Resist_Fire + else if (.@i <= 2390) callsub L_Bag,12119,10; //Resist_Water + else if (.@i <= 2490) callsub L_Bag,12121,10; //Resist_Wind + else if (.@i <= 2590) callsub L_Bag,12120,10; //Resist_Earth + else if (.@i <= 2690) callsub L_Bag,929,40; //Immortal_Heart + else if (.@i <= 2790) callsub L_Bag,1059,40; //Transparent_Cloth + else if (.@i <= 2890) callsub L_Bag,905,40; //Stem + else if (.@i <= 2990) callsub L_Bag,606,20; //Aloebera + else if (.@i <= 3090) callsub L_Bag,609,20; //Amulet + else if (.@i <= 3190) callsub L_Bag,710,4; //Illusion_Flower + else if (.@i <= 3290) callsub L_Bag,576,40; //Prickly_Fruit + else if (.@i <= 3390) callsub L_Bag,621,20; //Bitter_Herb + else if (.@i <= 3490) callsub L_Bag,709,20; //Izidor + else if (.@i <= 3590) callsub L_Bag,605,20; //Anodyne + else if (.@i <= 3690) callsub L_Bag,11548,20; //Woe_White_Potion + else if (.@i <= 3790) callsub L_Bag,706,20; //Four_Leaf_Clover + else if (.@i <= 3890) callsub L_Bag,521,20; //Leaflet_Of_Aloe + else if (.@i <= 3990) callsub L_Bag,707,20; //Singing_Plant + else if (.@i <= 4090) callsub L_Bag,610,20; //Leaf_Of_Yggdrasil + else if (.@i <= 4140) callsub L_Bag,12676,1; //Sg_Violet_Potion_Box + else if (.@i <= 4240) callsub L_Bag,6249,20; //Savage_Meat + else if (.@i <= 4340) callsub L_Bag,6252,20; //Wolf_Blood + else if (.@i <= 4440) callsub L_Bag,6254,20; //Beef_Head_Meat + else if (.@i <= 4540) callsub L_Bag,6253,20; //Cold_Ice + else if (.@i <= 4640) callsub L_Bag,6256,20; //Ice_Fragment + else if (.@i <= 4740) callsub L_Bag,6257,20; //Ice_Crystal + else if (.@i <= 4840) callsub L_Bag,6260,20; //Petti_Tail + else if (.@i <= 4940) callsub L_Bag,7932,40; //Poison_Herb_Nerium + else if (.@i <= 5040) callsub L_Bag,7933,40; //Poison_Herb_Rantana + else if (.@i <= 5140) callsub L_Bag,7934,40; //Poison_Herb_Makulata + else if (.@i <= 5240) callsub L_Bag,7935,40; //Poison_Herb_Seratum + else if (.@i <= 5340) callsub L_Bag,7936,40; //Poison_Herb_Scopolia + else if (.@i <= 5440) callsub L_Bag,7937,40; //Poison_Herb_Amoena + else if (.@i <= 5540) callsub L_Bag,6217,40; //Mandragora_Flowerpot + else if (.@i <= 6000) callsub L_Bag,12016,20; //Speed_Up_Potion + else if (.@i <= 6500) callsub L_Bag,2483,1; //Siege_Greave + else if (.@i <= 7000) callsub L_Bag,2484,1; //Siege_Boots + else if (.@i <= 7500) callsub L_Bag,2485,1; //Siege_Shoes + else if (.@i <= 8000) callsub L_Bag,2586,1; //Siege_Manteau + else if (.@i <= 8500) callsub L_Bag,2587,1; //Siege_Muffler + else if (.@i <= 9000) callsub L_Bag,15046,1; //Siege_Plate + else if (.@i <= 9500) callsub L_Bag,15047,1; //Siege_Suits + else callsub L_Bag,15048,1; //Siege_Robe + end; + } + end; + +//callsub L_Purchase,,,{,}; +L_Purchase: + if (countitem(6488) < getarg(0)) { + mes "You don't have enough ^FF0000Invest Thanks Ticket^000000 to proceed."; + close; + } + delitem 6488,getarg(0); //Thanks_Invest_Ticket + getitem getarg(1),getarg(2); + mes "- Done! -"; + next; + mes "The item ^0000FF"+((getargcount() > 3)?getarg(3,""):getitemname(getarg(1)))+"^000000 has been obtained."; + close; + +//callsub L_Bag,,{,}; +L_Bag: + getitem getarg(0),getarg(1); + mes "- Done! -"; + next; + mes "The item ^0000FF"+((getargcount() > 2)?getarg(2,""):getitemname(getarg(0)))+"^000000 has been obtained."; + close; +} diff --git a/npc/re/guild/invest_npc.txt b/npc/re/guild/invest_npc.txt new file mode 100644 index 000000000..3c6c45ee5 --- /dev/null +++ b/npc/re/guild/invest_npc.txt @@ -0,0 +1,66 @@ +//===== rAthena Script ======================================= +//= Hall of Abyss - NPC Duplicates +//===== By: ================================================== +//= Euphy +//===== Current Version: ===================================== +//= 1.0 +//===== Compatible With: ===================================== +//= rAthena SVN +//===== Description: ========================================= +//= Expansion for War of Emperium FE. +//= Invest in each realm to unlock new maps: +//= - Guild Dungeon F2, total 20,000,000z. +//= - Hall of Abyss, total 70,000,000z. +//===== Additional Comments: ================================= +//= 1.0 First version. [Euphy] +//============================================================ + +// Realms - Merchant Guilds, Gate Managers, Status Boards +//============================================================ +alde_gld,186,157,3 duplicate(Cat Paw Merchant Guild) Cat Paw Merchant Megrez 549 +alde_gld,191,164,3 duplicate(Gate Manager#realm) Gate Manager#alde_f00 421 +alde_gld,188,158,3 duplicate(Investment Status Board) Investment Status Board::InvestStatus_Alde 857 + +gef_fild13,187,208,3 duplicate(Cat Paw Merchant Guild) Cat Paw Merchant Meraq 549 +gef_fild13,189,206,3 duplicate(Gate Manager#realm) Gate Manager#gef_f00 421 +gef_fild13,190,209,3 duplicate(Investment Status Board) Investment Status Board::InvestStatus_Gef 857 + +pay_gld,203,189,3 duplicate(Cat Paw Merchant Guild) Cat Paw Merchant Phecda 549 +pay_gld,206,189,3 duplicate(Gate Manager#realm) Gate Manager#pay_f00 421 +pay_gld,200,189,5 duplicate(Investment Status Board) Investment Status Board::InvestStatus_Pay 857 + +prt_gld,158,96,5 duplicate(Cat Paw Merchant Guild) Cat Paw Merchant Dubae 549 +prt_gld,161,96,3 duplicate(Gate Manager#realm) Gate Manager#prt_f00 421 +prt_gld,163,99,3 duplicate(Investment Status Board) Investment Status Board::InvestStatus_Prt 857 + +// Inside Castles - Gate Managers +//============================================================ +aldeg_cas01,85,105,4 duplicate(Gate Manager#castle) Gate Manager#alde_f01 421 +aldeg_cas02,124,49,3 duplicate(Gate Manager#castle) Gate Manager#alde_f02 421 +aldeg_cas03,121,75,3 duplicate(Gate Manager#castle) Gate Manager#alde_f03 421 +aldeg_cas04,25,67,7 duplicate(Gate Manager#castle) Gate Manager#alde_f04 421 +aldeg_cas05,54,200,3 duplicate(Gate Manager#castle) Gate Manager#alde_f05 421 + +gefg_cas01,39,49,4 duplicate(Gate Manager#castle) Gate Manager#gef_f01 421 +gefg_cas02,10,65,4 duplicate(Gate Manager#castle) Gate Manager#gef_f02 421 +gefg_cas03,100,87,4 duplicate(Gate Manager#castle) Gate Manager#gef_f03 421 +gefg_cas04,35,44,3 duplicate(Gate Manager#castle) Gate Manager#gef_f04 421 +gefg_cas05,84,46,3 duplicate(Gate Manager#castle) Gate Manager#gef_f05 421 + +payg_cas01,129,59,3 duplicate(Gate Manager#castle) Gate Manager#pay_f01 421 +payg_cas02,27,277,3 duplicate(Gate Manager#castle) Gate Manager#pay_f02 421 +payg_cas03,51,266,3 duplicate(Gate Manager#castle) Gate Manager#pay_f03 421 +payg_cas04,39,264,4 duplicate(Gate Manager#castle) Gate Manager#pay_f04 421 +payg_cas05,272,252,4 duplicate(Gate Manager#castle) Gate Manager#pay_f05 421 + +prtg_cas01,114,178,3 duplicate(Gate Manager#castle) Gate Manager#prt_f01 421 +prtg_cas02,89,63,5 duplicate(Gate Manager#castle) Gate Manager#prt_f02 421 +prtg_cas03,72,109,3 duplicate(Gate Manager#castle) Gate Manager#prt_f03 421 +prtg_cas04,29,263,4 duplicate(Gate Manager#castle) Gate Manager#prt_f04 421 +prtg_cas05,24,23,4 duplicate(Gate Manager#castle) Gate Manager#prt_f05 421 + +// iRO NPC Locations +//============================================================ +//prt_gld,148,253,4 duplicate(Cat Paw Merchants Notice) Cat Paw Merchants Notice::CatPawNotice_iRO 857 +//prt_gld,145,255,6 duplicate(Namis#invest) Namis::Namis_iRO 545,4,4 +//prt_gld,165,50,4 duplicate(Thanks Ticket Machine) Thanks Ticket Machine::ThanksMachine_iRO 564 diff --git a/npc/re/mobs/dungeons/gld_dun.txt b/npc/re/mobs/dungeons/gld_dun.txt deleted file mode 100644 index 7ac2d9f9f..000000000 --- a/npc/re/mobs/dungeons/gld_dun.txt +++ /dev/null @@ -1,52 +0,0 @@ -//===== Hercules Script ====================================== -//= Guild Dungeons Monster Spawn Script -//===== By: ================================================== -//= Athena (1.0) -//===== Current Version: ===================================== -//= 1.3 -//===== Compatible With: ===================================== -//= Hercules -//===== Additional Comments: ================================= -//= 1.2 Official kRO 10.1 spawns [Playtester] -//= 1.3 Corrected MVP spawn variance. [Gepard] -//============================================================ - -//================================================== -// gld_dun01 - Guild Dungeon -//================================================== -gld_dun01,0,0,0,0 monster Am Mut 1301,20,5000,0,0 -gld_dun01,0,0,0,0 monster Skeleton General 1290,10,5000,0,0 -gld_dun01,0,0,0,0 monster Gajomart 1309,10,5000,0,0 -gld_dun01,0,0,0,0 monster Cat o' Nine Tails 1307,3,1200000,0,0 -gld_dun01,0,0,0,0 monster Vagabond Wolf 1092,1,14400000,7200000,1 -gld_dun01,0,0,0,0 boss_monster Eddga 1115,1,28800000,600000,1 - -//================================================== -// gld_dun02 - Guild Dungeon -//================================================== -gld_dun02,0,0,0,0 monster Giant Hornet 1303,10,120000,60000,0 -gld_dun02,0,0,0,0 monster Giant Spider 1304,10,240000,120000,0 -gld_dun02,0,0,0,0 monster Ancient Worm 1305,7,120000,60000,0 -gld_dun02,0,0,0,0 monster Killer Mantis 1294,5,120000,60000,0 -gld_dun02,0,0,0,0 monster Owl Baron 1295,1,5000,0,0 -gld_dun02,0,0,0,0 boss_monster Doppelganger 1046,1,28800000,600000,1 - -//================================================== -// gld_dun03 - Guild Dungeon -//================================================== -gld_dun03,0,0,0,0 monster Caterpillar 1300,20,5000,0,0 -gld_dun03,0,0,0,0 monster Creamy Fear 1293,20,5000,0,0 -gld_dun03,0,0,0,0 monster Leib Olmai 1306,20,5000,0,0 -gld_dun03,0,0,0,0 monster Gullinbursti 1311,10,5000,0,0 -gld_dun03,0,0,0,0 monster Maya Purple 1289,3,1200000,600000,0 -gld_dun03,0,0,0,0 boss_monster Maya 1147,1,28800000,600000,1 - -//================================================== -// gld_dun04 - Guild Dungeon -//================================================== -gld_dun04,0,0,0,0 monster Zombie Master 1298,29,5000,0,0 -gld_dun04,0,0,0,0 monster Wraith Dead 1291,27,5000,0,0 -gld_dun04,0,0,0,0 monster Mini Demon 1292,3,5000,0,0 -gld_dun04,0,0,0,0 monster Dark Illusion 1302,1,1200000,0,0 -gld_dun04,0,0,0,0 monster Ghostring 1120,1,14400000,7200000,1 -gld_dun04,0,0,0,0 boss_monster Dark Lord 1272,1,28800000,600000,1 diff --git a/npc/re/mobs/dungeons/gld_re.txt b/npc/re/mobs/dungeons/gld_re.txt new file mode 100644 index 000000000..29955c381 --- /dev/null +++ b/npc/re/mobs/dungeons/gld_re.txt @@ -0,0 +1,100 @@ +//===== rAthena Script ======================================= +//= Renewal Guild Monster Spawn Script +//===== By: ================================================== +//= Euphy +//===== Current Version: ===================================== +//= 1.0 +//===== Compatible With: ===================================== +//= rAthena SVN +//===== Additional Comments: ================================= +//= 1.0 First version, Hall of Abyss update. [Euphy] +//============================================================ + +//================================================== +// Baldur - gld_dun01, gld_dun01_2, gld2_pay +//================================================== +gld_dun01,0,0,0,0 monster Gullinbursti 1311,30,5000,0,0 +gld_dun01,0,0,0,0 monster Leib Olmai 1306,55,5000,0,0 +gld_dun01,0,0,0,0 monster Cat O' Nine Tails 1307,3,1200000,0,0 +gld_dun01,0,0,0,0 boss_monster Moonlight Flower 1150,1,28800000,600000,1 + +gld_dun01_2,0,0,0,0 monster Skeleton General 1290,50,5000,0,0 +gld_dun01_2,0,0,0,0 monster Am Mut 1301,15,5000,0,0 +gld_dun01_2,0,0,0,0 monster Gajomart 1309,20,5000,0,0 +gld_dun01_2,0,0,0,0 boss_monster Eddga 1115,1,28800000,600000,1 + +gld2_pay,0,0,0,0 monster Skeleton General 1290,60,5000,0,0 +gld2_pay,0,0,0,0 monster Am Mut 1301,25,5000,0,0 +gld2_pay,0,0,0,0 monster Gajomart 1309,30,5000,0,0 +gld2_pay,0,0,0,0 boss_monster General Daehyun 2253,1,28800000,600000,1 +gld2_pay,0,0,0,0 monster Samurai Soheon 2254,1,1800000,600000,1 + +//================================================== +// Luina - gld_dun02, gld_dun02_2, gld2_ald +//================================================== +gld_dun02,0,0,0,0 monster Giant Hornet 1303,30,5000,0,0 +gld_dun02,0,0,0,0 monster Ancient Worm 1305,25,5000,0,0 +gld_dun02,0,0,0,0 monster Giant Spider 1304,15,5000,0,0 +gld_dun02,0,0,0,0 boss_monster Mistress 1059,1,28800000,600000,1 + +gld_dun02_2,0,0,0,0 monster Killer Mantis 1294,30,5000,0,0 +gld_dun02_2,0,0,0,0 monster Angra Mantis 2133,40,5000,0,0 +gld_dun02_2,0,0,0,0 monster Maya Purple 1289,3,1200000,600000,0 +gld_dun02_2,0,0,0,0 boss_monster Maya 1147,1,28800000,600000,1 + +gld2_ald,0,0,0,0 monster Killer Mantis 1294,60,5000,0,0 +gld2_ald,0,0,0,0 monster Angra Mantis 2133,70,5000,0,0 +gld2_ald,0,0,0,0 monster Maya Purple 1289,3,1200000,0,0 +gld2_ald,0,0,0,0 boss_monster Gioia 2251,1,28800000,600000,1 +gld2_ald,0,0,0,0 monster Elvira 2252,1,1800000,600000,1 + +//================================================== +// Valkyrie - gld_dun03, gld_dun03_02, gld2_prt +//================================================== +gld_dun03,0,0,0,0 monster Caterpillar 1300,35,5000,0,0 +gld_dun03,0,0,0,0 monster Creamy Fear 1293,35,5000,0,0 +gld_dun03,0,0,0,0 boss_monster Baphomet 1039,1,28800000,600000,1 + +gld_dun03_2,0,0,0,0 monster Dark Axe Kobold 2284,13,5000,0,0 +gld_dun03_2,0,0,0,0 monster Dark Hammer Kobold 2285,23,5000,0,0 +gld_dun03_2,0,0,0,0 monster Dark Mace Kobold 2286,23,5000,0,0 +gld_dun03_2,0,0,0,0 monster Dark Kobold Archer 2287,23,5000,0,0 +gld_dun03_2,0,0,0,0 monster Kobold Leader 1296,1,14400000,7200000,1 +gld_dun03_2,0,0,0,0 boss_monster Atroce 1785,1,28800000,600000,1 + +gld2_prt,0,0,0,0 monster Dark Axe Kobold 2284,25,5000,0,0 +gld2_prt,0,0,0,0 monster Dark Hammer Kobold 2285,35,5000,0,0 +gld2_prt,0,0,0,0 monster Dark Mace Kobold 2286,35,5000,0,0 +gld2_prt,0,0,0,0 monster Dark Kobold Archer 2287,35,5000,0,0 +gld2_prt,0,0,0,0 boss_monster Angry Student Pyuriel 2249,1,28800000,600000,1 +gld2_prt,0,0,0,0 monster Warrior Laura 2250,1,1800000,600000,1 + +//================================================== +// Britoniah - gld_dun04, gld_dun04_02, gld2_gef +//================================================== +gld_dun04,0,0,0,0 monster Mini Demon 1292,10,5000,0,0 +gld_dun04,0,0,0,0 monster Zombie Master 1298,55,5000,0,0 +gld_dun04,0,0,0,0 monster Wraith Dead 1291,25,5000,0,0 +gld_dun04,0,0,0,0 monster Ghostring 1120,1,14400000,7200000,1 +gld_dun04,0,0,0,0 boss_monster Doppelganger 1046,1,28800000,600000,1 + +gld_dun04_2,0,0,0,0 monster Dark Frame 2282,15,5000,0,0 +gld_dun04_2,0,0,0,0 monster Dark Priest 2283,15,5000,0,0 +gld_dun04_2,0,0,0,0 monster Dark Shadow 2281,45,5000,0,0 +gld_dun04_2,0,0,0,0 monster Dark Illusion 1302,1,1200000,0,0 +gld_dun04_2,0,0,0,0 boss_monster Dark Lord 1272,1,28800000,600000,1 + +gld2_gef,0,0,0,0 monster Dark Frame 2282,20,5000,0,0 +gld2_gef,0,0,0,0 monster Dark Priest 2283,20,5000,0,0 +gld2_gef,0,0,0,0 monster Dark Shadow 2281,80,5000,0,0 +gld2_gef,0,0,0,0 monster Dark Illusion 1302,1,1200000,0,0 +gld2_gef,0,0,0,0 boss_monster Dark Guardian Kades 2255,1,28800000,600000,1 +gld2_gef,0,0,0,0 monster Rudo 2256,1,1800000,600000,1 + +//================================================== +// Treasure Chests +//================================================== +gld2_pay,0,0,0,0 monster Treasure Chest 2288,5,5000,0,0 +gld2_ald,0,0,0,0 monster Treasure Chest 2288,5,5000,0,0 +gld2_prt,0,0,0,0 monster Treasure Chest 2288,5,5000,0,0 +gld2_gef,0,0,0,0 monster Treasure Chest 2288,5,5000,0,0 diff --git a/npc/re/warps/guildcastles.txt b/npc/re/warps/guildcastles.txt new file mode 100644 index 000000000..d8eab7cea --- /dev/null +++ b/npc/re/warps/guildcastles.txt @@ -0,0 +1,43 @@ +//===== rAthena Script ======================================= +//= Guild Castles Warp Script +//===== By: ================================================== +//= Euphy +//===== Current Version: ===================================== +//= 1.0 +//===== Compatible With: ===================================== +//= rAthena SVN +//===== Description: ========================================= +//= Warp Points for Renewal Guild Castles +//===== Additional Comments: ================================= +//= 1.0 First version. [Euphy] +//============================================================ + +// Hall of Abyss +//============================================================ +gld2_prt,10,22,0 warp dun2prt_to_gld 1,1,prt_gld,252,247 +gld2_prt,14,252,0 warp dun2prt_to_gld#2 1,1,prt_gld,63,66 +gld2_prt,266,236,0 warp dun2prt_to_gld#3 1,1,prt_gld,252,247 +gld2_prt,226,21,0 warp dun2prt_to_gld#4 1,1,prt_gld,63,66 +gld2_prt,103,11,0 warp dun2prt_to_gld#5 1,1,prt_gld,252,247 +gld_dun03_2,238,274,0 warp gdun03a_prtg#abyss 1,1,prt_gld,252,247 +gld_dun03_2,42,30,0 warp gdun03b_prtg#abyss 1,1,prt_gld,63,66 +gld2_pay,33,105,0 warp dun2pay_to_gld 1,1,pay_gld,53,141 +gld2_pay,119,21,0 warp dun2pay_to_gld#2 1,1,pay_gld,53,141 +gld2_pay,205,105,0 warp dun2pay_to_gld#3 1,1,pay_gld,53,141 +gld2_pay,175,215,0 warp dun2pay_to_gld#4 1,1,pay_gld,53,141 +gld2_pay,61,215,0 warp dun2pay_to_gld#5 1,1,pay_gld,53,141 +gld_dun01_2,119,14,0 warp gdun01_payg#abyss 1,1,pay_gld,53,141 +gld2_gef,28,205,0 warp dun2gef_to_gld 1,1,gef_fild13,42,331 +gld2_gef,221,145,0 warp dun2gef_to_gld#2 1,1,gef_fild13,373,62 +gld2_gef,175,198,0 warp dun2gef_to_gld#3 1,1,gef_fild13,42,331 +gld2_gef,25,68,0 warp dun2gef_to_gld#4 1,1,gef_fild13,373,62 +gld2_gef,111,35,0 warp dun2gef_to_gld#5 1,1,gef_fild13,42,331 +gld_dun04_2,37,230,0 warp gdun04_g13a#abyss 1,1,gef_fild13,42,331 +gld_dun04_2,110,20,0 warp gdun04_g13b#abyss 1,1,gef_fild13,373,62 +gld2_ald,172,46,0 warp dun2gef_to_gld#6 1,1,alde_gld,242,121 +gld2_ald,77,58,0 warp dun2gef_to_gld#7 1,1,alde_gld,229,185 +gld2_ald,46,122,0 warp dun2gef_to_gld#8 1,1,alde_gld,242,121 +gld2_ald,104,250,0 warp dun2gef_to_gld#9 1,1,alde_gld,229,185 +gld2_ald,247,156,0 warp dun2gef_to_gld#10 1,1,alde_gld,242,121 +gld_dun02_2,20,160,0 warp gdun02a_aldega#abyss 1,1,alde_gld,229,185 +gld_dun02_2,180,112,0 warp gdun02b_aldegb#abyss 1,1,alde_gld,242,121 -- cgit v1.2.3-70-g09d2 From 2410110dece79b4598c12f1c953219f1d0d1904a Mon Sep 17 00:00:00 2001 From: Mysteries Date: Mon, 17 Jun 2013 10:17:16 -0400 Subject: Fixed BugReport: 7388 http://hercules.ws/board/tracker/issue-7388-renamed-gld-dun-for-gld-re/? gopid=18608#entry18608 Simple fix and adjusted placeholders for Hercules. --- npc/re/instances/HazyForest.txt | 16 ++++++++-------- npc/re/mobs/dungeons/gld_re.txt | 4 ++-- npc/re/scripts_monsters.conf | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'npc') diff --git a/npc/re/instances/HazyForest.txt b/npc/re/instances/HazyForest.txt index cb65f11d7..cecdadd20 100644 --- a/npc/re/instances/HazyForest.txt +++ b/npc/re/instances/HazyForest.txt @@ -1,18 +1,18 @@ -//===== rAthena Script ======================================= +//===== Hercules Script ====================================== //= Hazy Forest -//===== By: ================================================== +//===== By: ================================================== //= Euphy -//===== Current Version: ===================================== +//===== Current Version: ===================================== //= 1.0 -//===== Compatible With: ===================================== -//= rAthena SVN -//===== Description: ========================================= +//===== Compatible With: ===================================== +//= Hercules +//===== Description: ========================================= //= [Official Conversion] //= Cross through the Hazy Forest to reach the Bifrost. //= Contains the Wandering Guardian quest. -//===== Additional Comments: ================================= +//===== Additional Comments: ================================= //= 1.0 First version. [Euphy] -//============================================================ +//============================================================ // Instance Creation //============================================================ diff --git a/npc/re/mobs/dungeons/gld_re.txt b/npc/re/mobs/dungeons/gld_re.txt index 29955c381..1280755a7 100644 --- a/npc/re/mobs/dungeons/gld_re.txt +++ b/npc/re/mobs/dungeons/gld_re.txt @@ -1,11 +1,11 @@ -//===== rAthena Script ======================================= +//===== Hercules Script ====================================== //= Renewal Guild Monster Spawn Script //===== By: ================================================== //= Euphy //===== Current Version: ===================================== //= 1.0 //===== Compatible With: ===================================== -//= rAthena SVN +//= Hercules //===== Additional Comments: ================================= //= 1.0 First version, Hall of Abyss update. [Euphy] //============================================================ diff --git a/npc/re/scripts_monsters.conf b/npc/re/scripts_monsters.conf index 25811f8b3..46ab419d8 100644 --- a/npc/re/scripts_monsters.conf +++ b/npc/re/scripts_monsters.conf @@ -18,7 +18,7 @@ npc: npc/re/mobs/dungeons/ein_dun.txt npc: npc/re/mobs/dungeons/gef_dun.txt npc: npc/re/mobs/dungeons/gefenia.txt npc: npc/re/mobs/dungeons/glastheim.txt -npc: npc/re/mobs/dungeons/gld_dun.txt +npc: npc/re/mobs/dungeons/gld_re.txt npc: npc/re/mobs/dungeons/gld_dunSE.txt npc: npc/re/mobs/dungeons/gon_dun.txt npc: npc/re/mobs/dungeons/ice_dun.txt -- cgit v1.2.3-70-g09d2 From bd95eccf047bda9d72abcea0724ad34b31131ab0 Mon Sep 17 00:00:00 2001 From: jaBote Date: Wed, 19 Jun 2013 03:40:37 +0300 Subject: Update citycleaners.txt Changed a High Orc spawn (incorrect) to a Thief Bug Egg spawn (correct) in map job3_war01. Thanks to @Euphyy, who noticed it. --- npc/mobs/citycleaners.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'npc') diff --git a/npc/mobs/citycleaners.txt b/npc/mobs/citycleaners.txt index 876017fd4..749efed85 100644 --- a/npc/mobs/citycleaners.txt +++ b/npc/mobs/citycleaners.txt @@ -47,4 +47,4 @@ einbech,0,0,0,0 monster Tarou 1175,5,1800000,1500000,0 //================================================== payon_in02,23,68,5,5 monster Thief Bug Egg 1048,7,1200000,600000,0 -job3_war01,19,33,5,5 monster Thief Bug Egg 1213,1,12,60,0 +job3_war01,19,33,5,5 monster Thief Bug Egg 1048,1,12,60,0 -- cgit v1.2.3-70-g09d2