Browse Source

Bug Fixes:
* Fixed #445, fixed Health Conversion cast time & cooldown.
* Fixed #404:
* Added new item bonus `bonus2 bSubDefEle,e,x;` to reduce x% damage received from monster with element e.
* Fixed item script for item 4442 until 4449.
* Added config `subdef_ele` in conf/battle/items.conf to change bSubDefEle behavior.
* Follow up 111eb0c1c1a048219cb7c908cf8be0b0a24afdde, added state requirement for skill 'elementalspirit2' for skill that need summoned Elemental Spirit and removes it.
* Fixed monster that `is_infinite_defense` ignored Safety Wall && Pneuma effect.
* Also fixed bugreport:6741.
* But the effects are still ignored for Emperium when WOE time, and BG monsters in BG Arena (like previous).
* Item Updates:
* Transformation chance to becomes Atroce as combo of Fidelity_Necklace (2959) and Black_Shiba_Inu_Hat (18756).
* Transformation chance to becomes Eddga as bonus of King_Tiger_Doll_Hat (5497) and W_King_Tiger_Doll_Hat (18856).
* Cooldown reduction for skill WL_RECOGNIZEDSPELL in Naqsh (2904).
* Fixed bonus damage for WS_CARTTERMINATION as combo of Gigant_Helm (19021) and Giant_Axe (1387).
* Changed `bonus3 bSPDrainRate` to `bonus2 bSPGainAttackRate` and `bonus3 bHPDrainRate` to `bonus2 bHPGainAttackRate` in db/re/pet_db.txt.
* Corrected calculation in `battle_calc_cardfix` for BF_MISC, it's should be `if( cardfix != 1000 )`!.
* Source documentation updates for `battle_calc_cardfix`.
* Typo at MOBID_GUARIDAN1 and MOBID_GUARIDAN2.

Signed-off-by: Cydh Ramdh <cydh@pservero.com>

Cydh Ramdh 10 năm trước cách đây
mục cha
commit
5a4cd7426e

+ 1 - 0
db/const.txt

@@ -637,6 +637,7 @@ bSPGainAttack	2080
 bHPGainAttackRate	2081
 bSPGainAttackRate	2082
 bSubSkill	2083
+bSubDefEle	2084
 
 EQI_HEAD_TOP	1
 EQI_ARMOR	2

+ 2 - 1
db/pre-re/skill_require_db.txt

@@ -20,6 +20,7 @@
 //  ridingwarg = Requires to ride a Warg
 //  mado = Requires to have an active mado
 //  elementalspirit = Requires to have an Elemental Spirit summoned.
+//  elementalspirit2 = Requires to have an Elemental Spirit summoned, and will be removed.
 //  peco = Requires riding a peco
 //
 // 'RequiredStatuses'
@@ -948,7 +949,7 @@
 5005,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//RK_LUXANIMA
 5006,0,0,60:70:80:90:100,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0				//NC_MAGMA_ERUPTION
 5007,0,0,200:230:260:290:320,0,0,0,13:14,0,0,none,0,0,6144,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0		//WM_FRIGG_SONG
-5008,0,0,120,0,0,0,99,0,0,elementalspirit,0,0,717,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0					//SO_ELEMENTAL_SHIELD
+5008,0,0,120,0,0,0,99,0,0,elementalspirit2,0,0,717,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0					//SO_ELEMENTAL_SHIELD
 5009,0,0,65,0,0,0,99,0,0,none,0,5:5:4:4:3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0						//SR_FLASHCOMBO
 5010,0,0,30:26:22:18:14,0,0,0,99,0,0,none,0,0,7940,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0				//SC_ESCAPE
 5011,0,0,30:60:90:120:150,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0				//AB_OFFERTORIUM

+ 2 - 2
db/re/item_combo_db.txt

@@ -221,7 +221,7 @@
 2826:2827:5577,{ autobonus "{ bonus bAspdRate,2; }",50,10000,0,"{ specialeffect2 EF_POTION_BERSERK; }"; bonus bMaxHP,BaseLevel*15; bonus bMaxSP,(BaseLevel*12)/10; bonus2 bAddClass,Class_All,3; }
 2855:5360,{ bonus bCritAtkRate,10; if( getequiprefinerycnt(EQI_HEAD_TOP)>5 ) bonus bCritical,50; }
 2957:2958,{ bonus4 bAutoSpell,"MO_EXTREMITYFIST",1,3,1; bonus3 bAutoSpell,"PR_LEXAETERNA",1,20; bonus3 bAutoSpell,"AS_SONICBLOW",5,50; bonus3 bAutoSpell,"MO_INVESTIGATE",5,20; bonus3 bAutoSpell,"ASC_METEORASSAULT",2,50; }
-2959:18756,{ .@r = 3+(3*getequiprefinerycnt(EQI_HEAD_TOP)); autobonus "{ /* Active_Montransform ATROCE, SetDisappearSPAmount COMBIITEM_Shiba_Set 1 5 */ bonus bBaseAtk,30; }",.@r,5000,0,"{ specialeffect2 EF_POTION_BERSERK; }"; autobonus2 "{ /* Active_Montransform ATROCE, SetDisappearSPAmount COMBIITEM_Shiba_Set 1 5 */ bonus bBaseAtk,30; }",.@r,5000,BF_WEAPON,"{ specialeffect2 EF_POTION_BERSERK; }"; }
+2959:18756,{ .@r = 3+(3*getequiprefinerycnt(EQI_HEAD_TOP)); autobonus "{ bonus2 bSPLossRate,5,1000; bonus bBaseAtk,30; }",.@r,5000,BF_WEAPON,"{ transform 1785,5000; specialeffect2 EF_POTION_BERSERK; }"; autobonus2 "{ bonus2 bSPLossRate,5,1000; bonus bBaseAtk,30; }",.@r,5000,BF_WEAPON,"{ transform 1785,5000; specialeffect2 EF_POTION_BERSERK; }"; }
 2966:2967:13092,{ bonus bBaseAtk,-(getequiprefinerycnt(EQI_HAND_R)*10); }
 2966:2967:16026,{ bonus bBaseAtk,-(getequiprefinerycnt(EQI_HAND_R)*5); }
 2966:2967:18821,{ bonus2 bAddClass,Class_All, -(getequiprefinerycnt(EQI_HEAD_TOP)/2); }
@@ -350,7 +350,7 @@
 19020:1619,{ .@r = getequiprefinerycnt(EQI_HEAD_TOP); bonus bMatk,.@r; if (.@r >= 10) { autobonus "{ bonus bVariableCastrate,-50; }",100,5000,BF_MAGIC; /* Confirm: Success rate? */ } }
 19020:1620,{ .@r = getequiprefinerycnt(EQI_HEAD_TOP); bonus bMatk,.@r; if (.@r >= 10) { autobonus "{ bonus bVariableCastrate,-50; }",100,5000,BF_MAGIC; /* Confirm: Success rate? */ } }
 19021:2160,{ bonus2 bSubSize,Size_Large,5+(getequiprefinerycnt(EQI_HAND_L)*2); }
