Small walkpath optimizations (#5322)

* Thanks to @mattthewaz
Co-authored-by: Aleos <aleos89@users.noreply.github.com>
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
This commit is contained in:
Daegaladh 2020-10-27 11:58:35 +01:00 committed by GitHub
parent 7a4bef2ab7
commit 8682a9e02e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -78,25 +78,28 @@ struct unit_data* unit_bl2ud(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);
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) )
return 0;
#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;
#endif
memcpy(&ud->walkpath,&wpd,sizeof(wpd));
ud->walkpath = wpd;
int i;
if (ud->target_to && ud->chaserange>1) {
// 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
* @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;
static TIMER_FUNC(unit_walktoxy_timer)
{
block_list *bl = map_id2bl(id);
bl = map_id2bl(id);
if(bl == NULL)
if(bl == nullptr)
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;
if(ud->walktimer != tid) {
@ -393,7 +382,7 @@ static TIMER_FUNC(unit_walktoxy_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
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)
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];
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)
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
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);
//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.
return 0;
int speed;
//If stepaction is set then we remembered a client request that should be executed on the next step
if (ud->stepaction && ud->target_to) {
//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)
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
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) {
@ -581,14 +584,14 @@ static TIMER_FUNC(unit_walktoxy_timer){
ud->walkpath.path_pos++;
if(ud->walkpath.path_pos >= ud->walkpath.path_len)
i = -1;
speed = -1;
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
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
clif_move(ud);
} 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)
{
struct unit_data* ud = NULL;
struct status_change* sc = NULL;
struct walkpath_data wpd;
TBL_PC *sd = NULL;
nullpo_ret(bl);
ud = unit_bl2ud(bl);
unit_data* ud = unit_bl2ud(bl);
if (ud == NULL)
if (ud == nullptr)
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
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
return 0;
#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.
// 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;
#endif
}
if ((wpd.path_len > battle_config.max_walk_path) && (bl->type != BL_NPC))
return 0;
#ifdef OFFICIAL_WALKPATH
// 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;
}
#endif
}
if (flag&4) {
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;
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
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;
}
TBL_PC *sd = BL_CAST(BL_PC, bl);
// 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);
}
@ -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)
{
struct unit_data *ud = NULL;
struct status_change *sc = NULL;
nullpo_ret(bl);
nullpo_ret(tbl);
ud = unit_bl2ud(bl);
unit_data *ud = unit_bl2ud(bl);
if(ud == NULL)
if(ud == nullptr)
return 0;
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.
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
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;
#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
return true;