summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2016-02-22 03:10:04 +0100
committerHaru <haru@dotalux.com>2016-02-24 21:02:17 +0100
commit23f1ef310719081c79aebf3f8921240773f5a507 (patch)
tree1b873269dba4d5b9f88b6db3f215c2d245a6b90b
parentc1ab5a9db773d399c86eb59a3dded649387480c0 (diff)
downloadhercules-23f1ef310719081c79aebf3f8921240773f5a507.tar.gz
hercules-23f1ef310719081c79aebf3f8921240773f5a507.tar.bz2
hercules-23f1ef310719081c79aebf3f8921240773f5a507.tar.xz
hercules-23f1ef310719081c79aebf3f8921240773f5a507.zip
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 <haru@dotalux.com>
-rw-r--r--src/map/clif.c20
-rw-r--r--src/map/skill.c35
-rw-r--r--src/map/skill.h5
3 files changed, 38 insertions, 22 deletions
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);