Forráskód Böngészése

Soul Reaper souls now persist relog (#5142)

* Fixes #5032.
* Soul Reaper souls will now persist relogs.
* Removed the soul_timer as the timer data is stored to the status change.
Thanks to @laziem and @Tokeiburu!
Aleos 4 éve
szülő
commit
cef956d352
8 módosított fájl, 55 hozzáadás és 94 törlés
  1. 4 5
      src/map/atcommand.cpp
  2. 1 1
      src/map/battle.cpp
  3. 2 2
      src/map/clif.cpp
  4. 26 74
      src/map/pc.cpp
  5. 2 3
      src/map/pc.hpp
  6. 4 4
      src/map/skill.cpp
  7. 16 4
      src/map/status.cpp
  8. 0 1
      src/map/unit.cpp

+ 4 - 5
src/map/atcommand.cpp

@@ -3492,22 +3492,21 @@ ACMD_FUNC(spiritball)
 
 ACMD_FUNC(soulball)
 {
-	uint32 max_soulballs = min(ARRAYLENGTH(sd->soul_timer), 0x7FFF);
 	int number;
 	nullpo_retr(-1, sd);
 
-	if (!message || !*message || (number = atoi(message)) < 0 || number > max_soulballs) {
+	if (!message || !*message || (number = atoi(message)) < 0 || number > MAX_SOUL_BALL) {
 		char msg[CHAT_SIZE_MAX];
-		safesnprintf(msg, sizeof(msg), "Usage: @soulball <number: 0-%d>", max_soulballs);
+
+		safesnprintf(msg, sizeof(msg), "Usage: @soulball <number: 0-%d>", MAX_SOUL_BALL);
 		clif_displaymessage(fd, msg);
 		return -1;
 	}
 
 	if (sd->soulball > 0)
-		pc_delsoulball(sd, sd->soulball, 1);
+		pc_delsoulball(sd, sd->soulball, true);
 	sd->soulball = number;
 	clif_soulball(sd);
-	// no message, player can see the difference
 
 	return 0;
 }

+ 1 - 1
src/map/battle.cpp

@@ -1643,7 +1643,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 		if (tsd && (sce = tsc->data[SC_SOULREAPER])) {
 			if (rnd()%100 < sce->val2 && tsd->soulball < MAX_SOUL_BALL) {
 				clif_specialeffect(src, 1208, AREA);
-				pc_addsoulball(tsd, 0, 5 + 3 * pc_checkskill(tsd, SP_SOULENERGY));
+				pc_addsoulball(tsd, 5 + 3 * pc_checkskill(tsd, SP_SOULENERGY));
 			}
 		}
 	}

+ 2 - 2
src/map/clif.cpp

@@ -4635,11 +4635,11 @@ void clif_storageclose(struct map_session_data* sd)
 /// Note: Spirit spheres and Soul spheres work on
 /// seprate systems officially, but both send out
 /// the same packet which leads to confusion on how
-/// much soul energy a Soul Reaper acturally has
+/// much soul energy a Soul Reaper actually has
 /// should the player also have spirit spheres.
 /// They will likely create a new packet for this soon
 /// to seprate the animations for spirit and soul spheres.
-/// For now well use this and replace it later when possible. [Rytech]
+/// For now we'll use this and replace it later when possible. [Rytech]
 /// 
 /// 01d0 <id>.L <amount>.W (ZC_SPIRITS)
 /// 01e1 <id>.L <amount>.W (ZC_SPIRITS2)

+ 26 - 74
src/map/pc.cpp

@@ -553,68 +553,30 @@ void pc_delspiritball(struct map_session_data *sd,int count,int type)
 	}
 }
 
-static TIMER_FUNC(pc_soulball_timer)
-{
-	struct map_session_data *sd;
-
-	if ((sd = (struct map_session_data *)map_id2sd(id)) == nullptr || sd->bl.type != BL_PC)
-		return 1;
-
-	if (sd->soulball <= 0) {
-		ShowError("pc_soulball_timer: %d soulball's available. (aid=%d tid=%d)\n", sd->soulball, sd->status.account_id, tid);
-		sd->soulball = 0;
-		return 0;
-	}
-
-	int i;
-
-	ARR_FIND(0, sd->soulball, i, sd->soul_timer[i] == tid);
-	if (i == sd->soulball) {
-		ShowError("pc_soulball_timer: timer not found (aid=%d tid=%d)\n", sd->status.account_id, tid);
-		return 0;
-	}
-
-	sd->soulball--;
-	if (i != sd->soulball)
-		memmove(sd->soul_timer + i, sd->soul_timer + i + 1, (sd->soulball - i) * sizeof(int));
-	sd->soul_timer[sd->soulball] = INVALID_TIMER;
-	clif_soulball(sd);
-
-	return 0;
-}
-
 /**
- * Adds a soulball to player for 'interval' ms
+ * Adds a soulball to player
  * @param sd: Player data
- * @param interval: Duration
  * @param max: Max amount of soulballs
  */
