From e7b654aaab97f64cabaf54adb5f5031a866c6bde Mon Sep 17 00:00:00 2001 From: Cydh Ramdh Date: Thu, 26 Jun 2014 22:12:19 +0700 Subject: [PATCH] - Follow up a8a4425 (bugreport:9062) - Added check for item group ID usage on item bonus - Moved this '(sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= battle_config.taekwon_ranker_min_lv && pc_famerank(sd->status.char_id, MAPID_TAEKWON)' to a macro 'pc_is_taekwon_ranker(sd)' Signed-off-by: Cydh Ramdh --- src/map/itemdb.c | 49 ++++++++++++++++++++++++++++-------------------- src/map/itemdb.h | 6 +++--- src/map/mob.c | 2 +- src/map/pc.c | 24 ++++++++++++++---------- src/map/pc.h | 2 ++ src/map/skill.c | 2 +- src/map/status.c | 9 ++++----- 7 files changed, 54 insertions(+), 40 deletions(-) diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 79bc519ff9..0ca102ce87 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -18,18 +18,28 @@ #include #include -struct item_data *dummy_item; /// This is the default dummy item used for non-existant items. [Skotlex] - -static DBMap* itemdb; /// Item DB +static DBMap *itemdb; /// Item DB static DBMap *itemdb_combo; /// Item Combo DB static DBMap *itemdb_group; /// Item Group DB -DBMap * itemdb_get_combodb(){ - return itemdb_combo; +struct item_data *dummy_item; /// This is the default dummy item used for non-existant items. [Skotlex] + +/** +* Check if combo exists +* @param combo_id +* @return NULL if not exist, or struct item_combo* +*/ +struct item_combo *itemdb_combo_exists(unsigned short combo_id) { + return (struct item_combo *)idb_get(itemdb_combo, combo_id); } -DBMap * itemdb_get_groupdb() { - return itemdb_group; +/** +* Check if item group exists +* @param group_id +* @return NULL if not exist, or s_item_group_db * +*/ +struct s_item_group_db *itemdb_group_exists(unsigned short group_id) { + return (struct s_item_group_db *)idb_get(itemdb_group, group_id); } /** @@ -44,17 +54,15 @@ static int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap) str = va_arg(ap,char *); dst = va_arg(ap,struct item_data **); dst2 = va_arg(ap,struct item_data **); + if (item == dummy_item) return 0; //Absolute priority to Aegis code name. - if (*dst != NULL) - return 0; if (strcmpi(item->name,str) == 0) *dst = item; //Second priority to Client displayed name. - if (*dst2 != NULL) return 0; if (strcmpi(item->jname,str) == 0) *dst2 = item; return 0; @@ -67,8 +75,7 @@ static int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap) *------------------------------------------*/ struct item_data* itemdb_searchname(const char *str) { - struct item_data* item = NULL; - struct item_data* item2 = NULL; + struct item_data *item = NULL, * item2 = NULL; itemdb->foreach(itemdb,itemdb_searchname_sub,str,&item,&item2); return item ? item : item2; @@ -82,8 +89,10 @@ static int itemdb_searchname_array_sub(DBKey key, DBData data, va_list ap) struct item_data *item = db_data2ptr(&data); char *str; str = va_arg(ap,char *); - if (item == dummy_item) - return 1; //Invalid item. + + if (item && dummy_item) + return 1; + if (stristr(item->jname,str)) return 0; if (stristr(item->name,str)) @@ -369,8 +378,7 @@ static void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask) /** * Create dummy item data */ -static void create_dummy_data(void) -{ +static void create_dummy_data(void) { CREATE(dummy_item, struct item_data, 1); memset(dummy_item, 0, sizeof(struct item_data)); @@ -381,6 +389,7 @@ static void create_dummy_data(void) safestrncpy(dummy_item->name, "UNKNOWN_ITEM", sizeof(dummy_item->name)); safestrncpy(dummy_item->jname, "Unknown Item", sizeof(dummy_item->jname)); dummy_item->view_id = UNKNOWN_ITEM_ID; + idb_put(itemdb, dummy_item->nameid, dummy_item); } /*========================================== @@ -392,7 +401,8 @@ struct item_data* itemdb_search(unsigned short nameid) { struct item_data* id = (struct item_data*)idb_get(itemdb, nameid); if (id) return id; - ShowWarning("itemdb_search: Item ID %hu does not exists in the item_db. Using dummy data.\n", nameid); + if (nameid != dummy_item->nameid) // Avoid previous item that assigned with dummy_item to shows this message again + ShowWarning("itemdb_search: Item ID %hu does not exists in the item_db. Using dummy data.\n", nameid); return dummy_item; } @@ -1674,10 +1684,10 @@ void itemdb_reload(void) { * Finalizing Item DB */ void do_final_itemdb(void) { + db_destroy(itemdb_combo); itemdb_group->destroy(itemdb_group, itemdb_group_free); itemdb->destroy(itemdb, itemdb_final_sub); destroy_item_data(dummy_item); - db_destroy(itemdb_combo); } /** @@ -1687,7 +1697,6 @@ void do_init_itemdb(void) { itemdb = idb_alloc(DB_OPT_BASE); itemdb_combo = idb_alloc(DB_OPT_BASE); itemdb_group = idb_alloc(DB_OPT_BASE); - create_dummy_data(); //Dummy data item. - + create_dummy_data(); //Dummy data item. itemdb_read(); } diff --git a/src/map/itemdb.h b/src/map/itemdb.h index dca8c8f7f3..5c0265e691 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -482,12 +482,12 @@ bool itemdb_isstackable2(struct item_data *id); uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID bool itemdb_isNoEquip(struct item_data *id, uint16 m); +struct item_combo *itemdb_combo_exists(unsigned short combo_id); + +struct s_item_group_db *itemdb_group_exists(unsigned short group_id); char itemdb_pc_get_itemgroup(uint16 group_id, struct map_session_data *sd); uint16 itemdb_get_randgroupitem_count(uint16 group_id, uint8 sub_group, unsigned short nameid); -DBMap * itemdb_get_combodb(); -DBMap * itemdb_get_groupdb(); - void itemdb_reload(void); void do_final_itemdb(void); diff --git a/src/map/mob.c b/src/map/mob.c index d98f3f5193..531db89183 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -2436,7 +2436,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) for (i = 0; i < ARRAYLENGTH(sd->add_drop); i++) { if (!&sd->add_drop[i] || (!sd->add_drop[i].nameid && !sd->add_drop[i].group)) continue; - if ((sd->add_drop[i].race < 0 && sd->add_drop[i].race == -md->mob_id) || //Race < 0, use mob_id + if ((sd->add_drop[i].race < RC_NONE_ && sd->add_drop[i].race == -md->mob_id) || //Race < 0, use mob_id (sd->add_drop[i].race == RC_ALL || sd->add_drop[i].race == status->race) || //Matched race (sd->add_drop[i].class_ == CLASS_ALL || sd->add_drop[i].class_ == status->class_)) //Matched class { diff --git a/src/map/pc.c b/src/map/pc.c index 4cd299727d..ad941d26fb 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -401,7 +401,7 @@ void pc_addfame(struct map_session_data *sd,int count) } /** - * Check whether a player ID is in the fame rankers' list of its job, returns his/her position if so, 0 else + * Check whether a player ID is in the fame rankers list of its job, returns his/her position if so, 0 else * @param sd * @param job Job use enum e_mapid * @return Rank @@ -1654,7 +1654,7 @@ void pc_calc_skilltree(struct map_session_data *sd) } } while(flag); - if( c > 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= battle_config.taekwon_ranker_min_lv && sd->status.skill_point == 0 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) ) { + if( c > 0 && sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) ) { /* Taekwon Ranker Bonus Skill Tree ============================================ - Grant All Taekwon Tree, but only as Bonus Skills in case they drop from ranking. @@ -2031,10 +2031,16 @@ static void pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, static void pc_bonus_item_drop(struct s_add_drop *drop, const short max, unsigned short nameid, uint16 group, int class_, short race, int rate) { uint8 i; - if (nameid && !group && !itemdb_exists(nameid)) { + struct s_item_group_db *group_ = NULL; + if (nameid && !itemdb_exists(nameid)) { ShowWarning("pc_bonus_item_drop: Invalid item id %hu\n",nameid); return; } + if (!group || (group_ = itemdb_group_exists(group)) == NULL) { + ShowWarning("pc_bonus_item_drop: Invalid Item Group %hu\n",group); + return; + } + //Apply config rate adjustment settings. if (rate >= 0) { //Absolute drop. if (battle_config.item_rate_adddrop != 100) @@ -3382,8 +3388,7 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val) break; case SP_ADD_ITEMGROUP_HEAL_RATE: { - struct s_item_group_db *group = (struct s_item_group_db *) idb_get(itemdb_get_groupdb(), type2); - if (!group) { + if (!type2 || !itemdb_group_exists(type)) { ShowError("pc_bonus2: SP_ADD_ITEMGROUP_HEAL_RATE Invalid item group with id %d\n", type2); break; } @@ -6624,7 +6629,7 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) sd->status.skill_point--; if( !skill_get_inf(skill_id) ) 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 >= battle_config.taekwon_ranker_min_lv && pc_famerank(sd->status.char_id, MAPID_TAEKWON) ) + else if( sd->status.skill_point == 0 && pc_is_taekwon_ranker(sd) ) pc_calc_skilltree(sd); // Required to grant all TK Ranker skills. else pc_check_skilltree(sd, skill_id); // Check if a new skill can Lvlup @@ -6866,11 +6871,10 @@ int pc_resetskill(struct map_session_data* sd, int flag) return 0; if( !(flag&2) ) { //Remove stuff lost when resetting skills. - /** * It has been confirmed on official servers that when you reset skills with a ranked Taekwon your skills are not reset (because you have all of them anyway) **/ - if( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= battle_config.taekwon_ranker_min_lv && pc_famerank(sd->status.char_id, MAPID_TAEKWON) ) + if( pc_is_taekwon_ranker(sd) ) return 0; if( pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd) ) @@ -11012,8 +11016,8 @@ short pc_get_itemgroup_bonus(struct map_session_data* sd, unsigned short nameid) return bonus; for (i = 0; i < sd->itemgrouphealrate_count; i++) { uint16 group_id = sd->itemgrouphealrate[i]->group_id, j; - struct s_item_group_db *group = (struct s_item_group_db *) idb_get(itemdb_get_groupdb(), group_id); - if (!group) + struct s_item_group_db *group = NULL; + if (!group_id || !(group = itemdb_group_exists(group_id))) continue; for (j = 0; j < group->random[0].data_qty; j++) { diff --git a/src/map/pc.h b/src/map/pc.h index bc70287a27..144e28c62e 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -1107,6 +1107,8 @@ short pc_get_itemgroup_bonus(struct map_session_data* sd, unsigned short nameid) short pc_get_itemgroup_bonus_group(struct map_session_data* sd, uint16 group_id); bool pc_is_same_equip_index(enum equip_index eqi, int *equip_index, int8 index); +/// Check if player is Taekwon Ranker and the level is >= 90 (battle_config.taekwon_ranker_min_lv) +#define pc_is_taekwon_ranker(sd) (((sd)->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && (sd)->status.base_level >= battle_config.taekwon_ranker_min_lv && pc_famerank((sd)->status.char_id,MAPID_TAEKWON)) #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) int pc_level_penalty_mod(struct map_session_data *sd, int mob_level, uint32 mob_class, int type); diff --git a/src/map/skill.c b/src/map/skill.c index bda7e70b5e..97449d2f55 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -13917,7 +13917,7 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i status_change_end(&sd->bl, SC_COMBO, INVALID_TIMER); return false; } - if(sc->data[SC_COMBO]->val1 != skill_id && !( sd && sd->status.base_level >= battle_config.taekwon_ranker_min_lv && pc_famerank(sd->status.char_id, MAPID_TAEKWON) )) { //Cancel combo wait. + if(sc->data[SC_COMBO]->val1 != skill_id && !pc_is_taekwon_ranker(sd)) { //Cancel combo wait. unit_cancel_combo(&sd->bl); return false; } diff --git a/src/map/status.c b/src/map/status.c index fa01cb7ad2..9336f6a0e6 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -2609,7 +2609,7 @@ static int status_get_hpbonus(struct block_list *bl, enum e_status_bonus type) { bonus -= 100; //Default hprate is 100, so it should be add 0% //+200% for top ranking Taekwons over level 90. - if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= battle_config.taekwon_ranker_min_lv && pc_famerank(sd->status.char_id,MAPID_TAEKWON)) + if (pc_is_taekwon_ranker(sd)) bonus += 200; } @@ -2720,7 +2720,7 @@ static int status_get_spbonus(struct block_list *bl, enum e_status_bonus type) { bonus += 2 * i; //+200% for top ranking Taekwons over level 90. - if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= battle_config.taekwon_ranker_min_lv && pc_famerank(sd->status.char_id, MAPID_TAEKWON)) + if (pc_is_taekwon_ranker(sd)) bonus += 200; } @@ -3050,13 +3050,12 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) // We've got combos to process and check if( sd->combos.count ) { - DBMap *combo_db = itemdb_get_combodb(); for (i = 0; i < sd->combos.count; i++) { uint8 j = 0; bool no_run = false; - struct item_combo *combo = (struct item_combo *)idb_get(combo_db,sd->combos.id[i]); + struct item_combo *combo = NULL; - if (!sd->combos.bonus[i]) + if (!sd->combos.bonus[i] || !(combo = itemdb_combo_exists(sd->combos.id[i]))) continue; // Check combo items while (j < combo->count) {