diff options
Diffstat (limited to 'src/map/npc.c')
-rw-r--r-- | src/map/npc.c | 298 |
1 files changed, 212 insertions, 86 deletions
diff --git a/src/map/npc.c b/src/map/npc.c index 2b1a541d8..6b55bf5ae 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -47,6 +47,7 @@ #include "common/nullpo.h" #include "common/showmsg.h" #include "common/socket.h" +#include "common/sql.h" #include "common/strlib.h" #include "common/timer.h" #include "common/utils.h" @@ -61,17 +62,6 @@ struct npc_interface npc_s; struct npc_interface *npc; -static int npc_id=START_NPC_NUM; -static int npc_warp=0; -static int npc_shop=0; -static int npc_script=0; -static int npc_mob=0; -static int npc_delay_mob=0; -static int npc_cache_mob=0; - -static const char *npc_last_path; -static const char *npc_last_ref; -struct npc_path_data *npc_last_npd; //For holding the view data of npc classes. [Skotlex] static struct view_data npc_viewdb[MAX_NPC_CLASS]; @@ -131,15 +121,15 @@ bool npc_db_checkid(int id) /// Returns a new npc id that isn't being used in id_db. /// Fatal error if nothing is available. int npc_get_new_npc_id(void) { - if( npc_id >= START_NPC_NUM && !map->blid_exists(npc_id) ) - return npc_id++;// available + if (npc->npc_id >= START_NPC_NUM && !map->blid_exists(npc->npc_id)) + return npc->npc_id++;// available else {// find next id - int base_id = npc_id; - while( base_id != ++npc_id ) { - if( npc_id < START_NPC_NUM ) - npc_id = START_NPC_NUM; - if( !map->blid_exists(npc_id) ) - return npc_id++;// available + int base_id = npc->npc_id; + while (base_id != ++npc->npc_id) { + if (npc->npc_id < START_NPC_NUM) + npc->npc_id = START_NPC_NUM; + if (!map->blid_exists(npc->npc_id)) + return npc->npc_id++;// available } // full loop, nothing available ShowFatalError("npc_get_new_npc_id: All ids are taken. Exiting..."); @@ -176,6 +166,7 @@ int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd) { char name[EVENT_NAME_LENGTH]; + nullpo_retr(1, nd); if( nd->touching_id ) return 0; // Attached a player already. Can't trigger on anyone else. @@ -190,6 +181,8 @@ int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd) { char name[EVENT_NAME_LENGTH]; + nullpo_retr(1, sd); + nullpo_retr(1, nd); if (sd->areanpc_id == nd->bl.id) return 0; @@ -201,6 +194,8 @@ int npc_onuntouch_event(struct map_session_data *sd, struct npc_data *nd) { char name[EVENT_NAME_LENGTH]; + nullpo_ret(sd); + nullpo_ret(nd); if (sd->areanpc_id != nd->bl.id) return 0; @@ -366,7 +361,7 @@ int npc_event_dequeue(struct map_session_data* sd) /** * @see DBCreateData */ -DBData npc_event_export_create(DBKey key, va_list args) +struct DBData npc_event_export_create(union DBKey key, va_list args) { struct linkdb_node** head_ptr; CREATE(head_ptr, struct linkdb_node*, 1); @@ -380,8 +375,12 @@ DBData npc_event_export_create(DBKey key, va_list args) *------------------------------------------*/ int npc_event_export(struct npc_data *nd, int i) { - char* lname = nd->u.scr.label_list[i].name; - int pos = nd->u.scr.label_list[i].pos; + char* lname; + int pos; + nullpo_ret(nd); + Assert_ret(i >= 0 && i < nd->u.scr.label_list_num); + lname = nd->u.scr.label_list[i].name; + pos = nd->u.scr.label_list[i].pos; if ((lname[0] == 'O' || lname[0] == 'o') && (lname[1] == 'N' || lname[1] == 'n')) { struct event_data *ev; struct linkdb_node **label_linkdb = NULL; @@ -434,6 +433,7 @@ void npc_event_doall_sub(void *key, void *data, va_list ap) // runs the specified event (supports both single-npc and global events) int npc_event_do(const char* name) { + nullpo_ret(name); if( name[0] == ':' && name[1] == ':' ) { return npc->event_doall(name+2); // skip leading "::" } @@ -538,9 +538,12 @@ void npc_event_do_oninit( bool reload ) int npc_timerevent_export(struct npc_data *nd, int i) { int t = 0, len = 0; - char *lname = nd->u.scr.label_list[i].name; - int pos = nd->u.scr.label_list[i].pos; - if (sscanf(lname, "OnTimer%d%n", &t, &len) == 1 && lname[len] == '\0') { + char *lname; + int pos; + nullpo_ret(nd); + lname = nd->u.scr.label_list[i].name; + pos = nd->u.scr.label_list[i].pos; + if (sscanf(lname, "OnTimer%d%n", &t, &len) == 1 && len < NAME_LENGTH && lname[len] == '\0') { // Timer event struct npc_timerevent_list *te = nd->u.scr.timer_event; int j, k = nd->u.scr.timeramount; @@ -580,6 +583,8 @@ int npc_timerevent(int tid, int64 tick, int id, intptr_t data) struct timer_event_data *ted = (struct timer_event_data*)data; struct map_session_data *sd=NULL; + nullpo_ret(ted); + if( nd == NULL ) { ShowError("npc_timerevent: NPC not found??\n"); return 0; @@ -732,6 +737,7 @@ void npc_timerevent_quit(struct map_session_data* sd) struct npc_data* nd; struct timer_event_data *ted; + nullpo_retv(sd); // Check timer existence if( sd->npc_timer_id == INVALID_TIMER ) return; @@ -763,6 +769,7 @@ void npc_timerevent_quit(struct map_session_data* sd) { int old_rid,old_timer; int64 old_tick; + nullpo_retv(ted); //Set timer related info. old_rid = (nd->u.scr.rid == sd->bl.id ? 0 : nd->u.scr.rid); // Detach rid if the last attached player logged off. @@ -831,6 +838,8 @@ int npc_settimerevent_tick(struct npc_data* nd, int newtimer) int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char* eventname) { + nullpo_retr(2, sd); + nullpo_retr(2, eventname); if ( sd->npc_id != 0 ) { //Enqueue the event trigger. @@ -915,9 +924,11 @@ int npc_touch_areanpc_sub(struct block_list *bl, va_list ap) { * If not, it unsets it and searches for another player in range. *------------------------------------------*/ int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap) { - struct npc_data *nd = map->id2nd(sd->touching_id); + struct npc_data *nd; short xs, ys; + nullpo_retr(1, sd); + nd = map->id2nd(sd->touching_id); if( !nd || nd->touching_id != sd->bl.id ) return 1; @@ -949,7 +960,7 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) int j, found_warp = 0; nullpo_retr(1, sd); - + Assert_retr(1, m >= 0 && m < map->count); #if 0 // Why not enqueue it? [Inkfish] if(sd->npc_id) return 1; @@ -1034,6 +1045,7 @@ int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) { struct npc_data *nd = NULL; nullpo_retr(1, sd); + Assert_retr(1, m >= 0 && m < map->count); if (!sd->areanpc_id) return 0; @@ -1053,11 +1065,16 @@ int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) // Return 1 if Warped int npc_touch_areanpc2(struct mob_data *md) { - int i, m = md->bl.m, x = md->bl.x, y = md->bl.y, id; + int i, m, x, y, id; char eventname[EVENT_NAME_LENGTH]; struct event_data* ev; int xs, ys; + nullpo_ret(md); + m = md->bl.m; + x = md->bl.x; + y = md->bl.y; + for( i = 0; i < map->list[m].npc_num; i++ ) { if( map->list[m].npc[i]->option&OPTION_INVISIBLE ) continue; @@ -1116,6 +1133,8 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) { int x0,y0,x1,y1; int xs,ys; + Assert_retr(1, m >= 0 && m < map->count); + if (range < 0) return 0; x0 = max(x-range, 0); y0 = max(y-range, 0); @@ -1187,6 +1206,7 @@ struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* b if (distance > nd->area_size) distance = nd->area_size; + nullpo_retr(NULL, bl); if (bl->m != sd->bl.m || bl->x < sd->bl.x - distance || bl->x > sd->bl.x + distance || bl->y < sd->bl.y - distance || bl->y > sd->bl.y + distance) @@ -1208,6 +1228,9 @@ int npc_globalmessage(const char* name, const char* mes) if (!nd) return 0; + nullpo_ret(name); + nullpo_ret(mes); + snprintf(temp, sizeof(temp), "%s : %s", name, mes); clif->GlobalMessage(&nd->bl,temp); @@ -1219,6 +1242,7 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd) { char buffer[200]; char time[10]; + nullpo_retv(nd); strftime(time, sizeof(time), "%H:%M", localtime(&nd->u.tomb.kill_time)); // TODO: Find exact color? @@ -1393,6 +1417,8 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, struct itemlis struct npc_item_list *shop = NULL; unsigned short shop_size = 0; + nullpo_retr(ERROR_TYPE_SYSTEM, sd); + nullpo_retr(ERROR_TYPE_SYSTEM, item_list); if( sd->state.trading ) return ERROR_TYPE_EXCHANGE; @@ -1492,6 +1518,9 @@ int npc_buylist_sub(struct map_session_data *sd, struct itemlist *item_list, str int key_nameid = 0; int key_amount = 0; + nullpo_ret(item_list); + nullpo_ret(nd); + // discard old contents script->cleararray_pc(sd, "@bought_nameid", (void*)0); script->cleararray_pc(sd, "@bought_quantity", (void*)0); @@ -1514,8 +1543,9 @@ int npc_buylist_sub(struct map_session_data *sd, struct itemlist *item_list, str /** * Loads persistent NPC Market Data from SQL **/ -void npc_market_fromsql(void) { - SqlStmt* stmt = SQL->StmtMalloc(map->mysql_handle); +void npc_market_fromsql(void) +{ + struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle); char name[NAME_LENGTH+1]; int itemid; int amount; @@ -1565,6 +1595,8 @@ void npc_market_fromsql(void) { * Saves persistent NPC Market Data into SQL **/ void npc_market_tosql(struct npc_data *nd, unsigned short index) { + nullpo_retv(nd); + Assert_retv(index < nd->u.scr.shop->items); if (SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s','%d','%u')", map->npc_market_data_db, nd->exname, nd->u.scr.shop->item[index].nameid, nd->u.scr.shop->item[index].qty)) Sql_ShowDebug(map->mysql_handle); @@ -1586,12 +1618,16 @@ void npc_market_delfromsql_sub(const char *npcname, unsigned short index) { * Removes persistent NPC Market Data from SQL **/ void npc_market_delfromsql(struct npc_data *nd, unsigned short index) { + nullpo_retv(nd); + Assert_retv(index == USHRT_MAX || index < nd->u.scr.shop->items); npc->market_delfromsql_sub(nd->exname, index == USHRT_MAX ? index : nd->u.scr.shop->item[index].nameid); } /** * Judges whether to allow and spawn a trader's window. **/ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) { + nullpo_retr(false, sd); + nullpo_retr(false, nd); if( !nd->u.scr.shop || !nd->u.scr.shop->items ) return false; @@ -1630,7 +1666,7 @@ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) { * @param master id of the original npc **/ void npc_trader_update(int master) { - DBIterator* iter; + struct DBIterator *iter; struct block_list* bl; struct npc_data *master_nd = map->id2nd(master); @@ -1657,6 +1693,9 @@ void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd) { char evname[EVENT_NAME_LENGTH]; struct event_data *ev = NULL; + nullpo_retv(nd); + nullpo_retv(sd); + npc->trader_funds[0] = npc->trader_funds[1] = 0;/* clear */ switch( nd->u.scr.shop->type ) { @@ -1694,6 +1733,8 @@ bool npc_trader_pay(struct npc_data *nd, struct map_session_data *sd, int price, char evname[EVENT_NAME_LENGTH]; struct event_data *ev = NULL; + nullpo_retr(false, nd); + nullpo_retr(false, sd); npc->trader_ok = false;/* clear */ snprintf(evname, EVENT_NAME_LENGTH, "%s::OnPayFunds",nd->exname); @@ -1716,6 +1757,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po int i, price, w; unsigned short shop_size = 0; + nullpo_retr(ERROR_TYPE_SYSTEM, sd); if( amount <= 0 ) return ERROR_TYPE_ITEM_ID; @@ -2055,6 +2097,10 @@ int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, st int key_identify = 0; int key_card[MAX_SLOTS]; + nullpo_ret(sd); + nullpo_ret(item_list); + nullpo_ret(nd); + // discard old contents script->cleararray_pc(sd, "@sold_nameid", (void*)0); script->cleararray_pc(sd, "@sold_quantity", (void*)0); @@ -2222,7 +2268,7 @@ int npc_remove_map(struct npc_data* nd) { /** * @see DBApply */ -int npc_unload_ev(DBKey key, DBData *data, va_list ap) +int npc_unload_ev(union DBKey key, struct DBData *data, va_list ap) { struct event_data* ev = DB->data2ptr(data); char* npcname = va_arg(ap, char *); @@ -2237,7 +2283,7 @@ int npc_unload_ev(DBKey key, DBData *data, va_list ap) /** * @see DBApply */ -int npc_unload_ev_label(DBKey key, DBData *data, va_list ap) +int npc_unload_ev_label(union DBKey key, struct DBData *data, va_list ap) { struct linkdb_node **label_linkdb = DB->data2ptr(data); struct npc_data* nd = va_arg(ap, struct npc_data *); @@ -2253,6 +2299,7 @@ int npc_unload_dup_sub(struct npc_data* nd, va_list args) { int src_id; + nullpo_ret(nd); src_id = va_arg(args, int); if (nd->src_id == src_id) npc->unload(nd, true); @@ -2261,6 +2308,7 @@ int npc_unload_dup_sub(struct npc_data* nd, va_list args) //Removes all npcs that are duplicates of the passed one. [Skotlex] void npc_unload_duplicates(struct npc_data* nd) { + nullpo_retv(nd); map->foreachnpc(npc->unload_dup_sub,nd->bl.id); } @@ -2384,6 +2432,7 @@ void npc_addsrcfile(const char* name) struct npc_src_list* file; struct npc_src_list* file_prev = NULL; + nullpo_retv(name); if( strcmpi(name, "clear") == 0 ) { npc->clearsrcfile(); @@ -2415,6 +2464,7 @@ void npc_delsrcfile(const char* name) struct npc_src_list* file = npc->src_files; struct npc_src_list* file_prev = NULL; + nullpo_retv(name); if( strcmpi(name, "all") == 0 ) { npc->clearsrcfile(); @@ -2448,10 +2498,10 @@ const char *npc_retainpathreference(const char *filepath) struct npc_path_data * npd = NULL; nullpo_ret(filepath); - if (npc_last_path == filepath) { - if (npc_last_npd != NULL) - npc_last_npd->references++; - return npc_last_ref; + if (npc->npc_last_path == filepath) { + if (npc->npc_last_npd != NULL) + npc->npc_last_npd->references++; + return npc->npc_last_ref; } if ((npd = strdb_get(npc->path_db,filepath)) == NULL) { @@ -2466,9 +2516,9 @@ const char *npc_retainpathreference(const char *filepath) npd->references++; - npc_last_npd = npd; - npc_last_ref = npd->path; - npc_last_path = filepath; + npc->npc_last_npd = npd; + npc->npc_last_ref = npd->path; + npc->npc_last_path = filepath; return npd->path; } @@ -2484,7 +2534,7 @@ void npc_releasepathreference(const char *filepath) nullpo_retv(filepath); - if (filepath != npc_last_ref) { + if (filepath != npc->npc_last_ref) { npd = strdb_get(npc->path_db, filepath); } @@ -2502,6 +2552,8 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con struct npc_data* dnd;// duplicate npc char newname[NAME_LENGTH]; + nullpo_retv(nd); + nullpo_retv(name); // parse name p = strstr(name,"::"); if( p ) { // <Display name>::<Unique name> @@ -2557,6 +2609,7 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c int val = FAKE_NPC, i = 0; char viewid[1024]; // Max size of name from constants.conf, see script->read_constdb. + nullpo_retr(FAKE_NPC, w4); // Extract view ID / constant while (w4[i] != '\0') { if (ISSPACE(w4[i]) || w4[i] == '/' || w4[i] == ',') @@ -2588,6 +2641,7 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c // Checks if given view is an ID or constant. bool npc_viewisid(const char * viewid) { + nullpo_retr(false, viewid); if (atoi(viewid) != FAKE_NPC) { // Loop through view, looking for non-numeric character. while (*viewid) { @@ -2634,6 +2688,8 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short int i, flag = 0; struct npc_data *nd; + nullpo_retr(NULL, name); + nd = npc->create_npc(WARP, from_mapid, from_x, from_y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS); safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname)); @@ -2682,6 +2738,9 @@ const char *npc_parse_warp(const char *w1, const char *w2, const char *w3, const char mapname[32], to_mapname[32]; struct npc_data *nd; + nullpo_retr(strchr(start,'\n'), w1); + nullpo_retr(strchr(start,'\n'), w4); + // w1=<from map name>,<fromX>,<fromY>,<facing> // w4=<spanx>,<spany>,<to map name>,<toX>,<toY> if( sscanf(w1, "%31[^,],%d,%d", mapname, &x, &y) != 3 @@ -2715,7 +2774,7 @@ const char *npc_parse_warp(const char *w1, const char *w2, const char *w3, const nd->u.warp.y = to_y; nd->u.warp.xs = xs; nd->u.warp.ys = ys; - npc_warp++; + npc->npc_warp++; npc->add_to_location(nd); @@ -2753,6 +2812,8 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const struct npc_data *nd; enum npc_subtype type; + nullpo_retr(strchr(start,'\n'), w1); + nullpo_retr(strchr(start,'\n'), w4); if( strcmp(w1,"-") == 0 ) { // 'floating' shop x = y = dir = 0; @@ -2858,7 +2919,7 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const npc->parsename(nd, w3, start, buffer, filepath); nd->path = npc->retainpathreference(filepath); - ++npc_shop; + ++npc->npc_shop; npc->add_to_location(nd); return strchr(start,'\n');// continue @@ -2867,6 +2928,7 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath) { int i; + nullpo_retv(label_list); for( i = 0; i < script->label_count; i++ ) { const char* lname = script->get_str(script->labels[i].key); int lpos = script->labels[i].pos; @@ -2993,6 +3055,7 @@ const char *npc_parse_script(const char *w1, const char *w2, const char *w3, con int label_list_num; struct npc_data* nd; + nullpo_retr(NULL, w1); if (strcmp(w1, "-") == 0) { // floating npc x = 0; @@ -3062,7 +3125,7 @@ const char *npc_parse_script(const char *w1, const char *w2, const char *w3, con if( options&NPO_TRADER ) nd->u.scr.trader = true; nd->u.scr.shop = NULL; - ++npc_script; + ++npc->npc_script; npc->add_to_location(nd); //----------------------------------------- @@ -3129,7 +3192,10 @@ bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, i int i; bool retval = true; - ++npc_script; + nullpo_retr(false, nd); + nullpo_retr(false, snd); + + ++npc->npc_script; nd->u.scr.xs = xs; nd->u.scr.ys = ys; nd->u.scr.script = snd->u.scr.script; @@ -3173,7 +3239,10 @@ bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, i */ bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) { - ++npc_shop; + nullpo_retr(false, nd); + nullpo_retr(false, snd); + + ++npc->npc_shop; nd->u.shop.shop_item = snd->u.shop.shop_item; nd->u.shop.count = snd->u.shop.count; @@ -3188,7 +3257,10 @@ bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int */ bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) { - ++npc_warp; + nullpo_retr(false, nd); + nullpo_retr(false, snd); + + ++npc->npc_warp; nd->u.warp.xs = xs; nd->u.warp.ys = ys; nd->u.warp.mapindex = snd->u.warp.mapindex; @@ -3217,6 +3289,9 @@ bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int */ bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) { + nullpo_retr(false, nd); + nullpo_retr(false, snd); + nd->src_id = snd->bl.id; switch (nd->subtype) { case SCRIPT: @@ -3282,6 +3357,8 @@ const char *npc_parse_duplicate(const char *w1, const char *w2, const char *w3, struct npc_data* dnd; end = strchr(start,'\n'); + nullpo_retr(end, w2); + nullpo_retr(end, w4); length = strlen(w2); // get the npc being duplicated @@ -3366,7 +3443,13 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) int dm = -1, im = -1, xs = -1, ys = -1; struct npc_data *nd = NULL; - if( m == -1 || map->list[m].instance_id == -1 ) + if (m == -1) + return 1; + + Assert_retr(1, m >= 0 && m < map->count); + nullpo_retr(1, snd); + + if (map->list[m].instance_id == -1) return 1; snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", map->list[m].instance_id, snd->bl.id); @@ -3410,10 +3493,15 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) } //Set mapcell CELL_NPC to trigger event later -void npc_setcells(struct npc_data* nd) { - int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; +void npc_setcells(struct npc_data* nd) +{ + int16 m, x, y, xs, ys; int i,j; + nullpo_retv(nd); + m = nd->bl.m; + x = nd->bl.x; + y = nd->bl.y; switch(nd->subtype) { case WARP: xs = nd->u.warp.xs; @@ -3455,9 +3543,13 @@ int npc_unsetcells_sub(struct block_list *bl, va_list ap) } void npc_unsetcells(struct npc_data* nd) { - int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; + int16 m, x, y, xs, ys; int i,j, x0, x1, y0, y1; + nullpo_retv(nd); + m = nd->bl.m; + x = nd->bl.x; + y = nd->bl.y; switch(nd->subtype) { case WARP: xs = nd->u.warp.xs; @@ -3492,7 +3584,9 @@ void npc_unsetcells(struct npc_data* nd) { void npc_movenpc(struct npc_data* nd, int16 x, int16 y) { - const int16 m = nd->bl.m; + int16 m; + nullpo_retv(nd); + m = nd->bl.m; if (m < 0 || nd->bl.prev == NULL) return; //Not on a map. x = cap_value(x, 0, map->list[m].xs-1); @@ -3510,6 +3604,7 @@ void npc_movenpc(struct npc_data* nd, int16 x, int16 y) void npc_setdisplayname(struct npc_data* nd, const char* newname) { nullpo_retv(nd); + nullpo_retv(newname); safestrncpy(nd->name, newname, sizeof(nd->name)); if( map->list[nd->bl.m].users ) @@ -3544,6 +3639,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c size_t len; nullpo_ret(sd); + nullpo_ret(message); if( ev == NULL || (nd = ev->nd) == NULL ) { ShowError("npc_event: event not found [%s]\n", eventname); @@ -3567,7 +3663,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c } st = script->alloc_state(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id); - script->setd_sub(st, NULL, ".@atcmd_command$", 0, (void *)command, NULL); + script->setd_sub(st, NULL, ".@atcmd_command$", 0, command, NULL); len = strlen(message); if (len) { @@ -3623,12 +3719,19 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c */ const char *npc_parse_function(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval) { - DBMap* func_db; - DBData old_data; + struct DBMap *func_db; + struct DBData old_data; struct script_code *scriptroot; const char* end; const char* script_start; + nullpo_retr(NULL, w1); + nullpo_retr(NULL, w2); + nullpo_retr(NULL, w3); + nullpo_retr(NULL, w4); + nullpo_retr(NULL, start); + nullpo_retr(NULL, retval); + script_start = strstr(start,"\t{"); end = strchr(start,'\n'); if( *w4 != '{' || script_start == NULL || (end != NULL && script_start > end) ) { @@ -3672,6 +3775,7 @@ void npc_parse_mob2(struct spawn_data* mobspawn) { int i; + nullpo_retv(mobspawn); for( i = mobspawn->active; i < mobspawn->num; ++i ) { struct mob_data* md = mob->spawn_dataset(mobspawn); md->spawn = mobspawn; @@ -3705,6 +3809,11 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const struct spawn_data mobspawn, *data; struct mob_db* db; + nullpo_retr(strchr(start,'\n'), w1); + nullpo_retr(strchr(start,'\n'), w2); + nullpo_retr(strchr(start,'\n'), w3); + nullpo_retr(strchr(start,'\n'), w4); + memset(&mobspawn, 0, sizeof(struct spawn_data)); mobspawn.state.boss = (strcmp(w2,"boss_monster") == 0 ? 1 : 0); @@ -3847,7 +3956,7 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const // spawn / cache the new mobs if( battle_config.dynamic_mobs && map->addmobtolist(data->m, data) >= 0 ) { data->state.dynamic = true; - npc_cache_mob += data->num; + npc->npc_cache_mob += data->num; // check if target map has players // (usually shouldn't occur when map server is just starting, @@ -3858,10 +3967,10 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const } else { data->state.dynamic = false; npc->parse_mob2(data); - npc_delay_mob += data->num; + npc->npc_delay_mob += data->num; } - npc_mob++; + npc->npc_mob++; return strchr(start,'\n');// continue } @@ -3911,6 +4020,9 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co char mapname[32]; int state = 1; + nullpo_retr(strchr(start,'\n'), w1); + nullpo_retr(strchr(start,'\n'), w3); + // w1=<mapname> if( sscanf(w1, "%31[^,]", mapname) != 1 ) { @@ -4335,6 +4447,7 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co */ const char *npc_parse_unknown_object(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval) { + nullpo_retr(start, retval); ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); start = strchr(start,'\n');// skip and continue *retval = EXIT_FAILURE; @@ -4359,6 +4472,8 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) { char* buffer; const char* p; + nullpo_retr(EXIT_FAILURE, filepath); + // read whole file to buffer fp = fopen(filepath, "rb"); if( fp == NULL ) { @@ -4567,11 +4682,10 @@ void npc_read_event_script(void) {"Kill NPC Event",script->config.kill_mob_event_name}, }; - for (i = 0; i < NPCE_MAX; i++) - { - DBIterator* iter; - DBKey key; - DBData *data; + for (i = 0; i < NPCE_MAX; i++) { + struct DBIterator *iter; + union DBKey key; + struct DBData *data; char name[64]="::"; safestrncpy(name+2,config[i].event_name,62); @@ -4614,9 +4728,10 @@ void npc_read_event_script(void) /** * @see DBApply */ -int npc_path_db_clear_sub(DBKey key, DBData *data, va_list args) +int npc_path_db_clear_sub(union DBKey key, struct DBData *data, va_list args) { struct npc_path_data *npd = DB->data2ptr(data); + nullpo_ret(npd); if (npd->path) aFree(npd->path); return 0; @@ -4625,7 +4740,7 @@ int npc_path_db_clear_sub(DBKey key, DBData *data, va_list args) /** * @see DBApply */ -int npc_ev_label_db_clear_sub(DBKey key, DBData *data, va_list args) +int npc_ev_label_db_clear_sub(union DBKey key, struct DBData *data, va_list args) { struct linkdb_node **label_linkdb = DB->data2ptr(data); linkdb_final(label_linkdb); // linked data (struct event_data*) is freed when clearing ev_db @@ -4652,12 +4767,12 @@ void npc_process_files( int npc_min ) { "\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n" "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", - npc_id - npc_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); + npc->npc_id - npc_min, npc->npc_warp, npc->npc_shop, npc->npc_script, npc->npc_mob, npc->npc_cache_mob, npc->npc_delay_mob); } //Clear then reload npcs files int npc_reload(void) { - int npc_new_min = npc_id; + int npc_new_min = npc->npc_id; struct s_mapiterator* iter; struct block_list* bl; @@ -4673,9 +4788,9 @@ int npc_reload(void) { db_clear(npc->ev_db); npc->ev_label_db->clear(npc->ev_label_db, npc->ev_label_db_clear_sub); - npc_last_npd = NULL; - npc_last_path = NULL; - npc_last_ref = NULL; + npc->npc_last_npd = NULL; + npc->npc_last_path = NULL; + npc->npc_last_ref = NULL; //Remove all npcs/mobs. [Skotlex] iter = mapit_geteachiddb(); @@ -4715,8 +4830,8 @@ int npc_reload(void) { // clear mob spawn lookup index mob->clear_spawninfo(); - npc_warp = npc_shop = npc_script = 0; - npc_mob = npc_cache_mob = npc_delay_mob = 0; + npc->npc_warp = npc->npc_shop = npc->npc_script = 0; + npc->npc_mob = npc->npc_cache_mob = npc->npc_delay_mob = 0; // reset mapflags map->flags_init(); @@ -4754,11 +4869,14 @@ int npc_reload(void) { } //Unload all npc in the given file -bool npc_unloadfile( const char* filepath ) { - DBIterator * iter = db_iterator(npc->name_db); +bool npc_unloadfile(const char *filepath) +{ + struct DBIterator *iter = db_iterator(npc->name_db); struct npc_data* nd = NULL; bool found = false; + nullpo_retr(false, filepath); + for( nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter) ) { if( nd->path && strcasecmp(nd->path,filepath) == 0 ) { // FIXME: This can break in case-sensitive file systems found = true; @@ -4797,6 +4915,9 @@ int do_final_npc(void) { void npc_debug_warps_sub(struct npc_data* nd) { int16 m; + + nullpo_retv(nd); + if (nd->bl.type != BL_NPC || nd->subtype != WARP || nd->bl.m < 0) return; @@ -4833,14 +4954,8 @@ static void npc_debug_warps(void) { int do_init_npc(bool minimal) { int i; - memset(&npc->base_ud, 0, sizeof( struct unit_data) ); - npc->base_ud.bl = NULL; - npc->base_ud.walktimer = INVALID_TIMER; - npc->base_ud.skilltimer = INVALID_TIMER; - npc->base_ud.attacktimer = INVALID_TIMER; - npc->base_ud.attackabletime = - npc->base_ud.canact_tick = - npc->base_ud.canmove_tick = timer->gettick(); + unit->init_ud(&npc->base_ud); + npc->base_ud.bl = NULL; //Stock view data for normal npcs. memset(&npc_viewdb, 0, sizeof(npc_viewdb)); @@ -4856,9 +4971,9 @@ int do_init_npc(bool minimal) { npc->name_db = strdb_alloc(DB_OPT_BASE, NAME_LENGTH); npc->path_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0); - npc_last_npd = NULL; - npc_last_path = NULL; - npc_last_ref = NULL; + npc->npc_last_npd = NULL; + npc->npc_last_path = NULL; + npc->npc_last_ref = NULL; // Should be loaded before npc processing, otherwise labels could overwrite constant values // and lead to undefined behavior [Panikon] @@ -4902,7 +5017,7 @@ int do_init_npc(bool minimal) { strcpy(npc->fake_nd->name,"FAKE_NPC"); memcpy(npc->fake_nd->exname, npc->fake_nd->name, 9); - npc_script++; + npc->npc_script++; npc->fake_nd->bl.type = BL_NPC; npc->fake_nd->subtype = SCRIPT; @@ -4916,6 +5031,17 @@ int do_init_npc(bool minimal) { void npc_defaults(void) { npc = &npc_s; + npc->npc_id = START_NPC_NUM; + npc->npc_warp = 0; + npc->npc_shop = 0; + npc->npc_script = 0; + npc->npc_mob = 0; + npc->npc_delay_mob = 0; + npc->npc_cache_mob = 0; + npc->npc_last_path = NULL; + npc->npc_last_ref = NULL; + npc->npc_last_npd = NULL; + npc->motd = NULL; npc->ev_db = NULL; npc->ev_label_db = NULL; |