From efc39a408c225e1f030b1d21938ad7004b65af96 Mon Sep 17 00:00:00 2001 From: epoque11 Date: Sun, 29 Apr 2012 22:52:10 +0000 Subject: - Updated the unit engine to cache attacker count rather than utilise CPU intensive block iterations - This update removes two unofficial settings, nothing that will go amiss git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16011 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/battle.c | 22 +++++----------- src/map/battle.h | 5 +--- src/map/mob.c | 8 +++--- src/map/unit.c | 79 ++++++++++++++++++++++++++++++++------------------------ src/map/unit.h | 5 +++- 5 files changed, 61 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/map/battle.c b/src/map/battle.c index 167a040ce..9ea7f5595 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1461,13 +1461,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo hitrate = 80; //Default hitrate #endif - if(battle_config.agi_penalty_type && - battle_config.agi_penalty_target&target->type) - { + if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) { unsigned char attacker_count; //256 max targets should be a sane max - attacker_count = unit_counttargeted(target,battle_config.agi_penalty_count_lv); - if(attacker_count >= battle_config.agi_penalty_count) - { + attacker_count = unit_counttargeted(target); + if(attacker_count >= battle_config.agi_penalty_count) { if (battle_config.agi_penalty_type == 1) flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100; else //asume type 2: absolute reduction @@ -2507,10 +2504,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } } - if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) - { + if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) { unsigned char target_count; //256 max targets should be a sane max - target_count = unit_counttargeted(target,battle_config.vit_penalty_count_lv); + target_count = unit_counttargeted(target); if(target_count >= battle_config.vit_penalty_count) { if(battle_config.vit_penalty_type == 1) { if( !tsc || !tsc->data[SC_STEELBODY] ) @@ -3920,11 +3916,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * hitrate = 80; //Default hitrate #endif - if(battle_config.agi_penalty_type && - battle_config.agi_penalty_target&target->type) - { + if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) { unsigned char attacker_count; //256 max targets should be a sane max - attacker_count = unit_counttargeted(target,battle_config.agi_penalty_count_lv); + attacker_count = unit_counttargeted(target); if(attacker_count >= battle_config.agi_penalty_count) { if (battle_config.agi_penalty_type == 1) @@ -5040,12 +5034,10 @@ static const struct _battle_data { { "agi_penalty_type", &battle_config.agi_penalty_type, 1, 0, 2, }, { "agi_penalty_count", &battle_config.agi_penalty_count, 3, 2, INT_MAX, }, { "agi_penalty_num", &battle_config.agi_penalty_num, 10, 0, INT_MAX, }, - { "agi_penalty_count_lv", &battle_config.agi_penalty_count_lv, ATK_FLEE, 0, INT_MAX, }, { "vit_penalty_target", &battle_config.vit_penalty_target, BL_PC, BL_NUL, BL_ALL, }, { "vit_penalty_type", &battle_config.vit_penalty_type, 1, 0, 2, }, { "vit_penalty_count", &battle_config.vit_penalty_count, 3, 2, INT_MAX, }, { "vit_penalty_num", &battle_config.vit_penalty_num, 5, 0, INT_MAX, }, - { "vit_penalty_count_lv", &battle_config.vit_penalty_count_lv, ATK_MISS, 0, INT_MAX, }, { "weapon_defense_type", &battle_config.weapon_defense_type, 0, 0, INT_MAX, }, { "magic_defense_type", &battle_config.magic_defense_type, 0, 0, INT_MAX, }, { "skill_reiteration", &battle_config.skill_reiteration, BL_NUL, BL_NUL, BL_ALL, }, diff --git a/src/map/battle.h b/src/map/battle.h index f8f0a10d7..3b42c52b7 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -312,10 +312,7 @@ extern struct Battle_Config int manner_system; // end additions [Valaris] int show_mob_info; - - int agi_penalty_count_lv; - int vit_penalty_count_lv; - + int gx_allhit; int gx_disptype; int devotion_level_difference; diff --git a/src/map/mob.c b/src/map/mob.c index 3e8df661f..8318d492f 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1293,7 +1293,7 @@ int mob_unlocktarget(struct mob_data *md, unsigned int tick) } if (md->target_id) { md->target_id=0; - md->ud.target = 0; + unit_set_target(&md->ud, 0); } return 0; } @@ -3082,11 +3082,11 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) case MSC_SLAVELT: // slave < num flag = (mob_countslave(&md->bl) < c2 ); break; case MSC_ATTACKPCGT: // attack pc > num - flag = (unit_counttargeted(&md->bl, 0) > c2); break; + flag = (unit_counttargeted(&md->bl) > c2); break; case MSC_SLAVELE: // slave <= num flag = (mob_countslave(&md->bl) <= c2 ); break; case MSC_ATTACKPCGE: // attack pc >= num - flag = (unit_counttargeted(&md->bl, 0) >= c2); break; + flag = (unit_counttargeted(&md->bl) >= c2); break; case MSC_AFTERSKILL: flag = (md->ud.skillid == c2); break; case MSC_RUDEATTACKED: @@ -3096,7 +3096,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) case MSC_MASTERHPLTMAXRATE: flag = ((fbl = mob_getmasterhpltmaxrate(md, ms[i].cond2)) != NULL); break; case MSC_MASTERATTACKED: - flag = (md->master_id > 0 && (fbl=map_id2bl(md->master_id)) && unit_counttargeted(fbl, 0) > 0); break; + flag = (md->master_id > 0 && (fbl=map_id2bl(md->master_id)) && unit_counttargeted(fbl) > 0); break; case MSC_ALCHEMIST: flag = (md->state.alchemist); break; diff --git a/src/map/unit.c b/src/map/unit.c index e35aca262..51bf92020 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -73,7 +73,7 @@ int unit_walktoxy_sub(struct block_list *bl) memcpy(&ud->walkpath,&wpd,sizeof(wpd)); - if (ud->target && ud->chaserange>1) { + if (ud->target_to && ud->chaserange>1) { //Generally speaking, the walk path is already to an adjacent tile //so we only need to shorten the path if the range is greater than 1. int dir; @@ -234,14 +234,15 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data if ( !(unit_run(bl) || unit_wugdash(bl,sd)) ) ud->state.running = 0; } - else if (ud->target) { + else if (ud->target_to) { //Update target trajectory. - struct block_list *tbl = map_id2bl(ud->target); + struct block_list *tbl = map_id2bl(ud->target_to); if (!tbl || !status_check_visibility(bl, tbl)) { //Cancel chase. ud->to_x = bl->x; ud->to_y = bl->y; - if (tbl && bl->type == BL_MOB) //See if the mob can do a warp chase. - mob_warpchase((TBL_MOB*)bl, tbl); + if (tbl && bl->type == BL_MOB && mob_warpchase((TBL_MOB*)bl, tbl) ) + return 0; + ud->target_to = 0; return 0; } if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange)) @@ -249,6 +250,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data if (ud->state.attack_continue) { //Aegis uses one before every attack, we should //only need this one for syncing purposes. [Skotlex] + ud->target_to = 0; clif_fixpos(bl); unit_attack(bl, tbl->id, ud->state.attack_continue); } @@ -260,6 +262,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data else { //Stopped walking. Update to_x and to_y to current location [Skotlex] ud->to_x = bl->x; ud->to_y = bl->y; + ud->target_to = 0; } return 0; } @@ -300,9 +303,9 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag) return 0; ud->state.walk_easy = flag&1; - ud->target = 0; ud->to_x = x; ud->to_y = y; + unit_set_target(ud, 0); sc = status_get_sc(bl); if (sc && sc->data[SC_CONFUSION]) //Randomize the target position @@ -368,13 +371,15 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int if (!unit_can_reach_bl(bl, tbl, distance_bl(bl, tbl)+1, flag&1, &ud->to_x, &ud->to_y)) { ud->to_x = bl->x; ud->to_y = bl->y; + ud->target_to = 0; return 0; } ud->state.walk_easy = flag&1; - ud->target = tbl->id; + ud->target_to = tbl->id; ud->chaserange = range; //Note that if flag&2, this SHOULD be attack-range ud->state.attack_continue = flag&2?1:0; //Chase to attack. + unit_set_target(ud, 0); sc = status_get_sc(bl); if (sc && sc->data[SC_CONFUSION]) //Randomize the target position @@ -1032,7 +1037,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh target_id = ud->target; //Auto-select target. [Skotlex] temp = 1; } - + if (sd) { //Target_id checking. if(skillnotok(skill_num, sd)) // [MouseJstr] @@ -1446,6 +1451,27 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh return 1; } +/*======================================== + * update a block's attack target + *----------------------------------------*/ +int unit_set_target(struct unit_data* ud, int target_id) +{ + struct unit_data * ux; + struct block_list* target; + + nullpo_ret(ud); + + if( ud->target != target_id ) { + if( ud->target && (target = map_id2bl(ud->target)) && (ux = unit_bl2ud(target)) && ux->target_count > 0 ) + ux->target_count --; + if( target_id && (target = map_id2bl(target_id)) && (ux = unit_bl2ud(target)) ) + ux->target_count ++; + } + + ud->target = target_id; + return 0; +} + int unit_stop_attack(struct block_list *bl) { struct unit_data *ud = unit_bl2ud(bl); @@ -1456,7 +1482,7 @@ int unit_stop_attack(struct block_list *bl) delete_timer( ud->attacktimer, unit_attack_timer ); ud->attacktimer = INVALID_TIMER; - ud->target = 0; + unit_set_target(ud, 0); return 0; } @@ -1465,8 +1491,8 @@ int unit_unattackable(struct block_list *bl) { struct unit_data *ud = unit_bl2ud(bl); if (ud) { - ud->target = 0; ud->state.attack_continue = 0; + unit_set_target(ud, 0); } if(bl->type == BL_MOB) @@ -1515,8 +1541,9 @@ int unit_attack(struct block_list *src,int target_id,int continuous) return 1; } - ud->target = target_id; ud->state.attack_continue = continuous; + unit_set_target(ud, target_id); + if (continuous) //If you're to attack continously, set to auto-case character ud->chaserange = status_get_range(src); @@ -1889,34 +1916,16 @@ void unit_dataset(struct block_list *bl) } /*========================================== - * Returns 1 if this unit is attacking target 'id' + * Counts the number of units attacking 'bl' *------------------------------------------*/ -static int unit_counttargeted_sub(struct block_list* bl, va_list ap) +int unit_counttargeted(struct block_list* bl) { - int id = va_arg(ap, int); - int target_lv = va_arg(ap, int); // extra condition struct unit_data* ud; - - if(bl->id == id) - return 0; - - ud = unit_bl2ud(bl); - - if (ud && ud->target == id && ud->attacktimer != INVALID_TIMER && ud->attacktarget_lv >= target_lv) - return 1; - + if( bl && (ud = unit_bl2ud(bl)) ) + return ud->target_count; return 0; } -/*========================================== - * Counts the number of units attacking 'bl' - *------------------------------------------*/ -int unit_counttargeted(struct block_list* bl, int target_lv) -{ - nullpo_ret(bl); - return (map_foreachinrange(unit_counttargeted_sub, bl, AREA_SIZE, BL_CHAR, bl->id, target_lv)); -} - /*========================================== * *------------------------------------------*/ @@ -1968,13 +1977,15 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, map_freeblock_lock(); - ud->target = 0; //Unlock walk/attack target. + unit_set_target(ud, 0); + if (ud->walktimer != INVALID_TIMER) unit_stop_walking(bl,0); if (ud->attacktimer != INVALID_TIMER) unit_stop_attack(bl); if (ud->skilltimer != INVALID_TIMER) unit_skillcastcancel(bl,0); + // Do not reset can-act delay. [Skotlex] ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = gettick(); diff --git a/src/map/unit.h b/src/map/unit.h index 6a0bf26f6..11f5fba0e 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -27,6 +27,7 @@ struct unit_data { int skilltarget; int skilltimer; int target; + int target_to; int attacktimer; int walktimer; int chaserange; @@ -35,6 +36,7 @@ struct unit_data { unsigned int canmove_tick; uint8 dir; unsigned char walk_count; + unsigned char target_count; struct { unsigned change_walk_target : 1 ; unsigned skillcastcancel : 1 ; @@ -113,7 +115,8 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh // 詠唱キャンセル int unit_skillcastcancel(struct block_list *bl,int type); -int unit_counttargeted(struct block_list *bl,int target_lv); +int unit_counttargeted(struct block_list *bl); +int unit_set_target(struct unit_data* ud, int target_id); // unit_data の初期化処理 void unit_dataset(struct block_list *bl); -- cgit v1.2.3-70-g09d2