|
@@ -169,11 +169,21 @@ int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd)
|
|
|
{
|
|
|
char name[EVENT_NAME_LENGTH];
|
|
|
|
|
|
+ if (pc_isdead(sd)) // Dead player don't trigger 'OnTouch_'
|
|
|
+ return 0;
|
|
|
+
|
|
|
if( nd->touching_id )
|
|
|
return 0; // Attached a player already. Can't trigger on anyone else.
|
|
|
|
|
|
- if( pc_ishiding(sd) )
|
|
|
- return 1; // Can't trigger 'OnTouch_'. try 'OnTouch' later.
|
|
|
+ // pc_ishiding moved in npc_event for now.
|
|
|
+ // If OnTouch_ event exists hiding player doesn't click the npc.
|
|
|
+ // if( pc_ishiding(sd) )
|
|
|
+ // return 1; // Can't trigger 'OnTouch_'.
|
|
|
+
|
|
|
+ auto it = std::find(sd->npc_ontouch_.begin(), sd->npc_ontouch_.end(), nd->bl.id);
|
|
|
+
|
|
|
+ if (it != sd->npc_ontouch_.end())
|
|
|
+ return 0;
|
|
|
|
|
|
safesnprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_event_name);
|
|
|
return npc_event(sd,name,1);
|
|
@@ -182,8 +192,9 @@ int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd)
|
|
|
int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd)
|
|
|
{
|
|
|
char name[EVENT_NAME_LENGTH];
|
|
|
+ auto it = std::find(sd->areanpc.begin(), sd->areanpc.end(), nd->bl.id);
|
|
|
|
|
|
- if( sd->areanpc_id == nd->bl.id )
|
|
|
+ if (it != sd->areanpc.end())
|
|
|
return 0;
|
|
|
|
|
|
safesnprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch2_event_name);
|
|
@@ -206,6 +217,7 @@ int npc_enable_sub(struct block_list *bl, va_list ap)
|
|
|
if (nd->sc.option&OPTION_INVISIBLE)
|
|
|
return 1;
|
|
|
|
|
|
+ // note : disablenpc doesn't reset the previous trigger status on official
|
|
|
if( npc_ontouch_event(sd,nd) > 0 && npc_ontouch2_event(sd,nd) > 0 )
|
|
|
{ // failed to run OnTouch event, so just click the npc
|
|
|
if (sd->npc_id != 0)
|
|
@@ -252,7 +264,7 @@ int npc_enable(const char* name, int flag)
|
|
|
} else
|
|
|
clif_changeoption(&nd->bl);
|
|
|
|
|
|
- if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) ) //check if player standing on a OnTouchArea
|
|
|
+ if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) )// check if player standing on a OnTouchArea
|
|
|
map_foreachinallarea( npc_enable_sub, nd->bl.m, nd->bl.x-nd->u.scr.xs, nd->bl.y-nd->u.scr.ys, nd->bl.x+nd->u.scr.xs, nd->bl.y+nd->u.scr.ys, BL_PC, nd );
|
|
|
|
|
|
return 0;
|
|
@@ -898,18 +910,25 @@ int npc_event(struct map_session_data* sd, const char* eventname, int ontouch)
|
|
|
return ontouch;
|
|
|
}
|
|
|
|
|
|
- switch(ontouch)
|
|
|
- {
|
|
|
- case 1:
|
|
|
+ if (ontouch == 1) { // OnTouch_
|
|
|
+ if (pc_ishiding(sd))
|
|
|
+ return 0;
|
|
|
+
|
|
|
nd->touching_id = sd->bl.id;
|
|
|
- sd->touching_id = nd->bl.id;
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- sd->areanpc_id = nd->bl.id;
|
|
|
- break;
|
|
|
+
|
|
|
+ auto it = std::find(sd->npc_ontouch_.begin(), sd->npc_ontouch_.end(), nd->bl.id);
|
|
|
+
|
|
|
+ if (it == sd->npc_ontouch_.end())
|
|
|
+ sd->npc_ontouch_.push_back(nd->bl.id);
|
|
|
+ } else if (ontouch == 2) { // OnTouch
|
|
|
+ auto it = std::find(sd->areanpc.begin(), sd->areanpc.end(), nd->bl.id);
|
|
|
+
|
|
|
+ if (it == sd->areanpc.end())
|
|
|
+ sd->areanpc.push_back(nd->bl.id);
|
|
|
}
|
|
|
|
|
|
- return npc_event_sub(sd,ev,eventname);
|
|
|
+ npc_event_sub(sd,ev,eventname); // Don't return this value so npc_enable_sub doesn't attempt to "click" the NPC if OnTouch fails.
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/*==========================================
|
|
@@ -931,6 +950,8 @@ int npc_touch_areanpc_sub(struct block_list *bl, va_list ap)
|
|
|
return 0;
|
|
|
if( pc_ishiding(sd) )
|
|
|
return 0;
|
|
|
+ if( pc_isdead(sd) )
|
|
|
+ return 0;
|
|
|
if( pc_id == sd->bl.id )
|
|
|
return 0;
|
|
|
|
|
@@ -945,27 +966,40 @@ int npc_touch_areanpc_sub(struct block_list *bl, va_list ap)
|
|
|
*------------------------------------------*/
|
|
|
int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap)
|
|
|
{
|
|
|
- struct npc_data *nd = map_id2nd(sd->touching_id);
|
|
|
- short xs, ys;
|
|
|
+ if (sd->npc_ontouch_.empty())
|
|
|
+ return 0;
|
|
|
|
|
|
- if( !nd || nd->touching_id != sd->bl.id )
|
|
|
- return 1;
|
|
|
+ bool found = false;
|
|
|
|
|
|
- xs = nd->u.scr.xs;
|
|
|
- ys = nd->u.scr.ys;
|
|
|
+ sd->npc_ontouch_.erase(std::remove_if(sd->npc_ontouch_.begin(), sd->npc_ontouch_.end(), [&] (const int ¤t_npc_id) {
|
|
|
+ struct npc_data *nd = map_id2nd(current_npc_id);
|
|
|
|
|
|
- if( sd->bl.m != nd->bl.m ||
|
|
|
- sd->bl.x < nd->bl.x - xs || sd->bl.x > nd->bl.x + xs ||
|
|
|
- sd->bl.y < nd->bl.y - ys || sd->bl.y > nd->bl.y + ys ||
|
|
|
- pc_ishiding(sd) || leavemap )
|
|
|
- {
|
|
|
- char name[EVENT_NAME_LENGTH];
|
|
|
+ if (!nd) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ int16 xs = nd->u.scr.xs;
|
|
|
+ int16 ys = nd->u.scr.ys;
|
|
|
+
|
|
|
+ // note : hiding doesn't reset the previous trigger status
|
|
|
+ // player must leave the area to reset nd->touching_id on official
|
|
|
+ if (sd->bl.m != nd->bl.m || sd->bl.x < nd->bl.x - xs || sd->bl.x > nd->bl.x + xs || sd->bl.y < nd->bl.y - ys || sd->bl.y > nd->bl.y + ys || leavemap) {
|
|
|
+ char name[EVENT_NAME_LENGTH];
|
|
|
+
|
|
|
+ if (nd->touching_id && nd->touching_id == sd->bl.id) {// empty when reload script
|
|
|
+ found = true;
|
|
|
+ nd->touching_id = 0;
|
|
|
+ safesnprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_event_name);
|
|
|
+ map_forcountinarea(npc_touch_areanpc_sub,nd->bl.m,nd->bl.x - xs,nd->bl.y - ys,nd->bl.x + xs,nd->bl.y + ys,1,BL_PC,sd->bl.id,name);
|
|
|
+ }
|
|
|
|
|
|
- nd->touching_id = sd->touching_id = 0;
|
|
|
- safesnprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_event_name);
|
|
|
- map_forcountinarea(npc_touch_areanpc_sub,nd->bl.m,nd->bl.x - xs,nd->bl.y - ys,nd->bl.x + xs,nd->bl.y + ys,1,BL_PC,sd->bl.id,name);
|
|
|
- }
|
|
|
- return 0;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }), sd->npc_ontouch_.end());
|
|
|
+
|
|
|
+ return found;
|
|
|
}
|
|
|
|
|
|
/*==========================================
|
|
@@ -973,97 +1007,81 @@ int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap)
|
|
|
*------------------------------------------*/
|
|
|
int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
|
|
|
{
|
|
|
- int xs,ys;
|
|
|
- int f = 1;
|
|
|
- int i;
|
|
|
- int j, found_warp = 0;
|
|
|
+ int xs, ys, i, f = 1;
|
|
|
|
|
|
nullpo_retr(1, sd);
|
|
|
|
|
|
- // Why not enqueue it? [Inkfish]
|
|
|
- //if(sd->npc_id)
|
|
|
- // return 1;
|
|
|
+ // Remove NPCs that are no longer within the OnTouch area
|
|
|
+ for (i = 0; i < sd->areanpc.size(); i++) {
|
|
|
+ struct npc_data *nd = map_id2nd(sd->areanpc[i]);
|
|
|
+
|
|
|
+ if (!nd || nd->subtype != NPCTYPE_SCRIPT ||
|
|
|
+ !(x >= nd->bl.x - nd->u.scr.xs && x <= nd->bl.x + nd->u.scr.xs && y >= nd->bl.y - nd->u.scr.ys && y <= nd->bl.y + nd->u.scr.ys))
|
|
|
+ sd->areanpc.erase(sd->areanpc.begin() + i);
|
|
|
+ }
|
|
|
|
|
|
if (sd->state.block_action & PCBLOCK_NPCCLICK)
|
|
|
return 0;
|
|
|
|
|
|
struct map_data *mapdata = map_getmapdata(m);
|
|
|
|
|
|
- for(i=0;i<mapdata->npc_num;i++)
|
|
|
- {
|
|
|
+ for (i = 0; i < mapdata->npc_num_area; i++) {
|
|
|
if (mapdata->npc[i]->sc.option&OPTION_INVISIBLE) {
|
|
|
- f=0; // a npc was found, but it is disabled; don't print warning
|
|
|
+ f = 0; // a npc was found, but it is disabled; don't print warning
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
switch(mapdata->npc[i]->subtype) {
|
|
|
case NPCTYPE_WARP:
|
|
|
- xs=mapdata->npc[i]->u.warp.xs;
|
|
|
- ys=mapdata->npc[i]->u.warp.ys;
|
|
|
+ xs = mapdata->npc[i]->u.warp.xs;
|
|
|
+ ys = mapdata->npc[i]->u.warp.ys;
|
|
|
break;
|
|
|
case NPCTYPE_SCRIPT:
|
|
|
- xs=mapdata->npc[i]->u.scr.xs;
|
|
|
- ys=mapdata->npc[i]->u.scr.ys;
|
|
|
+ xs = mapdata->npc[i]->u.scr.xs;
|
|
|
+ ys = mapdata->npc[i]->u.scr.ys;
|
|
|
break;
|
|
|
default:
|
|
|
continue;
|
|
|
}
|
|
|
- if( x >= mapdata->npc[i]->bl.x-xs && x <= mapdata->npc[i]->bl.x+xs
|
|
|
- && y >= mapdata->npc[i]->bl.y-ys && y <= mapdata->npc[i]->bl.y+ys )
|
|
|
- break;
|
|
|
- }
|
|
|
- if( i == mapdata->npc_num )
|
|
|
- {
|
|
|
- if( f == 1 ) // no npc found
|
|
|
- ShowError("npc_touch_areanpc : stray NPC cell/NPC not found in the block on coordinates '%s',%d,%d\n", mapdata->name, x, y);
|
|
|
- return 1;
|
|
|
- }
|
|
|
- switch(mapdata->npc[i]->subtype) {
|
|
|
- case NPCTYPE_WARP:
|
|
|
- if ((!mapdata->npc[i]->trigger_on_hidden && (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]))) || pc_isdead(sd))
|
|
|
- break; // hidden or dead chars cannot use warps
|
|
|
- if (!pc_job_can_entermap((enum e_job)sd->status.class_, map_mapindex2mapid(mapdata->npc[i]->u.warp.mapindex), sd->group_level))
|
|
|
- break;
|
|
|
- if(sd->count_rewarp > 10){
|
|
|
- ShowWarning("Prevented infinite warp loop for player (%d:%d). Please fix NPC: '%s', path: '%s'\n", sd->status.account_id, sd->status.char_id, mapdata->npc[i]->exname, mapdata->npc[i]->path);
|
|
|
- sd->count_rewarp=0;
|
|
|
- break;
|
|
|
- }
|
|
|
- pc_setpos(sd,mapdata->npc[i]->u.warp.mapindex,mapdata->npc[i]->u.warp.x,mapdata->npc[i]->u.warp.y,CLR_OUTSIGHT);
|
|
|
- break;
|
|
|
- case NPCTYPE_SCRIPT:
|
|
|
- for (j = i; j < mapdata->npc_num; j++) {
|
|
|
- if (mapdata->npc[j]->subtype != NPCTYPE_WARP) {
|
|
|
- continue;
|
|
|
- }
|
|
|
|
|
|
- if ((sd->bl.x >= (mapdata->npc[j]->bl.x - mapdata->npc[j]->u.warp.xs) && sd->bl.x <= (mapdata->npc[j]->bl.x + mapdata->npc[j]->u.warp.xs)) &&
|
|
|
- (sd->bl.y >= (mapdata->npc[j]->bl.y - mapdata->npc[j]->u.warp.ys) && sd->bl.y <= (mapdata->npc[j]->bl.y + mapdata->npc[j]->u.warp.ys))) {
|
|
|
- if ((!mapdata->npc[i]->trigger_on_hidden && (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]))) || pc_isdead(sd))
|
|
|
- break; // hidden or dead chars cannot use warps
|
|
|
- pc_setpos(sd,mapdata->npc[j]->u.warp.mapindex,mapdata->npc[j]->u.warp.x,mapdata->npc[j]->u.warp.y,CLR_OUTSIGHT);
|
|
|
- found_warp = 1;
|
|
|
+ if (x >= mapdata->npc[i]->bl.x - xs && x <= mapdata->npc[i]->bl.x + xs && y >= mapdata->npc[i]->bl.y - ys && y <= mapdata->npc[i]->bl.y + ys) {
|
|
|
+ f = 0;
|
|
|
+
|
|
|
+ switch (mapdata->npc[i]->subtype) {
|
|
|
+ case NPCTYPE_WARP:
|
|
|
+ if ((!mapdata->npc[i]->trigger_on_hidden && (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]))) || pc_isdead(sd))
|
|
|
+ break; // hidden or dead chars cannot use warps
|
|
|
+ if (!pc_job_can_entermap((enum e_job)sd->status.class_, map_mapindex2mapid(mapdata->npc[i]->u.warp.mapindex), sd->group_level))
|
|
|
+ break;
|
|
|
+ if (sd->count_rewarp > 10) {
|
|
|
+ ShowWarning("Prevented infinite warp loop for player (%d:%d). Please fix NPC: '%s', path: '%s'\n", sd->status.account_id, sd->status.char_id, mapdata->npc[i]->exname, mapdata->npc[i]->path);
|
|
|
+ sd->count_rewarp = 0;
|
|
|
break;
|
|
|
}
|
|
|
- }
|
|
|
+ pc_setpos(sd, mapdata->npc[i]->u.warp.mapindex, mapdata->npc[i]->u.warp.x, mapdata->npc[i]->u.warp.y, CLR_OUTSIGHT);
|
|
|
+ return 0;
|
|
|
+ case NPCTYPE_SCRIPT:
|
|
|
+ // warp type sorted first, no need to check if they override any other OnTouch areas.
|
|
|
|
|
|
- if (found_warp > 0) {
|
|
|
- break;
|
|
|
- }
|
|
|
+ if (npc_ontouch_event(sd, mapdata->npc[i]) > 0 && npc_ontouch2_event(sd, mapdata->npc[i]) > 0) { // failed to run OnTouch event, so just click the npc
|
|
|
+ auto it = std::find(sd->areanpc.begin(), sd->areanpc.end(), mapdata->npc[i]->bl.id);
|
|
|
+
|
|
|
+ if (it == sd->areanpc.end())
|
|
|
+ sd->areanpc.push_back(mapdata->npc[i]->bl.id);
|
|
|
|
|
|
- if( npc_ontouch_event(sd,mapdata->npc[i]) > 0 && npc_ontouch2_event(sd,mapdata->npc[i]) > 0 )
|
|
|
- { // failed to run OnTouch event, so just click the npc
|
|
|
- struct unit_data *ud = unit_bl2ud(&sd->bl);
|
|
|
- if( ud && ud->walkpath.path_pos < ud->walkpath.path_len )
|
|
|
- { // Since walktimer always == INVALID_TIMER at this time, we stop walking manually. [Inkfish]
|
|
|
- clif_fixpos(&sd->bl);
|
|
|
- ud->walkpath.path_pos = ud->walkpath.path_len;
|
|
|
+ npc_click(sd, mapdata->npc[i]);
|
|
|
}
|
|
|
- sd->areanpc_id = mapdata->npc[i]->bl.id;
|
|
|
- npc_click(sd,mapdata->npc[i]);
|
|
|
+
|
|
|
+ break;
|
|
|
}
|
|
|
- break;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ if (f == 1) {
|
|
|
+ ShowError("npc_touch_areanpc : stray NPC cell/NPC not found in the block on coordinates '%s',%d,%d\n", mapdata->name, x, y);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1077,7 +1095,7 @@ int npc_touch_areanpc2(struct mob_data *md)
|
|
|
int xs, ys;
|
|
|
struct map_data *mapdata = map_getmapdata(md->bl.m);
|
|
|
|
|
|
- for( i = 0; i < mapdata->npc_num; i++ )
|
|
|
+ for( i = 0; i < mapdata->npc_num_area; i++ )
|
|
|
{
|
|
|
if( mapdata->npc[i]->sc.option&OPTION_INVISIBLE )
|
|
|
continue;
|
|
@@ -1166,7 +1184,7 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range)
|
|
|
if (!i) return 0; //No NPC_CELLs.
|
|
|
|
|
|
//Now check for the actual NPC on said range.
|
|
|
- for(i=0;i<mapdata->npc_num;i++)
|
|
|
+ for (i = 0; i < mapdata->npc_num_area; i++)
|
|
|
{
|
|
|
if (mapdata->npc[i]->sc.option&OPTION_INVISIBLE)
|
|
|
continue;
|
|
@@ -1193,7 +1211,7 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range)
|
|
|
&& y1 >= mapdata->npc[i]->bl.y-ys && y0 <= mapdata->npc[i]->bl.y+ys )
|
|
|
break; // found a npc
|
|
|
}
|
|
|
- if (i==mapdata->npc_num)
|
|
|
+ if (i == mapdata->npc_num_area)
|
|
|
return 0;
|
|
|
|
|
|
return (mapdata->npc[i]->bl.id);
|
|
@@ -2164,8 +2182,21 @@ int npc_remove_map(struct npc_data* nd)
|
|
|
if( i == mapdata->npc_num ) return 2; //failed to find it?
|
|
|
|
|
|
mapdata->npc_num--;
|
|
|
- mapdata->npc[i] = mapdata->npc[mapdata->npc_num];
|
|
|
- mapdata->npc[mapdata->npc_num] = NULL;
|
|
|
+ if (i >= mapdata->npc_num_area)
|
|
|
+ mapdata->npc[i] = mapdata->npc[ mapdata->npc_num ];
|
|
|
+ else if (i >= mapdata->npc_num_warp) {
|
|
|
+ mapdata->npc_num_area--;
|
|
|
+ mapdata->npc[i] = mapdata->npc[ mapdata->npc_num_area ];
|
|
|
+ mapdata->npc[ mapdata->npc_num_area ] = mapdata->npc[ mapdata->npc_num ];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ mapdata->npc_num_warp--;
|
|
|
+ mapdata->npc_num_area--;
|
|
|
+ mapdata->npc[i] = mapdata->npc[ mapdata->npc_num_warp ];
|
|
|
+ mapdata->npc[ mapdata->npc_num_warp ] = mapdata->npc[ mapdata->npc_num_area ];
|
|
|
+ mapdata->npc[ mapdata->npc_num_area ] = mapdata->npc[ mapdata->npc_num ];
|
|
|
+ }
|
|
|
+ mapdata->npc[ mapdata->npc_num ] = NULL;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -2570,7 +2601,6 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
|
|
|
struct npc_data *nd;
|
|
|
|
|
|
nd = npc_create_npc(from_mapid, from_x, from_y);
|
|
|
- map_addnpc(from_mapid, nd);
|
|
|
|
|
|
safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname));
|
|
|
if (npc_name2id(nd->exname) != NULL)
|
|
@@ -2597,6 +2627,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
|
|
|
nd->bl.type = BL_NPC;
|
|
|
nd->subtype = NPCTYPE_WARP;
|
|
|
nd->trigger_on_hidden = false;
|
|
|
+ map_addnpc(from_mapid, nd);
|
|
|
npc_setcells(nd);
|
|
|
if(map_addblock(&nd->bl))
|
|
|
return NULL;
|
|
@@ -2654,7 +2685,6 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
|
|
|
}
|
|
|
|
|
|
nd = npc_create_npc(m, x, y);
|
|
|
- map_addnpc(m, nd);
|
|
|
npc_parsename(nd, w3, start, buffer, filepath);
|
|
|
|
|
|
if (!battle_config.warp_point_debug)
|
|
@@ -2675,6 +2705,7 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
|
|
|
nd->trigger_on_hidden = true;
|
|
|
else
|
|
|
nd->trigger_on_hidden = false;
|
|
|
+ map_addnpc(m, nd);
|
|
|
npc_setcells(nd);
|
|
|
if(map_addblock(&nd->bl)) //couldn't add on map
|
|
|
return strchr(start,'\n');
|
|
@@ -3376,7 +3407,6 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
|
|
|
}
|
|
|
|
|
|
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_ = JT_WARPNPC;
|
|
@@ -3390,6 +3420,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
|
|
|
wnd->subtype = NPCTYPE_WARP;
|
|
|
wnd->trigger_on_hidden = snd->trigger_on_hidden;
|
|
|
wnd->src_id = snd->src_id ? snd->src_id : snd->bl.id;
|
|
|
+ map_addnpc(m, wnd);
|
|
|
npc_setcells(wnd);
|
|
|
if(map_addblock(&wnd->bl))
|
|
|
return 1;
|