Skip to content

Commit db6fe14

Browse files
committed
Add *duplicate/remove npc script command
- `npc_duplicate()` duplicate any existing duplicated NPC. - `npc_duplicate_remove()` will remove any existing NPC other than source NPC.
1 parent c037226 commit db6fe14

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

doc/script_commands.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7039,6 +7039,20 @@ NPCs talking while hidden then revealing... you can wonder around =P).
70397039

70407040
---------------------------------------
70417041

7042+
*npc_duplicate("<source_npc_name>", "<new_npc_name>", "<new_npc_hidden_name>", "<mapname>", <map_x>, <map_y>, <dir>{, <sprite_id>{, <map_xs>, <map_ys>}});
7043+
7044+
Duplicate any existing NPC based on <source_npc_name>.
7045+
Return 1 on success, 0 if failed.
7046+
7047+
---------------------------------------
7048+
7049+
*npc_duplicate_remove({"<npc_name>"});
7050+
7051+
Remove any duplicated NPC from source NPC or depend on <npc_name> if specified.
7052+
If <npc_name> are source NPC, it will only remove all duplicated NPC.
7053+
7054+
---------------------------------------
7055+
70427056
*doevent("<NPC object name>::<event label>")
70437057

70447058
This command will start a new execution thread in a specified NPC object

src/map/script.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12490,6 +12490,100 @@ static BUILDIN(hideonnpc)
1249012490
return true;
1249112491
}
1249212492

12493+
static BUILDIN(npc_duplicate)
12494+
{
12495+
int txs = -1, tys = -1;
12496+
12497+
if (script_hasdata(st, 10))
12498+
txs = (script_getnum(st, 10) < -1) ? -1 : script_getnum(st, 10);
12499+
if (script_hasdata(st, 11))
12500+
tys = (script_getnum(st, 11) < -1) ? -1 : script_getnum(st, 10);
12501+
12502+
if (txs == -1 && tys != -1)
12503+
txs = 0;
12504+
if (txs != -1 && tys == -1)
12505+
tys = 0;
12506+
12507+
const char *npc_name = script_getstr(st, 2);
12508+
const char *dup_name = script_getstr(st, 3);
12509+
const char *dup_hidden_name = script_getstr(st, 4);
12510+
12511+
char targetname[NAME_LENGTH] = "";
12512+
strcat(targetname, dup_name);
12513+
if (strcmp(dup_hidden_name, "") != 0) {
12514+
strncat(targetname, "#", 1);
12515+
strncat(targetname, dup_hidden_name, strlen(dup_hidden_name));
12516+
}
12517+
12518+
if (strlen(targetname) > NAME_LENGTH) {
12519+
ShowError("buildin_npc_duplicate: NPC name '%s' is to long (max %d chars).\n", targetname, NAME_LENGTH);
12520+
script_pushint(st, 0);
12521+
return false;
12522+
} else if (npc->name2id(targetname) != NULL) {
12523+
ShowError("buildin_npc_duplicate: NPC named '%s' already exists.\n", targetname);
12524+
script_pushint(st, 0);
12525+
return false;
12526+
}
12527+
12528+
struct npc_data *nd_source = npc->name2id(npc_name);
12529+
int tclass_;
12530+
if (script_hasdata(st, 9))
12531+
tclass_ = (script_getnum(st, 9) < -1) ? -1 : script_getnum(st, 9);
12532+
else
12533+
tclass_ = nd_source->class_;
12534+
12535+
if (nd_source == NULL) {
12536+
ShowError("buildin_npc_duplicate: Source NPC not found. (%s)\n", npc_name);
12537+
script_pushint(st, 0);
12538+
return false;
12539+
}
12540+
12541+
const char *tmap = script_getstr(st, 5);
12542+
int tmapid = map->mapname2mapid(tmap);
12543+
if (tmapid < 0) {
12544+
ShowError("buildin_npc_duplicate: Target map not found. (%s)\n", tmap);
12545+
script_pushint(st, 0);
12546+
return false;
12547+
}
12548+
12549+
int tx = script_getnum(st, 6);
12550+
int ty = script_getnum(st, 7);
12551+
int tdir = script_getnum(st, 8);
12552+
struct npc_data *nd_target = npc->create_npc(nd_source->subtype, tmapid, tx, ty, tdir, tclass_);
12553+
12554+
safestrncpy(nd_target->name, targetname, sizeof(nd_target->name));
12555+
safestrncpy(nd_target->exname, targetname, sizeof(nd_target->exname));
12556+
12557+
script_pushint(st, npc->duplicate_sub(nd_target, nd_source, txs, tys, NPO_ONINIT));
12558+
return true;
12559+
}
12560+
12561+
static BUILDIN(npc_duplicate_remove)
12562+
{
12563+
struct npc_data *nd;
12564+
12565+
if (script_hasdata(st, 2)) {
12566+
nd = npc->name2id(script_getstr(st, 2));
12567+
if (nd == NULL) {
12568+
ShowError("buildin_npc_duplicate_remove: Duplicate NPC not found. (%s)\n", script_getstr(st, 2));
12569+
script_pushint(st, 0);
12570+
return false;
12571+
}
12572+
}
12573+
else
12574+
nd = map->id2nd(st->oid);
12575+
12576+
if (nd != NULL) {
12577+
if (nd->src_id == 0) //remove all dupicates for this source npc
12578+
map->foreachnpc(npc->unload_dup_sub, nd->bl.id);
12579+
else // just remove this duplicate
12580+
npc->unload(nd, true);
12581+
}
12582+
12583+
script_pushint(st, 1);
12584+
return true;
12585+
}
12586+
1249312587
/* Starts a status effect on the target unit or on the attached player.
1249412588
*
1249512589
* sc_start <effect_id>,<duration>,<val1>{,<rate>,<flag>,{<unit_id>}};
@@ -26410,6 +26504,8 @@ static void script_parse_builtin(void)
2641026504
BUILDIN_DEF(disablenpc,"s"),
2641126505
BUILDIN_DEF(hideoffnpc,"s"),
2641226506
BUILDIN_DEF(hideonnpc,"s"),
26507+
BUILDIN_DEF(npc_duplicate, "ssssiii???"),
26508+
BUILDIN_DEF(npc_duplicate_remove, "?"),
2641326509
BUILDIN_DEF(sc_start,"iii???"),
2641426510
BUILDIN_DEF2(sc_start,"sc_start2","iiii???"),
2641526511
BUILDIN_DEF2(sc_start,"sc_start4","iiiiii???"),

0 commit comments

Comments
 (0)