|
@@ -78,25 +78,28 @@ struct unit_data* unit_bl2ud(struct block_list *bl)
|
|
*/
|
|
*/
|
|
int unit_walktoxy_sub(struct block_list *bl)
|
|
int unit_walktoxy_sub(struct block_list *bl)
|
|
{
|
|
{
|
|
- int i;
|
|
|
|
- struct walkpath_data wpd;
|
|
|
|
- struct unit_data *ud = NULL;
|
|
|
|
-
|
|
|
|
nullpo_retr(1, bl);
|
|
nullpo_retr(1, bl);
|
|
- ud = unit_bl2ud(bl);
|
|
|
|
- if(ud == NULL) return 0;
|
|
|
|
|
|
+
|
|
|
|
+ unit_data *ud = unit_bl2ud(bl);
|
|
|
|
+
|
|
|
|
+ if (ud == nullptr)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ walkpath_data wpd = { 0 };
|
|
|
|
|
|
if( !path_search(&wpd,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) )
|
|
if( !path_search(&wpd,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) )
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
#ifdef OFFICIAL_WALKPATH
|
|
#ifdef OFFICIAL_WALKPATH
|
|
- if( !path_search_long(NULL, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) // Check if there is an obstacle between
|
|
|
|
- && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
|
|
|
|
- && (bl->type != BL_NPC) ) // If type is a NPC, please disregard.
|
|
|
|
|
|
+ if( bl->type != BL_NPC // If type is a NPC, please disregard.
|
|
|
|
+ && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
|
|
|
|
+ && !path_search_long(nullptr, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) ) // Check if there is an obstacle between
|
|
return 0;
|
|
return 0;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- memcpy(&ud->walkpath,&wpd,sizeof(wpd));
|
|
|
|
|
|
+ ud->walkpath = wpd;
|
|
|
|
+
|
|
|
|
+ int i;
|
|
|
|
|
|
if (ud->target_to && ud->chaserange>1) {
|
|
if (ud->target_to && ud->chaserange>1) {
|
|
// Generally speaking, the walk path is already to an adjacent tile
|
|
// Generally speaking, the walk path is already to an adjacent tile
|
|
@@ -360,30 +363,16 @@ int unit_walktoxy_ontouch(struct block_list *bl, va_list ap)
|
|
* @param data: Data used in timer calls
|
|
* @param data: Data used in timer calls
|
|
* @return 0 or unit_walktoxy_sub() or unit_walktoxy()
|
|
* @return 0 or unit_walktoxy_sub() or unit_walktoxy()
|
|
*/
|
|
*/
|
|
-static TIMER_FUNC(unit_walktoxy_timer){
|
|
|
|
- int i;
|
|
|
|
- int x,y,dx,dy;
|
|
|
|
- unsigned char icewall_walk_block;
|
|
|
|
- struct block_list *bl;
|
|
|
|
- struct unit_data *ud;
|
|
|
|
- TBL_PC *sd=NULL;
|
|
|
|
- TBL_MOB *md=NULL;
|
|
|
|
- TBL_NPC *nd=NULL;
|
|
|
|
-
|
|
|
|
- bl = map_id2bl(id);
|
|
|
|
|
|
+static TIMER_FUNC(unit_walktoxy_timer)
|
|
|
|
+{
|
|
|
|
+ block_list *bl = map_id2bl(id);
|
|
|
|
|
|
- if(bl == NULL)
|
|
|
|
|
|
+ if(bl == nullptr)
|
|
return 0;
|
|
return 0;
|
|
|
|
+
|
|
|
|
+ unit_data *ud = unit_bl2ud(bl);
|
|
|
|
|
|
- switch(bl->type) { // svoid useless cast, we can only be 1 type
|
|
|
|
- case BL_PC: sd = BL_CAST(BL_PC, bl); break;
|
|
|
|
- case BL_MOB: md = BL_CAST(BL_MOB, bl); break;
|
|
|
|
- case BL_NPC: nd = BL_CAST(BL_NPC, bl); break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- ud = unit_bl2ud(bl);
|
|
|
|
-
|
|
|
|
- if(ud == NULL)
|
|
|
|
|
|
+ if(ud == nullptr)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
if(ud->walktimer != tid) {
|
|
if(ud->walktimer != tid) {
|
|
@@ -393,7 +382,7 @@ static TIMER_FUNC(unit_walktoxy_timer){
|
|
|
|
|
|
ud->walktimer = INVALID_TIMER;
|
|
ud->walktimer = INVALID_TIMER;
|
|
|
|
|
|
- if (bl->prev == NULL)
|
|
|
|
|
|
+ if (bl->prev == nullptr)
|
|
return 0; // Stop moved because it is missing from the block_list
|
|
return 0; // Stop moved because it is missing from the block_list
|
|
|
|
|
|
if(ud->walkpath.path_pos>=ud->walkpath.path_len)
|
|
if(ud->walkpath.path_pos>=ud->walkpath.path_len)
|
|
@@ -402,26 +391,38 @@ static TIMER_FUNC(unit_walktoxy_timer){
|
|
if(ud->walkpath.path[ud->walkpath.path_pos]>=DIR_MAX)
|
|
if(ud->walkpath.path[ud->walkpath.path_pos]>=DIR_MAX)
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
- x = bl->x;
|
|
|
|
- y = bl->y;
|
|
|
|
|
|
+ int x = bl->x;
|
|
|
|
+ int y = bl->y;
|
|
|
|
|
|
enum directions dir = ud->walkpath.path[ud->walkpath.path_pos];
|
|
enum directions dir = ud->walkpath.path[ud->walkpath.path_pos];
|
|
ud->dir = dir;
|
|
ud->dir = dir;
|
|
|
|
|
|
- dx = dirx[dir];
|
|
|
|
- dy = diry[dir];
|
|
|
|
|
|
+ int dx = dirx[dir];
|
|
|
|
+ int dy = diry[dir];
|
|
|
|
+
|
|
|
|
+ map_session_data *sd = nullptr;
|
|
|
|
+ mob_data *md = nullptr;
|
|
|
|
+ npc_data *nd = nullptr;
|
|
|
|
|
|
// Get icewall walk block depending on Status Immune mode (players can't be trapped)
|
|
// Get icewall walk block depending on Status Immune mode (players can't be trapped)
|
|
- if(md && status_has_mode(&md->status,MD_STATUS_IMMUNE))
|
|
|
|
- icewall_walk_block = battle_config.boss_icewall_walk_block;
|
|
|
|
- else if(md)
|
|
|
|
- icewall_walk_block = battle_config.mob_icewall_walk_block;
|
|
|
|
- else
|
|
|
|
- icewall_walk_block = 0;
|
|
|
|
|
|
+ unsigned char icewall_walk_block = 0;
|
|
|
|
+
|
|
|
|
+ switch(bl->type) { // avoid useless cast, we can only be 1 type
|
|
|
|
+ case BL_PC: sd = BL_CAST(BL_PC, bl); break;
|
|
|
|
+ case BL_MOB:
|
|
|
|
+ md = BL_CAST(BL_MOB, bl);
|
|
|
|
+
|
|
|
|
+ if (status_has_mode(&md->status,MD_STATUS_IMMUNE))
|
|
|
|
+ icewall_walk_block = battle_config.boss_icewall_walk_block;
|
|
|
|
+ else
|
|
|
|
+ icewall_walk_block = battle_config.mob_icewall_walk_block;
|
|
|
|
+ break;
|
|
|
|
+ case BL_NPC: nd = BL_CAST(BL_NPC, bl); break;
|
|
|
|
+ }
|
|
|
|
|
|
//Monsters will walk into an icewall from the west and south if they already started walking
|
|
//Monsters will walk into an icewall from the west and south if they already started walking
|
|
if(map_getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS)
|
|
if(map_getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS)
|
|
- && (icewall_walk_block == 0 || !map_getcell(bl->m,x+dx,y+dy,CELL_CHKICEWALL) || dx < 0 || dy < 0))
|
|
|
|
|
|
+ && (icewall_walk_block == 0 || dx < 0 || dy < 0 || !map_getcell(bl->m,x+dx,y+dy,CELL_CHKICEWALL)))
|
|
return unit_walktoxy_sub(bl);
|
|
return unit_walktoxy_sub(bl);
|
|
|
|
|
|
//Monsters can only leave icewalls to the west and south
|
|
//Monsters can only leave icewalls to the west and south
|
|
@@ -554,6 +555,8 @@ static TIMER_FUNC(unit_walktoxy_timer){
|
|
if(tid == INVALID_TIMER) // A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
|
|
if(tid == INVALID_TIMER) // A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
+ int speed;
|
|
|
|
+
|
|
//If stepaction is set then we remembered a client request that should be executed on the next step
|
|
//If stepaction is set then we remembered a client request that should be executed on the next step
|
|
if (ud->stepaction && ud->target_to) {
|
|
if (ud->stepaction && ud->target_to) {
|
|
//Delete old stepaction even if not executed yet, the latest command is what counts
|
|
//Delete old stepaction even if not executed yet, the latest command is what counts
|
|
@@ -563,10 +566,10 @@ static TIMER_FUNC(unit_walktoxy_timer){
|
|
}
|
|
}
|
|
//Delay stepactions by half a step (so they are executed at full step)
|
|
//Delay stepactions by half a step (so they are executed at full step)
|
|
if( direction_diagonal( ud->walkpath.path[ud->walkpath.path_pos] ) )
|
|
if( direction_diagonal( ud->walkpath.path[ud->walkpath.path_pos] ) )
|
|
- i = status_get_speed(bl)*MOVE_DIAGONAL_COST/MOVE_COST/2;
|
|
|
|
|
|
+ speed = status_get_speed(bl)*MOVE_DIAGONAL_COST/MOVE_COST/2;
|
|
else
|
|
else
|
|
- i = status_get_speed(bl)/2;
|
|
|
|
- ud->steptimer = add_timer(tick+i, unit_step_timer, bl->id, 0);
|
|
|
|
|
|
+ speed = status_get_speed(bl)/2;
|
|
|
|
+ ud->steptimer = add_timer(tick+speed, unit_step_timer, bl->id, 0);
|
|
}
|
|
}
|
|
|
|
|
|
if(ud->state.change_walk_target) {
|
|
if(ud->state.change_walk_target) {
|
|
@@ -581,14 +584,14 @@ static TIMER_FUNC(unit_walktoxy_timer){
|
|
ud->walkpath.path_pos++;
|
|
ud->walkpath.path_pos++;
|
|
|
|
|
|
if(ud->walkpath.path_pos >= ud->walkpath.path_len)
|
|
if(ud->walkpath.path_pos >= ud->walkpath.path_len)
|
|
- i = -1;
|
|
|
|
|
|
+ speed = -1;
|
|
else if( direction_diagonal( ud->walkpath.path[ud->walkpath.path_pos] ) )
|
|
else if( direction_diagonal( ud->walkpath.path[ud->walkpath.path_pos] ) )
|
|
- i = status_get_speed(bl)*MOVE_DIAGONAL_COST/MOVE_COST;
|
|
|
|
|
|
+ speed = status_get_speed(bl)*MOVE_DIAGONAL_COST/MOVE_COST;
|
|
else
|
|
else
|
|
- i = status_get_speed(bl);
|
|
|
|
|
|
+ speed = status_get_speed(bl);
|
|
|
|
|
|
- if(i > 0) {
|
|
|
|
- ud->walktimer = add_timer(tick+i,unit_walktoxy_timer,id,i);
|
|
|
|
|
|
+ if(speed > 0) {
|
|
|
|
+ ud->walktimer = add_timer(tick+speed,unit_walktoxy_timer,id,speed);
|
|
if( md && DIFF_TICK(tick,md->dmgtick) < 3000 ) // Not required not damaged recently
|
|
if( md && DIFF_TICK(tick,md->dmgtick) < 3000 ) // Not required not damaged recently
|
|
clif_move(ud);
|
|
clif_move(ud);
|
|
} else if(ud->state.running) { // Keep trying to run.
|
|
} else if(ud->state.running) { // Keep trying to run.
|
|
@@ -696,36 +699,34 @@ TIMER_FUNC(unit_delay_walktobl_timer){
|
|
*/
|
|
*/
|
|
int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)
|
|
int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)
|
|
{
|
|
{
|
|
- struct unit_data* ud = NULL;
|
|
|
|
- struct status_change* sc = NULL;
|
|
|
|
- struct walkpath_data wpd;
|
|
|
|
- TBL_PC *sd = NULL;
|
|
|
|
-
|
|
|
|
nullpo_ret(bl);
|
|
nullpo_ret(bl);
|
|
|
|
|
|
- ud = unit_bl2ud(bl);
|
|
|
|
|
|
+ unit_data* ud = unit_bl2ud(bl);
|
|
|
|
|
|
- if (ud == NULL)
|
|
|
|
|
|
+ if (ud == nullptr)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- if (bl->type == BL_PC)
|
|
|
|
- sd = BL_CAST(BL_PC, bl);
|
|
|
|
-
|
|
|
|
if ((flag&8) && !map_closest_freecell(bl->m, &x, &y, BL_CHAR|BL_NPC, 1)) //This might change x and y
|
|
if ((flag&8) && !map_closest_freecell(bl->m, &x, &y, BL_CHAR|BL_NPC, 1)) //This might change x and y
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
+ walkpath_data wpd = { 0 };
|
|
|
|
+
|
|
if (!path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS)) // Count walk path cells
|
|
if (!path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS)) // Count walk path cells
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
+ // NPCs do not need to fulfill the following checks
|
|
|
|
+ if( bl->type != BL_NPC ){
|
|
|
|
+ if( wpd.path_len > battle_config.max_walk_path ){
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
#ifdef OFFICIAL_WALKPATH
|
|
#ifdef OFFICIAL_WALKPATH
|
|
- if( !path_search_long(NULL, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS) // Check if there is an obstacle between
|
|
|
|
- && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
|
|
|
|
- && (bl->type != BL_NPC) ) // If type is a NPC, please disregard.
|
|
|
|
|
|
+ // Official number of walkable cells is 14 if and only if there is an obstacle between.
|
|
|
|
+ if( wpd.path_len > 14 && !path_search_long( nullptr, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS ) ){
|
|
return 0;
|
|
return 0;
|
|
|
|
+ }
|
|
#endif
|
|
#endif
|
|
-
|
|
|
|
- if ((wpd.path_len > battle_config.max_walk_path) && (bl->type != BL_NPC))
|
|
|
|
- return 0;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
if (flag&4) {
|
|
if (flag&4) {
|
|
unit_unattackable(bl);
|
|
unit_unattackable(bl);
|
|
@@ -745,7 +746,7 @@ int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)
|
|
ud->to_y = y;
|
|
ud->to_y = y;
|
|
unit_stop_attack(bl); //Sets target to 0
|
|
unit_stop_attack(bl); //Sets target to 0
|
|
|
|
|
|
- sc = status_get_sc(bl);
|
|
|
|
|
|
+ status_change* sc = status_get_sc(bl);
|
|
if (sc && sc->data[SC_CONFUSION]) // Randomize the target position
|
|
if (sc && sc->data[SC_CONFUSION]) // Randomize the target position
|
|
map_random_dir(bl, &ud->to_x, &ud->to_y);
|
|
map_random_dir(bl, &ud->to_x, &ud->to_y);
|
|
|
|
|
|
@@ -756,15 +757,19 @@ int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ TBL_PC *sd = BL_CAST(BL_PC, bl);
|
|
|
|
+
|
|
// Start timer to recall summon
|
|
// Start timer to recall summon
|
|
- if (sd && sd->md)
|
|
|
|
- unit_check_start_teleport_timer(&sd->md->bl);
|
|
|
|
- if (sd && sd->ed)
|
|
|
|
- unit_check_start_teleport_timer(&sd->ed->bl);
|
|
|
|
- if (sd && sd->hd)
|
|
|
|
- unit_check_start_teleport_timer(&sd->hd->bl);
|
|
|
|
- if (sd && sd->pd)
|
|
|
|
- unit_check_start_teleport_timer(&sd->pd->bl);
|
|
|
|
|
|
+ if( sd != nullptr ){
|
|
|
|
+ if (sd->md != nullptr)
|
|
|
|
+ unit_check_start_teleport_timer(&sd->md->bl);
|
|
|
|
+ if (sd->ed != nullptr)
|
|
|
|
+ unit_check_start_teleport_timer(&sd->ed->bl);
|
|
|
|
+ if (sd->hd != nullptr)
|
|
|
|
+ unit_check_start_teleport_timer(&sd->hd->bl);
|
|
|
|
+ if (sd->pd != nullptr)
|
|
|
|
+ unit_check_start_teleport_timer(&sd->pd->bl);
|
|
|
|
+ }
|
|
|
|
|
|
return unit_walktoxy_sub(bl);
|
|
return unit_walktoxy_sub(bl);
|
|
}
|
|
}
|
|
@@ -819,15 +824,12 @@ static TIMER_FUNC(unit_walktobl_sub){
|
|
*/
|
|
*/
|
|
int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, unsigned char flag)
|
|
int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, unsigned char flag)
|
|
{
|
|
{
|
|
- struct unit_data *ud = NULL;
|
|
|
|
- struct status_change *sc = NULL;
|
|
|
|
-
|
|
|
|
nullpo_ret(bl);
|
|
nullpo_ret(bl);
|
|
nullpo_ret(tbl);
|
|
nullpo_ret(tbl);
|
|
|
|
|
|
- ud = unit_bl2ud(bl);
|
|
|
|
|
|
+ unit_data *ud = unit_bl2ud(bl);
|
|
|
|
|
|
- if(ud == NULL)
|
|
|
|
|
|
+ if(ud == nullptr)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
if (!status_bl_has_mode(bl,MD_CANMOVE))
|
|
if (!status_bl_has_mode(bl,MD_CANMOVE))
|
|
@@ -851,7 +853,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, unsi
|
|
ud->state.attack_continue = flag&2?1:0; // Chase to attack.
|
|
ud->state.attack_continue = flag&2?1:0; // Chase to attack.
|
|
unit_stop_attack(bl); //Sets target to 0
|
|
unit_stop_attack(bl); //Sets target to 0
|
|
|
|
|
|
- sc = status_get_sc(bl);
|
|
|
|
|
|
+ status_change *sc = status_get_sc(bl);
|
|
if (sc && sc->data[SC_CONFUSION]) // Randomize the target position
|
|
if (sc && sc->data[SC_CONFUSION]) // Randomize the target position
|
|
map_random_dir(bl, &ud->to_x, &ud->to_y);
|
|
map_random_dir(bl, &ud->to_x, &ud->to_y);
|
|
|
|
|
|
@@ -2541,10 +2543,10 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range,
|
|
return false;
|
|
return false;
|
|
|
|
|
|
#ifdef OFFICIAL_WALKPATH
|
|
#ifdef OFFICIAL_WALKPATH
|
|
- if( !path_search_long(NULL, bl->m, bl->x, bl->y, tbl->x-dx, tbl->y-dy, CELL_CHKNOPASS) // Check if there is an obstacle between
|
|
|
|
- && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
|
|
|
|
- && (bl->type != BL_NPC) ) // If type is a NPC, please disregard.
|
|
|
|
- return false;
|
|
|
|
|
|
+ if( bl->type != BL_NPC // If type is a NPC, please disregard.
|
|
|
|
+ && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
|
|
|
|
+ && !path_search_long(nullptr, bl->m, bl->x, bl->y, tbl->x-dx, tbl->y-dy, CELL_CHKNOPASS) ) // Check if there is an obstacle between
|
|
|
|
+ return false;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
return true;
|
|
return true;
|