- 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://svn.code.sf.net/p/rathena/svn/trunk@16011 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
1bac5ef84d
commit
33cad70492
@ -101,24 +101,6 @@ weapon_defense_type: 0
|
||||
//MDEF‚same as above....(MDEF*value)
|
||||
magic_defense_type: 0
|
||||
|
||||
// How to count the number of attackers when applying agi penalty ? (choose one)
|
||||
// 1-: Count every attack attempt (even those that were dodged/lucky-dodged)
|
||||
// 2 : Count every non-lucky-dodged attack attempt
|
||||
// 3 : Count attacks that miss due to element/race modifier
|
||||
// 4 : Count attacks whose damages are blocked by skills
|
||||
// 5 : Count only attacks that actually connect
|
||||
// 6+: None of the above, count will always be 0
|
||||
agi_penalty_count_lv: 2
|
||||
|
||||
// How to count the number of attackers when applying vit penalty ? (choose one)
|
||||
// 1-: Count every attack attempt (even those that were dodged/lucky-dodged)
|
||||
// 2 : Count every non-lucky-dodged attack attempt
|
||||
// 3 : Count attacks that miss due to element/race modifier
|
||||
// 4 : Count attacks whose damages are blocked by skills
|
||||
// 5 : Count only attacks that actually connect
|
||||
// 6+: None of the above, count will always be 0
|
||||
vit_penalty_count_lv: 3
|
||||
|
||||
// Change attacker's direction to face opponent on every attack? (Note 3)
|
||||
attack_direction_change: 15
|
||||
|
||||
|
@ -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, },
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
@ -1888,33 +1915,15 @@ void unit_dataset(struct block_list *bl)
|
||||
ud->canmove_tick = gettick();
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Returns 1 if this unit is attacking target 'id'
|
||||
*------------------------------------------*/
|
||||
static int unit_counttargeted_sub(struct block_list* bl, va_list ap)
|
||||
{
|
||||
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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Counts the number of units attacking 'bl'
|
||||
*------------------------------------------*/
|
||||
int unit_counttargeted(struct block_list* bl, int target_lv)
|
||||
int unit_counttargeted(struct block_list* bl)
|
||||
{
|
||||
nullpo_ret(bl);
|
||||
return (map_foreachinrange(unit_counttargeted_sub, bl, AREA_SIZE, BL_CHAR, bl->id, target_lv));
|
||||
struct unit_data* ud;
|
||||
if( bl && (ud = unit_bl2ud(bl)) )
|
||||
return ud->target_count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user