-19021:1387,{ /* What is 'High Speed Cart Ram'? +15%+(1387_refine*5%) */ }
+19021:1387,{ bonus2 bSkillAtk,"WS_CARTTERMINATION",15+(getequiprefinerycnt(EQI_HAND_R))*5; }
 19021:1490,{ bonus2 bSkillAtk,"LK_SPIRALPIERCE",getequiprefinerycnt(EQI_HAND_R)*5; .@lv = getskilllv("LK_SPIRALPIERCE"); bonus4 bAutoSpellOnSkill,"LK_JOINTBEAT","LK_SPIRALPIERCE",(.@lv ? .@lv : 1),50+(getskilllv("LK_JOINTBEAT")*10); /* Confirm: Success rate */ }
 19026:15138,{ bonus2 bSubRace,RC_Fish,(10+getequiprefinerycnt(EQI_ARMOR)); bonus bUnbreakableArmor,1; }
 19026:20756,{ .@r = getequiprefinerycnt(EQI_GARMENT); bonus2 bSPGainRace,RC_Fish,10; bonus3 bAddMonsterDropItem,551,RC_Fish,(5+.@r); bonus2 bAddItemHealRate,551,5; bonus bHPrecovRate,(5+.@r); }

+ 10 - 10
db/re/item_db.txt

@@ -1986,7 +1986,7 @@
 2901,Morrigane's_Pendant_,Morrigane's Pendant,4,30000,,200,,0,,1,0xFFFFFFFE,63,2,136,,61,0,0,{ bonus bStr,2; },{},{}
 2902,Morpheus's_Ring_,Morpheus's Ring,4,30000,,100,,0,,1,0xFFFFFFFE,63,2,136,,33,0,0,{ bonus bInt,1; },{},{}
 2903,Morpheus's_Armlet_,Morpheus's Armlet,4,30000,,100,,0,,1,0xFFFFFFFE,63,2,136,,33,0,0,{ bonus bInt,1; },{},{}
-2904,Naqsh,Naqsi,4,0,,0,,0,,0,0xFFFFFFFF,63,2,136,,0,0,0,{ skill "BS_MAXIMIZE",5; skill "BS_WEAPONPERFECT",5; skill "WL_RECOGNIZEDSPELL",5; skill "ECL_SNOWFLIP",1; skill "ECL_PEONYMAMY",1; skill "ECL_SADAGUI",1; skill "ECL_SEQUOIADUST",1; /* bonus2 bSkillDelay,"WL_RECOGNIZEDSPELL",-180000; */ bonus bDelayRate,-100; },{},{}
+2904,Naqsh,Naqsi,4,0,,0,,0,,0,0xFFFFFFFF,63,2,136,,0,0,0,{ skill "BS_MAXIMIZE",5; skill "BS_WEAPONPERFECT",5; skill "WL_RECOGNIZEDSPELL",5; skill "ECL_SNOWFLIP",1; skill "ECL_PEONYMAMY",1; skill "ECL_SADAGUI",1; skill "ECL_SEQUOIADUST",1; bonus2 bSkillCooldown,"WL_RECOGNIZEDSPELL",-180000; bonus bDelayRate,-100; },{},{}
 2905,Super_Ora_Ora,Super Ora Ora,4,0,,1000,,0,,0,0xFFFFFFFF,63,2,136,,0,0,0,{},{},{}
 2906,Happy_Gauntlet,Happy Gauntlet,4,20,,1000,,3,,1,0xFFFFFFFF,63,2,136,,70,0,0,{ bonus bMdef,3; },{},{}
 2907,Buwaya_Tattoo,Bawaya Agimat Tattoo,4,20,,100,,0,,0,0xFFFFFFFF,63,2,136,,1,0,0,{ bonus bMatkRate,7; bonus bVariableCastrate,-7; },{},{}
@@ -2495,13 +2495,13 @@
 4439,Flame_Skull_Card,Flame Skull Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bResEff,Eff_Blind,3000; bonus2 bResEff,Eff_Stun,3000; bonus2 bResEff,Eff_Curse,3000; bonus2 bResEff,Eff_Stone,3000; bonus2 bAddEffWhenHit,Eff_Blind,500; bonus2 bAddEffWhenHit,Eff_Stun,500; bonus2 bAddEffWhenHit,Eff_Curse,500; bonus2 bAddEffWhenHit,Eff_Stone,500; },{},{}
 4440,Necromancer_Card,Necromancer Card,6,20,,10,,,,,,,,2,,,,,{ if(getiteminfo(getequipid(EQI_HAND_R),11)==10) { bonus bInt,1; bonus2 bIgnoreMdefClassRate,Class_Normal,2; bonus2 bIgnoreMdefClassRate,Class_Boss,2; } },{},{}
 4441,Fallen_Bishop_Card,Fallen Bishop Hibram Card,6,20,,10,,,,,,,,64,,,,,{ bonus bMatkRate,10; bonus bMaxSPrate,-50; bonus2 bMagicAddRace,RC_Angel,50; bonus2 bMagicAddRace,RC_DemiHuman,50; bonus2 bMagicAddRace,RC_Player,50; },{},{}
-4442,Tatacho_Card,Tatacho Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubEle,Ele_Neutral,20; bonus2 bAddEle,Ele_Neutral,5; },{},{}
-4443,Aqua_Elemental_Card,Aqua Elemental Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubEle,Ele_Water,20; bonus2 bAddEle,Ele_Water,5; },{},{}
-4444,Draco_Card,Draco Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubEle,Ele_Earth,20; bonus2 bAddEle,Ele_Earth,5; },{},{}
-4445,Luciola_Vespa_Card,Luciola Vespa Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubEle,Ele_Wind,20; bonus2 bAddEle,Ele_Wind,5; },{},{}
-4447,Centipede_Card,Centipede Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubEle,Ele_Poison,20; bonus2 bAddEle,Ele_Poison,5; },{},{}
-4448,Cornus_Card,Cornus Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubEle,Ele_Holy,20; bonus2 bAddEle,Ele_Holy,5; },{},{}
-4449,Dark_Shadow_Card,Dark Shadow Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubEle,Ele_Dark,20; bonus2 bAddEle,Ele_Dark,5; },{},{}
+4442,Tatacho_Card,Tatacho Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubDefEle,Ele_Neutral,20; bonus2 bAddEle,Ele_Neutral,5; },{},{}
+4443,Aqua_Elemental_Card,Aqua Elemental Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubDefEle,Ele_Water,20; bonus2 bAddEle,Ele_Water,5; },{},{}
+4444,Draco_Card,Draco Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubDefEle,Ele_Earth,20; bonus2 bAddEle,Ele_Earth,5; },{},{}
+4445,Luciola_Vespa_Card,Luciola Vespa Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubDefEle,Ele_Wind,20; bonus2 bAddEle,Ele_Wind,5; },{},{}
+4447,Centipede_Card,Centipede Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubDefEle,Ele_Poison,20; bonus2 bAddEle,Ele_Poison,5; },{},{}
+4448,Cornus_Card,Cornus Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubDefEle,Ele_Holy,20; bonus2 bAddEle,Ele_Holy,5; },{},{}
+4449,Dark_Shadow_Card,Dark Shadow Card,6,20,,10,,,,,,,,32,,,,,{ bonus2 bSubDefEle,Ele_Dark,20; bonus2 bAddEle,Ele_Dark,5; },{},{}
 4450,Banshee_Master_Card,Banshee Master Card,6,20,,10,,,,,,,,16,,,,,{ bonus bInt,1; bonus bMatk,10; },{},{}
 4451,Ant_Buyanne_Card,Entweihen Crothen Card,6,20,,10,,,,,,,,16,,,,,{ bonus bMatk,100; },{},{}
 4452,Centipede_Larva_Card,Centipede Larva Card,6,20,,10,,,,,,,,2,,,,,{ bonus bInt,1; bonus bMatk,3; },{},{}
