Bug fixes & Misc:

-- Map crashed because empty item_combo script (bugreport:8959)
-- Wrong MATK calculation of Distort Crescent/Zangetsu effect (SC_ZANGETSU) (bugreport:8998)
-- Wrong damage reduction of Sera's Pain Killer effect (SC_PAIN_KILLER) (bugreport:8994)
-- Fixed Shape Shift (NC_SHAPESHIFT) wrong requirement (bugreport:9002)
-- @itembound, getitembound usage. Not, now allowed for unspecified bound_type (thank Ceejay Abne! http://rathena.org/board/index.php?showtopic=94726)
-- Change check behavior for skill requirement level-dependent check.
-- Removed NC_REPAIR hardcoded requirement.
-- Moved the required equipped item to 'RequiredEquipment' on skill_require_db.txt.
-- Missing "Option_Ruwach" as contantan.
-- Corrected Chasewalk STR bonus, it's SC_CHASEWALK2, different with SC_INCSTR.
-- Corrected some Rebellion skill's effects.
-- USESKILL_FAIL_MADOGEAR message for failed skill that needs player has Madogear.
-- Changed skill name and description length to 31 chars.
-- Some documentation updates.
-- Follow up 0f2dd7f. (Well, using empty password in import file, won't works, if you want, empty the original conf file. Fix this later, related on 'sscanf' for those files)
-- Follow up 28c90bb, thank @julia40124009
-- Misc. :P

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>
This commit is contained in:
Cydh Ramdh 2014-05-31 21:42:44 +07:00
parent 28c90bb841
commit 794c1a8247
32 changed files with 498 additions and 495 deletions

View File

@ -1743,6 +1743,7 @@ SC__FEINTBOMB 594
SC__CHAOS 595 SC__CHAOS 595
SC_ELEMENTAL_SHIELD 596 SC_ELEMENTAL_SHIELD 596
SC_EXTREMITYFIST2 597 SC_EXTREMITYFIST2 597
SC_CHASEWALK2 598
//Status Icon //Status Icon
SI_BLANK -1 SI_BLANK -1
@ -1926,7 +1927,7 @@ SI_MAXSPPERCENT 178
SI_DEFENCE 179 SI_DEFENCE 179
SI_SLOWDOWN 180 SI_SLOWDOWN 180
SI_PRESERVE 181 SI_PRESERVE 181
SI_INCSTR 182 SI_CHASEWALK2 182
SI_NOT_EXTREMITYFIST 183 SI_NOT_EXTREMITYFIST 183
SI_INTRAVISION 184 SI_INTRAVISION 184
SI_MOVESLOW_POTION 185 SI_MOVESLOW_POTION 185
@ -4598,5 +4599,10 @@ IT_AMMO 10
IT_DELAYCONSUME 11 IT_DELAYCONSUME 11
IT_CASH 18 IT_CASH 18
Bound_Account 1
Bound_Guild 2
Bound_Party 3
Bound_Char 4
false 0 false 0
true 1 true 1

View File

@ -4,3 +4,4 @@
// <Flag>: // <Flag>:
// 1 - As Dead Branch item (will be logged at `branchlog` table and cannot be used at 'nobranch' mapflag) // 1 - As Dead Branch item (will be logged at `branchlog` table and cannot be used at 'nobranch' mapflag)
// 2 - As item group container, check player's inventory and weight before consumed // 2 - As item group container, check player's inventory and weight before consumed
// NOTE: For removing flag by import file, use "-" to remove the flag. Example, 604,-1 will removes flag 1 from Branch_Of_Dead_Tree

View File

@ -4,6 +4,7 @@
// <Flag>: // <Flag>:
// 1 - As Dead Branch item (will be logged at `branchlog` table and cannot be used at 'nobranch' mapflag) // 1 - As Dead Branch item (will be logged at `branchlog` table and cannot be used at 'nobranch' mapflag)
// 2 - As item group container, check player's inventory and weight before consumed // 2 - As item group container, check player's inventory and weight before consumed
// NOTE: For removing flag by import file, use "-" to remove the flag. Example, 604,-1 will removes flag 1 from Branch_Of_Dead_Tree
// Logged as Dead Branch item // Logged as Dead Branch item
604,1 //Branch_Of_Dead_Tree 604,1 //Branch_Of_Dead_Tree

View File

@ -118,7 +118,7 @@
//**** //****
// WZ Wizard // WZ Wizard
80,0,0,75,0,0,0,99,0,0,none,0,0,717,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WZ_FIREPILLAR 80,0,0,75,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,717,1,717,1,717,1,717,1,717,1,0 //WZ_FIREPILLAR
81,0,0,35:37:39:41:43:45:47:49:51:53,0,0,0,99,0,0,none,SC_SIGHT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WZ_SIGHTRASHER 81,0,0,35:37:39:41:43:45:47:49:51:53,0,0,0,99,0,0,none,SC_SIGHT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WZ_SIGHTRASHER
83,0,0,20:24:30:34:40:44:50:54:60:64,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 //WZ_METEOR 83,0,0,20:24:30:34:40:44:50:54:60:64,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 //WZ_METEOR
84,0,0,20:23:26:29:32:35:38:41:44:47,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 //WZ_JUPITEL 84,0,0,20:23:26:29:32:35:38:41:44:47,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 //WZ_JUPITEL
@ -678,25 +678,25 @@
//**** //****
// NC Mechanic // NC Mechanic
2256,0,0,3:6:9:12:15,0,0,0,99,0,0,mado,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_BOOSTKNUCKLE 2256,0,0,3:6:9:12:15,0,0,0,99,0,0,mado,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_BOOSTKNUCKLE
2257,0,0,50,0,0,0,99,0,0,mado,0,0,1549,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_PILEBUNKER 2257,0,0,50,0,0,0,99,0,0,mado,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1549 //NC_PILEBUNKER
2258,0,0,2:4:6,0,0,0,99,0,0,mado,0,0,6145,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_VULCANARM 2258,0,0,2:4:6,0,0,0,99,0,0,mado,0,0,6145,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_VULCANARM
2259,0,0,20,0,0,0,99,0,0,mado,0,0,2139,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_FLAMELAUNCHER 2259,0,0,20,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2139 //NC_FLAMELAUNCHER
2260,0,0,20,0,0,0,99,0,0,mado,0,0,6146,1,6147,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_COLDSLOWER 2260,0,0,20,0,0,0,99,0,0,mado,0,0,6146,1,6147,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_COLDSLOWER
2261,0,0,40:45:50,0,0,0,99,8,1,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_ARMSCANNON 2261,0,0,40:45:50,0,0,0,99,8,1,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_ARMSCANNON
2262,0,0,20:40:60,0,0,0,99,0,0,mado,0,0,2800,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_ACCELERATION 2262,0,0,20:40:60,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2800 //NC_ACCELERATION
2263,0,0,25,0,0,0,99,0,0,mado,0,0,2801,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_HOVERING 2263,0,0,25,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2801 //NC_HOVERING
2264,0,0,5,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_F_SIDESLIDE 2264,0,0,5,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_F_SIDESLIDE
2265,0,0,5,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_B_SIDESLIDE 2265,0,0,5,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_B_SIDESLIDE
2267,0,0,1,0,0,0,99,0,0,mado,0,0,2802,0,6146,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_SELFDESTRUCTION 2267,0,0,1,0,0,0,99,0,0,mado,0,0,6146,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2802 //NC_SELFDESTRUCTION
2268,0,0,100,0,0,0,99,0,0,mado,0,0,2803,0,6360,1,6363,1,6362,1,6361,1,6146,2,0,0,0,0,0,0,0,0,0 //NC_SHAPESHIFT 2268,0,0,100,0,0,0,99,0,0,mado,0,0,6360,1,6363,1,6362,1,6361,1,0,0,0,0,0,0,0,0,0,0,6146,2,2803 //NC_SHAPESHIFT
2269,0,0,20,0,0,0,99,0,0,mado,0,0,2804,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_EMERGENCYCOOL 2269,0,0,20,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2804 //NC_EMERGENCYCOOL
2270,0,0,45,0,0,0,99,0,0,mado,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_INFRAREDSCAN 2270,0,0,45,0,0,0,99,0,0,mado,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_INFRAREDSCAN
2271,0,0,30,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_ANALYZE 2271,0,0,30,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_ANALYZE
2272,0,0,90,0,0,0,99,0,0,mado,0,0,2805,0,6146,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_MAGNETICFIELD 2272,0,0,90,0,0,0,99,0,0,mado,0,0,6146,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2805 //NC_MAGNETICFIELD
2273,0,0,90,0,0,0,99,0,0,mado,0,0,2806,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_NEUTRALBARRIER 2273,0,0,90,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2806 //NC_NEUTRALBARRIER
2274,0,0,100:150:200,0,0,0,99,0,0,mado,0,0,2808,0,6146,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_STEALTHFIELD 2274,0,0,100:150:200,0,0,0,99,0,0,mado,0,0,6146,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2808 //NC_STEALTHFIELD
2275,0,0,25:30:35:40:45,0,0,0,99,0,0,mado,0,0,2807,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_REPAIR 2275,0,0,25:30:35:40:45,0,0,0,99,0,0,mado,0,0,12392,1,12392,1,12393,1,12393,1,12394,1,0,0,0,0,0,0,0,0,6146,1,2807 //NC_REPAIR
2278,0,0,20:22:24:26:28,0,0,0,6:7,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_AXEBOOMERANG 2278,0,0,20:22:24:26:28,0,0,0,6:7,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_AXEBOOMERANG
2279,0,0,20:22:24:26:28,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_POWERSWING 2279,0,0,20:22:24:26:28,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_POWERSWING

View File

@ -248,7 +248,7 @@
15068:20710,{ bonus bAgi,5; bonus bFlee,10; } 15068:20710,{ bonus bAgi,5; bonus bFlee,10; }
15088:18816:18818,{ bonus bMatk,BaseLevel/3; bonus2 bExpAddClass,Class_All,5; } 15088:18816:18818,{ bonus bMatk,BaseLevel/3; bonus2 bExpAddClass,Class_All,5; }
15088:18817:18819,{ bonus bBaseAtk,BaseLevel/3; bonus2 bExpAddClass,Class_All,5; } 15088:18817:18819,{ bonus bBaseAtk,BaseLevel/3; bonus2 bExpAddClass,Class_All,5; }
15116:20743:22046,{ bonus bMaxSPrate,25; bonus bMaxSPrate,25; bonus bSpeedAddRate,n; } 15116:20743:22046,{ bonus bMaxSPrate,25; bonus bMaxSPrate,25; bonus bSpeedAddRate,10; }
18507:18539,{ bonus bUseSPrate,-3; } 18507:18539,{ bonus bUseSPrate,-3; }
18538:5041,{ bonus2 bSubRace,RC_Angel,9; } 18538:5041,{ bonus2 bSubRace,RC_Angel,9; }
18538:5048,{ bonus2 bSubRace,RC_Demon,9; } 18538:5048,{ bonus2 bSubRace,RC_Demon,9; }
@ -260,6 +260,7 @@
18656:5475,{ bonus bBaseAtk,30; bonus bMatk,30; bonus2 bAddMonsterDropItem,529,400; bonus2 bAddMonsterDropItem,530,400; bonus2 bAddMonsterDropItem,538,400; bonus2 bAddMonsterDropItem,12192,400;} 18656:5475,{ bonus bBaseAtk,30; bonus bMatk,30; bonus2 bAddMonsterDropItem,529,400; bonus2 bAddMonsterDropItem,530,400; bonus2 bAddMonsterDropItem,538,400; bonus2 bAddMonsterDropItem,12192,400;}
18776:20710,{ bonus bBaseAtk,10; } 18776:20710,{ bonus bBaseAtk,10; }
18776:22015,{ bonus bMatk,20; } 18776:22015,{ bonus bMatk,20; }
18997:28326:28327,{ bonus bSpeed,25; bonus bBaseAtk,50; bonus bMatk,50; }
24012:24013:24014:24015:24016:24017,{ bonus bAllStats,9; } 24012:24013:24014:24015:24016:24017,{ bonus bAllStats,9; }
24018:24019:24020,{ if(getequiprefinerycnt(EQI_SHADOW_ACC_R) + getequiprefinerycnt(EQI_SHADOW_ACC_L) + getequiprefinerycnt(EQI_SHADOW_WEAPON) >= 23) { bonus bAtkRate,1; } } 24018:24019:24020,{ if(getequiprefinerycnt(EQI_SHADOW_ACC_R) + getequiprefinerycnt(EQI_SHADOW_ACC_L) + getequiprefinerycnt(EQI_SHADOW_WEAPON) >= 23) { bonus bAtkRate,1; } }
24021:24022:24023,{ if(getequiprefinerycnt(EQI_SHADOW_ACC_R) + getequiprefinerycnt(EQI_SHADOW_ACC_L) + getequiprefinerycnt(EQI_SHADOW_WEAPON) >= 23) { bonus bMatkRate,1; } } 24021:24022:24023,{ if(getequiprefinerycnt(EQI_SHADOW_ACC_R) + getequiprefinerycnt(EQI_SHADOW_ACC_L) + getequiprefinerycnt(EQI_SHADOW_WEAPON) >= 23) { bonus bMatkRate,1; } }
@ -303,5 +304,4 @@
24150:24151,{ bonus bAtkRate,1; if (getequiprefinerycnt(EQI_SHADOW_ACC_R)+getequiprefinerycnt(EQI_SHADOW_ACC_L) >= 15) bonus bNoSizeFix,1; } 24150:24151,{ bonus bAtkRate,1; if (getequiprefinerycnt(EQI_SHADOW_ACC_R)+getequiprefinerycnt(EQI_SHADOW_ACC_L) >= 15) bonus bNoSizeFix,1; }
24152:24153,{ bonus bAtk,getequiprefinerycnt(EQI_SHADOW_WEAPON); if (getequiprefinerycnt(EQI_SHADOW_WEAPON)+getequiprefinerycnt(EQI_SHADOW_ACC_R) >= 15) bonus bUnbreakableWeapon,1; } 24152:24153,{ bonus bAtk,getequiprefinerycnt(EQI_SHADOW_WEAPON); if (getequiprefinerycnt(EQI_SHADOW_WEAPON)+getequiprefinerycnt(EQI_SHADOW_ACC_R) >= 15) bonus bUnbreakableWeapon,1; }
24154:24155,{ bonus bDef,getequiprefinerycnt(EQI_SHADOW_ARMOR); if (getequiprefinerycnt(EQI_SHADOW_ARMOR)+getequiprefinerycnt(EQI_SHADOW_ACC_L) >= 15) bonus bUnbreakableArmor,1; } 24154:24155,{ bonus bDef,getequiprefinerycnt(EQI_SHADOW_ARMOR); if (getequiprefinerycnt(EQI_SHADOW_ARMOR)+getequiprefinerycnt(EQI_SHADOW_ACC_L) >= 15) bonus bUnbreakableArmor,1; }
18997:28326:28327,{ bonus bSpeed,25; bonus bBaseAtk,50; bonus bMatk,50; }
28326:28327,{ bonus bInt,8; bonus bStr,8; } 28326:28327,{ bonus bInt,8; bonus bStr,8; }

View File

@ -4,6 +4,7 @@
// <Flag>: // <Flag>:
// 1 - As Dead Branch item (will be logged at `branchlog` table and cannot be used at 'nobranch' mapflag) // 1 - As Dead Branch item (will be logged at `branchlog` table and cannot be used at 'nobranch' mapflag)
// 2 - As item group container, check player's inventory and weight before consumed // 2 - As item group container, check player's inventory and weight before consumed
// NOTE: For removing flag by import file, use "-" to remove the flag. Example, 604,-1 will removes flag 1 from Branch_Of_Dead_Tree
// Logged as Dead Branch item // Logged as Dead Branch item
604,1 //Branch_Of_Dead_Tree 604,1 //Branch_Of_Dead_Tree

View File

@ -118,7 +118,7 @@
//**** //****
// WZ Wizard // WZ Wizard
80,0,0,75,0,0,0,99,0,0,none,0,0,717,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WZ_FIREPILLAR 80,0,0,75,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,717,1,717,1,717,1,717,1,717,1,0 //WZ_FIREPILLAR
81,0,0,35:37:39:41:43:45:47:49:51:53,0,0,0,99,0,0,none,SC_SIGHT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WZ_SIGHTRASHER 81,0,0,35:37:39:41:43:45:47:49:51:53,0,0,0,99,0,0,none,SC_SIGHT,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //WZ_SIGHTRASHER
83,0,0,20:24:30:34:40:44:50:54:60:64,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 //WZ_METEOR 83,0,0,20:24:30:34:40:44:50:54:60:64,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 //WZ_METEOR
84,0,0,20:23:26:29:32:35:38:41:44:47,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 //WZ_JUPITEL 84,0,0,20:23:26:29:32:35:38:41:44:47,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 //WZ_JUPITEL
@ -678,25 +678,25 @@
//**** //****
// NC Mechanic // NC Mechanic
2256,0,0,3:6:9:12:15,0,0,0,99,0,0,mado,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_BOOSTKNUCKLE 2256,0,0,3:6:9:12:15,0,0,0,99,0,0,mado,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_BOOSTKNUCKLE
2257,0,0,50,0,0,0,99,0,0,mado,0,0,1549,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_PILEBUNKER 2257,0,0,50,0,0,0,99,0,0,mado,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1549 //NC_PILEBUNKER
2258,0,0,2:4:6,0,0,0,99,0,0,mado,0,0,6145,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_VULCANARM 2258,0,0,2:4:6,0,0,0,99,0,0,mado,0,0,6145,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_VULCANARM
2259,0,0,20,0,0,0,99,0,0,mado,0,0,2139,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_FLAMELAUNCHER 2259,0,0,20,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2139 //NC_FLAMELAUNCHER
2260,0,0,20,0,0,0,99,0,0,mado,0,0,6146,1,6147,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_COLDSLOWER 2260,0,0,20,0,0,0,99,0,0,mado,0,0,6146,1,6147,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_COLDSLOWER
2261,0,0,40:45:50,0,0,0,99,8,1,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_ARMSCANNON 2261,0,0,40:45:50,0,0,0,99,8,1,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_ARMSCANNON
2262,0,0,20:40:60,0,0,0,99,0,0,mado,0,0,2800,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_ACCELERATION 2262,0,0,20:40:60,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2800 //NC_ACCELERATION
2263,0,0,25,0,0,0,99,0,0,mado,0,0,2801,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_HOVERING 2263,0,0,25,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2801 //NC_HOVERING
2264,0,0,5,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_F_SIDESLIDE 2264,0,0,5,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_F_SIDESLIDE
2265,0,0,5,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_B_SIDESLIDE 2265,0,0,5,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_B_SIDESLIDE
2267,0,0,1,0,0,0,99,0,0,mado,0,0,2802,0,6146,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_SELFDESTRUCTION 2267,0,0,1,0,0,0,99,0,0,mado,0,0,6146,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2802 //NC_SELFDESTRUCTION
2268,0,0,100,0,0,0,99,0,0,mado,0,0,2803,0,6360,1,6363,1,6362,1,6361,1,6146,2,0,0,0,0,0,0,0,0,0 //NC_SHAPESHIFT 2268,0,0,100,0,0,0,99,0,0,mado,0,0,6360,1,6363,1,6362,1,6361,1,0,0,0,0,0,0,0,0,0,0,6146,2,2803 //NC_SHAPESHIFT
2269,0,0,20,0,0,0,99,0,0,mado,0,0,2804,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_EMERGENCYCOOL 2269,0,0,20,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2804 //NC_EMERGENCYCOOL
2270,0,0,45,0,0,0,99,0,0,mado,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_INFRAREDSCAN 2270,0,0,45,0,0,0,99,0,0,mado,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_INFRAREDSCAN
2271,0,0,30,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_ANALYZE 2271,0,0,30,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_ANALYZE
2272,0,0,90,0,0,0,99,0,0,mado,0,0,2805,0,6146,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_MAGNETICFIELD 2272,0,0,90,0,0,0,99,0,0,mado,0,0,6146,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2805 //NC_MAGNETICFIELD
2273,0,0,90,0,0,0,99,0,0,mado,0,0,2806,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_NEUTRALBARRIER 2273,0,0,90,0,0,0,99,0,0,mado,0,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2806 //NC_NEUTRALBARRIER
2274,0,0,100:150:200,0,0,0,99,0,0,mado,0,0,2808,0,6146,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_STEALTHFIELD 2274,0,0,100:150:200,0,0,0,99,0,0,mado,0,0,6146,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2808 //NC_STEALTHFIELD
2275,0,0,25:30:35:40:45,0,0,0,99,0,0,mado,0,0,2807,0,6146,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //NC_REPAIR 2275,0,0,25:30:35:40:45,0,0,0,99,0,0,mado,0,0,12392,1,12392,1,12393,1,12393,1,12394,1,0,0,0,0,0,0,0,0,6146,1,2807 //NC_REPAIR
2278,0,0,20:22:24:26:28,0,0,0,6:7,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_AXEBOOMERANG 2278,0,0,20:22:24:26:28,0,0,0,6:7,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_AXEBOOMERANG
2279,0,0,20:22:24:26:28,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_POWERSWING 2279,0,0,20:22:24:26:28,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_POWERSWING

View File

@ -4353,10 +4353,10 @@ in this manner cannot be dropped, sold, vended, auctioned, or mailed, and in
some cases cannot be traded or stored. some cases cannot be traded or stored.
Valid bound types are: Valid bound types are:
1 - Account Bound Bound_Account : Account Bound item
2 - Guild Bound Bound_Guild : Guild Bound item
3 - Party Bound Bound_Party : Party Bound item
4 - Character Bound Bound_Char : Character Bound item
--------------------------------------- ---------------------------------------
@ -4506,8 +4506,8 @@ See 'getitem2' for an explanation of the expanded parameters.
*cartdelitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}; *cartdelitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
*cartdelitem2 "<item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}; *cartdelitem2 "<item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
*storageitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}; *storagedelitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
*storageitem2 "<item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}; *storagedelitem2 "<item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
Same like delitem2, but deletes item from cart or storage. Same like delitem2, but deletes item from cart or storage.
If cart is not mounted, it will be failed. If cart is not mounted, it will be failed.

