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: ==================================================
|
||||
//= rAthena Dev Team
|
||||
//===== Last Updated: ========================================
|
||||
//= 20180831
|
||||
//= 20211112
|
||||
//===== Description: =========================================
|
||||
//= An example of how duplicate NPCs are handled:
|
||||
//= NPC variables are shared between all duplicates.
|
||||
@ -18,14 +18,88 @@ prontera,150,175,4 script Duplicate Test Script 909,{
|
||||
close;
|
||||
|
||||
OnInit:
|
||||
getmapxy(.map$, .x, .y, 1);
|
||||
getmapxy(.map$, .x, .y, BL_NPC);
|
||||
end;
|
||||
|
||||
OnTouch:
|
||||
getmapxy(.map$, .x, .y, 1);
|
||||
getmapxy(.map$, .x, .y, BL_NPC);
|
||||
emotion ET_SCISSOR;
|
||||
end;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
//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>}};
|
||||
*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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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);
|
||||
int npc_globalmessage(const char* name,const char* mes);
|
||||
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_unsetcells(struct npc_data* nd);
|
||||
|
@ -8815,6 +8815,7 @@ BUILDIN_FUNC(getcharid)
|
||||
|
||||
/*==========================================
|
||||
* returns the GID of an NPC
|
||||
* Returns 0 if the NPC name provided is not found.
|
||||
*------------------------------------------*/
|
||||
BUILDIN_FUNC(getnpcid)
|
||||
{
|
||||
@ -8825,9 +8826,9 @@ BUILDIN_FUNC(getnpcid)
|
||||
{// unique npc name
|
||||
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);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25020,6 +25021,115 @@ BUILDIN_FUNC(unloadnpc) {
|
||||
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
|
||||
* achievementadd(<achievement ID>{,<char ID>});
|
||||
@ -27173,6 +27283,7 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(jobcanentermap,"s?"),
|
||||
BUILDIN_DEF(openstorage2,"ii?"),
|
||||
BUILDIN_DEF(unloadnpc, "s"),
|
||||
BUILDIN_DEF(duplicate, "ssii?????"),
|
||||
|
||||
// WoE TE
|
||||
BUILDIN_DEF(agitstart3,""),
|
||||
|
Loading…
x
Reference in New Issue
Block a user