@@ -3411,7 +3411,7 @@
 5494,Spinx_Helm_I,Sphinx Hat,4,0,,0,,5,,0,0x00004082,63,2,257,,0,0,137,{ bonus bStr,5; },{},{}
 5495,Power_Of_Thor,Power Of Thor,4,20,,100,,6,,1,0xFFFFFFFF,63,2,256,,0,1,493,{ bonus bInt,1; bonus bDex,1; bonus bMdef,3; bonus bFlee,5; },{},{}
 5496,Dice_Hat,Dice Hat,4,20,,300,,3,,0,0xFFFFFFFF,63,2,256,,50,0,494,{ bonus bLuk,4; },{},{}
-5497,King_Tiger_Doll_Hat,King Tiger Doll Hat,4,20,,400,,6,,1,0xFFFFFFFE,63,2,256,,1,1,495,{ bonus bStr,2; bonus bDex,2; bonus2 bAddRace,RC_Brute,10; bonus2 bMagicAddRace,RC_Brute,10; /*Need more info*/ },{},{}
+5497,King_Tiger_Doll_Hat,King Tiger Doll Hat,4,20,,400,,6,,1,0xFFFFFFFE,63,2,256,,1,1,495,{ bonus bStr,2; bonus bDex,2; bonus2 bAddRace,RC_Brute,10; bonus2 bMagicAddRace,RC_Brute,10; .@r = getrefine(); autobonus "{ bonus2 bSPLossRate,5,1000; bonus bBaseAtk,25*.@r; }",3*.@r,3000,BF_NORMAL,"{ transform 1115,3000; specialeffect2 EF_POTION_BERSERK; }"; autobonus2 "{ bonus2 bSPLossRate,5,1000; bonus bBaseAtk,25*.@r; }",.@r,3000,BF_NORMAL,"{ transform 1115,3000; specialeffect2 EF_POTION_BERSERK; }"; },{},{}
 5498,Wondering_Wolf_Helm,Wandering Wolf Helm,4,20,,600,,5,,1,0xFFFFFFFE,63,2,768,,1,0,490,{ bonus bAgi,5; bonus bFlee,10; bonus2 bIgnoreDefRaceRate,RC_DemiHuman,10; bonus2 bIgnoreDefRaceRate,RC_Brute,10; if(getrefine()>=7){ bonus2 bAddEff,Eff_Bleeding,10; } if(getrefine()>=9){ bonus3 bAutoSpellWhenHit,"MC_LOUD",1,1; } },{},{}
 5499,Pizza_Hat,Pizza Hat,4,20,,600,,0,,0,0xFFFFFFFF,63,2,256,,0,0,487,{ skill "SM_PROVOKE",1; },{},{}
 5500,Icecream_Hat,Icecream Hat,4,0,,300,,6,,0,0xFFFFFFFF,63,2,256,,30,1,488,{ bonus bMdef,3; skill "MG_FROSTDIVER",3; },{},{}
@@ -9334,7 +9334,7 @@
 18850,Polar_Bear_Cap,Polar Bear Cap,4,20,,300,,7,,0,0xFFFFFFFF,63,2,256,,1,0,966,{ bonus bUnbreakableHelm,0; bonus bDex,1; bonus bAgi,1; bonus bMdef,3; bonus bHPrecovRate,5; bonus bSPrecovRate,3; bonus2 bAddMonsterDropItem,12354,100; },{},{}
 18851,C_Polar_Bear_Cap,Costume Polar Bear Cap,4,20,,0,,0,,0,0xFFFFFFFF,63,2,1024,,1,1,966,{},{},{}
 18855,Aviator_Hat,Aviator Hat,4,10,,100,,10,,0,0xFFFFFFFF,63,2,256,,1,1,972,{ bonus bAgi,3; bonus bInt,3; autobonus "{ bonus bAtkEle,Ele_Wind; }",500,180,BF_NORMAL; },{},{}
-18856,W_King_Tiger_Doll_Hat,W King Tiger Doll Hat,4,10,,0,,10,,0,0xFFFFFFFF,63,2,256,,1,1,973,{ bonus bStr,2; bonus bDex,2; bonus2 bAddRace,RC_Brute,10; /*Transform to be Eddga when attacking or receiving damage. Loss 5 SP each secs, gain 'brutal' power. Success chance by refine value.*/ },{},{}
+18856,W_King_Tiger_Doll_Hat,W King Tiger Doll Hat,4,10,,0,,10,,0,0xFFFFFFFF,63,2,256,,1,1,973,{ bonus bStr,2; bonus bDex,2; bonus2 bAddRace,RC_Brute,10; .@r = getrefine(); autobonus "{ bonus2 bSPLossRate,5,1000; bonus bBaseAtk,25*.@r; }",3*.@r,3000,BF_NORMAL,"{ transform 1115,3000; specialeffect2 EF_POTION_BERSERK; }"; autobonus2 "{ bonus2 bSPLossRate,5,1000; bonus bBaseAtk,25*.@r; }",.@r,3000,BF_NORMAL,"{ transform 1115,3000; specialeffect2 EF_POTION_BERSERK; }"; },{},{}
 18857,Curupira_Hat,Curupira Hat,4,10,,100,,20,,0,0xFFFFFFFF,63,2,256,,1,1,974,{ bonus bDex,3; bonus2 bAddEffWhenHit,Eff_Confusion,500; },{},{}
 18859,Angeling_Bubble,Angeling Bubble,4,10,,50,,5,,0,0xFFFFFFFF,63,2,1,,1,,975,{ bonus bDex,1; bonus bMatkRate,2; bonus bMaxHP,100; },{},{}
 18861,Zaha_Doll_J_Hat,Zaha Doll J Hat,4,10,,100,,,,0,0xFFFFFFFF,63,2,256,,50,1,461,{ bonus bHealPower,15; bonus bUseSPrate,15; },{},{}

+ 2 - 2
db/re/pet_db.txt

@@ -78,8 +78,8 @@
 1148,MEDUSA,Medusa,12368,9050,10032,6108,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus bVit,1; bonus2 bResEff,Eff_Stone,500; }
 1179,WHISPER,Whisper,12363,9045,10027,6100,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bFlee,7; bonus bDef,-3; }
 1299,GOBLIN_LEADER,Goblin Leader,12364,9046,10028,6104,80,60,10,100,250,20,50,150,0,0,300,300,800,{},{ bonus2 bAddRace,RC_DemiHuman,3; }
