summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/HPMmap.c5
-rw-r--r--src/map/atcommand.c225
-rw-r--r--src/map/atcommand.h4
-rw-r--r--src/map/battle.c9
-rw-r--r--src/map/battle.h2
-rw-r--r--src/map/battleground.c44
-rw-r--r--src/map/battleground.h11
-rw-r--r--src/map/chrif.c6
-rw-r--r--src/map/chrif.h2
-rw-r--r--src/map/clif.c28
-rw-r--r--src/map/clif.h4
-rw-r--r--src/map/duel.c5
-rw-r--r--src/map/duel.h2
-rw-r--r--src/map/elemental.c7
-rw-r--r--src/map/elemental.h2
-rw-r--r--src/map/guild.c17
-rw-r--r--src/map/guild.h2
-rw-r--r--src/map/homunculus.c18
-rw-r--r--src/map/homunculus.h2
-rw-r--r--src/map/instance.c5
-rw-r--r--src/map/instance.h2
-rw-r--r--src/map/irc-bot.c5
-rw-r--r--src/map/irc-bot.h2
-rw-r--r--src/map/itemdb.c24
-rw-r--r--src/map/itemdb.h4
-rw-r--r--src/map/map.c172
-rw-r--r--src/map/map.h5
-rw-r--r--src/map/mercenary.c7
-rw-r--r--src/map/mercenary.h2
-rw-r--r--src/map/mob.c32
-rw-r--r--src/map/mob.h4
-rw-r--r--src/map/npc.c149
-rw-r--r--src/map/npc.h4
-rw-r--r--src/map/packets.h4
-rw-r--r--src/map/party.c7
-rw-r--r--src/map/party.h2
-rw-r--r--src/map/pc.c149
-rw-r--r--src/map/pc.h7
-rw-r--r--src/map/pc_groups.c202
-rw-r--r--src/map/pc_groups.h67
-rw-r--r--src/map/pet.c22
-rw-r--r--src/map/pet.h2
-rw-r--r--src/map/quest.c5
-rw-r--r--src/map/quest.h2
-rw-r--r--src/map/script.c105
-rw-r--r--src/map/script.h4
-rw-r--r--src/map/skill.c15
-rw-r--r--src/map/skill.h4
-rw-r--r--src/map/status.c141
-rw-r--r--src/map/status.h55
-rw-r--r--src/map/storage.c4
-rw-r--r--src/map/storage.h2
-rw-r--r--src/map/unit.c7
-rw-r--r--src/map/unit.h2
-rw-r--r--src/map/vending.c2
-rw-r--r--src/map/vending.h2
56 files changed, 1023 insertions, 601 deletions
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c
index ca4a7a2e8..8a69cba97 100644
--- a/src/map/HPMmap.c
+++ b/src/map/HPMmap.c
@@ -142,10 +142,7 @@ void HPM_map_atcommands(void) {
unsigned int i;
for(i = 0; i < atcommand_list_items; i++) {
- if( !atcommand->add(atcommand_list[i].name,atcommand_list[i].func) ) {
- ShowDebug("HPM_map_atcommands: duplicate command '%s', skipping...\n", atcommand_list[i].name);
- continue;
- }
+ atcommand->add(atcommand_list[i].name,atcommand_list[i].func,true);
}
}
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 2900fde03..3f3e9679e 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -574,7 +574,7 @@ ACMD(who) {
case 2: {
StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s "
if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
- StrBuf->Printf(&buf, msg_txt(344), pc_group_get_name(pl_sd->group)); // "(%s) "
+ StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) "
StrBuf->Printf(&buf, msg_txt(347), pl_sd->status.base_level, pl_sd->status.job_level,
pc->job_name(pl_sd->status.class_)); // "| Lv:%d/%d | Job: %s"
break;
@@ -584,7 +584,7 @@ ACMD(who) {
StrBuf->Printf(&buf, msg_txt(912), pl_sd->status.char_id, pl_sd->status.account_id); // "(CID:%d/AID:%d) "
StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s "
if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
- StrBuf->Printf(&buf, msg_txt(344), pc_group_get_name(pl_sd->group)); // "(%s) "
+ StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) "
StrBuf->Printf(&buf, msg_txt(348), mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); // "| Location: %s %d %d"
break;
}
@@ -594,7 +594,7 @@ ACMD(who) {
StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s "
if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
- StrBuf->Printf(&buf, msg_txt(344), pc_group_get_name(pl_sd->group)); // "(%s) "
+ StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) "
if (p != NULL)
StrBuf->Printf(&buf, msg_txt(345), p->party.name); // " | Party: '%s'"
if (g != NULL)
@@ -766,15 +766,21 @@ ACMD(speed)
return false;
}
- if (speed < 0) {
+ sd->state.permanent_speed = 0;
+
+ if (speed < 0)
sd->base_status.speed = DEFAULT_WALK_SPEED;
- sd->state.permanent_speed = 0; // Remove lock when set back to default speed.
- } else {
+ else
sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED);
- sd->state.permanent_speed = 1; // Set lock when set to non-default speed.
- }
+
status_calc_bl(&sd->bl, SCB_SPEED);
- clif->message(fd, msg_txt(8)); // Speed changed.
+
+ if( sd->base_status.speed != DEFAULT_WALK_SPEED ) {
+ sd->state.permanent_speed = 1; // Set lock when set to non-default speed.
+ clif->message(fd, msg_txt(8)); // Speed changed.
+ } else
+ clif->message(fd, msg_txt(172)); //Speed returned to normal.
+
return true;
}
@@ -1294,6 +1300,7 @@ ACMD(baselevelup)
sd->status.status_point += status_point;
sd->status.base_level += (unsigned int)level;
+ status_calc_pc(sd, SCO_FORCE);
status_percent_heal(&sd->bl, 100, 100);
clif->misceffect(&sd->bl, 0);
clif->message(fd, msg_txt(21)); // Base level raised.
@@ -1315,13 +1322,13 @@ ACMD(baselevelup)
sd->status.status_point -= status_point;
sd->status.base_level -= (unsigned int)level;
clif->message(fd, msg_txt(22)); // Base level lowered.
+ status_calc_pc(sd, SCO_FORCE);
}
sd->status.base_exp = 0;
clif->updatestatus(sd, SP_STATUSPOINT);
clif->updatestatus(sd, SP_BASELEVEL);
clif->updatestatus(sd, SP_BASEEXP);
clif->updatestatus(sd, SP_NEXTBASEEXP);
- status_calc_pc(sd, 0);
pc->baselevelchanged(sd);
if(sd->status.party_id)
party->send_levelup(sd);
@@ -1374,7 +1381,7 @@ ACMD(joblevelup)
clif->updatestatus(sd, SP_JOBEXP);
clif->updatestatus(sd, SP_NEXTJOBEXP);
clif->updatestatus(sd, SP_SKILLPOINT);
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
return true;
}
@@ -2388,7 +2395,7 @@ ACMD(param) {
*stats[i] = new_value;
clif->updatestatus(sd, SP_STR + i);
clif->updatestatus(sd, SP_USTR + i);
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
clif->message(fd, msg_txt(42)); // Stat changed.
} else {
if (value < 0)
@@ -2445,7 +2452,7 @@ ACMD(stat_all) {
}
if (count > 0) { // if at least 1 stat modified
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
clif->message(fd, msg_txt(84)); // All stats changed!
} else {
if (value < 0)
@@ -3548,7 +3555,7 @@ ACMD(reloadatcommand) {
config_destroy(&run_test);
atcommand->doload();
- pc_groups_reload();
+ pcg->reload();
clif->message(fd, msg_txt(254));
return true;
}
@@ -5639,16 +5646,16 @@ ACMD(autolootitem)
}
else if (!strcmp(message,"reset"))
action = 4;
- }
-
- if (action < 3) // add or remove
- {
- if ((item_data = itemdb->exists(atoi(message))) == NULL)
- item_data = itemdb->search_name(message);
- if (!item_data) {
- // No items founds in the DB with Id or Name
- clif->message(fd, msg_txt(1189)); // Item not found.
- return false;
+
+ if (action < 3) // add or remove
+ {
+ if ((item_data = itemdb->exists(atoi(message))) == NULL)
+ item_data = itemdb->search_name(message);
+ if (!item_data) {
+ // No items founds in the DB with Id or Name
+ clif->message(fd, msg_txt(1189)); // Item not found.
+ return false;
+ }
}
}
@@ -5716,6 +5723,103 @@ ACMD(autolootitem)
}
/*==========================================
+ * @autoloottype
+ * Credits:
+ * chriser,Aleos
+ *------------------------------------------*/
+ACMD(autoloottype) {
+ int i;
+ uint8 action = 3; // 1=add, 2=remove, 3=help+list (default), 4=reset
+ enum item_types type = -1;
+ int ITEM_NONE = 0;
+
+ if (message && *message) {
+ if (message[0] == '+') {
+ message++;
+ action = 1;
+ } else if (message[0] == '-') {
+ message++;
+ action = 2;
+ } else if (strcmp(message,"reset") == 0) {
+ action = 4;
+ }
+
+ if (action < 3) {
+ // add or remove
+ if (strncmp(message, "healing", 3) == 0)
+ type = IT_HEALING;
+ else if (strncmp(message, "usable", 3) == 0)
+ type = IT_USABLE;
+ else if (strncmp(message, "etc", 3) == 0)
+ type = IT_ETC;
+ else if (strncmp(message, "weapon", 3) == 0)
+ type = IT_WEAPON;
+ else if (strncmp(message, "armor", 3) == 0)
+ type = IT_ARMOR;
+ else if (strncmp(message, "card", 3) == 0)
+ type = IT_CARD;
+ else if (strncmp(message, "petegg", 4) == 0)
+ type = IT_PETEGG;
+ else if (strncmp(message, "petarmor", 4) == 0)
+ type = IT_PETARMOR;
+ else if (strncmp(message, "ammo", 3) == 0)
+ type = IT_AMMO;
+ else {
+ clif->message(fd, msg_txt(1491)); // Item type not found.
+ return false;
+ }
+ }
+ }
+
+ switch (action) {
+ case 1:
+ if (sd->state.autoloottype&(1<<type)) {
+ clif->message(fd, msg_txt(1490)); // You're already autolooting this item type.
+ return false;
+ }
+ sd->state.autoloottype |= (1<<type); // Stores the type
+ sprintf(atcmd_output, msg_txt(1492), itemdb->typename(type)); // Autolooting item type: '%s'
+ clif->message(fd, atcmd_output);
+ break;
+ case 2:
+ if (!(sd->state.autoloottype&(1<<type))) {
+ clif->message(fd, msg_txt(1493)); // You're currently not autolooting this item type.
+ return false;
+ }
+ sd->state.autoloottype &= ~(1<<type);
+ sprintf(atcmd_output, msg_txt(1494), itemdb->typename(type)); // Removed item type: '%s' from your autoloottype list.
+ clif->message(fd, atcmd_output);
+ break;
+ case 3:
+ clif->message(fd, msg_txt(38)); // Invalid location number, or name.
+
+ {
+ // attempt to find the text help string
+ const char *text = atcommand_help_string(info);
+ if (text) clif->messageln(fd, text); // send the text to the client
+ }
+
+ if (sd->state.autoloottype == ITEM_NONE) {
+ clif->message(fd, msg_txt(1495)); // Your autoloottype list is empty.
+ } else {
+ clif->message(fd, msg_txt(1496)); // Item types on your autoloottype list:
+ for(i=0; i < IT_MAX; i++) {
+ if (sd->state.autoloottype&(1<<i)) {
+ sprintf(atcmd_output, " '%s'", itemdb->typename(i));
+ clif->message(fd, atcmd_output);
+ }
+ }
+ }
+ break;
+ case 4:
+ sd->state.autoloottype = ITEM_NONE;
+ clif->message(fd, msg_txt(1497)); // Your autoloottype list has been reset.
+ break;
+ }
+ return true;
+}
+
+/*==========================================
* It is made to snow.
*------------------------------------------*/
ACMD(snow) {
@@ -6664,7 +6768,7 @@ ACMD(homlevel) {
hd->homunculus.exp += hd->exp_next;
} while( hd->homunculus.level < level && homun->levelup(hd) );
- status_calc_homunculus(hd,0);
+ status_calc_homunculus(hd,SCO_NONE);
status_percent_heal(&hd->bl, 100, 100);
clif->specialeffect(&hd->bl,568,AREA);
return true;
@@ -8200,11 +8304,11 @@ void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommand
switch( type ) {
case COMMAND_CHARCOMMAND:
- if( cmd->char_groups[pc_group_get_idx(sd->group)] == 0 )
+ if( cmd->char_groups[pcg->get_idx(sd->group)] == 0 )
continue;
break;
case COMMAND_ATCOMMAND:
- if( cmd->at_groups[pc_group_get_idx(sd->group)] == 0 )
+ if( cmd->at_groups[pcg->get_idx(sd->group)] == 0 )
continue;
break;
default:
@@ -8413,7 +8517,7 @@ ACMD(reloadquestdb) {
return true;
}
ACMD(addperm) {
- int perm_size = ARRAYLENGTH(pc_g_permission_name);
+ int perm_size = pcg->permission_count;
bool add = (strcmpi(command+1, "addperm") == 0) ? true : false;
int i;
@@ -8422,37 +8526,37 @@ ACMD(addperm) {
clif->message(fd, atcmd_output);
clif->message(fd, msg_txt(1379)); // -- Permission List
for( i = 0; i < perm_size; i++ ) {
- sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name);
+ sprintf(atcmd_output,"- %s",pcg->permissions[i].name);
clif->message(fd, atcmd_output);
}
return false;
}
- ARR_FIND(0, perm_size, i, strcmpi(pc_g_permission_name[i].name, message) == 0);
+ ARR_FIND(0, perm_size, i, strcmpi(pcg->permissions[i].name, message) == 0);
if( i == perm_size ) {
sprintf(atcmd_output,msg_txt(1380),message); // '%s' is not a known permission.
clif->message(fd, atcmd_output);
clif->message(fd, msg_txt(1379)); // -- Permission List
for( i = 0; i < perm_size; i++ ) {
- sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name);
+ sprintf(atcmd_output,"- %s",pcg->permissions[i].name);
clif->message(fd, atcmd_output);
}
return false;
}
- if( add && (sd->extra_temp_permissions&pc_g_permission_name[i].permission) ) {
- sprintf(atcmd_output, msg_txt(1381),sd->status.name,pc_g_permission_name[i].name); // User '%s' already possesses the '%s' permission.
+ if( add && (sd->extra_temp_permissions&pcg->permissions[i].permission) ) {
+ sprintf(atcmd_output, msg_txt(1381),sd->status.name,pcg->permissions[i].name); // User '%s' already possesses the '%s' permission.
clif->message(fd, atcmd_output);
return false;
- } else if ( !add && !(sd->extra_temp_permissions&pc_g_permission_name[i].permission) ) {
- sprintf(atcmd_output, msg_txt(1382),sd->status.name,pc_g_permission_name[i].name); // User '%s' doesn't possess the '%s' permission.
+ } else if ( !add && !(sd->extra_temp_permissions&pcg->permissions[i].permission) ) {
+ sprintf(atcmd_output, msg_txt(1382),sd->status.name,pcg->permissions[i].name); // User '%s' doesn't possess the '%s' permission.
clif->message(fd, atcmd_output);
sprintf(atcmd_output,msg_txt(1383),sd->status.name); // -- User '%s' Permissions
clif->message(fd, atcmd_output);
for( i = 0; i < perm_size; i++ ) {
- if( sd->extra_temp_permissions&pc_g_permission_name[i].permission ) {
- sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name);
+ if( sd->extra_temp_permissions&pcg->permissions[i].permission ) {
+ sprintf(atcmd_output,"- %s",pcg->permissions[i].name);
clif->message(fd, atcmd_output);
}
}
@@ -8461,9 +8565,9 @@ ACMD(addperm) {
}
if( add )
- sd->extra_temp_permissions |= pc_g_permission_name[i].permission;
+ sd->extra_temp_permissions |= pcg->permissions[i].permission;
else
- sd->extra_temp_permissions &=~ pc_g_permission_name[i].permission;
+ sd->extra_temp_permissions &=~ pcg->permissions[i].permission;
sprintf(atcmd_output, msg_txt(1384),sd->status.name); // User '%s' permissions updated successfully. The changes are temporary.
@@ -9421,6 +9525,7 @@ void atcommand_basecommands(void) {
ACMD_DEF(changelook),
ACMD_DEF(autoloot),
ACMD_DEF2("alootid", autolootitem),
+ ACMD_DEF(autoloottype),
ACMD_DEF(mobinfo),
ACMD_DEF(exp),
ACMD_DEF(version),
@@ -9504,7 +9609,7 @@ void atcommand_basecommands(void) {
int i;
for( i = 0; i < ARRAYLENGTH(atcommand_base); i++ ) {
- if(!atcommand->add(atcommand_base[i].command,atcommand_base[i].func)) { // Should not happen if atcommand_base[] array is OK
+ if(!atcommand->add(atcommand_base[i].command,atcommand_base[i].func,false)) { // Should not happen if atcommand_base[] array is OK
ShowDebug("atcommand_basecommands: duplicate ACMD_DEF for '%s'.\n", atcommand_base[i].command);
continue;
}
@@ -9516,21 +9621,22 @@ void atcommand_basecommands(void) {
return;
}
-bool atcommand_add(char *name,AtCommandFunc func) {
+bool atcommand_add(char *name,AtCommandFunc func, bool replace) {
AtCommandInfo* cmd;
- if(atcommand->exists(name)) //caller will handle/display on false
- return false;
-
- CREATE(cmd, AtCommandInfo, 1);
+ if( (cmd = atcommand->exists(name)) ) { //caller will handle/display on false
+ if( !replace )
+ return false;
+ } else {
+ CREATE(cmd, AtCommandInfo, 1);
+ strdb_put(atcommand->db, name, cmd);
+ }
safestrncpy(cmd->command, name, sizeof(cmd->command));
cmd->func = func;
cmd->help = NULL;
cmd->log = true;
-
- strdb_put(atcommand->db, cmd->command, cmd);
-
+
return true;
}
@@ -9701,7 +9807,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
if( !pc->get_group_level(sd) ) {
if( x >= 1 || y >= 1 ) { /* we have command */
info = atcommand->get_info_byname(atcommand->check_alias(command + 1));
- if( !info || info->char_groups[pc_group_get_idx(sd->group)] == 0 ) /* if we can't use or doesn't exist: don't even display the command failed message */
+ if( !info || info->char_groups[pcg->get_idx(sd->group)] == 0 ) /* if we can't use or doesn't exist: don't even display the command failed message */
return false;
} else
return false;/* display as normal message */
@@ -9781,8 +9887,8 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message
// type == 1 : player invoked
if (type == 1) {
int i;
- if ((*command == atcommand->at_symbol && info->at_groups[pc_group_get_idx(sd->group)] == 0) ||
- (*command == atcommand->char_symbol && info->char_groups[pc_group_get_idx(sd->group)] == 0) ) {
+ if ((*command == atcommand->at_symbol && info->at_groups[pcg->get_idx(sd->group)] == 0) ||
+ (*command == atcommand->char_symbol && info->char_groups[pcg->get_idx(sd->group)] == 0) ) {
return false;
}
if( pc_isdead(sd) && pc->has_permission(sd,PC_PERM_DISABLE_CMD_DEAD) ) {
@@ -9980,13 +10086,13 @@ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **command
continue;
}
- idx = pc_group_get_idx(group);
+ idx = pcg->get_idx(group);
if (idx < 0 || idx >= sz) {
ShowError("atcommand_db_load_groups: index (%d) out of bounds [0,%d]\n", idx, sz - 1);
continue;
}
- if (pc_group_has_permission(group, PC_PERM_USE_ALL_COMMANDS)) {
+ if (pcg->has_permission(group, PC_PERM_USE_ALL_COMMANDS)) {
atcmd->at_groups[idx] = atcmd->char_groups[idx] = 1;
continue;
}
@@ -10024,8 +10130,8 @@ bool atcommand_can_use(struct map_session_data *sd, const char *command) {
if (info == NULL)
return false;
- if ((*command == atcommand->at_symbol && info->at_groups[pc_group_get_idx(sd->group)] != 0) ||
- (*command == atcommand->char_symbol && info->char_groups[pc_group_get_idx(sd->group)] != 0) ) {
+ if ((*command == atcommand->at_symbol && info->at_groups[pcg->get_idx(sd->group)] != 0) ||
+ (*command == atcommand->char_symbol && info->char_groups[pcg->get_idx(sd->group)] != 0) ) {
return true;
}
@@ -10037,8 +10143,8 @@ bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtComm
if (info == NULL)
return false;
- if ((type == COMMAND_ATCOMMAND && info->at_groups[pc_group_get_idx(sd->group)] != 0) ||
- (type == COMMAND_CHARCOMMAND && info->char_groups[pc_group_get_idx(sd->group)] != 0) ) {
+ if ((type == COMMAND_ATCOMMAND && info->at_groups[pcg->get_idx(sd->group)] != 0) ||
+ (type == COMMAND_CHARCOMMAND && info->char_groups[pcg->get_idx(sd->group)] != 0) ) {
return true;
}
@@ -10089,7 +10195,10 @@ void atcommand_doload(void) {
atcommand->config_read(map->ATCOMMAND_CONF_FILENAME);
}
-void do_init_atcommand(void) {
+void do_init_atcommand(bool minimal) {
+ if (minimal)
+ return;
+
atcommand->at_symbol = '@';
atcommand->char_symbol = '#';
atcommand->binding_count = 0;
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index 63c38e4d1..6b5a52fcb 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -77,7 +77,7 @@ struct atcommand_interface {
/* */
char* msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
/* */
bool (*parse) (const int fd, struct map_session_data* sd, const char* message, int type);
@@ -110,7 +110,7 @@ struct atcommand_interface {
int (*cmd_db_clear_sub) (DBKey key, DBData *data, va_list args);
void (*doload) (void);
void (*base_commands) (void);
- bool (*add) (char *name, AtCommandFunc func);
+ bool (*add) (char *name, AtCommandFunc func, bool replace);
};
struct atcommand_interface *atcommand;
diff --git a/src/map/battle.c b/src/map/battle.c
index 94222f663..9a70acaca 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -206,7 +206,7 @@ int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
if( !target || status->isdead(target) ) {/* nothing we can do */
if( dat->src_type == BL_PC && ( src = map->id2bl(dat->src_id) ) && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) {
((TBL_PC*)src)->state.hold_recalc = 0;
- status_calc_pc(((TBL_PC*)src),0);
+ status_calc_pc(((TBL_PC*)src),SCO_FORCE);
}
ers_free(battle->delay_damage_ers, dat);
return 0;
@@ -237,7 +237,7 @@ int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
if( src && src->type == BL_PC && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) {
((TBL_PC*)src)->state.hold_recalc = 0;
- status_calc_pc(((TBL_PC*)src),0);
+ status_calc_pc(((TBL_PC*)src),SCO_FORCE);
}
}
ers_free(battle->delay_damage_ers, dat);
@@ -6759,7 +6759,10 @@ int battle_config_read(const char* cfgName)
return 0;
}
-void do_init_battle(void) {
+void do_init_battle(bool minimal) {
+ if (minimal)
+ return;
+
battle->delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR);
timer->add_func_list(battle->delay_damage_sub, "battle_delay_damage_sub");
diff --git a/src/map/battle.h b/src/map/battle.h
index bf08ab8d6..0f3a22c4b 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -506,7 +506,7 @@ struct battle_interface {
int attr_fix_table[4][ELE_MAX][ELE_MAX];
struct eri *delay_damage_ers; //For battle delay damage structures.
/* init */
- void (*init) (void);
+ void (*init) (bool minimal);
/* final */
void (*final) (void);
/* damage calculation */
diff --git a/src/map/battleground.c b/src/map/battleground.c
index 62688659e..6b9695849 100644
--- a/src/map/battleground.c
+++ b/src/map/battleground.c
@@ -520,13 +520,43 @@ void bg_begin(struct bg_arena *arena) {
bg->queue_pc_cleanup(sd);
}
}
+ /* TODO/FIXME? I *think* it should check what kind of queue the player used, then check if his party/guild
+ * (his team) still meet the join criteria (sort of what bg->can_queue does)
+ */
if( count < arena->min_players ) {
bg->match_over(arena,true);
} else {
arena->ongoing = true;
- mapreg->setreg(script->add_str("$@bg_queue_id"),arena->queue_id);/* TODO: make this a arena-independant var? or just .@? */
+ /* TODO: make this a arena-independant var? or just .@? */
+ mapreg->setreg(script->add_str("$@bg_queue_id"),arena->queue_id);
mapreg->setregstr(script->add_str("$@bg_delay_var$"),bg->gdelay_var);
+
+ count = 0;
+ for( i = 0; i < queue->size; i++ ) {
+ struct map_session_data * sd = NULL;
+
+ if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
+ if( sd->bg_queue.ready == 1 ) {
+
+ mapreg->setreg(reference_uid(script->add_str("$@bg_member"), count), sd->status.account_id);
+
+ mapreg->setreg(reference_uid(script->add_str("$@bg_member_group"), count),
+ sd->bg_queue.type == BGQT_GUILD ? sd->status.guild_id :
+ sd->bg_queue.type == BGQT_PARTY ? sd->status.party_id :
+ 0
+ );
+ mapreg->setreg(reference_uid(script->add_str("$@bg_member_type"), count),
+ sd->bg_queue.type == BGQT_GUILD ? 1 :
+ sd->bg_queue.type == BGQT_PARTY ? 2 :
+ 0
+ );
+ count++;
+ }
+ }
+ }
+ mapreg->setreg(script->add_str("$@bg_member_size"),count);
+
npc->event_do(arena->npc_event);
/* we split evenly? */
/* but if a party of say 10 joins, it cant be split evenly unless by luck there are 10 soloers in the queue besides them */
@@ -685,12 +715,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
if( sd->bg_queue.arena != NULL )
return BGQA_DUPLICATE_REQUEST;
-
- if( type != BGQT_INDIVIDUAL ) {/* until we get the damn balancing correct */
- clif->colormes(sd->fd,COLOR_RED,"Queueing is only currently enabled only for Solo Mode");
- return BGQA_FAIL_TEAM_COUNT;
- }
-
+
switch(type) {
case BGQT_GUILD:
if( !sd->guild || !sd->state.gmaster_flag )
@@ -757,7 +782,10 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
return BGQA_SUCCESS;
}
-void do_init_battleground(void) {
+void do_init_battleground(bool minimal) {
+ if (minimal)
+ return;
+
bg->team_db = idb_alloc(DB_OPT_RELEASE_DATA);
timer->add_func_list(bg->send_xy_timer, "bg_send_xy_timer");
timer->add_interval(timer->gettick() + battle_config.bg_update_interval, bg->send_xy_timer, 0, 0, battle_config.bg_update_interval);
diff --git a/src/map/battleground.h b/src/map/battleground.h
index a5e540924..7f15a4bbc 100644
--- a/src/map/battleground.h
+++ b/src/map/battleground.h
@@ -19,10 +19,11 @@
* Enumerations
**/
enum bg_queue_types {
- BGQT_INVALID,
- BGQT_INDIVIDUAL,
- BGQT_PARTY,
- BGQT_GUILD
+ BGQT_INVALID = 0x0,
+ BGQT_INDIVIDUAL = 0x1,
+ BGQT_PARTY = 0x2,
+ /* yup no 0x3 */
+ BGQT_GUILD = 0x4,
};
struct battleground_member_data {
@@ -75,7 +76,7 @@ struct battleground_interface {
DBMap *team_db; // int bg_id -> struct battleground_data*
unsigned int team_counter; // Next bg_id
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
/* */
struct bg_arena *(*name2arena) (char *name);
diff --git a/src/map/chrif.c b/src/map/chrif.c
index a13217060..87ec71ec5 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -1611,8 +1611,10 @@ int do_final_chrif(void) {
/*==========================================
*
*------------------------------------------*/
-int do_init_chrif(void) {
-
+int do_init_chrif(bool minimal) {
+ if (minimal)
+ return 0;
+
chrif->auth_db = idb_alloc(DB_OPT_BASE);
chrif->auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE);
diff --git a/src/map/chrif.h b/src/map/chrif.h
index 9df4b9931..56aa569a3 100644
--- a/src/map/chrif.h
+++ b/src/map/chrif.h
@@ -63,7 +63,7 @@ struct chrif_interface {
int state;
/* */
int (*final) (void);
- int (*init) (void);
+ int (*init) (bool minimal);
/* funcs */
void (*setuserid) (char* id);
void (*setpasswd) (char* pwd);
diff --git a/src/map/clif.c b/src/map/clif.c
index 99f7c87d7..04614158a 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9217,7 +9217,9 @@ void clif_hercules_chsys_mjoin(struct map_session_data *sd) {
/// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT).
/// 007d
void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
+#if PACKETVER >= 20090218
int i;
+#endif
if(sd->bl.prev != NULL)
return;
@@ -9477,7 +9479,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
}
map->iwall_get(sd); // Updates Walls Info on this Map to Client
- status_calc_pc(sd, false);/* some conditions are map-dependent so we must recalculate */
+ status_calc_pc(sd, SCO_NONE);/* some conditions are map-dependent so we must recalculate */
sd->state.changemap = false;
if( hChSys.local && hChSys.local_autojoin && !map->list[sd->bl.m].flag.chsysnolocalaj ) {
@@ -17578,9 +17580,7 @@ void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) {
clif->bgqueue_ack(sd,BGQA_FAIL_BGNAME_INVALID,0);
return;
}
- //debug
- safestrncpy(arena->name, p->bg_name, sizeof(arena->name));
-
+
switch( (enum bg_queue_types)p->type ) {
case BGQT_INDIVIDUAL:
case BGQT_PARTY:
@@ -17804,6 +17804,19 @@ void clif_bank_withdraw(struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
+/* TODO: official response packet (tried 0x8cb/0x97b but the display was quite screwed up.) */
+/* currently mimicing */
+void clif_show_modifiers (struct map_session_data *sd) {
+
+ if( sd->status.mod_exp != 100 || sd->status.mod_drop != 100 || sd->status.mod_death != 100 ) {
+ char output[128];
+
+ snprintf(output,128,"Base EXP : %d%% | Base Drop: %d%% | Base Death Penalty: %d%%",
+ sd->status.mod_exp,sd->status.mod_drop,sd->status.mod_death);
+ clif->broadcast2(&sd->bl,output, strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF);
+ }
+
+}
/* */
unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
@@ -18052,10 +18065,13 @@ void clif_bc_ready(void) {
/*==========================================
*
*------------------------------------------*/
-int do_init_clif(void) {
+int do_init_clif(bool minimal) {
const char* colors[COLOR_MAX] = { "0xFF0000", "0x00ff00", "0xffffff" };
int i;
+ if (minimal)
+ return 0;
+
/**
* Setup Color Table (saves unnecessary load of strtoul on every call)
**/
@@ -18603,6 +18619,8 @@ void clif_defaults(void) {
/* Bank System [Yommy/Hercules] */
clif->bank_deposit = clif_bank_deposit;
clif->bank_withdraw = clif_bank_withdraw;
+ /* */
+ clif->show_modifiers = clif_show_modifiers;
/*------------------------
*- Parse Incoming Packet
*------------------------*/
diff --git a/src/map/clif.h b/src/map/clif.h
index cbe3fa857..710cb6590 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -526,7 +526,7 @@ struct clif_interface {
/* */
bool ally_only;
/* core */
- int (*init) (void);
+ int (*init) (bool minimal);
void (*final) (void);
int (*setip) (const char* ip);
void (*setbindip) (const char* ip);
@@ -1006,6 +1006,8 @@ struct clif_interface {
/* Bank System [Yommy/Hercules] */
void (*bank_deposit) (struct map_session_data *sd, enum e_BANKING_DEPOSIT_ACK reason);
void (*bank_withdraw) (struct map_session_data *sd,enum e_BANKING_WITHDRAW_ACK reason);
+ /* */
+ void (*show_modifiers) (struct map_session_data *sd);
/*------------------------
*- Parse Incoming Packet
*------------------------*/
diff --git a/src/map/duel.c b/src/map/duel.c
index 4e41865d4..5e305244a 100644
--- a/src/map/duel.c
+++ b/src/map/duel.c
@@ -166,7 +166,10 @@ void duel_reject(const unsigned int did, struct map_session_data* sd) {
void do_final_duel(void) {
}
-void do_init_duel(void) {
+void do_init_duel(bool minimal) {
+ if (minimal)
+ return;
+
memset(&duel->list[0], 0, sizeof(duel->list));
}
diff --git a/src/map/duel.h b/src/map/duel.h
index d1ec58415..d60c9531a 100644
--- a/src/map/duel.h
+++ b/src/map/duel.h
@@ -34,7 +34,7 @@ struct duel_interface {
void (*showinfo) (const unsigned int did, struct map_session_data* sd);
int (*checktime) (struct map_session_data* sd);
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
} duel_s;
diff --git a/src/map/elemental.c b/src/map/elemental.c
index f15b735b2..f335600d6 100644
--- a/src/map/elemental.c
+++ b/src/map/elemental.c
@@ -258,7 +258,7 @@ int elemental_data_received(struct s_elemental *ele, bool flag) {
ed->bl.y = ed->ud.to_y;
map->addiddb(&ed->bl);
- status_calc_elemental(ed,1);
+ status_calc_elemental(ed,SCO_FIRST);
ed->last_spdrain_time = ed->last_thinktime = timer->gettick();
ed->summon_timer = INVALID_TIMER;
elemental->summon_init(ed);
@@ -931,7 +931,10 @@ void reload_elemental_skilldb(void) {
elemental->read_skilldb();
}
-int do_init_elemental(void) {
+int do_init_elemental(bool minimal) {
+ if (minimal)
+ return 0;
+
elemental->read_db();
elemental->read_skilldb();
diff --git a/src/map/elemental.h b/src/map/elemental.h
index 3cd819d53..8ffffa5e3 100644
--- a/src/map/elemental.h
+++ b/src/map/elemental.h
@@ -73,7 +73,7 @@ struct elemental_interface {
struct s_elemental_db db[MAX_ELEMENTAL_CLASS]; // Elemental Database
/* */
- int (*init) (void);
+ int (*init) (bool minimal);
void (*final) (void);
/* funcs */
bool (*class) (int class_);
diff --git a/src/map/guild.c b/src/map/guild.c
index 517a49cc4..719d6bf69 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -1975,7 +1975,7 @@ int guild_castledatasave(int castle_id, int index, int value)
gc->defense = value;
for (i = 0; i < MAX_GUARDIANS; i++)
if (gc->guardian[i].visible && (gd = map->id2md(gc->guardian[i].id)) != NULL)
- status_calc_mob(gd, 0);
+ status_calc_mob(gd, SCO_NONE);
break;
}
case 4:
@@ -2224,12 +2224,15 @@ void guild_flags_clear(void) {
guild->flags_count = 0;
}
-void do_init_guild(void) {
- guild->db = idb_alloc(DB_OPT_RELEASE_DATA);
- guild->castle_db = idb_alloc(DB_OPT_BASE);
- guild->expcache_db = idb_alloc(DB_OPT_BASE);
- guild->infoevent_db = idb_alloc(DB_OPT_BASE);
- guild->expcache_ers = ers_new(sizeof(struct guild_expcache),"guild.c::expcache_ers",ERS_OPT_NONE);
+void do_init_guild(bool minimal) {
+ if (minimal)
+ return;
+
+ guild->db = idb_alloc(DB_OPT_RELEASE_DATA);
+ guild->castle_db = idb_alloc(DB_OPT_BASE);
+ guild->expcache_db = idb_alloc(DB_OPT_BASE);
+ guild->infoevent_db = idb_alloc(DB_OPT_BASE);
+ guild->expcache_ers = ers_new(sizeof(struct guild_expcache),"guild.c::expcache_ers",ERS_OPT_NONE);
sv->readdb(map->db_path, "castle_db.txt", ',', 4, 5, -1, guild->read_castledb);
diff --git a/src/map/guild.h b/src/map/guild.h
index 57148867a..9326d8d5a 100644
--- a/src/map/guild.h
+++ b/src/map/guild.h
@@ -56,7 +56,7 @@ struct s_guild_skill_tree {
struct guild_interface {
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
/* */
DBMap* db; // int guild_id -> struct guild*
diff --git a/src/map/homunculus.c b/src/map/homunculus.c
index 52f0572c0..0a162958a 100644
--- a/src/map/homunculus.c
+++ b/src/map/homunculus.c
@@ -272,7 +272,7 @@ void homunculus_skillup(struct homun_data *hd,uint16 skill_id) {
{
hd->homunculus.hskill[i].lv++;
hd->homunculus.skillpts-- ;
- status_calc_homunculus(hd,0);
+ status_calc_homunculus(hd,SCO_NONE);
if (hd->master) {
clif->homskillup(hd->master, skill_id);
clif->hominfo(hd->master,hd,0);
@@ -413,7 +413,7 @@ bool homunculus_evolve(struct homun_data *hd) {
//status_Calc flag&1 will make current HP/SP be reloaded from hom structure
hom->hp = hd->battle_status.hp;
hom->sp = hd->battle_status.sp;
- status_calc_homunculus(hd,1);
+ status_calc_homunculus(hd,SCO_FIRST);
if (!(battle_config.hom_setting&0x2))
skill->unit_move(&sd->hd->bl,timer->gettick(),1); // apply land skills immediately
@@ -460,7 +460,7 @@ bool homunculus_mutate(struct homun_data *hd, int homun_id) {
hom->hp = hd->battle_status.hp;
hom->sp = hd->battle_status.sp;
hom->prev_class = prev_class;
- status_calc_homunculus(hd,1);
+ status_calc_homunculus(hd,SCO_FIRST);
if (!(battle_config.hom_setting&0x2))
skill->unit_move(&sd->hd->bl,timer->gettick(),1); // apply land skills immediately
@@ -505,7 +505,7 @@ int homunculus_gainexp(struct homun_data *hd,unsigned int exp) {
hd->homunculus.exp = 0;
clif->specialeffect(&hd->bl,568,AREA);
- status_calc_homunculus(hd,0);
+ status_calc_homunculus(hd,SCO_NONE);
status_percent_heal(&hd->bl, 100, 100);
return 0;
}
@@ -757,7 +757,7 @@ bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) {
hd->bl.y = hd->ud.to_y;
map->addiddb(&hd->bl);
- status_calc_homunculus(hd,1);
+ status_calc_homunculus(hd,SCO_FIRST);
hd->hungry_timer = INVALID_TIMER;
return true;
@@ -1003,7 +1003,7 @@ bool homunculus_shuffle(struct homun_data *hd) {
memcpy(&hd->homunculus.hskill, &b_skill, sizeof(b_skill));
hd->homunculus.skillpts = skillpts;
clif->homskillinfoblock(sd);
- status_calc_homunculus(hd,0);
+ status_calc_homunculus(hd,SCO_NONE);
status_percent_heal(&hd->bl, 100, 100);
clif->specialeffect(&hd->bl,568,AREA);
@@ -1229,8 +1229,12 @@ void homunculus_skill_reload(void) {
homun->skill_db_read();
}
-void do_init_homunculus(void) {
+void do_init_homunculus(bool minimal) {
int class_;
+
+ if (minimal)
+ return;
+
homun->read_db();
homun->exp_db_read();
homun->skill_db_read();
diff --git a/src/map/homunculus.h b/src/map/homunculus.h
index e3ec38f7b..bf1de6171 100644
--- a/src/map/homunculus.h
+++ b/src/map/homunculus.h
@@ -91,7 +91,7 @@ struct homunculus_interface {
struct s_homunculus_db db[MAX_HOMUNCULUS_CLASS];
struct homun_skill_tree_entry skill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE];
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
void (*reload) (void);
void (*reload_skill) (void);
diff --git a/src/map/instance.c b/src/map/instance.c
index 6b96c3112..ab68c9e22 100644
--- a/src/map/instance.c
+++ b/src/map/instance.c
@@ -691,7 +691,10 @@ void do_final_instance(void) {
instance->instances = 0;
}
-void do_init_instance(void) {
+void do_init_instance(bool minimal) {
+ if (minimal)
+ return;
+
timer->add_func_list(instance->destroy_timer, "instance_destroy_timer");
}
diff --git a/src/map/instance.h b/src/map/instance.h
index 27a9401b4..4f65d7db0 100644
--- a/src/map/instance.h
+++ b/src/map/instance.h
@@ -47,7 +47,7 @@ struct instance_data {
};
struct instance_interface {
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
void (*reload) (void);
/* start point */
diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c
index f67446629..0f487d8f7 100644
--- a/src/map/irc-bot.c
+++ b/src/map/irc-bot.c
@@ -386,7 +386,7 @@ void irc_relay(char *name, const char *msg) {
/**
* IRC bot initializer
*/
-void irc_bot_init(void) {
+void irc_bot_init(bool minimal) {
/// Command handlers
const struct irc_func irc_func_base[] = {
{ "PING" , ircbot->pong },
@@ -399,6 +399,9 @@ void irc_bot_init(void) {
struct irc_func* function;
int i;
+ if (minimal)
+ return;
+
if( !hChSys.irc )
return;
diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h
index 52ff0c9be..305cdfd91 100644
--- a/src/map/irc-bot.h
+++ b/src/map/irc-bot.h
@@ -34,7 +34,7 @@ struct irc_bot_interface {
unsigned int size;
} funcs;
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
/* */
int (*parse) (int fd);
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index feb17ddc8..d7d117574 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -1027,7 +1027,10 @@ void itemdb_read_packages(void) {
if( itemdb->packages[count].random_qty ) {
CREATE(itemdb->packages[count].random_groups, struct item_package_rand_group, itemdb->packages[count].random_qty);
for( c = 0; c < itemdb->packages[count].random_qty; c++ ) {
- CREATE(itemdb->packages[count].random_groups[c].random_list, struct item_package_rand_entry, rgroups[ i - 1 ][c]);
+ if( !rgroups[ i - 1 ][c] )
+ ShowError("itemdb_read_packages: package '%s' missing 'Random' field %d! there must not be gaps!\n",config_setting_name(itg),c+1);
+ else
+ CREATE(itemdb->packages[count].random_groups[c].random_list, struct item_package_rand_entry, rgroups[ i - 1 ][c]);
itemdb->packages[count].random_groups[c].random_qty = 0;
}
}
@@ -1090,7 +1093,7 @@ void itemdb_read_packages(void) {
itemdb->packages[count].random_groups[gidx].random_list[r].id = data ? data->nameid : 0;
itemdb->packages[count].random_groups[gidx].random_list[r].qty = icount;
if( (itemdb->packages[count].random_groups[gidx].random_list[r].rate = rate) == 10000 ) {
- ShowWarning("itemdb_read_packages: item '%s' in '%s' has 100% drop rate!! set this item as 'Random: 0' or other items won't drop!!!\n",itname,config_setting_name(itg));
+ ShowWarning("itemdb_read_packages: item '%s' in '%s' has 100%% drop rate!! set this item as 'Random: 0' or other items won't drop!!!\n",itname,config_setting_name(itg));
}
itemdb->packages[count].random_groups[gidx].random_list[r].hours = expire;
itemdb->packages[count].random_groups[gidx].random_list[r].announce = announce == true ? 1 : 0;
@@ -1924,7 +1927,7 @@ int itemdb_uid_load() {
/*====================================
* read all item-related databases
*------------------------------------*/
-void itemdb_read(void) {
+void itemdb_read(bool minimal) {
int i;
DBData prev;
@@ -1942,6 +1945,9 @@ void itemdb_read(void) {
}
}
+ if (minimal)
+ return;
+
itemdb->read_combos();
itemdb->read_groups();
itemdb->read_chains();
@@ -2062,7 +2068,7 @@ void itemdb_reload(void) {
db_clear(itemdb->names);
// read new data
- itemdb->read();
+ itemdb->read(false);
//Epoque's awesome @reloaditemdb fix - thanks! [Ind]
//- Fixes the need of a @reloadmobdb after a @reloaditemdb to re-link monster drop data
@@ -2105,7 +2111,7 @@ void itemdb_reload(void) {
sd->combos.id = NULL;
sd->combos.count = 0;
if( pc->load_combo(sd) > 0 )
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
}
}
@@ -2171,12 +2177,16 @@ void do_final_itemdb(void) {
db_destroy(itemdb->names);
}
-void do_init_itemdb(void) {
+void do_init_itemdb(bool minimal) {
memset(itemdb->array, 0, sizeof(itemdb->array));
itemdb->other = idb_alloc(DB_OPT_BASE);
itemdb->names = strdb_alloc(DB_OPT_BASE,ITEM_NAME_LENGTH);
itemdb->create_dummy_data(); //Dummy data item.
- itemdb->read();
+ itemdb->read(minimal);
+
+ if (minimal)
+ return;
+
clif->cashshop_load();
}
void itemdb_defaults(void) {
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 2579d84ca..80d2fd0ce 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -266,7 +266,7 @@ struct item_package {
#define itemdb_canauction(item, gmlv) itemdb->isrestricted(item , gmlv, 0, itemdb->canauction_sub)
struct itemdb_interface {
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
void (*reload) (void);
void (*name_constants) (void);
@@ -343,7 +343,7 @@ struct itemdb_interface {
int (*read_sqldb) (void);
uint64 (*unique_id) (int8 flag, int64 value);
int (*uid_load) ();
- void (*read) (void);
+ void (*read) (bool minimal);
void (*destroy_item_data) (struct item_data *self, int free_self);
int (*final_sub) (DBKey key, DBData *data, va_list ap);
};
diff --git a/src/map/map.c b/src/map/map.c
index b50297ca6..cd192b7d4 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -1722,8 +1722,6 @@ int map_quit(struct map_session_data *sd) {
if( sd->state.storage_flag == 1 ) sd->state.storage_flag = 0; // No need to Double Save Storage on Quit.
- if (sd->state.permanent_speed == 1) sd->state.permanent_speed = 0; // Remove lock so speed is set back to normal at login.
-
if( sd->ed ) {
elemental->clean_effect(sd->ed);
unit->remove_map(&sd->ed->bl,CLR_TELEPORT,ALC_MARK);
@@ -2907,7 +2905,7 @@ int map_readfromcache(struct map_data *m, char *buffer) {
}
-int map_addmap(char* mapname) {
+int map_addmap(const char* mapname) {
map->list[map->count].instance_id = -1;
mapindex_getmapname(mapname, map->list[map->count++].name);
return 0;
@@ -5344,6 +5342,7 @@ void map_hp_symbols(void) {
HPM->share(skill,"skill");
HPM->share(vending,"vending");
HPM->share(pc,"pc");
+ HPM->share(pcg,"pc_groups");
HPM->share(party,"party");
HPM->share(storage,"storage");
HPM->share(trade,"trade");
@@ -5398,6 +5397,7 @@ void map_load_defaults(void) {
skill_defaults();
vending_defaults();
pc_defaults();
+ pc_groups_defaults();
party_defaults();
storage_defaults();
trade_defaults();
@@ -5419,6 +5419,8 @@ void map_load_defaults(void) {
}
int do_init(int argc, char *argv[])
{
+ bool minimal = false;
+ char *scriptcheck = NULL;
int i;
#ifdef GCOLLECT
@@ -5468,6 +5470,11 @@ int do_init(int argc, char *argv[])
map->LOG_CONF_NAME = argv[++i];
} else if( strcmp(arg, "run-once") == 0 ) { // close the map-server as soon as its done.. for testing [Celest]
runflag = CORE_ST_STOP;
+ } else if( strcmp(arg, "script-check") == 0 ) {
+ minimal = true;
+ runflag = CORE_ST_STOP;
+ if( map->arg_next_value(arg, i, argc) )
+ scriptcheck = argv[++i];
} else {
ShowError("Unknown option '%s'.\n", argv[i]);
exit(EXIT_FAILURE);
@@ -5489,39 +5496,42 @@ int do_init(int argc, char *argv[])
}
map_load_defaults();
- map->config_read(map->MAP_CONF_NAME);
- CREATE(map->list,struct map_data,map->count);
- map->count = 0;
- map->config_read_sub(map->MAP_CONF_NAME);
- // loads npcs
- map->reloadnpc(false);
+ if (!minimal) {
+ map->config_read(map->MAP_CONF_NAME);
+ CREATE(map->list,struct map_data,map->count);
+ map->count = 0;
+ map->config_read_sub(map->MAP_CONF_NAME);
- chrif->checkdefaultlogin();
+ // loads npcs
+ map->reloadnpc(false);
- if (!map->ip_set || !map->char_ip_set) {
- char ip_str[16];
- ip2str(addr_[0], ip_str);
+ chrif->checkdefaultlogin();
- ShowWarning("Not all IP addresses in /conf/map-server.conf configured, autodetecting...\n");
+ if (!map->ip_set || !map->char_ip_set) {
+ char ip_str[16];
+ ip2str(addr_[0], ip_str);
- if (naddr_ == 0)
- ShowError("Unable to determine your IP address...\n");
- else if (naddr_ > 1)
- ShowNotice("Multiple interfaces detected...\n");
+ ShowWarning("Not all IP addresses in /conf/map-server.conf configured, autodetecting...\n");
- ShowInfo("Defaulting to %s as our IP address\n", ip_str);
+ if (naddr_ == 0)
+ ShowError("Unable to determine your IP address...\n");
+ else if (naddr_ > 1)
+ ShowNotice("Multiple interfaces detected...\n");
- if (!map->ip_set)
- clif->setip(ip_str);
- if (!map->char_ip_set)
- chrif->setip(ip_str);
- }
+ ShowInfo("Defaulting to %s as our IP address\n", ip_str);
- battle->config_read(map->BATTLE_CONF_FILENAME);
- atcommand->msg_read(map->MSG_CONF_NAME);
+ if (!map->ip_set)
+ clif->setip(ip_str);
+ if (!map->char_ip_set)
+ chrif->setip(ip_str);
+ }
+
+ battle->config_read(map->BATTLE_CONF_FILENAME);
+ atcommand->msg_read(map->MSG_CONF_NAME);
+ map->inter_config_read(map->INTER_CONF_NAME);
+ logs->config_read(map->LOG_CONF_NAME);
+ }
script->config_read(map->SCRIPT_CONF_NAME);
- map->inter_config_read(map->INTER_CONF_NAME);
- logs->config_read(map->LOG_CONF_NAME);
map->id_db = idb_alloc(DB_OPT_BASE);
map->pc_db = idb_alloc(DB_OPT_BASE); //Added for reliable map->id2sd() use. [Skotlex]
@@ -5538,53 +5548,77 @@ int do_init(int argc, char *argv[])
map->flooritem_ers = ers_new(sizeof(struct flooritem_data),"map.c::map_flooritem_ers",ERS_OPT_NONE);
ers_chunk_size(map->flooritem_ers, 100);
-
- map->sql_init();
- if (logs->config.sql_logs)
- logs->sql_init();
- mapindex_init();
+ if (!minimal) {
+ map->sql_init();
+ if (logs->config.sql_logs)
+ logs->sql_init();
+ }
+
+ i = mapindex_init();
+
+ if (minimal) {
+ // Pretend all maps from the mapindex are on this mapserver
+ CREATE(map->list,struct map_data,i);
+
+ for( i = 0; i < MAX_MAPINDEX; i++ ) {
+ if (mapindex_exists(i)) {
+ map->addmap(mapindex_id2name(i));
+ }
+ }
+ }
+
if(map->enable_grf)
grfio_init(map->GRF_PATH_FILENAME);
map->readallmaps();
- timer->add_func_list(map->freeblock_timer, "map_freeblock_timer");
- timer->add_func_list(map->clearflooritem_timer, "map_clearflooritem_timer");
- timer->add_func_list(map->removemobs_timer, "map_removemobs_timer");
- timer->add_interval(timer->gettick()+1000, map->freeblock_timer, 0, 0, 60*1000);
-
- HPM->load_sub = HPM_map_plugin_load_sub;
- HPM->symbol_defaults_sub = map_hp_symbols;
- HPM->config_read();
- HPM->event(HPET_INIT);
-
- atcommand->init();
- battle->init();
- instance->init();
- chrif->init();
- clif->init();
- ircbot->init();
- script->init();
- itemdb->init();
- skill->init();
- map->read_zone_db();/* read after item and skill initalization */
- mob->init();
- pc->init();
- status->init();
- party->init();
- guild->init();
- gstorage->init();
- pet->init();
- homun->init();
- mercenary->init();
- elemental->init();
- quest->init();
- npc->init();
- unit->init();
- bg->init();
- duel->init();
- vending->init();
+
+ if (!minimal) {
+ timer->add_func_list(map->freeblock_timer, "map_freeblock_timer");
+ timer->add_func_list(map->clearflooritem_timer, "map_clearflooritem_timer");
+ timer->add_func_list(map->removemobs_timer, "map_removemobs_timer");
+ timer->add_interval(timer->gettick()+1000, map->freeblock_timer, 0, 0, 60*1000);
+
+ HPM->load_sub = HPM_map_plugin_load_sub;
+ HPM->symbol_defaults_sub = map_hp_symbols;
+ HPM->config_read();
+ HPM->event(HPET_INIT);
+ }
+
+ atcommand->init(minimal);
+ battle->init(minimal);
+ instance->init(minimal);
+ chrif->init(minimal);
+ clif->init(minimal);
+ ircbot->init(minimal);
+ script->init(minimal);
+ itemdb->init(minimal);
+ skill->init(minimal);
+ if (!minimal)
+ map->read_zone_db();/* read after item and skill initalization */
+ mob->init(minimal);
+ pc->init(minimal);
+ status->init(minimal);
+ party->init(minimal);
+ guild->init(minimal);
+ gstorage->init(minimal);
+ pet->init(minimal);
+ homun->init(minimal);
+ mercenary->init(minimal);
+ elemental->init(minimal);
+ quest->init(minimal);
+ npc->init(minimal);
+ unit->init(minimal);
+ bg->init(minimal);
+ duel->init(minimal);
+ vending->init(minimal);
+
+ if (minimal) {
+ if (npc->parsesrcfile(scriptcheck, false) == 0)
+ exit(EXIT_SUCCESS);
+ exit(EXIT_FAILURE);
+ }
npc->event_do_oninit(); // Init npcs (OnInit)
diff --git a/src/map/map.h b/src/map/map.h
index 6b7d2a630..20e328c88 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -360,6 +360,9 @@ enum _sp {
SP_KILLEDRID=122,
SP_SLOTCHANGE=123,
SP_CHARRENAME=124,
+ SP_MOD_EXP=125,
+ SP_MOD_DROP=126,
+ SP_MOD_DEATH=127,
// Mercenaries
SP_MERCFLEE=165, SP_MERCKILLS=189, SP_MERCFAITH=190,
@@ -1020,7 +1023,7 @@ struct map_interface {
int (*eraseallipport_sub) (DBKey key, DBData *data, va_list va);
char* (*init_mapcache) (FILE *fp);
int (*readfromcache) (struct map_data *m, char *buffer);
- int (*addmap) (char *mapname);
+ int (*addmap) (const char *mapname);
void (*delmapid) (int id);
void (*zone_db_clear) (void);
void (*list_final) (void);
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index 8c74a5e1e..87e7d2f3c 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -317,7 +317,7 @@ int merc_data_received(struct s_mercenary *merc, bool flag) {
md->bl.y = md->ud.to_y;
map->addiddb(&md->bl);
- status_calc_mercenary(md,1);
+ status_calc_mercenary(md,SCO_FIRST);
md->contract_timer = INVALID_TIMER;
merc_contract_init(md);
}
@@ -490,7 +490,10 @@ int read_mercenary_skilldb(void) {
return 0;
}
-void do_init_mercenary(void) {
+void do_init_mercenary(bool minimal) {
+ if (minimal)
+ return;
+
mercenary->read_db();
mercenary->read_skilldb();
diff --git a/src/map/mercenary.h b/src/map/mercenary.h
index 3245606cf..3f2214b65 100644
--- a/src/map/mercenary.h
+++ b/src/map/mercenary.h
@@ -59,7 +59,7 @@ struct mercenary_interface {
/* funcs */
- void (*init) (void);
+ void (*init) (bool minimal);
bool (*class) (int class_);
struct view_data * (*get_viewdata) (int class_);
diff --git a/src/map/mob.c b/src/map/mob.c
index 97f8ea6c1..b8a8ed6c5 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -601,7 +601,7 @@ int mob_spawn_guardian_sub(int tid, int64 tick, int id, intptr_t data) {
memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH);
md->guardian_data->guardup_lv = guardup_lv;
if( guardup_lv )
- status_calc_mob(md, 0); //Give bonuses.
+ status_calc_mob(md, SCO_NONE); //Give bonuses.
return 0;
}
@@ -919,7 +919,7 @@ int mob_spawn (struct mob_data *md)
}
memset(&md->state, 0, sizeof(md->state));
- status_calc_mob(md, 1);
+ status_calc_mob(md, SCO_FIRST);
md->attacked_id = 0;
md->target_id = 0;
md->move_fail_count = 0;
@@ -2332,6 +2332,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
drop_rate = 1;
}
#endif
+ if( sd && sd->status.mod_drop != 100 ) {
+ drop_rate = drop_rate * sd->status.mod_drop / 100;
+ if( drop_rate < 1 )
+ drop_rate = 1;
+ }
+
// attempt to drop the item
if (rnd() % 10000 >= drop_rate)
continue;
@@ -2725,7 +2731,7 @@ int mob_class_change (struct mob_data *md, int class_)
unit->skillcastcancel(&md->bl, 0);
status->set_viewdata(&md->bl, class_);
clif->class_change(&md->bl, md->vd->class_, 1);
- status_calc_mob(md, 1);
+ status_calc_mob(md, SCO_FIRST);
md->ud.state.speed_changed = 1; //Speed change update.
if (battle_config.monster_class_change_recover) {
@@ -4534,7 +4540,12 @@ bool mob_readdb_itemratio(char* str[], int columns, int current)
/**
* read all mob-related databases
*/
-void mob_load(void) {
+void mob_load(bool minimal) {
+ if (minimal) {
+ // Only read the mob db in minimal mode
+ mob->readdb();
+ return;
+ }
sv->readdb(map->db_path, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, mob->readdb_itemratio); // must be read before mobdb
mob->readchatdb();
if (map->db_use_sql_mob_db) {
@@ -4569,7 +4580,7 @@ void mob_reload(void) {
}
}
- mob->load();
+ mob->load(false);
}
void mob_clear_spawninfo()
@@ -4583,15 +4594,18 @@ void mob_clear_spawninfo()
/*==========================================
* Circumference initialization of mob
*------------------------------------------*/
-int do_init_mob(void)
-{ //Initialize the mob database
+int do_init_mob(bool minimal) {
+ // Initialize the mob database
memset(mob->db_data,0,sizeof(mob->db_data)); //Clear the array
- mob->db_data[0] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db)); //This mob is used for random spawns
+ mob->db_data[0] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db)); //This mob is used for random spawns
mob->makedummymobdb(0); //The first time this is invoked, it creates the dummy mob
item_drop_ers = ers_new(sizeof(struct item_drop),"mob.c::item_drop_ers",ERS_OPT_NONE);
item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"mob.c::item_drop_list_ers",ERS_OPT_NONE);
- mob->load();
+ mob->load(minimal);
+
+ if (minimal)
+ return 0;
timer->add_func_list(mob->delayspawn,"mob_delayspawn");
timer->add_func_list(mob->delay_item_drop,"mob_delay_item_drop");
diff --git a/src/map/mob.h b/src/map/mob.h
index 2f425e285..31a8666a2 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -259,7 +259,7 @@ struct mob_interface {
int manuk[8];
int splendide[5];
/* */
- int (*init) (void);
+ int (*init) (bool mimimal);
int (*final) (void);
void (*reload) (void);
/* */
@@ -354,7 +354,7 @@ struct mob_interface {
int (*read_sqlskilldb) (void);
bool (*readdb_race2) (char *fields[], int columns, int current);
bool (*readdb_itemratio) (char *str[], int columns, int current);
- void (*load) (void);
+ void (*load) (bool minimal);
void (*clear_spawninfo) ();
};
diff --git a/src/map/npc.c b/src/map/npc.c
index f0bdd7bd0..9330d59d3 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1253,6 +1253,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) {
}
return 0;
}
+
/*==========================================
* Cash Shop Buy List
*------------------------------------------*/
@@ -1944,7 +1945,7 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con
if( p ) { // <Display name>::<Unique name>
size_t len = p-name;
if( len > NAME_LENGTH ) {
- ShowWarning("npc_parsename: Display name of '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
+ ShowWarning("npc_parsename: Display name of '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
safestrncpy(nd->name, name, sizeof(nd->name));
} else {
memcpy(nd->name, name, len);
@@ -1952,19 +1953,19 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con
}
len = strlen(p+2);
if( len > NAME_LENGTH )
- ShowWarning("npc_parsename: Unique name of '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
+ ShowWarning("npc_parsename: Unique name of '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
safestrncpy(nd->exname, p+2, sizeof(nd->exname));
} else {// <Display name>
size_t len = strlen(name);
if( len > NAME_LENGTH )
- ShowWarning("npc_parsename: Name '%s' is too long (len=%u) in file '%s', line'%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
+ ShowWarning("npc_parsename: Name '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH);
safestrncpy(nd->name, name, sizeof(nd->name));
safestrncpy(nd->exname, name, sizeof(nd->exname));
}
if( *nd->exname == '\0' || strstr(nd->exname,"::") != NULL ) {// invalid
snprintf(newname, ARRAYLENGTH(newname), "0_%d_%d_%d", nd->bl.m, nd->bl.x, nd->bl.y);
- ShowWarning("npc_parsename: Invalid unique name in file '%s', line'%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname);
+ ShowWarning("npc_parsename: Invalid unique name in file '%s', line '%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname);
safestrncpy(nd->exname, newname, sizeof(nd->exname));
}
@@ -1981,7 +1982,7 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con
strcpy(this_mapname, (nd->bl.m == -1 ? "(not on a map)" : mapindex_id2name(map_id2index(nd->bl.m))));
strcpy(other_mapname, (dnd->bl.m == -1 ? "(not on a map)" : mapindex_id2name(map_id2index(dnd->bl.m))));
- ShowWarning("npc_parsename: Duplicate unique name in file '%s', line'%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname);
+ ShowWarning("npc_parsename: Duplicate unique name in file '%s', line '%d'. Renaming '%s' to '%s'.\n", filepath, strline(buffer,start-buffer), nd->exname, newname);
ShowDebug("this npc:\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n", nd->name, nd->exname, this_mapname, nd->bl.x, nd->bl.y);
ShowDebug("other npc in '%s' :\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n",dnd->path, dnd->name, dnd->exname, other_mapname, dnd->bl.x, dnd->bl.y);
safestrncpy(nd->exname, newname, sizeof(nd->exname));
@@ -2240,7 +2241,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s
}
if( type == SHOP && value*0.75 < id->value_sell*1.24 )
{// Exploit possible: you can buy and sell back with profit
- ShowWarning("npc_parse_shop: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) at file '%s', line '%d'.\n",
+ ShowWarning("npc_parse_shop: Item %s [%d] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) in file '%s', line '%d'.\n",
id->name, nameid, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer));
}
//for logs filters, atcommands and iteminfo script command
@@ -2308,7 +2309,7 @@ void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath
// here we check if the label fit into the buffer
if( len > 23 ) {
- ShowError("npc_parse_script: label name longer than 23 chars! '%s'\n (%s)", lname, filepath);
+ ShowError("npc_parse_script: label name longer than 23 chars! (%s) in file '%s'.\n", lname, filepath);
return;
}
@@ -2332,7 +2333,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f
p = strchr(start,'{');
if( p == NULL )
{
- ShowError("npc_skip_script: Missing left curly in file '%s', line'%d'.", filepath, strline(buffer,start-buffer));
+ ShowError("npc_skip_script: Missing left curly in file '%s', line '%d'.\n", filepath, strline(buffer,start-buffer));
return NULL;// can't continue
}
@@ -2368,7 +2369,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f
}
else if( *p == '\0' )
{// end of buffer
- ShowError("Missing %d right curlys at file '%s', line '%d'.\n", curly_count, filepath, strline(buffer,p-buffer));
+ ShowError("Missing %d right curlys in file '%s', line '%d'.\n", curly_count, filepath, strline(buffer,p-buffer));
return NULL;// can't continue
}
}
@@ -2478,7 +2479,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char*
// Loop through labels to export them as necessary
for (i = 0; i < nd->u.scr.label_list_num; i++) {
if (npc->event_export(nd, i)) {
- ShowWarning("npc_parse_script : duplicate event %s::%s (%s)\n",
+ ShowWarning("npc_parse_script: duplicate event %s::%s in file '%s'.\n",
nd->exname, nd->u.scr.label_list[i].name, filepath);
}
npc->timerevent_export(nd, i);
@@ -2529,14 +2530,14 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
// get the npc being duplicated
if( w2[length-1] != ')' || length <= 11 || length-11 >= sizeof(srcname) )
{// does not match 'duplicate(%127s)', name is empty or too long
- ShowError("npc_parse_script: bad duplicate name in file '%s', line '%d' : %s\n", filepath, strline(buffer,start-buffer), w2);
+ ShowError("npc_parse_script: bad duplicate name in file '%s', line '%d': %s\n", filepath, strline(buffer,start-buffer), w2);
return end;// next line, try to continue
}
safestrncpy(srcname, w2+10, length-10);
dnd = npc->name2id(srcname);
if( dnd == NULL) {
- ShowError("npc_parse_script: original npc not found for duplicate in file '%s', line '%d' : %s\n", filepath, strline(buffer,start-buffer), srcname);
+ ShowError("npc_parse_script: original npc not found for duplicate in file '%s', line '%d': %s\n", filepath, strline(buffer,start-buffer), srcname);
return end;// next line, try to continue
}
src_id = dnd->bl.id;
@@ -2547,8 +2548,10 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
x = y = dir = 0;
m = -1;
} else {
- if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 )// <map name>,<x>,<y>,<facing>
- {
+ int fields = sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir);
+ if( type == WARP && fields == 3 ) { // <map name>,<x>,<y>
+ dir = 0;
+ } else if( fields != 4 ) {// <map name>,<x>,<y>,<facing>
ShowError("npc_parse_duplicate: Invalid placement format for duplicate in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
return end;// next line, try to continue
}
@@ -2636,7 +2639,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
// Loop through labels to export them as necessary
for (i = 0; i < nd->u.scr.label_list_num; i++) {
if (npc->event_export(nd, i)) {
- ShowWarning("npc_parse_duplicate : duplicate event %s::%s (%s)\n",
+ ShowWarning("npc_parse_duplicate: duplicate event %s::%s in file '%s'.\n",
nd->exname, nd->u.scr.label_list[i].name, filepath);
}
npc->timerevent_export(nd, i);
@@ -2919,7 +2922,7 @@ const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const cha
if (func_db->put(func_db, DB->str2key(w3), DB->ptr2data(scriptroot), &old_data))
{
struct script_code *oldscript = (struct script_code*)DB->data2ptr(&old_data);
- ShowInfo("npc_parse_function: Overwriting user function [%s] (%s:%d)\n", w3, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_function: Overwriting user function [%s] in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
script->free_vars(oldscript->script_vars);
aFree(oldscript->script_buf);
aFree(oldscript);
@@ -2977,33 +2980,33 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
mobspawn.m = (unsigned short)m;
if( x < 0 || x >= map->list[mobspawn.m].xs || y < 0 || y >= map->list[mobspawn.m].ys ) {
- ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s (file '%s', line '%d').\n", map->list[mobspawn.m].name, x, y, (map->list[mobspawn.m].xs-1), (map->list[mobspawn.m].ys-1), w1, w3, filepath, strline(buffer,start-buffer));
+ ShowError("npc_parse_mob: Spawn coordinates out of range: %s (%d,%d), map size is (%d,%d) - %s %s in file '%s', line '%d'.\n", map->list[mobspawn.m].name, x, y, (map->list[mobspawn.m].xs-1), (map->list[mobspawn.m].ys-1), w1, w3, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// skip and continue
}
// check monster ID if exists!
if( mob->db_checkid(class_) == 0 ) {
- ShowError("npc_parse_mob: Unknown mob ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer));
+ ShowError("npc_parse_mob: Unknown mob ID %d in file '%s', line '%d'.\n", class_, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// skip and continue
}
if( num < 1 || num > 1000 ) {
- ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] (file '%s', line '%d').\n", num, filepath, strline(buffer,start-buffer));
+ ShowError("npc_parse_mob: Invalid number of monsters %d, must be inside the range [1,1000] in file '%s', line '%d'.\n", num, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// skip and continue
}
if( (mobspawn.state.size < 0 || mobspawn.state.size > 2) && size != -1 ) {
- ShowError("npc_parse_mob: Invalid size number %d for mob ID %d (file '%s', line '%d').\n", mobspawn.state.size, class_, filepath, strline(buffer, start - buffer));
+ ShowError("npc_parse_mob: Invalid size number %d for mob ID %d in file '%s', line '%d'.\n", mobspawn.state.size, class_, filepath, strline(buffer, start - buffer));
return strchr(start, '\n');
}
if( (mobspawn.state.ai < 0 || mobspawn.state.ai > 4) && ai != -1 ) {
- ShowError("npc_parse_mob: Invalid ai %d for mob ID %d (file '%s', line '%d').\n", mobspawn.state.ai, class_, filepath, strline(buffer, start - buffer));
+ ShowError("npc_parse_mob: Invalid ai %d for mob ID %d in file '%s', line '%d'.\n", mobspawn.state.ai, class_, filepath, strline(buffer, start - buffer));
return strchr(start, '\n');
}
if( (mob_lv == 0 || mob_lv > MAX_LEVEL) && mob_lv != -1 ) {
- ShowError("npc_parse_mob: Invalid level %d for mob ID %d (file '%s', line '%d').\n", mob_lv, class_, filepath, strline(buffer, start - buffer));
+ ShowError("npc_parse_mob: Invalid level %d for mob ID %d in file '%s', line '%d'.\n", mob_lv, class_, filepath, strline(buffer, start - buffer));
return strchr(start, '\n');
}
@@ -3033,7 +3036,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
}
if(mobspawn.delay1>0xfffffff || mobspawn.delay2>0xfffffff) {
- ShowError("npc_parse_mob: Invalid spawn delays %u %u (file '%s', line '%d').\n", mobspawn.delay1, mobspawn.delay2, filepath, strline(buffer,start-buffer));
+ ShowError("npc_parse_mob: Invalid spawn delays %u %u in file '%s', line '%d'.\n", mobspawn.delay1, mobspawn.delay2, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// skip and continue
}
@@ -3047,7 +3050,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
//Verify dataset.
if( !mob->parse_dataset(&mobspawn) ) {
- ShowError("npc_parse_mob: Invalid dataset for monster ID %d (file '%s', line '%d').\n", class_, filepath, strline(buffer,start-buffer));
+ ShowError("npc_parse_mob: Invalid dataset for monster ID %d in file '%s', line '%d'.\n", class_, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// skip and continue
}
@@ -3141,7 +3144,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
map->list[m].save.x = savex;
map->list[m].save.y = savey;
if (!map->list[m].save.map) {
- ShowWarning("npc_parse_mapflag: Specified save point map '%s' for mapflag 'nosave' not found (file '%s', line '%d'), using 'SavePoint'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", savemap, filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
+ ShowWarning("npc_parse_mapflag: Specified save point map '%s' for mapflag 'nosave' not found in file '%s', line '%d', using 'SavePoint'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", savemap, filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
map->list[m].save.x = -1;
map->list[m].save.y = -1;
}
@@ -3179,11 +3182,11 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
map->list[m].flag.gvg = 0;
map->list[m].flag.gvg_dungeon = 0;
map->list[m].flag.gvg_castle = 0;
- ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s (file '%s', line '%d').\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
}
if( state && map->list[m].flag.battleground ) {
map->list[m].flag.battleground = 0;
- ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
}
if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) && map->list[m].zone != zone ) {
map->zone_change(m,zone,start,buffer,filepath);
@@ -3229,11 +3232,11 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
map->list[m].flag.gvg = state;
if( state && map->list[m].flag.pvp ) {
map->list[m].flag.pvp = 0;
- ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
}
if( state && map->list[m].flag.battleground ) {
map->list[m].flag.battleground = 0;
- ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
}
if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_GVG_NAME)) && map->list[m].zone != zone ) {
map->zone_change(m,zone,start,buffer,filepath);
@@ -3261,13 +3264,13 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
if( map->list[m].flag.battleground && map->list[m].flag.pvp ) {
map->list[m].flag.pvp = 0;
- ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
}
if( map->list[m].flag.battleground && (map->list[m].flag.gvg || map->list[m].flag.gvg_dungeon || map->list[m].flag.gvg_castle) ) {
map->list[m].flag.gvg = 0;
map->list[m].flag.gvg_dungeon = 0;
map->list[m].flag.gvg_castle = 0;
- ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s (file '%s', line '%d').\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
}
if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_BG_NAME)) && map->list[m].zone != zone ) {
@@ -3368,11 +3371,11 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
}
if( modifier[0] == '\0' ) {
- ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
} else if( !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) ) {
- ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n",skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n",skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
} else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
- ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n", atoi(modifier), skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_unit_duration' flag! removing flag from %s in file '%s', line '%d'.\n", atoi(modifier), skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
} else {
int idx = map->list[m].unit_count;
@@ -3422,11 +3425,11 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
}
if( modifier[0] == '\0' ) {
- ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_skill_damage' flag! removing flag from %s (file '%s', line '%d').\n", map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", map->list[m].name, filepath, strline(buffer,start-buffer));
} else if( !( skill_id = skill->name2id(skill_name) ) ) {
- ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_skill_damage' flag! removing flag from %s (file '%s', line '%d').\n", skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
} else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) {
- ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_skill_damage' flag! removing flag from %s (file '%s', line '%d').\n", atoi(modifier), skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_skill_damage' flag! removing flag from %s in file '%s', line '%d'.\n", atoi(modifier), skill_name, map->list[m].name, filepath, strline(buffer,start-buffer));
} else {
int idx = map->list[m].skill_count;
@@ -3464,7 +3467,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
struct map_zone_data *zone;
if( !(zone = strdb_get(map->zone_db, w4)) ) {
- ShowWarning("npc_parse_mapflag: Invalid zone '%s'! removing flag from %s (file '%s', line '%d').\n", w4, map->list[m].name, filepath, strline(buffer,start-buffer));
+ ShowWarning("npc_parse_mapflag: Invalid zone '%s'! removing flag from %s in file '%s', line '%d'.\n", w4, map->list[m].name, filepath, strline(buffer,start-buffer));
} else if( map->list[m].zone != zone ) {
map->zone_change(m,zone,start,buffer,filepath);
}
@@ -3489,15 +3492,14 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
} else if ( !strcmpi(w3,"nocashshop") ) {
map->list[m].flag.nocashshop = (state) ? 1 : 0;
} else
- ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer));
+ ShowError("npc_parse_mapflag: unrecognized mapflag '%s' in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
return strchr(start,'\n');// continue
}
//Read file and create npc/func/mapflag/monster... accordingly.
//@runOnInit should we exec OnInit when it's done ?
-void npc_parsesrcfile(const char* filepath, bool runOnInit)
-{
+int npc_parsesrcfile(const char* filepath, bool runOnInit) {
int16 m, x, y;
int lines = 0;
FILE* fp;
@@ -3510,7 +3512,7 @@ void npc_parsesrcfile(const char* filepath, bool runOnInit)
if( fp == NULL )
{
ShowError("npc_parsesrcfile: File not found '%s'.\n", filepath);
- return;
+ return -1;
}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
@@ -3523,7 +3525,7 @@ void npc_parsesrcfile(const char* filepath, bool runOnInit)
ShowError("npc_parsesrcfile: Failed to read file '%s' - %s\n", filepath, strerror(errno));
aFree(buffer);
fclose(fp);
- return;
+ return -1;
}
fclose(fp);
@@ -3658,7 +3660,7 @@ void npc_parsesrcfile(const char* filepath, bool runOnInit)
}
aFree(buffer);
- return;
+ return 0;
}
int npc_script_event(struct map_session_data* sd, enum npce_event type)
@@ -3935,8 +3937,7 @@ static void npc_debug_warps(void) {
/*==========================================
* npc initialization
*------------------------------------------*/
-int do_init_npc(void)
-{
+int do_init_npc(bool minimal) {
struct npc_src_list *file;
int i;
@@ -3963,43 +3964,47 @@ int do_init_npc(void)
npc->name_db = strdb_alloc(DB_OPT_BASE, NAME_LENGTH);
npc->path_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0);
- npc->timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE);
-
npc_last_npd = NULL;
npc_last_path = NULL;
npc_last_ref = NULL;
- // process all npc files
- ShowStatus("Loading NPCs...\r");
- for( file = npc->src_files; file != NULL; file = file->next ) {
- ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name);
- npc->parsesrcfile(file->name,false);
+ if (!minimal) {
+ npc->timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE);
+
+ // process all npc files
+ ShowStatus("Loading NPCs...\r");
+ for( file = npc->src_files; file != NULL; file = file->next ) {
+ ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name);
+ npc->parsesrcfile(file->name,false);
+ }
+ ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n"
+ "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
+ npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
}
- ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Warps\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Shops\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n"
- "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
- npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
itemdb->name_constants();
+
+ if (!minimal) {
+ map->zone_init();
- map->zone_init();
-
- npc->motd = npc->name2id("HerculesMOTD"); /* [Ind/Hercules] */
+ npc->motd = npc->name2id("HerculesMOTD"); /* [Ind/Hercules] */
- // set up the events cache
- memset(script_event, 0, sizeof(script_event));
- npc->read_event_script();
+ // set up the events cache
+ memset(script_event, 0, sizeof(script_event));
+ npc->read_event_script();
- //Debug function to locate all endless loop warps.
- if (battle_config.warp_point_debug)
- npc->debug_warps();
+ //Debug function to locate all endless loop warps.
+ if (battle_config.warp_point_debug)
+ npc->debug_warps();
- timer->add_func_list(npc->event_do_clock,"npc_event_do_clock");
- timer->add_func_list(npc->timerevent,"npc_timerevent");
+ timer->add_func_list(npc->event_do_clock,"npc_event_do_clock");
+ timer->add_func_list(npc->timerevent,"npc_timerevent");
+ }
// Init dummy NPC
npc->fake_nd = (struct npc_data *)aCalloc(1,sizeof(struct npc_data));
diff --git a/src/map/npc.h b/src/map/npc.h
index 5ec201e55..10f3406b4 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -140,7 +140,7 @@ struct npc_interface {
struct npc_src_list *src_files;
struct unit_data base_ud;
/* */
- int (*init) (void);
+ int (*init) (bool minimal);
int (*final) (void);
/* */
int (*get_new_npc_id) (void);
@@ -218,7 +218,7 @@ struct npc_interface {
void (*parse_mob2) (struct spawn_data *mobspawn);
const char* (*parse_mob) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath);
const char* (*parse_mapflag) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath);
- void (*parsesrcfile) (const char *filepath, bool runOnInit);
+ int (*parsesrcfile) (const char *filepath, bool runOnInit);
int (*script_event) (struct map_session_data *sd, enum npce_event type);
void (*read_event_script) (void);
int (*path_db_clear_sub) (DBKey key, DBData *data, va_list args);
diff --git a/src/map/packets.h b/src/map/packets.h
index 918f0a10f..55a85e182 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -2646,4 +2646,8 @@ packet(0x020d,-1);
packetKeys(0x7E241DE0,0x5E805580,0x3D807D80); /* Thanks to Shakto */
#endif
+#if defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3)
+ packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3);
+#endif
+
#endif /* _PACKETS_H_ */
diff --git a/src/map/party.c b/src/map/party.c
index 69b343fb7..16b9d99f9 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -856,7 +856,7 @@ int party_send_xy_timer(int tid, int64 tick, int id, intptr_t data) {
for( i = 0; i < MAX_PARTY; i++ )
{
struct map_session_data* sd = p->data[i].sd;
- if( !sd ) continue;
+ if( !sd || sd->bg_id ) continue;
if( p->data[i].x != sd->bl.x || p->data[i].y != sd->bl.y )
{// perform position update
@@ -1313,7 +1313,10 @@ void do_final_party(void) {
db_destroy(party->booking_db); // Party Booking [Spiria]
}
// Constructor, init vars
-void do_init_party(void) {
+void do_init_party(bool minimal) {
+ if (minimal)
+ return;
+
party->db = idb_alloc(DB_OPT_RELEASE_DATA);
party->booking_db = idb_alloc(DB_OPT_RELEASE_DATA); // Party Booking [Spiria]
timer->add_func_list(party->send_xy_timer, "party_send_xy_timer");
diff --git a/src/map/party.h b/src/map/party.h
index ab14d1a31..91f4c1b7d 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -73,7 +73,7 @@ struct party_interface {
DBMap* booking_db; // int char_id -> struct party_booking_ad_info* (releases data) // Party Booking [Spiria]
unsigned long booking_nextid;
/* funcs */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
/* */
struct party_data* (*search) (int party_id);
diff --git a/src/map/pc.c b/src/map/pc.c
index 6c4ebe149..31a38372a 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -72,7 +72,7 @@ struct map_session_data* pc_get_dummy_sd(void)
{
struct map_session_data *dummy_sd;
CREATE(dummy_sd, struct map_session_data, 1);
- dummy_sd->group = pc_group_get_dummy_group(); // map_session_data.group is expected to be non-NULL at all times
+ dummy_sd->group = pcg->get_dummy_group(); // map_session_data.group is expected to be non-NULL at all times
return dummy_sd;
}
@@ -82,7 +82,7 @@ struct map_session_data* pc_get_dummy_sd(void)
*/
int pc_get_group_level(struct map_session_data *sd)
{
- return pc_group_get_level(sd->group);
+ return pcg->get_level(sd->group);
}
/**
@@ -93,7 +93,7 @@ int pc_get_group_level(struct map_session_data *sd)
*/
int pc_set_group(struct map_session_data *sd, int group_id)
{
- GroupSettings *group = pc_group_id2group(group_id);
+ GroupSettings *group = pcg->id2group(group_id);
if (group == NULL)
return 1;
sd->group_id = group_id;
@@ -104,9 +104,9 @@ int pc_set_group(struct map_session_data *sd, int group_id)
/**
* Checks if player has permission to perform action.
*/
-bool pc_has_permission(struct map_session_data *sd, enum e_pc_permission permission)
+bool pc_has_permission(struct map_session_data *sd, unsigned int permission)
{
- return ((sd->extra_temp_permissions&permission) != 0 || pc_group_has_permission(sd->group, permission));
+ return ((sd->extra_temp_permissions&permission) != 0 || pcg->has_permission(sd->group, permission));
}
/**
@@ -114,7 +114,7 @@ bool pc_has_permission(struct map_session_data *sd, enum e_pc_permission permiss
*/
bool pc_should_log_commands(struct map_session_data *sd)
{
- return pc_group_should_log_commands(sd->group);
+ return pcg->should_log_commands(sd->group);
}
int pc_invincible_timer(int tid, int64 tick, int id, intptr_t data) {
@@ -1340,7 +1340,7 @@ int pc_reg_received(struct map_session_data *sd)
pc->load_combo(sd);
- status_calc_pc(sd,1);
+ status_calc_pc(sd,SCO_FIRST|SCO_FORCE);
chrif->scdata_request(sd->status.account_id, sd->status.char_id);
intif->Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox
@@ -2048,7 +2048,7 @@ int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus)
autobonus->active = timer->add(timer->gettick()+autobonus->duration, pc->endautobonus, sd->bl.id, (intptr_t)autobonus);
sd->state.autobonus |= autobonus->pos;
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
return 0;
}
@@ -2062,7 +2062,7 @@ int pc_endautobonus(int tid, int64 tick, int id, intptr_t data) {
autobonus->active = INVALID_TIMER;
sd->state.autobonus &= ~autobonus->pos;
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
return 0;
}
@@ -3569,7 +3569,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) {
} else
clif->addskill(sd,id);
if( !skill->db[index].inf ) //Only recalculate for passive skills.
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_NONE);
break;
case 1: //Item bonus skill.
if( sd->status.skill[index].id == id ) {
@@ -3603,7 +3603,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) {
} else
clif->addskill(sd,id);
if( !skill->db[index].inf ) //Only recalculate for passive skills.
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_NONE);
break;
default: //Unknown flag?
return 0;
@@ -5827,13 +5827,13 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
} while ((next=pc->nextbaseexp(sd)) > 0 && sd->status.base_exp >= next);
if (battle_config.pet_lv_rate && sd->pd) //<Skotlex> update pet's level
- status_calc_pet(sd->pd,0);
+ status_calc_pet(sd->pd,SCO_NONE);
clif->updatestatus(sd,SP_STATUSPOINT);
clif->updatestatus(sd,SP_BASELEVEL);
clif->updatestatus(sd,SP_BASEEXP);
clif->updatestatus(sd,SP_NEXTBASEEXP);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
status_percent_heal(&sd->bl,100,100);
if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
@@ -5893,7 +5893,7 @@ int pc_checkjoblevelup(struct map_session_data *sd)
clif->updatestatus(sd,SP_JOBEXP);
clif->updatestatus(sd,SP_NEXTJOBEXP);
clif->updatestatus(sd,SP_SKILLPOINT);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
clif->misceffect(&sd->bl,1);
if (pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd))
clif->status_change(&sd->bl,SI_DEVIL1, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL.
@@ -5927,6 +5927,12 @@ void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned in
*job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * bonus/100., 1, UINT_MAX);
+ if( sd->status.mod_exp != 100 ) {
+ *base_exp = (unsigned int) cap_value((double)*base_exp * sd->status.mod_exp/100., 1, UINT_MAX);
+ *job_exp = (unsigned int) cap_value((double)*job_exp * sd->status.mod_exp/100., 1, UINT_MAX);
+
+ }
+
return;
}
/*==========================================
@@ -6181,7 +6187,7 @@ int pc_statusup(struct map_session_data* sd, int type)
val = pc->setstat(sd, type, pc->getstat(sd,type) + 1);
sd->status.status_point -= need;
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
// update increase cost indicator
if( need != pc->need_status_point(sd,type,1) )
@@ -6221,7 +6227,7 @@ int pc_statusup2(struct map_session_data* sd, int type, int val)
max = pc_maxparameter(sd);
val = pc->setstat(sd, type, cap_value(pc->getstat(sd,type) + val, 1, max));
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
// update increase cost indicator
if( need != pc->need_status_point(sd,type,1) )
@@ -6264,7 +6270,7 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
sd->status.skill[index].lv++;
sd->status.skill_point--;
if( !skill->db[index].inf )
- status_calc_pc(sd,0); // Only recalculate for passive skills.
+ status_calc_pc(sd,SCO_NONE); // Only recalculate for passive skills.
else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )
pc->calc_skilltree(sd); // Required to grant all TK Ranger skills.
else
@@ -6337,7 +6343,7 @@ int pc_allskillup(struct map_session_data *sd)
sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_); // celest
}
}
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
//Required because if you could level up all skills previously,
//the update will not be sent as only the lv variable changes.
clif->skillinfoblock(sd);
@@ -6427,7 +6433,7 @@ int pc_resetlvl(struct map_session_data* sd,int type)
if ((type == 1 || type == 2 || type == 3) && sd->status.party_id)
party->send_levelup(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
clif->skillinfoblock(sd);
return 0;
@@ -6492,7 +6498,7 @@ int pc_resetstate(struct map_session_data* sd)
pc_setglobalreg(sd,"TK_MISSION_ID", 0);
}
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
return 1;
}
@@ -6603,7 +6609,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( flag&1 ) {
clif->updatestatus(sd,SP_SKILLPOINT);
clif->skillinfoblock(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
}
return skill_point;
@@ -6857,7 +6863,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
) { // monster level up [Valaris]
clif->misceffect(&md->bl,0);
md->level++;
- status_calc_mob(md, 0);
+ status_calc_mob(md, SCO_NONE);
status_percent_heal(src,10,0);
if( battle_config.show_mob_info&4 )
@@ -6949,47 +6955,55 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
// changed penalty options, added death by player if pk_mode [Valaris]
if( battle_config.death_penalty_type
- && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty
- && !map->list[sd->bl.m].flag.noexppenalty && !map_flag_gvg2(sd->bl.m)
- && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY]
- ) {
- unsigned int base_penalty =0;
+ && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty
+ && !map->list[sd->bl.m].flag.noexppenalty && !map_flag_gvg2(sd->bl.m)
+ && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY]
+ ) {
+ unsigned int base_penalty = 0;
if (battle_config.death_penalty_base > 0) {
+
switch (battle_config.death_penalty_type) {
case 1:
base_penalty = (unsigned int) ((double)pc->nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000);
- break;
+ break;
case 2:
base_penalty = (unsigned int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000);
- break;
+ break;
}
+
if(base_penalty) {
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
+ if( sd->status.mod_death != 100 )
+ base_penalty = base_penalty * sd->status.mod_death / 100;
sd->status.base_exp -= min(sd->status.base_exp, base_penalty);
clif->updatestatus(sd,SP_BASEEXP);
}
}
- if(battle_config.death_penalty_job > 0)
- {
+
+ if(battle_config.death_penalty_job > 0) {
base_penalty = 0;
+
switch (battle_config.death_penalty_type) {
case 1:
base_penalty = (unsigned int) ((double)pc->nextjobexp(sd) * (double)battle_config.death_penalty_job/10000);
- break;
+ break;
case 2:
base_penalty = (unsigned int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000);
- break;
+ break;
}
+
if(base_penalty) {
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
+ if( sd->status.mod_death != 100 )
+ base_penalty = base_penalty * sd->status.mod_death / 100;
sd->status.job_exp -= min(sd->status.job_exp, base_penalty);
clif->updatestatus(sd,SP_JOBEXP);
}
}
- if(battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty)
- {
+
+ if(battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty) {
base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.);
if(base_penalty)
pc->payzeny(sd, base_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL);
@@ -7141,6 +7155,9 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_KILLEDRID: val = sd->killedrid; break;
case SP_SLOTCHANGE: val = sd->status.slotchange; break;
case SP_CHARRENAME: val = sd->status.rename; break;
+ case SP_MOD_EXP: val = sd->status.mod_exp; break;
+ case SP_MOD_DROP: val = sd->status.mod_drop; break;
+ case SP_MOD_DEATH: val = sd->status.mod_death; break;
case SP_CRITICAL: val = sd->battle_status.cri/10; break;
case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break;
case SP_BASE_ATK: val = sd->battle_status.batk; break;
@@ -7273,7 +7290,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
clif->updatestatus(sd, SP_NEXTBASEEXP);
clif->updatestatus(sd, SP_STATUSPOINT);
clif->updatestatus(sd, SP_BASEEXP);
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
if(sd->status.party_id)
{
party->send_levelup(sd);
@@ -7290,7 +7307,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
// clif->updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom
clif->updatestatus(sd, SP_NEXTJOBEXP);
clif->updatestatus(sd, SP_JOBEXP);
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
break;
case SP_SKILLPOINT:
sd->status.skill_point = val;
@@ -7388,6 +7405,15 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
case SP_CHARRENAME:
sd->status.rename = val;
return 1;
+ case SP_MOD_EXP:
+ sd->status.mod_exp = val;
+ return 1;
+ case SP_MOD_DROP:
+ sd->status.mod_drop = val;
+ return 1;
+ case SP_MOD_DEATH:
+ sd->status.mod_death = val;
+ return 1;
default:
ShowError("pc_setparam: Attempted to set unknown parameter '%d'.\n", type);
return 0;
@@ -7700,7 +7726,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
if(sd->status.manner < 0)
clif->changestatus(sd,SP_MANNER,sd->status.manner);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
pc->checkallowskill(sd);
pc->equiplookall(sd);
@@ -7823,11 +7849,11 @@ int pc_setoption(struct map_session_data *sd,int type)
if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc->checkskill(sd,RK_DRAGONTRAINING) > 0) ) {
// Mounting
clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_RIDING, 0, 0, 0);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
} else if( (!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON) ) {
// Dismount
clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_RIDING);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
#ifndef NEW_CARTS
@@ -7835,11 +7861,11 @@ int pc_setoption(struct map_session_data *sd,int type)
clif->cartlist(sd);
clif->updatestatus(sd, SP_CARTINFO);
if(pc->checkskill(sd, MC_PUSHCART) < 10)
- status_calc_pc(sd,0); //Apply speed penalty.
+ status_calc_pc(sd,SCO_NONE); //Apply speed penalty.
} else if( !( type&OPTION_CART ) && p_type&OPTION_CART ){ //Cart Off
clif->clearcart(sd->fd);
if(pc->checkskill(sd, MC_PUSHCART) < 10)
- status_calc_pc(sd,0); //Remove speed penalty.
+ status_calc_pc(sd,SCO_NONE); //Remove speed penalty.
}
#endif
@@ -7851,18 +7877,18 @@ int pc_setoption(struct map_session_data *sd,int type)
if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) {
if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting
clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER, 0, 0, 0);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
} else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount
clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
}
if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) {
int i;
if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) )
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_NONE);
else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR )
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_NONE);
for( i = 0; i < SC_MAX; i++ ){
if ( !sd->sc.data[i] || !status->get_sc_type(i) )
continue;
@@ -7941,7 +7967,7 @@ int pc_setcart(struct map_session_data *sd,int type) {
}
if(pc->checkskill(sd, MC_PUSHCART) < 10)
- status_calc_pc(sd,0); //Recalc speed penalty.
+ status_calc_pc(sd,SCO_NONE); //Recalc speed penalty.
#else
// Update option
option = sd->sc.option;
@@ -8193,7 +8219,7 @@ int pc_setregistry(struct map_session_data *sd,const char *reg,int val,int type)
i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
sd->die_counter = val;
if( i )
- status_calc_pc(sd,0); // Lost the bonus.
+ status_calc_pc(sd,SCO_NONE); // Lost the bonus.
}
else if( !strcmp(reg,"COOK_MASTERY") && sd->cook_mastery != val )
{
@@ -8797,7 +8823,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
}
}
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
if (flag) //Update skill data
clif->skillinfoblock(sd);
@@ -8962,7 +8988,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
if(flag&1 || status_cacl) {
pc->checkallowskill(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
if(sd->sc.data[SC_CRUCIS] && !battle->check_undead(sd->battle_status.race,sd->battle_status.def_ele))
@@ -9067,7 +9093,7 @@ int pc_checkitem(struct map_session_data *sd)
if( calc_flag && sd->state.active ) {
pc->checkallowskill(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
return 0;
@@ -9452,10 +9478,16 @@ void pc_overheat(struct map_session_data *sd, int val) {
*/
bool pc_isautolooting(struct map_session_data *sd, int nameid)
{
- int i;
- if( !sd->state.autolooting )
+ int i = 0;
+
+ if (sd->state.autoloottype && sd->state.autoloottype&(1<<itemdb_type(nameid)))
+ return true;
+
+ if (!sd->state.autolooting)
return false;
+
ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == nameid);
+
return (i != AUTOLOOTITEM_SIZE);
}
@@ -10232,6 +10264,7 @@ void pc_bank_withdraw(struct map_session_data *sd, int money) {
/* status change data arrived from char-server */
void pc_scdata_received(struct map_session_data *sd) {
pc->inventory_rentals(sd);
+ clif->show_modifiers(sd);
}
/*==========================================
@@ -10241,13 +10274,15 @@ void do_final_pc(void) {
db_destroy(pc->itemcd_db);
- do_final_pc_groups();
+ pcg->final();
ers_destroy(pc->sc_display_ers);
return;
}
-void do_init_pc(void) {
+void do_init_pc(bool minimal) {
+ if (minimal)
+ return;
pc->itemcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
@@ -10279,7 +10314,7 @@ void do_init_pc(void) {
pc->night_timer_tid = timer->add_interval(timer->gettick() + day_duration + (map->night_flag ? night_duration : 0), pc->map_night_timer, 0, 0, day_duration + night_duration);
}
- do_init_pc_groups();
+ pcg->init();
pc->sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.c:sc_display_ers", ERS_OPT_NONE);
}
@@ -10295,7 +10330,7 @@ void pc_defaults(void) {
{ SG_MOON_ANGER, SG_MOON_BLESS, SG_MOON_COMFORT, "PC_FEEL_MOON", "PC_HATE_MOB_MOON", is_day_of_moon },
{ SG_STAR_ANGER, SG_STAR_BLESS, SG_STAR_COMFORT, "PC_FEEL_STAR", "PC_HATE_MOB_STAR", is_day_of_star }
};
- unsigned short equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO};
+ unsigned int equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO, EQP_SHADOW_ARMOR, EQP_SHADOW_WEAPON, EQP_SHADOW_SHIELD, EQP_SHADOW_SHOES, EQP_SHADOW_ACC_R, EQP_SHADOW_ACC_L };
pc = &pc_s;
diff --git a/src/map/pc.h b/src/map/pc.h
index d517d8fcf..3645fc599 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -166,6 +166,7 @@ struct map_session_data {
short pmap; // Previous map on Map Change
unsigned short autoloot;
unsigned short autolootid[AUTOLOOTITEM_SIZE]; // [Zephyrus]
+ unsigned short autoloottype;
unsigned int autolooting : 1; //performance-saver, autolooting state for @alootid
unsigned short autobonus; //flag to indicate if an autobonus is activated. [Inkfish]
unsigned int gmaster_flag : 1;
@@ -731,7 +732,7 @@ struct pc_interface {
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
unsigned int level_penalty[3][RC_MAX][MAX_LEVEL*2+1];
#endif
- unsigned short equip_pos[EQI_MAX];
+ unsigned int equip_pos[EQI_MAX];
/* */
struct skill_tree_entry skill_tree[CLASS_COUNT][MAX_SKILL_TREE];
struct fame_list smith_fame_list[MAX_FAME_LIST];
@@ -741,7 +742,7 @@ struct pc_interface {
/* */
struct eri *sc_display_ers;
/* funcs */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
struct map_session_data* (*get_dummy_sd) (void);
@@ -752,7 +753,7 @@ struct pc_interface {
bool (*can_give_bounded_items) (struct map_session_data *sd);
bool (*can_use_command) (struct map_session_data *sd, const char *command);
- bool (*has_permission) (struct map_session_data *sd, enum e_pc_permission permission);
+ bool (*has_permission) (struct map_session_data *sd, unsigned int permission);
int (*set_group) (struct map_session_data *sd, int group_id);
bool (*should_log_commands) (struct map_session_data *sd);
diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c
index 41bc19cba..78d111b1c 100644
--- a/src/map/pc_groups.c
+++ b/src/map/pc_groups.c
@@ -16,53 +16,10 @@
#include "map.h" // mapiterator
#include "pc.h" // pc->set_group()
-// Cached config settings for quick lookup
-struct GroupSettings {
- unsigned int id; // groups.[].id
- int level; // groups.[].level
- char *name; // copy of groups.[].name
- unsigned int e_permissions; // packed groups.[].permissions
- bool log_commands; // groups.[].log_commands
- int index; // internal index of the group (contiguous range starting at 0) [Ind]
- /// Following are used/available only during config reading
- config_setting_t *commands; // groups.[].commands
- config_setting_t *permissions; // groups.[].permissions
- config_setting_t *inherit; // groups.[].inherit
- bool inheritance_done; // have all inheritance rules been evaluated?
- config_setting_t *root; // groups.[]
-};
-
-const struct pc_permission_name_table pc_g_permission_name[NUM_PC_PERM] = {
- { "can_trade", PC_PERM_TRADE },
- { "can_party", PC_PERM_PARTY },
- { "all_skill", PC_PERM_ALL_SKILL },
- { "all_equipment", PC_PERM_USE_ALL_EQUIPMENT },
- { "skill_unconditional", PC_PERM_SKILL_UNCONDITIONAL },
- { "join_chat", PC_PERM_JOIN_ALL_CHAT },
- { "kick_chat", PC_PERM_NO_CHAT_KICK },
- { "hide_session", PC_PERM_HIDE_SESSION },
- { "who_display_aid", PC_PERM_WHO_DISPLAY_AID },
- { "hack_info", PC_PERM_RECEIVE_HACK_INFO },
- { "any_warp", PC_PERM_WARP_ANYWHERE },
- { "view_hpmeter", PC_PERM_VIEW_HPMETER },
- { "view_equipment", PC_PERM_VIEW_EQUIPMENT },
- { "use_check", PC_PERM_USE_CHECK },
- { "use_changemaptype", PC_PERM_USE_CHANGEMAPTYPE },
- { "all_commands", PC_PERM_USE_ALL_COMMANDS },
- { "receive_requests", PC_PERM_RECEIVE_REQUESTS },
- { "show_bossmobs", PC_PERM_SHOW_BOSS },
- { "disable_pvm", PC_PERM_DISABLE_PVM },
- { "disable_pvp", PC_PERM_DISABLE_PVP },
- { "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD },
- { "hchsys_admin", PC_PERM_HCHSYS_ADMIN },
- { "can_trade_bounded", PC_PERM_TRADE_BOUNDED },
-};
-
-static DBMap* pc_group_db; // id -> GroupSettings
-static DBMap* pc_groupname_db; // name -> GroupSettings
-
static GroupSettings dummy_group; ///< dummy group used in dummy map sessions @see pc_get_dummy_sd()
+struct pc_groups_interface pcg_s;
+
/**
* Returns dummy group.
* Used in dummy map sessions.
@@ -79,7 +36,7 @@ GroupSettings* pc_group_get_dummy_group(void)
*/
static inline GroupSettings* name2group(const char* group_name)
{
- return strdb_get(pc_groupname_db, group_name);
+ return strdb_get(pcg->name_db, group_name);
}
/**
@@ -117,7 +74,7 @@ static void read_config(void) {
continue;
}
- if (pc_group_exists(id)) {
+ if (pcg->exists(id)) {
ShowConfigWarning(group, "pc_groups:read_config: duplicate group id %d, removing...", i);
config_setting_remove_elem(groups, i);
--i;
@@ -163,15 +120,15 @@ static void read_config(void) {
group_settings->root = group;
group_settings->index = i;
- strdb_put(pc_groupname_db, groupname, group_settings);
- idb_put(pc_group_db, id, group_settings);
+ strdb_put(pcg->name_db, groupname, group_settings);
+ idb_put(pcg->db, id, group_settings);
}
group_count = config_setting_length(groups); // Save number of groups
- assert(group_count == db_size(pc_group_db));
+ assert(group_count == db_size(pcg->db));
// Check if all commands and permissions exist
- iter = db_iterator(pc_group_db);
+ iter = db_iterator(pcg->db);
for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions;
int count = 0, i;
@@ -202,8 +159,8 @@ static void read_config(void) {
const char *name = config_setting_name(permission);
int j;
- ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0);
- if (j == ARRAYLENGTH(pc_g_permission_name)) {
+ ARR_FIND(0, pcg->permission_count, j, strcmp(pcg->permissions[j].name, name) == 0);
+ if (j == pcg->permission_count) {
ShowConfigWarning(permission, "pc_groups:read_config: non-existent permission name '%s', removing...", name);
config_setting_remove(permissions, name);
--i;
@@ -216,7 +173,7 @@ static void read_config(void) {
// Apply inheritance
i = 0; // counter for processed groups
while (i < group_count) {
- iter = db_iterator(pc_group_db);
+ iter = db_iterator(pcg->db);
for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
config_setting_t *inherit = NULL,
*commands = group_settings->commands,
@@ -281,7 +238,7 @@ static void read_config(void) {
} // while(i < group_count)
// Pack permissions into GroupSettings.e_permissions for faster checking
- iter = db_iterator(pc_group_db);
+ iter = db_iterator(pcg->db);
for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
config_setting_t *permissions = group_settings->permissions;
int i, count = config_setting_length(permissions);
@@ -294,8 +251,8 @@ static void read_config(void) {
if (val == 0) // does not have this permission
continue;
- ARR_FIND(0, ARRAYLENGTH(pc_g_permission_name), j, strcmp(pc_g_permission_name[j].name, name) == 0);
- group_settings->e_permissions |= pc_g_permission_name[j].permission;
+ ARR_FIND(0, pcg->permission_count, j, strcmp(pcg->permissions[j].name, name) == 0);
+ group_settings->e_permissions |= pcg->permissions[j].permission;
}
}
dbi_destroy(iter);
@@ -309,7 +266,7 @@ static void read_config(void) {
config_setting_t **commands = NULL;
CREATE(groups, GroupSettings*, group_count);
CREATE(commands, config_setting_t*, group_count);
- iter = db_iterator(pc_group_db);
+ iter = db_iterator(pcg->db);
for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) {
groups[i] = group_settings;
commands[i] = group_settings->commands;
@@ -333,7 +290,7 @@ static void read_config(void) {
* @param group group
* @param permission permission to check
*/
-bool pc_group_has_permission(GroupSettings *group, enum e_pc_permission permission)
+bool pc_group_has_permission(GroupSettings *group, unsigned int permission)
{
return ((group->e_permissions&permission) != 0);
}
@@ -354,7 +311,7 @@ bool pc_group_should_log_commands(GroupSettings *group)
*/
bool pc_group_exists(int group_id)
{
- return idb_exists(pc_group_db, group_id);
+ return idb_exists(pcg->db, group_id);
}
/**
@@ -362,7 +319,7 @@ bool pc_group_exists(int group_id)
*/
GroupSettings* pc_group_id2group(int group_id)
{
- return idb_get(pc_group_db, group_id);
+ return idb_get(pcg->db, group_id);
}
/**
@@ -399,13 +356,79 @@ int pc_group_get_idx(GroupSettings *group)
}
/**
+ * Insert a new permission
+ * @return inserted key or 0 upon failure.
+ **/
+unsigned int pc_groups_add_permission(const char *name) {
+ uint64 key = 0x1;
+ unsigned char i;
+
+ for(i = 0; i < pcg->permission_count; i++) {
+ if( strcmpi(name,pcg->permissions[i].name) == 0 ) {
+ ShowError("pc_groups_add_permission(%s): failed! duplicate permission name!\n",name);
+ return 0;
+ }
+ }
+
+ if( i != 0 )
+ key = (uint64)pcg->permissions[i - 1].permission << 1;
+
+ if( key >= UINT_MAX ) {
+ ShowError("pc_groups_add_permission(%s): failed! not enough room, too many permissions!\n",name);
+ return 0;
+ }
+
+ i = pcg->permission_count;
+ RECREATE(pcg->permissions, struct pc_groups_permission_table, ++pcg->permission_count);
+
+ pcg->permissions[i].name = aStrdup(name);
+ pcg->permissions[i].permission = (unsigned int)key;
+
+ return (unsigned int)key;
+}
+/**
* Initialize PC Groups: allocate DBMaps and read config.
* @public
*/
-void do_init_pc_groups(void)
-{
- pc_group_db = idb_alloc(DB_OPT_RELEASE_DATA);
- pc_groupname_db = stridb_alloc(DB_OPT_DUP_KEY, 0);
+void do_init_pc_groups(void) {
+ const struct {
+ const char *name;
+ unsigned int permission;
+ } pc_g_defaults[] = {
+ { "can_trade", PC_PERM_TRADE },
+ { "can_party", PC_PERM_PARTY },
+ { "all_skill", PC_PERM_ALL_SKILL },
+ { "all_equipment", PC_PERM_USE_ALL_EQUIPMENT },
+ { "skill_unconditional", PC_PERM_SKILL_UNCONDITIONAL },
+ { "join_chat", PC_PERM_JOIN_ALL_CHAT },
+ { "kick_chat", PC_PERM_NO_CHAT_KICK },
+ { "hide_session", PC_PERM_HIDE_SESSION },
+ { "who_display_aid", PC_PERM_WHO_DISPLAY_AID },
+ { "hack_info", PC_PERM_RECEIVE_HACK_INFO },
+ { "any_warp", PC_PERM_WARP_ANYWHERE },
+ { "view_hpmeter", PC_PERM_VIEW_HPMETER },
+ { "view_equipment", PC_PERM_VIEW_EQUIPMENT },
+ { "use_check", PC_PERM_USE_CHECK },
+ { "use_changemaptype", PC_PERM_USE_CHANGEMAPTYPE },
+ { "all_commands", PC_PERM_USE_ALL_COMMANDS },
+ { "receive_requests", PC_PERM_RECEIVE_REQUESTS },
+ { "show_bossmobs", PC_PERM_SHOW_BOSS },
+ { "disable_pvm", PC_PERM_DISABLE_PVM },
+ { "disable_pvp", PC_PERM_DISABLE_PVP },
+ { "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD },
+ { "hchsys_admin", PC_PERM_HCHSYS_ADMIN },
+ };
+ unsigned char i, len = ARRAYLENGTH(pc_g_defaults);
+
+ for(i = 0; i < len; i++) {
+ unsigned int p;
+ if( ( p = pcg->add_permission(pc_g_defaults[i].name) ) != pc_g_defaults[i].permission )
+ ShowError("do_init_pc_groups: %s error : %d != %d\n",pc_g_defaults[i].name,p,pc_g_defaults[i].permission);
+ }
+
+ pcg->db = idb_alloc(DB_OPT_RELEASE_DATA);
+ pcg->name_db = stridb_alloc(DB_OPT_DUP_KEY, 0);
+
read_config();
}
@@ -426,10 +449,19 @@ static int group_db_clear_sub(DBKey key, DBData *data, va_list args)
*/
void do_final_pc_groups(void)
{
- if (pc_group_db != NULL)
- pc_group_db->destroy(pc_group_db, group_db_clear_sub);
- if (pc_groupname_db != NULL)
- db_destroy(pc_groupname_db);
+ if (pcg->db != NULL)
+ pcg->db->destroy(pcg->db, group_db_clear_sub);
+ if (pcg->name_db != NULL)
+ db_destroy(pcg->name_db);
+
+ if(pcg->permissions != NULL) {
+ unsigned char i;
+ for(i = 0; i < pcg->permission_count; i++)
+ aFree(pcg->permissions[i].name);
+ aFree(pcg->permissions);
+ pcg->permissions = NULL;
+ }
+ pcg->permission_count = 0;
}
/**
@@ -441,8 +473,8 @@ void pc_groups_reload(void) {
struct map_session_data *sd = NULL;
struct s_mapiterator *iter;
- do_final_pc_groups();
- do_init_pc_groups();
+ pcg->final();
+ pcg->init();
/* refresh online users permissions */
iter = mapit_getallusers();
@@ -455,3 +487,31 @@ void pc_groups_reload(void) {
}
mapit->free(iter);
}
+
+/**
+ * Connect Interface
+ **/
+void pc_groups_defaults(void) {
+ pcg = &pcg_s;
+
+ /* */
+ pcg->db = NULL;
+ pcg->name_db = NULL;
+ /* */
+ pcg->permissions = NULL;
+ pcg->permission_count = 0;
+ /* */
+ pcg->init = do_init_pc_groups;
+ pcg->final = do_final_pc_groups;
+ pcg->reload = pc_groups_reload;
+ /* */
+ pcg->get_dummy_group = pc_group_get_dummy_group;
+ pcg->exists = pc_group_exists;
+ pcg->id2group = pc_group_id2group;
+ pcg->has_permission = pc_group_has_permission;
+ pcg->should_log_commands = pc_group_should_log_commands;
+ pcg->get_name = pc_group_get_name;
+ pcg->get_level = pc_group_get_level;
+ pcg->get_idx = pc_group_get_idx;
+ pcg->add_permission = pc_groups_add_permission;
+}
diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h
index 63e7acc51..28c82d619 100644
--- a/src/map/pc_groups.h
+++ b/src/map/pc_groups.h
@@ -30,37 +30,56 @@ enum e_pc_permission {
PC_PERM_DISABLE_PVP = 0x080000, // #20
PC_PERM_DISABLE_CMD_DEAD = 0x100000,
PC_PERM_HCHSYS_ADMIN = 0x200000,
- PC_PERM_TRADE_BOUNDED = 0x400000,
};
-/// Total number of PC permissions (without PC_PERM_NONE).
-/// This is manifest constant for the size of pc_g_permission_name array,
-/// so it's possible to apply sizeof to it [C-FAQ 1.24]
-/// Whenever adding new permission: 1. add enum entry above, 2. add entry into
-/// pc_g_permission_name (in pc.c), 3. increase NUM_PC_PERM below by 1.
-#define NUM_PC_PERM 23
-
-struct pc_permission_name_table {
- const char *name;
- enum e_pc_permission permission;
+// Cached config settings for quick lookup
+struct GroupSettings {
+ unsigned int id; // groups.[].id
+ int level; // groups.[].level
+ char *name; // copy of groups.[].name
+ unsigned int e_permissions; // packed groups.[].permissions
+ bool log_commands; // groups.[].log_commands
+ int index; // internal index of the group (contiguous range starting at 0) [Ind]
+ /// Following are used/available only during config reading
+ config_setting_t *commands; // groups.[].commands
+ config_setting_t *permissions; // groups.[].permissions
+ config_setting_t *inherit; // groups.[].inherit
+ bool inheritance_done; // have all inheritance rules been evaluated?
+ config_setting_t *root; // groups.[]
};
-/// Name <-> enum table for PC permissions
-extern const struct pc_permission_name_table pc_g_permission_name[NUM_PC_PERM];
+struct pc_groups_permission_table {
+ char *name;
+ unsigned int permission;
+};
typedef struct GroupSettings GroupSettings;
-GroupSettings* pc_group_get_dummy_group(void);
-bool pc_group_exists(int group_id);
-GroupSettings* pc_group_id2group(int group_id);
-bool pc_group_has_permission(GroupSettings *group, enum e_pc_permission permission);
-bool pc_group_should_log_commands(GroupSettings *group);
-const char* pc_group_get_name(GroupSettings *group);
-int pc_group_get_level(GroupSettings *group);
-int pc_group_get_idx(GroupSettings *group);
+struct pc_groups_interface {
+ /* */
+ DBMap* db; // id -> GroupSettings
+ DBMap* name_db; // name -> GroupSettings
+ /* */
+ struct pc_groups_permission_table *permissions;
+ unsigned char permission_count;
+ /* */
+ void (*init) (void);
+ void (*final) (void);
+ void (*reload) (void);
+ /* */
+ GroupSettings* (*get_dummy_group) (void);
+ bool (*exists) (int group_id);
+ GroupSettings* (*id2group) (int group_id);
+ bool (*has_permission) (GroupSettings *group, unsigned int permission);
+ bool (*should_log_commands) (GroupSettings *group);
+ const char* (*get_name) (GroupSettings *group);
+ int (*get_level) (GroupSettings *group);
+ int (*get_idx) (GroupSettings *group);
+ unsigned int (*add_permission) (const char *name);
+};
+
+struct pc_groups_interface *pcg;
-void do_init_pc_groups(void);
-void do_final_pc_groups(void);
-void pc_groups_reload(void);
+void pc_groups_defaults(void);
#endif // _PC_GROUPS_H_
diff --git a/src/map/pet.c b/src/map/pet.c
index 7dcf06c02..a2695d3b0 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -65,7 +65,7 @@ void pet_set_intimate(struct pet_data *pd, int value)
pd->pet.intimate = value;
if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) )
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
int pet_create_egg(struct map_session_data *sd, int item_id)
@@ -219,7 +219,7 @@ int pet_hungry(int tid, int64 tick, int id, intptr_t data) {
pd->pet.intimate = 0;
pd->status.speed = pd->db->status.speed;
}
- status_calc_pet(pd, 0);
+ status_calc_pet(pd, SCO_NONE);
clif->send_petdata(sd,pd,1,pd->pet.intimate);
}
clif->send_petdata(sd,pd,2,pd->pet.hungry);
@@ -304,7 +304,7 @@ int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
pd->pet.incuvate = 1;
unit->free(&pd->bl,CLR_OUTSIGHT);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
sd->status.pet_id = 0;
return 1;
@@ -360,14 +360,14 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *petinfo)
pd->bl.y = pd->ud.to_y;
map->addiddb(&pd->bl);
- status_calc_pet(pd,1);
+ status_calc_pet(pd,SCO_FIRST);
pd->last_thinktime = timer->gettick();
pd->state.skillbonus = 0;
if( battle_config.pet_status_support )
script->run(pet->db[i].pet_script,0,sd->bl.id,0);
if( pd->petDB && pd->petDB->equip_script )
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
if( battle_config.pet_hungry_delay_rate != 100 )
interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100;
@@ -703,7 +703,7 @@ int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) {
if( pd->state.skillbonus )
{
pd->state.skillbonus = 0;
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
if( pd->s_skill && pd->s_skill->timer != INVALID_TIMER )
{
@@ -759,7 +759,7 @@ int pet_food(struct map_session_data *sd, struct pet_data *pd)
}
else if( pd->pet.intimate > 1000 )
pd->pet.intimate = 1000;
- status_calc_pet(pd, 0);
+ status_calc_pet(pd, SCO_NONE);
pd->pet.hungry += pd->petDB->fullness;
if( pd->pet.hungry > 100 )
pd->pet.hungry = 100;
@@ -1062,7 +1062,7 @@ int pet_skill_bonus_timer(int tid, int64 tick, int id, intptr_t data) {
if (pd->state.skillbonus != bonus) {
pd->state.skillbonus = bonus;
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_NONE);
}
// wait for the next timer
pd->bonus->timer=timer->add(tick+duration,pet->skill_bonus_timer,sd->bl.id,0);
@@ -1328,8 +1328,10 @@ int read_petdb()
/*==========================================
* Initialization process relationship skills
*------------------------------------------*/
-int do_init_pet(void)
-{
+int do_init_pet(bool minimal) {
+ if (minimal)
+ return 0;
+
pet->read_db();
pet->item_drop_ers = ers_new(sizeof(struct item_drop),"pet.c::item_drop_ers",ERS_OPT_NONE);
diff --git a/src/map/pet.h b/src/map/pet.h
index f95e860a2..f9a756de2 100644
--- a/src/map/pet.h
+++ b/src/map/pet.h
@@ -106,7 +106,7 @@ struct pet_interface {
struct eri *item_drop_ers; //For loot drops delay structures.
struct eri *item_drop_list_ers;
/* */
- int (*init) (void);
+ int (*init) (bool minimal);
int (*final) (void);
/* */
int (*hungry_val) (struct pet_data *pd);
diff --git a/src/map/quest.c b/src/map/quest.c
index f40b60c3d..0719b8dbb 100644
--- a/src/map/quest.c
+++ b/src/map/quest.c
@@ -351,7 +351,10 @@ int quest_read_db(void) {
return 0;
}
-void do_init_quest(void) {
+void do_init_quest(bool minimal) {
+ if (minimal)
+ return;
+
quest->read_db();
}
diff --git a/src/map/quest.h b/src/map/quest.h
index 340bc8608..0725a8c46 100644
--- a/src/map/quest.h
+++ b/src/map/quest.h
@@ -19,7 +19,7 @@ typedef enum quest_check_type { HAVEQUEST, PLAYTIME, HUNTING } quest_check_type;
struct quest_interface {
struct s_quest_db db[MAX_QUEST_DB];
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*reload) (void);
/* */
int (*search_db) (int quest_id);
diff --git a/src/map/script.c b/src/map/script.c
index 174d12316..6dce018ef 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -1863,66 +1863,98 @@ void read_constdb(void) {
fclose(fp);
}
+// Standard UNIX tab size is 8
+#define TAB_SIZE 8
+#define update_tabstop(tabstop,chars) \
+ do { \
+ (tabstop) -= (chars); \
+ while ((tabstop) <= 0) (tabstop) += TAB_SIZE; \
+ } while (false)
+
/*==========================================
* Display emplacement line of script
*------------------------------------------*/
const char* script_print_line(StringBuf* buf, const char* p, const char* mark, int line)
{
- int i;
+ int i, mark_pos = 0, tabstop = TAB_SIZE;
if( p == NULL || !p[0] ) return NULL;
if( line < 0 )
- StrBuf->Printf(buf, "*% 5d : ", -line);
+ StrBuf->Printf(buf, "*%5d: ", -line); // len = 8
else
- StrBuf->Printf(buf, " % 5d : ", line);
- for(i=0;p[i] && p[i] != '\n';i++){
- if(p + i != mark)
- StrBuf->Printf(buf, "%c", p[i]);
+ StrBuf->Printf(buf, " %5d: ", line); // len = 8
+ update_tabstop(tabstop,8); // len = 8
+ for( i=0; p[i] && p[i] != '\n'; i++ ) {
+ char c = p[i];
+ int w = 1;
+ // Like Clang does, let's print the code with tabs expanded to spaces to ensure that the marker will be under the right character
+ if( c == '\t' ) {
+ c = ' ';
+ w = tabstop;
+ }
+ update_tabstop(tabstop, w);
+ if( p + i < mark)
+ mark_pos += w;
+ if( p + i != mark)
+ StrBuf->Printf(buf, "%*c", w, c);
else
- StrBuf->Printf(buf, "\'%c\'", p[i]);
+ StrBuf->Printf(buf, CL_BT_RED"%*c"CL_RESET, w, c);
}
StrBuf->AppendStr(buf, "\n");
+ if( mark ) {
+ StrBuf->AppendStr(buf, " "CL_BT_CYAN); // len = 8
+ for( ; mark_pos > 0; mark_pos-- ) {
+ StrBuf->AppendStr(buf, "~");
+ }
+ StrBuf->AppendStr(buf, CL_RESET CL_BT_GREEN"^"CL_RESET"\n");
+ }
return p+i+(p[i] == '\n' ? 1 : 0);
}
+#undef TAB_SIZE
+#undef update_tabstop
+#define CONTEXTLINES 3
void script_errorwarning_sub(StringBuf *buf, const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) {
// Find the line where the error occurred
int j;
int line = start_line;
- const char *p;
- const char *linestart[5] = { NULL, NULL, NULL, NULL, NULL };
+ const char *p, *error_linepos;
+ const char *linestart[CONTEXTLINES];
+ memset(linestart, '\0', sizeof(linestart));
for(p=src;p && *p;line++){
const char *lineend=strchr(p,'\n');
if(lineend==NULL || error_pos<lineend){
break;
}
- for( j = 0; j < 4; j++ ) {
+ for( j = 0; j < CONTEXTLINES-1; j++ ) {
linestart[j] = linestart[j+1];
}
- linestart[4] = p;
- p=lineend+1;
+ linestart[CONTEXTLINES-1] = p;
+ p = lineend+1;
}
+ error_linepos = p;
if( line >= 0 )
- StrBuf->Printf(buf, "script error on %s line %d\n", file, line);
+ StrBuf->Printf(buf, "script error in file '%s' line %d column %d\n", file, line, error_pos-error_linepos+1);
else
- StrBuf->Printf(buf, "script error on %s item ID %d\n", file, -line);
+ StrBuf->Printf(buf, "script error in file '%s' item ID %d\n", file, -line);
StrBuf->Printf(buf, " %s\n", error_msg);
- for(j = 0; j < 5; j++ ) {
- script->print_line(buf, linestart[j], NULL, line + j - 5);
+ for(j = 0; j < CONTEXTLINES; j++ ) {
+ script->print_line(buf, linestart[j], NULL, line + j - CONTEXTLINES);
}
p = script->print_line(buf, p, error_pos, -line);
- for(j = 0; j < 5; j++) {
+ for(j = 0; j < CONTEXTLINES; j++) {
p = script->print_line(buf, p, NULL, line + j + 1 );
}
}
+#undef CONTEXTLINES
void script_error(const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos) {
StringBuf buf;
StrBuf->Init(&buf);
- StrBuf->AppendStr(&buf, "\a\n");
+ StrBuf->AppendStr(&buf, "\a");
script->errorwarning_sub(&buf, src, file, start_line, error_msg, error_pos);
@@ -3694,7 +3726,7 @@ void do_final_script(void) {
/*==========================================
* Initialization
*------------------------------------------*/
-void do_init_script(void) {
+void do_init_script(bool minimal) {
script->st_db = idb_alloc(DB_OPT_BASE);
script->userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0);
script->autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0);
@@ -3707,6 +3739,10 @@ void do_init_script(void) {
script->parse_builtin();
script->read_constdb();
+
+ if (minimal)
+ return;
+
mapreg->init();
}
@@ -9426,15 +9462,8 @@ BUILDIN(sc_end) {
if (!sce)
return true;
- switch (type) {
- case SC_WEIGHTOVER50:
- case SC_WEIGHTOVER90:
- case SC_NOCHAT:
- case SC_PUSH_CART:
- return true;
- default:
- break;
- }
+ if( status->get_sc_type(type)&SC_NO_CLEAR )
+ return true;
//This should help status_change_end force disabling the SC in case it has no limit.
sce->val1 = sce->val2 = sce->val3 = sce->val4 = 0;
@@ -12103,7 +12132,7 @@ BUILDIN(nude)
}
if( calcflag )
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
return true;
}
@@ -12429,9 +12458,9 @@ BUILDIN(npcwalkto) {
if( nd ) {
unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit
if (!nd->status.hp) {
- status_calc_npc(nd, true);
+ status_calc_npc(nd, SCO_FIRST);
} else {
- status_calc_npc(nd, false);
+ status_calc_npc(nd, SCO_NONE);
}
unit->walktoxy(&nd->bl,x,y,0);
}
@@ -14971,9 +15000,9 @@ BUILDIN(unitskilluseid) {
if( bl != NULL ) {
if( bl->type == BL_NPC ) {
if (!((TBL_NPC*)bl)->status.hp) {
- status_calc_npc(((TBL_NPC*)bl), true);
+ status_calc_npc(((TBL_NPC*)bl), SCO_FIRST);
} else {
- status_calc_npc(((TBL_NPC*)bl), false);
+ status_calc_npc(((TBL_NPC*)bl), SCO_NONE);
}
}
unit->skilluse_id(bl, target_id, skill_id, skill_lv);
@@ -15005,9 +15034,9 @@ BUILDIN(unitskillusepos) {
if( bl != NULL ) {
if( bl->type == BL_NPC ) {
if (!((TBL_NPC*)bl)->status.hp) {
- status_calc_npc(((TBL_NPC*)bl), true);
+ status_calc_npc(((TBL_NPC*)bl), SCO_FIRST);
} else {
- status_calc_npc(((TBL_NPC*)bl), false);
+ status_calc_npc(((TBL_NPC*)bl), SCO_NONE);
}
}
unit->skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv);
@@ -17017,9 +17046,9 @@ BUILDIN(npcskill) {
nd->stat_point = stat_point;
if (!nd->status.hp) {
- status_calc_npc(nd, true);
+ status_calc_npc(nd, SCO_FIRST);
} else {
- status_calc_npc(nd, false);
+ status_calc_npc(nd, SCO_NONE);
}
if (skill->get_inf(skill_id)&INF_GROUND_SKILL) {
@@ -18433,7 +18462,7 @@ void script_label_add(int key, int pos) {
void script_defaults(void) {
// aegis->athena slot position conversion table
- unsigned int equip[SCRIPT_EQUIP_TABLE_SIZE] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_GARMENT};
+ unsigned int equip[SCRIPT_EQUIP_TABLE_SIZE] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_GARMENT,EQP_SHADOW_ARMOR, EQP_SHADOW_WEAPON, EQP_SHADOW_SHIELD, EQP_SHADOW_SHOES, EQP_SHADOW_ACC_R, EQP_SHADOW_ACC_L};
script = &script_s;
diff --git a/src/map/script.h b/src/map/script.h
index c6cb6070b..6aebc8a30 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -35,7 +35,7 @@ struct eri;
//#define SCRIPT_HASH_SDBM
#define SCRIPT_HASH_ELF
-#define SCRIPT_EQUIP_TABLE_SIZE 14
+#define SCRIPT_EQUIP_TABLE_SIZE 20
//#define SCRIPT_DEBUG_DISP
//#define SCRIPT_DEBUG_DISASM
@@ -507,7 +507,7 @@ struct script_interface {
int potion_hp, potion_per_hp, potion_sp, potion_per_sp;
int potion_target;
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
int (*reload) (void);
/* parse */
diff --git a/src/map/skill.c b/src/map/skill.c
index b70e58c46..c16ab832c 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -18027,7 +18027,7 @@ bool skill_parse_row_changematerialdb(char* split[], int columns, int current) {
* create_arrow_db.txt
* abra_db.txt
*------------------------------*/
-void skill_readdb(void) {
+void skill_readdb(bool minimal) {
// init skill db structures
db_clear(skill->name2id_db);
@@ -18050,6 +18050,10 @@ void skill_readdb(void) {
safestrncpy(skill->db[0].desc, "Unknown Skill", sizeof(skill->db[0].desc));
sv->readdb(map->db_path, DBPATH"skill_db.txt", ',', 17, 17, MAX_SKILL_DB, skill->parse_row_skilldb);
+
+ if (minimal)
+ return;
+
sv->readdb(map->db_path, DBPATH"skill_require_db.txt", ',', 32, 32, MAX_SKILL_DB, skill->parse_row_requiredb);
#ifdef RENEWAL_CAST
sv->readdb(map->db_path, "re/skill_cast_db.txt", ',', 8, 8, MAX_SKILL_DB, skill->parse_row_castdb);
@@ -18077,7 +18081,7 @@ void skill_reload (void) {
struct map_session_data *sd;
int i,c,k;
- skill->read_db();
+ skill->read_db(false);
//[Ind/Hercules] refresh index cache
for(c = 0; c < CLASS_COUNT; c++) {
@@ -18103,9 +18107,12 @@ void skill_reload (void) {
/*==========================================
*
*------------------------------------------*/
-int do_init_skill (void) {
+int do_init_skill(bool minimal) {
skill->name2id_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, MAX_SKILL_NAME_LENGTH);
- skill->read_db();
+ skill->read_db(minimal);
+
+ if (minimal)
+ return 0;
skill->group_db = idb_alloc(DB_OPT_BASE);
skill->unit_db = idb_alloc(DB_OPT_BASE);
diff --git a/src/map/skill.h b/src/map/skill.h
index fca4952ef..918216e8a 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -1797,10 +1797,10 @@ typedef int (*SkillFunc)(struct block_list *src, struct block_list *target, uint
* Skill.c Interface
**/
struct skill_interface {
- int (*init) (void);
+ int (*init) (bool minimal);
int (*final) (void);
void (*reload) (void);
- void (*read_db) (void);
+ void (*read_db) (bool minimal);
/* */
DBMap* cd_db; // char_id -> struct skill_cd
DBMap* name2id_db;
diff --git a/src/map/status.c b/src/map/status.c
index 9e98b2801..ef211e97e 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -1999,13 +1999,12 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level)
//Skotlex: Calculates the initial status for the given mob
//first will only be false when the mob leveled up or got a GuardUp level.
-int status_calc_mob_(struct mob_data* md, bool first) {
+int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
struct status_data *mstatus;
struct block_list *mbl = NULL;
int flag=0;
- if(first)
- { //Set basic level on respawn.
+ if(opt&SCO_FIRST) { //Set basic level on respawn.
if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv)
;
else
@@ -2036,7 +2035,7 @@ int status_calc_mob_(struct mob_data* md, bool first) {
aFree(md->base_status);
md->base_status = NULL;
}
- if(first)
+ if(opt&SCO_FIRST)
memcpy(&md->status, &md->db->status, sizeof(struct status_data));
return 0;
}
@@ -2160,18 +2159,18 @@ int status_calc_mob_(struct mob_data* md, bool first) {
}
}
- if( first ) //Initial battle status
+ if( opt&SCO_FIRST ) //Initial battle status
memcpy(&md->status, mstatus, sizeof(struct status_data));
return 1;
}
//Skotlex: Calculates the stats of the given pet.
-int status_calc_pet_(struct pet_data *pd, bool first)
+int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
{
nullpo_ret(pd);
- if (first) {
+ if (opt&SCO_FIRST) {
memcpy(&pd->status, &pd->db->status, sizeof(struct status_data));
pd->status.mode = MD_CANMOVE; // pets discard all modes, except walking
pd->status.speed = pd->petDB->speed;
@@ -2189,10 +2188,10 @@ int status_calc_pet_(struct pet_data *pd, bool first)
lv =sd->status.base_level*battle_config.pet_lv_rate/100;
if (lv < 0)
lv = 1;
- if (lv != pd->pet.level || first) {
+ if (lv != pd->pet.level || opt&SCO_FIRST) {
struct status_data *bstat = &pd->db->status, *pstatus = &pd->status;
pd->pet.level = lv;
- if (!first) //Lv Up animation
+ if (! (opt&SCO_FIRST) ) //Lv Up animation
clif->misceffect(&pd->bl, 0);
pstatus->rhw.atk = (bstat->rhw.atk*lv)/pd->db->lv;
pstatus->rhw.atk2 = (bstat->rhw.atk2*lv)/pd->db->lv;
@@ -2214,10 +2213,10 @@ int status_calc_pet_(struct pet_data *pd, bool first)
status->calc_misc(&pd->bl, &pd->status, lv);
- if (!first) //Not done the first time because the pet is not visible yet
+ if (! (opt&SCO_FIRST) ) //Not done the first time because the pet is not visible yet
clif->send_petstatus(sd);
}
- } else if (first) {
+ } else if ( opt&SCO_FIRST ) {
status->calc_misc(&pd->bl, &pd->status, pd->db->lv);
if (!battle_config.pet_lv_rate && pd->pet.level != pd->db->lv)
pd->pet.level = pd->db->lv;
@@ -2295,7 +2294,7 @@ unsigned int status_base_pc_maxsp(struct map_session_data* sd, struct status_dat
//Calculates player data from scratch without counting SC adjustments.
//Should be invoked whenever players raise stats, learn passive skills or change equipment.
-int status_calc_pc_(struct map_session_data* sd, bool first) {
+int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
static int calculating = 0; //Check for recursive call preemption. [Skotlex]
struct status_data *bstatus; // pointer to the player's base status
const struct status_change *sc = &sd->sc;
@@ -2317,7 +2316,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) {
sd->max_weight = status->max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300;
- if(first) {
+ if(opt&SCO_FIRST) {
//Load Hp/SP from char-received data.
sd->battle_status.hp = sd->status.hp;
sd->battle_status.sp = sd->status.sp;
@@ -2389,11 +2388,17 @@ int status_calc_pc_(struct map_session_data* sd, bool first) {
clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_CLAIRVOYANCE);
memset(&sd->special_state,0,sizeof(sd->special_state));
- memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp)));
-
- //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex]
- if (!sd->state.permanent_speed)
+
+ if (!sd->state.permanent_speed) {
+ memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp)));
bstatus->speed = DEFAULT_WALK_SPEED;
+ } else {
+ int pSpeed = bstatus->speed;
+ memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp)));
+ bstatus->speed = pSpeed;
+ }
+
+ //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex]
//Give them all modes except these (useful for clones)
bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
@@ -2476,7 +2481,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) {
bstatus->def += sd->inventory_data[index]->def;
- if(first && sd->inventory_data[index]->equip_script)
+ if(opt&SCO_FIRST && sd->inventory_data[index]->equip_script)
{ //Execute equip-script on login
script->run(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
if (!calculating)
@@ -2619,7 +2624,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) {
if( k < map->list[sd->bl.m].zone->disabled_items_count )
continue;
- if(first && data->equip_script) {//Execute equip-script on login
+ if(opt&SCO_FIRST && data->equip_script) {//Execute equip-script on login
script->run(data->equip_script,0,sd->bl.id,0);
if (!calculating)
return 1;
@@ -3129,11 +3134,11 @@ int status_calc_pc_(struct map_session_data* sd, bool first) {
return 0;
}
-int status_calc_mercenary_(struct mercenary_data *md, bool first) {
+int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt) {
struct status_data *mstatus = &md->base_status;
struct s_mercenary *merc = &md->mercenary;
- if( first ) {
+ if( opt&SCO_FIRST ) {
memcpy(mstatus, &md->db->status, sizeof(struct status_data));
mstatus->mode = MD_CANMOVE|MD_CANATTACK;
mstatus->hp = mstatus->max_hp;
@@ -3148,7 +3153,7 @@ int status_calc_mercenary_(struct mercenary_data *md, bool first) {
return 0;
}
-int status_calc_homunculus_(struct homun_data *hd, bool first) {
+int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) {
struct status_data *hstatus = &hd->base_status;
struct s_homunculus *hom = &hd->homunculus;
int skill_lv;
@@ -3161,7 +3166,7 @@ int status_calc_homunculus_(struct homun_data *hd, bool first) {
hstatus->int_ = hom->int_ / 10;
hstatus->luk = hom->luk / 10;
- if (first) { //[orn]
+ if ( opt&SCO_FIRST ) { //[orn]
const struct s_homunculus_db *db = hd->homunculusDB;
hstatus->def_ele = db->element;
hstatus->ele_lv = 1;
@@ -3201,7 +3206,7 @@ int status_calc_homunculus_(struct homun_data *hd, bool first) {
if((skill_lv = homun->checkskill(hd,HLIF_BRAIN)) > 0)
hstatus->max_sp += (1 +skill_lv/2 -skill_lv/4 +skill_lv/5) * hstatus->max_sp / 100;
- if (first) {
+ if ( opt&SCO_FIRST ) {
hd->battle_status.hp = hom->hp;
hd->battle_status.sp = hom->sp;
}
@@ -3225,7 +3230,7 @@ int status_calc_homunculus_(struct homun_data *hd, bool first) {
return 1;
}
-int status_calc_elemental_(struct elemental_data *ed, bool first) {
+int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt) {
struct status_data *estatus = &ed->base_status;
struct s_elemental *ele = &ed->elemental;
struct map_session_data *sd = ed->master;
@@ -3233,7 +3238,7 @@ int status_calc_elemental_(struct elemental_data *ed, bool first) {
if( !sd )
return 0;
- if( first ) {
+ if( opt&SCO_FIRST ) {
memcpy(estatus, &ed->db->status, sizeof(struct status_data));
if( !ele->mode )
estatus->mode = EL_MODE_PASSIVE;
@@ -3264,13 +3269,13 @@ int status_calc_elemental_(struct elemental_data *ed, bool first) {
return 0;
}
-int status_calc_npc_(struct npc_data *nd, bool first) {
+int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) {
struct status_data *nstatus = &nd->status;
if (!nd)
return 0;
- if (first) {
+ if ( opt&SCO_FIRST ) {
nstatus->hp = 1;
nstatus->sp = 1;
nstatus->max_hp = 1;
@@ -3670,6 +3675,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
if(flag&SCB_SPEED) {
struct unit_data *ud = unit->bl2ud(bl);
+
st->speed = status->calc_speed(bl, sc, bst->speed);
//Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER
@@ -3678,13 +3684,11 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
if (ud)
ud->state.change_walk_target = ud->state.speed_changed = 1;
- if( bl->type&BL_PC && st->speed < battle_config.max_walk_speed )
+ if( bl->type&BL_PC && !(sd && sd->state.permanent_speed) && st->speed < battle_config.max_walk_speed )
st->speed = battle_config.max_walk_speed;
if( bl->type&BL_HOM && battle_config.hom_setting&0x8 && ((TBL_HOM*)bl)->master)
st->speed = status->get_speed(&((TBL_HOM*)bl)->master->bl);
-
-
}
if(flag&SCB_CRI && bst->cri) {
@@ -3858,13 +3862,17 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
/// Also sends updates to the client wherever applicable.
/// @param flag bitfield of values from enum scb_flag
/// @param first if true, will cause status_calc_* functions to run their base status initialization code
-void status_calc_bl_(struct block_list *bl, enum scb_flag flag, bool first) {
+void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt) {
struct status_data bst; // previous battle status
struct status_data *st; // pointer to current battle status
if( bl->type == BL_PC && ((TBL_PC*)bl)->delayed_damage != 0 ) {
- ((TBL_PC*)bl)->state.hold_recalc = 1;
- return;
+ if( opt&SCO_FORCE )
+ ((TBL_PC*)bl)->state.hold_recalc = 0;/* clear and move on */
+ else {
+ ((TBL_PC*)bl)->state.hold_recalc = 1;/* flag and stop */
+ return;
+ }
}
// remember previous values
@@ -3873,25 +3881,25 @@ void status_calc_bl_(struct block_list *bl, enum scb_flag flag, bool first) {
if( flag&SCB_BASE ) {// calculate the object's base status too
switch( bl->type ) {
- case BL_PC: status->calc_pc_(BL_CAST(BL_PC,bl), first); break;
- case BL_MOB: status->calc_mob_(BL_CAST(BL_MOB,bl), first); break;
- case BL_PET: status->calc_pet_(BL_CAST(BL_PET,bl), first); break;
- case BL_HOM: status->calc_homunculus_(BL_CAST(BL_HOM,bl), first); break;
- case BL_MER: status->calc_mercenary_(BL_CAST(BL_MER,bl), first); break;
- case BL_ELEM: status->calc_elemental_(BL_CAST(BL_ELEM,bl), first); break;
- case BL_NPC: status->calc_npc_(BL_CAST(BL_NPC,bl), first); break;
+ case BL_PC: status->calc_pc_(BL_CAST(BL_PC,bl), opt); break;
+ case BL_MOB: status->calc_mob_(BL_CAST(BL_MOB,bl), opt); break;
+ case BL_PET: status->calc_pet_(BL_CAST(BL_PET,bl), opt); break;
+ case BL_HOM: status->calc_homunculus_(BL_CAST(BL_HOM,bl), opt); break;
+ case BL_MER: status->calc_mercenary_(BL_CAST(BL_MER,bl), opt); break;
+ case BL_ELEM: status->calc_elemental_(BL_CAST(BL_ELEM,bl), opt); break;
+ case BL_NPC: status->calc_npc_(BL_CAST(BL_NPC,bl), opt); break;
}
}
if( bl->type == BL_PET )
return; // pets are not affected by statuses
- if( first && bl->type == BL_MOB )
+ if( opt&SCO_FIRST && bl->type == BL_MOB )
return; // assume there will be no statuses active
status->calc_bl_main(bl, flag);
- if( first && bl->type == BL_HOM )
+ if( opt&SCO_FIRST && bl->type == BL_HOM )
return; // client update handled by caller
// compare against new values and send client updates
@@ -5045,11 +5053,8 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
TBL_PC* sd = BL_CAST(BL_PC, bl);
int speed_rate;
- if( sc == NULL )
- return cap_value(speed,10,USHRT_MAX);
-
- if (sd && sd->state.permanent_speed)
- return (short)cap_value(speed,10,USHRT_MAX);
+ if( sc == NULL || ( sd && sd->state.permanent_speed ) )
+ return (unsigned short)cap_value(speed,MIN_WALK_SPEED,MAX_WALK_SPEED);
if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) )
{
@@ -5222,7 +5227,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
}
- return (short)cap_value(speed,10,USHRT_MAX);
+ return (unsigned short)cap_value(speed,MIN_WALK_SPEED,MAX_WALK_SPEED);
}
// flag&1 - fixed value [malufett]
@@ -9218,17 +9223,8 @@ int status_change_clear(struct block_list* bl, int type) {
}
}
}
- if( type == 3 ) {
- switch (i) {// TODO: This list may be incomplete
- case SC_WEIGHTOVER50:
- case SC_WEIGHTOVER90:
- case SC_NOCHAT:
- case SC_PUSH_CART:
- case SC_JAILED:
- case SC_ALL_RIDING:
- continue;
- }
- }
+ if( type == 3 && status->get_sc_type(i)&SC_NO_CLEAR )
+ continue;
status_change_end(bl, (sc_type)i, INVALID_TIMER);
@@ -10377,7 +10373,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
if (sd && !pc_issit(sd)) { //can't cast if sit
int mushroom_skill_id = 0, i;
unit->stop_attack(bl);
- unit->skillcastcancel(bl,1);
+ unit->skillcastcancel(bl,0);
do {
i = rnd() % MAX_SKILL_MAGICMUSHROOM_DB;
mushroom_skill_id = skill->magicmushroom_db[i].skill_id;
@@ -10385,15 +10381,15 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
while( mushroom_skill_id == 0 );
switch( skill->get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage
- case CAST_GROUND:
- skill->castend_pos2(bl,bl->x,bl->y,mushroom_skill_id,1,tick,0);
- break;
- case CAST_NODAMAGE:
- skill->castend_nodamage_id(bl,bl,mushroom_skill_id,1,tick,0);
- break;
- case CAST_DAMAGE:
- skill->castend_damage_id(bl,bl,mushroom_skill_id,1,tick,0);
- break;
+ case CAST_GROUND:
+ skill->castend_pos2(bl,bl->x,bl->y,mushroom_skill_id,1,tick,0);
+ break;
+ case CAST_NODAMAGE:
+ skill->castend_nodamage_id(bl,bl,mushroom_skill_id,1,tick,0);
+ break;
+ case CAST_DAMAGE:
+ skill->castend_damage_id(bl,bl,mushroom_skill_id,1,tick,0);
+ break;
}
}
@@ -11534,7 +11530,10 @@ int status_readdb(void)
/*==========================================
* Status db init and destroy.
*------------------------------------------*/
-int do_init_status(void) {
+int do_init_status(bool minimal) {
+ if (minimal)
+ return 0;
+
timer->add_func_list(status->change_timer,"status_change_timer");
timer->add_func_list(status->kaahi_heal_timer,"status_kaahi_heal_timer");
timer->add_func_list(status->natural_heal_timer,"status_natural_heal_timer");
diff --git a/src/map/status.h b/src/map/status.h
index 254f3bfab..cdd5fa481 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -34,13 +34,14 @@ enum refine_type {
};
typedef enum sc_conf_type {
- SC_NO_REM_DEATH = 0x1,
- SC_NO_SAVE = 0x2,
- SC_NO_DISPELL = 0x4,
- SC_NO_CLEARANCE = 0x8,
- SC_BUFF = 0x10,
- SC_DEBUFF = 0x20,
- SC_MADO_NO_RESET = 0x40
+ SC_NO_REM_DEATH = 0x01,
+ SC_NO_SAVE = 0x02,
+ SC_NO_DISPELL = 0x04,
+ SC_NO_CLEARANCE = 0x08,
+ SC_BUFF = 0x10,
+ SC_DEBUFF = 0x20,
+ SC_MADO_NO_RESET = 0x40,
+ SC_NO_CLEAR = 0x80,
} sc_conf_type;
// Status changes listing. These code are for use by the server.
@@ -1627,6 +1628,12 @@ enum e_regen {
RGN_SSP = 0x08,
};
+enum e_status_calc_opt {
+ SCO_NONE = 0x0,
+ SCO_FIRST = 0x1, /* trigger the calculations that should take place only onspawn/once */
+ SCO_FORCE = 0x2, /* only relevant to BL_PC types, ensures call bypasses the queue caused by delayed damage */
+};
+
//Define to determine who gets HP/SP consumed on doing skills/etc. [Skotlex]
#define BL_CONSUME (BL_PC|BL_HOM|BL_MER|BL_ELEM)
//Define to determine who has regen
@@ -1810,14 +1817,14 @@ struct status_change {
#define status_change_end(bl,type,tid) status->change_end_(bl,type,tid,__FILE__,__LINE__)
-#define status_calc_bl(bl, flag) status->calc_bl_(bl, (enum scb_flag)(flag), false)
-#define status_calc_mob(md, first) status->calc_bl_(&(md)->bl, SCB_ALL, first)
-#define status_calc_pet(pd, first) status->calc_bl_(&(pd)->bl, SCB_ALL, first)
-#define status_calc_pc(sd, first) status->calc_bl_(&(sd)->bl, SCB_ALL, first)
-#define status_calc_homunculus(hd, first) status->calc_bl_(&(hd)->bl, SCB_ALL, first)
-#define status_calc_mercenary(md, first) status->calc_bl_(&(md)->bl, SCB_ALL, first)
-#define status_calc_elemental(ed, first) status->calc_bl_(&(ed)->bl, SCB_ALL, first)
-#define status_calc_npc(nd, first) status->calc_bl_(&(nd)->bl, SCB_ALL, first)
+#define status_calc_bl(bl, flag) status->calc_bl_(bl, (enum scb_flag)(flag), SCO_NONE)
+#define status_calc_mob(md, opt) status->calc_bl_(&(md)->bl, SCB_ALL, opt)
+#define status_calc_pet(pd, opt) status->calc_bl_(&(pd)->bl, SCB_ALL, opt)
+#define status_calc_pc(sd, opt) status->calc_bl_(&(sd)->bl, SCB_ALL, opt)
+#define status_calc_homunculus(hd, opt) status->calc_bl_(&(hd)->bl, SCB_ALL, opt)
+#define status_calc_mercenary(md, opt) status->calc_bl_(&(md)->bl, SCB_ALL, opt)
+#define status_calc_elemental(ed, opt) status->calc_bl_(&(ed)->bl, SCB_ALL, opt)
+#define status_calc_npc(nd, opt) status->calc_bl_(&(nd)->bl, SCB_ALL, opt)
// bonus values and upgrade chances for refining equipment
struct s_refine_info {
@@ -1864,7 +1871,7 @@ struct status_interface {
int64 natural_heal_prev_tick;
unsigned int natural_heal_diff_tick;
/* */
- int (*init) (void);
+ int (*init) (bool minimal);
void (*final) (void);
/* funcs */
int (*get_refine_chance) (enum refine_type wlv, int refine);
@@ -1911,13 +1918,13 @@ struct status_interface {
int (*change_timer_sub) (struct block_list* bl, va_list ap);
int (*change_clear) (struct block_list* bl, int type);
int (*change_clear_buffs) (struct block_list* bl, int type);
- void (*calc_bl_) (struct block_list *bl, enum scb_flag flag, bool first);
- int (*calc_mob_) (struct mob_data* md, bool first);
- int (*calc_pet_) (struct pet_data* pd, bool first);
- int (*calc_pc_) (struct map_session_data* sd, bool first);
- int (*calc_homunculus_) (struct homun_data *hd, bool first);
- int (*calc_mercenary_) (struct mercenary_data *md, bool first);
- int (*calc_elemental_) (struct elemental_data *ed, bool first);
+ void (*calc_bl_) (struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt);
+ int (*calc_mob_) (struct mob_data* md, enum e_status_calc_opt opt);
+ int (*calc_pet_) (struct pet_data* pd, enum e_status_calc_opt opt);
+ int (*calc_pc_) (struct map_session_data* sd, enum e_status_calc_opt opt);
+ int (*calc_homunculus_) (struct homun_data *hd, enum e_status_calc_opt opt);
+ int (*calc_mercenary_) (struct mercenary_data *md, enum e_status_calc_opt opt);
+ int (*calc_elemental_) (struct elemental_data *ed, enum e_status_calc_opt opt);
void (*calc_misc) (struct block_list *bl, struct status_data *status, int level);
void (*calc_regen) (struct block_list *bl, struct status_data *st, struct regen_data *regen);
void (*calc_regen_rate) (struct block_list *bl, struct regen_data *regen, struct status_change *sc);
@@ -1943,7 +1950,7 @@ struct status_interface {
void (*calc_sigma) (void);
unsigned int (*base_pc_maxhp) (struct map_session_data *sd, struct status_data *st);
unsigned int (*base_pc_maxsp) (struct map_session_data *sd, struct status_data *st);
- int (*calc_npc_) (struct npc_data *nd, bool first);
+ int (*calc_npc_) (struct npc_data *nd, enum e_status_calc_opt opt);
unsigned short (*calc_str) (struct block_list *bl, struct status_change *sc, int str);
unsigned short (*calc_agi) (struct block_list *bl, struct status_change *sc, int agi);
unsigned short (*calc_vit) (struct block_list *bl, struct status_change *sc, int vit);
diff --git a/src/map/storage.c b/src/map/storage.c
index df406257d..cffbf23ec 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -728,7 +728,9 @@ int storage_guild_storage_quit(struct map_session_data* sd, int flag) {
return 0;
}
-void do_init_gstorage(void) {
+void do_init_gstorage(bool minimal) {
+ if (minimal)
+ return;
gstorage->db = idb_alloc(DB_OPT_RELEASE_DATA);
}
void do_final_gstorage(void) {
diff --git a/src/map/storage.h b/src/map/storage.h
index 9258e0265..8a10c9f3b 100644
--- a/src/map/storage.h
+++ b/src/map/storage.h
@@ -36,7 +36,7 @@ struct guild_storage_interface {
struct guild_storage *(*id2storage) (int guild_id);
struct guild_storage *(*id2storage2) (int guild_id);
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
/* */
int (*delete) (int guild_id);
diff --git a/src/map/unit.c b/src/map/unit.c
index 08e97cfee..b1240def2 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1966,7 +1966,7 @@ int unit_skillcastcancel(struct block_list *bl,int type)
else
ret = timer->delete( ud->skilltimer, skill->castend_id );
if( ret < 0 )
- ShowError("delete timer error : skill_id : %d\n",ret);
+ ShowError("delete timer error %d : skill %d (%s)\n",ret,skill_id,skill->get_name(skill_id));
ud->skilltimer = INVALID_TIMER;
@@ -2573,7 +2573,10 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
return 0;
}
-int do_init_unit(void) {
+int do_init_unit(bool minimal) {
+ if (minimal)
+ return 0;
+
timer->add_func_list(unit->attack_timer, "unit_attack_timer");
timer->add_func_list(unit->walktoxy_timer,"unit_walktoxy_timer");
timer->add_func_list(unit->walktobl_sub, "unit_walktobl_sub");
diff --git a/src/map/unit.h b/src/map/unit.h
index 0567688a1..8220b7e8f 100644
--- a/src/map/unit.h
+++ b/src/map/unit.h
@@ -72,7 +72,7 @@ extern const short dirx[8];
extern const short diry[8];
struct unit_interface {
- int (*init) (void);
+ int (*init) (bool minimal);
int (*final) (void);
/* */
struct unit_data* (*bl2ud) (struct block_list *bl);
diff --git a/src/map/vending.c b/src/map/vending.c
index be3826754..14a5e64d1 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -361,7 +361,7 @@ void final(void) {
db_destroy(vending->db);
}
-void init(void) {
+void init(bool minimal) {
vending->db = idb_alloc(DB_OPT_BASE);
vending->next_id = 0;
}
diff --git a/src/map/vending.h b/src/map/vending.h
index 968811ecd..b760bf064 100644
--- a/src/map/vending.h
+++ b/src/map/vending.h
@@ -20,7 +20,7 @@ struct vending_interface {
unsigned int next_id;/* next vender id */
DBMap *db;
/* */
- void (*init) (void);
+ void (*init) (bool minimal);
void (*final) (void);
/* */
void (*close) (struct map_session_data* sd);