From 29a057e286d2203108f93f362c1250c70d7bf511 Mon Sep 17 00:00:00 2001 From: Haru Date: Sun, 25 Oct 2015 15:40:25 +0100 Subject: Split the source path reference retain mechanism out of npc_parsename. Signed-off-by: Haru --- src/map/npc.c | 106 ++++++++++++++++++++++++++++++++++++++-------------------- src/map/npc.h | 4 ++- 2 files changed, 72 insertions(+), 38 deletions(-) diff --git a/src/map/npc.c b/src/map/npc.c index 7044fefcf..f015ed4c9 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -53,8 +53,8 @@ static int npc_mob=0; static int npc_delay_mob=0; static int npc_cache_mob=0; -static char *npc_last_path; -static char *npc_last_ref; +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] @@ -2244,16 +2244,9 @@ int npc_unload(struct npc_data* nd, bool single) npc_chat->finalize(nd); // deallocate npc PCRE data structures #endif - if( single && nd->path ) { - struct npc_path_data* npd = NULL; - if( nd->path && nd->path != npc_last_ref ) { - npd = strdb_get(npc->path_db, nd->path); - } - - if( npd && --npd->references == 0 ) { - strdb_remove(npc->path_db, nd->path);/* remove from db */ - aFree(nd->path);/* remove now that no other instances exist */ - } + if (single && nd->path != NULL) { + npc->releasepathreference(nd->path); + nd->path = NULL; } if( single && nd->bl.m != -1 ) @@ -2404,6 +2397,64 @@ void npc_delsrcfile(const char* name) } } +/** + * Retains a reference to filepath, for use in nd->path + * + * @param filepath The file path to retain. + * @return A retained reference to filepath. + */ +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 ((npd = strdb_get(npc->path_db,filepath)) == NULL) { + CREATE(npd, struct npc_path_data, 1); + strdb_put(npc->path_db, filepath, npd); + + CREATE(npd->path, char, strlen(filepath)+1); + safestrncpy(npd->path, filepath, strlen(filepath)+1); + + npd->references = 0; + } + + npd->references++; + + npc_last_npd = npd; + npc_last_ref = npd->path; + npc_last_path = filepath; + + return npd->path; +} + +/** + * Releases a previously retained filepath. + * + * @param filepath The file path to release. + */ +void npc_releasepathreference(const char *filepath) +{ + struct npc_path_data* npd = NULL; + + nullpo_retv(filepath); + + if (filepath != npc_last_ref) { + npd = strdb_get(npc->path_db, filepath); + } + + if (npd != NULL && --npd->references == 0) { + char *npcpath = npd->path; + strdb_remove(npc->path_db, filepath);/* remove from db */ + aFree(npcpath); + } +} + /// Parses and sets the name and exname of a npc. /// Assumes that m, x and y are already set in nd. void npc_parsename(struct npc_data* nd, const char* name, const char* start, const char* buffer, const char* filepath) { @@ -2458,31 +2509,6 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con ShowDebug("other npc in '%s' :\n display name '%s'\n unique name '%s'\n map=%s, x=%d, y=%d\n",dnd->path, dnd->name, dnd->exname, other_mapname, dnd->bl.x, dnd->bl.y); safestrncpy(nd->exname, newname, sizeof(nd->exname)); } - - if( npc_last_path != filepath ) { - struct npc_path_data * npd = NULL; - - if( !(npd = strdb_get(npc->path_db,filepath) ) ) { - CREATE(npd, struct npc_path_data, 1); - strdb_put(npc->path_db, filepath, npd); - - CREATE(npd->path, char, strlen(filepath)+1); - safestrncpy(npd->path, filepath, strlen(filepath)+1); - - npd->references = 0; - } - - nd->path = npd->path; - npd->references++; - - npc_last_npd = npd; - npc_last_ref = npd->path; - npc_last_path = (char*) filepath; - } else { - nd->path = npc_last_ref; - if( npc_last_npd ) - npc_last_npd->references++; - } } // Parse View @@ -2626,6 +2652,7 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s nd = npc->create_npc(m, x, y); map->addnpc(m, nd); npc->parsename(nd, w3, start, buffer, filepath); + nd->path = npc->retainpathreference(filepath); if (!battle_config.warp_point_debug) nd->class_ = WARP_CLASS; @@ -2772,6 +2799,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s nd->u.shop.count = i; npc->parsename(nd, w3, start, buffer, filepath); + nd->path = npc->retainpathreference(filepath); nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); nd->speed = 200; @@ -2959,6 +2987,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* } npc->parsename(nd, w3, start, buffer, filepath); + nd->path = npc->retainpathreference(filepath); nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); nd->speed = 200; nd->u.scr.script = scriptroot; @@ -3100,6 +3129,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch nd = npc->create_npc(m, x, y); npc->parsename(nd, w3, start, buffer, filepath); + nd->path = npc->retainpathreference(filepath); nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); nd->speed = 200; nd->src_id = src_id; @@ -4732,6 +4762,8 @@ void npc_defaults(void) { npc->clearsrcfile = npc_clearsrcfile; npc->addsrcfile = npc_addsrcfile; npc->delsrcfile = npc_delsrcfile; + npc->retainpathreference = npc_retainpathreference; + npc->releasepathreference = npc_releasepathreference; npc->parsename = npc_parsename; npc->parseview = npc_parseview; npc->viewisid = npc_viewisid; diff --git a/src/map/npc.h b/src/map/npc.h index bf3d1494d..340785aa6 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -70,7 +70,7 @@ struct npc_data { unsigned short stat_point; struct npc_parse *chatdb; - char* path;/* path dir */ + const char *path; ///< Source path reference enum npc_subtype subtype; int src_id; union { @@ -225,6 +225,8 @@ struct npc_interface { void (*clearsrcfile) (void); void (*addsrcfile) (const char *name); void (*delsrcfile) (const char *name); + const char *(*retainpathreference) (const char *filepath); + void (*releasepathreference) (const char *filepath); void (*parsename) (struct npc_data *nd, const char *name, const char *start, const char *buffer, const char *filepath); int (*parseview) (const char *w4, const char *start, const char *buffer, const char *filepath); bool (*viewisid) (const char *viewid); -- cgit v1.2.3-70-g09d2 From 8db74e2781bb71be6cf58d495739dcd1787428e3 Mon Sep 17 00:00:00 2001 From: Haru Date: Sun, 25 Oct 2015 17:14:22 +0100 Subject: Split the duplication logic away from the parsing logic in NPC duplicates - Fixes #812 (warning message while creating instances) Signed-off-by: Haru --- src/map/npc.c | 290 +++++++++++++++++++++++++++++++--------------------------- src/map/npc.h | 1 + 2 files changed, 155 insertions(+), 136 deletions(-) diff --git a/src/map/npc.c b/src/map/npc.c index f015ed4c9..b01091f54 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -3048,6 +3048,110 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* return end; } +/** + * Duplicates a warp, shop, cashshop or script. + * + * @param nd An already initialized NPC data. Expects bl->m, bl->x, bl->y, name, exname, path to be already filled. + * @param snd The source NPC to duplicate. + * @param class_ The npc view class. + * @param dir The facing direction. + * @param xs The x-span, if any. + * @param ys The y-span, if any. + * @param options The NPC options. + * @retval false if there were any issues while creating and validating the NPC. + */ +bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int class_, int dir, int xs, int ys, int options) +{ + int i; + bool retval = true; + + nd->class_ = class_; + nd->speed = 200; + nd->src_id = snd->bl.id; + nd->bl.type = BL_NPC; + nd->subtype = snd->subtype; + switch (nd->subtype) { + case SCRIPT: + ++npc_script; + nd->u.scr.xs = xs; + nd->u.scr.ys = ys; + nd->u.scr.script = snd->u.scr.script; + nd->u.scr.label_list = snd->u.scr.label_list; + nd->u.scr.label_list_num = snd->u.scr.label_list_num; + nd->u.scr.shop = snd->u.scr.shop; + nd->u.scr.trader = snd->u.scr.trader; + break; + + case SHOP: + case CASHSHOP: + ++npc_shop; + nd->u.shop.shop_item = snd->u.shop.shop_item; + nd->u.shop.count = snd->u.shop.count; + break; + + case WARP: + ++npc_warp; + if( !battle_config.warp_point_debug ) + nd->class_ = WARP_CLASS; + else + nd->class_ = WARP_DEBUG_CLASS; + nd->u.warp.xs = xs; + nd->u.warp.ys = ys; + nd->u.warp.mapindex = snd->u.warp.mapindex; + nd->u.warp.x = snd->u.warp.x; + nd->u.warp.y = snd->u.warp.y; + break; + } + + //Add the npc to its location + if (nd->bl.m >= 0) { + map->addnpc(nd->bl.m, nd); + nd->ud = &npc->base_ud; + nd->dir = dir; + npc->setcells(nd); + map->addblock(&nd->bl); + if (nd->class_ >= 0) { + status->set_viewdata(&nd->bl, nd->class_); + if (map->list[nd->bl.m].users) + clif->spawn(&nd->bl); + } + } else { + // we skip map->addnpc, but still add it to the list of ID's + map->addiddb(&nd->bl); + } + strdb_put(npc->name_db, nd->exname, nd); + + if (nd->subtype != SCRIPT) + return true; + + //----------------------------------------- + // Loop through labels to export them as necessary + for (i = 0; i < nd->u.scr.label_list_num; i++) { + if (npc->event_export(nd, i)) { + ShowWarning("npc_parse_duplicate: duplicate event %s::%s in file '%s'.\n", + nd->exname, nd->u.scr.label_list[i].name, nd->path); + retval = false; + } + npc->timerevent_export(nd, i); + } + + nd->u.scr.timerid = INVALID_TIMER; + + if (options&NPO_ONINIT) { + // From npc_parse_script + char evname[EVENT_NAME_LENGTH]; + struct event_data *ev; + + snprintf(evname, ARRAYLENGTH(evname), "%s::OnInit", nd->exname); + + if ((ev = (struct event_data*)strdb_get(npc->ev_db, evname)) != NULL) { + //Execute OnInit + script->run_npc(nd->u.scr.script,ev->pos,0,nd->bl.id); + } + } + return retval; +} + /// Duplicate a warp, shop, cashshop or script. [Orcao] /// warp: ,,,%TAB%duplicate()%TAB%%TAB%, /// shop/cashshop/npc: -%TAB%duplicate()%TAB%%TAB% @@ -3058,12 +3162,10 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval) { int x, y, dir, m, xs = -1, ys = -1; char srcname[128]; - int i; - const char* end; + const char *end; size_t length; - int src_id; - int type; + int class_; struct npc_data* nd; struct npc_data* dnd; @@ -3085,18 +3187,16 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch if (retval) *retval = EXIT_FAILURE; return end;// next line, try to continue } - src_id = dnd->bl.id; - type = dnd->subtype; // get placement - if ((type==SHOP || type==CASHSHOP || type==SCRIPT) && strcmp(w1, "-") == 0) { + if ((dnd->subtype==SHOP || dnd->subtype==CASHSHOP || dnd->subtype==SCRIPT) && strcmp(w1, "-") == 0) { // floating shop/chashshop/script x = y = dir = 0; m = -1; } else { char mapname[32]; int fields = sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir); - if (type == WARP && fields == 3) { + if (dnd->subtype == WARP && fields == 3) { // ,, dir = 0; } else if (fields != 4) { @@ -3119,9 +3219,11 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch return end;//try next } - if( type == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2 );// , - else if( type == SCRIPT && sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2);// ,, - else if( type == WARP ) { + if (dnd->subtype == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2) { // , + ; + } else if (dnd->subtype == SCRIPT && sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2) { // ,, + ; + } else if (dnd->subtype == WARP) { ShowError("npc_parse_duplicate: Invalid span format for duplicate warp 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); if (retval) *retval = EXIT_FAILURE; return end;// next line, try to continue @@ -3130,97 +3232,27 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch nd = npc->create_npc(m, x, y); npc->parsename(nd, w3, start, buffer, filepath); nd->path = npc->retainpathreference(filepath); - nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); - nd->speed = 200; - nd->src_id = src_id; - nd->bl.type = BL_NPC; - nd->subtype = (enum npc_subtype)type; - switch( type ) { - case SCRIPT: - ++npc_script; - nd->u.scr.xs = xs; - nd->u.scr.ys = ys; - nd->u.scr.script = dnd->u.scr.script; - nd->u.scr.label_list = dnd->u.scr.label_list; - nd->u.scr.label_list_num = dnd->u.scr.label_list_num; - nd->u.scr.shop = dnd->u.scr.shop; - nd->u.scr.trader = dnd->u.scr.trader; - break; - - case SHOP: - case CASHSHOP: - ++npc_shop; - nd->u.shop.shop_item = dnd->u.shop.shop_item; - nd->u.shop.count = dnd->u.shop.count; - break; - - case WARP: - ++npc_warp; - if( !battle_config.warp_point_debug ) - nd->class_ = WARP_CLASS; - else - nd->class_ = WARP_DEBUG_CLASS; - nd->u.warp.xs = xs; - nd->u.warp.ys = ys; - nd->u.warp.mapindex = dnd->u.warp.mapindex; - nd->u.warp.x = dnd->u.warp.x; - nd->u.warp.y = dnd->u.warp.y; - break; - } - - //Add the npc to its location - if( m >= 0 ) { - map->addnpc(m, nd); - nd->ud = &npc->base_ud; - nd->dir = dir; - npc->setcells(nd); - map->addblock(&nd->bl); - if( nd->class_ >= 0 ) { - status->set_viewdata(&nd->bl, nd->class_); - if( map->list[nd->bl.m].users ) - clif->spawn(&nd->bl); - } - } else { - // we skip map->addnpc, but still add it to the list of ID's - map->addiddb(&nd->bl); - } - strdb_put(npc->name_db, nd->exname, nd); - - if( type != SCRIPT ) - return end; - - //----------------------------------------- - // Loop through labels to export them as necessary - for (i = 0; i < nd->u.scr.label_list_num; i++) { - if (npc->event_export(nd, i)) { - ShowWarning("npc_parse_duplicate: duplicate event %s::%s in file '%s'.\n", - nd->exname, nd->u.scr.label_list[i].name, filepath); - if (retval) *retval = EXIT_FAILURE; - } - npc->timerevent_export(nd, i); + class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); + if (!npc->duplicate_sub(nd, dnd, class_, dir, xs, ys, options)) { + if (retval) *retval = EXIT_FAILURE; } - nd->u.scr.timerid = INVALID_TIMER; - - if (options&NPO_ONINIT) { - // From npc_parse_script - char evname[EVENT_NAME_LENGTH]; - struct event_data *ev; - - snprintf(evname, ARRAYLENGTH(evname), "%s::OnInit", nd->exname); - - if( ( ev = (struct event_data*)strdb_get(npc->ev_db, evname) ) ) { - - //Execute OnInit - script->run_npc(nd->u.scr.script,ev->pos,0,nd->bl.id); - - } - } return end; } -int npc_duplicate4instance(struct npc_data *snd, int16 m) { +/** + * Duplicates an NPC for instancing purposes. + * + * @param snd The NPC to duplicate. + * @param m The instanced map ID. + * @return success state. + * @retval 0 in case of successful creation. + */ +int npc_duplicate4instance(struct npc_data *snd, int16 m) +{ char newname[NAME_LENGTH]; + int dm = -1, im = -1, xs = -1, ys = -1; + struct npc_data *nd = NULL; if( m == -1 || map->list[m].instance_id == -1 ) return 1; @@ -3231,50 +3263,35 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) { return 1; } - if( snd->subtype == WARP ) { // Adjust destination, if instanced - struct npc_data *wnd = NULL; // New NPC - int dm = map->mapindex2mapid(snd->u.warp.mapindex), im; - if( dm < 0 ) return 1; - - if( ( im = instance->mapid2imapid(dm, map->list[m].instance_id) ) == -1 ) { + switch (snd->subtype) { + case SCRIPT: + xs = snd->u.scr.xs; + ys = snd->u.scr.ys; + break; + case WARP: + xs = snd->u.warp.xs; + ys = snd->u.warp.ys; + // Adjust destination, if instanced + if ((dm = map->mapindex2mapid(snd->u.warp.mapindex)) < 0) { + return 1; + } + if ((im = instance->mapid2imapid(dm, map->list[m].instance_id)) == -1) { ShowError("npc_duplicate4instance: warp (%s) leading to instanced map (%s), but instance map is not attached to current instance.\n", map->list[dm].name, snd->exname); return 1; } + break; + default: // Other types have no xs/ys + break; + } - wnd = npc->create_npc(m, snd->bl.x, snd->bl.y); - map->addnpc(m, wnd); - safestrncpy(wnd->name, "", ARRAYLENGTH(wnd->name)); - safestrncpy(wnd->exname, newname, ARRAYLENGTH(wnd->exname)); - wnd->class_ = WARP_CLASS; - wnd->speed = 200; - wnd->u.warp.mapindex = map_id2index(im); - wnd->u.warp.x = snd->u.warp.x; - wnd->u.warp.y = snd->u.warp.y; - wnd->u.warp.xs = snd->u.warp.xs; - wnd->u.warp.ys = snd->u.warp.ys; - wnd->bl.type = BL_NPC; - wnd->subtype = WARP; - npc->setcells(wnd); - map->addblock(&wnd->bl); - status->set_viewdata(&wnd->bl, wnd->class_); - wnd->ud = &npc->base_ud; - if( map->list[wnd->bl.m].users ) - clif->spawn(&wnd->bl); - strdb_put(npc->name_db, wnd->exname, wnd); - } else { - static char w1[50], w2[50], w3[50], w4[50]; - const char* stat_buf = "- call from instancing subsystem -\n"; - - snprintf(w1, sizeof(w1), "%s,%d,%d,%d", map->list[m].name, snd->bl.x, snd->bl.y, snd->dir); - snprintf(w2, sizeof(w2), "duplicate(%s)", snd->exname); - snprintf(w3, sizeof(w3), "%s::%s", snd->name, newname); - - if( snd->u.scr.xs >= 0 && snd->u.scr.ys >= 0 ) - snprintf(w4, sizeof(w4), "%d,%d,%d", snd->class_, snd->u.scr.xs, snd->u.scr.ys); // Touch Area - else - snprintf(w4, sizeof(w4), "%d", snd->class_); - - npc->parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "INSTANCING", NPO_NONE, NULL); + nd = npc->create_npc(m, snd->bl.x, snd->bl.y); + safestrncpy(nd->name, snd->name, sizeof(nd->name)); + safestrncpy(nd->exname, newname, sizeof(nd->exname)); + nd->path = npc->retainpathreference("INSTANCING"); + npc->duplicate_sub(nd, snd, snd->class_, snd->dir, xs, ys, NPO_NONE); + if (nd->subtype == WARP) { + // Adjust destination, if instanced + nd->u.warp.mapindex = map_id2index(im); } return 0; @@ -4774,6 +4791,7 @@ void npc_defaults(void) { npc->convertlabel_db = npc_convertlabel_db; npc->skip_script = npc_skip_script; npc->parse_script = npc_parse_script; + npc->duplicate_sub = npc_duplicate_sub; npc->parse_duplicate = npc_parse_duplicate; npc->duplicate4instance = npc_duplicate4instance; npc->setcells = npc_setcells; diff --git a/src/map/npc.h b/src/map/npc.h index 340785aa6..a4ebf3d76 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -238,6 +238,7 @@ struct npc_interface { void (*convertlabel_db) (struct npc_label_list *label_list, const char *filepath); const char* (*skip_script) (const char *start, const char *buffer, const char *filepath, int *retval); const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval); + bool (*duplicate_sub) (struct npc_data *nd, const struct npc_data *snd, int class_, int dir, int xs, int ys, int options); const char* (*parse_duplicate) (char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval); int (*duplicate4instance) (struct npc_data *snd, int16 m); void (*setcells) (struct npc_data *nd); -- cgit v1.2.3-70-g09d2 From 556ea4c20bb7ca06adb572ccefc1986f71e6a5c0 Mon Sep 17 00:00:00 2001 From: Haru Date: Tue, 3 Nov 2015 14:42:46 +0100 Subject: Moved class and dir initializers to npc_create_npc Signed-off-by: Haru --- src/map/mob.c | 7 +---- src/map/npc.c | 84 +++++++++++++++++++++++++---------------------------------- src/map/npc.h | 5 ++-- 3 files changed, 39 insertions(+), 57 deletions(-) diff --git a/src/map/mob.c b/src/map/mob.c index 2b519462d..c925d02ce 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -142,15 +142,11 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time) if ( md->tomb_nid ) mob->mvptomb_destroy(md); - nd = npc->create_npc(md->bl.m, md->bl.x, md->bl.y); + nd = npc->create_npc(md->bl.m, md->bl.x, md->bl.y, md->ud.dir, MOB_TOMB); md->tomb_nid = nd->bl.id; - nd->dir = md->ud.dir; - nd->bl.type = BL_NPC; safestrncpy(nd->name, msg_txt(856), sizeof(nd->name)); // "Tomb" - nd->class_ = 565; - nd->speed = 200; nd->subtype = TOMB; nd->u.tomb.md = md; @@ -165,7 +161,6 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time) map->addblock(&nd->bl); status->set_viewdata(&nd->bl, nd->class_); clif->spawn(&nd->bl); - } void mvptomb_destroy(struct mob_data *md) { diff --git a/src/map/npc.c b/src/map/npc.c index b01091f54..9271d643a 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2560,17 +2560,31 @@ bool npc_viewisid(const char * viewid) return true; } -struct npc_data* npc_create_npc(int m, int x, int y) +/** + * Creates a new NPC. + * + * @param m The map id. + * @param x The x coordinate on map. + * @param y The y coordinate on map. + * @param dir The facing direction. + * @param class_ The NPC view class. + * @return A pointer to the created NPC data (ownership passed to the caller). + */ +struct npc_data *npc_create_npc(int m, int x, int y, uint8 dir, int16 class_) { struct npc_data *nd; CREATE(nd, struct npc_data, 1); + nd->bl.type = BL_NPC; nd->bl.id = npc->get_new_npc_id(); nd->bl.prev = nd->bl.next = NULL; nd->bl.m = m; nd->bl.x = x; nd->bl.y = y; + nd->dir = dir; nd->area_size = AREA_SIZE + 1; + nd->class_ = class_; + nd->speed = 200; return nd; } @@ -2580,7 +2594,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short int i, flag = 0; struct npc_data *nd; - nd = npc->create_npc(from_mapid, from_x, from_y); + nd = npc->create_npc(from_mapid, from_x, from_y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS); map->addnpc(from_mapid, nd); safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname)); @@ -2594,18 +2608,11 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp%d_%d_%d_%d", i, from_mapid, from_x, from_y); safestrncpy(nd->name, nd->exname, ARRAYLENGTH(nd->name)); - if( battle_config.warp_point_debug ) - nd->class_ = WARP_DEBUG_CLASS; - else - nd->class_ = WARP_CLASS; - nd->speed = 200; - nd->u.warp.mapindex = to_mapindex; nd->u.warp.x = to_x; nd->u.warp.y = to_y; nd->u.warp.xs = xs; nd->u.warp.ys = xs; - nd->bl.type = BL_NPC; nd->subtype = WARP; npc->setcells(nd); map->addblock(&nd->bl); @@ -2649,24 +2656,17 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s return strchr(start,'\n');;//try next } - nd = npc->create_npc(m, x, y); + nd = npc->create_npc(m, x, y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS); map->addnpc(m, nd); npc->parsename(nd, w3, start, buffer, filepath); nd->path = npc->retainpathreference(filepath); - if (!battle_config.warp_point_debug) - nd->class_ = WARP_CLASS; - else - nd->class_ = WARP_DEBUG_CLASS; - nd->speed = 200; - nd->u.warp.mapindex = i; nd->u.warp.x = to_x; nd->u.warp.y = to_y; nd->u.warp.xs = xs; nd->u.warp.ys = ys; npc_warp++; - nd->bl.type = BL_NPC; nd->subtype = WARP; npc->setcells(nd); map->addblock(&nd->bl); @@ -2693,7 +2693,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s size_t items_count = 40; // Starting items size char *p; - int x, y, dir, m, i; + int x, y, dir, m, i, class_; struct npc_data *nd; enum npc_subtype type; @@ -2792,7 +2792,8 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s return strchr(start,'\n');// continue } - nd = npc->create_npc(m, x, y); + class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); + nd = npc->create_npc(m, x, y, dir, class_); CREATE(nd->u.shop.shop_item, struct npc_item_list, i); memcpy(nd->u.shop.shop_item, items, sizeof(items[0])*i); aFree(items); @@ -2800,18 +2801,14 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s nd->u.shop.count = i; npc->parsename(nd, w3, start, buffer, filepath); nd->path = npc->retainpathreference(filepath); - nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); - nd->speed = 200; ++npc_shop; - nd->bl.type = BL_NPC; nd->subtype = type; if( m >= 0 ) {// normal shop npc map->addnpc(m,nd); map->addblock(&nd->bl); status->set_viewdata(&nd->bl, nd->class_); nd->ud = &npc->base_ud; - nd->dir = dir; if( map->list[nd->bl.m].users ) clif->spawn(&nd->bl); } else {// 'floating' shop @@ -2917,7 +2914,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* { int x, y, dir = 0, m, xs = 0, ys = 0; // [Valaris] thanks to fov struct script_code *scriptroot; - int i; + int i, class_; const char* end; const char* script_start; @@ -2974,22 +2971,20 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* npc->convertlabel_db(label_list,filepath); } - nd = npc->create_npc(m, x, y); - if( sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2 ) - {// OnTouch area defined + class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); + nd = npc->create_npc(m, x, y, dir, class_); + if (sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2) { + // OnTouch area defined nd->u.scr.xs = xs; nd->u.scr.ys = ys; - } - else - {// no OnTouch area + } else { + // no OnTouch area nd->u.scr.xs = -1; nd->u.scr.ys = -1; } npc->parsename(nd, w3, start, buffer, filepath); nd->path = npc->retainpathreference(filepath); - nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); - nd->speed = 200; nd->u.scr.script = scriptroot; nd->u.scr.label_list = label_list; nd->u.scr.label_list_num = label_list_num; @@ -2998,13 +2993,11 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* nd->u.scr.shop = NULL; ++npc_script; - nd->bl.type = BL_NPC; nd->subtype = SCRIPT; if( m >= 0 ) { map->addnpc(m, nd); nd->ud = &npc->base_ud; - nd->dir = dir; npc->setcells(nd); map->addblock(&nd->bl); if( nd->class_ >= 0 ) { @@ -3051,7 +3044,8 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* /** * Duplicates a warp, shop, cashshop or script. * - * @param nd An already initialized NPC data. Expects bl->m, bl->x, bl->y, name, exname, path to be already filled. + * @param nd An already initialized NPC data. Expects bl->m, bl->x, bl->y, + * name, exname, path, dir, class_, speed to be already filled. * @param snd The source NPC to duplicate. * @param class_ The npc view class. * @param dir The facing direction. @@ -3060,15 +3054,12 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* * @param options The NPC options. * @retval false if there were any issues while creating and validating the NPC. */ -bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int class_, int dir, int xs, int ys, int options) +bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) { int i; bool retval = true; - nd->class_ = class_; - nd->speed = 200; nd->src_id = snd->bl.id; - nd->bl.type = BL_NPC; nd->subtype = snd->subtype; switch (nd->subtype) { case SCRIPT: @@ -3091,10 +3082,6 @@ bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int clas case WARP: ++npc_warp; - if( !battle_config.warp_point_debug ) - nd->class_ = WARP_CLASS; - else - nd->class_ = WARP_DEBUG_CLASS; nd->u.warp.xs = xs; nd->u.warp.ys = ys; nd->u.warp.mapindex = snd->u.warp.mapindex; @@ -3107,7 +3094,6 @@ bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int clas if (nd->bl.m >= 0) { map->addnpc(nd->bl.m, nd); nd->ud = &npc->base_ud; - nd->dir = dir; npc->setcells(nd); map->addblock(&nd->bl); if (nd->class_ >= 0) { @@ -3229,11 +3215,11 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch return end;// next line, try to continue } - nd = npc->create_npc(m, x, y); + class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); + nd = npc->create_npc(m, x, y, dir, class_); npc->parsename(nd, w3, start, buffer, filepath); nd->path = npc->retainpathreference(filepath); - class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); - if (!npc->duplicate_sub(nd, dnd, class_, dir, xs, ys, options)) { + if (!npc->duplicate_sub(nd, dnd, xs, ys, options)) { if (retval) *retval = EXIT_FAILURE; } @@ -3284,11 +3270,11 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) break; } - nd = npc->create_npc(m, snd->bl.x, snd->bl.y); + nd = npc->create_npc(m, snd->bl.x, snd->bl.y, snd->dir, snd->class_); safestrncpy(nd->name, snd->name, sizeof(nd->name)); safestrncpy(nd->exname, newname, sizeof(nd->exname)); nd->path = npc->retainpathreference("INSTANCING"); - npc->duplicate_sub(nd, snd, snd->class_, snd->dir, xs, ys, NPO_NONE); + npc->duplicate_sub(nd, snd, xs, ys, NPO_NONE); if (nd->subtype == WARP) { // Adjust destination, if instanced nd->u.warp.mapindex = map_id2index(im); diff --git a/src/map/npc.h b/src/map/npc.h index a4ebf3d76..213c5df38 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -111,6 +111,7 @@ struct npc_data { enum actor_classes { WARP_CLASS = 45, HIDDEN_WARP_CLASS = 139, + MOB_TOMB = 565, WARP_DEBUG_CLASS = 722, FLAG_CLASS = 722, INVISIBLE_CLASS = 32767, @@ -230,7 +231,7 @@ struct npc_interface { void (*parsename) (struct npc_data *nd, const char *name, const char *start, const char *buffer, const char *filepath); int (*parseview) (const char *w4, const char *start, const char *buffer, const char *filepath); bool (*viewisid) (const char *viewid); - struct npc_data* (*create_npc) (int m, int x, int y); + struct npc_data *(*create_npc) (int m, int x, int y, uint8 dir, int16 class_); struct npc_data* (*add_warp) (char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y); const char* (*parse_warp) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval); const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval); @@ -238,7 +239,7 @@ struct npc_interface { void (*convertlabel_db) (struct npc_label_list *label_list, const char *filepath); const char* (*skip_script) (const char *start, const char *buffer, const char *filepath, int *retval); const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval); - bool (*duplicate_sub) (struct npc_data *nd, const struct npc_data *snd, int class_, int dir, int xs, int ys, int options); + bool (*duplicate_sub) (struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options); const char* (*parse_duplicate) (char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval); int (*duplicate4instance) (struct npc_data *snd, int16 m); void (*setcells) (struct npc_data *nd); -- cgit v1.2.3-70-g09d2 From 57f09704aaa62295a9a967726a0dbabda40770c4 Mon Sep 17 00:00:00 2001 From: Haru Date: Tue, 3 Nov 2015 15:26:12 +0100 Subject: Added subtype initializer to npc_create_npc Signed-off-by: Haru --- src/map/mob.c | 4 +--- src/map/npc.c | 33 ++++++++++++++++++--------------- src/map/npc.h | 2 +- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/map/mob.c b/src/map/mob.c index c925d02ce..6cbbd3a2a 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -142,13 +142,11 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time) if ( md->tomb_nid ) mob->mvptomb_destroy(md); - nd = npc->create_npc(md->bl.m, md->bl.x, md->bl.y, md->ud.dir, MOB_TOMB); + nd = npc->create_npc(TOMB, md->bl.m, md->bl.x, md->bl.y, md->ud.dir, MOB_TOMB); md->tomb_nid = nd->bl.id; safestrncpy(nd->name, msg_txt(856), sizeof(nd->name)); // "Tomb" - nd->subtype = TOMB; - nd->u.tomb.md = md; nd->u.tomb.kill_time = time; diff --git a/src/map/npc.c b/src/map/npc.c index 9271d643a..e92e3c447 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2563,6 +2563,11 @@ bool npc_viewisid(const char * viewid) /** * Creates a new NPC. * + * @remark + * When creating a npc with subtype TOMB, no ID is assigned. The caller + * must assign the dead mob ID after the NPC is created. + * + * @param subtype The NPC subtype. * @param m The map id. * @param x The x coordinate on map. * @param y The y coordinate on map. @@ -2570,13 +2575,16 @@ bool npc_viewisid(const char * viewid) * @param class_ The NPC view class. * @return A pointer to the created NPC data (ownership passed to the caller). */ -struct npc_data *npc_create_npc(int m, int x, int y, uint8 dir, int16 class_) +struct npc_data *npc_create_npc(enum npc_subtype subtype, int m, int x, int y, uint8 dir, int16 class_) { struct npc_data *nd; CREATE(nd, struct npc_data, 1); + nd->subtype = subtype; nd->bl.type = BL_NPC; - nd->bl.id = npc->get_new_npc_id(); + if (subtype != TOMB) { + nd->bl.id = npc->get_new_npc_id(); + } nd->bl.prev = nd->bl.next = NULL; nd->bl.m = m; nd->bl.x = x; @@ -2594,7 +2602,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short int i, flag = 0; struct npc_data *nd; - nd = npc->create_npc(from_mapid, from_x, from_y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS); + nd = npc->create_npc(WARP, from_mapid, from_x, from_y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS); map->addnpc(from_mapid, nd); safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname)); @@ -2613,7 +2621,6 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short nd->u.warp.y = to_y; nd->u.warp.xs = xs; nd->u.warp.ys = xs; - nd->subtype = WARP; npc->setcells(nd); map->addblock(&nd->bl); status->set_viewdata(&nd->bl, nd->class_); @@ -2656,7 +2663,7 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s return strchr(start,'\n');;//try next } - nd = npc->create_npc(m, x, y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS); + nd = npc->create_npc(WARP, m, x, y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS); map->addnpc(m, nd); npc->parsename(nd, w3, start, buffer, filepath); nd->path = npc->retainpathreference(filepath); @@ -2667,7 +2674,6 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s nd->u.warp.xs = xs; nd->u.warp.ys = ys; npc_warp++; - nd->subtype = WARP; npc->setcells(nd); map->addblock(&nd->bl); status->set_viewdata(&nd->bl, nd->class_); @@ -2793,7 +2799,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s } class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); - nd = npc->create_npc(m, x, y, dir, class_); + nd = npc->create_npc(type, m, x, y, dir, class_); CREATE(nd->u.shop.shop_item, struct npc_item_list, i); memcpy(nd->u.shop.shop_item, items, sizeof(items[0])*i); aFree(items); @@ -2803,7 +2809,6 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s nd->path = npc->retainpathreference(filepath); ++npc_shop; - nd->subtype = type; if( m >= 0 ) {// normal shop npc map->addnpc(m,nd); map->addblock(&nd->bl); @@ -2972,7 +2977,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* } class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); - nd = npc->create_npc(m, x, y, dir, class_); + nd = npc->create_npc(SCRIPT, m, x, y, dir, class_); if (sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2) { // OnTouch area defined nd->u.scr.xs = xs; @@ -2991,9 +2996,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* if( options&NPO_TRADER ) nd->u.scr.trader = true; nd->u.scr.shop = NULL; - ++npc_script; - nd->subtype = SCRIPT; if( m >= 0 ) { map->addnpc(m, nd); @@ -3045,7 +3048,8 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* * Duplicates a warp, shop, cashshop or script. * * @param nd An already initialized NPC data. Expects bl->m, bl->x, bl->y, - * name, exname, path, dir, class_, speed to be already filled. + * name, exname, path, dir, class_, speed, subtype to be already + * filled. * @param snd The source NPC to duplicate. * @param class_ The npc view class. * @param dir The facing direction. @@ -3060,7 +3064,6 @@ bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, bool retval = true; nd->src_id = snd->bl.id; - nd->subtype = snd->subtype; switch (nd->subtype) { case SCRIPT: ++npc_script; @@ -3216,7 +3219,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch } class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); - nd = npc->create_npc(m, x, y, dir, class_); + nd = npc->create_npc(dnd->subtype, m, x, y, dir, class_); npc->parsename(nd, w3, start, buffer, filepath); nd->path = npc->retainpathreference(filepath); if (!npc->duplicate_sub(nd, dnd, xs, ys, options)) { @@ -3270,7 +3273,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) break; } - nd = npc->create_npc(m, snd->bl.x, snd->bl.y, snd->dir, snd->class_); + nd = npc->create_npc(snd->subtype, m, snd->bl.x, snd->bl.y, snd->dir, snd->class_); safestrncpy(nd->name, snd->name, sizeof(nd->name)); safestrncpy(nd->exname, newname, sizeof(nd->exname)); nd->path = npc->retainpathreference("INSTANCING"); diff --git a/src/map/npc.h b/src/map/npc.h index 213c5df38..bec17fd8d 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -231,7 +231,7 @@ struct npc_interface { void (*parsename) (struct npc_data *nd, const char *name, const char *start, const char *buffer, const char *filepath); int (*parseview) (const char *w4, const char *start, const char *buffer, const char *filepath); bool (*viewisid) (const char *viewid); - struct npc_data *(*create_npc) (int m, int x, int y, uint8 dir, int16 class_); + struct npc_data *(*create_npc) (enum npc_subtype subtype, int m, int x, int y, uint8 dir, int16 class_); struct npc_data* (*add_warp) (char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y); const char* (*parse_warp) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval); const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval); -- cgit v1.2.3-70-g09d2 From d0bc38acd10a05bfdc8116b316a6b6eb62b9b580 Mon Sep 17 00:00:00 2001 From: Haru Date: Tue, 3 Nov 2015 15:33:10 +0100 Subject: Split frequently repeated code to add/register new NPCs to its own function Signed-off-by: Haru --- src/map/npc.c | 92 ++++++++++++++++++++++------------------------------------- src/map/npc.h | 1 + 2 files changed, 35 insertions(+), 58 deletions(-) diff --git a/src/map/npc.c b/src/map/npc.c index e92e3c447..ea73c2f81 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -2603,7 +2603,6 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short struct npc_data *nd; nd = npc->create_npc(WARP, from_mapid, from_x, from_y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS); - map->addnpc(from_mapid, nd); safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname)); if (npc->name2id(nd->exname) != NULL) @@ -2621,13 +2620,8 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short nd->u.warp.y = to_y; nd->u.warp.xs = xs; nd->u.warp.ys = xs; - npc->setcells(nd); - map->addblock(&nd->bl); - status->set_viewdata(&nd->bl, nd->class_); - nd->ud = &npc->base_ud; - if( map->list[nd->bl.m].users ) - clif->spawn(&nd->bl); - strdb_put(npc->name_db, nd->exname, nd); + + npc->add_to_location(nd); return nd; } @@ -2664,7 +2658,6 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s } nd = npc->create_npc(WARP, m, x, y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS); - map->addnpc(m, nd); npc->parsename(nd, w3, start, buffer, filepath); nd->path = npc->retainpathreference(filepath); @@ -2674,13 +2667,8 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s nd->u.warp.xs = xs; nd->u.warp.ys = ys; npc_warp++; - npc->setcells(nd); - map->addblock(&nd->bl); - status->set_viewdata(&nd->bl, nd->class_); - nd->ud = &npc->base_ud; - if( map->list[nd->bl.m].users ) - clif->spawn(&nd->bl); - strdb_put(npc->name_db, nd->exname, nd); + + npc->add_to_location(nd); return strchr(start,'\n');// continue } @@ -2809,17 +2797,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s nd->path = npc->retainpathreference(filepath); ++npc_shop; - if( m >= 0 ) {// normal shop npc - map->addnpc(m,nd); - map->addblock(&nd->bl); - status->set_viewdata(&nd->bl, nd->class_); - nd->ud = &npc->base_ud; - if( map->list[nd->bl.m].users ) - clif->spawn(&nd->bl); - } else {// 'floating' shop - map->addiddb(&nd->bl); - } - strdb_put(npc->name_db, nd->exname, nd); + npc->add_to_location(nd); return strchr(start,'\n');// continue } @@ -2997,22 +2975,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* nd->u.scr.trader = true; nd->u.scr.shop = NULL; ++npc_script; - - if( m >= 0 ) { - map->addnpc(m, nd); - nd->ud = &npc->base_ud; - npc->setcells(nd); - map->addblock(&nd->bl); - if( nd->class_ >= 0 ) { - status->set_viewdata(&nd->bl, nd->class_); - if( map->list[nd->bl.m].users ) - clif->spawn(&nd->bl); - } - } else { - // we skip map->addnpc, but still add it to the list of ID's - map->addiddb(&nd->bl); - } - strdb_put(npc->name_db, nd->exname, nd); + npc->add_to_location(nd); //----------------------------------------- // Loop through labels to export them as necessary @@ -3044,6 +3007,32 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* return end; } +/** + * Registers the NPC and adds it to its location (on map or floating). + * + * @param nd The NPC to register. + */ +void npc_add_to_location(struct npc_data *nd) +{ + nullpo_retv(nd); + + if (nd->bl.m > 0) { + map->addnpc(nd->bl.m, nd); + npc->setcells(nd); + map->addblock(&nd->bl); + nd->ud = &npc->base_ud; + if (nd->class_ >= 0) { + status->set_viewdata(&nd->bl, nd->class_); + if( map->list[nd->bl.m].users ) + clif->spawn(&nd->bl); + } + } else { + // we skip map->addnpc, but still add it to the list of ID's + map->addiddb(&nd->bl); + } + strdb_put(npc->name_db, nd->exname, nd); +} + /** * Duplicates a warp, shop, cashshop or script. * @@ -3094,21 +3083,7 @@ bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, } //Add the npc to its location - if (nd->bl.m >= 0) { - map->addnpc(nd->bl.m, nd); - nd->ud = &npc->base_ud; - npc->setcells(nd); - map->addblock(&nd->bl); - if (nd->class_ >= 0) { - status->set_viewdata(&nd->bl, nd->class_); - if (map->list[nd->bl.m].users) - clif->spawn(&nd->bl); - } - } else { - // we skip map->addnpc, but still add it to the list of ID's - map->addiddb(&nd->bl); - } - strdb_put(npc->name_db, nd->exname, nd); + npc->add_to_location(nd); if (nd->subtype != SCRIPT) return true; @@ -4780,6 +4755,7 @@ void npc_defaults(void) { npc->convertlabel_db = npc_convertlabel_db; npc->skip_script = npc_skip_script; npc->parse_script = npc_parse_script; + npc->add_to_location = npc_add_to_location; npc->duplicate_sub = npc_duplicate_sub; npc->parse_duplicate = npc_parse_duplicate; npc->duplicate4instance = npc_duplicate4instance; diff --git a/src/map/npc.h b/src/map/npc.h index bec17fd8d..57000f1d6 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -239,6 +239,7 @@ struct npc_interface { void (*convertlabel_db) (struct npc_label_list *label_list, const char *filepath); const char* (*skip_script) (const char *start, const char *buffer, const char *filepath, int *retval); const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval); + void (*add_to_location) (struct npc_data *nd); bool (*duplicate_sub) (struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options); const char* (*parse_duplicate) (char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval); int (*duplicate4instance) (struct npc_data *snd, int16 m); -- cgit v1.2.3-70-g09d2 From 8be9ef957862e249a3a2e4f810be2cada31a4e94 Mon Sep 17 00:00:00 2001 From: Haru Date: Tue, 3 Nov 2015 15:39:17 +0100 Subject: Split npc_duplicate_sub into separate functions based on subtypes - For plugin overriding purposes. Thanks to Andrei Karas for the idea. Signed-off-by: Haru --- src/map/npc.c | 130 ++++++++++++++++++++++++++++++++++++---------------------- src/map/npc.h | 3 ++ 2 files changed, 85 insertions(+), 48 deletions(-) diff --git a/src/map/npc.c b/src/map/npc.c index ea73c2f81..17a8b9414 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -3034,61 +3034,25 @@ void npc_add_to_location(struct npc_data *nd) } /** - * Duplicates a warp, shop, cashshop or script. - * - * @param nd An already initialized NPC data. Expects bl->m, bl->x, bl->y, - * name, exname, path, dir, class_, speed, subtype to be already - * filled. - * @param snd The source NPC to duplicate. - * @param class_ The npc view class. - * @param dir The facing direction. - * @param xs The x-span, if any. - * @param ys The y-span, if any. - * @param options The NPC options. - * @retval false if there were any issues while creating and validating the NPC. + * Duplicates a script (@see npc_duplicate_sub) */ -bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) +bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) { int i; bool retval = true; - nd->src_id = snd->bl.id; - switch (nd->subtype) { - case SCRIPT: - ++npc_script; - nd->u.scr.xs = xs; - nd->u.scr.ys = ys; - nd->u.scr.script = snd->u.scr.script; - nd->u.scr.label_list = snd->u.scr.label_list; - nd->u.scr.label_list_num = snd->u.scr.label_list_num; - nd->u.scr.shop = snd->u.scr.shop; - nd->u.scr.trader = snd->u.scr.trader; - break; - - case SHOP: - case CASHSHOP: - ++npc_shop; - nd->u.shop.shop_item = snd->u.shop.shop_item; - nd->u.shop.count = snd->u.shop.count; - break; - - case WARP: - ++npc_warp; - nd->u.warp.xs = xs; - nd->u.warp.ys = ys; - nd->u.warp.mapindex = snd->u.warp.mapindex; - nd->u.warp.x = snd->u.warp.x; - nd->u.warp.y = snd->u.warp.y; - break; - } - - //Add the npc to its location + ++npc_script; + nd->u.scr.xs = xs; + nd->u.scr.ys = ys; + nd->u.scr.script = snd->u.scr.script; + nd->u.scr.label_list = snd->u.scr.label_list; + nd->u.scr.label_list_num = snd->u.scr.label_list_num; + nd->u.scr.shop = snd->u.scr.shop; + nd->u.scr.trader = snd->u.scr.trader; + + //add the npc to its location npc->add_to_location(nd); - if (nd->subtype != SCRIPT) - return true; - - //----------------------------------------- // Loop through labels to export them as necessary for (i = 0; i < nd->u.scr.label_list_num; i++) { if (npc->event_export(nd, i)) { @@ -3116,6 +3080,73 @@ bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, return retval; } +/** + * Duplicates a shop or cash shop (@see npc_duplicate_sub) + */ +bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) +{ + ++npc_shop; + nd->u.shop.shop_item = snd->u.shop.shop_item; + nd->u.shop.count = snd->u.shop.count; + + //add the npc to its location + npc->add_to_location(nd); + + return true; +} + +/** + * Duplicates a warp (@see npc_duplicate_sub) + */ +bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) +{ + ++npc_warp; + nd->u.warp.xs = xs; + nd->u.warp.ys = ys; + nd->u.warp.mapindex = snd->u.warp.mapindex; + nd->u.warp.x = snd->u.warp.x; + nd->u.warp.y = snd->u.warp.y; + + //Add the npc to its location + npc->add_to_location(nd); + + return true; +} + +/** + * Duplicates a warp, shop, cashshop or script. + * + * @param nd An already initialized NPC data. Expects bl->m, bl->x, bl->y, + * name, exname, path, dir, class_, speed, subtype to be already + * filled. + * @param snd The source NPC to duplicate. + * @param class_ The npc view class. + * @param dir The facing direction. + * @param xs The x-span, if any. + * @param ys The y-span, if any. + * @param options The NPC options. + * @retval false if there were any issues while creating and validating the NPC. + */ +bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options) +{ + nd->src_id = snd->bl.id; + switch (nd->subtype) { + case SCRIPT: + return npc->duplicate_script_sub(nd, snd, xs, ys, options); + + case SHOP: + case CASHSHOP: + return npc->duplicate_shop_sub(nd, snd, xs, ys, options); + + case WARP: + return npc->duplicate_warp_sub(nd, snd, xs, ys, options); + + case TOMB: + return false; + } + return false; +} + /// Duplicate a warp, shop, cashshop or script. [Orcao] /// warp: ,,,%TAB%duplicate()%TAB%%TAB%, /// shop/cashshop/npc: -%TAB%duplicate()%TAB%%TAB% @@ -4756,6 +4787,9 @@ void npc_defaults(void) { npc->skip_script = npc_skip_script; npc->parse_script = npc_parse_script; npc->add_to_location = npc_add_to_location; + npc->duplicate_script_sub = npc_duplicate_script_sub; + npc->duplicate_shop_sub = npc_duplicate_shop_sub; + npc->duplicate_warp_sub = npc_duplicate_warp_sub; npc->duplicate_sub = npc_duplicate_sub; npc->parse_duplicate = npc_parse_duplicate; npc->duplicate4instance = npc_duplicate4instance; diff --git a/src/map/npc.h b/src/map/npc.h index 57000f1d6..de403fe76 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -240,6 +240,9 @@ struct npc_interface { const char* (*skip_script) (const char *start, const char *buffer, const char *filepath, int *retval); const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval); void (*add_to_location) (struct npc_data *nd); + bool (*duplicate_script_sub) (struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options); + bool (*duplicate_shop_sub) (struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options); + bool (*duplicate_warp_sub) (struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options); bool (*duplicate_sub) (struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options); const char* (*parse_duplicate) (char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval); int (*duplicate4instance) (struct npc_data *snd, int16 m); -- cgit v1.2.3-70-g09d2