瀏覽代碼

Merge branch 'master' into feature/adoption_system_update

aleos 5 年之前
父節點
當前提交
e1193118cb

+ 1 - 1
conf/battle/client.conf

@@ -38,7 +38,7 @@ hide_woe_damage: no
 pet_hair_style: 100
 
 // Visible area size (how many squares away from a player they can see)
-area_size: 14
+area_size: 15
 
 // Maximum walk path (how many cells a player can walk going to cursor)
 max_walk_path: 17

+ 8 - 0
conf/battle/skill.conf

@@ -362,6 +362,14 @@ skill_eightpath_algorithm: yes
 // damage skills (previous behavior).
 can_damage_skill: 1
 
+// Land Protector behavior (Note 1)
+// On official servers, players standing on the border (outer cell) of the Land Protector can still be affected/hit
+// by AoE skills (if the skill has a splash effect, such as Storm Gust). The Athena behavior ignores AoE affects/hits
+// while players are standing on the border.
+// Official: 0
+// Legacy Athena: 1
+land_protector_behavior: 0
+
 // Should Tarot Card of Fate have the same chance for each card to occur? (Note 1)
 // Official chances: 15%: LOVERS | 10%: FOOL, MAGICIAN, HIGH PRIESTESS, STRENGTH, SUN | 8%: TEMPERANCE
 // 7%: CHARIOT | 6%: THE HANGED MAN | 5%: DEATH, STAR | 2%: TOWER | 1%: WHEEL OF FORTUNE, DEVIL

+ 17 - 5
conf/msg_conf/map_msg.conf

@@ -1706,12 +1706,24 @@
 1503: You've entered a PK Zone.
 1504: You've entered a PK Zone (safe until level %d).
 
+// @setquest, @erasequest, @completequest
+1505: Usage: %s <quest ID>
+1506: Quest %d not found in DB.
+1507: Character already has quest %d.
+1508: Character doesn't have quest %d.
+
+// @checkquest
+1509: Checkquest value for quest %d
+1510: >    HAVEQUEST : %d
+1511: >    HUNTING   : %d
+1512: >    PLAYTIME  : %d
+
 // More Adoption
-1505: The Baby is not level 50 or lower.
-1506: Baby has been disowned.
-1507: Baby is not adopted.
-1508: A Parent is not the father or mother of the Baby.
-1509: Usage: <char name> <independent_baby>
+1513: The Baby is not level 50 or lower.
+1514: Baby has been disowned.
+1515: Baby is not adopted.
+1516: A Parent is not the father or mother of the Baby.
+1517: Usage: <char name> <independent_baby>
 
 //Custom translations
 import: conf/msg_conf/import/map_msg_eng_conf.txt

+ 0 - 7
db/import-tmpl/size_fix.txt

@@ -1,7 +0,0 @@
-// Size Fix Tables
-// Contains size fixes for weapon damage.
-//
-// Struture of Database:
-// Columns - Weapon type
-// Rows    - Target size
-

+ 33 - 0
db/import-tmpl/size_fix.yml

@@ -0,0 +1,33 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2019 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Size Fix Database
+###########################################################################
+#
+# Size Fix Settings
+#
+###########################################################################
+# - Weapon    Weapon type.
+#   Small     Small size modifier. (Default: 100)
+#   Medium    Medium size modifier. (Default: 100)
+#   Large     Large size modifier. (Default: 100)
+###########################################################################
+
+Header:
+  Type: SIZE_FIX_DB
+  Version: 1

+ 38 - 0
db/pre-re/size_fix.yml

@@ -0,0 +1,38 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2019 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Size Fix Database
+###########################################################################
+#
+# Size Fix Settings
+#
+###########################################################################
+# - Weapon    Weapon type.
+#   Small     Small size modifier. (Default: 100)
+#   Medium    Medium size modifier. (Default: 100)
+#   Large     Large size modifier. (Default: 100)
+###########################################################################
+
+Header:
+  Type: SIZE_FIX_DB
+  Version: 1
+
+Body:
+  - Weapon: Knuckle
+    Medium: 75
+    Large: 50

+ 37 - 0
db/re/size_fix.yml

@@ -0,0 +1,37 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2019 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Size Fix Database
+###########################################################################
+#
+# Size Fix Settings
+#
+###########################################################################
+# - Weapon    Weapon type.
+#   Small     Small size modifier. (Default: 100)
+#   Medium    Medium size modifier. (Default: 100)
+#   Large     Large size modifier. (Default: 100)
+###########################################################################
+
+Header:
+  Type: SIZE_FIX_DB
+  Version: 1
+
+Body:
+  - Weapon: Knuckle
+    Large: 75

文件差異過大導致無法顯示
+ 208 - 304
db/re/skill_db.yml


+ 5 - 0
db/re/skill_nocast_db.txt

@@ -26,6 +26,11 @@
 //----------------------------------------------------------------------------
 // Normal
 //----------------------------------------------------------------------------
+308,1	//BD_ETERNALCHAOS
+311,1	//BD_ROKISWEIL
+317,1	//BA_DISSONANCE
+325,1	//DC_UGLYDANCE
+328,1	//DC_DONTFORGETME
 2422,1	//WM_LULLABY_DEEPSLEEP
 2423,1	//WM_SIRCLEOFNATURE
 2430,1	//WM_SATURDAY_NIGHT_FEVER

+ 8 - 4
db/re/skill_tree.txt

@@ -1306,7 +1306,8 @@
 4020,394,10,47,5,316,1,46,5,0,0,0,0 //CG_ARROWVULCAN#Vulcan Arrow#
 4020,395,5,45,5,315,7,0,0,0,0,0,0 //CG_MOONLIT#Sheltering Bliss#
 4020,396,1,45,10,315,5,0,0,0,0,0,0 //CG_MARIONETTE#Marionette Control#
-4020,487,5,315,10,396,1,317,3,0,0,0,0 //CG_LONGINGFREEDOM#Longing for Freedom#
+//4020,487,5,315,10,396,1,317,3,0,0,0,0 //CG_LONGINGFREEDOM#Longing for Freedom# // Replaced with Skilled Special Singer
+4020,5068,1,315,10,396,1,317,3,0,0,0,0 //CG_SPECIALSINGER#Skilled Special Singer#
 4020,488,5,45,10,315,10,0,0,0,0,0,0 //CG_HERMODE#Wand of Hermod#
 4020,489,5,45,10,317,3,0,0,0,0,0,0 //CG_TAROTCARD#Tarot Card of Fate#
 4020,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
@@ -1342,7 +1343,8 @@
 4021,394,10,47,5,324,1,46,5,0,0,0,0 //CG_ARROWVULCAN#Vulcan Arrow#
 4021,395,5,45,5,323,7,0,0,0,0,0,0 //CG_MOONLIT#Sheltering Bliss#
 4021,396,1,45,10,323,5,0,0,0,0,0,0 //CG_MARIONETTE#Marionette Control#
-4021,487,5,323,10,396,1,325,3,0,0,0,0 //CG_LONGINGFREEDOM#Longing for Freedom#
+//4021,487,5,323,10,396,1,325,3,0,0,0,0 //CG_LONGINGFREEDOM#Longing for Freedom# // Replaced with Skilled Special Singer
+4021,5068,1,323,10,396,1,325,3,0,0,0,0 //CG_SPECIALSINGER#Skilled Special Singer#
 4021,488,5,45,10,323,10,0,0,0,0,0,0 //CG_HERMODE#Wand of Hermod#
 4021,489,5,45,10,325,3,0,0,0,0,0,0 //CG_TAROTCARD#Tarot Card of Fate#
 4021,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
@@ -3668,7 +3670,8 @@
 4075,394,10,47,5,316,1,46,5,0,0,0,0 //CG_ARROWVULCAN#Vulcan Arrow#
 4075,395,5,45,5,315,7,0,0,0,0,0,0 //CG_MOONLIT#Sheltering Bliss#
 4075,396,1,45,10,315,5,0,0,0,0,0,0 //CG_MARIONETTE#Marionette Control#
-4075,487,5,315,10,396,1,317,3,0,0,0,0 //CG_LONGINGFREEDOM#Longing for Freedom#
+//4075,487,5,315,10,396,1,317,3,0,0,0,0 //CG_LONGINGFREEDOM#Longing for Freedom# // Replaced with Skilled Special Singer
+4075,5068,1,315,10,396,1,317,3,0,0,0,0 //CG_SPECIALSINGER#Skilled Special Singer#
 4075,488,5,45,10,315,10,0,0,0,0,0,0 //CG_HERMODE#Wand of Hermod#
 4075,489,5,45,10,317,3,0,0,0,0,0,0 //CG_TAROTCARD#Tarot Card of Fate#
 4075,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#
@@ -3730,7 +3733,8 @@
 4076,394,10,47,5,324,1,46,5,0,0,0,0 //CG_ARROWVULCAN#Vulcan Arrow#
 4076,395,5,45,5,323,7,0,0,0,0,0,0 //CG_MOONLIT#Sheltering Bliss#
 4076,396,1,45,10,323,5,0,0,0,0,0,0 //CG_MARIONETTE#Marionette Control#
-4076,487,5,323,10,396,1,325,3,0,0,0,0 //CG_LONGINGFREEDOM#Longing for Freedom#
+//4076,487,5,323,10,396,1,325,3,0,0,0,0 //CG_LONGINGFREEDOM#Longing for Freedom# // Replaced with Skilled Special Singer
+4076,5068,1,323,10,396,1,325,3,0,0,0,0 //CG_SPECIALSINGER#Skilled Special Singer#
 4076,488,5,45,10,323,10,0,0,0,0,0,0 //CG_HERMODE#Wand of Hermod#
 4076,489,5,45,10,325,3,0,0,0,0,0,0 //CG_TAROTCARD#Tarot Card of Fate#
 4076,410,1,0,0,0,0,0,0,0,0,0,0 //WE_CALLBABY#Call Baby#

+ 0 - 11
db/size_fix.txt

@@ -1,11 +0,0 @@
-// Size Fix Tables
-// Contains size fixes for weapon damage.
-//
-// Struture of Database:
-// Columns - Weapon type
-// Rows    - Target size
-
-//Unarmed, Knife, 1H Sword, 2H Sword, 1H Spear, 2H Spears, 1H Axe, 2H Axe, Mace, 2H Mace, Staff, Bow, Knuckle, Musical Instrument, Whip, Book, Katar, Revolver, Rifle, Shotgun, Gatling Gun, Grenade Launcher, Fuuma Shuriken, 2H Staff
-100,100, 75, 75, 75, 75, 50, 50, 75,100,100,100,100, 75, 75,100, 75,100,100,100,100,100,100,100	// Size: Small
-100, 75,100, 75, 75, 75, 75, 75,100,100,100,100, 75,100,100,100,100,100,100,100,100,100,100,100	// Size: Medium
-100, 50, 75,100,100,100,100,100,100,100,100, 75, 50, 75, 50, 50, 75,100,100,100,100,100,100,100	// Size: Large

+ 89 - 0
db/size_fix.yml

@@ -0,0 +1,89 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2019 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Size Fix Database
+###########################################################################
+#
+# Size Fix Settings
+#
+###########################################################################
+# - Weapon  Weapon type.
+#   Small   Small size modifier. (Default: 100)
+#   Medium  Medium size modifier. (Default: 100)
+#   Large   Large size modifier. (Default: 100)
+###########################################################################
+
+Header:
+  Type: SIZE_FIX_DB
+  Version: 1
+
+Body:
+  - Weapon: Fist
+  - Weapon: Dagger
+    Medium: 75
+    Large: 50
+  - Weapon: 1hSword
+    Small: 75
+    Large: 75
+  - Weapon: 2hSword
+    Small: 75
+    Medium: 75
+  - Weapon: 1hSpear
+    Small: 75
+    Medium: 75
+  - Weapon: 2hSpear
+    Small: 75
+    Medium: 75
+  - Weapon: 1hAxe
+    Small: 50
+    Medium: 75
+  - Weapon: 2hAxe
+    Small: 50
+    Medium: 75
+  - Weapon: Mace
+    Small: 75
+  - Weapon: 2hMace
+  - Weapon: Staff
+  - Weapon: Bow
+    Large: 75
+  - Weapon: Musical
+    Small: 75
+    Large: 75
+  - Weapon: Whip
+    Small: 75
+    Large: 50
+  - Weapon: Book
+    Large: 50
+  - Weapon: Katar
+    Small: 75
+    Large: 75
+  - Weapon: Revolver
+  - Weapon: Rifle
+  - Weapon: Gatling
+  - Weapon: Shotgun
+  - Weapon: Grenade
+  - Weapon: Huuma
+  - Weapon: 2hStaff
+
+Footer:
+  Imports:
+  - Path: db/pre-re/size_fix.yml
+    Mode: Prerenewal
+  - Path: db/re/size_fix.yml
+    Mode: Renewal
+  - Path: db/import/size_fix.yml

+ 9 - 0
doc/atcommands.txt

@@ -1766,3 +1766,12 @@ Bans or unbans a player from the specified channel.
 Binds or unbinds your global chat with the specified channel, which sends all global messages to the specified channel.
 
 ---------------------------------------
+
+@setquest <quest ID>
+@erasequest <quest ID>
+@completequest <quest ID>
+@checkquest <quest ID>
+
+Changes/checks the status of the specified quest ID.
+
+---------------------------------------

+ 22 - 0
doc/script_commands.txt

@@ -6511,6 +6511,28 @@ while hidden then revealing.... you can wonder around =P
 
 This command will fully unload a NPC object and all of it's duplicates.
 
+---------------------------------------
+ 
+*cloakonnpc "<NPC object name>"{,<character ID>};
+*cloakoffnpc "<NPC object name>"{,<character ID>};
+
+These commands will make the NPC object specified display as cloaked/uncloaked,
+even though not actually disabled.
+The player can interact with a NPC cloaked (via NPC click, monster event..)
+but the NPC trigger area is disabled.
+
+If <character ID> is given then the NPC will only display to the specified
+player until he/she leaves the map, logs out, or the npc option is changed.
+If no <character ID> is specified it will display to the area.
+
+---------------------------------------
+
+*isnpccloaked "<NPC object name>"{,<character ID>};
+
+Returns true if the NPC has been cloaked to the attached player or given
+<character ID>, false otherwise. This works in association with cloakonnpc
+when it is targetting a specific character.
+
 ---------------------------------------
 
 *doevent "<NPC object name>::<event label>";

+ 166 - 78
npc/custom/woe_controller.txt

@@ -21,6 +21,7 @@
 //= Be sure to disable the default agit controllers!
 //= npc\guild\agit_controller.txt
 //= npc\guild2\agit_start_se.txt
+//= npc\re\guild3\agit_start_te.txt
 //============================================================
 
 // Information NPC
