Fox RM Опубликовано 16 декабря, 2014 Жалоба Поделиться Опубликовано 16 декабря, 2014 Доброго времени суток, сразу скажу по поводу исходников, нашел мод в своем старом эмуле, соответственно мод написал [ToastOfDoom], под eAthena (в rAthena ,по моему, есть по дефолту этот скрипт.)Мод включает в себя 3 команды, а именно:bindatcmd (<atcmd>,<event>);Да бы каждый раз не править src , в первой строке atcmd - вводите название команды (бинд) , во втором event - название лейбла который будет использовать скрипт нпц. Чтобы все стало понятней, ниже будет рассмотрен пример работы.unbindatcmd(<atcmd>); Это позволит удалить все существующие привязки к определенной atcmd.</span><br />useatcmd(<atcmd string>);Работает по принципу atcommand() . Более подробный принцип работы увидете ниже, в примере.Когда atcmd перенаправляется к лейблу, параметры этого atcmd передаются следующими переменными:. @ atcmd_command $: atcmd который используется.. @ atcmd_numparameters: количество параметров. @ atcmd_parameters $ [-]: Параметры, указанные в массивеПример:- script atcmd_sample_inject -1,{OnInit:bindatcmd("warp", "atcmd_sample_inject::OnAtCmd");end;OnAtCmd:if(Zeny >= 1000) {set Zeny, Zeny - 1000;useatcmd "@warp " + .@atcmd_parameters$[0] + " " + .@atcmd_parameters$[1] + " " + .@atcmd_parameters$[2];} else {dispbottom "Sorry... you need at least 1000z to use this service";}end;}Соответственно вводите в игре @warp и в работу включается лейбл OnAtCmd: ,объяснять его работу не буду, т.к все итак понятно.Непосредственно сам код:Index: map/atcommand.c===================================================================--- map/atcommand.c (revision 15268)+++ map/atcommand.c (working copy)@@ -9182,6 +9494,13 @@return ( info != NULL ) ? info->level : 100; // 100: command can not be used}+struct Atcmd_Binding* get_atcommandbind_byname(const char* name)+{+ int i;+ if( *name == atcommand_symbol || *name == charcommand_symbol ) name++; // for backwards compatibility+ ARR_FIND( 0, ARRAYLENGTH(atcmd_binding), i, strcmp(atcmd_binding[i].command, name) == 0 );+ return ( i < ARRAYLENGTH(atcmd_binding) ) ? &atcmd_binding[i] : NULL;+}/// Executes an at-command.bool is_atcommand(const int fd, struct map_session_data* sd, const char* message, int type)@@ -9287,6 +9607,18 @@if( sscanf(atcmd_msg, "%99s %99[^\n]", command, params) < 2 )params[0] = '\0';++ //check for atcmd events+ if( type == 1 )+ {+ Atcmd_Binding * binding = get_atcommandbind_byname(command);+ if( binding != NULL && binding->npc_event[0] )+ { //execute event if binded+ npc_do_atcmd_event((*atcmd_msg == atcommand_symbol) ? sd : ssd, command, params, binding->npc_event);+ return true;+ }+ }+//Grab the command information and check for the proper GM level required to use it or if the command existsinfo = get_atcommandinfo_byname(command);if( info == NULL || info->func == NULL || ( type && ((*atcmd_msg == atcommand_symbol && pc_isGM(sd) < info->level) || (*atcmd_msg == charcommand_symbol && pc_isGM(sd) < info->level2)) ) )Index: map/atcommand.h===================================================================--- map/atcommand.h (revision 15268)+++ map/atcommand.h (working copy)@@ -45,4 +45,16 @@int msg_config_read(const char* cfgName);void do_final_msg(void);+#define MAX_ATCMD_BINDINGS 100++typedef struct Atcmd_Binding {+ char command[50];+ char npc_event[50];+} Atcmd_Binding;++//At command events+struct Atcmd_Binding atcmd_binding[MAX_ATCMD_BINDINGS];+struct Atcmd_Binding* get_atcommandbind_byname(const char* name);++#endif /* _ATCOMMAND_H_ */Index: map/npc.c===================================================================--- map/npc.c (revision 15268)+++ map/npc.c (working copy)@@ -27,6 +27,7 @@#include "unit.h"#include "npc.h"#include "chat.h"+#include "atcommand.h"#include <stdio.h>#include <stdlib.h>@@ -2649,6 +2715,115 @@clif_spawn(&nd->bl);// fade in}+int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const char* message, const char* eventname)+{+ struct event_data* ev = (struct event_data*)strdb_get(ev_db, eventname);+ struct npc_data *nd;+ struct script_state *st;+ int i = 0, j = 0, k = 0;+ char *temp;+ temp = (char*)aMallocA(strlen(message) + 1);++ nullpo_ret(sd);++ if( ev == NULL || (nd = ev->nd) == NULL )+ {+ ShowError("npc_event: event not found [%s]\n", eventname);+ return 0;+ }++ if( sd->npc_id != 0 )+ { // Enqueue the event trigger.+ int i;+ ARR_FIND( 0, MAX_EVENTQUEUE, i, sd->eventqueue[i][0] == '\0' );+ if( i < MAX_EVENTQUEUE )+ {+ safestrncpy(sd->eventqueue[i],eventname,50); //Event enqueued.+ return 0;+ }++ ShowWarning("npc_event: player's event queue is full, can't add event '%s' !\n", eventname);+ return 1;+ }++ if( ev->nd->sc.option&OPTION_INVISIBLE )+ { // Disabled npc, shouldn't trigger event.+ npc_event_dequeue(sd);+ return 2;+ }++ st = script_alloc_state(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);+ setd_sub(st, NULL, ".@atcmd_command$", 0, (void *)command, NULL);++ // split atcmd parameters based on spaces+ i = 0;+ j = 0;+ while( message[i] != '\0' )+ {+ if( message[i] == ' ' && k < 127 )+ {+ temp[j] = '\0';+ setd_sub(st, NULL, ".@atcmd_parameters$", k++, (void *)temp, NULL);+ j = 0;+ ++i;+ }+ else+ temp[j++] = message[i++];+ }++ temp[j] = '\0';+ setd_sub(st, NULL, ".@atcmd_parameters$", k++, (void *)temp, NULL);+ setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)k, NULL);+ aFree(temp);++ run_script_main(st);+ return 0;+}+/// Parses a function./// function%TAB%script%TAB%<function name>%TAB%{<code>}static const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)Index: map/npc.h===================================================================--- map/npc.h (revision 15268)+++ map/npc.h (working copy)@@ -153,7 +164,12 @@int npc_duplicate4instance(struct npc_data *snd, int m);int npc_cashshop_buy(struct map_session_data* sd, unsigned int nameid, int amount, int points);extern struct npc_data* fake_nd;+// @commands (script-based)+int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const char* message, const char* eventname);++#endif /* _NPC_H_ */Index: map/script.c===================================================================--- map/script.c (revision 15268)+++ map/script.c (working copy)@@ -3821,9 +3823,18 @@int script_reload(){+ int i;userfunc_db->clear(userfunc_db,do_final_userfunc_sub);scriptlabel_db->clear(scriptlabel_db, NULL);++ // clear atcmd bindings+ for( i = 0; i < MAX_ATCMD_BINDINGS; i++ )+ {+ safestrncpy(atcmd_binding[i].command, "", 50);+ safestrncpy(atcmd_binding[i].npc_event, "", 50);+ }+if(sleep_db) {struct linkdb_node *n = (struct linkdb_node *)sleep_db;while(n) {@@ -15417,7 +16577,301 @@return 0;}+BUILDIN_FUNC(bindatcmd)+{+ const char* atcmd;+ const char* eventName;+ int i = 0;++ atcmd = script_getstr(st,2);+ eventName = script_getstr(st,3);++ // check if event is already binded+ ARR_FIND(0, MAX_ATCMD_BINDINGS, i, strcmp(atcmd_binding[i].command,atcmd) == 0);+ if( i < MAX_ATCMD_BINDINGS )+ safestrncpy(atcmd_binding[i].npc_event, eventName, 50);+ else+ { // make new binding+ ARR_FIND(0, MAX_ATCMD_BINDINGS, i, atcmd_binding[i].command[0] == '\0');+ if( i < MAX_ATCMD_BINDINGS )+ {+ safestrncpy(atcmd_binding[i].command, atcmd, 50);+ safestrncpy(atcmd_binding[i].npc_event, eventName, 50);+ }+ }++ return 0;+}++BUILDIN_FUNC(unbindatcmd)+{+ const char* atcmd;+ int i = 0;++ atcmd = script_getstr(st, 2);++ ARR_FIND(0, MAX_ATCMD_BINDINGS, i, strcmp(atcmd_binding[i].command, atcmd) == 0);+ if( i < MAX_ATCMD_BINDINGS )+ {+ safestrncpy(atcmd_binding[i].command, "", 50);+ safestrncpy(atcmd_binding[i].npc_event, "", 50);+ }++ return 0;+}++BUILDIN_FUNC(useatcmd)+{+ TBL_PC dummy_sd;+ TBL_PC* sd;+ int fd;+ const char* cmd;++ cmd = script_getstr(st,2);++ if( st->rid )+ {+ sd = script_rid2sd(st);+ fd = sd->fd;+ }+ else+ { // Use a dummy character.+ sd = &dummy_sd;+ fd = 0;++ memset(&dummy_sd, 0, sizeof(TBL_PC));+ if( st->oid )+ {+ struct block_list* bl = map_id2bl(st->oid);+ memcpy(&dummy_sd.bl, bl, sizeof(struct block_list));+ if( bl->type == BL_NPC )+ safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH);+ }+ }++ // compatibility with previous implementation (deprecated!)+ if( cmd[0] != atcommand_symbol )+ {+ cmd += strlen(sd->status.name);+ while( *cmd != atcommand_symbol && *cmd != 0 )+ cmd++;+ }++ is_atcommand(fd, sd, cmd, 2);+ return 0;+}@@ -15834,5 +17330,23 @@BUILDIN_DEF(checkquest, "i?"),BUILDIN_DEF(changequest, "ii"),BUILDIN_DEF(showevent, "ii"),+ BUILDIN_DEF(bindatcmd, "ss"),+ BUILDIN_DEF(unbindatcmd, "s"),+ BUILDIN_DEF(useatcmd, "s"),+{NULL,NULL,NULL},};Index: map/script.h===================================================================--- map/script.h (revision 15268)+++ map/script.h (working copy)@@ -181,5 +182,8 @@int add_str(const char* p);const char* get_str(int id);int script_reload(void);+//At command events [ToastOfDoom]+void setd_sub(struct script_state *st, TBL_PC *sd, const char *varname, int elem, void *value, struct linkdb_node **ref);#endif /* _SCRIPT_H_ */ 2 Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения