diff options
-rw-r--r-- | Changelog-Trunk.txt | 10 | ||||
-rw-r--r-- | src/map/map.c | 29 | ||||
-rw-r--r-- | src/map/map.h | 7 | ||||
-rw-r--r-- | src/map/mob.c | 11 | ||||
-rw-r--r-- | src/map/script.c | 9 | ||||
-rw-r--r-- | src/map/status.c | 92 |
6 files changed, 95 insertions, 63 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 71fd7d9d6..72b0c8cff 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,16 @@ Date Added AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
+2006/09/04
+ * status_calc_misc will now be invoked in status_calc_bl even on the first
+ call, since status could have gone up due to skill bonuses. [Skotlex]
+ * Moved max HP/SP calculations to before invoking status_calc_misc
+ [Skotlex]
+ * Simplified distance and check_distance to use "aegis" methods (greater of
+ dx/dy = distance), there's a new define in map.h called CIRCULAR_AREA, when
+ set, the previous method is used, and "for each in range" calls will also
+ check for distances, making most ground skills and battle system use real
+ circles instead of squares. [Skotlex]
2006/09/03
* Fixed SC_BERSERK's no regen penalty lasting pretty much forever.
[Skotlex]
diff --git a/src/map/map.c b/src/map/map.c index 87300b2e4..c25c61e79 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -220,14 +220,20 @@ int map_getusers(void) { return map_users; } - //Distance functions, taken from http://www.flipcode.com/articles/article_fastdistance.shtml int check_distance(int dx, int dy, int distance) { +#ifdef CIRCULAR_AREA //In this case, we just do a square comparison. Add 1 tile grace for diagonal range checks. return (dx*dx + dy*dy <= distance*distance + (dx&&dy?1:0)); +#else + if (dx < 0) dx = -dx; + if (dy < 0) dy = -dy; + return ((dx<dy?dy:dx) <= distance); +#endif } unsigned int distance(int dx, int dy) { +#ifdef CIRCULAR_AREA unsigned int min, max; if ( dx < 0 ) dx = -dx; @@ -247,6 +253,11 @@ unsigned int distance(int dx, int dy) { // coefficients equivalent to ( 123/128 * max ) and ( 51/128 * min ) return ((( max << 8 ) + ( max << 3 ) - ( max << 4 ) - ( max << 1 ) + ( min << 7 ) - ( min << 5 ) + ( min << 3 ) - ( min << 1 )) >> 8 ); +#else + if (dx < 0) dx = -dx; + if (dy < 0) dy = -dy; + return (dx<dy?dy:dx); +#endif } // @@ -657,9 +668,9 @@ int map_foreachinrange(int (*func)(struct block_list*,va_list),struct block_list for(i=0;i<c && bl;i++,bl=bl->next){ if(bl && bl->type&type && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 - //For speed purposes, it does not checks actual range by default. - //Feel free to uncomment if you want a more "exact" approach. -// && check_distance_bl(center, bl, range) +#ifdef CIRCULAR_AREA + && check_distance_bl(center, bl, range) +#endif && bl_list_count<BL_LIST_MAX) bl_list[bl_list_count++]=bl; } @@ -673,7 +684,9 @@ int map_foreachinrange(int (*func)(struct block_list*,va_list),struct block_list for(i=0;i<c && bl;i++,bl=bl->next){ if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 -// && check_distance_bl(center, bl, range) +#ifdef CIRCULAR_AREA + && check_distance_bl(center, bl, range) +#endif && bl_list_count<BL_LIST_MAX) bl_list[bl_list_count++]=bl; } @@ -731,6 +744,9 @@ int map_foreachinshootrange(int (*func)(struct block_list*,va_list),struct block for(i=0;i<c && bl;i++,bl=bl->next){ if(bl && bl->type&type && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 +#ifdef CIRCULAR_AREA + && check_distance_bl(center, bl, range) +#endif && path_search_long(NULL,center->m,center->x,center->y,bl->x,bl->y) && bl_list_count<BL_LIST_MAX) bl_list[bl_list_count++]=bl; @@ -745,6 +761,9 @@ int map_foreachinshootrange(int (*func)(struct block_list*,va_list),struct block for(i=0;i<c && bl;i++,bl=bl->next){ if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 +#ifdef CIRCULAR_AREA + && check_distance_bl(center, bl, range) +#endif && path_search_long(NULL,center->m,center->x,center->y,bl->x,bl->y) && bl_list_count<BL_LIST_MAX) bl_list[bl_list_count++]=bl; diff --git a/src/map/map.h b/src/map/map.h index 2cb6896e4..5788efbdb 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -14,6 +14,13 @@ //Only chars affected are those defined in BL_CHAR (mobs and players currently)
//#define CELL_NOSTACK
+//Uncomment to enable circular area checks.
+//By default, all range checks in Aegis are of Square shapes, so a weapon range
+// of 10 allows you to attack from anywhere within a 21x21 area.
+//Enabling this changes such checks to circular checks, which is more realistic,
+// but is not the official behaviour.
+//#define CIRCULAR_AREA
+
#define MAX_PC_CLASS 4050
#define PC_CLASS_BASE 0
#define PC_CLASS_BASE2 (PC_CLASS_BASE + 4001)
diff --git a/src/map/mob.c b/src/map/mob.c index 636d94ff0..0d7fceb83 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -786,7 +786,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) return 0; //For some reason Homun targets are never overriden. dist = distance_bl(&md->bl, bl); - if(dist < md->db->range2 && + if( ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) && battle_check_range(&md->bl,bl,md->db->range2) ) { //Pick closest target? @@ -825,9 +825,8 @@ static int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) case BL_PC: case BL_HOM: //[orn] case BL_MOB: - if(check_distance_bl(&md->bl, bl, md->status.rhw.range) && - battle_check_range (&md->bl, bl, md->status.rhw.range) - ) { + if(battle_check_range (&md->bl, bl, md->status.rhw.range)) + { (*target) = bl; md->target_id=bl->id; md->min_chase= md->db->range3; @@ -852,8 +851,8 @@ static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap) md=va_arg(ap,struct mob_data *); target= va_arg(ap,struct block_list**); - if((dist=distance_bl(&md->bl, bl)) < md->db->range2 && - mob_can_reach(md,bl,dist+1, MSS_LOOT) && + dist=distance_bl(&md->bl, bl); + if(mob_can_reach(md,bl,dist+1, MSS_LOOT) && ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) //New target closer than previous one. ) { (*target) = bl; diff --git a/src/map/script.c b/src/map/script.c index e497430ef..fea3661dd 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -9100,17 +9100,15 @@ int buildin_stoptimer(struct script_state *st) // Added by RoVeRT int buildin_mobcount_sub(struct block_list *bl,va_list ap) // Added by RoVeRT { char *event=va_arg(ap,char *); - int *c=va_arg(ap,int *); - if(strcmp(event,((struct mob_data *)bl)->npc_event)==0) - (*c)++; + return 1; return 0; } int buildin_mobcount(struct script_state *st) // Added by RoVeRT { char *mapname,*event; - int m,c=0; + int m; mapname=conv_str(st,& (st->stack->stack_data[st->start+2])); event=conv_str(st,& (st->stack->stack_data[st->start+3])); check_event(st, event); @@ -9119,9 +9117,8 @@ int buildin_mobcount(struct script_state *st) // Added by RoVeRT push_val(st->stack,C_INT,-1); return 0; } - map_foreachinmap(buildin_mobcount_sub, m, BL_MOB, event,&c ); - push_val(st->stack,C_INT, (c)); + push_val(st->stack,C_INT,map_foreachinmap(buildin_mobcount_sub, m, BL_MOB, event)); return 0; } diff --git a/src/map/status.c b/src/map/status.c index 665d1df1e..f73513ca2 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1941,6 +1941,49 @@ int status_calc_pc(struct map_session_data* sd,int first) if((skill=pc_checkskill(sd,BS_HILTBINDING))>0)
status->batk += 4;
+// ----- HP MAX CALCULATION -----
+
+ // Basic MaxHP value
+ //We hold the standard Max HP here to make it faster to recalculate on vit changes.
+ sd->status.max_hp = status_base_pc_maxhp(sd,status);
+ status->max_hp += sd->status.max_hp;
+
+ // Absolute modifiers from passive skills
+ if((skill=pc_checkskill(sd,CR_TRUST))>0)
+ status->max_hp += skill*200;
+
+// ----- SP MAX CALCULATION -----
+
+ // Basic MaxSP value
+ sd->status.max_sp = status_base_pc_maxsp(sd,status);
+ status->max_sp += sd->status.max_sp;
+
+ // Absolute modifiers from passive skills
+ if((skill=pc_checkskill(sd,SL_KAINA))>0)
+ status->max_sp += 30*skill;
+
+ if(status->sp>status->max_sp)
+ status->sp=status->max_sp;
+
+// ----- RESPAWN HP/SP -----
+//
+ //Calc respawn hp and store it on base_status
+ if (sd->special_state.restart_full_recover)
+ {
+ status->hp = status->max_hp;
+ status->sp = status->max_sp;
+ } else {
+ if((sd->class_&MAPID_BASEMASK) == MAPID_NOVICE && !(sd->class_&JOBL_2)
+ && battle_config.restart_hp_rate < 50)
+ status->hp=status->max_hp>>1;
+ else
+ status->hp=status->max_hp * battle_config.restart_hp_rate/100;
+ if(!status->hp)
+ status->hp = 1;
+
+ status->sp = status->max_sp * battle_config.restart_sp_rate /100;
+ }
+
// ----- MISC CALCULATION -----
status_calc_misc(&sd->bl, status, sd->status.base_level);
@@ -2047,49 +2090,6 @@ int status_calc_pc(struct map_session_data* sd,int first) i = 800-status->agi*4;
status->dmotion = cap_value(i, 400, 800);
-// ----- HP MAX CALCULATION -----
-
- // Basic MaxHP value
- //We hold the standard Max HP here to make it faster to recalculate on vit changes.
- sd->status.max_hp = status_base_pc_maxhp(sd,status);
- status->max_hp += sd->status.max_hp;
-
- // Absolute modifiers from passive skills
- if((skill=pc_checkskill(sd,CR_TRUST))>0)
- status->max_hp += skill*200;
-
-// ----- SP MAX CALCULATION -----
-
- // Basic MaxSP value
- sd->status.max_sp = status_base_pc_maxsp(sd,status);
- status->max_sp += sd->status.max_sp;
-
- // Absolute modifiers from passive skills
- if((skill=pc_checkskill(sd,SL_KAINA))>0)
- status->max_sp += 30*skill;
-
- if(status->sp>status->max_sp)
- status->sp=status->max_sp;
-
-// ----- RESPAWN HP/SP -----
-//
- //Calc respawn hp and store it on base_status
- if (sd->special_state.restart_full_recover)
- {
- status->hp = status->max_hp;
- status->sp = status->max_sp;
- } else {
- if((sd->class_&MAPID_BASEMASK) == MAPID_NOVICE && !(sd->class_&JOBL_2)
- && battle_config.restart_hp_rate < 50)
- status->hp=status->max_hp>>1;
- else
- status->hp=status->max_hp * battle_config.restart_hp_rate/100;
- if(!status->hp)
- status->hp = 1;
-
- status->sp = status->max_sp * battle_config.restart_sp_rate /100;
- }
-
// ----- MISC CALCULATIONS -----
// Weight
@@ -2720,9 +2720,9 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag) unit_walktoxy(&sd->bl, sd->ud.to_x, sd->ud.to_y, sd->ud.state.walk_easy);
}
- //Avoid calculating twice (SCB_ALL -> status_calc_pc -> was calculated in
- //status_calc_misc() [Skotlex]
- if(flag&(SCB_INT|SCB_MAXSP|SCB_VIT|SCB_MAXHP) && flag != SCB_ALL)
+ //Needs be done even when it was already done in status_calc_misc, because
+ //int/vit max hp/sp could have changed due to skills.
+ if(flag&(SCB_INT|SCB_MAXSP|SCB_VIT|SCB_MAXHP))
status_calc_regen(&sd->bl, status, &sd->regen);
if(flag&SCB_REGEN)
|