diff --git a/src/custom/script.inc b/src/custom/script.inc
index 839b990cb..624cecb8a 100644
--- a/src/custom/script.inc
+++ b/src/custom/script.inc
@@ -17,3 +17,227 @@
// script_pushint(st,1);
// return 0;
//}
+
+/*==========================================
+ * Duplicate any npc on live server
+ * duplicatenpc "<Source NPC name>","<New NPC shown name>","<New NPC hidden name>","<mapname>",<map_x>,<map_y>,<dir>{, spriteid{, map_xs, map_ys}}};
+ *------------------------------------------*/
+BUILDIN_FUNC(duplicatenpc)
+{
+ int map_x = script_getnum(st, 6);
+ int map_y = script_getnum(st, 7);
+ int dir = script_getnum(st, 8);
+ int spriteid, map_xs = -1, map_ys = -1, sourceid, type, mapid, i;
+ const char *sourcename = script_getstr(st, 2);
+ const char *new_shown_name = script_getstr(st, 3);
+ const char *new_hidden_name = script_getstr(st, 4);
+ const char *mapname = script_getstr(st, 5);
+
+ char new_npc_name[24] = "";
+ struct npc_data *nd_source, *nd_target;
+
+ if(script_hasdata(st, 10))
+ map_xs = (script_getnum(st, 10) < -1) ? -1 : script_getnum(st, 10);
+
+ if(script_hasdata(st, 11))
+ map_ys = (script_getnum(st, 11) < -1) ? -1 : script_getnum(st, 10);
+
+ if(map_xs == -1 && map_ys != -1)
+ map_xs = 0;
+
+ if(map_xs != - 1 && map_ys == -1)
+ map_ys = 0;
+
+ if(strlen(new_shown_name) + strlen(new_hidden_name) > NAME_LENGTH) {
+ ShowError("buildin_duplicatenpc: New NPC shown name + New NPC hidden name is too long (max %d chars). (%s)\n", sourcename, NAME_LENGTH);
+ script_pushint(st, 0);
+ return SCRIPT_CMD_FAILURE;
+ }
+
+ nd_source = npc_name2id(sourcename);
+
+ if(script_hasdata(st, 9))
+ spriteid = (script_getnum(st, 9) < -1) ? -1 : script_getnum(st, 9);
+ else
+ spriteid = nd_source->class_;
+
+ if(nd_source == NULL) {
+ ShowError("buildin_duplicatenpc: original npc not found for duplicate. (%s)\n", sourcename);
+ script_pushint(st, 0);
+ return SCRIPT_CMD_FAILURE;
+ }
+
+ sourceid = nd_source->bl.id;
+ type = nd_source->subtype;
+ mapid = map_mapname2mapid(mapname);
+
+ if(mapid < 0) {
+ ShowError("buildin_duplicatenpc: target map not found. (%s)\n", mapname);
+ script_pushint(st, 0);
+ return SCRIPT_CMD_FAILURE;
+ }
+
+ CREATE(nd_target, struct npc_data, 1);
+
+ strcat(new_npc_name, new_shown_name);
+ strncat(new_npc_name, "#", 1);
+ strncat(new_npc_name, new_hidden_name, strlen(new_hidden_name));
+
+ safestrncpy(nd_target->name, new_npc_name , sizeof(nd_target->name));
+ safestrncpy(nd_target->exname, new_npc_name, sizeof(nd_target->exname));
+
+ nd_target->bl.prev = nd_target->bl.next = NULL;
+ nd_target->bl.m = mapid;
+ nd_target->bl.x = map_x;
+ nd_target->bl.y = map_y;
+ nd_target->bl.id = npc_get_new_npc_id();
+ nd_target->class_ = spriteid;
+ nd_target->speed = 200;
+ nd_target->src_id = sourceid;
+ nd_target->bl.type = BL_NPC;
+ nd_target->subtype = (enum npc_subtype)type;
+
+ switch(type) {
+ case NPCTYPE_SCRIPT:
+ nd_target->u.scr.xs = map_xs;
+ nd_target->u.scr.ys = map_ys;
+ nd_target->u.scr.script = nd_source->u.scr.script;
+ nd_target->u.scr.label_list = nd_source->u.scr.label_list;
+ nd_target->u.scr.label_list_num = nd_source->u.scr.label_list_num;
+ break;
+ case NPCTYPE_SHOP:
+ case NPCTYPE_CASHSHOP:
+ case NPCTYPE_ITEMSHOP:
+ case NPCTYPE_POINTSHOP:
+ case NPCTYPE_MARKETSHOP:
+ nd_target->u.shop.shop_item = nd_source->u.shop.shop_item;
+ nd_target->u.shop.count = nd_source->u.shop.count;
+ break;
+ case NPCTYPE_WARP:
+ if( !battle_config.warp_point_debug )
+ nd_target->class_ = JT_WARPNPC;
+ else
+ nd_target->class_ = JT_GUILD_FLAG;
+ nd_target->u.warp.xs = map_xs;
+ nd_target->u.warp.ys = map_ys;
+ nd_target->u.warp.mapindex = nd_source->u.warp.mapindex;
+ nd_target->u.warp.x = nd_source->u.warp.x;
+ nd_target->u.warp.y = nd_source->u.warp.y;
+ nd_target->trigger_on_hidden = nd_source->trigger_on_hidden;
+ break;
+ }
+
+ map_addnpc(mapid, nd_target);
+ status_change_init(&nd_target->bl);
+ unit_dataset(&nd_target->bl);
+ nd_target->ud.dir = dir;
+ npc_setcells(nd_target);
+ map_addblock(&nd_target->bl);
+
+ if(spriteid >= 0) {
+ status_set_viewdata(&nd_target->bl, nd_target->class_);
+ clif_spawn(&nd_target->bl);
+ }
+
+ strdb_put(npcname_db, nd_target->exname, nd_target);
+
+ if(type == NPCTYPE_SCRIPT) {
+ for (i = 0; i < nd_target->u.scr.label_list_num; i++) {
+ char* lname = nd_target->u.scr.label_list[i].name;
+ int pos = nd_target->u.scr.label_list[i].pos;
+
+ if ((lname[0] == 'O' || lname[0] == 'o') && (lname[1] == 'N' || lname[1] == 'n')) {
+ struct event_data* ev;
+ char buf[NAME_LENGTH*2+3];
+ snprintf(buf, ARRAYLENGTH(buf), "%s::%s", nd_target->exname, lname);
+
+ CREATE(ev, struct event_data, 1);
+ ev->nd = nd_target;
+ ev->pos = pos;
+ if(strdb_put(ev_db, buf, ev))
+ ShowWarning("npc_parse_duplicate : duplicate event %s (%s)\n", buf, nd_target->name);
+ }
+ }
+
+ for (i = 0; i < nd_target->u.scr.label_list_num; i++) {
+ int t = 0, k = 0;
+ char *lname = nd_target->u.scr.label_list[i].name;
+ int pos = nd_target->u.scr.label_list[i].pos;
+ if (sscanf(lname, "OnTimer%d%n", &t, &k) == 1 && lname[k] == '\0') {
+ struct npc_timerevent_list *te = nd_target->u.scr.timer_event;
+ int j, k = nd_target->u.scr.timeramount;
+ if (te == NULL)
+ te = (struct npc_timerevent_list *)aMalloc(sizeof(struct npc_timerevent_list));
+ else
+ te = (struct npc_timerevent_list *)aRealloc( te, sizeof(struct npc_timerevent_list) * (k+1) );
+ for (j = 0; j < k; j++) {
+ if (te[j].timer > t) {
+ memmove(te+j+1, te+j, sizeof(struct npc_timerevent_list)*(k-j));
+ break;
+ }
+ }
+ te[j].timer = t;
+ te[j].pos = pos;
+ nd_target->u.scr.timer_event = te;
+ nd_target->u.scr.timeramount++;
+ }
+ }
+ nd_target->u.scr.timerid = INVALID_TIMER;
+ }
+
+ script_pushint(st, 1);
+ return SCRIPT_CMD_SUCCESS;
+}
+
+/*==========================================
+ * Remove any npc duplicate on live server
+ * duplicateremove "<NPC name>";
+ *------------------------------------------*/
+BUILDIN_FUNC(duplicateremove)
+{
+ struct npc_data *nd;
+
+ if(script_hasdata(st, 2)) {
+ nd = npc_name2id(script_getstr(st, 2));
+ if(nd == NULL) {
+ script_pushint(st, -1);
+ return SCRIPT_CMD_FAILURE;
+ }
+ } else
+ nd = (struct npc_data *)map_id2bl(st->oid);
+
+ if(!nd->src_id)
+ npc_unload_duplicates(nd);
+ else
+ npc_unload(nd,true);
+
+ script_pushint(st, 1);
+ return SCRIPT_CMD_SUCCESS;
+}
+
diff --git a/src/custom/script_def.inc b/src/custom/script_def.inc
index 886399273..ed7956a7f 100644
--- a/src/custom/script_def.inc
+++ b/src/custom/script_def.inc
@@ -9,3 +9,6 @@
**/
//BUILDIN_DEF(example,""),
+BUILDIN_DEF(duplicatenpc, "ssssiii???"),
+BUILDIN_DEF(duplicateremove, "?"),
diff --git a/src/map/npc.cpp b/src/map/npc.cpp
index 558c019fe..ce9e5f039 100644
--- a/src/map/npc.cpp
+++ b/src/map/npc.cpp
@@ -85,13 +85,8 @@ int npc_get_new_npc_id(void) {
}
}
-static DBMap* ev_db; // const char* event_name -> struct event_data*
-static DBMap* npcname_db; // const char* npc_name -> struct npc_data*
-
-struct event_data {
- struct npc_data *nd;
- int pos;
-};
+DBMap* ev_db; // const char* event_name -> struct event_data*
+DBMap* npcname_db; // const char* npc_name -> struct npc_data*
static struct eri *timer_event_ers; //For the npc timer data. [Skotlex]
@@ -2136,7 +2131,7 @@ static int npc_unload_ev(DBKey key, DBData *data, va_list ap)
//Chk if npc matches src_id, then unload.
//Sub-function used to find duplicates.
-static int npc_unload_dup_sub(struct npc_data* nd, va_list args)
+int npc_unload_dup_sub(struct npc_data* nd, va_list args)
{
int src_id;
diff --git a/src/map/npc.hpp b/src/map/npc.hpp
index af71f3507..c2a1817de 100644
--- a/src/map/npc.hpp
+++ b/src/map/npc.hpp
@@ -107,6 +107,14 @@ struct npc_data {
struct eri;
extern struct eri *npc_sc_display_ers;
+extern DBMap* ev_db; // const char* event_name -> struct event_data*
+extern DBMap* npcname_db; // const char* npc_name -> struct npc_data*
+
+struct event_data {
+ struct npc_data *nd;
+ int pos;
+};
+
#define START_NPC_NUM 110000000
enum e_job_types
@@ -1206,6 +1214,8 @@ int npc_instanceinit(struct npc_data* nd);
int npc_instancedestroy(struct npc_data* nd);
int npc_cashshop_buy(struct map_session_data *sd, unsigned short nameid, int amount, int points);
+int npc_unload_dup_sub(struct npc_data *nd, va_list args);
+
void npc_shop_currency_type(struct map_session_data *sd, struct npc_data *nd, int cost[2], bool display);
extern struct npc_data* fake_nd;
Comments
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