Skip to content

Commit

Permalink
Add *duplicate/remove npc script command
Browse files Browse the repository at this point in the history
- `npc_duplicate()` duplicate any existing duplicated NPC.
- `npc_duplicate_remove()` will remove any existing NPC other than source NPC.
  • Loading branch information
Emistry committed May 16, 2019
1 parent 647a3d2 commit 3164dc7
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 0 deletions.
14 changes: 14 additions & 0 deletions doc/script_commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6828,6 +6828,20 @@ NPCs talking while hidden then revealing... you can wonder around =P).

---------------------------------------

*npc_duplicate("<source_npc_name>", "<new_npc_name>", "<new_npc_hidden_name>", "<mapname>", <map_x>, <map_y>, <dir>{, <sprite_id>{, <map_xs>, <map_ys>}});

Duplicate any existing NPC based on <source_npc_name>.
Return 1 on success, 0 if failed.

---------------------------------------

*npc_duplicate_remove({"<npc_name>"});

Remove any duplicated NPC from source NPC or depend on <npc_name> if specified.
If <npc_name> are source NPC, it will only remove all duplicated NPC.

---------------------------------------

*doevent("<NPC object name>::<event label>")

This command will start a new execution thread in a specified NPC object
Expand Down
96 changes: 96 additions & 0 deletions src/map/script.c
Original file line number Diff line number Diff line change
Expand Up @@ -12183,6 +12183,100 @@ static BUILDIN(hideonnpc)
return true;
}

static BUILDIN(npc_duplicate)
{
int txs = -1, tys = -1;

if (script_hasdata(st, 10))
txs = (script_getnum(st, 10) < -1) ? -1 : script_getnum(st, 10);
if (script_hasdata(st, 11))
tys = (script_getnum(st, 11) < -1) ? -1 : script_getnum(st, 10);

if (txs == -1 && tys != -1)
txs = 0;
if (txs != -1 && tys == -1)
tys = 0;

const char *npc_name = script_getstr(st, 2);
const char *dup_name = script_getstr(st, 3);
const char *dup_hidden_name = script_getstr(st, 4);

char targetname[NAME_LENGTH] = "";
strcat(targetname, dup_name);
if (strcmp(dup_hidden_name, "") != 0) {
strncat(targetname, "#", 1);
strncat(targetname, dup_hidden_name, strlen(dup_hidden_name));
}

if (strlen(dup_name) + strlen(dup_hidden_name) > NAME_LENGTH) {
ShowError("buildin_npc_duplicate: %s is to long (max %d chars).\n", npc_name, NAME_LENGTH);
script_pushint(st, 0);
return false;
} else if (npc->name2id(targetname) != NULL) {
ShowError("buildin_npc_duplicate: NPC named '%s' already exists.\n", targetname, NAME_LENGTH);
script_pushint(st, 0);
return false;
}

struct npc_data *nd_source = npc->name2id(npc_name);
int tclass_;
if (script_hasdata(st, 9))
tclass_ = (script_getnum(st, 9) < -1) ? -1 : script_getnum(st, 9);
else
tclass_ = nd_source->class_;

if (nd_source == NULL) {
ShowError("buildin_npc_duplicate: original npc not found for duplicate. (%s)\n", npc_name);
script_pushint(st, 0);
return false;
}

const char *tmap = script_getstr(st, 5);
int tmapid = map->mapname2mapid(tmap);
if (tmapid < 0) {
ShowError("buildin_npc_duplicate: target map not found. (%s)\n", tmap);
script_pushint(st, 0);
return false;
}

int tx = script_getnum(st, 6);
int ty = script_getnum(st, 7);
int tdir = script_getnum(st, 8);
struct npc_data *nd_target = npc->create_npc(nd_source->subtype, tmapid, tx, ty, tdir, tclass_);

safestrncpy(nd_target->name, targetname, sizeof(nd_target->name));
safestrncpy(nd_target->exname, targetname, sizeof(nd_target->exname));

script_pushint(st, npc->duplicate_sub(nd_target, nd_source, txs, tys, NPO_ONINIT));
return true;
}

static BUILDIN(npc_duplicate_remove)
{
struct npc_data *nd;

if (script_hasdata(st, 2)) {
nd = npc->name2id(script_getstr(st, 2));
if (nd == NULL) {
ShowError("buildin_npc_duplicate_remove: Duplicate NPC not found. (%s)\n", script_getstr(st, 2));
script_pushint(st, 0);
return false;
}
}
else
nd = map->id2nd(st->oid);

if (nd != NULL) {
if (nd->src_id == 0) //remove all dupicates for this source npc
map->foreachnpc(npc->unload_dup_sub, nd->bl.id);
else // just remove this duplicate
npc->unload(nd, true);
}

script_pushint(st, 1);
return true;
}

/* Starts a status effect on the target unit or on the attached player.
*
* sc_start <effect_id>,<duration>,<val1>{,<rate>,<flag>,{<unit_id>}};
Expand Down Expand Up @@ -25623,6 +25717,8 @@ static void script_parse_builtin(void)
BUILDIN_DEF(disablenpc,"s"),
BUILDIN_DEF(hideoffnpc,"s"),
BUILDIN_DEF(hideonnpc,"s"),
BUILDIN_DEF(npc_duplicate, "ssssiii???"),
BUILDIN_DEF(npc_duplicate_remove, "?"),
BUILDIN_DEF(sc_start,"iii???"),
BUILDIN_DEF2(sc_start,"sc_start2","iiii???"),
BUILDIN_DEF2(sc_start,"sc_start4","iiiiii???"),
Expand Down

0 comments on commit 3164dc7

Please sign in to comment.