summaryrefslogtreecommitdiff
path: root/src/map/npc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/npc.c')
-rw-r--r--src/map/npc.c326
1 files changed, 35 insertions, 291 deletions
diff --git a/src/map/npc.c b/src/map/npc.c
index b469878eb..177612b50 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -6,6 +6,7 @@
#include "../common/nullpo.h"
#include "../common/malloc.h"
#include "../common/showmsg.h"
+#include "../common/strlib.h"
#include "../common/utils.h"
#include "../common/ers.h"
#include "../common/db.h"
@@ -184,99 +185,6 @@ int npc_event_dequeue(struct map_session_data* sd)
}
/*==========================================
- * イベントの遅延実行
- *------------------------------------------*/
-int npc_event_timer(int tid, unsigned int tick, int id, int data)
-{
- char* eventname = (char *)data;
- struct event_data* ev = strdb_get(ev_db,eventname);
- struct npc_data* nd;
- struct map_session_data* sd = map_id2sd(id);
- size_t i;
-
- if((ev==NULL || (nd=ev->nd)==NULL))
- {
- if(battle_config.error_log)
- ShowWarning("npc_event: event not found [%s]\n",eventname);
- }
- else
- {
- for(i=0;i<MAX_EVENTTIMER;i++) {
- if( nd->eventtimer[i]==tid ) {
- nd->eventtimer[i]=-1;
- npc_event(sd,eventname,0); // sd NULL check is within
- break;
- }
- }
- if(i==MAX_EVENTTIMER && battle_config.error_log)
- ShowWarning("npc_event_timer: event timer not found [%s]!\n",eventname);
- }
-
- aFree(eventname);
- return 0;
-}
-
-int npc_timer_event(const char* eventname) // Added by RoVeRT
-{
- struct event_data* ev = strdb_get(ev_db, eventname);
- struct npc_data *nd;
-// int xs,ys;
-
- if((ev==NULL || (nd=ev->nd)==NULL)){
- ShowWarning("npc_timer_event: event not found [%s]\n",eventname);
- return 0;
- }
-
- run_script(nd->u.scr.script,ev->pos,nd->bl.id,nd->bl.id);
-
- return 0;
-}
-/*
-int npc_timer_sub_sub(DBKey key,void *data,va_list ap) // Added by RoVeRT
-{
- char *p=(char *)key;
- struct event_data *ev=(struct event_data *)data;
- int *c=va_arg(ap,int *);
- int tick=0,ctick=gettick();
- char temp[10];
- char event[100];
-
- if(ev->nd->bl.id==(int)*c && (p=strchr(p,':')) && p && strncasecmp("::OnTimer",p,8)==0 ){
- sscanf(&p[9],"%s",temp);
- tick=atoi(temp);
-
- strcpy( event, ev->nd->name);
- strcat( event, p);
-
- if (ctick >= ev->nd->lastaction && ctick - ev->nd->timer >= tick) {
- npc_timer_event(event);
- ev->nd->lastaction = ctick;
- }
- }
- return 0;
-}
-
-int npc_timer_sub(DBKey key,void *data,va_list ap) // Added by RoVeRT
-{
- struct npc_data *nd=(struct npc_data*)data;
-
- if(nd->timer == -1)
- return 0;
-
- sv_db->foreach(ev_db,npc_timer_sub_sub,&nd->bl.id);
-
- return 0;
-}
-
-int npc_timer(int tid,unsigned int tick,int id,int data) // Added by RoVeRT
-{
- npcname_db->foreach(npcname_db,npc_timer_sub);
-
- aFree((void*)data);
- return 0;
-}*/
-
-/*==========================================
* exports a npc event label
* npc_parse_script->strdb_foreachから呼ばれる
*------------------------------------------*/
@@ -444,93 +352,7 @@ int npc_event_do_oninit(void)
return 0;
}
-/*==========================================
- * OnTimer NPC event - by RoVeRT
- *------------------------------------------*/
-int npc_addeventtimer(struct npc_data* nd, int tick, const char* name)
-{
- int i;
- char* evname;
-
- for(i=0;i<MAX_EVENTTIMER;i++)
- if( nd->eventtimer[i]==-1 )
- break;
- if(i<MAX_EVENTTIMER){
- if (!strdb_get(ev_db,name)) {
- if (battle_config.error_log)
- ShowError("npc_addeventimer: Event %s does not exists.\n", name);
- return 1; //Event does not exists!
- }
- evname = (char *)aMallocA(NAME_LENGTH*sizeof(char));
- if(evname==NULL){
- ShowFatalError("npc_addeventtimer: out of memory !\n");exit(1);
- }
- strncpy(evname,name,NAME_LENGTH);
- evname[NAME_LENGTH-1] = '\0';
- nd->eventtimer[i]=add_timer(gettick()+tick,
- npc_event_timer,nd->bl.id,(int)evname);
- }else
- ShowWarning("npc_addtimer: event timer is full !\n");
-
- return 0;
-}
-
-int npc_deleventtimer(struct npc_data* nd, const char* name)
-{
- int i;
- for(i=0;i<MAX_EVENTTIMER;i++)
- if( nd->eventtimer[i]!=-1 && strcmp((char *)(get_timer(nd->eventtimer[i])->data), name)==0 ){
- delete_timer(nd->eventtimer[i],npc_event_timer);
- nd->eventtimer[i]=-1;
- break;
- }
- return 0;
-}
-
-int npc_cleareventtimer(struct npc_data* nd)
-{
- int i;
- for(i=0;i<MAX_EVENTTIMER;i++)
- if( nd->eventtimer[i]!=-1 ){
- delete_timer(nd->eventtimer[i],npc_event_timer);
- nd->eventtimer[i]=-1;
- }
-
- return 0;
-}
-
-int npc_do_ontimer_sub(DBKey key, void* data, va_list ap)
-{
- const char *p = key.str;
- struct event_data *ev = (struct event_data *)data;
- int *c = va_arg(ap,int *);
-// struct map_session_data *sd=va_arg(ap,struct map_session_data *);
- int option = va_arg(ap,int);
- int tick = 0;
- char temp[10];
- char event[50];
-
- if(ev->nd->bl.id == (int)*c && (p = strchr(p,':')) && strnicmp("::OnTimer",p,8) == 0){
- sscanf(&p[9], "%s", temp);
- tick = atoi(temp);
-
- strcpy(event, ev->nd->name);
- strcat(event, p);
-
- if (option!=0) {
- npc_addeventtimer(ev->nd, tick, event);
- } else {
- npc_deleventtimer(ev->nd, event);
- }
- }
- return 0;
-}
-int npc_do_ontimer(int npc_id, int option)
-{
- ev_db->foreach(ev_db, npc_do_ontimer_sub, &npc_id, option);
- return 0;
-}
/*==========================================
* タイマーイベント用ラベルの取り込み
* npc_parse_script->strdb_foreachから呼ばれる
@@ -817,19 +639,21 @@ int npc_settimerevent_tick(struct npc_data* nd, int newtimer)
int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char* eventname)
{
- if ( sd->npc_id!=0) {
+ if ( sd->npc_id != 0 )
+ {
//Enqueue the event trigger.
int i;
- for(i=0;i<MAX_EVENTQUEUE && sd->eventqueue[i][0];i++);
-
- if (i==MAX_EVENTQUEUE) {
- if (battle_config.error_log)
+ ARR_FIND( 0, MAX_EVENTQUEUE, i, sd->eventqueue[i][0] == '\0' );
+ if( i < MAX_EVENTQUEUE )
+ safestrncpy(sd->eventqueue[i],eventname,50); //Event enqueued.
+ else
+ if( battle_config.error_log )
ShowWarning("npc_event: event queue is full !\n");
- }else //Event enqueued.
- memcpy(sd->eventqueue[i],eventname,50);
+
return 1;
}
- if (ev->nd->sc.option&OPTION_INVISIBLE) {
+ if( ev->nd->sc.option&OPTION_INVISIBLE )
+ {
//Disabled npc, shouldn't trigger event.
npc_event_dequeue(sd);
return 2;
@@ -890,31 +714,6 @@ int npc_event(struct map_session_data* sd, const char* eventname, int mob_kill)
return npc_event_sub(sd,ev,eventname);
}
-
-int npc_command_sub(DBKey key,void *data,va_list ap)
-{
- const char* p = (const char*)key.str;
- struct event_data *ev=(struct event_data *)data;
- const char* npcname = va_arg(ap, const char*);
- const char* command = va_arg(ap, const char*);
- char temp[100];
-
- if(strcmp(ev->nd->name,npcname)==0 && (p=strchr(p,':')) && strnicmp("::OnCommand",p,10)==0 ){
- sscanf(&p[11],"%s",temp);
-
- if (strcmp(command,temp)==0)
- run_script(ev->nd->u.scr.script,ev->pos,0,ev->nd->bl.id);
- }
-
- return 0;
-}
-
-int npc_command(struct map_session_data* sd, const char* npcname, const char* command)
-{
- ev_db->foreach(ev_db, npc_command_sub, npcname, command);
-
- return 0;
-}
/*==========================================
* 接触型のNPC処理
*------------------------------------------*/
@@ -1523,7 +1322,6 @@ int npc_unload(struct npc_data* nd)
ers_free(timer_event_ers, (struct event_timer_data*)td->data);
delete_timer(nd->u.scr.timerid, npc_timerevent);
}
- npc_cleareventtimer (nd);
if (nd->u.scr.timer_event)
aFree(nd->u.scr.timer_event);
if (nd->u.scr.src_id == 0) {
@@ -1723,7 +1521,6 @@ static int npc_parse_shop(char* w1, char* w2, char* w3, char* w4)
nd->u.shop_item[pos].value = value;
// check for bad prices that can possibly cause exploits
if (value/124. < id->value_sell/75.) { //Clened up formula to prevent overflows.
- printf("\r"); //Carriage return to clear the 'loading..' line. [Skotlex]
if (value < id->value_sell)
ShowWarning ("Item %s [%d] buying price (%d) is less than selling price (%d) at %s\n",
id->name, id->nameid, value, id->value_sell, current_file);
@@ -1749,8 +1546,7 @@ static int npc_parse_shop(char* w1, char* w2, char* w3, char* w4)
nd->bl.x = x;
nd->bl.y = y;
nd->bl.id = npc_get_new_npc_id();
- memcpy(nd->name, w3, NAME_LENGTH);
- nd->name[NAME_LENGTH-1] = '\0';
+ safestrncpy(nd->name, w3, NAME_LENGTH);
nd->class_ = m==-1?-1:atoi(w4);
nd->speed = 200;
@@ -1810,8 +1606,7 @@ int npc_convertlabel_db(DBKey key, void* data, va_list ap)
ShowError("npc_parse_script: label name longer than 23 chars! '%s'\n (%s)", lname, current_file);
exit(1);
}
- memcpy(lst[num].name, lname, len);
- lst[num].name[len]=0;
+ safestrncpy(lst[num].name, lname, NAME_LENGTH);
lst[num].pos = pos;
nd->u.scr.label_list = lst;
nd->u.scr.label_list_num = num+1;
@@ -2047,8 +1842,6 @@ static int npc_parse_script(char* w1, char* w2, char* w3, char* w4, char* first_
nd->bl.type = BL_NPC;
nd->bl.subtype = SCRIPT;
- for (i = 0; i < MAX_EVENTTIMER; i++)
- nd->eventtimer[i] = -1;
if (m >= 0) {
nd->n = map_addnpc(m, nd);
status_change_init(&nd->bl);
@@ -2298,7 +2091,6 @@ static int npc_parse_function(char* w1, char* w2, char* w3, char* w4, char* firs
user_db = script_get_userfunc_db();
oldscript = (struct script_code *)strdb_get(user_db, p);
if(oldscript != NULL) {
- printf("\r"); //Carriage return to clear the 'loading..' line. [Skotlex]
ShowInfo("parse_function: Overwriting user function [%s] (%s:%d)\n", p, file, *lines);
script_free_vars( &oldscript->script_vars );
aFree( oldscript->script_buf );
@@ -2782,10 +2574,8 @@ void npc_parsesrcfile(const char* name)
if ((count = sscanf(line, "%s %s %[^\t]\t %n%[^\n]", w1, w2, w3, &w4pos, w4)) == 4 ||
(count = sscanf(line, "%s %s %s %n%[^\n]\n", w1, w2, w3, &w4pos, w4)) >= 3)
{
- ShowWarning("\r");
ShowWarning("Incorrect separator syntax in file '%s', line '%i'. Use tabs instead of spaces!\n * %s %s %s %s\n",current_file,lines,w1,w2,w3,w4);
} else {
- ShowError("\r"); //Erase the npc spinner.
ShowError("Could not parse file '%s', line '%i'.\n * %s %s %s %s\n",current_file,lines,w1,w2,w3,w4);
continue;
}
@@ -2926,11 +2716,9 @@ void npc_read_event_script(void)
}
}
-/*==========================================
- *
- *------------------------------------------*/
-static int npc_cleanup_sub(struct block_list* bl, va_list ap)
+static int npc_cleanup_dbsub(DBKey key, void* data, va_list ap)
{
+ struct block_list* bl = (struct block_list*)data;
nullpo_retr(0, bl);
switch(bl->type) {
@@ -2945,18 +2733,11 @@ static int npc_cleanup_sub(struct block_list* bl, va_list ap)
return 0;
}
-static int npc_cleanup_dbsub(DBKey key, void* data, va_list ap)
-{
- return npc_cleanup_sub((struct block_list*)data, 0);
-}
-
int npc_reload(void)
{
struct npc_src_list *nsl;
int m, i;
- time_t last_time = time(0);
- int busy = 0, npc_new_min = npc_id;
- char c = '-';
+ int npc_new_min = npc_id;
//Remove all npcs/mobs. [Skotlex]
map_foreachiddb(npc_cleanup_dbsub);
@@ -2971,36 +2752,21 @@ int npc_reload(void)
}
mob_clear_spawninfo();
- // anything else we should cleanup?
- // Reloading npc's now
+ // clear npc-related data structures
ev_db->clear(ev_db,NULL);
npcname_db->clear(npcname_db,NULL);
npc_warp = npc_shop = npc_script = 0;
npc_mob = npc_cache_mob = npc_delay_mob = 0;
- for (nsl = npc_src_files; nsl; nsl = nsl->next) {
+ //TODO: the following code is copy-pasted from do_init_npc(); clean it up
+ // Reloading npcs now
+ for (nsl = npc_src_files; nsl; nsl = nsl->next)
+ {
+ ShowStatus("Loading NPC file: %s"CL_CLL"\r", nsl->name);
npc_parsesrcfile(nsl->name);
- if (script_config.verbose_mode) {
- printf("\r");
- ShowStatus("Loading NPCs... %-53s", nsl->name);
- } else {
- if (last_time != time(0)) {
- printf("\r");
- ShowStatus("Loading NPCs... Working: ");
- last_time = time(0);
- switch(busy) {
- case 0: c='\\'; busy++; break;
- case 1: c='|'; busy++; break;
- case 2: c='/'; busy++; break;
- case 3: c='-'; busy=0;
- }
- printf("[%c]",c);
- }
- }
- fflush(stdout);
}
- printf("\r");
- ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:\n"
+
+ ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n"
"\t-'"CL_WHITE"%d"CL_RESET"' Warps\n"
"\t-'"CL_WHITE"%d"CL_RESET"' Shops\n"
"\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n"
@@ -3013,8 +2779,7 @@ int npc_reload(void)
npc_read_event_script();
//Execute the OnInit event for freshly loaded npcs. [Skotlex]
- ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"
- CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit"));
+ ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit"));
// Execute rest of the startup events if connected to char-server. [Lance]
if(!CheckForCharServer()){
ShowStatus("Event '"CL_WHITE"OnCharIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnCharIfInit"));
@@ -3090,10 +2855,7 @@ static void npc_debug_warps(void)
int do_init_npc(void)
{
struct npc_src_list *file;
- time_t last_time = time(NULL);
- int busy = 0;
int i;
- char c = '-';
//Stock view data for normal npcs.
memset(&npc_viewdb, 0, sizeof(npc_viewdb));
@@ -3101,38 +2863,21 @@ int do_init_npc(void)
for( i = 1; i < MAX_NPC_CLASS; i++ )
npc_viewdb[i].class_ = i;
- // comparing only the first 24 chars of labels that are 50 chars long isn't that nice
- // will cause "duplicated" labels where actually no dup is...
- ev_db = db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,51);
+ ev_db = db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1);
npcname_db = db_alloc(__FILE__,__LINE__,DB_STRING,DB_OPT_BASE,NAME_LENGTH);
memset(&ev_tm_b, -1, sizeof(ev_tm_b));
timer_event_ers = ers_new(sizeof(struct timer_event_data));
- for( file = npc_src_files; file != NULL; file = file->next) {
+ // process all npc files
+ ShowStatus("Loading NPCs...\r");
+ for( file = npc_src_files; file != NULL; file = file->next )
+ {
+ ShowStatus("Loading NPC file: %s"CL_CLL"\r", file->name);
npc_parsesrcfile(file->name);
- printf("\r");
- if (script_config.verbose_mode)
- ShowStatus("Loading NPCs... %-53s", file->name);
- else
- {
- ShowStatus("Loading NPCs... Working: ");
- if (last_time != time(NULL))
- {// change character at least every second
- last_time = time(NULL);
- switch(busy) {
- case 0: c='\\'; busy++; break;
- case 1: c='|'; busy++; break;
- case 2: c='/'; busy++; break;
- case 3: c='-'; busy=0;
- }
- }
- printf("[%c]",c);
- }
- fflush(stdout);
}
- printf("\r");
- ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:\n"
+
+ ShowInfo ("Done loading '"CL_WHITE"%d"CL_RESET"' NPCs:"CL_CLL"\n"
"\t-'"CL_WHITE"%d"CL_RESET"' Warps\n"
"\t-'"CL_WHITE"%d"CL_RESET"' Shops\n"
"\t-'"CL_WHITE"%d"CL_RESET"' Scripts\n"
@@ -3141,13 +2886,14 @@ int do_init_npc(void)
"\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
+ // set up the events cache
memset(script_event, 0, sizeof(script_event));
npc_read_event_script();
+
//Debug function to locate all endless loop warps.
if (battle_config.warp_point_debug)
npc_debug_warps();
- add_timer_func_list(npc_event_timer,"npc_event_timer");
add_timer_func_list(npc_event_do_clock,"npc_event_do_clock");
add_timer_func_list(npc_timerevent,"npc_timerevent");
@@ -3157,8 +2903,6 @@ int do_init_npc(void)
fake_nd->bl.id = npc_get_new_npc_id();
fake_nd->class_ = -1;
fake_nd->speed = 200;
- for (i = 0; i < MAX_EVENTTIMER; i++)
- fake_nd->eventtimer[i] = -1;
strcpy(fake_nd->name,"FAKE_NPC");
memcpy(fake_nd->exname, fake_nd->name, 9);