diff --git a/src/map/mob.c b/src/map/mob.c index cf65071d0b..83ab17bd82 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -57,6 +57,15 @@ #define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used? #define MAX_MOB_CHAT 50 //Max Skill's messages +// On official servers, monsters will only seek targets that are closer to walk to than their +// search range. The search range is affected depending on if the monster is walking or not. +// On some maps there can be a quite long path for just walking two cells in a direction and +// the client does not support displaying walk paths that are longer than 14 cells, so this +// option reduces position lag in such situation. But doing a complex search for every possible +// target, might be CPU intensive. +// Disable this to make monsters not do any path search when looking for a target (old behavior). +#define ACTIVEPATHSEARCH + //Dynamic mob database, allows saving of memory when there's big gaps in the mob_db [Skotlex] struct mob_db *mob_db_data[MAX_MOB_DB+1]; struct mob_db *mob_dummy = NULL; //Dummy mob to be returned when a non-existant one is requested. @@ -1059,6 +1068,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) { struct mob_data *md; struct block_list **target; + struct walkpath_data wpd; int mode; int dist; @@ -1093,6 +1103,14 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) && battle_check_range(&md->bl,bl,md->db->range2) ) { //Pick closest target? +#ifdef ACTIVEPATHSEARCH + if (!path_search(&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0, CELL_CHKNOPASS)) // Count walk path cells + return 0; + //Standing monsters use range2, walking monsters use range3 + if ((md->ud.walktimer == INVALID_TIMER && wpd.path_len > md->db->range2) + || (md->ud.walktimer != INVALID_TIMER && wpd.path_len > md->db->range3)) + return 0; +#endif (*target) = bl; md->target_id=bl->id; md->min_chase= dist + md->db->range3; diff --git a/src/map/status.c b/src/map/status.c index 6380d63886..7041008f05 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -4117,6 +4117,21 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if (!b_status || !status) return; + /** [Playtester] + * This needs to be done even if there is currently no status change active, because + * we need to update the speed on the client when the last status change ends. + **/ + if(flag&SCB_SPEED) { + struct unit_data *ud = unit_bl2ud(bl); + /** [Skotlex] + * Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER + * because if you step on something while walking, the moment this + * piece of code triggers the walk-timer is set on INVALID_TIMER) + **/ + if (ud) + ud->state.change_walk_target = ud->state.speed_changed = 1; + } + if((!(bl->type&BL_REGEN)) && (!sc || !sc->count)) { // No difference. status_cpy(status, b_status); return; @@ -4294,18 +4309,8 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) } if(flag&SCB_SPEED) { - struct unit_data *ud = unit_bl2ud(bl); - status->speed = status_calc_speed(bl, sc, b_status->speed); - /** [Skotlex] - * Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER - * because if you step on something while walking, the moment this - * piece of code triggers the walk-timer is set on INVALID_TIMER) - **/ - if (ud) - ud->state.change_walk_target = ud->state.speed_changed = 1; - if( bl->type&BL_PC && !(sd && sd->state.permanent_speed) && status->speed < battle_config.max_walk_speed ) status->speed = battle_config.max_walk_speed; @@ -4753,8 +4758,6 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang str -= sc->data[SC_HARMONIZE]->val2; return (unsigned short)cap_value(str,0,USHRT_MAX); } - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && str < 50) - return 50; if(sc->data[SC_INCALLSTATUS]) str += sc->data[SC_INCALLSTATUS]->val1; if(sc->data[SC_CHASEWALK2]) @@ -4787,6 +4790,8 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang str -= ((sc->data[SC_MARIONETTE]->val3)>>16)&0xFF; if(sc->data[SC_MARIONETTE2]) str += ((sc->data[SC_MARIONETTE2]->val3)>>16)&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH) + str += ((sc->data[SC_SPIRIT]->val3)>>16)&0xFF; if(sc->data[SC_GIANTGROWTH]) str += 30; if(sc->data[SC_BEYONDOFWARCRY]) @@ -4821,8 +4826,6 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang agi -= sc->data[SC_HARMONIZE]->val2; return (unsigned short)cap_value(agi,0,USHRT_MAX); } - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && agi < 50) - return 50; if(sc->data[SC_CONCENTRATE] && !sc->data[SC_QUAGMIRE]) agi += (agi-sc->data[SC_CONCENTRATE]->val3)*sc->data[SC_CONCENTRATE]->val2/100; if(sc->data[SC_INCALLSTATUS]) @@ -4851,6 +4854,8 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang agi -= ((sc->data[SC_MARIONETTE]->val3)>>8)&0xFF; if(sc->data[SC_MARIONETTE2]) agi += ((sc->data[SC_MARIONETTE2]->val3)>>8)&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH) + agi += ((sc->data[SC_SPIRIT]->val3)>>8)&0xFF; if(sc->data[SC_ADORAMUS]) agi -= sc->data[SC_ADORAMUS]->val2; if(sc->data[SC_MARSHOFABYSS]) @@ -4885,8 +4890,6 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang vit -= sc->data[SC_HARMONIZE]->val2; return (unsigned short)cap_value(vit,0,USHRT_MAX); } - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && vit < 50) - return 50; if(sc->data[SC_INCALLSTATUS]) vit += sc->data[SC_INCALLSTATUS]->val1; if(sc->data[SC_INCVIT]) @@ -4905,6 +4908,8 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang vit -= sc->data[SC_MARIONETTE]->val3&0xFF; if(sc->data[SC_MARIONETTE2]) vit += sc->data[SC_MARIONETTE2]->val3&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH) + vit += sc->data[SC_SPIRIT]->val3&0xFF; if(sc->data[SC_LAUDAAGNUS]) vit += 4 + sc->data[SC_LAUDAAGNUS]->val1; if(sc->data[SC_MINOR_BBQ]) @@ -4943,8 +4948,6 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang int_ -= sc->data[SC_HARMONIZE]->val2; return (unsigned short)cap_value(int_,0,USHRT_MAX); } - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && int_ < 50) - return 50; if(sc->data[SC_INCALLSTATUS]) int_ += sc->data[SC_INCALLSTATUS]->val1; if(sc->data[SC_INCINT]) @@ -4971,6 +4974,8 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang int_ -= ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF; if(sc->data[SC_MARIONETTE2]) int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH) + int_ += ((sc->data[SC_SPIRIT]->val4)>>16)&0xFF; if(sc->data[SC_INSPIRATION]) int_ += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_MELODYOFSINK]) @@ -5012,8 +5017,6 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang dex -= sc->data[SC_HARMONIZE]->val2; return (unsigned short)cap_value(dex,0,USHRT_MAX); } - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && dex < 50) - return 50; if(sc->data[SC_CONCENTRATE] && !sc->data[SC_QUAGMIRE]) dex += (dex-sc->data[SC_CONCENTRATE]->val4)*sc->data[SC_CONCENTRATE]->val2/100; if(sc->data[SC_INCALLSTATUS]) @@ -5044,6 +5047,8 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang dex -= ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF; if(sc->data[SC_MARIONETTE2]) dex += ((sc->data[SC_MARIONETTE2]->val4)>>8)&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH) + dex += ((sc->data[SC_SPIRIT]->val4)>>8)&0xFF; if(sc->data[SC_SIROMA_ICE_TEA]) dex += sc->data[SC_SIROMA_ICE_TEA]->val1; if(sc->data[SC_INSPIRATION]) @@ -5081,8 +5086,6 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang } if(sc->data[SC_CURSE]) return 0; - if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && luk < 50) - return 50; if(sc->data[SC_INCALLSTATUS]) luk += sc->data[SC_INCALLSTATUS]->val1; if(sc->data[SC_INCLUK]) @@ -5099,6 +5102,8 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang luk -= sc->data[SC_MARIONETTE]->val4&0xFF; if(sc->data[SC_MARIONETTE2]) luk += sc->data[SC_MARIONETTE2]->val4&0xFF; + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH) + luk += sc->data[SC_SPIRIT]->val4&0xFF; if(sc->data[SC_PUTTI_TAILS_NOODLES]) luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1; if(sc->data[SC_INSPIRATION]) @@ -7979,10 +7984,14 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) status_change_end(bl, SC_STONE, INVALID_TIMER); } + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH) + status_change_end(bl, SC_SPIRIT, INVALID_TIMER); break; case SC_INCREASEAGI: status_change_end(bl, SC_DECREASEAGI, INVALID_TIMER); status_change_end(bl, SC_ADORAMUS, INVALID_TIMER); + if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH) + status_change_end(bl, SC_SPIRIT, INVALID_TIMER); break; case SC_QUAGMIRE: status_change_end(bl, SC_CONCENTRATE, INVALID_TIMER); @@ -8831,6 +8840,24 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - status2->luk ); val4 |= cap_value(stat,0,0xFF); break; } + case SC_SPIRIT: + //1st Transcendent Spirit works similar to Marionette Control + if(sd && val2 == SL_HIGH) { + int stat,max_stat; + // Fetch target's stats + struct status_data* status2 = status_get_status_data(bl); // Battle status + val3 = 0; + val4 = 0; + max_stat = (status_get_lv(bl)-10<50)?status_get_lv(bl)-10:50; + stat = max(0, max_stat - status2->str ); val3 |= cap_value(stat,0,0xFF)<<16; + stat = max(0, max_stat - status2->agi ); val3 |= cap_value(stat,0,0xFF)<<8; + stat = max(0, max_stat - status2->vit ); val3 |= cap_value(stat,0,0xFF); + stat = max(0, max_stat - status2->int_); val4 |= cap_value(stat,0,0xFF)<<16; + stat = max(0, max_stat - status2->dex ); val4 |= cap_value(stat,0,0xFF)<<8; + stat = max(0, max_stat - status2->luk ); val4 |= cap_value(stat,0,0xFF); + } + break; + case SC_REJECTSWORD: val2 = 15*val1; // Reflect chance val3 = 3; // Reflections diff --git a/src/map/unit.c b/src/map/unit.c index 599dac59e6..15a3b8a66a 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -92,6 +92,13 @@ int unit_walktoxy_sub(struct block_list *bl) 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. + return 0; +#endif + memcpy(&ud->walkpath,&wpd,sizeof(wpd)); if (ud->target_to && ud->chaserange>1) { @@ -469,8 +476,14 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data ud->steptimer = add_timer(tick+i, unit_step_timer, bl->id, 0); } - if(ud->state.change_walk_target) - return unit_walktoxy_sub(bl); + if(ud->state.change_walk_target) { + if(unit_walktoxy_sub(bl)) { + return 1; + } else { + clif_fixpos(bl); + return 0; + } + } ud->walkpath.path_pos++;