소스 검색

Cleaned up Banding behavior (#3486)

* Fixes #3478.
* Adjusted Banding to use proper party counting functions.
* Corrected the DEF and HP Regen bonus for Banding.
* Banding Defense will no longer stack on itself.
Thanks to @admkakaroto and @exneval!
Aleos 6 년 전
부모
커밋
0d77398385
9개의 변경된 파일69개의 추가작업 그리고 107개의 파일을 삭제
  1. 1 1
      db/pre-re/skill_db.txt
  2. 1 1
      db/re/skill_db.txt
  3. 29 0
      src/map/party.cpp
  4. 1 0
      src/map/party.hpp
  5. 0 94
      src/map/pc.cpp
  6. 0 2
      src/map/pc.hpp
  7. 29 5
      src/map/skill.cpp
  8. 2 0
      src/map/skill.hpp
  9. 6 4
      src/map/status.cpp

+ 1 - 1
db/pre-re/skill_db.txt

@@ -1115,7 +1115,7 @@
 2316,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0,0x0,	LG_EXEEDBREAK,Exceed Break
 2317,2,6,2,-1,0x2,0,5,1,yes,0,0,0,weapon,0,0x0,	LG_OVERBRAND,Over Brand
 2318,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0,0x0,	LG_PRESTIGE,Prestige
-2319,0,6,4,0,0x3,3,5,1,no,0,0,0,weapon,0,0x0,	LG_BANDING,Banding //CHECK Splash isnt needed right? Banding has its own UNIT ID.
+2319,0,6,4,0,0x3,3,5,1,no,0,0,0,weapon,0,0x0,	LG_BANDING,Banding
 2320,0,6,4,-1,0x2,3,5,1,yes,0,0,0,weapon,0,0x1000,	LG_MOONSLASHER,Moon Slasher
 2321,1,8,2,6,0x2,5,5,-7,yes,0,0,0,weapon,0,0x0,	LG_RAYOFGENESIS,Ray of Genesis
 2322,0,6,16,0,0x3,1,5,1,yes,0,0,0,none,0,0x0,	LG_PIETY,Piety

+ 1 - 1
db/re/skill_db.txt

@@ -1121,7 +1121,7 @@
 2316,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0,0x0,	LG_EXEEDBREAK,Exceed Break
 2317,2,6,2,-1,0x2,0,5,1,yes,0,0,0,weapon,0,0x0,	LG_OVERBRAND,Over Brand
 2318,0,6,4,0,0x1,0,5,1,yes,0,0,0,none,0,0x0,	LG_PRESTIGE,Prestige
-2319,0,6,4,0,0x3,3,5,1,no,0,0,0,weapon,0,0x0,	LG_BANDING,Banding //CHECK Splash isnt needed right? Banding has its own UNIT ID.
+2319,0,6,4,0,0x3,3,5,1,no,0,0,0,weapon,0,0x0,	LG_BANDING,Banding
 2320,0,6,4,-1,0x2,3,5,1,yes,0,0,0,weapon,0,0x1000,	LG_MOONSLASHER,Moon Slasher
 2321,1,8,2,6,0x2,5,5,-7,yes,0,0,0,weapon,0,0x0,	LG_RAYOFGENESIS,Ray of Genesis
 2322,0,6,16,0,0x3,1,5,1,yes,0,0,0,none,0,0x0,	LG_PIETY,Piety

+ 29 - 0
src/map/party.cpp

@@ -1249,6 +1249,35 @@ int party_sub_count_class(struct block_list *bl, va_list ap)
 	return 1;
 }
 
