diff options
Diffstat (limited to 'src/emap/script_buildins.c')
-rw-r--r-- | src/emap/script_buildins.c | 1655 |
1 files changed, 1655 insertions, 0 deletions
diff --git a/src/emap/script_buildins.c b/src/emap/script_buildins.c new file mode 100644 index 0000000..05f6841 --- /dev/null +++ b/src/emap/script_buildins.c @@ -0,0 +1,1655 @@ +// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// Copyright (c) 2014 - 2015 Evol developers + +#include "common/hercules.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "common/HPMi.h" +#include "common/memmgr.h" +#include "common/utils.h" +#include "common/timer.h" +#include "map/chat.h" +#include "map/chrif.h" +#include "map/npc.h" +#include "map/pc.h" +#include "map/script.h" +#include "map/quest.h" + +#include "emap/clif.h" +#include "emap/craft.h" +#include "emap/lang.h" +#include "emap/map.h" +#include "emap/scriptdefines.h" +#include "emap/send.h" +#include "emap/data/bgd.h" +#include "emap/data/mapd.h" +#include "emap/data/session.h" +#include "emap/struct/bgdext.h" +#include "emap/struct/mapdext.h" +#include "emap/struct/sessionext.h" +#include "emap/utils/formatutils.h" + +extern int mountScriptId; + +uint32 MakeDWord(uint16 word0, uint16 word1) +{ + return ((uint32)(word0)) | ((uint32)(word1 << 0x10)); +} + +BUILDIN(l) +{ + format_sub(st, 1); + return true; +} + +BUILDIN(lg) +{ + format_sub(st, 2); + return true; +} + +BUILDIN(setCamNpc) +{ + getSD(); + TBL_NPC *nd = NULL; + + int x = 0; + int y = 0; + + if (script_hasdata(st, 2)) + { + nd = npc->name2id (script_getstr(st, 2)); + } + else + { + if (!st->oid) + { + ShowWarning("npc not attached\n"); + script->reportsrc(st); + return false; + } + + nd = map->id2nd(st->oid); + } + if (!nd) + { + ShowWarning("npc not found\n"); + script->reportsrc(st); + return false; + } + if (sd->bl.m != nd->bl.m) + { + ShowWarning("npc and player located in other maps\n"); + script->reportsrc(st); + return false; + } + + if (script_hasdata(st, 3) && script_hasdata(st, 4)) + { + x = script_getnum(st, 3); + y = script_getnum(st, 4); + } + + send_npccommand2(sd, st->oid, 2, nd->bl.id, x, y); + + return true; +} + +BUILDIN(setCam) +{ + send_npccommand2(script->rid2sd (st), st->oid, 2, 0, + script_getnum(st, 2), script_getnum(st, 3)); + + return true; +} + +BUILDIN(moveCam) +{ + send_npccommand2(script->rid2sd (st), st->oid, 4, 0, + script_getnum(st, 2), script_getnum(st, 3)); + + return true; +} + +BUILDIN(restoreCam) +{ + getSD(); + send_npccommand(sd, st->oid, 3); + return true; +} + +BUILDIN(npcTalk3) +{ + const char *msg; + + getSD(); + + TBL_NPC *nd = map->id2nd(st->oid); + const char *str = script_getstr(st, 2); + + if (!nd) + { + ShowWarning("npc not found\n"); + script->reportsrc(st); + return false; + } + + if (!str) + { + ShowWarning("error in string\n"); + script->reportsrc(st); + return false; + } + + if (sd) + msg = lang_pctrans (nd->name, sd); + else + msg = nd->name; + + if (!msg) + { + ShowWarning("error in string\n"); + script->reportsrc(st); + return false; + } + if (strlen(str) + strlen(msg) > 450) + { + ShowWarning("text message too big\n"); + script->reportsrc(st); + return false; + } + + if (nd) + { + char message[500]; + char name[500]; + strcpy (name, msg); + strtok(name, "#"); + strcpy (message, name); + strcat (message, " : "); + strcat (message, str); + send_local_message (sd->fd, &(nd->bl), message); + } + + return true; +} + +BUILDIN(closeDialog) +{ + getSD(); + send_npccommand(sd, st->oid, 5); + return true; +} + +BUILDIN(shop) +{ + getSD(); + TBL_NPC *nd = npc->name2id (script_getstr(st, 2)); + if (!nd) + { + ShowWarning("shop npc not found\n"); + script->reportsrc(st); + return false; + } + + st->state = sd->state.dialog == 1 ? CLOSE : END; + clif->scriptclose(sd, st->oid); + + clif->npcbuysell (sd, nd->bl.id); + return true; +} + +#define paramToItem(param) \ + if (script_isstringtype(st, param)) \ + { \ + i_data = itemdb->search_name (script_getstr(st, param)); \ + } \ + else \ + { \ + item_id = script_getnum (st, param); \ + if (item_id) \ + i_data = itemdb->search (item_id); \ + } + +BUILDIN(getItemLink) +{ + struct item_data *i_data = NULL; + char *item_name; + int item_id = 0; + + paramToItem(2); + + item_name = (char *) aCalloc (1000, sizeof (char)); + TBL_PC *sd = script->rid2sd(st); + + if (sd) + { + int version = 0; + struct SessionExt *data = session_get_bysd(sd); + if (data) + version = data->clientVersion; + + if (i_data && version >= 7) + { + if (!script_hasdata(st, 3)) + { + sprintf(item_name, "[@@%u|@@]", (unsigned)i_data->nameid); + } + else + { + sprintf(item_name, "[@@%u", (unsigned)i_data->nameid); + int f; + for (f = 3; f < 7 && script_hasdata(st, f); f ++) + { + paramToItem(f); + if (i_data) + { + char buf[100]; + sprintf(buf, ",%u", (unsigned)i_data->nameid); + strcat(item_name, buf); + } + } + strcat(item_name, "|@@]"); + } + } + else if (i_data) + { + sprintf(item_name, "[@@%u|%s@@]", (unsigned)i_data->nameid, lang_pctrans (i_data->jname, sd)); + } + else if (item_id > 0) + { + sprintf(item_name, "[@@%u|Unknown Item@@]", (unsigned)item_id); + } + else + { + sprintf(item_name, "[Unknown Item]"); + } + } + else + { + if (i_data) + sprintf(item_name, "[%s]", lang_pctrans (i_data->jname, sd)); + else + sprintf(item_name, "[Unknown Item]"); + } + + script_pushstr(st, item_name); + + return true; +} + +#undef paramToItem + +BUILDIN(requestLang) +{ + getSDReturn(-1); + + if (!sd->state.menu_or_input) + { + // first invocation, display npc input box + sd->state.menu_or_input = 1; + st->state = RERUNLINE; + + // send lang request + send_npccommand(sd, st->oid, 0); + clif->scriptinputstr(sd, st->oid); + } + else + { + // take received text/value and store it in the designated variable + sd->state.menu_or_input = 0; + + int lng = -1; + if (*sd->npc_str) + lng = lang_getId(sd->npc_str); + script_pushint(st, lng); + st->state = RUN; + } + return true; +} + +BUILDIN(requestItem) +{ + getSDReturn(0); + + if (!sd->state.menu_or_input) + { + // first invocation, display npc input box + sd->state.menu_or_input = 1; + st->state = RERUNLINE; + + // send item request + send_npccommand(sd, st->oid, 10); + } + else + { + // take received text/value and store it in the designated variable + sd->state.menu_or_input = 0; + + int item = 0; + + if (!sd->npc_str) + { + ShowWarning("npc string not found\n"); + script_pushint(st, 0); + script->reportsrc(st); + return false; + } + + if (sscanf (sd->npc_str, "%5d", &item) < 1) + { + ShowWarning("input data is not item id\n"); + script_pushint(st, 0); + script->reportsrc(st); + return false; + } + + script_pushint(st, item); + st->state = RUN; + } + return true; +} + +BUILDIN(requestItems) +{ + getSDReturnS("0,0"); + int count = 1; + + if (script_hasdata(st, 2)) + { + count = script_getnum(st, 2); + if (count < 0) + count = 1; + } + + if (!sd->state.menu_or_input) + { + // first invocation, display npc input box + sd->state.menu_or_input = 1; + st->state = RERUNLINE; + + // send item request with limit count + send_npccommand2(sd, st->oid, 10, count, 0, 0); + } + else + { + // take received text/value and store it in the designated variable + sd->state.menu_or_input = 0; + + if (!sd->npc_str) + { + ShowWarning("npc string not found\n"); + script_pushstr(st, aStrdup("0,0")); + script->reportsrc(st); + return false; + } + + script_pushstr(st, aStrdup(sd->npc_str)); + st->state = RUN; + } + return true; +} + +BUILDIN(requestItemIndex) +{ + getSessionDataReturn(client, -1); + + if (!sd->state.menu_or_input) + { + // first invocation, display npc input box + sd->state.menu_or_input = 1; + st->state = RERUNLINE; + + // send item request + if (client || client->clientVersion >= 11) + send_npccommand(sd, st->oid, 11); + else + clif->scriptinputstr(sd, st->oid); + } + else + { + // take received text/value and store it in the designated variable + sd->state.menu_or_input = 0; + + int item = -1; + + if (!sd->npc_str) + { + script_pushint(st, -1); + ShowWarning("npc string not found\n"); + script->reportsrc(st); + return false; + } + + if (sscanf (sd->npc_str, "%5d", &item) < 1) + { + script_pushint(st, -1); + ShowWarning("input data is not item id\n"); + script->reportsrc(st); + return false; + } + + script_pushint(st, item); + st->state = RUN; + } + return true; +} + +BUILDIN(requestItemsIndex) +{ + getSessionDataReturnS(client, "-1"); + int count = 1; + + if (script_hasdata(st, 2)) + { + count = script_getnum(st, 2); + if (count < 0) + count = 1; + } + + if (!sd->state.menu_or_input) + { + // first invocation, display npc input box + sd->state.menu_or_input = 1; + st->state = RERUNLINE; + + // send item request with limit count + if (client || client->clientVersion >= 11) + send_npccommand2(sd, st->oid, 11, count, 0, 0); + else + clif->scriptinputstr(sd, st->oid); + } + else + { + // take received text/value and store it in the designated variable + sd->state.menu_or_input = 0; + + if (!sd->npc_str) + { + script_pushstr(st, aStrdup("-1")); + ShowWarning("npc string not found\n"); + script->reportsrc(st); + return false; + } + + script_pushstr(st, aStrdup(sd->npc_str)); + st->state = RUN; + } + return true; +} + +BUILDIN(requestCraft) +{ + getSessionData(client); + + int count = 1; + + if (script_hasdata(st, 2)) + { + count = script_getnum(st, 2); + if (count < 0) + count = 1; + } + + if (!sd->state.menu_or_input) + { + // first invocation, display npc input box + sd->state.menu_or_input = 1; + st->state = RERUNLINE; + + // send item request with limit count + if (client || client->clientVersion >= 16) + send_npccommand2(sd, st->oid, 12, count, 0, 0); + else + clif->scriptinputstr(sd, st->oid); + } + else + { + // take received text/value and store it in the designated variable + sd->state.menu_or_input = 0; + + if (!sd->npc_str) + { + ShowWarning("npc string not found\n"); + script->reportsrc(st); + script_pushstr(st, aStrdup("")); + return false; + } + + script_pushstr(st, aStrdup(sd->npc_str)); + st->state = RUN; + } + return true; +} + +BUILDIN(setq) +{ + int i; + getSD(); + + int quest_id = script_getnum(st, 2); + int quest_value = script_getnum(st, 3); + + if (quest->check(sd, quest_id, HAVEQUEST) < 0) + quest->add(sd, quest_id); + ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id); + if (i == sd->num_quests) + { + ShowError("Quest with id=%d not found\n", quest_id); + script->reportsrc(st); + return false; + } + + sd->quest_log[i].count[0] = quest_value; + sd->save_quest = true; + if (map->save_settings & 64) + chrif->save(sd,0); + + eclif_quest_add(sd, &sd->quest_log[i]); + return true; +} + +BUILDIN(getq) +{ + int i; + getSDReturn(0); + + int quest_id = script_getnum(st, 2); + if (quest->check(sd, quest_id, HAVEQUEST) < 0) + { + script_pushint(st, 0); + return true; + } + ARR_FIND(0, sd->num_quests, i, sd->quest_log[i].quest_id == quest_id); + if (i == sd->num_quests) + { + script_pushint(st, 0); + return true; + } + script_pushint(st, sd->quest_log[i].count[0]); + return true; +} + +BUILDIN(setNpcDir) +{ + int newdir; + TBL_NPC *nd = 0; + + if (script_hasdata(st, 3)) + { + nd = npc->name2id (script_getstr(st, 2)); + newdir = script_getnum(st, 3); + } + else if (script_hasdata(st, 2)) + { + if (!st->oid) + { + ShowWarning("npc not found\n"); + script->reportsrc(st); + return false; + } + + nd = map->id2nd(st->oid); + newdir = script_getnum(st, 2); + } + if (!nd) + { + ShowWarning("npc not found\n"); + script->reportsrc(st); + return false; + } + + if (newdir < 0) + newdir = 0; + else if (newdir > 7) + newdir = 7; + + nd->dir = newdir; + npc->enable (nd->name, 1); + + return true; +} + +BUILDIN(rif) +{ + const char *str = 0; + if (script_getnum(st, 2)) + { + str = script_getstr(st, 3); + if (str) + script_pushstr(st, aStrdup(str)); + else + script_pushconststr(st, (char *)""); + } + else if (script_hasdata(st, 4)) + { + str = script_getstr(st, 4); + if (str) + script_pushstr(st, aStrdup(str)); + else + script_pushconststr(st, (char *)""); + } + else + { + script_pushconststr(st, (char *)""); + } + + return true; +} + +BUILDIN(miscEffect) +{ + int type = script_getnum(st, 2); + struct block_list *bl = NULL; + + if (script_hasdata(st, 3)) + { + if (script_isstring(st, 3)) + { + TBL_PC *sd = map->nick2sd(script_getstr(st, 3)); + if (sd) + bl = &sd->bl; + } + else if (script_isint(st, 3)) + { + bl = map->id2bl(script_getnum(st, 3)); + } + } + + if (!bl) + { + TBL_PC *sd = script->rid2sd (st); + if (sd) + bl = &sd->bl; + } + if (bl) + clif->specialeffect(bl, type, AREA); + return true; +} + +BUILDIN(setMapMask) +{ + const char *const mapName = script_getstr(st, 2); + if (!mapName) + { + ShowWarning("invalid map name\n"); + script->reportsrc(st); + return false; + } + const int m = map->mapname2mapid(mapName); + if (m < 0) + { + ShowWarning("map not found\n"); + script->reportsrc(st); + return false; + } + getMapData(m); + + const int val = script_getnum(st, 3); + const unsigned int old = mapData->mask; + mapData->mask = val; + if (old != mapData->mask) + send_mapmask_brodcast(m, mapData->mask); + return true; +} + +BUILDIN(getMapMask) +{ + const char *const mapName = script_getstr(st, 2); + if (!mapName) + { + script_pushint(st, 0); + ShowWarning("invalid map name\n"); + script->reportsrc(st); + return false; + } + const int m = map->mapname2mapid(mapName); + if (m < 0) + { + script_pushint(st, 0); + ShowWarning("map not found\n"); + script->reportsrc(st); + return false; + } + getMapDataReturn(m, 0); + script_pushint(st, mapData->mask); + return true; +} + +BUILDIN(addMapMask) +{ + const char *const mapName = script_getstr(st, 2); + if (!mapName) + { + ShowWarning("invalid map name\n"); + script->reportsrc(st); + return false; + } + const int m = map->mapname2mapid(mapName); + if (m < 0) + { + ShowWarning("map not found\n"); + script->reportsrc(st); + return false; + } + getMapData(m); + const int val = script_getnum(st, 3); + const unsigned int old = mapData->mask; + mapData->mask |= val; + if (old != mapData->mask) + send_mapmask_brodcast(m, mapData->mask); + + return true; +} + +BUILDIN(removeMapMask) +{ + const char *const mapName = script_getstr(st, 2); + if (!mapName) + { + ShowWarning("invalid map name\n"); + script->reportsrc(st); + return true; + } + const int m = map->mapname2mapid(mapName); + if (m < 0) + { + ShowWarning("map not found\n"); + script->reportsrc(st); + return false; + } + getMapData(m); + const int val = script_getnum(st, 3); + const unsigned int old = mapData->mask; + mapData->mask |= val; + mapData->mask ^= val; + if (old != mapData->mask) + send_mapmask_brodcast(m, mapData->mask); + return true; +} + +BUILDIN(setNpcSex) +{ + TBL_NPC *nd = NULL; + int sex = 0; + if (script_hasdata(st, 3)) + { + nd = npc->name2id (script_getstr(st, 2)); + sex = script_getnum(st, 3); + } + + if (!nd || !nd->vd) + { + ShowWarning("npc not found\n"); + script->reportsrc(st); + return false; + } + + clif->clearunit_area(&nd->bl, CLR_OUTSIGHT); + nd->vd->sex = sex; + clif->spawn(&nd->bl); + return true; +} + +BUILDIN(showAvatar) +{ + int id = 0; + if (script_hasdata(st, 2)) + id = script_getnum(st, 2); + + send_npccommand2(script->rid2sd (st), st->oid, 6, id, 0, 0); + return true; +} + +BUILDIN(setAvatarDir) +{ + int newdir = script_getnum(st, 2); + + if (newdir < 0) + newdir = 0; + else if (newdir > 7) + newdir = 7; + + send_npccommand2(script->rid2sd (st), st->oid, 7, newdir, 0, 0); + return true; +} + +BUILDIN(setAvatarAction) +{ + send_npccommand2(script->rid2sd (st), st->oid, 8, script_getnum(st, 2), 0, 0); + return true; +} + +BUILDIN(clear) +{ + send_npccommand(script->rid2sd (st), st->oid, 9); + return true; +} + +BUILDIN(changeMusic) +{ + const char *const mapName = script_getstr(st, 2); + const char *const music = script_getstr(st, 3); + if (!music) + { + ShowWarning("invalid music file\n"); + script->reportsrc(st); + return false; + } + if (!mapName) + { + ShowWarning("invalid map file\n"); + script->reportsrc(st); + return false; + } + const int m = map->mapname2mapid(mapName); + if (m < 0) + { + ShowWarning("map not found\n"); + script->reportsrc(st); + return false; + } + + send_changemusic_brodcast(m, music); + return true; +} + +BUILDIN(setNpcDialogTitle) +{ + const char *const name = script_getstr(st, 2); + if (!name) + { + ShowWarning("invalid window title\n"); + script->reportsrc(st); + return false; + } + TBL_PC *sd = script->rid2sd (st); + if (!sd) + { + ShowWarning("player not attached\n"); + script->reportsrc(st); + return false; + } + + send_changenpc_title(sd, st->oid, name); + return true; +} + +BUILDIN(getMapName) +{ + TBL_PC *sd = script->rid2sd(st); + if (!sd) + { + script_pushstr(st, aStrdup("")); + ShowWarning("player not attached\n"); + script->reportsrc(st); + return false; + } + if (sd->bl.m == -1) + { + script_pushstr(st, aStrdup("")); + ShowWarning("invalid map\n"); + script->reportsrc(st); + return false; + } + script_pushstr(st, aStrdup(map->list[sd->bl.m].name)); + return true; +} + +BUILDIN(unequipById) +{ + int nameid = 0; + int i; + struct item_data *item_data; + TBL_PC *sd = script->rid2sd(st); + + if (sd == NULL) + { + ShowWarning("player not attached\n"); + script->reportsrc(st); + return false; + } + + nameid = script_getnum(st, 2); + if((item_data = itemdb->exists(nameid)) == NULL) + { + ShowWarning("item %d not found\n", nameid); + script->reportsrc(st); + return false; + } + for (i = 0; i < EQI_MAX; i++) + { + const int idx = sd->equip_index[i]; + if (idx >= 0) + { + if (sd->status.inventory[idx].nameid == nameid) + pc->unequipitem(sd, idx, 1 | 2); + } + } + return true; +} + +BUILDIN(isPcDead) +{ + TBL_PC *sd = script->rid2sd(st); + + if (sd == NULL) + { + ShowWarning("player not attached\n"); + script->reportsrc(st); + return false; + } + + script_pushint(st, pc_isdead(sd) ? 1 : 0); + return true; +} + +static int areatimer_sub(struct block_list *bl, va_list ap) +{ + int tick; + char *event; + TBL_PC *sd; + + tick = va_arg(ap, int); + event = va_arg(ap, char*); + + sd = (TBL_PC *)bl; + if (!pc->addeventtimer(sd, tick, event)) + { + if (sd) + ShowWarning("buildin_addtimer: Event timer is full, can't add new event timer. (cid:%d timer:%s)\n", sd->status.char_id, event); + } + return 0; +} + +BUILDIN(areaTimer) +{ + const char *const mapname = script_getstr(st, 2); + const int x1 = script_getnum(st, 3); + const int y1 = script_getnum(st, 4); + const int x2 = script_getnum(st, 5); + const int y2 = script_getnum(st, 6); + const int time = script_getnum(st, 7); + const char *const eventName = script_getstr(st, 8); + int m; + + if ((m = map->mapname2mapid(mapname)) < 0) + { + ShowWarning("map not found\n"); + script->reportsrc(st); + return false; + } + + map->foreachinarea(areatimer_sub, m, x1, y1, x2, y2, BL_PC, time, eventName); + + return true; +} + +static int buildin_getareadropitem_sub_del(struct block_list *bl, va_list ap) +{ + if (!bl) + return 0; + + const int item = va_arg(ap, int); + int *const amount = va_arg(ap, int *); + TBL_ITEM *drop = (TBL_ITEM *)bl; + + if (drop->item_data.nameid == item) + { + (*amount) += drop->item_data.amount; + map->clearflooritem(&drop->bl); + } + + return 0; +} + +BUILDIN(getAreaDropItem) +{ + const char *const str = script_getstr(st, 2); + int16 m; + int x0 = script_getnum(st, 3); + int y0 = script_getnum(st, 4); + int x1 = script_getnum(st, 5); + int y1 = script_getnum(st, 6); + int item; + int amount = 0; + + if (script_isstringtype(st, 7)) + { + const char *name = script_getstr(st, 7); + struct item_data *item_data = itemdb->search_name(name); + item = UNKNOWN_ITEM_ID; + if (item_data) + item = item_data->nameid; + } + else + { + item = script_getnum(st, 7); + } + + if ((m = map->mapname2mapid(str)) < 0) + { + script_pushint(st, -1); + ShowWarning("map not found\n"); + script->reportsrc(st); + return false; + } + + if (script_hasdata(st, 8) && script_getnum(st, 8)) + { + map->foreachinarea(buildin_getareadropitem_sub_del, + m, x0, y0, x1, y1, BL_ITEM, item, &amount); + } + else + { + map->foreachinarea(script->buildin_getareadropitem_sub, + m, x0, y0, x1, y1, BL_ITEM, item, &amount); + } + script_pushint(st, amount); + return true; +} + +BUILDIN(clientCommand) +{ + getSD(); + + const char *const command = script_getstr(st, 2); + if (!command) + { + ShowWarning("invalid client command\n"); + script->reportsrc(st); + return false; + } + send_client_command(sd, command); + return true; +} + +BUILDIN(isUnitWalking) +{ + int id = 0; + if (script_hasdata(st, 2)) + id = script_getnum(st, 2); + else + id = st->oid; + struct block_list *bl = map->id2bl(id); + if (!bl) + { + ShowWarning("invalid unit id\n"); + script->reportsrc(st); + script_pushint(st, 0); + return false; + } + struct unit_data *ud = unit->bl2ud(bl); + if (!ud) + { + ShowWarning("invalid unit data\n"); + script->reportsrc(st); + script_pushint(st, 0); + return false; + } + script_pushint(st, ud->walktimer != INVALID_TIMER); + return true; +} + +BUILDIN(failedRefIndex) +{ + getSD() + getInventoryIndex(2) + + if (sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0) + return false; + + sd->status.inventory[n].refine = 0; + if (sd->status.inventory[n].equip) + pc->unequipitem(sd, n, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); + clif->refine(sd->fd, 1, n, sd->status.inventory[n].refine); + pc->delitem(sd, n, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT); + clif->misceffect(&sd->bl, 2); + return true; +} + +BUILDIN(downRefIndex) +{ + getSD() + getInventoryIndex(2) + + if (sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0) + return false; + + const int down = script_getnum(st, 3); + + logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[n], sd->inventory_data[n]); + + if (sd->status.inventory[n].equip) + pc->unequipitem(sd, n, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); + sd->status.inventory[n].refine -= down; + sd->status.inventory[n].refine = cap_value(sd->status.inventory[n].refine, 0, MAX_REFINE); + + clif->refine(sd->fd, 2, n, sd->status.inventory[n].refine); + clif->delitem(sd, n, 1, DELITEM_MATERIALCHANGE); + logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[n], sd->inventory_data[n]); + clif->additem(sd, n, 1, 0); + clif->misceffect(&sd->bl, 2); + return true; +} + +BUILDIN(successRefIndex) +{ + getSD() + getInventoryIndex(2) + + if (sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0) + return false; + + const int up = script_getnum(st, 3); + + logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[n],sd->inventory_data[n]); + + if (sd->status.inventory[n].refine >= MAX_REFINE) + return true; + + sd->status.inventory[n].refine += up; + sd->status.inventory[n].refine = cap_value( sd->status.inventory[n].refine, 0, MAX_REFINE); + if (sd->status.inventory[n].equip) + pc->unequipitem(sd, n, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); + clif->refine(sd->fd, 0, n, sd->status.inventory[n].refine); + clif->delitem(sd, n, 1, DELITEM_MATERIALCHANGE); + logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[n],sd->inventory_data[n]); + clif->additem(sd, n, 1, 0); + clif->misceffect(&sd->bl, 3); + + if (sd->status.inventory[n].refine == 10 && + sd->status.inventory[n].card[0] == CARD0_FORGE && + sd->status.char_id == (int)MakeDWord(sd->status.inventory[n].card[2], sd->status.inventory[n].card[3])) + { // Fame point system [DracoRPG] + switch (sd->inventory_data[n]->wlv) + { + case 1: + pc->addfame(sd,1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point + break; + case 2: + pc->addfame(sd,25); // Success to refine to +10 a lv2 weapon you forged = +25 fame point + break; + case 3: + pc->addfame(sd,1000); // Success to refine to +10 a lv3 weapon you forged = +1000 fame point + break; + } + } + + return true; +} + +// return paramater type +// 0 - int +// 1 - string +// 2 - other +BUILDIN(isStr) +{ + if (script_isinttype(st, 2)) + script_pushint(st, 0); + else if (script_isstringtype(st, 2)) + script_pushint(st, 1); + else + script_pushint(st, 2); + return true; +} + +BUILDIN(npcSit) +{ + TBL_NPC *nd = NULL; + + if (script_hasdata(st, 2)) + { + nd = npc->name2id (script_getstr(st, 2)); + } + else + { + if (!st->oid) + { + ShowWarning("npc not attached\n"); + script->reportsrc(st); + return false; + } + + nd = map->id2nd(st->oid); + } + if (!nd) + { + ShowWarning("npc not found\n"); + script->reportsrc(st); + return false; + } + nd->vd->dead_sit = 2; + clif->sitting(&nd->bl); + return true; +} + +BUILDIN(npcStand) +{ + TBL_NPC *nd = NULL; + + if (script_hasdata(st, 2)) + { + nd = npc->name2id (script_getstr(st, 2)); + } + else + { + if (!st->oid) + { + ShowWarning("npc not attached\n"); + script->reportsrc(st); + return false; + } + + nd = map->id2nd(st->oid); + } + if (!nd) + { + ShowWarning("npc not found\n"); + script->reportsrc(st); + return false; + } + nd->vd->dead_sit = 0; + clif->standing(&nd->bl); + return true; +} + +BUILDIN(npcWalkTo) +{ + struct npc_data *nd = map->id2nd(st->oid); + int x = 0, y = 0; + + x = script_getnum(st, 2); + y = script_getnum(st, 3); + + if (nd) + { + unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit + if (!nd->status.hp) + { + status_calc_npc(nd, SCO_FIRST); + } + else + { + status_calc_npc(nd, SCO_NONE); + } + nd->vd->dead_sit = 0; + unit->walktoxy(&nd->bl,x,y,0); + } + else + { + ShowWarning("npc not found\n"); + script->reportsrc(st); + return false; + } + + return true; +} + +BUILDIN(setBgTeam) +{ + int bgId = script_getnum(st, 2); + int teamId = script_getnum(st, 3); + + struct battleground_data *bgd = bg->team_search(bgId); + struct BgdExt *data = bgd_get(bgd); + if (!data) + { + ShowWarning("bettle ground not found\n"); + script->reportsrc(st); + return false; + } + + data->teamId = teamId; + return true; +} + +// chatjoin chatId [,char [,password]] +BUILDIN(chatJoin) +{ + int chatId = script_getnum(st, 2); + TBL_PC *sd = NULL; + const char *password = ""; + if (script_hasdata(st, 4)) + { + if (script_isstringtype(st, 3)) + sd = map->nick2sd(script_getstr(st, 3)); + if (script_isstringtype(st, 4)) + password = script_getstr(st, 4); + } + else if (script_hasdata(st, 3)) + { + if (script_isstringtype(st, 3)) + sd = map->nick2sd(script_getstr(st, 3)); + } + else + { + sd = script->rid2sd(st); + } + if (!sd) + { + ShowWarning("player not found\n"); + script->reportsrc(st); + return false; + } + + chat->join(sd, chatId, password); + return true; +} + +/// Retrieves the value of the specified flag of the specified cell. +/// +/// checknpccell("<map name>",<x>,<y>,<type>) -> <bool> +/// +/// @see cell_chk* constants in const.txt for the types +BUILDIN(checkNpcCell) +{ + int16 m = map->mapname2mapid(script_getstr(st, 2)); + int16 x = script_getnum(st, 3); + int16 y = script_getnum(st, 4); + cell_chk type = (cell_chk)script_getnum(st, 5); + + if (m == -1) + { + ShowWarning("checknpccell: Attempted to run on unexsitent map '%s', type %u, x/y %d,%d\n", script_getstr(st, 2), type, x, y); + return true; + } + + TBL_NPC *nd = map->id2nd(st->oid); + struct block_list *bl = NULL; + if (nd) + bl = &nd->bl; + + script_pushint(st, map->getcell(m, bl, x, y, type)); + + return true; +} + +BUILDIN(setCells) +{ + int m; + + const char *mapname = script_getstr(st, 2); + int x1 = script_getnum(st, 3); + int y1 = script_getnum(st, 4); + int x2 = script_getnum(st, 5); + int y2 = script_getnum(st, 6); + int mask = script_getnum(st, 7); + const char *name = script_getstr(st, 8); + + if ((m = map->mapname2mapid(mapname)) < 0) + return true; // Invalid Map + + emap_iwall_set2(m, 0, x1, y1, x2, y2, mask, name); + + return true; +} + +BUILDIN(delCells) +{ + const char *name = script_getstr(st,2); + map->iwall_remove(name); + return true; +} + +BUILDIN(setMount) +{ + getSD() + int mount = script_getnum(st, 2); + pc_setglobalreg(sd, mountScriptId, mount); + status_calc_pc(sd, SCO_NONE); + send_pc_info(&sd->bl, &sd->bl, AREA); + return true; +} + +BUILDIN(setSkin) +{ + if (!st->oid) + return false; + + getSD() + + const char *skin = script_getstr(st, 2); + send_pc_skin(sd->fd, st->oid, skin); + return true; +} + +BUILDIN(initCraft) +{ + getSDReturn(-1) + + int var = str_to_craftvar(sd, script_getstr(st, 2)); + script_pushint(st, var); + return true; +} + +BUILDIN(dumpCraft) +{ + getSD() + + craft_dump(sd, script_getnum(st, 2)); + return true; +} + +BUILDIN(deleteCraft) +{ + getSD() + + craft_delete(script_getnum(st, 2)); + return true; +} + +BUILDIN(getCraftSlotId) +{ + getSDReturn(0) + + const struct craft_slot *crslot = craft_get_slot(script_getnum(st, 2), + script_getnum(st, 3)); + if (!crslot) + return false; + const int len = VECTOR_LENGTH(crslot->items); + if (len > 0) + { + struct item_pair *pair = &VECTOR_INDEX(crslot->items, 0); + const int invIndex = pair->index; + const int item_id = sd->status.inventory[invIndex].nameid; + script_pushint(st, item_id); + } + else + { + script_pushint(st, 0); + } + return true; +} + +BUILDIN(getCraftSlotAmount) +{ + getSDReturn(0) + + const struct craft_slot *crslot = craft_get_slot(script_getnum(st, 2), + script_getnum(st, 3)); + if (!crslot) + return false; + const int len = VECTOR_LENGTH(crslot->items); + if (len > 0) + { + int slot; + int amount = 0; + for (slot = 0; slot < len; slot ++) + { + struct item_pair *pair = &VECTOR_INDEX(crslot->items, slot); + const int invIndex = pair->index; + const int item_id = sd->status.inventory[invIndex].nameid; + if (item_id > 0) + { + const int item_amount = sd->status.inventory[invIndex].amount; + if (item_amount > 0) + amount += pair->amount; + } + } + script_pushint(st, amount); + } + else + { + script_pushint(st, 0); + } + return true; +} + +BUILDIN(validateCraft) +{ + getSDReturn(0) + const bool valid = craft_validate(sd, script_getnum(st, 2)); + script_pushint(st, valid ? 1 : 0); + return true; +} + +BUILDIN(findCraftEntry) +{ + getSDReturn(-1) + const int id = craft_find_entry(sd, + script_getnum(st, 2), + script_getnum(st, 3)); + script_pushint(st, id); + return true; +} + +BUILDIN(useCraft) +{ + getSD() + return craft_use(sd, script_getnum(st, 2)); +} + +BUILDIN(getCraftCode) +{ + getSDReturn(-1) + script_pushint(st, craft_get_entry_code(sd, script_getnum(st, 2))); + return true; +} + +BUILDIN(getInvIndexLink) +{ + getSDReturnS("") + + int index = script_getnum (st, 2); + + if (index < 0 || index >= MAX_INVENTORY) + { + script_pushstr(st, ""); + return false; + } + + const int item_id = sd->status.inventory[index].nameid; + const struct item_data *i_data = NULL; + if (item_id) + i_data = itemdb->search(item_id); + char *const item_name = (char *) aCalloc (1000, sizeof (char)); + + if (sd) + { + int version = 0; + struct SessionExt *data = session_get_bysd(sd); + if (data) + version = data->clientVersion; + + if (i_data && version >= 7) + { + const struct item *const item = &sd->status.inventory[index]; + if (item->card[0] == CARD0_PET || + item->card[0] == CARD0_FORGE || + item->card[0] == CARD0_CREATE) + { + sprintf(item_name, "[@@%u|@@]", (unsigned)i_data->nameid); + } + else + { + sprintf(item_name, "[@@%u", (unsigned)i_data->nameid); + int f; + for (f = 0; f < 4 && item->card[f]; f ++) + { + char buf[100]; + sprintf(buf, ",%u", (unsigned)item->card[f]); + strcat(item_name, buf); + } + strcat(item_name, "|@@]"); + } + } + else if (i_data) + { + sprintf(item_name, "[@@%u|%s@@]", (unsigned)i_data->nameid, lang_pctrans (i_data->jname, sd)); + } + else if (item_id > 0) + { + sprintf(item_name, "[@@%u|Unknown Item@@]", (unsigned)item_id); + } + else + { + sprintf(item_name, "[Unknown Item]"); + } + } + else + { + if (i_data) + sprintf(item_name, "[%s]", lang_pctrans (i_data->jname, sd)); + else + sprintf(item_name, "[Unknown Item]"); + } + + script_pushstr(st, item_name); + + return true; +} + +/*========================================== + * Shows an emoticon on top of the player/npc + * emotion emotion#, <target: 0 - NPC, 1 - PC>, <NPC/PC name> + *------------------------------------------*/ +//Optional second parameter added by [Skotlex] +BUILDIN(emotion) +{ + int player = 0; + + int type = script_getnum(st, 2); + + if (script_hasdata(st, 3)) + player = script_getnum(st, 3); + + if (player != 0) + { + struct map_session_data *sd = NULL; + if (script_hasdata(st, 4)) + sd = script->nick2sd(st, script_getstr(st, 4)); + else + sd = script->rid2sd(st); + if (sd != NULL) + clif->emotion(&sd->bl, type); + } + else if (script_hasdata(st, 4)) + { + struct npc_data *nd = npc->name2id(script_getstr(st, 4)); + if (nd != NULL) + clif->emotion(&nd->bl,type); + } + else + { + clif->emotion(map->id2bl(st->oid), type); + } + return true; +} + +BUILDIN(setLook) +{ + const int type = script_getnum(st, 2); + const int val = script_getnum(st, 3); + + struct map_session_data *sd = script->rid2sd(st); + if (sd == NULL) + return true; + + pc->changelook(sd, type, val); + send_changelook2(sd, &sd->bl, sd->bl.id, type, val, 0, NULL, 0, AREA); + return true; +} |