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_ELEMENTAL_SHIELD 596
SC_EXTREMITYFIST2 597
SC_CHASEWALK2 598
//Status Icon
SI_BLANK -1
@ -1926,7 +1927,7 @@ SI_MAXSPPERCENT 178
SI_DEFENCE 179
SI_SLOWDOWN 180
SI_PRESERVE 181
SI_INCSTR 182
SI_CHASEWALK2 182
SI_NOT_EXTREMITYFIST 183
SI_INTRAVISION 184
SI_MOVESLOW_POTION 185
@ -4598,5 +4599,10 @@ IT_AMMO 10
IT_DELAYCONSUME 11
IT_CASH 18
Bound_Account 1
Bound_Guild 2
Bound_Party 3
Bound_Char 4
false 0
true 1

View File

@ -4,3 +4,4 @@
// <Flag>:
// 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
// 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>:
// 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
// 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
604,1 //Branch_Of_Dead_Tree

View File

@ -118,7 +118,7 @@
//****
// 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
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
@ -678,25 +678,25 @@
//****
// 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
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
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
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
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
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,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
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
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
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
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,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,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
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
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
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
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
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,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,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,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
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; }
15088:18816:18818,{ bonus bMatk,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; }
18538:5041,{ bonus2 bSubRace,RC_Angel,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;}
18776:20710,{ bonus bBaseAtk,10; }
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; }
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; } }
@ -303,5 +304,4 @@
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; }
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; }

View File

@ -4,6 +4,7 @@
// <Flag>:
// 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
// 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
604,1 //Branch_Of_Dead_Tree

View File

