[Suggestion] Implement cloakonnpc/cloakoffnpc (#4688)
* The player can interact with a NPC cloaked by cloakonnpc command (click, mob event..) but the NPC trigger area is disabled (= the OnTouch* part is disabled). * The changes last until the player leaves the map, logs out, or the npc option is updated by disablenpc/enablenpc/hideonnpc/hideoffnpc/cloakonnpc/cloakoffnpc commands. Thanks to @aleos89
This commit is contained in:
parent
e2de896414
commit
de80c5aab6
@ -6493,6 +6493,28 @@ while hidden then revealing.... you can wonder around =P
|
||||
|
||||
This command will fully unload a NPC object and all of it's duplicates.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*cloakonnpc "<NPC object name>"{,<character ID>};
|
||||
*cloakoffnpc "<NPC object name>"{,<character ID>};
|
||||
|
||||
These commands will make the NPC object specified display as cloaked/uncloaked,
|
||||
even though not actually disabled.
|
||||
The player can interact with a NPC cloaked (via NPC click, monster event..)
|
||||
but the NPC trigger area is disabled.
|
||||
|
||||
If <character ID> is given then the NPC will only display to the specified
|
||||
player until he/she leaves the map, logs out, or the npc option is changed.
|
||||
If no <character ID> is specified it will display to the area.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*isnpccloaked "<NPC object name>"{,<character ID>};
|
||||
|
||||
Returns true if the NPC has been cloaked to the attached player or given
|
||||
<character ID>, false otherwise. This works in association with cloakonnpc
|
||||
when it is targetting a specific character.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*doevent "<NPC object name>::<event label>";
|
||||
|
110
src/map/clif.cpp
110
src/map/clif.cpp
@ -980,7 +980,7 @@ static int clif_setlevel(struct block_list* bl) {
|
||||
/*==========================================
|
||||
* Prepares 'unit standing/spawning' packet
|
||||
*------------------------------------------*/
|
||||
static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn)
|
||||
static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn, bool option, unsigned int option_val)
|
||||
{
|
||||
struct map_session_data* sd;
|
||||
struct status_change* sc = status_get_sc(bl);
|
||||
@ -996,6 +996,9 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
|
||||
#endif
|
||||
sd = BL_CAST(BL_PC, bl);
|
||||
|
||||
if (!option)
|
||||
option_val = ((sc) ? sc->option : 0);
|
||||
|
||||
#if PACKETVER < 20091103
|
||||
if(type)
|
||||
WBUFW(buf,0) = spawn ? 0x7c : 0x78;
|
||||
@ -1053,7 +1056,7 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
|
||||
WBUFW(buf,10) = (sc)? sc->opt2 : 0;
|
||||
#if PACKETVER < 20091103
|
||||
if (type&&spawn) { //uses an older and different packet structure
|
||||
WBUFW(buf,12) = (sc)? sc->option : 0;
|
||||
WBUFW(buf,12) = option_val;
|
||||
WBUFW(buf,14) = vd->hair_style;
|
||||
WBUFW(buf,16) = vd->weapon;
|
||||
WBUFW(buf,18) = vd->head_bottom;
|
||||
@ -1062,18 +1065,18 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool
|
||||
} else {
|
||||
#endif
|
||||
#if PACKETVER >= 20091103
|
||||
WBUFL(buf,12) = (sc)? sc->option : 0;
|
||||
WBUFL(buf,12) = option_val;
|
||||
offset+=2;
|
||||
buf = WBUFP(buffer,offset);
|
||||
#elif PACKETVER >= 7
|
||||
if (!type) {
|
||||
WBUFL(buf,12) = (sc)? sc->option : 0;
|
||||
WBUFL(buf,12) = option_val;
|
||||
offset+=2;
|
||||
buf = WBUFP(buffer,offset);
|
||||
} else
|
||||
WBUFW(buf,12) = (sc)? sc->option : 0;
|
||||
WBUFW(buf,12) = option_val;
|
||||
#else
|
||||
WBUFW(buf,12) = (sc)? sc->option : 0;
|
||||
WBUFW(buf,12) = option_val;
|
||||
#endif
|
||||
WBUFW(buf,14) = vd->class_;
|
||||
WBUFW(buf,16) = vd->hair_style;
|
||||
@ -1455,7 +1458,7 @@ int clif_spawn(struct block_list *bl)
|
||||
if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE))
|
||||
return 0;
|
||||
|
||||
len = clif_set_unit_idle(bl, buf, (bl->type == BL_NPC && vd->dead_sit ? false : true));
|
||||
len = clif_set_unit_idle(bl, buf, (bl->type == BL_NPC && vd->dead_sit ? false : true), false, 0);
|
||||
clif_send(buf, len, bl, AREA_WOS);
|
||||
if (disguised(bl))
|
||||
clif_setdisguise(bl, buf, len);
|
||||
@ -3937,57 +3940,60 @@ void clif_misceffect(struct block_list* bl,int type)
|
||||
/// Notifies clients in the area of a state change.
|
||||
/// 0119 <id>.L <body state>.W <health state>.W <effect state>.W <pk mode>.B (ZC_STATE_CHANGE)
|
||||
/// 0229 <id>.L <body state>.W <health state>.W <effect state>.L <pk mode>.B (ZC_STATE_CHANGE3)
|
||||
void clif_changeoption(struct block_list* bl)
|
||||
void clif_changeoption_target(struct block_list* bl, struct block_list *target)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
struct status_change *sc;
|
||||
struct map_session_data* sd;
|
||||
|
||||
nullpo_retv(bl);
|
||||
sc = status_get_sc(bl);
|
||||
if (!sc) return; //How can an option change if there's no sc?
|
||||
sd = BL_CAST(BL_PC, bl);
|
||||
|
||||
#if PACKETVER >= 7
|
||||
WBUFW(buf,0) = 0x229;
|
||||
struct status_change *sc = status_get_sc(bl);
|
||||
|
||||
if (!sc || (target && (target->type != BL_PC || bl->type != BL_NPC)))
|
||||
return; //How can an option change if there's no sc?
|
||||
|
||||
struct map_session_data *sd = BL_CAST(BL_PC, bl);
|
||||
unsigned char buf[32];
|
||||
#if PAKCETVER >= 7
|
||||
int cmd = 0x229;
|
||||
#else
|
||||
int cmd = 0x119;
|
||||
#endif
|
||||
|
||||
WBUFW(buf,0) = cmd;
|
||||
WBUFL(buf,2) = bl->id;
|
||||
WBUFW(buf,6) = sc->opt1;
|
||||
WBUFW(buf,8) = sc->opt2;
|
||||
WBUFL(buf,10) = sc->option;
|
||||
#if PACKETVER >= 7
|
||||
WBUFB(buf,14) = (sd)? sd->status.karma : 0;
|
||||
if(disguised(bl)) {
|
||||
clif_send(buf,packet_len(0x229),bl,AREA_WOS);
|
||||
WBUFL(buf,2) = -bl->id;
|
||||
clif_send(buf,packet_len(0x229),bl,SELF);
|
||||
WBUFL(buf,2) = bl->id;
|
||||
WBUFL(buf,10) = OPTION_INVISIBLE;
|
||||
clif_send(buf,packet_len(0x229),bl,SELF);
|
||||
} else
|
||||
clif_send(buf,packet_len(0x229),bl,AREA);
|
||||
#else
|
||||
WBUFW(buf,0) = 0x119;
|
||||
WBUFL(buf,2) = bl->id;
|
||||
WBUFW(buf,6) = sc->opt1;
|
||||
WBUFW(buf,8) = sc->opt2;
|
||||
WBUFW(buf,10) = sc->option;
|
||||
WBUFB(buf,12) = (sd)? sd->status.karma : 0;
|
||||
if(disguised(bl)) {
|
||||
clif_send(buf,packet_len(0x119),bl,AREA_WOS);
|
||||
WBUFL(buf,2) = -bl->id;
|
||||
clif_send(buf,packet_len(0x119),bl,SELF);
|
||||
WBUFL(buf,2) = bl->id;
|
||||
WBUFW(buf,10) = OPTION_INVISIBLE;
|
||||
clif_send(buf,packet_len(0x119),bl,SELF);
|
||||
} else
|
||||
clif_send(buf,packet_len(0x119),bl,AREA);
|
||||
#endif
|
||||
if (!target) {
|
||||
if (disguised(bl)) {
|
||||
clif_send(buf,packet_len(cmd),bl,AREA_WOS);
|
||||
WBUFL(buf,2) = -bl->id;
|
||||
clif_send(buf,packet_len(cmd),bl,SELF);
|
||||
WBUFL(buf,2) = bl->id;
|
||||
WBUFL(buf,10) = OPTION_INVISIBLE;
|
||||
clif_send(buf,packet_len(cmd),bl,SELF);
|
||||
} else
|
||||
clif_send(buf,packet_len(cmd),bl,AREA);
|
||||
|
||||
//Whenever we send "changeoption" to the client, the provoke icon is lost
|
||||
//There is probably an option for the provoke icon, but as we don't know it, we have to do this for now
|
||||
if (sc->data[SC_PROVOKE]) {
|
||||
const struct TimerData *td = get_timer(sc->data[SC_PROVOKE]->timer);
|
||||
//Whenever we send "changeoption" to the client, the provoke icon is lost
|
||||
//There is probably an option for the provoke icon, but as we don't know it, we have to do this for now
|
||||
if (sc->data[SC_PROVOKE]) {
|
||||
const struct TimerData *td = get_timer(sc->data[SC_PROVOKE]->timer);
|
||||
|
||||
clif_status_change(bl, StatusIconChangeTable[SC_PROVOKE], 1, (!td ? INFINITE_TICK : DIFF_TICK(td->tick, gettick())), 0, 0, 0);
|
||||
clif_status_change(bl, StatusIconChangeTable[SC_PROVOKE], 1, (!td ? INFINITE_TICK : DIFF_TICK(td->tick, gettick())), 0, 0, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (disguised(bl)) {
|
||||
WBUFL(buf,2) = -bl->id;
|
||||
clif_send(buf,packet_len(cmd),target,SELF);
|
||||
WBUFL(buf,2) = bl->id;
|
||||
WBUFL(buf,10) = OPTION_INVISIBLE;
|
||||
}
|
||||
clif_send(buf,packet_len(cmd),target,SELF);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4644,10 +4650,14 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d
|
||||
|
||||
void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
|
||||
{
|
||||
nullpo_retv(bl);
|
||||
|
||||
uint8 buf[128];
|
||||
struct unit_data *ud;
|
||||
struct view_data *vd;
|
||||
int len;
|
||||
bool option = false;
|
||||
unsigned int option_val = 0;
|
||||
|
||||
vd = status_get_viewdata(bl);
|
||||
if (!vd || vd->class_ == JT_INVISIBLE)
|
||||
@ -4660,7 +4670,15 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl)
|
||||
return;
|
||||
|
||||
ud = unit_bl2ud(bl);
|
||||
len = ( ud && ud->walktimer != INVALID_TIMER ) ? clif_set_unit_walking(bl,ud,buf) : clif_set_unit_idle(bl,buf,false);
|
||||
if (sd && bl->type == BL_NPC) { // npc option changed?
|
||||
npc_data* nd = BL_CAST(BL_NPC, bl);
|
||||
option_val = nd->sc.option;
|
||||
option = true;
|
||||
|
||||
if (std::find(sd->cloaked_npc.begin(), sd->cloaked_npc.end(), nd->bl.id) != sd->cloaked_npc.end())
|
||||
option_val ^= OPTION_CLOAK;
|
||||
}
|
||||
len = ( ud && ud->walktimer != INVALID_TIMER ) ? clif_set_unit_walking(bl,ud,buf) : clif_set_unit_idle(bl,buf,false,option,option_val);
|
||||
clif_send(buf,len,&sd->bl,SELF);
|
||||
|
||||
if (vd->cloth_color)
|
||||
|
@ -631,7 +631,8 @@ void clif_statusupack(struct map_session_data *sd,int type,int ok,int val); // s
|
||||
void clif_equipitemack(struct map_session_data *sd,int n,int pos,uint8 flag); // self
|
||||
void clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok); // self
|
||||
void clif_misceffect(struct block_list* bl,int type); // area
|
||||
void clif_changeoption(struct block_list* bl); // area
|
||||
void clif_changeoption_target(struct block_list* bl, struct block_list* target);
|
||||
#define clif_changeoption(bl) clif_changeoption_target(bl, NULL) // area
|
||||
void clif_changeoption2(struct block_list* bl); // area
|
||||
void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok); // self
|
||||
void clif_GlobalMessage(struct block_list* bl, const char* message,enum send_target target);
|
||||
|
112
src/map/npc.cpp
112
src/map/npc.cpp
@ -252,41 +252,102 @@ int npc_enable_sub(struct block_list *bl, va_list ap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool npc_is_cloaked(struct npc_data* nd, struct map_session_data* sd) {
|
||||
bool npc_cloaked = (nd->sc.option & OPTION_CLOAK) ? true : false;
|
||||
|
||||
if (std::find(sd->cloaked_npc.begin(), sd->cloaked_npc.end(), nd->bl.id) != sd->cloaked_npc.end())
|
||||
return (!npc_cloaked);
|
||||
return npc_cloaked;
|
||||
}
|
||||
|
||||
static int npc_cloaked_sub(struct block_list *bl, va_list ap)
|
||||
{
|
||||
struct map_session_data* sd;
|
||||
|
||||
nullpo_ret(bl);
|
||||
nullpo_ret(sd = (struct map_session_data *)bl);
|
||||
int id = va_arg(ap, int);
|
||||
|
||||
auto it = std::find(sd->cloaked_npc.begin(), sd->cloaked_npc.end(), id);
|
||||
|
||||
if (it != sd->cloaked_npc.end())
|
||||
sd->cloaked_npc.erase(it);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Disable / Enable NPC
|
||||
*------------------------------------------*/
|
||||
bool npc_enable(const char* name, int flag)
|
||||
bool npc_enable_target(const char* name, uint32 char_id, int flag)
|
||||
{
|
||||
struct npc_data* nd = npc_name2id(name);
|
||||
|
||||
if (nd==NULL)
|
||||
{
|
||||
ShowError("npc_enable: Attempted to %s a non-existing NPC '%s' (flag=%d).\n", (flag&3) ? "show" : "hide", name, flag);
|
||||
if (!nd) {
|
||||
ShowError("npc_enable: Attempted to %s a non-existing NPC '%s' (flag=%d).\n", (flag&11) ? "show" : "hide", name, flag);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flag&1) {
|
||||
nd->sc.option&=~OPTION_INVISIBLE;
|
||||
clif_spawn(&nd->bl);
|
||||
} else if (flag&2)
|
||||
nd->sc.option&=~OPTION_HIDE;
|
||||
else if (flag&4)
|
||||
nd->sc.option|= OPTION_HIDE;
|
||||
else { //Can't change the view_data to invisible class because the view_data for all npcs is shared! [Skotlex]
|
||||
nd->sc.option|= OPTION_INVISIBLE;
|
||||
clif_clearunit_area(&nd->bl,CLR_OUTSIGHT); // Hack to trick maya purple card [Xazax]
|
||||
if (char_id > 0 && (flag & 24)) {
|
||||
map_session_data *sd = map_charid2sd(char_id);
|
||||
|
||||
if (!sd) {
|
||||
ShowError("npc_enable: Attempted to %s a NPC '%s' on an invalid target %d.\n", (flag & 8) ? "show" : "hide", name, char_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int option = nd->sc.option;
|
||||
if (flag&8)
|
||||
nd->sc.option &= ~OPTION_CLOAK;
|
||||
else
|
||||
nd->sc.option |= OPTION_CLOAK;
|
||||
|
||||
auto it = std::find(sd->cloaked_npc.begin(), sd->cloaked_npc.end(), nd->bl.id);
|
||||
|
||||
if (it == sd->cloaked_npc.end() && option != nd->sc.option)
|
||||
sd->cloaked_npc.push_back(nd->bl.id);
|
||||
else if (it != sd->cloaked_npc.end() && option == nd->sc.option)
|
||||
sd->cloaked_npc.erase(it);
|
||||
|
||||
if (nd->class_ != JT_WARPNPC && nd->class_ != JT_GUILD_FLAG)
|
||||
clif_changeoption_target(&nd->bl, &sd->bl);
|
||||
else {
|
||||
if (nd->sc.option&(OPTION_HIDE|OPTION_INVISIBLE|OPTION_CLOAK))
|
||||
clif_clearunit_single(nd->bl.id, CLR_OUTSIGHT, sd->fd);
|
||||
else
|
||||
clif_spawn(&nd->bl);
|
||||
}
|
||||
nd->sc.option = option;
|
||||
}
|
||||
else {
|
||||
if (flag&1) {
|
||||
nd->sc.option &= ~OPTION_INVISIBLE;
|
||||
clif_spawn(&nd->bl);
|
||||
}
|
||||
else if (flag&2)
|
||||
nd->sc.option &= ~OPTION_HIDE;
|
||||
else if (flag&4)
|
||||
nd->sc.option |= OPTION_HIDE;
|
||||
else if (flag&8)
|
||||
nd->sc.option &= ~OPTION_CLOAK;
|
||||
else if (flag&16)
|
||||
nd->sc.option |= OPTION_CLOAK;
|
||||
else { //Can't change the view_data to invisible class because the view_data for all npcs is shared! [Skotlex]
|
||||
nd->sc.option |= OPTION_INVISIBLE;
|
||||
clif_clearunit_area(&nd->bl,CLR_OUTSIGHT); // Hack to trick maya purple card [Xazax]
|
||||
}
|
||||
if (nd->class_ != JT_WARPNPC && nd->class_ != JT_GUILD_FLAG) //Client won't display option changes for these classes [Toms]
|
||||
clif_changeoption(&nd->bl);
|
||||
else {
|
||||
if (nd->sc.option&(OPTION_HIDE|OPTION_INVISIBLE|OPTION_CLOAK))
|
||||
clif_clearunit_area(&nd->bl,CLR_OUTSIGHT);
|
||||
else
|
||||
clif_spawn(&nd->bl);
|
||||
}
|
||||
map_foreachinmap(npc_cloaked_sub, nd->bl.m, BL_PC, nd->bl.id); // Because npc option has been updated we remove the npc id from sd->cloaked_npc
|
||||
}
|
||||
|
||||
if (nd->class_ == JT_WARPNPC || nd->class_ == JT_GUILD_FLAG)
|
||||
{ //Client won't display option changes for these classes [Toms]
|
||||
if (nd->sc.option&(OPTION_HIDE|OPTION_INVISIBLE))
|
||||
clif_clearunit_area(&nd->bl, CLR_OUTSIGHT);
|
||||
else
|
||||
clif_spawn(&nd->bl);
|
||||
} 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&11 && (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 true;
|
||||
@ -1069,6 +1130,9 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
|
||||
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;
|
||||
|
||||
if (npc_is_cloaked(mapdata->npc[i], sd))
|
||||
continue;
|
||||
|
||||
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))
|
||||
|
@ -1221,7 +1221,9 @@ const char *npc_get_script_event_name(int npce_index);
|
||||
void npc_setcells(struct npc_data* nd);
|
||||
void npc_unsetcells(struct npc_data* nd);
|
||||
bool npc_movenpc(struct npc_data* nd, int16 x, int16 y);
|
||||
bool npc_enable(const char* name, int flag);
|
||||
bool npc_is_cloaked(struct npc_data* nd, struct map_session_data* sd);
|
||||
bool npc_enable_target(const char* name, uint32 char_id, int flag);
|
||||
#define npc_enable(name, flag) npc_enable_target(name, 0, flag)
|
||||
void npc_setdisplayname(struct npc_data* nd, const char* newname);
|
||||
void npc_setclass(struct npc_data* nd, short class_);
|
||||
struct npc_data* npc_name2id(const char* name);
|
||||
|
@ -5783,6 +5783,16 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
|
||||
}
|
||||
|
||||
channel_pcquit(sd,4); //quit map chan
|
||||
|
||||
// Remove Cloaked NPC if changing to another map
|
||||
for (auto it = sd->cloaked_npc.begin(); it != sd->cloaked_npc.end(); ++it) {
|
||||
block_list *npc_bl = map_id2bl(*it);
|
||||
|
||||
if (npc_bl && npc_bl->m != m) {
|
||||
sd->cloaked_npc.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m < 0 )
|
||||
|
@ -648,6 +648,8 @@ struct map_session_data {
|
||||
// Title system
|
||||
std::vector<int> titles;
|
||||
|
||||
std::vector<int> cloaked_npc;
|
||||
|
||||
/* ShowEvent Data Cache flags from map */
|
||||
bool *qi_display;
|
||||
int qi_count;
|
||||
|
@ -24608,6 +24608,40 @@ BUILDIN_FUNC(convertpcinfo) {
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC(cloakoffnpc)
|
||||
{
|
||||
if (npc_enable_target(script_getstr(st, 2), script_hasdata(st, 3) ? script_getnum(st, 3) : 0, 8))
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC(cloakonnpc)
|
||||
{
|
||||
if (npc_enable_target(script_getstr(st, 2), script_hasdata(st, 3) ? script_getnum(st, 3) : 0, 16))
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
BUILDIN_FUNC(isnpccloaked)
|
||||
{
|
||||
struct npc_data *nd = npc_name2id(script_getstr(st, 2));
|
||||
|
||||
if (!nd) {
|
||||
ShowError("buildin_isnpccloaked: %s is a non-existing NPC.\n", script_getstr(st, 2));
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
map_session_data* sd;
|
||||
|
||||
if (!script_charid2sd(3, sd))
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
|
||||
script_pushint(st, npc_is_cloaked(nd, sd));
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
#include "../custom/script.inc"
|
||||
|
||||
// declarations that were supposed to be exported from npc_chat.cpp
|
||||
@ -25280,6 +25314,9 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(achievement_condition,"i"),
|
||||
BUILDIN_DEF(getvariableofinstance,"ri"),
|
||||
BUILDIN_DEF(convertpcinfo,"vi"),
|
||||
BUILDIN_DEF(cloakoffnpc, "s?"),
|
||||
BUILDIN_DEF(cloakonnpc, "s?"),
|
||||
BUILDIN_DEF(isnpccloaked, "s?"),
|
||||
#include "../custom/script_def.inc"
|
||||
|
||||
{NULL,NULL,NULL},
|
||||
|
Loading…
x
Reference in New Issue
Block a user