-1370,SUCCUBUS,Succubus,12373,9055,10037,6113,80,60,10,100,250,20,200,150,0,0,300,300,800,{ /*bonus3 bHPDrainRate,10,5,0;*/ },{ /*bonus3 bHPDrainRate,30,5,0;*/ bonus bMaxHPrate,1; }
-1374,INCUBUS,Incubus,12370,9052,10034,6110,80,60,10,100,250,20,50,150,0,0,300,300,800,{ bonus bMaxSPRate,3; bonus3 bSPDrainRate,10,1,0; },{ bonus bMaxSPRate,5; bonus3 bSPDrainRate,30,1,0; }
+1370,SUCCUBUS,Succubus,12373,9055,10037,6113,80,60,10,100,250,20,200,150,0,0,300,300,800,{ bonus2 bHPGainAttackRate,10,5; },{ bonus2 bHPGainAttackRate,30,5; bonus bMaxHPrate,1; }
+1374,INCUBUS,Incubus,12370,9052,10034,6110,80,60,10,100,250,20,50,150,0,0,300,300,800,{ bonus bMaxSPRate,3; bonus2 bSPGainAttackRate,10,1; },{ bonus bMaxSPRate,5; bonus2 bSPGainAttackRate,30,1; }
 1379,NIGHTMARE_TERROR,Nightmare Terror,12372,9054,10036,6112,80,60,10,100,250,20,200,150,0,0,300,300,800,{},{ bonus2 bResEff,Eff_Sleep,10000; }
 1401,SHINOBI,Shinobi,12362,9044,10026,6099,80,60,20,100,250,20,500,150,0,0,300,300,800,{},{ bonus bAgi,2; }
 1404,MIYABI_NINGYO,Miyabi Doll,12366,9048,10030,6106,80,60,15,100,250,20,200,150,0,0,300,300,800,{},{ bonus bInt,1; bonus bCastrate,-3; }

+ 1 - 1
db/re/skill_cast_db.txt

@@ -574,7 +574,7 @@
 
 //===== Professor ==========================
 //-- PF_HPCONVERSION
-373,1000:1200:1400:1600:1800,0,0,0,0,0,0
+373,0,1000:1200:1400:1600:1800,0,0,0,0,0
 //-- PF_SOULCHANGE
 374,0,0,0,0,0,0,3000
 //-- PF_SOULBURN

+ 2 - 1
db/re/skill_require_db.txt

@@ -20,6 +20,7 @@
 //  ridingwarg = Requires to ride a Warg
 //  mado = Requires to have an active mado
 //  elementalspirit = Requires to have an Elemental Spirit summoned.
+//  elementalspirit2 = Requires to have an Elemental Spirit summoned, and will be removed.
 //  peco = Requires riding a peco
 //
 // 'RequiredStatuses'
@@ -963,7 +964,7 @@
 5005,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//RK_LUXANIMA
 5006,0,0,60:70:80:90:100,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0				//NC_MAGMA_ERUPTION
 5007,0,0,200:230:260:290:320,0,0,0,13:14,0,0,none,0,0,6144,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0		//WM_FRIGG_SONG
-5008,0,0,120,0,0,0,99,0,0,elementalspirit,0,0,717,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0					//SO_ELEMENTAL_SHIELD
+5008,0,0,120,0,0,0,99,0,0,elementalspirit2,0,0,717,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0					//SO_ELEMENTAL_SHIELD
 5009,0,0,65,0,0,0,99,0,0,none,0,5:5:4:4:3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0						//SR_FLASHCOMBO
 5010,0,0,30:26:22:18:14,0,0,0,99,0,0,none,0,0,7940,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0				//SC_ESCAPE
 5011,0,0,30:60:90:120:150,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0				//AB_OFFERTORIUM

+ 3 - 2
doc/item_bonus.txt

@@ -202,8 +202,9 @@ Damage modifiers
 bonus2 bAddEle,e,x;       		+x% physical damage against element e
 bonus3 bAddEle,e,x,bf;    		+x% physical damage against element e with trigger criteria bf
 bonus2 bMagicAddEle,e,x;  		+x% magical damage against element e
-bonus2 bSubEle,e,x;       		+x% damage reduction against element e
-bonus3 bSubEle,e,x,bf;    		+x% damage reduction against element e with trigger criteria bf
+bonus2 bSubEle,e,x;       		+x% damage reduction against attack element e
+bonus3 bSubEle,e,x,bf;    		+x% damage reduction against attack element e with trigger criteria bf
+bonus2 bSubDefEle,e,x;    		+x% damage reduction from enemy with defense element e
 
 bonus2 bAddRace,r,x;      		+x% physical damage against race r
 bonus2 bMagicAddRace,r,x; 		+x% magical damage against race r

+ 171 - 101
src/map/battle.c

@@ -481,21 +481,31 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
 
 /**
  * Calculates card bonuses damage adjustments.
- * @param attack_type
- * @param src
- * @param target
- * @param nk
- * @param s_ele
- * @param s_ele_
- * @param damage
- * @param left
- * @param flag
- * @return damage
+ * @param attack_type @see enum e_battle_flag
+ * @param src Attacker
+ * @param target Target
+ * @param nk Skill's nk @see enum e_skill_nk [NK_NO_CARDFIX_ATK|NK_NO_ELEFIX|NK_NO_CARDFIX_DEF]
+ * @param rh_ele Right-hand weapon element
+ * @param lh_ele Left-hand weapon element (BF_MAGIC and BF_MISC ignore this value)
+ * @param damage Original damage
+ * @param left Left hand flag (BF_MISC and BF_MAGIC ignore flag value)
+ *         3: Calculates attacker bonuses in both hands.
+ *         2: Calculates attacker bonuses in right-hand only.
+ *         0 or 1: Only calculates target bonuses.
+ * @param flag Misc value of skill & damage flags
+ * @return damage Damage diff between original damage and after calculation
  */
