View difference between Paste ID: 7pkGU0ZN and SWd3DWn1
SHOW: | | - or go back to the newest paste.
1
diff --git a/src/custom/script.inc b/src/custom/script.inc
2
index 839b990cb..624cecb8a 100644
3
--- a/src/custom/script.inc
4
+++ b/src/custom/script.inc
5
@@ -17,3 +17,227 @@
6
 //	script_pushint(st,1);
7
 //	return 0;
8
 //}
9
+
10
+/*==========================================
11
+ * Duplicate any npc on live server
12
+ * duplicatenpc "<Source NPC name>","<New NPC shown name>","<New NPC hidden name>","<mapname>",<map_x>,<map_y>,<dir>{, spriteid{, map_xs, map_ys}}};
13
+ *------------------------------------------*/
14
+BUILDIN_FUNC(duplicatenpc)
15
+{
16
+	int map_x = script_getnum(st, 6);
17
+	int map_y = script_getnum(st, 7);
18
+	int dir = script_getnum(st, 8);
19
+	int spriteid, map_xs = -1, map_ys = -1, sourceid, type, mapid, i;
20
+	const char *sourcename = script_getstr(st, 2);
21
+	const char *new_shown_name = script_getstr(st, 3);
22
+	const char *new_hidden_name = script_getstr(st, 4);
23
+	const char *mapname = script_getstr(st, 5);
24
+
25
+	char new_npc_name[24] = "";
26
+	struct npc_data *nd_source, *nd_target;
27
+
28
+	if(script_hasdata(st, 10))
29
+		map_xs = (script_getnum(st, 10) < -1) ? -1 : script_getnum(st, 10);
30
+
31
+	if(script_hasdata(st, 11))
32
+		map_ys = (script_getnum(st, 11) < -1) ? -1 : script_getnum(st, 10);
33
+
34
+	if(map_xs == -1 && map_ys != -1)
35
+		map_xs = 0;
36
+
37
+	if(map_xs != - 1 && map_ys == -1)
38
+		map_ys = 0;
39
+
40
+	if(strlen(new_shown_name) + strlen(new_hidden_name) > NAME_LENGTH) {
41
+		ShowError("buildin_duplicatenpc: New NPC shown name + New NPC hidden name is too long (max %d chars). (%s)\n", sourcename, NAME_LENGTH);
42
+		script_pushint(st, 0);
43
+		return SCRIPT_CMD_FAILURE;
44
+	}
45
+
46
+	nd_source = npc_name2id(sourcename);
47
+
48
+	if(script_hasdata(st, 9))
49
+		spriteid = (script_getnum(st, 9) < -1) ? -1 : script_getnum(st, 9);
50
+	else
51
+		spriteid = nd_source->class_;
52
+
53
+	if(nd_source == NULL) {
54
+		ShowError("buildin_duplicatenpc: original npc not found for duplicate. (%s)\n", sourcename);
55
+		script_pushint(st, 0);
56
+		return SCRIPT_CMD_FAILURE;
57
+	}
58
+	
59
+	sourceid = nd_source->bl.id;
60
+	type = nd_source->subtype;
61
+	mapid = map_mapname2mapid(mapname);
62
+
63
+	if(mapid < 0) {
64
+		ShowError("buildin_duplicatenpc: target map not found. (%s)\n", mapname);
65
+		script_pushint(st, 0);
66
+		return SCRIPT_CMD_FAILURE;
67
+	}
68
+
69
+	CREATE(nd_target, struct npc_data, 1);
70
+	
71
+	strcat(new_npc_name, new_shown_name);
72
+	strncat(new_npc_name, "#", 1);
73
+	strncat(new_npc_name, new_hidden_name, strlen(new_hidden_name));
74
+
75
+	safestrncpy(nd_target->name, new_npc_name , sizeof(nd_target->name));
76
+	safestrncpy(nd_target->exname, new_npc_name, sizeof(nd_target->exname));
77
+
78
+	nd_target->bl.prev = nd_target->bl.next = NULL;
79
+	nd_target->bl.m = mapid;
80
+	nd_target->bl.x = map_x;
81
+	nd_target->bl.y = map_y;
82
+	nd_target->bl.id = npc_get_new_npc_id();
83
+	nd_target->class_ = spriteid;
84
+	nd_target->speed = 200;
85
+	nd_target->src_id = sourceid;
86
+	nd_target->bl.type = BL_NPC;
87
+	nd_target->subtype = (enum npc_subtype)type;
88
+
89
+	switch(type) {
90
+		case NPCTYPE_SCRIPT:
91
+			nd_target->u.scr.xs = map_xs;
92
+			nd_target->u.scr.ys = map_ys;
93
+			nd_target->u.scr.script = nd_source->u.scr.script;
94
+			nd_target->u.scr.label_list = nd_source->u.scr.label_list;
95
+			nd_target->u.scr.label_list_num = nd_source->u.scr.label_list_num;
96
+			break;
97
+		case NPCTYPE_SHOP:
98
+		case NPCTYPE_CASHSHOP:
99
+		case NPCTYPE_ITEMSHOP:
100
+		case NPCTYPE_POINTSHOP:
101
+		case NPCTYPE_MARKETSHOP:
102
+			nd_target->u.shop.shop_item = nd_source->u.shop.shop_item;
103
+			nd_target->u.shop.count = nd_source->u.shop.count;
104
+			break;
105
+		case NPCTYPE_WARP:
106
+			if( !battle_config.warp_point_debug )
107
+				nd_target->class_ = JT_WARPNPC;
108
+			else
109
+				nd_target->class_ = JT_GUILD_FLAG;
110
+			nd_target->u.warp.xs = map_xs;
111
+			nd_target->u.warp.ys = map_ys;
112
+			nd_target->u.warp.mapindex = nd_source->u.warp.mapindex;
113
+			nd_target->u.warp.x = nd_source->u.warp.x;
114
+			nd_target->u.warp.y = nd_source->u.warp.y;
115
+			nd_target->trigger_on_hidden = nd_source->trigger_on_hidden;
116
+			break;
117
+	}
118
+
119
+	map_addnpc(mapid, nd_target);
120
+	status_change_init(&nd_target->bl);
121
+	unit_dataset(&nd_target->bl);
122
+	nd_target->ud.dir = dir;
123
+	npc_setcells(nd_target);
124
+	map_addblock(&nd_target->bl);
125
+
126
+	if(spriteid >= 0) {
127
+		status_set_viewdata(&nd_target->bl, nd_target->class_);
128
+		clif_spawn(&nd_target->bl);
129
+	}
130
+
131
+	strdb_put(npcname_db, nd_target->exname, nd_target);
132
+
133
+	if(type == NPCTYPE_SCRIPT) {
134
+		for (i = 0; i < nd_target->u.scr.label_list_num; i++) {
135
+			char* lname = nd_target->u.scr.label_list[i].name;
136
+			int pos = nd_target->u.scr.label_list[i].pos;
137
+
138
+			if ((lname[0] == 'O' || lname[0] == 'o') && (lname[1] == 'N' || lname[1] == 'n')) {
139
+				struct event_data* ev;
140
+				char buf[NAME_LENGTH*2+3];
141
+				snprintf(buf, ARRAYLENGTH(buf), "%s::%s", nd_target->exname, lname);
142
+
143
+				CREATE(ev, struct event_data, 1);
144
+				ev->nd = nd_target;
145
+				ev->pos = pos;
146
+				if(strdb_put(ev_db, buf, ev))
147
+					ShowWarning("npc_parse_duplicate : duplicate event %s (%s)\n", buf, nd_target->name);
148
+			}
149
+		}
150
+
151
+		for (i = 0; i < nd_target->u.scr.label_list_num; i++) {
152
+			int t = 0, k = 0;
153
+			char *lname = nd_target->u.scr.label_list[i].name;
154
+			int pos = nd_target->u.scr.label_list[i].pos;
155
+			if (sscanf(lname, "OnTimer%d%n", &t, &k) == 1 && lname[k] == '\0') {
156
+				struct npc_timerevent_list *te = nd_target->u.scr.timer_event;
157
+				int j, k = nd_target->u.scr.timeramount;
158
+				if (te == NULL)
159
+					te = (struct npc_timerevent_list *)aMalloc(sizeof(struct npc_timerevent_list));
160
+				else
161
+					te = (struct npc_timerevent_list *)aRealloc( te, sizeof(struct npc_timerevent_list) * (k+1) );
162
+				for (j = 0; j < k; j++) {
163
+					if (te[j].timer > t) {
164
+						memmove(te+j+1, te+j, sizeof(struct npc_timerevent_list)*(k-j));
165
+						break;
166
+					}
167
+				}
168
+				te[j].timer = t;
169
+				te[j].pos = pos;
170
+				nd_target->u.scr.timer_event = te;
171
+				nd_target->u.scr.timeramount++;
172
+			}
173
+		}
174
+		nd_target->u.scr.timerid = INVALID_TIMER;
175
+	}
176
+
177
+	script_pushint(st, 1);
178
+	return SCRIPT_CMD_SUCCESS;
179
+}
180
+
181
+/*==========================================
182
+ * Remove any npc duplicate on live server
183
+ * duplicateremove "<NPC name>";
184
+ *------------------------------------------*/
185
+BUILDIN_FUNC(duplicateremove)
186
+{
187
+	struct npc_data *nd;
188
+
189
+	if(script_hasdata(st, 2)) {
190
+		nd = npc_name2id(script_getstr(st, 2));
191
+		if(nd == NULL) {
192
+			script_pushint(st, -1);
193
+			return SCRIPT_CMD_FAILURE;
194
+		}
195
+	} else
196
+		nd = (struct npc_data *)map_id2bl(st->oid);
197
+
198
+	if(!nd->src_id)
199
+		npc_unload_duplicates(nd);
200
+	else
201
+		npc_unload(nd,true);
202
+
203
+	script_pushint(st, 1);
204
+	return SCRIPT_CMD_SUCCESS;
205
+}
206
+
207
diff --git a/src/custom/script_def.inc b/src/custom/script_def.inc
208
index 886399273..ed7956a7f 100644
209
--- a/src/custom/script_def.inc
210
+++ b/src/custom/script_def.inc
211
@@ -9,3 +9,6 @@
212
  **/
