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!
This commit is contained in:
parent
87da34f28c
commit
cef956d352
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
100
src/map/pc.cpp
100
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);
|
||||
|
||||
status_change *sc = status_get_sc(&sd->bl);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
max = min(max, MAX_SOUL_BALL);
|
||||
sd->soulball = cap_value(sd->soulball, 0, MAX_SOUL_BALL);
|
||||
|
||||
if (sd->soulball && sd->soulball >= max) {
|
||||
if (sd->soul_timer[0] != INVALID_TIMER)
|
||||
delete_timer(sd->soul_timer[0], pc_soulball_timer);
|
||||
if (sd->soulball && sd->soulball >= max)
|
||||
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 (interval > 0) {
|
||||
int tid = add_timer(gettick() + interval, pc_soulball_timer, sd->bl.id, 0), i;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user