summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-10-24 13:02:00 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2007-10-24 13:02:00 +0000
commit339ac6c105cc0548328e15adce1f94d7ecddb0bc (patch)
tree6f58fd8315d917657445a115fc0800c360c873c3
parent3ecde465534c93315a1f88430129e8400f4d9fe2 (diff)
downloadhercules-339ac6c105cc0548328e15adce1f94d7ecddb0bc.tar.gz
hercules-339ac6c105cc0548328e15adce1f94d7ecddb0bc.tar.bz2
hercules-339ac6c105cc0548328e15adce1f94d7ecddb0bc.tar.xz
hercules-339ac6c105cc0548328e15adce1f94d7ecddb0bc.zip
- added defines JOB_MAX_BASIC and JOB_MAX to mmo.h so the code can know which are the max valid classes.
- @/#jobchange no longer strip your equipment since pc_jobchange removes any unequippables already. - removed the wasteful define MAX_PC_CLASS and replaced it by the CLASS_COUNT define (which is automatically updated using the previous JOB_MAX* defines) + pc_class2idx function (which converts high class IDs into values that fit in CLASS_COUNT) - Made status_charge a function rather than a define to get rid of those warnings that have been there since forever. - Merged the CELL_NOVENDING code (see topic #129209) - Small check that disables the pet catching process if you try to use another item. - Added a check to fix a warning and prevent a crash in the npc duplicate check (even though I have no idea what this check is supposed to do, therefore I can't fix it properly other than to avoid the crash) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@11572 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r--Changelog-Trunk.txt6
-rw-r--r--src/common/mmo.h2
-rw-r--r--src/map/atcommand.c8
-rw-r--r--src/map/charcommand.c8
-rw-r--r--src/map/map.c4
-rw-r--r--src/map/map.h8
-rw-r--r--src/map/npc.c5
-rw-r--r--src/map/pc.c86
-rw-r--r--src/map/pc.h9
-rw-r--r--src/map/script.c2
-rw-r--r--src/map/status.c63
-rw-r--r--src/map/status.h2
-rw-r--r--src/map/vending.c6
13 files changed, 127 insertions, 82 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index 0890fc636..c0e733aa2 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -4,6 +4,12 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2007/10/24
+ * @/#jobchange no longer strips your equipment since pc_jobchange removes
+ any unequippables already.
+ * Removed the wasteful define MAX_PC_CLASS and replaced it by the
+ CLASS_COUNT define + pc_class2idx function. This should save a bunch of
+ memory from the map server.
+ * Merged the CELL_NOVENDING code (see topic #129209) [Skotlex]
* Increased the max. send buffer size to 5M since 1M is not enough
* Updated vs7 and vs6 project files
* Added upgrade_svn11548.sql to convert the mail table to new format
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 171c6c3de..e9f3a80a5 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -475,6 +475,7 @@ enum {
JOB_NINJA,
JOB_XMAS,
JOB_SUMMER,
+ JOB_MAX_BASIC,
JOB_NOVICE_HIGH = 4001,
JOB_SWORDMAN_HIGH,
@@ -527,6 +528,7 @@ enum {
JOB_STAR_GLADIATOR,
JOB_STAR_GLADIATOR2,
JOB_SOUL_LINKER,
+ JOB_MAX,
};
// sanity checks...
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 5ed008419..045448888 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -2175,14 +2175,8 @@ int atcommand_jobchange(const int fd, struct map_session_data* sd, const char* c
if (job == 37 ||job == 45)
return 0;
- if ((job >= 0 && job < MAX_PC_CLASS))
+ if (pcdb_checkid(job))
{
- int j;
-
- for (j=0; j < MAX_INVENTORY; j++) {
- if(sd->status.inventory[j].nameid>0 && sd->status.inventory[j].equip!=0)
- pc_unequipitem(sd, j, 3);
- }
if (pc_jobchange(sd, job, upper) == 0)
clif_displaymessage(fd, msg_txt(12)); // Your job has been changed.
else {
diff --git a/src/map/charcommand.c b/src/map/charcommand.c
index f2747e6e1..c2689b8e8 100644
--- a/src/map/charcommand.c
+++ b/src/map/charcommand.c
@@ -421,7 +421,7 @@ int charcommand_jobchange(const int fd, struct map_session_data* sd, const char*
{
char character[100];
struct map_session_data* pl_sd;
- int job = 0, upper = -1, j = 0;
+ int job = 0, upper = -1;
memset(character, '\0', sizeof(character));
@@ -462,15 +462,11 @@ int charcommand_jobchange(const int fd, struct map_session_data* sd, const char*
return -1;
}
- if (job < 0 || job > MAX_PC_CLASS) {
+ if (!pcdb_checkid(job)) {
clif_displaymessage(fd, msg_txt(49)); // Invalid job ID.
return -1;
}
- for (j=0; j < MAX_INVENTORY; j++) {
- if(pl_sd->status.inventory[j].nameid>0 && pl_sd->status.inventory[j].equip!=0)
- pc_unequipitem(pl_sd, j, 3);
- }
if (pc_jobchange(pl_sd, job, upper) != 0) {
clif_displaymessage(fd, msg_txt(192)); // Impossible to change the character's job.
return -1;
diff --git a/src/map/map.c b/src/map/map.c
index 929ee7c36..43a05810c 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -2307,6 +2307,8 @@ int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk)
return (type2&CELL_REGEN);
case CELL_CHKICEWALL:
return (type2&CELL_ICEWALL);
+ case CELL_CHKNOVENDING:
+ return (type2&CELL_NOVENDING);
default:
return 0;
}
@@ -2336,6 +2338,8 @@ void map_setcell(int m,int x,int y,int cell)
case CELL_SETLANDPROTECTOR: map[m].cell[j] |= CELL_LANDPROTECTOR; break;
case CELL_CLRLANDPROTECTOR: map[m].cell[j] &= ~CELL_LANDPROTECTOR; break;
case CELL_SETREGEN: map[m].cell[j] |= CELL_REGEN; break;
+ case CELL_SETNOVENDING: map[m].cell[j] |= CELL_NOVENDING; break;
+ case CELL_CLRNOVENDING: map[m].cell[j] &= ~CELL_NOVENDING; break;
default:
map[m].gat[j] = cell;
break;
diff --git a/src/map/map.h b/src/map/map.h
index b0f823d8e..896af5507 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -28,10 +28,6 @@
// but is not the official behaviour.
//#define CIRCULAR_AREA
-#define MAX_PC_CLASS 4050
-#define PC_CLASS_BASE 0
-#define PC_CLASS_BASE2 (PC_CLASS_BASE + 4001)
-#define PC_CLASS_BASE3 (PC_CLASS_BASE2 + 22)
#define MAX_NPC_PER_MAP 512
#define BLOCK_SIZE 8
#define AREA_SIZE battle_config.area_size
@@ -1219,6 +1215,7 @@ enum _look {
#define CELL_SAFETYWALL 0x8
#define CELL_LANDPROTECTOR 0x10
#define CELL_BASILICA 0x20
+#define CELL_NOVENDING 0x40
#define CELL_ICEWALL 0x80
/*
* map_getcell()で使用されるフラグ
@@ -1241,6 +1238,7 @@ typedef enum {
CELL_CHKLANDPROTECTOR,
CELL_CHKICEWALL,
CELL_CHKSTACK,
+ CELL_CHKNOVENDING,
} cell_t;
// map_setcell()で使用されるフラグ
enum {
@@ -1257,6 +1255,8 @@ enum {
CELL_CLRSAFETYWALL,
CELL_SETICEWALL,
CELL_CLRICEWALL,
+ CELL_SETNOVENDING,
+ CELL_CLRNOVENDING,
};
extern struct map_data map[];
diff --git a/src/map/npc.c b/src/map/npc.c
index 87ceb8afb..bbd0363e1 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1463,6 +1463,11 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
char this_mapname[32];
char other_mapname[32];
int i = 0;
+
+ //TODO: the debug message is broken, if nd->exname == NULL
+ //dnd is left uninitialized, and then is printed as that!
+ if (*nd->exname == '\0')
+ dnd = nd; //Dumb anti-crash measure since I am not sure what this piece of code is supposed to do.
do
{
++i;
diff --git a/src/map/pc.c b/src/map/pc.c
index a984796ae..ccd6955a7 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -42,12 +42,12 @@
#define PVP_CALCRANK_INTERVAL 1000 // PVP順位計算の間隔
-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);
diff --git a/src/map/pc.h b/src/map/pc.h
index 442c9e188..05368d6d5 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -7,12 +7,14 @@
#include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus
#include "../common/timer.h" // INVALID_TIMER
#include "battle.h" // battle_config
-#include "map.h" // MAX_PC_CLASS, struct map_session_data
+#include "map.h" // struct map_session_data
#include "status.h" // OPTION_*
#include "unit.h" // unit_stop_attack(), unit_stop_walking()
//Update this max as necessary. 54 is the value needed for Super Baby currently
#define MAX_SKILL_TREE 54
+//Total number of classes (for data storage)
+#define CLASS_COUNT (JOB_MAX - JOB_NOVICE_HIGH + JOB_MAX_BASIC)
enum {
W_FIST, //Bare hands
@@ -115,8 +117,9 @@ enum {
#define pc_check_weapontype(sd, type) ((type)&((sd)->status.weapon < MAX_WEAPON_TYPE? \
1<<(sd)->status.weapon:(1<<(sd)->weapontype1)|(1<<(sd)->weapontype2)))
//Checks if the given class value corresponds to a player class. [Skotlex]
-#define pcdb_checkid(class_) (class_ <= JOB_SUMMER || (class_ >= JOB_NOVICE_HIGH && class_ <= JOB_SOUL_LINKER))
+#define pcdb_checkid(class_) (class_ < JOB_MAX_BASIC || (class_ >= JOB_NOVICE_HIGH && class_ < JOB_MAX))
+int pc_class2idx(int class_);
int pc_isGM(struct map_session_data *sd);
int pc_getrefinebonus(int lv,int type);
int pc_can_give_items(int level); //[Lupus]
@@ -289,7 +292,7 @@ struct skill_tree_entry {
unsigned char lv;
} need[5];
}; // Celest
-extern struct skill_tree_entry skill_tree[MAX_PC_CLASS][MAX_SKILL_TREE];
+extern struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE];
int pc_read_gm_account(int fd);
void pc_setinvincibletimer(struct map_session_data* sd, int val);
diff --git a/src/map/script.c b/src/map/script.c
index 0e4144605..d00d5f700 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -5331,7 +5331,7 @@ BUILDIN_FUNC(jobchange)
if( script_hasdata(st,3) )
upper=script_getnum(st,3);
- if ((job >= 0 && job < MAX_PC_CLASS))
+ if (pcdb_checkid(job))
{
pc_jobchange(script_rid2sd(st),job, upper);
if(use_irc && irc_announce_jobchange_flag)
diff --git a/src/map/status.c b/src/map/status.c
index 02c2bf7b3..ce0403885 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -45,16 +45,16 @@ int StatusIconChangeTable[SC_MAX]; //Stores the icon that should be associated t
int StatusSkillChangeTable[SC_MAX]; //Stores the skill that should be considered associated to this status change.
unsigned long StatusChangeFlagTable[SC_MAX]; //Stores the flag specifying what this SC changes.
-static int max_weight_base[MAX_PC_CLASS];
-static int hp_coefficient[MAX_PC_CLASS];
-static int hp_coefficient2[MAX_PC_CLASS];
-static int hp_sigma_val[MAX_PC_CLASS][MAX_LEVEL+1];
-static int sp_coefficient[MAX_PC_CLASS];
-static int aspd_base[MAX_PC_CLASS][MAX_WEAPON_TYPE]; //[blackhole89]
+static int max_weight_base[CLASS_COUNT];
+static int hp_coefficient[CLASS_COUNT];
+static int hp_coefficient2[CLASS_COUNT];
+static int hp_sigma_val[CLASS_COUNT][MAX_LEVEL+1];
+static int sp_coefficient[CLASS_COUNT];
+static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE]; //[blackhole89]
static int refinebonus[MAX_REFINE_BONUS][3]; // 精錬ボーナステーブル(refine_db.txt)
int percentrefinery[5][MAX_REFINE+1]; // 精錬成功率(refine_db.txt)
static int atkmods[3][MAX_WEAPON_TYPE]; // 武器ATKサイズ修正(size_fix.txt)
-static char job_bonus[MAX_PC_CLASS][MAX_LEVEL];
+static char job_bonus[CLASS_COUNT][MAX_LEVEL];
static struct status_data dummy_status;
int current_equip_item_index; //Contains inventory index of an equipped item. To pass it into the EQUP_SCRIPT [Lupus]
@@ -584,6 +584,13 @@ int status_set_sp(struct block_list *bl, unsigned int sp, int flag)
return status_zap(bl, 0, status->sp - sp);
}
+int status_charge(struct block_list* bl, int hp, int sp)
+{
+ if(!((bl)->type&BL_CONSUME))
+ return hp+sp; //Assume all was charged so there are no 'not enough' fails.
+ return status_damage(NULL, bl, hp, sp, 0, 3);
+}
+
//Inflicts damage on the target with the according walkdelay.
//If flag&1, damage is passive and does not triggers cancelling status changes.
//If flag&2, fail if target does not has enough to substract.
@@ -1189,8 +1196,8 @@ int status_base_amotion_pc(struct map_session_data* sd, struct status_data* stat
// base weapon delay
amotion = (sd->status.weapon < MAX_WEAPON_TYPE)
- ? (aspd_base[sd->status.class_][sd->status.weapon]) // single weapon
- : (aspd_base[sd->status.class_][sd->weapontype1] + aspd_base[sd->status.class_][sd->weapontype2])*7/10; // dual-wield
+ ? (aspd_base[pc_class2idx(sd->status.class_)][sd->status.weapon]) // single weapon
+ : (aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype1] + aspd_base[pc_class2idx(sd->status.class_)][sd->weapontype2])*7/10; // dual-wield
// percentual delay reduction from stats
amotion-= amotion * (4*status->agi + status->dex)/1000;
@@ -1517,7 +1524,7 @@ static void status_calc_sigma(void)
{
int i,j;
- for(i = 0; i < MAX_PC_CLASS; i++)
+ for(i = 0; i < CLASS_COUNT; i++)
{
unsigned int k = 0;
hp_sigma_val[i][0] = hp_sigma_val[i][1] = 0;
@@ -1540,8 +1547,8 @@ static void status_calc_sigma(void)
/// f(x) = 35 + x*(A + B*C/D) + sum(i=2..x){ i*C/D }
static unsigned int status_base_pc_maxhp(struct map_session_data* sd, struct status_data* status)
{
- unsigned int val;
- val = 35 + sd->status.base_level*hp_coefficient2[sd->status.class_]/100 + hp_sigma_val[sd->status.class_][sd->status.base_level];
+ unsigned int val = pc_class2idx(sd->status.class_);
+ val = 35 + sd->status.base_level*hp_coefficient2[val]/100 + hp_sigma_val[val][sd->status.base_level];
if((sd->class_&MAPID_UPPERMASK) == MAPID_NINJA || (sd->class_&MAPID_UPPERMASK) == MAPID_GUNSLINGER)
val += 100; //Since their HP can't be approximated well enough without this.
@@ -1563,7 +1570,7 @@ static unsigned int status_base_pc_maxsp(struct map_session_data* sd, struct sta
{
unsigned int val;
- val = 10 + sd->status.base_level*sp_coefficient[sd->status.class_]/100;
+ val = 10 + sd->status.base_level*sp_coefficient[pc_class2idx(sd->status.class_)]/100;
val += val * status->int_/100;
if (sd->class_&JOBL_UPPER)
@@ -1606,7 +1613,7 @@ int status_calc_pc(struct map_session_data* sd,int first)
pc_calc_skilltree(sd); // スキルツリ?の計算
- sd->max_weight = max_weight_base[sd->status.class_]+sd->status.str*300;
+ sd->max_weight = max_weight_base[pc_class2idx(sd->status.class_)]+sd->status.str*300;
if(first&1) {
//Load Hp/SP from char-received data.
@@ -1959,10 +1966,11 @@ int status_calc_pc(struct map_session_data* sd,int first)
// ----- STATS CALCULATION -----
// Job bonuses
+ index = pc_class2idx(sd->status.class_);
for(i=0;i<(int)sd->status.job_level && i<MAX_LEVEL;i++){
- if(!job_bonus[sd->status.class_][i])
+ if(!job_bonus[index][i])
continue;
- switch(job_bonus[sd->status.class_][i]) {
+ switch(job_bonus[index][i]) {
case 1: status->str++; break;
case 2: status->agi++; break;
case 3: status->vit++; break;
@@ -7296,7 +7304,7 @@ static int status_natural_heal_timer(int tid,unsigned int tick,int id,int data)
int status_readdb(void)
{
- int i,j;
+ int i,j,class_;
FILE *fp;
char line[1024], path[1024],*p;
@@ -7323,15 +7331,16 @@ int status_readdb(void)
ShowDebug("%s: Not enough columns at line %d\n", path, i);
continue;
}
- if(atoi(split[0])>=MAX_PC_CLASS)
+ class_ = atoi(split[0]);
+ if(!pcdb_checkid(class_))
continue;
-
- max_weight_base[atoi(split[0])]=atoi(split[1]);
- hp_coefficient[atoi(split[0])]=atoi(split[2]);
- hp_coefficient2[atoi(split[0])]=atoi(split[3]);
- sp_coefficient[atoi(split[0])]=atoi(split[4]);
+ class_ = pc_class2idx(class_);
+ max_weight_base[class_]=atoi(split[1]);
+ hp_coefficient[class_]=atoi(split[2]);
+ hp_coefficient2[class_]=atoi(split[3]);
+ sp_coefficient[class_]=atoi(split[4]);
for(j=0;j<MAX_WEAPON_TYPE;j++)
- aspd_base[atoi(split[0])][j]=atoi(split[j+5]);
+ aspd_base[class_][j]=atoi(split[j+5]);
}
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",path);
@@ -7353,10 +7362,12 @@ int status_readdb(void)
p=strchr(p,',');
if(p) *p++=0;
}
- if(atoi(split[0])>=MAX_PC_CLASS)
+ class_ = atoi(split[0]);
+ if(!pcdb_checkid(class_))
continue;
+ class_ = pc_class2idx(class_);
for(i=1;i<j && split[i];i++)
- job_bonus[atoi(split[0])][i-1]=atoi(split[i]);
+ job_bonus[class_][i-1]=atoi(split[i]);
}
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",path);
diff --git a/src/map/status.h b/src/map/status.h
index 50ed1eb44..a3c03557d 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -579,7 +579,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp,int sp
//Define for standard HP/SP damage triggers.
#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)
-#define status_charge(bl, hp, sp) (!((bl)->type&BL_CONSUME) || status_damage(NULL, bl, hp, sp, 0, 3))
+int status_charge(struct block_list* bl, int hp, int sp);
int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int 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), 1)
diff --git a/src/map/vending.c b/src/map/vending.c
index 7c0024eb3..45ec08edf 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -236,6 +236,12 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool
clif_skill_fail(sd, MC_VENDING, 0, 0);
return;
}
+
+ if ( map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOVENDING) )
+ {
+ clif_displaymessage (sd->fd, msg_txt(276));
+ return; //Can't vend in novending mapflag maps.
+ }
// check number of items in shop
if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl )