diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/char/char.c | 247 | ||||
-rw-r--r-- | src/char/char.h | 3 | ||||
-rw-r--r-- | src/char/int_party.c | 7 | ||||
-rw-r--r-- | src/common/mmo.h | 7 | ||||
-rw-r--r-- | src/map/atcommand.c | 192 | ||||
-rw-r--r-- | src/map/itemdb.c | 25 | ||||
-rw-r--r-- | src/map/pc.c | 5 | ||||
-rw-r--r-- | src/map/pc.h | 4 | ||||
-rw-r--r-- | src/map/status.c | 6 | ||||
-rw-r--r-- | src/map/status.h | 2 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc | 4 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc | 1 | ||||
-rw-r--r-- | src/plugins/HPMHooking/HPMHooking_char.Hooks.inc | 27 | ||||
-rw-r--r-- | src/plugins/db2sql.c | 115 |
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" |