// Copyright (c) Copyright (c) Hercules Dev Team, licensed under GNU GPL. // Copyright (c) 2014 Evol developers #include "common/hercules.h" #include #include #include #include "common/HPMi.h" #include "common/malloc.h" #include "common/mmo.h" #include "common/utils.h" #include "common/socket.h" #include "common/strlib.h" #include "common/timer.h" #include "map/chrif.h" #include "map/clif.h" #include "map/npc.h" #include "map/pc.h" #include "map/script.h" #include "map/quest.h" #include "map/unit.h" #include "emap/script.h" #include "emap/clif.h" #include "emap/lang.h" #include "emap/scriptdefines.h" #include "emap/send.h" #include "emap/data/bgd.h" #include "emap/data/mapd.h" #include "emap/data/npcd.h" #include "emap/data/session.h" #include "emap/struct/bgdext.h" #include "emap/struct/mapdext.h" #include "emap/struct/npcdext.h" #include "emap/struct/sessionext.h" #include "emap/utils/formatutils.h" #define getExt() \ TBL_NPC *nd = map->id2nd(st->oid); \ if (!nd) \ return; \ struct NpcdExt *ext = npcd_get(nd); \ if (!ext) \ return #define getExtRet(r) \ TBL_NPC *nd = map->id2nd(st->oid); \ if (!nd) \ return r; \ struct NpcdExt *ext = npcd_get(nd); \ if (!ext) \ return r void escript_set_reg_npc_num(struct script_state* st, struct reg_db *n, int64 *num, const char* name, int *val) { if (!strcmp(name, ".lang")) { getExt(); ext->language = *val; hookStop(); } else if (!strcmp(name, ".sex")) { getND(); clif->clearunit_area(&nd->bl, CLR_OUTSIGHT); nd->vd->sex = *val; clif->spawn(&nd->bl); hookStop(); } else if (!strcmp(name, ".distance")) { getND(); nd->area_size = *val; hookStop(); } else if (!strcmp(name, ".dir")) { getND(); int newdir = *val; if (newdir < 0) newdir = 0; else if (newdir > 7) newdir = 7; nd->dir = newdir; npc->enable(nd->name, 1); hookStop(); } else if (!strcmp(name, ".x")) { ShowWarning("you cant assign '.x'\n"); script->reportsrc(st); hookStop(); } else if (!strcmp(name, ".y")) { ShowWarning("you cant assign '.y'.\n"); script->reportsrc(st); hookStop(); } else if (!strcmp(name, ".class")) { getND(); int class_ = *val; if (nd->class_ != class_) npc->setclass(nd, class_); hookStop(); } else if (!strcmp(name, ".speed")) { getND(); unit->bl2ud2(&nd->bl); // ensure nd->ud is safe to edit nd->speed = *val; nd->ud->state.speed_changed = 1; hookStop(); } else if (!strcmp(name, ".chat")) { ShowWarning("you cant assign '.chat'.\n"); script->reportsrc(st); hookStop(); } else if (!strcmp(name, ".sit")) { getND(); nd->vd->dead_sit = (*val) ? 2 : 0; clif->sitting(&nd->bl); hookStop(); } else if (!strcmp(name, ".stand")) { getND(); nd->vd->dead_sit = (*val) ? 0 : 2; clif->sitting(&nd->bl); hookStop(); } } int escript_get_val_npcscope_num(struct script_state* st, struct reg_db *n, struct script_data* data) { const char *name = reference_getname(data); if (!strcmp(name, ".lang")) { getExtRet(0); hookStop(); return ext->language; } else if (!strcmp(name, ".sex")) { getNDReturn(0); hookStop(); return nd->vd->sex; } else if (!strcmp(name, ".distance")) { getNDReturn(0); hookStop(); return nd->area_size; } else if (!strcmp(name, ".dir")) { getNDReturn(0); hookStop(); return nd->dir; } else if (!strcmp(name, ".x")) { getNDReturn(0); hookStop(); return nd->bl.x; } else if (!strcmp(name, ".y")) { getNDReturn(0); hookStop(); return nd->bl.y; } else if (!strcmp(name, ".class")) { getNDReturn(0); hookStop(); return nd->class_; } else if (!strcmp(name, ".speed")) { getNDReturn(0); hookStop(); return nd->speed; } else if (!strcmp(name, ".chat")) { getNDReturn(0); hookStop(); return nd->chat_id; } else if (!strcmp(name, ".sit")) { getNDReturn(0); hookStop(); return nd->vd->dead_sit == 2 ? 1 : 0; } else if (!strcmp(name, ".stand")) { getNDReturn(0); hookStop(); return nd->vd->dead_sit == 0 ? 1 : 0; } return 0; } void escript_set_reg_npc_str(struct script_state* st, struct reg_db *n, int64 *num, const char* name, const char *str) { if (!strcmp(name, ".map$")) { ShowWarning("you cant assign '.map$'.\n"); script->reportsrc(st); hookStop(); } else if (!strcmp(name, ".name$")) { getND(); npc->setdisplayname(nd, str); // not working because cant sent brodcast with translated npc name. need add for_each function for this. // clif->clearunit_area(&nd->bl, CLR_OUTSIGHT); // safestrncpy(nd->name, str, sizeof(nd->name)); // clif->spawn(&nd->bl); hookStop(); } else if (!strcmp(name, ".extname$")) { ShowWarning("you cant assign '.extname$'.\n"); script->reportsrc(st); hookStop(); } } char *escript_get_val_npcscope_str(struct script_state* st, struct reg_db *n, struct script_data* data) { const char *name = reference_getname(data); if (!strcmp(name, ".map$")) { getNDReturn(0); hookStop(); return map->list[nd->bl.m].name; } else if (!strcmp(name, ".name$")) { getNDReturn(0); hookStop(); return nd->name; } else if (!strcmp(name, ".extname$")) { getNDReturn(0); hookStop(); return nd->exname; } return NULL; } 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 = (TBL_NPC *) map->id2bl (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 *str; char *msg; TBL_NPC *nd = NULL; getSD(); if (script_hasdata(st, 3)) { nd = npc->name2id (script_getstr(st, 2)); str = script_getstr(st, 3); } else { nd = (TBL_NPC *) map->id2bl (st->oid); 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 = (char*)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; } BUILDIN(getItemLink) { struct item_data *i_data; char *item_name; int item_id = 0; if (script_isstringtype(st, 2)) { i_data = itemdb->search_name (script_getstr(st, 2)); } else { item_id = script_getnum (st, 2); i_data = itemdb->search (item_id); } item_name = (char *) aCalloc (100, 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) sprintf(item_name, "[@@%u|@@]", (unsigned)i_data->nameid); 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; } BUILDIN(requestLang) { getSD(); struct script_data* data; int64 uid; const char* name; data = script_getdata(st, 2); if (!data_isreference(data)) { ShowError("script:requestlang: not a variable\n"); script->reportsrc(st); st->state = END; return false; } uid = reference_getuid(data); name = reference_getname(data); if (is_string_variable(name)) { ShowError("script:requestlang: not a variable\n"); script->reportsrc(st); return false; } 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->set_reg(st, sd, uid, name, (void*)h64BPTRSIZE(lng), script_getref(st,2)); st->state = RUN; } return true; } BUILDIN(requestItem) { getSD(); struct script_data* data; int64 uid; const char* name; data = script_getdata(st, 2); if (!data_isreference(data)) { ShowError("script:requestitem: not a variable\n"); script->reportsrc(st); st->state = END; return false; } uid = reference_getuid(data); name = reference_getname(data); if (is_string_variable(name)) { ShowError("script:requestitem: not a variable\n"); script->reportsrc(st); return false; } 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->reportsrc(st); return false; } if (sscanf (sd->npc_str, "%5d", &item) < 1) { ShowWarning("input data is not item id\n"); script->reportsrc(st); return false; } script->set_reg(st, sd, uid, name, (void*)h64BPTRSIZE(item), script_getref(st,2)); st->state = RUN; } return true; } BUILDIN(requestItems) { getSD(); struct script_data* data; int64 uid; const char* name; data = script_getdata(st, 2); if (!data_isreference(data)) { ShowError("script:requestitem: not a variable\n"); script->reportsrc(st); st->state = END; return false; } uid = reference_getuid(data); name = reference_getname(data); if (!is_string_variable(name)) { ShowWarning("parameter is not variable\n"); script->reportsrc(st); return false; } int count = 1; if (script_hasdata(st, 3)) { count = script_getnum(st, 3); 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->reportsrc(st); return false; } script->set_reg(st, sd, uid, name, (void*)sd->npc_str, script_getref(st, 2)); st->state = RUN; } return true; } BUILDIN(requestItemIndex) { getSessionData(client); struct script_data* data; int64 uid; const char* name; data = script_getdata(st, 2); if (!data_isreference(data)) { ShowError("script:requestitem: not a variable\n"); script->reportsrc(st); st->state = END; return false; } uid = reference_getuid(data); name = reference_getname(data); if (is_string_variable(name)) { ShowError("script:requestitemindex: not a variable\n"); script->reportsrc(st); return false; } 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 = 0; if (!sd->npc_str) { ShowWarning("npc string not found\n"); script->reportsrc(st); return false; } if (sscanf (sd->npc_str, "%5d", &item) < 1) { ShowWarning("input data is not item id\n"); script->reportsrc(st); return false; } script->set_reg(st, sd, uid, name, (void*)h64BPTRSIZE(item), script_getref(st,2)); st->state = RUN; } return true; } BUILDIN(requestItemsIndex) { getSessionData(client); struct script_data* data; int64 uid; const char* name; data = script_getdata(st, 2); if (!data_isreference(data)) { ShowError("script:requestitem: not a variable\n"); script->reportsrc(st); st->state = END; return false; } uid = reference_getuid(data); name = reference_getname(data); if (!is_string_variable(name)) { ShowWarning("parameter is not variable\n"); script->reportsrc(st); return false; } int count = 1; if (script_hasdata(st, 3)) { count = script_getnum(st, 3); 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) { ShowWarning("npc string not found\n"); script->reportsrc(st); return false; } script->set_reg(st, sd, uid, name, (void*)sd->npc_str, script_getref(st, 2)); 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 = (TBL_NPC *) map->id2bl (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(countItemColor) { int nameid, i; int count = 0; struct item_data* id = NULL; getSD(); if (script_isstringtype(st, 2)) { // item name id = itemdb->search_name(script_getstr(st, 2)); } else { // item id id = itemdb->exists(script_getnum(st, 2)); } if (id == NULL) { ShowError("buildin_countitem: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was script->reportsrc(st); script_pushint(st,0); return false; } nameid = id->nameid; for(i = 0; i < MAX_INVENTORY; i++) { if(sd->status.inventory[i].nameid == nameid) count += sd->status.inventory[i].amount; } script_pushint(st, count); 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; } enum setmount_type { SETMOUNT_TYPE_NONE = 0, SETMOUNT_TYPE_PECO = 1, SETMOUNT_TYPE_WUG = 2, SETMOUNT_TYPE_MADO = 3, SETMOUNT_TYPE_DRAGON_GREEN = 4, SETMOUNT_TYPE_DRAGON_BROWN = 5, SETMOUNT_TYPE_DRAGON_GRAY = 6, SETMOUNT_TYPE_DRAGON_BLUE = 7, SETMOUNT_TYPE_DRAGON_RED = 8, SETMOUNT_TYPE_MAX, SETMOUNT_TYPE_DRAGON = SETMOUNT_TYPE_DRAGON_GREEN, }; BUILDIN(setMount) { int flag = SETMOUNT_TYPE_NONE; TBL_PC* sd = script->rid2sd(st); if (sd == NULL) return true; // no player attached, report source if (script_hasdata(st, 2)) flag = script_getnum(st, 2); // Sanity checks and auto-detection if (flag >= SETMOUNT_TYPE_DRAGON_GREEN && flag <= SETMOUNT_TYPE_DRAGON_RED) { if (pc->checkskill(sd, RK_DRAGONTRAINING)) { // Rune Knight (Dragon) unsigned int option; option = ( flag == SETMOUNT_TYPE_DRAGON_GREEN ? OPTION_DRAGON1 : flag == SETMOUNT_TYPE_DRAGON_BROWN ? OPTION_DRAGON2 : flag == SETMOUNT_TYPE_DRAGON_GRAY ? OPTION_DRAGON3 : flag == SETMOUNT_TYPE_DRAGON_BLUE ? OPTION_DRAGON4 : flag == SETMOUNT_TYPE_DRAGON_RED ? OPTION_DRAGON5 : OPTION_DRAGON1); // default value pc->setridingdragon(sd, option); } } else if (flag == SETMOUNT_TYPE_WUG) { // Ranger (Warg) if (pc->checkskill(sd, RA_WUGRIDER)) pc->setridingwug(sd, true); } else if (flag == SETMOUNT_TYPE_MADO) { // Mechanic (Mado Gear) if (pc->checkskill(sd, NC_MADOLICENCE)) pc->setmadogear(sd, true); } else if (flag == SETMOUNT_TYPE_PECO) { // Knight / Crusader (Peco Peco) if (pc->checkskill(sd, KN_RIDING)) pc->setridingpeco(sd, true); } else if (flag == SETMOUNT_TYPE_NONE && pc_hasmount(sd)) { if (pc_isridingdragon(sd)) { pc->setridingdragon(sd, 0); } if (pc_isridingwug(sd)) { pc->setridingwug(sd, false); } if (pc_ismadogear(sd)) { pc->setmadogear(sd, false); } if (pc_isridingpeco(sd)) { pc->setridingpeco(sd, false); } } 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 = (TBL_NPC *) map->id2bl (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 = (TBL_NPC *) map->id2bl (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 = (struct npc_data *)map->id2bl(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; }