+/**
+ * Special check for Royal Guard's Banding skill.
+ * @param bl: Object invoking the counter
+ * @param ap: List of parameters: Check Type
+ * @return 1 or total HP on success or 0 otherwise
+ */
+int party_sub_count_banding(struct block_list *bl, va_list ap)
+{
+	struct map_session_data *sd = (TBL_PC *)bl;
+	int type = va_arg(ap, int); // 0 = Banding Count, 1 = HP Check
+
+	if (sd->state.autotrade)
+		return 0;
+
+	if (battle_config.idle_no_share && pc_isidle(sd))
+		return 0;
+
+	if ((sd->class_&MAPID_THIRDMASK) != MAPID_ROYAL_GUARD)
+		return 0;
+
+	if (!sd->sc.data[SC_BANDING])
+		return 0;
+
+	if (type == 1)
+		return status_get_hp(bl);
+
+	return 1;
+}
+
 /// Executes 'func' for each party member on the same map and in range (0:whole map)
 int party_foreachsamemap(int (*func)(struct block_list*,va_list),struct map_session_data *sd,int range,...)
 {

+ 1 - 0
src/map/party.hpp

@@ -89,6 +89,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
 int party_send_dot_remove(struct map_session_data *sd);
 int party_sub_count(struct block_list *bl, va_list ap);
 int party_sub_count_class(struct block_list *bl, va_list ap);
+int party_sub_count_banding(struct block_list *bl, va_list ap);
 int party_foreachsamemap(int (*func)(struct block_list *,va_list),struct map_session_data *sd,int range,...);
 
 /*==========================================

+ 0 - 94
src/map/pc.cpp

@@ -339,100 +339,6 @@ void pc_delspiritball(struct map_session_data *sd,int count,int type)
 	}
 }
 
-static int pc_check_banding( struct block_list *bl, va_list ap ) {
-	int *c, *b_sd;
-	struct block_list *src;
-	struct map_session_data *tsd;
-	struct status_change *sc;
-
-	nullpo_ret(bl);
-	nullpo_ret(tsd = (struct map_session_data*)bl);
-	nullpo_ret(src = va_arg(ap,struct block_list *));
-	c = va_arg(ap,int *);
-	b_sd = va_arg(ap, int *);
-
-	if(pc_isdead(tsd))
-		return 0;
-
-	sc = status_get_sc(bl);
-
-	if( sc && sc->data[SC_BANDING] )
-	{
-		b_sd[(*c)++] = tsd->bl.id;
-		return 1;
-	}
-
-	return 0;
-}
-
-int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
-	int c;
-	int b_sd[MAX_PARTY]; // In case of a full Royal Guard party.
-	int i, j, hp, extra_hp = 0, tmp_qty = 0;
-	int range = skill_get_splash(LG_BANDING,skill_lv);
-
-	nullpo_ret(sd);
-
-	c = 0;
-	memset(b_sd, 0, sizeof(b_sd));
-	i = party_foreachsamemap(pc_check_banding,sd,range,&sd->bl,&c,&b_sd);
-
-	if( c < 1 ) //just recalc status no need to recalc hp
-	{	// No more Royal Guards in Banding found.
-		struct status_change *sc;
-		if( (sc = status_get_sc(&sd->bl)) != NULL  && sc->data[SC_BANDING] )
-		{
-			sc->data[SC_BANDING]->val2 = 0; // Reset the counter
-			status_calc_bl(&sd->bl, status_sc2scb_flag(SC_BANDING));
-		}
-		return 0;
-	}
-
-	//Add yourself
-	hp = status_get_hp(&sd->bl);
-	i++;
-
-	// Get total HP of all Royal Guards in party.
-	for( j = 0; j < i; j++ ){
-		struct map_session_data *bsd = map_id2sd(b_sd[j]);
-		if( bsd != NULL )
-			hp += status_get_hp(&bsd->bl);
-	}
-
-	// Set average HP.
-	hp = hp / i;
-
-	// If a Royal Guard have full HP, give more HP to others that haven't full HP.
-	for( j = 0; j < i; j++ )
-	{
-		int tmp_hp=0;
-		struct map_session_data *bsd = map_id2sd(b_sd[j]);
-		if( bsd != NULL && (tmp_hp = hp - status_get_max_hp(&bsd->bl)) > 0 ){
-			extra_hp += tmp_hp;
-			tmp_qty++;
-		}
-	}
-
-	if( extra_hp > 0 && tmp_qty > 0 )
-		hp += extra_hp / tmp_qty;
-
-	for( j = 0; j < i; j++ ){
-		struct map_session_data *bsd = map_id2sd(b_sd[j]);
-		if( bsd != NULL )
-		{
-			struct status_change *sc;
-			status_set_hp(&bsd->bl,hp,0);	// Set hp
-			if( (sc = status_get_sc(&bsd->bl)) != NULL  && sc->data[SC_BANDING] )
-			{
-				sc->data[SC_BANDING]->val2 = c; // Set the counter. It doesn't count your self.
-				status_calc_bl(&bsd->bl, status_sc2scb_flag(SC_BANDING));	// Set atk and def.
-			}
-		}
-	}
-
-	return c;
-}
-
 /**
 * Increases a player's fame points and displays a notice to him
 * @param sd Player

+ 0 - 2
src/map/pc.hpp

@@ -1290,8 +1290,6 @@ bool pc_isautolooting(struct map_session_data *sd, unsigned short nameid);
 
 void pc_overheat(struct map_session_data *sd, int16 heat);
 
-int pc_banding(struct map_session_data *sd, uint16 skill_lv);
-
 void pc_itemcd_do(struct map_session_data *sd, bool load);
 uint8 pc_itemcd_add(struct map_session_data *sd, struct item_data *id, unsigned int tick, unsigned short n);
 uint8 pc_itemcd_check(struct map_session_data *sd, struct item_data *id, unsigned int tick, unsigned short n);

+ 29 - 5
src/map/skill.cpp

@@ -2366,8 +2366,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list *
 		{
 			struct status_change *sc = status_get_sc(src);
 			if( sc && sc->data[SC_FORCEOFVANGUARD] && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 6 ) {
-				char i;
-				for( i = 0; i < sc->data[SC_FORCEOFVANGUARD]->val3; i++ )
+				for(int i = 0; i < sc->data[SC_FORCEOFVANGUARD]->val3; i++ )
 					pc_addspiritball(sd, skill_get_time(LG_FORCEOFVANGUARD,1),sc->data[SC_FORCEOFVANGUARD]->val3);
 			}
 		}
@@ -12247,10 +12246,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
 	case LG_BANDING:
 		if( sc && sc->data[SC_BANDING] )
 			status_change_end(src,SC_BANDING,INVALID_TIMER);
-		else if( (sg = skill_unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL ) {
+		else if( (sg = skill_unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL )
 			sc_start4(src,src,SC_BANDING,100,skill_lv,0,0,sg->group_id,skill_get_time(skill_id,skill_lv));
-			if( sd ) pc_banding(sd,skill_lv);
-		}
 		clif_skill_nodamage(src,src,skill_id,skill_lv,1);
 		break;
 
@@ -17333,6 +17330,33 @@ int skill_detonator(struct block_list *bl, va_list ap)
 	return 0;
 }
 
+/**
+ * Calculate Royal Guard's Banding bonus
+ * @param sd: Player data
+ * @return Number of Royal Guard
+ */
+int skill_banding_count(struct map_session_data *sd)
+{
+ 	nullpo_ret(sd);
+
+	int range = skill_get_splash(LG_BANDING, 1);
+	uint8 count = party_foreachsamemap(party_sub_count_banding, sd, range, 0);
+	unsigned int group_hp = party_foreachsamemap(party_sub_count_banding, sd, range, 1);
+
+ 	// HP is set to the average HP of the Banding group
+	if (count > 1)
+		status_set_hp(&sd->bl, group_hp / count, 0);
+
+ 	// Royal Guard count check for Banding
+	if (sd && sd->status.party_id) {
+		if (count > MAX_PARTY)
+			return MAX_PARTY;
+		else if (count > 1)
+			return count; // Effect bonus from additional Royal Guards if not above the max
+	}
+ 	return 0;
+}
+
 /**
  * Rebellion's Bind Trap explosion
  * @author [Cydh]

+ 2 - 0
src/map/skill.hpp

@@ -2205,6 +2205,8 @@ int skill_elementalanalysis(struct map_session_data *sd, int n, uint16 skill_lv,
 int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list);	// Genetic Change Material.
 int skill_get_elemental_type(uint16 skill_id, uint16 skill_lv);
 
+int skill_banding_count(struct map_session_data *sd);
+
 int skill_is_combo(uint16 skill_id);
 void skill_combo_toggle_inf(struct block_list* bl, uint16 skill_id, int inf);
 void skill_combo(struct block_list* src,struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int tick);

+ 6 - 4
src/map/status.cpp

@@ -715,7 +715,7 @@ void initChangeTables(void)
 	set_sc( LG_FORCEOFVANGUARD	, SC_FORCEOFVANGUARD	, EFST_FORCEOFVANGUARD	, SCB_MAXHP );
 	set_sc( LG_EXEEDBREAK		, SC_EXEEDBREAK		, EFST_EXEEDBREAK		, SCB_NONE );
 	set_sc( LG_PRESTIGE		, SC_PRESTIGE		, EFST_PRESTIGE		, SCB_DEF );
-	set_sc( LG_BANDING		, SC_BANDING		, EFST_BANDING		, SCB_DEF2|SCB_WATK );
+	set_sc( LG_BANDING		, SC_BANDING		, EFST_BANDING		, SCB_DEF|SCB_WATK|SCB_REGEN );
 	set_sc( LG_PIETY		, SC_BENEDICTIO		, EFST_BENEDICTIO		, SCB_DEF_ELE );
 	set_sc( LG_EARTHDRIVE		, SC_EARTHDRIVE		, EFST_EARTHDRIVE		, SCB_DEF|SCB_ASPD );
 	set_sc( LG_INSPIRATION		, SC_INSPIRATION	, EFST_INSPIRATION	, SCB_WATK|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_HIT|SCB_MAXHP);
@@ -4657,6 +4657,8 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
 		} else
 			regen->flag &= ~sce->val4; // Remove regen as specified by val4
 	}
+	if (sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1)
+		regen->hp += cap_value(regen->hp * 50 / 100, 1, SHRT_MAX);
 	if(sc->data[SC_GT_REVITALIZE]) {
 		regen->hp += cap_value(regen->hp * sc->data[SC_GT_REVITALIZE]->val3/100, 1, SHRT_MAX);
 		regen->state.walk = 1;
@@ -6522,8 +6524,6 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change
 
 	if(sc->data[SC_SUN_COMFORT])
 		def2 += sc->data[SC_SUN_COMFORT]->val2;
-	if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 )
-		def2 += (5 + sc->data[SC_BANDING]->val1) * sc->data[SC_BANDING]->val2;
 #ifdef RENEWAL
 	if (sc->data[SC_SKA])
 		def2 += 80;
@@ -9333,6 +9333,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			case SC_OBLIVIONCURSE:
 			case SC_LEECHESEND:
 			case SC_CURSEDCIRCLE_TARGET:
+			case SC_BANDING_DEFENCE:
 			case SC__ENERVATION:
 			case SC__GROOMY:
 			case SC__IGNORANCE:
@@ -10631,6 +10632,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			val3 = ((val1 * 15) + (10 * (sd?pc_checkskill(sd,CR_DEFENDER):skill_get_max(CR_DEFENDER)))) * status_get_lv(bl) / 100; // Defence added
 			break;
 		case SC_BANDING:
+			val2 = (sd ? skill_banding_count(sd) : 1);
 			tick_time = 5000; // [GodLesZ] tick time
 			break;
 		case SC_MAGNETICFIELD:
@@ -13351,7 +13353,7 @@ TIMER_FUNC(status_change_timer){
 
 	case SC_BANDING:
 		if( status_charge(bl, 0, 7 - sce->val1) ) {
-			if( sd ) pc_banding(sd, sce->val1);
+			sce->val2 = (sd ? skill_banding_count(sd) : 1);
 			sc_timer_next(5000 + tick);
 			return 0;
 		}