diff options
Diffstat (limited to 'src/emap/script_buildins.c')
-rw-r--r-- | src/emap/script_buildins.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/emap/script_buildins.c b/src/emap/script_buildins.c index b01d100..9acbf7c 100644 --- a/src/emap/script_buildins.c +++ b/src/emap/script_buildins.c @@ -3699,6 +3699,169 @@ BUILDIN(bgjoin) return true; } +// Constants for the next function (from db/constants.conf) +#define UNIT_DIR_UNDEFINED -1 +#define UNIT_DIR_MAX 8 +/* + * Create a duplicate of source NPC. + * npc_duplicate("<source_npc_name>", "<new_npc_name>", "<mapname>", <map_x>, <map_y>, {<sprite_id>, <dir>{, <map_xs>, <map_ys>}}); + * Return 1 on success, 0 if failed. + */ +BUILDIN(npc_duplicate) +{ + int txs = -1; + int tys = -1; + int tdir = 0; + + if (script_hasdata(st, 9)) + txs = script_getnum(st, 9); + if (script_hasdata(st, 10)) + tys = script_getnum(st, 10); + + if (txs < -1) + txs = -1; + if (tys < -1) + tys = -1; + + if (txs == -1 && tys != -1) + txs = 0; + if (txs != -1 && tys == -1) + tys = 0; + + const char *targetname = script_getstr(st, 3); + + size_t len_dup = strlen(targetname); + + if (len_dup > NAME_LENGTH - 1) { + ShowError("buildin_npc_duplicate: NPC name '%s' is too long (max %d chars).\n", targetname, NAME_LENGTH - 1); + script_pushint(st, 0); + return false; + } + if (strlen(targetname) > NAME_LENGTH) { + ShowError("buildin_npc_duplicate: NPC name '%s' is too long (max %d chars).\n", targetname, 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); + script_pushint(st, 0); + return false; + } + + const char *npc_name = script_getstr(st, 2); + struct npc_data *nd_source = npc->name2id(npc_name); + + if (nd_source == NULL) { + ShowError("buildin_npc_duplicate: Source NPC '%s' not found.\n", npc_name); + script_pushint(st, 0); + return false; + } + + int tclass_ = nd_source->class_; + + if (script_hasdata(st, 7)) + tclass_ = script_getnum(st, 7); + if (tclass_ < -1) + tclass_ = FAKE_NPC; + + ShowDebug("Dupe %s as %s; Class %d\n", npc_name, targetname, tclass_); + if (nd_source->src_id != 0) { + ShowError("buildin_npc_duplicate: Source NPC '%s' is a duplicated NPC of %d.\n", nd_source->name, nd_source->src_id); + script_pushint(st, 0); + return false; + } + + const char *tmap = script_getstr(st, 4); + ShowDebug("Dupe %s in %s as %s; Class %d\n", npc_name, tmap, targetname, tclass_); + int tmapid = map->mapname2mapid(tmap); + if (tmapid < 0) { + ShowError("buildin_npc_duplicate: Target map '%s' not found.\n", tmap); + script_pushint(st, 0); + return false; + } + + if (map->list[tmapid].npc_num >= MAX_NPC_PER_MAP) { + ShowError("buildin_npc_duplicate: Exceeded MAX NPC per map (%d).\n", MAX_NPC_PER_MAP); + return false; + } + + int tx = script_getnum(st, 5); + int ty = script_getnum(st, 6); + if (script_hasdata(st, 8)) + tdir = script_getnum(st, 8); + + ShowDebug("Dir %d at (%d,%d)\n", tdir, tx, ty); +#if 0 + if (tclass_ != FAKE_NPC && tclass_ != HIDDEN_WARP_CLASS) { + if (map->getcell(tmapid, NULL, tx, ty, CELL_CHKNOPASS) > 0) { + ShowError("buildin_npc_duplicate: Invalid NPC Location. %s,%d,%d\n", tmap, tx, ty); + script_pushint(st, 0); + return false; + } + } +#endif + + if (tdir >= UNIT_DIR_MAX) { + ShowWarning("buildin_npc_duplicate: Invalid NPC direction %d. Default to %d.\n", tdir, (tdir % UNIT_DIR_MAX)); + tdir %= UNIT_DIR_MAX; // trim spin-over + } else if (tdir <= UNIT_DIR_UNDEFINED) { + ShowWarning("buildin_npc_duplicate: Invalid NPC direction %d. Default to %d.\n", tdir, 0); + tdir = 0; + } + + struct npc_data *nd_target = npc->create_npc(nd_source->subtype, tmapid, tx, ty, tdir, tclass_); + + if (nd_target == NULL) { + ShowError("buildin_npc_duplicate: Failed to duplicate NPC.\n"); + return false; + } + + safestrncpy(nd_target->name, targetname, sizeof(nd_target->name)); + safestrncpy(nd_target->exname, targetname, sizeof(nd_target->exname)); + + if (npc->duplicate_sub(nd_target, nd_source, txs, tys, NPO_ONINIT) == true) + script_pushint(st, 1); + else + script_pushint(st, 0); + + return true; +} + +/* + * npc_duplicate_remove({"<npc_name>"}); + * Return 1 on success, 0 if failed. + */ +BUILDIN(npc_duplicate_remove) +{ + struct npc_data *nd = map->id2nd(st->oid); + + if (script_hasdata(st, 2)) + nd = npc->name2id(script_getstr(st, 2)); + + if (nd == NULL) { + if (script_hasdata(st, 2)) { + ShowError("buildin_npc_duplicate_remove: NPC '%s' not found.\n", script_getstr(st, 2)); + } else { + ShowError("buildin_npc_duplicate_remove: NPC not found.\n"); + } + script_pushint(st, 0); + return false; + } + + if (nd->src_id == 0) { // remove all dupicates for this source npc + npc->unload_duplicates(nd); + } else if (nd != map->id2nd(st->oid)) { // just remove this duplicate NPC + npc->unload(nd, true); + } else { + // Same as "else if (!script_hasdata(st, 2))" + ShowError("buildin_npc_duplicate_remove: Cannot remove yourself.\n"); + script_pushint(st, 0); + return false; + } + + script_pushint(st, 1); + return true; +} + /*========================================== * Sends something over PyLog |