Skip to content

Commit

Permalink
Fix slavemob bahavior (#7978)
Browse files Browse the repository at this point in the history
Fixes #6885

Co-authored-by: aleos89 <aleos89@users.noreply.github.com>
  • Loading branch information
eppc0330 and aleos89 committed May 19, 2024
1 parent b81904d commit 949a330
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 3 deletions.
18 changes: 17 additions & 1 deletion src/map/battle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10473,6 +10473,22 @@ struct block_list* battle_get_master(struct block_list *src)
return prev;
}

bool battle_get_exception_ai(block_list &src) {
mob_data *md = BL_CAST(BL_MOB, &src);

if (!md)
return false;

switch (md->special_state.ai) {
case AI_ABR:
case AI_ATTACK:
case AI_BIONIC:
case AI_ZANZOU:
return true;
}
return false;
}

/*==========================================
* Checks the state between two targets
* (enemy, friend, party, guild, etc)
Expand Down Expand Up @@ -10724,7 +10740,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if( !md->special_state.ai )
{ //Normal mobs
if(
( target->type == BL_MOB && t_bl->type == BL_PC && ( ((TBL_MOB*)target)->special_state.ai != AI_ZANZOU && ((TBL_MOB*)target)->special_state.ai != AI_ATTACK ) ) ||
( target->type == BL_MOB && t_bl->type == BL_PC && !battle_get_exception_ai(*target) ) ||
( t_bl->type == BL_MOB && (((TBL_MOB*)t_bl)->special_state.ai == AI_NONE || ((TBL_MOB*)t_bl)->special_state.ai == AI_WAVEMODE ))
)
state |= BCT_PARTY; //Normal mobs with no ai or with AI_WAVEMODE are friends.
Expand Down
40 changes: 38 additions & 2 deletions src/map/mob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1444,8 +1444,17 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,t_tick tick)
}
}

if(md->target_id) //Slave is busy with a target.
return 0;
// Slave is busy with a target.
if(md->target_id) {
// Player's slave should come back when master's too far, even if it is doing with a target.
if (bl->type == BL_PC && md->master_dist > 5) {
mob_unlocktarget(md, tick);
unit_walktobl(&md->bl, bl, MOB_SLAVEDISTANCE, 1);
return 1;
} else {
return 0;
}
}

// Approach master if within view range, chase back to Master's area also if standing on top of the master.
if ((md->master_dist > MOB_SLAVEDISTANCE || md->master_dist == 0) && unit_can_move(&md->bl)) {
Expand Down Expand Up @@ -3502,6 +3511,33 @@ int mob_countslave(struct block_list *bl)
return map_foreachinmap(mob_countslave_sub, bl->m, BL_MOB,bl->id);
}

/**
* Remove slaves if master logs off.
* @param bl: Mob data
* @param ap: List of arguments
* @return 1 on removal, otherwise 0
*/
int mob_removeslaves_sub(block_list *bl, va_list ap) {
int id = va_arg(ap, int);
mob_data *md = (mob_data *)bl;

if (md != nullptr && md->master_id == id) {
unit_free(bl, CLR_OUTSIGHT);
return 1;
}

return 0;
}

/**
* Remove slaves on a map.
* @param bl: Player data
* @return 1 on removal, otherwise 0
*/
int mob_removeslaves(block_list *bl) {
return map_foreachinmap(mob_removeslaves_sub, bl->m, BL_MOB, bl->id);
}

/*==========================================
* Summons amount slaves contained in the value[5] array using round-robin. [adapted by Skotlex]
*------------------------------------------*/
Expand Down
1 change: 1 addition & 0 deletions src/map/mob.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,7 @@ int mobskill_event(struct mob_data *md,struct block_list *src,t_tick tick, int f
int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id);
int mob_countslave(struct block_list *bl);
int mob_count_sub(struct block_list *bl, va_list ap);
int mob_removeslaves(block_list* bl);

int mob_is_clone(int mob_id);

Expand Down
1 change: 1 addition & 0 deletions src/map/unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3465,6 +3465,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
pc_inventory_rental_clear(sd);
pc_delspiritball(sd, sd->spiritball, 1);
pc_delspiritcharm(sd, sd->spiritcharm, sd->spiritcharm_type);
mob_removeslaves(&sd->bl);

if( sd->st && sd->st->state != RUN ) {// free attached scripts that are waiting
script_free_state(sd->st);
Expand Down

0 comments on commit 949a330

Please sign in to comment.