summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-09-04 14:10:14 +0000
committerskotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>2006-09-04 14:10:14 +0000
commit2d5e8b6e1a67df8c0719e744211a188f9c855445 (patch)
tree4e6118dfb3785efb9a4657db0b3d559b26ee638d
parenta933e1dd3618225e7bb3565bad3c0aa2b42907ad (diff)
downloadhercules-2d5e8b6e1a67df8c0719e744211a188f9c855445.tar.gz
hercules-2d5e8b6e1a67df8c0719e744211a188f9c855445.tar.bz2
hercules-2d5e8b6e1a67df8c0719e744211a188f9c855445.tar.xz
hercules-2d5e8b6e1a67df8c0719e744211a188f9c855445.zip
- Some cleanup of how mobcount works.
- 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. - Moved max HP/SP calculations to before invoking status_calc_misc - 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 map for each in range calls will also check for distances, making most ground skills and battle system use real circles instead of squares. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@8609 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r--Changelog-Trunk.txt10
-rw-r--r--src/map/map.c29
-rw-r--r--src/map/map.h7
-rw-r--r--src/map/mob.c11
-rw-r--r--src/map/script.c9
-rw-r--r--src/map/status.c92
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)