|
@@ -42,12 +42,12 @@
|
|
|
|
|
|
|
|
|
#define PVP_CALCRANK_INTERVAL 1000 // PVP�‡ˆÊŒvŽZ‚ÌŠÔŠu
|
|
|
-static unsigned int exp_table[MAX_PC_CLASS][2][MAX_LEVEL];
|
|
|
-static unsigned int max_level[MAX_PC_CLASS][2];
|
|
|
+static unsigned int exp_table[CLASS_COUNT][2][MAX_LEVEL];
|
|
|
+static unsigned int max_level[CLASS_COUNT][2];
|
|
|
static short statp[MAX_LEVEL+1];
|
|
|
|
|
|
// h-files are for declarations, not for implementations... [Shinomori]
|
|
|
-struct skill_tree_entry skill_tree[MAX_PC_CLASS][MAX_SKILL_TREE];
|
|
|
+struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE];
|
|
|
// timer for night.day implementation
|
|
|
int day_timer_tid;
|
|
|
int night_timer_tid;
|
|
@@ -67,6 +67,15 @@ char motd_text[MOTD_LINE_SIZE][256]; // Message of the day buffer [Valaris]
|
|
|
static const char feel_var[3][NAME_LENGTH] = {"PC_FEEL_SUN","PC_FEEL_MOON","PC_FEEL_STAR"};
|
|
|
static const char hate_var[3][NAME_LENGTH] = {"PC_HATE_MOB_SUN","PC_HATE_MOB_MOON","PC_HATE_MOB_STAR"};
|
|
|
|
|
|
+//Converts a class to its array index for CLASS_COUNT defined arrays.
|
|
|
+//Note that it does not do a validity check for speed purposes, where parsing
|
|
|
+//player input make sure to use a pcdb_checkid first!
|
|
|
+int pc_class2idx(int class_) {
|
|
|
+ if (class_ >= JOB_NOVICE_HIGH)
|
|
|
+ return class_- JOB_NOVICE_HIGH+JOB_MAX_BASIC;
|
|
|
+ return class_;
|
|
|
+}
|
|
|
+
|
|
|
int pc_isGM(struct map_session_data* sd)
|
|
|
{
|
|
|
int i;
|
|
@@ -934,7 +943,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
|
|
|
ShowError("pc_calc_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id);
|
|
|
return 1;
|
|
|
}
|
|
|
-
|
|
|
+ c = pc_class2idx(c);
|
|
|
for(i=0;i<MAX_SKILL;i++){
|
|
|
if (sd->status.skill[i].flag != 13) //Don't touch plagiarized skills
|
|
|
sd->status.skill[i].id=0; //First clear skills.
|
|
@@ -1054,7 +1063,7 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill)
|
|
|
ShowError("pc_check_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id);
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
+ c = pc_class2idx(c);
|
|
|
do {
|
|
|
flag=0;
|
|
|
for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0;i++){
|
|
@@ -3008,7 +3017,7 @@ int pc_isUseitem(struct map_session_data *sd,int n)
|
|
|
if(item == NULL)
|
|
|
return 0;
|
|
|
//Not consumable item
|
|
|
- if(item->type != 0 && item->type != 2)
|
|
|
+ if(item->type != IT_HEALING && item->type != IT_USABLE)
|
|
|
return 0;
|
|
|
if(!item->script) //if it has no script, you can't really consume it!
|
|
|
return 0;
|
|
@@ -3106,6 +3115,9 @@ int pc_useitem(struct map_session_data *sd,int n)
|
|
|
|
|
|
sd->itemid = sd->status.inventory[n].nameid;
|
|
|
sd->itemindex = n;
|
|
|
+ if(sd->catch_target_class != -1) //Abort pet catching.
|
|
|
+ sd->catch_target_class = -1;
|
|
|
+
|
|
|
amount = sd->status.inventory[n].amount;
|
|
|
script = sd->inventory_data[n]->script;
|
|
|
//Check if the item is to be consumed immediately [Skotlex]
|
|
@@ -4313,12 +4325,12 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int
|
|
|
*------------------------------------------*/
|
|
|
unsigned int pc_maxbaselv(struct map_session_data *sd)
|
|
|
{
|
|
|
- return max_level[sd->status.class_][0];
|
|
|
+ return max_level[pc_class2idx(sd->status.class_)][0];
|
|
|
};
|
|
|
|
|
|
unsigned int pc_maxjoblv(struct map_session_data *sd)
|
|
|
{
|
|
|
- return max_level[sd->status.class_][1];
|
|
|
+ return max_level[pc_class2idx(sd->status.class_)][1];
|
|
|
};
|
|
|
|
|
|
/*==========================================
|
|
@@ -4331,7 +4343,7 @@ unsigned int pc_nextbaseexp(struct map_session_data *sd)
|
|
|
if(sd->status.base_level>=pc_maxbaselv(sd) || sd->status.base_level<=0)
|
|
|
return 0;
|
|
|
|
|
|
- return exp_table[sd->status.class_][0][sd->status.base_level-1];
|
|
|
+ return exp_table[pc_class2idx(sd->status.class_)][0][sd->status.base_level-1];
|
|
|
}
|
|
|
|
|
|
/*==========================================
|
|
@@ -4343,7 +4355,7 @@ unsigned int pc_nextjobexp(struct map_session_data *sd)
|
|
|
|
|
|
if(sd->status.job_level>=pc_maxjoblv(sd) || sd->status.job_level<=0)
|
|
|
return 0;
|
|
|
- return exp_table[sd->status.class_][1][sd->status.job_level-1];
|
|
|
+ return exp_table[pc_class2idx(sd->status.class_)][1][sd->status.job_level-1];
|
|
|
}
|
|
|
|
|
|
/*==========================================
|
|
@@ -4584,7 +4596,7 @@ int pc_allskillup(struct map_session_data *sd)
|
|
|
else
|
|
|
{
|
|
|
int inf2;
|
|
|
- for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[sd->status.class_][i].id)>0;i++){
|
|
|
+ for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[pc_class2idx(sd->status.class_)][i].id)>0;i++){
|
|
|
inf2 = skill_get_inf2(id);
|
|
|
if (
|
|
|
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
|
|
@@ -7330,7 +7342,7 @@ int pc_readdb(void)
|
|
|
}
|
|
|
while(fgets(line, sizeof(line), fp))
|
|
|
{
|
|
|
- int jobs[MAX_PC_CLASS], job_count, job;
|
|
|
+ int jobs[CLASS_COUNT], job_count, job, job_id;
|
|
|
int type;
|
|
|
unsigned int ui,maxlv;
|
|
|
char *split[4];
|
|
@@ -7339,12 +7351,12 @@ int pc_readdb(void)
|
|
|
if (pc_split_str(line,split,4) < 4)
|
|
|
continue;
|
|
|
|
|
|
- job_count = pc_split_atoi(split[1],jobs,':',MAX_PC_CLASS);
|
|
|
+ job_count = pc_split_atoi(split[1],jobs,':',CLASS_COUNT);
|
|
|
if (job_count < 1)
|
|
|
continue;
|
|
|
- job = jobs[0];
|
|
|
- if (!pcdb_checkid(job)) {
|
|
|
- ShowError("pc_readdb: Invalid job ID %d.\n", job);
|
|
|
+ job_id = jobs[0];
|
|
|
+ if (!pcdb_checkid(job_id)) {
|
|
|
+ ShowError("pc_readdb: Invalid job ID %d.\n", job_id);
|
|
|
continue;
|
|
|
}
|
|
|
type = atoi(split[2]);
|
|
@@ -7354,9 +7366,11 @@ int pc_readdb(void)
|
|
|
}
|
|
|
maxlv = atoi(split[0]);
|
|
|
if (maxlv > MAX_LEVEL) {
|
|
|
- ShowWarning("pc_readdb: Specified max level %u for job %d is beyond server's limit (%u).\n ", maxlv, job, MAX_LEVEL);
|
|
|
+ ShowWarning("pc_readdb: Specified max level %u for job %d is beyond server's limit (%u).\n ", maxlv, job_id, MAX_LEVEL);
|
|
|
maxlv = MAX_LEVEL;
|
|
|
}
|
|
|
+
|
|
|
+ job = jobs[0] = pc_class2idx(job_id);
|
|
|
//We send one less and then one more because the last entry in the exp array should hold 0.
|
|
|
max_level[job][type] = pc_split_atoui(split[3], exp_table[job][type],',',maxlv-1)+1;
|
|
|
//Reverse check in case the array has a bunch of trailing zeros... [Skotlex]
|
|
@@ -7366,7 +7380,7 @@ int pc_readdb(void)
|
|
|
while ((ui = max_level[job][type]) >= 2 && exp_table[job][type][ui-2] <= 0)
|
|
|
max_level[job][type]--;
|
|
|
if (max_level[job][type] < maxlv) {
|
|
|
- ShowWarning("pc_readdb: Specified max %u for job %d, but that job's exp table only goes up to level %u.\n", maxlv, job, max_level[job][type]);
|
|
|
+ ShowWarning("pc_readdb: Specified max %u for job %d, but that job's exp table only goes up to level %u.\n", maxlv, job_id, max_level[job][type]);
|
|
|
ShowInfo("Filling the missing values with the last exp entry.\n");
|
|
|
//Fill the requested values with the last entry.
|
|
|
ui = (max_level[job][type] <= 2? 0: max_level[job][type]-2);
|
|
@@ -7374,26 +7388,28 @@ int pc_readdb(void)
|
|
|
exp_table[job][type][ui] = exp_table[job][type][ui-1];
|
|
|
max_level[job][type] = maxlv;
|
|
|
}
|
|
|
-// ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job, max_level[job][type]);
|
|
|
+// ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job_id, max_level[job][type]);
|
|
|
for (i = 1; i < job_count; i++) {
|
|
|
- job = jobs[i];
|
|
|
- if (!pcdb_checkid(job)) {
|
|
|
- ShowError("pc_readdb: Invalid job ID %d.\n", job);
|
|
|
+ job_id = jobs[i];
|
|
|
+ if (!pcdb_checkid(job_id)) {
|
|
|
+ ShowError("pc_readdb: Invalid job ID %d.\n", job_id);
|
|
|
continue;
|
|
|
}
|
|
|
+ job = pc_class2idx(job_id);
|
|
|
memcpy(exp_table[job][type], exp_table[jobs[0]][type], sizeof(exp_table[0][0]));
|
|
|
max_level[job][type] = maxlv;
|
|
|
-// ShowDebug("%s - Class %d: %u\n", type?"Job":"Base", job, max_level[job][type]);
|
|
|
+// ShowDebug("%s - Class %d: %u\n", type?"Job":"Base", job_id, max_level[job][type]);
|
|
|
}
|
|
|
}
|
|
|
fclose(fp);
|
|
|
- for (i = 0; i < MAX_PC_CLASS; i++) {
|
|
|
+ for (i = 0; i < JOB_MAX; i++) {
|
|
|
if (!pcdb_checkid(i)) continue;
|
|
|
if (i == JOB_WEDDING || i == JOB_XMAS || i == JOB_SUMMER)
|
|
|
continue; //Classes that do not need exp tables.
|
|
|
- if (!max_level[i][0])
|
|
|
+ j = pc_class2idx(i);
|
|
|
+ if (!max_level[j][0])
|
|
|
ShowWarning("Class %s (%d) does not has a base exp table.\n", job_name(i), i);
|
|
|
- if (!max_level[i][1])
|
|
|
+ if (!max_level[j][1])
|
|
|
ShowWarning("Class %s (%d) does not has a job exp table.\n", job_name(i), i);
|
|
|
}
|
|
|
ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","exp.txt");
|
|
@@ -7410,7 +7426,7 @@ int pc_readdb(void)
|
|
|
while(fgets(line, sizeof(line), fp))
|
|
|
{
|
|
|
char *split[50];
|
|
|
- int f=0, m=3;
|
|
|
+ int f=0, m=3, idx;
|
|
|
if(line[0]=='/' && line[1]=='/')
|
|
|
continue;
|
|
|
for(j=0,p=line;j<14 && p;j++){
|
|
@@ -7425,22 +7441,24 @@ int pc_readdb(void)
|
|
|
m++;
|
|
|
}
|
|
|
// check for bounds [celest]
|
|
|
- if (atoi(split[0]) >= MAX_PC_CLASS)
|
|
|
+ idx = atoi(split[0]);
|
|
|
+ if(!pcdb_checkid(idx))
|
|
|
continue;
|
|
|
+ idx = pc_class2idx(idx);
|
|
|
k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex]
|
|
|
- for(j = 0; j < MAX_SKILL_TREE && skill_tree[atoi(split[0])][j].id && skill_tree[atoi(split[0])][j].id != k; j++);
|
|
|
+ for(j = 0; j < MAX_SKILL_TREE && skill_tree[idx][j].id && skill_tree[idx][j].id != k; j++);
|
|
|
if (j == MAX_SKILL_TREE)
|
|
|
{
|
|
|
ShowWarning("Unable to load skill %d into job %d's tree. Maximum number of skills per class has been reached.\n", k, atoi(split[0]));
|
|
|
continue;
|
|
|
}
|
|
|
- skill_tree[atoi(split[0])][j].id=k;
|
|
|
- skill_tree[atoi(split[0])][j].max=atoi(split[2]);
|
|
|
- if (f) skill_tree[atoi(split[0])][j].joblv=atoi(split[3]);
|
|
|
+ skill_tree[idx][j].id=k;
|
|
|
+ skill_tree[idx][j].max=atoi(split[2]);
|
|
|
+ if (f) skill_tree[idx][j].joblv=atoi(split[3]);
|
|
|
|
|
|
for(k=0;k<5;k++){
|
|
|
- skill_tree[atoi(split[0])][j].need[k].id=atoi(split[k*2+m]);
|
|
|
- skill_tree[atoi(split[0])][j].need[k].lv=atoi(split[k*2+m+1]);
|
|
|
+ skill_tree[idx][j].need[k].id=atoi(split[k*2+m]);
|
|
|
+ skill_tree[idx][j].need[k].lv=atoi(split[k*2+m+1]);
|
|
|
}
|
|
|
}
|
|
|
fclose(fp);
|