-int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int left, int flag){
-	struct map_session_data *sd, *tsd;
-	short cardfix = 1000, t_class, s_class, s_race2, t_race2;
-	struct status_data *sstatus, *tstatus;
+int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int rh_ele, int lh_ele, int64 damage, int left, int flag){
+	struct map_session_data *sd, ///< Attacker session data if BL_PC
+		*tsd; ///< Target session data if BL_PC
+	short cardfix = 1000;
+	enum e_classAE s_class, ///< Attacker class
+		t_class; ///< Target class
+	enum e_race2 s_race2, /// Attacker Race2
+		t_race2; ///< Target Race2
+	enum e_element s_defele; ///< Attacker Element (not a weapon or skill element!)
+	struct status_data *sstatus, ///< Attacker status data
+		*tstatus; ///< Target status data
 	int64 original_damage;
 	int i;
 
@@ -506,21 +516,24 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 
 	sd = BL_CAST(BL_PC, src);
 	tsd = BL_CAST(BL_PC, target);
-	t_class = status_get_class(target);
-	s_class = status_get_class(src);
+	t_class = (enum e_classAE)status_get_class(target);
+	s_class = (enum e_classAE)status_get_class(src);
 	sstatus = status_get_status_data(src);
 	tstatus = status_get_status_data(target);
-	s_race2 = status_get_race2(src);
+	s_race2 = (enum e_race2)status_get_race2(src);
+	s_defele = (tsd) ? (enum e_element)status_get_element(src) : ELE_NONE;
 
 	switch( attack_type ) {
 		case BF_MAGIC:
+			// Affected by attacker ATK bonuses
 			if( sd && !(nk&NK_NO_CARDFIX_ATK) ) {
 				cardfix = cardfix * (100 + sd->magic_addrace[tstatus->race] + sd->magic_addrace[RC_ALL]) / 100;
-				if( !(nk&NK_NO_ELEFIX) )
+				if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
 					cardfix = cardfix * (100 + sd->magic_addele[tstatus->def_ele] + sd->magic_addele[ELE_ALL]) / 100;
+					cardfix = cardfix * (100 + sd->magic_atk_ele[rh_ele] + sd->magic_atk_ele[ELE_ALL]) / 100;
+				}
 				cardfix = cardfix * (100 + sd->magic_addsize[tstatus->size] + sd->magic_addsize[SZ_ALL]) / 100;
 				cardfix = cardfix * (100 + sd->magic_addclass[tstatus->class_] + sd->magic_addclass[CLASS_ALL]) / 100;
-				cardfix = cardfix * (100 + sd->magic_atk_ele[s_ele] + sd->magic_atk_ele[ELE_ALL]) / 100;
 				for( i = 0; i < ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate; i++ ) {
 					if( sd->add_mdmg[i].class_ == t_class ) {
 						cardfix = cardfix * (100 + sd->add_mdmg[i].rate) / 100;
@@ -530,14 +543,16 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 				if( cardfix != 1000 )
 					damage = damage * cardfix / 1000;
 			}
-			if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) { // Target cards.
+
+			// Affected by target DEF bonuses
+			if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) {
 				cardfix = 1000; // reset var for target
 
-				if( !(nk&NK_NO_ELEFIX) ) {
-					int ele_fix = tsd->subele[s_ele] + tsd->subele[ELE_ALL];
+				if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
+					int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL];
 
 					for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) {
-						if( tsd->subele2[i].ele != s_ele )
+						if( tsd->subele2[i].ele != rh_ele )
 							continue;
 						if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK &&
 							((tsd->subele2[i].flag)&flag)&BF_RANGEMASK &&
@@ -545,6 +560,8 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 							continue;
 						ele_fix += tsd->subele2[i].rate;
 					}
+					if (s_defele != ELE_NONE)
+						ele_fix += tsd->subdefele[s_defele] + tsd->subdefele[ELE_ALL];
 					cardfix = cardfix * (100 - ele_fix) / 100;
 				}
 				cardfix = cardfix * (100 - tsd->subsize[sstatus->size] - tsd->subsize[SZ_ALL]) / 100;
@@ -573,15 +590,17 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 					damage = damage * cardfix / 1000;
 			}
 			break;
+
 		case BF_WEAPON:
