diff options
-rw-r--r-- | db/const.txt | 1 | ||||
-rw-r--r-- | src/map/mob.h | 1 | ||||
-rw-r--r-- | src/map/npc.c | 73 | ||||
-rw-r--r-- | src/map/status.c | 7 | ||||
-rw-r--r-- | src/map/status.h | 1 | ||||
-rw-r--r-- | src/map/unit.c | 7 |
6 files changed, 65 insertions, 25 deletions
diff --git a/db/const.txt b/db/const.txt index 6579ec259..8850f9174 100644 --- a/db/const.txt +++ b/db/const.txt @@ -790,6 +790,7 @@ SC_COMMONSC_RESIST 273 SC_SEVENWIND 274 SC_DEF_RATE 275 SC_SPREGEN 276 +SC_WALKSPEED 277 e_gasp 0 e_what 1 diff --git a/src/map/mob.h b/src/map/mob.h index 161a35126..cade69305 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -125,6 +125,7 @@ struct mob_data { unsigned int tdmg; //Stores total damage given to the mob, for exp calculations. [Skotlex] int level; int target_id,attacked_id; + int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs) unsigned int next_walktime,last_thinktime,last_linktime,last_pcneartime; short move_fail_count; diff --git a/src/map/npc.c b/src/map/npc.c index 24fe8787b..c576295df 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -777,35 +777,70 @@ int npc_touch_areanpc(struct map_session_data* sd, int m, int x, int y) return 0; } -int npc_touch_areanpc2(struct block_list* bl) +int npc_touch_areanpc2(struct mob_data *md) { - int i,m=bl->m; - int xs,ys; + int i, m = md->bl.m, x = md->bl.x, y = md->bl.y; + char eventname[NAME_LENGTH*2+3]; + struct event_data* ev; + int xs, ys; - for(i=0;i<map[m].npc_num;i++) + for( i = 0; i < map[m].npc_num; i++ ) { - if (map[m].npc[i]->sc.option&OPTION_INVISIBLE) + if( map[m].npc[i]->sc.option&OPTION_INVISIBLE ) continue; - if (map[m].npc[i]->subtype!=WARP) + switch( map[m].npc[i]->subtype ) + { + case WARP: + if( battle_config.mob_warp&1 ) + { + xs = map[m].npc[i]->u.warp.xs; + ys = map[m].npc[i]->u.warp.ys; + } + else + continue; + break; + case SCRIPT: + xs = map[m].npc[i]->u.scr.xs; + ys = map[m].npc[i]->u.scr.ys; + snprintf(eventname, ARRAYLENGTH(eventname), "%s::OnTouchNPC", map[m].npc[i]->exname); + break; + default: continue; - - xs=map[m].npc[i]->u.warp.xs; - ys=map[m].npc[i]->u.warp.ys; + } + if( x >= map[m].npc[i]->bl.x-xs && x <= map[m].npc[i]->bl.x+xs && y >= map[m].npc[i]->bl.y-ys && y <= map[m].npc[i]->bl.y+ys ) + { + if( map[m].npc[i]->subtype == SCRIPT + && ((ev = (struct event_data*)strdb_get(ev_db, eventname)) == NULL || ev->nd == NULL) ) + continue; // No OnTouchNPC Event found - if( bl->x >= map[m].npc[i]->bl.x-xs && bl->x <= map[m].npc[i]->bl.x+xs - && bl->y >= map[m].npc[i]->bl.y-ys && bl->y <= map[m].npc[i]->bl.y+ys ) break; + } } - if (i==map[m].npc_num) - return 0; - - xs = map_mapindex2mapid(map[m].npc[i]->u.warp.mapindex); - if (xs < 0) // Can't warp object between map servers... - return 0; - if (unit_warp(bl, xs, map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,0)) - return 0; //Failed to warp. + if( i == map[m].npc_num ) return 0; + + switch( map[m].npc[i]->subtype ) + { + case WARP: + xs = map_mapindex2mapid(map[m].npc[i]->u.warp.mapindex); + if( xs < 0 ) + return 0; // Can't warp object between map servers... + if( unit_warp(&md->bl, xs, map[m].npc[i]->u.warp.x, map[m].npc[i]->u.warp.y, 0) ) + return 0; // Failed to warp. + break; + case SCRIPT: + { + if( md->areanpc_id == map[m].npc[i]->bl.id ) + return 0; // Allready touch this NPC + + md->areanpc_id = map[m].npc[i]->bl.id; + run_script(ev->nd->u.scr.script, ev->pos, md->bl.id, ev->nd->bl.id); + + return 0; + break; + } + } return 1; } diff --git a/src/map/status.c b/src/map/status.c index 0be72cc2e..d3d9f3544 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -502,6 +502,7 @@ void initChangeTables(void) StatusChangeFlagTable[SC_ARMOR_ELEMENT] |= SCB_PC; StatusChangeFlagTable[SC_ARMOR_RESIST] |= SCB_PC; StatusChangeFlagTable[SC_SPCOST_RATE] |= SCB_PC; + StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; if (!battle_config.display_hallucination) //Disable Hallucination. StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK; @@ -3706,7 +3707,6 @@ static signed short status_calc_mdef2(struct block_list *bl, struct status_chang static unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed) { - //Default speed coming in means there's no speed_rate adjustments. int new_speed = speed; bool default_speed = (speed == DEFAULT_WALK_SPEED); @@ -3714,6 +3714,9 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha if(!sc || !sc->count) return cap_value(speed,10,USHRT_MAX); + if(sc->data[SC_WALKSPEED]) + new_speed = sc->data[SC_WALKSPEED]->val1; + // Fixed reductions if(sc->data[SC_CURSE]) new_speed += 450; @@ -3739,8 +3742,6 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha if(sc->data[SC_FUSION]) new_speed -= new_speed * 25/100; - - //These only apply if you don't have increase agi and/or fusion and/or sprint if(speed == new_speed) { diff --git a/src/map/status.h b/src/map/status.h index ebbb90884..55fea6b2e 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -294,6 +294,7 @@ typedef enum sc_type { SC_SEVENWIND, SC_DEF_RATE, SC_SPREGEN, + SC_WALKSPEED, SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; diff --git a/src/map/unit.c b/src/map/unit.c index 1c21c5300..06a0a07bf 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -183,9 +183,10 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data) bl->id, sd->status.guild_id, strvit, agidex); } } else if (md) { - if(battle_config.mob_warp&1 && map_getcell(bl->m,x,y,CELL_CHKNPC) && - npc_touch_areanpc2(bl)) // Enable mobs to step on warps. [Skotlex] - return 0; + if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) { + if( npc_touch_areanpc2(md) ) return 0; // Warped + } else + md->areanpc_id = 0; if (md->min_chase > md->db->range3) md->min_chase--; //Walk skills are triggered regardless of target due to the idle-walk mob state. //But avoid triggering on stop-walk calls. |