213
 
214
 //BUILDIN_DEF(example,""),
215
+BUILDIN_DEF(duplicatenpc, "ssssiii???"),
216
+BUILDIN_DEF(duplicateremove, "?"),
217
diff --git a/src/map/npc.cpp b/src/map/npc.cpp
218
index 558c019fe..ce9e5f039 100644
219
--- a/src/map/npc.cpp
220
+++ b/src/map/npc.cpp
221
@@ -85,13 +85,8 @@ int npc_get_new_npc_id(void) {
222
 	}
223
 }
224
 
225
-static DBMap* ev_db; // const char* event_name -> struct event_data*
226
-static DBMap* npcname_db; // const char* npc_name -> struct npc_data*
227
-
228
-struct event_data {
229
-	struct npc_data *nd;
230
-	int pos;
231
-};
232
+DBMap* ev_db; // const char* event_name -> struct event_data*
233
+DBMap* npcname_db; // const char* npc_name -> struct npc_data*
234
 
235
 static struct eri *timer_event_ers; //For the npc timer data. [Skotlex]
236
 
237
@@ -2136,7 +2131,7 @@ static int npc_unload_ev(DBKey key, DBData *data, va_list ap)
238
 
239
 //Chk if npc matches src_id, then unload.
240
 //Sub-function used to find duplicates.
