Просмотр исходного кода

* Bug Fixes:
-- Added itemstack check when init autotrader (bugreport:9077)
-- 'getitem' issue, gave unidentified item (bugreport:9075), follow up 62a2813
-- Invalid Def & Mdef reduction of SC_ARMORCHANGE & duration (NPC_STONESKIN & NPC_ANTIMAGIC), should be percentage (bugreport:9076)
-- Invalid Effect duration & Reflect chance of SC_MAGICMIRROR (NPC_MAGICMIRROR)
-- Wrong usage of script_isstring() for script commands: addspiritball, delspiritball, & countspiritball
* Misc:
-- Moved mail send progress to mail.c mail_send() from clif.c clif_parse_Mail_send()
-- Moved hardcoded flood protection when send a mail to 'mail_delay' in misc.conf

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>

Cydh Ramdh 11 лет назад
Родитель
Сommit
462b2bebdb

+ 3 - 0
conf/battle/misc.conf

@@ -138,3 +138,6 @@ discount_item_point_shop: 0
 
 // Don't display message "login-serv has been asked to %s the player '%.*s'." (Note 1)
 disp_serverbank_msg: no
+
+// Delay to allow user resend new mail (default & minimum is 1000)
+mail_delay: 1000

+ 5 - 5
db/pre-re/item_db.txt

@@ -1089,7 +1089,7 @@
 2119,Improved_Arm_Guard,Advanced Arm Guard,4,40000,,150,,4,,0,0x02000000,7,2,32,,50,1,1,{ bonus bMdef,5; },{},{}
 2120,Improved_Arm_Guard_,Advanced Arm Guard,4,40000,,150,,4,,1,0x02000000,7,2,32,,50,1,1,{ bonus bMdef,5; },{},{}
 2121,Memorize_Book_,Memory Book,4,20,,1000,,3,,1,0x00810204,7,2,32,,0,1,5,{ bonus bInt,1; bonus bMdef,2; },{},{}
