From f4edc7e4431b929acc62e4c2427e815ba9d69779 Mon Sep 17 00:00:00 2001 From: skotlex Date: Wed, 6 Dec 2006 18:21:32 +0000 Subject: - Cleaned up the implementation of map_foreachinmovearea so that the number of arguments passed is less. - Moved setting a mob's chase/attack states from the mob_ai to unit_attack and unit_walktobl. - Cleaned the change-target/cast-sensor code to account for the new mob modes. - Cleaned up a bit the mob ai sub hard function. - Made the monster_active_enable config setting take effect on mob load. - Updated the doc explaining mob modes. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@9422 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/map.c | 69 +++++++++------- src/map/map.h | 2 +- src/map/mob.c | 233 +++++++++++++++++++++++++++---------------------------- src/map/skill.c | 10 +-- src/map/status.c | 4 +- src/map/status.h | 29 +++---- src/map/unit.c | 50 +++++++----- 7 files changed, 212 insertions(+), 185 deletions(-) (limited to 'src/map') diff --git a/src/map/map.c b/src/map/map.c index 3a321fc68..1247206ab 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -629,10 +629,8 @@ int map_foreachinrange(int (*func)(struct block_list*,va_list),struct block_list struct block_list *bl=NULL; int blockcount=bl_list_count,i,c; int x0,x1,y0,y1; - m = center->m; - if (m < 0) - return 0; va_start(ap,type); + m = center->m; x0 = center->x-range; x1 = center->x+range; y0 = center->y-range; @@ -854,14 +852,23 @@ int map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int y * dx,dyは-1,0,1のみとする(どんな値でもいいっぽい?) *------------------------------------------ */ -int map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int dx,int dy,int type,...) { - int bx,by; +int map_foreachinmovearea(int (*func)(struct block_list*,va_list),struct block_list *center,int range, int dx,int dy,int type,...) { + int bx,by,m; int returnCount =0; //total sum of returned values of func() [Skotlex] struct block_list *bl=NULL; va_list ap; int blockcount=bl_list_count,i,c; + int x0, x1, y0, y1; + if (!range) return 0; + if (!dx && !dy) return 0; //No movement. va_start(ap,type); + m = center->m; + x0 = center->x-range; + x1 = center->x+range; + y0 = center->y-range; + y1 = center->y+range; + if (x1 < x0) { //Swap range bx = x0; @@ -875,19 +882,17 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,i y1 = bx; } if(dx==0 || dy==0){ - // 矩形領域の場合 + //Movement along one axis only. if(dx==0){ - if(dy<0){ + if(dy<0) //Moving south y0=y1+dy+1; - } else { + else //North y1=y0+dy-1; - } - } else if(dy==0){ - if(dx<0){ + } else { //dy == 0 + if(dx<0) //West x0=x1+dx+1; - } else { + else //East x1=x0+dx-1; - } } if(x0<0) x0=0; if(y0<0) y0=0; @@ -899,7 +904,10 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,i bl = map[m].block[bx+by*map[m].bxs]; c = map[m].block_count[bx+by*map[m].bxs]; for(i=0;inext){ - if(bl && bl->type&type && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_counttype&type && + bl->x>=x0 && bl->x<=x1 && + bl->y>=y0 && bl->y<=y1 && + bl_list_countnext){ - if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_countx>=x0 && bl->x<=x1 && + bl->y>=y0 && bl->y<=y1 && + bl_list_count=map[m].xs) x1=map[m].xs-1; @@ -926,23 +935,31 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,i bl = map[m].block[bx+by*map[m].bxs]; c = map[m].block_count[bx+by*map[m].bxs]; for(i=0;inext){ - if(!bl || !(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1)) + if(!(bl->type&type && + bl->x>=x0 && bl->x<=x1 && + bl->y>=y0 && bl->y<=y1 && + bl_list_counttype&type && ((dx>0 && bl->xx>x1+dx) || - (dy>0 && bl->yy>y1+dy)) && - bl_list_count0 && bl->xx>x1+dx) || + (dy>0 && bl->yy>y1+dy)) + bl_list[bl_list_count++]=bl; } } if (type & BL_MOB) { bl = map[m].block_mob[bx+by*map[m].bxs]; c = map[m].block_mob_count[bx+by*map[m].bxs]; for(i=0;inext){ - if(!bl || !(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1)) + if(!( + bl->x>=x0 && bl->x<=x1 && + bl->y>=y0 && bl->y<=y1 && + bl_list_count0 && bl->xx>x1+dx) || - (dy>0 && bl->yy>y1+dy)) && - bl_list_count0 && bl->xx>x1+dx) || + (dy>0 && bl->yy>y1+dy)) bl_list[bl_list_count++]=bl; } } diff --git a/src/map/map.h b/src/map/map.h index 2f61a07d5..5bf9ab006 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -1327,7 +1327,7 @@ int map_foreachinshootrange(int (*)(struct block_list*,va_list),struct block_lis int map_foreachinarea(int (*)(struct block_list*,va_list),int,int,int,int,int,int,...); // -- moonsoul (added map_foreachincell) int map_foreachincell(int (*)(struct block_list*,va_list),int,int,int,int,...); -int map_foreachinmovearea(int (*)(struct block_list*,va_list),int,int,int,int,int,int,int,int,...); +int map_foreachinmovearea(int (*)(struct block_list*,va_list),struct block_list*,int,int,int,int,...); int map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int range,int type,...); // Celest int map_foreachinmap(int (*)(struct block_list*,va_list),int,int,...); int map_countnearpc(int,int,int); diff --git a/src/map/mob.c b/src/map/mob.c index 5f22c8212..fb26a9d26 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -726,13 +726,12 @@ static int mob_can_changetarget(struct mob_data* md, struct block_list* target, } switch (md->state.skillstate) { - case MSS_BERSERK: //Only Assist, Angry or Aggressive+CastSensor mobs can change target while attacking. - if (mode&(MD_ASSIST|MD_ANGRY|MD_CHANGETARGET) || (mode&(MD_AGGRESSIVE|MD_CASTSENSOR)) == (MD_AGGRESSIVE|MD_CASTSENSOR)) - return (battle_config.mob_ai&0x4 || check_distance_bl(&md->bl, target, 3)); - else + case MSS_BERSERK: + if (!mode&MD_CHANGETARGET_MELEE) return 0; + return (battle_config.mob_ai&0x4 || check_distance_bl(&md->bl, target, 3)); case MSS_RUSH: - return (mode&MD_AGGRESSIVE); + return (mode&MD_CHANGETARGET_CHASE); case MSS_FOLLOW: case MSS_ANGRY: case MSS_IDLE: @@ -1156,7 +1155,6 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) { //Change if the new target is closer than the actual one //or if the previous target is not attacking the mob. [Skotlex] md->target_id = md->attacked_id; // set target - md->state.aggressive = 0; //Retaliating. if (md->attacked_count) md->attacked_count--; //Should we reset rude attack count? md->min_chase = dist+md->db->range3; @@ -1167,7 +1165,13 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) } } if (md->state.aggressive && md->attacked_id == md->target_id) - md->state.aggressive = 0; //No longer aggressive, change to retaliate AI. + { //No longer aggressive, change to retaliate AI. + md->state.aggressive = 0; + if(md->state.skillstate== MSS_ANGRY) + md->state.skillstate = MSS_BERSERK; + if(md->state.skillstate== MSS_FOLLOW) + md->state.skillstate = MSS_RUSH; + } //Clear it since it's been checked for already. md->attacked_players = 0; md->attacked_id = 0; @@ -1185,135 +1189,126 @@ static int mob_ai_sub_hard(struct block_list *bl,va_list ap) view_range, BL_ITEM, md, &tbl); } - if ((!tbl && mode&MD_AGGRESSIVE && battle_config.monster_active_enable) || - (mode&MD_ANGRY && md->state.skillstate == MSS_FOLLOW) - ) { + if ((!tbl && mode&MD_AGGRESSIVE) || md->state.skillstate == MSS_FOLLOW) + { map_foreachinrange (mob_ai_sub_hard_activesearch, &md->bl, view_range, md->special_state.ai?BL_CHAR:BL_PC|BL_HOM, md, &tbl); - if(!tbl && mode&MD_ANGRY && !md->state.aggressive) - md->state.aggressive = 1; //Restore angry state when no targets are visible. - } else if (mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) { + } else + if (mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) + { search_size = view_rangestatus.rhw.range ? view_range:md->status.rhw.range; map_foreachinrange (mob_ai_sub_hard_changechase, &md->bl, search_size, (md->special_state.ai?BL_CHAR:BL_PC|BL_HOM), md, &tbl); } - if (tbl) - { //Target exists, attack or loot as applicable. - if (tbl->type != BL_ITEM) - { //Attempt to attack. - //At this point we know the target is attackable, we just gotta check if the range matches. - if (md->ud.target == tbl->id && md->ud.attacktimer != -1) - { - if (md->state.skillstate!=(md->state.aggressive?MSS_ANGRY:MSS_BERSERK)) - md->state.skillstate = md->state.aggressive?MSS_ANGRY:MSS_BERSERK; //Correct the state. - return 0; //Already locked. - } - - if (!battle_check_range (&md->bl, tbl, md->status.rhw.range)) - { //Out of range... - if (!(mode&MD_CANMOVE)) - { //Can't chase. Attempt to use a ranged skill at least? - md->state.skillstate = MSS_IDLE; - if (!mobskill_use(md, tick, -1)) - mob_unlocktarget(md,tick); - return 0; - } + if (!tbl) { //No targets available. + if (mode&MD_ANGRY && !md->state.aggressive) + md->state.aggressive = 1; //Restore angry state when no targets are available. - if (!can_move) - { //Stuck. Use an idle skill. o.O' - md->state.skillstate = MSS_IDLE; - if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL)) - mobskill_use(md, tick, -1); - return 0; - } - - md->state.skillstate = md->state.aggressive?MSS_FOLLOW:MSS_RUSH; - if (md->ud.walktimer != -1 && md->ud.target == tbl->id && - ( - !(battle_config.mob_ai&0x1) || - check_distance_blxy(tbl, md->ud.to_x, md->ud.to_y, md->status.rhw.range) - )) //Current target tile is still within attack range. - return 0; - - //Follow up - if (!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) || - !unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2)) - //Give up. - mob_unlocktarget(md,tick); + if(md->ud.walktimer == -1) { + // Idle skill. + md->state.skillstate = MSS_IDLE; + if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL) && mobskill_use(md, tick, -1)) return 0; - } - //Target within range, engage - md->state.skillstate = md->state.aggressive?MSS_ANGRY:MSS_BERSERK; - unit_attack(&md->bl,tbl->id,1); + } + // Random walk. + if (can_move && !md->master_id && DIFF_TICK(md->next_walktime, tick) <= 0) + mob_randomwalk(md,tick); + return 0; + } + + //Target exists, attack or loot as applicable. + if (tbl->type == BL_ITEM) + { //Loot time. + struct flooritem_data *fitem; + if (md->ud.target == tbl->id && md->ud.walktimer != -1) + return 0; //Already locked. + if (md->lootitem == NULL) + { //Can't loot... + mob_unlocktarget (md, tick); + mob_stop_walking(md,0); return 0; - } else { //Target is BL_ITEM, attempt loot. - struct flooritem_data *fitem; - int i; - if (md->ud.target == tbl->id && md->ud.walktimer != -1) - return 0; //Already locked. - if (md->lootitem == NULL) - { //Can't loot... - mob_unlocktarget (md, tick); - mob_stop_walking(md,0); + } + if (!check_distance_bl(&md->bl, tbl, 1)) + { //Still not within loot range. + if (!(mode&MD_CANMOVE)) + { //A looter that can't move? Real smart. + mob_unlocktarget(md,tick); return 0; } - - if (!check_distance_bl(&md->bl, tbl, 1)) - { //Still not within loot range. - if (!(mode&MD_CANMOVE)) - { //A looter that can't move? Real smart. - mob_unlocktarget(md,tick); - return 0; - } - if (!can_move) //Stuck. Wait before walking. - return 0; - md->state.skillstate = MSS_LOOT; // ルート時スキル使用 - if (!unit_walktobl(&md->bl, tbl, 0, 1)) - mob_unlocktarget(md, tick); //Can't loot... + if (!can_move) //Stuck. Wait before walking. return 0; - } - //Within looting range. - if (md->ud.attacktimer != -1) - return 0; //Busy attacking? - - fitem = (struct flooritem_data *)tbl; - if (md->lootitem_count < LOOTITEM_SIZE) { - memcpy (&md->lootitem[md->lootitem_count++], &fitem->item_data, sizeof(md->lootitem[0])); - if(log_config.enable_logs&0x10) //Logs items, taken by (L)ooter Mobs [Lupus] - log_pick_mob(md, "L", md->lootitem[md->lootitem_count-1].nameid, md->lootitem[md->lootitem_count-1].amount, &md->lootitem[md->lootitem_count-1]); - } else { //Destroy first looted item... - if (md->lootitem[0].card[0] == (short)0xff00) - intif_delete_petdata( MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2]) ); - for (i = 0; i < LOOTITEM_SIZE - 1; i++) - memcpy (&md->lootitem[i], &md->lootitem[i+1], sizeof(md->lootitem[0])); - memcpy (&md->lootitem[LOOTITEM_SIZE-1], &fitem->item_data, sizeof(md->lootitem[0])); - } - //Clear item. - if (pcdb_checkid(md->vd->class_)) - { //Give them walk act/delay to properly mimic players. [Skotlex] - clif_takeitem(&md->bl,tbl); - md->ud.canact_tick = tick + md->status.amotion; - unit_set_walkdelay(&md->bl, tick, md->status.amotion, 1); - } - map_clearflooritem (tbl->id); - mob_unlocktarget (md,tick); + md->state.skillstate = MSS_LOOT; + if (!unit_walktobl(&md->bl, tbl, 0, 1)) + mob_unlocktarget(md, tick); //Can't loot... return 0; } + //Within looting range. + if (md->ud.attacktimer != -1) + return 0; //Busy attacking? + + fitem = (struct flooritem_data *)tbl; + if(log_config.enable_logs&0x10) //Logs items, taken by (L)ooter Mobs [Lupus] + log_pick_mob(md, "L", fitem->item_data.nameid, fitem->item_data.amount, &fitem->item_data); + + if (md->lootitem_count < LOOTITEM_SIZE) { + memcpy (&md->lootitem[md->lootitem_count++], &fitem->item_data, sizeof(md->lootitem[0])); + } else { //Destroy first looted item... + if (md->lootitem[0].card[0] == CARD0_PET) + intif_delete_petdata( MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2]) ); + memmove(&md->lootitem[0], &md->lootitem[1], sizeof(md->lootitem) - sizeof(md->lootitem[0])); + memcpy (&md->lootitem[LOOTITEM_SIZE-1], &fitem->item_data, sizeof(md->lootitem[0])); + } + if (pcdb_checkid(md->vd->class_)) + { //Give them walk act/delay to properly mimic players. [Skotlex] + clif_takeitem(&md->bl,tbl); + md->ud.canact_tick = tick + md->status.amotion; + unit_set_walkdelay(&md->bl, tick, md->status.amotion, 1); + } + //Clear item. + map_clearflooritem (tbl->id); + mob_unlocktarget (md,tick); + return 0; + } + //Attempt to attack. + //At this point we know the target is attackable, we just gotta check if the range matches. + if (md->ud.target == tbl->id && md->ud.attacktimer != -1) //Already locked. + return 0; + + if (battle_check_range (&md->bl, tbl, md->status.rhw.range)) + { //Target within range, engage + unit_attack(&md->bl,tbl->id,1); + return 0; } - if(md->ud.walktimer == -1) { - // When there's no target, it is idling. - // Is it terribly exploitable to reuse the walkcounter for idle state skills? [Skotlex] + //Out of range... + if (!(mode&MD_CANMOVE)) + { //Can't chase. Attempt an idle skill before unlocking. md->state.skillstate = MSS_IDLE; - if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL) && mobskill_use(md, tick, -1)) - return 0; + if (!mobskill_use(md, tick, -1)) + mob_unlocktarget(md,tick); + return 0; } - // Nothing else to do... except random walking. - // Slaves do not random walk! [Skotlex] - if (can_move && !md->master_id && DIFF_TICK(md->next_walktime, tick) <= 0) - mob_randomwalk(md,tick); + if (!can_move) + { //Stuck. Attempt an idle skill + md->state.skillstate = MSS_IDLE; + if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL)) + mobskill_use(md, tick, -1); + return 0; + } + + if (md->ud.walktimer != -1 && md->ud.target == tbl->id && + ( + !(battle_config.mob_ai&0x1) || + check_distance_blxy(tbl, md->ud.to_x, md->ud.to_y, md->status.rhw.range) + )) //Current target tile is still within attack range. + return 0; + + //Follow up if possible. + if (!mob_can_reach(md, tbl, md->min_chase, MSS_RUSH) || + !unit_walktobl(&md->bl, tbl, md->status.rhw.range, 2)) + mob_unlocktarget(md,tick); return 0; } @@ -3315,7 +3310,9 @@ static int mob_readdb(void) ShowWarning("Mob with ID: %d has invalid element level %d (max is 4)\n", class_, status->ele_lv); status->ele_lv = 1; } - status->mode=atoi(str[25]); + status->mode=(int)strtol(str[25],NULL,0); + if (!battle_config.monster_active_enable) + status->mode&=~MD_AGGRESSIVE; status->speed=atoi(str[26]); status->aspd_rate = 1000; db->min_thinktime=atoi(str[27]); @@ -4002,6 +3999,8 @@ static int mob_read_sqldb(void) status->ele_lv = 1; } status->mode = TO_INT(25); + if (!battle_config.monster_active_enable) + status->mode&=~MD_AGGRESSIVE; status->speed = TO_INT(26); status->aspd_rate = 1000; db->min_thinktime = TO_INT(27); diff --git a/src/map/skill.c b/src/map/skill.c index 378e46796..daf0abc04 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1780,18 +1780,16 @@ int skill_blown (struct block_list *src, struct block_list *target, int count) if (!dx && !dy) //Could not knockback. return 0; - map_foreachinmovearea(clif_outsight,target->m, - x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE, - dx,dy,target->type==BL_PC?BL_ALL:BL_PC,target); + map_foreachinmovearea(clif_outsight, target, AREA_SIZE, + dx, dy, target->type==BL_PC?BL_ALL:BL_PC, target); if(su) skill_unit_move_unit_group(su->group,target->m,dx,dy); else map_moveblock(target, nx, ny, gettick()); - map_foreachinmovearea(clif_insight,target->m, - nx-AREA_SIZE,ny-AREA_SIZE,nx+AREA_SIZE,ny+AREA_SIZE, - -dx,-dy,target->type==BL_PC?BL_ALL:BL_PC,target); + map_foreachinmovearea(clif_insight, target, AREA_SIZE, + -dx, -dy, target->type==BL_PC?BL_ALL:BL_PC, target); if(!(count&0x20000)) clif_blown(target); diff --git a/src/map/status.c b/src/map/status.c index 6a2ef578f..397319d72 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1633,7 +1633,7 @@ int status_calc_pc(struct map_session_data* sd,int first) //FIXME: Most of these stuff should be calculated once, but how do I fix the malloc_set above to do that? [Skotlex] status->speed = DEFAULT_WALK_SPEED; - status->mode = MD_CANMOVE|MD_CANATTACK|MD_LOOTER|MD_ASSIST|MD_AGGRESSIVE|MD_CASTSENSOR; + status->mode = MD_CANMOVE|MD_CANATTACK|MD_LOOTER|MD_ASSIST|MD_AGGRESSIVE|MD_CASTSENSOR_MELEE|MD_CASTSENSOR_CHASE; status->size = (sd->class_&JOBL_BABY)?0:1; if (battle_config.character_size && pc_isriding(sd)) { //[Lupus] if (sd->class_&JOBL_BABY) { @@ -2373,7 +2373,7 @@ int status_calc_homunculus(struct homun_data *hd, int first) status->race = hd->homunculusDB->race ; status->size = hd->homunculusDB->size ; status->rhw.range = 1 + status->size; - status->mode = MD_CANMOVE|MD_CANATTACK|MD_ASSIST|MD_AGGRESSIVE|MD_CASTSENSOR; + status->mode = MD_CANMOVE|MD_CANATTACK; status->speed = DEFAULT_WALK_SPEED; if (battle_config.slaves_inherit_speed&1 && hd->master && hd->master->state.auth) //Master needs be authed to have valid speed. diff --git a/src/map/status.h b/src/map/status.h index c680ab89b..9986ad9a0 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -408,20 +408,21 @@ extern int current_equip_card_id; extern int percentrefinery[5][MAX_REFINE+1]; //The last slot always has a 0% success chance [Skotlex] //Mode definitions to clear up code reading. [Skotlex] -#define MD_CANMOVE 0x001 -#define MD_LOOTER 0x002 -//MD_ANGRY mobs are also aggressive. -#define MD_AGGRESSIVE 0x804 -#define MD_ASSIST 0x008 -#define MD_CASTSENSOR 0x010 -#define MD_BOSS 0x020 -#define MD_PLANT 0x040 -#define MD_CANATTACK 0x080 -#define MD_DETECTOR 0x100 -#define MD_CHANGETARGET 0x200 -#define MD_CHANGECHASE 0x400 -#define MD_ANGRY 0x800 -#define MD_MASK 0xFFF +#define MD_CANMOVE 0x0001 +#define MD_LOOTER 0x0002 +#define MD_AGGRESSIVE 0x0004 +#define MD_ASSIST 0x0008 +#define MD_CASTSENSOR_MELEE 0x0010 +#define MD_BOSS 0x0020 +#define MD_PLANT 0x0040 +#define MD_CANATTACK 0x0080 +#define MD_DETECTOR 0x0100 +#define MD_CASTSENSOR_CHASE 0x0200 +#define MD_CHANGECHASE 0x0400 +#define MD_ANGRY 0x0800 +#define MD_CHANGETARGET_MELEE 0x1000 +#define MD_CHANGETARGET_CHASE 0x2000 +#define MD_MASK 0xFFFF //Status change option definitions (options are what makes status changes visible to chars //who were not on your field of sight when it happened) diff --git a/src/map/unit.c b/src/map/unit.c index 9b6e4e85c..ef60579b6 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -145,9 +145,8 @@ static int unit_walktoxy_timer(int tid,unsigned int tick,int id,int data) // バシリカ判定 - map_foreachinmovearea(clif_outsight,bl->m, - x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE, - dx,dy,sd?BL_ALL:BL_PC,bl); + map_foreachinmovearea(clif_outsight,bl, AREA_SIZE, + dx, dy, sd?BL_ALL:BL_PC, bl); x += dx; y += dy; @@ -155,9 +154,8 @@ static int unit_walktoxy_timer(int tid,unsigned int tick,int id,int data) ud->walk_count++; //walked cell counter, to be used for walk-triggered skills. [Skotlex] ud->walktimer = 1; - map_foreachinmovearea(clif_insight,bl->m, - x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE, - -dx,-dy,sd?BL_ALL:BL_PC,bl); + map_foreachinmovearea(clif_insight, bl, AREA_SIZE, + -dx, -dy, sd?BL_ALL:BL_PC, bl); ud->walktimer = -1; if(sd) { @@ -244,9 +242,10 @@ static int unit_walktoxy_timer(int tid,unsigned int tick,int id,int data) } if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange)) { //Reached destination. - if (ud->state.attack_continue) { - clif_fixpos(bl); //Aegis uses one before every attack, we should - //only need this one for syncing purposes. [Skotlex] + if (ud->state.attack_continue) + { //Aegis uses one before every attack, we should + //only need this one for syncing purposes. [Skotlex] + clif_fixpos(bl); unit_attack(bl, tbl->id, ud->state.attack_continue); } } else { //Update chase-path @@ -342,6 +341,10 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int if (sc && sc->count && sc->data[SC_CONFUSION].timer != -1) //Randomize the target position map_random_dir(bl, &ud->to_x, &ud->to_y); + //Set Mob's CHASE/FOLLOW states. + if(bl->type == BL_MOB && flag&2) + ((TBL_MOB*)bl)->state.skillstate = ((TBL_MOB*)bl)->state.aggressive?MSS_FOLLOW:MSS_RUSH; + if(ud->walktimer != -1) { ud->state.change_walk_target = 1; return 1; @@ -438,16 +441,14 @@ int unit_movepos(struct block_list *bl,int dst_x,int dst_y, int easy, int checkp dx = dst_x - bl->x; dy = dst_y - bl->y; - map_foreachinmovearea(clif_outsight,bl->m, - bl->x-AREA_SIZE,bl->y-AREA_SIZE,bl->x+AREA_SIZE,bl->y+AREA_SIZE, - dx,dy,sd?BL_ALL:BL_PC,bl); + map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, + dx, dy, sd?BL_ALL:BL_PC, bl); map_moveblock(bl, dst_x, dst_y, gettick()); ud->walktimer = 1; - map_foreachinmovearea(clif_insight,bl->m, - bl->x-AREA_SIZE,bl->y-AREA_SIZE,bl->x+AREA_SIZE,bl->y+AREA_SIZE, - -dx,-dy,sd?BL_ALL:BL_PC,bl); + map_foreachinmovearea(clif_insight, bl, AREA_SIZE, + -dx, -dy, sd?BL_ALL:BL_PC, bl); ud->walktimer = -1; if(sd) { @@ -950,15 +951,22 @@ int unit_skilluse_id2(struct block_list *src, int target_id, int skill_num, int TBL_MOB *md = (TBL_MOB*)target; mobskill_event(md, src, tick, -1); //Cast targetted skill event. //temp: used to store mob's mode now. - if (tstatus->mode&MD_CASTSENSOR && + if (tstatus->mode&(MD_CASTSENSOR_MELEE|MD_CASTSENSOR_CHASE) && battle_check_target(target, src, BCT_ENEMY) > 0) { switch (md->state.skillstate) { - case MSS_ANGRY: case MSS_RUSH: case MSS_FOLLOW: - if (!(tstatus->mode&(MD_AGGRESSIVE|MD_ANGRY))) - break; //Only Aggressive mobs change target while chasing. + if (!(tstatus->mode&MD_CASTSENSOR_CHASE)) + break; + md->target_id = src->id; + md->state.aggressive = (temp&MD_ANGRY)?1:0; + md->min_chase = md->db->range3; + break; + case MSS_ANGRY: + case MSS_BERSERK: + if (!(tstatus->mode&MD_CASTSENSOR_MELEE)) + break; case MSS_IDLE: case MSS_WALK: md->target_id = src->id; @@ -1168,6 +1176,10 @@ int unit_attack(struct block_list *src,int target_id,int type) if(ud->attacktimer != -1) return 0; + //Set Mob's ANGRY/BERSERK states. + if(src->type == BL_MOB) + ((TBL_MOB*)src)->state.skillstate = ((TBL_MOB*)src)->state.aggressive?MSS_ANGRY:MSS_BERSERK; + if(DIFF_TICK(ud->attackabletime, gettick()) > 0) //Do attack next time it is possible. [Skotlex] ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,src->id,0); -- cgit v1.2.3-70-g09d2