241
-static int npc_unload_dup_sub(struct npc_data* nd, va_list args)
242
+int npc_unload_dup_sub(struct npc_data* nd, va_list args)
243
 {
244
 	int src_id;
245
 
246
diff --git a/src/map/npc.hpp b/src/map/npc.hpp
247
index af71f3507..c2a1817de 100644
248
--- a/src/map/npc.hpp
249
+++ b/src/map/npc.hpp
250
@@ -107,6 +107,14 @@ struct npc_data {
251
 struct eri;
252
 extern struct eri *npc_sc_display_ers;
253
 
254
+extern DBMap* ev_db; // const char* event_name -> struct event_data*
255
+extern DBMap* npcname_db; // const char* npc_name -> struct npc_data*
256
+
257
+struct event_data {
258
+	struct npc_data *nd;
259
+	int pos;
260
+};
261
+
262
 #define START_NPC_NUM 110000000
263
 
264
 enum e_job_types
265
@@ -1206,6 +1214,8 @@ int npc_instanceinit(struct npc_data* nd);
266
 int npc_instancedestroy(struct npc_data* nd);
267
 int npc_cashshop_buy(struct map_session_data *sd, unsigned short nameid, int amount, int points);
268
 
269
+int npc_unload_dup_sub(struct npc_data *nd, va_list args);
270
+
271
 void npc_shop_currency_type(struct map_session_data *sd, struct npc_data *nd, int cost[2], bool display);
272
 
273
 extern struct npc_data* fake_nd;