summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/map/battle.c42
-rw-r--r--src/map/pc.c19
-rw-r--r--src/map/pc.h1
-rw-r--r--src/map/skill.c45
-rw-r--r--src/map/skill.h1
-rw-r--r--src/map/status.c13
6 files changed, 67 insertions, 54 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index 3b030a5d0..a6507dacf 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -3161,28 +3161,31 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) )
status->change_spread(bl, src); // Deadly infect attacked side
+
+ if ( sd && damage > 0 && (sce = sc->data[SC_GENTLETOUCH_ENERGYGAIN]) ) {
+ if ( rnd() % 100 < sce->val2 )
+ pc->addspiritball(sd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(sd, 0));
+ }
}
//SC effects from caster side.
- sc = status->get_sc(src);
-
- if (sc && sc->count) {
- if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
+ if (tsc && tsc->count) {
+ if( tsc->data[SC_INVINCIBLE] && !tsc->data[SC_INVINCIBLEOFF] )
damage += damage * 75 / 100;
// [Epoque]
if (bl->type == BL_MOB) {
int i;
- if ( ((sce=sc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) ||
- ((sce=sc->data[SC_MANU_MATK]) && (flag&BF_MAGIC))
+ if ( ((sce=tsc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) ||
+ ((sce=tsc->data[SC_MANU_MATK]) && (flag&BF_MAGIC))
)
for (i=0;ARRAYLENGTH(mob->manuk)>i;i++)
if (((TBL_MOB*)bl)->class_==mob->manuk[i]) {
damage += damage * sce->val1 / 100;
break;
}
- if ( ((sce=sc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) ||
- ((sce=sc->data[SC_SPL_MATK]) && (flag&BF_MAGIC))
+ if ( ((sce=tsc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) ||
+ ((sce=tsc->data[SC_SPL_MATK]) && (flag&BF_MAGIC))
)
for (i=0;ARRAYLENGTH(mob->splendide)>i;i++)
if (((TBL_MOB*)bl)->class_==mob->splendide[i]) {
@@ -3199,14 +3202,19 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
sc_start(src,bl,tsc->data[SC_POISONINGWEAPON]->val2,rate,tsc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000);
}
}
- if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) )
+ if( tsc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * tsc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) )
status->change_spread(src, bl);
- if (sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0)
+ if (tsc->data[SC_SHIELDSPELL_REF] && tsc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0)
skill->break_equip(bl,EQP_ARMOR,10000,BCT_ENEMY );
- if (sc->data[SC_STYLE_CHANGE] && rnd()%2) {
+ if (tsc->data[SC_STYLE_CHANGE] && rnd()%2) {
TBL_HOM *hd = BL_CAST(BL_HOM,bl);
if (hd) homun->addspiritball(hd, 10);
}
+ if ( src->type == BL_PC && damage > 0 && (sce = tsc->data[SC_GENTLETOUCH_ENERGYGAIN]) ) {
+ struct map_session_data *tsd = (struct map_session_data *)src;
+ if ( tsd && rnd() % 100 < sce->val2 )
+ pc->addspiritball(tsd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(tsd, 0));
+ }
}
/* no data claims these settings affect anything other than players */
if( damage && sd && bl->type == BL_PC ) {
@@ -6020,18 +6028,6 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
return ATK_DEF;
return ATK_MISS;
}
- if( sc->data[SC_GENTLETOUCH_ENERGYGAIN] ) {
- if( sd && rnd()%100 < 10 + 5 * sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1)
- pc->addspiritball(sd,
- skill->get_time(MO_CALLSPIRITS, sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1),
- sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1);
- }
- if( tsc && tsc->data[SC_GENTLETOUCH_ENERGYGAIN] ) {
- if( tsd && rnd()%100 < 10 + 5 * tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1)
- pc->addspiritball(tsd,
- skill->get_time(MO_CALLSPIRITS, tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1),
- tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1);
- }
if( tsc && tsc->data[SC_MTF_MLEATKED] && rnd()%100 < 20 )
clif->skill_nodamage(target, target, SM_ENDURE, 5,
diff --git a/src/map/pc.c b/src/map/pc.c
index 5fc6469f3..4c97a4fef 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -174,6 +174,24 @@ int pc_spiritball_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
+/**
+* Get the possible number of spiritball that a player can call.
+* @param sd the affected player structure
+* @param min the minimum number of spiritball regardless the level of MO_CALLSPIRITS
+* @retval total number of spiritball
+**/
+int pc_getmaxspiritball(struct map_session_data *sd, int min) {
+ nullpo_ret(sd);
+ int result = pc->checkskill(sd, MO_CALLSPIRITS);
+ if ( min && result < min )
+ result = min;
+ else if ( sd->sc.data[SC_RAISINGDRAGON] )
+ result += sd->sc.data[SC_RAISINGDRAGON]->val1;
+ if ( result > MAX_SPIRITBALL )
+ result = MAX_SPIRITBALL;
+ return result;
+}
+
int pc_addspiritball(struct map_session_data *sd,int interval,int max)
{
int tid, i;
@@ -11247,6 +11265,7 @@ void pc_defaults(void) {
pc->addfame = pc_addfame;
pc->famerank = pc_famerank;
pc->set_hate_mob = pc_set_hate_mob;
+ pc->getmaxspiritball = pc_getmaxspiritball;
pc->readdb = pc_readdb;
pc->map_day_timer = map_day_timer; // by [yor]
diff --git a/src/map/pc.h b/src/map/pc.h
index c3bf1e4cc..5716ed30a 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -957,6 +957,7 @@ END_ZEROED_BLOCK; /* End */
int (*addspiritball) (struct map_session_data *sd,int interval,int max);
int (*delspiritball) (struct map_session_data *sd,int count,int type);
+ int (*getmaxspiritball) (struct map_session_data *sd, int min);
void (*addfame) (struct map_session_data *sd,int count);
unsigned char (*famerank) (int char_id, int job);
int (*set_hate_mob) (struct map_session_data *sd, int pos, struct block_list *bl);
diff --git a/src/map/skill.c b/src/map/skill.c
index 55fcc6d03..5498ed07d 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -6133,22 +6133,17 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case MO_CALLSPIRITS:
if(sd) {
- int limit = skill_lv;
- if( sd->sc.data[SC_RAISINGDRAGON] )
- limit += sd->sc.data[SC_RAISINGDRAGON]->val1;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),limit);
+ pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), pc->getmaxspiritball(sd, 0));
}
break;
case CH_SOULCOLLECT:
if(sd) {
- int limit = 5, i;
- if( sd->sc.data[SC_RAISINGDRAGON] )
- limit += sd->sc.data[SC_RAISINGDRAGON]->val1;
+ int i, limit = pc->getmaxspiritball(sd, 5);
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- for (i = 0; i < limit; i++)
- pc->addspiritball(sd,skill->get_time(skill_id,skill_lv),limit);
+ for ( i = 0; i < limit; i++ )
+ pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), limit);
}
break;
@@ -9010,13 +9005,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case SR_RAISINGDRAGON:
- if( sd ) {
- short max = 5 + skill_lv;
- int i;
+ if ( sd ) {
+ int i, max;
sc_start(src, bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill->get_time(skill_id, skill_lv));
- for( i = 0; i < max; i++ ) // Don't call more than max available spheres.
- pc->addspiritball(sd, skill->get_time(skill_id, skill_lv), max);
- clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv)));
+ clif->skill_nodamage(src, bl, skill_id, skill_lv,
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
+ max = pc->getmaxspiritball(sd, 0);
+ for ( i = 0; i < max; i++ )
+ pc->addspiritball(sd, skill->get_time(MO_CALLSPIRITS, skill_lv), max);
}
break;
@@ -9042,12 +9038,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SR_POWERVELOCITY:
if( !dstsd )
break;
- if( sd && dstsd->spiritball <= 5 ) {
- int i;
- for(i = 0; i <= 5; i++) {
- pc->addspiritball(dstsd, skill->get_time(MO_CALLSPIRITS, pc->checkskill(sd,MO_CALLSPIRITS)), i);
- pc->delspiritball(sd, sd->spiritball, 0);
+ if ( sd && (dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER ) {
+ int i, max = pc->getmaxspiritball(dstsd, 5);
+ for ( i = 0; i < max; i++ ) {
+ pc->addspiritball(dstsd, skill->get_time(MO_CALLSPIRITS, 1), max);
}
+ pc->delspiritball(sd, sd->spiritball, 0);
}
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
break;
@@ -11979,8 +11975,6 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
break;
default:
skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
- if ( sg->interval == skill->get_time(sg->skill_id, sg->skill_lv) )
- sg->unit_id = UNT_USED_TRAPS; // remove unit once it does its job once.
}
break;
@@ -15956,7 +15950,8 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
su->group=group;
su->alive=1;
su->val1=val1;
- su->val2=val2;
+ su->val2 = val2;
+ su->prev = 0;
idb_put(skill->unit_db, su->bl.id, su);
map->addiddb(&su->bl);
@@ -16550,7 +16545,7 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
dissonance = skill->dance_switch(su, 0);
- if( su->range >= 0 && group->interval != -1 ) {
+ if( su->range >= 0 && group->interval != -1 && su->bl.id != su->prev) {
if( battle_config.skill_wall_check )
map->foreachinshootrange(skill->unit_timer_sub_onplace, bl, su->range, group->bl_flag, bl,tick);
else
@@ -16566,6 +16561,8 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
group->bl_flag= BL_NUL;
}
}
+ if ( group->limit == group->interval )
+ su->prev = su->bl.id;
}
if( dissonance ) skill->dance_switch(su, 1);
diff --git a/src/map/skill.h b/src/map/skill.h
index c5341e9bd..bbf5b5458 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -1732,6 +1732,7 @@ struct skill_unit {
int limit;
int val1,val2;
short alive,range;
+ int prev;
};
struct skill_unit_group_tickset {
diff --git a/src/map/status.c b/src/map/status.c
index 8d228c763..cb9b67299 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -8806,6 +8806,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
else
val2 = val2 / 4 * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level]
break;
+ case SC_GENTLETOUCH_ENERGYGAIN:
+ val2 = 10 + 5 * val1;
+ break;
case SC_PYROTECHNIC_OPTION:
val2 = 60;
break;
@@ -10127,15 +10130,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
map->foreachinrange(status->change_timer_sub, bl, battle_config.area_size,BL_CHAR, bl, sce, SC_CURSEDCIRCLE_TARGET, timer->gettick());
break;
case SC_RAISINGDRAGON:
- if( sd && sce->val2 && !pc_isdead(sd) ) {
+ if ( sd && sce->val2 && !pc_isdead(sd) ) {
int i;
- i = min(sd->spiritball,5);
- pc->delspiritball(sd, sd->spiritball, 0);
+ if ( (i = (sd->spiritball - 5)) > 0 )
+ pc->delspiritball(sd, i, 0);
status_change_end(bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
- while( i > 0 ) {
- pc->addspiritball(sd, skill->get_time(MO_CALLSPIRITS, pc->checkskill(sd,MO_CALLSPIRITS)), 5);
- --i;
- }
}
break;
case SC_CURSEDCIRCLE_TARGET: