duplicate npc command script (#5960)
Co-authored-by: Aleos <aleos89@users.noreply.github.com> Co-authored-by: Atemo <Atemo@users.noreply.github.com> Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
This commit is contained in:
parent
c7ec076a6c
commit
9c2576f47a
@ -3,7 +3,7 @@
|
|||||||
//===== By: ==================================================
|
//===== By: ==================================================
|
||||||
//= rAthena Dev Team
|
//= rAthena Dev Team
|
||||||
//===== Last Updated: ========================================
|
//===== Last Updated: ========================================
|
||||||
//= 20180831
|
//= 20211112
|
||||||
//===== Description: =========================================
|
//===== Description: =========================================
|
||||||
//= An example of how duplicate NPCs are handled:
|
//= An example of how duplicate NPCs are handled:
|
||||||
//= NPC variables are shared between all duplicates.
|
//= NPC variables are shared between all duplicates.
|
||||||
@ -18,14 +18,88 @@ prontera,150,175,4 script Duplicate Test Script 909,{
|
|||||||
close;
|
close;
|
||||||
|
|
||||||
OnInit:
|
OnInit:
|
||||||
getmapxy(.map$, .x, .y, 1);
|
getmapxy(.map$, .x, .y, BL_NPC);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
OnTouch:
|
OnTouch:
|
||||||
getmapxy(.map$, .x, .y, 1);
|
getmapxy(.map$, .x, .y, BL_NPC);
|
||||||
emotion ET_SCISSOR;
|
emotion ET_SCISSOR;
|
||||||
end;
|
end;
|
||||||
}
|
}
|
||||||
|
|
||||||
prontera,155,175,4 duplicate(Duplicate Test Script) Duplicate Test2 909,2,2
|
prontera,155,175,4 duplicate(Duplicate Test Script) Duplicate Test2 909,2,2
|
||||||
prontera,160,175,4 duplicate(Duplicate Test Script) Duplicate Test3 909,3,3
|
prontera,160,175,4 duplicate(Duplicate Test Script) Duplicate Test3 909,3,3
|
||||||
|
|
||||||
|
//duplicate command script
|
||||||
|
prontera,150,168,4 script Duplicate Command Test 909,{
|
||||||
|
mes "Would you like to create a new NPC?";
|
||||||
|
.@original_npc$ = "original_npc_unique_name";
|
||||||
|
|
||||||
|
mes "Input Map Name";
|
||||||
|
mes "recommended 'prontera'";
|
||||||
|
input .@map$;
|
||||||
|
clear;
|
||||||
|
mes "Input x";
|
||||||
|
mes "recommended '155'";
|
||||||
|
input .@x,0;
|
||||||
|
clear;
|
||||||
|
mes "Input y";
|
||||||
|
mes "recommended '168'";
|
||||||
|
input .@y,0;
|
||||||
|
clear;
|
||||||
|
|
||||||
|
switch( .@s = select( "Provide no info:With name:With name and look:With name, look and dir:cancel" ) ){
|
||||||
|
case 1:
|
||||||
|
.@new_npc$ = duplicate( .@original_npc$, .@map$, .@x, .@y );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
mes "Input Duplicate NPC Name";
|
||||||
|
input .@name$;
|
||||||
|
clear;
|
||||||
|
.@new_npc$ = duplicate( .@original_npc$, .@map$, .@x, .@y, .@name$ );
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
mes "Input Duplicate NPC Name";
|
||||||
|
input .@name$;
|
||||||
|
clear;
|
||||||
|
mes "Input look";
|
||||||
|
mes "recommended '445'";
|
||||||
|
input .@look,0;
|
||||||
|
.@new_npc$ = duplicate( .@original_npc$, .@map$, .@x, .@y, .@name$, .@look );
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
mes "Input Duplicate NPC Name";
|
||||||
|
input .@name$;
|
||||||
|
clear;
|
||||||
|
mes "Input look";
|
||||||
|
mes "recommended '445'";
|
||||||
|
input .@look,0;
|
||||||
|
clear;
|
||||||
|
mes "Input dir";
|
||||||
|
mes "between " + DIR_NORTH + " and " + DIR_NORTHEAST;
|
||||||
|
input .@dir,DIR_NORTH,DIR_NORTHEAST;
|
||||||
|
.@new_npc$ = duplicate( .@original_npc$, .@map$, .@x, .@y, .@name$, .@look, .@dir );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mes "Ok, see you next time!";
|
||||||
|
close;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( getnpcid( 0, .@new_npc$ ) == 0 ){
|
||||||
|
mes "Something went wrong!";
|
||||||
|
mes "The new NPC could not be found!";
|
||||||
|
close;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear;
|
||||||
|
mes "The new NPC is now at " + .@map$ + "," + .@x + "," + .@y;
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
|
||||||
|
prontera,150,165,0 script test npc::original_npc_unique_name 444,{
|
||||||
|
getmapxy(.@map$, .@x, .@y, BL_NPC);
|
||||||
|
mes "Hi.";
|
||||||
|
mes "My Unique Name is: " + strnpcinfo(3);
|
||||||
|
mes "My coords are "+ .@map$ +", "+ .@x +"/" +.@y ;
|
||||||
|
close;
|
||||||
|
}
|
@ -6840,6 +6840,18 @@ This command will fully unload a NPC object and all of it's duplicates.
|
|||||||
|
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
*duplicate "<NPC name>","<map>",<x>,<y>{,"<Duplicate NPC name>"{,<sprite>{,<dir>{,<xs>{,<xy>}}}}};
|
||||||
|
|
||||||
|
This command will duplicate the NPC with the given <NPC name> on <map> at <x>/<y>.
|
||||||
|
If <Duplicate NPC name>, <sprite>, <dir>, <xs> or <ys> is not provided the value of the original NPC will be used.
|
||||||
|
The Unique name of the new duplicated NPC is returned on success. An empty string is returned on failure.
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
Duplicates will always have the same NPC variables as the original NPC.
|
||||||
|
Editing a NPC variable in a duplicate or the original NPC will change it for the others.
|
||||||
|
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
*cloakonnpc {"<NPC object name>"{,<character ID>}};
|
*cloakonnpc {"<NPC object name>"{,<character ID>}};
|
||||||
*cloakoffnpc {"<NPC object name>"{,<character ID>}};
|
*cloakoffnpc {"<NPC object name>"{,<character ID>}};
|
||||||
|
|
||||||
|
@ -5630,6 +5630,60 @@ int npc_script_event(struct map_session_data* sd, enum npce_event type){
|
|||||||
return vector.size();
|
return vector.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicates a NPC.
|
||||||
|
* nd: Original NPC data
|
||||||
|
* name: Duplicate NPC name
|
||||||
|
* m: Map ID of duplicate NPC
|
||||||
|
* x: X coordinate of duplicate NPC
|
||||||
|
* y: Y coordinate of duplicate NPC
|
||||||
|
* class_: View of duplicate NPC
|
||||||
|
* dir: Facing direction of duplicate NPC
|
||||||
|
* Returns duplicate NPC data on success
|
||||||
|
*/
|
||||||
|
npc_data* npc_duplicate_npc( npc_data* nd, char name[NPC_NAME_LENGTH + 1], int16 mapid, int16 x, int16 y, int class_, uint8 dir, int16 xs, int16 ys ){
|
||||||
|
static char w1[128], w2[128], w3[128], w4[128];
|
||||||
|
const char* stat_buf = "- call from duplicate subsystem -\n";
|
||||||
|
char exname[NPC_NAME_LENGTH + 1];
|
||||||
|
|
||||||
|
snprintf(w1, sizeof(w1), "%s,%d,%d,%d", map_getmapdata(mapid)->name, x, y, dir);
|
||||||
|
snprintf(w2, sizeof(w2), "duplicate(%s)", nd->exname);
|
||||||
|
|
||||||
|
//Making sure the generated name is not used for another npc.
|
||||||
|
int i = 0;
|
||||||
|
snprintf(exname, ARRAYLENGTH(exname), "%d_%d_%d_%d", i, mapid, x, y);
|
||||||
|
while (npc_name2id(exname) != nullptr) {
|
||||||
|
++i;
|
||||||
|
snprintf(exname, ARRAYLENGTH(exname), "%d_%d_%d_%d", i, mapid, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(w3, sizeof(w3), "%s::%s", name, exname);
|
||||||
|
|
||||||
|
if( xs >= 0 && ys >= 0 ){
|
||||||
|
snprintf( w4, sizeof( w4 ), "%d,%d,%d", class_, xs, ys ); // Touch Area
|
||||||
|
}else{
|
||||||
|
snprintf( w4, sizeof( w4 ), "%d", class_ );
|
||||||
|
}
|
||||||
|
|
||||||
|
npc_parse_duplicate(w1, w2, w3, w4, stat_buf, stat_buf, "DUPLICATE");//DUPLICATE means nothing for now.
|
||||||
|
|
||||||
|
npc_data* dnd = npc_name2id( exname );
|
||||||
|
|
||||||
|
// No need to try and execute any events
|
||||||
|
if( dnd == nullptr ){
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//run OnInit Events
|
||||||
|
char evname[EVENT_NAME_LENGTH];
|
||||||
|
safesnprintf(evname, EVENT_NAME_LENGTH, "%s::%s", exname, script_config.init_event_name);
|
||||||
|
if ((struct event_data*)strdb_get(ev_db, evname)) {
|
||||||
|
npc_event_do(evname);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dnd;
|
||||||
|
}
|
||||||
|
|
||||||
const char *npc_get_script_event_name(int npce_index)
|
const char *npc_get_script_event_name(int npce_index)
|
||||||
{
|
{
|
||||||
switch (npce_index) {
|
switch (npce_index) {
|
||||||
|
@ -1494,6 +1494,7 @@ void npc_parse_mob2(struct spawn_data* mob);
|
|||||||
struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y);
|
struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y);
|
||||||
int npc_globalmessage(const char* name,const char* mes);
|
int npc_globalmessage(const char* name,const char* mes);
|
||||||
const char *npc_get_script_event_name(int npce_index);
|
const char *npc_get_script_event_name(int npce_index);
|
||||||
|
npc_data* npc_duplicate_npc( npc_data* nd, char name[NPC_NAME_LENGTH + 1], int16 mapid, int16 x, int16 y, int class_, uint8 dir, int16 xs, int16 ys );
|
||||||
|
|
||||||
void npc_setcells(struct npc_data* nd);
|
void npc_setcells(struct npc_data* nd);
|
||||||
void npc_unsetcells(struct npc_data* nd);
|
void npc_unsetcells(struct npc_data* nd);
|
||||||
|
@ -8815,6 +8815,7 @@ BUILDIN_FUNC(getcharid)
|
|||||||
|
|
||||||
/*==========================================
|
/*==========================================
|
||||||
* returns the GID of an NPC
|
* returns the GID of an NPC
|
||||||
|
* Returns 0 if the NPC name provided is not found.
|
||||||
*------------------------------------------*/
|
*------------------------------------------*/
|
||||||
BUILDIN_FUNC(getnpcid)
|
BUILDIN_FUNC(getnpcid)
|
||||||
{
|
{
|
||||||
@ -8825,9 +8826,9 @@ BUILDIN_FUNC(getnpcid)
|
|||||||
{// unique npc name
|
{// unique npc name
|
||||||
if( ( nd = npc_name2id(script_getstr(st,3)) ) == NULL )
|
if( ( nd = npc_name2id(script_getstr(st,3)) ) == NULL )
|
||||||
{
|
{
|
||||||
ShowError("buildin_getnpcid: No such NPC '%s'.\n", script_getstr(st,3));
|
//Npc not found.
|
||||||
script_pushint(st,0);
|
script_pushint(st,0);
|
||||||
return SCRIPT_CMD_FAILURE;
|
return SCRIPT_CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25020,6 +25021,115 @@ BUILDIN_FUNC(unloadnpc) {
|
|||||||
return SCRIPT_CMD_SUCCESS;
|
return SCRIPT_CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicate a NPC.
|
||||||
|
* Return the duplicate Unique name on success or empty string on failure.
|
||||||
|
* duplicate "<NPC name>","<map>",<x>,<y>{,"<Duplicate NPC name>"{,<sprite>{,<dir>{,<xs>{,<xy>}}}}};
|
||||||
|
*/
|
||||||
|
BUILDIN_FUNC(duplicate)
|
||||||
|
{
|
||||||
|
const char* old_npcname = script_getstr( st, 2 );
|
||||||
|
npc_data* nd = npc_name2id( old_npcname );
|
||||||
|
|
||||||
|
if( nd == nullptr ){
|
||||||
|
ShowError( "buildin_duplicate: No such NPC '%s'.\n", old_npcname );
|
||||||
|
script_pushstrcopy( st, "" );
|
||||||
|
return SCRIPT_CMD_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* mapname = script_getstr( st, 3 );
|
||||||
|
int16 mapid = map_mapname2mapid( mapname );
|
||||||
|
|
||||||
|
if( mapid < 0 ){
|
||||||
|
ShowError( "buildin_duplicate: map '%s' in not found!\n", mapname );
|
||||||
|
script_pushstrcopy( st, "" );
|
||||||
|
return SCRIPT_CMD_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct map_data* mapdata = map_getmapdata( mapid );
|
||||||
|
|
||||||
|
if( mapdata == nullptr ){
|
||||||
|
// Should not happen, but who knows...
|
||||||
|
ShowError( "buildin_duplicate: mapdata for '%s' is unavailable!\n", mapname );
|
||||||
|
script_pushstrcopy( st, "" );
|
||||||
|
return SCRIPT_CMD_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 x = script_getnum( st, 4 );
|
||||||
|
|
||||||
|
if( x < 0 || x >= mapdata->xs ){
|
||||||
|
ShowError( "buildin_duplicate: x coordinate %hd is out of bounds for map %s[0-%hd]!\n", x, mapname, mapdata->xs );
|
||||||
|
script_pushstrcopy( st, "" );
|
||||||
|
return SCRIPT_CMD_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 y = script_getnum( st, 5 );
|
||||||
|
|
||||||
|
if( y < 0 || y >= mapdata->ys ){
|
||||||
|
ShowError( "buildin_duplicate: y coordinate %hd is out of bounds for map %s[0-%hd]!\n", y, mapname, mapdata->ys );
|
||||||
|
script_pushstrcopy( st, "" );
|
||||||
|
return SCRIPT_CMD_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char name[NPC_NAME_LENGTH + 1];
|
||||||
|
|
||||||
|
if( script_hasdata( st, 6 ) ){
|
||||||
|
const char* new_name = script_getstr( st, 6 );
|
||||||
|
|
||||||
|
if( strlen( new_name ) > NPC_NAME_LENGTH ){
|
||||||
|
ShowError( "buildin_duplicate: new NPC name \"%s\" is too long!\n", new_name );
|
||||||
|
script_pushstrcopy( st, "" );
|
||||||
|
return SCRIPT_CMD_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
safestrncpy( name, new_name, sizeof( name ) );
|
||||||
|
}else{
|
||||||
|
safestrncpy( name, nd->name, sizeof( name ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
int class_;
|
||||||
|
|
||||||
|
if( script_hasdata( st, 7 ) ){
|
||||||
|
class_ = script_getnum( st, 7 );
|
||||||
|
}else{
|
||||||
|
class_ = nd->class_;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 dir;
|
||||||
|
|
||||||
|
if( script_hasdata( st, 8 ) ){
|
||||||
|
dir = script_getnum( st, 8 );
|
||||||
|
}else{
|
||||||
|
dir = nd->ud.dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 xs;
|
||||||
|
|
||||||
|
if( script_hasdata( st, 9 ) ){
|
||||||
|
xs = script_getnum( st, 9 );
|
||||||
|
}else{
|
||||||
|
xs = nd->u.scr.xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 ys;
|
||||||
|
|
||||||
|
if( script_hasdata( st, 10 ) ){
|
||||||
|
ys = script_getnum( st, 10 );
|
||||||
|
}else{
|
||||||
|
ys = nd->u.scr.ys;
|
||||||
|
}
|
||||||
|
|
||||||
|
npc_data* dnd = npc_duplicate_npc( nd, name, mapid, x, y, class_, dir, xs, ys );
|
||||||
|
|
||||||
|
if( dnd == nullptr ){
|
||||||
|
script_pushstrcopy( st, "" );
|
||||||
|
return SCRIPT_CMD_FAILURE;
|
||||||
|
}else{
|
||||||
|
script_pushstrcopy( st, dnd->exname );
|
||||||
|
return SCRIPT_CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an achievement to the player's log
|
* Add an achievement to the player's log
|
||||||
* achievementadd(<achievement ID>{,<char ID>});
|
* achievementadd(<achievement ID>{,<char ID>});
|
||||||
@ -27173,6 +27283,7 @@ struct script_function buildin_func[] = {
|
|||||||
BUILDIN_DEF(jobcanentermap,"s?"),
|
BUILDIN_DEF(jobcanentermap,"s?"),
|
||||||
BUILDIN_DEF(openstorage2,"ii?"),
|
BUILDIN_DEF(openstorage2,"ii?"),
|
||||||
BUILDIN_DEF(unloadnpc, "s"),
|
BUILDIN_DEF(unloadnpc, "s"),
|
||||||
|
BUILDIN_DEF(duplicate, "ssii?????"),
|
||||||
|
|
||||||
// WoE TE
|
// WoE TE
|
||||||
BUILDIN_DEF(agitstart3,""),
|
BUILDIN_DEF(agitstart3,""),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user