diff options
Diffstat (limited to 'src/map/npc.c')
-rw-r--r-- | src/map/npc.c | 107 |
1 files changed, 78 insertions, 29 deletions
diff --git a/src/map/npc.c b/src/map/npc.c index c52dce325..f0bdd7bd0 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -215,7 +215,7 @@ struct npc_data* npc_name2id(const char* name) /** * Timer to check for idle time and timeout the dialog if necessary **/ -int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data) { +int npc_rr_secure_timeout_timer(int tid, int64 tick, int id, intptr_t data) { #ifdef SECURE_NPCTIMEOUT struct map_session_data* sd = NULL; unsigned int timeout = NPC_SECURE_TIMEOUT_NEXT; @@ -394,8 +394,7 @@ int npc_event_doall(const char* name) * Clock event execution * OnMinute/OnClock/OnHour/OnDay/OnDDHHMM *------------------------------------------*/ -int npc_event_do_clock(int tid, unsigned int tick, int id, intptr_t data) -{ +int npc_event_do_clock(int tid, int64 tick, int id, intptr_t data) { static struct tm ev_tm_b; // tracks previous execution time time_t clock; struct tm* t; @@ -493,9 +492,9 @@ struct timer_event_data { /*========================================== * triger 'OnTimerXXXX' events *------------------------------------------*/ -int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) { +int npc_timerevent(int tid, int64 tick, int id, intptr_t data) { int old_rid, old_timer; - unsigned int old_tick; + int64 old_tick; struct npc_data* nd=(struct npc_data *)map->id2bl(id); struct npc_timerevent_list *te; struct timer_event_data *ted = (struct timer_event_data*)data; @@ -529,8 +528,7 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) { ted->next++; if( nd->u.scr.timeramount > ted->next ) { - int next; - next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer; + int next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer; ted->time += next; if( sd ) sd->npc_timer_id = timer->add(tick+next,npc->timerevent,id,(intptr_t)ted); @@ -564,7 +562,7 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) { *------------------------------------------*/ int npc_timerevent_start(struct npc_data* nd, int rid) { int j; - unsigned int tick = timer->gettick(); + int64 tick = timer->gettick(); struct map_session_data *sd = NULL; //Player to whom script is attached. nullpo_ret(nd); @@ -642,7 +640,7 @@ int npc_timerevent_stop(struct npc_data* nd) if( !sd && nd->u.scr.timertick ) { - nd->u.scr.timer += DIFF_TICK(timer->gettick(),nd->u.scr.timertick); // Set 'timer' to the time that has passed since the beginning of the timers + nd->u.scr.timer += DIFF_TICK32(timer->gettick(),nd->u.scr.timertick); // Set 'timer' to the time that has passed since the beginning of the timers nd->u.scr.timertick = 0; // Set 'tick' to zero so that we know it's off. } @@ -688,7 +686,7 @@ void npc_timerevent_quit(struct map_session_data* sd) if( ev ) { int old_rid,old_timer; - unsigned int old_tick; + int64 old_tick; //Set timer related info. old_rid = (nd->u.scr.rid == sd->bl.id ? 0 : nd->u.scr.rid); // Detach rid if the last attached player logged off. @@ -715,9 +713,8 @@ void npc_timerevent_quit(struct map_session_data* sd) * Get the tick value of an NPC timer * If it's stopped, return stopped time *------------------------------------------*/ -int npc_gettimerevent_tick(struct npc_data* nd) -{ - int tick; +int64 npc_gettimerevent_tick(struct npc_data* nd) { + int64 tick; nullpo_ret(nd); // TODO: Get player attached timer's tick. Now we can just get it by using 'getnpctimer' inside OnTimer event. @@ -1790,6 +1787,9 @@ int npc_unload(struct npc_data* nd, bool single) { aFree(nd->path);/* remove now that no other instances exist */ } } + + if( single && nd->bl.m != -1 ) + map->remove_questinfo(nd->bl.m,nd); if( (nd->subtype == SHOP || nd->subtype == CASHSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao] aFree(nd->u.shop.shop_item); @@ -2013,6 +2013,53 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con } } +// Parse View +// Support for using Constants in place of NPC View IDs. +int npc_parseview(const char* w4, const char* start, const char* buffer, const char* filepath) { + int val = -1, i = 0; + char viewid[1024]; // Max size of name from const.txt, see script->read_constdb. + + // Extract view ID / constant + while (w4[i] != '\0') { + if (isspace(w4[i]) || w4[i] == '/' || w4[i] == ',') + break; + + i++; + } + + safestrncpy(viewid, w4, i+=1); + + // Check if view id is not an ID (only numbers). + if(!npc->viewisid(viewid)) + { + // Check if constant exists and get its value. + if(!script->get_constant(viewid, &val)) { + ShowWarning("npc_parseview: Invalid NPC constant '%s' specified in file '%s', line'%d'. Defaulting to INVISIBLE_CLASS. \n", viewid, filepath, strline(buffer,start-buffer)); + val = INVISIBLE_CLASS; + } + } else { + // NPC has an ID specified for view id. + val = atoi(w4); + } + + return val; +} + +// View is ID +// Checks if given view is an ID or constant. +bool npc_viewisid(const char * viewid) +{ + if(atoi(viewid) != -1) + { + // Loop through view, looking for non-numeric character. + while (*viewid) { + if (isdigit(*viewid++) == 0) return false; + } + } + + return true; +} + //Add then display an npc warp on map struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y) { int i, flag = 0; @@ -2220,7 +2267,7 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s nd->bl.y = y; nd->bl.id = npc->get_new_npc_id(); npc->parsename(nd, w3, start, buffer, filepath); - nd->class_ = m==-1?-1:atoi(w4); + nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); nd->speed = 200; ++npc_shop; @@ -2335,7 +2382,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f /// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>} /// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>} const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, bool runOnInit) { - int x, y, dir = 0, m, xs = 0, ys = 0, class_ = 0; // [Valaris] thanks to fov + int x, y, dir = 0, m, xs = 0, ys = 0; // [Valaris] thanks to fov char mapname[32]; struct script_code *scriptroot; int i; @@ -2383,14 +2430,13 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* CREATE(nd, struct npc_data, 1); - if( sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3 ) + if( sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2 ) {// OnTouch area defined nd->u.scr.xs = xs; nd->u.scr.ys = ys; } else {// no OnTouch area - class_ = atoi(w4); nd->u.scr.xs = -1; nd->u.scr.ys = -1; } @@ -2401,7 +2447,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* nd->bl.y = y; npc->parsename(nd, w3, start, buffer, filepath); nd->bl.id = npc->get_new_npc_id(); - nd->class_ = class_; + nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); nd->speed = 200; nd->u.scr.script = scriptroot; nd->u.scr.label_list = label_list; @@ -2417,7 +2463,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* nd->dir = dir; npc->setcells(nd); map->addblock(&nd->bl); - if( class_ >= 0 ) { + if( nd->class_ >= 0 ) { status->set_viewdata(&nd->bl, nd->class_); if( map->list[nd->bl.m].users ) clif->spawn(&nd->bl); @@ -2465,7 +2511,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* /// npc: <map name>,<x>,<y>,<facing>%TAB%duplicate(<name of target>)%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY> const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) { - int x, y, dir, m, xs = -1, ys = -1, class_ = 0; + int x, y, dir, m, xs = -1, ys = -1; char mapname[32]; char srcname[128]; int i; @@ -2515,9 +2561,8 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch } if( type == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2 );// <spanx>,<spany> - else if( type == SCRIPT && sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3);// <sprite id>,<triggerX>,<triggerY> - else if( type != WARP ) class_ = atoi(w4);// <sprite id> - else { + else if( type == SCRIPT && sscanf(w4, "%*d,%d,%d", &xs, &ys) == 2);// <sprite id>,<triggerX>,<triggerY> + else if( type == WARP ) { ShowError("npc_parse_duplicate: Invalid span format for duplicate warp in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); return end;// next line, try to continue } @@ -2530,7 +2575,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch nd->bl.y = y; npc->parsename(nd, w3, start, buffer, filepath); nd->bl.id = npc->get_new_npc_id(); - nd->class_ = class_; + nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath); nd->speed = 200; nd->src_id = src_id; nd->bl.type = BL_NPC; @@ -2573,7 +2618,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch nd->dir = dir; npc->setcells(nd); map->addblock(&nd->bl); - if( class_ >= 0 ) { + if( nd->class_ >= 0 ) { status->set_viewdata(&nd->bl, nd->class_); if( map->list[nd->bl.m].users ) clif->spawn(&nd->bl); @@ -3439,6 +3484,10 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char map->list[m].short_damage_rate = (state) ? atoi(w4) : 100; } else if ( !strcmpi(w3,"long_damage_rate") ) { map->list[m].long_damage_rate = (state) ? atoi(w4) : 100; + } else if ( !strcmpi(w3,"src4instance") ) { + map->list[m].flag.src4instance = (state) ? 1 : 0; + } else if ( !strcmpi(w3,"nocashshop") ) { + map->list[m].flag.nocashshop = (state) ? 1 : 0; } else ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer)); @@ -3784,10 +3833,8 @@ int npc_reload(void) { npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); itemdb->name_constants(); - - for(i = 0; i < instance->instances; i++) { - instance->destroy(i); - } + + instance->reload(); map->zone_init(); @@ -4043,6 +4090,8 @@ void npc_defaults(void) { npc->addsrcfile = npc_addsrcfile; npc->delsrcfile = npc_delsrcfile; npc->parsename = npc_parsename; + npc->parseview = npc_parseview; + npc->viewisid = npc_viewisid; npc->add_warp = npc_add_warp; npc->parse_warp = npc_parse_warp; npc->parse_shop = npc_parse_shop; |