-2122,Platinum_Shield,Platinum Shield,4,20,,1200,,5,,0,0xFFFFFFFE,2,2,32,,68,1,4,{ bonus bMdef,5; bonus2 bSubSize,Size_Medium,15; bonus2 bSubSize,Size_Large,15; bonus2 bSubRace,RC_Undead,10; bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",2,150,BF_MAGIC,0; },{},{}
+2122,Platinum_Shield,Platinum Shield,4,20,,1200,,5,,0,0xFFFFFFFE,2,2,32,,68,1,4,{ bonus bMdef,5; bonus2 bSubSize,Size_Medium,15; bonus2 bSubSize,Size_Large,15; bonus2 bSubRace,RC_Undead,10; bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",7,150,BF_MAGIC,0; },{},{}
 2123,Orleans_Server,Orleans's Server,4,20,,1000,,5,,1,0xFFFFFFFE,2,2,32,,55,1,4,{ bonus bMdef,2; bonus bMagicDamageReturn,5; },{},{}
 2124,Thorny_Buckler,Thorny Buckler,4,20,,1000,,5,,1,0xFFFFFFFE,2,2,32,,55,1,2,{ bonus bMdef,2; },{},{}
 2125,Strong_Shield,Strong Shield,4,20,,2500,,4,,1,0xFFFFFFFE,2,2,32,,75,1,4,{ bonus bNoKnockback,0; bonus2 bSubEle,Ele_Neutral,-20; bonus2 bSubEle,Ele_Fire,-20; bonus2 bSubEle,Ele_Water,-20; bonus2 bSubEle,Ele_Wind,-20; bonus2 bSubEle,Ele_Earth,-20; bonus2 bSubEle,Ele_Dark,-20; bonus2 bSubEle,Ele_Holy,-20; bonus2 bSubEle,Ele_Ghost,-20; },{},{}
@@ -1394,8 +1394,8 @@
 2528,Wool_Scarf,Wool Scarf,4,20,,500,,3,,1,0xFFFFFFFE,2,2,4,,55,1,0,{ bonus bMdef,4; },{},{}
 2529,Rider_Insignia,Rider Insignia,4,20,,500,,4,,0,0xFFFFFFFE,2,2,4,,55,1,0,{ bonus bAgi,2; },{},{}
 2530,Rider_Insignia_,Rider Insignia,4,20,,500,,4,,1,0xFFFFFFFE,2,2,4,,55,1,0,{ bonus bAgi,2; },{},{}
-2531,Ulfhedinn,Ulfhedinn,4,20,,700,,3,,1,0x000654E2,2,2,4,,70,1,0,{ bonus3 bAutoSpellWhenHit,"NPC_STONESKIN",1,20; },{},{}
-2532,Mithril_Magic_Cape,Mithril Magic Cape,4,20,,400,,3,,1,0x00098B1C,2,2,4,,70,1,0,{ bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",1,200,BF_MAGIC,0; },{},{}
+2531,Ulfhedinn,Ulfhedinn,4,20,,700,,3,,1,0x000654E2,2,2,4,,70,1,0,{ bonus3 bAutoSpellWhenHit,"NPC_STONESKIN",6,20; },{},{}
+2532,Mithril_Magic_Cape,Mithril Magic Cape,4,20,,400,,3,,1,0x00098B1C,2,2,4,,70,1,0,{ bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",6,200,BF_MAGIC,0; },{},{}
 //2533,Freyja_Cape,Freyja Cape,4,0,,200,,10,,0,0xFFFFFFFE,7,2,4,,0,0,0,{ bonus2 bSubRace,RC_DemiHuman,15; bonus2 bSubRace,RC_Player,15; },{},{}
 2534,Ruffler,Ruffler,4,20,,0,,10,,0,0xFFFFFFFF,7,2,4,,0,0,0,{ bonus2 bSubEle,Ele_Neutral,17; bonus bFlee,17; },{},{}
 2535,Cloak_Of_Survival_C,Cloak Of Survival,4,1,,0,,5,,0,0x00810204,7,2,4,,0,0,0,{ bonus bVit,10; bonus bMdef,10; },{},{}
@@ -1415,7 +1415,7 @@
 2549,Krieger_Muffler1,Glorious Muffler,4,20,,0,,0,,0,0xFFFFFFFE,7,2,4,,81,1,0,{ bonus bMaxHPRate,5; bonus2 bSubRace,RC_DemiHuman,5; bonus2 bSubRace,RC_Player,5; },{},{}
 2550,Fisher's_Muffler,Fisher's Muffler,4,20,,200,,0,,0,0xFFFFFFFF,7,2,4,,0,1,0,{},{},{}
 2551,Rider_Insignia_M,Crest of the Rider,4,20,,500,,4,,1,0xFFFFFFFE,2,2,4,,55,1,0,{ bonus bAgi,2; },{},{}
-2552,Mithril_Magic_Cape_M,Mithril Magic Manteau,4,20,,400,,3,,1,0x00098B1C,2,2,4,,70,1,0,{ bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",1,200,BF_MAGIC,0; },{},{}
+2552,Mithril_Magic_Cape_M,Mithril Magic Manteau,4,20,,400,,3,,1,0x00098B1C,2,2,4,,70,1,0,{ bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",6,200,BF_MAGIC,0; },{},{}
 2553,Dragon_Manteau,Dragon Manteau,4,20,,1000,,5,,1,0xFFFFFFFE,2,2,4,,0,1,0,{ bonus bAgi,1; bonus bMdef,5; },{},{}
 2554,Piece_Of_Angent_Skin,Nydhorgg's Shadow Garb,4,20,,400,,5,,1,0xFFFFFFFE,2,2,4,,90,1,0,{ bonus2 bSubEle,Ele_Neutral,7; bonus2 bSubEle,Ele_Water,7; bonus2 bSubEle,Ele_Earth,7; bonus2 bSubEle,Ele_Fire,7; bonus2 bSubEle,Ele_Wind,7; bonus2 bSubEle,Ele_Poison,7; bonus2 bSubEle,Ele_Holy,7; bonus2 bSubEle,Ele_Dark,7; bonus2 bSubEle,Ele_Ghost,7; bonus2 bSubEle,Ele_Undead,7; bonus bMaxSP,(BaseLevel/3)+(getrefine()*10); bonus3 bSPDrainRate,10,1,0; bonus bMdef,3; },{},{}
 // Accessories
@@ -2849,7 +2849,7 @@
 //5679,Engineer_Cap,Engineer Cap,4,20,,200,,2,,1,0xFFFFFFFF,7,2,256,,10,1,608,{},{},{}
 //5680,Hawkeyes,Hawkeyes,4,20,,100,,0,,0,0xFFFFFFFF,7,2,512,,10,0,609,{},{},{}
 5681,F_Ribbon_Green,Green Ribbon,4,800,,100,,1,,0,0xFFFFFFFF,7,0,256,,0,1,244,{ bonus bMdef,3; },{},{}
-5682,Triangle_Rune_Cap,Triangle Rune Cap,4,20,,300,,5,,1,0xFFFFFFFF,7,2,256,,1,1,610,{ bonus bInt,1; },{},{}
+5682,Triangle_Rune_Cap,Triangle Rune Cap,4,20,,300,,5,,1,0xFFFFFFFF,7,2,256,,1,1,610,{ bonus bHealPower,2; if (getrefine() > 6) { bonus bMatk,10; bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",8,150,BF_MAGIC,0; } else { bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",7,150,BF_MAGIC,0; } },{},{}
 5683,Majestic_Goat_Repl,Baphomet Horns,4,20,,100,,5,,0,0xFFFFFFFF,7,2,256,,1,1,41,{},{},{}
 5684,Jewel_Crown_Repl,Ornate Crown,4,20,,100,,5,,0,0xFFFFFFFF,7,2,256,,1,1,88,{},{},{}
 5685,Prontera_Army_Cap_Repl,Army Cap,4,20,,100,,5,,0,0xFFFFFFFF,7,2,256,,1,1,48,{},{},{}

+ 3 - 3
db/pre-re/skill_cast_db.txt

@@ -988,15 +988,15 @@
 //-- NPC_EVILLAND
 670,0,0,0,30000,30000,0
 //-- NPC_MAGICMIRROR
-671,0,0,0,30000,0,0
+671,0,0,0,30000:30000:30000:30000:30000:2000:2000:2000:2000:2000,0,0
 //-- NPC_SLOWCAST
 672,0,0,0,0,30000,0
 //-- NPC_CRITICALWOUND
 673,0,0,0,0,30000,0
 //-- NPC_STONESKIN
-675,0,0,0,30000,0,0
+675,0,0,0,30000:30000:30000:30000:30000:2000:2000:2000:2000:2000,0,0
 //-- NPC_ANTIMAGIC
-676,0,0,0,30000,0,0
+676,0,0,0,30000:30000:30000:30000:30000:2000:2000:2000:2000:2000,0,0
 //-- NPC_WIDECURSE
 677,0,0,0,0,30000,0
 //-- NPC_WIDESTUN

+ 3 - 3
db/re/item_db.txt

@@ -1610,7 +1610,7 @@
 2529,Rider_Insignia,Rider Insignia,4,20,,500,,13,,0,0xFFFFFFFE,18,2,4,,55,1,0,{ bonus bAgi,2; },{},{}
 2530,Rider_Insignia_,Rider Insignia,4,20,,500,,13,,1,0xFFFFFFFE,18,2,4,,55,1,0,{ bonus bAgi,2; },{},{}
 2531,Ulfhedinn,Ulfhedinn,4,20,,700,,13,,1,0x000654E2,18,2,4,,70,1,0,{ bonus3 bAutoSpellWhenHit,"NPC_STONESKIN",6,20; },{},{}
-2532,Mithril_Magic_Cape,Mithril Magic Cape,4,20,,400,,8,,1,0x00098B1C,18,2,4,,70,1,0,{ bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",1,200,BF_MAGIC,0; },{},{}
+2532,Mithril_Magic_Cape,Mithril Magic Cape,4,20,,400,,8,,1,0x00098B1C,18,2,4,,70,1,0,{ bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",6,200,BF_MAGIC,0; },{},{}
 2533,Freyja_Cape,Freyja Cape,4,0,,200,,10,,0,0xFFFFFFFE,63,2,4,,0,0,0,{ bonus2 bSubRace,RC_DemiHuman,15; bonus2 bSubRace,RC_Player,15; },{},{}
 2534,Ruffler,Ruffler,4,20,,0,,10,,0,0xFFFFFFFF,63,2,4,,0,0,0,{ bonus2 bSubEle,Ele_Neutral,17; bonus bFlee,17; },{},{}
 2535,Cloak_Of_Survival_C,Cloak Of Survival,4,1,,0,,5,,0,0x00810204,63,2,4,,0,0,0,{ bonus bVit,10; bonus bMdef,10; },{},{}
@@ -1630,7 +1630,7 @@
 2549,Krieger_Muffler1,Glorious Muffler,4,20,,0,,0,,0,0xFFFFFFFE,63,2,4,,80,1,0,{ bonus bMaxHPrate,5; bonus2 bSubRace,RC_DemiHuman,5; bonus2 bSubRace,RC_Player,5; },{},{}
 2550,Fisher's_Muffler,Fisher's Muffler,4,20,,200,,0,,0,0xFFFFFFFF,63,2,4,,0,1,0,{},{},{}
 2551,Rider_Insignia_M,Crest of the Rider,4,20,,500,,4,,1,0xFFFFFFFE,18,2,4,,55,1,0,{ bonus bAgi,2; },{},{}
-2552,Mithril_Magic_Cape_M,Mithril Magic Manteau,4,20,,400,,3,,1,0x00098B1C,18,2,4,,70,1,0,{ bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",1,200,BF_MAGIC,0; },{},{}
+2552,Mithril_Magic_Cape_M,Mithril Magic Manteau,4,20,,400,,3,,1,0x00098B1C,18,2,4,,70,1,0,{ bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",6,200,BF_MAGIC,0; },{},{}
 2553,Dragon_Manteau,Dragon Manteau,4,20,,1000,,14,,1,0xFFFFFFFE,18,2,4,,0,1,0,{ bonus bAgi,1; bonus bMdef,5; },{},{}
 2554,Piece_Of_Angent_Skin,Nydhorgg's Shadow Garb,4,20,,400,,25,,1,0xFFFFFFFE,18,2,4,,90,1,0,{ bonus2 bSubEle,Ele_Neutral,7; bonus2 bSubEle,Ele_Water,7; bonus2 bSubEle,Ele_Earth,7; bonus2 bSubEle,Ele_Fire,7; bonus2 bSubEle,Ele_Wind,7; bonus2 bSubEle,Ele_Poison,7; bonus2 bSubEle,Ele_Holy,7; bonus2 bSubEle,Ele_Dark,7; bonus2 bSubEle,Ele_Ghost,7; bonus2 bSubEle,Ele_Undead,7; bonus bMaxSP,(BaseLevel/3)+(getrefine()*10); bonus3 bSPDrainRate,10,1,0; bonus bMdef,3; },{},{}
 2555,Freyja_SScarf7,Freyja Soul Scarf,4,20,,400,,4,,0,0xFFFFFFFF,63,2,4,,20,0,0,{ bonus bFlee,15; bonus2 bSubEle,Ele_Neutral,15; },{},{}
@@ -3577,7 +3577,7 @@
 5679,Engineer_Cap,Engineer Cap,4,20,,200,,2,,1,0xFFFFFFFF,63,2,256,,10,1,608,{},{},{}
 5680,Hawkeyes,Hawkeyes,4,20,,100,,0,,0,0xFFFFFFFF,63,2,512,,10,0,609,{ bonus bUnbreakableHelm,0; },{},{}
 5681,F_Ribbon_Green,Green Ribbon,4,800,,100,,1,,0,0xFFFFFFFF,63,0,256,,0,1,244,{ bonus bMdef,3; },{},{}
-5682,Triangle_Rune_Cap,Triangle Rune Cap,4,20,,300,,5,,1,0xFFFFFFFF,63,2,256,,1,1,610,{ bonus bInt,1; },{},{}
+5682,Triangle_Rune_Cap,Triangle Rune Cap,4,20,,300,,5,,1,0xFFFFFFFF,63,2,256,,1,1,610,{ bonus bHealPower,2; if (getrefine() > 6) { bonus bMatk,10; bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",8,150,BF_MAGIC,0; } else { bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",7,150,BF_MAGIC,0; } },{},{}
 5683,Majestic_Goat_Repl,Baphomet Horns,4,20,,100,,5,,0,0xFFFFFFFF,63,2,256,,1,1,41,{},{},{}
 5684,Jewel_Crown_Repl,Ornate Crown,4,20,,100,,5,,0,0xFFFFFFFF,63,2,256,,1,1,88,{},{},{}
 5685,Prontera_Army_Cap_Repl,Army Cap,4,20,,100,,5,,0,0xFFFFFFFF,63,2,256,,1,1,48,{},{},{}

+ 3 - 3
db/re/skill_cast_db.txt

@@ -990,15 +990,15 @@
 //-- NPC_EVILLAND
 670,0,0,0,30000,30000,0,-1
 //-- NPC_MAGICMIRROR
-671,0,0,0,30000,0,0,-1
+671,0,0,0,30000:30000:30000:30000:30000:2000:2000:2000:2000:2000,0,0,-1
 //-- NPC_SLOWCAST
 672,0,0,0,0,30000,0,-1
 //-- NPC_CRITICALWOUND
 673,0,0,0,0,30000,0,-1
 //-- NPC_STONESKIN
-675,0,0,0,30000,0,0,-1
+675,0,0,0,30000:30000:30000:30000:30000:2000:2000:2000:2000:2000,0,0,-1
 //-- NPC_ANTIMAGIC
-676,0,0,0,30000,0,0,-1
+676,0,0,0,30000:30000:30000:30000:30000:2000:2000:2000:2000:2000,0,0,-1
 //-- NPC_WIDECURSE
 677,0,0,0,0,30000,0,-1
 //-- NPC_WIDESTUN

+ 5 - 5
sql-files/item_db.sql

@@ -1120,7 +1120,7 @@ REPLACE INTO `item_db` VALUES (2118,'Arm_Guard_','Arm Guard',4,10000,NULL,150,NU
 REPLACE INTO `item_db` VALUES (2119,'Improved_Arm_Guard','Advanced Arm Guard',4,40000,NULL,150,NULL,4,NULL,0,0x02000000,7,2,32,NULL,50,1,1,'bonus bMdef,5;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2120,'Improved_Arm_Guard_','Advanced Arm Guard',4,40000,NULL,150,NULL,4,NULL,1,0x02000000,7,2,32,NULL,50,1,1,'bonus bMdef,5;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2121,'Memorize_Book_','Memory Book',4,20,NULL,1000,NULL,3,NULL,1,0x00810204,7,2,32,NULL,0,1,5,'bonus bInt,1; bonus bMdef,2;',NULL,NULL);
-REPLACE INTO `item_db` VALUES (2122,'Platinum_Shield','Platinum Shield',4,20,NULL,1200,NULL,5,NULL,0,0xFFFFFFFE,2,2,32,NULL,68,1,4,'bonus bMdef,5; bonus2 bSubSize,Size_Medium,15; bonus2 bSubSize,Size_Large,15; bonus2 bSubRace,RC_Undead,10; bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",2,150,BF_MAGIC,0;',NULL,NULL);
+REPLACE INTO `item_db` VALUES (2122,'Platinum_Shield','Platinum Shield',4,20,NULL,1200,NULL,5,NULL,0,0xFFFFFFFE,2,2,32,NULL,68,1,4,'bonus bMdef,5; bonus2 bSubSize,Size_Medium,15; bonus2 bSubSize,Size_Large,15; bonus2 bSubRace,RC_Undead,10; bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",7,150,BF_MAGIC,0;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2123,'Orleans_Server','Orleans\'s Server',4,20,NULL,1000,NULL,5,NULL,1,0xFFFFFFFE,2,2,32,NULL,55,1,4,'bonus bMdef,2; bonus bMagicDamageReturn,5;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2124,'Thorny_Buckler','Thorny Buckler',4,20,NULL,1000,NULL,5,NULL,1,0xFFFFFFFE,2,2,32,NULL,55,1,2,'bonus bMdef,2;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2125,'Strong_Shield','Strong Shield',4,20,NULL,2500,NULL,4,NULL,1,0xFFFFFFFE,2,2,32,NULL,75,1,4,'bonus bNoKnockback,0; bonus2 bSubEle,Ele_Neutral,-20; bonus2 bSubEle,Ele_Fire,-20; bonus2 bSubEle,Ele_Water,-20; bonus2 bSubEle,Ele_Wind,-20; bonus2 bSubEle,Ele_Earth,-20; bonus2 bSubEle,Ele_Dark,-20; bonus2 bSubEle,Ele_Holy,-20; bonus2 bSubEle,Ele_Ghost,-20;',NULL,NULL);
@@ -1425,8 +1425,8 @@ REPLACE INTO `item_db` VALUES (2527,'Dragon_Breath','Dragon Breath',4,20,NULL,60
 REPLACE INTO `item_db` VALUES (2528,'Wool_Scarf','Wool Scarf',4,20,NULL,500,NULL,3,NULL,1,0xFFFFFFFE,2,2,4,NULL,55,1,0,'bonus bMdef,4;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2529,'Rider_Insignia','Rider Insignia',4,20,NULL,500,NULL,4,NULL,0,0xFFFFFFFE,2,2,4,NULL,55,1,0,'bonus bAgi,2;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2530,'Rider_Insignia_','Rider Insignia',4,20,NULL,500,NULL,4,NULL,1,0xFFFFFFFE,2,2,4,NULL,55,1,0,'bonus bAgi,2;',NULL,NULL);
-REPLACE INTO `item_db` VALUES (2531,'Ulfhedinn','Ulfhedinn',4,20,NULL,700,NULL,3,NULL,1,0x000654E2,2,2,4,NULL,70,1,0,'bonus3 bAutoSpellWhenHit,"NPC_STONESKIN",1,20;',NULL,NULL);
-REPLACE INTO `item_db` VALUES (2532,'Mithril_Magic_Cape','Mithril Magic Cape',4,20,NULL,400,NULL,3,NULL,1,0x00098B1C,2,2,4,NULL,70,1,0,'bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",1,200,BF_MAGIC,0;',NULL,NULL);
+REPLACE INTO `item_db` VALUES (2531,'Ulfhedinn','Ulfhedinn',4,20,NULL,700,NULL,3,NULL,1,0x000654E2,2,2,4,NULL,70,1,0,'bonus3 bAutoSpellWhenHit,"NPC_STONESKIN",6,20;',NULL,NULL);
+REPLACE INTO `item_db` VALUES (2532,'Mithril_Magic_Cape','Mithril Magic Cape',4,20,NULL,400,NULL,3,NULL,1,0x00098B1C,2,2,4,NULL,70,1,0,'bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",6,200,BF_MAGIC,0;',NULL,NULL);
 #REPLACE INTO `item_db` VALUES (2533,'Freyja_Cape','Freyja Cape',4,0,NULL,200,NULL,10,NULL,0,0xFFFFFFFE,7,2,4,NULL,0,0,0,'bonus2 bSubRace,RC_DemiHuman,15; bonus2 bSubRace,RC_Player,15;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2534,'Ruffler','Ruffler',4,20,NULL,0,NULL,10,NULL,0,0xFFFFFFFF,7,2,4,NULL,0,0,0,'bonus2 bSubEle,Ele_Neutral,17; bonus bFlee,17;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2535,'Cloak_Of_Survival_C','Cloak Of Survival',4,1,NULL,0,NULL,5,NULL,0,0x00810204,7,2,4,NULL,0,0,0,'bonus bVit,10; bonus bMdef,10;',NULL,NULL);
@@ -1446,7 +1446,7 @@ REPLACE INTO `item_db` VALUES (2548,'Muffler_C','Neo Muffler',4,0,NULL,0,NULL,5,
 REPLACE INTO `item_db` VALUES (2549,'Krieger_Muffler1','Glorious Muffler',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFE,7,2,4,NULL,81,1,0,'bonus bMaxHPRate,5; bonus2 bSubRace,RC_DemiHuman,5; bonus2 bSubRace,RC_Player,5;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2550,'Fisher\'s_Muffler','Fisher\'s Muffler',4,20,NULL,200,NULL,0,NULL,0,0xFFFFFFFF,7,2,4,NULL,0,1,0,NULL,NULL,NULL);
 REPLACE INTO `item_db` VALUES (2551,'Rider_Insignia_M','Crest of the Rider',4,20,NULL,500,NULL,4,NULL,1,0xFFFFFFFE,2,2,4,NULL,55,1,0,'bonus bAgi,2;',NULL,NULL);
-REPLACE INTO `item_db` VALUES (2552,'Mithril_Magic_Cape_M','Mithril Magic Manteau',4,20,NULL,400,NULL,3,NULL,1,0x00098B1C,2,2,4,NULL,70,1,0,'bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",1,200,BF_MAGIC,0;',NULL,NULL);
+REPLACE INTO `item_db` VALUES (2552,'Mithril_Magic_Cape_M','Mithril Magic Manteau',4,20,NULL,400,NULL,3,NULL,1,0x00098B1C,2,2,4,NULL,70,1,0,'bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",6,200,BF_MAGIC,0;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2553,'Dragon_Manteau','Dragon Manteau',4,20,NULL,1000,NULL,5,NULL,1,0xFFFFFFFE,2,2,4,NULL,0,1,0,'bonus bAgi,1; bonus bMdef,5;',NULL,NULL);
 REPLACE INTO `item_db` VALUES (2554,'Piece_Of_Angent_Skin','Nydhorgg\'s Shadow Garb',4,20,NULL,400,NULL,5,NULL,1,0xFFFFFFFE,2,2,4,NULL,90,1,0,'bonus2 bSubEle,Ele_Neutral,7; bonus2 bSubEle,Ele_Water,7; bonus2 bSubEle,Ele_Earth,7; bonus2 bSubEle,Ele_Fire,7; bonus2 bSubEle,Ele_Wind,7; bonus2 bSubEle,Ele_Poison,7; bonus2 bSubEle,Ele_Holy,7; bonus2 bSubEle,Ele_Dark,7; bonus2 bSubEle,Ele_Ghost,7; bonus2 bSubEle,Ele_Undead,7; bonus bMaxSP,(BaseLevel/3)+(getrefine()*10); bonus3 bSPDrainRate,10,1,0; bonus bMdef,3;',NULL,NULL);
 # Accessories
@@ -2880,7 +2880,7 @@ REPLACE INTO `item_db` VALUES (5671,'Drooping_Morocc_Minion','Drooping Morocc Mi
 #REPLACE INTO `item_db` VALUES (5679,'Engineer_Cap','Engineer Cap',4,20,NULL,200,NULL,2,NULL,1,0xFFFFFFFF,7,2,256,NULL,10,1,608,NULL,NULL,NULL);
 #REPLACE INTO `item_db` VALUES (5680,'Hawkeyes','Hawkeyes',4,20,NULL,100,NULL,0,NULL,0,0xFFFFFFFF,7,2,512,NULL,10,0,609,NULL,NULL,NULL);
 REPLACE INTO `item_db` VALUES (5681,'F_Ribbon_Green','Green Ribbon',4,800,NULL,100,NULL,1,NULL,0,0xFFFFFFFF,7,0,256,NULL,0,1,244,'bonus bMdef,3;',NULL,NULL);
-REPLACE INTO `item_db` VALUES (5682,'Triangle_Rune_Cap','Triangle Rune Cap',4,20,NULL,300,NULL,5,NULL,1,0xFFFFFFFF,7,2,256,NULL,1,1,610,'bonus bInt,1;',NULL,NULL);
+REPLACE INTO `item_db` VALUES (5682,'Triangle_Rune_Cap','Triangle Rune Cap',4,20,NULL,300,NULL,5,NULL,1,0xFFFFFFFF,7,2,256,NULL,1,1,610,'bonus bHealPower,2; if (getrefine() > 6) { bonus bMatk,10; bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",8,150,BF_MAGIC,0; } else { bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",7,150,BF_MAGIC,0; }',NULL,NULL);
 REPLACE INTO `item_db` VALUES (5683,'Majestic_Goat_Repl','Baphomet Horns',4,20,NULL,100,NULL,5,NULL,0,0xFFFFFFFF,7,2,256,NULL,1,1,41,NULL,NULL,NULL);
 REPLACE INTO `item_db` VALUES (5684,'Jewel_Crown_Repl','Ornate Crown',4,20,NULL,100,NULL,5,NULL,0,0xFFFFFFFF,7,2,256,NULL,1,1,88,NULL,NULL,NULL);
 REPLACE INTO `item_db` VALUES (5685,'Prontera_Army_Cap_Repl','Army Cap',4,20,NULL,100,NULL,5,NULL,0,0xFFFFFFFF,7,2,256,NULL,1,1,48,NULL,NULL,NULL);

+ 3 - 3
sql-files/item_db_re.sql

@@ -1641,7 +1641,7 @@ REPLACE INTO `item_db_re` VALUES (2528,'Wool_Scarf','Wool Scarf',4,20,NULL,500,N
 REPLACE INTO `item_db_re` VALUES (2529,'Rider_Insignia','Rider Insignia',4,20,NULL,500,NULL,13,NULL,0,0xFFFFFFFE,18,2,4,NULL,'55',1,0,'bonus bAgi,2;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2530,'Rider_Insignia_','Rider Insignia',4,20,NULL,500,NULL,13,NULL,1,0xFFFFFFFE,18,2,4,NULL,'55',1,0,'bonus bAgi,2;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2531,'Ulfhedinn','Ulfhedinn',4,20,NULL,700,NULL,13,NULL,1,0x000654E2,18,2,4,NULL,'70',1,0,'bonus3 bAutoSpellWhenHit,"NPC_STONESKIN",6,20;',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (2532,'Mithril_Magic_Cape','Mithril Magic Cape',4,20,NULL,400,NULL,8,NULL,1,0x00098B1C,18,2,4,NULL,'70',1,0,'bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",1,200,BF_MAGIC,0;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (2532,'Mithril_Magic_Cape','Mithril Magic Cape',4,20,NULL,400,NULL,8,NULL,1,0x00098B1C,18,2,4,NULL,'70',1,0,'bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",6,200,BF_MAGIC,0;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2533,'Freyja_Cape','Freyja Cape',4,0,NULL,200,NULL,10,NULL,0,0xFFFFFFFE,63,2,4,NULL,'0',0,0,'bonus2 bSubRace,RC_DemiHuman,15; bonus2 bSubRace,RC_Player,15;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2534,'Ruffler','Ruffler',4,20,NULL,0,NULL,10,NULL,0,0xFFFFFFFF,63,2,4,NULL,'0',0,0,'bonus2 bSubEle,Ele_Neutral,17; bonus bFlee,17;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2535,'Cloak_Of_Survival_C','Cloak Of Survival',4,1,NULL,0,NULL,5,NULL,0,0x00810204,63,2,4,NULL,'0',0,0,'bonus bVit,10; bonus bMdef,10;',NULL,NULL);
@@ -1661,7 +1661,7 @@ REPLACE INTO `item_db_re` VALUES (2548,'Muffler_C','Neo Muffler',4,0,NULL,0,NULL
 REPLACE INTO `item_db_re` VALUES (2549,'Krieger_Muffler1','Glorious Muffler',4,20,NULL,0,NULL,0,NULL,0,0xFFFFFFFE,63,2,4,NULL,'80',1,0,'bonus bMaxHPrate,5; bonus2 bSubRace,RC_DemiHuman,5; bonus2 bSubRace,RC_Player,5;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2550,'Fisher\'s_Muffler','Fisher\'s Muffler',4,20,NULL,200,NULL,0,NULL,0,0xFFFFFFFF,63,2,4,NULL,'0',1,0,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2551,'Rider_Insignia_M','Crest of the Rider',4,20,NULL,500,NULL,4,NULL,1,0xFFFFFFFE,18,2,4,NULL,'55',1,0,'bonus bAgi,2;',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (2552,'Mithril_Magic_Cape_M','Mithril Magic Manteau',4,20,NULL,400,NULL,3,NULL,1,0x00098B1C,18,2,4,NULL,'70',1,0,'bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",1,200,BF_MAGIC,0;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (2552,'Mithril_Magic_Cape_M','Mithril Magic Manteau',4,20,NULL,400,NULL,3,NULL,1,0x00098B1C,18,2,4,NULL,'70',1,0,'bonus bMdef,3; bonus5 bAutoSpellWhenHit,"NPC_ANTIMAGIC",6,200,BF_MAGIC,0;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2553,'Dragon_Manteau','Dragon Manteau',4,20,NULL,1000,NULL,14,NULL,1,0xFFFFFFFE,18,2,4,NULL,'0',1,0,'bonus bAgi,1; bonus bMdef,5;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2554,'Piece_Of_Angent_Skin','Nydhorgg\'s Shadow Garb',4,20,NULL,400,NULL,25,NULL,1,0xFFFFFFFE,18,2,4,NULL,'90',1,0,'bonus2 bSubEle,Ele_Neutral,7; bonus2 bSubEle,Ele_Water,7; bonus2 bSubEle,Ele_Earth,7; bonus2 bSubEle,Ele_Fire,7; bonus2 bSubEle,Ele_Wind,7; bonus2 bSubEle,Ele_Poison,7; bonus2 bSubEle,Ele_Holy,7; bonus2 bSubEle,Ele_Dark,7; bonus2 bSubEle,Ele_Ghost,7; bonus2 bSubEle,Ele_Undead,7; bonus bMaxSP,(BaseLevel/3)+(getrefine()*10); bonus3 bSPDrainRate,10,1,0; bonus bMdef,3;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (2555,'Freyja_SScarf7','Freyja Soul Scarf',4,20,NULL,400,NULL,4,NULL,0,0xFFFFFFFF,63,2,4,NULL,'20',0,0,'bonus bFlee,15; bonus2 bSubEle,Ele_Neutral,15;',NULL,NULL);
@@ -3608,7 +3608,7 @@ REPLACE INTO `item_db_re` VALUES (5678,'Notation_Hairband','Notation Hairband',4
 REPLACE INTO `item_db_re` VALUES (5679,'Engineer_Cap','Engineer Cap',4,20,NULL,200,NULL,2,NULL,1,0xFFFFFFFF,63,2,256,NULL,'10',1,608,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (5680,'Hawkeyes','Hawkeyes',4,20,NULL,100,NULL,0,NULL,0,0xFFFFFFFF,63,2,512,NULL,'10',0,609,'bonus bUnbreakableHelm,0;',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (5681,'F_Ribbon_Green','Green Ribbon',4,800,NULL,100,NULL,1,NULL,0,0xFFFFFFFF,63,0,256,NULL,'0',1,244,'bonus bMdef,3;',NULL,NULL);
-REPLACE INTO `item_db_re` VALUES (5682,'Triangle_Rune_Cap','Triangle Rune Cap',4,20,NULL,300,NULL,5,NULL,1,0xFFFFFFFF,63,2,256,NULL,'1',1,610,'bonus bInt,1;',NULL,NULL);
+REPLACE INTO `item_db_re` VALUES (5682,'Triangle_Rune_Cap','Triangle Rune Cap',4,20,NULL,300,NULL,5,NULL,1,0xFFFFFFFF,63,2,256,NULL,'1',1,610,'bonus bHealPower,2; if (getrefine() > 6) { bonus bMatk,10; bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",8,150,BF_MAGIC,0; } else { bonus5 bAutoSpellWhenHit,"NPC_MAGICMIRROR",7,150,BF_MAGIC,0; }',NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (5683,'Majestic_Goat_Repl','Baphomet Horns',4,20,NULL,100,NULL,5,NULL,0,0xFFFFFFFF,63,2,256,NULL,'1',1,41,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (5684,'Jewel_Crown_Repl','Ornate Crown',4,20,NULL,100,NULL,5,NULL,0,0xFFFFFFFF,63,2,256,NULL,'1',1,88,NULL,NULL,NULL);
 REPLACE INTO `item_db_re` VALUES (5685,'Prontera_Army_Cap_Repl','Army Cap',4,20,NULL,100,NULL,5,NULL,0,0xFFFFFFFF,63,2,256,NULL,'1',1,48,NULL,NULL,NULL);

+ 1 - 0
src/map/battle.c

@@ -7845,6 +7845,7 @@ static const struct _battle_data {
 	{ "fame_pharmacy_5",                    &battle_config.fame_pharmacy_5,                 3,      0,      INT_MAX,        },
 	{ "fame_pharmacy_7",                    &battle_config.fame_pharmacy_7,                 10,     0,      INT_MAX,        },
 	{ "fame_pharmacy_10",                   &battle_config.fame_pharmacy_10,                50,     0,      INT_MAX,        },
+	{ "mail_delay",                         &battle_config.mail_delay,                      1000,   1000,   INT_MAX,        },
 };
 #ifndef STATS_OPT_OUT
 /**

+ 1 - 0
src/map/battle.h

@@ -542,6 +542,7 @@ extern struct Battle_Config
 	int transcendent_status_points;
 	int taekwon_ranker_min_lv;
 	int revive_onwarp;
+	int mail_delay;
 
 	// Fame points
 	int fame_taekwon_mission;

+ 2 - 44
src/map/clif.c

@@ -14526,7 +14526,7 @@ void clif_parse_Mail_setattach(int fd, struct map_session_data *sd){
 		return;
 
 	flag = mail_setitem(sd, idx, amount);
-	clif_Mail_setattachment(fd,idx,flag);
+	clif_Mail_setattachment(fd,idx,!flag);
 }
 
 
@@ -14551,59 +14551,17 @@ void clif_parse_Mail_winopen(int fd, struct map_session_data *sd)
 /// 0248 <packet len>.W <recipient>.24B <title>.40B <body len>.B <body>.?B
 void clif_parse_Mail_send(int fd, struct map_session_data *sd)
 {
-	struct mail_message msg;
-	int body_len;
 	struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)];
 
 	if( !chrif_isconnected() )
 		return;
-	if( sd->state.trading )
-		return;
 
 	if( RFIFOW(fd,info->pos[0]) < 69 ) {
 		ShowWarning("Invalid Msg Len from account %d.\n", sd->status.account_id);
 		return;
 	}
 
-	if( DIFF_TICK(sd->cansendmail_tick, gettick()) > 0 ) {
-		clif_displaymessage(sd->fd,msg_txt(sd,675)); //"Cannot send mails too fast!!."
-		clif_Mail_send(fd, true); // fail
-		return;
-	}
-
-	body_len = RFIFOB(fd,info->pos[3]);
-
-	if (body_len > MAIL_BODY_LENGTH)
-		body_len = MAIL_BODY_LENGTH;
-
-	if( !mail_setattachment(sd, &msg) ) { // Invalid Append condition
-		clif_Mail_send(sd->fd, true); // fail
-		mail_removeitem(sd,0);
-		mail_removezeny(sd,0);
-		return;
-	}
-
-	msg.id = 0; // id will be assigned by charserver
-	msg.send_id = sd->status.char_id;
-	msg.dest_id = 0; // will attempt to resolve name
-	safestrncpy(msg.send_name, sd->status.name, NAME_LENGTH);
-	safestrncpy(msg.dest_name, (char*)RFIFOP(fd,info->pos[1]), NAME_LENGTH);
-	safestrncpy(msg.title, (char*)RFIFOP(fd,info->pos[2]), MAIL_TITLE_LENGTH);
-
-	if (msg.title[0] == '\0') {
-		return; // Message has no length and somehow client verification was skipped.
-	}
-
-	if (body_len)
-		safestrncpy(msg.body, (char*)RFIFOP(fd,info->pos[4]), body_len + 1);
-	else
-		memset(msg.body, 0x00, MAIL_BODY_LENGTH);
-
-	msg.timestamp = time(NULL);
-	if( !intif_Mail_send(sd->status.account_id, &msg) )
-		mail_deliveryfail(sd, &msg);
-
-	sd->cansendmail_tick = gettick() + 1000; // 1 Second flood Protection
+	mail_send(sd, (char*)RFIFOP(fd,info->pos[1]), (char*)RFIFOP(fd,info->pos[2]), (char*)RFIFOP(fd,info->pos[4]), RFIFOB(fd,info->pos[3]));
 }
 
 

+ 72 - 9
src/map/mail.c

@@ -3,6 +3,7 @@
 
 #include "../common/nullpo.h"
 #include "../common/showmsg.h"
+#include "../common/strlib.h"
 
 #include "mail.h"
 #include "atcommand.h"
@@ -10,6 +11,7 @@
 #include "clif.h"
 #include "pc.h"
 #include "log.h"
+#include "intif.h"
 
 #include <time.h>
 #include <string.h>
@@ -55,40 +57,46 @@ int mail_removezeny(struct map_session_data *sd, short flag)
 	return 1;
 }
 
-unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
+/**
+* Attempt to set item or zeny
+* @param sd
+* @param idx 0 - Zeny; >= 2 - Inventory item
+* @param amount
+* @return True if item/zeny can be set, False if failed
+*/
+bool mail_setitem(struct map_session_data *sd, short idx, unsigned short amount) {
 
 	if( pc_istrading(sd) )
-		return 1;
+		return false;
 
 	if( idx == 0 ) { // Zeny Transfer
 		if( amount < 0 || !pc_can_give_items(sd) )
-			return 1;
+			return false;
 
 		if( amount > sd->status.zeny )
 			amount = sd->status.zeny;
 
 		sd->mail.zeny = amount;
 		// clif_updatestatus(sd, SP_ZENY);
-		return 0;
+		return true;
 	} else { // Item Transfer
 		idx -= 2;
 		mail_removeitem(sd, 0);
 
 		if( idx < 0 || idx >= MAX_INVENTORY )
-			return 1;
+			return false;
 		if( amount < 0 || amount > sd->status.inventory[idx].amount )
-			return 1;
+			return false;
 		if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time
 			|| !itemdb_available(sd->status.inventory[idx].nameid)
 			|| !itemdb_canmail(&sd->status.inventory[idx],pc_get_group_level(sd))
 			|| (sd->status.inventory[idx].bound && !pc_can_give_bounded_items(sd)) )
-			return 1;
+			return false;
 
 		sd->mail.index = idx;
 		sd->mail.nameid = sd->status.inventory[idx].nameid;
 		sd->mail.amount = amount;
-
-		return 0;
+		return true;
 	}
 }
 
@@ -185,3 +193,58 @@ bool mail_invalid_operation(struct map_session_data *sd)
 
 	return false;
 }
+
+/**
+* Attempt to send mail
+* @param sd Sender
+* @param dest_name Destination name
+* @param title Mail title
+* @param body_msg Mail message
+* @param body_len Message's length
+*/
+void mail_send(struct map_session_data *sd, const char *dest_name, const char *title, const char *body_msg, int body_len) {
+	struct mail_message msg;
+
+	nullpo_retv(sd);
+
+	if( sd->state.trading )
+		return;
+
+	if( DIFF_TICK(sd->cansendmail_tick, gettick()) > 0 ) {
+		clif_displaymessage(sd->fd,msg_txt(sd,675)); //"Cannot send mails too fast!!."
+		clif_Mail_send(sd->fd, true); // fail
+		return;
+	}
+
+	if( body_len > MAIL_BODY_LENGTH )
+		body_len = MAIL_BODY_LENGTH;
+
+	if( !mail_setattachment(sd, &msg) ) { // Invalid Append condition
+		clif_Mail_send(sd->fd, true); // fail
+		mail_removeitem(sd,0);
+		mail_removezeny(sd,0);
+		return;
+	}
+
+	msg.id = 0; // id will be assigned by charserver
+	msg.send_id = sd->status.char_id;
+	msg.dest_id = 0; // will attempt to resolve name
+	safestrncpy(msg.send_name, sd->status.name, NAME_LENGTH);
+	safestrncpy(msg.dest_name, (char*)dest_name, NAME_LENGTH);
+	safestrncpy(msg.title, (char*)title, MAIL_TITLE_LENGTH);
+
+	if (msg.title[0] == '\0') {
+		return; // Message has no length and somehow client verification was skipped.
+	}
+
+	if (body_len)
+		safestrncpy(msg.body, (char*)body_msg, body_len + 1);
+	else
+		memset(msg.body, 0x00, MAIL_BODY_LENGTH);
+
+	msg.timestamp = time(NULL);
+	if( !intif_Mail_send(sd->status.account_id, &msg) )
+		mail_deliveryfail(sd, &msg);
+
+	sd->cansendmail_tick = gettick() + battle_config.mail_delay; // Flood Protection
+}

+ 2 - 1
src/map/mail.h

@@ -9,11 +9,12 @@
 void mail_clear(struct map_session_data *sd);
 int mail_removeitem(struct map_session_data *sd, short flag);
 int mail_removezeny(struct map_session_data *sd, short flag);
-unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount);
+bool mail_setitem(struct map_session_data *sd, short idx, unsigned short amount);
 bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg);
 void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item);
 int mail_openmail(struct map_session_data *sd);
 void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg);
 bool mail_invalid_operation(struct map_session_data *sd);
+void mail_send(struct map_session_data *sd, const char *dest_name, const char *title, const char *body_msg, int body_len);
 
 #endif /* _MAIL_H_ */

+ 59 - 55
src/map/script.c

@@ -6421,7 +6421,7 @@ BUILDIN_FUNC(checkweight2){
  *------------------------------------------*/
 BUILDIN_FUNC(getitem)
 {
-	int amount,get_count,i;
+	int amount, get_count, i;
 	unsigned short nameid;
 	struct item it;
 	TBL_PC *sd;
@@ -6432,49 +6432,49 @@ BUILDIN_FUNC(getitem)
 	data=script_getdata(st,2);
 	get_val(st,data);
 	if( data_isstring(data) ) {// "<item name>"
-		const char *name=conv_str(st,data);
+		const char *name = conv_str(st,data);
 		struct item_data *item_data = itemdb_searchname(name);
 		if( item_data == NULL ){
 			ShowError("buildin_getitem: Nonexistant item %s requested.\n", name);
-			return 1; //No item created.
+			return SCRIPT_CMD_FAILURE; //No item created.
 		}
-		nameid=item_data->nameid;
+		nameid = item_data->nameid;
 	} else if( data_isint(data) ) {// <item id>
-		nameid=conv_num(st,data);
+		nameid = conv_num(st,data);
 		if( !itemdb_exists(nameid) ){
 			ShowError("buildin_getitem: Nonexistant item %d requested.\n", nameid);
-			return 1; //No item created.
+			return SCRIPT_CMD_FAILURE; //No item created.
 		}
 	} else {
 		ShowError("buildin_getitem: invalid data type for argument #1 (%d).", data->type);
-		return 1;
+		return SCRIPT_CMD_FAILURE;
 	}
 
 	// <amount>
-	if( (amount=script_getnum(st,3)) <= 0)
-		return 0; //return if amount <=0, skip the useles iteration
+	if( (amount = script_getnum(st,3)) <= 0)
+		return SCRIPT_CMD_SUCCESS; //return if amount <=0, skip the useles iteration
 
 	memset(&it,0,sizeof(it));
-	it.nameid=nameid;
-	it.identify=itemdb_isidentified(nameid);
+	it.nameid = nameid;
+	it.identify = 1;
 
 	if( !strcmp(command,"getitembound") ) {
 		char bound = script_getnum(st,4);
 		if( bound > BOUND_NONE && bound < BOUND_MAX ) {
 			it.bound = bound;
 			if( script_hasdata(st,5) )
-				sd=map_id2sd(script_getnum(st,5));
+				sd = map_id2sd(script_getnum(st,5));
 			else
-				sd=script_rid2sd(st); // Attached player
+				sd = script_rid2sd(st); // Attached player
 		}
 		else { //Not a correct bound type
 			ShowError("script_getitembound: Not a correct bound type! Type=%d\n",bound);
 			return SCRIPT_CMD_FAILURE;
 		}
 	} else if( script_hasdata(st,4) )
-		sd=map_id2sd(script_getnum(st,4)); // <Account ID>
+		sd = map_id2sd(script_getnum(st,4)); // <Account ID>
 	else
-		sd=script_rid2sd(st); // Attached player
+		sd = script_rid2sd(st); // Attached player
 
 	if( sd == NULL ) // no target
 		return SCRIPT_CMD_SUCCESS;
@@ -6510,7 +6510,7 @@ BUILDIN_FUNC(getitem2)
 	unsigned short nameid;
 	int iden, ref, attr, c1, c2, c3, c4;
 	char bound = BOUND_NONE;
-	struct item_data *item_data;
+	struct item_data *item_data = NULL;
 	struct item item_tmp;
 	unsigned char flag = 0;
 	TBL_PC *sd;
@@ -6521,49 +6521,50 @@ BUILDIN_FUNC(getitem2)
 		bound = script_getnum(st,11);
 		if( bound > BOUND_NONE && bound < BOUND_MAX ) {
 			if( script_hasdata(st,12) )
-				sd=map_id2sd(script_getnum(st,12));
+				sd = map_id2sd(script_getnum(st,12));
 			else
-				sd=script_rid2sd(st); // Attached player
+				sd = script_rid2sd(st); // Attached player
 		}
 		else {
 			ShowError("script_getitembound2: Not a correct bound type! Type=%d\n",bound);
 			return SCRIPT_CMD_FAILURE;
 		}
 	} else if( script_hasdata(st,11) )
-		sd=map_id2sd(script_getnum(st,11)); // <Account ID>
+		sd = map_id2sd(script_getnum(st,11)); // <Account ID>
 	else
-		sd=script_rid2sd(st); // Attached player
+		sd = script_rid2sd(st); // Attached player
 
 	if( sd == NULL ) // no target
 		return SCRIPT_CMD_SUCCESS;
 
-	data=script_getdata(st,2);
+	data = script_getdata(st,2);
 	get_val(st,data);
 	if( data_isstring(data) ) {
-		const char *name=conv_str(st,data);
-		struct item_data *item_data_tmp = itemdb_searchname(name);
-		if( item_data_tmp )
-			nameid=item_data_tmp->nameid;
-		else
-			nameid=UNKNOWN_ITEM_ID;
-	} else
-		nameid=conv_num(st,data);
+		const char *name = conv_str(st,data);
+		if( (item_data = itemdb_searchname(name)) == NULL ){
+			ShowError("buildin_getitem2: Nonexistant item %s requested.\n", name);
+			return SCRIPT_CMD_FAILURE; //No item created.
+		}
+	} else {
+		nameid = conv_num(st,data);
+		if( !(item_data == itemdb_exists(nameid)) ){
+			ShowError("buildin_getitem2: Nonexistant item %d requested.\n", nameid);
+			return SCRIPT_CMD_FAILURE; //No item created.
+		}
+	}
 
-	amount=script_getnum(st,3);
-	iden=script_getnum(st,4);
-	ref=script_getnum(st,5);
-	attr=script_getnum(st,6);
-	c1=(short)script_getnum(st,7);
-	c2=(short)script_getnum(st,8);
-	c3=(short)script_getnum(st,9);
-	c4=(short)script_getnum(st,10);
+	amount = script_getnum(st,3);
+	iden = script_getnum(st,4);
+	ref = script_getnum(st,5);
+	attr = script_getnum(st,6);
+	c1 = (short)script_getnum(st,7);
+	c2 = (short)script_getnum(st,8);
+	c3 = (short)script_getnum(st,9);
+	c4 = (short)script_getnum(st,10);
 
-	if(nameid > 0) {
+	if(item_data) {
 		memset(&item_tmp,0,sizeof(item_tmp));
-		item_data=itemdb_exists(nameid);
-		if (item_data == NULL)
-			return -1;
-		if(item_data->type==IT_WEAPON || item_data->type==IT_ARMOR || item_data->type==IT_SHADOWGEAR ) {
+		if(item_data->type == IT_WEAPON || item_data->type == IT_ARMOR || item_data->type == IT_SHADOWGEAR ) {
 			if(ref > MAX_REFINE) ref = MAX_REFINE;
 		}
 		else if(item_data->type==IT_PETEGG) {
@@ -6575,15 +6576,15 @@ BUILDIN_FUNC(getitem2)
 			ref = attr = 0;
 		}
 
-		item_tmp.nameid=nameid;
-		item_tmp.identify=iden;
-		item_tmp.refine=ref;
-		item_tmp.attribute=attr;
-		item_tmp.card[0]=(short)c1;
-		item_tmp.card[1]=(short)c2;
-		item_tmp.card[2]=(short)c3;
-		item_tmp.card[3]=(short)c4;
-		item_tmp.bound=bound;
+		item_tmp.nameid = nameid;
+		item_tmp.identify = iden;
+		item_tmp.refine = ref;
+		item_tmp.attribute = attr;
+		item_tmp.card[0] = (short)c1;
+		item_tmp.card[1] = (short)c2;
+		item_tmp.card[2] = (short)c3;
+		item_tmp.card[3] = (short)c4;
+		item_tmp.bound = bound;
 
 		//Check if it's stackable.
 		if (!itemdb_isstackable(nameid))
@@ -18797,7 +18798,7 @@ BUILDIN_FUNC(disable_command) {
 }
 
 /** Get the information of the members of a guild by type.
- * getguildmember  <guild_id>{,<type>};
+ * getguildmember <guild_id>{,<type>};
  * @param guild_id: ID of guild
  * @param type: Type of option (optional)
  */
@@ -18834,6 +18835,7 @@ BUILDIN_FUNC(getguildmember)
 }
 
 /** Adds spirit ball to player for 'duration' in milisecond
+* addspiritball <count>,<duration>{,<char_id>};
 * @param count How many spirit ball will be added
 * @param duration How long spiritball is active until it disappears
 * @param char_id Target player (Optional)
@@ -18848,7 +18850,7 @@ BUILDIN_FUNC(addspiritball) {
 		return SCRIPT_CMD_SUCCESS;
 
 	if (script_hasdata(st,4)) {
-		if (script_isstring(st,4))
+		if (!script_isstring(st,4))
 			sd = map_charid2sd(script_getnum(st,4));
 		else
 			sd = map_nick2sd(script_getstr(st,4));
@@ -18864,6 +18866,7 @@ BUILDIN_FUNC(addspiritball) {
 }
 
 /** Deletes the spirit ball(s) from player
+* delspiritball <count>{,<char_id>};
 * @param count How many spirit ball will be deleted
 * @param char_id Target player (Optional)
 * @author [Cydh]
@@ -18876,7 +18879,7 @@ BUILDIN_FUNC(delspiritball) {
 		count = 1;
 	
 	if (script_hasdata(st,3)) {
-		if (script_isstring(st,3))
+		if (!script_isstring(st,3))
 			sd = map_charid2sd(script_getnum(st,3));
 		else
 			sd = map_nick2sd(script_getstr(st,3));
@@ -18891,6 +18894,7 @@ BUILDIN_FUNC(delspiritball) {
 }
 
 /** Counts the spirit ball that player has
+* countspiritball {,<char_id>};
 * @param char_id Target player (Optional)
 * @author [Cydh]
 */
@@ -18898,7 +18902,7 @@ BUILDIN_FUNC(countspiritball) {
 	struct map_session_data *sd;
 
 	if (script_hasdata(st,2)) {
-		if (script_isstring(st,2))
+		if (!script_isstring(st,2))
 			sd = map_charid2sd(script_getnum(st,2));
 		else
 			sd = map_nick2sd(script_getstr(st,2));

+ 10 - 4
src/map/status.c

@@ -5598,7 +5598,7 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc,
 		return 1;
 
 	if(sc->data[SC_ARMORCHANGE])
-		def += sc->data[SC_ARMORCHANGE]->val2;
+		def += (def * sc->data[SC_ARMORCHANGE]->val2) / 100;
 	if(sc->data[SC_DRUMBATTLE])
 		def += sc->data[SC_DRUMBATTLE]->val3;
 #ifndef RENEWAL
@@ -5763,7 +5763,7 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc,
 		return 1;
 
 	if(sc->data[SC_ARMORCHANGE])
-		mdef += sc->data[SC_ARMORCHANGE]->val3;
+		mdef += (mdef * sc->data[SC_ARMORCHANGE]->val3) / 100;
 	if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3)
 		mdef += 50;
 	if(sc->data[SC_ENDURE]) // It has been confirmed that Eddga card grants 1 MDEF, not 0, not 10, but 1.
@@ -9061,6 +9061,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			val2 = 20*val1; // Heal effectiveness decrease
 			break;
 		case SC_MAGICMIRROR:
+			// Level 1 ~ 5 & 6 ~ 10 has different duration
+			// Level 6 ~ 10 use effect of level 1 ~ 5
+			val1 %= 5;
 		case SC_SLOWCAST:
 			val2 = 20*val1; // Magic reflection/cast rate
 			break;
@@ -9073,8 +9076,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 				val2 = 20;
 				val3 =-20;
 			}
-			val2*=val1; // 20% per level
-			val3*=val1;
+			// Level 1 ~ 5 & 6 ~ 10 has different duration
+			// Level 6 ~ 10 use effect of level 1 ~ 5
+			val1 %= 5;
+			val2 *= val1; // 20% per level
+			val3 *= val1;
 			break;
 		case SC_EXPBOOST:
 		case SC_JEXPBOOST:

+ 1 - 1
src/map/vending.c

@@ -508,7 +508,7 @@ void vending_reopen( struct map_session_data* sd ){
 			}
 
 			*index = entry->index + 2;
-			*amount = entry->amount;
+			*amount = itemdb_isstackable(sd->status.cart[entry->index].id) ? entry->amount : 1;
 			*value = entry->price;
 
 			p += 8;