From 5a4cd7426ee67bc87a845651bedc55bce2ff4487 Mon Sep 17 00:00:00 2001 From: Cydh Ramdh Date: Wed, 10 Jun 2015 12:03:52 +0700 Subject: [PATCH] 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 --- db/const.txt | 1 + db/pre-re/skill_require_db.txt | 3 +- db/re/item_combo_db.txt | 4 +- db/re/item_db.txt | 20 +-- db/re/pet_db.txt | 4 +- db/re/skill_cast_db.txt | 2 +- db/re/skill_require_db.txt | 3 +- doc/item_bonus.txt | 5 +- src/map/battle.c | 272 +++++++++++++++++++++------------ src/map/map.h | 5 +- src/map/mob.h | 2 +- src/map/pc.c | 41 +---- src/map/pc.h | 1 + src/map/skill.c | 16 +- src/map/skill.h | 1 + src/map/status.c | 1 + 16 files changed, 217 insertions(+), 164 deletions(-) diff --git a/db/const.txt b/db/const.txt index 6536855aa3..05e9901ff8 100644 --- a/db/const.txt +++ b/db/const.txt @@ -637,6 +637,7 @@ bSPGainAttack 2080 bHPGainAttackRate 2081 bSPGainAttackRate 2082 bSubSkill 2083 +bSubDefEle 2084 EQI_HEAD_TOP 1 EQI_ARMOR 2 diff --git a/db/pre-re/skill_require_db.txt b/db/pre-re/skill_require_db.txt index d701ea3c1f..4796b97066 100644 --- a/db/pre-re/skill_require_db.txt +++ b/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 diff --git a/db/re/item_combo_db.txt b/db/re/item_combo_db.txt index ce24aba641..8a6457c764 100644 --- a/db/re/item_combo_db.txt +++ b/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); } diff --git a/db/re/item_db.txt b/db/re/item_db.txt index c85696ff84..9bc3ad1576 100644 --- a/db/re/item_db.txt +++ b/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; },{},{} diff --git a/db/re/pet_db.txt b/db/re/pet_db.txt index abf4a2191c..63cc247809 100644 --- a/db/re/pet_db.txt +++ b/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; } diff --git a/db/re/skill_cast_db.txt b/db/re/skill_cast_db.txt index 576ddaa034..a25faa4b7c 100644 --- a/db/re/skill_cast_db.txt +++ b/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 diff --git a/db/re/skill_require_db.txt b/db/re/skill_require_db.txt index c8fb9b09bc..7b962bdfbb 100644 --- a/db/re/skill_require_db.txt +++ b/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 diff --git a/doc/item_bonus.txt b/doc/item_bonus.txt index 6e1b49822c..979881c499 100644 --- a/doc/item_bonus.txt +++ b/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 diff --git a/src/map/battle.c b/src/map/battle.c index d0128d496c..1cac4c6f82 100644 --- a/src/map/battle.c +++ b/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,49 +1001,14 @@ 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 (!battle_check_sc(src, bl, sc, d, damage, skill_id, skill_lv)) + return 0; if (sc->data[SC__MANHOLE] || (src->type == BL_PC && sc->data[SC_KINGS_GRACE])) { d->dmg_lv = ATK_BLOCK; return 0; } - if( sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG ) { - d->dmg_lv = ATK_BLOCK; - skill_blown(src,bl,skill_get_blewcount(skill_id,skill_lv),-1,0); - return 0; - } - if( sc->data[SC_WEAPONBLOCKING] && flag&(BF_SHORT|BF_WEAPON) && rnd()%100 < sc->data[SC_WEAPONBLOCKING]->val2 ) { clif_skill_nodamage(bl,src,GC_WEAPONBLOCKING,sc->data[SC_WEAPONBLOCKING]->val1,1); sc_start2(src,bl,SC_COMBO,100,GC_WEAPONBLOCKING,src->id,skill_get_time2(GC_WEAPONBLOCKING,sc->data[SC_WEAPONBLOCKING]->val1)); @@ -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; diff --git a/src/map/map.h b/src/map/map.h index 6b70fbe0ca..04169f59f4 100644 --- a/src/map/map.h +++ b/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 { diff --git a/src/map/mob.h b/src/map/mob.h index a975fd2510..24cad6e27a 100644 --- a/src/map/mob.h +++ b/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)) diff --git a/src/map/pc.c b/src/map/pc.c index 0f9dbe5320..1cecf81e78 100755 --- a/src/map/pc.c +++ b/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 diff --git a/src/map/pc.h b/src/map/pc.h index 85595faa17..09fdafbacd 100644 --- a/src/map/pc.h +++ b/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]; diff --git a/src/map/skill.c b/src/map/skill.c index 441e0a388d..79af5cdd5d 100755 --- a/src/map/skill.c +++ b/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 diff --git a/src/map/skill.h b/src/map/skill.h index 763f61403c..341e959bd4 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -529,6 +529,7 @@ enum e_require_state { ST_RIDINGWUG, ST_MADO, ST_ELEMENTALSPIRIT, + ST_ELEMENTALSPIRIT2, ST_PECO, }; diff --git a/src/map/status.c b/src/map/status.c index 5dbeaa1381..93ee641225 100644 --- a/src/map/status.c +++ b/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)