Upon converting some of my scripts I noticed Herc didn't have a few scriptcommands that rA had. No big deal since we got plugins here!
Anyhow, that's what I thought until I bumped into getting stuck with the follow plugin that I'm attempting to create:
#include <stdio.h>#include <string.h>#include <stdlib.h>#include "common/HPMi.h"#include "map/pc.h"#include "common/HPMDataCheck.h" // should always be the last file included! (if you don't make it last, it'll intentionally break compile time)HPExport struct hplugin_info pinfo = { "storagecountitem", // Plugin name SERVER_TYPE_MAP,// Which server types this plugin works with? "0.1", // Plugin version HPM_VERSION, // HPM Version (don't change, macro is automatically updated)};/*========================================== * storagecountitem(nameID,{accountID}) * returns number of items that meet the conditions *==========================================*/BUILDIN(storagecountitem) { int nameid, i; int count = 0; struct item_data* id = NULL; TBL_PC* sd = script->rid2sd(st); if( !sd ) return true; if( script_isstringtype(st, 2) ) { // item name id = itemdb->search_name(script_getstr(st, 2)); } else { // item id id = itemdb->exists(script_getnum(st, 2)); } if( id == NULL ) { ShowError("buildin_storagecountitem: Invalid item '%s'.n", script_getstr(st,2)); // returns string, regardless of what it was script_pushint(st,0); return false; } nameid = id->nameid; for(i = 0; i < MAX_STORAGE; i++) if(sd->status.storage.items[i].nameid == nameid) count += sd->status.storage.items[i].amount; script_pushint(st,count); return true;}/*========================================== * storagecountitem2(nameID,Identified,Refine,Attribute,Card0,Card1,Card2,Card3) * returns number of items that meet the conditions *==========================================*/BUILDIN(storagecountitem2) { int nameid, iden, ref, attr, c0, c1, c2, c3; int count = 0; int i; struct item_data* id = NULL; TBL_PC* sd = script->rid2sd(st); if (!sd) { return true; } if( script_isstringtype(st, 2) ) { //item name id = itemdb->search_name(script_getstr(st, 2)); } else { //item id id = itemdb->exists(script_getnum(st, 2)); } if( id == NULL ) { ShowError("buildin_storagecountitem2: Invalid item '%s'.n", script_getstr(st,2)); // returns string, regardless of what it was script_pushint(st,0); return false; } nameid = id->nameid; iden = script_getnum(st,3); ref = script_getnum(st,4); attr = script_getnum(st,5); c0 = (short)script_getnum(st,6); c1 = (short)script_getnum(st,7); c2 = (short)script_getnum(st,8); c3 = (short)script_getnum(st,9); for(i = 0; i < MAX_STORAGE; i++) { if(sd->status.storage.items[i].nameid > 0 && sd->status.storage.items[i].amount > 0 && sd->status.storage.items[i].nameid == nameid && sd->status.storage.items[i].identify == iden && sd->status.storage.items[i].refine == ref && sd->status.storage.items[i].attribute == attr && sd->status.storage.items[i].card[0] == c0 && sd->status.storage.items[i].card[1] == c1 && sd->status.storage.items[i].card[2] == c2 && sd->status.storage.items[i].card[3] == c3 ) count += sd->status.storage.items[i].amount; } script_pushint(st,count); return true;}/* Server Startup */HPExport void plugin_init (void) { addScriptCommand( "storagecountitem", "v", storagecountitem); addScriptCommand( "storagecountitem2", "viiiiiii", storagecountitem2);}
Fixed the above script, added it incase people are interested. Will 'officially' release it in the plugin release when the below script is finished/working as well.
The next script that had to be made was the deletion of items in the storage. Thus storagedelitem came here to ruin my night, the follow is what I got, but doesn't work for one milimeter:
#include <stdio.h>#include <string.h>#include <stdlib.h>#include "common/HPMi.h"#include "common/utils.c"#include "map/intif.h"#include "map/pc.h"#include "map/storage.c"#include "common/HPMDataCheck.h" // should always be the last file included! (if you don't make it last, it'll intentionally break compile time)HPExport struct hplugin_info pinfo = { "storagedelitem", // Plugin name SERVER_TYPE_MAP,// Which server types this plugin works with? "0.1", // Plugin version HPM_VERSION, // HPM Version (don't change, macro is automatically updated)};/// Counts / deletes the current item given by idx./// Used by buildin_delitem_search/// Relies on all input data being already fully valid.void buildin_storage_delitem_delete(struct map_session_data* sd, int idx, int* amount, bool delete_items){ int delamount; struct item* inv = &sd->status.storage.items[idx]; delamount = ( amount[0] < inv->amount ) ? amount[0] : inv->amount; if( delete_items ) { if( itemdb_type(inv->nameid) == IT_PETEGG && inv->card[0] == CARD0_PET ) {// delete associated pet intif->delete_petdata(MakeDWord(inv->card[1], inv->card[2])); } storage_delitem(sd, idx, delamount); } amount[0]-= delamount;}/// Searches for item(s) and checks, if there is enough of them./// Used by delitem and delitem2/// Relies on all input data being already fully valid./// @param exact_match will also match item attributes and cards, not just name id/// @return true when all items could be deleted, false when there were not enough items to deletebool buildin_storage_delitem_search(struct map_session_data* sd, struct item* it, bool exact_match){ bool delete_items = false; int i, amount, size; struct item* inv; // prefer always non-equipped items it->equip = 0; // when searching for nameid only, prefer additionally if (!exact_match) { // non-refined items it->refine = 0; // card-less items memset(it->card, 0, sizeof(it->card)); } size = MAX_STORAGE; for (; { int important = 0; amount = it->amount; // 1st pass -- less important items / exact match for (i = 0; amount && i < size; i++) { inv = &sd->status.storage.items[i]; if (!inv->nameid || !&inv || inv->nameid != it->nameid) { // wrong/invalid item continue; } if (inv->equip != it->equip || inv->refine != it->refine) { // not matching attributes important++; continue; } if (exact_match) { if (inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card))) { // not matching exact attributes continue; } } else { if (itemdb_type(inv->nameid) == IT_PETEGG) { if (inv->card[0] == CARD0_PET && intif->CheckForCharServer()) { // pet which cannot be deleted continue; } } else if (memcmp(inv->card, it->card, sizeof(inv->card))) { // named/carded item important++; continue; } } // count / delete item buildin_storage_delitem_delete(sd, i, &amount, delete_items); } // 2nd pass -- any matching item if (amount == 0 || important == 0) { // either everything was already consumed or no items were skipped ; } else { for (i = 0; amount && i < size; i++) { inv = &sd->status.storage.items[i]; if (!inv->nameid || !&inv || inv->nameid != it->nameid) { // wrong/invalid item continue; } if (itemdb_type(inv->nameid) == IT_PETEGG && inv->card[0] == CARD0_PET && intif->CheckForCharServer()) { // pet which cannot be deleted continue; } if (exact_match) { if (inv->refine != it->refine || inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card))) { // not matching attributes continue; } } // count / delete item buildin_storage_delitem_delete(sd, i, &amount, delete_items); } } if (amount) { // not enough items return false; } else if(delete_items) { // we are done with the work return true; } else { // get rid of the items now delete_items = true; } }}/*========================================== * delitem <item id>,<amount>{,<account id>} * delitem "<item name>",<amount>{,<account id>} * Deletes items from the target/attached player. *==========================================*/BUILDIN(storagedelitem) { TBL_PC *sd; struct item it; if (script_hasdata(st,4)) { int account_id = script_getnum(st,4); sd = map->id2sd(account_id); // <account id> if (sd == NULL) { ShowError("script:storagedelitem: player not found (AID=%d).n", account_id); st->state = END; return false; } } else { sd = script->rid2sd(st);// attached player if (sd == NULL) return true; } memset(&it, 0, sizeof(it)); if (script_isstringtype(st, 2)) { const char* item_name = script_getstr(st, 2); struct item_data* id = itemdb->search_name(item_name); if (id == NULL) { ShowError("script:storagedelitem: unknown item "%s".n", item_name); st->state = END; return false; } it.nameid = id->nameid;// "<item name>" } else { it.nameid = script_getnum(st, 2);// <item id> if (!itemdb->exists(it.nameid)) { ShowError("script:storagedelitem: unknown item "%d".n", it.nameid); st->state = END; return false; } } it.amount=script_getnum(st,3); if( it.amount <= 0 ) return true;// nothing to do if( buildin_storage_delitem_search(sd, &it, false) ) {// success return true; } ShowError("script:storagedelitem: failed to delete %d items (AID=%d item_id=%d).n", it.amount, sd->status.account_id, it.nameid); st->state = END; clif->scriptclose(sd, st->oid); return false;}/* Server Startup */HPExport void plugin_init (void) { addScriptCommand( "storagedelitem", "vi?", storagedelitem);}
The original delitem script is used as reference and is as following:
/// Counts / deletes the current item given by idx./// Used by buildin_delitem_search/// Relies on all input data being already fully valid.void buildin_delitem_delete(struct map_session_data* sd, int idx, int* amount, bool delete_items){ int delamount; struct item* inv = &sd->status.inventory[idx]; delamount = ( amount[0] < inv->amount ) ? amount[0] : inv->amount; if( delete_items ) { if( sd->inventory_data[idx]->type == IT_PETEGG && inv->card[0] == CARD0_PET ) {// delete associated pet intif->delete_petdata(MakeDWord(inv->card[1], inv->card[2])); } pc->delitem(sd, idx, delamount, 0, DELITEM_NORMAL, LOG_TYPE_SCRIPT); } amount[0]-= delamount;}/// Searches for item(s) and checks, if there is enough of them./// Used by delitem and delitem2/// Relies on all input data being already fully valid./// @param exact_match will also match item attributes and cards, not just name id/// @return true when all items could be deleted, false when there were not enough items to deletebool buildin_delitem_search(struct map_session_data* sd, struct item* it, bool exact_match){ bool delete_items = false; int i, amount; struct item* inv; // prefer always non-equipped items it->equip = 0; // when searching for nameid only, prefer additionally if (!exact_match) { // non-refined items it->refine = 0; // card-less items memset(it->card, 0, sizeof(it->card)); } for (; { int important = 0; amount = it->amount; // 1st pass -- less important items / exact match for (i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++) { inv = &sd->status.inventory[i]; if (!inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid) { // wrong/invalid item continue; } if (inv->equip != it->equip || inv->refine != it->refine) { // not matching attributes important++; continue; } if (exact_match) { if (inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card))) { // not matching exact attributes continue; } } else { if (sd->inventory_data[i]->type == IT_PETEGG) { if (inv->card[0] == CARD0_PET && intif->CheckForCharServer()) { // pet which cannot be deleted continue; } } else if (memcmp(inv->card, it->card, sizeof(inv->card))) { // named/carded item important++; continue; } } // count / delete item script->buildin_delitem_delete(sd, i, &amount, delete_items); } // 2nd pass -- any matching item if (amount == 0 || important == 0) { // either everything was already consumed or no items were skipped ; } else { for (i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++) { inv = &sd->status.inventory[i]; if (!inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid) { // wrong/invalid item continue; } if (sd->inventory_data[i]->type == IT_PETEGG && inv->card[0] == CARD0_PET && intif->CheckForCharServer()) { // pet which cannot be deleted continue; } if (exact_match) { if (inv->refine != it->refine || inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card))) { // not matching attributes continue; } } // count / delete item script->buildin_delitem_delete(sd, i, &amount, delete_items); } } if (amount) { // not enough items return false; } else if(delete_items) { // we are done with the work return true; } else { // get rid of the items now delete_items = true; } }}/// Deletes items from the target/attached player./// Prioritizes ordinary items.////// delitem <item id>,<amount>{,<account id>}/// delitem "<item name>",<amount>{,<account id>}BUILDIN(delitem) { TBL_PC *sd; struct item it; if (script_hasdata(st,4)) { int account_id = script_getnum(st,4); sd = map->id2sd(account_id); // <account id> if (sd == NULL) { ShowError("script:delitem: player not found (AID=%d).n", account_id); st->state = END; return false; } } else { sd = script->rid2sd(st);// attached player if (sd == NULL) return true; } memset(&it, 0, sizeof(it)); if (script_isstringtype(st, 2)) { const char* item_name = script_getstr(st, 2); struct item_data* id = itemdb->search_name(item_name); if (id == NULL) { ShowError("script:delitem: unknown item "%s".n", item_name); st->state = END; return false; } it.nameid = id->nameid;// "<item name>" } else { it.nameid = script_getnum(st, 2);// <item id> if (!itemdb->exists(it.nameid)) { ShowError("script:delitem: unknown item "%d".n", it.nameid); st->state = END; return false; } } it.amount=script_getnum(st,3); if( it.amount <= 0 ) return true;// nothing to do if( script->buildin_delitem_search(sd, &it, false) ) {// success return true; } ShowError("script:delitem: failed to delete %d items (AID=%d item_id=%d).n", it.amount, sd->status.account_id, it.nameid); st->state = END; clif->scriptclose(sd, st->oid); return false;}
And what I think is needed is the following part from storage.c:
Greetings,
Upon converting some of my scripts I noticed Herc didn't have a few scriptcommands that rA had. No big deal since we got plugins here!
Anyhow, that's what I thought until I bumped into getting stuck with the follow plugin that I'm attempting to create:
Fixed the above script, added it incase people are interested. Will 'officially' release it in the plugin release when the below script is finished/working as well.
The next script that had to be made was the deletion of items in the storage. Thus storagedelitem came here to ruin my night, the follow is what I got, but doesn't work for one milimeter:
The original delitem script is used as reference and is as following:
And what I think is needed is the following part from storage.c:
Where did I mess up this time? Where didn't I mess up you're probably thinking by now..
Edited by TranquilityShare this post
Link to post
Share on other sites