diff --git a/db/import-tmpl/job_exp.txt b/db/import-tmpl/job_exp.txt index 4420fc8b9f..eb50ece572 100644 --- a/db/import-tmpl/job_exp.txt +++ b/db/import-tmpl/job_exp.txt @@ -20,3 +20,57 @@ //Job - Renewal 255 Levels //60,x,1,112000,355000,615000,917000,1253000,1595000,2007000,2430000,2868000,3420000,3863000,4504000,4998000,5769000,6321000,7254000,7870000,9015000,9530000,11072000,11848000,13467000,14337000,16243000,17216000,19446000,20781000,23070000,24453000,27568000,29118000,31820000,34125000,37048000,40204000,42972000,45937000,49110000,52696000,57158000,61305000,67167000,72285000,77647000,83624000,91113000,98548000,107630000,119077000,131668000,145518000,160753000,177511000,195944000,216220000,238523000,263056000,290042000,319726000,324726000,329726000,334726000,339726000,344726000,349726000,354726000,359726000,364726000,369726000,374726000,379726000,384726000,389726000,394726000,399726000,404726000,409726000,414726000,419726000,424726000,429726000,434726000,439726000,444726000,449726000,454726000,459726000,464726000,469726000,474726000,479726000,484726000,489726000,494726000,499726000,504726000,509726000,514726000,519726000,524726000,529726000,534726000,539726000,544726000,549726000,554726000,559726000,564726000,569726000,574726000,579726000,584726000,589726000,594726000,599726000,604726000,609726000,614726000,619726000,624726000,629726000,634726000,639726000,644726000,649726000,654726000,659726000,664726000,669726000,674726000,679726000,684726000,689726000,694726000,699726000,704726000,709726000,714726000,719726000,724726000,729726000,734726000,739726000,744726000,749726000,754726000,759726000,764726000,769726000,774726000,779726000,784726000,789726000,794726000,799726000,804726000,809726000,814726000,819726000,824726000,829726000,834726000,839726000,844726000,849726000,854726000,859726000,864726000,869726000,874726000,879726000,884726000,889726000,894726000,899726000,904726000,909726000,914726000,919726000,924726000,929726000,934726000,939726000,944726000,949726000,954726000,959726000,964726000,969726000,974726000,979726000,984726000,989726000,994726000,999726000,1004726000,1009726000,1014726000,1019726000,1024726000,1029726000,1034726000,1039726000,1044726000,1049726000,1054726000,1059726000,1064726000,1069726000,1074726000,1079726000,1084726000,1089726000,1094726000,1099726000,1104726000,1109726000,1114726000,1119726000,1124726000,1129726000,1134726000,1139726000,1144726000,1149726000,1154726000,1159726000,1164726000,1169726000,1174726000,1179726000,1184726000,1189726000,1194726000,1199726000,1204726000,1209726000,1214726000,1219726000,1224726000,1229726000,1234726000,1239726000,1244726000,1249726000,1254726000,1259726000,1264726000,1269726000,1274726000,1279726000,1284726000,1289726000,1294726000,1299726000 + + +// RENEWAL 175/60 (before kRO Updates to 185/65) +// ============================================= +////Base - Normal and Baby Jobs +//99,0:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:23:24:25:4023:4024:4025:4026:4027:4028:4029:4030:4031:4032:4033:4034:4035:4036:4037:4038:4039:4040:4041:4042:4043:4044:4045:4046:4047:4048:4049:4050:4051:4052:4222:4225:4226:4227:4228:4238,0,550,900,1500,2200,3200,3800,4200,4550,5000,5500,6000,6100,6350,6700,7350,8000,8400,8800,9200,9700,10300,11000,11800,13000,14000,15000,16000,17000,18000,19000,20000,21000,22000,23200,24000,26000,27500,29000,30000,31500,33000,34000,36000,37500,38000,40000,42000,44500,47000,49000,51000,53000,55000,57000,59000,61500,63000,65000,67000,69000,70000,73000,77000,80000,84000,88000,91000,95000,110000,128000,140000,155000,163000,170000,180000,188000,195000,200000,230000,260000,300000,350000,400000,480000,550000,600000,680000,750000,900000,1000000,1200000,1500000,1800000,2100000,2400000,2800000,3300000,4000000,99999999 +// +////Base - Adv Jobs +//99,4001:4002:4003:4004:4005:4006:4007:4008:4009:4010:4011:4012:4013:4014:4015:4016:4017:4018:4019:4020:4021:4022,0,660,1080,1800,2640,3840,4560,5040,5460,6000,6600,7200,7320,7620,8040,8820,9600,10080,10560,11040,12610,13390,14300,15340,16900,18460,19500,20800,22100,23400,24700,26000,27300,28600,30160,31200,33800,35750,37700,39000,44100,46200,47600,50400,52500,53200,56000,58800,62300,65800,68600,71400,74200,77000,79800,82600,86100,88200,91000,93800,103500,105000,109500,115500,120000,126000,132000,136500,142500,165000,192000,210000,232500,244500,255000,270000,282000,292500,300000,345000,416000,480000,560000,640000,768000,880000,960000,1088000,1200000,1440000,1700000,2040000,2550000,3060000,3570000,4080000,4760000,5610000,6800000,99999999 +// +////Base - 3rd Jobs, Baby 3rds, Oboro/Kagerou, Rebellion, Summoner, Star Emperor, Soul Reaper +////Note: (First 98 values [Level 1 - 98] are only used by Summoner Class, because 3rd classes start at level 99.) +//175,4054:4055:4056:4057:4058:4059:4060:4061:4062:4063:4064:4065:4066:4067:4068:4069:4070:4071:4072:4073:4074:4075:4076:4077:4078:4079:4080:4081:4082:4083:4084:4085:4086:4087:4096:4097:4098:4099:4100:4101:4102:4103:4104:4105:4106:4107:4108:4109:4110:4111:4112:4211:4212:4215:4218:4220:4223:4224:4229:4239:4240:4241:4242:4243:4244,0,55,90,150,220,320,380,420,455,500,600,700,800,900,1000,1100,1200,1300,1400,1500,1800,2100,2400,2700,3000,3300,3600,3900,4200,4500,5400,6300,7200,8100,9000,9900,10800,11700,12600,13500,16200,18900,21600,24300,27000,29700,32400,35100,37800,40500,43200,45900,48600,51300,54000,56700,59400,62100,64800,67500,75600,83700,91800,99900,108000,116100,124200,132300,140400,165000,192000,210000,232500,244500,255000,270000,282000,292500,300000,345000,416000,480000,560000,640000,768000,880000,960000,1088000,1200000,1440000,1700000,2040000,2550000,3060000,3570000,4080000,4760000,5610000,6800000,7070000,7400000,7770000,8150000,8550000,9100000,9610000,10150000,10570000,11180000,12000000,12200000,12930000,13150000,14030000,14420000,15420000,15670000,16870000,17140000,18720000,19020000,20590000,20930000,22690000,23310000,25290000,26020000,27860000,28535000,30990000,31680000,33560000,34942000,36372000,38350000,39890000,41545000,43330000,45400000,48100000,50410000,53370000,56250000,59230000,62590000,66120000,70200000,75330000,81100000,95000000,98000000,103000000,107000000,112000000,116000000,121000000,125000000,130000000,134000000,139000000,145000000,152200000,160840000,171200000,191930000,202290000,214720000,229640000,247550000,283370000,301280000,322770000,348560000,379500000,441390000,99999999 +// +////Base - Expanded Super Novice & Expanded Super Baby +//160,4190:4191,0,660,1080,1800,2640,3840,4560,5040,5460,6000,6600,7200,7320,7620,8040,8820,9600,10080,10560,11040,12610,13390,14300,15340,16900,18460,19500,20800,22100,23400,24700,26000,27300,28600,30160,31200,33800,35750,37700,39000,44100,46200,47600,50400,52500,53200,56000,58800,62300,65800,68600,71400,74200,77000,79800,82600,86100,88200,91000,93800,103500,105000,109500,115500,120000,126000,132000,136500,142500,165000,192000,210000,232500,244500,255000,270000,282000,292500,300000,345000,416000,480000,560000,640000,768000,880000,960000,1088000,1200000,1440000,1700000,2040000,2550000,3060000,3570000,4080000,4760000,5610000,6800000,7070000,7400000,7770000,8150000,8550000,9100000,9610000,10150000,10570000,11180000,12000000,12200000,12930000,13150000,14030000,14420000,15420000,15670000,16870000,17140000,18720000,19020000,20590000,20930000,22690000,23310000,25290000,26020000,27860000,28535000,30990000,31680000,33560000,34942000,36372000,38350000,39890000,41545000,43330000,45400000,48100000,50410000,53370000,56250000,59230000,62590000,66120000,70200000,75330000,81100000,95000000,98000000,103000000,107000000,112000000,116000000,121000000,125000000,130000000,134000000,139000000,145000000,152200000,160840000,171200000,191930000,202290000,214720000,229640000,247550000,283370000,301280000,322770000,348560000,379500000,441390000,99999999 +// +////Job - Novice & Baby Novice +//10,0:4023,1,10,18,28,40,91,151,205,268,340,999999999 +// +////Job - 1st Classes & Baby 1st Classes, Taekwon +//50,1:2:3:4:5:6:4024:4025:4026:4027:4028:4029:4046:4050:4225,1,60,130,260,460,780,1060,1300,1560,1910,2290,2680,2990,3340,3740,4360,4970,5530,6120,6700,8090,8920,9970,11080,12690,14440,15850,17400,19220,21060,22870,24910,26840,29080,31320,33300,37110,40500,43570,46180,53510,57200,60310,65690,70090,72130,77540,83320,90120,97180,999999999 +// +////Job - 2nd Classes & Baby 2nd Classes, Soul Linker +//50,7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:4030:4031:4032:4033:4034:4035:4036:4037:4038:4039:4040:4041:4042:4043:4044:4049:4051:4052:4227,1,2500,4200,7000,10300,15900,18900,20900,22600,24900,28800,31500,32000,33300,35100,40500,44100,46300,48500,50700,56000,59400,63500,68100,75000,85700,90500,96600,102600,108600,119700,126000,132300,138600,146100,157500,170600,180400,190300,196800,214900,225200,232000,245700,255900,279300,294000,308700,327000,345400,999999999 +// +////Job - Novice High +//10,4001,1,11,20,31,44,100,166,226,295,374,999999999 +// +////Job - Adv First Classes +//50,4002:4003:4004:4005:4006:4007,1,100,200,350,550,800,1100,1450,1850,2300,2800,3350,3950,4600,5300,6050,6850,7700,8600,9550,10550,11600,12700,13850,15050,16300,17600,18950,20350,21800,23300,24850,26450,28100,29800,31550,33350,35200,37100,39050,41050,43100,45200,47350,49550,51800,54100,56450,58850,61300,999999999 +// +////Job - Adv Second Classes +//70,4008:4009:4010:4011:4012:4013:4014:4015:4016:4017:4018:4019:4020:4021:4022,1,3800,6200,10400,15200,22900,27100,30000,32500,35700,41300,45000,45800,47600,50300,58700,63900,67100,70300,73500,90600,96200,102700,110200,121400,144700,152900,163100,173300,183500,213500,224700,236000,247200,260700,299800,324800,343600,362300,374800,474400,497000,512100,542200,564800,644300,678200,712100,754500,796900,873100,911900,950600,989400,1028100,1143300,1199900,1233800,1279100,1324300,1486900,1515900,1603000,1719200,1806300,2040300,2244300,2415900,2746000,3326000,999999999 +// +////Job - 3rd Jobs & Baby 3rds, Oboro/Kagerou, Rebellion, Star Emperor, Soul Reaper +//60,4054:4055:4056:4057:4058:4059:4060:4061:4062:4063:4064:4065:4066:4067:4068:4069:4070:4071:4072:4073:4074:4075:4076:4077:4078:4079:4080:4081:4082:4083:4084:4085:4086:4087:4096:4097:4098:4099:4100:4101:4102:4103:4104:4105:4106:4107:4108:4109:4110:4111:4112:4211:4212:4215:4223:4224:4229:4239:4240:4241:4242:4243:4244,1,112000,355000,615000,917000,1253000,1595000,2007000,2430000,2868000,3420000,3863000,4504000,4998000,5769000,6321000,7254000,7870000,9015000,9530000,11072000,11848000,13467000,14337000,16243000,17216000,19446000,20781000,23070000,24453000,27568000,29118000,31820000,34125000,37048000,40204000,42972000,45937000,49110000,52696000,57158000,61305000,67167000,72285000,77647000,83624000,91113000,98548000,107630000,119077000,131668000,145518000,160753000,177511000,195944000,216220000,238523000,263056000,290042000,319726000,999999999 +// +////Job - Expanded Super Novice & Expanded Super Baby +//50,4190:4191,1,112000,355000,615000,917000,1253000,1595000,2007000,2430000,2868000,3420000,3863000,4504000,4998000,5769000,6321000,7254000,7870000,9015000,9530000,11072000,11848000,13467000,14337000,16243000,17216000,19446000,20781000,23070000,24453000,27568000,29118000,31820000,34125000,37048000,40204000,42972000,45937000,49110000,52696000,57158000,61305000,67167000,72285000,77647000,83624000,91113000,98548000,107630000,119077000,999999999 +// +////Job - Ninja/Gunslinger +//70,24:25:4222:4228,1,200,300,400,600,700,1000,1200,1400,1700,1900,2400,2700,3200,3600,4200,4900,5500,6100,6900,7700,8400,9300,10100,11100,12100,13000,14600,16100,17500,18600,21500,23300,24700,27000,29000,30000,32400,35000,38100,41100,44000,46700,49600,52500,55600,58900,62700,65500,69200,72300,81200,84100,89300,95500,100900,107800,114900,120700,128600,150500,176900,196100,219600,234200,247900,266400,281300,296600,308000,999999999 +// +////Job - Star Gladiator +//50,4047:4048:4226:4238,1,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,101400,112000,118800,127000,136200,150000,171400,181000,193200,205200,217200,239400,252000,264600,277200,292200,315000,341200,360800,380600,393600,429800,450400,464000,491400,511800,558600,588000,617400,654000,690800,999999999 +// +////Job - Super Novice & Baby Super Novice +//99,23:4045,1,60,130,260,460,780,1060,1300,1560,1910,2290,2680,2990,3340,3740,4360,4970,5530,6120,6700,8090,8920,9970,11080,12690,14440,15850,17400,19220,21060,22870,24910,26840,29080,31320,33300,37110,40500,43570,46180,53510,57200,60310,65690,70090,72130,77540,83320,90120,97180,590120,600120,610120,620120,630120,640120,650120,660120,670120,680120,690120,700120,710120,720120,730120,740120,750120,760120,770120,780120,790120,800120,810120,820120,830120,840120,850120,860120,870120,880120,890120,900120,910120,920120,930120,940120,950120,960120,970120,980120,990120,1000120,1010120,1020120,1030120,1040120,1050120,1060120,1070120,999999999 +// +////Job - Summoner +//50,4218:4220,1,60,130,260,460,780,1060,1300,1560,1910,2500,4200,7000,10300,15900,18900,20900,22600,24900,28800,31500,34900,38300,41700,45100,48500,51900,55000,72000,89000,106000,112000,355000,615000,917000,1253000,1595000,2007000,2430000,2868000,3420000,3863000,4504000,4998000,5769000,6321000,7254000,7870000,9015000,9530000,999999999 + + diff --git a/db/re/job_exp.txt b/db/re/job_exp.txt index 68b5223e19..5ef1e27df8 100644 --- a/db/re/job_exp.txt +++ b/db/re/job_exp.txt @@ -2,26 +2,28 @@ // Only official levels included, check db/import-tmpl/job_exp.txt for an expanded list // // Structure of Database: -// Max Level,Class list,Type,Exp for Lv 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175 +// Max Level,Class list,Type,Exp for Lv 1,2,3,...,200 // // Type: // 0 = Base Exp, 1 = Job Exp //Base - Normal and Baby Jobs -99,0:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:23:24:25:4023:4024:4025:4026:4027:4028:4029:4030:4031:4032:4033:4034:4035:4036:4037:4038:4039:4040:4041:4042:4043:4044:4045:4046:4047:4048:4049:4050:4051:4052:4222:4225:4226:4227:4228:4238,0,550,900,1500,2200,3200,3800,4200,4550,5000,5500,6000,6100,6350,6700,7350,8000,8400,8800,9200,9700,10300,11000,11800,13000,14000,15000,16000,17000,18000,19000,20000,21000,22000,23200,24000,26000,27500,29000,30000,31500,33000,34000,36000,37500,38000,40000,42000,44500,47000,49000,51000,53000,55000,57000,59000,61500,63000,65000,67000,69000,70000,73000,77000,80000,84000,88000,91000,95000,110000,128000,140000,155000,163000,170000,180000,188000,195000,200000,230000,260000,300000,350000,400000,480000,550000,600000,680000,750000,900000,1000000,1200000,1500000,1800000,2100000,2400000,2800000,3300000,4000000,99999999 +99,0:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:23:24:25:4023:4024:4025:4026:4027:4028:4029:4030:4031:4032:4033:4034:4035:4036:4037:4038:4039:4040:4041:4042:4043:4044:4045:4046:4047:4048:4049:4050:4051:4052:4222:4225:4226:4227:4228:4238,0,550,900,1500,2200,3200,3800,4200,4550,5000,5500,6000,6100,6350,6700,7350,8000,8400,8800,9200,9700,10300,11000,11800,13000,14000,15000,16000,17000,18000,19000,20000,21000,22000,23200,24000,26000,27500,29000,30000,31500,33000,34000,36000,37500,38000,40000,42000,44500,47000,49000,51000,53000,55000,59000,61500,61500,63000,65000,67000,69000,70000,73000,77000,80000,84000,88000,91000,95000,110000,128000,140000,155000,163000,170000,180000,188000,195000,200000,230000,260000,300000,350000,400000,480000,550000,600000,680000,750000,900000,1000000,1200000,1500000,1800000,2100000,2400000,2800000,3300000,4000000,99999999 -//Base - Adv Jobs -99,4001:4002:4003:4004:4005:4006:4007:4008:4009:4010:4011:4012:4013:4014:4015:4016:4017:4018:4019:4020:4021:4022,0,660,1080,1800,2640,3840,4560,5040,5460,6000,6600,7200,7320,7620,8040,8820,9600,10080,10560,11040,12610,13390,14300,15340,16900,18460,19500,20800,22100,23400,24700,26000,27300,28600,30160,31200,33800,35750,37700,39000,44100,46200,47600,50400,52500,53200,56000,58800,62300,65800,68600,71400,74200,77000,79800,82600,86100,88200,91000,93800,103500,105000,109500,115500,120000,126000,132000,136500,142500,165000,192000,210000,232500,244500,255000,270000,282000,292500,300000,345000,416000,480000,560000,640000,768000,880000,960000,1088000,1200000,1440000,1700000,2040000,2550000,3060000,3570000,4080000,4760000,5610000,6800000,99999999 +//Base - Trans classes +99,4001:4002:4003:4004:4005:4006:4007:4008:4009:4010:4011:4012:4013:4014:4015:4016:4017:4018:4019:4020:4021:4022,0,600,1080,1800,2640,3840,4560,5040,5460,6000,6600,7200,7320,7620,8040,8820,9600,10080,10560,11040,12610,13390,14300,15340,16900,18460,19500,20800,22100,23400,24700,26000,27300,28600,30160,31200,33800,35750,37700,39000,44100,46200,47600,50400,52500,53200,56000,58800,62300,65800,68600,71400,74200,77000,79800,82600,86100,88200,91000,93800,103500,105000,109500,115500,120000,126000,132000,136500,142500,165000,192000,210000,232500,244500,255000,270000,282000,292500,300000,345000,416000,480000,560000,640000,768000,880000,960000,1088000,1200000,1440000,1700000,2040000,2550000,3060000,3570000,4080000,4760000,5610000,6800000,99999999 -//Base - 3rd Jobs, Baby 3rds, Oboro/Kagerou, Rebellion, Summoner, Star Emperor, Soul Reaper -//Note: (First 98 values [Level 1 - 98] are only used by Summoner Class, because 3rd classes start at level 99.) -175,4054:4055:4056:4057:4058:4059:4060:4061:4062:4063:4064:4065:4066:4067:4068:4069:4070:4071:4072:4073:4074:4075:4076:4077:4078:4079:4080:4081:4082:4083:4084:4085:4086:4087:4096:4097:4098:4099:4100:4101:4102:4103:4104:4105:4106:4107:4108:4109:4110:4111:4112:4211:4212:4215:4218:4220:4223:4224:4229:4239:4240:4241:4242:4243:4244,0,55,90,150,220,320,380,420,455,500,600,700,800,900,1000,1100,1200,1300,1400,1500,1800,2100,2400,2700,3000,3300,3600,3900,4200,4500,5400,6300,7200,8100,9000,9900,10800,11700,12600,13500,16200,18900,21600,24300,27000,29700,32400,35100,37800,40500,43200,45900,48600,51300,54000,56700,59400,62100,64800,67500,75600,83700,91800,99900,108000,116100,124200,132300,140400,165000,192000,210000,232500,244500,255000,270000,282000,292500,300000,345000,416000,480000,560000,640000,768000,880000,960000,1088000,1200000,1440000,1700000,2040000,2550000,3060000,3570000,4080000,4760000,5610000,6800000,7070000,7400000,7770000,8150000,8550000,9100000,9610000,10150000,10570000,11180000,12000000,12200000,12930000,13150000,14030000,14420000,15420000,15670000,16870000,17140000,18720000,19020000,20590000,20930000,22690000,23310000,25290000,26020000,27860000,28535000,30990000,31680000,33560000,34942000,36372000,38350000,39890000,41545000,43330000,45400000,48100000,50410000,53370000,56250000,59230000,62590000,66120000,70200000,75330000,81100000,95000000,98000000,103000000,107000000,112000000,116000000,121000000,125000000,130000000,134000000,139000000,145000000,152200000,160840000,171200000,191930000,202290000,214720000,229640000,247550000,283370000,301280000,322770000,348560000,379500000,441390000,99999999 +//Base - Extended classes - Values for level 1 - 99 are unused and are simply copy-pasted from Normal classes values. +200,4190:4191:4211:4212:4215:4239:4240:4223:4224:4229:4239:4240:4241:4242:4243:4244,0,550,900,1500,2200,3200,3800,4200,4550,5000,5500,6000,6100,6350,6700,7350,8000,8400,8800,9200,9700,10300,11000,11800,13000,14000,15000,16000,17000,18000,19000,20000,21000,22000,23200,24000,26000,27500,29000,30000,31500,33000,34000,36000,37500,38000,40000,42000,44500,47000,49000,51000,53000,55000,59000,61500,61500,63000,65000,67000,69000,70000,73000,77000,80000,84000,88000,91000,95000,110000,128000,140000,155000,163000,170000,180000,188000,195000,200000,230000,260000,300000,350000,400000,480000,550000,600000,680000,750000,900000,1000000,1200000,1500000,1800000,2100000,2400000,2800000,3300000,4000000,1272747,1354202,1440870,1533085,1631202,1735598,1846676,1964863,2090614,2224413,2366775,2518248,2679415,2850897,3033354,3227488,3434047,3653826,3887670,4136480,4401214,4755467,5138234,5551810,5998675,6481508,7003204,7566891,8175950,8834032,9545083,10313366,11143488,12040427,13009560,14056699,15188122,16410613,17731503,19158711,20700795,22367001,24167320,26112547,28214345,30485317,32939080,35590346,38455012,41550255,44894635,48508204,52412629,56631321,61189576,66114724,71436298,77186205,83398922,90111701,97364791,105201683,113669366,122818613,132704283,143385650,154926760,167396814,180870583,195428856,211158924,229155105,246519309,266361648,287801097,310966207,352013746,398479560,451078861,510621270,578023277,654322349,740692899,838464361,949141656,1074428354,1216252896,1376798278,1558535650,1764262355,1997144985,2260768123,2559189515,2897002530,3279406863,3712288568,4202310658,4757015664,5384941731,6095754039,6900363572,99999999 -//Base - Expanded Super Novice & Expanded Super Baby -160,4190:4191,0,660,1080,1800,2640,3840,4560,5040,5460,6000,6600,7200,7320,7620,8040,8820,9600,10080,10560,11040,12610,13390,14300,15340,16900,18460,19500,20800,22100,23400,24700,26000,27300,28600,30160,31200,33800,35750,37700,39000,44100,46200,47600,50400,52500,53200,56000,58800,62300,65800,68600,71400,74200,77000,79800,82600,86100,88200,91000,93800,103500,105000,109500,115500,120000,126000,132000,136500,142500,165000,192000,210000,232500,244500,255000,270000,282000,292500,300000,345000,416000,480000,560000,640000,768000,880000,960000,1088000,1200000,1440000,1700000,2040000,2550000,3060000,3570000,4080000,4760000,5610000,6800000,7070000,7400000,7770000,8150000,8550000,9100000,9610000,10150000,10570000,11180000,12000000,12200000,12930000,13150000,14030000,14420000,15420000,15670000,16870000,17140000,18720000,19020000,20590000,20930000,22690000,23310000,25290000,26020000,27860000,28535000,30990000,31680000,33560000,34942000,36372000,38350000,39890000,41545000,43330000,45400000,48100000,50410000,53370000,56250000,59230000,62590000,66120000,70200000,75330000,81100000,95000000,98000000,103000000,107000000,112000000,116000000,121000000,125000000,130000000,134000000,139000000,145000000,152200000,160840000,171200000,191930000,202290000,214720000,229640000,247550000,283370000,301280000,322770000,348560000,379500000,441390000,99999999 +//Base - Third classes - Values for level 1 - 99 are unused and are simply copy-pasted from Trans classes values. +200,4054:4055:4056:4057:4058:4059:4066:4067:4068:4069:4070:4071:4072:4060:4061:4062:4063:4064:4065:4073:4074:4075:4076:4077:4078:4079:4080:4081:4082:4083:4084:4085:4086:4087:4096:4097:4098:4099:4100:4101:4102:4103:4104:4105:4106:4107:4108:4109:4110:4111:4112,0,600,1080,1800,2640,3840,4560,5040,5460,6000,6600,7200,7320,7620,8040,8820,9600,10080,10560,11040,12610,13390,14300,15340,16900,18460,19500,20800,22100,23400,24700,26000,27300,28600,30160,31200,33800,35750,37700,39000,44100,46200,47600,50400,52500,53200,56000,58800,62300,65800,68600,71400,74200,77000,79800,82600,86100,88200,91000,93800,103500,105000,109500,115500,120000,126000,132000,136500,142500,165000,192000,210000,232500,244500,255000,270000,282000,292500,300000,345000,416000,480000,560000,640000,768000,880000,960000,1088000,1200000,1440000,1700000,2040000,2550000,3060000,3570000,4080000,4760000,5610000,6800000,1272747,1354202,1440870,1533085,1631202,1735598,1846676,1964863,2090614,2224413,2366775,2518248,2679415,2850897,3033354,3227488,3434047,3653826,3887670,4136480,4401214,4755467,5138234,5551810,5998675,6481508,7003204,7566891,8175950,8834032,9545083,10313366,11143488,12040427,13009560,14056699,15188122,16410613,17731503,19158711,20700795,22367001,24167320,26112547,28214345,30485317,32939080,35590346,38455012,41550255,44894635,48508204,52412629,56631321,61189576,66114724,71436298,77186205,83398922,90111701,97364791,105201683,113669366,122818613,132704283,143385650,154926760,167396814,180870583,195428856,211158924,229155105,246519309,266361648,287801097,310966207,352013746,398479560,451078861,510621270,578023277,654322349,740692899,838464361,949141656,1074428354,1216252896,1376798278,1558535650,1764262355,1997144985,2260768123,2559189515,2897002530,3279406863,3712288568,4202310658,4757015664,5384941731,6095754039,6900363572,99999999 + +//Base- Summoner +200,4218:4220,0,55,90,150,220,320,380,420,455,500,550,600,700,800,900,1000,1100,1200,1400,1500,1800,2100,2400,2700,3000,3300,3600,3900,4200,4500,5400,6300,7200,8100,9000,9900,10800,11700,12600,13500,16200,18900,21600,24300,27000,29700,32400,35100,37800,40500,43200,45900,48600,51300,54000,56700,59400,62100,64800,67500,70200,72900,75600,78300,81000,83700,86400,89100,91800,94500,103950,114345,125779,138356,152201,167421,184163,202579,222836,240662,259914,280707,303163,327416,353609,381897,412448,445443,481078,519564,561129,606019,654500,706860,763408,824480,890438,961673,1038606,1121694,1211429,1308343,1413010,1526050,1648134,1779984,1922382,2076172,2242265,2421646,2615377,2824607,3050575,3294621,3558190,3842845,4150272,4482293,4840876,5228146,5646397,6098108,6585956,7112832,7681858,8296406,8960118,9676927,10451081,11287167,12190140,13165351,14218579,15356065,16584550,17911314,19344219,20891756,22563096,24368143,26317594,28423001,30696841,33152588,35804795,38669178,41762712,45103728,48712026,52608988,56817707,61363123,66272172,71573945,77299860,83483848,90162555,97375559,105165603,113578851,122665159,132478371,143076640,154522771,166884592,177548517,188893867,200964185,222383346,234614430,247518223,261131725,275493969,290646137,306631674,347137718,392994610,444909197,503681701,570218053,645543857,730820200,827361548,936656008,1060388266,1200465555,1359047054,1538577169,1741823213,1971918059,2232408434,2527309588,2861167184,3239127369,3667016094,4151428920,4699832680,5320680577,6023542481,6819252442,99999999 //Job - Novice & Baby Novice -10,0:4023,1,10,18,28,40,91,151,205,268,340,999999999 +10,0:4023,1,55,90,150,150,320,380,420,455,500,999999999 //Job - 1st Classes & Baby 1st Classes, Taekwon 50,1:2:3:4:5:6:4024:4025:4026:4027:4028:4029:4046:4050:4225,1,60,130,260,460,780,1060,1300,1560,1910,2290,2680,2990,3340,3740,4360,4970,5530,6120,6700,8090,8920,9970,11080,12690,14440,15850,17400,19220,21060,22870,24910,26840,29080,31320,33300,37110,40500,43570,46180,53510,57200,60310,65690,70090,72130,77540,83320,90120,97180,999999999 @@ -29,29 +31,29 @@ //Job - 2nd Classes & Baby 2nd Classes, Soul Linker 50,7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:4030:4031:4032:4033:4034:4035:4036:4037:4038:4039:4040:4041:4042:4043:4044:4049:4051:4052:4227,1,2500,4200,7000,10300,15900,18900,20900,22600,24900,28800,31500,32000,33300,35100,40500,44100,46300,48500,50700,56000,59400,63500,68100,75000,85700,90500,96600,102600,108600,119700,126000,132300,138600,146100,157500,170600,180400,190300,196800,214900,225200,232000,245700,255900,279300,294000,308700,327000,345400,999999999 -//Job - Novice High -10,4001,1,11,20,31,44,100,166,226,295,374,999999999 - -//Job - Adv First Classes -50,4002:4003:4004:4005:4006:4007,1,100,200,350,550,800,1100,1450,1850,2300,2800,3350,3950,4600,5300,6050,6850,7700,8600,9550,10550,11600,12700,13850,15050,16300,17600,18950,20350,21800,23300,24850,26450,28100,29800,31550,33350,35200,37100,39050,41050,43100,45200,47350,49550,51800,54100,56450,58850,61300,999999999 - -//Job - Adv Second Classes -70,4008:4009:4010:4011:4012:4013:4014:4015:4016:4017:4018:4019:4020:4021:4022,1,3800,6200,10400,15200,22900,27100,30000,32500,35700,41300,45000,45800,47600,50300,58700,63900,67100,70300,73500,90600,96200,102700,110200,121400,144700,152900,163100,173300,183500,213500,224700,236000,247200,260700,299800,324800,343600,362300,374800,474400,497000,512100,542200,564800,644300,678200,712100,754500,796900,873100,911900,950600,989400,1028100,1143300,1199900,1233800,1279100,1324300,1486900,1515900,1603000,1719200,1806300,2040300,2244300,2415900,2746000,3326000,999999999 - -//Job - 3rd Jobs & Baby 3rds, Oboro/Kagerou, Rebellion, Star Emperor, Soul Reaper -60,4054:4055:4056:4057:4058:4059:4060:4061:4062:4063:4064:4065:4066:4067:4068:4069:4070:4071:4072:4073:4074:4075:4076:4077:4078:4079:4080:4081:4082:4083:4084:4085:4086:4087:4096:4097:4098:4099:4100:4101:4102:4103:4104:4105:4106:4107:4108:4109:4110:4111:4112:4211:4212:4215:4223:4224:4229:4239:4240:4241:4242:4243:4244,1,112000,355000,615000,917000,1253000,1595000,2007000,2430000,2868000,3420000,3863000,4504000,4998000,5769000,6321000,7254000,7870000,9015000,9530000,11072000,11848000,13467000,14337000,16243000,17216000,19446000,20781000,23070000,24453000,27568000,29118000,31820000,34125000,37048000,40204000,42972000,45937000,49110000,52696000,57158000,61305000,67167000,72285000,77647000,83624000,91113000,98548000,107630000,119077000,131668000,145518000,160753000,177511000,195944000,216220000,238523000,263056000,290042000,319726000,999999999 - -//Job - Expanded Super Novice & Expanded Super Baby -50,4190:4191,1,112000,355000,615000,917000,1253000,1595000,2007000,2430000,2868000,3420000,3863000,4504000,4998000,5769000,6321000,7254000,7870000,9015000,9530000,11072000,11848000,13467000,14337000,16243000,17216000,19446000,20781000,23070000,24453000,27568000,29118000,31820000,34125000,37048000,40204000,42972000,45937000,49110000,52696000,57158000,61305000,67167000,72285000,77647000,83624000,91113000,98548000,107630000,119077000,999999999 - -//Job - Ninja/Gunslinger +//Job - Ninja, Gunslinger 70,24:25:4222:4228,1,200,300,400,600,700,1000,1200,1400,1700,1900,2400,2700,3200,3600,4200,4900,5500,6100,6900,7700,8400,9300,10100,11100,12100,13000,14600,16100,17500,18600,21500,23300,24700,27000,29000,30000,32400,35000,38100,41100,44000,46700,49600,52500,55600,58900,62700,65500,69200,72300,81200,84100,89300,95500,100900,107800,114900,120700,128600,150500,176900,196100,219600,234200,247900,266400,281300,296600,308000,999999999 //Job - Star Gladiator 50,4047:4048:4226:4238,1,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,50700,101400,112000,118800,127000,136200,150000,171400,181000,193200,205200,217200,239400,252000,264600,277200,292200,315000,341200,360800,380600,393600,429800,450400,464000,491400,511800,558600,588000,617400,654000,690800,999999999 +//Job - High Novice +10,4001,1,12,22,35,50,113,188,256,335,425,999999999 + +//Job - Trans 1st Classes +50,4002:4003:4004:4005:4006:4007,1,340,550,760,990,1250,1600,1980,2340,2740,3140,3950,4510,5210,5950,7000,8150,9130,10220,11480,12780,14090,15560,16980,18620,20280,21780,24510,27000,29000,31000,36000,39000,41000,45000,49000,51900,55000,59450,64630,70030,74940,79800,84630,89610,95170,100420,107250,112070,118120,999999999 + +//Job - Trans 2nd Classes +70,4008:4009:4010:4011:4012:4013:4014:4015:4016:4017:4018:4019:4020:4021:4022,1,1803,2972,5036,7434,11312,13520,15117,16540,18350,21441,23596,24256,25461,27174,32029,35216,37349,39521,41734,51958,55721,60081,65113,72448,87216,93081,100283,107620,115094,135249,143768,152508,161343,171856,199607,218415,233368,248529,259675,331968,351261,365552,390909,411275,473857,503777,534248,571719,609886,674886,711926,749561,787957,826965,928824,984554,1022494,1070636,1119554,1269585,1307290,1396228,1512414,1604928,1830969,2034180,2211611,2538936,3105953,999999 + +//Job - 3rd Jobs & Baby 3rds, Oboro, Kagerou, Rebellion, Star Emperor, Soul Reaper +70,4054:4055:4056:4057:4058:4059:4060:4061:4062:4063:4064:4065:4066:4067:4068:4069:4070:4071:4072:4073:4074:4075:4076:4077:4078:4079:4080:4081:4082:4083:4084:4085:4086:4087:4096:4097:4098:4099:4100:4101:4102:4103:4104:4105:4106:4107:4108:4109:4110:4111:4112:4211:4212:4215:4223:4224:4229:4239:4240:4241:4242:4243:4244,1,12800,16384,20971,26843,34359,43980,56294,72057,92233,118059,151115,193428,247588,316912,405648,519229,664613,850705,1088903,1393796,1784059,2283596,2923003,3741444,4231573,4785909,5412863,6121948,6923924,7830958,8856813,10017056,11329290,12813427,14491986,16390436,18537584,20966007,23712554,26818899,30332175,34305690,38799735,43882500,49631108,56132783,63486178,71802867,81209043,91847428,103879441,117487647,132878529,150285617,169973033,192239500,217422874,245905271,278118862,319836691,367812195,422984024,486431628,559396372,632361116,705325860,778290604,851255348,924220092,999999999 + +//Job - Expanded Super Novice & Expanded Super Baby +50,4190:4191,1,112000,355000,615000,917000,1253000,1595000,2007000,2430000,2868000,3420000,3863000,4504000,4998000,5769000,6321000,7254000,7870000,9015000,9530000,11072000,11848000,13467000,14337000,16243000,17216000,19446000,20781000,23070000,24453000,27568000,29118000,31820000,34125000,37048000,40204000,42972000,45937000,49110000,52696000,57158000,61305000,67167000,72285000,77647000,83624000,91113000,98548000,107630000,119077000,999999999 + //Job - Super Novice & Baby Super Novice -99,23:4045,1,60,130,260,460,780,1060,1300,1560,1910,2290,2680,2990,3340,3740,4360,4970,5530,6120,6700,8090,8920,9970,11080,12690,14440,15850,17400,19220,21060,22870,24910,26840,29080,31320,33300,37110,40500,43570,46180,53510,57200,60310,65690,70090,72130,77540,83320,90120,97180,590120,600120,610120,620120,630120,640120,650120,660120,670120,680120,690120,700120,710120,720120,730120,740120,750120,760120,770120,780120,790120,800120,810120,820120,830120,840120,850120,860120,870120,880120,890120,900120,910120,920120,930120,940120,950120,960120,970120,980120,990120,1000120,1010120,1020120,1030120,1040120,1050120,1060120,1070120,999999999 +99,23:4045,1,60,130,260,460,780,1060,1300,1560,1910,2290,2680,2990,3340,3740,4360,4970,5530,6120,6700,8090,8920,9970,11080,12690,14440,15850,17400,19220,21060,22870,24910,26840,29080,31320,33300,37110,40500,43570,46180,53510,57200,60310,65690,70090,72130,77540,83320,90120,590120,600120,610120,620120,630120,640120,650120,660120,670120,680120,690120,700120,710120,720120,730120,740120,750120,760120,770120,780120,790120,800120,810120,820120,830120,840120,850120,860120,870120,880120,890120,900120,910120,920120,930120,940120,950120,960120,970120,980120,990120,1000120,1010120,1020120,1030120,1040120,1050120,1060120,1070120,1080120,999999999 //Job - Summoner -50,4218:4220,1,60,130,260,460,780,1060,1300,1560,1910,2500,4200,7000,10300,15900,18900,20900,22600,24900,28800,31500,34900,38300,41700,45100,48500,51900,55000,72000,89000,106000,112000,355000,615000,917000,1253000,1595000,2007000,2430000,2868000,3420000,3863000,4504000,4998000,5769000,6321000,7254000,7870000,9015000,9530000,999999999 +70,4218:4220,1,60,130,260,460,780,1060,1300,1560,1910,2500,4200,7000,10300,15900,18900,20900,22600,24900,28800,33100,35100,40500,44100,46300,48500,50700,56000,59000,63500,68100,75000,85700,90500,106000,112000,355000,615000,917000,1253000,1595000,2007000,2430000,2868000,3420000,3863000,4504000,4998000,5769000,6321000,7585200,9860760,13805064,20707596,33132154,53011447,72890740,92770033,112649326,132528619,319836691,367812195,422984024,486431628,559396372,632361116,705325860,778290604,851255348,924220092,999999999 diff --git a/sql-files/main.sql b/sql-files/main.sql index 6669526676..01c1869e81 100644 --- a/sql-files/main.sql +++ b/sql-files/main.sql @@ -439,7 +439,7 @@ CREATE TABLE IF NOT EXISTS `guild` ( `max_member` tinyint(6) unsigned NOT NULL default '0', `average_lv` smallint(6) unsigned NOT NULL default '1', `exp` bigint(20) unsigned NOT NULL default '0', - `next_exp` int(11) unsigned NOT NULL default '0', + `next_exp` bigint(20) unsigned NOT NULL default '0', `skill_point` tinyint(11) unsigned NOT NULL default '0', `mes1` varchar(60) NOT NULL default '', `mes2` varchar(120) NOT NULL default '', diff --git a/sql-files/upgrades/upgrade_20200728.sql b/sql-files/upgrades/upgrade_20200728.sql new file mode 100644 index 0000000000..d2558343e3 --- /dev/null +++ b/sql-files/upgrades/upgrade_20200728.sql @@ -0,0 +1,2 @@ +ALTER TABLE `guild` + CHANGE COLUMN `next_exp` `next_exp` bigint(20) unsigned NOT NULL default '0'; diff --git a/src/char/char.cpp b/src/char/char.cpp index c12d0f4e56..08b714186e 100644 --- a/src/char/char.cpp +++ b/src/char/char.cpp @@ -303,7 +303,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){ ) { //Save status if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d'," - "`base_exp`='%u', `job_exp`='%u', `zeny`='%d'," + "`base_exp`='%" PRIu64 "', `job_exp`='%" PRIu64 "', `zeny`='%d'," "`max_hp`='%u',`hp`='%u',`max_sp`='%u',`sp`='%u',`status_point`='%d',`skill_point`='%d'," "`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d'," "`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d'," @@ -916,8 +916,8 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf, uint8* coun || SQL_ERROR == SqlStmt_BindColumn(stmt, 3, SQLDT_SHORT, &p.class_, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_UINT, &p.base_level, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 5, SQLDT_UINT, &p.job_level, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 6, SQLDT_UINT, &p.base_exp, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &p.job_exp, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 6, SQLDT_UINT64, &p.base_exp, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 7, SQLDT_UINT64, &p.job_exp, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 8, SQLDT_INT, &p.zeny, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 9, SQLDT_SHORT, &p.str, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 10, SQLDT_SHORT, &p.agi, 0, NULL, NULL) @@ -1034,8 +1034,8 @@ int char_mmo_char_fromsql(uint32 char_id, struct mmo_charstatus* p, bool load_ev || SQL_ERROR == SqlStmt_BindColumn(stmt, 4, SQLDT_SHORT, &p->class_, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 5, SQLDT_UINT, &p->base_level, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 6, SQLDT_UINT, &p->job_level, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 7, SQLDT_UINT, &p->base_exp, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 8, SQLDT_UINT, &p->job_exp, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 7, SQLDT_UINT64, &p->base_exp, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 8, SQLDT_UINT64, &p->job_exp, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 9, SQLDT_INT, &p->zeny, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 10, SQLDT_SHORT, &p->str, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 11, SQLDT_SHORT, &p->agi, 0, NULL, NULL) @@ -1756,19 +1756,19 @@ int char_mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) buf = WBUFP(buffer,0); WBUFL(buf,0) = p->char_id; #if PACKETVER >= 20170830 - WBUFQ(buf,4) = u64min((uint64)p->base_exp, INT64_MAX); + WBUFQ(buf,4) = u64min(p->base_exp, MAX_EXP); offset += 4; buf = WBUFP(buffer, offset); #else - WBUFL(buf,4) = umin(p->base_exp, INT32_MAX); + WBUFL(buf,4) = (int32)u64min(p->base_exp, MAX_EXP); #endif WBUFL(buf,8) = p->zeny; #if PACKETVER >= 20170830 - WBUFQ(buf,12) = u64min((uint64)p->job_exp, INT64_MAX); + WBUFQ(buf,12) = u64min(p->job_exp, MAX_EXP); offset += 4; buf = WBUFP(buffer, offset); #else - WBUFL(buf,12) = umin(p->job_exp, INT32_MAX); + WBUFL(buf,12) = (int32)u64min(p->job_exp, MAX_EXP); #endif WBUFL(buf,16) = p->job_level; WBUFL(buf,20) = 0; // probably opt1 diff --git a/src/char/int_guild.cpp b/src/char/int_guild.cpp index 9f2335a8c8..14a2d1d4c9 100644 --- a/src/char/int_guild.cpp +++ b/src/char/int_guild.cpp @@ -19,6 +19,8 @@ #include "char_mapif.hpp" #include "inter.hpp" +using namespace rathena; + #define GS_MEMBER_UNMODIFIED 0x00 #define GS_MEMBER_MODIFIED 0x01 #define GS_MEMBER_NEW 0x02 @@ -36,7 +38,7 @@ static const char dataToHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9 static DBMap* guild_db_; // int guild_id -> struct guild* static DBMap *castle_db; -static unsigned int guild_exp[100]; +static t_exp guild_exp[MAX_GUILDLEVEL]; int mapif_parse_GuildLeave(int fd,int guild_id,uint32 account_id,uint32 char_id,int flag,const char *mes); int mapif_guild_broken(int guild_id,int flag); @@ -221,7 +223,7 @@ int inter_guild_tosql(struct guild *g,int flag) StringBuf_AppendStr(&buf, ", "); //else //last condition using add_coma setting // add_comma = true; - StringBuf_Printf(&buf, "`guild_lv`=%d, `skill_point`=%d, `exp`=%" PRIu64 ", `next_exp`=%u, `max_member`=%d", g->guild_lv, g->skill_point, g->exp, g->next_exp, g->max_member); + StringBuf_Printf(&buf, "`guild_lv`=%d, `skill_point`=%d, `exp`=%" PRIu64 ", `next_exp`=%" PRIu64 ", `max_member`=%d", g->guild_lv, g->skill_point, g->exp, g->next_exp, g->max_member); } StringBuf_Printf(&buf, " WHERE `guild_id`=%d", g->guild_id); if( SQL_ERROR == Sql_Query(sql_handle, "%s", StringBuf_Value(&buf)) ) @@ -377,7 +379,7 @@ struct guild * inter_guild_fromsql(int guild_id) } Sql_GetData(sql_handle, 5, &data, NULL); g->average_lv = atoi(data); Sql_GetData(sql_handle, 6, &data, NULL); g->exp = strtoull(data, NULL, 10); - Sql_GetData(sql_handle, 7, &data, NULL); g->next_exp = (unsigned int)strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 7, &data, NULL); g->next_exp = strtoull(data, nullptr, 10); Sql_GetData(sql_handle, 8, &data, NULL); g->skill_point = atoi(data); Sql_GetData(sql_handle, 9, &data, &len); memcpy(g->mes1, data, zmin(len, sizeof(g->mes1))); Sql_GetData(sql_handle, 10, &data, &len); memcpy(g->mes2, data, zmin(len, sizeof(g->mes2))); @@ -638,10 +640,10 @@ struct guild_castle* inter_guildcastle_fromsql(int castle_id) // Read exp_guild.txt bool exp_guild_parse_row(char* split[], int column, int current) { - unsigned int exp = (unsigned int)atol(split[0]); + t_exp exp = strtoull(split[0], nullptr, 10); - if (exp >= UINT_MAX) { - ShowError("exp_guild: Invalid exp %d at line %d\n", exp, current); + if (exp > MAX_GUILD_EXP) { + ShowError("exp_guild: Invalid exp %" PRIu64 " at line %d, exceeds max of %" PRIu64 "\n", exp, current, MAX_GUILD_EXP); return false; } @@ -833,7 +835,7 @@ bool guild_check_empty(struct guild *g) return i < g->max_member ? false : true; // not empty } -unsigned int guild_nextexp(int level) +t_exp guild_nextexp(int level) { if (level == 0) return 1; @@ -852,7 +854,7 @@ int guild_checkskill(struct guild *g,int id) int guild_calcinfo(struct guild *g) { int i,c; - unsigned int nextexp; + t_exp nextexp; struct guild before = *g; // Save guild current values if(g->guild_lv<=0) @@ -1546,22 +1548,19 @@ int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,uint32 account_id,uint } case GMI_EXP: { // EXP - uint64 old_exp=g->member[i].exp; - g->member[i].exp=*((uint64 *)data); + t_exp old_exp=g->member[i].exp; + g->member[i].exp=*((t_exp *)data); g->member[i].modified = GS_MEMBER_MODIFIED; if (g->member[i].exp > old_exp) { - uint64 exp = g->member[i].exp - old_exp; + t_exp exp = g->member[i].exp - old_exp; // Compute gained exp if (charserv_config.guild_exp_rate != 100) exp = exp*(charserv_config.guild_exp_rate)/100; // Update guild exp - if (exp > UINT64_MAX - g->exp) - g->exp = UINT64_MAX; - else - g->exp+=exp; + g->exp = util::safe_addition_cap(g->exp, exp, MAX_GUILD_EXP); guild_calcinfo(g); mapif_guild_basicinfochanged(guild_id,GBI_EXP,&g->exp,sizeof(g->exp)); diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp index 0d071186bb..bc24022e4a 100644 --- a/src/common/mmo.hpp +++ b/src/common/mmo.hpp @@ -488,7 +488,7 @@ struct mmo_charstatus { uint32 mother; uint32 child; - unsigned int base_exp,job_exp; + t_exp base_exp,job_exp; int zeny; short class_; ///< Player's JobID @@ -632,7 +632,7 @@ struct map_session_data; struct guild_member { uint32 account_id, char_id; short hair,hair_color,gender,class_,lv; - uint64 exp; + t_exp exp; short online,position; char name[NAME_LENGTH]; struct map_session_data *sd; @@ -667,8 +667,8 @@ struct Channel; struct guild { int guild_id; short guild_lv, connect_member, max_member, average_lv; - uint64 exp; - unsigned int next_exp; + t_exp exp; + t_exp next_exp; int skill_point; char name[NAME_LENGTH],master[NAME_LENGTH]; struct guild_member member[MAX_GUILD]; diff --git a/src/common/utilities.cpp b/src/common/utilities.cpp index 9b5267cf8b..6e5e50a9cd 100644 --- a/src/common/utilities.cpp +++ b/src/common/utilities.cpp @@ -69,28 +69,6 @@ int levenshtein(const std::string &s1, const std::string &s2) return result; } -bool rathena::util::safe_addition( int64 a, int64 b, int64& result ){ -#if __has_builtin( __builtin_add_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 ) - return __builtin_add_overflow( a, b, &result ); -#else - bool overflow = false; - - if( b < 0 ){ - if( a < ( INT64_MIN - b ) ){ - overflow = true; - } - }else{ - if( a > ( INT64_MAX - b ) ){ - overflow = true; - } - } - - result = a + b; - - return overflow; -#endif -} - bool rathena::util::safe_substraction( int64 a, int64 b, int64& result ){ #if __has_builtin( __builtin_sub_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 ) return __builtin_sub_overflow( a, b, &result ); diff --git a/src/common/utilities.hpp b/src/common/utilities.hpp index 15ba32cef6..c68009919a 100644 --- a/src/common/utilities.hpp +++ b/src/common/utilities.hpp @@ -14,6 +14,10 @@ #include "cbasetypes.hpp" #include "random.hpp" +#ifndef __has_builtin + #define __has_builtin(x) 0 +#endif + // Class used to perform time measurement class cScopeTimer { struct sPimpl; //this is to avoid long compilation time @@ -192,9 +196,55 @@ namespace rathena { } } - bool safe_addition( int64 a, int64 b, int64& result ); +#if __has_builtin( __builtin_add_overflow ) || ( defined( __GNUC__ ) && !defined( __clang__ ) && defined( GCC_VERSION ) && GCC_VERSION >= 50100 ) + template bool safe_addition(T a, T b, T &result) { + return __builtin_add_overflow(a, b, &result); + } +#else + template bool safe_addition( T a, T b, T& result ){ + bool overflow = false; + + if( std::numeric_limits::is_signed ){ + if( b < 0 ){ + if( a < ( (std::numeric_limits::min)() - b ) ){ + overflow = true; + } + }else{ + if( a > ( (std::numeric_limits::max)() - b ) ){ + overflow = true; + } + } + }else{ + if( a > ( (std::numeric_limits::max)() - b ) ){ + overflow = true; + } + } + + result = a + b; + + return overflow; + } +#endif + bool safe_substraction( int64 a, int64 b, int64& result ); bool safe_multiplication( int64 a, int64 b, int64& result ); + + /** + * Safely add values without overflowing. + * @param a: Holder of value to increment + * @param b: Increment by + * @param cap: Cap value + * @return Result of a + b + */ + template T safe_addition_cap( T a, T b, T cap ){ + T result; + + if( rathena::util::safe_addition( a, b, result ) ){ + return cap; + }else{ + return result; + } + } } } diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 9fde03e677..9ceff76f1e 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -365,7 +365,7 @@ unsigned int get_percentage(const unsigned int A, const unsigned int B) if( B == 0 ) { - ShowError("get_percentage(): divison by zero! (A=%u,B=%u)\n", A, B); + ShowError("get_percentage: divison by zero! (A=%u,B=%u)\n", A, B); return ~0U; } @@ -373,9 +373,30 @@ unsigned int get_percentage(const unsigned int A, const unsigned int B) if( result > UINT_MAX ) { - ShowError("get_percentage(): result percentage too high! (A=%u,B=%u,result=%g)\n", A, B, result); + ShowError("get_percentage: result percentage too high! (A=%u,B=%u,result=%g)\n", A, B, result); return UINT_MAX; } return (unsigned int)floor(result); } + +uint32 get_percentage_exp(const uint64 a, const uint64 b) +{ + double result; + + if (b == 0) + { + ShowError("get_percentage_exp: divison by zero! (a=%" PRIu64 ",b=%" PRIu64 ")\n", a, b); + return ~0U; + } + + result = 100.0 * ((double)a / (double)b); + + if (result > UINT32_MAX) + { + ShowError("get_percentage_exp: result percentage too high! (a=%" PRIu64 ",b=%" PRIu64 ",result=%g)\n", a, b, result); + return UINT32_MAX; + } + + return (uint32)floor(result); +} diff --git a/src/common/utils.hpp b/src/common/utils.hpp index ca946ec949..5fedcf0138 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -27,6 +27,7 @@ bool exists(const char* filename); /// calculates the value of A / B, in percent (rounded down) unsigned int get_percentage(const unsigned int A, const unsigned int B); +uint32 get_percentage_exp(const uint64 a, const uint64 b); ////////////////////////////////////////////////////////////////////////// // byte word dword access [Shinomori] diff --git a/src/config/const.hpp b/src/config/const.hpp index ee627672c5..a430ff5168 100644 --- a/src/config/const.hpp +++ b/src/config/const.hpp @@ -4,6 +4,8 @@ #ifndef CONFIG_CONST_H #define CONFIG_CONST_H +#include "../common/cbasetypes.hpp" + /** * rAthena configuration file (http://rathena.org) * For detailed guidance on these check http://rathena.org/wiki/SRC/config/ @@ -53,6 +55,25 @@ #define DEFTYPE_MAX CHAR_MAX #endif +/** + * EXP definition type + */ +typedef uint64 t_exp; + +/// Max Base and Job EXP for players +#if PACKETVER >= 20170830 + const t_exp MAX_EXP = INT64_MAX; +#else + const t_exp MAX_EXP = INT32_MAX; +#endif + +/// Max EXP for guilds +const t_exp MAX_GUILD_EXP = INT32_MAX; +/// Max Base EXP for player on Max Base Level +const t_exp MAX_LEVEL_BASE_EXP = 99999999; +/// Max Job EXP for player on Max Job Level +const t_exp MAX_LEVEL_JOB_EXP = 999999999; + /* pointer size fix which fixes several gcc warnings */ #ifdef __64BIT__ #define __64BPRTSIZE(y) (intptr)y diff --git a/src/map/atcommand.cpp b/src/map/atcommand.cpp index 1f7fefa0fc..3f2c8680d5 100644 --- a/src/map/atcommand.cpp +++ b/src/map/atcommand.cpp @@ -5313,11 +5313,11 @@ ACMD_FUNC(exp) nullpo_retr(-1, sd); memset(output, '\0', sizeof(output)); - nextb = pc_nextbaseexp(sd); + nextb = (double)pc_nextbaseexp(sd); if (nextb) nextb = sd->status.base_exp*100.0/nextb; - nextj = pc_nextjobexp(sd); + nextj = (double)pc_nextjobexp(sd); if (nextj) nextj = sd->status.job_exp*100.0/nextj; diff --git a/src/map/clif.cpp b/src/map/clif.cpp index cbcb73fbea..439d3408f5 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -65,6 +65,16 @@ static inline uint32 client_tick( t_tick tick ){ return (uint32)tick; } +#if PACKETVER >= 20170830 +static inline int64 client_exp(t_exp exp) { + return (int64)u64min(exp, MAX_EXP); +} +#else +static inline int32 client_exp(t_exp exp) { + return (int32)u64min(exp, MAX_EXP); +} +#endif + /* for clif_clearunit_delayed */ static struct eri *delay_clearunit_ers; @@ -3357,40 +3367,40 @@ void clif_updatestatus(struct map_session_data *sd,int type) #if PACKETVER >= 20170830 case SP_BASEEXP: WFIFOW(fd,0)=0xacb; - WFIFOQ(fd,4)=sd->status.base_exp; + WFIFOQ(fd,4)=client_exp(sd->status.base_exp); len = packet_len(0xacb); break; case SP_JOBEXP: WFIFOW(fd,0)=0xacb; - WFIFOQ(fd,4)=sd->status.job_exp; + WFIFOQ(fd,4)=client_exp(sd->status.job_exp); len = packet_len(0xacb); break; case SP_NEXTBASEEXP: WFIFOW(fd,0)=0xacb; - WFIFOQ(fd,4)=pc_nextbaseexp(sd); + WFIFOQ(fd,4)=client_exp(pc_nextbaseexp(sd)); len = packet_len(0xacb); break; case SP_NEXTJOBEXP: WFIFOW(fd,0)=0xacb; - WFIFOQ(fd,4)=pc_nextjobexp(sd); + WFIFOQ(fd,4)=client_exp(pc_nextjobexp(sd)); len = packet_len(0xacb); break; #else case SP_BASEEXP: WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=sd->status.base_exp; + WFIFOL(fd,4)=client_exp(sd->status.base_exp); break; case SP_JOBEXP: WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=sd->status.job_exp; + WFIFOL(fd,4)=client_exp(sd->status.job_exp); break; case SP_NEXTBASEEXP: WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=pc_nextbaseexp(sd); + WFIFOL(fd,4)= client_exp(pc_nextbaseexp(sd)); break; case SP_NEXTJOBEXP: WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=pc_nextjobexp(sd); + WFIFOL(fd,4)= client_exp(pc_nextjobexp(sd)); break; #endif @@ -8525,8 +8535,8 @@ void clif_guild_basicinfo(struct map_session_data *sd) { WFIFOL(fd,10)=g->connect_member; WFIFOL(fd,14)=g->max_member; WFIFOL(fd,18)=g->average_lv; - WFIFOL(fd,22)=(uint32)cap_value(g->exp,0,INT32_MAX); - WFIFOL(fd,26)=g->next_exp; + WFIFOL(fd,22)=(uint32)cap_value(g->exp, 0, MAX_GUILD_EXP); + WFIFOL(fd,26)=(uint32)cap_value(g->next_exp, 0, MAX_GUILD_EXP); WFIFOL(fd,30)=0; // Tax Points WFIFOL(fd,34)=0; // Honor: (left) Vulgar [-100,100] Famed (right) WFIFOL(fd,38)=0; // Virtue: (down) Wicked [-100,100] Righteous (up) @@ -14707,10 +14717,10 @@ void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) { if( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE ) { - unsigned int next = pc_nextbaseexp(sd); + t_exp next = pc_nextbaseexp(sd); if( next ) { - int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. ); + int percent = (int)( ( (double)sd->status.base_exp/(double)next )*1000. ); if( percent && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0% sc_start(&sd->bl,&sd->bl, status_skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill_get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] @@ -18168,9 +18178,9 @@ void clif_party_show_picker( struct map_session_data* sd, struct item* item_data * @param exp EXP value gained/loss * @param type SP_BASEEXP, SP_JOBEXP * @param quest False:Normal EXP; True:Quest EXP (displayed in purple color) - * @param lost True:if lossing EXP + * @param lost True:if losing EXP */ -void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool quest, bool lost) +void clif_displayexp(struct map_session_data *sd, t_exp exp, char type, bool quest, bool lost) { int fd; int offset; @@ -18188,10 +18198,10 @@ void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, b WFIFOW(fd,0) = cmd; WFIFOL(fd,2) = sd->bl.id; #if PACKETVER >= 20170830 - WFIFOQ(fd,6) = (int64)u64min((uint64)exp, INT_MAX) * (lost ? -1 : 1); + WFIFOQ(fd,6) = client_exp(exp) * (lost ? -1 : 1); offset = 4; #else - WFIFOL(fd,6) = (int)umin(exp, INT_MAX) * (lost ? -1 : 1); + WFIFOL(fd,6) = client_exp(exp) * (lost ? -1 : 1); offset = 0; #endif WFIFOW(fd,10+offset) = type; diff --git a/src/map/clif.hpp b/src/map/clif.hpp index f50e83b3d1..8ea64f5c68 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -932,7 +932,7 @@ void clif_quest_delete(struct map_session_data * sd, int quest_id); void clif_quest_update_status(struct map_session_data * sd, int quest_id, bool active); void clif_quest_update_objective(struct map_session_data * sd, struct quest * qd); void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, e_questinfo_types effect, e_questinfo_markcolor color); -void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool quest, bool lost); +void clif_displayexp(struct map_session_data *sd, t_exp exp, char type, bool quest, bool lost); int clif_send(const void* buf, int len, struct block_list* bl, enum send_target type); void do_init_clif(void); diff --git a/src/map/guild.cpp b/src/map/guild.cpp index cd478eb167..0e50769291 100644 --- a/src/map/guild.cpp +++ b/src/map/guild.cpp @@ -51,7 +51,7 @@ struct eventlist { //Guild EXP cache struct guild_expcache { int guild_id, account_id, char_id; - uint64 exp; + t_exp exp; }; static struct eri *expcache_ers; //For handling of guild exp payment. @@ -402,10 +402,7 @@ int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) { return 0; } - if (g->member[i].exp > UINT64_MAX - c->exp) - g->member[i].exp = UINT64_MAX; - else - g->member[i].exp+= c->exp; + g->member[i].exp = util::safe_addition_cap(g->member[i].exp, c->exp, MAX_GUILD_EXP); intif_guild_change_memberinfo(g->guild_id,c->account_id,c->char_id, GMI_EXP,&g->member[i].exp,sizeof(g->member[i].exp)); @@ -1384,7 +1381,7 @@ static DBData create_expcache(DBKey key, va_list args) { /*==================================================== * Return taxed experience from player sd to guild *---------------------------------------------------*/ -unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) { +t_exp guild_payexp(struct map_session_data *sd,t_exp exp) { struct guild *g; struct guild_expcache *c; int per; @@ -1405,11 +1402,7 @@ unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) { //Otherwise tax everything. c = (struct guild_expcache *)db_data2ptr(guild_expcache_db->ensure(guild_expcache_db, db_i2key(sd->status.char_id), create_expcache, sd)); - - if (c->exp > UINT64_MAX - exp) - c->exp = UINT64_MAX; - else - c->exp += exp; + c->exp = util::safe_addition_cap(c->exp, exp, MAX_GUILD_EXP); return exp; } @@ -1419,7 +1412,7 @@ unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) { * Add this experience to guild exp * [Celest] *---------------------------------------------------*/ -int guild_getexp(struct map_session_data *sd,int exp) { +t_exp guild_getexp(struct map_session_data *sd,t_exp exp) { struct guild_expcache *c; nullpo_ret(sd); @@ -1427,10 +1420,8 @@ int guild_getexp(struct map_session_data *sd,int exp) { return 0; c = (struct guild_expcache *)db_data2ptr(guild_expcache_db->ensure(guild_expcache_db, db_i2key(sd->status.char_id), create_expcache, sd)); - if (c->exp > UINT64_MAX - exp) - c->exp = UINT64_MAX; - else - c->exp += exp; + c->exp = util::safe_addition_cap(c->exp, exp, MAX_GUILD_EXP); + return exp; } diff --git a/src/map/guild.hpp b/src/map/guild.hpp index 37e4530f3c..d4f2371e97 100644 --- a/src/map/guild.hpp +++ b/src/map/guild.hpp @@ -44,8 +44,8 @@ struct guild_castle* guild_mapindex2gc(short mapindex); struct map_session_data *guild_getavailablesd(struct guild *g); int guild_getindex(struct guild *g,uint32 account_id,uint32 char_id); int guild_getposition(struct map_session_data *sd); -unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp); -int guild_getexp(struct map_session_data *sd,int exp); // [Celest] +t_exp guild_payexp(struct map_session_data *sd,t_exp exp); +t_exp guild_getexp(struct map_session_data *sd,t_exp exp); // [Celest] int guild_create(struct map_session_data *sd, const char *name); int guild_created(uint32 account_id,int guild_id); diff --git a/src/map/map.hpp b/src/map/map.hpp index 2e49a0ccec..1d39a46b70 100644 --- a/src/map/map.hpp +++ b/src/map/map.hpp @@ -51,7 +51,7 @@ void map_msg_reload(void); #define NATURAL_HEAL_INTERVAL 500 #define MIN_FLOORITEM 2 #define MAX_FLOORITEM START_ACCOUNT_NUM -#define MAX_LEVEL 175 +#define MAX_LEVEL 200 #define MAX_DROP_PER_MAP 48 #define MAX_IGNORE_LIST 20 // official is 14 #define MAX_VENDING 12 diff --git a/src/map/pc.cpp b/src/map/pc.cpp index 66926eea87..14c4481975 100755 --- a/src/map/pc.cpp +++ b/src/map/pc.cpp @@ -65,8 +65,6 @@ int pc_split_atoui(char* str, unsigned int* val, char sep, int max); static inline bool pc_attendance_rewarded_today( struct map_session_data* sd ); #define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval -#define MAX_LEVEL_BASE_EXP 99999999 ///< Max Base EXP for player on Max Base Level -#define MAX_LEVEL_JOB_EXP 999999999 ///< Max Job EXP for player on Max Job Level static unsigned int statp[MAX_LEVEL+1]; #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) @@ -1227,7 +1225,7 @@ enum adopt_responses pc_try_adopt(struct map_session_data *p1_sd, struct map_ses bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd) { int job, joblevel; - unsigned int jobexp; + t_exp jobexp; if( pc_try_adopt(p1_sd, p2_sd, b_sd) != ADOPT_ALLOWED ) return false; @@ -7041,7 +7039,7 @@ int pc_follow(struct map_session_data *sd,int target_id) } int pc_checkbaselevelup(struct map_session_data *sd) { - unsigned int next = pc_nextbaseexp(sd); + t_exp next = pc_nextbaseexp(sd); if (!next || sd->status.base_exp < next || pc_is_maxbaselv(sd)) return 0; @@ -7052,12 +7050,10 @@ int pc_checkbaselevelup(struct map_session_data *sd) { if( ( !battle_config.multi_level_up || ( battle_config.multi_level_up_base > 0 && sd->status.base_level >= battle_config.multi_level_up_base ) ) && sd->status.base_exp > next-1 ) sd->status.base_exp = next-1; - next = pc_gets_status_point(sd->status.base_level); - sd->status.base_level++; - sd->status.status_point += next; + sd->status.status_point += pc_gets_status_point(sd->status.base_level++); if( pc_is_maxbaselv(sd) ){ - sd->status.base_exp = u32min(sd->status.base_exp,MAX_LEVEL_BASE_EXP); + sd->status.base_exp = u64min(sd->status.base_exp,MAX_LEVEL_BASE_EXP); break; } } while ((next=pc_nextbaseexp(sd)) > 0 && sd->status.base_exp >= next); @@ -7109,7 +7105,7 @@ void pc_baselevelchanged(struct map_session_data *sd) { int pc_checkjoblevelup(struct map_session_data *sd) { - unsigned int next = pc_nextjobexp(sd); + t_exp next = pc_nextjobexp(sd); nullpo_ret(sd); if(!next || sd->status.job_exp < next || pc_is_maxjoblv(sd)) @@ -7125,7 +7121,7 @@ int pc_checkjoblevelup(struct map_session_data *sd) sd->status.skill_point ++; if( pc_is_maxjoblv(sd) ){ - sd->status.job_exp = u32min(sd->status.job_exp,MAX_LEVEL_JOB_EXP); + sd->status.job_exp = u64min(sd->status.job_exp,MAX_LEVEL_JOB_EXP); break; } } while ((next=pc_nextjobexp(sd)) > 0 && sd->status.job_exp >= next); @@ -7152,7 +7148,7 @@ int pc_checkjoblevelup(struct map_session_data *sd) * @param job_exp Job EXP before peronal bonuses * @param src Block list that affecting the exp calculation */ -static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src) +static void pc_calcexp(struct map_session_data *sd, t_exp *base_exp, t_exp *job_exp, struct block_list *src) { int bonus = 0, vip_bonus_base = 0, vip_bonus_job = 0; @@ -7186,8 +7182,8 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi } if (*base_exp) { - unsigned int exp = (unsigned int)(*base_exp + (double)*base_exp * (bonus + vip_bonus_base)/100.); - *base_exp = cap_value(exp, 1, UINT_MAX); + t_exp exp = (t_exp)(*base_exp + ((double)*base_exp * ((bonus + vip_bonus_base) / 100.))); + *base_exp = cap_value(exp, 1, MAX_EXP); } // Give JEXPBOOST for quests even if src is NULL. @@ -7195,8 +7191,8 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi bonus += sd->sc.data[SC_JEXPBOOST]->val1; if (*job_exp) { - unsigned int exp = (unsigned int)(*job_exp + (double)*job_exp * (bonus + vip_bonus_job)/100.); - *job_exp = cap_value(exp, 1, UINT_MAX); + t_exp exp = (t_exp)(*job_exp + ((double)*job_exp * ((bonus + vip_bonus_job) / 100.))); + *job_exp = cap_value(exp, 1, MAX_EXP); } return; @@ -7211,7 +7207,7 @@ static void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsi * @param next_job_exp Job EXP needed for next job level * @param lost True:EXP penalty, lose EXP **/ -void pc_gainexp_disp(struct map_session_data *sd, unsigned int base_exp, unsigned int next_base_exp, unsigned int job_exp, unsigned int next_job_exp, bool lost) { +void pc_gainexp_disp(struct map_session_data *sd, t_exp base_exp, t_exp next_base_exp, t_exp job_exp, t_exp next_job_exp, bool lost) { char output[CHAT_SIZE_MAX]; nullpo_retv(sd); @@ -7232,9 +7228,9 @@ void pc_gainexp_disp(struct map_session_data *sd, unsigned int base_exp, unsigne * @param exp_flag 1: Quest EXP; 2: Param Exp (Ignore Guild EXP tax, EXP adjustments) * @return **/ -void pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, uint8 exp_flag) +void pc_gainexp(struct map_session_data *sd, struct block_list *src, t_exp base_exp, t_exp job_exp, uint8 exp_flag) { - unsigned int nextb = 0, nextj = 0; + t_exp nextb = 0, nextj = 0; uint8 flag = 0; ///< 1: Base EXP given, 2: Job EXP given, 4: Max Base level, 8: Max Job Level nullpo_retv(sd); @@ -7292,20 +7288,16 @@ void pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in // Give EXP for Base Level if (base_exp) { - if ((uint64)sd->status.base_exp + base_exp > UINT32_MAX) - sd->status.base_exp = UINT32_MAX; - else - sd->status.base_exp += base_exp; + sd->status.base_exp = util::safe_addition_cap(sd->status.base_exp, base_exp, MAX_EXP); + if (!pc_checkbaselevelup(sd)) clif_updatestatus(sd,SP_BASEEXP); } // Give EXP for Job Level if (job_exp) { - if ((uint64)sd->status.job_exp + job_exp > UINT32_MAX) - sd->status.job_exp = UINT32_MAX; - else - sd->status.job_exp += job_exp; + sd->status.job_exp = util::safe_addition_cap(sd->status.job_exp, job_exp, MAX_EXP); + if (!pc_checkjoblevelup(sd)) clif_updatestatus(sd,SP_JOBEXP); } @@ -7325,19 +7317,19 @@ void pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in * @param base_exp Base EXP lost * @param job_exp Job EXP lost **/ -void pc_lostexp(struct map_session_data *sd, unsigned int base_exp, unsigned int job_exp) { +void pc_lostexp(struct map_session_data *sd, t_exp base_exp, t_exp job_exp) { nullpo_retv(sd); if (base_exp) { - base_exp = u32min(sd->status.base_exp, base_exp); + base_exp = u64min(sd->status.base_exp, base_exp); sd->status.base_exp -= base_exp; clif_displayexp(sd, base_exp, SP_BASEEXP, false, true); clif_updatestatus(sd, SP_BASEEXP); } if (job_exp) { - job_exp = u32min(sd->status.job_exp, job_exp); + job_exp = u64min(sd->status.job_exp, job_exp); sd->status.job_exp -= job_exp; clif_displayexp(sd, job_exp, SP_JOBEXP, false, true); clif_updatestatus(sd, SP_JOBEXP); @@ -7408,7 +7400,7 @@ bool pc_is_maxjoblv(struct map_session_data *sd) { * @param sd * @return Base EXP needed for next base level **/ -unsigned int pc_nextbaseexp(struct map_session_data *sd){ +t_exp pc_nextbaseexp(struct map_session_data *sd){ nullpo_ret(sd); if (sd->status.base_level == 0) // Is this something that possible? return 0; @@ -7422,7 +7414,7 @@ unsigned int pc_nextbaseexp(struct map_session_data *sd){ * @param sd * @return Job EXP needed for next job level **/ -unsigned int pc_nextjobexp(struct map_session_data *sd){ +t_exp pc_nextjobexp(struct map_session_data *sd){ nullpo_ret(sd); if (sd->status.job_level == 0) // Is this something that possible? return 0; @@ -8244,9 +8236,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) // Activate Steel body if a super novice dies at 99+% exp [celest] // Super Novices have no kill or die functions attached when saved by their angel if (!sd->state.snovice_dead_flag && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) { - unsigned int exp = pc_nextbaseexp(sd); + t_exp exp = pc_nextbaseexp(sd); - if( exp && get_percentage(sd->status.base_exp,exp) >= 99 ) { + if( exp && get_percentage_exp(sd->status.base_exp, exp) >= 99 ) { sd->state.snovice_dead_flag = 1; pc_setrestartvalue(sd,1); status_percent_heal(&sd->bl, 100, 100); @@ -8447,8 +8439,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_LIFEINSURANCE] && !mapdata->flag[MF_NOEXPPENALTY] && !mapdata_flag_gvg2(mapdata)) { - uint32 base_penalty = 0; - uint32 job_penalty = 0; + t_exp base_penalty = 0; + t_exp job_penalty = 0; uint32 zeny_penalty = 0; if (pc_isvip(sd)) { // EXP penalty for VIP @@ -8463,13 +8455,13 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if ((battle_config.death_penalty_maxlv&1 || !pc_is_maxbaselv(sd)) && base_penalty > 0) { switch (battle_config.death_penalty_type) { - case 1: base_penalty = (uint32) ( pc_nextbaseexp(sd) * ( base_penalty / 10000. ) ); break; - case 2: base_penalty = (uint32) ( sd->status.base_exp * ( base_penalty / 10000. ) ); break; + case 1: base_penalty = (t_exp) ( pc_nextbaseexp(sd) * ( base_penalty / 10000. ) ); break; + case 2: base_penalty = (t_exp) ( sd->status.base_exp * ( base_penalty / 10000. ) ); break; } if (base_penalty){ //recheck after altering to speedup if (battle_config.pk_mode && src && src->type==BL_PC) base_penalty *= 2; - base_penalty = u32min(sd->status.base_exp, base_penalty); + base_penalty = u64min(sd->status.base_exp, base_penalty); } } else @@ -8483,7 +8475,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if (job_penalty) { if (battle_config.pk_mode && src && src->type==BL_PC) job_penalty *= 2; - job_penalty = u32min(sd->status.job_exp, job_penalty); + job_penalty = u64min(sd->status.job_exp, job_penalty); } } else @@ -8658,10 +8650,10 @@ int64 pc_readparam(struct map_session_data* sd,int64 type) case SP_SEX: val = sd->status.sex; break; case SP_WEIGHT: val = sd->weight; break; case SP_MAXWEIGHT: val = sd->max_weight; break; - case SP_BASEEXP: val = sd->status.base_exp; break; - case SP_JOBEXP: val = sd->status.job_exp; break; - case SP_NEXTBASEEXP: val = pc_nextbaseexp(sd); break; - case SP_NEXTJOBEXP: val = pc_nextjobexp(sd); break; + case SP_BASEEXP: val = u64min(sd->status.base_exp, MAX_EXP); break; + case SP_JOBEXP: val = u64min(sd->status.job_exp, MAX_EXP); break; + case SP_NEXTBASEEXP: val = u64min(pc_nextbaseexp(sd), MAX_EXP); break; + case SP_NEXTJOBEXP: val = u64min(pc_nextjobexp(sd), MAX_EXP); break; case SP_HP: val = sd->battle_status.hp; break; case SP_MAXHP: val = sd->battle_status.max_hp; break; case SP_SP: val = sd->battle_status.sp; break; @@ -8866,22 +8858,18 @@ bool pc_setparam(struct map_session_data *sd,int64 type,int64 val_tmp) sd->status.zeny = cap_value(val, 0, MAX_ZENY); break; case SP_BASEEXP: - { - val = cap_value(val, 0, INT_MAX); - if (val < sd->status.base_exp) // Lost - pc_lostexp(sd, sd->status.base_exp - val, 0); - else // Gained - pc_gainexp(sd, NULL, val - sd->status.base_exp, 0, 2); - } + val_tmp = cap_value(val_tmp, 0, pc_is_maxbaselv(sd) ? MAX_LEVEL_BASE_EXP : MAX_EXP); + if (val_tmp < sd->status.base_exp) // Lost + pc_lostexp(sd, sd->status.base_exp - val_tmp, 0); + else // Gained + pc_gainexp(sd, NULL, val_tmp - sd->status.base_exp, 0, 2); return true; case SP_JOBEXP: - { - val = cap_value(val, 0, INT_MAX); - if (val < sd->status.job_exp) // Lost - pc_lostexp(sd, 0, sd->status.job_exp - val); - else // Gained - pc_gainexp(sd, NULL, 0, val - sd->status.job_exp, 2); - } + val_tmp = cap_value(val_tmp, 0, pc_is_maxjoblv(sd) ? MAX_LEVEL_JOB_EXP : MAX_EXP); + if (val_tmp < sd->status.job_exp) // Lost + pc_lostexp(sd, 0, sd->status.job_exp - val_tmp); + else // Gained + pc_gainexp(sd, NULL, 0, val_tmp - sd->status.job_exp, 2); return true; case SP_SEX: sd->status.sex = val ? SEX_MALE : SEX_FEMALE; @@ -12035,8 +12023,19 @@ static bool pc_readdb_job_exp(char* fields[], int columns, int current) idx = pc_class2idx(job_id); job_info[idx].max_level[type] = maxlvl; - for(i=0; i MAX_EXP ){ + ShowWarning( "pc_readdb_job_exp: Value %" PRIu64 " is too high, capping to %" PRIu64 "...\n", exp, MAX_EXP ); + exp = MAX_EXP; + } + + job_info[idx].exp_table[type][i] = exp; + } //Reverse check in case the array has a bunch of trailing zeros... [Skotlex] //The reasoning behind the -2 is this... if the max level is 5, then the array //should look like this: diff --git a/src/map/pc.hpp b/src/map/pc.hpp index fe05b221cd..68e1bafacc 100644 --- a/src/map/pc.hpp +++ b/src/map/pc.hpp @@ -894,7 +894,7 @@ struct s_job_info { #else int aspd_base[MAX_WEAPON_TYPE]; //[blackhole89] #endif - uint32 exp_table[2][MAX_LEVEL]; + t_exp exp_table[2][MAX_LEVEL]; uint32 max_level[2]; struct s_params { uint16 str, agi, vit, int_, dex, luk; @@ -1201,11 +1201,11 @@ bool pc_is_maxbaselv(struct map_session_data *sd); bool pc_is_maxjoblv(struct map_session_data *sd); int pc_checkbaselevelup(struct map_session_data *sd); int pc_checkjoblevelup(struct map_session_data *sd); -void pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int base_exp, unsigned int job_exp, uint8 exp_flag); -void pc_gainexp_disp(struct map_session_data *sd, unsigned int base_exp, unsigned int next_base_exp, unsigned int job_exp, unsigned int next_job_exp, bool lost); -void pc_lostexp(struct map_session_data *sd, unsigned int base_exp, unsigned int job_exp); -unsigned int pc_nextbaseexp(struct map_session_data *sd); -unsigned int pc_nextjobexp(struct map_session_data *sd); +void pc_gainexp(struct map_session_data *sd, struct block_list *src, t_exp base_exp, t_exp job_exp, uint8 exp_flag); +void pc_gainexp_disp(struct map_session_data *sd, t_exp base_exp, t_exp next_base_exp, t_exp job_exp, t_exp next_job_exp, bool lost); +void pc_lostexp(struct map_session_data *sd, t_exp base_exp, t_exp job_exp); +t_exp pc_nextbaseexp(struct map_session_data *sd); +t_exp pc_nextjobexp(struct map_session_data *sd); int pc_gets_status_point(int); int pc_need_status_point(struct map_session_data *,int,int); int pc_maxparameterincrease(struct map_session_data*,int); diff --git a/src/map/skill.cpp b/src/map/skill.cpp index cfa8f192d6..4c5239891a 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -6633,7 +6633,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui skill_area_temp[0] = battle_config.exp_cost_redemptio_limit - skill_area_temp[0]; // The actual penalty... if (skill_area_temp[0] > 0 && !map_getmapflag(src->m, MF_NOEXPPENALTY) && battle_config.exp_cost_redemptio) { //Apply penalty //If total penalty is 1% => reduced 0.2% penalty per each revived player - pc_lostexp(sd, u32min(sd->status.base_exp, (pc_nextbaseexp(sd) * skill_area_temp[0] * battle_config.exp_cost_redemptio / battle_config.exp_cost_redemptio_limit) / 100), 0); + pc_lostexp(sd, u64min(sd->status.base_exp, (pc_nextbaseexp(sd) * skill_area_temp[0] * battle_config.exp_cost_redemptio / battle_config.exp_cost_redemptio_limit) / 100), 0); } status_set_hp(src, 1, 0); status_set_sp(src, 0, 0); @@ -6675,14 +6675,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui clif_skill_nodamage(src,bl,ALL_RESURRECTION,skill_lv,1); //Both Redemptio and Res show this skill-animation. if(sd && dstsd && battle_config.resurrection_exp > 0) { - int exp = 0,jexp = 0; + t_exp exp = 0,jexp = 0; int lv = dstsd->status.base_level - sd->status.base_level, jlv = dstsd->status.job_level - sd->status.job_level; if(lv > 0 && pc_nextbaseexp(dstsd)) { - exp = (int)((double)dstsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); + exp = (t_exp)(dstsd->status.base_exp * lv * battle_config.resurrection_exp / 1000000.); if (exp < 1) exp = 1; } if(jlv > 0 && pc_nextjobexp(dstsd)) { - jexp = (int)((double)dstsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); + jexp = (t_exp)(dstsd->status.job_exp * lv * battle_config.resurrection_exp / 1000000.); if (jexp < 1) jexp = 1; } if(exp > 0 || jexp > 0) @@ -10525,7 +10525,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case LG_INSPIRATION: if( sd && !map_getmapflag(sd->bl.m, MF_NOEXPPENALTY) && battle_config.exp_cost_inspiration ) - pc_lostexp(sd, u32min(sd->status.base_exp, pc_nextbaseexp(sd) * battle_config.exp_cost_inspiration / 100), 0); // 1% penalty. + pc_lostexp(sd, u64min(sd->status.base_exp, pc_nextbaseexp(sd) * battle_config.exp_cost_inspiration / 100), 0); // 1% penalty. clif_skill_nodamage(bl,src,skill_id,skill_lv, sc_start(src,bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv))); break; case SR_CURSEDCIRCLE: @@ -15809,7 +15809,8 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i case PR_REDEMPTIO: case LG_INSPIRATION: { - unsigned int exp, exp_needp = 0; + t_exp exp; + uint32 exp_needp; switch (skill_id) { case PR_REDEMPTIO: exp_needp = battle_config.exp_cost_redemptio; @@ -15818,7 +15819,7 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i exp_needp = battle_config.exp_cost_inspiration; break; } - if (exp_needp && ((exp = pc_nextbaseexp(sd)) > 0 && get_percentage(sd->status.base_exp, exp) < exp_needp)) { + if (exp_needp && ((exp = pc_nextbaseexp(sd)) > 0 && get_percentage_exp(sd->status.base_exp, exp) < exp_needp)) { clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); //Not enough exp. return false; }