diff --git a/db/const.txt b/db/const.txt index 57250e4837..79dc4b66ea 100644 --- a/db/const.txt +++ b/db/const.txt @@ -626,6 +626,8 @@ bAddClassDropItemGroup 2071 bAddMaxWeight 2072 bAddItemGroupHealRate 2073 +bHPVanishRaceRate 2074 +bSPVanishRaceRate 2075 EQI_HEAD_TOP 1 EQI_ARMOR 2 diff --git a/db/re/item_db.txt b/db/re/item_db.txt index 9661543bb4..21bafae87a 100644 --- a/db/re/item_db.txt +++ b/db/re/item_db.txt @@ -646,7 +646,7 @@ 1291,Guillotine_Katar,Guillotine Katar,5,56000,,1500,200,,1,1,0x00001000,63,2,34,4,140,1,16,{ bonus bDex,2; bonus bFlee,-30; bonus2 bAddRace,RC_DemiHuman,50; bonus2 bAddRace,RC_Player,50; bonus2 bSkillAtk,"GC_CROSSIMPACT",30; },{},{} 1292,Upg_Katar,Upg Katar,5,20,,1000,80,,1,1,0x00001000,63,2,34,3,1,1,16,{ bonus bBaseAtk,(getrefine()*10); bonus bCritAtkRate,(getrefine()*2); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10); },{},{} 1293,Velum_Jamadhar,Vellum Jamadhar,5,20,,1200,170,,1,0,0x00001000,63,2,34,4,95,1,16,{ bonus4 bSetDefRace,RC_Player,10000,5000,1; bonus4 bSetMDefRace,RC_Player,10000,5000,1; bonus bAspdRate,getrefine(); },{},{} -1294,Velum_Scare,Vellum Scale,5,20,,1200,50,,1,0,0x00001000,63,2,34,4,95,1,16,{ bonus2 bSPVanishRate,10000,10; },{},{} +1294,Velum_Scare,Vellum Scale,5,20,,1200,50,,1,0,0x00001000,63,2,34,4,95,1,16,{ bonus3 bSPVanishRaceRate,RC_Player,10000,10; },{},{} 1295,Blood_Tears_,Blood Tears,5,20,,1700,120,,1,1,0x00001000,18,2,34,4,55,1,16,{},{},{} 1296,Metal_Katar,Metal Katar,5,20,,0,75,,1,1,0x00001000,63,2,34,3,1,1,16,{ bonus bBaseAtk,(getrefine()*5); bonus bCritAtkRate,getrefine(); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5); },{},{} // @@ -716,7 +716,7 @@ 1392,Ygnus_Stale,Ignus Steel,5,56000,,1900,250,,1,1,0x000444A2,63,2,34,4,95,1,7,{ bonus bAtkEle,Ele_Fire; bonus bUnbreakableWeapon,0; },{},{} 1393,End_Sektura,End Sectora,5,56000,,1900,250,,1,1,0x000444A2,63,2,34,4,95,1,7,{ bonus bAtkEle,Ele_Water; bonus bUnbreakableWeapon,0; },{},{} 1394,Upg_Two_Handed_Axe,Upg Two Handed Axe,5,20,,2000,110,,1,1,0x000444A2,63,2,34,3,1,1,7,{ bonus bBaseAtk,(getrefine()*14); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10); },{},{} -1395,Velum_Buster,Vellum Buster,5,20,,2500,50,,1,0,0x000444A2,63,2,34,4,95,1,7,{ bonus bUnbreakableWeapon,0; bonus2 bSPVanishRate,10000,10; },{},{} +1395,Velum_Buster,Vellum Buster,5,20,,2500,50,,1,0,0x000444A2,63,2,34,4,95,1,7,{ bonus bUnbreakableWeapon,0; bonus3 bSPVanishRaceRate,RC_Player,10000,10; },{},{} 1396,Velum_Guillotine,Vellum Guillotine,5,20,,5500,300,,1,0,0x000444A2,63,2,34,4,95,1,7,{ bonus bUnbreakableWeapon,0; bonus2 bAddRace,RC_Player,40; bonus2 bIgnoreDefRaceRate,RC_Player,30; if(getrefine()>=6) { bonus2 bSkillAtk,"NC_AXEBOOMERANG",80; bonus2 bSkillAtk,"NC_POWERSWING",80; } if(getrefine()>=9) { bonus2 bAddRace,RC_Player,60; } },{},{} 1397,Bradium_Stonehammer_,Bradium Stonehammer,5,20,,2700,210,,1,2,0x000444A2,63,2,34,4,75,1,7,{ bonus bUnbreakableWeapon,0; },{},{} 1398,Metal_Two_Handed_Axe,Metal Two Handed Axe,5,20,,0,105,,1,1,0x000444A2,63,2,34,3,1,1,7,{ bonus bUnbreakableWeapon,0; bonus bBaseAtk,(getrefine()*7); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5); },{},{} @@ -8943,7 +8943,7 @@ 18110,Big_CrossBow,Giant Crossbow,5,56000,,900,160,,5,2,0x00000800,63,2,34,4,110,1,11,{ bonus2 bSkillAtk,"RA_ARROWSTORM",(getrefine()*5); bonus2 bSkillUseSP,"RA_ARROWSTORM",(getrefine()*5); if(readparam(bAgi)>=120){ bonus bAspd,1; } },{},{} 18111,Creeper_Bow,Creeper Bow,5,56000,,1500,150,,5,2,0x00080800,63,2,34,3,120,1,11,{ bonus bDex,1; bonus3 bAutoSpell,"PF_SPIDERWEB",1,200; },{},{} 18112,Upg_Bow,Upg Bow,5,20,,600,60,,5,1,0x000A0848,63,2,34,3,1,0,11,{ bonus bBaseAtk,(getrefine()*7); bonus bLongAtkRate,(getrefine()*2); if(BaseJob==Job_Hunter) bonus bBaseAtk,20; if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10); },{},{} -18113,Velum_Arbalest,Vellum Arbalest,5,20,,1100,50,,5,0,0x000A0848,63,2,34,4,95,1,11,{ bonus2 bSPVanishRate,10000,4; bonus bAspd,-5; },{},{} +18113,Velum_Arbalest,Vellum Arbalest,5,20,,1100,50,,5,0,0x000A0848,63,2,34,4,95,1,11,{ bonus3 bSPVanishRaceRate,RC_Player,10000,4; bonus bAspd,-5; },{},{} 18114,Velum_CrossBow,Vellum CrossBow,5,20,,1100,110,,5,0,0x000A0848,63,2,34,4,95,1,11,{ bonus2 bAddRace,RC_Player,30+getrefine(); bonus2 bIgnoreDefRaceRate,RC_Player,30; },{},{} 18115,Orc_Archer_Bow_,Orc Archer Bow,5,20,,1600,120,,5,1,0x000A0848,63,2,34,3,65,1,11,{},{},{} 18116,Metal_Bow,Metal Bow,5,20,,0,50,,5,1,0x00080800,63,2,34,3,1,1,11,{ if(BaseJob==Job_Hunter && Upper!=2) bonus bBaseAtk,10; bonus bBaseAtk,(getrefine()*3); bonus bLongAtkRate,getrefine(); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5); },{},{} @@ -9691,7 +9691,7 @@ // More 2-Handed Swords 21000,Upg_Twohand_Sword,Upg Two-Handed Sword,5,20,,1500,100,,1,1,0x00004082,63,2,34,3,1,1,3,{ bonus bBaseAtk,(getrefine()*12); bonus bMatk,(getrefine()*5); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10); },{},{} 21001,Velum_Claymore,Vellum Claymore,5,20,,3500,260,,1,0,0x00004082,63,2,34,4,95,1,3,{ bonus2 bAddRace,RC_Player,80; bonus2 bIgnoreDefRaceRate,RC_Player,30; if(getrefine()>=6) { bonus2 bAddRace,RC_Player,40; } if(getrefine()>=9) { autobonus2 "{ bonus bShortWeaponDamageReturn,20; bonus bMagicDamageReturn,20; }",6000,2000,BF_WEAPON,"{ specialeffect2 EF_REFLECTSHIELD; }"; } },{},{} -21002,Velum_Katzbalger,Vellum Katzbalger,5,20,,2500,100,,1,0,0x00004082,63,2,34,4,95,1,3,{ bonus2 bHPVanishRate,10000,8; },{},{} +21002,Velum_Katzbalger,Vellum Katzbalger,5,20,,2500,100,,1,0,0x00004082,63,2,34,4,95,1,3,{ bonus3 bHPVanishRaceRate,RC_Player,10000,8; },{},{} 21003,Muramasa_,Muramasa,5,20,,1000,155,,1,2,0x00004082,63,2,34,4,48,1,3,{},{},{} 21004,Alca_Bringer_,Alca Bringer,5,20,,3400,280,,2,2,0x00004082,63,2,34,3,100,1,3,{},{},{} 21005,Metal_Two_Hand_Sword,Metal Two Hand Sword,5,20,,0,95,,1,1,0x00004082,63,2,34,3,1,1,3,{ bonus bBaseAtk,(getrefine()*6); bonus bMatk,(getrefine()*2); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5); },{},{} diff --git a/doc/item_bonus.txt b/doc/item_bonus.txt index de8138d842..5975401918 100644 --- a/doc/item_bonus.txt +++ b/doc/item_bonus.txt @@ -333,8 +333,11 @@ bonus2 bSPDrainRate,n,x; Adds a n/10% chance to drain x% SP when attacking bonus3 bSPDrainRate,n,x,y; Adds a n/10% chance to either gain SP equivalent to x% of damage dealt, OR drain the amount of SP from the enemy (y: 0=gain SP, 1=drain SP from target) -bonus2 bHPVanishRate,n,x; Add a n/10% chance of decreasing enemy's HP (player) amount by x% when attacking -bonus2 bSPVanishRate,n,x; Add a n/10% chance of decreasing enemy's SP (player) amount by x% when attacking +bonus2 bHPVanishRate,n,x; Add a n/100% chance of decreasing enemy's HP amount by x% when attacking +bonus2 bSPVanishRate,n,x; Add a n/100% chance of decreasing enemy's SP amount by x% when attacking + +bonus3 bHPVanishRaceRate,r,n,x; Add a n/100% chance of decreasing enemy's HP amount by x% when attacking, depends on enemy race r +bonus3 bSPVanishRaceRate,r,n,x; Add a n/100% chance of decreasing enemy's SP amount by x% when attacking, depends on enemy race r bonus2 bHPGainRaceAttack,r,n; Heals +n HP on every hit when attacking an enemy of race r bonus2 bSPGainRaceAttack,r,n; Heals +n SP on every hit when attacking an enemy of race r diff --git a/sql-files/item_db_re.sql b/sql-files/item_db_re.sql index bc0f53a519..e9084c3dc3 100644 --- a/sql-files/item_db_re.sql +++ b/sql-files/item_db_re.sql @@ -677,7 +677,7 @@ REPLACE INTO `item_db_re` VALUES (1290,'Agent_Katar','Agent Katar',5,41000,NULL, REPLACE INTO `item_db_re` VALUES (1291,'Guillotine_Katar','Guillotine Katar',5,56000,NULL,1500,'200',NULL,1,1,0x00001000,63,2,34,4,'140',1,16,'bonus bDex,2; bonus bFlee,-30; bonus2 bAddRace,RC_DemiHuman,50; bonus2 bAddRace,RC_Player,50; bonus2 bSkillAtk,"GC_CROSSIMPACT",30;',NULL,NULL); REPLACE INTO `item_db_re` VALUES (1292,'Upg_Katar','Upg Katar',5,20,NULL,1000,'80',NULL,1,1,0x00001000,63,2,34,3,'1',1,16,'bonus bBaseAtk,(getrefine()*10); bonus bCritAtkRate,(getrefine()*2); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10);',NULL,NULL); REPLACE INTO `item_db_re` VALUES (1293,'Velum_Jamadhar','Vellum Jamadhar',5,20,NULL,1200,'170',NULL,1,0,0x00001000,63,2,34,4,'95',1,16,'bonus4 bSetDefRace,RC_Player,10000,5000,1; bonus4 bSetMDefRace,RC_Player,10000,5000,1; bonus bAspdRate,getrefine();',NULL,NULL); -REPLACE INTO `item_db_re` VALUES (1294,'Velum_Scare','Vellum Scale',5,20,NULL,1200,'50',NULL,1,0,0x00001000,63,2,34,4,'95',1,16,'bonus2 bSPVanishRate,10000,10;',NULL,NULL); +REPLACE INTO `item_db_re` VALUES (1294,'Velum_Scare','Vellum Scale',5,20,NULL,1200,'50',NULL,1,0,0x00001000,63,2,34,4,'95',1,16,'bonus3 bSPVanishRaceRate,RC_Player,10000,10;',NULL,NULL); REPLACE INTO `item_db_re` VALUES (1295,'Blood_Tears_','Blood Tears',5,20,NULL,1700,'120',NULL,1,1,0x00001000,18,2,34,4,'55',1,16,NULL,NULL,NULL); REPLACE INTO `item_db_re` VALUES (1296,'Metal_Katar','Metal Katar',5,20,NULL,0,'75',NULL,1,1,0x00001000,63,2,34,3,'1',1,16,'bonus bBaseAtk,(getrefine()*5); bonus bCritAtkRate,getrefine(); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5);',NULL,NULL); # @@ -747,7 +747,7 @@ REPLACE INTO `item_db_re` VALUES (1391,'P_Two_Handed_Axe1','Eden Two-Handed Axe REPLACE INTO `item_db_re` VALUES (1392,'Ygnus_Stale','Ignus Steel',5,56000,NULL,1900,'250',NULL,1,1,0x000444A2,63,2,34,4,'95',1,7,'bonus bAtkEle,Ele_Fire; bonus bUnbreakableWeapon,0;',NULL,NULL); REPLACE INTO `item_db_re` VALUES (1393,'End_Sektura','End Sectora',5,56000,NULL,1900,'250',NULL,1,1,0x000444A2,63,2,34,4,'95',1,7,'bonus bAtkEle,Ele_Water; bonus bUnbreakableWeapon,0;',NULL,NULL); REPLACE INTO `item_db_re` VALUES (1394,'Upg_Two_Handed_Axe','Upg Two Handed Axe',5,20,NULL,2000,'110',NULL,1,1,0x000444A2,63,2,34,3,'1',1,7,'bonus bBaseAtk,(getrefine()*14); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10);',NULL,NULL); -REPLACE INTO `item_db_re` VALUES (1395,'Velum_Buster','Vellum Buster',5,20,NULL,2500,'50',NULL,1,0,0x000444A2,63,2,34,4,'95',1,7,'bonus bUnbreakableWeapon,0; bonus2 bSPVanishRate,10000,10;',NULL,NULL); +REPLACE INTO `item_db_re` VALUES (1395,'Velum_Buster','Vellum Buster',5,20,NULL,2500,'50',NULL,1,0,0x000444A2,63,2,34,4,'95',1,7,'bonus bUnbreakableWeapon,0; bonus3 bSPVanishRaceRate,RC_Player,10000,10;',NULL,NULL); REPLACE INTO `item_db_re` VALUES (1396,'Velum_Guillotine','Vellum Guillotine',5,20,NULL,5500,'300',NULL,1,0,0x000444A2,63,2,34,4,'95',1,7,'bonus bUnbreakableWeapon,0; bonus2 bAddRace,RC_Player,40; bonus2 bIgnoreDefRaceRate,RC_Player,30; if(getrefine()>=6) { bonus2 bSkillAtk,"NC_AXEBOOMERANG",80; bonus2 bSkillAtk,"NC_POWERSWING",80; } if(getrefine()>=9) { bonus2 bAddRace,RC_Player,60; }',NULL,NULL); REPLACE INTO `item_db_re` VALUES (1397,'Bradium_Stonehammer_','Bradium Stonehammer',5,20,NULL,2700,'210',NULL,1,2,0x000444A2,63,2,34,4,'75',1,7,'bonus bUnbreakableWeapon,0;',NULL,NULL); REPLACE INTO `item_db_re` VALUES (1398,'Metal_Two_Handed_Axe','Metal Two Handed Axe',5,20,NULL,0,'105',NULL,1,1,0x000444A2,63,2,34,3,'1',1,7,'bonus bUnbreakableWeapon,0; bonus bBaseAtk,(getrefine()*7); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5);',NULL,NULL); @@ -8974,7 +8974,7 @@ REPLACE INTO `item_db_re` VALUES (18109,'Catapult','Thief Crossbow',5,56000,NULL REPLACE INTO `item_db_re` VALUES (18110,'Big_CrossBow','Giant Crossbow',5,56000,NULL,900,'160',NULL,5,2,0x00000800,63,2,34,4,'110',1,11,'bonus2 bSkillAtk,"RA_ARROWSTORM",(getrefine()*5); bonus2 bSkillUseSP,"RA_ARROWSTORM",(getrefine()*5); if(readparam(bAgi)>=120){ bonus bAspd,1; }',NULL,NULL); REPLACE INTO `item_db_re` VALUES (18111,'Creeper_Bow','Creeper Bow',5,56000,NULL,1500,'150',NULL,5,2,0x00080800,63,2,34,3,'120',1,11,'bonus bDex,1; bonus3 bAutoSpell,"PF_SPIDERWEB",1,200;',NULL,NULL); REPLACE INTO `item_db_re` VALUES (18112,'Upg_Bow','Upg Bow',5,20,NULL,600,'60',NULL,5,1,0x000A0848,63,2,34,3,'1',0,11,'bonus bBaseAtk,(getrefine()*7); bonus bLongAtkRate,(getrefine()*2); if(BaseJob==Job_Hunter) bonus bBaseAtk,20; if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10);',NULL,NULL); -REPLACE INTO `item_db_re` VALUES (18113,'Velum_Arbalest','Vellum Arbalest',5,20,NULL,1100,'50',NULL,5,0,0x000A0848,63,2,34,4,'95',1,11,'bonus2 bSPVanishRate,10000,4; bonus bAspd,-5;',NULL,NULL); +REPLACE INTO `item_db_re` VALUES (18113,'Velum_Arbalest','Vellum Arbalest',5,20,NULL,1100,'50',NULL,5,0,0x000A0848,63,2,34,4,'95',1,11,'bonus3 bSPVanishRaceRate,RC_Player,10000,4; bonus bAspd,-5;',NULL,NULL); REPLACE INTO `item_db_re` VALUES (18114,'Velum_CrossBow','Vellum CrossBow',5,20,NULL,1100,'110',NULL,5,0,0x000A0848,63,2,34,4,'95',1,11,'bonus2 bAddRace,RC_Player,30+getrefine(); bonus2 bIgnoreDefRaceRate,RC_Player,30;',NULL,NULL); REPLACE INTO `item_db_re` VALUES (18115,'Orc_Archer_Bow_','Orc Archer Bow',5,20,NULL,1600,'120',NULL,5,1,0x000A0848,63,2,34,3,'65',1,11,NULL,NULL,NULL); REPLACE INTO `item_db_re` VALUES (18116,'Metal_Bow','Metal Bow',5,20,NULL,0,'50',NULL,5,1,0x00080800,63,2,34,3,'1',1,11,'if(BaseJob==Job_Hunter && Upper!=2) bonus bBaseAtk,10; bonus bBaseAtk,(getrefine()*3); bonus bLongAtkRate,getrefine(); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5);',NULL,NULL); @@ -9722,7 +9722,7 @@ REPLACE INTO `item_db_re` VALUES (20761,'C_Happiness_Wings','Costume Happiness W # More 2-Handed Swords REPLACE INTO `item_db_re` VALUES (21000,'Upg_Twohand_Sword','Upg Two-Handed Sword',5,20,NULL,1500,'100',NULL,1,1,0x00004082,63,2,34,3,'1',1,3,'bonus bBaseAtk,(getrefine()*12); bonus bMatk,(getrefine()*5); if(BaseLevel>70) bonus bBaseAtk,(((BaseLevel-70)/10)*10);',NULL,NULL); REPLACE INTO `item_db_re` VALUES (21001,'Velum_Claymore','Vellum Claymore',5,20,NULL,3500,'260',NULL,1,0,0x00004082,63,2,34,4,'95',1,3,'bonus2 bAddRace,RC_Player,80; bonus2 bIgnoreDefRaceRate,RC_Player,30; if(getrefine()>=6) { bonus2 bAddRace,RC_Player,40; } if(getrefine()>=9) { autobonus2 "{ bonus bShortWeaponDamageReturn,20; bonus bMagicDamageReturn,20; }",6000,2000,BF_WEAPON,"{ specialeffect2 EF_REFLECTSHIELD; }"; }',NULL,NULL); -REPLACE INTO `item_db_re` VALUES (21002,'Velum_Katzbalger','Vellum Katzbalger',5,20,NULL,2500,'100',NULL,1,0,0x00004082,63,2,34,4,'95',1,3,'bonus2 bHPVanishRate,10000,8;',NULL,NULL); +REPLACE INTO `item_db_re` VALUES (21002,'Velum_Katzbalger','Vellum Katzbalger',5,20,NULL,2500,'100',NULL,1,0,0x00004082,63,2,34,4,'95',1,3,'bonus3 bHPVanishRaceRate,RC_Player,10000,8;',NULL,NULL); REPLACE INTO `item_db_re` VALUES (21003,'Muramasa_','Muramasa',5,20,NULL,1000,'155',NULL,1,2,0x00004082,63,2,34,4,'48',1,3,NULL,NULL,NULL); REPLACE INTO `item_db_re` VALUES (21004,'Alca_Bringer_','Alca Bringer',5,20,NULL,3400,'280',NULL,2,2,0x00004082,63,2,34,3,'100',1,3,NULL,NULL,NULL); REPLACE INTO `item_db_re` VALUES (21005,'Metal_Two_Hand_Sword','Metal Two Hand Sword',5,20,NULL,0,'95',NULL,1,1,0x00004082,63,2,34,3,'1',1,3,'bonus bBaseAtk,(getrefine()*6); bonus bMatk,(getrefine()*2); set .@i,((BaseLevel/10)>12)?12:(BaseLevel/10); if(.@i>2) bonus bBaseAtk,((.@i-2)*5);',NULL,NULL); diff --git a/src/common/utils.h b/src/common/utils.h index 2fd3e9e2e8..b8eb40fc2d 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -16,13 +16,13 @@ void findfile(const char *p, const char *pat, void (func)(const char*)); bool exists(const char* filename); /// Caps values to min/max -#define cap_value(a, min, max) ((a >= max) ? max : (a <= min) ? min : a) +#define cap_value(a, min, max) (((a) >= (max)) ? (max) : ((a) <= (min)) ? (min) : (a)) /// Apply rate for val, divided by 100) -#define apply_rate(val, rate) (((rate) == 100) ? (val) : ((val) > 100000) ? (val) / 100 * (rate) : (val) * (rate) / 100) +#define apply_rate(val, rate) (((rate) == 100) ? (val) : ((val) > 100000) ? ((val) / 100 * (rate)) : ((val) * (rate) / 100)) /// Apply rate for val, divided by per -#define apply_rate2(val, rate, per) (((rate) == (per)) ? (val) : ((val) > 100000) ? (val) / (per) * (rate) : (val) * (rate) / (per)) +#define apply_rate2(val, rate, per) (((rate) == (per)) ? (val) : ((val) > 100000) ? ((val) / (per) * (rate)) : ((val) * (rate) / (per))) /// calculates the value of A / B, in percent (rounded down) unsigned int get_percentage(const unsigned int A, const unsigned int B); diff --git a/src/map/battle.c b/src/map/battle.c index 084d9608ef..1c5ed2ca16 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -6517,10 +6517,28 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama { struct weapon_data *wd; int64 *damage; - int thp = 0, tsp = 0, rhp = 0, rsp = 0, hp=0, sp=0, i; + int thp = 0, tsp = 0, rhp = 0, rsp = 0, hp = 0, sp = 0; + uint8 i = 0; + short vrate_hp = 0, vrate_sp = 0, v_hp = 0, v_sp = 0; + if (!CHK_RACE(race) && !CHK_CLASS(class_)) return; + // Check for vanish HP/SP. !CHECKME: Which first, drain or vanish? + vrate_hp = cap_value(sd->bonus.hp_vanish_rate + sd->vanish_race[race].hp_rate + sd->vanish_race[RC_ALL].hp_rate, SHRT_MIN, SHRT_MAX); + v_hp = cap_value(sd->bonus.hp_vanish_per + sd->vanish_race[race].hp_per + sd->vanish_race[RC_ALL].hp_per, INT8_MIN, INT8_MAX); + + vrate_sp = cap_value(sd->bonus.sp_vanish_rate + sd->vanish_race[race].sp_rate + sd->vanish_race[RC_ALL].sp_rate, SHRT_MIN, SHRT_MAX); + v_sp = cap_value(sd->bonus.sp_vanish_per + sd->vanish_race[race].sp_per + sd->vanish_race[RC_ALL].sp_per, INT8_MIN, INT8_MAX); + + if (v_hp > 0 && vrate_hp > 0 && (vrate_hp >= 10000 || rnd()%10000 < vrate_hp)) + i |= 1; + if (v_sp > 0 && vrate_sp > 0 && (vrate_sp >= 10000 || rnd()%10000 < vrate_sp)) + i |= 2; + if (i) + status_percent_damage(&sd->bl, tbl, (i&1 ? (int8)v_hp: 0), (i&2 ? (int8)v_sp : 0), false); + + i = 0; for (i = 0; i < 4; i++) { //First two iterations: Right hand if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; } @@ -6585,13 +6603,6 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama } } - if (sd->bonus.sp_vanish_rate && rnd()%1000 < sd->bonus.sp_vanish_rate) - status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->bonus.sp_vanish_per, false); - - if (sd->bonus.hp_vanish_rate && rnd()%1000 < sd->bonus.hp_vanish_rate - && tbl->type == BL_PC && (map[sd->bl.m].flag.pvp || map[sd->bl.m].flag.gvg)) - status_percent_damage(&sd->bl, tbl, (unsigned char)sd->bonus.hp_vanish_per, 0, false); - if( sd->sp_gain_race_attack[race] ) tsp += sd->sp_gain_race_attack[race]; if( sd->sp_gain_race_attack[RC_ALL] ) @@ -6601,7 +6612,8 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama if( sd->hp_gain_race_attack[RC_ALL] ) thp += sd->hp_gain_race_attack[RC_ALL]; - if (!thp && !tsp) return; + if (!thp && !tsp) + return; status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1); diff --git a/src/map/map.h b/src/map/map.h index 5981f9abf1..211d697dba 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -498,7 +498,8 @@ enum _sp { SP_IGNORE_DEF_CLASS, SP_DEF_RATIO_ATK_CLASS, SP_ADDCLASS, SP_SUBCLASS, SP_MAGIC_ADDCLASS, //2062-2066 SP_WEAPON_COMA_CLASS, SP_IGNORE_MDEF_CLASS_RATE, SP_EXP_ADDCLASS, SP_ADD_CLASS_DROP_ITEM, //2067-2070 - SP_ADD_CLASS_DROP_ITEMGROUP, SP_ADDMAXWEIGHT, SP_ADD_ITEMGROUP_HEAL_RATE // 2071-2073 + SP_ADD_CLASS_DROP_ITEMGROUP, SP_ADDMAXWEIGHT, SP_ADD_ITEMGROUP_HEAL_RATE, // 2071-2073 + SP_HP_VANISH_RACE_RATE, SP_SP_VANISH_RACE_RATE, // 2074-2075 }; enum _look { diff --git a/src/map/pc.c b/src/map/pc.c index 923f138655..8ac1cd44f9 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1903,15 +1903,15 @@ int pc_disguise(struct map_session_data *sd, int class_) /// Show error message #define PC_BONUS_SHOW_ERROR(type,type2,val) { ShowError("%s: %s: Invalid %s %d.\n",__FUNCTION__,#type,#type2,(val)); break; } /// Check for valid Element, break & show error message if invalid Element -#define PC_BONUS_CHK_ELEMENT(ele,bonus) { if (!CHK_ELEMENT(ele)) { PC_BONUS_SHOW_ERROR(bonus,Element,(ele)); }} +#define PC_BONUS_CHK_ELEMENT(ele,bonus) { if (!CHK_ELEMENT((ele))) { PC_BONUS_SHOW_ERROR((bonus),Element,(ele)); }} /// Check for valid Race, break & show error message if invalid Race -#define PC_BONUS_CHK_RACE(rc,bonus) { if (!CHK_RACE(rc)) { PC_BONUS_SHOW_ERROR(bonus,Race,(rc)); }} +#define PC_BONUS_CHK_RACE(rc,bonus) { if (!CHK_RACE((rc))) { PC_BONUS_SHOW_ERROR((bonus),Race,(rc)); }} /// Check for valid Race2, break & show error message if invalid Race2 -#define PC_BONUS_CHK_RACE2(rc2,bonus) { if (!CHK_RACE2(rc2)) { PC_BONUS_SHOW_ERROR(bonus,Race2,(rc2)); }} +#define PC_BONUS_CHK_RACE2(rc2,bonus) { if (!CHK_RACE2((rc2))) { PC_BONUS_SHOW_ERROR((bonus),Race2,(rc2)); }} /// Check for valid Class, break & show error message if invalid Class -#define PC_BONUS_CHK_CLASS(cl,bonus) { if (!CHK_CLASS(cl)) { PC_BONUS_SHOW_ERROR(bonus,Class,(cl)); }} +#define PC_BONUS_CHK_CLASS(cl,bonus) { if (!CHK_CLASS((cl))) { PC_BONUS_SHOW_ERROR((bonus),Class,(cl)); }} /// Check for valid Size, break & show error message if invalid Size -#define PC_BONUS_CHK_SIZE(sz,bonus) { if (!CHK_MOBSIZE(sz)) { PC_BONUS_SHOW_ERROR(bonus,Size,(sz)); }} +#define PC_BONUS_CHK_SIZE(sz,bonus) { if (!CHK_MOBSIZE((sz))) { PC_BONUS_SHOW_ERROR((bonus),Size,(sz)); }} static void pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, short rate, short flag, unsigned short card_id) { @@ -3702,6 +3702,22 @@ void pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) if (sd->state.lr_flag != 2) pc_bonus_subele(sd, (unsigned char)type2, type3, val); break; + + case SP_SP_VANISH_RACE_RATE: // bonus3 bSPVanishRaceRate,r,n,x; + PC_BONUS_CHK_RACE(type2,SP_SP_VANISH_RACE_RATE); + if(sd->state.lr_flag != 2) { + sd->vanish_race[type2].sp_rate += type3; + sd->vanish_race[type2].sp_per += val; + } + break; + + case SP_HP_VANISH_RACE_RATE: // bonus3 bHPVanishRaceRate,r,n,x; + PC_BONUS_CHK_RACE(type2,SP_HP_VANISH_RACE_RATE); + if(sd->state.lr_flag != 2) { + sd->vanish_race[type2].hp_rate += type3; + sd->vanish_race[type2].hp_per += val; + } + break; default: ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val); diff --git a/src/map/pc.h b/src/map/pc.h index acc7e4066f..f1a0150853 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -379,6 +379,12 @@ struct map_session_data { short value; int rate, tick; } def_set_race[RC_MAX], mdef_set_race[RC_MAX]; + struct s_bonus_vanish_race { + short hp_rate, ///< Rate 0 - 10000 (100%) + hp_per, ///< % HP vanished + sp_rate, ///< Rate 0 - 10000 (100%) + sp_per; ///< % SP vanished + } vanish_race[RC_MAX]; // zeroed structures end here // manually zeroed structures start here. diff --git a/src/map/status.c b/src/map/status.c index d9cbb993b8..5c7fc5c2a9 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1628,21 +1628,22 @@ int status_heal(struct block_list *bl,int64 hhp,int64 hsp, int flag) } /** - * Applies percentage based damage to a unit - * If a mob is killed this way and there is no src, no EXP/Drops will be awarded + * Applies percentage based damage to a unit. + * If a mob is killed this way and there is no src, no EXP/Drops will be awarded. * @param src: Object initiating HP/SP modification [PC|MOB|PET|HOM|MER|ELEM] * @param target: Object to modify HP/SP * @param hp_rate: Percentage of HP to modify * @param sp_rate: Percentage of SP to modify * @param flag: \n * 0: Heal target \n - * 2: Target must not die from subtraction + * 1: Use status_damage \n + * 2: Use status_damage and make sure target must not die from subtraction * @return hp+sp through status_heal() */ -int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag) +int status_percent_change(struct block_list *src, struct block_list *target, int8 hp_rate, int8 sp_rate, uint8 flag) { struct status_data *status; - unsigned int hp =0, sp = 0; + unsigned int hp = 0, sp = 0; status = status_get_status_data(target); @@ -1651,15 +1652,11 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe if (hp_rate > 99) hp = status->hp; else if (hp_rate > 0) - hp = status->hp>10000? - hp_rate*(status->hp/100): - ((int64)hp_rate*status->hp)/100; + hp = apply_rate(status->hp, hp_rate); else if (hp_rate < -99) hp = status->max_hp; else if (hp_rate < 0) - hp = status->max_hp>10000? - (-hp_rate)*(status->max_hp/100): - ((int64)-hp_rate*status->max_hp)/100; + hp = (apply_rate(status->hp, -hp_rate)); if (hp_rate && !hp) hp = 1; @@ -1669,29 +1666,29 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe if (sp_rate > 99) sp = status->sp; else if (sp_rate > 0) - sp = ((int64)sp_rate*status->sp)/100; + sp = apply_rate(status->sp, sp_rate); else if (sp_rate < -99) sp = status->max_sp; else if (sp_rate < 0) - sp = ((int64)-sp_rate)*status->max_sp/100; + sp = (apply_rate(status->sp, -sp_rate)); if (sp_rate && !sp) sp = 1; // Ugly check in case damage dealt is too much for the received args of // status_heal / status_damage. [Skotlex] if (hp > INT_MAX) { - hp -= INT_MAX; + hp -= INT_MAX; if (flag) status_damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1)); else - status_heal(target, INT_MAX, 0, 0); + status_heal(target, INT_MAX, 0, 0); } - if (sp > INT_MAX) { + if (sp > INT_MAX) { sp -= INT_MAX; if (flag) status_damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1)); else - status_heal(target, 0, INT_MAX, 0); + status_heal(target, 0, INT_MAX, 0); } if (flag) return status_damage(src, target, hp, sp, 0, (!src||src==target?5:1)); @@ -2962,6 +2959,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) + sizeof(sd->subele2) + sizeof(sd->def_set_race) + sizeof(sd->mdef_set_race) + + sizeof(sd->vanish_race) ); memset (&sd->bonus, 0, sizeof(sd->bonus)); diff --git a/src/map/status.h b/src/map/status.h index 8f6959260d..cbfde738ab 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1936,7 +1936,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp,int #define status_zap(bl, hp, sp) status_damage(NULL, bl, hp, sp, 0, 1) //Define for standard HP/SP skill-related cost triggers (mobs require no HP/SP to use skills) int64 status_charge(struct block_list* bl, int64 hp, int64 sp); -int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag); +int status_percent_change(struct block_list *src, struct block_list *target, int8 hp_rate, int8 sp_rate, uint8 flag); //Easier handling of status_percent_change #define status_percent_heal(bl, hp_rate, sp_rate) status_percent_change(NULL, bl, -(hp_rate), -(sp_rate), 0) #define status_percent_damage(src, target, hp_rate, sp_rate, kill) status_percent_change(src, target, hp_rate, sp_rate, (kill)?1:2)