View File

@ -184,7 +184,7 @@ static bool mail_loadmessage(int mail_id, struct mail_message* msg)
Sql_GetData(sql_handle,14, &data, NULL); msg->item.identify = atoi(data); Sql_GetData(sql_handle,14, &data, NULL); msg->item.identify = atoi(data);
Sql_GetData(sql_handle,15, &data, NULL); msg->item.unique_id = strtoull(data, NULL, 10); Sql_GetData(sql_handle,15, &data, NULL); msg->item.unique_id = strtoull(data, NULL, 10);
msg->item.expire_time = 0; msg->item.expire_time = 0;
msg->item.bound = 0; msg->item.bound = BOUND_NONE;
for( j = 0; j < MAX_SLOTS; j++ ) for( j = 0; j < MAX_SLOTS; j++ )
{ {

View File

@ -289,7 +289,7 @@ int mapif_parse_itembound_retrieve(int fd)
SqlStmt_BindColumn(stmt, 9+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL); SqlStmt_BindColumn(stmt, 9+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
while( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) { while( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) {
if(item.bound == 2) { if(item.bound == BOUND_GUILD) {
memcpy(&items[i],&item,sizeof(struct item)); memcpy(&items[i],&item,sizeof(struct item));
i++; i++;
} }

View File

@ -785,6 +785,16 @@ enum {
SEX_SERVER SEX_SERVER
}; };
/// Item Bound Type
enum bound_type {
BOUND_NONE = 0, /// No bound
BOUND_ACCOUNT, /// 1- Account Bound
BOUND_GUILD, /// 2 - Guild Bound
BOUND_PARTY, /// 3 - Party Bound
BOUND_CHAR, /// 4 - Character Bound
BOUND_MAX
};
// sanity checks... // sanity checks...
#if MAX_ZENY > INT_MAX #if MAX_ZENY > INT_MAX
#error MAX_ZENY is too big #error MAX_ZENY is too big

View File

@ -62,12 +62,7 @@
/// Uncomment to enable skills damage adjustments /// Uncomment to enable skills damage adjustments
/// By enabling this, db/skill_damage.txt and the skill_damage mapflag will adjust the /// By enabling this, db/skill_damage.txt and the skill_damage mapflag will adjust the
/// damage rate of specified skills. /// damage rate of specified skills.
//#define ADJUST_SKILL_DAMAGE #define ADJUST_SKILL_DAMAGE
/// The skill damage adjustment rate is capped at 100000.
#ifdef ADJUST_SKILL_DAMAGE
#define MAX_SKILL_DAMAGE_RATE 100000
#endif
/// Uncomment to enable the job base HP/SP table (job_basehpsp_db.txt) /// Uncomment to enable the job base HP/SP table (job_basehpsp_db.txt)
//#define HP_SP_TABLES //#define HP_SP_TABLES

View File

@ -13,7 +13,7 @@
static char global_db_hostname[32] = "127.0.0.1"; static char global_db_hostname[32] = "127.0.0.1";
static uint16 global_db_port = 3306; static uint16 global_db_port = 3306;
static char global_db_username[32] = "ragnarok"; static char global_db_username[32] = "ragnarok";
static char global_db_password[32] = "ragnarok"; static char global_db_password[32] = "";
static char global_db_database[32] = "ragnarok"; static char global_db_database[32] = "ragnarok";
static char global_codepage[32] = ""; static char global_codepage[32] = "";
// local sql settings // local sql settings

View File

@ -1198,7 +1198,7 @@ ACMD_FUNC(heal)
ACMD_FUNC(item) ACMD_FUNC(item)
{ {
char item_name[100]; char item_name[100];
int number = 0, flag = 0, bound = 0; int number = 0, flag = 0, bound = BOUND_NONE;
struct item item_tmp; struct item item_tmp;
struct item_data *item_data[10]; struct item_data *item_data[10];
int get_count, i, j=0; int get_count, i, j=0;
@ -1207,12 +1207,19 @@ ACMD_FUNC(item)
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
memset(item_name, '\0', sizeof(item_name)); memset(item_name, '\0', sizeof(item_name));
if (!strcmpi(command+1,"itembound") && (!message || !*message || ( if (!strcmpi(command+1,"itembound")) {
sscanf(message, "\"%99[^\"]\" %d %d", item_name, &number, &bound) < 2 && if (!message || !*message || (
sscanf(message, "%99s %d %d", item_name, &number, &bound) < 2 sscanf(message, "\"%99[^\"]\" %d %d", item_name, &number, &bound) < 3 &&
))) { sscanf(message, "%99s %d %d", item_name, &number, &bound) < 3))
clif_displaymessage(fd, msg_txt(sd,295)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity> <bound_type>). {
return -1; clif_displaymessage(fd, msg_txt(sd,295)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity> <bound_type>).
clif_displaymessage(fd, msg_txt(sd,298)); // Invalid bound type
return -1;
}
if( bound <= BOUND_NONE || bound >= BOUND_MAX ) {
clif_displaymessage(fd, msg_txt(sd,298)); // Invalid bound type
return -1;
}
} else if (!message || !*message || ( } else if (!message || !*message || (
sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 && sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 &&
sscanf(message, "%99s %d", item_name, &number) < 1 sscanf(message, "%99s %d", item_name, &number) < 1
@ -1231,11 +1238,6 @@ ACMD_FUNC(item)
j++; j++;
} }
if( bound < 0 || bound > 4 ) {
clif_displaymessage(fd, msg_txt(sd,298)); // Invalid bound type
return -1;
}
if (number <= 0) if (number <= 0)
number = 1; number = 1;
get_count = number; get_count = number;
@ -1273,19 +1275,27 @@ ACMD_FUNC(item2)
struct item item_tmp; struct item item_tmp;
struct item_data *item_data; struct item_data *item_data;
char item_name[100]; char item_name[100];
int item_id, number = 0, bound = 0; int item_id, number = 0, bound = BOUND_NONE;
int identify = 0, refine = 0, attr = 0; int identify = 0, refine = 0, attr = 0;
int c1 = 0, c2 = 0, c3 = 0, c4 = 0; int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
memset(item_name, '\0', sizeof(item_name)); memset(item_name, '\0', sizeof(item_name));
if (!strcmpi(command+1,"itembound2") && (!message || !*message || ( if (!strcmpi(command+1,"itembound2")) {
sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 && if (!message || !*message || (
sscanf(message, "%99s %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 ))) { sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 &&
clif_displaymessage(fd, msg_txt(sd,296)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity> sscanf(message, "%99s %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 ))
clif_displaymessage(fd, msg_txt(sd,297)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4> <bound_type>). {
return -1; clif_displaymessage(fd, msg_txt(sd,296)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity>
clif_displaymessage(fd, msg_txt(sd,297)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4> <bound_type>).
clif_displaymessage(fd, msg_txt(sd,298)); // Invalid bound type
return -1;
}
if( bound <= BOUND_NONE || bound >= BOUND_MAX ) {
clif_displaymessage(fd, msg_txt(sd,298)); // Invalid bound type
return -1;
}
} else if ( !message || !*message || ( } else if ( !message || !*message || (
sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 && sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 &&
sscanf(message, "%99s %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 sscanf(message, "%99s %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9
@ -1298,11 +1308,6 @@ ACMD_FUNC(item2)
if (number <= 0) if (number <= 0)
number = 1; number = 1;
if( bound < 0 || bound > 4 ) {
clif_displaymessage(fd, msg_txt(sd,298)); // Invalid bound type
return -1;
}
item_id = 0; item_id = 0;
if ((item_data = itemdb_searchname(item_name)) != NULL || if ((item_data = itemdb_searchname(item_name)) != NULL ||
(item_data = itemdb_exists(atoi(item_name))) != NULL) (item_data = itemdb_exists(atoi(item_name))) != NULL)
@ -3926,7 +3931,7 @@ ACMD_FUNC(mapinfo) {
if (map[m_id].skill_damage[j].skill_id) { if (map[m_id].skill_damage[j].skill_id) {
sprintf(atcmd_output," %d. %s : %d%%, %d%%, %d%%, %d%% | %d" sprintf(atcmd_output," %d. %s : %d%%, %d%%, %d%%, %d%% | %d"
,j+1 ,j+1
,skill_db[skill_get_index(map[m_id].skill_damage[j].skill_id)].name ,skill_get_name(map[m_id].skill_damage[j].skill_id)
,map[m_id].skill_damage[j].pc ,map[m_id].skill_damage[j].pc
,map[m_id].skill_damage[j].mob ,map[m_id].skill_damage[j].mob
,map[m_id].skill_damage[j].boss ,map[m_id].skill_damage[j].boss

View File

@ -1066,7 +1066,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
DAMAGE_SUBRATE(sc->data[SC_GRANITIC_ARMOR]->val2) DAMAGE_SUBRATE(sc->data[SC_GRANITIC_ARMOR]->val2)
if(sc->data[SC_PAIN_KILLER]) if(sc->data[SC_PAIN_KILLER])
DAMAGE_SUBRATE(sc->data[SC_PAIN_KILLER]->val3); damage -= sc->data[SC_PAIN_KILLER]->val3;
if( sc->data[SC_DARKCROW] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT ) if( sc->data[SC_DARKCROW] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT )
DAMAGE_ADDRATE(sc->data[SC_DARKCROW]->val2); DAMAGE_ADDRATE(sc->data[SC_DARKCROW]->val2);
@ -1723,45 +1723,44 @@ static int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id)
return 0; return 0;
} }
/*========================================== /** Damage calculation for adjusting skill damage
* Damage calculation for adjusting skill damage * @param caster Applied caster type for damage skill
* Credits: * @param type BL_Type of attacker
[Lilith] for the first release of this * @author [Lilith] for the first release of this, [Cydh]
[Cydh] finishing and adding mapflag **/
* battle_skill_damage_skill() - skill_id based
* battle_skill_damage_map() - map based
*------------------------------------------*/
#ifdef ADJUST_SKILL_DAMAGE #ifdef ADJUST_SKILL_DAMAGE
static bool battle_skill_damage_iscaster(uint8 caster, enum bl_type type) static bool battle_skill_damage_iscaster(uint8 caster, enum bl_type src_type) {
{
if (caster == 0) if (caster == 0)
return false; return false;
while (1) { switch (src_type) {
if (caster&SDC_PC && type == BL_PC) break; case BL_PC: if (caster&SDC_PC) return true; break;
if (caster&SDC_MOB && type == BL_MOB) break; case BL_MOB: if (caster&SDC_MOB) return true; break;
if (caster&SDC_PET && type == BL_PET) break; case BL_PET: if (caster&SDC_PET) return true; break;
if (caster&SDC_HOM && type == BL_HOM) break; case BL_HOM: if (caster&SDC_HOM) return true; break;
if (caster&SDC_MER && type == BL_MER) break; case BL_MER: if (caster&SDC_MER) return true; break;
if (caster&SDC_ELEM && type == BL_ELEM) break; case BL_ELEM: if (caster&SDC_ELEM) return true; break;
return false;
} }
return true; return false;
} }
static int battle_skill_damage_skill(struct block_list *src, struct block_list *target, uint16 skill_id) /** Gets skill damage rate from a skill (based on skill_damage_db.txt)
{ * @param src
unsigned short m = src->m; * @param target
int idx; * @param skill_id
* @return Skill damage rate
*/
static int battle_skill_damage_skill(struct block_list *src, struct block_list *target, uint16 skill_id) {
uint16 idx = skill_get_index(skill_id), m = src->m;
struct s_skill_damage *damage = NULL; struct s_skill_damage *damage = NULL;
if ((idx = skill_get_index(skill_id)) < 0 || !skill_db[idx].damage.map) if (!idx || !skill_db[idx].damage.map)
return 0; return 0;
damage = &skill_db[idx].damage; damage = &skill_db[idx].damage;
//check the adjustment works for specified type //check the adjustment works for specified type
if (!battle_skill_damage_iscaster(damage->caster,src->type)) if (!battle_skill_damage_iscaster(damage->caster, src->type))
return 0; return 0;
if ((damage->map&1 && (!map[m].flag.pvp && !map_flag_gvg(m) && !map[m].flag.battleground && !map[m].flag.skill_damage && !map[m].flag.restricted)) || if ((damage->map&1 && (!map[m].flag.pvp && !map_flag_gvg(m) && !map[m].flag.battleground && !map[m].flag.skill_damage && !map[m].flag.restricted)) ||
@ -1787,8 +1786,13 @@ static int battle_skill_damage_skill(struct block_list *src, struct block_list *
return 0; return 0;
} }
static int battle_skill_damage_map(struct block_list *src, struct block_list *target, uint16 skill_id) /** Gets skill damage rate from a skill (based on 'skill_damage' mapflag)
{ * @param src
* @param target
* @param skill_id
* @return Skill damage rate
*/
static int battle_skill_damage_map(struct block_list *src, struct block_list *target, uint16 skill_id) {
int rate = 0; int rate = 0;
uint16 m = src->m; uint16 m = src->m;
uint8 i; uint8 i;
@ -1796,8 +1800,8 @@ static int battle_skill_damage_map(struct block_list *src, struct block_list *ta
if (!map[m].flag.skill_damage) if (!map[m].flag.skill_damage)
return 0; return 0;
/* modifier for all skills */ // Damage rate for all skills at this map
if (battle_skill_damage_iscaster(map[m].adjust.damage.caster,src->type)) { if (battle_skill_damage_iscaster(map[m].adjust.damage.caster, src->type)) {
switch (target->type) { switch (target->type) {
case BL_PC: case BL_PC:
rate = map[m].adjust.damage.pc; rate = map[m].adjust.damage.pc;
@ -1814,10 +1818,10 @@ static int battle_skill_damage_map(struct block_list *src, struct block_list *ta
} }
} }
/* modifier for specified map */ // Damage rate for specified skill at this map
ARR_FIND(0,MAX_MAP_SKILL_MODIFIER,i,map[m].skill_damage[i].skill_id == skill_id); ARR_FIND(0, ARRAYLENGTH(map[m].skill_damage), i, map[m].skill_damage[i].skill_id == skill_id);
if (i < MAX_MAP_SKILL_MODIFIER) { if (i < ARRAYLENGTH(map[m].skill_damage)) {
if (battle_skill_damage_iscaster(map[m].skill_damage[i].caster,src->type)) { if (battle_skill_damage_iscaster(map[m].skill_damage[i].caster, src->type)) {
switch (target->type) { switch (target->type) {
case BL_PC: case BL_PC:
rate += map[m].skill_damage[i].pc; rate += map[m].skill_damage[i].pc;
@ -1837,11 +1841,16 @@ static int battle_skill_damage_map(struct block_list *src, struct block_list *ta
return rate; return rate;
} }
static int battle_skill_damage(struct block_list *src, struct block_list *target, uint16 skill_id) /** Check skill damage adjustment based on mapflags and skill_damage_db.txt for specified skill
{ * @param src
* @param target
* @param skill_id
* @return Total damage rate
*/
static int battle_skill_damage(struct block_list *src, struct block_list *target, uint16 skill_id) {
if (!target) if (!target)
return 0; return 0;
return battle_skill_damage_skill(src,target,skill_id) + battle_skill_damage_map(src,target,skill_id); return battle_skill_damage_skill(src, target, skill_id) + battle_skill_damage_map(src, target, skill_id);
} }
#endif #endif
@ -2865,9 +2874,9 @@ struct Damage battle_calc_skill_base_damage(struct Damage wd, struct block_list
} }
//For quick div adjustment. //For quick div adjustment.
#define damage_div_fix(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; } #define DAMAGE_DIV_FIX(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; }
#define damage_div_fix2(dmg, div) { if (div > 1) (dmg)*=div; } #define DAMAGE_DIV_FIX2(dmg, div) { if (div > 1) (dmg)*=div; }
#define damage_div_fix_renewal(wd, div) { damage_div_fix2(wd.statusAtk, div); damage_div_fix2(wd.weaponAtk, div); damage_div_fix2(wd.equipAtk, div); damage_div_fix2(wd.masteryAtk, div); } #define DAMAGE_DIV_FIX_RENEWAL(wd, div) { DAMAGE_DIV_FIX2(wd.statusAtk, div); DAMAGE_DIV_FIX2(wd.weaponAtk, div); DAMAGE_DIV_FIX2(wd.equipAtk, div); DAMAGE_DIV_FIX2(wd.masteryAtk, div); }
/*======================================= /*=======================================
* Check for and calculate multi attacks * Check for and calculate multi attacks
*--------------------------------------- *---------------------------------------
@ -3825,8 +3834,8 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
break; break;
case RL_D_TAIL: case RL_D_TAIL:
skillratio += -100 + (2500 + 500 * skill_lv ); skillratio += -100 + (2500 + 500 * skill_lv );
if (sd && &sd->c_marker) //if (sd && &sd->c_marker)
skillratio /= max(sd->c_marker.count,1); // skillratio /= max(sd->c_marker.count,1);
break; break;
case RL_R_TRIP: case RL_R_TRIP:
skillratio += -100 + (150 * skill_lv); //(custom) skillratio += -100 + (150 * skill_lv); //(custom)
@ -3849,6 +3858,9 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
case RL_FIRE_RAIN: case RL_FIRE_RAIN:
skillratio += -100 + 2000 + status_get_dex(src); //(custom) //kRO Update 2013-07-24. 2,000% + caster's DEX (?) [Cydh] skillratio += -100 + 2000 + status_get_dex(src); //(custom) //kRO Update 2013-07-24. 2,000% + caster's DEX (?) [Cydh]
break; break;
case RL_AM_BLAST:
skillratio += -100 + (skill_lv * status_get_dex(src) / 2); //(custom)
break;
} }
return skillratio; return skillratio;
} }
@ -4656,7 +4668,7 @@ struct Damage battle_calc_weapon_final_atk_modifiers(struct Damage wd, struct bl
#endif #endif
} }
/* Skill damage adjustment */ // Skill damage adjustment
#ifdef ADJUST_SKILL_DAMAGE #ifdef ADJUST_SKILL_DAMAGE
if ((skill_damage = battle_skill_damage(src, target, skill_id)) != 0) if ((skill_damage = battle_skill_damage(src, target, skill_id)) != 0)
ATK_ADDRATE(wd.damage, wd.damage2, skill_damage); ATK_ADDRATE(wd.damage, wd.damage2, skill_damage);
@ -5118,9 +5130,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
} }
// perform multihit calculations // perform multihit calculations
damage_div_fix_renewal(wd, wd.div_); DAMAGE_DIV_FIX_RENEWAL(wd, wd.div_);
#endif #endif
damage_div_fix(wd.damage, wd.div_); DAMAGE_DIV_FIX(wd.damage, wd.div_);
// only do 1 dmg to plant, no need to calculate rest // only do 1 dmg to plant, no need to calculate rest
if(target_has_infinite_defense(target, skill_id)) if(target_has_infinite_defense(target, skill_id))
@ -5886,7 +5898,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
#endif #endif
} }
damage_div_fix(ad.damage, ad.div_); DAMAGE_DIV_FIX(ad.damage, ad.div_);
if (flag.infdef && ad.damage) if (flag.infdef && ad.damage)
ad.damage = ad.damage>0?1:-1; ad.damage = ad.damage>0?1:-1;
@ -5906,7 +5918,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
break; break;
} }
/* Skill damage adjustment */ // Skill damage adjustment
#ifdef ADJUST_SKILL_DAMAGE #ifdef ADJUST_SKILL_DAMAGE
if ((skill_damage = battle_skill_damage(src,target,skill_id)) != 0) if ((skill_damage = battle_skill_damage(src,target,skill_id)) != 0)
MATK_ADDRATE(skill_damage); MATK_ADDRATE(skill_damage);
@ -6015,7 +6027,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
if (skill_id == SN_FALCONASSAULT) { if (skill_id == SN_FALCONASSAULT) {
//Div fix of Blitzbeat //Div fix of Blitzbeat
damage_div_fix2(md.damage, skill_get_num(HT_BLITZBEAT, 5)); DAMAGE_DIV_FIX2(md.damage, skill_get_num(HT_BLITZBEAT, 5));
//Falcon Assault Modifier //Falcon Assault Modifier
md.damage=(int64)md.damage*(150+70*skill_lv)/100; md.damage=(int64)md.damage*(150+70*skill_lv)/100;
@ -6189,7 +6201,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill_get_name(skill_id)); ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill_get_name(skill_id));
} }
damage_div_fix(md.damage, md.div_); DAMAGE_DIV_FIX(md.damage, md.div_);
if (!(nk&NK_IGNORE_FLEE)) if (!(nk&NK_IGNORE_FLEE))
{ {
@ -6294,7 +6306,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
break; break;
} }
/* Skill damage adjustment */ // Skill damage adjustment
#ifdef ADJUST_SKILL_DAMAGE #ifdef ADJUST_SKILL_DAMAGE
if ((skill_damage = battle_skill_damage(src,target,skill_id)) != 0) if ((skill_damage = battle_skill_damage(src,target,skill_id)) != 0)
md.damage += (int64)md.damage * skill_damage / 100; md.damage += (int64)md.damage * skill_damage / 100;

View File

@ -2261,7 +2261,7 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail)
WFIFOL(fd,offs+23)=sd->status.inventory[n].expire_time; WFIFOL(fd,offs+23)=sd->status.inventory[n].expire_time;
#endif #endif
#if PACKETVER >= 20071002 #if PACKETVER >= 20071002
WFIFOW(fd,offs+27)=sd->status.inventory[n].bound ? 2 : 0; WFIFOW(fd,offs+27)=sd->status.inventory[n].bound ? BOUND_GUILD : 0;
#endif #endif
} }
@ -2367,7 +2367,7 @@ void clif_item_sub(unsigned char *buf, int n, int idx, struct item *i, struct it
clif_addcards(WBUFP(buf, n+12), i); //8B clif_addcards(WBUFP(buf, n+12), i); //8B
#if PACKETVER >= 20071002 #if PACKETVER >= 20071002
WBUFL(buf,n+20)=i->expire_time; WBUFL(buf,n+20)=i->expire_time;
WBUFW(buf,n+24)=i->bound ? 2 : 0; WBUFW(buf,n+24)=i->bound ? BOUND_GUILD : 0;
#endif #endif
#if PACKETVER >= 20100629 #if PACKETVER >= 20100629
WBUFW(buf,n+26)= (id->equip&EQP_VISIBLE)?id->look:0; WBUFW(buf,n+26)= (id->equip&EQP_VISIBLE)?id->look:0;

View File

@ -561,19 +561,19 @@ int elemental_unlocktarget(struct elemental_data *ed) {
return 0; return 0;
} }
int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed) { bool elemental_skillnotok(uint16 skill_id, struct elemental_data *ed) {
int idx = skill_get_index(skill_id); uint16 idx = skill_get_index(skill_id);
nullpo_retr(1,ed); nullpo_retr(1,ed);
if (idx == 0) if (idx == 0)
return 1; // invalid skill id return false; // invalid skill id
return skill_isNotOk(skill_id,ed->master); return skill_isNotOk(skill_id,ed->master);
} }
struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){ struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){
struct skill_condition req; struct skill_condition req;
int idx = skill_get_index(skill_id); uint16 idx = skill_get_index(skill_id);
memset(&req,0,sizeof(req)); memset(&req,0,sizeof(req));

View File

@ -92,7 +92,7 @@ void elemental_summon_stop(struct elemental_data *ed);
int elemental_get_lifetime(struct elemental_data *ed); int elemental_get_lifetime(struct elemental_data *ed);
int elemental_unlocktarget(struct elemental_data *ed); int elemental_unlocktarget(struct elemental_data *ed);
int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed); bool elemental_skillnotok(uint16 skill_id, struct elemental_data *ed);
int elemental_set_target( struct map_session_data *sd, struct block_list *bl ); int elemental_set_target( struct map_session_data *sd, struct block_list *bl );
int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id); int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id);
int elemental_clean_effect(struct elemental_data *ed); int elemental_clean_effect(struct elemental_data *ed);

View File

@ -1807,7 +1807,7 @@ int guild_break(struct map_session_data *sd,char *name) {
//Guild bound item check - Removes the bound flag //Guild bound item check - Removes the bound flag
j = pc_bound_chk(sd,2,idxlist); j = pc_bound_chk(sd,2,idxlist);
for(i=0;i<j;i++) for(i=0;i<j;i++)
sd->status.inventory[idxlist[i]].bound = 0; sd->status.inventory[idxlist[i]].bound = BOUND_NONE;
#endif #endif
intif_guild_break(g->guild_id); intif_guild_break(g->guild_id);

View File

@ -471,13 +471,14 @@ struct item_data* itemdb_search(int nameid)
return id; return id;
} }
/*========================================== /** Checks if item is equip type or not
* Returns if given item is a player-equippable piece. * @param id Item data
*------------------------------------------*/ * @return True if item is equip, false otherwise
bool itemdb_isequip(int nameid) */
bool itemdb_isequip2(struct item_data *id)
{ {
int type=itemdb_type(nameid); nullpo_ret(id);
switch (type) { switch(id->type) {
case IT_WEAPON: case IT_WEAPON:
case IT_ARMOR: case IT_ARMOR:
case IT_AMMO: case IT_AMMO:
@ -488,48 +489,14 @@ bool itemdb_isequip(int nameid)
} }
} }
/*========================================== /** Checks if item is stackable or not
* Alternate version of itemdb_isequip * @param id Item data
*------------------------------------------*/ * @return True if item is stackable, false otherwise
bool itemdb_isequip2(struct item_data *data) */
bool itemdb_isstackable2(struct item_data *id)
{ {
nullpo_ret(data); nullpo_ret(id);
switch(data->type) { switch(id->type) {
case IT_WEAPON:
case IT_ARMOR:
case IT_AMMO:
case IT_SHADOWGEAR:
return true;
default:
return false;
}
}
/*==========================================
* Returns if given item's type is stackable.
*------------------------------------------*/
bool itemdb_isstackable(uint16 nameid)
{
uint8 type = itemdb_type(nameid);
switch(type) {
case IT_WEAPON:
case IT_ARMOR:
case IT_PETEGG:
case IT_PETARMOR:
case IT_SHADOWGEAR:
return false;
default:
return true;
}
}
/*==========================================
* Alternate version of itemdb_isstackable
*------------------------------------------*/
bool itemdb_isstackable2(struct item_data *data)
{
nullpo_ret(data);
switch(data->type) {
case IT_WEAPON: case IT_WEAPON:
case IT_ARMOR: case IT_ARMOR:
case IT_PETEGG: case IT_PETEGG:
@ -665,7 +632,7 @@ static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
unsigned int j, prob = 1; unsigned int j, prob = 1;
uint16 nameid, amt = 1, dur = 0; uint16 nameid, amt = 1, dur = 0;
uint8 rand_group = 1; uint8 rand_group = 1;
char *str[9], *p, announced = 0, named = 0, bound = 0; char *str[9], *p, announced = 0, named = 0, bound = BOUND_NONE;
struct s_item_group_random *random = NULL; struct s_item_group_random *random = NULL;
struct s_item_group_db *group = NULL; struct s_item_group_db *group = NULL;
bool found = false; bool found = false;
@ -739,7 +706,7 @@ static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
if (str[5] != NULL) announced = atoi(str[5]); if (str[5] != NULL) announced = atoi(str[5]);
if (str[6] != NULL) dur = cap_value(atoi(str[6]),0,UINT16_MAX); if (str[6] != NULL) dur = cap_value(atoi(str[6]),0,UINT16_MAX);
if (str[7] != NULL) named = atoi(str[7]); if (str[7] != NULL) named = atoi(str[7]);
if (str[8] != NULL) bound = cap_value(atoi(str[8]),0,4); if (str[8] != NULL) bound = cap_value(atoi(str[8]),BOUND_NONE,BOUND_MAX-1);
found = true; found = true;
if (!(group = (struct s_item_group_db *) idb_get(itemdb_group, group_id))) { if (!(group = (struct s_item_group_db *) idb_get(itemdb_group, group_id))) {
@ -986,23 +953,25 @@ static bool itemdb_read_nouse(char* fields[], int columns, int current) {
/** Misc Item flags /** Misc Item flags
* <item_id>,<flag> * <item_id>,<flag>
* &1 - Log as dead branch * &1 - As dead branch item
* &2 - As item container * &2 - As item container
*/ */
static bool itemdb_read_flag(char* fields[], int columns, int current) { static bool itemdb_read_flag(char* fields[], int columns, int current) {
uint16 nameid = atoi(fields[0]); uint16 nameid = atoi(fields[0]);
uint8 flag = atoi(fields[1]); uint8 flag;
bool set;
struct item_data *id; struct item_data *id;
if (!(id = itemdb_exists(nameid))) { if (!(id = itemdb_exists(nameid))) {
ShowError("itemdb_read_flag: Invalid item item with id %d\n", nameid); ShowError("itemdb_read_flag: Invalid item item with id %d\n", nameid);
return true; return true;
} }
flag = abs(atoi(fields[1]));
set = atoi(fields[1]) > 0;
if (flag&1) if (flag&1) id->flag.dead_branch = set ? 1 : 0;
id->flag.dead_branch = 1; if (flag&2) id->flag.group = set ? 1 : 0;
if (flag&2)
id->flag.group = 1;
return true; return true;
} }
@ -1653,7 +1622,8 @@ static void destroy_item_data(struct item_data* self, bool free_self) {
for( i = 0; i < self->combos_count; i++ ) { for( i = 0; i < self->combos_count; i++ ) {
if( !self->combos[i]->isRef ) { if( !self->combos[i]->isRef ) {
aFree(self->combos[i]->nameid); aFree(self->combos[i]->nameid);
script_free_code(self->combos[i]->script); if (self->combos[i]->script)
script_free_code(self->combos[i]->script);
} }
aFree(self->combos[i]); aFree(self->combos[i]);
} }

View File

@ -475,11 +475,11 @@ bool itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(str
#define itemdb_canmail(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canmail_sub) #define itemdb_canmail(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canmail_sub)
#define itemdb_canauction(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canauction_sub) #define itemdb_canauction(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canauction_sub)
bool itemdb_isequip(int); bool itemdb_isequip2(struct item_data *id);
bool itemdb_isequip2(struct item_data *); #define itemdb_isequip(nameid) itemdb_isequip2(itemdb_search(nameid))
char itemdb_isidentified(int); char itemdb_isidentified(int);
bool itemdb_isstackable(uint16 nameid); bool itemdb_isstackable2(struct item_data *id);
bool itemdb_isstackable2(struct item_data *data); #define itemdb_isstackable(nameid) itemdb_isstackable2(itemdb_search(nameid))
uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID
bool itemdb_isNoEquip(struct item_data *id, uint16 m); bool itemdb_isNoEquip(struct item_data *id, uint16 m);

View File

@ -65,7 +65,7 @@ char default_codepage[32] = "";
int map_server_port = 3306; int map_server_port = 3306;
char map_server_ip[32] = "127.0.0.1"; char map_server_ip[32] = "127.0.0.1";
char map_server_id[32] = "ragnarok"; char map_server_id[32] = "ragnarok";
char map_server_pw[32] = "ragnarok"; char map_server_pw[32] = "";
char map_server_db[32] = "ragnarok"; char map_server_db[32] = "ragnarok";
Sql* mmysql_handle; Sql* mmysql_handle;
@ -1677,6 +1677,7 @@ int map_quit(struct map_session_data *sd) {
status_change_end(&sd->bl, SC_GLORYWOUNDS, INVALID_TIMER); status_change_end(&sd->bl, SC_GLORYWOUNDS, INVALID_TIMER);
status_change_end(&sd->bl, SC_SOULCOLD, INVALID_TIMER); status_change_end(&sd->bl, SC_SOULCOLD, INVALID_TIMER);
status_change_end(&sd->bl, SC_HAWKEYES, INVALID_TIMER); status_change_end(&sd->bl, SC_HAWKEYES, INVALID_TIMER);
status_change_end(&sd->bl, SC_CHASEWALK2, INVALID_TIMER);
if(sd->sc.data[SC_ENDURE] && sd->sc.data[SC_ENDURE]->val4) if(sd->sc.data[SC_ENDURE] && sd->sc.data[SC_ENDURE]->val4)
status_change_end(&sd->bl, SC_ENDURE, INVALID_TIMER); //No need to save infinite endure. status_change_end(&sd->bl, SC_ENDURE, INVALID_TIMER); //No need to save infinite endure.
status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER); status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER);

View File

@ -124,9 +124,9 @@ int npc_isnear_sub(struct block_list* bl, va_list args) {
int skill_id = va_arg(args, int); int skill_id = va_arg(args, int);
if (skill_id > 0) { //If skill_id > 0 that means is used for INF2_NO_NEARNPC [Cydh] if (skill_id > 0) { //If skill_id > 0 that means is used for INF2_NO_NEARNPC [Cydh]
int16 idx = skill_get_index(skill_id); uint16 idx = skill_get_index(skill_id);
if (idx >= 0 && skill_db[idx].unit_nonearnpc_type) { if (idx > 0 && skill_db[idx].unit_nonearnpc_type) {
while (1) { while (1) {
if (skill_db[idx].unit_nonearnpc_type&1 && nd->subtype == WARP) break; if (skill_db[idx].unit_nonearnpc_type&1 && nd->subtype == WARP) break;
if (skill_db[idx].unit_nonearnpc_type&2 && nd->subtype == SHOP) break; if (skill_db[idx].unit_nonearnpc_type&2 && nd->subtype == SHOP) break;
@ -3723,40 +3723,46 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
map[m].flag.notomb = state; map[m].flag.notomb = state;
else if (!strcmpi(w3,"skill_damage")) { else if (!strcmpi(w3,"skill_damage")) {
#ifdef ADJUST_SKILL_DAMAGE #ifdef ADJUST_SKILL_DAMAGE
char skill[NAME_LENGTH]; char skill[SKILL_NAME_LENGTH];
int pc = 0, mob = 0, boss = 0, other = 0, caster = 0; int pc = 0, mob = 0, boss = 0, other = 0, caster = 0;
memset(skill,0,sizeof(skill)); memset(skill, 0, sizeof(skill));
map[m].flag.skill_damage = state; //set the mapflag map[m].flag.skill_damage = state; // Set the mapflag
if (sscanf(w4,"%24[^,],%d,%d,%d,%d,%d[^\n]",skill,&caster,&pc,&mob,&boss,&other) >= 3) { if (!state) {
caster = (!caster) ? SDC_ALL : caster; memset(map[m].skill_damage, 0, sizeof(map[m].skill_damage));
pc = cap_value(pc,-100,MAX_SKILL_DAMAGE_RATE); memset(&map[m].adjust.damage, 0, sizeof(map[m].adjust.damage));
mob = cap_value(mob,-100,MAX_SKILL_DAMAGE_RATE); }
boss = cap_value(boss,-100,MAX_SKILL_DAMAGE_RATE); else {
other = cap_value(other,-100,MAX_SKILL_DAMAGE_RATE); if (sscanf(w4, "%30[^,],%d,%d,%d,%d,%d[^\n]", skill, &caster, &pc, &mob, &boss, &other) >= 3) {
caster = (!caster) ? SDC_ALL : caster;
pc = cap_value(pc, -100, INT_MAX);
mob = cap_value(mob, -100, INT_MAX);
boss = cap_value(boss, -100, INT_MAX);
other = cap_value(other, -100, INT_MAX);
if (strcmp(skill,"all") == 0) { //adjust damages for all skills if (strcmp(skill,"all") == 0) { // Adjust damages for all skills
map[m].adjust.damage.caster = caster; map[m].adjust.damage.caster = caster;
map[m].adjust.damage.pc = pc; map[m].adjust.damage.pc = pc;
map[m].adjust.damage.mob = mob; map[m].adjust.damage.mob = mob;
map[m].adjust.damage.boss = boss; map[m].adjust.damage.boss = boss;
map[m].adjust.damage.other = other; map[m].adjust.damage.other = other;
} }
else if (skill_name2id(skill) <= 0) else if (skill_name2id(skill) <= 0)
ShowWarning("npc_parse_mapflag: skill_damage: Invalid skill name '%s'. Skipping (file '%s', line '%d')\n",skill,filepath,strline(buffer,start-buffer)); ShowWarning("npc_parse_mapflag: skill_damage: Invalid skill name '%s'. Skipping (file '%s', line '%d')\n", skill, filepath, strline(buffer,start-buffer));
else { //damages for specified skill else { //damages for specified skill
int i; uint8 i;
ARR_FIND(0,MAX_MAP_SKILL_MODIFIER,i,map[m].skill_damage[i].skill_id <= 0); ARR_FIND(0, ARRAYLENGTH(map[m].skill_damage), i, map[m].skill_damage[i].skill_id <= 0);
if (i >= MAX_SKILL) if (i >= ARRAYLENGTH(map[m].skill_damage))
ShowWarning("npc_parse_mapflag: skill_damage: Skill damage for map '%s' is overflow.\n",map[m].name); ShowWarning("npc_parse_mapflag: skill_damage: Skill damage for map '%s' is overflow.\n", map[m].name);
else { else {
map[m].skill_damage[i].skill_id = skill_name2id(skill); map[m].skill_damage[i].skill_id = skill_name2id(skill);
map[m].skill_damage[i].caster = caster; map[m].skill_damage[i].caster = caster;
map[m].skill_damage[i].pc = pc; map[m].skill_damage[i].pc = pc;
map[m].skill_damage[i].mob = mob; map[m].skill_damage[i].mob = mob;
map[m].skill_damage[i].boss = boss; map[m].skill_damage[i].boss = boss;
map[m].skill_damage[i].other = other; map[m].skill_damage[i].other = other;
}
} }
} }
} }

View File

@ -4132,15 +4132,17 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
return 0; return 0;
} }
/*========================================== /**
* Searching a specified itemid in inventory and return his stored index * Searching a specified itemid in inventory and return his stored index
*------------------------------------------*/ * @param sd Player
int pc_search_inventory(struct map_session_data *sd,int item_id) * @param nameid Find this Item!
{ * @return Stored index in inventory, or -1 if not found.
**/
short pc_search_inventory(struct map_session_data *sd, uint16 nameid) {
int16 i; int16 i;
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == item_id && (sd->status.inventory[i].amount > 0 || item_id == 0) ); ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid && (sd->status.inventory[i].amount > 0 || nameid == 0) );
return ( i < MAX_INVENTORY ) ? i : -1; return ( i < MAX_INVENTORY ) ? i : -1;
} }
@ -4736,7 +4738,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
return 1; return 1;
} }
if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) || (item_data->bound > 1 && !pc_can_give_bounded_items(sd))) if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) || (item_data->bound > BOUND_ACCOUNT && !pc_can_give_bounded_items(sd)))
{ // Check item trade restrictions [Skotlex] { // Check item trade restrictions [Skotlex]
clif_displaymessage (sd->fd, msg_txt(sd,264)); clif_displaymessage (sd->fd, msg_txt(sd,264));
return 1; return 1;
@ -4896,7 +4898,7 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
* 3 Party Bound * 3 Party Bound
* 4 Character Bound * 4 Character Bound
*------------------------------------------*/ *------------------------------------------*/
int pc_bound_chk(TBL_PC *sd,int type,int *idxlist) int pc_bound_chk(TBL_PC *sd,enum bound_type type,int *idxlist)
{ {
int i=0, j=0; int i=0, j=0;
for(i=0;i<MAX_INVENTORY;i++){ for(i=0;i<MAX_INVENTORY;i++){
@ -5308,17 +5310,17 @@ int pc_memo(struct map_session_data* sd, int pos)
* @param lv : skill lv * @param lv : skill lv
* @return player skill cooldown * @return player skill cooldown
*/ */
int pc_get_skillcooldown(struct map_session_data *sd, int id, int lv) { int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv) {
int i, cooldown=0; uint8 i;
int idx = skill_get_index (id); uint16 idx = skill_get_index(skill_id);
int cooldownlen = ARRAYLENGTH(sd->skillcooldown); int cooldown = 0, cooldownlen = ARRAYLENGTH(sd->skillcooldown);
if (!idx) return 0; if (!idx) return 0;
if (skill_db[idx].cooldown[lv - 1]) if (skill_db[idx].cooldown[skill_lv - 1])
cooldown = skill_db[idx].cooldown[lv - 1]; cooldown = skill_db[idx].cooldown[skill_lv - 1];
ARR_FIND(0, cooldownlen, i, sd->skillcooldown[i].id == id); ARR_FIND(0, cooldownlen, i, sd->skillcooldown[i].id == skill_id);
if(i<cooldownlen){ if (i < cooldownlen) {
cooldown += sd->skillcooldown[i].val; cooldown += sd->skillcooldown[i].val;
cooldown = max(0,cooldown); cooldown = max(0,cooldown);
} }

View File

@ -827,7 +827,7 @@ int pc_isequip(struct map_session_data *sd,int n);
int pc_equippoint(struct map_session_data *sd,int n); int pc_equippoint(struct map_session_data *sd,int n);
int pc_setinventorydata(struct map_session_data *sd); int pc_setinventorydata(struct map_session_data *sd);
int pc_get_skillcooldown(struct map_session_data *sd, int id, int lv); int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv);
int pc_checkskill(struct map_session_data *sd,uint16 skill_id); int pc_checkskill(struct map_session_data *sd,uint16 skill_id);
short pc_checkequip(struct map_session_data *sd,int pos); short pc_checkequip(struct map_session_data *sd,int pos);
bool pc_checkequip2(struct map_session_data *sd,int nameid,int min, int max); bool pc_checkequip2(struct map_session_data *sd,int nameid,int min, int max);
@ -851,14 +851,14 @@ int pc_memo(struct map_session_data* sd, int pos);
int pc_checkadditem(struct map_session_data*,int,int); int pc_checkadditem(struct map_session_data*,int,int);
int pc_inventoryblank(struct map_session_data*); int pc_inventoryblank(struct map_session_data*);
int pc_search_inventory(struct map_session_data *sd,int item_id); short pc_search_inventory(struct map_session_data *sd, uint16 nameid);
int pc_payzeny(struct map_session_data*,int, enum e_log_pick_type type, struct map_session_data*); int pc_payzeny(struct map_session_data*,int, enum e_log_pick_type type, struct map_session_data*);
char pc_additem(struct map_session_data *sd,struct item *item,int amount,e_log_pick_type log_type); char pc_additem(struct map_session_data *sd,struct item *item,int amount,e_log_pick_type log_type);
int pc_getzeny(struct map_session_data*,int, enum e_log_pick_type, struct map_session_data*); int pc_getzeny(struct map_session_data*,int, enum e_log_pick_type, struct map_session_data*);
int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type); int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type);
//Bound items //Bound items
int pc_bound_chk(TBL_PC *sd,int type,int *idxlist); int pc_bound_chk(TBL_PC *sd,enum bound_type type,int *idxlist);
// Special Shop System // Special Shop System
int pc_paycash( struct map_session_data *sd, int price, int points, e_log_pick_type type ); int pc_paycash( struct map_session_data *sd, int price, int points, e_log_pick_type type );

View File

@ -2289,6 +2289,7 @@ void script_hardcoded_constants(void) {
script_set_constant("Option_Invisible",OPTION_INVISIBLE,false); script_set_constant("Option_Invisible",OPTION_INVISIBLE,false);
script_set_constant("Option_Orcish",OPTION_ORCISH,false); script_set_constant("Option_Orcish",OPTION_ORCISH,false);
script_set_constant("Option_Wedding",OPTION_WEDDING,false); script_set_constant("Option_Wedding",OPTION_WEDDING,false);
script_set_constant("Option_Ruwach",OPTION_RUWACH,false);
script_set_constant("Option_Chasewalk",OPTION_CHASEWALK,false); script_set_constant("Option_Chasewalk",OPTION_CHASEWALK,false);
script_set_constant("Option_Flying",OPTION_FLYING,false); script_set_constant("Option_Flying",OPTION_FLYING,false);
script_set_constant("Option_Xmas",OPTION_XMAS,false); script_set_constant("Option_Xmas",OPTION_XMAS,false);
@ -6455,22 +6456,24 @@ BUILDIN_FUNC(getitem)
if( !strcmp(script_getfuncname(st),"getitembound") ) { if( !strcmp(script_getfuncname(st),"getitembound") ) {
char bound = script_getnum(st,4); char bound = script_getnum(st,4);
if( bound < 1 || bound > 4) { //Not a correct bound type if( bound > BOUND_NONE && bound < BOUND_MAX ) {
ShowError("script_getitembound: Not a correct bound type! Type=%d\n",bound); it.bound = bound;
return 1; if( script_hasdata(st,5) )
sd=map_id2sd(script_getnum(st,5));
else
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;
} }
it.bound = bound;
if( script_hasdata(st,5) )
sd=map_id2sd(script_getnum(st,5));
else
sd=script_rid2sd(st); // Attached player
} else if( script_hasdata(st,4) ) } 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 else
sd=script_rid2sd(st); // Attached player sd=script_rid2sd(st); // Attached player
if( sd == NULL ) // no target if( sd == NULL ) // no target
return 0; return SCRIPT_CMD_SUCCESS;
//Check if it's stackable. //Check if it's stackable.
if (!itemdb_isstackable(nameid)) if (!itemdb_isstackable(nameid))
@ -6499,9 +6502,9 @@ BUILDIN_FUNC(getitem)
*------------------------------------------*/ *------------------------------------------*/
BUILDIN_FUNC(getitem2) BUILDIN_FUNC(getitem2)
{ {
int nameid,amount,get_count,i,flag = 0; int nameid, amount, get_count, i, flag = 0;
int iden,ref,attr,c1,c2,c3,c4; int iden, ref, attr, c1, c2, c3, c4;
char bound=0; char bound = BOUND_NONE;
struct item_data *item_data; struct item_data *item_data;
struct item item_tmp; struct item item_tmp;
TBL_PC *sd; TBL_PC *sd;
@ -6509,21 +6512,23 @@ BUILDIN_FUNC(getitem2)
if( !strcmp(script_getfuncname(st),"getitembound2") ) { if( !strcmp(script_getfuncname(st),"getitembound2") ) {
bound = script_getnum(st,11); bound = script_getnum(st,11);
if( bound < 1 || bound > 3) { //Not a correct bound type if( bound > BOUND_NONE && bound < BOUND_MAX ) {
ShowError("script_getitembound2: Not a correct bound type! Type=%d\n",bound); if( script_hasdata(st,12) )
return 1; sd=map_id2sd(script_getnum(st,12));
else
sd=script_rid2sd(st); // Attached player
}
else {
ShowError("script_getitembound2: Not a correct bound type! Type=%d\n",bound);
return SCRIPT_CMD_FAILURE;
} }
if( script_hasdata(st,12) )
sd=map_id2sd(script_getnum(st,12));
else
sd=script_rid2sd(st); // Attached player
} else if( script_hasdata(st,11) ) } 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 else
sd=script_rid2sd(st); // Attached player sd=script_rid2sd(st); // Attached player
if( sd == NULL ) // no target if( sd == NULL ) // no target
return 0; return SCRIPT_CMD_SUCCESS;
data=script_getdata(st,2); data=script_getdata(st,2);
get_val(st,data); get_val(st,data);
@ -6652,7 +6657,7 @@ BUILDIN_FUNC(rentitem) {
it.nameid = nameid; it.nameid = nameid;
it.identify = 1; it.identify = 1;
it.expire_time = (unsigned int)(time(NULL) + seconds); it.expire_time = (unsigned int)(time(NULL) + seconds);
it.bound = 0; it.bound = BOUND_NONE;
if( (flag = pc_additem(sd, &it, 1, LOG_TYPE_SCRIPT)) ) if( (flag = pc_additem(sd, &it, 1, LOG_TYPE_SCRIPT)) )
{ {
@ -11472,7 +11477,8 @@ BUILDIN_FUNC(removemapflag)
case MF_SKILL_DAMAGE: case MF_SKILL_DAMAGE:
{ {
map[m].flag.skill_damage = 0; map[m].flag.skill_damage = 0;
memset(&map[m].adjust.damage,0,sizeof(map[m].adjust.damage)); memset(map[m].skill_damage, 0, sizeof(map[m].skill_damage));
memset(&map[m].adjust.damage, 0, sizeof(map[m].adjust.damage));
} break; } break;
#endif #endif
} }
@ -18228,24 +18234,24 @@ BUILDIN_FUNC(stand)
/** Creates an array of bounded item IDs /** Creates an array of bounded item IDs
* countbound {<type>}; * countbound {<type>};
* @param type: 1 - Account Bound; 2 - Guild Bound; 3 - Party Bound * @param type: 0 - All bound items; 1 - Account Bound; 2 - Guild Bound; 3 - Party Bound
* @return amt: Amount of items found * @return amt: Amount of items found
*/ */
BUILDIN_FUNC(countbound) BUILDIN_FUNC(countbound)
{ {
int i, type, j=0, k=0; int i, type, j = 0, k = 0;
TBL_PC *sd; TBL_PC *sd;
if( (sd = script_rid2sd(st)) == NULL ) if( (sd = script_rid2sd(st)) == NULL )
return SCRIPT_CMD_FAILURE; return SCRIPT_CMD_FAILURE;
type = script_hasdata(st,2)?script_getnum(st,2):0; type = script_getnum(st,2);
for(i=0;i<MAX_INVENTORY;i++){ for( i = 0; i < MAX_INVENTORY; i ++ ) {
if(sd->status.inventory[i].nameid > 0 && ( if( sd->status.inventory[i].nameid > 0 && (
(!type && sd->status.inventory[i].bound > 0) || (!type && sd->status.inventory[i].bound) || (type && sd->status.inventory[i].bound == type)
(type && sd->status.inventory[i].bound == type) ))
)) { {
pc_setreg(sd,reference_uid(add_str("@bound_items"), k),sd->status.inventory[i].nameid); pc_setreg(sd,reference_uid(add_str("@bound_items"), k),sd->status.inventory[i].nameid);
k++; k++;
j += sd->status.inventory[i].amount; j += sd->status.inventory[i].amount;

View File

@ -445,7 +445,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
* @author Aru - for previous check; Jobbie for class restriction idea; Cydh expands the copyable skill * @author Aru - for previous check; Jobbie for class restriction idea; Cydh expands the copyable skill
*/ */
static char skill_isCopyable(struct map_session_data *sd, uint16 skill_id) { static char skill_isCopyable(struct map_session_data *sd, uint16 skill_id) {
int idx = skill_get_index(skill_id); uint16 idx = skill_get_index(skill_id);
// Only copy skill that player doesn't have or the skill is old clone // Only copy skill that player doesn't have or the skill is old clone
if (sd->status.skill[idx].id != 0 && sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED) if (sd->status.skill[idx].id != 0 && sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED)
@ -721,7 +721,7 @@ bool skill_isNotOk_mercenary(uint16 skill_id, struct mercenary_data *md)
bool skill_isNotOk_npcRange(struct block_list *src, uint16 skill_id, uint16 skill_lv, int pos_x, int pos_y) { bool skill_isNotOk_npcRange(struct block_list *src, uint16 skill_id, uint16 skill_lv, int pos_x, int pos_y) {
int inf; int inf;
if (!src || skill_get_index(skill_id) < 0) if (!src || skill_get_index(skill_id) == 0)
return false; return false;
if (src->type == BL_PC && pc_has_permission(BL_CAST(BL_PC,src),PC_PERM_SKILL_UNCONDITIONAL)) if (src->type == BL_PC && pc_has_permission(BL_CAST(BL_PC,src),PC_PERM_SKILL_UNCONDITIONAL))
@ -1550,10 +1550,9 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
case RL_SLUGSHOT: case RL_SLUGSHOT:
if (bl->type != BL_PC) if (bl->type != BL_PC)
sc_start(src,bl,SC_STUN,10 * skill_lv + rnd()%50,skill_lv,skill_get_time2(skill_id,skill_lv)); //(custom) sc_start(src,bl,SC_STUN,10 * skill_lv + rnd()%50,skill_lv,skill_get_time2(skill_id,skill_lv)); //(custom)
else if (dstsd) { else if (dstsd)
pc_setsit(dstsd); //sit duration 2+skill_lv
clif_sitting(bl); status_change_start(src,bl,SC_SITDOWN_FORCE,10000,skill_lv,0,0,0,(2+skill_lv)*1000,1|2|8);
}
break; break;
case RL_BANISHING_BUSTER: case RL_BANISHING_BUSTER:
{ {
@ -1625,7 +1624,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
case SC_REBOUND: case SC_TELEKINESIS_INTENSE: case SC_REBOUND: case SC_TELEKINESIS_INTENSE:
case SC_HEAT_BARREL: case SC_HEAT_BARREL_AFTER: case SC_P_ALTER: case SC_HEAT_BARREL: case SC_HEAT_BARREL_AFTER: case SC_P_ALTER:
case SC_E_CHAIN: case SC_C_MARKER: case SC_B_TRAP: case SC_E_CHAIN: case SC_C_MARKER: case SC_B_TRAP:
case SC_H_MINE: case SC_RECOGNIZEDSPELL: case SC_H_MINE: case SC_RECOGNIZEDSPELL: case SC_CHASEWALK2:
case SC_MTF_ASPD: case SC_MTF_RANGEATK: case SC_MTF_MATK: case SC_MTF_ASPD: case SC_MTF_RANGEATK: case SC_MTF_MATK:
case SC_MTF_MLEATKED: case SC_MTF_CRIDAMAGE: case SC_GN_CARTBOOST: case SC_MTF_MLEATKED: case SC_MTF_CRIDAMAGE: case SC_GN_CARTBOOST:
#ifdef RENEWAL #ifdef RENEWAL
@ -2594,7 +2593,7 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
else if (&tsd->sc && tsd->sc.data[SC_PRESERVE] && !tsd->sc.data[SC__REPRODUCE]) else if (&tsd->sc && tsd->sc.data[SC_PRESERVE] && !tsd->sc.data[SC__REPRODUCE])
return; return;
else { else {
short idx; uint16 idx;
unsigned char lv; unsigned char lv;
// Copy Referal: dummy skills should point to their source upon copying // Copy Referal: dummy skills should point to their source upon copying
@ -2629,7 +2628,7 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
} }
//Use skill index, avoiding out-of-bound array [Cydh] //Use skill index, avoiding out-of-bound array [Cydh]
if ((idx = skill_get_index(skill_id)) < 0) if (!(idx = skill_get_index(skill_id)))
return; return;
switch (skill_isCopyable(tsd,skill_id)) { switch (skill_isCopyable(tsd,skill_id)) {
@ -3011,7 +3010,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
map_freeblock_lock(); map_freeblock_lock();
if (bl->type == BL_PC && skill_id && skill_get_index(skill_id) >= 0 && skill_db[skill_get_index(skill_id)].copyable.option && //Only copy skill that copyable [Cydh] if (bl->type == BL_PC && skill_id && skill_get_index(skill_id) > 0 && skill_db[skill_get_index(skill_id)].copyable.option && //Only copy skill that copyable [Cydh]
dmg.flag&BF_SKILL && dmg.damage+dmg.damage2 > 0 && damage < status_get_hp(bl)) //Cannot copy skills if the blow will kill you. [Skotlex] dmg.flag&BF_SKILL && dmg.damage+dmg.damage2 > 0 && damage < status_get_hp(bl)) //Cannot copy skills if the blow will kill you. [Skotlex]
skill_do_copy(src,bl,skill_id,skill_lv); skill_do_copy(src,bl,skill_id,skill_lv);
@ -3413,7 +3412,7 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int
if( (idx = skill_get_index(skill)) == 0 ) if( (idx = skill_get_index(skill)) == 0 )
return 0; return 0;
// Requeriments // Requirements
for( i = 0; i < ARRAYLENGTH(itemid); i++ ) for( i = 0; i < ARRAYLENGTH(itemid); i++ )
{ {
itemid[i] = skill_db[idx].require.itemid[i]; itemid[i] = skill_db[idx].require.itemid[i];
@ -14453,7 +14452,7 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
break; break;
case ST_MADO: case ST_MADO:
if( !pc_ismadogear(sd) ) { if( !pc_ismadogear(sd) ) {
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); clif_skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR,0);
return false; return false;
} }
break; break;
@ -14475,10 +14474,6 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
if (require.status_count) { if (require.status_count) {
uint8 i; uint8 i;
/* May has multiple requirements */ /* May has multiple requirements */
//if (!sc) {
// clif_skill_fail(sd, skill_id, USESKILL_FAIL_CONDITION, 0);
// return false;
//}
for (i = 0; i < require.status_count; i++) { for (i = 0; i < require.status_count; i++) {
enum sc_type req_sc = require.status[i]; enum sc_type req_sc = require.status[i];
if (req_sc == SC_NONE) if (req_sc == SC_NONE)
@ -14512,10 +14507,11 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
//check if equiped item //check if equiped item
if (require.eqItem_count) { if (require.eqItem_count) {
for (i = 0; i < require.eqItem_count; i++) { for (i = 0; i < require.eqItem_count; i++) {
int reqeqit = require.eqItem[i]; uint16 reqeqit = require.eqItem[i];
if(!reqeqit) break; //no more required item get out of here if (!reqeqit)
break; //no more required item get out of here
if (!pc_checkequip2(sd,reqeqit,EQI_ACC_L,EQI_MAX)) { if (!pc_checkequip2(sd,reqeqit,EQI_ACC_L,EQI_MAX)) {
char output[128]; char output[CHAT_SIZE_MAX];
//Official use msgstringtable.txt for each skill failure //Official use msgstringtable.txt for each skill failure
sprintf(output,msg_txt(sd,722),itemdb_jname(reqeqit)); sprintf(output,msg_txt(sd,722),itemdb_jname(reqeqit));
clif_colormes(sd,color_table[COLOR_RED],output); clif_colormes(sd,color_table[COLOR_RED],output);
@ -14566,7 +14562,7 @@ bool skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
struct skill_condition require; struct skill_condition require;
struct status_data *status; struct status_data *status;
int i; int i;
int index[MAX_SKILL_ITEM_REQUIRE]; short index[MAX_SKILL_ITEM_REQUIRE];
nullpo_retr(false,sd); nullpo_retr(false,sd);
@ -14724,8 +14720,7 @@ bool skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
else if( require.itemid[i] == ITEMID_ANCILLA ) else if( require.itemid[i] == ITEMID_ANCILLA )
clif_skill_fail(sd,skill_id,USESKILL_FAIL_ANCILLA,0); //Ancilla is required. clif_skill_fail(sd,skill_id,USESKILL_FAIL_ANCILLA,0); //Ancilla is required.
else { else {
char output[128]; char output[CHAT_SIZE_MAX];
//Official is using msgstringtable.txt for each requirement failure //Official is using msgstringtable.txt for each requirement failure
//clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); //clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
sprintf(output, msg_txt(sd,720), itemdb_jname(require.itemid[i])); // %s is required. sprintf(output, msg_txt(sd,720), itemdb_jname(require.itemid[i])); // %s is required.
@ -14748,45 +14743,45 @@ bool skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
*/ */
void skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type) void skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type)
{ {
struct skill_condition req; struct skill_condition require;
nullpo_retv(sd); nullpo_retv(sd);
req = skill_get_requirement(sd,skill_id,skill_lv); require = skill_get_requirement(sd,skill_id,skill_lv);
if( type&1 ) { if( type&1 ) {
switch( skill_id ) { switch( skill_id ) {
case CG_TAROTCARD: // TarotCard will consume sp in skill_cast_nodamage_id [Inkfish] case CG_TAROTCARD: // TarotCard will consume sp in skill_cast_nodamage_id [Inkfish]
case MC_IDENTIFY: case MC_IDENTIFY:
case RL_D_TAIL: case RL_D_TAIL:
req.sp = 0; require.sp = 0;
break; break;
case GS_DESPERADO: case GS_DESPERADO:
if (sd->skill_id_old == RL_FALLEN_ANGEL) //Don't consume SP if triggered by Fallen Angel if (sd->skill_id_old == RL_FALLEN_ANGEL) //Don't consume SP if triggered by Fallen Angel
req.sp = 0; require.sp = 0;
break; break;
default: default:
if(sd->state.autocast) if(sd->state.autocast)
req.sp = 0; require.sp = 0;
break; break;
} }
if(req.hp || req.sp) if(require.hp || require.sp)
status_zap(&sd->bl, req.hp, req.sp); status_zap(&sd->bl, require.hp, require.sp);
if(req.spiritball > 0) if(require.spiritball > 0)
pc_delspiritball(sd,req.spiritball,0); pc_delspiritball(sd,require.spiritball,0);
else if(req.spiritball == -1) { else if(require.spiritball == -1) {
sd->spiritball_old = sd->spiritball; sd->spiritball_old = sd->spiritball;
pc_delspiritball(sd,sd->spiritball,0); pc_delspiritball(sd,sd->spiritball,0);
} }
if(req.zeny > 0) if(require.zeny > 0)
{ {
if( skill_id == NJ_ZENYNAGE ) if( skill_id == NJ_ZENYNAGE )
req.zeny = 0; //Zeny is reduced on skill_attack. require.zeny = 0; //Zeny is reduced on skill_attack.
if( sd->status.zeny < req.zeny ) if( sd->status.zeny < require.zeny )
req.zeny = sd->status.zeny; require.zeny = sd->status.zeny;
pc_payzeny(sd,req.zeny,LOG_TYPE_CONSUME,NULL); pc_payzeny(sd,require.zeny,LOG_TYPE_CONSUME,NULL);
} }
} }
@ -14799,10 +14794,10 @@ void skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, ui
for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; ++i ) for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; ++i )
{ {
if( !req.itemid[i] ) if( !require.itemid[i] )
continue; continue;
if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_WIZARD ) if( itemid_isgemstone(require.itemid[i]) && skill_id != HW_GANBANTEIN && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_WIZARD )
continue; //Gemstones are checked, but not substracted from inventory. continue; //Gemstones are checked, but not substracted from inventory.
switch( skill_id ){ switch( skill_id ){
@ -14831,8 +14826,8 @@ void skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, ui
break; break;
} }
if( (n = pc_search_inventory(sd,req.itemid[i])) >= 0 ) if( (n = pc_search_inventory(sd,require.itemid[i])) >= 0 )
pc_delitem(sd,n,req.amount[i],0,1,LOG_TYPE_CONSUME); pc_delitem(sd,n,require.amount[i],0,1,LOG_TYPE_CONSUME);
} }
} }
} }
@ -14851,6 +14846,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
struct status_change *sc; struct status_change *sc;
int i,hp_rate,sp_rate, sp_skill_rate_bonus = 100; int i,hp_rate,sp_rate, sp_skill_rate_bonus = 100;
uint16 idx; uint16 idx;
bool level_dependent = false;
memset(&req,0,sizeof(req)); memset(&req,0,sizeof(req));
@ -14945,85 +14941,13 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
req.eqItem_count = skill_db[idx].require.eqItem_count; req.eqItem_count = skill_db[idx].require.eqItem_count;
req.eqItem = skill_db[idx].require.eqItem; req.eqItem = skill_db[idx].require.eqItem;
for( i = 0; i < MAX_SKILL_ITEM_REQUIRE; i++ ) {
if( (skill_id == AM_POTIONPITCHER || skill_id == CR_SLIMPITCHER || skill_id == CR_CULTIVATION) && i != skill_lv%11 - 1 )
continue;
switch( skill_id ) {
case AM_CALLHOMUN:
if (sd->status.hom_id) //Don't delete items when hom is already out.
continue;
break;
case NC_SHAPESHIFT:
if( i < 4 )
continue;
break;
case WZ_FIREPILLAR: // celest
if (skill_lv <= 5) // no gems required at level 1-5
continue;
break;
case AB_ADORAMUS:
if( itemid_isgemstone(skill_db[idx].require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 2)) )
continue;
break;
case WL_COMET:
if( itemid_isgemstone(skill_db[idx].require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 0)) )
continue;
break;
case GN_FIRE_EXPANSION:
if( i < 5 )
continue;
break;
case SO_SUMMON_AGNI:
case SO_SUMMON_AQUA:
case SO_SUMMON_VENTUS:
case SO_SUMMON_TERA:
case SO_WATER_INSIGNIA:
case SO_FIRE_INSIGNIA:
case SO_WIND_INSIGNIA:
case SO_EARTH_INSIGNIA:
if( i < 3 )
continue;
break;
}
req.itemid[i] = skill_db[idx].require.itemid[i];
req.amount[i] = skill_db[idx].require.amount[i];
// Check requirement for gemstone.
if (itemid_isgemstone(req.itemid[i])) {
if( sd->special_state.no_gemstone == 2 ) // Remove all Magic Stone required for all skills for VIP.
req.itemid[i] = req.amount[i] = 0;
else {
if( sd->special_state.no_gemstone )
{ // All gem skills except Hocus Pocus and Ganbantein can cast for free with Mistress card -helvetica
if( skill_id != SA_ABRACADABRA )
req.itemid[i] = req.amount[i] = 0;
else if( --req.amount[i] < 1 )
req.amount[i] = 1; // Hocus Pocus always use at least 1 gem
}
if(sc && sc->data[SC_INTOABYSS])
{
if( skill_id != SA_ABRACADABRA )
req.itemid[i] = req.amount[i] = 0;
else if( --req.amount[i] < 1 )
req.amount[i] = 1; // Hocus Pocus always use at least 1 gem
}
}
}
if( skill_id >= HT_SKIDTRAP && skill_id <= HT_TALKIEBOX && pc_checkskill(sd, RA_RESEARCHTRAP) > 0){
int16 itIndex;
if( (itIndex = pc_search_inventory(sd,req.itemid[i])) < 0 || ( itIndex >= 0 && sd->status.inventory[itIndex].amount < req.amount[i] ) ){
req.itemid[i] = ITEMID_TRAP_ALLOY;
req.amount[i] = 1;
}
break;
}
}
/* requirements are level-dependent */
switch( skill_id ) { switch( skill_id ) {
/* Skill level-dependent checks */
case NC_SHAPESHIFT: case NC_SHAPESHIFT:
case NC_REPAIR:
//NOTE: Please make sure Magic_Gear_Fuel in the last position in skill_require_db.txt
req.itemid[1] = skill_db[idx].require.itemid[MAX_SKILL_ITEM_REQUIRE-1];
req.amount[1] = skill_db[idx].require.amount[MAX_SKILL_ITEM_REQUIRE-1];
case GN_FIRE_EXPANSION: case GN_FIRE_EXPANSION:
case SO_SUMMON_AGNI: case SO_SUMMON_AGNI:
case SO_SUMMON_AQUA: case SO_SUMMON_AQUA:
@ -15033,26 +14957,74 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
case SO_FIRE_INSIGNIA: case SO_FIRE_INSIGNIA:
case SO_WIND_INSIGNIA: case SO_WIND_INSIGNIA:
case SO_EARTH_INSIGNIA: case SO_EARTH_INSIGNIA:
req.itemid[skill_lv-1] = skill_db[idx].require.itemid[skill_lv-1]; case WZ_FIREPILLAR: // no gems required at level 1-5 [celest]
req.amount[skill_lv-1] = skill_db[idx].require.amount[skill_lv-1]; req.itemid[0] = skill_db[idx].require.itemid[min(skill_lv-1,MAX_SKILL_ITEM_REQUIRE-1)];
req.amount[0] = skill_db[idx].require.amount[min(skill_lv-1,MAX_SKILL_ITEM_REQUIRE-1)];
level_dependent = true;
/* Normal skill requirements and gemstone checks */
default:
for( i = 0; i < ((!level_dependent) ? MAX_SKILL_ITEM_REQUIRE : 2); i++ ) {
// Skip this for level_dependent requirement, just looking forward for gemstone removal. Assumed if there is gemstone there.
if (!level_dependent) {
switch( skill_id ) {
case AM_POTIONPITCHER:
case CR_SLIMPITCHER:
case CR_CULTIVATION:
if (i != skill_lv%11 - 1)
continue;
break;
case AM_CALLHOMUN:
if (sd->status.hom_id) //Don't delete items when hom is already out.
continue;
break;
case AB_ADORAMUS:
if( itemid_isgemstone(skill_db[idx].require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 2)) )
continue;
break;
case WL_COMET:
if( itemid_isgemstone(skill_db[idx].require.itemid[i]) && (sd->special_state.no_gemstone == 2 || skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 0)) )
continue;
break;
}
req.itemid[i] = skill_db[idx].require.itemid[i];
req.amount[i] = skill_db[idx].require.amount[i];
if( skill_id >= HT_SKIDTRAP && skill_id <= HT_TALKIEBOX && pc_checkskill(sd, RA_RESEARCHTRAP) > 0){
int16 itIndex;
if( (itIndex = pc_search_inventory(sd,req.itemid[i])) < 0 || ( itIndex >= 0 && sd->status.inventory[itIndex].amount < req.amount[i] ) ){
req.itemid[i] = ITEMID_TRAP_ALLOY;
req.amount[i] = 1;
}
break;
}
}
// Check requirement for gemstone.
if (itemid_isgemstone(req.itemid[i])) {
if( sd->special_state.no_gemstone == 2 ) // Remove all Magic Stone required for all skills for VIP.
req.itemid[i] = req.amount[i] = 0;
else {
if( sd->special_state.no_gemstone )
{ // All gem skills except Hocus Pocus and Ganbantein can cast for free with Mistress card -helvetica
if( skill_id != SA_ABRACADABRA )
req.itemid[i] = req.amount[i] = 0;
else if( --req.amount[i] < 1 )
req.amount[i] = 1; // Hocus Pocus always use at least 1 gem
}
if(sc && sc->data[SC_INTOABYSS])
{
if( skill_id != SA_ABRACADABRA )
req.itemid[i] = req.amount[i] = 0;
else if( --req.amount[i] < 1 )
req.amount[i] = 1; // Hocus Pocus always use at least 1 gem
}
}
}
}
break; break;
} }
if (skill_id == NC_REPAIR) {
switch(skill_lv) {
case 1:
case 2:
req.itemid[1] = ITEMID_REPAIR_A;
break;
case 3:
case 4:
req.itemid[1] = ITEMID_REPAIR_B;
break;
case 5:
req.itemid[1] = ITEMID_REPAIR_C;
break;
}
req.amount[1] = 1;
}
// Check for cost reductions due to skills & SCs // Check for cost reductions due to skills & SCs
switch(skill_id) { switch(skill_id) {
@ -19350,29 +19322,37 @@ static bool skill_parse_row_skilldb(char* split[], int columns, int current)
return true; return true;
} }
/** Split string to int or constanta value (const.txt) /** Split string to int by constanta value (const.txt) or atoi()
* @param *str: String input * @param *str: String input
* @param *val: Temporary storage * @param *val: Temporary storage
* @param *delim: Delimiter (for multiple value support) * @param *delim: Delimiter (for multiple value support)
* @param useConst: 'true' uses const.txt as reference, 'false' uses atoi() * @param min_value: Minimum value. If the splitted value is less or equal than this, will be skipped
* @param min: Min value of each const. Example: SC has min value SC_NONE (-1), so the value that less or equal won't be counted * @param max: Maximum number that can be allocated
* @return count: Number of success * @return count: Number of success
*/ */
uint8 skill_split2(char *str, int *val, const char *delim, bool useConst, short min) { uint8 skill_split_atoi2(char *str, int *val, const char *delim, int min_value, uint16 max) {
uint8 i = 0; uint8 i = 0;
char *p = strtok(str,delim); char *p = strtok(str, delim);
while (p != NULL) { while (p != NULL) {
int n = -1; int n = min_value;
if (useConst) trim(p);
script_get_constant(trim(p),&n);
else if (ISDIGIT(p[0])) // If using numeric
n = atoi(p); n = atoi(p);
if (n > min) { else if (!script_get_constant(p, &n)) { // If using constant value
ShowError("skill_split_atoi2: Invalid value: '%s'\n", p);
p = strtok(NULL, delim);
continue;
}
if (n > min_value) {
val[i] = n; val[i] = n;
i++; i++;
if (i >= max)
break;
} }
p = strtok(NULL,delim); p = strtok(NULL, delim);
} }
return i; return i;
} }
@ -19383,8 +19363,10 @@ static void skill_destroy_requirement(void) {
for (i = 0; i < MAX_SKILL; i++) { for (i = 0; i < MAX_SKILL; i++) {
if (skill_db[i].require.status_count) if (skill_db[i].require.status_count)
aFree(skill_db[i].require.status); aFree(skill_db[i].require.status);
skill_db[i].require.status_count = 0;
if (skill_db[i].require.eqItem_count) if (skill_db[i].require.eqItem_count)
aFree(skill_db[i].require.eqItem); aFree(skill_db[i].require.eqItem);
skill_db[i].require.eqItem_count = 0;
} }
} }
@ -19396,10 +19378,9 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
char* p; char* p;
uint16 skill_id = atoi(split[0]), idx, i; uint16 skill_id = atoi(split[0]), idx, i;
if (!skill_get_index(skill_id)) // invalid skill id if (!(idx = skill_get_index(skill_id))) // invalid skill id
return false; return false;
idx = skill_get_index(skill_id);
skill_split_atoi(split[1],skill_db[idx].require.hp); skill_split_atoi(split[1],skill_db[idx].require.hp);
skill_split_atoi(split[2],skill_db[idx].require.mhp); skill_split_atoi(split[2],skill_db[idx].require.mhp);
skill_split_atoi(split[3],skill_db[idx].require.sp); skill_split_atoi(split[3],skill_db[idx].require.sp);
@ -19455,11 +19436,12 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
else skill_db[idx].require.state = ST_NONE; // Unknown or no state else skill_db[idx].require.state = ST_NONE; // Unknown or no state
//Status requirements //Status requirements
//FIXME: Default entry should be -1/SC_ALL in skill_require_db.txt but it's 0/SC_STONE.
trim(split[11]); trim(split[11]);
if (split[11][0] != '\0') { if (split[11][0] != '\0' || atoi(split[11])) {
int require[MAX_SKILL_STATUS_REQUIRE]; int require[MAX_SKILL_STATUS_REQUIRE];
if ((skill_db[idx].require.status_count = skill_split2(split[11],require,":",true,SC_NONE))) { if ((skill_db[idx].require.status_count = skill_split_atoi2(split[11], require, ":", SC_STONE, ARRAYLENGTH(require)))) {
skill_db[idx].require.status = aMalloc(skill_db[idx].require.status_count * sizeof(sc_type)); CREATE(skill_db[idx].require.status, enum sc_type, skill_db[idx].require.status_count);
for (i = 0; i < skill_db[idx].require.status_count; i++) for (i = 0; i < skill_db[idx].require.status_count; i++)
skill_db[idx].require.status[i] = (sc_type)require[i]; skill_db[idx].require.status[i] = (sc_type)require[i];
} }
@ -19475,10 +19457,10 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
//Equipped Item requirements. //Equipped Item requirements.
//NOTE: We don't check the item is exist or not here //NOTE: We don't check the item is exist or not here
trim(split[33]); trim(split[33]);
if (split[33][0] != '\0') { if (split[33][0] != '\0' || atoi(split[33])) {
int require[MAX_SKILL_EQUIP_REQUIRE]; int require[MAX_SKILL_EQUIP_REQUIRE];
if ((skill_db[idx].require.eqItem_count = skill_split2(split[33],require,":",false,501))) { if ((skill_db[idx].require.eqItem_count = skill_split_atoi2(split[33], require, ":", 500, ARRAYLENGTH(require)))) {
skill_db[idx].require.eqItem = aMalloc(skill_db[idx].require.eqItem_count * sizeof(short)); CREATE(skill_db[idx].require.eqItem, uint16, skill_db[idx].require.eqItem_count);
for (i = 0; i < skill_db[idx].require.eqItem_count; i++) for (i = 0; i < skill_db[idx].require.eqItem_count; i++)
skill_db[idx].require.eqItem[i] = require[i]; skill_db[idx].require.eqItem[i] = require[i];
} }
@ -19490,8 +19472,7 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
* SkillID,CastingTime,AfterCastActDelay,AfterCastWalkDelay,Duration1,Duration2,Cooldown{,Fixedcast} * SkillID,CastingTime,AfterCastActDelay,AfterCastWalkDelay,Duration1,Duration2,Cooldown{,Fixedcast}
*/ */
static bool skill_parse_row_castdb(char* split[], int columns, int current) { static bool skill_parse_row_castdb(char* split[], int columns, int current) {
uint16 skill_id = atoi(split[0]); uint16 idx = skill_get_index(atoi(split[0]));
uint16 idx = skill_get_index(skill_id);
if( !idx ) // invalid skill id if( !idx ) // invalid skill id
return false; return false;
@ -19511,8 +19492,7 @@ static bool skill_parse_row_castdb(char* split[], int columns, int current) {
* SkillID,Cast,Delay (optional) * SkillID,Cast,Delay (optional)
*/ */
static bool skill_parse_row_castnodexdb(char* split[], int columns, int current) { static bool skill_parse_row_castnodexdb(char* split[], int columns, int current) {
uint16 skill_id = atoi(split[0]); uint16 idx = skill_get_index(atoi(split[0]));
uint16 idx = skill_get_index(skill_id);
if( !idx ) // invalid skill id if( !idx ) // invalid skill id
return false; return false;
@ -19527,8 +19507,7 @@ static bool skill_parse_row_castnodexdb(char* split[], int columns, int current)
* SkillID,Flag * SkillID,Flag
*/ */
static bool skill_parse_row_nocastdb(char* split[], int columns, int current) { static bool skill_parse_row_nocastdb(char* split[], int columns, int current) {
uint16 skill_id = atoi(split[0]); uint16 idx = skill_get_index(atoi(split[0]));
uint16 idx = skill_get_index(skill_id);
if( !idx ) // invalid skill id if( !idx ) // invalid skill id
return false; return false;
@ -19541,8 +19520,7 @@ static bool skill_parse_row_nocastdb(char* split[], int columns, int current) {
* ID,unit ID,unit ID 2,layout,range,interval,target,flag * ID,unit ID,unit ID 2,layout,range,interval,target,flag
*/ */
static bool skill_parse_row_unitdb(char* split[], int columns, int current) { static bool skill_parse_row_unitdb(char* split[], int columns, int current) {
uint16 skill_id = atoi(split[0]); uint16 idx = skill_get_index(atoi(split[0]));
uint16 idx = skill_get_index(skill_id);
if( !idx ) // invalid skill id if( !idx ) // invalid skill id
return false; return false;
@ -19635,7 +19613,7 @@ static bool skill_parse_row_spellbookdb(char* split[], int columns, int current)
if( !skill_get_index(skill_id) || !skill_get_max(skill_id) ) if( !skill_get_index(skill_id) || !skill_get_max(skill_id) )
ShowError("spellbook_db: Invalid skill ID %d\n", skill_id); ShowError("spellbook_db: Invalid skill ID %d\n", skill_id);
if ( !skill_get_inf(skill_id) ) if( !skill_get_inf(skill_id) )
ShowError("spellbook_db: Passive skills cannot be memorized (%d/%s)\n", skill_id, skill_get_name(skill_id)); ShowError("spellbook_db: Passive skills cannot be memorized (%d/%s)\n", skill_id, skill_get_name(skill_id));
if( points < 1 ) if( points < 1 )
ShowError("spellbook_db: PreservePoints have to be 1 or above! (%d/%s)\n", skill_id, skill_get_name(skill_id)); ShowError("spellbook_db: PreservePoints have to be 1 or above! (%d/%s)\n", skill_id, skill_get_name(skill_id));
@ -19709,12 +19687,12 @@ static bool skill_parse_row_copyabledb(char* split[], int column, int current) {
uint8 option; uint8 option;
trim(split[0]); trim(split[0]);
if(ISDIGIT(split[0][0])) if (ISDIGIT(split[0][0]))
id = atoi(split[0]); id = atoi(split[0]);
else else
id = skill_name2id(split[0]); id = skill_name2id(split[0]);
if ((id = skill_get_index(id)) < 0) { if ((id = skill_get_index(id)) == 0) {
ShowError("skill_parse_row_copyabledb: Invalid skill '%s'\n",split[0]); ShowError("skill_parse_row_copyabledb: Invalid skill '%s'\n",split[0]);
return false; return false;
} }
@ -19739,12 +19717,12 @@ static bool skill_parse_row_nonearnpcrangedb(char* split[], int column, int curr
int16 id; int16 id;
trim(split[0]); trim(split[0]);
if(ISDIGIT(split[0][0])) if (ISDIGIT(split[0][0]))
id = atoi(split[0]); id = atoi(split[0]);
else else
id = skill_name2id(split[0]); id = skill_name2id(split[0]);
if ((id = skill_get_index(id)) < 0) { // invalid skill id if ((id = skill_get_index(id)) == 0) { // invalid skill id
ShowError("skill_parse_row_nonearnpcrangedb: Invalid skill '%s'\n",split[0]); ShowError("skill_parse_row_nonearnpcrangedb: Invalid skill '%s'\n",split[0]);
return false; return false;
} }
@ -19811,27 +19789,27 @@ static bool skill_parse_row_changematerialdb(char* split[], int columns, int cur
return true; return true;
} }
/*========================================== /**
* Manage Skill Damage database [Lilith] * Manage Skill Damage database [Lilith]
*------------------------------------------*/ **/
#ifdef ADJUST_SKILL_DAMAGE #ifdef ADJUST_SKILL_DAMAGE
static bool skill_parse_row_skilldamage(char* split[], int columns, int current) static bool skill_parse_row_skilldamage(char* split[], int columns, int current)
{ {
uint16 skill_id = skill_name2id(split[0]), idx; uint16 skill_id = skill_name2id(split[0]), idx;
if ((idx = skill_get_index(skill_id)) < 0) { // invalid skill id if ((idx = skill_get_index(skill_id)) == 0) { // invalid skill id
ShowWarning("skill_parse_row_skilldamage: Invalid skill '%s'. Skipping..",split[0]); ShowWarning("skill_parse_row_skilldamage: Invalid skill '%s'. Skipping..",split[0]);
return false; return false;
} }
memset(&skill_db[idx].damage,0,sizeof(struct s_skill_damage)); memset(&skill_db[idx].damage,0,sizeof(struct s_skill_damage));
skill_db[idx].damage.caster |= atoi(split[1]); skill_db[idx].damage.caster |= atoi(split[1]);
skill_db[idx].damage.map |= atoi(split[2]); skill_db[idx].damage.map |= atoi(split[2]);
skill_db[idx].damage.pc = cap_value(atoi(split[3]),-100,MAX_SKILL_DAMAGE_RATE); skill_db[idx].damage.pc = cap_value(atoi(split[3]),-100,INT_MAX);
if (split[3]) if (split[3])
skill_db[idx].damage.mob = cap_value(atoi(split[4]),-100,MAX_SKILL_DAMAGE_RATE); skill_db[idx].damage.mob = cap_value(atoi(split[4]),-100,INT_MAX);
if (split[4]) if (split[4])
skill_db[idx].damage.boss = cap_value(atoi(split[5]),-100,MAX_SKILL_DAMAGE_RATE); skill_db[idx].damage.boss = cap_value(atoi(split[5]),-100,INT_MAX);
if (split[5]) if (split[5])
skill_db[idx].damage.other = cap_value(atoi(split[6]),-100,MAX_SKILL_DAMAGE_RATE); skill_db[idx].damage.other = cap_value(atoi(split[6]),-100,INT_MAX);
return true; return true;
} }
#endif #endif

View File

@ -22,6 +22,8 @@ struct status_change_entry;
#define MAX_SKILL_IMPROVISE_DB 50 #define MAX_SKILL_IMPROVISE_DB 50
#define MAX_SKILL_LEVEL 100 #define MAX_SKILL_LEVEL 100
#define MAX_SKILL_CRIMSON_MARKER 3 #define MAX_SKILL_CRIMSON_MARKER 3
#define SKILL_NAME_LENGTH 31
#define SKILL_DESC_LENGTH 31
DBMap* skilldb_name2id; DBMap* skilldb_name2id;
@ -104,51 +106,53 @@ enum e_skill_display {
SD_PREAMBLE = 0x8000, // skill_area_sub will transmit a 'magic' damage packet (-30000 dmg) for the first target selected SD_PREAMBLE = 0x8000, // skill_area_sub will transmit a 'magic' damage packet (-30000 dmg) for the first target selected
}; };
#define MAX_SKILL_ITEM_REQUIRE 10 #define MAX_SKILL_ITEM_REQUIRE 10 /// Maximum required items
#define MAX_SKILL_STATUS_REQUIRE 3 #define MAX_SKILL_STATUS_REQUIRE 3 /// Maximum required statuses
#define MAX_SKILL_EQUIP_REQUIRE 10 #define MAX_SKILL_EQUIP_REQUIRE 10 /// Maximum required equipped item
struct skill_condition { struct skill_condition {
int hp, int hp, /// HP cost
mhp, mhp, /// Max HP to trigger
sp, sp, /// SP cost
hp_rate, hp_rate, /// HP cost (%)
sp_rate, sp_rate, /// SP cost (%)
ammo, ammo, /// Ammo type
ammo_qty, ammo_qty, /// Amount of ammo
weapon, weapon, /// Weapon type
zeny, zeny, /// Zeny cost
state, state, /// State/condition
spiritball, spiritball, /// Spiritball cost
itemid[MAX_SKILL_ITEM_REQUIRE], itemid[MAX_SKILL_ITEM_REQUIRE], /// Required item
amount[MAX_SKILL_ITEM_REQUIRE]; amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
short *eqItem; uint16 *eqItem; /// List of equipped item
enum sc_type *status; enum sc_type *status; /// List of Status required (SC)
uint8 status_count, eqItem_count; uint8 status_count, /// Count of SC
eqItem_count; /// Count of equipped item
}; };
struct s_skill_require { struct s_skill_require {
int hp[MAX_SKILL_LEVEL], int hp[MAX_SKILL_LEVEL], /// HP cost
mhp[MAX_SKILL_LEVEL], mhp[MAX_SKILL_LEVEL], /// Max HP to trigger
sp[MAX_SKILL_LEVEL], sp[MAX_SKILL_LEVEL], /// SP cost
hp_rate[MAX_SKILL_LEVEL], hp_rate[MAX_SKILL_LEVEL], /// HP cost (%)
sp_rate[MAX_SKILL_LEVEL], sp_rate[MAX_SKILL_LEVEL], /// SP cost (%)
zeny[MAX_SKILL_LEVEL], zeny[MAX_SKILL_LEVEL], /// Zeny cost
weapon, weapon, /// Weapon type
ammo, ammo, /// Ammo type
ammo_qty[MAX_SKILL_LEVEL], ammo_qty[MAX_SKILL_LEVEL], /// Amount of ammo
state, state, /// State/condition
spiritball[MAX_SKILL_LEVEL], spiritball[MAX_SKILL_LEVEL], /// Spiritball cost
itemid[MAX_SKILL_ITEM_REQUIRE], itemid[MAX_SKILL_ITEM_REQUIRE], /// Required item
amount[MAX_SKILL_ITEM_REQUIRE]; amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
short *eqItem; uint16 *eqItem; /// List of equipped item
enum sc_type *status; enum sc_type *status; /// List of Status required (SC)
uint8 status_count, eqItem_count; uint8 status_count, /// Count of SC
eqItem_count; /// Count of equipped item
}; };
/// Database skills /// Database skills
struct s_skill_db { struct s_skill_db {
char name[NAME_LENGTH]; char name[SKILL_NAME_LENGTH];
char desc[40]; char desc[SKILL_DESC_LENGTH];
int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max; int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max;
int num[MAX_SKILL_LEVEL]; int num[MAX_SKILL_LEVEL];
int cast[MAX_SKILL_LEVEL],walkdelay[MAX_SKILL_LEVEL],delay[MAX_SKILL_LEVEL]; int cast[MAX_SKILL_LEVEL],walkdelay[MAX_SKILL_LEVEL],delay[MAX_SKILL_LEVEL];
@ -261,7 +265,7 @@ enum {
UF_ENSEMBLE = 0x0200, // Duet UF_ENSEMBLE = 0x0200, // Duet
UF_SONG = 0x0400, // Song UF_SONG = 0x0400, // Song
UF_DUALMODE = 0x0800, // Spells should trigger both ontimer and onplace/onout/onleft effects. UF_DUALMODE = 0x0800, // Spells should trigger both ontimer and onplace/onout/onleft effects.
UF_RANGEDSINGLEUNIT = 0x2000 // hack for ranged layout, only display center UF_RANGEDSINGLEUNIT = 0x2000 // hack for ranged layout, only display center
}; };
/// Create Database item /// Create Database item

View File

@ -821,11 +821,11 @@ void initChangeTables(void)
add_sc( RL_HAMMER_OF_GOD , SC_STUN ); add_sc( RL_HAMMER_OF_GOD , SC_STUN );
set_sc( RL_B_TRAP , SC_B_TRAP , SI_B_TRAP , SCB_SPEED ); set_sc( RL_B_TRAP , SC_B_TRAP , SI_B_TRAP , SCB_SPEED );
set_sc( RL_E_CHAIN , SC_E_CHAIN , SI_E_CHAIN , SCB_NONE ); set_sc( RL_E_CHAIN , SC_E_CHAIN , SI_E_CHAIN , SCB_NONE );
set_sc( RL_P_ALTER , SC_P_ALTER , SI_P_ALTER , SCB_BATK ); set_sc( RL_P_ALTER , SC_P_ALTER , SI_P_ALTER , SCB_NONE );
set_sc( RL_SLUGSHOT , SC_STUN , SI_SLUGSHOT , SCB_NONE ); set_sc( RL_SLUGSHOT , SC_STUN , SI_SLUGSHOT , SCB_NONE );
set_sc( RL_HEAT_BARREL , SC_HEAT_BARREL , SI_HEAT_BARREL , SCB_BATK|SCB_ASPD|SCB_HIT ); set_sc( RL_HEAT_BARREL , SC_HEAT_BARREL , SI_HEAT_BARREL , SCB_FLEE|SCB_ASPD );
set_sc_with_vfx( RL_C_MARKER , SC_C_MARKER , SI_C_MARKER , SCB_SPEED ); set_sc_with_vfx( RL_C_MARKER , SC_C_MARKER , SI_C_MARKER , SCB_FLEE );
set_sc_with_vfx( RL_AM_BLAST , SC_ANTI_M_BLAST , SI_ANTI_M_BLAST , SCB_DEF_ELE ); set_sc_with_vfx( RL_AM_BLAST , SC_ANTI_M_BLAST , SI_ANTI_M_BLAST , SCB_NONE );
set_sc_with_vfx( SC_ALL_RIDING , SC_ALL_RIDING , SI_ALL_RIDING , SCB_SPEED ); set_sc_with_vfx( SC_ALL_RIDING , SC_ALL_RIDING , SI_ALL_RIDING , SCB_SPEED );
@ -855,7 +855,7 @@ void initChangeTables(void)
StatusIconChangeTable[SC_ASPDPOTION3] = SI_ASPDPOTIONINFINITY; StatusIconChangeTable[SC_ASPDPOTION3] = SI_ASPDPOTIONINFINITY;
StatusIconChangeTable[SC_SPEEDUP0] = SI_MOVHASTE_HORSE; StatusIconChangeTable[SC_SPEEDUP0] = SI_MOVHASTE_HORSE;
StatusIconChangeTable[SC_SPEEDUP1] = SI_SPEEDPOTION1; StatusIconChangeTable[SC_SPEEDUP1] = SI_SPEEDPOTION1;
StatusIconChangeTable[SC_INCSTR] = SI_INCSTR; StatusIconChangeTable[SC_CHASEWALK2] = SI_CHASEWALK2;
StatusIconChangeTable[SC_MIRACLE] = SI_SPIRIT; StatusIconChangeTable[SC_MIRACLE] = SI_SPIRIT;
StatusIconChangeTable[SC_INTRAVISION] = SI_INTRAVISION; StatusIconChangeTable[SC_INTRAVISION] = SI_INTRAVISION;
StatusIconChangeTable[SC_STRFOOD] = SI_FOODSTR; StatusIconChangeTable[SC_STRFOOD] = SI_FOODSTR;
@ -1055,6 +1055,7 @@ void initChangeTables(void)
StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED;
StatusChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL; StatusChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL;
StatusChangeFlagTable[SC_SLOWDOWN] |= SCB_SPEED; StatusChangeFlagTable[SC_SLOWDOWN] |= SCB_SPEED;
StatusChangeFlagTable[SC_CHASEWALK2] |= SCB_STR;
/* Cash Items */ /* Cash Items */
StatusChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR; StatusChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR;
@ -4749,6 +4750,8 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang
return 50; return 50;
if(sc->data[SC_INCALLSTATUS]) if(sc->data[SC_INCALLSTATUS])
str += sc->data[SC_INCALLSTATUS]->val1; str += sc->data[SC_INCALLSTATUS]->val1;
if(sc->data[SC_CHASEWALK2])
str += sc->data[SC_CHASEWALK2]->val1;
if(sc->data[SC_INCSTR]) if(sc->data[SC_INCSTR])
str += sc->data[SC_INCSTR]->val1; str += sc->data[SC_INCSTR]->val1;
if(sc->data[SC_STRFOOD]) if(sc->data[SC_STRFOOD])
@ -5174,7 +5177,7 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan
if(sc->data[SC__ENERVATION]) if(sc->data[SC__ENERVATION])
batk -= batk * sc->data[SC__ENERVATION]->val2 / 100; batk -= batk * sc->data[SC__ENERVATION]->val2 / 100;
if( sc->data[SC_ZANGETSU] ) if( sc->data[SC_ZANGETSU] )
batk += batk * sc->data[SC_ZANGETSU]->val2 / 100; batk += sc->data[SC_ZANGETSU]->val2;
if(sc->data[SC_EQC]) if(sc->data[SC_EQC])
batk -= batk * sc->data[SC_EQC]->val3 / 100; batk -= batk * sc->data[SC_EQC]->val3 / 100;
if(sc->data[SC_QUEST_BUFF1]) if(sc->data[SC_QUEST_BUFF1])
@ -5543,7 +5546,7 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
if (sc->data[SC_TEARGAS]) if (sc->data[SC_TEARGAS])
flee -= flee * 50 / 100; flee -= flee * 50 / 100;
if( sc->data[SC_C_MARKER] ) if( sc->data[SC_C_MARKER] )
flee -= 10; flee -= (flee * sc->data[SC_C_MARKER]->val3) / 100;
if(sc->data[SC_HEAT_BARREL]) if(sc->data[SC_HEAT_BARREL])
flee -= sc->data[SC_HEAT_BARREL]->val4; flee -= sc->data[SC_HEAT_BARREL]->val4;
@ -9695,7 +9698,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break; break;
case SC_PAIN_KILLER: // Yommy leak need confirm case SC_PAIN_KILLER: // Yommy leak need confirm
val2 = 10 * val1; // aspd reduction % val2 = 10 * val1; // aspd reduction %
val3 = (( 200 * val1 ) * status_get_lv(src)) / 150; // dmg reduction linear val3 = min((( 200 * val1 ) * status_get_lv(src)) / 150, 1000); // dmg reduction linear. upto a maximum of 1000 [iRO Wiki]
if(sc->data[SC_PARALYSIS]) if(sc->data[SC_PARALYSIS])
sc_start(src,bl, SC_ENDURE, 100, val1, tick); // Start endure for same duration sc_start(src,bl, SC_ENDURE, 100, val1, tick); // Start endure for same duration
break; break;
@ -9775,8 +9778,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break; break;
case SC_C_MARKER: case SC_C_MARKER:
val2 = src->id; val2 = src->id;
val3 = 10; //-10% flee
//Start timer to send mark on mini map //Start timer to send mark on mini map
val3 = tick/1000; val4 = tick/1000;
tick_time = 1000; tick_time = 1000;
break; break;
case SC_H_MINE: case SC_H_MINE:
@ -11256,8 +11260,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
if(!status_charge(bl, 0, sce->val4)) if(!status_charge(bl, 0, sce->val4))
break; // Not enough SP to continue. break; // Not enough SP to continue.
if (!sc->data[SC_INCSTR]) { if (!sc->data[SC_CHASEWALK2]) {
sc_start(bl,bl, SC_INCSTR,100,1<<(sce->val1-1), sc_start(bl,bl, SC_CHASEWALK2,100,1<<(sce->val1-1),
(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE?10:1) // SL bonus -> x10 duration (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE?10:1) // SL bonus -> x10 duration
*skill_get_time2(status_sc2skill(type),sce->val1)); *skill_get_time2(status_sc2skill(type),sce->val1));
} }
@ -12039,7 +12043,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
} }
break; break;
case SC_C_MARKER: case SC_C_MARKER:
if( --(sce->val3) >= 0 ) { if( --(sce->val4) >= 0 ) {
TBL_PC *tsd = map_id2sd(sce->val2); TBL_PC *tsd = map_id2sd(sce->val2);
if (!tsd || tsd->bl.m != bl->m) //End the SC if caster isn't in same map if (!tsd || tsd->bl.m != bl->m) //End the SC if caster isn't in same map
break; break;

View File

@ -701,6 +701,7 @@ typedef enum sc_type {
SC__FEINTBOMB, SC__FEINTBOMB,
SC__CHAOS, SC__CHAOS,
SC_ELEMENTAL_SHIELD, SC_ELEMENTAL_SHIELD,
SC_CHASEWALK2,
#ifdef RENEWAL #ifdef RENEWAL
SC_EXTREMITYFIST2, //! NOTE: This SC should be right before SC_MAX, so it doesn't disturb if RENEWAL is disabled SC_EXTREMITYFIST2, //! NOTE: This SC should be right before SC_MAX, so it doesn't disturb if RENEWAL is disabled
@ -893,7 +894,7 @@ enum si_type {
// SI_DEFENCE = 179, // SI_DEFENCE = 179,
// SI_SLOWDOWN = 180, // SI_SLOWDOWN = 180,
SI_PRESERVE = 181, SI_PRESERVE = 181,
SI_INCSTR = 182, SI_CHASEWALK2 = 182,
// SI_NOT_EXTREMITYFIST = 183, // SI_NOT_EXTREMITYFIST = 183,
SI_INTRAVISION = 184, SI_INTRAVISION = 184,
// SI_MOVESLOW_POTION = 185, // SI_MOVESLOW_POTION = 185,

View File

@ -180,7 +180,7 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data,
return 1; return 1;
} }
if( (item_data->bound > 1) && !pc_can_give_bounded_items(sd) ) { if( (item_data->bound > BOUND_ACCOUNT) && !pc_can_give_bounded_items(sd) ) {
clif_displaymessage(sd->fd, msg_txt(sd,294)); clif_displaymessage(sd->fd, msg_txt(sd,294));
return 1; return 1;
} }
@ -519,7 +519,7 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
return 1; return 1;
} }
if( (item_data->bound == 1 || item_data->bound > 2) && !pc_can_give_bounded_items(sd) ) { if( (item_data->bound == BOUND_ACCOUNT || item_data->bound > BOUND_GUILD) && !pc_can_give_bounded_items(sd) ) {
clif_displaymessage(sd->fd, msg_txt(sd,294)); clif_displaymessage(sd->fd, msg_txt(sd,294));
return 1; return 1;
} }

View File

@ -379,7 +379,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
return; return;
} }
if( ((item->bound == 1 || item->bound > 2) || (item->bound == 2 && sd->status.guild_id != target_sd->status.guild_id)) && !pc_can_give_bounded_items(sd) ) { // Item Bound if( ((item->bound == BOUND_ACCOUNT || item->bound > BOUND_GUILD) || (item->bound == BOUND_GUILD && sd->status.guild_id != target_sd->status.guild_id)) && !pc_can_give_bounded_items(sd) ) { // Item Bound
clif_displaymessage(sd->fd, msg_txt(sd,293)); clif_displaymessage(sd->fd, msg_txt(sd,293));
clif_tradeitemok(sd, index+2, 1); clif_tradeitemok(sd, index+2, 1);
return; return;