From 23f1ef310719081c79aebf3f8921240773f5a507 Mon Sep 17 00:00:00 2001 From: Haru Date: Mon, 22 Feb 2016 03:10:04 +0100 Subject: Edited skill->changematerial() and skill->elementalanalysis() to use the new struct itemlist - The skill-side code no longer depends on the client packet data layout. - Some data validation has been added. Signed-off-by: Haru --- src/map/clif.c | 20 ++++++++++++++------ src/map/skill.c | 35 +++++++++++++++++++++-------------- src/map/skill.h | 5 +++-- 3 files changed, 38 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/map/clif.c b/src/map/clif.c index 9e0977cc4..9dc42bb07 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -16441,7 +16441,8 @@ void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd) int n = ((int)RFIFOW(fd,2) - 12) / 4; int type = RFIFOL(fd,4); int flag = RFIFOL(fd,8); // Button clicked: 0 = Cancel, 1 = OK - unsigned short *item_list = NULL; + struct itemlist item_list = { 0 }; + int i; if( sd->state.trading || sd->npc_shopid ) return; @@ -16459,18 +16460,25 @@ void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd) return; // Prevent hacking. } - item_list = aMalloc(sizeof *item_list * 2 * n); - memcpy(item_list, RFIFOP(fd,12), sizeof *item_list * 2 * n); + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, n, 1); + for (i = 0; i < n; i++) { + struct itemlist_entry entry = { 0 }; + entry.id = (int)RFIFOW(fd, 12 + 4 * i) - 2; // Inventory index + entry.amount = RFIFOW(fd, 12 + 4 * i + 2); + VECTOR_PUSH(item_list, entry); + } + switch( type ) { case 0: // Change Material - skill->changematerial(sd,n,item_list); + skill->changematerial(sd, &item_list); break; case 1: // Level 1: Pure to Rough case 2: // Level 2: Rough to Pure - skill->elementalanalysis(sd,n,type,item_list); + skill->elementalanalysis(sd, type, &item_list); break; } - aFree(item_list); + VECTOR_CLEAR(item_list); clif_menuskill_clear(sd); return; diff --git a/src/map/skill.c b/src/map/skill.c index a13e3a071..68cb3ff0e 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -17879,27 +17879,31 @@ int skill_select_menu(struct map_session_data *sd,uint16 skill_id) { sc_start4(&sd->bl,&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill->get_time(SC_AUTOSHADOWSPELL,aslvl)); return 0; } -int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, unsigned short* item_list) { + +int skill_elementalanalysis(struct map_session_data *sd, uint16 skill_lv, const struct itemlist *item_list) +{ int i; nullpo_ret(sd); nullpo_ret(item_list); - if( n <= 0 ) + if (VECTOR_LENGTH(*item_list) <= 0) return 1; - for (i = 0; i < n; i++) { - int nameid, add_amount, del_amount, idx, product; + for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { struct item tmp_item; - - idx = item_list[i*2+0]-2; - del_amount = item_list[i*2+1]; + const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); + int nameid, add_amount, product; + int del_amount = entry->amount; + int idx = entry->id; if( skill_lv == 2 ) del_amount -= (del_amount % 10); add_amount = (skill_lv == 1) ? del_amount * (5 + rnd()%5) : del_amount / 10 ; - if( (nameid = sd->status.inventory[idx].nameid) <= 0 || del_amount > sd->status.inventory[idx].amount ) { + if (idx < 0 || idx >= MAX_INVENTORY + || (nameid = sd->status.inventory[idx].nameid) <= 0 + || del_amount < 0 || del_amount > sd->status.inventory[idx].amount) { clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); return 1; } @@ -17949,7 +17953,8 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, return 0; } -int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list) { +int skill_changematerial(struct map_session_data *sd, const struct itemlist *item_list) +{ int i, j, k, c, p = 0, nameid, amount; nullpo_ret(sd); @@ -17964,11 +17969,13 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite // Verification of overlap between the objects required and the list submitted. for( j = 0; j < MAX_PRODUCE_RESOURCE; j++ ) { if( skill->dbs->produce_db[i].mat_id[j] > 0 ) { - for( k = 0; k < n; k++ ) { - int idx = item_list[k*2+0]-2; + for (k = 0; k < VECTOR_LENGTH(*item_list); k++) { + const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, k); + int idx = entry->id; + Assert_ret(idx >= 0 && idx < MAX_INVENTORY); + amount = entry->amount; nameid = sd->status.inventory[idx].nameid; - amount = item_list[k*2+1]; - if( nameid > 0 && sd->status.inventory[idx].identify == 0 ){ + if (nameid > 0 && sd->status.inventory[idx].identify == 0) { clif->msgtable_skill(sd, GN_CHANGEMATERIAL, MSG_SKILL_ITEM_NEED_IDENTIFY); return 0; } @@ -17981,7 +17988,7 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite break; // No more items required } p++; - } while(n == j && c == n); + } while (c == j && VECTOR_LENGTH(*item_list) == c); p--; if ( p > 0 ) { skill->produce_mix(sd,GN_CHANGEMATERIAL,skill->dbs->produce_db[i].nameid,0,0,0,p); diff --git a/src/map/skill.h b/src/map/skill.h index 96bef090a..fb2acfb62 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -32,6 +32,7 @@ **/ struct Damage; struct homun_data; +struct itemlist; // map/itemdb.h struct map_session_data; struct mercenary_data; struct unit_data; @@ -2060,8 +2061,8 @@ struct skill_interface { int (*magicdecoy) (struct map_session_data *sd, int nameid); int (*poisoningweapon) ( struct map_session_data *sd, int nameid); int (*select_menu) (struct map_session_data *sd,uint16 skill_id); - int (*elementalanalysis) (struct map_session_data *sd, int n, uint16 skill_lv, unsigned short *item_list); - int (*changematerial) (struct map_session_data *sd, int n, unsigned short *item_list); + int (*elementalanalysis) (struct map_session_data *sd, uint16 skill_lv, const struct itemlist *item_list); + int (*changematerial) (struct map_session_data *sd, const struct itemlist *item_list); int (*get_elemental_type) (uint16 skill_id, uint16 skill_lv); void (*cooldown_save) (struct map_session_data * sd); int (*get_new_group_id) (void); -- cgit v1.2.3-60-g2f50