summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorepoque11 <epoque11@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-04-29 22:52:10 +0000
committerepoque11 <epoque11@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-04-29 22:52:10 +0000
commitefc39a408c225e1f030b1d21938ad7004b65af96 (patch)
treec7a5a9a7e19d82dd0663d31969c2bb47964f9545
parentcb54f6e503c6160eb5896088f04dcb75860ef153 (diff)
downloadhercules-efc39a408c225e1f030b1d21938ad7004b65af96.tar.gz
hercules-efc39a408c225e1f030b1d21938ad7004b65af96.tar.bz2
hercules-efc39a408c225e1f030b1d21938ad7004b65af96.tar.xz
hercules-efc39a408c225e1f030b1d21938ad7004b65af96.zip
- 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
-rw-r--r--conf/battle/battle.conf18
-rw-r--r--src/map/battle.c22
-rw-r--r--src/map/battle.h5
-rw-r--r--src/map/mob.c8
-rw-r--r--src/map/unit.c79
-rw-r--r--src/map/unit.h5
6 files changed, 61 insertions, 76 deletions
diff --git a/conf/battle/battle.conf b/conf/battle/battle.conf
index 377ebabb2..2cbb5bb45 100644
--- a/conf/battle/battle.conf
+++ b/conf/battle/battle.conf
@@ -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
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,35 +1916,17 @@ 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));
-}
-
-/*==========================================
*
*------------------------------------------*/
int unit_fixdamage(struct block_list *src,struct block_list *target,unsigned int tick,int sdelay,int ddelay,int damage,int div,int type,int damage2)
@@ -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
// ‰r₯ƒLƒƒƒ“ƒZƒ‹
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);