@ -118,7 +118,7 @@
//****
// 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
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
@ -678,25 +678,25 @@
//****
// 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
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
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
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
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
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,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
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
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
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
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,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,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
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
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
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
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
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,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,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,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
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.
Valid bound types are:
1 - Account Bound
2 - Guild Bound
3 - Party Bound
4 - Character Bound
Bound_Account : Account Bound item
Bound_Guild : Guild Bound item
Bound_Party : Party Bound item
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 name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>};
*storageitem2 <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 id>,<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.
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,15, &data, NULL); msg->item.unique_id = strtoull(data, NULL, 10);
msg->item.expire_time = 0;
msg->item.bound = 0;
msg->item.bound = BOUND_NONE;
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);
while( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) {
if(item.bound == 2) {
if(item.bound == BOUND_GUILD) {
memcpy(&items[i],&item,sizeof(struct item));
i++;
}

View File

@ -785,6 +785,16 @@ enum {
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...
#if MAX_ZENY > INT_MAX
#error MAX_ZENY is too big

View File

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

View File

@ -13,7 +13,7 @@
static char global_db_hostname[32] = "127.0.0.1";
static uint16 global_db_port = 3306;
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_codepage[32] = "";
// local sql settings

View File

@ -1198,7 +1198,7 @@ ACMD_FUNC(heal)
ACMD_FUNC(item)
{
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_data *item_data[10];
int get_count, i, j=0;
@ -1207,12 +1207,19 @@ ACMD_FUNC(item)
nullpo_retr(-1, sd);
memset(item_name, '\0', sizeof(item_name));
if (!strcmpi(command+1,"itembound") && (!message || !*message || (
sscanf(message, "\"%99[^\"]\" %d %d", item_name, &number, &bound) < 2 &&
sscanf(message, "%99s %d %d", item_name, &number, &bound) < 2
))) {
clif_displaymessage(fd, msg_txt(sd,295)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity> <bound_type>).
return -1;
if (!strcmpi(command+1,"itembound")) {
if (!message || !*message || (
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>).
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 || (
sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 &&
sscanf(message, "%99s %d", item_name, &number) < 1
@ -1231,11 +1238,6 @@ ACMD_FUNC(item)
j++;
}
if( bound < 0 || bound > 4 ) {
clif_displaymessage(fd, msg_txt(sd,298)); // Invalid bound type
return -1;
}
if (number <= 0)
number = 1;
get_count = number;
@ -1273,19 +1275,27 @@ ACMD_FUNC(item2)
struct item item_tmp;
struct item_data *item_data;
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 c1 = 0, c2 = 0, c3 = 0, c4 = 0;
nullpo_retr(-1, sd);
memset(item_name, '\0', sizeof(item_name));
if (!strcmpi(command+1,"itembound2") && (!message || !*message || (
sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 &&
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,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>).
return -1;
if (!strcmpi(command+1,"itembound2")) {
if (!message || !*message || (
sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 &&
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,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 || (
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
@ -1298,11 +1308,6 @@ ACMD_FUNC(item2)
if (number <= 0)
number = 1;
if( bound < 0 || bound > 4 ) {
clif_displaymessage(fd, msg_txt(sd,298)); // Invalid bound type
return -1;
}
item_id = 0;
if ((item_data = itemdb_searchname(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) {
sprintf(atcmd_output," %d. %s : %d%%, %d%%, %d%%, %d%% | %d"
,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].mob
,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)
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 )
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;
}
/*==========================================
* Damage calculation for adjusting skill damage
* Credits:
[Lilith] for the first release of this
[Cydh] finishing and adding mapflag
* battle_skill_damage_skill() - skill_id based
* battle_skill_damage_map() - map based
*------------------------------------------*/
/** Damage calculation for adjusting skill damage
* @param caster Applied caster type for damage skill
* @param type BL_Type of attacker
* @author [Lilith] for the first release of this, [Cydh]
**/
#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)
return false;
while (1) {
if (caster&SDC_PC && type == BL_PC) break;
if (caster&SDC_MOB && type == BL_MOB) break;
if (caster&SDC_PET && type == BL_PET) break;
if (caster&SDC_HOM && type == BL_HOM) break;
if (caster&SDC_MER && type == BL_MER) break;
if (caster&SDC_ELEM && type == BL_ELEM) break;
return false;
switch (src_type) {
case BL_PC: if (caster&SDC_PC) return true; break;
case BL_MOB: if (caster&SDC_MOB) return true; break;
case BL_PET: if (caster&SDC_PET) return true; break;
case BL_HOM: if (caster&SDC_HOM) return true; break;
case BL_MER: if (caster&SDC_MER) return true; break;
case BL_ELEM: if (caster&SDC_ELEM) return true; break;
}
return true;
return false;
}
static int battle_skill_damage_skill(struct block_list *src, struct block_list *target, uint16 skill_id)
{
unsigned short m = src->m;
int idx;
/** Gets skill damage rate from a skill (based on skill_damage_db.txt)
* @param src
* @param target
* @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;
if ((idx = skill_get_index(skill_id)) < 0 || !skill_db[idx].damage.map)
if (!idx || !skill_db[idx].damage.map)
return 0;
damage = &skill_db[idx].damage;
//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;
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;
}
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;
uint16 m = src->m;
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)
return 0;
/* modifier for all skills */
if (battle_skill_damage_iscaster(map[m].adjust.damage.caster,src->type)) {
// Damage rate for all skills at this map
if (battle_skill_damage_iscaster(map[m].adjust.damage.caster, src->type)) {
switch (target->type) {
case BL_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 */
ARR_FIND(0,MAX_MAP_SKILL_MODIFIER,i,map[m].skill_damage[i].skill_id == skill_id);
if (i < MAX_MAP_SKILL_MODIFIER) {
if (battle_skill_damage_iscaster(map[m].skill_damage[i].caster,src->type)) {
// Damage rate for specified skill at this map
ARR_FIND(0, ARRAYLENGTH(map[m].skill_damage), i, map[m].skill_damage[i].skill_id == skill_id);
if (i < ARRAYLENGTH(map[m].skill_damage)) {
if (battle_skill_damage_iscaster(map[m].skill_damage[i].caster, src->type)) {
switch (target->type) {
case BL_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;
}
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)
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
@ -2865,9 +2874,9 @@ struct Damage battle_calc_skill_base_damage(struct Damage wd, struct block_list
}
//For quick div adjustment.
#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_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(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_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
*---------------------------------------
@ -3825,8 +3834,8 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
break;
case RL_D_TAIL:
skillratio += -100 + (2500 + 500 * skill_lv );
if (sd && &sd->c_marker)
skillratio /= max(sd->c_marker.count,1);
//if (sd && &sd->c_marker)
// skillratio /= max(sd->c_marker.count,1);
break;
case RL_R_TRIP:
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:
skillratio += -100 + 2000 + status_get_dex(src); //(custom) //kRO Update 2013-07-24. 2,000% + caster's DEX (?) [Cydh]
break;
case RL_AM_BLAST:
skillratio += -100 + (skill_lv * status_get_dex(src) / 2); //(custom)
break;
}
return skillratio;
}
@ -4656,7 +4668,7 @@ struct Damage battle_calc_weapon_final_atk_modifiers(struct Damage wd, struct bl
#endif
}
/* Skill damage adjustment */
// Skill damage adjustment
#ifdef ADJUST_SKILL_DAMAGE
if ((skill_damage = battle_skill_damage(src, target, skill_id)) != 0)
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
damage_div_fix_renewal(wd, wd.div_);
DAMAGE_DIV_FIX_RENEWAL(wd, wd.div_);
#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
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
}
damage_div_fix(ad.damage, ad.div_);
DAMAGE_DIV_FIX(ad.damage, ad.div_);
if (flag.infdef && ad.damage)
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;
}
/* Skill damage adjustment */
// Skill damage adjustment
#ifdef ADJUST_SKILL_DAMAGE
if ((skill_damage = battle_skill_damage(src,target,skill_id)) != 0)
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) {
//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
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));
}
damage_div_fix(md.damage, md.div_);
DAMAGE_DIV_FIX(md.damage, md.div_);
if (!(nk&NK_IGNORE_FLEE))
{
@ -6294,7 +6306,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
break;
}
/* Skill damage adjustment */
// Skill damage adjustment
#ifdef ADJUST_SKILL_DAMAGE
if ((skill_damage = battle_skill_damage(src,target,skill_id)) != 0)
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;
#endif
#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
}
@ -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
#if PACKETVER >= 20071002
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
#if PACKETVER >= 20100629
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;
}
int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed) {
int idx = skill_get_index(skill_id);
bool elemental_skillnotok(uint16 skill_id, struct elemental_data *ed) {
uint16 idx = skill_get_index(skill_id);
nullpo_retr(1,ed);
if (idx == 0)
return 1; // invalid skill id
return false; // invalid skill id
return skill_isNotOk(skill_id,ed->master);
}
struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){
struct skill_condition req;
int idx = skill_get_index(skill_id);
uint16 idx = skill_get_index(skill_id);
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_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_clean_single_effect(struct elemental_data *ed, uint16 skill_id);
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
j = pc_bound_chk(sd,2,idxlist);
for(i=0;i<j;i++)
sd->status.inventory[idxlist[i]].bound = 0;
sd->status.inventory[idxlist[i]].bound = BOUND_NONE;
#endif
intif_guild_break(g->guild_id);

View File

@ -471,13 +471,14 @@ struct item_data* itemdb_search(int nameid)
return id;
}
/*==========================================
* Returns if given item is a player-equippable piece.
*------------------------------------------*/
bool itemdb_isequip(int nameid)
/** Checks if item is equip type or not
* @param id Item data
* @return True if item is equip, false otherwise
*/
bool itemdb_isequip2(struct item_data *id)
{
int type=itemdb_type(nameid);
switch (type) {
nullpo_ret(id);
switch(id->type) {
case IT_WEAPON:
case IT_ARMOR:
case IT_AMMO:
@ -488,48 +489,14 @@ bool itemdb_isequip(int nameid)
}
}
/*==========================================
* Alternate version of itemdb_isequip
*------------------------------------------*/
bool itemdb_isequip2(struct item_data *data)
/** Checks if item is stackable or not
* @param id Item data
* @return True if item is stackable, false otherwise
*/
bool itemdb_isstackable2(struct item_data *id)
{
nullpo_ret(data);
switch(data->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) {
nullpo_ret(id);
switch(id->type) {
case IT_WEAPON:
case IT_ARMOR:
case IT_PETEGG:
@ -665,7 +632,7 @@ static void itemdb_read_itemgroup_sub(const char* filename, bool silent)
unsigned int j, prob = 1;
uint16 nameid, amt = 1, dur = 0;
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_db *group = NULL;
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[6] != NULL) dur = cap_value(atoi(str[6]),0,UINT16_MAX);
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;
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
* <item_id>,<flag>
* &1 - Log as dead branch
* &1 - As dead branch item
* &2 - As item container
*/
static bool itemdb_read_flag(char* fields[], int columns, int current) {
uint16 nameid = atoi(fields[0]);
uint8 flag = atoi(fields[1]);
uint8 flag;
bool set;
struct item_data *id;
if (!(id = itemdb_exists(nameid))) {
ShowError("itemdb_read_flag: Invalid item item with id %d\n", nameid);
return true;
}
flag = abs(atoi(fields[1]));
set = atoi(fields[1]) > 0;
if (flag&1)
id->flag.dead_branch = 1;
if (flag&2)
id->flag.group = 1;
if (flag&1) id->flag.dead_branch = set ? 1 : 0;
if (flag&2) id->flag.group = set ? 1 : 0;
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++ ) {
if( !self->combos[i]->isRef ) {
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]);
}

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_canauction(item, gmlv) itemdb_isrestricted(item , gmlv, 0, itemdb_canauction_sub)
bool itemdb_isequip(int);
bool itemdb_isequip2(struct item_data *);
bool itemdb_isequip2(struct item_data *id);
#define itemdb_isequip(nameid) itemdb_isequip2(itemdb_search(nameid))
char itemdb_isidentified(int);
bool itemdb_isstackable(uint16 nameid);
bool itemdb_isstackable2(struct item_data *data);
bool itemdb_isstackable2(struct item_data *id);
#define itemdb_isstackable(nameid) itemdb_isstackable2(itemdb_search(nameid))
uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID
bool itemdb_isNoEquip(struct item_data *id, uint16 m);

View File

@ -65,7 +65,7 @@ char default_codepage[32] = "";
int map_server_port = 3306;
char map_server_ip[32] = "127.0.0.1";
char map_server_id[32] = "ragnarok";
char map_server_pw[32] = "ragnarok";
char map_server_pw[32] = "";
char map_server_db[32] = "ragnarok";
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_SOULCOLD, 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)
status_change_end(&sd->bl, SC_ENDURE, INVALID_TIMER); //No need to save infinite endure.
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);
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) {
if (skill_db[idx].unit_nonearnpc_type&1 && nd->subtype == WARP) 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;
else if (!strcmpi(w3,"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;
memset(skill,0,sizeof(skill));
map[m].flag.skill_damage = state; //set the mapflag
memset(skill, 0, sizeof(skill));
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) {
caster = (!caster) ? SDC_ALL : caster;
pc = cap_value(pc,-100,MAX_SKILL_DAMAGE_RATE);
mob = cap_value(mob,-100,MAX_SKILL_DAMAGE_RATE);
boss = cap_value(boss,-100,MAX_SKILL_DAMAGE_RATE);
other = cap_value(other,-100,MAX_SKILL_DAMAGE_RATE);
if (!state) {
memset(map[m].skill_damage, 0, sizeof(map[m].skill_damage));
memset(&map[m].adjust.damage, 0, sizeof(map[m].adjust.damage));
}
else {
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
map[m].adjust.damage.caster = caster;
map[m].adjust.damage.pc = pc;
map[m].adjust.damage.mob = mob;
map[m].adjust.damage.boss = boss;
map[m].adjust.damage.other = other;
}
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));
else { //damages for specified skill
int i;
ARR_FIND(0,MAX_MAP_SKILL_MODIFIER,i,map[m].skill_damage[i].skill_id <= 0);
if (i >= MAX_SKILL)
ShowWarning("npc_parse_mapflag: skill_damage: Skill damage for map '%s' is overflow.\n",map[m].name);
else {
map[m].skill_damage[i].skill_id = skill_name2id(skill);
map[m].skill_damage[i].caster = caster;
map[m].skill_damage[i].pc = pc;
map[m].skill_damage[i].mob = mob;
map[m].skill_damage[i].boss = boss;
map[m].skill_damage[i].other = other;
if (strcmp(skill,"all") == 0) { // Adjust damages for all skills
map[m].adjust.damage.caster = caster;
map[m].adjust.damage.pc = pc;
map[m].adjust.damage.mob = mob;
map[m].adjust.damage.boss = boss;
map[m].adjust.damage.other = other;
}
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));
else { //damages for specified skill
uint8 i;
ARR_FIND(0, ARRAYLENGTH(map[m].skill_damage), i, map[m].skill_damage[i].skill_id <= 0);
if (i >= ARRAYLENGTH(map[m].skill_damage))
ShowWarning("npc_parse_mapflag: skill_damage: Skill damage for map '%s' is overflow.\n", map[m].name);
else {
map[m].skill_damage[i].skill_id = skill_name2id(skill);
map[m].skill_damage[i].caster = caster;
map[m].skill_damage[i].pc = pc;
map[m].skill_damage[i].mob = mob;
map[m].skill_damage[i].boss = boss;
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;
}
/*==========================================
/**
* Searching a specified itemid in inventory and return his stored index
*------------------------------------------*/
int pc_search_inventory(struct map_session_data *sd,int item_id)
{
* @param sd Player
* @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;
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;
}
@ -4736,7 +4738,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
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]
clif_displaymessage (sd->fd, msg_txt(sd,264));
return 1;
@ -4896,7 +4898,7 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
* 3 Party 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;
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
* @return player skill cooldown
*/
int pc_get_skillcooldown(struct map_session_data *sd, int id, int lv) {
int i, cooldown=0;
int idx = skill_get_index (id);
int cooldownlen = ARRAYLENGTH(sd->skillcooldown);
int pc_get_skillcooldown(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv) {
uint8 i;
uint16 idx = skill_get_index(skill_id);
int cooldown = 0, cooldownlen = ARRAYLENGTH(sd->skillcooldown);
if (!idx) return 0;
if (skill_db[idx].cooldown[lv - 1])
cooldown = skill_db[idx].cooldown[lv - 1];
if (skill_db[idx].cooldown[skill_lv - 1])
cooldown = skill_db[idx].cooldown[skill_lv - 1];
ARR_FIND(0, cooldownlen, i, sd->skillcooldown[i].id == id);
if(i<cooldownlen){
ARR_FIND(0, cooldownlen, i, sd->skillcooldown[i].id == skill_id);
if (i < cooldownlen) {
cooldown += sd->skillcooldown[i].val;
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_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);
short pc_checkequip(struct map_session_data *sd,int pos);
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_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*);
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_delitem(struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type);
//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
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_Orcish",OPTION_ORCISH,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_Flying",OPTION_FLYING,false);
script_set_constant("Option_Xmas",OPTION_XMAS,false);
@ -6455,22 +6456,24 @@ BUILDIN_FUNC(getitem)
if( !strcmp(script_getfuncname(st),"getitembound") ) {
char bound = script_getnum(st,4);
if( bound < 1 || bound > 4) { //Not a correct bound type
ShowError("script_getitembound: Not a correct bound type! Type=%d\n",bound);
return 1;
if( bound > BOUND_NONE && bound < BOUND_MAX ) {
it.bound = bound;
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) )
sd=map_id2sd(script_getnum(st,4)); // <Account ID>
else
sd=script_rid2sd(st); // Attached player
if( sd == NULL ) // no target
return 0;
return SCRIPT_CMD_SUCCESS;
//Check if it's stackable.
if (!itemdb_isstackable(nameid))
@ -6499,9 +6502,9 @@ BUILDIN_FUNC(getitem)
*------------------------------------------*/
BUILDIN_FUNC(getitem2)
{
int nameid,amount,get_count,i,flag = 0;
int iden,ref,attr,c1,c2,c3,c4;
char bound=0;
int nameid, amount, get_count, i, flag = 0;
int iden, ref, attr, c1, c2, c3, c4;
char bound = BOUND_NONE;
struct item_data *item_data;
struct item item_tmp;
TBL_PC *sd;
@ -6509,21 +6512,23 @@ BUILDIN_FUNC(getitem2)
if( !strcmp(script_getfuncname(st),"getitembound2") ) {
bound = script_getnum(st,11);
if( bound < 1 || bound > 3) { //Not a correct bound type
ShowError("script_getitembound2: Not a correct bound type! Type=%d\n",bound);
return 1;
if( bound > BOUND_NONE && bound < BOUND_MAX ) {
if( script_hasdata(st,12) )
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) )
sd=map_id2sd(script_getnum(st,11)); // <Account ID>
else
sd=script_rid2sd(st); // Attached player
if( sd == NULL ) // no target
return 0;
return SCRIPT_CMD_SUCCESS;
data=script_getdata(st,2);
get_val(st,data);
@ -6652,7 +6657,7 @@ BUILDIN_FUNC(rentitem) {
it.nameid = nameid;
it.identify = 1;
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)) )
{
@ -11472,7 +11477,8 @@ BUILDIN_FUNC(removemapflag)
case MF_SKILL_DAMAGE:
{
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;
#endif
}
@ -18228,24 +18234,24 @@ BUILDIN_FUNC(stand)
/** Creates an array of bounded item IDs
* 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
*/
BUILDIN_FUNC(countbound)
{
int i, type, j=0, k=0;
int i, type, j = 0, k = 0;
TBL_PC *sd;
if( (sd = script_rid2sd(st)) == NULL )
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++){
if(sd->status.inventory[i].nameid > 0 && (
(!type && sd->status.inventory[i].bound > 0) ||
(type && sd->status.inventory[i].bound == type)
)) {
for( i = 0; i < MAX_INVENTORY; i ++ ) {
if( sd->status.inventory[i].nameid > 0 && (
(!type && sd->status.inventory[i].bound) || (type && sd->status.inventory[i].bound == type)
))
{
pc_setreg(sd,reference_uid(add_str("@bound_items"), k),sd->status.inventory[i].nameid);
k++;
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
*/
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
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) {
int inf;
if (!src || skill_get_index(skill_id) < 0)
if (!src || skill_get_index(skill_id) == 0)
return false;
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:
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)
else if (dstsd) {
pc_setsit(dstsd);
clif_sitting(bl);
}
else if (dstsd)
//sit duration 2+skill_lv
status_change_start(src,bl,SC_SITDOWN_FORCE,10000,skill_lv,0,0,0,(2+skill_lv)*1000,1|2|8);
break;
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_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_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_MLEATKED: case SC_MTF_CRIDAMAGE: case SC_GN_CARTBOOST:
#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])
return;
else {
short idx;
uint16 idx;
unsigned char lv;
// 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]
if ((idx = skill_get_index(skill_id)) < 0)
if (!(idx = skill_get_index(skill_id)))
return;
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();
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]
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 )
return 0;
// Requeriments
// Requirements
for( i = 0; i < ARRAYLENGTH(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;
case ST_MADO:
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;
}
break;
@ -14475,10 +14474,6 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
if (require.status_count) {
uint8 i;
/* 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++) {
enum sc_type req_sc = require.status[i];
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
if (require.eqItem_count) {
for (i = 0; i < require.eqItem_count; i++) {
int reqeqit = require.eqItem[i];
if(!reqeqit) break; //no more required item get out of here
uint16 reqeqit = require.eqItem[i];
if (!reqeqit)
break; //no more required item get out of here
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
sprintf(output,msg_txt(sd,722),itemdb_jname(reqeqit));
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 status_data *status;
int i;
int index[MAX_SKILL_ITEM_REQUIRE];
short index[MAX_SKILL_ITEM_REQUIRE];
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 )
clif_skill_fail(sd,skill_id,USESKILL_FAIL_ANCILLA,0); //Ancilla is required.
else {
char output[128];
char output[CHAT_SIZE_MAX];
//Official is using msgstringtable.txt for each requirement failure
//clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
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)
{
struct skill_condition req;
struct skill_condition require;
nullpo_retv(sd);
req = skill_get_requirement(sd,skill_id,skill_lv);
require = skill_get_requirement(sd,skill_id,skill_lv);
if( type&1 ) {
switch( skill_id ) {
case CG_TAROTCARD: // TarotCard will consume sp in skill_cast_nodamage_id [Inkfish]
case MC_IDENTIFY:
case RL_D_TAIL:
req.sp = 0;
require.sp = 0;
break;
case GS_DESPERADO:
if (sd->skill_id_old == RL_FALLEN_ANGEL) //Don't consume SP if triggered by Fallen Angel
req.sp = 0;
require.sp = 0;
break;
default:
if(sd->state.autocast)
req.sp = 0;
require.sp = 0;
break;
}
if(req.hp || req.sp)
status_zap(&sd->bl, req.hp, req.sp);
if(require.hp || require.sp)
status_zap(&sd->bl, require.hp, require.sp);
if(req.spiritball > 0)
pc_delspiritball(sd,req.spiritball,0);
else if(req.spiritball == -1) {
if(require.spiritball > 0)
pc_delspiritball(sd,require.spiritball,0);
else if(require.spiritball == -1) {
sd->spiritball_old = sd->spiritball;
pc_delspiritball(sd,sd->spiritball,0);
}
if(req.zeny > 0)
if(require.zeny > 0)
{
if( skill_id == NJ_ZENYNAGE )
req.zeny = 0; //Zeny is reduced on skill_attack.
if( sd->status.zeny < req.zeny )
req.zeny = sd->status.zeny;
pc_payzeny(sd,req.zeny,LOG_TYPE_CONSUME,NULL);
require.zeny = 0; //Zeny is reduced on skill_attack.
if( sd->status.zeny < require.zeny )
require.zeny = sd->status.zeny;
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 )
{
if( !req.itemid[i] )
if( !require.itemid[i] )
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.
switch( skill_id ){
@ -14831,8 +14826,8 @@ void skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, ui
break;
}
if( (n = pc_search_inventory(sd,req.itemid[i])) >= 0 )
pc_delitem(sd,n,req.amount[i],0,1,LOG_TYPE_CONSUME);
if( (n = pc_search_inventory(sd,require.itemid[i])) >= 0 )
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;
int i,hp_rate,sp_rate, sp_skill_rate_bonus = 100;
uint16 idx;
bool level_dependent = false;
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 = 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 ) {
/* Skill level-dependent checks */
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 SO_SUMMON_AGNI:
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_WIND_INSIGNIA:
case SO_EARTH_INSIGNIA:
req.itemid[skill_lv-1] = skill_db[idx].require.itemid[skill_lv-1];
req.amount[skill_lv-1] = skill_db[idx].require.amount[skill_lv-1];
case WZ_FIREPILLAR: // no gems required at level 1-5 [celest]
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;
}
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
switch(skill_id) {
@ -19350,29 +19322,37 @@ static bool skill_parse_row_skilldb(char* split[], int columns, int current)
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 *val: Temporary storage
* @param *delim: Delimiter (for multiple value support)
* @param useConst: 'true' uses const.txt as reference, 'false' uses atoi()
* @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 min_value: Minimum value. If the splitted value is less or equal than this, will be skipped
* @param max: Maximum number that can be allocated
* @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;
char *p = strtok(str,delim);
char *p = strtok(str, delim);
while (p != NULL) {
int n = -1;
if (useConst)
script_get_constant(trim(p),&n);
else
int n = min_value;
trim(p);
if (ISDIGIT(p[0])) // If using numeric
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;
i++;
if (i >= max)
break;
}
p = strtok(NULL,delim);
p = strtok(NULL, delim);
}
return i;
}
@ -19383,8 +19363,10 @@ static void skill_destroy_requirement(void) {
for (i = 0; i < MAX_SKILL; i++) {
if (skill_db[i].require.status_count)
aFree(skill_db[i].require.status);
skill_db[i].require.status_count = 0;
if (skill_db[i].require.eqItem_count)
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;
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;
idx = skill_get_index(skill_id);
skill_split_atoi(split[1],skill_db[idx].require.hp);
skill_split_atoi(split[2],skill_db[idx].require.mhp);
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
//Status requirements
//FIXME: Default entry should be -1/SC_ALL in skill_require_db.txt but it's 0/SC_STONE.
trim(split[11]);
if (split[11][0] != '\0') {
if (split[11][0] != '\0' || atoi(split[11])) {
int require[MAX_SKILL_STATUS_REQUIRE];
if ((skill_db[idx].require.status_count = skill_split2(split[11],require,":",true,SC_NONE))) {
skill_db[idx].require.status = aMalloc(skill_db[idx].require.status_count * sizeof(sc_type));
if ((skill_db[idx].require.status_count = skill_split_atoi2(split[11], require, ":", SC_STONE, ARRAYLENGTH(require)))) {
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++)
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.
//NOTE: We don't check the item is exist or not here
trim(split[33]);
if (split[33][0] != '\0') {
if (split[33][0] != '\0' || atoi(split[33])) {
int require[MAX_SKILL_EQUIP_REQUIRE];
if ((skill_db[idx].require.eqItem_count = skill_split2(split[33],require,":",false,501))) {
skill_db[idx].require.eqItem = aMalloc(skill_db[idx].require.eqItem_count * sizeof(short));
if ((skill_db[idx].require.eqItem_count = skill_split_atoi2(split[33], require, ":", 500, ARRAYLENGTH(require)))) {
CREATE(skill_db[idx].require.eqItem, uint16, skill_db[idx].require.eqItem_count);
for (i = 0; i < skill_db[idx].require.eqItem_count; 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}
*/
static bool skill_parse_row_castdb(char* split[], int columns, int current) {
uint16 skill_id = atoi(split[0]);
uint16 idx = skill_get_index(skill_id);
uint16 idx = skill_get_index(atoi(split[0]));
if( !idx ) // invalid skill id
return false;
@ -19511,8 +19492,7 @@ static bool skill_parse_row_castdb(char* split[], int columns, int current) {
* SkillID,Cast,Delay (optional)
*/
static bool skill_parse_row_castnodexdb(char* split[], int columns, int current) {
uint16 skill_id = atoi(split[0]);
uint16 idx = skill_get_index(skill_id);
uint16 idx = skill_get_index(atoi(split[0]));
if( !idx ) // invalid skill id
return false;
@ -19527,8 +19507,7 @@ static bool skill_parse_row_castnodexdb(char* split[], int columns, int current)
* SkillID,Flag
*/
static bool skill_parse_row_nocastdb(char* split[], int columns, int current) {
uint16 skill_id = atoi(split[0]);
uint16 idx = skill_get_index(skill_id);
uint16 idx = skill_get_index(atoi(split[0]));
if( !idx ) // invalid skill id
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
*/
static bool skill_parse_row_unitdb(char* split[], int columns, int current) {
uint16 skill_id = atoi(split[0]);
uint16 idx = skill_get_index(skill_id);
uint16 idx = skill_get_index(atoi(split[0]));
if( !idx ) // invalid skill id
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) )
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));
if( points < 1 )
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;
trim(split[0]);
if(ISDIGIT(split[0][0]))
if (ISDIGIT(split[0][0]))
id = atoi(split[0]);
else
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]);
return false;
}
@ -19739,12 +19717,12 @@ static bool skill_parse_row_nonearnpcrangedb(char* split[], int column, int curr
int16 id;
trim(split[0]);
if(ISDIGIT(split[0][0]))
if (ISDIGIT(split[0][0]))
id = atoi(split[0]);
else
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]);
return false;
}
@ -19811,27 +19789,27 @@ static bool skill_parse_row_changematerialdb(char* split[], int columns, int cur
return true;
}
/*==========================================
/**
* Manage Skill Damage database [Lilith]
*------------------------------------------*/
**/
#ifdef ADJUST_SKILL_DAMAGE
static bool skill_parse_row_skilldamage(char* split[], int columns, int current)
{
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]);
return false;
}
memset(&skill_db[idx].damage,0,sizeof(struct s_skill_damage));
skill_db[idx].damage.caster |= atoi(split[1]);
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])
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])
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])
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;
}
#endif

View File

@ -22,6 +22,8 @@ struct status_change_entry;
#define MAX_SKILL_IMPROVISE_DB 50
#define MAX_SKILL_LEVEL 100
#define MAX_SKILL_CRIMSON_MARKER 3
#define SKILL_NAME_LENGTH 31
#define SKILL_DESC_LENGTH 31
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
};
#define MAX_SKILL_ITEM_REQUIRE 10
#define MAX_SKILL_STATUS_REQUIRE 3
#define MAX_SKILL_EQUIP_REQUIRE 10
#define MAX_SKILL_ITEM_REQUIRE 10 /// Maximum required items
#define MAX_SKILL_STATUS_REQUIRE 3 /// Maximum required statuses
#define MAX_SKILL_EQUIP_REQUIRE 10 /// Maximum required equipped item
struct skill_condition {
int hp,
mhp,
sp,
hp_rate,
sp_rate,
ammo,
ammo_qty,
weapon,
zeny,
state,
spiritball,
itemid[MAX_SKILL_ITEM_REQUIRE],
amount[MAX_SKILL_ITEM_REQUIRE];
short *eqItem;
enum sc_type *status;
uint8 status_count, eqItem_count;
int hp, /// HP cost
mhp, /// Max HP to trigger
sp, /// SP cost
hp_rate, /// HP cost (%)
sp_rate, /// SP cost (%)
ammo, /// Ammo type
ammo_qty, /// Amount of ammo
weapon, /// Weapon type
zeny, /// Zeny cost
state, /// State/condition
spiritball, /// Spiritball cost
itemid[MAX_SKILL_ITEM_REQUIRE], /// Required item
amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
uint16 *eqItem; /// List of equipped item
enum sc_type *status; /// List of Status required (SC)
uint8 status_count, /// Count of SC
eqItem_count; /// Count of equipped item
};
struct s_skill_require {
int hp[MAX_SKILL_LEVEL],
mhp[MAX_SKILL_LEVEL],
sp[MAX_SKILL_LEVEL],
hp_rate[MAX_SKILL_LEVEL],
sp_rate[MAX_SKILL_LEVEL],
zeny[MAX_SKILL_LEVEL],
weapon,
ammo,
ammo_qty[MAX_SKILL_LEVEL],
state,
spiritball[MAX_SKILL_LEVEL],
itemid[MAX_SKILL_ITEM_REQUIRE],
amount[MAX_SKILL_ITEM_REQUIRE];
short *eqItem;
enum sc_type *status;
uint8 status_count, eqItem_count;
int hp[MAX_SKILL_LEVEL], /// HP cost
mhp[MAX_SKILL_LEVEL], /// Max HP to trigger
sp[MAX_SKILL_LEVEL], /// SP cost
hp_rate[MAX_SKILL_LEVEL], /// HP cost (%)
sp_rate[MAX_SKILL_LEVEL], /// SP cost (%)
zeny[MAX_SKILL_LEVEL], /// Zeny cost
weapon, /// Weapon type
ammo, /// Ammo type
ammo_qty[MAX_SKILL_LEVEL], /// Amount of ammo
state, /// State/condition
spiritball[MAX_SKILL_LEVEL], /// Spiritball cost
itemid[MAX_SKILL_ITEM_REQUIRE], /// Required item
amount[MAX_SKILL_ITEM_REQUIRE]; /// Amount of item
uint16 *eqItem; /// List of equipped item
enum sc_type *status; /// List of Status required (SC)
uint8 status_count, /// Count of SC
eqItem_count; /// Count of equipped item
};
/// Database skills
struct s_skill_db {
char name[NAME_LENGTH];
char desc[40];
char name[SKILL_NAME_LENGTH];
char desc[SKILL_DESC_LENGTH];
int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max;
int num[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_SONG = 0x0400, // Song
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

View File

@ -821,11 +821,11 @@ void initChangeTables(void)
add_sc( RL_HAMMER_OF_GOD , SC_STUN );
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_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_HEAT_BARREL , SC_HEAT_BARREL , SI_HEAT_BARREL , SCB_BATK|SCB_ASPD|SCB_HIT );
set_sc_with_vfx( RL_C_MARKER , SC_C_MARKER , SI_C_MARKER , SCB_SPEED );
set_sc_with_vfx( RL_AM_BLAST , SC_ANTI_M_BLAST , SI_ANTI_M_BLAST , SCB_DEF_ELE );
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_FLEE );
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 );
@ -855,7 +855,7 @@ void initChangeTables(void)
StatusIconChangeTable[SC_ASPDPOTION3] = SI_ASPDPOTIONINFINITY;
StatusIconChangeTable[SC_SPEEDUP0] = SI_MOVHASTE_HORSE;
StatusIconChangeTable[SC_SPEEDUP1] = SI_SPEEDPOTION1;
StatusIconChangeTable[SC_INCSTR] = SI_INCSTR;
StatusIconChangeTable[SC_CHASEWALK2] = SI_CHASEWALK2;
StatusIconChangeTable[SC_MIRACLE] = SI_SPIRIT;
StatusIconChangeTable[SC_INTRAVISION] = SI_INTRAVISION;
StatusIconChangeTable[SC_STRFOOD] = SI_FOODSTR;
@ -1055,6 +1055,7 @@ void initChangeTables(void)
StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED;
StatusChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL;
StatusChangeFlagTable[SC_SLOWDOWN] |= SCB_SPEED;
StatusChangeFlagTable[SC_CHASEWALK2] |= SCB_STR;
/* Cash Items */
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;
if(sc->data[SC_INCALLSTATUS])
str += sc->data[SC_INCALLSTATUS]->val1;
if(sc->data[SC_CHASEWALK2])
str += sc->data[SC_CHASEWALK2]->val1;
if(sc->data[SC_INCSTR])
str += sc->data[SC_INCSTR]->val1;
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])
batk -= batk * sc->data[SC__ENERVATION]->val2 / 100;
if( sc->data[SC_ZANGETSU] )
batk += batk * sc->data[SC_ZANGETSU]->val2 / 100;
batk += sc->data[SC_ZANGETSU]->val2;
if(sc->data[SC_EQC])
batk -= batk * sc->data[SC_EQC]->val3 / 100;
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])
flee -= flee * 50 / 100;
if( sc->data[SC_C_MARKER] )
flee -= 10;
flee -= (flee * sc->data[SC_C_MARKER]->val3) / 100;
if(sc->data[SC_HEAT_BARREL])
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;
case SC_PAIN_KILLER: // Yommy leak need confirm
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])
sc_start(src,bl, SC_ENDURE, 100, val1, tick); // Start endure for same duration
break;
@ -9775,8 +9778,9 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
break;
case SC_C_MARKER:
val2 = src->id;
val3 = 10; //-10% flee
//Start timer to send mark on mini map
val3 = tick/1000;
val4 = tick/1000;
tick_time = 1000;
break;
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))
break; // Not enough SP to continue.
if (!sc->data[SC_INCSTR]) {
sc_start(bl,bl, SC_INCSTR,100,1<<(sce->val1-1),
if (!sc->data[SC_CHASEWALK2]) {
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
*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;
case SC_C_MARKER:
if( --(sce->val3) >= 0 ) {
if( --(sce->val4) >= 0 ) {
TBL_PC *tsd = map_id2sd(sce->val2);
if (!tsd || tsd->bl.m != bl->m) //End the SC if caster isn't in same map
break;

View File

@ -701,6 +701,7 @@ typedef enum sc_type {
SC__FEINTBOMB,
SC__CHAOS,
SC_ELEMENTAL_SHIELD,
SC_CHASEWALK2,
#ifdef RENEWAL
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_SLOWDOWN = 180,
SI_PRESERVE = 181,
SI_INCSTR = 182,
SI_CHASEWALK2 = 182,
// SI_NOT_EXTREMITYFIST = 183,
SI_INTRAVISION = 184,
// 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;
}
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));
return 1;
}
@ -519,7 +519,7 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
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));
return 1;
}

View File

@ -379,7 +379,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
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_tradeitemok(sd, index+2, 1);
return;