-int pc_addsoulball(struct map_session_data *sd, int interval, int max)
+int pc_addsoulball(map_session_data *sd, int max)
 {
 	nullpo_ret(sd);
 
-	max = min(max, MAX_SOUL_BALL);
-	sd->soulball = cap_value(sd->soulball, 0, MAX_SOUL_BALL);
+	status_change *sc = status_get_sc(&sd->bl);
 
-	if (sd->soulball && sd->soulball >= max) {
-		if (sd->soul_timer[0] != INVALID_TIMER)
-			delete_timer(sd->soul_timer[0], pc_soulball_timer);
-		sd->soulball--;
-		if (sd->soulball != 0)
-			memmove(sd->soul_timer + 0, sd->soul_timer + 1, (sd->soulball) * sizeof(int));
-		sd->soul_timer[sd->soulball] = INVALID_TIMER;
+	if (sc == nullptr || sc->data[SC_SOULENERGY] == nullptr) {
+		sc_start(&sd->bl, &sd->bl, SC_SOULENERGY, 100, 0, skill_get_time2(SP_SOULCOLLECT, 1));
+		sd->soulball = 0;
 	}
 
-	if (interval > 0) {
-		int tid = add_timer(gettick() + interval, pc_soulball_timer, sd->bl.id, 0), i;
+	max = min(max, MAX_SOUL_BALL);
+	sd->soulball = cap_value(sd->soulball, 0, MAX_SOUL_BALL);
 
-		ARR_FIND(0, sd->soulball, i, sd->soul_timer[i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->soul_timer[i])->tick) < 0);
-		if (i != sd->soulball)
-			memmove(sd->soul_timer + i + 1, sd->soul_timer + i, (sd->soulball - i) * sizeof(int));
-		sd->soul_timer[i] = tid;
-	}
+	if (sd->soulball && sd->soulball >= max)
+		sd->soulball--;
 
 	sd->soulball++;
+	sc_start(&sd->bl, &sd->bl, SC_SOULENERGY, 100, sd->soulball, skill_get_time2(SP_SOULCOLLECT, 1));
 	clif_soulball(sd);
 
 	return 0;
@@ -624,37 +586,27 @@ int pc_addsoulball(struct map_session_data *sd, int interval, int max)
  * Removes number of soulball from player
  * @param sd: Player data
  * @param count: Amount to remove
- * @param type: 1 = doesn't give client effect
+ * @param type: true = doesn't give client effect
  */
-int pc_delsoulball(struct map_session_data *sd, int count, int type)
+int pc_delsoulball(map_session_data *sd, int count, bool type)
 {
 	nullpo_ret(sd);
 
-	if (sd->soulball <= 0) {
-		sd->soulball = 0;
-		return 0;
-	}
-
 	if (count <= 0)
 		return 0;
 
-	if (count > sd->soulball)
-		count = sd->soulball;
-	sd->soulball -= count;
-	if (count > MAX_SOUL_BALL)
-		count = MAX_SOUL_BALL;
+	status_change *sc = status_get_sc(&sd->bl);
 
-	for (int i = 0; i < count; i++) {
-		if (sd->soul_timer[i] != INVALID_TIMER) {
-			delete_timer(sd->soul_timer[i], pc_soulball_timer);
-			sd->soul_timer[i] = INVALID_TIMER;
-		}
+	if (sd->soulball <= 0 || sc == nullptr || sc->data[SC_SOULENERGY] == nullptr) {
+		sd->soulball = 0;
+		return 0;
 	}
 
-	for (int i = count; i < MAX_SOUL_BALL; i++) {
-		sd->soul_timer[i - count] = sd->soul_timer[i];
-		sd->soul_timer[i] = INVALID_TIMER;
-	}
+	sd->soulball -= cap_value(count, 0, sd->soulball);
+	if (sd->soulball == 0)
+		status_change_end(&sd->bl, SC_SOULENERGY, INVALID_TIMER);
+	else
+		sc->data[SC_SOULENERGY]->val1 = sd->soulball;
 
 	if (!type)
 		clif_soulball(sd);
@@ -1562,8 +1514,6 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
 
 	for(i = 0; i < MAX_SPIRITBALL; i++)
 		sd->spirit_timer[i] = INVALID_TIMER;
-	for (i = 0; i < MAX_SOUL_BALL; i++)
-		sd->soul_timer[i] = INVALID_TIMER;
 
 	if (battle_config.item_auto_get)
 		sd->state.autoloot = 10000;
@@ -8333,7 +8283,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 	if ( sd->spiritball !=0 )
 		pc_delspiritball(sd,sd->spiritball,0);
 	if (sd->soulball != 0)
-		pc_delsoulball(sd, sd->soulball, 0);
+		pc_delsoulball(sd, sd->soulball, false);
 
 	if (sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm > 0)
 		pc_delspiritcharm(sd,sd->spiritcharm,sd->spiritcharm_type);
@@ -12586,6 +12536,9 @@ void pc_scdata_received(struct map_session_data *sd) {
 		sd->cart_weight_max = 0; // Force a client refesh
 		status_calc_cart_weight(sd, (e_status_calc_weight_opt)(CALCWT_ITEM|CALCWT_MAXBONUS|CALCWT_CARTSTATE));
 	}
+
+	if (sd->sc.data[SC_SOULENERGY])
+		sd->soulball = sd->sc.data[SC_SOULENERGY]->val1;
 }
 
 /**
@@ -13526,7 +13479,6 @@ void do_init_pc(void) {
 	add_timer_func_list(pc_calc_pvprank_timer, "pc_calc_pvprank_timer");
 	add_timer_func_list(pc_autosave, "pc_autosave");
 	add_timer_func_list(pc_spiritball_timer, "pc_spiritball_timer");
-	add_timer_func_list(pc_soulball_timer, "pc_soulball_timer");
 	add_timer_func_list(pc_follow_timer, "pc_follow_timer");
 	add_timer_func_list(pc_endautobonus, "pc_endautobonus");
 	add_timer_func_list(pc_spiritcharm_timer, "pc_spiritcharm_timer");

+ 2 - 3
src/map/pc.hpp

@@ -541,7 +541,6 @@ struct map_session_data {
 	int spiritcharm_type; //Spirit type
 	int spiritcharm_timer[MAX_SPIRITCHARM];
 	int8 soulball, soulball_old;
-	int soul_timer[MAX_SOUL_BALL];
 
 	unsigned char potion_success_counter; //Potion successes in row counter
 	unsigned char mission_count; //Stores the bounty kill count for TK_MISSION
@@ -1321,8 +1320,8 @@ void pc_delinvincibletimer(struct map_session_data* sd);
 
 void pc_addspiritball(struct map_session_data *sd,int interval,int max);
 void pc_delspiritball(struct map_session_data *sd,int count,int type);
-int pc_addsoulball(struct map_session_data *sd,int interval,int max);
-int pc_delsoulball(struct map_session_data *sd,int count,int type);
+int pc_addsoulball(map_session_data *sd, int max);
+int pc_delsoulball(map_session_data *sd, int count, bool type);
 
 void pc_addfame(struct map_session_data *sd,int count);
 unsigned char pc_famerank(uint32 char_id, int job);

+ 4 - 4
src/map/skill.cpp

@@ -2034,7 +2034,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 					case SC_DRESSUP:		case SC_HANBOK:			case SC_OKTOBERFEST:
 					case SC_LHZ_DUN_N1:		case SC_LHZ_DUN_N2:			case SC_LHZ_DUN_N3:			case SC_LHZ_DUN_N4:
 					case SC_ENTRY_QUEUE_APPLY_DELAY:	case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
-					case SC_REUSE_LIMIT_LUXANIMA:	case SC_LUXANIMA:
+					case SC_REUSE_LIMIT_LUXANIMA:	case SC_LUXANIMA:	case SC_SOULENERGY:
 						continue;
 					case SC_WHISTLE:		case SC_ASSNCROS:		case SC_POEMBRAGI:
 					case SC_APPLEIDUN:		case SC_HUMMING:		case SC_DONTFORGETME:
@@ -8515,7 +8515,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 					case SC_WEDDING:		case SC_XMAS:			case SC_SUMMER:
 					case SC_DRESSUP:		case SC_HANBOK:			case SC_OKTOBERFEST:
 					case SC_LHZ_DUN_N1:		case SC_LHZ_DUN_N2:			case SC_LHZ_DUN_N3:			case SC_LHZ_DUN_N4:
-					case SC_REUSE_LIMIT_LUXANIMA:	case SC_LUXANIMA:
+					case SC_REUSE_LIMIT_LUXANIMA:	case SC_LUXANIMA:	case SC_SOULENERGY:
 						continue;
 					case SC_WHISTLE:
 					case SC_ASSNCROS:
@@ -10002,7 +10002,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 					case SC_DRESSUP:		case SC_HANBOK:			case SC_OKTOBERFEST:
 					case SC_LHZ_DUN_N1:		case SC_LHZ_DUN_N2:			case SC_LHZ_DUN_N3:			case SC_LHZ_DUN_N4:
 					case SC_ENTRY_QUEUE_APPLY_DELAY:	case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
-					case SC_REUSE_LIMIT_LUXANIMA:		case SC_LUXANIMA:
+					case SC_REUSE_LIMIT_LUXANIMA:		case SC_LUXANIMA:	case SC_SOULENERGY:
 					continue;
 				case SC_ASSUMPTIO:
 					if( bl->type == BL_MOB )
@@ -16728,7 +16728,7 @@ void skill_consume_requirement(struct map_session_data *sd, uint16 skill_id, uin
 				case SP_SOULREAPER:
 				case SP_SOULEXPLOSION:
 				case SP_KAUTE:
-					pc_delsoulball(sd, require.spiritball, 0);
+					pc_delsoulball(sd, require.spiritball, false);
 					break;
 
 				default: // Skills that require spirit/coin spheres.

+ 16 - 4
src/map/status.cpp

@@ -1390,6 +1390,11 @@ void initChangeTables(void)
 	StatusIconChangeTable[SC_ENTRY_QUEUE_APPLY_DELAY] = EFST_ENTRY_QUEUE_APPLY_DELAY;
 	StatusIconChangeTable[SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT] = EFST_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT;
 
+	// Soul Reaper
+	StatusIconChangeTable[SC_SOULENERGY] = EFST_SOULENERGY;
+	StatusIconChangeTable[SC_USE_SKILL_SP_SPA] = EFST_USE_SKILL_SP_SPA;
+	StatusIconChangeTable[SC_USE_SKILL_SP_SHA] = EFST_USE_SKILL_SP_SHA;
+
 	/* Other SC which are not necessarily associated to skills */
 	StatusChangeFlagTable[SC_ASPDPOTION0] |= SCB_ASPD;
 	StatusChangeFlagTable[SC_ASPDPOTION1] |= SCB_ASPD;
@@ -1558,8 +1563,9 @@ void initChangeTables(void)
 	StatusChangeFlagTable[SC_DORAM_BUF_02] |= SCB_REGEN;
 
 	// Soul Reaper
-	StatusIconChangeTable[SC_USE_SKILL_SP_SPA] = EFST_USE_SKILL_SP_SPA;
-	StatusIconChangeTable[SC_USE_SKILL_SP_SHA] = EFST_USE_SKILL_SP_SHA;
+	StatusChangeFlagTable[SC_SOULENERGY] |= SCB_NONE;
+	StatusChangeFlagTable[SC_USE_SKILL_SP_SPA] |= SCB_NONE;
+	StatusChangeFlagTable[SC_USE_SKILL_SP_SHA] |= SCB_NONE;
 
 	StatusChangeFlagTable[SC_ANCILLA] |= SCB_REGEN;
 	StatusChangeFlagTable[SC_ENSEMBLEFATIGUE] |= SCB_SPEED|SCB_ASPD;
@@ -12883,6 +12889,7 @@ int status_change_clear(struct block_list* bl, int type)
 			case SC_ENTRY_QUEUE_APPLY_DELAY:
 			case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
 			case SC_REUSE_LIMIT_LUXANIMA:
+			case SC_SOULENERGY:
 			// Costumes
 			case SC_MOONSTAR:
 			case SC_SUPER_STAR:
@@ -13567,6 +13574,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 		case SC_JUMPINGCLAN:
 			status_change_end(bl,SC_CLAN_INFO,INVALID_TIMER);
 			break;
+		case SC_SOULENERGY:
+			if (sd)
+				pc_delsoulball(sd, sd->soulball, false);
+			break;
 	}
 
 	opt_flag = 1;
@@ -14778,8 +14789,8 @@ TIMER_FUNC(status_change_timer){
 		}
 		break;
 	case SC_SOULCOLLECT:
-		pc_addsoulball(sd, skill_get_time2(SP_SOULCOLLECT, sce->val1), sce->val2);
-		if( sd->soulball < sce->val2 ){
+		pc_addsoulball(sd, sce->val2);
+		if (sd->soulball < sce->val2) {
 			sc_timer_next(sce->val3 + tick);
 			return 0;
 		}
@@ -15028,6 +15039,7 @@ void status_change_clear_buffs(struct block_list* bl, uint8 type)
 			case SC_LHZ_DUN_N4:
 			case SC_REUSE_LIMIT_LUXANIMA:
 			case SC_LUXANIMA:
+			case SC_SOULENERGY:
 			// Clans
 			case SC_CLAN_INFO:
 			case SC_SWORDCLAN:

+ 0 - 1
src/map/unit.cpp

@@ -3364,7 +3364,6 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 			pc_inventory_rental_clear(sd);
 			pc_delspiritball(sd, sd->spiritball, 1);
 			pc_delspiritcharm(sd, sd->spiritcharm, sd->spiritcharm_type);
-			pc_delsoulball(sd,sd->soulball, 1);
 
 			if( sd->st && sd->st->state != RUN ) {// free attached scripts that are waiting
 				script_free_state(sd->st);