-			t_race2 = status_get_race2(target);
-			if( sd && !(nk&NK_NO_CARDFIX_ATK) && (left&2) ) { //Attacker cards should be checked
+			t_race2 = (enum e_race2)status_get_race2(target);
+			// Affected by attacker ATK bonuses
+			if( sd && !(nk&NK_NO_CARDFIX_ATK) && (left&2) ) {
 				short cardfix_ = 1000;
 
-				if( sd->state.arrow_atk ) {
+				if( sd->state.arrow_atk ) { // Ranged attack
 					cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->arrow_addrace[tstatus->race] +
 						sd->right_weapon.addrace[RC_ALL] + sd->arrow_addrace[RC_ALL]) / 100;
-					if( !(nk&NK_NO_ELEFIX) ) {
+					if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
 						int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele] +
 							sd->right_weapon.addele[ELE_ALL] + sd->arrow_addele[ELE_ALL];
 
@@ -604,9 +623,11 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 				} else { // Melee attack
 					int skill = 0;
 
+					// Calculates each right & left hand weapon bonuses separatedly
 					if( !battle_config.left_cardfix_to_right ) {
+						// Right-handed weapon
 						cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->right_weapon.addrace[RC_ALL]) / 100;
-						if( !(nk&NK_NO_ELEFIX) ) {
+						if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
 							int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->right_weapon.addele[ELE_ALL];
 
 							for( i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++ ) {
@@ -624,9 +645,9 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 						cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2]) / 100;
 						cardfix = cardfix * (100 + sd->right_weapon.addclass[tstatus->class_] + sd->right_weapon.addclass[CLASS_ALL]) / 100;
 
-						if( left&1 ) {
+						if( left&1 ) { // Left-handed weapon
 							cardfix_ = cardfix_ * (100 + sd->left_weapon.addrace[tstatus->race] + sd->left_weapon.addrace[RC_ALL]) / 100;
-							if( !(nk&NK_NO_ELEFIX) ) {
+							if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
 								int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[ELE_ALL];
 
 								for( i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++ ) {
@@ -644,31 +665,36 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 							cardfix_ = cardfix_ * (100 + sd->left_weapon.addrace2[t_race2]) / 100;
 							cardfix_ = cardfix_ * (100 + sd->left_weapon.addclass[tstatus->class_] + sd->left_weapon.addclass[CLASS_ALL]) / 100;
 						}
-					} else {
-						int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]
-									+ sd->right_weapon.addele[ELE_ALL] + sd->left_weapon.addele[ELE_ALL];
+					}
+					// Calculates right & left hand weapon as unity
+					else {
+						//! CHECKME: If 'left_cardfix_to_right' is yes, doesn't need to check NK_NO_ELEFIX?
+						//if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
+							int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]
+										+ sd->right_weapon.addele[ELE_ALL] + sd->left_weapon.addele[ELE_ALL];
 
-						for( i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++ ) {
-							if( sd->right_weapon.addele2[i].ele != tstatus->def_ele )
-								continue;
-							if( !(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK &&
-								((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK &&
-								((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) )
-								continue;
-							ele_fix += sd->right_weapon.addele2[i].rate;
-						}
-						for( i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++ ) {
-							if( sd->left_weapon.addele2[i].ele != tstatus->def_ele )
-								continue;
-							if( !(((sd->left_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK &&
-								((sd->left_weapon.addele2[i].flag)&flag)&BF_RANGEMASK &&
-								((sd->left_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) )
-								continue;
-							ele_fix += sd->left_weapon.addele2[i].rate;
-						}
+							for( i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++ ) {
+								if( sd->right_weapon.addele2[i].ele != tstatus->def_ele )
+									continue;
+								if( !(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK &&
+									((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK &&
+									((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) )
+									continue;
+								ele_fix += sd->right_weapon.addele2[i].rate;
+							}
+							for( i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++ ) {
+								if( sd->left_weapon.addele2[i].ele != tstatus->def_ele )
+									continue;
+								if( !(((sd->left_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK &&
+									((sd->left_weapon.addele2[i].flag)&flag)&BF_RANGEMASK &&
+									((sd->left_weapon.addele2[i].flag)&flag)&BF_SKILLMASK) )
+									continue;
+								ele_fix += sd->left_weapon.addele2[i].rate;
+							}
+							cardfix = cardfix * (100 + ele_fix) / 100;
+						//}
 						cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->left_weapon.addrace[tstatus->race] +
 							sd->right_weapon.addrace[RC_ALL] + sd->left_weapon.addrace[RC_ALL]) / 100;
-						cardfix = cardfix * (100 + ele_fix) / 100;
 						cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size] + sd->left_weapon.addsize[tstatus->size] +
 							sd->right_weapon.addsize[SZ_ALL] + sd->left_weapon.addsize[SZ_ALL]) / 100;
 						cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2] + sd->left_weapon.addrace2[t_race2]) / 100;
@@ -678,6 +704,8 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 					if( sd->status.weapon == W_KATAR && (skill = pc_checkskill(sd,ASC_KATAR)) > 0 ) // Adv. Katar Mastery functions similar to a +%ATK card on official [helvetica]
 						cardfix = cardfix * (100 + (10 + 2 * skill)) / 100;
 				}
+
+				//! CHECKME: These right & left hand weapon ignores 'left_cardfix_to_right'?
 				for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ ) {
 					if( sd->right_weapon.add_dmg[i].class_ == t_class ) {
 						cardfix = cardfix * (100 + sd->right_weapon.add_dmg[i].rate) / 100;
@@ -700,12 +728,14 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 					damage = damage * cardfix_ / 1000;
 				else if( cardfix != 1000 )
 					damage = damage * cardfix / 1000;
-			} else if( tsd && !(nk&NK_NO_CARDFIX_DEF) && !(left&2) ) { //Target cards should be checked
-				if( !(nk&NK_NO_ELEFIX) ) {
-					int ele_fix = tsd->subele[s_ele] + tsd->subele[ELE_ALL];
+			}
+			// Affected by target DEF bonuses
+			else if( tsd && !(nk&NK_NO_CARDFIX_DEF) && !(left&2) ) {
+				if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
+					int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL];
 
 					for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) {
-						if( tsd->subele2[i].ele != s_ele )
+						if( tsd->subele2[i].ele != rh_ele )
 							continue;
 						if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK &&
 							((tsd->subele2[i].flag)&flag)&BF_RANGEMASK &&
@@ -714,11 +744,12 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 						ele_fix += tsd->subele2[i].rate;
 					}
 					cardfix = cardfix * (100 - ele_fix) / 100;
-					if( left&1 && s_ele_ != s_ele ) {
-						int ele_fix_lh = tsd->subele[s_ele_] + tsd->subele[ELE_ALL];
+
+					if( left&1 && lh_ele != rh_ele ) {
+						int ele_fix_lh = tsd->subele[lh_ele] + tsd->subele[ELE_ALL];
 
 						for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) {
-							if( tsd->subele2[i].ele != s_ele_ )
+							if( tsd->subele2[i].ele != lh_ele )
 								continue;
 							if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK &&
 								((tsd->subele2[i].flag)&flag)&BF_RANGEMASK &&
@@ -728,6 +759,8 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 						}
 						cardfix = cardfix * (100 - ele_fix_lh) / 100;
 					}
+
+					cardfix = cardfix * (100 - tsd->subdefele[s_defele] - tsd->subdefele[ELE_ALL]) / 100;
 				}
 				cardfix = cardfix * (100 - tsd->subsize[sstatus->size] - tsd->subsize[SZ_ALL]) / 100;
 				cardfix = cardfix * (100 - tsd->subrace2[s_race2]) / 100;
@@ -749,13 +782,15 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 					damage = damage * cardfix / 1000;
 			}
 			break;
+
 		case BF_MISC:
-			if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) { // misc damage reduction from equipment
-				if( !(nk&NK_NO_ELEFIX) ) {
-					int ele_fix = tsd->subele[s_ele] + tsd->subele[ELE_ALL];
+			// Affected by target DEF bonuses
+			if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) {
+				if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
+					int ele_fix = tsd->subele[rh_ele] + tsd->subele[ELE_ALL];
 
 					for( i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++ ) {
-						if( tsd->subele2[i].ele != s_ele )
+						if( tsd->subele2[i].ele != rh_ele )
 							continue;
 						if( !(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK &&
 							((tsd->subele2[i].flag)&flag)&BF_RANGEMASK &&
@@ -763,6 +798,8 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 							continue;
 						ele_fix += tsd->subele2[i].rate;
 					}
+					if (s_defele != ELE_NONE)
+						ele_fix += tsd->subdefele[s_defele] + tsd->subdefele[ELE_ALL];
 					cardfix = cardfix * (100 - ele_fix) / 100;
 				}
 				cardfix = cardfix * (100 - tsd->subsize[sstatus->size] - tsd->subsize[SZ_ALL]) / 100;
@@ -774,7 +811,7 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li
 					cardfix = cardfix * (100 - tsd->bonus.near_attack_def_rate) / 100;
 				else	// BF_LONG (there's no other choice)
 					cardfix = cardfix * (100 - tsd->bonus.long_attack_def_rate) / 100;
-				if( cardfix != 10000 )
+				if( cardfix != 1000 )
 					damage = damage * cardfix / 1000;
 			}
 			break;
@@ -829,6 +866,62 @@ static void battle_absorb_damage(struct block_list *bl, struct Damage *d) {
 	}
 }
 
+/**
+ * Check Safety Wall and Pneuma effect.
+ * Maybe expand this to move checks the target's SC from battle_calc_damage?
+ * @param src Attacker
+ * @param target Target of attack
+ * @param sc STatus Change
+ * @param d Damage data
+ * @param damage Damage received
+ * @param skill_id
+ * @param skill_lv
+ * @return True:Damage inflicted, False:Missed
+ **/
+bool battle_check_sc(struct block_list *src, struct block_list *target, struct status_change *sc, struct Damage *d, int64 damage, uint16 skill_id, uint16 skill_lv) {
+	if (!sc)
+		return true;
+
+	if (sc->data[SC_SAFETYWALL] && (d->flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT) {
+		struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3);
+		uint16 skill_id_val = sc->data[SC_SAFETYWALL]->val2;
+
+		if (group) {
+			if (skill_id_val == MH_STEINWAND) {
+				if (--group->val2 <= 0)
+					skill_delunitgroup(group);
+				d->dmg_lv = ATK_BLOCK;
+				if( (group->val3 - damage) > 0 )
+					group->val3 -= (int)cap_value(damage, INT_MIN, INT_MAX);
+				else
+					skill_delunitgroup(group);
+				return false;
+			}
+			//in RE, SW possesses a lifetime equal to group val2, (3x caster hp, or homon formula)
+			d->dmg_lv = ATK_BLOCK;
+#ifdef RENEWAL
+			if ( ( group->val2 - damage) > 0 ) {
+				group->val2 -= (int)cap_value(damage, INT_MIN, INT_MAX);
+			} else
+				skill_delunitgroup(group);
+			return false;
+#else
+			if (--group->val2 <= 0)
+				skill_delunitgroup(group);
+			return false;
+#endif
+		}
+		status_change_end(target, SC_SAFETYWALL, INVALID_TIMER);
+	}
+
+	if( sc->data[SC_PNEUMA] && (d->flag&(BF_MAGIC|BF_LONG)) == BF_LONG ) {
+		d->dmg_lv = ATK_BLOCK;
+		skill_blown(src,target,skill_get_blewcount(skill_id,skill_lv),-1,0);
+		return false;
+	}
+	return true;
+}
+
 /**
  * Check damage through status.
  * ATK may be MISS, BLOCKED FAIL, reduc, increase, end status.
@@ -908,46 +1001,11 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 			return 0;
 		}
 
-		if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) {
-			struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3);
-			uint16 skill_id_val = sc->data[SC_SAFETYWALL]->val2;
-
-			if (group) {
-				if (skill_id_val == MH_STEINWAND) {
-					if (--group->val2 <= 0)
-						skill_delunitgroup(group);
-					d->dmg_lv = ATK_BLOCK;
-					if( (group->val3 - damage) > 0 )
-						group->val3 -= (int)cap_value(damage, INT_MIN, INT_MAX);
-					else
-						skill_delunitgroup(group);
-					return 0;
-				}
-				//in RE, SW possesses a lifetime equal to group val2, (3x caster hp, or homon formula)
-				d->dmg_lv = ATK_BLOCK;
-#ifdef RENEWAL
-				if ( ( group->val2 - damage) > 0 ) {
-					group->val2 -= (int)cap_value(damage, INT_MIN, INT_MAX);
-				} else
-					skill_delunitgroup(group);
-				return 0;
-#else
-				if (--group->val2 <= 0)
-					skill_delunitgroup(group);
-				return 0;
-#endif
-			}
-			status_change_end(bl, SC_SAFETYWALL, INVALID_TIMER);
-		}
-
-		if (sc->data[SC__MANHOLE] || (src->type == BL_PC && sc->data[SC_KINGS_GRACE])) {
-			d->dmg_lv = ATK_BLOCK;
+		if (!battle_check_sc(src, bl, sc, d, damage, skill_id, skill_lv))
 			return 0;
-		}
 
-		if( sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG ) {
+		if (sc->data[SC__MANHOLE] || (src->type == BL_PC && sc->data[SC_KINGS_GRACE])) {
 			d->dmg_lv = ATK_BLOCK;
-			skill_blown(src,bl,skill_get_blewcount(skill_id,skill_lv),-1,0);
 			return 0;
 		}
 
@@ -4626,6 +4684,18 @@ struct Damage battle_calc_attack_plant(struct Damage wd, struct block_list *src,
 		}
 	}
 
+	if (attack_hits && target->type == BL_MOB) {
+		struct status_change *sc = status_get_sc(target);
+		struct mob_data *md = BL_CAST(BL_MOB,target);
+		if (sc &&
+			class_ != MOBID_EMPERIUM && !mob_is_battleground(md) &&
+			!battle_check_sc(src, target, sc, &wd, 1, skill_id, skill_lv))
+		{
+			wd.damage = wd.damage2 = 0;
+			return wd;
+		}
+	}
+
 	if( attack_hits && class_ == MOBID_EMPERIUM ) {
 		if(target && map_flag_gvg2(target->m) && !battle_can_hit_gvg_target(src,target,skill_id,(skill_id)?BF_SKILL:0)) {
 			wd.damage = wd.damage2 = 0;

+ 3 - 2
src/map/map.h

@@ -77,8 +77,8 @@ enum MOBID {
 	MOBID_A_GUARDIAN_,
 	MOBID_BARRICADE1		= 1905,
 	MOBID_BARRICADE2,
-	MOBID_GUARIDAN_STONE1,
-	MOBID_GUARIDAN_STONE2,
+	MOBID_GUARDIAN_STONE1,
+	MOBID_GUARDIAN_STONE2,
 	MOBID_FOOD_STOR,
 	MOBID_BLUE_CRYST		= 1914,
 	MOBID_PINK_CRYST,
@@ -501,6 +501,7 @@ enum _sp {
 	SP_ADD_CLASS_DROP_ITEMGROUP, SP_ADDMAXWEIGHT, SP_ADD_ITEMGROUP_HEAL_RATE,  // 2071-2073
 	SP_HP_VANISH_RACE_RATE, SP_SP_VANISH_RACE_RATE, SP_HP_GAIN_RACE_ATTACK_RATE, SP_SP_GAIN_RACE_ATTACK_RATE, // 2074-2077
 	SP_ABSORB_DMG_MAXHP, SP_HP_GAIN_ATTACK, SP_SP_GAIN_ATTACK, SP_HP_GAIN_ATTACK_RATE, SP_SP_GAIN_ATTACK_RATE, SP_SUB_SKILL, // 2078-2083
+	SP_SUBDEF_ELE, // 2084
 };
 
 enum _look {

+ 1 - 1
src/map/mob.h

@@ -281,7 +281,7 @@ void mob_heal(struct mob_data *md,unsigned int heal);
 #define mob_stop_walking(md, type) unit_stop_walking(&(md)->bl, type)
 #define mob_stop_attack(md) unit_stop_attack(&(md)->bl)
 #define mob_is_battleground(md) ( map[(md)->bl.m].flag.battleground && ((md)->mob_id == MOBID_BARRICADE2 || ((md)->mob_id >= MOBID_FOOD_STOR && (md)->mob_id <= MOBID_PINK_CRYST)) )
-#define mob_is_gvg(md) (map[(md)->bl.m].flag.gvg_castle && ( (md)->mob_id == MOBID_EMPERIUM || (md)->mob_id == MOBID_BARRICADE1 || (md)->mob_id == MOBID_GUARIDAN_STONE1 || (md)->mob_id == MOBID_GUARIDAN_STONE2) )
+#define mob_is_gvg(md) (map[(md)->bl.m].flag.gvg_castle && ( (md)->mob_id == MOBID_EMPERIUM || (md)->mob_id == MOBID_BARRICADE1 || (md)->mob_id == MOBID_GUARDIAN_STONE1 || (md)->mob_id == MOBID_GUARDIAN_STONE2) )
 #define mob_is_treasure(md) (((md)->mob_id >= MOBID_TREAS01 && (md)->mob_id <= MOBID_TREAS40) || ((md)->mob_id >= MOBID_TREAS41 && (md)->mob_id <= MOBID_TREAS49))
 #define mob_is_guardian(mob_id) ((mob_id >= MOBID_A_GUARDIAN && mob_id <= MOBID_S_GUARDIAN) || mob_id == MOBID_S_GUARDIAN_ || mob_id == MOBID_A_GUARDIAN_)
 #define mob_is_goblin(md, mid) (((md)->mob_id >= MOBID_GOBLIN_1 && (md)->mob_id <= MOBID_GOBLIN_5) && (mid >= MOBID_GOBLIN_1 && mid <= MOBID_GOBLIN_5))

+ 4 - 37
src/map/pc.c

@@ -3650,6 +3650,10 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
 			sd->subskill[i].val = val;
 		}
 		break;
+	case SP_SUBDEF_ELE: // bonus2 bSubDefEle,e,x;
+		PC_BONUS_CHK_ELEMENT(type2,SP_SUBDEF_ELE);
+		sd->subdefele[type2] += val;
+		break;
 	default:
 		ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
 		break;
@@ -11430,43 +11434,6 @@ void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag) {
 		status_calc_pc(sd,SCO_NONE);
 }
 
-/**
-* Clear all bonus script from player
-* @param sd
-* @param flag &1 - Remove permanent bonus_script, &2 - Logout
-* @author [Cydh]
-**/
-void pc_bonus_script_clear_all(struct map_session_data *sd, uint8 flag) {
-	struct linkdb_node *node = NULL;
-	uint16 count = 0;
-
-	if (!sd || !(node = sd->bonus_script.head))
-		return;
-
-	while (node) {
-		struct linkdb_node *next = node->next;
-		struct s_bonus_script_entry *entry = (struct s_bonus_script_entry *)node->data;
-
-		if (entry && (
-				!(entry->flag&BSF_PERMANENT) ||
-				((flag&1) && entry->flag&BSF_PERMANENT)
-				)
-			)
-		{
-			linkdb_erase(&sd->bonus_script.head, (void *)((intptr_t)entry));
-			pc_bonus_script_free_entry(sd, entry);
-			count++;
-		}
-
-		node = next;
-	}
-
-	pc_bonus_script_check_final(sd);
-
-	if (count && !(flag&2))
-		status_calc_pc(sd,SCO_NONE);
-}
-
 /** [Cydh]
  * Gives/removes SC_BASILICA when player steps in/out the cell with 'cell_basilica'
  * @param sd: Target player

+ 1 - 0
src/map/pc.h

@@ -323,6 +323,7 @@ struct map_session_data {
 	// here start arrays to be globally zeroed at the beginning of status_calc_pc()
 	int param_bonus[6],param_equip[6]; //Stores card/equipment bonuses.
 	int subele[ELE_MAX];
+	int subdefele[ELE_MAX];
 	int subrace[RC_MAX];
 	int subclass[CLASS_MAX];
 	int subrace2[RC2_MAX];

+ 12 - 4
src/map/skill.c

@@ -7974,7 +7974,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 	// Slim Pitcher
 	case CR_SLIMPITCHER:
 		// Updated to block Slim Pitcher from working on barricades and guardian stones.
-		if( dstmd && (dstmd->mob_id == MOBID_EMPERIUM || (dstmd->mob_id >= MOBID_BARRICADE1 && dstmd->mob_id <= MOBID_GUARIDAN_STONE2)) )
+		if( dstmd && (dstmd->mob_id == MOBID_EMPERIUM || (dstmd->mob_id >= MOBID_BARRICADE1 && dstmd->mob_id <= MOBID_GUARDIAN_STONE2)) )
 			break;
 		if (potion_hp || potion_sp) {
 			int hp = potion_hp, sp = potion_sp;
@@ -9807,7 +9807,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		if( sd ) {
 			int elemental_class = skill_get_elemental_type(skill_id,skill_lv);
 
-			// Remove previous elemental fisrt.
+			// Remove previous elemental first.
 			if( sd->ed )
 				elemental_delete(sd->ed,0);
 
@@ -10357,12 +10357,18 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 
 	case SO_ELEMENTAL_SHIELD:
 		if (!sd || sd->status.party_id == 0 || flag&1) {
+			if (sd && sd->status.party_id == 0) {
+				clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
+				if (sd->ed && skill_get_state(skill_id) == ST_ELEMENTALSPIRIT2)
+					elemental_delete(sd->ed,0);
+			}
 			skill_unitsetting(bl, MG_SAFETYWALL, skill_lv + 5, bl->x, bl->y, 0);
 			skill_unitsetting(bl, AL_PNEUMA, 1, bl->x, bl->y, 0);
 		}
 		else {
 			clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
-			elemental_delete(sd->ed,0);
+			if (sd->ed && skill_get_state(skill_id) == ST_ELEMENTALSPIRIT2)
+				elemental_delete(sd->ed,0);
 			party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id,skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
 		}
 		break;
@@ -14693,7 +14699,7 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
 		case SR_CURSEDCIRCLE:
 			if (map_flag_gvg(sd->bl.m)) {
 			    if (map_foreachinrange(mob_count_sub, &sd->bl, skill_get_splash(skill_id, skill_lv), BL_MOB,
-				    MOBID_EMPERIUM, MOBID_GUARIDAN_STONE1, MOBID_GUARIDAN_STONE2)) {
+				    MOBID_EMPERIUM, MOBID_GUARDIAN_STONE1, MOBID_GUARDIAN_STONE2)) {
 				char output[128];
 				sprintf(output,"%s",msg_txt(sd,382)); // You're too close to a stone or emperium to use this skill.
 				clif_colormes(sd,color_table[COLOR_RED], output);
@@ -14871,6 +14877,7 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
 			}
 			break;
 		case ST_ELEMENTALSPIRIT:
+		case ST_ELEMENTALSPIRIT2:
 			if(!sd->ed) {
 				clif_skill_fail(sd,skill_id,USESKILL_FAIL_EL_SUMMON,0);
 				return false;
@@ -20081,6 +20088,7 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
 	else if( strcmpi(split[10],"ridingwarg")          == 0 ) skill_db[idx]->require.state = ST_RIDINGWUG;
 	else if( strcmpi(split[10],"mado")                == 0 ) skill_db[idx]->require.state = ST_MADO;
 	else if( strcmpi(split[10],"elementalspirit")     == 0 ) skill_db[idx]->require.state = ST_ELEMENTALSPIRIT;
+	else if( strcmpi(split[10],"elementalspirit2")    == 0 ) skill_db[idx]->require.state = ST_ELEMENTALSPIRIT2;
 	else if( strcmpi(split[10],"peco")                == 0 ) skill_db[idx]->require.state = ST_PECO;
 	else skill_db[idx]->require.state = ST_NONE;	// Unknown or no state
 

+ 1 - 0
src/map/skill.h

@@ -529,6 +529,7 @@ enum e_require_state {
 	ST_RIDINGWUG,
 	ST_MADO,
 	ST_ELEMENTALSPIRIT,
+	ST_ELEMENTALSPIRIT2,
 	ST_PECO,
 };
 

+ 1 - 0
src/map/status.c

@@ -2980,6 +2980,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
 	memset (sd->param_bonus, 0, sizeof(sd->param_bonus)
 		+ sizeof(sd->param_equip)
 		+ sizeof(sd->subele)
+		+ sizeof(sd->subdefele)
 		+ sizeof(sd->subrace)
 		+ sizeof(sd->subclass)
 		+ sizeof(sd->subrace2)