summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c247
-rw-r--r--src/char/char.h3
-rw-r--r--src/char/int_party.c7
-rw-r--r--src/common/mmo.h7
-rw-r--r--src/map/atcommand.c192
-rw-r--r--src/map/itemdb.c25
-rw-r--r--src/map/pc.c5
-rw-r--r--src/map/pc.h4
-rw-r--r--src/map/status.c6
-rw-r--r--src/map/status.h2
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc4
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc1
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.Hooks.inc27
-rw-r--r--src/plugins/db2sql.c115
14 files changed, 292 insertions, 353 deletions
diff --git a/src/char/char.c b/src/char/char.c
index 0fe48def3..6cfeb7d1a 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -416,7 +416,7 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
//map inventory data
if( memcmp(p->inventory, cp->inventory, sizeof(p->inventory)) ) {
- if (!chr->inventory_to_sql(p->inventory, MAX_INVENTORY, p->char_id))
+ if (!chr->memitemdata_to_sql(p->inventory, MAX_INVENTORY, p->char_id, TABLE_INVENTORY))
strcat(save_status, " inventory");
else
errors++;
@@ -689,53 +689,63 @@ int char_mmo_char_tosql(int char_id, struct mmo_charstatus* p)
return 0;
}
-/// Saves an array of 'item' entries into the specified table.
+/**
+ * Saves an array of 'item' entries into the specified table.
+ *
+ * @param items The items array.
+ * @param max The array size.
+ * @param id The character/account/guild ID (depending on tableswitch).
+ * @param tableswitch The type of table (@see enum inventory_table_type).
+ * @return Error code.
+ * @retval 0 in case of success.
+ */
int char_memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch)
{
StringBuf buf;
- SqlStmt* stmt;
- int i;
- int j;
- const char* tablename;
- const char* selectoption;
- struct item item; // temp storage variable
- bool* flag; // bit array for inventory matching
+ SqlStmt *stmt = NULL;
+ int i, j;
+ const char *tablename = NULL;
+ const char *selectoption = NULL;
+ bool has_favorite = false;
+ struct item item = { 0 }; // temp storage variable
+ bool *flag = NULL; // bit array for inventory matching
bool found;
int errors = 0;
+ nullpo_ret(items);
+
switch (tableswitch) {
- case TABLE_INVENTORY: tablename = inventory_db; selectoption = "char_id"; break;
+ case TABLE_INVENTORY: tablename = inventory_db; selectoption = "char_id"; has_favorite = true; break;
case TABLE_CART: tablename = cart_db; selectoption = "char_id"; break;
case TABLE_STORAGE: tablename = storage_db; selectoption = "account_id"; break;
case TABLE_GUILD_STORAGE: tablename = guild_storage_db; selectoption = "guild_id"; break;
default:
ShowError("Invalid table name!\n");
- return 1;
+ Assert_retr(1, tableswitch);
}
-
// The following code compares inventory with current database values
// and performs modification/deletion/insertion only on relevant rows.
// This approach is more complicated than a trivial delete&insert, but
// it significantly reduces cpu load on the database server.
StrBuf->Init(&buf);
- StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`");
- for( j = 0; j < MAX_SLOTS; ++j )
+ StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`");
+ for (j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ", `card%d`", j);
+ if (has_favorite)
+ StrBuf->AppendStr(&buf, ", `favorite`");
StrBuf->Printf(&buf, " FROM `%s` WHERE `%s`='%d'", tablename, selectoption, id);
stmt = SQL->StmtMalloc(inter->sql_handle);
- if( SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
- || SQL_ERROR == SQL->StmtExecute(stmt) )
- {
+ if (SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
+ || SQL_ERROR == SQL->StmtExecute(stmt)) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
StrBuf->Destroy(&buf);
return 1;
}
- memset(&item, 0, sizeof(item));
SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL);
@@ -745,30 +755,32 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 8, SQLDT_UCHAR, &item.bound, 0, NULL, NULL);
- for( j = 0; j < MAX_SLOTS; ++j )
- SQL->StmtBindColumn(stmt, 9+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
+ SQL->StmtBindColumn(stmt, 9, SQLDT_UINT64, &item.unique_id, 0, NULL, NULL);
+ for (j = 0; j < MAX_SLOTS; ++j)
+ SQL->StmtBindColumn(stmt, 10+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
+ if (has_favorite)
+ SQL->StmtBindColumn(stmt, 10+MAX_SLOTS, SQLDT_UCHAR, &item.favorite, 0, NULL, NULL);
// bit array indicating which inventory items have already been matched
- flag = (bool*) aCalloc(max, sizeof(bool));
+ flag = aCalloc(max, sizeof(bool));
- while( SQL_SUCCESS == SQL->StmtNextRow(stmt) )
- {
+ while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
found = false;
// search for the presence of the item in the char's inventory
- for( i = 0; i < max; ++i )
- {
+ for (i = 0; i < max; ++i) {
// skip empty and already matched entries
- if( items[i].nameid == 0 || flag[i] )
+ if (items[i].nameid == 0 || flag[i])
continue;
- if( items[i].nameid == item.nameid
+ if (items[i].nameid == item.nameid
+ && items[i].unique_id == item.unique_id
&& items[i].card[0] == item.card[0]
&& items[i].card[2] == item.card[2]
&& items[i].card[3] == item.card[3]
) {
- //They are the same item.
- ARR_FIND( 0, MAX_SLOTS, j, items[i].card[j] != item.card[j] );
- if( j == MAX_SLOTS
+ // They are the same item.
+ ARR_FIND(0, MAX_SLOTS, j, items[i].card[j] != item.card[j]);
+ if (j == MAX_SLOTS
&& items[i].amount == item.amount
&& items[i].equip == item.equip
&& items[i].identify == item.identify
@@ -776,6 +788,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
&& items[i].attribute == item.attribute
&& items[i].expire_time == item.expire_time
&& items[i].bound == item.bound
+ && (!has_favorite || items[i].favorite == item.favorite)
) {
; //Do nothing.
} else {
@@ -783,12 +796,13 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%u', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `bound`='%d'",
tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].bound);
- for( j = 0; j < MAX_SLOTS; ++j )
+ for (j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ", `card%d`=%d", j, items[i].card[j]);
+ if (has_favorite)
+ StrBuf->Printf(&buf, ", `favorite`='%d'", items[i].favorite);
StrBuf->Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id);
- if( SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)) )
- {
+ if (SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
Sql_ShowDebug(inter->sql_handle);
errors++;
}
@@ -798,10 +812,9 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
break; //skip to next item in the db.
}
}
- if( !found )
- {// Item not present in inventory, remove it.
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", tablename, item.id) )
- {
+ if (!found) {
+ // Item not present in inventory, remove it.
+ if (SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", tablename, item.id)) {
Sql_ShowDebug(inter->sql_handle);
errors++;
}
@@ -811,173 +824,34 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, int tabl
StrBuf->Clear(&buf);
StrBuf->Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `bound`, `unique_id`", tablename, selectoption);
- for( j = 0; j < MAX_SLOTS; ++j )
+ for (j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ", `card%d`", j);
+ if (has_favorite)
+ StrBuf->AppendStr(&buf, ", `favorite`");
StrBuf->AppendStr(&buf, ") VALUES ");
found = false;
// insert non-matched items into the db as new items
- for( i = 0; i < max; ++i )
- {
+ for (i = 0; i < max; ++i) {
// skip empty and already matched entries
- if( items[i].nameid == 0 || flag[i] )
+ if (items[i].nameid == 0 || flag[i])
continue;
- if( found )
+ if (found)
StrBuf->AppendStr(&buf, ",");
else
found = true;
StrBuf->Printf(&buf, "('%d', '%d', '%d', '%u', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'",
id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].bound, items[i].unique_id);
- for( j = 0; j < MAX_SLOTS; ++j )
- StrBuf->Printf(&buf, ", '%d'", items[i].card[j]);
- StrBuf->AppendStr(&buf, ")");
- }
-
- if( found && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)) )
- {
- Sql_ShowDebug(inter->sql_handle);
- errors++;
- }
-
- StrBuf->Destroy(&buf);
- aFree(flag);
-
- return errors;
-}
-/* pretty much a copy of chr->memitemdata_to_sql except it handles inventory_db exclusively,
- * - this is required because inventory db is the only one with the 'favorite' column. */
-int char_inventory_to_sql(const struct item items[], int max, int id) {
- StringBuf buf;
- SqlStmt* stmt;
- int i;
- int j;
- struct item item; // temp storage variable
- bool* flag; // bit array for inventory matching
- bool found;
- int errors = 0;
-
- nullpo_ret(items);
-
- // The following code compares inventory with current database values
- // and performs modification/deletion/insertion only on relevant rows.
- // This approach is more complicated than a trivial delete&insert, but
- // it significantly reduces cpu load on the database server.
-
- StrBuf->Init(&buf);
- StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`");
- for( j = 0; j < MAX_SLOTS; ++j )
- StrBuf->Printf(&buf, ", `card%d`", j);
- StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", inventory_db, id);
-
- stmt = SQL->StmtMalloc(inter->sql_handle);
- if( SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
- || SQL_ERROR == SQL->StmtExecute(stmt) )
- {
- SqlStmt_ShowDebug(stmt);
- SQL->StmtFree(stmt);
- StrBuf->Destroy(&buf);
- return 1;
- }
-
- memset(&item, 0, sizeof(item));
- SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 3, SQLDT_UINT, &item.equip, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 4, SQLDT_CHAR, &item.identify, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 7, SQLDT_UINT, &item.expire_time, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 8, SQLDT_CHAR, &item.favorite, 0, NULL, NULL);
- SQL->StmtBindColumn(stmt, 9, SQLDT_UCHAR, &item.bound, 0, NULL, NULL);
- for( j = 0; j < MAX_SLOTS; ++j )
- SQL->StmtBindColumn(stmt, 10+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL);
-
- // bit array indicating which inventory items have already been matched
- flag = (bool*) aCalloc(max, sizeof(bool));
-
- while( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) {
- found = false;
- // search for the presence of the item in the char's inventory
- for( i = 0; i < max; ++i ) {
- // skip empty and already matched entries
- if( items[i].nameid == 0 || flag[i] )
- continue;
-
- if( items[i].nameid == item.nameid
- && items[i].card[0] == item.card[0]
- && items[i].card[2] == item.card[2]
- && items[i].card[3] == item.card[3]
- ) {
- //They are the same item.
- ARR_FIND( 0, MAX_SLOTS, j, items[i].card[j] != item.card[j] );
- if( j == MAX_SLOTS
- && items[i].amount == item.amount
- && items[i].equip == item.equip
- && items[i].identify == item.identify
- && items[i].refine == item.refine
- && items[i].attribute == item.attribute
- && items[i].expire_time == item.expire_time
- && items[i].favorite == item.favorite
- && items[i].bound == item.bound
- ) {
- ; //Do nothing.
- } else {
- // update all fields.
- StrBuf->Clear(&buf);
- StrBuf->Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%u', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `favorite`='%d', `bound`='%d'",
- inventory_db, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound);
- for( j = 0; j < MAX_SLOTS; ++j )
- StrBuf->Printf(&buf, ", `card%d`=%d", j, items[i].card[j]);
- StrBuf->Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id);
-
- if( SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)) ) {
- Sql_ShowDebug(inter->sql_handle);
- errors++;
- }
- }
-
- found = flag[i] = true; //Item dealt with,
- break; //skip to next item in the db.
- }
- }
- if( !found ) {// Item not present in inventory, remove it.
- if( SQL_ERROR == SQL->Query(inter->sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", inventory_db, item.id) ) {
- Sql_ShowDebug(inter->sql_handle);
- errors++;
- }
- }
- }
- SQL->StmtFree(stmt);
-
- StrBuf->Clear(&buf);
- StrBuf->Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `bound`, `unique_id`", inventory_db);
- for( j = 0; j < MAX_SLOTS; ++j )
- StrBuf->Printf(&buf, ", `card%d`", j);
- StrBuf->AppendStr(&buf, ") VALUES ");
-
- found = false;
- // insert non-matched items into the db as new items
- for( i = 0; i < max; ++i ) {
- // skip empty and already matched entries
- if( items[i].nameid == 0 || flag[i] )
- continue;
-
- if( found )
- StrBuf->AppendStr(&buf, ",");
- else
- found = true;
-
- StrBuf->Printf(&buf, "('%d', '%d', '%d', '%u', '%d', '%d', '%d', '%u', '%d', '%d', '%"PRIu64"'",
- id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].bound, items[i].unique_id);
- for( j = 0; j < MAX_SLOTS; ++j )
+ for (j = 0; j < MAX_SLOTS; ++j)
StrBuf->Printf(&buf, ", '%d'", items[i].card[j]);
+ if (has_favorite)
+ StrBuf->Printf(&buf, ", '%d'", items[i].favorite);
StrBuf->AppendStr(&buf, ")");
}
- if( found && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf)) ) {
+ if (found && SQL_ERROR == SQL->QueryStr(inter->sql_handle, StrBuf->Value(&buf))) {
Sql_ShowDebug(inter->sql_handle);
errors++;
}
@@ -6062,7 +5936,6 @@ void char_defaults(void)
chr->create_charstatus = char_create_charstatus;
chr->mmo_char_tosql = char_mmo_char_tosql;
chr->memitemdata_to_sql = char_memitemdata_to_sql;
- chr->inventory_to_sql = char_inventory_to_sql;
chr->mmo_gender = char_mmo_gender;
chr->mmo_chars_fromsql = char_mmo_chars_fromsql;
chr->mmo_char_fromsql = char_mmo_char_fromsql;
diff --git a/src/char/char.h b/src/char/char.h
index 6d8a9815c..aedc52fbe 100644
--- a/src/char/char.h
+++ b/src/char/char.h
@@ -72,7 +72,7 @@ struct mmo_map_server {
#define DEFAULT_AUTOSAVE_INTERVAL (300*1000)
-enum {
+enum inventory_table_type {
TABLE_INVENTORY,
TABLE_CART,
TABLE_STORAGE,
@@ -129,7 +129,6 @@ struct char_interface {
DBData (*create_charstatus) (DBKey key, va_list args);
int (*mmo_char_tosql) (int char_id, struct mmo_charstatus* p);
int (*memitemdata_to_sql) (const struct item items[], int max, int id, int tableswitch);
- int (*inventory_to_sql) (const struct item items[], int max, int id);
int (*mmo_gender) (const struct char_session_data *sd, const struct mmo_charstatus *p, char sex);
int (*mmo_chars_fromsql) (struct char_session_data* sd, uint8* buf);
int (*mmo_char_fromsql) (int char_id, struct mmo_charstatus* p, bool load_everything);
diff --git a/src/char/int_party.c b/src/char/int_party.c
index c011f1b8f..684d846d4 100644
--- a/src/char/int_party.c
+++ b/src/char/int_party.c
@@ -485,7 +485,7 @@ int mapif_parse_CreateParty(int fd, const char *name, int item, int item2, const
int i;
nullpo_ret(name);
nullpo_ret(leader);
- if( (p=inter_party->search_partyname(name))!=NULL){
+ if (!*name || (p = inter_party->search_partyname(name)) != NULL) {
mapif->party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}
@@ -496,7 +496,8 @@ int mapif_parse_CreateParty(int fd, const char *name, int item, int item2, const
if (name[i] == '"') { /* client-special-char */
char *newname = aStrndup(name, NAME_LENGTH-1);
normalize_name(newname,"\"");
- mapif->parse_CreateParty(fd,name,item,item2,leader);
+ trim(newname);
+ mapif->parse_CreateParty(fd, newname, item, item2, leader);
aFree(newname);
return 0;
}
@@ -513,7 +514,7 @@ int mapif_parse_CreateParty(int fd, const char *name, int item, int item2, const
p = (struct party_data*)aCalloc(1, sizeof(struct party_data));
- memcpy(p->party.name,name,NAME_LENGTH);
+ safestrncpy(p->party.name, name, NAME_LENGTH);
p->party.exp=0;
p->party.item=(item?1:0)|(item2?2:0);
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 77b9abab6..0abae6092 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -971,7 +971,7 @@ enum weapon_type {
W_GRENADE, //21
W_HUUMA, //22
W_2HSTAFF, //23
- MAX_WEAPON_TYPE,
+ MAX_SINGLE_WEAPON_TYPE,
// dual-wield constants
W_DOUBLE_DD, ///< 2 daggers
W_DOUBLE_SS, ///< 2 swords
@@ -979,6 +979,7 @@ enum weapon_type {
W_DOUBLE_DS, ///< dagger + sword
W_DOUBLE_DA, ///< dagger + axe
W_DOUBLE_SA, ///< sword + axe
+ MAX_WEAPON_TYPE,
};
enum ammo_type {
@@ -1047,4 +1048,8 @@ enum hz_char_ask_name_answer {
#error MAX_ZENY is too big
#endif
+#if MAX_SLOTS < 4
+#error MAX_SLOTS it too small
+#endif
+
#endif /* COMMON_MMO_H */
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 14eab56e0..f28c24dcb 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -9800,143 +9800,124 @@ void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bo
}
/**
- * Executes an at-command
+ * Executes an at-command.
+ *
* @param fd fd associated to the invoking character
* @param sd sd associated to the invoking character
* @param message atcommand arguments
* @param player_invoked true if the command was invoked by a player, false if invoked by the server (bypassing any restrictions)
+ *
+ * @retval true if the message was recognized as atcommand.
+ * @retval false if the message should be considered a non-command message.
*/
-bool atcommand_exec(const int fd, struct map_session_data *sd, const char *message, bool player_invoked) {
- char charname[NAME_LENGTH], params[100];
- char charname2[NAME_LENGTH];
- char command[100];
+bool atcommand_exec(const int fd, struct map_session_data *sd, const char *message, bool player_invoked)
+{
+ char params[100], command[100];
char output[CHAT_SIZE_MAX];
- //Reconstructed message
+ // Reconstructed message
char atcmd_msg[CHAT_SIZE_MAX];
struct map_session_data *ssd = NULL; //sd for target
- AtCommandInfo * info;
+ AtCommandInfo *info;
+
+ bool is_atcommand = true; // false if it's a charcommand
nullpo_retr(false, sd);
- //Shouldn't happen
- if ( !message || !*message )
+ // Shouldn't happen
+ if (message == NULL || *message == '\0')
return false;
- //Block NOCHAT but do not display it as a normal message
+ // Block NOCHAT but do not display it as a normal message
if (pc_ismuted(&sd->sc, MANNER_NOCOMMAND))
return true;
// skip 10/11-langtype's codepage indicator, if detected
- if ( message[0] == '|' && strlen(message) >= 4 && (message[3] == atcommand->at_symbol || message[3] == atcommand->char_symbol) )
+ if (message[0] == '|' && strlen(message) >= 4 && (message[3] == atcommand->at_symbol || message[3] == atcommand->char_symbol))
message += 3;
- //Should display as a normal message
- if ( *message != atcommand->at_symbol && *message != atcommand->char_symbol )
+ // Should display as a normal message
+ if (*message != atcommand->at_symbol && *message != atcommand->char_symbol)
return false;
if (player_invoked) {
- //Commands are disabled on maps flagged as 'nocommand'
- if ( map->list[sd->bl.m].nocommand && pc_get_group_level(sd) < map->list[sd->bl.m].nocommand ) {
+ // Commands are disabled on maps flagged as 'nocommand'
+ if (map->list[sd->bl.m].nocommand && pc_get_group_level(sd) < map->list[sd->bl.m].nocommand) {
clif->message(fd, msg_fd(fd,143));
return false;
}
}
- if (*message == atcommand->char_symbol) {
- do {
- char params2[100];
- int x, y, z;
-
- //Checks to see if #command has a name or a name + parameters.
- x = sscanf(message, "%99s \"%23[^\"]\" %99[^\n]", command, charname, params);
- y = sscanf(message, "%99s %23s %99[^\n]", command, charname2, params2);
-
- //z always has the value of the scan that was successful
- z = ( x > 1 ) ? x : y;
+ if (*message == atcommand->char_symbol)
+ is_atcommand = false;
- //#command + name means the sufficient target was used and anything else after
- //can be looked at by the actual command function since most scan to see if the
- //right parameters are used.
- if ( x > 2 ) {
- sprintf(atcmd_msg, "%s %s", command, params);
- break;
- }
- else if ( y > 2 ) {
- sprintf(atcmd_msg, "%s %s", command, params2);
- break;
- }
- //Regardless of what style the #command is used, if it's correct, it will always have
- //this value if there is no parameter. Send it as just the #command
- else if ( z == 2 ) {
- sprintf(atcmd_msg, "%s", command);
- break;
- }
+ if (is_atcommand) { // #command
+ sprintf(atcmd_msg, "%s", message);
+ ssd = sd;
+ } else { // @command
+ char charname[NAME_LENGTH];
+ int n;
+
+ // Checks to see if #command has a name or a name + parameters.
+ if ((n = sscanf(message, "%99s \"%23[^\"]\" %99[^\n]", command, charname, params)) < 2
+ && (n = sscanf(message, "%99s %23s %99[^\n]", command, charname, params)) < 2
+ ) {
+ if (pc_get_group_level(sd) == 0) {
+ if (n < 1)
+ return false; // no command found. Display as normal 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[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 */
+ info = atcommand->get_info_byname(atcommand->check_alias(command + 1));
+ if (info == NULL || 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;
+ }
}
sprintf(output, msg_fd(fd,1388), atcommand->char_symbol); // Charcommand failed (usage: %c<command> <char name> <parameters>).
clif->message(fd, output);
return true;
- } while(0);
- }
- else /*if (*message == atcommand->at_symbol)*/ {
- //atcmd_msg is constructed above differently for charcommands
- //it's copied from message if not a charcommand so it can
- //pass through the rest of the code compatible with both symbols
- sprintf(atcmd_msg, "%s", message);
+ }
+
+ ssd = map->nick2sd(charname);
+ if (ssd == NULL) {
+ sprintf(output, msg_fd(fd,1389), command); // %s failed. Player not found.
+ clif->message(fd, output);
+ return true;
+ }
+
+ if (n > 2)
+ sprintf(atcmd_msg, "%s %s", command, params);
+ else
+ sprintf(atcmd_msg, "%s", command);
}
pc->update_idle_time(sd, BCIDLE_ATCOMMAND);
//Clearing these to be used once more.
- memset(command, '\0', sizeof(command));
- memset(params, '\0', sizeof(params));
+ memset(command, '\0', sizeof command);
+ memset(params, '\0', sizeof params);
//check to see if any params exist within this command
- if( sscanf(atcmd_msg, "%99s %99[^\n]", command, params) < 2 )
+ if (sscanf(atcmd_msg, "%99s %99[^\n]", command, params) < 2)
params[0] = '\0';
// @commands (script based)
- if(player_invoked && atcommand->binding_count > 0) {
- struct atcmd_binding_data * binding;
-
+ if (player_invoked && atcommand->binding_count > 0) {
// Get atcommand binding
- binding = atcommand->get_bind_byname(command);
+ struct atcmd_binding_data *binding = atcommand->get_bind_byname(command);
// Check if the binding isn't NULL and there is a NPC event, level of usage met, et cetera
- if( binding != NULL
- && binding->npc_event[0]
+ if (binding != NULL && binding->npc_event[0] != '\0'
&& (
- (*atcmd_msg == atcommand->at_symbol && pc_get_group_level(sd) >= binding->group_lv)
- || (*atcmd_msg == atcommand->char_symbol && pc_get_group_level(sd) >= binding->group_lv_char)
+ (is_atcommand && pc_get_group_level(sd) >= binding->group_lv)
+ || (!is_atcommand && pc_get_group_level(sd) >= binding->group_lv_char)
)
) {
- // Check if self or character invoking; if self == character invoked, then self invoke.
- bool invokeFlag = ((*atcmd_msg == atcommand->at_symbol) ? 1 : 0);
-
- // Check if the command initiated is a character command
- if (*message == atcommand->char_symbol
- && (ssd = map->nick2sd(charname)) == NULL
- && (ssd = map->nick2sd(charname2)) == NULL
- ) {
- sprintf(output, msg_fd(fd,1389), command); // %s failed. Player not found.
- clif->message(fd, output);
- return true;
- }
-
- if( binding->log ) /* log only if this command should be logged [Ind/Hercules] */
+ if (binding->log) /* log only if this command should be logged [Ind/Hercules] */
logs->atcommand(sd, atcmd_msg);
- npc->do_atcmd_event((invokeFlag ? sd : ssd), command, params, binding->npc_event);
+ npc->do_atcmd_event(ssd, command, params, binding->npc_event);
return true;
}
}
@@ -9944,51 +9925,40 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
//Grab the command information and check for the proper GM level required to use it or if the command exists
info = atcommand->get_info_byname(atcommand->check_alias(command + 1));
if (info == NULL) {
- if( pc_get_group_level(sd) ) { // TODO: remove or replace with proper permission
- sprintf(output, msg_fd(fd,153), command); // "%s is Unknown Command."
- clif->message(fd, output);
- atcommand->get_suggestions(sd, command + 1, *message == atcommand->at_symbol);
- return true;
- } else
+ if (pc_get_group_level(sd) == 0) // TODO: remove or replace with proper permission
return false;
+
+ sprintf(output, msg_fd(fd,153), command); // "%s is Unknown Command."
+ clif->message(fd, output);
+ atcommand->get_suggestions(sd, command + 1, is_atcommand);
+ return true;
}
if (player_invoked) {
int i;
- 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) ) {
+ if ((is_atcommand && info->at_groups[pcg->get_idx(sd->group)] == 0)
+ || (!is_atcommand && info->char_groups[pcg->get_idx(sd->group)] == 0))
return false;
- }
- if( pc_isdead(sd) && pc_has_permission(sd,PC_PERM_DISABLE_CMD_DEAD) ) {
+
+ if (pc_isdead(sd) && pc_has_permission(sd,PC_PERM_DISABLE_CMD_DEAD)) {
clif->message(fd, msg_fd(fd,1393)); // You can't use commands while dead
return true;
}
- for(i = 0; i < map->list[sd->bl.m].zone->disabled_commands_count; i++) {
- if( info->func == map->list[sd->bl.m].zone->disabled_commands[i]->cmd ) {
+ for (i = 0; i < map->list[sd->bl.m].zone->disabled_commands_count; i++) {
+ if (info->func == map->list[sd->bl.m].zone->disabled_commands[i]->cmd) {
if (pc_get_group_level(sd) < map->list[sd->bl.m].zone->disabled_commands[i]->group_lv) {
clif->messagecolor_self(sd->fd, COLOR_RED, "This command is disabled in this area");
return true;
- } else {
- break;/* already found the matching command, no need to keep checking -- just go on */
}
+ break; /* already found the matching command, no need to keep checking -- just go on */
}
}
}
- // Check if target is valid only if confirmed that player can use command.
- if (*message == atcommand->char_symbol
- && (ssd = map->nick2sd(charname)) == NULL
- && (ssd = map->nick2sd(charname2)) == NULL
- ) {
- sprintf(output, msg_fd(fd,1389), command); // %s failed. Player not found.
- clif->message(fd, output);
- return true;
- }
-
//Attempt to use the command
- if ( (info->func(fd, (*atcmd_msg == atcommand->at_symbol) ? sd : ssd, command, params,info) != true) ) {
+ if ((info->func(fd, ssd, command, params,info) != true)) {
#ifdef AUTOTRADE_PERSISTENCY
- if( info->func == atcommand_autotrade ) /** autotrade deletes caster, so we got nothing more to do here **/
+ if (info->func == atcommand_autotrade) /* autotrade deletes caster, so we got nothing more to do here */
return true;
#endif
sprintf(output,msg_fd(fd,154), command); // %s failed.
@@ -9996,8 +9966,8 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
return true;
}
- if( info->log ) /* log only if this command should be logged [Ind/Hercules] */
- logs->atcommand(sd, *atcmd_msg == atcommand->at_symbol ? atcmd_msg : message);
+ if (info->log) /* log only if this command should be logged [Ind/Hercules] */
+ logs->atcommand(sd, is_atcommand ? atcmd_msg : message);
return true;
}
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 27adc387b..630bc4488 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -1613,6 +1613,12 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
memset(&entry->stack, '\0', sizeof(entry->stack));
}
+ if (entry->type == IT_WEAPON && (entry->look < 0 || entry->look >= MAX_SINGLE_WEAPON_TYPE)) {
+ ShowWarning("itemdb_validate_entry: Invalid View for weapon items. View value %d for item %d (%s) in '%s', defaulting to 1.\n",
+ entry->look, entry->nameid, entry->jname, source);
+ entry->look = 1;
+ }
+
entry->wlv = cap_value(entry->wlv, REFINE_TYPE_ARMOR, REFINE_TYPE_MAX);
if( !entry->elvmax )
@@ -1666,14 +1672,21 @@ void itemdb_readdb_job_sub(struct item_data *id, struct config_setting_t *t)
{
int idx = 0;
struct config_setting_t *it = NULL;
+ bool enable_all = false;
+
id->class_base[0] = id->class_base[1] = id->class_base[2] = 0;
+
+ if (libconfig->setting_lookup_bool_real(t, "All", &enable_all) && enable_all) {
+ itemdb->jobmask2mapid(id->class_base, UINT64_MAX);
+ }
while ((it = libconfig->setting_get_elem(t, idx++)) != NULL) {
const char *job_name = config_setting_name(it);
int job_id;
- if (strcmp(job_name, "All") == 0) {
- itemdb->jobmask2mapid(id->class_base, UINT64_MAX);
- } else if ((job_id = pc->check_job_name(job_name)) == -1) {
+ if (strcmp(job_name, "All") == 0)
+ continue;
+
+ if ((job_id = pc->check_job_name(job_name)) == -1) {
ShowWarning("itemdb_readdb_job_sub: unknown job name '%s'!\n", job_name);
} else {
itemdb->jobid2mapid(id->class_base, job_id, libconfig->setting_get_bool(it));
@@ -1825,8 +1838,10 @@ int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *
if ((t = libconfig->setting_get_member(it, "Job")) != NULL) {
if (config_setting_is_group(t)) {
itemdb->readdb_job_sub(&id, t);
- } else if (itemdb->lookup_const(it, "Job", &i32) && i32 >= 0) {
- itemdb->jobmask2mapid(id.class_base, i32);
+ } else if (itemdb->lookup_const(it, "Job", &i32)) { // This is an unsigned value, do not check for >= 0
+ itemdb->jobmask2mapid(id.class_base, (uint64)i32);
+ } else if (!inherit) {
+ itemdb->jobmask2mapid(id.class_base, UINT64_MAX);
}
} else if (!inherit) {
itemdb->jobmask2mapid(id.class_base, UINT64_MAX);
diff --git a/src/map/pc.c b/src/map/pc.c
index 51aba9509..7b4d47db2 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -2885,6 +2885,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
break;
default:
ShowWarning("pc_bonus: unknown type %d %d !\n",type,val);
+ Assert_report(0);
break;
}
return 0;
@@ -3677,6 +3678,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
#endif
default:
ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
+ Assert_report(0);
break;
}
return 0;
@@ -3849,6 +3851,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
default:
ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val);
+ Assert_report(0);
break;
}
@@ -3943,6 +3946,7 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4
default:
ShowWarning("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val);
+ Assert_report(0);
break;
}
@@ -3970,6 +3974,7 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4
default:
ShowWarning("pc_bonus5: unknown type %d %d %d %d %d %d!\n",type,type2,type3,type4,type5,val);
+ Assert_report(0);
break;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index db1d7a9da..0d2bca84d 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -302,8 +302,8 @@ BEGIN_ZEROED_BLOCK; // this block will be globally zeroed at the beginning of st
int reseff[SC_COMMON_MAX-SC_COMMON_MIN+1];
int weapon_coma_ele[ELE_MAX];
int weapon_coma_race[RC_MAX];
- int weapon_atk[16];
- int weapon_atk_rate[16];
+ int weapon_atk[MAX_WEAPON_TYPE];
+ int weapon_atk_rate[MAX_WEAPON_TYPE];
int arrow_addele[ELE_MAX];
int arrow_addrace[RC_MAX];
int arrow_addsize[3];
diff --git a/src/map/status.c b/src/map/status.c
index d04e88e3c..82c427317 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -12826,7 +12826,7 @@ bool status_readdb_sizefix(char* fields[], int columns, int current)
{
unsigned int i;
- for(i = 0; i < MAX_WEAPON_TYPE; i++)
+ for(i = 0; i < MAX_SINGLE_WEAPON_TYPE; i++)
{
status->dbs->atkmods[current][i] = atoi(fields[i]);
}
@@ -13008,7 +13008,7 @@ int status_readdb(void)
// size_fix.txt
for(i = 0; i < ARRAYLENGTH(status->dbs->atkmods); i++)
- for(j = 0; j < MAX_WEAPON_TYPE; j++)
+ for(j = 0; j < MAX_SINGLE_WEAPON_TYPE; j++)
status->dbs->atkmods[i][j] = 100;
// refine_db.txt
@@ -13023,7 +13023,7 @@ int status_readdb(void)
// read databases
//
sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2);
- sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->dbs->atkmods), status->readdb_sizefix);
+ sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_SINGLE_WEAPON_TYPE, MAX_SINGLE_WEAPON_TYPE, ARRAYLENGTH(status->dbs->atkmods), status->readdb_sizefix);
status->readdb_refine_libconfig(DBPATH"refine_db.conf");
sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig);
status->read_job_db();
diff --git a/src/map/status.h b/src/map/status.h
index 296b5baae..4e2f1bdc0 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -2169,7 +2169,7 @@ BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when sta
/* */
struct s_refine_info refine_info[REFINE_TYPE_MAX];
/* */
- int atkmods[3][MAX_WEAPON_TYPE];//ATK weapon modification for size (size_fix.txt)
+ int atkmods[3][MAX_SINGLE_WEAPON_TYPE];//ATK weapon modification for size (size_fix.txt)
char job_bonus[CLASS_COUNT][MAX_LEVEL];
sc_conf_type sc_conf[SC_MAX];
END_ZEROED_BLOCK; /* End */
diff --git a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc
index 89bb847ce..7210920e5 100644
--- a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc
@@ -62,8 +62,6 @@ struct {
struct HPMHookPoint *HP_chr_mmo_char_tosql_post;
struct HPMHookPoint *HP_chr_memitemdata_to_sql_pre;
struct HPMHookPoint *HP_chr_memitemdata_to_sql_post;
- struct HPMHookPoint *HP_chr_inventory_to_sql_pre;
- struct HPMHookPoint *HP_chr_inventory_to_sql_post;
struct HPMHookPoint *HP_chr_mmo_gender_pre;
struct HPMHookPoint *HP_chr_mmo_gender_post;
struct HPMHookPoint *HP_chr_mmo_chars_fromsql_pre;
@@ -1469,8 +1467,6 @@ struct {
int HP_chr_mmo_char_tosql_post;
int HP_chr_memitemdata_to_sql_pre;
int HP_chr_memitemdata_to_sql_post;
- int HP_chr_inventory_to_sql_pre;
- int HP_chr_inventory_to_sql_post;
int HP_chr_mmo_gender_pre;
int HP_chr_mmo_gender_post;
int HP_chr_mmo_chars_fromsql_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc
index f579fb301..fbf332ffb 100644
--- a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc
@@ -44,7 +44,6 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(chr->create_charstatus, HP_chr_create_charstatus) },
{ HP_POP(chr->mmo_char_tosql, HP_chr_mmo_char_tosql) },
{ HP_POP(chr->memitemdata_to_sql, HP_chr_memitemdata_to_sql) },
- { HP_POP(chr->inventory_to_sql, HP_chr_inventory_to_sql) },
{ HP_POP(chr->mmo_gender, HP_chr_mmo_gender) },
{ HP_POP(chr->mmo_chars_fromsql, HP_chr_mmo_chars_fromsql) },
{ HP_POP(chr->mmo_char_fromsql, HP_chr_mmo_char_fromsql) },
diff --git a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
index 6ede0eb2b..4dcc5dffb 100644
--- a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
@@ -555,33 +555,6 @@ int HP_chr_memitemdata_to_sql(const struct item items[], int max, int id, int ta
}
return retVal___;
}
-int HP_chr_inventory_to_sql(const struct item items[], int max, int id) {
- int hIndex = 0;
- int retVal___ = 0;
- if( HPMHooks.count.HP_chr_inventory_to_sql_pre ) {
- int (*preHookFunc) (const struct item *items[], int *max, int *id);
- *HPMforce_return = false;
- for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_inventory_to_sql_pre; hIndex++ ) {
- preHookFunc = HPMHooks.list.HP_chr_inventory_to_sql_pre[hIndex].func;
- retVal___ = preHookFunc(&items, &max, &id);
- }
- if( *HPMforce_return ) {
- *HPMforce_return = false;
- return retVal___;
- }
- }
- {
- retVal___ = HPMHooks.source.chr.inventory_to_sql(items, max, id);
- }
- if( HPMHooks.count.HP_chr_inventory_to_sql_post ) {
- int (*postHookFunc) (int retVal___, const struct item *items[], int *max, int *id);
- for(hIndex = 0; hIndex < HPMHooks.count.HP_chr_inventory_to_sql_post; hIndex++ ) {
- postHookFunc = HPMHooks.list.HP_chr_inventory_to_sql_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, &items, &max, &id);
- }
- }
- return retVal___;
-}
int HP_chr_mmo_gender(const struct char_session_data *sd, const struct mmo_charstatus *p, char sex) {
int hIndex = 0;
int retVal___ = 0;
diff --git a/src/plugins/db2sql.c b/src/plugins/db2sql.c
index 34e1c2053..86708ebbc 100644
--- a/src/plugins/db2sql.c
+++ b/src/plugins/db2sql.c
@@ -30,6 +30,7 @@
#include "map/itemdb.h"
#include "map/mob.h"
#include "map/map.h"
+#include "map/pc.h"
#include "common/HPMDataCheck.h"
@@ -120,6 +121,100 @@ void db2sql_fileheader(void)
}
/**
+ * Converts the Job field of an Item DB entry to the numeric format used in the SQL table.
+ */
+uint64 itemdb2sql_readdb_job_sub(struct config_setting_t *t)
+{
+ uint64 jobmask = 0;
+ int idx = 0;
+ struct config_setting_t *it = NULL;
+ bool enable_all = false;
+
+ if (libconfig->setting_lookup_bool_real(t, "All", &enable_all) && enable_all) {
+ jobmask |= UINT64_MAX;
+ }
+ while ((it = libconfig->setting_get_elem(t, idx++)) != NULL) {
+ const char *job_name = config_setting_name(it);
+ int job_id;
+
+ if (strcmp(job_name, "All") == 0)
+ continue;
+
+ if ((job_id = pc->check_job_name(job_name)) != -1) {
+ uint64 newmask = 0;
+ switch (job_id) {
+ // Base Classes
+ case JOB_NOVICE:
+ case JOB_SUPER_NOVICE:
+ newmask = 1ULL << JOB_NOVICE;
+ break;
+ case JOB_SWORDMAN:
+ case JOB_MAGE:
+ case JOB_ARCHER:
+ case JOB_ACOLYTE:
+ case JOB_MERCHANT:
+ case JOB_THIEF:
+ // 2-1 Classes
+ case JOB_KNIGHT:
+ case JOB_PRIEST:
+ case JOB_WIZARD:
+ case JOB_BLACKSMITH:
+ case JOB_HUNTER:
+ case JOB_ASSASSIN:
+ // 2-2 Classes
+ case JOB_CRUSADER:
+ case JOB_MONK:
+ case JOB_SAGE:
+ case JOB_ALCHEMIST:
+ case JOB_BARD:
+ case JOB_DANCER:
+ case JOB_ROGUE:
+ // Extended Classes
+ case JOB_GUNSLINGER:
+ case JOB_NINJA:
+ newmask = 1ULL << job_id;
+ break;
+ // Extended Classes (special handling)
+ case JOB_TAEKWON:
+ newmask = 1ULL << 21;
+ break;
+ case JOB_STAR_GLADIATOR:
+ newmask = 1ULL << 22;
+ break;
+ case JOB_SOUL_LINKER:
+ newmask = 1ULL << 23;
+ break;
+ // Other Classes
+ case JOB_GANGSI: //Bongun/Munak
+ newmask = 1ULL << 26;
+ break;
+ case JOB_DEATH_KNIGHT:
+ newmask = 1ULL << 27;
+ break;
+ case JOB_DARK_COLLECTOR:
+ newmask = 1ULL << 28;
+ break;
+ case JOB_KAGEROU:
+ case JOB_OBORO:
+ newmask = 1ULL << 29;
+ break;
+ case JOB_REBELLION:
+ newmask = 1ULL << 30;
+ break;
+ }
+
+ if (libconfig->setting_get_bool(it)) {
+ jobmask |= newmask;
+ } else {
+ jobmask &= ~newmask;
+ }
+ }
+ }
+
+ return jobmask;
+}
+
+/**
* Converts an Item DB entry to SQL.
*
* @see itemdb_readdb_libconfig_sub.
@@ -134,6 +229,7 @@ int itemdb2sql_sub(struct config_setting_t *entry, int n, const char *source)
char *str;
int i32;
uint32 ui32;
+ uint64 ui64;
struct config_setting_t *t = NULL;
StringBuf buf;
@@ -180,11 +276,18 @@ int itemdb2sql_sub(struct config_setting_t *entry, int n, const char *source)
StrBuf->Printf(&buf, "'%d',", it->slot);
// equip_jobs
- if (libconfig->setting_lookup_int(entry, "Job", &i32)) // This is an unsigned value, do not check for >= 0
- ui32 = (uint32)i32;
- else
- ui32 = UINT_MAX;
- StrBuf->Printf(&buf, "'%u',", ui32);
+ if ((t = libconfig->setting_get_member(entry, "Job")) != NULL) {
+ if (config_setting_is_group(t)) {
+ ui64 = itemdb2sql_readdb_job_sub(t);
+ } else if (itemdb->lookup_const(entry, "Job", &i32)) { // This is an unsigned value, do not check for >= 0
+ ui64 = (uint64)i32;
+ } else {
+ ui64 = UINT64_MAX;
+ }
+ } else {
+ ui64 = UINT64_MAX;
+ }
+ StrBuf->Printf(&buf, "'0x%"PRIX64"',", ui64);
// equip_upper
if (libconfig->setting_lookup_int(entry, "Upper", &i32) && i32 >= 0)
@@ -344,7 +447,7 @@ void itemdb2sql_tableheader(void)
" `defence` smallint(5) UNSIGNED DEFAULT NULL,\n"
" `range` tinyint(2) UNSIGNED DEFAULT NULL,\n"
" `slots` tinyint(2) UNSIGNED DEFAULT NULL,\n"
- " `equip_jobs` int(12) UNSIGNED DEFAULT NULL,\n"
+ " `equip_jobs` bigint(20) UNSIGNED DEFAULT NULL,\n"
" `equip_upper` tinyint(8) UNSIGNED DEFAULT NULL,\n"
" `equip_genders` tinyint(2) UNSIGNED DEFAULT NULL,\n"
" `equip_locations` smallint(4) UNSIGNED DEFAULT NULL,\n"