Просмотр исходного кода

- 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://svn.code.sf.net/p/rathena/svn/trunk@8609 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex 18 лет назад
Родитель
Сommit
def8753415
6 измененных файлов с 95 добавлено и 63 удалено
  1. 10 0
      Changelog-Trunk.txt
  2. 24 5
      src/map/map.c
  3. 7 0
      src/map/map.h
  4. 5 6
      src/map/mob.c
  5. 3 6
      src/map/script.c
  6. 46 46
      src/map/status.c

+ 10 - 0
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]

+ 24 - 5
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;

+ 7 - 0
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)

+ 5 - 6
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;

+ 3 - 6
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;
 }

+ 46 - 46
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)