Emistry icon

[RO] rA - NPC Duplicate / Remove - Script Commands

Emistry | PRO | 11/01/18 02:30:56 PM UTC | 0 ⭐ | 3473 👁️ | Never ⏰ | []
Diff |

8.64 KB

|

None

|

0 👍

/

0 👎

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

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