Monster Losing Target Display (#8479)
- When a monster loses its target, it will now properly display movement to the next cell rather than snapping back to the previous cell - Looters will no longer spam movement packets to the client when they go for loot - Added some base implementation for sub-cell coordinates - Fixes #8232 Co-authored-by: Lemongrass3110
This commit is contained in:
@@ -180,7 +180,7 @@ static inline void WBUFPOS(uint8* p, unsigned short pos, short x, short y, unsig
|
||||
|
||||
|
||||
// client-side: x0+=sx0*0.0625-0.5 and y0+=sy0*0.0625-0.5
|
||||
static inline void WBUFPOS2(uint8* p, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) {
|
||||
static inline void WBUFPOS2(uint8* p, unsigned short pos, short x0, short y0, short x1, short y1, uint8 sx0, uint8 sy0) {
|
||||
p += pos;
|
||||
p[0] = (uint8)(x0>>2);
|
||||
p[1] = (uint8)((x0<<6) | ((y0>>4)&0x3f));
|
||||
@@ -1436,7 +1436,7 @@ static void clif_set_unit_walking( struct block_list& bl, map_session_data* tsd,
|
||||
p.virtue = (sc) ? sc->opt3 : 0;
|
||||
p.isPKModeON = (sd && sd->status.karma) ? 1 : 0;
|
||||
p.sex = vd->sex;
|
||||
WBUFPOS2( &p.MoveData[0], 0, bl.x, bl.y, ud.to_x, ud.to_y, 8, 8 );
|
||||
WBUFPOS2(&p.MoveData[0], 0, bl.x, bl.y, ud.to_x, ud.to_y, ud.sx, ud.sy);
|
||||
p.xSize = p.ySize = (sd) ? 5 : 0;
|
||||
p.clevel = clif_setlevel( &bl );
|
||||
#if PACKETVER >= 20080102
|
||||
|
||||
@@ -1566,7 +1566,7 @@ int mob_unlocktarget(struct mob_data *md, t_tick tick)
|
||||
break;
|
||||
default:
|
||||
mob_stop_attack(md);
|
||||
mob_stop_walking(md,1); //Stop chasing.
|
||||
unit_stop_walking_soon(md->bl); //Stop chasing.
|
||||
if (status_has_mode(&md->status,MD_ANGRY) && !md->state.aggressive)
|
||||
md->state.aggressive = 1; //Restore angry state when switching to idle
|
||||
md->state.skillstate = MSS_IDLE;
|
||||
@@ -1908,6 +1908,8 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
|
||||
md->state.skillstate = MSS_LOOT;
|
||||
if (!unit_walktobl(&md->bl, tbl, 0, 0))
|
||||
mob_unlocktarget(md, tick); //Can't loot...
|
||||
else
|
||||
unit_set_target(&md->ud, tbl->id); //Remember current loot target
|
||||
return true;
|
||||
}
|
||||
//Within looting range.
|
||||
|
||||
@@ -397,6 +397,9 @@ static TIMER_FUNC(unit_walktoxy_timer)
|
||||
}
|
||||
|
||||
ud->walktimer = INVALID_TIMER;
|
||||
// As movement to next cell finished, set sub-cell position to center
|
||||
ud->sx = 8;
|
||||
ud->sy = 8;
|
||||
|
||||
if (bl->prev == nullptr)
|
||||
return 0; // Stop moved because it is missing from the block_list
|
||||
@@ -1404,6 +1407,78 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the walkpath of a unit to end after 0.5-1.5 cells moved
|
||||
* Sends required packet for proper display on the client using subcoordinates
|
||||
* @param bl: Object to stop walking
|
||||
*/
|
||||
void unit_stop_walking_soon(struct block_list& bl)
|
||||
{
|
||||
struct unit_data* ud = unit_bl2ud(&bl);
|
||||
|
||||
if (ud == nullptr)
|
||||
return;
|
||||
|
||||
if (ud->walktimer == INVALID_TIMER)
|
||||
return;
|
||||
|
||||
if (ud->walkpath.path_pos + 1 >= ud->walkpath.path_len)
|
||||
return;
|
||||
|
||||
const struct TimerData* td = get_timer(ud->walktimer);
|
||||
|
||||
if (td == nullptr)
|
||||
return;
|
||||
|
||||
// Get how much percent we traversed on the timer
|
||||
double cell_percent = 1.0 - ((double)DIFF_TICK(td->tick, gettick()) / (double)td->data);
|
||||
|
||||
short ox = bl.x, oy = bl.y; // Remember original x and y coordinates
|
||||
short path_remain = 1; // Remaining path to walk
|
||||
|
||||
if (cell_percent > 0.0 && cell_percent < 1.0) {
|
||||
// Set subcell coordinates according to timer
|
||||
// This gives a value between 8 and 39
|
||||
ud->sx = static_cast<decltype(ud->sx)>(24.0 + dirx[ud->walkpath.path[ud->walkpath.path_pos]] * 16.0 * cell_percent);
|
||||
ud->sy = static_cast<decltype(ud->sy)>(24.0 + diry[ud->walkpath.path[ud->walkpath.path_pos]] * 16.0 * cell_percent);
|
||||
// 16-31 reflect sub position 0-15 on the current cell
|
||||
// 8-15 reflect sub position 8-15 at -1 main coordinate
|
||||
// 32-39 reflect sub position 0-7 at +1 main coordinate
|
||||
if (ud->sx < 16 || ud->sy < 16 || ud->sx > 31 || ud->sy > 31) {
|
||||
path_remain = 2;
|
||||
if (ud->sx < 16) bl.x--;
|
||||
if (ud->sy < 16) bl.y--;
|
||||
if (ud->sx > 31) bl.x++;
|
||||
if (ud->sy > 31) bl.y++;
|
||||
}
|
||||
ud->sx %= 16;
|
||||
ud->sy %= 16;
|
||||
}
|
||||
else if (cell_percent >= 1.0) {
|
||||
// Assume exactly one cell moved
|
||||
bl.x += dirx[ud->walkpath.path[ud->walkpath.path_pos]];
|
||||
bl.y += diry[ud->walkpath.path[ud->walkpath.path_pos]];
|
||||
path_remain = 2;
|
||||
}
|
||||
// Shorten walkpath
|
||||
if (ud->walkpath.path_pos + path_remain < ud->walkpath.path_len) {
|
||||
ud->walkpath.path_len = ud->walkpath.path_pos + path_remain;
|
||||
ud->to_x = ox;
|
||||
ud->to_y = oy;
|
||||
for (int i = 0; i < path_remain; i++) {
|
||||
ud->to_x += dirx[ud->walkpath.path[ud->walkpath.path_pos + i]];
|
||||
ud->to_y += diry[ud->walkpath.path[ud->walkpath.path_pos + i]];
|
||||
}
|
||||
// Send movement packet with calculated coordinates and subcoordinates
|
||||
clif_move(*ud);
|
||||
}
|
||||
// Reset coordinates
|
||||
bl.x = ox;
|
||||
bl.y = oy;
|
||||
ud->sx = 8;
|
||||
ud->sy = 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops a unit from walking
|
||||
* @param bl: Object to stop walking
|
||||
@@ -1446,8 +1521,12 @@ int unit_stop_walking(struct block_list *bl,int type)
|
||||
unit_walktoxy_timer(INVALID_TIMER, tick, bl->id, ud->walkpath.path_pos);
|
||||
}
|
||||
|
||||
if(type&USW_FIXPOS)
|
||||
clif_fixpos( *bl );
|
||||
if (type&USW_FIXPOS) {
|
||||
// Stop on cell center
|
||||
ud->sx = 8;
|
||||
ud->sy = 8;
|
||||
clif_fixpos(*bl);
|
||||
}
|
||||
|
||||
ud->walkpath.path_len = 0;
|
||||
ud->walkpath.path_pos = 0;
|
||||
@@ -3014,6 +3093,8 @@ void unit_dataset(struct block_list *bl)
|
||||
ud->attackabletime =
|
||||
ud->canact_tick =
|
||||
ud->canmove_tick = gettick();
|
||||
ud->sx = 8;
|
||||
ud->sy = 8;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,7 @@ struct unit_data {
|
||||
struct skill_unit_group_tickset skillunittick[MAX_SKILLUNITGROUPTICKSET];
|
||||
short attacktarget_lv;
|
||||
short to_x, to_y;
|
||||
uint8 sx, sy; // Subtile position (0-15, with 8 being center of cell)
|
||||
short skillx, skilly;
|
||||
uint16 skill_id, skill_lv;
|
||||
int skilltarget;
|
||||
@@ -114,6 +115,7 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir);
|
||||
TIMER_FUNC(unit_delay_walktoxy_timer);
|
||||
TIMER_FUNC(unit_delay_walktobl_timer);
|
||||
|
||||
void unit_stop_walking_soon(struct block_list& bl);
|
||||
// Causes the target object to stop moving.
|
||||
int unit_stop_walking(struct block_list *bl,int type);
|
||||
bool unit_can_move(struct block_list *bl);
|
||||
|
||||
Reference in New Issue
Block a user