From 5d58c4554f4264a1ba546a31439216c90da527b0 Mon Sep 17 00:00:00 2001 From: skotlex Date: Thu, 1 Feb 2007 22:23:14 +0000 Subject: - Cleaned up the npcshop(add/del) item script commands, fixed a possible dangling pointer crash caused by their improper use of realloc. They no longer automatically attach the script to the shop, and they will return true/false based on whether the shop was found or not. - Added script command npcshopattach to enable attaching/detaching your script from any npc shop. - Updated doc/script_commands.txt with entries for npcshopitem, npcshopadditem, npcshopdelitem and npcshopattach git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@9769 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/script.c | 155 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 95 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/map/script.c b/src/map/script.c index 2182e5c74..b2dfda578 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -3772,6 +3772,7 @@ int buildin_callshop(struct script_state *st); // [Skotlex] int buildin_npcshopitem(struct script_state *st); // [Lance] int buildin_npcshopadditem(struct script_state *st); int buildin_npcshopdelitem(struct script_state *st); +int buildin_npcshopattach(struct script_state *st); int buildin_equip(struct script_state *st); int buildin_autoequip(struct script_state *st); int buildin_setbattleflag(struct script_state *st); @@ -4109,6 +4110,7 @@ struct script_function buildin_func[] = { {buildin_npcshopitem,"npcshopitem","sii*"}, // [Lance] {buildin_npcshopadditem,"npcshopadditem","sii*"}, {buildin_npcshopdelitem,"npcshopdelitem","si*"}, + {buildin_npcshopattach,"npcshopattach","s?"}, {buildin_equip,"equip","i"}, {buildin_autoequip,"autoequip","ii"}, {buildin_setbattleflag,"setbattleflag","ss"}, @@ -11891,32 +11893,33 @@ int buildin_npcshopitem(struct script_state *st) char* npcname = conv_str(st, & (st->stack->stack_data[st->start + 2])); nd = npc_name2id(npcname); - if(nd && nd->bl.subtype==SHOP){ - amount = ((st->end-2)/2)+1; - // st->end - 2 = nameid + value # ... / 2 = number of items ... + 1 to end it - nd = (struct npc_data *)aRealloc(nd,sizeof(struct npc_data) + - sizeof(nd->u.shop_item[0]) * amount); + if(!nd || nd->bl.subtype!=SHOP) + { //Not found. + push_val(st->stack,C_INT,0); + return 0; + } - // Reset sell list. - memset(nd->u.shop_item, 0, sizeof(nd->u.shop_item[0]) * amount); + // st->end - 2 = nameid + value # ... / 2 = number of items ... + 1 to end it + amount = ((st->end-2)/2)+1; - n = 0; + //Reinsert as realloc could change the pointer address. + map_deliddb(&nd->bl); + nd = (struct npc_data *)aRealloc(nd,sizeof(struct npc_data) + + sizeof(nd->u.shop_item[0]) * amount); + map_addiddb(&nd->bl); - while (st->end > st->start + i) { - nd->u.shop_item[n].nameid = conv_num(st, & (st->stack->stack_data[st->start+i])); - i++; - nd->u.shop_item[n].value = conv_num(st, & (st->stack->stack_data[st->start+i])); - i++; - n++; - } + // Reset sell list. + memset(nd->u.shop_item, 0, sizeof(nd->u.shop_item[0]) * amount); - map_addiddb(&nd->bl); + n = 0; - nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); - } else { - ShowError("buildin_npcshopitem: shop not found.\n"); + while (st->end > st->start + i) { + nd->u.shop_item[n].nameid = conv_num(st, & (st->stack->stack_data[st->start+i])); + i++; + nd->u.shop_item[n].value = conv_num(st, & (st->stack->stack_data[st->start+i])); + i++; + n++; } - return 0; } @@ -11929,32 +11932,35 @@ int buildin_npcshopadditem(struct script_state *st) { char* npcname = conv_str(st, & (st->stack->stack_data[st->start+2])); nd = npc_name2id(npcname); - if (nd && nd->bl.subtype==SHOP){ - amount = ((st->end-2)/2)+1; - while (nd->u.shop_item[n].nameid && n < MAX_SHOPITEM) - n++; - - nd = (struct npc_data *)aRealloc(nd,sizeof(struct npc_data) + - sizeof(nd->u.shop_item[0]) * (amount+n)); + if (!nd || nd->bl.subtype!=SHOP) + { //Not found. + push_val(st->stack,C_INT,0); + return 0; + } + amount = ((st->end-2)/2)+1; + while (nd->u.shop_item[n].nameid && n < MAX_SHOPITEM) + n++; - while(st->end > st->start + i){ - nd->u.shop_item[n].nameid = conv_num(st, & (st->stack->stack_data[st->start+i])); - i++; - nd->u.shop_item[n].value = conv_num(st, & (st->stack->stack_data[st->start+i])); - i++; - n++; - } - // Marks the last of our stuff.. - nd->u.shop_item[n].value = 0; - nd->u.shop_item[n].nameid = 0; + //Reinsert as realloc could change the pointer address. + map_deliddb(&nd->bl); + nd = (struct npc_data *)aRealloc(nd,sizeof(struct npc_data) + + sizeof(nd->u.shop_item[0]) * (amount+n)); + map_addiddb(&nd->bl); - map_addiddb(&nd->bl); - nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); - } else { - ShowError("buildin_npcshopadditem: shop not found.\n"); + while(st->end > st->start + i){ + nd->u.shop_item[n].nameid = conv_num(st, & (st->stack->stack_data[st->start+i])); + i++; + nd->u.shop_item[n].value = conv_num(st, & (st->stack->stack_data[st->start+i])); + i++; + n++; } + // Marks the last of our stuff.. + nd->u.shop_item[n].value = 0; + nd->u.shop_item[n].nameid = 0; + + push_val(st->stack,C_INT,1); return 0; } @@ -11968,34 +11974,63 @@ int buildin_npcshopdelitem(struct script_state *st) char* npcname = conv_str(st, & (st->stack->stack_data[st->start+2])); nd = npc_name2id(npcname); - if (nd && nd->bl.subtype==SHOP) { - while (nd->u.shop_item[size].nameid) - size++; + if (!nd || nd->bl.subtype!=SHOP) + { //Not found. + push_val(st->stack,C_INT,0); + return 0; + } + + while (nd->u.shop_item[size].nameid) + size++; - while (st->end > st->start+i) { - for(n=0;nd->u.shop_item[n].nameid && n < MAX_SHOPITEM;n++) { - if (nd->u.shop_item[n].nameid == conv_num(st, & (st->stack->stack_data[st->start+i]))) { - // We're moving 1 extra empty block. Junk data is eliminated later. - memmove(&nd->u.shop_item[n], &nd->u.shop_item[n+1], sizeof(nd->u.shop_item[0])*(size-n)); - } + while (st->end > st->start+i) { + for(n=0;nd->u.shop_item[n].nameid && n < MAX_SHOPITEM;n++) { + if (nd->u.shop_item[n].nameid == conv_num(st, & (st->stack->stack_data[st->start+i]))) { + // We're moving 1 extra empty block. Junk data is eliminated later. + memmove(&nd->u.shop_item[n], &nd->u.shop_item[n+1], sizeof(nd->u.shop_item[0])*(size-n)); } - i++; } + i++; + } - size = 0; + size = 0; - while (nd->u.shop_item[size].nameid) - size++; + while (nd->u.shop_item[size].nameid) + size++; - nd = (struct npc_data *)aRealloc(nd,sizeof(struct npc_data) + - sizeof(nd->u.shop_item[0]) * (size+1)); + //Reinsert as realloc could change the pointer address. + map_deliddb(&nd->bl); + nd = (struct npc_data *)aRealloc(nd,sizeof(struct npc_data) + + sizeof(nd->u.shop_item[0]) * (size+1)); + map_addiddb(&nd->bl); - map_addiddb(&nd->bl); - nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); - } else { - ShowError("buildin_npcshopdelitem: shop not found.\n"); + push_val(st->stack,C_INT,1); + return 0; +} + +//Sets a script to attach to an npc. +int buildin_npcshopattach(struct script_state *st) +{ + struct npc_data *nd=NULL; + char* npcname = conv_str(st, & (st->stack->stack_data[st->start+2])); + int flag = 1; + + if( script_hasdata(st,2) ) + flag = conv_num(st, script_getdata(st,2)); + + nd = npc_name2id(npcname); + + if (!nd || nd->bl.subtype!=SHOP) + { //Not found. + push_val(st->stack,C_INT,0); + return 0; } + if (flag) + nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); + else + nd->master_nd = NULL; + push_val(st->stack,C_INT,1); return 0; } -- cgit v1.2.3-60-g2f50