@@ -29,9 +30,9 @@ prontera,149,193,4	script	WOE Information	835,{
 	doevent "WOE_CONTROL::OnMenu";
 	end;
 OnAgitStart:
-	while(agitcheck()) {
-		specialeffect EF_BEGINSPELL6;
+	while(agitcheck() || agitcheck2() || agitcheck3()) {
 		sleep 425;
+		specialeffect EF_BEGINSPELL6;
 	}
 	end;
 }
@@ -40,9 +41,10 @@ OnAgitStart:
 //============================================================
 -	script	WOE_CONTROL	-1,{
 function Disp_Owner; function Add_Zero;
+function Region;
+function Castle;
 
 OnInit:
-
 // -----------------------------------------------------------
 //  Configuration settings.
 // -----------------------------------------------------------
@@ -82,45 +84,93 @@ OnInit:
 	.reward_zeny = 0;
 
 // -----------------------------------------------------------
-//  Constants (leave this section alone).
+//  Castles datas.
 // -----------------------------------------------------------
 
-	setarray .Castles$[0],
-		"prtg_cas01","prtg_cas02","prtg_cas03","prtg_cas04","prtg_cas05",
-		"payg_cas01","payg_cas02","payg_cas03","payg_cas04","payg_cas05",
-		"gefg_cas01","gefg_cas02","gefg_cas03","gefg_cas04","gefg_cas05",
-		"aldeg_cas01","aldeg_cas02","aldeg_cas03","aldeg_cas04","aldeg_cas05",
-		"arug_cas01","arug_cas02","arug_cas03","arug_cas04","arug_cas05",
-		"schg_cas01","schg_cas02","schg_cas03","schg_cas04","schg_cas05";
-	setarray .EndLabel$[0],"ar01","ar02","ar03","ar04","ar05","sc01","sc02","sc03","sc04","sc05";
+// Region function defines the region of the castle defined by Castle function.
+// Region("<region name>");
+// Castle("<castle map name>", "<event name when woe end>", "<event killmonster name>", "<map name special warp>",<x>,<y>)
+
+	Region("Prontera");
+		Castle("prtg_cas01", "Agit#prtg_cas01::OnAgitEnd", "Agit#prtg_cas01::OnAgitBreak", "prt_gld",134,65);
+		Castle("prtg_cas02", "Agit#prtg_cas02::OnAgitEnd", "Agit#prtg_cas02::OnAgitBreak", "prt_gld",240,128);
+		Castle("prtg_cas03", "Agit#prtg_cas03::OnAgitEnd", "Agit#prtg_cas03::OnAgitBreak", "prt_gld",153,137);
+		Castle("prtg_cas04", "Agit#prtg_cas04::OnAgitEnd", "Agit#prtg_cas04::OnAgitBreak", "prt_gld",111,240);
+		Castle("prtg_cas05", "Agit#prtg_cas05::OnAgitEnd", "Agit#prtg_cas05::OnAgitBreak", "prt_gld",208,240);
+	Region("Payon");
+		Castle("payg_cas01", "Agit#payg_cas01::OnAgitEnd", "Agit#payg_cas01::OnAgitBreak", "pay_gld",121,233);
+		Castle("payg_cas02", "Agit#payg_cas02::OnAgitEnd", "Agit#payg_cas02::OnAgitBreak", "pay_gld",295,116);
+		Castle("payg_cas03", "Agit#payg_cas03::OnAgitEnd", "Agit#payg_cas03::OnAgitBreak", "pay_gld",317,293);
+		Castle("payg_cas04", "Agit#payg_cas04::OnAgitEnd", "Agit#payg_cas04::OnAgitBreak", "pay_gld",140,160);
+		Castle("payg_cas05", "Agit#payg_cas05::OnAgitEnd", "Agit#payg_cas05::OnAgitBreak", "pay_gld",204,266);
+	Region("Geffen");
+		Castle("gefg_cas01", "Agit#gefg_cas01::OnAgitEnd", "Agit#gefg_cas01::OnAgitBreak", "gef_fild13",214,75);
+		Castle("gefg_cas02", "Agit#gefg_cas02::OnAgitEnd", "Agit#gefg_cas02::OnAgitBreak", "gef_fild13",308,240);
+		Castle("gefg_cas03", "Agit#gefg_cas03::OnAgitEnd", "Agit#gefg_cas03::OnAgitBreak", "gef_fild13",143,240);
+		Castle("gefg_cas04", "Agit#gefg_cas04::OnAgitEnd", "Agit#gefg_cas04::OnAgitBreak", "gef_fild13",193,278);
+		Castle("gefg_cas05", "Agit#gefg_cas05::OnAgitEnd", "Agit#gefg_cas05::OnAgitBreak", "gef_fild13",305,87);
+	Region("Aldebaran");
+		Castle("aldeg_cas01", "Agit#aldeg_cas01::OnAgitEnd", "Agit#aldeg_cas01::OnAgitBreak", "alde_gld",48,83);
+		Castle("aldeg_cas02", "Agit#aldeg_cas02::OnAgitEnd", "Agit#aldeg_cas02::OnAgitBreak", "alde_gld",95,249);
+		Castle("aldeg_cas03", "Agit#aldeg_cas03::OnAgitEnd", "Agit#aldeg_cas03::OnAgitBreak", "alde_gld",142,85);
+		Castle("aldeg_cas04", "Agit#aldeg_cas04::OnAgitEnd", "Agit#aldeg_cas04::OnAgitBreak", "alde_gld",239,242);
+		Castle("aldeg_cas05", "Agit#aldeg_cas05::OnAgitEnd", "Agit#aldeg_cas05::OnAgitBreak", "alde_gld",264,90);
+	Region("Arunafeltz");
+		Castle("arug_cas01", "Manager#arug_cas01::OnAgitEnd2", "Steward#ar01::OnStartArena", "aru_gld",158,272);
+		Castle("arug_cas02", "Manager#arug_cas02::OnAgitEnd2", "Steward#ar02::OnStartArena", "aru_gld",83,47);
+		Castle("arug_cas03", "Manager#arug_cas03::OnAgitEnd2", "Steward#ar03::OnStartArena", "aru_gld",68,155);
+		Castle("arug_cas04", "Manager#arug_cas04::OnAgitEnd2", "Steward#ar04::OnStartArena", "aru_gld",299,345);
+		Castle("arug_cas05", "Manager#arug_cas05::OnAgitEnd2", "Steward#ar05::OnStartArena", "aru_gld",292,107);
+	Region("Schwarzwald");
+		Castle("schg_cas01", "Manager#schg_cas01::OnAgitEnd2", "Steward#sc01::OnStartArena", "sch_gld",293,100);
+		Castle("schg_cas02", "Manager#schg_cas02::OnAgitEnd2", "Steward#sc02::OnStartArena", "sch_gld",288,252);
+		Castle("schg_cas03", "Manager#schg_cas03::OnAgitEnd2", "Steward#sc03::OnStartArena", "sch_gld",97,196);
+		Castle("schg_cas04", "Manager#schg_cas04::OnAgitEnd2", "Steward#sc04::OnStartArena", "sch_gld",137,90);
+		Castle("schg_cas05", "Manager#schg_cas05::OnAgitEnd2", "Steward#sc05::OnStartArena", "sch_gld",71,315);
+	Region("Prontera (TE)");
+		Castle("te_prtcas01", "Manager_TE#Gaebolg::OnAgitEnd3",	"Manager_TE#Gaebolg::OnAgitBreak",	"te_prt_gld",134,65);
+		Castle("te_prtcas02", "Manager_TE#Richard::OnAgitEnd3",	"Manager_TE#Richard::OnAgitBreak",	"te_prt_gld",240,128);
+		Castle("te_prtcas03", "Manager_TE#Wigner::OnAgitEnd3",	"Manager_TE#Wigner::OnAgitBreak",	"te_prt_gld",153,137);
+		Castle("te_prtcas04", "Manager_TE#Heine::OnAgitEnd3",	"Manager_TE#Heine::OnAgitBreak",	"te_prt_gld",111,240);
+		Castle("te_prtcas05", "Manager_TE#Nerious::OnAgitEnd3",	"Manager_TE#Nerious::OnAgitBreak",	"te_prt_gld",208,240);
+	Region("Aldebaran (TE)");
+		Castle("te_aldecas1", "Manager_TE#Glaris::OnAgitEnd3",	"Manager_TE#Glaris::OnAgitBreak",	"te_alde_gld",48,83);
+		Castle("te_aldecas2", "Manager_TE#Defolty::OnAgitEnd3",	"Manager_TE#Defolty::OnAgitBreak",	"te_alde_gld",95,249);
+		Castle("te_aldecas3", "Manager_TE#Sorin::OnAgitEnd3",	"Manager_TE#Sorin::OnAgitBreak",	"te_alde_gld",142,85);
+		Castle("te_aldecas4", "Manager_TE#Bennit::OnAgitEnd3",	"Manager_TE#Bennit::OnAgitBreak",	"te_alde_gld",239,242);
+		Castle("te_aldecas5", "Manager_TE#W::OnAgitEnd3",		"Manager_TE#W::OnAgitBreak",		"te_alde_gld",264,90);
+
 	setarray .Days$[0],"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday";
-	setarray .Regions$[0],"Prontera","Payon","Geffen","Aldebaran","Arunafeltz","Schwarzwald";
-	setarray .Map$[0],"prt_gld","pay_gld","gef_fild13","alde_gld","aru_gld","sch_gld";
-	setarray .MapX[0],134,240,153,111,208,121,295,317,140,204,214,308,143,193,305,48, 95,142,239,264,158,83, 68,299,292,293,288, 97,137, 71;
-	setarray .MapY[0], 65,128,137,240,240,233,116,293,160,266, 75,240,240,278, 87,83,249, 85,242, 90,272,47,155,345,107,100,252,196, 90,315;
 
 // -----------------------------------------------------------
 
 	.reward_id_size = getarraysize(.reward_id);
 	set .Size, getarraysize($WOE_CONTROL);
-	if (.AutoKick || .NoOwner)
-		for(set .@i,0; .@i<getarraysize(.Castles$); set .@i,.@i+1) {
+
+	if (.AutoKick || .NoOwner) {
+		for(set .@i,0; .@i<.total_castle; set .@i,.@i+1) {
 			setmapflag .Castles$[.@i], mf_loadevent;
 			setd "."+.Castles$[.@i], .@i;
 		}
-	if (!agitcheck() && !agitcheck2()) sleep 4000;
+	}
+	else {
+		for(set .@i,0; .@i<.total_castle; set .@i,.@i+1)
+			setd "."+.Castles$[.@i], 0;
+	}
+	if (!agitcheck() && !agitcheck2() && !agitcheck3()) sleep 4000;
 	set .Init,1;
+	.current_region = 0;
 
 OnMinute00:
 	freeloop(1);
-	if (agitcheck() || agitcheck2()) {
-		for(set .@i,0; .@i<.Size; set .@i,.@i+4)
+	if (agitcheck() || agitcheck2() || agitcheck3()) {
+		for(set .@i,0; .@i<.Size; set .@i,.@i+4) {
 			if (gettime(DT_DAYOFWEEK) == $WOE_CONTROL[.@i] && gettime(DT_HOUR) == $WOE_CONTROL[.@i+2]) {
 			OnWOEEnd:
 				announce "The War Of Emperium is over!",bc_all|bc_woe;
-				AgitEnd; AgitEnd2;
+				AgitEnd; AgitEnd2; AgitEnd3;
 				sleep 1000;
-				for(set .@j,0; .@j<getarraysize(.Castles$); set .@j,.@j+1) {
+				for(set .@j,0; .@j<.total_castle; set .@j,.@j+1) {
 					if (.Active[0]&(1<<.@j)) Disp_Owner(.Castles$[.@j],1);
 					if (.ExitWarp) maprespawnguildid .Castles$[.@j],0,3;
 				}
@@ -129,33 +179,31 @@ OnMinute00:
 				if (.ForceEnd) { set .ForceEnd,0; end; }
 				break;
 			}
+		}
 	}
-	if ((!agitcheck() && !agitcheck2()) || .Init) {
-		if (!agitcheck() && !agitcheck2()) set .Init,0;
-		for(set .@i,0; .@i<.Size; set .@i,.@i+4)
+	.@agit_check = (!agitcheck() && !agitcheck2() && !agitcheck3());
+	if (.@agit_check || .Init) {
+		if (.@agit_check) set .Init,0;
+		for(set .@i,0; .@i<.Size; set .@i,.@i+4) {
 			if (gettime(DT_DAYOFWEEK) == $WOE_CONTROL[.@i] && gettime(DT_HOUR) >= $WOE_CONTROL[.@i+1] && gettime(DT_HOUR) < $WOE_CONTROL[.@i+2]) {
 				deletearray .Active[0],2;
 				set .Active[0], $WOE_CONTROL[.@i+3];
-				if (.Init) { AgitEnd; AgitEnd2; }
+				if (.Init) { AgitEnd; AgitEnd2; AgitEnd3; }
 				else announce "The War Of Emperium has begun!",bc_all|bc_woe;
 				sleep 1000;
-				AgitStart; AgitStart2;
-				for(set .@j,0; .@j<getarraysize(.Castles$); set .@j,.@j+1) {
+				AgitStart; AgitStart2; AgitStart3;
+				for(set .@j,0; .@j<.total_castle; set .@j,.@j+1) {
 					if (.Active[0]&(1<<.@j)) {
 						if (!.Init) Disp_Owner(.Castles$[.@j],0);
-						set .Active[1], .Active[1] | (1<<((.@j/5)+1));
+						set .Active[1], .Active[1] | (1<<.castle_region[.@j]);
 					} else {
-						if (.@j<20) {
-							donpcevent "Agit#"+.Castles$[.@j]+"::OnAgitEnd";
-							killmonster .Castles$[.@j], "Agit#"+.Castles$[.@j]+"::OnAgitBreak";
-						} else {
-							donpcevent "Manager#"+.Castles$[.@j]+"::OnAgitEnd2";
-							killmonster .Castles$[.@j], "Steward#"+.EndLabel$[.@j-20]+"::OnStartArena";
-						}
+						donpcevent .event_name_agitend$[.@j];
+						killmonster .Castles$[.@j], .event_name_killmob$[.@j];
 					}
 				}
 				break;
 			}
+		}
 	}
 	set .Init,0;
 	end;
@@ -169,6 +217,44 @@ function Disp_Owner {
 function Add_Zero {
 	return ((getarg(0)<10)?"0":"")+getarg(0)+(getarg(1,0)?".":":")+"00";
 }
+function Castle {
+	.@map$ = getarg(0);
+	if (getd( "." + .@map$ ) > 0) {
+		debugmes sprintf("WOE_CONTROL: map %s already defined.", .@map$);
+		return;
+	}
+	if (.total_castle > 61) {
+		debugmes sprintf("WOE_CONTROL: Maximum of 62 castles defined, %s skipped.", .@map$);
+		return;
+	}
+	.Castles$[.total_castle] = .@map$;
+	.event_name_agitend$[.total_castle] = getarg(1);
+	.event_name_killmob$[.total_castle] = getarg(2);
+	.Map$[.total_castle] = getarg(3);
+	.MapX[.total_castle] = getarg(4);
+	.MapY[.total_castle] = getarg(5);
+	.castle_region[.total_castle] = .current_region;
+
+	setd ".castle_index_in_region_" + .current_region + "[" + .size_region[.current_region] + "]", .total_castle;
+	.total_castle++;
+	.size_region[.current_region]++;
+
+	setd "." + .Castles$[.total_castle-1], .total_castle;
+	return;
+}
+function Region {
+	.@zone$ = getarg(0);
+	for ( .@i = 0; .@i < .total_region; ++.@i ) {
+		if (.Regions$[.@i] == .@zone$) {
+			.current_region = .@index;
+			return;
+		}
+	}
+	.Regions$[.total_region] = .@zone$;
+	.current_region = .total_region;
+	.total_region++;
+	return;
+}
 
 OnReward:
 	if (!.reward_id_size && !.reward_zeny)
@@ -176,10 +262,11 @@ OnReward:
 
 	if (.Options&2) set .@str$,gettimestr("%B %d, %Y",21);
 	freeloop(1);
-	for(set .@i,0; .@i<getarraysize(.Castles$); set .@i,.@i+1) {
+	for(set .@i,0; .@i<.total_castle; set .@i,.@i+1) {
 		if (getarg(0)&(1<<.@i)) {
 			set .@gid, getcastledata(.Castles$[.@i],1);
-			if (!.@gid) continue;
+			if (!.@gid)
+				continue;
 
 			getguildmember( .@gid, 1, .@cid );
 			.@size_guild = getguildmember( .@gid, 2, .@aid );
@@ -199,13 +286,7 @@ OnReward:
 
 			for(set .@j,0; .@j<.@size_guild; set .@j,.@j+1) {
 				if ((.Options&8) && !(.Options&4)) {
-					if (isloggedin(.@aid[.@j],.@cid[.@j]))
-						set .@ip$, replacestr(getcharip(.@aid[.@j]),".","a");
-					else {
-						if (query_sql("SELECT `last_ip` FROM `login` WHERE `account_id` = '" + .@aid[.@j] + "'", .@last_ip$) < 1)
-							continue;
-						.@ip$ = replacestr(.@last_ip$, ".", "a");
-					}
+					set .@ip$, replacestr(getcharip(.@aid[.@j]),".","a");
 					if (getd(".@ip_"+.@i+"_"+.@ip$)) continue;
 					setd ".@ip_"+.@i+"_"+.@ip$,1;
 				}
@@ -224,7 +305,8 @@ OnReward:
 						setd ".@str_"+.@cid[.@j],1;
 						message rid2name(.@aid[.@j]),"You've got mail!";
 					}
-				} else if (isloggedin(.@aid[.@j],.@cid[.@j])) {
+				}
+				else if (isloggedin(.@aid[.@j],.@cid[.@j])) {
 					attachrid( .@aid[.@j], true );
 					.@name$ = strcharinfo( 0 );
 					.@castle_name$ = getcastlename(.Castles$[.@i]);
@@ -244,30 +326,33 @@ OnReward:
 	return;
 
 OnPCLoadMapEvent:
-	if (!compare(strcharinfo(3),"g_cas")) end;
+	.@compare_val = compare(strcharinfo(3),"g_cas");
+	if (!.@compare_val) end;
 	if (((.AutoKick && .Active[0]) || (.NoOwner && !getcastledata(strcharinfo(3),1))) && !(.Active[0]&(1<<getd("."+strcharinfo(3))))) {
 		if (getcharid(2) && getcastledata(strcharinfo(3),1) == getcharid(2)) end;
+		.@castle_name$ = getcastlename(strcharinfo(3));
 		sleep2 1000;
-		message strcharinfo(0), getcastlename(strcharinfo(3))+" is currently inactive.";
+		message strcharinfo(0), .@castle_name$ + " is currently inactive.";
 		sleep2 5000;
-		if (compare(strcharinfo(3),"g_cas")) warp "SavePoint",0,0;
+		if (.@compare_val) warp "SavePoint",0,0;
 	}
 	end;
 
 OnMenu:
 while(1) {
 	mes "[WOE Information]";
-	if (agitcheck() || agitcheck2()) {
+	if (agitcheck() || agitcheck2() || agitcheck3()) {
 		if (.Active[0]) {
-			for(set .@i,0; .@i<.Size; set .@i,.@i+4)
+			for(set .@i,0; .@i<.Size; set .@i,.@i+4) {
 				if (gettime(DT_DAYOFWEEK) == $WOE_CONTROL[.@i] && gettime(DT_HOUR) >= $WOE_CONTROL[.@i+1] && gettime(DT_HOUR) < $WOE_CONTROL[.@i+2]) {
 					set .@i, $WOE_CONTROL[.@i+2];
 					break;
 				}
+			}
 			mes "The War of Emperium is ^0055FFactive^000000 until ^FF0000"+Add_Zero(.@i)+"^000000 in the following regions:";
 			mes " ";
-			for(set .@i,0; .@i<6; set .@i,.@i+1)
-				if (.Active[1]&(1<<(.@i+1))) mes " > ^777777"+.Regions$[.@i]+"^000000";
+			for(set .@i,0; .@i < .total_region; set .@i,.@i+1)
+				if (.Active[1]&(1<<.@i)) mes " > ^777777"+.Regions$[.@i]+"^000000";
 		} else
 			mes "The War of Emperium is ^0055FFactive^000000.";
 	} else {
@@ -290,20 +375,22 @@ while(1) {
 	case 1:
 		if (.CastleWarp) set .@clr$,"^0055FF";
 		set .@menu$,"";
-		for(set .@i,0; .@i<6; set .@i,.@i+1) {
-			if (.CastleWarp || .Active[1]&(1<<(.@i+1)))
-				set .@menu$, .@menu$+" ~ "+((.Active[1]&(1<<(.@i+1)))?.@clr$:"^777777")+.Regions$[.@i]+" Castles^000000";
+		for(set .@i,0; .@i < .total_region; set .@i,.@i+1) {
+			if (.CastleWarp || .Active[1]&(1<<.@i))
+				set .@menu$, .@menu$+" ~ "+((.Active[1]&(1<<.@i))?.@clr$:"^777777")+.Regions$[.@i]+" Castles^000000";
 			set .@menu$, .@menu$+":";
 		}
 		set .@i, select(.@menu$)-1;
 		set .@menu$,"";
-		for(set .@j,.@i*5; .@j<(.@i*5)+5; set .@j,.@j+1) {
-			if (.CastleWarp || .Active[0]&(1<<.@j))
-				set .@menu$, .@menu$+" ~ "+((.Active[0]&(1<<.@j))?.@clr$:"^777777")+getcastlename(.Castles$[.@j])+"^000000";
+		for(set .@j,0; .@j < .size_region[.@i]; set .@j,.@j+1) {
+			.@index = getd( ".castle_index_in_region_" + .@i + "[" + .@j + "]" );
+			if (.CastleWarp || .Active[0]&(1<<.@index))
+				set .@menu$, .@menu$+" ~ "+((.Active[0]&(1<<.@index))?.@clr$:"^777777")+getcastlename(.Castles$[.@index])+"^000000";
 			set .@menu$, .@menu$+":";
 		}
 		set .@j, select(.@menu$)-1;
-		warp .Map$[.@i],.MapX[(.@i*5)+.@j],.MapY[(.@i*5)+.@j];
+		.@index = getd( ".castle_index_in_region_" + .@i + "[" + .@j + "]" );
+		warp .Map$[.@index],.MapX[.@index],.MapY[.@index];
 		close;
 	case 2:
 		mes "[Schedule]";
@@ -311,7 +398,7 @@ while(1) {
 			freeloop(1);
 			for(set .@i,0; .@i<.Size; set .@i,.@i+4) {
 				mes "> ^FF0000"+.Days$[$WOE_CONTROL[.@i]]+" ("+Add_Zero($WOE_CONTROL[.@i+1])+"-"+Add_Zero($WOE_CONTROL[.@i+2])+")^000000";
-				for(set .@j,0; .@j<getarraysize(.Castles$); set .@j,.@j+1)
+				for(set .@j,0; .@j<.total_castle; set .@j,.@j+1)
 					if ($WOE_CONTROL[.@i+3]&(1<<.@j)) mes "  ~ "+getcastlename(.Castles$[.@j])+" ^777777("+.Castles$[.@j]+")^000000";
 				if (.@i+4 < .Size) mes " ";
 			}
@@ -322,12 +409,13 @@ while(1) {
 		break;
 	case 3:
 		mes "[Castle Ownership]";
-		for(set .@i,0; .@i<6; set .@i,.@i+1) {
+		for(set .@i,0; .@i < .total_region; set .@i,.@i+1) {
 			set .@k, .@i*5;
 			mes "> ^FF0000"+.Regions$[.@i]+"^000000";
-			for(set .@j,.@k; .@j<(.@k+5); set .@j,.@j+1) { 
-				set .@t, getcastledata(.Castles$[.@j],1);
-				mes "  ~ "+getcastlename(.Castles$[.@j])+": "+((.@t)?"^0055FF"+getguildname(.@t):"^777777unoccupied")+"^000000";
+			for(set .@j,0; .@j<.size_region[.@i]; set .@j,.@j+1) {
+				.@index = getd( ".castle_index_in_region_" + .@i + "[" + .@j + "]" );
+				set .@t, getcastledata(.Castles$[.@index],1);
+				mes "  ~ "+getcastlename(.Castles$[.@index])+": "+((.@t)?"^0055FF"+getguildname(.@t):"^777777unoccupied")+"^000000";
 			}
 			if (.@i < 5) mes " ";
 		}
@@ -339,14 +427,9 @@ while(1) {
 		mes "There are ^0055FF"+(.Size/4)+" session(s)^000000 configured.";
 		mes "What would you like to do?";
 		next;
-		switch(select(" ~ Add a session...: ~ Delete a session...: ~ Reload settings...:"+((agitcheck() || agitcheck2())?" ~ End WOE session...":"")+": ~ ^777777Go back^000000")) {
+		switch(select(" ~ Add a session...: ~ Delete a session...: ~ Reload settings...:"+((agitcheck() || agitcheck2() || agitcheck3())?" ~ End WOE session...":"")+": ~ ^777777Go back^000000")) {
 		case 1:
 			mes "[New Session]";
-			if (.Size > 127) {
-				mes "You have already reached the maximum of 32 sessions.";
-				next;
-				break;
-			}
 			mes "Select a day.";
 			next;
 			set .@Day, select(" ~ "+implode(.Days$,": ~ "))-1;
@@ -383,11 +466,15 @@ while(1) {
 				mes " > Castles:";
 				if (!.@Castle)
 					mes "   ~ ^777777(none selected)^000000";
-				else for(set .@i,0; .@i<getarraysize(.Castles$); set .@i,.@i+1)
-					if (.@Castle&(1<<.@i)) mes "   ~ "+getcastlename(.Castles$[.@i])+" ("+.Castles$[.@i]+")";
+				else {
+					for(set .@i,0; .@i<.total_castle; set .@i,.@i+1) {
+						.@string$ = ( .@Castle&(1<<.@i) ) ? "   ~ "+getcastlename(.Castles$[.@i])+" ("+.Castles$[.@i]+")" : "";
+						mes .@string$;
+					}
+				}
 				next;
 				set .@menu$,((.@Castle)?" ~ ^FF0000Finished...^000000":"")+":";
-				for(set .@i,0; .@i<getarraysize(.Castles$); set .@i,.@i+1)
+				for(set .@i,0; .@i<.total_castle; set .@i,.@i+1)
 					set .@menu$, .@menu$+" ~ "+((.@Castle&(1<<.@i))?"^0055FF":"")+getcastlename(.Castles$[.@i])+" ("+.Castles$[.@i]+")^000000:";
 				set .@i, select(.@menu$)-1;
 				if (.@i)
@@ -398,11 +485,12 @@ while(1) {
 					next;
 					switch(select(" ~ ^0055FFAdd session...^000000: ~ Continue selecting castles...: ~ ^777777Cancel^000000")) {
 					case 1:
-						for(set .@i,0; .@i<.Size; set .@i,.@i+4)
+						for(set .@i,0; .@i<.Size; set .@i,.@i+4) {
 							if ((.@Day == $WOE_CONTROL[.@i] && .@End <= $WOE_CONTROL[.@i+1]) || .@Day < $WOE_CONTROL[.@i]) {
 								set .@d,1;
 								break;
 							}
+						}
 						if (!.@d) { set .@d,1; set .@i,.Size; }
 						copyarray $WOE_CONTROL[.@i+4], $WOE_CONTROL[.@i], .Size-.@i;
 						setarray $WOE_CONTROL[.@i], .@Day, .@Start, .@End, .@Castle;
@@ -452,7 +540,7 @@ while(1) {
 		case 3:
 			mes "[Reload Settings]";
 			mes "This will trigger all events related to new session configurations, if any.";
-			if (agitcheck() || agitcheck2()) {
+			if (agitcheck() || agitcheck2() || agitcheck3()) {
 				mes " ";
 				mes "Be aware that this will disrupt the current WOE session.";
 			}
@@ -469,7 +557,7 @@ while(1) {
 			break;
 		case 4:
 			mes "[Force Agit End]";
-			if (!agitcheck() && !agitcheck2())  {
+			if (!agitcheck() && !agitcheck2() && !agitcheck3())  {
 				mes "WOE has already ended.";
 				next;
 				break;

+ 13 - 19
npc/re/jobs/novice/academy.txt

@@ -64,22 +64,15 @@ iz_int04,51,30,0	duplicate(iz_int#intro_evt02)	iz_int04#intro_evt02	HIDDEN_WARP_
 
 //== Wounded Swordsman (iz_int) =================================
 iz_int,56,32,3	script	Wounded Swordsman#intro_npc01_iz_int	4_TOWER_01,5,5,{
-	@intro_npc01 = 1;
 	npctalk "Oh...", "", bc_self;
-	classchange HIDDEN_WARP_NPC, "", bc_self;// todo: classchange self remain on map
-	classchange 4_TOWER_02, "Wounded Swordsman#intro_npc02_" + strnpcinfo(4), bc_self;
+	cloakonnpc strnpcinfo(0), getcharid(0);
+	cloakoffnpc "Wounded Swordsman#intro_npc02_" + strnpcinfo(4), getcharid(0);
 	end;
 
 OnTouch:
-	if (@intro_npc01 == 0) {
-		npctalk "Urgh... please... help me...", "", bc_self;
-		sleep2 500;
-		npctalk "In order to talk with me.. click my body..", "", bc_self;
-	}
-	else {// debug
-		classchange HIDDEN_WARP_NPC, "", bc_self;
-		classchange 4_TOWER_02, "Wounded Swordsman#intro_npc02_" + strnpcinfo(4), bc_self;
-	}
+	npctalk "Urgh... please... help me...", "", bc_self;
+	sleep2 500;
+	npctalk "In order to talk with me.. click my body..", "", bc_self;
 	end;
 
 OnInit:
@@ -91,7 +84,7 @@ iz_int02,56,32,3	duplicate(Wounded Swordsman#intro_npc01_iz_int)	Wounded Swordsm
 iz_int03,56,32,3	duplicate(Wounded Swordsman#intro_npc01_iz_int)	Wounded Swordsman#intro_npc01_iz_int03	4_TOWER_01,5,5
 iz_int04,56,32,3	duplicate(Wounded Swordsman#intro_npc01_iz_int)	Wounded Swordsman#intro_npc01_iz_int04	4_TOWER_01,5,5
 
-iz_int,56,32,3	script	Wounded Swordsman#intro_npc02_iz_int	HIDDEN_WARP_NPC,{
+iz_int,56,32,3	script	Wounded Swordsman#intro_npc02_iz_int	4_TOWER_02,{
 	if (isbegin_quest(21001) == 0) {
 		mes "[Wounded]";
 		mes "Wow! Thanks a lot!";
@@ -126,12 +119,13 @@ iz_int,56,32,3	script	Wounded Swordsman#intro_npc02_iz_int	HIDDEN_WARP_NPC,{
 
 OnInit:
 	questinfo( QTYPE_QUEST, QMARK_YELLOW, "!isbegin_quest(21001) && Class == Job_Novice" );
+	cloakonnpc strnpcinfo(0);
 	end;
 }
-iz_int01,56,32,3	duplicate(Wounded Swordsman#intro_npc02_iz_int)	Wounded Swordsman#intro_npc02_iz_int01	HIDDEN_WARP_NPC
-iz_int02,56,32,3	duplicate(Wounded Swordsman#intro_npc02_iz_int)	Wounded Swordsman#intro_npc02_iz_int02	HIDDEN_WARP_NPC
-iz_int03,56,32,3	duplicate(Wounded Swordsman#intro_npc02_iz_int)	Wounded Swordsman#intro_npc02_iz_int03	HIDDEN_WARP_NPC
-iz_int04,56,32,3	duplicate(Wounded Swordsman#intro_npc02_iz_int)	Wounded Swordsman#intro_npc02_iz_int04	HIDDEN_WARP_NPC
+iz_int01,56,32,3	duplicate(Wounded Swordsman#intro_npc02_iz_int)	Wounded Swordsman#intro_npc02_iz_int01	4_TOWER_02
+iz_int02,56,32,3	duplicate(Wounded Swordsman#intro_npc02_iz_int)	Wounded Swordsman#intro_npc02_iz_int02	4_TOWER_02
+iz_int03,56,32,3	duplicate(Wounded Swordsman#intro_npc02_iz_int)	Wounded Swordsman#intro_npc02_iz_int03	4_TOWER_02
+iz_int04,56,32,3	duplicate(Wounded Swordsman#intro_npc02_iz_int)	Wounded Swordsman#intro_npc02_iz_int04	4_TOWER_02
 
 // - Captain Carocc (Ship)
 // -----------------------------------------------------------------------------
@@ -288,7 +282,7 @@ int_land,73,100,3	script	Lumin#new_ship	4_M_NOV_RUMIN,{
 		mes "[Lumin]";
 		mes "Yes.";
 		next;
-		classchange HIDDEN_WARP_NPC, "", bc_self;// todo: classchange self remain on map
+		cloakonnpc strnpcinfo(0), getcharid(0);
 		cutin "fly_trock.bmp",2;
 		mes "[Captain Carocc]";
 		mes "Oh boy.";
@@ -312,7 +306,7 @@ int_land,73,100,3	script	Lumin#new_ship	4_M_NOV_RUMIN,{
 	mes ".....";
 	mes "....So?";
 	next;
-	classchange HIDDEN_WARP_NPC, "", bc_self;// todo: classchange self remain on map
+	cloakonnpc strnpcinfo(0), getcharid(0);
 	mes "- Lu just walked away with a cynical look on his face.";
 	next;
 	cutin "fly_trock.bmp",2;

+ 70 - 16
npc/re/merchants/nightmare_biolab.txt

@@ -129,7 +129,30 @@ function	script	F_Cursed_Fragment	{	// 23016
 lighthalzen,321,218,4	script	Ohno Tohiro#1	4_M_RASWORD,{
 	disable_items;
 	mes "[Ohno Tohiro]";
-	mes "I was asked to collect some kind of research charts...";
+	.@r = rand(1,10);
+	if (.@r < 6)
+		mes "I was asked to collect some kind of research charts...";
+	else if (.@r < 7) {
+		mes "- I hear somebody talking - - remote communication -";
+		next;
+		mes "[Ohno Tohiro]";
+		mes "Yes... everything is proceeding smoothly.";
+		mes "The status of the report collection is okay.";
+		mes "Yes, sir.";
+		next;
+		mes "[Ohno Tohiro]";
+		mes "I'll immediately report the information related to the laboratory as a top priority.";
+		mes "Yes, sir...  I'll do so.";
+		next;
+		mes "[Ohno Tohiro]";
+		mes "Oh somebody has come! I'll call you again later.";
+	}
+	else {
+		mes "[Ohno Tohiro]";
+		mes "My shoulders are heavy.";
+		mes "Our long-cherished wish..";
+		mes "One by one, slowly..";
+	}
 	next;
 	mes "[Ohno Tohiro]";
 	mes "Uh...? I didn't realize someone is here already...";
@@ -185,8 +208,10 @@ lighthalzen,321,218,4	script	Ohno Tohiro#1	4_M_RASWORD,{
 			mes "Alright. Now that I received the Zeny, I'll open the crevice.";
 			mes "I hope you can come back alive!...";
 			next;
-			Zeny = Zeny - 100000;
-			warp "lhz_dun_n",100,202;
+			if (Zeny >= 100000) {
+				Zeny -= 100000;
+				warp "lhz_dun_n",100,202;
+			}
 			end;
 		case 4:
 			mes "[Ohno Tohiro]";
@@ -220,7 +245,7 @@ lighthalzen,321,218,4	script	Ohno Tohiro#1	4_M_RASWORD,{
 			mes "I'll send you to the crevice as promised.";
 			mes "I want you alive. See you again!";
 			next;
-			delitem 7347,10;// Research Chart
+			delitem 7347,10;// Lab_Staff_Record
 			warp "lhz_dun_n",100,202;
 			end;
 		}
@@ -348,10 +373,13 @@ lighthalzen,320,204,3	script	A kid with black finger	4_F_04,{
 lighthalzen,327,216,3	script	Crevice#1	4_CRACK,{
 	end;
 OnInit:
-	while(true) {
-		sleep 6000;
-		specialeffect EF_AGIUP3;
-	}
+	initnpctimer;
+	end;
+OnTimer5000:
+	specialeffect EF_AGIUP3;
+	end;
+OnTimer6000:
+	initnpctimer;
 	end;
 }
 
@@ -363,12 +391,14 @@ lhz_dun_n,96,203,3	script	Dungeon gateway#1	4_CRACK,{
 	}
 	warp "lighthalzen",310,228;
 	end;
-
 OnInit:
-	while(true) {
-		sleep 6000;
-		specialeffect EF_AGIUP3;
-	}
+	initnpctimer;
+	end;
+OnTimer5000:
+	specialeffect EF_AGIUP3;
+	end;
+OnTimer6000:
+	initnpctimer;
 	end;
 }
 
@@ -1040,6 +1070,12 @@ lhz_dun_n,143,269,4	script	Victimized Soul's Mind#1	4_M_DEATH2,{
 	mes "If you... bring... one... I'll restore... it... to energy... pieces...";
 	while(true) {
 		next;
+		if (checkweight(2677,5) == 0) {
+			mes "[Victimized Soul's Mind]";
+			mes "Your backpack..";
+			mes "is filled...";
+			close;
+		}
 		if (select( "Hand over the weapon.", "End the conversation." ) == 2) {
 			mes "[Victimized Soul's Mind]";
 			mes "...You... will... find me... again...";
@@ -1125,7 +1161,7 @@ S_Exchange:
 	.@menu$ = "Go back to previous menu.:";
 	for ( .@i = 0; .@i < .@size; .@i++ ) {
 		if (countitem(getarg(.@i)) < 1)
-			.@menu$ += "^777777Not enough " + getitemname(getarg(.@i)) + ".^000000:";
+			.@menu$ += "^999999Not enough " + getitemname(getarg(.@i)) + ".^000000:";
 		else
 			.@menu$ += "You have " + getitemname(getarg(.@i)) + ".:";
 	}
@@ -1143,7 +1179,8 @@ S_Exchange:
 			next;
 			return;
 		}
-		progressbar "000000",5;
+		donpcevent strnpcinfo(0) + "::OnBar";
+		sleep2 5000;
 		specialeffect EF_BLACKBODY;
 		specialeffect EF_GUMGANG4;
 		specialeffect EF_DARKCASTING2;
@@ -1152,7 +1189,14 @@ S_Exchange:
 		specialeffect2 EF_POISONSMOKE;
 		specialeffect2 EF_NPC_BURNT;
 		delitem getarg(.@s),1;
-		getitem 6820, rand(1,3);// Energy Fragment
+		.@r = rand(100);
+		if (.@r < 70)
+			.@amount = 1;
+		else if (.@r < 90)
+			.@amount = 2;
+		else
+			.@amount = 3;
+		getitem 6820, .@amount;// Energy Fragment
 		mes "[Victimized Soul's Mind]";
 		mes "I have made... Energy... Fragment... by restoring ^006400" + getitemname(getarg(.@s)) + "^000000...";
 		next;
@@ -1163,6 +1207,10 @@ S_Exchange:
 	mes "Do you have... any other business... with me?...";
 	next;
 	return;
+
+OnBar:
+	progressbar_npc "000000",5;
+	end;
 }
 
 lhz_dun_n,136,269,6	script	Sorrowful Soul's Mind#1	4_M_DEATH,{
@@ -1226,6 +1274,12 @@ lhz_dun_n,136,269,6	script	Sorrowful Soul's Mind#1	4_M_DEATH,{
 		getitemname(18983),	// Old_Protect_Of_Crown
 		getitemname(20749);	// Cloak of the Fallen Soldier[1]
 	while(true) {
+		if (checkweight(2677,5) == 0) {
+			mes "[Sorrowful Soul's Mind]";
+			mes "Your backpack..";
+			mes "is filled...";
+			close;
+		}
 		if (select( "Hand over the soul.", "End the conversation." ) == 2) {
 			mes "[Sorrowful Soul's Mind]";
 			mes "...I wish... you... can come back... to me again...";

+ 10 - 10
npc/re/mobs/dungeons/lhz_dun_n.txt

@@ -28,9 +28,9 @@ lhz_dun_n,0,0,0	script	lhz_dun_n	-1,{
 	end;
 OnRegularDead:
 	.@mob_id = killedrid;
-	if (getd( ".lhz_dun_n" + .@mob_id ) < 100 && .lhz_dun_n_boss == 0) {
-		setd ".lhz_dun_n" + .@mob_id, getd( ".lhz_dun_n" + .@mob_id ) + 1;
-		if (getd( ".lhz_dun_n" + .@mob_id ) == 100) {
+	if (.lhz_dun_n[.@mob_id] < 110 && .lhz_dun_n_boss == 0) {
+		.lhz_dun_n[.@mob_id]++;
+		if (.lhz_dun_n[.@mob_id] == 110) {
 			.@mini_boss = .@mob_id + 6 + (.@mob_id > 3213);	// mini boss version ID: regular ID +6 for non-transcendent, +7 for others
 			monster "lhz_dun_n",0,0,"--en--",.@mini_boss,1, "lhz_dun_n::OnMiniDead";
 		}
@@ -38,15 +38,15 @@ OnRegularDead:
 	end;
 OnMiniDead:
 	.@mob_id = killedrid;
-	if (getd( ".lhz_dun_n" + .@mob_id ) < 10 && .lhz_dun_n_boss == 0) {
-		setd ".lhz_dun_n" + .@mob_id, getd( ".lhz_dun_n" + .@mob_id ) + 1;
+	if (.lhz_dun_n[.@mob_id] < 4 && .lhz_dun_n_boss == 0) {
+		.lhz_dun_n[.@mob_id]++;
 		.@regular = .@mob_id - 6 - (.@mob_id > 3219);
-		if (getd( ".lhz_dun_n" + .@mob_id ) < 10)
-			setd ".lhz_dun_n" + .@regular, 0;	// note: mini boss version can re-spawn when the count of mini boss dead is reached? (currently they don't)
+		if (.lhz_dun_n[.@mob_id] < 4)
+			.lhz_dun_n[.@regular] = 0;	// note: mini boss version can re-spawn when the count of mini boss dead is reached? (currently they don't)
 		else {
 			setarray .@mini_boss_list[0], 3214,3215,3216,3217,3218,3219,3233,3234,3235,3236,3237,3238,3239;
 			for ( .@i = 0; .@i < 13; ++.@i ) {	
-				if (getd( ".lhz_dun_n" + .@mini_boss_list[.@i] ) < 10)
+				if (.lhz_dun_n[.@mini_boss_list[.@i]] < 4)
 					end;
 			}
 			// MvP monster seems to only spawn at 12 o'clock
@@ -55,8 +55,8 @@ OnMiniDead:
 			.lhz_dun_n_boss = 1;
 			for ( .@i = 0; .@i < 13; ++.@i ) {	
 				.@regular = .@mini_boss_list[.@i] - 6 - (.@mini_boss_list[.@i] > 3219);
-				setd ".lhz_dun_n" + .@regular, 0;
-				setd ".lhz_dun_n" + .@mini_boss_list[.@i], 0;
+				.lhz_dun_n[.@regular] = 0;
+				.lhz_dun_n[.@mini_boss_list[.@i]] = 0;
 			}
 		}
 	}

+ 416 - 162
npc/re/other/achievements.txt

@@ -4,26 +4,18 @@
 //= Spawns Adventure group type treasure chests.
 //===== Changelogs: ==========================================
 //= 1.0 Initial release. [Aleos]
+//= 1.1 Corrected the position using official script. [Atemo]
 //============================================================
 
--	script	ach_treasure#core	-1,{
-	if (strnpcinfo(3) == "")
-		end;
-	achievementcomplete(atoi(strnpcinfo(3)));
-	classchange HIDDEN_WARP_NPC;
-	initnpctimer;
+// Triggers NPCs
+-	script	ach_treasure#touch	-1,{
 	end;
-
 OnTouch:
-	if (getnpctimer(1)) // Don't trigger touch if the delay timer is active.
+	sscanf( strnpcinfo(0), "#wp%d", .@num );
+	if (.@num == 0)
 		end;
-	if (achievementexists(atoi(strnpcinfo(3)))) // Don't trigger if the player has already completed.
-		end;
-	classchange 4_TREASURE_BOX,"",bc_self;
-	end;
-
-OnTimer5000:
-	stopnpctimer;
+	if (!achievementexists(.@num)) // Don't trigger if the player has already completed.
+		cloakoffnpc ("#tr" + .@num), getcharid(0);
 	end;
 }
 
@@ -32,250 +24,511 @@ OnTimer5000:
 //-----------------
 
 // Abbey Underground
-abbey03,26,72,0	duplicate(ach_treasure#core)	#abb_ach1::120110	HIDDEN_WARP_NPC,5,5
+abbey03,27,72,4	duplicate(ach_treasure#touch)	#wp120110	HIDDEN_WARP_NPC,5,5
+
+// Abyss Lake
+abyss_03,86,55,4	duplicate(ach_treasure#touch)	#wp120111	HIDDEN_WARP_NPC,5,5
+
+// Amatsu Dungeon
+ama_dun03,60,163,4	duplicate(ach_treasure#touch)	#wp120113	HIDDEN_WARP_NPC,5,5
+
+// Ant Hell
+anthell02,253,41,4	duplicate(ach_treasure#touch)	#wp120114	HIDDEN_WARP_NPC,5,5
+
+// Ayothaya Dungeon
+ayo_dun02,150,256,4	duplicate(ach_treasure#touch)	#wp120115	HIDDEN_WARP_NPC,5,5
+
+// Bifrost
+ecl_tdun04,37,37,4	duplicate(ach_treasure#touch)	#wp120121	HIDDEN_WARP_NPC,5,5
+
+// Brasilis Dungeon
+bra_dun02,171,121,4	duplicate(ach_treasure#touch)	#wp120117	HIDDEN_WARP_NPC,5,5
+
+// Byalan Dungeon
+iz_dun05,64,223,4	duplicate(ach_treasure#touch)	#wp120141	HIDDEN_WARP_NPC,5,5
+
+// Clock Tower
+c_tower4,37,158,4	duplicate(ach_treasure#touch)	#wp120112	HIDDEN_WARP_NPC,5,5
+alde_dun04,90,107,4	duplicate(ach_treasure#touch)	#wp120118	HIDDEN_WARP_NPC,5,5
+
+// Coal Mine
+mjo_dun03,76,220,4	duplicate(ach_treasure#touch)	#wp120136	HIDDEN_WARP_NPC,5,5
+
+// Comodo Dungeon
+beach_dun3,102,71,4	duplicate(ach_treasure#touch)	#wp120116	HIDDEN_WARP_NPC,5,5
+
+// Einbech
+ein_dun02,31,255,4	duplicate(ach_treasure#touch)	#wp120122	HIDDEN_WARP_NPC,5,5
+
+// Geffen Dungeon
+gef_dun02,222,163,4	duplicate(ach_treasure#touch)	#wp120123	HIDDEN_WARP_NPC,5,5
+
+// Glastheim
+gl_cas02,53,151,4	duplicate(ach_treasure#touch)	#wp120124	HIDDEN_WARP_NPC,5,5
+gl_sew04,288,6,4	duplicate(ach_treasure#touch)	#wp120125	HIDDEN_WARP_NPC,5,5
+gl_knt02,126,235,4	duplicate(ach_treasure#touch)	#wp120126	HIDDEN_WARP_NPC,5,5
+gl_prison1,126,158,4	duplicate(ach_treasure#touch)	#wp120127	HIDDEN_WARP_NPC,5,5
+
+// Kunlun Dungeon
+gon_dun03,166,231,4	duplicate(ach_treasure#touch)	#wp120128	HIDDEN_WARP_NPC,5,5
+
+// Istana
+dew_dun02,87,272,4	duplicate(ach_treasure#touch)	#wp120119	HIDDEN_WARP_NPC,5,5
+
+// Labyrinth
+prt_maze03,11,14,4	duplicate(ach_treasure#touch)	#wp120140	HIDDEN_WARP_NPC,5,5
+
+// Luoyang Dungeon
+lou_dun03,29,228,4	duplicate(ach_treasure#touch)	#wp120134	HIDDEN_WARP_NPC,5,5
+
+// Nogg Road
+mag_dun02,197,77,4	duplicate(ach_treasure#touch)	#wp120135	HIDDEN_WARP_NPC,5,5
+
+// Orc Dungeon
+orcsdun02,31,72,4	duplicate(ach_treasure#touch)	#wp120138	HIDDEN_WARP_NPC,5,5
+
+// Payon Dungeon
+pay_dun04,120,124,4	duplicate(ach_treasure#touch)	#wp120139	HIDDEN_WARP_NPC,5,5
+
+// Prontera Culvert
+prt_sewb4,19,183,4	duplicate(ach_treasure#touch)	#wp120131	HIDDEN_WARP_NPC,5,5
+
+// Pyramid
+moc_pryd06,102,121,4	duplicate(ach_treasure#touch)	#wp120137	HIDDEN_WARP_NPC,5,5
+
+// Rachel Dungeon
+ice_dun03,45,261,4	duplicate(ach_treasure#touch)	#wp120129	HIDDEN_WARP_NPC,5,5
+
+// Robot Factory
+kh_dun02,70,107,4	duplicate(ach_treasure#touch)	#wp120132	HIDDEN_WARP_NPC,5,5
+
+// Scaraba Hall
+dic_dun03,216,211,4	duplicate(ach_treasure#touch)	#wp120120	HIDDEN_WARP_NPC,5,5
+
+// Somatology Lab
+lhz_dun03,240,221,4	duplicate(ach_treasure#touch)	#wp120133	HIDDEN_WARP_NPC,5,5
+
+// Sphinx
+in_sphinx5,154,107,4	duplicate(ach_treasure#touch)	#wp120130	HIDDEN_WARP_NPC,5,5
+
+// Sunken Ship
+treasure02,19,142,4	duplicate(ach_treasure#touch)	#wp120144	HIDDEN_WARP_NPC,5,5
+
+// Thanatos Tower
+tha_t06,150,176,4	duplicate(ach_treasure#touch)	#wp120142	HIDDEN_WARP_NPC,5,5
+
+// Thors Volcano
+thor_v03,220,221,4	duplicate(ach_treasure#touch)	#wp120143	HIDDEN_WARP_NPC,5,5
+
+// Toy Factory
+xmas_dun02,120,224,4	duplicate(ach_treasure#touch)	#wp120146	HIDDEN_WARP_NPC,5,5
+
+// Turtle Island Dungeon
+tur_dun04,134,130,4	duplicate(ach_treasure#touch)	#wp120145	HIDDEN_WARP_NPC,5,5
+
+//---------------
+// --- Fields ---
+//---------------
+
+// Comodo
+cmd_fild01,112,200,4	duplicate(ach_treasure#touch)	#wp120044	HIDDEN_WARP_NPC,5,5
+cmd_fild02,86,94,4	duplicate(ach_treasure#touch)	#wp120045	HIDDEN_WARP_NPC,5,5
+cmd_fild03,144,190,4	duplicate(ach_treasure#touch)	#wp120046	HIDDEN_WARP_NPC,5,5
+cmd_fild04,151,191,4	duplicate(ach_treasure#touch)	#wp120047	HIDDEN_WARP_NPC,5,5
+cmd_fild06,221,108,4	duplicate(ach_treasure#touch)	#wp120048	HIDDEN_WARP_NPC,5,5
+cmd_fild07,269,322,4	duplicate(ach_treasure#touch)	#wp120049	HIDDEN_WARP_NPC,5,5
+cmd_fild08,181,136,4	duplicate(ach_treasure#touch)	#wp120050	HIDDEN_WARP_NPC,5,5
+cmd_fild09,211,266,4	duplicate(ach_treasure#touch)	#wp120051	HIDDEN_WARP_NPC,5,5
+
+// Einbroch
+ein_fild01,266,277,4	duplicate(ach_treasure#touch)	#wp120067	HIDDEN_WARP_NPC,5,5
+ein_fild03,99,332,4	duplicate(ach_treasure#touch)	#wp120068	HIDDEN_WARP_NPC,5,5
+ein_fild04,334,305,4	duplicate(ach_treasure#touch)	#wp120069	HIDDEN_WARP_NPC,5,5
+ein_fild05,337,233,4	duplicate(ach_treasure#touch)	#wp120070	HIDDEN_WARP_NPC,5,5
+ein_fild06,174,245,4	duplicate(ach_treasure#touch)	#wp120071	HIDDEN_WARP_NPC,5,5
+ein_fild07,188,50,4	duplicate(ach_treasure#touch)	#wp120072	HIDDEN_WARP_NPC,5,5
+ein_fild08,258,78,4	duplicate(ach_treasure#touch)	#wp120073	HIDDEN_WARP_NPC,5,5
+ein_fild09,330,76,4	duplicate(ach_treasure#touch)	#wp120074	HIDDEN_WARP_NPC,5,5
+
+// Geffen
+gef_fild00,73,119,4	duplicate(ach_treasure#touch)	#wp120011	HIDDEN_WARP_NPC,5,5
+gef_fild01,222,224,4	duplicate(ach_treasure#touch)	#wp120012	HIDDEN_WARP_NPC,5,5
+gef_fild05,202,292,4	duplicate(ach_treasure#touch)	#wp120013	HIDDEN_WARP_NPC,5,5
+gef_fild06,279,105,4	duplicate(ach_treasure#touch)	#wp120014	HIDDEN_WARP_NPC,5,5
+gef_fild07,184,249,4	duplicate(ach_treasure#touch)	#wp120015	HIDDEN_WARP_NPC,5,5
+gef_fild09,170,73,4	duplicate(ach_treasure#touch)	#wp120016	HIDDEN_WARP_NPC,5,5
+gef_fild11,239,248,4	duplicate(ach_treasure#touch)	#wp120017	HIDDEN_WARP_NPC,5,5
+
+// Hugel
+hu_fild01,347,312,4	duplicate(ach_treasure#touch)	#wp120062	HIDDEN_WARP_NPC,5,5
+hu_fild02,80,152,4	duplicate(ach_treasure#touch)	#wp120063	HIDDEN_WARP_NPC,5,5
+hu_fild04,322,313,4	duplicate(ach_treasure#touch)	#wp120064	HIDDEN_WARP_NPC,5,5
+hu_fild06,204,228,4	duplicate(ach_treasure#touch)	#wp120065	HIDDEN_WARP_NPC,5,5
+hu_fild05,197,210,4	duplicate(ach_treasure#touch)	#wp120066	HIDDEN_WARP_NPC,5,5
+
+// Laphine
+ecl_fild01,234,217,4	duplicate(ach_treasure#touch)	#wp120090	HIDDEN_WARP_NPC,5,5
+bif_fild01,147,64,4	duplicate(ach_treasure#touch)	#wp120091	HIDDEN_WARP_NPC,5,5
+bif_fild02,155,322,4	duplicate(ach_treasure#touch)	#wp120092	HIDDEN_WARP_NPC,5,5
+spl_fild01,335,315,4	duplicate(ach_treasure#touch)	#wp120093	HIDDEN_WARP_NPC,5,5
+spl_fild02,153,358,4	duplicate(ach_treasure#touch)	#wp120094	HIDDEN_WARP_NPC,5,5
+spl_fild03,61,286,4	duplicate(ach_treasure#touch)	#wp120095	HIDDEN_WARP_NPC,5,5
+
+// Lighthalzen
+lhz_fild01,118,73,4	duplicate(ach_treasure#touch)	#wp120075	HIDDEN_WARP_NPC,5,5
+lhz_fild02,239,243,4	duplicate(ach_treasure#touch)	#wp120076	HIDDEN_WARP_NPC,5,5
+lhz_fild03,313,132,4	duplicate(ach_treasure#touch)	#wp120077	HIDDEN_WARP_NPC,5,5
+
+// Manuk
+man_fild01,41,172,4	duplicate(ach_treasure#touch)	#wp120096	HIDDEN_WARP_NPC,5,5
+man_fild02,268,355,4	duplicate(ach_treasure#touch)	#wp120097	HIDDEN_WARP_NPC,5,5
+man_fild03,198,91,4	duplicate(ach_treasure#touch)	#wp120098	HIDDEN_WARP_NPC,5,5
+dic_fild01,227,82,4	duplicate(ach_treasure#touch)	#wp120099	HIDDEN_WARP_NPC,5,5
+dic_fild02,147,196,4	duplicate(ach_treasure#touch)	#wp120100	HIDDEN_WARP_NPC,5,5
+
+// Misc
+ama_fild01,187,337,4	duplicate(ach_treasure#touch)	#wp120101	HIDDEN_WARP_NPC,5,5
+gon_fild01,171,332,4	duplicate(ach_treasure#touch)	#wp120102	HIDDEN_WARP_NPC,5,5
+lou_fild01,104,232,4	duplicate(ach_treasure#touch)	#wp120103	HIDDEN_WARP_NPC,5,5
+ayo_fild01,289,70,4	duplicate(ach_treasure#touch)	#wp120104	HIDDEN_WARP_NPC,5,5
+mosk_fild02,176,77,4	duplicate(ach_treasure#touch)	#wp120105	HIDDEN_WARP_NPC,5,5
+bra_fild01,99,193,4	duplicate(ach_treasure#touch)	#wp120106	HIDDEN_WARP_NPC,5,5
+dew_fild01,175,287,4	duplicate(ach_treasure#touch)	#wp120107	HIDDEN_WARP_NPC,5,5
+ma_fild01,308,206,4	duplicate(ach_treasure#touch)	#wp120108	HIDDEN_WARP_NPC,5,5
+ma_fild02,246,323,4	duplicate(ach_treasure#touch)	#wp120109	HIDDEN_WARP_NPC,5,5
+
+// Mjolnir
+mjolnir_01,47,60,4	duplicate(ach_treasure#touch)	#wp120032	HIDDEN_WARP_NPC,5,5
+mjolnir_02,77,49,4	duplicate(ach_treasure#touch)	#wp120033	HIDDEN_WARP_NPC,5,5
+mjolnir_03,190,200,4	duplicate(ach_treasure#touch)	#wp120034	HIDDEN_WARP_NPC,5,5
+mjolnir_04,201,146,4	duplicate(ach_treasure#touch)	#wp120035	HIDDEN_WARP_NPC,5,5
+mjolnir_05,43,327,4	duplicate(ach_treasure#touch)	#wp120036	HIDDEN_WARP_NPC,5,5
+mjolnir_06,162,290,4	duplicate(ach_treasure#touch)	#wp120037	HIDDEN_WARP_NPC,5,5
+mjolnir_07,321,127,4	duplicate(ach_treasure#touch)	#wp120038	HIDDEN_WARP_NPC,5,5
+mjolnir_08,175,225,4	duplicate(ach_treasure#touch)	#wp120039	HIDDEN_WARP_NPC,5,5
+mjolnir_09,299,123,4	duplicate(ach_treasure#touch)	#wp120040	HIDDEN_WARP_NPC,5,5
+mjolnir_10,353,371,4	duplicate(ach_treasure#touch)	#wp120041	HIDDEN_WARP_NPC,5,5
+mjolnir_11,325,178,4	duplicate(ach_treasure#touch)	#wp120042	HIDDEN_WARP_NPC,5,5
+mjolnir_12,110,298,4	duplicate(ach_treasure#touch)	#wp120043	HIDDEN_WARP_NPC,5,5
+
+// Morocc
+moc_fild11,188,218,4	duplicate(ach_treasure#touch)	#wp120018	HIDDEN_WARP_NPC,5,5
+moc_fild12,234,96,4	duplicate(ach_treasure#touch)	#wp120019	HIDDEN_WARP_NPC,5,5
+moc_fild13,290,207,4	duplicate(ach_treasure#touch)	#wp120020	HIDDEN_WARP_NPC,5,5
+moc_fild16,196,108,4	duplicate(ach_treasure#touch)	#wp120021	HIDDEN_WARP_NPC,5,5
+moc_fild17,269,105,4	duplicate(ach_treasure#touch)	#wp120022	HIDDEN_WARP_NPC,5,5
+moc_fild18,54,284,4	duplicate(ach_treasure#touch)	#wp120023	HIDDEN_WARP_NPC,5,5
+
+// Payon
+pay_fild01,167,243,4	duplicate(ach_treasure#touch)	#wp120024	HIDDEN_WARP_NPC,5,5
+pay_fild02,105,240,4	duplicate(ach_treasure#touch)	#wp120025	HIDDEN_WARP_NPC,5,5
+pay_fild03,144,97,4	duplicate(ach_treasure#touch)	#wp120026	HIDDEN_WARP_NPC,5,5
+pay_fild04,257,95,4	duplicate(ach_treasure#touch)	#wp120027	HIDDEN_WARP_NPC,5,5
+pay_fild07,365,37,4	duplicate(ach_treasure#touch)	#wp120028	HIDDEN_WARP_NPC,5,5
+pay_fild08,237,345,4	duplicate(ach_treasure#touch)	#wp120029	HIDDEN_WARP_NPC,5,5
+pay_fild09,251,42,4	duplicate(ach_treasure#touch)	#wp120030	HIDDEN_WARP_NPC,5,5
+pay_fild10,196,38,4	duplicate(ach_treasure#touch)	#wp120031	HIDDEN_WARP_NPC,5,5
+
+// Prontera
+prt_fild01,146,126,4	duplicate(ach_treasure#touch)	#wp120001	HIDDEN_WARP_NPC,5,5
+prt_fild02,142,221,4	duplicate(ach_treasure#touch)	#wp120002	HIDDEN_WARP_NPC,5,5
+prt_fild03,172,139,4	duplicate(ach_treasure#touch)	#wp120003	HIDDEN_WARP_NPC,5,5
+prt_fild04,118,57,4	duplicate(ach_treasure#touch)	#wp120004	HIDDEN_WARP_NPC,5,5
+prt_fild05,189,291,4	duplicate(ach_treasure#touch)	#wp120005	HIDDEN_WARP_NPC,5,5
+prt_fild06,298,304,4	duplicate(ach_treasure#touch)	#wp120006	HIDDEN_WARP_NPC,5,5
+prt_fild07,44,104,4	duplicate(ach_treasure#touch)	#wp120007	HIDDEN_WARP_NPC,5,5
+prt_fild08,203,222,4	duplicate(ach_treasure#touch)	#wp120008	HIDDEN_WARP_NPC,5,5
+prt_fild09,37,354,4	duplicate(ach_treasure#touch)	#wp120009	HIDDEN_WARP_NPC,5,5
+prt_fild10,177,206,4	duplicate(ach_treasure#touch)	#wp120010	HIDDEN_WARP_NPC,5,5
+
+// Rachel
+ra_fild01,138,166,4	duplicate(ach_treasure#touch)	#wp120078	HIDDEN_WARP_NPC,5,5
+ra_fild03,224,275,4	duplicate(ach_treasure#touch)	#wp120079	HIDDEN_WARP_NPC,5,5
+ra_fild08,326,45,4	duplicate(ach_treasure#touch)	#wp120080	HIDDEN_WARP_NPC,5,5
+ra_fild12,352,165,4	duplicate(ach_treasure#touch)	#wp120081	HIDDEN_WARP_NPC,5,5
+ra_fild04,92,302,4	duplicate(ach_treasure#touch)	#wp120082	HIDDEN_WARP_NPC,5,5
+ra_fild05,59,59,4	duplicate(ach_treasure#touch)	#wp120083	HIDDEN_WARP_NPC,5,5
+ra_fild06,362,230,4	duplicate(ach_treasure#touch)	#wp120084	HIDDEN_WARP_NPC,5,5
+
+// Veins
+ve_fild01,180,234,4	duplicate(ach_treasure#touch)	#wp120085	HIDDEN_WARP_NPC,5,5
+ve_fild02,65,194,4	duplicate(ach_treasure#touch)	#wp120086	HIDDEN_WARP_NPC,5,5
+ve_fild03,197,242,4	duplicate(ach_treasure#touch)	#wp120087	HIDDEN_WARP_NPC,5,5
+ve_fild04,288,279,4	duplicate(ach_treasure#touch)	#wp120088	HIDDEN_WARP_NPC,5,5
+ve_fild07,33,113,4	duplicate(ach_treasure#touch)	#wp120089	HIDDEN_WARP_NPC,5,5
+
+// Juno
+yuno_fild01,284,138,4	duplicate(ach_treasure#touch)	#wp120052	HIDDEN_WARP_NPC,5,5
+yuno_fild12,76,268,4	duplicate(ach_treasure#touch)	#wp120053	HIDDEN_WARP_NPC,5,5
+yuno_fild02,142,191,4	duplicate(ach_treasure#touch)	#wp120054	HIDDEN_WARP_NPC,5,5
+yuno_fild03,135,329,4	duplicate(ach_treasure#touch)	#wp120055	HIDDEN_WARP_NPC,5,5
+yuno_fild04,35,369,4	duplicate(ach_treasure#touch)	#wp120056	HIDDEN_WARP_NPC,5,5
+yuno_fild06,262,220,4	duplicate(ach_treasure#touch)	#wp120057	HIDDEN_WARP_NPC,5,5
+yuno_fild07,113,339,4	duplicate(ach_treasure#touch)	#wp120058	HIDDEN_WARP_NPC,5,5
+yuno_fild08,179,209,4	duplicate(ach_treasure#touch)	#wp120059	HIDDEN_WARP_NPC,5,5
+yuno_fild09,166,228,4	duplicate(ach_treasure#touch)	#wp120060	HIDDEN_WARP_NPC,5,5
+yuno_fild11,141,357,4	duplicate(ach_treasure#touch)	#wp120061	HIDDEN_WARP_NPC,5,5
+
+
+// Treasures
+-	script	ach_treasure#click	-1,{
+	sscanf( strnpcinfo(0), "#tr%d", .@num );
+	if (.@num == 0)
+		end;
+	if (!achievementexists(.@num))
+		achievementcomplete(.@num);
+	cloakonnpc strnpcinfo(0), getcharid(0);
+	end;
+OnInit:
+	cloakonnpc strnpcinfo(0);
+	end;
+}
+
+// Abbey Underground
+abbey03,27,72,4	duplicate(ach_treasure#click)	#tr120110	4_TREASURE_BOX
 
 // Abyss Lake
-abyss_03,86,55,0	duplicate(ach_treasure#core)	#aby_ach1::120111	HIDDEN_WARP_NPC,5,5
+abyss_03,86,55,4	duplicate(ach_treasure#click)	#tr120111	4_TREASURE_BOX
 
 // Amatsu Dungeon
-ama_dun03,60,163,0	duplicate(ach_treasure#core)	#ama_ach1::120113	HIDDEN_WARP_NPC,5,5
+ama_dun03,60,163,4	duplicate(ach_treasure#click)	#tr120113	4_TREASURE_BOX
 
 // Ant Hell
-anthell02,253,41,0	duplicate(ach_treasure#core)	#ant_ach1::120114	HIDDEN_WARP_NPC,5,5
+anthell02,253,41,4	duplicate(ach_treasure#click)	#tr120114	4_TREASURE_BOX
 
 // Ayothaya Dungeon
-ayo_dun02,150,256,0	duplicate(ach_treasure#core)	#ayo_ach1::120115	HIDDEN_WARP_NPC,5,5
+ayo_dun02,150,256,4	duplicate(ach_treasure#click)	#tr120115	4_TREASURE_BOX
 
 // Bifrost
-ecl_tdun04,37,37,0	duplicate(ach_treasure#core)	#ecl_ach1::120121	HIDDEN_WARP_NPC,5,5
+ecl_tdun04,37,37,4	duplicate(ach_treasure#click)	#tr120121	4_TREASURE_BOX
 
 // Brasilis Dungeon
-bra_dun02,171,121,0	duplicate(ach_treasure#core)	#bra_ach1::120117	HIDDEN_WARP_NPC,5,5
+bra_dun02,171,121,4	duplicate(ach_treasure#click)	#tr120117	4_TREASURE_BOX
 
 // Byalan Dungeon
-iz_dun05,64,223,0	duplicate(ach_treasure#core)	#iz_ach2::120141	HIDDEN_WARP_NPC,5,5
+iz_dun05,64,223,4	duplicate(ach_treasure#click)	#tr120141	4_TREASURE_BOX
 
 // Clock Tower
-c_tower4,37,158,0	duplicate(ach_treasure#core)	#ct_ach1::120112	HIDDEN_WARP_NPC,5,5
-alde_dun04,90,107,0	duplicate(ach_treasure#core)	#ct_ach2::120118	HIDDEN_WARP_NPC,5,5
+c_tower4,37,158,4	duplicate(ach_treasure#click)	#tr120112	4_TREASURE_BOX
+alde_dun04,90,107,4	duplicate(ach_treasure#click)	#tr120118	4_TREASURE_BOX
 
 // Coal Mine
-mjo_dun03,76,220,0	duplicate(ach_treasure#core)	#mjo_ach1::120136	HIDDEN_WARP_NPC,5,5
+mjo_dun03,76,220,4	duplicate(ach_treasure#click)	#tr120136	4_TREASURE_BOX
 
 // Comodo Dungeon
-beach_dun3,102,71,0	duplicate(ach_treasure#core)	#bea_ach1::120116	HIDDEN_WARP_NPC,5,5
+beach_dun3,102,71,4	duplicate(ach_treasure#click)	#tr120116	4_TREASURE_BOX
 
 // Einbech
-ein_dun02,31,255,0	duplicate(ach_treasure#core)	#eind_ach1::120122	HIDDEN_WARP_NPC,5,5
+ein_dun02,31,255,4	duplicate(ach_treasure#click)	#tr120122	4_TREASURE_BOX
 
 // Geffen Dungeon
-gef_dun02,222,163,0	duplicate(ach_treasure#core)	#gefd_ach1::120123	HIDDEN_WARP_NPC,5,5
+gef_dun02,222,163,4	duplicate(ach_treasure#click)	#tr120123	4_TREASURE_BOX
 
 // Glastheim
-gl_cas02,53,151,0	duplicate(ach_treasure#core)	#gl_ach1::120124	HIDDEN_WARP_NPC,5,5
-gl_sew04,288,6,0	duplicate(ach_treasure#core)	#gl_ach2::120125	HIDDEN_WARP_NPC,5,5
-gl_knt02,126,235,0	duplicate(ach_treasure#core)	#gl_ach3::120126	HIDDEN_WARP_NPC,5,5
-gl_prison1,125,159,0	duplicate(ach_treasure#core)	#gl_ach4::120127	HIDDEN_WARP_NPC,5,5
+gl_cas02,53,151,4	duplicate(ach_treasure#click)	#tr120124	4_TREASURE_BOX
+gl_sew04,288,6,4	duplicate(ach_treasure#click)	#tr120125	4_TREASURE_BOX
+gl_knt02,126,235,4	duplicate(ach_treasure#click)	#tr120126	4_TREASURE_BOX
+gl_prison1,126,158,4	duplicate(ach_treasure#click)	#tr120127	4_TREASURE_BOX
 
 // Kunlun Dungeon
-gon_dun03,167,232,0	duplicate(ach_treasure#core)	#gon_ach1::120128	HIDDEN_WARP_NPC,5,5
+gon_dun03,166,231,4	duplicate(ach_treasure#click)	#tr120128	4_TREASURE_BOX
 
 // Istana
-dew_dun02,87,272,0	duplicate(ach_treasure#core)	#dew_ach1::120119	HIDDEN_WARP_NPC,5,5
+dew_dun02,87,272,4	duplicate(ach_treasure#click)	#tr120119	4_TREASURE_BOX
 
 // Labyrinth
-prt_maze03,11,14,0	duplicate(ach_treasure#core)	#maze_ach1::120140	HIDDEN_WARP_NPC,5,5
+prt_maze03,11,14,4	duplicate(ach_treasure#click)	#tr120140	4_TREASURE_BOX
 
 // Luoyang Dungeon
-lou_dun03,29,228,0	duplicate(ach_treasure#core)	#lou_ach1::120134	HIDDEN_WARP_NPC,5,5
+lou_dun03,29,228,4	duplicate(ach_treasure#click)	#tr120134	4_TREASURE_BOX
 
 // Nogg Road
-mag_dun02,192,72,0	duplicate(ach_treasure#core)	#mag_ach1::120135	HIDDEN_WARP_NPC,5,5
+mag_dun02,197,77,4	duplicate(ach_treasure#click)	#tr120135	4_TREASURE_BOX
 
 // Orc Dungeon
-orcsdun02,32,72,0	duplicate(ach_treasure#core)	#orc_ach1::120138	HIDDEN_WARP_NPC,5,5
+orcsdun02,31,72,4	duplicate(ach_treasure#click)	#tr120138	4_TREASURE_BOX
 
 // Payon Dungeon
-pay_dun04,120,124,0	duplicate(ach_treasure#core)	#payd_ach1::120139	HIDDEN_WARP_NPC,5,5
+pay_dun04,120,124,4	duplicate(ach_treasure#click)	#tr120139	4_TREASURE_BOX
 
 // Prontera Culvert
-prt_sewb4,19,183,0	duplicate(ach_treasure#core)	#iz_ach1::120131	HIDDEN_WARP_NPC,5,5
+prt_sewb4,19,183,4	duplicate(ach_treasure#click)	#tr120131	4_TREASURE_BOX
 
 // Pyramid
-moc_pryd06,102,121,0	duplicate(ach_treasure#core)	#pyr_ach1::120137	HIDDEN_WARP_NPC,5,5
+moc_pryd06,102,121,4	duplicate(ach_treasure#click)	#tr120137	4_TREASURE_BOX
 
 // Rachel Dungeon
-ice_dun03,44,261,0	duplicate(ach_treasure#core)	#rad_ach1::120129	HIDDEN_WARP_NPC,5,5
+ice_dun03,45,261,4	duplicate(ach_treasure#click)	#tr120129	4_TREASURE_BOX
 
 // Robot Factory
-kh_dun02,70,106,0	duplicate(ach_treasure#core)	#jup_ach1::120132	HIDDEN_WARP_NPC,5,5
+kh_dun02,70,107,4	duplicate(ach_treasure#click)	#tr120132	4_TREASURE_BOX
 
 // Scaraba Hall
-dic_dun03,216,211,0	duplicate(ach_treasure#core)	#dic_ach1::120120	HIDDEN_WARP_NPC,5,5
+dic_dun03,216,211,4	duplicate(ach_treasure#click)	#tr120120	4_TREASURE_BOX
 
 // Somatology Lab
-lhz_dun03,240,221,0	duplicate(ach_treasure#core)	#lhzd_ach1::120133	HIDDEN_WARP_NPC,5,5
+lhz_dun03,240,221,4	duplicate(ach_treasure#click)	#tr120133	4_TREASURE_BOX
 
 // Sphinx
-in_sphinx5,154,107,0	duplicate(ach_treasure#core)	#sph_ach1::120130	HIDDEN_WARP_NPC,5,5
+in_sphinx5,154,107,4	duplicate(ach_treasure#click)	#tr120130	4_TREASURE_BOX
 
 // Sunken Ship
-treasure02,18,142,0	duplicate(ach_treasure#core)	#iz_ach3::120144	HIDDEN_WARP_NPC,5,5
+treasure02,19,142,4	duplicate(ach_treasure#click)	#tr120144	4_TREASURE_BOX
 
 // Thanatos Tower
-tha_t06,150,176,0	duplicate(ach_treasure#core)	#tha_ach1::120142	HIDDEN_WARP_NPC,5,5
+tha_t06,150,176,4	duplicate(ach_treasure#click)	#tr120142	4_TREASURE_BOX
 
 // Thors Volcano
-thor_v03,220,221,0	duplicate(ach_treasure#core)	#thor_ach1::120143	HIDDEN_WARP_NPC,5,5
+thor_v03,220,221,4	duplicate(ach_treasure#click)	#tr120143	4_TREASURE_BOX
 
 // Toy Factory
-xmas_dun02,120,224,0	duplicate(ach_treasure#core)	#xmas_ach1::120146	HIDDEN_WARP_NPC,5,5
+xmas_dun02,120,224,4	duplicate(ach_treasure#click)	#tr120146	4_TREASURE_BOX
 
 // Turtle Island Dungeon
-tur_dun04,134,130,0	duplicate(ach_treasure#core)	#tur_ach1::120145	HIDDEN_WARP_NPC,5,5
+tur_dun04,134,130,4	duplicate(ach_treasure#click)	#tr120145	4_TREASURE_BOX
 
 //---------------
 // --- Fields ---
 //---------------
 
 // Comodo
-cmd_fild01,112,200,0	duplicate(ach_treasure#core)	#cmd_ach1::120044	HIDDEN_WARP_NPC,5,5
-cmd_fild02,86,94,0	duplicate(ach_treasure#core)	#cmd_ach2::120045	HIDDEN_WARP_NPC,5,5
-cmd_fild03,144,190,0	duplicate(ach_treasure#core)	#cmd_ach3::120046	HIDDEN_WARP_NPC,5,5
-cmd_fild04,151,191,0	duplicate(ach_treasure#core)	#cmd_ach4::120047	HIDDEN_WARP_NPC,5,5
-cmd_fild06,221,108,0	duplicate(ach_treasure#core)	#cmd_ach5::120048	HIDDEN_WARP_NPC,5,5
-cmd_fild07,269,322,0	duplicate(ach_treasure#core)	#cmd_ach6::120049	HIDDEN_WARP_NPC,5,5
-cmd_fild08,181,136,0	duplicate(ach_treasure#core)	#cmd_ach7::120050	HIDDEN_WARP_NPC,5,5
-cmd_fild09,211,266,0	duplicate(ach_treasure#core)	#cmd_ach8::120051	HIDDEN_WARP_NPC,5,5
+cmd_fild01,112,200,4	duplicate(ach_treasure#click)	#tr120044	4_TREASURE_BOX
+cmd_fild02,86,94,4	duplicate(ach_treasure#click)	#tr120045	4_TREASURE_BOX
+cmd_fild03,144,190,4	duplicate(ach_treasure#click)	#tr120046	4_TREASURE_BOX
+cmd_fild04,151,191,4	duplicate(ach_treasure#click)	#tr120047	4_TREASURE_BOX
+cmd_fild06,221,108,4	duplicate(ach_treasure#click)	#tr120048	4_TREASURE_BOX
+cmd_fild07,269,322,4	duplicate(ach_treasure#click)	#tr120049	4_TREASURE_BOX
+cmd_fild08,181,136,4	duplicate(ach_treasure#click)	#tr120050	4_TREASURE_BOX
+cmd_fild09,211,266,4	duplicate(ach_treasure#click)	#tr120051	4_TREASURE_BOX
 
 // Einbroch
-ein_fild01,266,277,0	duplicate(ach_treasure#core)	#ein_ach1::120067	HIDDEN_WARP_NPC,5,5
-ein_fild03,99,332,0	duplicate(ach_treasure#core)	#ein_ach2::120068	HIDDEN_WARP_NPC,5,5
-ein_fild04,334,305,0	duplicate(ach_treasure#core)	#ein_ach3::120069	HIDDEN_WARP_NPC,5,5
-ein_fild05,337,233,0	duplicate(ach_treasure#core)	#ein_ach4::120070	HIDDEN_WARP_NPC,5,5
-ein_fild06,174,245,0	duplicate(ach_treasure#core)	#ein_ach5::120071	HIDDEN_WARP_NPC,5,5
-ein_fild07,188,50,0	duplicate(ach_treasure#core)	#ein_ach6::120072	HIDDEN_WARP_NPC,5,5
-ein_fild08,258,78,0	duplicate(ach_treasure#core)	#ein_ach7::120073	HIDDEN_WARP_NPC,5,5
-ein_fild09,330,76,0	duplicate(ach_treasure#core)	#ein_ach8::120074	HIDDEN_WARP_NPC,5,5
+ein_fild01,266,277,4	duplicate(ach_treasure#click)	#tr120067	4_TREASURE_BOX
+ein_fild03,99,332,4	duplicate(ach_treasure#click)	#tr120068	4_TREASURE_BOX
+ein_fild04,334,305,4	duplicate(ach_treasure#click)	#tr120069	4_TREASURE_BOX
+ein_fild05,337,233,4	duplicate(ach_treasure#click)	#tr120070	4_TREASURE_BOX
+ein_fild06,174,245,4	duplicate(ach_treasure#click)	#tr120071	4_TREASURE_BOX
+ein_fild07,188,50,4	duplicate(ach_treasure#click)	#tr120072	4_TREASURE_BOX
+ein_fild08,258,78,4	duplicate(ach_treasure#click)	#tr120073	4_TREASURE_BOX
+ein_fild09,330,76,4	duplicate(ach_treasure#click)	#tr120074	4_TREASURE_BOX
 
 // Geffen
-gef_fild00,74,119,0	duplicate(ach_treasure#core)	#gef_ach1::120011	HIDDEN_WARP_NPC,5,5
-gef_fild01,223,223,0	duplicate(ach_treasure#core)	#gef_ach2::120012	HIDDEN_WARP_NPC,5,5
-gef_fild05,202,292,0	duplicate(ach_treasure#core)	#gef_ach3::120013	HIDDEN_WARP_NPC,5,5
-gef_fild06,279,104,0	duplicate(ach_treasure#core)	#gef_ach4::120014	HIDDEN_WARP_NPC,5,5
-gef_fild07,181,250,0	duplicate(ach_treasure#core)	#gef_ach5::120015	HIDDEN_WARP_NPC,5,5
-gef_fild09,170,73,0	duplicate(ach_treasure#core)	#gef_ach6::120016	HIDDEN_WARP_NPC,5,5
-gef_fild11,238,249,0	duplicate(ach_treasure#core)	#gef_ach7::120017	HIDDEN_WARP_NPC,5,5
+gef_fild00,73,119,4	duplicate(ach_treasure#click)	#tr120011	4_TREASURE_BOX
+gef_fild01,222,224,4	duplicate(ach_treasure#click)	#tr120012	4_TREASURE_BOX
+gef_fild05,202,292,4	duplicate(ach_treasure#click)	#tr120013	4_TREASURE_BOX
+gef_fild06,279,105,4	duplicate(ach_treasure#click)	#tr120014	4_TREASURE_BOX
+gef_fild07,184,249,4	duplicate(ach_treasure#click)	#tr120015	4_TREASURE_BOX
+gef_fild09,170,73,4	duplicate(ach_treasure#click)	#tr120016	4_TREASURE_BOX
+gef_fild11,239,248,4	duplicate(ach_treasure#click)	#tr120017	4_TREASURE_BOX
 
 // Hugel
-hu_fild01,347,312,0	duplicate(ach_treasure#core)	#hu_ach1::120062	HIDDEN_WARP_NPC,5,5
-hu_fild02,80,152,0	duplicate(ach_treasure#core)	#hu_ach2::120063	HIDDEN_WARP_NPC,5,5
-hu_fild04,322,313,0	duplicate(ach_treasure#core)	#hu_ach3::120064	HIDDEN_WARP_NPC,5,5
-hu_fild06,204,228,0	duplicate(ach_treasure#core)	#hu_ach4::120065	HIDDEN_WARP_NPC,5,5
-hu_fild05,197,210,0	duplicate(ach_treasure#core)	#hu_ach5::120066	HIDDEN_WARP_NPC,5,5
+hu_fild01,347,312,4	duplicate(ach_treasure#click)	#tr120062	4_TREASURE_BOX
+hu_fild02,80,152,4	duplicate(ach_treasure#click)	#tr120063	4_TREASURE_BOX
+hu_fild04,322,313,4	duplicate(ach_treasure#click)	#tr120064	4_TREASURE_BOX
+hu_fild06,204,228,4	duplicate(ach_treasure#click)	#tr120065	4_TREASURE_BOX
+hu_fild05,197,210,4	duplicate(ach_treasure#click)	#tr120066	4_TREASURE_BOX
 
 // Laphine
-ecl_fild01,155,322,0	duplicate(ach_treasure#core)	#ecl_ach1::120090	HIDDEN_WARP_NPC,5,5
-bif_fild01,147,64,0	duplicate(ach_treasure#core)	#ecl_ach2::120091	HIDDEN_WARP_NPC,5,5
-bif_fild02,155,322,0	duplicate(ach_treasure#core)	#ecl_ach3::120092	HIDDEN_WARP_NPC,5,5
-spl_fild01,335,315,0	duplicate(ach_treasure#core)	#ecl_ach4::120093	HIDDEN_WARP_NPC,5,5
-spl_fild02,153,358,0	duplicate(ach_treasure#core)	#ecl_ach5::120094	HIDDEN_WARP_NPC,5,5
-spl_fild03,61,286,0	duplicate(ach_treasure#core)	#ecl_ach6::120095	HIDDEN_WARP_NPC,5,5
+ecl_fild01,234,217,4	duplicate(ach_treasure#click)	#tr120090	4_TREASURE_BOX
+bif_fild01,147,64,4	duplicate(ach_treasure#click)	#tr120091	4_TREASURE_BOX
+bif_fild02,155,322,4	duplicate(ach_treasure#click)	#tr120092	4_TREASURE_BOX
+spl_fild01,335,315,4	duplicate(ach_treasure#click)	#tr120093	4_TREASURE_BOX
+spl_fild02,153,358,4	duplicate(ach_treasure#click)	#tr120094	4_TREASURE_BOX
+spl_fild03,61,286,4	duplicate(ach_treasure#click)	#tr120095	4_TREASURE_BOX
 
 // Lighthalzen
-lhz_fild01,118,73,0	duplicate(ach_treasure#core)	#lhz_ach1::120075	HIDDEN_WARP_NPC,5,5
-lhz_fild02,239,243,0	duplicate(ach_treasure#core)	#lhz_ach2::120076	HIDDEN_WARP_NPC,5,5
-lhz_fild03,313,132,0	duplicate(ach_treasure#core)	#lhz_ach3::120077	HIDDEN_WARP_NPC,5,5
+lhz_fild01,118,73,4	duplicate(ach_treasure#click)	#tr120075	4_TREASURE_BOX
+lhz_fild02,239,243,4	duplicate(ach_treasure#click)	#tr120076	4_TREASURE_BOX
+lhz_fild03,313,132,4	duplicate(ach_treasure#click)	#tr120077	4_TREASURE_BOX
 
 // Manuk
-man_fild01,41,172,0	duplicate(ach_treasure#core)	#man_ach1::120096	HIDDEN_WARP_NPC,5,5
-man_fild02,268,355,0	duplicate(ach_treasure#core)	#man_ach2::120097	HIDDEN_WARP_NPC,5,5
-man_fild03,198,91,0	duplicate(ach_treasure#core)	#man_ach3::120098	HIDDEN_WARP_NPC,5,5
-dic_fild01,227,82,0	duplicate(ach_treasure#core)	#man_ach4::120099	HIDDEN_WARP_NPC,5,5
-dic_fild02,147,196,0	duplicate(ach_treasure#core)	#man_ach5::120100	HIDDEN_WARP_NPC,5,5
+man_fild01,41,172,4	duplicate(ach_treasure#click)	#tr120096	4_TREASURE_BOX
+man_fild02,268,355,4	duplicate(ach_treasure#click)	#tr120097	4_TREASURE_BOX
+man_fild03,198,91,4	duplicate(ach_treasure#click)	#tr120098	4_TREASURE_BOX
+dic_fild01,227,82,4	duplicate(ach_treasure#click)	#tr120099	4_TREASURE_BOX
+dic_fild02,147,196,4	duplicate(ach_treasure#click)	#tr120100	4_TREASURE_BOX
 
 // Misc
-ama_fild01,187,337,0	duplicate(ach_treasure#core)	#misc_ach1::120101	HIDDEN_WARP_NPC,5,5
-gon_fild01,171,332,0	duplicate(ach_treasure#core)	#misc_ach2::120102	HIDDEN_WARP_NPC,5,5
-lou_fild01,104,232,0	duplicate(ach_treasure#core)	#misc_ach3::120103	HIDDEN_WARP_NPC,5,5
-ayo_fild01,289,70,0	duplicate(ach_treasure#core)	#misc_ach4::120104	HIDDEN_WARP_NPC,5,5
-mosk_fild02,176,77,0	duplicate(ach_treasure#core)	#misc_ach5::120105	HIDDEN_WARP_NPC,5,5
-bra_fild01,99,193,0	duplicate(ach_treasure#core)	#misc_ach6::120106	HIDDEN_WARP_NPC,5,5
-dew_fild01,175,287,0	duplicate(ach_treasure#core)	#misc_ach7::120107	HIDDEN_WARP_NPC,5,5
-ma_fild01,308,206,0	duplicate(ach_treasure#core)	#misc_ach8::120108	HIDDEN_WARP_NPC,5,5
-ma_fild02,176,77,0	duplicate(ach_treasure#core)	#misc_ach9::120109	HIDDEN_WARP_NPC,5,5
+ama_fild01,187,337,4	duplicate(ach_treasure#click)	#tr120101	4_TREASURE_BOX
+gon_fild01,171,332,4	duplicate(ach_treasure#click)	#tr120102	4_TREASURE_BOX
+lou_fild01,104,232,4	duplicate(ach_treasure#click)	#tr120103	4_TREASURE_BOX
+ayo_fild01,289,70,4	duplicate(ach_treasure#click)	#tr120104	4_TREASURE_BOX
+mosk_fild02,176,77,4	duplicate(ach_treasure#click)	#tr120105	4_TREASURE_BOX
+bra_fild01,99,193,4	duplicate(ach_treasure#click)	#tr120106	4_TREASURE_BOX
+dew_fild01,175,287,4	duplicate(ach_treasure#click)	#tr120107	4_TREASURE_BOX
+ma_fild01,308,206,4	duplicate(ach_treasure#click)	#tr120108	4_TREASURE_BOX
+ma_fild02,246,323,4	duplicate(ach_treasure#click)	#tr120109	4_TREASURE_BOX
 
 // Mjolnir
-mjolnir_01,47,60,0	duplicate(ach_treasure#core)	#nmjo_ach1::120032	HIDDEN_WARP_NPC,5,5
-mjolnir_02,77,49,0	duplicate(ach_treasure#core)	#nmjo_ach2::120033	HIDDEN_WARP_NPC,5,5
-mjolnir_03,190,200,0	duplicate(ach_treasure#core)	#nmjo_ach3::120034	HIDDEN_WARP_NPC,5,5
-mjolnir_04,201,146,0	duplicate(ach_treasure#core)	#nmjo_ach4::120035	HIDDEN_WARP_NPC,5,5
-mjolnir_05,43,327,0	duplicate(ach_treasure#core)	#nmjo_ach5::120036	HIDDEN_WARP_NPC,5,5
-mjolnir_06,162,290,0	duplicate(ach_treasure#core)	#smjo_ach1::120037	HIDDEN_WARP_NPC,5,5
-mjolnir_07,321,127,0	duplicate(ach_treasure#core)	#smjo_ach2::120038	HIDDEN_WARP_NPC,5,5
-mjolnir_08,175,225,0	duplicate(ach_treasure#core)	#smjo_ach3::120039	HIDDEN_WARP_NPC,5,5
-mjolnir_09,299,123,0	duplicate(ach_treasure#core)	#smjo_ach4::120040	HIDDEN_WARP_NPC,5,5
-mjolnir_10,353,371,0	duplicate(ach_treasure#core)	#smjo_ach5::120041	HIDDEN_WARP_NPC,5,5
-mjolnir_11,329,182,0	duplicate(ach_treasure#core)	#smjo_ach6::120042	HIDDEN_WARP_NPC,5,5
-mjolnir_12,110,298,0	duplicate(ach_treasure#core)	#smjo_ach7::120043	HIDDEN_WARP_NPC,5,5
+mjolnir_01,47,60,4	duplicate(ach_treasure#click)	#tr120032	4_TREASURE_BOX
+mjolnir_02,77,49,4	duplicate(ach_treasure#click)	#tr120033	4_TREASURE_BOX
+mjolnir_03,190,200,4	duplicate(ach_treasure#click)	#tr120034	4_TREASURE_BOX
+mjolnir_04,201,146,4	duplicate(ach_treasure#click)	#tr120035	4_TREASURE_BOX
+mjolnir_05,43,327,4	duplicate(ach_treasure#click)	#tr120036	4_TREASURE_BOX
+mjolnir_06,162,290,4	duplicate(ach_treasure#click)	#tr120037	4_TREASURE_BOX
+mjolnir_07,321,127,4	duplicate(ach_treasure#click)	#tr120038	4_TREASURE_BOX
+mjolnir_08,175,225,4	duplicate(ach_treasure#click)	#tr120039	4_TREASURE_BOX
+mjolnir_09,299,123,4	duplicate(ach_treasure#click)	#tr120040	4_TREASURE_BOX
+mjolnir_10,353,371,4	duplicate(ach_treasure#click)	#tr120041	4_TREASURE_BOX
+mjolnir_11,325,178,4	duplicate(ach_treasure#click)	#tr120042	4_TREASURE_BOX
+mjolnir_12,110,298,4	duplicate(ach_treasure#click)	#tr120043	4_TREASURE_BOX
 
 // Morocc
-moc_fild11,188,218,0	duplicate(ach_treasure#core)	#moc_ach1::120018	HIDDEN_WARP_NPC,5,5
-moc_fild12,234,96,0	duplicate(ach_treasure#core)	#moc_ach2::120019	HIDDEN_WARP_NPC,5,5
-moc_fild13,290,207,0	duplicate(ach_treasure#core)	#moc_ach3::120020	HIDDEN_WARP_NPC,5,5
-moc_fild16,196,108,0	duplicate(ach_treasure#core)	#moc_ach4::120021	HIDDEN_WARP_NPC,5,5
-moc_fild17,269,105,0	duplicate(ach_treasure#core)	#moc_ach5::120022	HIDDEN_WARP_NPC,5,5
-moc_fild18,54,284,0	duplicate(ach_treasure#core)	#moc_ach6::120023	HIDDEN_WARP_NPC,5,5
+moc_fild11,188,218,4	duplicate(ach_treasure#click)	#tr120018	4_TREASURE_BOX
+moc_fild12,234,96,4	duplicate(ach_treasure#click)	#tr120019	4_TREASURE_BOX
+moc_fild13,290,207,4	duplicate(ach_treasure#click)	#tr120020	4_TREASURE_BOX
+moc_fild16,196,108,4	duplicate(ach_treasure#click)	#tr120021	4_TREASURE_BOX
+moc_fild17,269,105,4	duplicate(ach_treasure#click)	#tr120022	4_TREASURE_BOX
+moc_fild18,54,284,4	duplicate(ach_treasure#click)	#tr120023	4_TREASURE_BOX
 
 // Payon
-pay_fild01,167,243,0	duplicate(ach_treasure#core)	#pay_ach1::120024	HIDDEN_WARP_NPC,5,5
-pay_fild02,105,240,0	duplicate(ach_treasure#core)	#pay_ach2::120025	HIDDEN_WARP_NPC,5,5
-pay_fild03,144,97,0	duplicate(ach_treasure#core)	#pay_ach3::120026	HIDDEN_WARP_NPC,5,5
-pay_fild04,257,95,0	duplicate(ach_treasure#core)	#pay_ach4::120027	HIDDEN_WARP_NPC,5,5
-pay_fild07,365,37,0	duplicate(ach_treasure#core)	#pay_ach5::120028	HIDDEN_WARP_NPC,5,5
-pay_fild08,237,345,0	duplicate(ach_treasure#core)	#pay_ach6::120029	HIDDEN_WARP_NPC,5,5
-pay_fild09,251,42,0	duplicate(ach_treasure#core)	#pay_ach7::120030	HIDDEN_WARP_NPC,5,5
-pay_fild10,196,38,0	duplicate(ach_treasure#core)	#pay_ach8::120031	HIDDEN_WARP_NPC,5,5
+pay_fild01,167,243,4	duplicate(ach_treasure#click)	#tr120024	4_TREASURE_BOX
+pay_fild02,105,240,4	duplicate(ach_treasure#click)	#tr120025	4_TREASURE_BOX
+pay_fild03,144,97,4	duplicate(ach_treasure#click)	#tr120026	4_TREASURE_BOX
+pay_fild04,257,95,4	duplicate(ach_treasure#click)	#tr120027	4_TREASURE_BOX
+pay_fild07,365,37,4	duplicate(ach_treasure#click)	#tr120028	4_TREASURE_BOX
+pay_fild08,237,345,4	duplicate(ach_treasure#click)	#tr120029	4_TREASURE_BOX
+pay_fild09,251,42,4	duplicate(ach_treasure#click)	#tr120030	4_TREASURE_BOX
+pay_fild10,196,38,4	duplicate(ach_treasure#click)	#tr120031	4_TREASURE_BOX
 
 // Prontera
-prt_fild01,147,126,0	duplicate(ach_treasure#core)	#prt_ach1::120001	HIDDEN_WARP_NPC,5,5
-prt_fild02,140,219,0	duplicate(ach_treasure#core)	#prt_ach2::120002	HIDDEN_WARP_NPC,5,5
-prt_fild03,172,139,0	duplicate(ach_treasure#core)	#prt_ach3::120003	HIDDEN_WARP_NPC,5,5
-prt_fild04,119,291,0	duplicate(ach_treasure#core)	#prt_ach4::120004	HIDDEN_WARP_NPC,5,5
-prt_fild05,190,291,0	duplicate(ach_treasure#core)	#prt_ach5::120005	HIDDEN_WARP_NPC,5,5
-prt_fild06,296,303,0	duplicate(ach_treasure#core)	#prt_ach6::120006	HIDDEN_WARP_NPC,5,5
-prt_fild07,45,104,0	duplicate(ach_treasure#core)	#prt_ach7::120007	HIDDEN_WARP_NPC,5,5
-prt_fild08,203,223,0	duplicate(ach_treasure#core)	#prt_ach8::120008	HIDDEN_WARP_NPC,5,5
-prt_fild09,37,354,0	duplicate(ach_treasure#core)	#prt_ach9::120009	HIDDEN_WARP_NPC,5,5
-prt_fild10,177,206,0	duplicate(ach_treasure#core)	#prt_ach10::120010	HIDDEN_WARP_NPC,5,5
+prt_fild01,146,126,4	duplicate(ach_treasure#click)	#tr120001	4_TREASURE_BOX
+prt_fild02,142,221,4	duplicate(ach_treasure#click)	#tr120002	4_TREASURE_BOX
+prt_fild03,172,139,4	duplicate(ach_treasure#click)	#tr120003	4_TREASURE_BOX
+prt_fild04,118,57,4	duplicate(ach_treasure#click)	#tr120004	4_TREASURE_BOX
+prt_fild05,189,291,4	duplicate(ach_treasure#click)	#tr120005	4_TREASURE_BOX
+prt_fild06,298,304,4	duplicate(ach_treasure#click)	#tr120006	4_TREASURE_BOX
+prt_fild07,44,104,4	duplicate(ach_treasure#click)	#tr120007	4_TREASURE_BOX
+prt_fild08,203,222,4	duplicate(ach_treasure#click)	#tr120008	4_TREASURE_BOX
+prt_fild09,37,354,4	duplicate(ach_treasure#click)	#tr120009	4_TREASURE_BOX
+prt_fild10,177,206,4	duplicate(ach_treasure#click)	#tr120010	4_TREASURE_BOX
 
 // Rachel
-ra_fild01,138,166,0	duplicate(ach_treasure#core)	#ra_ach1::120078	HIDDEN_WARP_NPC,5,5
-ra_fild03,224,275,0	duplicate(ach_treasure#core)	#ra_ach2::120079	HIDDEN_WARP_NPC,5,5
-ra_fild08,326,45,0	duplicate(ach_treasure#core)	#ra_ach3::120080	HIDDEN_WARP_NPC,5,5
-ra_fild12,352,165,0	duplicate(ach_treasure#core)	#ra_ach4::120081	HIDDEN_WARP_NPC,5,5
-ra_fild04,92,302,0	duplicate(ach_treasure#core)	#ra_ach5::120082	HIDDEN_WARP_NPC,5,5
-ra_fild05,59,59,0	duplicate(ach_treasure#core)	#ra_ach6::120083	HIDDEN_WARP_NPC,5,5
-ra_fild06,362,230,0	duplicate(ach_treasure#core)	#ra_ach7::120084	HIDDEN_WARP_NPC,5,5
+ra_fild01,138,166,4	duplicate(ach_treasure#click)	#tr120078	4_TREASURE_BOX
+ra_fild03,224,275,4	duplicate(ach_treasure#click)	#tr120079	4_TREASURE_BOX
+ra_fild08,326,45,4	duplicate(ach_treasure#click)	#tr120080	4_TREASURE_BOX
+ra_fild12,352,165,4	duplicate(ach_treasure#click)	#tr120081	4_TREASURE_BOX
+ra_fild04,92,302,4	duplicate(ach_treasure#click)	#tr120082	4_TREASURE_BOX
+ra_fild05,59,59,4	duplicate(ach_treasure#click)	#tr120083	4_TREASURE_BOX
+ra_fild06,362,230,4	duplicate(ach_treasure#click)	#tr120084	4_TREASURE_BOX
 
 // Veins
-ve_fild01,180,234,0	duplicate(ach_treasure#core)	#ve_ach1::120085	HIDDEN_WARP_NPC,5,5
-ve_fild02,65,194,0	duplicate(ach_treasure#core)	#ve_ach2::120086	HIDDEN_WARP_NPC,5,5
-ve_fild03,197,242,0	duplicate(ach_treasure#core)	#ve_ach3::120087	HIDDEN_WARP_NPC,5,5
-ve_fild04,288,279,0	duplicate(ach_treasure#core)	#ve_ach4::120088	HIDDEN_WARP_NPC,5,5
-ve_fild07,33,113,0	duplicate(ach_treasure#core)	#ve_ach5::120089	HIDDEN_WARP_NPC,5,5
+ve_fild01,180,234,4	duplicate(ach_treasure#click)	#tr120085	4_TREASURE_BOX
+ve_fild02,65,194,4	duplicate(ach_treasure#click)	#tr120086	4_TREASURE_BOX
+ve_fild03,197,242,4	duplicate(ach_treasure#click)	#tr120087	4_TREASURE_BOX
+ve_fild04,288,279,4	duplicate(ach_treasure#click)	#tr120088	4_TREASURE_BOX
+ve_fild07,33,113,4	duplicate(ach_treasure#click)	#tr120089	4_TREASURE_BOX
 
 // Juno
-yuno_fild01,284,138,0	duplicate(ach_treasure#core)	#yuno_ach1::120052	HIDDEN_WARP_NPC,5,5
-yuno_fild12,76,268,0	duplicate(ach_treasure#core)	#yuno_ach2::120053	HIDDEN_WARP_NPC,5,5
-yuno_fild02,142,191,0	duplicate(ach_treasure#core)	#yuno_ach3::120054	HIDDEN_WARP_NPC,5,5
-yuno_fild03,135,329,0	duplicate(ach_treasure#core)	#yuno_ach4::120055	HIDDEN_WARP_NPC,5,5
-yuno_fild04,35,369,0	duplicate(ach_treasure#core)	#yuno_ach5::120056	HIDDEN_WARP_NPC,5,5
-yuno_fild06,262,220,0	duplicate(ach_treasure#core)	#yuno_ach6::120057	HIDDEN_WARP_NPC,5,5
-yuno_fild07,113,339,0	duplicate(ach_treasure#core)	#yuno_ach7::120058	HIDDEN_WARP_NPC,5,5
-yuno_fild08,179,209,0	duplicate(ach_treasure#core)	#yuno_ach8::120059	HIDDEN_WARP_NPC,5,5
-yuno_fild09,166,228,0	duplicate(ach_treasure#core)	#yuno_ach9::120060	HIDDEN_WARP_NPC,5,5
-yuno_fild11,141,357,0	duplicate(ach_treasure#core)	#yuno_ach10::120061	HIDDEN_WARP_NPC,5,5
+yuno_fild01,284,138,4	duplicate(ach_treasure#click)	#tr120052	4_TREASURE_BOX
+yuno_fild12,76,268,4	duplicate(ach_treasure#click)	#tr120053	4_TREASURE_BOX
+yuno_fild02,142,191,4	duplicate(ach_treasure#click)	#tr120054	4_TREASURE_BOX
+yuno_fild03,135,329,4	duplicate(ach_treasure#click)	#tr120055	4_TREASURE_BOX
+yuno_fild04,35,369,4	duplicate(ach_treasure#click)	#tr120056	4_TREASURE_BOX
+yuno_fild06,262,220,4	duplicate(ach_treasure#click)	#tr120057	4_TREASURE_BOX
+yuno_fild07,113,339,4	duplicate(ach_treasure#click)	#tr120058	4_TREASURE_BOX
+yuno_fild08,179,209,4	duplicate(ach_treasure#click)	#tr120059	4_TREASURE_BOX
+yuno_fild09,166,228,4	duplicate(ach_treasure#click)	#tr120060	4_TREASURE_BOX
+yuno_fild11,141,357,4	duplicate(ach_treasure#click)	#tr120061	4_TREASURE_BOX
 
 // If the feature is turned off these NPCs are useless
 -	script	AchievementInit	-1,{
@@ -283,7 +536,8 @@ yuno_fild11,141,357,0	duplicate(ach_treasure#core)	#yuno_ach10::120061	HIDDEN_WA
 
 OnInit:
 	if( !getbattleflag( "feature.achievement" ) ){
-		unloadnpc "ach_treasure#core";
+		unloadnpc "ach_treasure#touch";
+		unloadnpc "ach_treasure#click";
 	}
 	end;
 }

+ 52 - 35
npc/re/quests/quests_rockridge.txt

@@ -1013,7 +1013,7 @@ har_in01,89,26,5	script	Johnny James#har_in01	10213,{
 		setpcblock PCBLOCK_NPC, true;
 		npctalk "You sneaky bastards, how dare you show up again? Go to hell!", "", bc_self;
 		sleep2 2000;
-		classchange( 10212, "Ivoka Skudi#har02", bc_self );
+		cloakoffnpc  "Ivoka Skudi#har02", getcharid(0);
 		setpcblock PCBLOCK_NPC, false;
 		npctalk "Ah, you'd better show some respect to our future mayor.", "Ivoka Skudi#har02", bc_self;
 		mes "[Ivoka Skudi]";
@@ -1196,42 +1196,51 @@ OnInit:
 	end;
 }
 
-har_in01,88,22,6	script	Ivoka Skudi#har02	HIDDEN_WARP_NPC,{
+har_in01,88,22,6	script	Ivoka Skudi#har02	10212,{
 	if (rock_main_quest == 9) {
 		mes "[Ivoka Skudi]";
 		mes "(Whispering) He's more simpleminded than I thought. Let's go report to the Sheriff.";
 		close2;
-		classchange( HIDDEN_WARP_NPC, "Ivoka Skudi#har02", bc_self );
+		cloakonnpc  "Ivoka Skudi#har02", getcharid(0);
 		end;
 	}
+	end;
+OnInit:
+	cloakonnpc  "Ivoka Skudi#har02";
+	end;
 }
 
 // Fild 1
-rockrdg1,160,306,3	script	Johnny James#revt04	HIDDEN_WARP_NPC,{ end; }
-rockrdg1,168,306,3	duplicate(Johnny James#revt04)	Albert Ford#revt08	HIDDEN_WARP_NPC
-rockrdg1,156,302,7	duplicate(Johnny James#revt04)	Ivoka Skudi#revt02	HIDDEN_WARP_NPC
-rockrdg1,156,306,5	duplicate(Johnny James#revt04)	Cactus Gunslinger#revt01	HIDDEN_WARP_NPC
-rockrdg1,161,302,1	duplicate(Johnny James#revt04)	Cactus Gunslinger#revt02	HIDDEN_WARP_NPC
-rockrdg1,164,306,3	duplicate(Johnny James#revt04)	Cactus Gunslinger#revt03	HIDDEN_WARP_NPC
+rockrdg1,160,306,3	script	Johnny James#revt04	10213,{
+	end;
+OnInit:
+	cloakonnpc strnpcinfo(0);
+	end;
+}
+rockrdg1,168,306,3	duplicate(Johnny James#revt04)	Albert Ford#revt08	10214
+rockrdg1,156,302,7	duplicate(Johnny James#revt04)	Ivoka Skudi#revt02	10212
+rockrdg1,156,306,5	duplicate(Johnny James#revt04)	Cactus Gunslinger#revt01	10212
+rockrdg1,161,302,1	duplicate(Johnny James#revt04)	Cactus Gunslinger#revt02	10212
+rockrdg1,164,306,3	duplicate(Johnny James#revt04)	Cactus Gunslinger#revt03	10212
 
 rockrdg1,156,312,3	script	Unmoving Freight Train#	4_ENERGY_RED,{
 	if (rock_main_quest == 5) {
 		setpcblock PCBLOCK_NPC, true;
 		unittalk getcharid(3), "" + strcharinfo(0) + " : I think this is the place, but maybe I came too early.", bc_self;
 		sleep2 3000;
-		classchange( 10213, "Johnny James#revt04", bc_self );
+		cloakoffnpc "Johnny James#revt04", getcharid(0);
 		emotion ET_QUESTION, getnpcid(0, "Johnny James#revt04");
 		sleep2 200;
 		npctalk "Who's this? You're not the one I was expecting.", "Johnny James#revt04", bc_self;
 		sleep2 1000;
-		classchange( 10214, "Albert Ford#revt08", bc_self );
+		cloakoffnpc "Albert Ford#revt08", getcharid(0);
 		npctalk "Hey Boss, I told you not to go without me.", "Albert Ford#revt08", bc_self;
 		sleep2 2000;
 		npctalk "Mm? I don't remember if Costello looks like that.", "Albert Ford#revt08", bc_self;
 		sleep2 1500;
 		npctalk "Hey, I'm having an important meeting here. Scram!", "Johnny James#revt04", bc_self;
 		sleep2 3000;
-		classchange( 10211, "Wyatt Warp#revt03", bc_self );
+		cloakoffnpc "Wyatt Warp#revt03", getcharid(0);
 		npctalk "Johnny James? You shouldn't be so rude to the Officer.", "Wyatt Warp#revt03", bc_self;
 		sleep2 2500;
 		npctalk "Ah, the sheriff's here. Who's that with you? I told you I wanted to talk to the mayor.", "Johnny James#revt04", bc_self;
@@ -1263,14 +1272,14 @@ rockrdg1,156,312,3	script	Unmoving Freight Train#	4_ENERGY_RED,{
 		sleep2 500;
 		specialeffect EF_SCREEN_QUAKE,AREA,"Johnny James#revt04";
 		sleep2 200;
-		classchange( 10212, "Ivoka Skudi#revt02", bc_self );
+		cloakoffnpc "Ivoka Skudi#revt02", getcharid(0);
 		npctalk "Freeze!", "Ivoka Skudi#revt02", bc_self;
 		sleep2 800;
 		specialeffect EF_NPC_STOP,AREA,"Johnny James#revt04";
 		sleep2 200;
-		classchange( 10212, "Cactus Gunslinger#revt01", bc_self );
-		classchange( 10212, "Cactus Gunslinger#revt02", bc_self );
-		classchange( 10212, "Cactus Gunslinger#revt03", bc_self );
+		cloakoffnpc "Cactus Gunslinger#revt01", getcharid(0);
+		cloakoffnpc "Cactus Gunslinger#revt02", getcharid(0);
+		cloakoffnpc "Cactus Gunslinger#revt03", getcharid(0);
 		npctalk "Freeze!", "Cactus Gunslinger#revt01", bc_self;
 		npctalk "You're trapped", "Cactus Gunslinger#revt03", bc_self;
 		npctalk "Buffaloes!", "Cactus Gunslinger#revt02", bc_self;
@@ -1293,7 +1302,7 @@ rockrdg1,156,312,3	script	Unmoving Freight Train#	4_ENERGY_RED,{
 		sleep2 2000;
 		npctalk "I-I'll go bring the rest of our gang!", "Albert Ford#revt08", bc_self;
 		sleep2 1000;
-		classchange( HIDDEN_WARP_NPC, "Albert Ford#revt08", bc_self );
+		cloakonnpc "Albert Ford#revt08", getcharid(0);
 		npctalk "WHAT?", "Johnny James#revt04", bc_self;
 		sleep2 1000;
 		npctalk "ALBERT!", "Johnny James#revt04", bc_self;
@@ -1318,11 +1327,11 @@ rockrdg1,156,312,3	script	Unmoving Freight Train#	4_ENERGY_RED,{
 		sleep2 1000;
 		npctalk "Guys, let's go!", "Ivoka Skudi#revt02", bc_self;
 		sleep2 2000;
-		classchange( HIDDEN_WARP_NPC, "Ivoka Skudi#revt02", bc_self );
-		classchange( HIDDEN_WARP_NPC, "Cactus Gunslinger#revt01", bc_self );
-		classchange( HIDDEN_WARP_NPC, "Cactus Gunslinger#revt02", bc_self );
-		classchange( HIDDEN_WARP_NPC, "Cactus Gunslinger#revt03", bc_self );
-		classchange( HIDDEN_WARP_NPC, "Johnny James#revt04", bc_self );
+		cloakonnpc "Ivoka Skudi#revt02", getcharid(0);
+		cloakonnpc "Cactus Gunslinger#revt01", getcharid(0);
+		cloakonnpc "Cactus Gunslinger#revt02", getcharid(0);
+		cloakonnpc "Cactus Gunslinger#revt03", getcharid(0);
+		cloakonnpc "Johnny James#revt04", getcharid(0);
 		sleep2 2000;
 		npctalk "Let's go back, shall we?", "Wyatt Warp#revt03", bc_self;
 		rock_main_quest = 6;
@@ -1339,7 +1348,7 @@ OnInit:
 	end;
 }
 
-rockrdg1,153,303,5	script	Wyatt Warp#revt03	HIDDEN_WARP_NPC,{
+rockrdg1,153,303,5	script	Wyatt Warp#revt03	10211,{
 	if (rock_main_quest == 6) {
 		mes "[Wyatt Warp]";
 		mes "Ivoka's plan worked flawlessly.";
@@ -1356,9 +1365,13 @@ rockrdg1,153,303,5	script	Wyatt Warp#revt03	HIDDEN_WARP_NPC,{
 		mes "[Wyatt Warp]";
 		mes "Let's go back to my office.";
 		close2;
-		classchange( HIDDEN_WARP_NPC, "", bc_self );
+		cloakonnpc  "Wyatt Warp#revt03", getcharid(0);
 		end;
 	}
+	end;
+OnInit:
+	cloakonnpc "Wyatt Warp#revt03";
+	end;
 }
 
 harboro1,288,193,5	script	Shawn McCurdy#harboro1	10215,{
@@ -1747,14 +1760,14 @@ rockrdg2,279,313,3	script	Concaved Rock#revt09	4_ENERGY_RED,{
 			close;
 		}
 		npctalk "Boss? Is that you, Boss?", "Albert Ford#rockrdg2", bc_self;
-		classchange( 10214, "Albert Ford#rockrdg2", bc_self );
+		cloakoffnpc "Albert Ford#rockrdg2", getcharid(0);
 		close;
 	}
 	if (rock_main_quest == 14) {
 		if (countitem(25249) < 1) {
 			mes "I knocked on the signaling rock, and Albert Ford came out running.";
 			npctalk "Who are you?!", "Albert Ford#rockrdg2", bc_self;
-			classchange( 10214, "Albert Ford#rockrdg2", bc_self );
+			cloakoffnpc "Albert Ford#rockrdg2", getcharid(0);
 			close;
 		}
 		mes "I don't have to use this right now.";
@@ -1767,7 +1780,7 @@ rockrdg2,279,313,3	script	Concaved Rock#revt09	4_ENERGY_RED,{
 		}
 		mes "I knocked on the signaling rock, and Albert Ford came out running.";
 		npctalk "Who are you?!", "Albert Ford#rockrdg2", bc_self;
-		classchange( 10214, "Albert Ford#rockrdg2", bc_self );
+		cloakoffnpc "Albert Ford#rockrdg2", getcharid(0);
 		close;
 	}
 	mes "This rock creates a deep, echoing sound when struck.";
@@ -1775,7 +1788,7 @@ rockrdg2,279,313,3	script	Concaved Rock#revt09	4_ENERGY_RED,{
 	close;
 }
 
-rockrdg2,295,309,3	script	Albert Ford#rockrdg2	HIDDEN_WARP_NPC,{
+rockrdg2,295,309,3	script	Albert Ford#rockrdg2	10214,{
 	disable_items;
 	.@account_id = getcharid(3);
 	.@player_name$ = strcharinfo(0);
@@ -1967,7 +1980,7 @@ rockrdg2,295,309,3	script	Albert Ford#rockrdg2	HIDDEN_WARP_NPC,{
 		setquest 7803;// Happy for Broken Trust
 		rock_main_quest = 14;
 		close2;
-		classchange( HIDDEN_WARP_NPC, "", bc_self );
+		cloakonnpc strnpcinfo(0), getcharid(0);
 		end;
 	}
 	if (rock_main_quest == 14 && countitem(25249) < 1) {
@@ -1985,7 +1998,7 @@ rockrdg2,295,309,3	script	Albert Ford#rockrdg2	HIDDEN_WARP_NPC,{
 		mes "Here, take it.";
 		getitem 25249,1;// Buffalo_Bandit_Mane
 		close2;
-		classchange( HIDDEN_WARP_NPC, "", bc_self );
+		cloakonnpc strnpcinfo(0), getcharid(0);
 		end;
 	}
 	if (rock_main_quest == 20 && checkquest(7807,HUNTING) == 2) {
@@ -1997,7 +2010,7 @@ rockrdg2,295,309,3	script	Albert Ford#rockrdg2	HIDDEN_WARP_NPC,{
 			mes "What? What is it?";
 			mes "Don't call me unless you have something to tell me!";
 			close2;
-			classchange( HIDDEN_WARP_NPC, "", bc_self );
+			cloakonnpc strnpcinfo(0), getcharid(0);
 			end;
 		}
 		mes "[Albert Ford]";
@@ -2098,10 +2111,14 @@ rockrdg2,295,309,3	script	Albert Ford#rockrdg2	HIDDEN_WARP_NPC,{
 			setquest 7808;// Case Solved
 			rock_main_quest = 21;
 			close2;
-			classchange( HIDDEN_WARP_NPC, "", bc_self );
+			cloakonnpc strnpcinfo(0), getcharid(0);
 		}
 		end;
 	}
+	end;
+OnInit:
+	cloakonnpc strnpcinfo(0);
+	end;
 }
 
 
@@ -2402,7 +2419,7 @@ function	script	F_cacturon	{
 		}
 		if (getstrlen(strnpcinfo(2)) < 3)
 			.@string$ = "_bis";
-		classchange( HIDDEN_WARP_NPC, "Suspicious Sand Mound#" + strnpcinfo(2) + .@string$, bc_self );
+		cloakonnpc "Suspicious Sand Mound#" + strnpcinfo(2) + .@string$, getcharid(0);
 		close;
 	}
 	mes "- Someone must have piled this mound of sand. -";
@@ -4782,7 +4799,7 @@ rockrdg1,36,250,5	script	Mr. McPhy#rkdlout	4W_M_02,{
 	case 1328:
 		mes "[Mr. McPhy]";
 		mes "Did you find something? Then let's go back!";
-		classchange( HIDDEN_WARP_NPC, "", bc_self );
+		cloakonnpc strnpcinfo(0), getcharid(0);
 		close;
 	case 1329:
 		mes "[Mr. McPhy]";
@@ -4801,7 +4818,7 @@ rockrdg1,36,250,5	script	Mr. McPhy#rkdlout	4W_M_02,{
 		mes "[Mr. McPhy]";
 		mes "*Gasp* Buffalo Bandits!";
 		close2;
-		classchange( HIDDEN_WARP_NPC, "", bc_self );
+		cloakonnpc strnpcinfo(0), getcharid(0);
 		end;
 	}
 	end;

+ 3 - 3
src/config/const.hpp

@@ -72,14 +72,14 @@
 /* Renewal's dmg level modifier, used as a macro for a easy way to turn off. */
 #ifdef RENEWAL_LVDMG
 	#define RE_LVL_DMOD(val) \
-		if( status_get_lv(src) > 100 && val > 0 ) \
+		if( status_get_lv(src) > 99 && val > 0 ) \
 			skillratio = skillratio * status_get_lv(src) / val;
 	#define RE_LVL_MDMOD(val) \
-		if( status_get_lv(src) > 100 && val > 0) \
+		if( status_get_lv(src) > 99 && val > 0) \
 			md.damage = md.damage * status_get_lv(src) / val;
 	/* ranger traps special */
 	#define RE_LVL_TMDMOD() \
-		if( status_get_lv(src) > 100 ) \
+		if( status_get_lv(src) > 99 ) \
 			md.damage = md.damage * 150 / 100 + md.damage * status_get_lv(src) / 100;
 #else
 	#define RE_LVL_DMOD(val)

+ 68 - 4
src/map/atcommand.cpp

@@ -10081,7 +10081,7 @@ ACMD_FUNC(adopt)
 	if (response < ADOPT_MORE_CHILDREN) { // No displaymessage for client-type responses
 #ifdef RENEWAL
 		if (response == ADOPT_NOT_NOVICE)
-			clif_displaymessage(fd, msg_txt(sd, 1505));
+			clif_displaymessage(fd, msg_txt(sd, 1513));
 		else
 #endif
 		clif_displaymessage(fd, msg_txt(sd, 744 + response - 1));
@@ -10105,7 +10105,7 @@ ACMD_FUNC(unadopt)
 	uint8 independent_baby = 0;
 
 	if (!message || !*message || sscanf(message, "%23s %1hhu", atcmd_player_name, &independent_baby) < 1) {
-		sprintf(atcmd_output, msg_txt(sd, 1509), command); // Usage: <char name> <independent_baby>
+		sprintf(atcmd_output, msg_txt(sd, 1517), command); // Usage: <char name> <independent_baby>
 		clif_displaymessage(fd, atcmd_output);
 		return -1;
 	}
@@ -10118,14 +10118,14 @@ ACMD_FUNC(unadopt)
 	e_unadopt_responses response = pc_unadopt(sd, map_charid2sd(sd->status.partner_id), b_sd, independent_baby != 0);
 
 	if (response == UNADOPT_ALLOWED) {
-		clif_displaymessage(fd, msg_txt(sd, 1506)); // Baby has been disowned.
+		clif_displaymessage(fd, msg_txt(sd, 1514)); // Baby has been disowned.
 		return 0;
 	}
 
 	if (response == UNADOPT_CHARACTER_NOT_FOUND)
 		clif_displaymessage(fd, msg_txt(sd, 748)); // A Parent or Baby was not found.
 	else
-		clif_displaymessage(fd, msg_txt(sd, 1507 + response - 1));
+		clif_displaymessage(fd, msg_txt(sd, 1515 + response - 1));
 	return -1;
 }
 
@@ -10176,6 +10176,66 @@ ACMD_FUNC(resurrect) {
 	return 0;
 }
 
+ACMD_FUNC(quest) {
+	uint8 i;
+	int quest_id = 0;
+	nullpo_retr(-1, sd);
+	memset(atcmd_output, '\0', sizeof(atcmd_output));
+
+	if (!message || !*message || sscanf(message, "%11d", &quest_id) < 1 || quest_id == 0) {
+		sprintf(atcmd_output, msg_txt(sd,1505), command); // Usage: %s <quest ID>
+		clif_displaymessage(fd, atcmd_output);
+		return -1;
+	}
+	if (!quest_search(quest_id)) {
+		sprintf(atcmd_output,  msg_txt(sd,1506), quest_id); // Quest %d not found in DB.
+		clif_displaymessage(fd, atcmd_output);
+		return -1;
+	}
+
+	const char* type[] = { "setquest", "erasequest", "completequest", "checkquest" };
+	ARR_FIND( 0, ARRAYLENGTH(type), i, strcmpi(command+1, type[i]) == 0 );
+
+	switch(i) {
+	case 0:
+		if (quest_check(sd, quest_id, HAVEQUEST) >= 0) {
+			sprintf(atcmd_output,  msg_txt(sd,1507), quest_id); // Character already has quest %d.
+			clif_displaymessage(fd, atcmd_output);
+			return -1;
+		}
+		quest_add(sd, quest_id);
+		pc_show_questinfo(sd);
+		break;
+	case 1:
+		if (quest_check(sd, quest_id, HAVEQUEST) < 0) {
+			sprintf(atcmd_output,  msg_txt(sd,1508), quest_id); // Character doesn't have quest %d.
+			clif_displaymessage(fd, atcmd_output);
+			return -1;
+		}
+		quest_delete(sd, quest_id);
+		pc_show_questinfo(sd);
+		break;
+	case 2:
+		if (quest_check(sd, quest_id, HAVEQUEST) < 0)
+			quest_add(sd, quest_id);
+		if (quest_check(sd, quest_id, HAVEQUEST) < 2)
+			quest_update_status(sd, quest_id, Q_COMPLETE);
+		pc_show_questinfo(sd);
+		break;
+	case 3:
+		sprintf(atcmd_output, msg_txt(sd,1509), quest_id); // Checkquest value for quest %d
+		clif_displaymessage(fd, atcmd_output);
+		sprintf(atcmd_output, msg_txt(sd,1510), quest_check(sd, quest_id, HAVEQUEST));	// HAVEQUEST : %d
+		clif_displaymessage(fd, atcmd_output);
+		sprintf(atcmd_output, msg_txt(sd,1511), quest_check(sd, quest_id, HUNTING));	// HUNTING   : %d
+		clif_displaymessage(fd, atcmd_output);
+		sprintf(atcmd_output, msg_txt(sd,1512), quest_check(sd, quest_id, PLAYTIME));	// PLAYTIME  : %d
+		clif_displaymessage(fd, atcmd_output);
+		break;
+	}
+	return 0;
+}
+
 #include "../custom/atcommand.inc"
 
 /**
@@ -10479,6 +10539,10 @@ void atcommand_basecommands(void) {
 		ACMD_DEFR(changedress, ATCMD_NOCONSOLE|ATCMD_NOAUTOTRADE),
 		ACMD_DEFR(camerainfo, ATCMD_NOCONSOLE|ATCMD_NOAUTOTRADE),
 		ACMD_DEFR(resurrect, ATCMD_NOCONSOLE),
+		ACMD_DEF2("setquest", quest),
+		ACMD_DEF2("erasequest", quest),
+		ACMD_DEF2("completequest", quest),
+		ACMD_DEF2("checkquest", quest),
 	};
 	AtCommandInfo* atcommand;
 	int i;

+ 205 - 60
src/map/battle.cpp

@@ -352,7 +352,11 @@ int battle_delay_damage(t_tick tick, int amotion, struct block_list *src, struct
 	}
 
 	if( ((d_tbl && check_distance_bl(target, d_tbl, sc->data[SC_DEVOTION]->val3)) || e_tbl) &&
-		damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD ){
+		damage > 0 && skill_id != CR_REFLECTSHIELD
+#ifndef RENEWAL
+		&& skill_id != PA_PRESSURE
+#endif
+		) {
 		struct map_session_data* tsd = BL_CAST( BL_PC, target );
 
 		if( tsd && pc_issit( tsd ) && battle_config.devotion_standup_fix ){
@@ -416,6 +420,7 @@ int battle_attr_ratio(int atk_elem, int def_type, int def_lv)
  * @param atk_elem
  * @param def_type
  * @param def_lv
+ * @param flag
  * @return damage
  */
 int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 damage,int atk_elem,int def_type, int def_lv)
@@ -1091,15 +1096,24 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 	if (sc && sc->data[SC_MAXPAIN])
 		return 0;
 
-	if (skill_id == PA_PRESSURE || skill_id == HW_GRAVITATION)
+#ifndef RENEWAL
+	if (skill_id == PA_PRESSURE
+		|| skill_id == HW_GRAVITATION
+		)
 		return damage; //These skills bypass everything else.
+#endif
 
 	if( sc && sc->count ) { // SC_* that reduce damage to 0.
-		if( sc->data[SC_BASILICA] && !status_bl_has_mode(src,MD_STATUS_IMMUNE) ) {
+#ifdef RENEWAL
+		if (sc->data[SC_BASILICA_CELL]
+#else
+		if (sc->data[SC_BASILICA]
+#endif
+			&& !status_bl_has_mode(src,MD_STATUS_IMMUNE) ) {
 			d->dmg_lv = ATK_BLOCK;
 			return 0;
 		}
-		if( sc->data[SC_WHITEIMPRISON] ) { // Gravitation and Pressure do damage without removing the effect
+		if( sc->data[SC_WHITEIMPRISON] ) { // Pre-Renewal: Gravitation and Pressure do damage without removing the effect
 			if( skill_id == MG_NAPALMBEAT ||
 				skill_id == MG_SOULSTRIKE ||
 				skill_id == WL_SOULEXPANSION ||
@@ -1258,12 +1272,9 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 #ifdef RENEWAL
 		if( sc->data[SC_RAID] ) {
 			if (status_get_class_(bl) == CLASS_BOSS)
-				damage += damage * 10 / 100;
+				damage += damage * 15 / 100;
 			else
-				damage += damage * 20 / 100;
-
-			if (--sc->data[SC_RAID]->val1 == 0)
-				status_change_end(bl, SC_RAID, INVALID_TIMER);
+				damage += damage * 30 / 100;
 		}
 #endif
 
@@ -1303,7 +1314,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 		}
 
 		// Damage reductions
-		// Assumptio doubles the def & mdef on RE mode, otherwise gives a reduction on the final damage. [Igniz]
+		// Assumptio increases DEF 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) )
@@ -2276,6 +2287,10 @@ static int battle_skill_damage(struct block_list *src, struct block_list *target
  * @return Bonus value based on party count
  */
 int battle_calc_chorusbonus(struct map_session_data *sd) {
+#ifdef RENEWAL // No bonus in renewal
+	return 0;
+#endif
+
 	int members = 0;
 
 	if (!sd || !sd->status.party_id)
@@ -2468,7 +2483,11 @@ static bool is_attack_critical(struct Damage* wd, struct block_list *src, struct
 				break;
 			case SN_SHARPSHOOTING:
 			case MA_SHARPSHOOTING:
+#ifdef RENEWAL
+				cri += 300; // !TODO: Confirm new bonus
+#else
 				cri += 200;
+#endif
 				break;
 			case NJ_KIRIKAGE:
 				cri += 250 + 50*skill_lv;
@@ -2657,6 +2676,11 @@ static bool is_attack_hitting(struct Damage* wd, struct block_list *src, struct
 				if(sd && pc_checkskill(sd,AS_SONICACCEL) > 0)
 					hitrate += hitrate * 50 / 100;
 				break;
+#ifdef RENEWAL
+			case RG_BACKSTAP:
+				hitrate += skill_lv; // !TODO: What's the rate increase?
+				break;
+#endif
 			case RK_SONICWAVE:
 				hitrate += hitrate * 3 * skill_lv / 100; // !TODO: Confirm the hitrate bonus
 				break;
@@ -3152,6 +3176,7 @@ static void battle_calc_skill_base_damage(struct Damage* wd, struct block_list *
 			}
 
 			switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection?
+				// !TODO: Confirm new size modifiers
 				case SZ_SMALL: //Small: 125%
 					ATK_RATE(wd->damage, wd->damage2, 125);
 					RE_ALLATK_RATE(wd, 125);
@@ -3547,7 +3572,11 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 			break;
 		case KN_BRANDISHSPEAR:
 		case ML_BRANDISH: {
+#ifdef RENEWAL
+				int ratio = 100 + 20 * skill_lv + sstatus->str; // !TODO: Confirm STR role
+#else
 				int ratio = 100 + 20 * skill_lv;
+#endif
 
 				skillratio += -100 + ratio;
 				if(skill_lv > 3 && wd->miscflag == 0)
@@ -3576,6 +3605,10 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 			break;
 		case AS_SONICBLOW:
 			skillratio += 300 + 40 * skill_lv;
+#ifdef RENEWAL
+			if (tstatus->hp < tstatus->max_hp >> 1)
+				skillratio += skillratio / 2;
+#endif
 			break;
 		case TF_SPRINKLESAND:
 			skillratio += 30;
@@ -3625,9 +3658,9 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 		case RG_RAID:
 #ifdef RENEWAL
 			if (status_get_class_(target) == CLASS_BOSS)
-				skillratio += 10 * skill_lv;
+				skillratio += 10 * skill_lv; // !TODO: Did this change as well?
 			else
-				skillratio += 20 * skill_lv;
+				skillratio += 50 + skill_lv * 150;
 #else
 			skillratio += 40 * skill_lv;
 #endif
@@ -3639,7 +3672,11 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 			skillratio += 20 * skill_lv;
 			break;
 		case CR_SHIELDBOOMERANG:
+#ifdef RENEWAL
+			skillratio += -100 + skill_lv * 80;
+#else
 			skillratio += 30 * skill_lv;
+#endif
 			break;
 		case NPC_DARKCROSS:
 		case CR_HOLYCROSS:
@@ -3655,18 +3692,36 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 			break;
 		case AM_ACIDTERROR:
 #ifdef RENEWAL
-			skillratio += 200 + 80 * skill_lv;
+			skillratio += -100 + 200 * skill_lv;
+			if (sd && pc_checkskill(sd, AM_LEARNINGPOTION))
+				skillratio += 100; // !TODO: What's this bonus increase?
 #else
 			skillratio += 40 * skill_lv;
 #endif
 			break;
 		case MO_FINGEROFFENSIVE:
+#ifdef RENEWAL
+			skillratio += 500 + skill_lv * 2;
+			if (tsc && tsc->data[SC_BLADESTOP])
+				skillratio += skillratio / 2;
+#else
 			skillratio += 50 * skill_lv;
+#endif
 			break;
 		case MO_INVESTIGATE:
+#ifdef RENEWAL
+			skillratio += -100 + 100 * skill_lv;
+			if (tsc && tsc->data[SC_BLADESTOP])
+				skillratio += skillratio / 2;
+#else
 			skillratio += 75 * skill_lv;
+#endif
 			break;
 		case MO_EXTREMITYFIST:
+#ifdef RENEWAL
+			if (wd->miscflag&1)
+				skillratio += 100; // More than 5 spirit balls active
+#endif
 			skillratio += 100 * (7 + sstatus->sp / 10);
 			skillratio = min(500000,skillratio); //We stop at roughly 50k SP for overflow protection
 			break;
@@ -3674,29 +3729,56 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 			skillratio += 20 * skill_lv;
 			break;
 		case MO_CHAINCOMBO:
+#ifdef RENEWAL
+			skillratio += 150 + 50 * skill_lv;
+#else
 			skillratio += 50 + 50 * skill_lv;
+#endif
 			break;
 		case MO_COMBOFINISH:
+#ifdef RENEWAL
+			skillratio += 450 + 50 * skill_lv + sstatus->str; // !TODO: How does STR play a role?
+#else
 			skillratio += 140 + 60 * skill_lv;
+#endif
 			if (sc->data[SC_GT_ENERGYGAIN])
 				skillratio += skillratio * 50 / 100;
 			break;
 		case BA_MUSICALSTRIKE:
 		case DC_THROWARROW:
+#ifdef RENEWAL
+			skillratio += 10 + 40 * skill_lv;
+#else
 			skillratio += 25 + 25 * skill_lv;
+#endif
 			break;
 		case CH_TIGERFIST:
+#ifdef RENEWAL
+			skillratio += 400 + 150 * skill_lv;
+			RE_LVL_DMOD(100);
+#else
 			skillratio += -60 + 100 * skill_lv;
+#endif
 			if (sc->data[SC_GT_ENERGYGAIN])
 				skillratio += skillratio * 50 / 100;
 			break;
 		case CH_CHAINCRUSH:
+#ifdef RENEWAL
+			skillratio += -100 + 200 * skill_lv;
+			RE_LVL_DMOD(100);
+#else
 			skillratio += 300 + 100 * skill_lv;
+#endif
 			if (sc->data[SC_GT_ENERGYGAIN])
 				skillratio += skillratio * 50 / 100;
 			break;
 		case CH_PALMSTRIKE:
+#ifdef RENEWAL
+			skillratio += 100 + 100 * skill_lv + sstatus->str; // !TODO: How does STR play a role?
+			RE_LVL_DMOD(100);
+#else
 			skillratio += 100 + 100 * skill_lv;
+#endif
 			break;
 		case LK_HEADCRUSH:
 			skillratio += 40 * skill_lv;
@@ -3710,21 +3792,41 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 		// Renewal: skill ratio applies to entire damage [helvetica]
 		case LK_SPIRALPIERCE:
 		case ML_SPIRALPIERCE:
-			skillratio += 50 * skill_lv;
+			skillratio += 50 + 50 * skill_lv;
+			RE_LVL_DMOD(100);
 		break;
 #endif
 		case ASC_METEORASSAULT:
+#ifdef RENEWAL
+			skillratio += 100 + 120 * skill_lv;
+			RE_LVL_DMOD(100);
+#else
 			skillratio += -60 + 40 * skill_lv;
+#endif
 			break;
 		case SN_SHARPSHOOTING:
 		case MA_SHARPSHOOTING:
+#ifdef RENEWAL
+			skillratio += 50 + 200 * skill_lv;
+			RE_LVL_DMOD(100);
+#else
 			skillratio += 100 + 50 * skill_lv;
+#endif
 			break;
 		case CG_ARROWVULCAN:
+#ifdef RENEWAL
+			skillratio += 400 + 100 * skill_lv;
+			RE_LVL_DMOD(100);
+#else
 			skillratio += 100 + 100 * skill_lv;
+#endif
 			break;
 		case AS_SPLASHER:
+#ifdef RENEWAL
+			skillratio += 400 + 100 * skill_lv;
+#else
 			skillratio += 400 + 50 * skill_lv;
+#endif
 			if(sd)
 				skillratio += 20 * pc_checkskill(sd,AS_POISONREACT);
 			break;
@@ -3738,7 +3840,12 @@ static int battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list *
 			skillratio += -10 + 10 * skill_lv;
 			break;
 		case PA_SHIELDCHAIN:
+#ifdef RENEWAL
+			skillratio = 60 + 40 * skill_lv;
+			RE_LVL_DMOD(100);
+#else
 			skillratio += 30 * skill_lv;
+#endif
 			break;
 		case WS_CARTTERMINATION:
 			i = 10 * (16 - skill_lv);
@@ -4529,10 +4636,6 @@ static void battle_attack_sc_bonus(struct Damage* wd, struct block_list *src, st
 #ifdef RENEWAL
 		if (sc->data[SC_WATK_ELEMENT] && skill_id != ASC_METEORASSAULT)
 			ATK_ADDRATE(wd->weaponAtk, wd->weaponAtk2, sc->data[SC_WATK_ELEMENT]->val2);
-		if (sc->data[SC_IMPOSITIO])
-			ATK_ADD(wd->equipAtk, wd->equipAtk2, sc->data[SC_IMPOSITIO]->val2);
-		if (sc->data[SC_VOLCANO])
-			ATK_ADD(wd->equipAtk, wd->equipAtk2, sc->data[SC_VOLCANO]->val2);
 		if (sc->data[SC_DRUMBATTLE])
 			ATK_ADD(wd->equipAtk, wd->equipAtk2, sc->data[SC_DRUMBATTLE]->val2);
 		if (sc->data[SC_MADNESSCANCEL])
@@ -4579,18 +4682,6 @@ static void battle_attack_sc_bonus(struct Damage* wd, struct block_list *src, st
 					break; // skills above have no effect with EDP
 
 #ifdef RENEWAL
-				// renewal EDP mode requires renewal enabled as well
-				// Renewal EDP: damage gets a half modifier on top of EDP bonus for skills [helvetica]
-				// * Sonic Blow
-				// * Soul Breaker
-				// * Counter Slash
-				// * Cross Impact
-				case AS_SONICBLOW:
-				case ASC_BREAKER:
-				case GC_COUNTERSLASH:
-				case GC_CROSSIMPACT:
-					ATK_RATE(wd->weaponAtk, wd->weaponAtk2, 50);
-					ATK_RATE(wd->equipAtk, wd->equipAtk2, 50);
 				default: // fall through to apply EDP bonuses
 					// Renewal EDP formula [helvetica]
 					// weapon atk * (1 + (edp level * .8))
@@ -4729,11 +4820,6 @@ static void battle_calc_defense_reduction(struct Damage* wd, struct block_list *
 	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) {
 		int i = sd->ignore_def_by_race[tstatus->race] + sd->ignore_def_by_race[RC_ALL];
 		i += sd->ignore_def_by_class[tstatus->class_] + sd->ignore_def_by_class[CLASS_ALL];
@@ -4894,11 +4980,11 @@ static void battle_calc_attack_post_defense(struct Damage* wd, struct block_list
 				&& 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
+			ATK_ADD(wd->damage, wd->damage2, (3 + sc->data[SC_AURABLADE]->val1) * status_get_lv(src)); // !TODO: Confirm formula
+#else
+			ATK_ADD(wd->damage, wd->damage2, 20 * sc->data[SC_AURABLADE]->val1);
 #endif
-			ATK_ADD(wd->damage, wd->damage2, 20*lv);
 		}
 	}
 
@@ -5268,18 +5354,20 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
 		wd.flag |= battle_range_type(src, target, skill_id, skill_lv);
 		switch(skill_id)
 		{
+#ifdef RENEWAL
+			case RG_BACKSTAP:
+				if (sd && sd->status.weapon == W_DAGGER)
+					wd.div_ = 2;
+				break;
+#endif
 			case MH_SONIC_CRAW:{
 				TBL_HOM *hd = BL_CAST(BL_HOM,src);
 				wd.div_ = hd->homunculus.spiritball;
 			}
 				break;
 			case MO_FINGEROFFENSIVE:
-				if(sd) {
-					if (battle_config.finger_offensive_type)
-						wd.div_ = 1;
-					else
-						wd.div_ = sd->spiritball_old;
-				}
+				if (sd && battle_config.finger_offensive_type)
+					wd.div_ = 1;
 				break;
 
 			case KN_PIERCE:
@@ -5297,6 +5385,10 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
 				//Fall through
 			case KN_SPEARSTAB:
 			case KN_BOWLINGBASH:
+#ifdef RENEWAL
+				if (skill_id == KN_BOWLINGBASH && sd && sd->status.weapon == W_2HSWORD)
+					wd.div_ = cap_value(wd.miscflag, 2, 4);
+#endif
 			case MS_BOWLINGBASH:
 			case MO_BALKYOUNG:
 			case TK_TURNKICK:
@@ -5960,10 +6052,25 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 						skillratio += 30 * skill_lv;
 						break;
 					case WZ_STORMGUST:
+#ifdef RENEWAL
+						skillratio -= 30; // Offset only once
+						skillratio += 50 * skill_lv;
+#else
 						skillratio += 40 * skill_lv;
+#endif
 						break;
+#ifdef RENEWAL
+					case WZ_EARTHSPIKE:
+						skillratio += 100;
+						break;
+#endif
 					case HW_NAPALMVULCAN:
+#ifdef RENEWAL
+						skillratio += -100 + 70 * skill_lv;
+						RE_LVL_DMOD(100);
+#else
 						skillratio += 25;
+#endif
 						break;
 					case SL_STIN: //Target size must be small (0) for full damage
 						skillratio += (tstatus->size != SZ_SMALL ? -99 : 10 * skill_lv);
@@ -6032,22 +6139,38 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 						break;
 #ifdef RENEWAL
 					case WZ_HEAVENDRIVE:
+						skillratio += -100 + skill_lv * 100 + skill_lv * 25;
+						break;
 					case WZ_METEOR:
 						skillratio += 25;
 						break;
 					case WZ_VERMILION:
-						if(sd) {
-							int per = 0;
-							while ((++per) < skill_lv)
-								skillratio += per * 5; //100% 105% 115% 130% 150% 175% 205% 240% 280% 325%
-						} else {
+						if(sd)
+							skillratio += 25 + skill_lv * 5;
+						else
 							skillratio += 20 * skill_lv - 20; //Monsters use old formula
-						}
+						break;
+					case BA_DISSONANCE:
+						skillratio += skill_lv * 10;
+						if (sd)
+							skillratio += 3 * pc_checkskill(sd, BA_MUSICALLESSON);
+						break;
+					case HW_GRAVITATION:
+						skillratio += -100 + 50 * skill_lv;
+						RE_LVL_DMOD(100);
+						break;
+					case PA_PRESSURE:
+						skillratio += -100 + 500 + 150 * skill_lv;
+						RE_LVL_DMOD(100);
 						break;
 #else
 					case WZ_VERMILION:
 						skillratio += 20 * skill_lv - 20;
 						break;
+					case PR_MAGNUS:
+						if (battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON)
+							skillratio += 30;
+						break;
 #endif
 					case AB_JUDEX:
 						skillratio += -100 + 300 + 40 * skill_lv;
@@ -6333,10 +6456,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 		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 (sc && sc->data[SC_EXPIATIO]) {
 				i = 5 * sc->data[SC_EXPIATIO]->val1; // 5% per level
 
@@ -6419,12 +6539,17 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 					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;
+#ifdef RENEWAL
+					if (src == target)
+						ad.damage = 0;
+#else
 					if(src == target) {
 						if(src->type == BL_PC)
 							ad.damage = ad.damage / 2;
 						else
 							ad.damage = 0;
 					}
+#endif
 				}
 				break;
 		}
@@ -6553,9 +6678,14 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 				//Blitz-beat Damage
 				if(!sd || !(skill = pc_checkskill(sd,HT_STEELCROW)))
 					skill = 0;
+#ifdef RENEWAL
+				md.damage = (sstatus->dex / 10 + sstatus->agi / 2 + skill * 3 + 40) * 2;
+				RE_LVL_MDMOD(100);
+#else
 				md.damage = (sstatus->dex / 10 + sstatus->int_ / 2 + skill * 3 + 40) * 2;
 				if(mflag > 1) //Autocasted Blitz
 					nk.set(NK_SPLASHSPLIT);
+#endif
 				if (skill_id == SN_FALCONASSAULT) {
 					//Div fix of Blitzbeat
 					DAMAGE_DIV_FIX2(md.damage, skill_get_num(HT_BLITZBEAT, 5));
@@ -6564,11 +6694,13 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 				}
 			}
 			break;
+#ifndef RENEWAL
 		case BA_DISSONANCE:
 			md.damage = 30 + skill_lv * 10;
 			if (sd)
 				md.damage += 3 * pc_checkskill(sd,BA_MUSICALLESSON);
 			break;
+#endif
 		case NPC_SELFDESTRUCTION:
 			md.damage = sstatus->hp;
 			break;
@@ -6609,17 +6741,15 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 			nk.set(NK_IGNOREELEMENT); //These two are not properties of the weapon based part.
 #endif
 			break;
+#ifndef RENEWAL
 		case HW_GRAVITATION:
-#ifdef RENEWAL
-			md.damage = 500 + 100 * skill_lv;
-#else
 			md.damage = 200 + 200 * skill_lv;
-#endif
 			md.dmotion = 0; //No flinch animation
 			break;
 		case PA_PRESSURE:
 			md.damage = 500 + 300 * skill_lv;
 			break;
+#endif
 		case PA_GOSPEL:
 			if (mflag > 0)
 				md.damage = (rnd() % 4000) + 1500;
@@ -7284,10 +7414,19 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 		}
 	}
 
-	if( tsc && tsc->data[SC_BLADESTOP_WAIT] && status_get_class_(src) != CLASS_BOSS && (src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->status.weapon == W_FIST ? 1 : 2)) )
+	if( tsc && tsc->data[SC_BLADESTOP_WAIT] &&
+#ifndef RENEWAL
+		status_get_class_(src) != CLASS_BOSS &&
+#endif
+		(src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->status.weapon == W_FIST ? 1 : 2)) )
 	{
 		uint16 skill_lv = tsc->data[SC_BLADESTOP_WAIT]->val1;
 		int duration = skill_get_time2(MO_BLADESTOP,skill_lv);
+
+#ifdef RENEWAL
+			if (status_get_class_(src) == CLASS_BOSS)
+				duration = 2000; // Only lasts 2 seconds for Boss monsters
+#endif
 		status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER);
 		if(sc_start4(src,src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration))
 		{	//Target locked.
@@ -7299,7 +7438,12 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
 	}
 
 	if(sd && (skillv = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0) {
-		int triple_rate= 30 - skillv; //Base Rate
+#ifdef RENEWAL
+		int triple_rate = 30; //Base Rate
+#else
+		int triple_rate = 30 - skillv; //Base Rate
+#endif
+
 		if (sc && sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK) {
 			triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100;
 			status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER);
@@ -8462,6 +8606,7 @@ static const struct _battle_data {
 	{ "cashshop_show_points",               &battle_config.cashshop_show_points,            0,      0,      1,              },
 	{ "mail_show_status",                   &battle_config.mail_show_status,                0,      0,      2,              },
 	{ "client_limit_unit_lv",               &battle_config.client_limit_unit_lv,            0,      0,      BL_ALL,         },
+	{ "land_protector_behavior",            &battle_config.land_protector_behavior,         0,      0,      1,              },
 // BattleGround Settings
 	{ "bg_update_interval",                 &battle_config.bg_update_interval,              1000,   100,    INT_MAX,        },
 	{ "bg_short_attack_damage_rate",        &battle_config.bg_short_damage_rate,            80,     0,      INT_MAX,        },

+ 1 - 0
src/map/battle.hpp

@@ -348,6 +348,7 @@ struct Battle_Config
 
 	int prevent_logout;	// Added by RoVeRT
 	int prevent_logout_trigger;
+	int land_protector_behavior;
 
 	int alchemist_summon_reward;	// [Valaris]
 	int drops_by_luk;

+ 118 - 59
src/map/clif.cpp

@@ -980,7 +980,7 @@ static int clif_setlevel(struct block_list* bl) {
 /*==========================================
  * Prepares 'unit standing/spawning' packet
  *------------------------------------------*/
-static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn)
+static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn, bool option, unsigned int option_val)
 {
 	struct map_session_data* sd;
 	struct status_change* sc = status_get_sc(bl);
@@ -996,6 +996,9 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
 #endif
 	sd = BL_CAST(BL_PC, bl);
 
+	if (!option)
+		option_val = ((sc) ? sc->option : 0);
+
 #if PACKETVER < 20091103
 	if(type)
 		WBUFW(buf,0) = spawn ? 0x7c : 0x78;
@@ -1053,7 +1056,7 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
 	WBUFW(buf,10) = (sc)? sc->opt2 : 0;
 #if PACKETVER < 20091103
 	if (type&&spawn) { //uses an older and different packet structure
-		WBUFW(buf,12) = (sc)? sc->option : 0;
+		WBUFW(buf,12) = option_val;
 		WBUFW(buf,14) = vd->hair_style;
 		WBUFW(buf,16) = vd->weapon;
 		WBUFW(buf,18) = vd->head_bottom;
@@ -1062,18 +1065,18 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
 	} else {
 #endif
 #if PACKETVER >= 20091103
-		WBUFL(buf,12) = (sc)? sc->option : 0;
+		WBUFL(buf,12) = option_val;
 		offset+=2;
 		buf = WBUFP(buffer,offset);
 #elif PACKETVER >= 7
 		if (!type) {
-			WBUFL(buf,12) = (sc)? sc->option : 0;
+			WBUFL(buf,12) = option_val;
 			offset+=2;
 			buf = WBUFP(buffer,offset);
 		} else
-			WBUFW(buf,12) = (sc)? sc->option : 0;
+			WBUFW(buf,12) = option_val;
 #else
-		WBUFW(buf,12) = (sc)? sc->option : 0;
+		WBUFW(buf,12) = option_val;
 #endif
 		WBUFW(buf,14) = vd->class_;
 		WBUFW(buf,16) = vd->hair_style;
@@ -1455,7 +1458,7 @@ int clif_spawn(struct block_list *bl)
 	if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE))
 		return 0;
 
-	len = clif_set_unit_idle(bl, buf, (bl->type == BL_NPC && vd->dead_sit ? false : true));
+	len = clif_set_unit_idle(bl, buf, (bl->type == BL_NPC && vd->dead_sit ? false : true), false, 0);
 	clif_send(buf, len, bl, AREA_WOS);
 	if (disguised(bl))
 		clif_setdisguise(bl, buf, len);
@@ -3937,57 +3940,60 @@ void clif_misceffect(struct block_list* bl,int type)
 /// Notifies clients in the area of a state change.
 /// 0119 <id>.L <body state>.W <health state>.W <effect state>.W <pk mode>.B (ZC_STATE_CHANGE)
 /// 0229 <id>.L <body state>.W <health state>.W <effect state>.L <pk mode>.B (ZC_STATE_CHANGE3)
-void clif_changeoption(struct block_list* bl)
+void clif_changeoption_target(struct block_list* bl, struct block_list *target)
 {
-	unsigned char buf[32];
-	struct status_change *sc;
-	struct map_session_data* sd;
-
 	nullpo_retv(bl);
-	sc = status_get_sc(bl);
-	if (!sc) return; //How can an option change if there's no sc?
-	sd = BL_CAST(BL_PC, bl);
 
+	struct status_change *sc = status_get_sc(bl);
+
+	if (!sc || (target && (target->type != BL_PC || bl->type != BL_NPC)))
+		return; //How can an option change if there's no sc?
+
+	struct map_session_data *sd = BL_CAST(BL_PC, bl);
+	unsigned char buf[32];
 #if PACKETVER >= 7
-	WBUFW(buf,0) = 0x229;
+	int cmd = 0x229;
+#else
+	int cmd = 0x119;
+#endif
+
+	WBUFW(buf,0) = cmd;
 	WBUFL(buf,2) = bl->id;
 	WBUFW(buf,6) = sc->opt1;
 	WBUFW(buf,8) = sc->opt2;
 	WBUFL(buf,10) = sc->option;
+#if PACKETVER >= 7
 	WBUFB(buf,14) = (sd)? sd->status.karma : 0;
-	if(disguised(bl)) {
-		clif_send(buf,packet_len(0x229),bl,AREA_WOS);
-		WBUFL(buf,2) = -bl->id;
-		clif_send(buf,packet_len(0x229),bl,SELF);
-		WBUFL(buf,2) = bl->id;
-		WBUFL(buf,10) = OPTION_INVISIBLE;
-		clif_send(buf,packet_len(0x229),bl,SELF);
-	} else
-		clif_send(buf,packet_len(0x229),bl,AREA);
 #else
-	WBUFW(buf,0) = 0x119;
-	WBUFL(buf,2) = bl->id;
-	WBUFW(buf,6) = sc->opt1;
-	WBUFW(buf,8) = sc->opt2;
-	WBUFW(buf,10) = sc->option;
 	WBUFB(buf,12) = (sd)? sd->status.karma : 0;
-	if(disguised(bl)) {
-		clif_send(buf,packet_len(0x119),bl,AREA_WOS);
-		WBUFL(buf,2) = -bl->id;
-		clif_send(buf,packet_len(0x119),bl,SELF);
-		WBUFL(buf,2) = bl->id;
-		WBUFW(buf,10) = OPTION_INVISIBLE;
-		clif_send(buf,packet_len(0x119),bl,SELF);
-	} else
-		clif_send(buf,packet_len(0x119),bl,AREA);
 #endif
+	if (!target) {
+		if (disguised(bl)) {
+			clif_send(buf,packet_len(cmd),bl,AREA_WOS);
+			WBUFL(buf,2) = -bl->id;
+			clif_send(buf,packet_len(cmd),bl,SELF);
+			WBUFL(buf,2) = bl->id;
+			WBUFL(buf,10) = OPTION_INVISIBLE;
+			clif_send(buf,packet_len(cmd),bl,SELF);
+		} else
+			clif_send(buf,packet_len(cmd),bl,AREA);
 
-	//Whenever we send "changeoption" to the client, the provoke icon is lost
-	//There is probably an option for the provoke icon, but as we don't know it, we have to do this for now
-	if (sc->data[SC_PROVOKE]) {
-		const struct TimerData *td = get_timer(sc->data[SC_PROVOKE]->timer);
+		//Whenever we send "changeoption" to the client, the provoke icon is lost
+		//There is probably an option for the provoke icon, but as we don't know it, we have to do this for now
+		if (sc->data[SC_PROVOKE]) {
+			const struct TimerData *td = get_timer(sc->data[SC_PROVOKE]->timer);
 
-		clif_status_change(bl, StatusIconChangeTable[SC_PROVOKE], 1, (!td ? INFINITE_TICK : DIFF_TICK(td->tick, gettick())), 0, 0, 0);
+			clif_status_change(bl, StatusIconChangeTable[SC_PROVOKE], 1, (!td ? INFINITE_TICK : DIFF_TICK(td->tick, gettick())), 0, 0, 0);
+		}
+	}
+	else {
+		if (disguised(bl)) {
+			WBUFL(buf,2) = -bl->id;
+			clif_send(buf,packet_len(cmd),target,SELF);
+			WBUFL(buf,2) = bl->id;
+			WBUFL(buf,10) = OPTION_INVISIBLE;
+		}
+		clif_send(buf,packet_len(cmd),target,SELF);
 	}
 }
 
@@ -4644,10 +4650,14 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d
 
 void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
 {
+	nullpo_retv(bl);
+
 	uint8 buf[128];
 	struct unit_data *ud;
 	struct view_data *vd;
 	int len;
+	bool option = false;
+	unsigned int option_val = 0;
 
 	vd = status_get_viewdata(bl);
 	if (!vd || vd->class_ == JT_INVISIBLE)
@@ -4660,7 +4670,15 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
 		return;
 
 	ud = unit_bl2ud(bl);
-	len = ( ud && ud->walktimer != INVALID_TIMER ) ? clif_set_unit_walking(bl,ud,buf) : clif_set_unit_idle(bl,buf,false);
+	if (sd && bl->type == BL_NPC) {	// npc option changed? 
+		npc_data* nd = BL_CAST(BL_NPC, bl);
+		option_val = nd->sc.option;
+		option = true;
+
+		if (std::find(sd->cloaked_npc.begin(), sd->cloaked_npc.end(), nd->bl.id) != sd->cloaked_npc.end())
+			option_val ^= OPTION_CLOAK;
+	}
+	len = ( ud && ud->walktimer != INVALID_TIMER ) ? clif_set_unit_walking(bl,ud,buf) : clif_set_unit_idle(bl,buf,false,option,option_val);
 	clif_send(buf,len,&sd->bl,SELF);
 
 	if (vd->cloth_color)
@@ -8030,11 +8048,34 @@ void clif_pet_food(struct map_session_data *sd,int foodid,int fail)
 /// 01cd { <skill id>.L }*7
 void clif_autospell(struct map_session_data *sd,uint16 skill_lv)
 {
-	int fd;
-
 	nullpo_retv(sd);
 
-	fd=sd->fd;
+	int fd = sd->fd;
+
+#ifdef RENEWAL
+	uint16 autospell_skill[][2] = { 
+		{ MG_FIREBOLT, 0 }, { MG_COLDBOLT, 0 }, { MG_LIGHTNINGBOLT, 0 },
+		{ MG_SOULSTRIKE, 3 }, { MG_FIREBALL, 3 },
+		{ WZ_EARTHSPIKE, 6 }, { MG_FROSTDIVER, 6 },
+		{ MG_THUNDERSTORM, 9 }, { WZ_HEAVENDRIVE, 9 }
+	};
+	int count = 0;
+
+	WFIFOHEAD(fd, 2 * 6 + 4);
+	WFIFOW(fd, 0) = 0x442;
+
+	for (int i = 0; i < ARRAYLENGTH(autospell_skill); i++) {
+		if (skill_lv > autospell_skill[i][1] && pc_checkskill(sd, autospell_skill[i][0])) {
+			WFIFOW(fd, 8 + count * 2) = autospell_skill[i][0];
+			count++;
+		}
+	}
+
+	WFIFOW(fd, 2) = 8 + count * 2;
+	WFIFOL(fd, 4) = count;
+
+	WFIFOSET(fd, WFIFOW(fd, 2));
+#else
 	WFIFOHEAD(fd,packet_len(0x1cd));
 	WFIFOW(fd, 0)=0x1cd;
 
@@ -8068,6 +8109,8 @@ void clif_autospell(struct map_session_data *sd,uint16 skill_lv)
 		WFIFOL(fd,26)= 0x00000000;
 
 	WFIFOSET(fd,packet_len(0x1cd));
+#endif
+
 	sd->menuskill_id = SA_AUTOSPELL;
 	sd->menuskill_val = skill_lv;
 }
@@ -12190,7 +12233,11 @@ static void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_ses
 		return;
 	}
 
-	if( hd->sc.data[SC_BASILICA] )
+#ifdef RENEWAL
+	if (hd->sc.data[SC_BASILICA_CELL])
+#else
+	if (hd->sc.data[SC_BASILICA])
+#endif
 		return;
 	lv = hom_checkskill(hd, skill_id);
 	if( skill_lv > lv )
@@ -12239,7 +12286,11 @@ static void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct
 		return;
 	}
 
-	if( md->sc.data[SC_BASILICA] )
+#ifdef RENEWAL
+	if (md->sc.data[SC_BASILICA_CELL])
+#else
+	if (md->sc.data[SC_BASILICA])
+#endif
 		return;
 	lv = mercenary_checkskill(md, skill_id);
 	if( skill_lv > lv )
@@ -12317,8 +12368,10 @@ void clif_parse_skill_toid( struct map_session_data* sd, uint16 skill_id, uint16
 	if( sd->sc.option&OPTION_COSTUME )
 		return;
 
+#ifndef RENEWAL
 	if( sd->sc.data[SC_BASILICA] && (skill_id != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
 		return; // On basilica only caster can use Basilica again to stop it.
+#endif
 
 	if( sd->menuskill_id ) {
 		if( sd->menuskill_id == SA_TAMINGMONSTER ) {
@@ -12427,8 +12480,10 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin
 	if( sd->sc.option&OPTION_COSTUME )
 		return;
 
+#ifndef RENEWAL
 	if( sd->sc.data[SC_BASILICA] && (skill_id != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
 		return; // On basilica only caster can use Basilica again to stop it.
+#endif
 
 	if( sd->menuskill_id ) {
 		if( sd->menuskill_id == SA_TAMINGMONSTER ) {
@@ -18740,23 +18795,27 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uin
 }
 
 /*==========================================
- * Select a skill into a given list (used by SC_AUTOSHADOWSPELL)
+ * Select a skill into a given list (used by SA_AUTOSPELL/SC_AUTOSHADOWSPELL)
  * 0443 <type>.L <skill_id>.W (CZ_SKILL_SELECT_RESPONSE)
  * RFIFOL(fd,2) - type (currently not used)
  *------------------------------------------*/
 void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) {
 	struct s_packet_db* info = &packet_db[RFIFOW(fd,0)];
 	//int type = RFIFOL(fd,info->pos[0]); //WHY_LOWERVER_COMPATIBILITY =  0x0, WHY_SC_AUTOSHADOWSPELL =  0x1,
-	if( sd->menuskill_id != SC_AUTOSHADOWSPELL )
-		return;
 
-	if( pc_istrading(sd) ) {
-		clif_skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0);
-		clif_menuskill_clear(sd);
-		return;
-	}
+	if (sd->menuskill_id == SA_AUTOSPELL) {
+		sd->state.workinprogress = WIP_DISABLE_NONE;
+		skill_autospell(sd, RFIFOW(fd, info->pos[1]));
+	} else if (sd->menuskill_id == SC_AUTOSHADOWSPELL) {
+		if (pc_istrading(sd)) {
+			clif_skill_fail(sd, sd->ud.skill_id, USESKILL_FAIL_LEVEL, 0);
+			clif_menuskill_clear(sd);
+			return;
+		}
 
-	skill_select_menu(sd,RFIFOW(fd,info->pos[1]));
+		skill_select_menu(sd, RFIFOW(fd, info->pos[1]));
+	} else
+		return;
 
 	clif_menuskill_clear(sd);
 }

+ 2 - 1
src/map/clif.hpp

@@ -631,7 +631,8 @@ void clif_statusupack(struct map_session_data *sd,int type,int ok,int val);	// s
 void clif_equipitemack(struct map_session_data *sd,int n,int pos,uint8 flag);	// self
 void clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok);	// self
 void clif_misceffect(struct block_list* bl,int type);	// area
-void clif_changeoption(struct block_list* bl);	// area
+void clif_changeoption_target(struct block_list* bl, struct block_list* target);
+#define clif_changeoption(bl) clif_changeoption_target(bl, NULL)	// area
 void clif_changeoption2(struct block_list* bl);	// area
 void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok);	// self
 void clif_GlobalMessage(struct block_list* bl, const char* message,enum send_target target);

+ 1 - 1
src/map/map-server.vcxproj

@@ -359,7 +359,7 @@
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\produce_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\produce_db.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\quest_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\quest_db.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\refine_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\refine_db.yml')" />
-    <Copy SourceFiles="$(SolutionDir)db\import-tmpl\size_fix.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\size_fix.txt')" />
+    <Copy SourceFiles="$(SolutionDir)db\import-tmpl\size_fix.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\size_fix.yml')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_changematerial_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_changematerial_db.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_damage_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_damage_db.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\skill_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\skill_db.yml')" />

+ 5 - 0
src/map/mob.cpp

@@ -2534,8 +2534,13 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 	) { //Experience calculation.
 		int bonus = 100; //Bonus on top of your share (common to all attackers).
 		int pnum = 0;
+#ifndef RENEWAL
 		if (md->sc.data[SC_RICHMANKIM])
 			bonus += md->sc.data[SC_RICHMANKIM]->val2;
+#else
+		if (sd && sd->sc.data[SC_RICHMANKIM])
+			bonus += sd->sc.data[SC_RICHMANKIM]->val2;
+#endif
 		if(sd) {
 			temp = status_get_class(&md->bl);
 			if(sd->sc.data[SC_MIRACLE]) i = 2; //All mobs are Star Targets

+ 126 - 33
src/map/npc.cpp

@@ -220,58 +220,148 @@ 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->sc.option&(OPTION_INVISIBLE|OPTION_CLOAK))
 			return 1;
 
-		// note : disablenpc doesn't reset the previous trigger status on official
-		if( npc_ontouch_event(sd,nd) > 0 && npc_ontouch2_event(sd,nd) > 0 )
-		{ // failed to run OnTouch event, so just click the npc
-			if (sd->npc_id != 0)
-				return 0;
+		switch (nd->subtype) {
+		case NPCTYPE_WARP:
+			if ((!nd->trigger_on_hidden && (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]))) || pc_isdead(sd))
+				return 1;
+			if (!pc_job_can_entermap((enum e_job)sd->status.class_, map_mapindex2mapid(nd->u.warp.mapindex), sd->group_level))
+				return 1;
+			if (sd->count_rewarp > 10) {
+				ShowWarning("Prevented infinite warp loop for player (%d:%d). Please fix NPC: '%s', path: '%s'\n", sd->status.account_id, sd->status.char_id, nd->exname, nd->path);
+				sd->count_rewarp = 0;
+				return 1;
+			}
+			pc_setpos(sd, nd->u.warp.mapindex, nd->u.warp.x, nd->u.warp.y, CLR_OUTSIGHT);
+			break;
+		default:
+			// note : disablenpc doesn't reset the previous trigger status on official
+			if( npc_ontouch_event(sd,nd) > 0 && npc_ontouch2_event(sd,nd) > 0 )
+			{ // failed to run OnTouch event, so just click the npc
+				if (sd->npc_id != 0)
+					return 0;
 
-			pc_stop_walking(sd,1);
-			npc_click(sd,nd);
+				pc_stop_walking(sd,1);
+				npc_click(sd,nd);
+			}
+			break;
 		}
 	}
 	return 0;
 }
 
+bool npc_is_cloaked(struct npc_data* nd, struct map_session_data* sd) {
+	bool npc_cloaked = (nd->sc.option & OPTION_CLOAK) ? true : false;
+
+	if (std::find(sd->cloaked_npc.begin(), sd->cloaked_npc.end(), nd->bl.id) != sd->cloaked_npc.end())
+		return (!npc_cloaked);
+	return npc_cloaked;
+}
+
+static int npc_cloaked_sub(struct block_list *bl, va_list ap)
+{
+	struct map_session_data* sd;
+
+	nullpo_ret(bl);
+	nullpo_ret(sd = (struct map_session_data *)bl);
+	int id = va_arg(ap, int);
+
+	auto it = std::find(sd->cloaked_npc.begin(), sd->cloaked_npc.end(), id);
+
+	if (it != sd->cloaked_npc.end())
+		sd->cloaked_npc.erase(it);
+
+	return 1;
+}
+
 /*==========================================
  * Disable / Enable NPC
  *------------------------------------------*/
-bool npc_enable(const char* name, int flag)
+bool npc_enable_target(const char* name, uint32 char_id, int flag)
 {
 	struct npc_data* nd = npc_name2id(name);
 
-	if (nd==NULL)
-	{
-		ShowError("npc_enable: Attempted to %s a non-existing NPC '%s' (flag=%d).\n", (flag&3) ? "show" : "hide", name, flag);
+	if (!nd) {
+		ShowError("npc_enable: Attempted to %s a non-existing NPC '%s' (flag=%d).\n", (flag&11) ? "show" : "hide", name, flag);
 		return false;
 	}
 
-	if (flag&1) {
-		nd->sc.option&=~OPTION_INVISIBLE;
-		clif_spawn(&nd->bl);
-	} else if (flag&2)
-		nd->sc.option&=~OPTION_HIDE;
-	else if (flag&4)
-		nd->sc.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;
-		clif_clearunit_area(&nd->bl,CLR_OUTSIGHT);  // Hack to trick maya purple card [Xazax]
-	}
-
-	if (nd->class_ == JT_WARPNPC || nd->class_ == JT_GUILD_FLAG)
-	{	//Client won't display option changes for these classes [Toms]
-		if (nd->sc.option&(OPTION_HIDE|OPTION_INVISIBLE))
-			clif_clearunit_area(&nd->bl, CLR_OUTSIGHT);
+	if (char_id > 0 && (flag & 24)) {
+		map_session_data *sd = map_charid2sd(char_id);
+	
+		if (!sd) {
+			ShowError("npc_enable: Attempted to %s a NPC '%s' on an invalid target %d.\n", (flag & 8) ? "show" : "hide", name, char_id);
+			return false;
+		}
+
+		unsigned int option = nd->sc.option;
+		if (flag&8)
+			nd->sc.option &= ~OPTION_CLOAK;
 		else
+			nd->sc.option |= OPTION_CLOAK;
+
+		auto it = std::find(sd->cloaked_npc.begin(), sd->cloaked_npc.end(), nd->bl.id);
+	
+		if (it == sd->cloaked_npc.end() && option != nd->sc.option)
+			sd->cloaked_npc.push_back(nd->bl.id);
+		else if (it != sd->cloaked_npc.end() && option == nd->sc.option)
+			sd->cloaked_npc.erase(it);
+	
+		if (nd->class_ != JT_WARPNPC && nd->class_ != JT_GUILD_FLAG)
+			clif_changeoption_target(&nd->bl, &sd->bl);
+		else {
+			if (nd->sc.option&(OPTION_HIDE|OPTION_INVISIBLE|OPTION_CLOAK))
+				clif_clearunit_single(nd->bl.id, CLR_OUTSIGHT, sd->fd);
+			else
+				clif_spawn(&nd->bl);
+		}
+		nd->sc.option = option;
+	}
+	else {
+		if (flag&1) {
+			nd->sc.option &= ~OPTION_INVISIBLE;
 			clif_spawn(&nd->bl);
-	} else
-		clif_changeoption(&nd->bl);
+		}
+		else if (flag&2)
+			nd->sc.option &= ~OPTION_HIDE;
+		else if (flag&4)
+			nd->sc.option |= OPTION_HIDE;
+		else if (flag&8)
+			nd->sc.option &= ~OPTION_CLOAK;
+		else if (flag&16)
+			nd->sc.option |= OPTION_CLOAK;
+		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;
+			clif_clearunit_area(&nd->bl,CLR_OUTSIGHT);  // Hack to trick maya purple card [Xazax]
+		}
+		if (nd->class_ != JT_WARPNPC && nd->class_ != JT_GUILD_FLAG)	//Client won't display option changes for these classes [Toms]
+			clif_changeoption(&nd->bl);
+		else {
+			if (nd->sc.option&(OPTION_HIDE|OPTION_INVISIBLE|OPTION_CLOAK))
+				clif_clearunit_area(&nd->bl,CLR_OUTSIGHT);
+			else
+				clif_spawn(&nd->bl);
+		}
+		map_foreachinmap(npc_cloaked_sub, nd->bl.m, BL_PC, nd->bl.id);	// Because npc option has been updated we remove the npc id from sd->cloaked_npc
+	}
 
-	if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) )// check if player standing on a OnTouchArea
-		map_foreachinallarea( npc_enable_sub, nd->bl.m, nd->bl.x-nd->u.scr.xs, nd->bl.y-nd->u.scr.ys, nd->bl.x+nd->u.scr.xs, nd->bl.y+nd->u.scr.ys, BL_PC, nd );
+	if (flag&11) {	// check if player standing on a OnTouchArea
+		int xs = -1, ys = -1;
+		switch (nd->subtype) {
+		case NPCTYPE_SCRIPT:
+			xs = nd->u.scr.xs;
+			ys = nd->u.scr.ys;
+			break;
+		case NPCTYPE_WARP:
+			xs = nd->u.warp.xs;
+			ys = nd->u.warp.ys;
+			break;
+		}
+		if (xs >= 0 || ys >= 0)
+			map_foreachinallarea( npc_enable_sub, nd->bl.m, nd->bl.x-xs, nd->bl.y-ys, nd->bl.x+xs, nd->bl.y+ys, BL_PC, nd );
+	}
 
 	return true;
 }
@@ -1053,6 +1143,9 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
 		if (x >= mapdata->npc[i]->bl.x - xs && x <= mapdata->npc[i]->bl.x + xs && y >= mapdata->npc[i]->bl.y - ys && y <= mapdata->npc[i]->bl.y + ys) {
 			f = 0;
 
+			if (npc_is_cloaked(mapdata->npc[i], sd))
+				continue;
+
 			switch (mapdata->npc[i]->subtype) {
 			case NPCTYPE_WARP:
 				if ((!mapdata->npc[i]->trigger_on_hidden && (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]))) || pc_isdead(sd))
@@ -1103,7 +1196,7 @@ int npc_touch_areanpc2(struct mob_data *md)
 
 	for( i = 0; i < mapdata->npc_num_area; i++ )
 	{
-		if( mapdata->npc[i]->sc.option&OPTION_INVISIBLE )
+		if( mapdata->npc[i]->sc.option&(OPTION_INVISIBLE|OPTION_CLOAK) )
 			continue;
 
 		switch( mapdata->npc[i]->subtype )

+ 3 - 1
src/map/npc.hpp

@@ -1221,7 +1221,9 @@ const char *npc_get_script_event_name(int npce_index);
 void npc_setcells(struct npc_data* nd);
 void npc_unsetcells(struct npc_data* nd);
 bool npc_movenpc(struct npc_data* nd, int16 x, int16 y);
-bool npc_enable(const char* name, int flag);
+bool npc_is_cloaked(struct npc_data* nd, struct map_session_data* sd);
+bool npc_enable_target(const char* name, uint32 char_id, int flag);
+#define npc_enable(name, flag) npc_enable_target(name, 0, flag)
 void npc_setdisplayname(struct npc_data* nd, const char* newname);
 void npc_setclass(struct npc_data* nd, short class_);
 struct npc_data* npc_name2id(const char* name);

+ 38 - 6
src/map/pc.cpp

@@ -5860,6 +5860,16 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
 		}
 
 		channel_pcquit(sd,4); //quit map chan
+
+		// Remove Cloaked NPC if changing to another map
+		for (auto it = sd->cloaked_npc.begin(); it != sd->cloaked_npc.end(); ++it) {
+			block_list *npc_bl = map_id2bl(*it);
+
+			if (npc_bl && npc_bl->m != m) {
+				sd->cloaked_npc.erase(it);
+				break;
+			}
+		}
 	}
 
 	if( m < 0 )
@@ -8928,6 +8938,11 @@ int pc_itemheal(struct map_session_data *sd, int itemid, int hp, int sp)
 			sp += sp / 10;
 		}
 
+#ifdef RENEWAL
+		if (sd->sc.data[SC_APPLEIDUN])
+			hp += sd->sc.data[SC_APPLEIDUN]->val3 / 100;
+#endif
+
 		if (penalty > 0) {
 			hp -= hp * penalty / 100;
 			sp -= sp * penalty / 100;
@@ -9526,7 +9541,12 @@ bool pc_can_attack( struct map_session_data *sd, int target_id ) {
 	if (sd->state.block_action & PCBLOCK_ATTACK)
 		return false;
 
-	if( sd->sc.data[SC_BASILICA] ||
+	if(
+#ifdef RENEWAL
+		sd->sc.data[SC_BASILICA_CELL] ||
+#else
+		sd->sc.data[SC_BASILICA] ||
+#endif
 		sd->sc.data[SC__SHADOWFORM] ||
 		sd->sc.data[SC_CURSEDCIRCLE_ATKER] ||
 		sd->sc.data[SC_CURSEDCIRCLE_TARGET] ||
@@ -10637,6 +10657,12 @@ bool pc_unequipitem(struct map_session_data *sd, int n, int flag) {
 		status_change_end(&sd->bl, SC_ARMOR_RESIST, INVALID_TIMER);
 	}
 
+	// On equipment change
+#ifndef RENEWAL
+	if (!(flag&4))
+		status_change_end(&sd->bl, SC_CONCENTRATION, INVALID_TIMER);
+#endif
+
 	// On ammo change
 	if (sd->inventory_data[n]->type == IT_AMMO && (sd->inventory_data[n]->nameid != ITEMID_SILVER_BULLET || sd->inventory_data[n]->nameid != ITEMID_PURIFICATION_BULLET || sd->inventory_data[n]->nameid != ITEMID_SILVER_BULLET_))
 		status_change_end(&sd->bl, SC_P_ALTER, INVALID_TIMER);
@@ -12779,13 +12805,19 @@ void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag) {
  */
 void pc_cell_basilica(struct map_session_data *sd) {
 	nullpo_retv(sd);
-	
+
+#ifdef RENEWAL
+	enum sc_type type = SC_BASILICA_CELL;
+#else
+	enum sc_type type = SC_BASILICA;
+#endif
+
 	if (!map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKBASILICA)) {
-		if (sd->sc.data[SC_BASILICA])
-			status_change_end(&sd->bl,SC_BASILICA,INVALID_TIMER);
+		if (sd->sc.data[type])
+			status_change_end(&sd->bl, type,INVALID_TIMER);
 	}
-	else if (!sd->sc.data[SC_BASILICA])
-		sc_start(&sd->bl,&sd->bl,SC_BASILICA,100,0,INFINITE_TICK);
+	else if (!sd->sc.data[type])
+		sc_start(&sd->bl,&sd->bl, type,100,0,INFINITE_TICK);
 }
 
 /** [Cydh]

+ 3 - 1
src/map/pc.hpp

@@ -148,7 +148,7 @@ struct s_addele2 {
 };
 
 struct weapon_data {
-	int atkmods[3];
+	int atkmods[SZ_ALL];
 	// all the variables except atkmods get zero'ed in each call of status_calc_pc
 	// NOTE: if you want to add a non-zeroed variable, you need to update the memset call
 	//  in status_calc_pc as well! All the following are automatically zero'ed. [Skotlex]
@@ -648,6 +648,8 @@ struct map_session_data {
 	// Title system
 	std::vector<int> titles;
 
+	std::vector<int> cloaked_npc;
+
 	/* ShowEvent Data Cache flags from map */
 	bool *qi_display;
 	int qi_count;

+ 37 - 0
src/map/script.cpp

@@ -24665,6 +24665,40 @@ BUILDIN_FUNC(convertpcinfo) {
 	return SCRIPT_CMD_SUCCESS;
 }
 
+BUILDIN_FUNC(cloakoffnpc)
+{
+	if (npc_enable_target(script_getstr(st, 2), script_hasdata(st, 3) ? script_getnum(st, 3) : 0, 8))
+		return SCRIPT_CMD_SUCCESS;
+
+	return SCRIPT_CMD_FAILURE;
+}
+
+BUILDIN_FUNC(cloakonnpc)
+{
+	if (npc_enable_target(script_getstr(st, 2), script_hasdata(st, 3) ? script_getnum(st, 3) : 0, 16))
+		return SCRIPT_CMD_SUCCESS;
+
+	return SCRIPT_CMD_FAILURE;
+}
+
+BUILDIN_FUNC(isnpccloaked)
+{
+	struct npc_data *nd = npc_name2id(script_getstr(st, 2));
+
+	if (!nd) {
+		ShowError("buildin_isnpccloaked: %s is a non-existing NPC.\n", script_getstr(st, 2));
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	map_session_data* sd;
+
+	if (!script_charid2sd(3, sd))
+		return SCRIPT_CMD_FAILURE;
+
+	script_pushint(st, npc_is_cloaked(nd, sd));
+	return SCRIPT_CMD_SUCCESS;
+}
+
 #include "../custom/script.inc"
 
 // declarations that were supposed to be exported from npc_chat.cpp
@@ -25338,6 +25372,9 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(achievement_condition,"i"),
 	BUILDIN_DEF(getvariableofinstance,"ri"),
 	BUILDIN_DEF(convertpcinfo,"vi"),
+	BUILDIN_DEF(cloakoffnpc, "s?"),
+	BUILDIN_DEF(cloakonnpc, "s?"),
+	BUILDIN_DEF(isnpccloaked, "s?"),
 #include "../custom/script_def.inc"
 
 	{NULL,NULL,NULL},

+ 2 - 0
src/map/script_constants.hpp

@@ -1544,6 +1544,8 @@
 	export_constant(SC_WEAPONBLOCK_ON);
 	export_constant(SC_ENTRY_QUEUE_APPLY_DELAY);
 	export_constant(SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT);
+	export_constant(SC_ADAPTATION);
+	export_constant(SC_BASILICA_CELL);
 #ifdef RENEWAL
 	export_constant(SC_EXTREMITYFIST2);
 #endif

文件差異過大導致無法顯示
+ 339 - 59
src/map/skill.cpp


+ 18 - 0
src/map/skill.hpp

@@ -387,6 +387,22 @@ struct skill_unit_group_tickset {
 	int id;
 };
 
+/// Ring of Nibelungen bonuses
+enum e_nibelungen_status : uint8 {
+	RINGNBL_ASPDRATE = 1,		///< ASPD + 20%
+	RINGNBL_ATKRATE,		///< Physical damage + 20%
+	RINGNBL_MATKRATE,		///< MATK + 20%
+	RINGNBL_HPRATE,			///< Maximum HP + 30%
+	RINGNBL_SPRATE,			///< Maximum SP + 30%
+	RINGNBL_ALLSTAT,		///< All stats + 15
+	RINGNBL_HIT,			///< HIT + 50
+	RINGNBL_FLEE,			///< FLEE + 50
+	RINGNBL_SPCONSUM,		///< SP consumption - 30%
+	RINGNBL_HPREGEN,		///< HP recovery + 100%
+	RINGNBL_SPREGEN,		///< SP recovery + 100%
+	RINGNBL_MAX,
+};
+
 /// Enum for skill_blown
 enum e_skill_blown	{
 	BLOWN_NONE					= 0x00,
@@ -1933,6 +1949,8 @@ enum e_skill {
 
 	ALL_EQSWITCH = 5067,
 
+	CG_SPECIALSINGER,
+
 	AB_VITUPERATUM = 5072,
 	AB_CONVENIO,
 

文件差異過大導致無法顯示
+ 466 - 32
src/map/status.cpp


+ 20 - 0
src/map/status.hpp

@@ -4,6 +4,7 @@
 #ifndef STATUS_HPP
 #define STATUS_HPP
 
+#include "../common/database.hpp"
 #include "../common/mmo.hpp"
 #include "../common/timer.hpp"
 
@@ -59,6 +60,23 @@ struct refine_cost {
 int status_get_refine_chance(enum refine_type wlv, int refine, bool enriched);
 int status_get_refine_cost(int weapon_lv, int type, bool what);
 
+/// Weapon attack modification for size
+struct s_sizefix_db {
+	uint16 small, medium, large;
+};
+
+class SizeFixDatabase : public TypesafeYamlDatabase<int32, s_sizefix_db> {
+public:
+	SizeFixDatabase() : TypesafeYamlDatabase("SIZE_FIX_DB", 1) {
+
+	}
+
+	const std::string getDefaultLocation();
+	uint64 parseBodyNode(const YAML::Node &node);
+};
+
+extern SizeFixDatabase size_fix_db;
+
 /// Status changes listing. These code are for use by the server.
 enum sc_type : int16 {
 	SC_NONE = -1,
@@ -863,6 +881,8 @@ enum sc_type : int16 {
 	SC_EARTHSHAKER,
 	SC_WEAPONBLOCK_ON,
 	SC_SPORE_EXPLOSION,
+	SC_ADAPTATION,
+	SC_BASILICA_CELL, // Used in renewal mode for cell_basilica only
 
 	SC_ENTRY_QUEUE_APPLY_DELAY,
 	SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT,

+ 12 - 1
src/map/unit.cpp

@@ -1128,7 +1128,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, enum e_skill_bl
  *		UB_KNOCKABLE - can be knocked back / stopped
  *		UB_NO_KNOCKBACK_MAP - at WOE/BG map
  *		UB_MD_KNOCKBACK_IMMUNE - target is MD_KNOCKBACK_IMMUNE
- *		UB_TARGET_BASILICA - target is in Basilica area
+ *		UB_TARGET_BASILICA - target is in Basilica area (Pre-Renewal)
  *		UB_TARGET_NO_KNOCKBACK - target has 'special_state.no_knockback'
  *		UB_TARGET_TRAP - target is trap that cannot be knocked back
  */
@@ -1148,9 +1148,12 @@ enum e_unit_blown unit_blown_immune(struct block_list* bl, uint8 flag)
 			break;
 		case BL_PC: {
 				struct map_session_data *sd = BL_CAST(BL_PC, bl);
+
+#ifndef RENEWAL
 				// Basilica caster can't be knocked-back by normal monsters.
 				if( !(flag&0x4) && sd->sc.data[SC_BASILICA] && sd->sc.data[SC_BASILICA]->val4 == sd->bl.id)
 					return UB_TARGET_BASILICA;
+#endif
 				// Target has special_state.no_knockback (equip)
 				if( (flag&(0x1|0x2)) && !(flag&0x8) && sd->special_state.no_knockback )
 					return UB_TARGET_NO_KNOCKBACK;
@@ -1389,7 +1392,9 @@ int unit_can_move(struct block_list *bl) {
 		if( sc->cant.move // status placed here are ones that cannot be cached by sc->cant.move for they depend on other conditions other than their availability
 			|| sc->data[SC_SPIDERWEB]
 			|| (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && (
+#ifndef RENEWAL
 				!sc->data[SC_LONGING] ||
+#endif
 				(sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT ||
 				(sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE
 				) )
@@ -1799,10 +1804,12 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
 			if (sc && sc->data[SC_RUN])
 				casttime = -1;
 		break;
+#ifndef RENEWAL
 		case HP_BASILICA:
 			if( sc && sc->data[SC_BASILICA] )
 				casttime = -1; // No Casting time on basilica cancel
 		break;
+#endif
 #ifndef RENEWAL_CAST
 		case KN_CHARGEATK:
 		{
@@ -2879,7 +2886,11 @@ 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);
+#ifdef RENEWAL
+		status_change_end(bl, SC_BASILICA_CELL, INVALID_TIMER);
+#else
 		status_change_end(bl, SC_BASILICA, INVALID_TIMER);
+#endif
 		status_change_end(bl, SC_ANKLE, INVALID_TIMER);
 		status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER);
 		status_change_end(bl, SC_BLADESTOP_WAIT, INVALID_TIMER);

部分文件因文件數量過多而無法顯示