Spirit Charm Update
* Fixes #464 * Cleaned up and optimized the Spirit Charm system for Kagerou/Orobo. * Updated effects to mimic official server.
This commit is contained in:
parent
ef347830a0
commit
9f3fa0d757
153
src/map/battle.c
153
src/map/battle.c
@ -2638,7 +2638,6 @@ static int battle_get_weapon_element(struct Damage wd, struct block_list *src, s
|
||||
struct map_session_data *sd = BL_CAST(BL_PC, src);
|
||||
struct status_change *sc = status_get_sc(src);
|
||||
struct status_data *sstatus = status_get_status_data(src);
|
||||
uint8 i;
|
||||
int element = skill_get_ele(skill_id, skill_lv);
|
||||
|
||||
//Take weapon's element
|
||||
@ -2649,16 +2648,11 @@ static int battle_get_weapon_element(struct Damage wd, struct block_list *src, s
|
||||
element = sstatus->lhw.ele;
|
||||
if(is_skill_using_arrow(src, skill_id) && sd && sd->bonus.arrow_ele && weapon_position == EQI_HAND_R)
|
||||
element = sd->bonus.arrow_ele;
|
||||
if(sd && sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm >= MAX_SPIRITCHARM)
|
||||
element = sd->spiritcharm_type; // Summoning 10 spiritcharm will endow your weapon
|
||||
// on official endows override all other elements [helvetica]
|
||||
if (sd) { //Summoning 10 talisman will endow your weapon.
|
||||
ARR_FIND(1, 6, i, sd->talisman[i] >= 10);
|
||||
if (i < 5)
|
||||
element = i;
|
||||
if (sc) { // check for endows
|
||||
if(sc->data[SC_ENCHANTARMS])
|
||||
if(sc && sc->data[SC_ENCHANTARMS]) // Check for endows
|
||||
element = sc->data[SC_ENCHANTARMS]->val2;
|
||||
}
|
||||
}
|
||||
} else if( element == -2 ) //Use enchantment's element
|
||||
element = status_get_attack_sc_element(src,sc);
|
||||
else if( element == -3 ) //Use random element
|
||||
@ -4286,18 +4280,13 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, s
|
||||
#endif
|
||||
int inf3 = skill_get_inf3(skill_id);
|
||||
|
||||
if (sd) {
|
||||
int type;
|
||||
|
||||
// Kagerou/Oboro Earth Charm effect +15% wATK
|
||||
ARR_FIND(1, 6, type, sd->talisman[type] > 0);
|
||||
if (type == 2) { //KO Earth Charm effect +15% wATK
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, 15 * sd->talisman[type]);
|
||||
if(sd && sd->spiritcharm_type == CHARM_TYPE_LAND && sd->spiritcharm > 0) {
|
||||
ATK_ADDRATE(wd.damage, wd.damage2, 15 * sd->spiritcharm);
|
||||
#ifdef RENEWAL
|
||||
ATK_ADDRATE(wd.weaponAtk, wd.weaponAtk2, 15 * sd->talisman[type]);
|
||||
ATK_ADDRATE(wd.weaponAtk, wd.weaponAtk2, 15 * sd->spiritcharm);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//The following are applied on top of current damage and are stackable.
|
||||
if (sc) {
|
||||
@ -4453,7 +4442,6 @@ struct Damage battle_calc_defense_reduction(struct Damage wd, struct block_list
|
||||
#endif
|
||||
|
||||
if (sd) {
|
||||
int type;
|
||||
int i = sd->ignore_def_by_race[tstatus->race] + sd->ignore_def_by_race[RC_ALL];
|
||||
|
||||
if (i) {
|
||||
@ -4462,11 +4450,11 @@ struct Damage battle_calc_defense_reduction(struct Damage wd, struct block_list
|
||||
def2 -= def2 * i / 100;
|
||||
}
|
||||
|
||||
//Kagerou/Oboro Earth Charm effect +5% eDEF
|
||||
ARR_FIND(1, 6, type, sd->talisman[type] > 0);
|
||||
if (type == 2) {
|
||||
short j = 5 * sd->talisman[type];
|
||||
def1 = (def1 * (100 + j)) / 100;
|
||||
//Kagerou/Oboro Earth Charm effect +10% eDEF
|
||||
if(sd->spiritcharm_type == CHARM_TYPE_LAND && sd->spiritcharm > 0) {
|
||||
short i = 10 * sd->spiritcharm;
|
||||
|
||||
def1 = (def1 * (100 + i)) / 100;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5480,10 +5468,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
|
||||
if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element
|
||||
s_ele = sstatus->rhw.ele;
|
||||
if( sd ){ //Summoning 10 talisman will endow your weapon
|
||||
ARR_FIND(1, 6, i, sd->talisman[i] >= 10);
|
||||
if( i < 5 ) s_ele = i;
|
||||
}
|
||||
if(sd && sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm >= MAX_SPIRITCHARM)
|
||||
s_ele = sd->spiritcharm_type; // Summoning 10 spiritcharm will endow your weapon
|
||||
}else if (s_ele == -2) //Use status element
|
||||
s_ele = status_get_attack_sc_element(src,status_get_sc(src));
|
||||
else if( s_ele == -3 ) //Use random element
|
||||
@ -5503,11 +5489,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
}
|
||||
break;
|
||||
case KO_KAIHOU:
|
||||
if(sd) {
|
||||
ARR_FIND(1, 6, i, sd->talisman[i] > 0);
|
||||
if(i < 5)
|
||||
s_ele = i;
|
||||
}
|
||||
if(sd && sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm > 0)
|
||||
s_ele = sd->spiritcharm_type;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -5698,22 +5681,50 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
break;
|
||||
case NJ_KOUENKA:
|
||||
skillratio -= 10;
|
||||
if(sd && sd->spiritcharm_type == CHARM_TYPE_FIRE && sd->spiritcharm > 0)
|
||||
skillratio += 20 * sd->spiritcharm;
|
||||
break;
|
||||
case NJ_KAENSIN:
|
||||
skillratio -= 50;
|
||||
if(sd && sd->spiritcharm_type == CHARM_TYPE_FIRE && sd->spiritcharm > 0)
|
||||
skillratio += 10 * sd->spiritcharm;
|
||||
break;
|
||||
case NJ_BAKUENRYU:
|
||||
skillratio += 50*(skill_lv-1);
|
||||
skillratio += 50 * (skill_lv - 1);
|
||||
if(sd && sd->spiritcharm_type == CHARM_TYPE_FIRE && sd->spiritcharm > 0)
|
||||
skillratio += 15 * sd->spiritcharm;
|
||||
break;
|
||||
case NJ_HYOUSENSOU:
|
||||
#ifdef RENEWAL
|
||||
skillratio -= 30;
|
||||
#endif
|
||||
if(sd && sd->spiritcharm_type == CHARM_TYPE_WATER && sd->spiritcharm > 0)
|
||||
skillratio += 5 * sd->spiritcharm;
|
||||
break;
|
||||
case NJ_HYOUSYOURAKU:
|
||||
skillratio += 50*skill_lv;
|
||||
skillratio += 50 * skill_lv;
|
||||
if(sd && sd->spiritcharm_type == CHARM_TYPE_WATER && sd->spiritcharm > 0)
|
||||
skillratio += 25 * sd->spiritcharm;
|
||||
break;
|
||||
case NJ_RAIGEKISAI:
|
||||
skillratio += 60 + 40*skill_lv;
|
||||
skillratio += 60 + 40 * skill_lv;
|
||||
if(sd && sd->spiritcharm_type == CHARM_TYPE_WIND && sd->spiritcharm > 0)
|
||||
skillratio += 15 * sd->spiritcharm;
|
||||
break;
|
||||
case NJ_KAMAITACHI:
|
||||
skillratio += 100 * skill_lv;
|
||||
if(sd && sd->spiritcharm_type == CHARM_TYPE_WIND && sd->spiritcharm > 0)
|
||||
skillratio += 10 * sd->spiritcharm;
|
||||
break;
|
||||
case NJ_HUUJIN:
|
||||
#ifdef RENEWAL
|
||||
skillratio += 50;
|
||||
#endif
|
||||
if(sd && sd->spiritcharm_type == CHARM_TYPE_WIND && sd->spiritcharm > 0)
|
||||
skillratio += 20 * sd->spiritcharm;
|
||||
break;
|
||||
case NPC_ENERGYDRAIN:
|
||||
skillratio += 100*skill_lv;
|
||||
skillratio += 100 * skill_lv;
|
||||
break;
|
||||
case NPC_EARTHQUAKE:
|
||||
skillratio += 100 +100*skill_lv +100*(skill_lv/2);
|
||||
@ -5735,9 +5746,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
skillratio += ratio;
|
||||
}
|
||||
break;
|
||||
case NJ_HUUJIN:
|
||||
skillratio += 50;
|
||||
break;
|
||||
#else
|
||||
case WZ_VERMILION:
|
||||
skillratio += 20*skill_lv-20;
|
||||
@ -5921,15 +5929,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
skillratio += 10 + 20 * skill_lv;
|
||||
break;
|
||||
case KO_KAIHOU:
|
||||
if(sd) {
|
||||
int ttype;
|
||||
|
||||
ARR_FIND(1, 6, ttype, sd->talisman[ttype] > 0);
|
||||
if(ttype < 5) {
|
||||
skillratio += -100 + 200 * sd->talisman[ttype];
|
||||
if(sd && sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm > 0) {
|
||||
skillratio += -100 + 200 * sd->spiritcharm;
|
||||
RE_LVL_DMOD(100);
|
||||
pc_del_talisman(sd, sd->talisman[ttype], ttype);
|
||||
}
|
||||
pc_delspiritcharm(sd, sd->spiritcharm, sd->spiritcharm_type);
|
||||
}
|
||||
break;
|
||||
// Magical Elemental Spirits Attack Skills
|
||||
@ -5968,62 +5971,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
break;
|
||||
}
|
||||
|
||||
if (sd) {
|
||||
int sd_charm;
|
||||
|
||||
ARR_FIND(1, 6, sd_charm, sd->talisman[sd_charm] > 0);
|
||||
if(sd_charm < 5 && s_ele == sd_charm) {
|
||||
switch(skill_id) {
|
||||
case NJ_HYOUSYOURAKU:
|
||||
skillratio += 25 * sd->talisman[sd_charm];
|
||||
break;
|
||||
case NJ_KOUENKA:
|
||||
case NJ_HUUJIN:
|
||||
skillratio += 20 * sd->talisman[sd_charm];
|
||||
break;
|
||||
case NJ_BAKUENRYU:
|
||||
case NJ_RAIGEKISAI:
|
||||
skillratio += 15 * sd->talisman[sd_charm];
|
||||
break;
|
||||
case NJ_KAMAITACHI:
|
||||
skillratio += 10 * sd->talisman[sd_charm];
|
||||
break;
|
||||
case NJ_KAENSIN:
|
||||
case NJ_HYOUSENSOU:
|
||||
skillratio += 5 * sd->talisman[sd_charm];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tsd) {
|
||||
int tsd_charm;
|
||||
|
||||
ARR_FIND(1, 6, tsd_charm, tsd->talisman[tsd_charm] > 0);
|
||||
if(tsd_charm < 5 && s_ele == tsd_charm) {
|
||||
switch(skill_id) {
|
||||
case NJ_HYOUSYOURAKU:
|
||||
skillratio -= 25 * tsd->talisman[tsd_charm];
|
||||
break;
|
||||
case NJ_KOUENKA:
|
||||
case NJ_HUUJIN:
|
||||
skillratio -= 20 * tsd->talisman[tsd_charm];
|
||||
break;
|
||||
case NJ_BAKUENRYU:
|
||||
case NJ_RAIGEKISAI:
|
||||
skillratio -= 15 * tsd->talisman[tsd_charm];
|
||||
break;
|
||||
case NJ_KAMAITACHI:
|
||||
skillratio -= 10 * tsd->talisman[tsd_charm];
|
||||
break;
|
||||
case NJ_KAENSIN:
|
||||
case NJ_HYOUSENSOU:
|
||||
skillratio -= 5 * tsd->talisman[tsd_charm];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MATK_RATE(skillratio);
|
||||
|
||||
//Constant/misc additions from skills
|
||||
|
@ -1250,13 +1250,13 @@ static void clif_spiritball_single(int fd, struct map_session_data *sd)
|
||||
/*==========================================
|
||||
* Kagerou/Oboro amulet spirit
|
||||
*------------------------------------------*/
|
||||
static void clif_talisman_single(int fd, struct map_session_data *sd, short type)
|
||||
static void clif_spiritcharm_single(int fd, struct map_session_data *sd)
|
||||
{
|
||||
WFIFOHEAD(fd, packet_len(0x08cf));
|
||||
WFIFOW(fd,0)=0x08cf;
|
||||
WFIFOL(fd,2)=sd->bl.id;
|
||||
WFIFOW(fd,6)=type;
|
||||
WFIFOW(fd,8)=sd->talisman[type];
|
||||
WFIFOW(fd,6)=sd->spiritcharm_type;
|
||||
WFIFOW(fd,8)=sd->spiritcharm;
|
||||
WFIFOSET(fd, packet_len(0x08cf));
|
||||
}
|
||||
|
||||
@ -1354,10 +1354,8 @@ int clif_spawn(struct block_list *bl)
|
||||
clif_specialeffect(bl,421,AREA);
|
||||
if( sd->bg_id && map[sd->bl.m].flag.battleground )
|
||||
clif_sendbgemblem_area(sd);
|
||||
for(i = 1; i < 5; i++){
|
||||
if( sd->talisman[i] > 0 )
|
||||
clif_talisman(sd, i);
|
||||
}
|
||||
if (sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm > 0)
|
||||
clif_spiritcharm(sd);
|
||||
for (i = 0; i < sd->sc_display_count; i++) {
|
||||
if (sc && (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE|OPTION_CHASEWALK)))
|
||||
clif_status_change2(&sd->bl,sd->bl.id,AREA,SI_BLANK,0,0,0);
|
||||
@ -4310,10 +4308,8 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d
|
||||
|
||||
if(dstsd->spiritball > 0)
|
||||
clif_spiritball_single(sd->fd, dstsd);
|
||||
for(i = 1; i < 5; i++){
|
||||
if( dstsd->talisman[i] > 0 )
|
||||
clif_talisman_single(sd->fd, dstsd, i);
|
||||
}
|
||||
if (dstsd->spiritcharm_type != CHARM_TYPE_NONE && dstsd->spiritcharm > 0)
|
||||
clif_spiritcharm_single(sd->fd, dstsd);
|
||||
for( i = 0; i < dstsd->sc_display_count; i++ ) {
|
||||
if (dstsd->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE|OPTION_CHASEWALK))
|
||||
clif_status_change2(&sd->bl, dstsd->bl.id, SELF, SI_BLANK, 0, 0, 0);
|
||||
@ -8870,7 +8866,6 @@ void clif_refresh_storagewindow(struct map_session_data *sd) {
|
||||
// refresh the client's screen, getting rid of any effects
|
||||
void clif_refresh(struct map_session_data *sd)
|
||||
{
|
||||
int i;
|
||||
nullpo_retv(sd);
|
||||
|
||||
clif_changemap(sd,sd->bl.m,sd->bl.x,sd->bl.y);
|
||||
@ -8889,10 +8884,8 @@ void clif_refresh(struct map_session_data *sd)
|
||||
clif_updatestatus(sd,SP_LUK);
|
||||
if (sd->spiritball)
|
||||
clif_spiritball_single(sd->fd, sd);
|
||||
for(i = 1; i < 5; i++){
|
||||
if( sd->talisman[i] > 0 )
|
||||
clif_talisman_single(sd->fd, sd, i);
|
||||
}
|
||||
if (sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm > 0)
|
||||
clif_spiritcharm_single(sd->fd, sd);
|
||||
if (sd->vd.cloth_color)
|
||||
clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF);
|
||||
if(hom_is_active(sd->hd))
|
||||
@ -17166,7 +17159,7 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) {
|
||||
/*==========================================
|
||||
* Kagerou/Oboro amulet spirit
|
||||
*------------------------------------------*/
|
||||
void clif_talisman(struct map_session_data *sd,short type)
|
||||
void clif_spiritcharm(struct map_session_data *sd)
|
||||
{
|
||||
unsigned char buf[10];
|
||||
|
||||
@ -17174,8 +17167,8 @@ void clif_talisman(struct map_session_data *sd,short type)
|
||||
|
||||
WBUFW(buf,0)=0x08cf;
|
||||
WBUFL(buf,2)=sd->bl.id;
|
||||
WBUFW(buf,6)=type;
|
||||
WBUFW(buf,8)=sd->talisman[type];
|
||||
WBUFW(buf,6)=sd->spiritcharm_type;
|
||||
WBUFW(buf,8)=sd->spiritcharm;
|
||||
clif_send(buf,packet_len(0x08cf),&sd->bl,AREA);
|
||||
}
|
||||
/// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE]
|
||||
|
@ -883,7 +883,7 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uin
|
||||
void clif_elemental_info(struct map_session_data *sd);
|
||||
void clif_elemental_updatestatus(struct map_session_data *sd, int type);
|
||||
|
||||
void clif_talisman(struct map_session_data *sd, short type);
|
||||
void clif_spiritcharm(struct map_session_data *sd);
|
||||
|
||||
void clif_snap( struct block_list *bl, short x, short y );
|
||||
void clif_monster_hp_bar( struct mob_data* md, int fd );
|
||||
|
@ -370,6 +370,18 @@ enum e_element {
|
||||
|
||||
#define MAX_ELE_LEVEL 4 /// Maximum Element level
|
||||
|
||||
/**
|
||||
* Types of spirit charms
|
||||
* NOTE: Code assumes that this matches the first entries in enum elements
|
||||
*/
|
||||
enum spirit_charm_types {
|
||||
CHARM_TYPE_NONE = 0,
|
||||
CHARM_TYPE_WATER,
|
||||
CHARM_TYPE_LAND,
|
||||
CHARM_TYPE_FIRE,
|
||||
CHARM_TYPE_WIND
|
||||
};
|
||||
|
||||
enum mob_ai {
|
||||
AI_NONE = 0,
|
||||
AI_ATTACK,
|
||||
|
154
src/map/pc.c
154
src/map/pc.c
@ -7345,8 +7345,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
|
||||
if ( sd->spiritball !=0 )
|
||||
pc_delspiritball(sd,sd->spiritball,0);
|
||||
|
||||
for(i = 1; i < 5; i++)
|
||||
pc_del_talisman(sd, sd->talisman[i], i);
|
||||
if (sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm > 0)
|
||||
pc_delspiritcharm(sd,sd->spiritcharm,sd->spiritcharm_type);
|
||||
|
||||
if (src)
|
||||
switch (src->type) {
|
||||
@ -10207,102 +10207,138 @@ bool pc_should_log_commands(struct map_session_data *sd)
|
||||
return pc_group_should_log_commands(pc_get_group_id(sd));
|
||||
}
|
||||
|
||||
static int pc_talisman_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
/**
|
||||
* Spirit Charm expiration timer.
|
||||
* @see TimerFunc
|
||||
*/
|
||||
static int pc_spiritcharm_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
{
|
||||
struct map_session_data *sd;
|
||||
int i, type;
|
||||
int i;
|
||||
|
||||
if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC )
|
||||
if ((sd = (struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type != BL_PC)
|
||||
return 1;
|
||||
|
||||
ARR_FIND(1, 5, type, sd->talisman[type] > 0);
|
||||
|
||||
if( sd->talisman[type] <= 0 )
|
||||
{
|
||||
ShowError("pc_talisman_timer: %d talisman's available. (aid=%d cid=%d tid=%d)\n", sd->talisman[type], sd->status.account_id, sd->status.char_id, tid);
|
||||
sd->talisman[type] = 0;
|
||||
if (sd->spiritcharm <= 0) {
|
||||
ShowError("pc_spiritcharm_timer: %d spiritcharm's available. (aid=%d cid=%d tid=%d)\n", sd->spiritcharm, sd->status.account_id, sd->status.char_id, tid);
|
||||
sd->spiritcharm = 0;
|
||||
sd->spiritcharm_type = CHARM_TYPE_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == tid);
|
||||
if( i == sd->talisman[type] )
|
||||
{
|
||||
ShowError("pc_talisman_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid);
|
||||
ARR_FIND(0, sd->spiritcharm, i, sd->spiritcharm_timer[i] == tid);
|
||||
|
||||
if (i == sd->spiritcharm) {
|
||||
ShowError("pc_spiritcharm_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sd->talisman[type]--;
|
||||
if( i != sd->talisman[type] )
|
||||
memmove(sd->talisman_timer[type]+i, sd->talisman_timer[type]+i+1, (sd->talisman[type]-i)*sizeof(int));
|
||||
sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER;
|
||||
sd->spiritcharm--;
|
||||
|
||||
clif_talisman(sd, type);
|
||||
if (i != sd->spiritcharm)
|
||||
memmove(sd->spiritcharm_timer + i, sd->spiritcharm_timer + i + 1, (sd->spiritcharm - i) * sizeof(int));
|
||||
|
||||
sd->spiritcharm_timer[sd->spiritcharm] = INVALID_TIMER;
|
||||
|
||||
if (sd->spiritcharm <= 0)
|
||||
sd->spiritcharm_type = CHARM_TYPE_NONE;
|
||||
|
||||
clif_spiritcharm(sd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pc_add_talisman(struct map_session_data *sd,int interval,int max,int type)
|
||||
/**
|
||||
* Adds a spirit charm.
|
||||
* @param sd: Target character
|
||||
* @param interval: Duration
|
||||
* @param max: Maximum amount of charms to add
|
||||
* @param type: Charm type (@see spirit_charm_types)
|
||||
*/
|
||||
void pc_addspiritcharm(struct map_session_data *sd, int interval, int max, int type)
|
||||
{
|
||||
int tid, i;
|
||||
|
||||
nullpo_retv(sd);
|
||||
|
||||
if(max > 10)
|
||||
max = 10;
|
||||
if(sd->talisman[type] < 0)
|
||||
sd->talisman[type] = 0;
|
||||
if (sd->spiritcharm_type != CHARM_TYPE_NONE && type != sd->spiritcharm_type)
|
||||
pc_delspiritcharm(sd, sd->spiritcharm, sd->spiritcharm_type);
|
||||
|
||||
if( sd->talisman[type] && sd->talisman[type] >= max )
|
||||
{
|
||||
if(sd->talisman_timer[type][0] != INVALID_TIMER)
|
||||
delete_timer(sd->talisman_timer[type][0],pc_talisman_timer);
|
||||
sd->talisman[type]--;
|
||||
if( sd->talisman[type] != 0 )
|
||||
memmove(sd->talisman_timer[type]+0, sd->talisman_timer[type]+1, (sd->talisman[type])*sizeof(int));
|
||||
sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER;
|
||||
if (max > MAX_SPIRITCHARM)
|
||||
max = MAX_SPIRITCHARM;
|
||||
|
||||
if (sd->spiritcharm < 0)
|
||||
sd->spiritcharm = 0;
|
||||
|
||||
if (sd->spiritcharm && sd->spiritcharm >= max) {
|
||||
if (sd->spiritcharm_timer[0] != INVALID_TIMER)
|
||||
delete_timer(sd->spiritcharm_timer[0], pc_spiritcharm_timer);
|
||||
sd->spiritcharm--;
|
||||
if (sd->spiritcharm != 0)
|
||||
memmove(sd->spiritcharm_timer + 0, sd->spiritcharm_timer + 1, (sd->spiritcharm) * sizeof(int));
|
||||
sd->spiritcharm_timer[sd->spiritcharm] = INVALID_TIMER;
|
||||
}
|
||||
|
||||
tid = add_timer(gettick()+interval, pc_talisman_timer, sd->bl.id, 0);
|
||||
ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->talisman_timer[type][i])->tick) < 0);
|
||||
if( i != sd->talisman[type] )
|
||||
memmove(sd->talisman_timer[type]+i+1, sd->talisman_timer[type]+i, (sd->talisman[type]-i)*sizeof(int));
|
||||
sd->talisman_timer[type][i] = tid;
|
||||
sd->talisman[type]++;
|
||||
tid = add_timer(gettick() + interval, pc_spiritcharm_timer, sd->bl.id, 0);
|
||||
ARR_FIND(0, sd->spiritcharm, i, sd->spiritcharm_timer[i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->spiritcharm_timer[i])->tick) < 0);
|
||||
|
||||
clif_talisman(sd, type);
|
||||
if (i != sd->spiritcharm)
|
||||
memmove(sd->spiritcharm_timer + i + 1, sd->spiritcharm_timer + i, (sd->spiritcharm - i) * sizeof(int));
|
||||
|
||||
sd->spiritcharm_timer[i] = tid;
|
||||
sd->spiritcharm++;
|
||||
sd->spiritcharm_type = type;
|
||||
|
||||
clif_spiritcharm(sd);
|
||||
}
|
||||
|
||||
void pc_del_talisman(struct map_session_data *sd,int count,int type)
|
||||
/**
|
||||
* Removes one or more spirit charms.
|
||||
* @param sd: The target character
|
||||
* @param count: Amount of charms to remove
|
||||
* @param type: Type of charm to remove
|
||||
*/
|
||||
void pc_delspiritcharm(struct map_session_data *sd, int count, int type)
|
||||
{
|
||||
int i;
|
||||
|
||||
nullpo_retv(sd);
|
||||
|
||||
if( sd->talisman[type] <= 0 ) {
|
||||
sd->talisman[type] = 0;
|
||||
if (sd->spiritcharm_type != type)
|
||||
return;
|
||||
|
||||
if (sd->spiritcharm <= 0) {
|
||||
sd->spiritcharm = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if( count <= 0 )
|
||||
if (count <= 0)
|
||||
return;
|
||||
if( count > sd->talisman[type] )
|
||||
count = sd->talisman[type];
|
||||
sd->talisman[type] -= count;
|
||||
if( count > 10 )
|
||||
count = 10;
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
if(sd->talisman_timer[type][i] != INVALID_TIMER) {
|
||||
delete_timer(sd->talisman_timer[type][i],pc_talisman_timer);
|
||||
sd->talisman_timer[type][i] = INVALID_TIMER;
|
||||
if (count > sd->spiritcharm)
|
||||
count = sd->spiritcharm;
|
||||
|
||||
sd->spiritcharm -= count;
|
||||
|
||||
if (count > MAX_SPIRITCHARM)
|
||||
count = MAX_SPIRITCHARM;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (sd->spiritcharm_timer[i] != INVALID_TIMER) {
|
||||
delete_timer(sd->spiritcharm_timer[i], pc_spiritcharm_timer);
|
||||
sd->spiritcharm_timer[i] = INVALID_TIMER;
|
||||
}
|
||||
}
|
||||
for(i = count; i < 10; i++) {
|
||||
sd->talisman_timer[type][i-count] = sd->talisman_timer[type][i];
|
||||
sd->talisman_timer[type][i] = INVALID_TIMER;
|
||||
}
|
||||
|
||||
clif_talisman(sd, type);
|
||||
for (i = count; i < MAX_SPIRITCHARM; i++) {
|
||||
sd->spiritcharm_timer[i - count] = sd->spiritcharm_timer[i];
|
||||
sd->spiritcharm_timer[i] = INVALID_TIMER;
|
||||
}
|
||||
|
||||
if (sd->spiritcharm <= 0)
|
||||
sd->spiritcharm_type = CHARM_TYPE_NONE;
|
||||
|
||||
clif_spiritcharm(sd);
|
||||
}
|
||||
|
||||
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
|
||||
@ -11629,7 +11665,7 @@ void do_init_pc(void) {
|
||||
add_timer_func_list(pc_spiritball_timer, "pc_spiritball_timer");
|
||||
add_timer_func_list(pc_follow_timer, "pc_follow_timer");
|
||||
add_timer_func_list(pc_endautobonus, "pc_endautobonus");
|
||||
add_timer_func_list(pc_talisman_timer, "pc_talisman_timer");
|
||||
add_timer_func_list(pc_spiritcharm_timer, "pc_spiritcharm_timer");
|
||||
add_timer_func_list(pc_global_expiration_timer, "pc_global_expiration_timer");
|
||||
add_timer_func_list(pc_expiration_timer, "pc_expiration_timer");
|
||||
add_timer_func_list(pc_autotrade_timer, "pc_autotrade_timer");
|
||||
|
10
src/map/pc.h
10
src/map/pc.h
@ -28,6 +28,7 @@
|
||||
#define DAMAGELOG_SIZE_PC 100 /// Damage log
|
||||
#define MAX_SPIRITBALL 15 /// Max spirit balls
|
||||
#define MAX_DEVOTION 5 /// Max Devotion slots
|
||||
#define MAX_SPIRITCHARM 10 /// Max spirit charms
|
||||
|
||||
#define BANK_VAULT_VAR "#BANKVAULT"
|
||||
|
||||
@ -456,8 +457,9 @@ struct map_session_data {
|
||||
|
||||
int8 spiritball, spiritball_old;
|
||||
int spirit_timer[MAX_SPIRITBALL];
|
||||
short talisman[ELE_POISON+1]; // There are actually 5 talisman Fire, Ice, Wind, Earth & Poison maybe because its color violet.
|
||||
int talisman_timer[ELE_POISON+1][10];
|
||||
short spiritcharm; //No. of spirit
|
||||
int spiritcharm_type; //Spirit type
|
||||
int spiritcharm_timer[MAX_SPIRITCHARM];
|
||||
|
||||
unsigned char potion_success_counter; //Potion successes in row counter
|
||||
unsigned char mission_count; //Stores the bounty kill count for TK_MISSION
|
||||
@ -1144,8 +1146,8 @@ void pc_itemcd_do(struct map_session_data *sd, bool load);
|
||||
|
||||
int pc_load_combo(struct map_session_data *sd);
|
||||
|
||||
void pc_add_talisman(struct map_session_data *sd,int interval,int max,int type);
|
||||
void pc_del_talisman(struct map_session_data *sd,int count,int type);
|
||||
void pc_addspiritcharm(struct map_session_data *sd, int interval, int max, int type);
|
||||
void pc_delspiritcharm(struct map_session_data *sd, int count, int type);
|
||||
|
||||
void pc_baselevelchanged(struct map_session_data *sd);
|
||||
|
||||
|
@ -6491,8 +6491,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
i = 0;
|
||||
if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m) || (sd && sd->duel_group && sd->duel_group == dstsd->duel_group)) &&
|
||||
((dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK) != MAPID_REBELLION)) { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen]
|
||||
if (dstsd->spiritball > 0) {
|
||||
i = dstsd->spiritball * 7;
|
||||
pc_delspiritball(dstsd,dstsd->spiritball,0);
|
||||
}
|
||||
if (dstsd->spiritcharm_type != CHARM_TYPE_NONE && dstsd->spiritcharm > 0) {
|
||||
i += dstsd->spiritcharm * 7;
|
||||
pc_delspiritcharm(dstsd,dstsd->spiritcharm,dstsd->spiritcharm_type);
|
||||
}
|
||||
} else if (dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20) { // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen]
|
||||
i = 2 * dstmd->level;
|
||||
mob_target(dstmd,src,0);
|
||||
@ -9445,14 +9451,20 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
break;
|
||||
|
||||
case SR_ASSIMILATEPOWER:
|
||||
if( flag&1 ) {
|
||||
if (flag&1) {
|
||||
i = 0;
|
||||
if( dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER )
|
||||
{
|
||||
i = dstsd->spiritball; //1%sp per spiritball.
|
||||
pc_delspiritball(dstsd, dstsd->spiritball, 0);
|
||||
if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) {
|
||||
if (dstsd->spiritball > 0) {
|
||||
i = dstsd->spiritball;
|
||||
pc_delspiritball(dstsd,dstsd->spiritball,0);
|
||||
}
|
||||
if( i ) status_percent_heal(src, 0, i);
|
||||
if (dstsd->spiritcharm_type != CHARM_TYPE_NONE && dstsd->spiritcharm > 0) {
|
||||
i += dstsd->spiritcharm;
|
||||
pc_delspiritcharm(dstsd,dstsd->spiritcharm,dstsd->spiritcharm_type);
|
||||
}
|
||||
}
|
||||
if (i)
|
||||
status_percent_heal(src, 0, i);
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, i ? 1:0);
|
||||
} else {
|
||||
clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
|
||||
@ -10037,13 +10049,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
case KO_HYOUHU_HUBUKI:
|
||||
case KO_KAZEHU_SEIRAN:
|
||||
case KO_DOHU_KOUKAI:
|
||||
if(sd) {
|
||||
int i_tal, ttype = skill_get_ele(skill_id, skill_lv);
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
||||
ARR_FIND(1, 6, i_tal, sd->talisman[i_tal] > 0 && ttype != i_tal);
|
||||
if( i_tal < 6 )
|
||||
pc_del_talisman(sd, sd->talisman[i_tal], i_tal); // Replace talisman
|
||||
pc_add_talisman(sd, skill_get_time(skill_id, skill_lv), 10, ttype);
|
||||
if (sd) {
|
||||
int type = skill_get_ele(skill_id,skill_lv);
|
||||
|
||||
clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
|
||||
pc_addspiritcharm(sd,skill_get_time(skill_id,skill_lv),MAX_SPIRITCHARM,type);
|
||||
}
|
||||
break;
|
||||
case KO_ZANZOU:
|
||||
@ -12322,15 +12332,12 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
||||
limit = ((sd ? pc_checkskill(sd,GN_DEMONIC_FIRE) : 1) + 1) * limit;
|
||||
break;
|
||||
case KO_ZENKAI:
|
||||
if( sd ){
|
||||
ARR_FIND(1, 6, i, sd->talisman[i] > 0);
|
||||
if( i < 5 ){
|
||||
val1 = sd->talisman[i]; // no. of aura
|
||||
val2 = i; // aura type
|
||||
limit += val1 * 1000;
|
||||
subunt = i - 1;
|
||||
pc_del_talisman(sd, sd->talisman[i], i);
|
||||
}
|
||||
if (sd && sd->spiritcharm_type != CHARM_TYPE_NONE && sd->spiritcharm > 0) {
|
||||
val1 = sd->spiritcharm;
|
||||
val2 = sd->spiritcharm_type;
|
||||
limit = 6000 * val1;
|
||||
subunt = sd->spiritcharm_type - 1;
|
||||
pc_delspiritcharm(sd,sd->spiritcharm,sd->spiritcharm_type);
|
||||
}
|
||||
break;
|
||||
case HW_GRAVITATION:
|
||||
@ -14779,20 +14786,15 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
|
||||
case KO_HYOUHU_HUBUKI:
|
||||
case KO_KAZEHU_SEIRAN:
|
||||
case KO_DOHU_KOUKAI:
|
||||
{
|
||||
int ttype = skill_get_ele(skill_id, skill_lv);
|
||||
ARR_FIND(1, 5, i, sd->talisman[i] > 0 && i != ttype);
|
||||
if( sd->talisman[ttype] >= 10 ) {
|
||||
clif_skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0);
|
||||
if (sd->spiritcharm_type == skill_get_ele(skill_id,skill_lv) && sd->spiritcharm >= MAX_SPIRITCHARM) {
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KO_KAIHOU:
|
||||
case KO_ZENKAI:
|
||||
ARR_FIND(1, 6, i, sd->talisman[i] > 0);
|
||||
if( i > 4 ) {
|
||||
clif_skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0);
|
||||
if (sd->spiritcharm_type == CHARM_TYPE_NONE || sd->spiritcharm <= 0) {
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON_NONE,0);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -9614,7 +9614,10 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
break;
|
||||
case SC__ENERVATION:
|
||||
val2 = 20 + 10 * val1; // ATK Reduction
|
||||
if( sd ) pc_delspiritball(sd,sd->spiritball,0);
|
||||
if (sd) {
|
||||
pc_delspiritball(sd,sd->spiritball,0);
|
||||
pc_delspiritcharm(sd,sd->spiritcharm,sd->spiritcharm_type);
|
||||
}
|
||||
break;
|
||||
case SC__GROOMY:
|
||||
val2 = 20 + 10 * val1; // ASPD
|
||||
|
@ -3163,10 +3163,8 @@ int unit_free(struct block_list *bl, clr_type clrtype)
|
||||
guild_send_memberinfoshort(sd,0);
|
||||
pc_cleareventtimer(sd);
|
||||
pc_inventory_rental_clear(sd);
|
||||
pc_delspiritball(sd,sd->spiritball,1);
|
||||
|
||||
for(i = 1; i < 5; i++)
|
||||
pc_del_talisman(sd, sd->talisman[i], i);
|
||||
pc_delspiritball(sd, sd->spiritball, 1);
|
||||
pc_delspiritcharm(sd, sd->spiritcharm, sd->spiritcharm_type);
|
||||
|
||||
if( sd->reg ) { // Double logout already freed pointer fix... [Skotlex]
|
||||
aFree(sd->reg);
|
||||
|
Loading…
x
Reference in New Issue
Block a user