summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-12-06 18:21:32 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-12-06 18:21:32 +0000
commitf4edc7e4431b929acc62e4c2427e815ba9d69779 (patch)
treeac82447101de9f643bef0fa7a5b3a56bd1e37194 /src
parentf7ff1f208a2ce086fe6636b8359c65cf14ab68f4 (diff)
downloadhercules-f4edc7e4431b929acc62e4c2427e815ba9d69779.tar.gz
hercules-f4edc7e4431b929acc62e4c2427e815ba9d69779.tar.bz2
hercules-f4edc7e4431b929acc62e4c2427e815ba9d69779.tar.xz
hercules-f4edc7e4431b929acc62e4c2427e815ba9d69779.zip
- 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
Diffstat (limited to 'src')
-rw-r--r--src/map/map.c69
-rw-r--r--src/map/map.h2
-rw-r--r--src/map/mob.c233
-rw-r--r--src/map/skill.c10
-rw-r--r--src/map/status.c4
-rw-r--r--src/map/status.h29
-rw-r--r--src/map/unit.c50
7 files changed, 212 insertions, 185 deletions
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;i<c && bl;i++,bl=bl->next){
- if(bl && bl->type&type && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
+ if(bl->type&type &&
+ bl->x>=x0 && bl->x<=x1 &&
+ bl->y>=y0 && bl->y<=y1 &&
+ bl_list_count<BL_LIST_MAX)
bl_list[bl_list_count++]=bl;
}
}
@@ -907,15 +915,16 @@ int map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,i
bl = map[m].block_mob[bx+by*map[m].bxs];
c = map[m].block_mob_count[bx+by*map[m].bxs];
for(i=0;i<c && bl;i++,bl=bl->next){
- if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
+ if(bl->x>=x0 && bl->x<=x1 &&
+ bl->y>=y0 && bl->y<=y1 &&
+ bl_list_count<BL_LIST_MAX)
bl_list[bl_list_count++]=bl;
}
}
}
}
}else{
- // L字領域の場合
-
+ // Diagonal movement
if(x0<0) x0=0;
if(y0<0) y0=0;
if(x1>=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;i<c && bl;i++,bl=bl->next){
- 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_count<BL_LIST_MAX))
continue;
- if(bl && bl->type&type && ((dx>0 && bl->x<x0+dx) || (dx<0 && bl->x>x1+dx) ||
- (dy>0 && bl->y<y0+dy) || (dy<0 && bl->y>y1+dy)) &&
- bl_list_count<BL_LIST_MAX)
- bl_list[bl_list_count++]=bl;
+ if((dx>0 && bl->x<x0+dx) ||
+ (dx<0 && bl->x>x1+dx) ||
+ (dy>0 && bl->y<y0+dy) ||
+ (dy<0 && bl->y>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;i<c && bl;i++,bl=bl->next){
- 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_count<BL_LIST_MAX))
continue;
- if(bl && ((dx>0 && bl->x<x0+dx) || (dx<0 && bl->x>x1+dx) ||
- (dy>0 && bl->y<y0+dy) || (dy<0 && bl->y>y1+dy)) &&
- bl_list_count<BL_LIST_MAX)
+ if((dx>0 && bl->x<x0+dx) ||
+ (dx<0 && bl->x>x1+dx) ||
+ (dy>0 && bl->y<y0+dy) ||
+ (dy<0 && bl->y>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_range<md->status.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);