Created
December 31, 2015 09:37
-
-
Save lighta/a5787fcb795028714792 to your computer and use it in GitHub Desktop.
* cf issue #722, devotion code Move devotion check_distance to map_moveblock check, Extend battle_check_devotion and replace duplicate code with it Add skill_foundDevotionPlace meant to search for a valid place for new devotion, (small performance upd and avoid duplicate)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/map/battle.c b/src/map/battle.c | |
index 0d87c16..1d03c01 100644 | |
--- a/src/map/battle.c | |
+++ b/src/map/battle.c | |
@@ -313,12 +313,14 @@ int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src, | |
sc = status_get_sc(target); | |
- if (sc && sc->data[SC_DEVOTION] && sc->data[SC_DEVOTION]->val1) | |
- d_tbl = map_id2bl(sc->data[SC_DEVOTION]->val1); | |
- | |
- if( d_tbl && check_distance_bl(target, d_tbl, sc->data[SC_DEVOTION]->val3) && | |
- damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD ) | |
- damage = 0; | |
+ switch (skill_id) { | |
+ case PA_PRESSURE: | |
+ case CR_REFLECTSHIELD: | |
+ break; //list of skill not affected by devotion (@TODO move me in inf3) | |
+ default: | |
+ if(damage > 0 && battle_check_devotion(target,0) != NULL ) damage = 0; | |
+ } | |
+ | |
if ( !battle_config.delay_battle_damage || amotion <= 1 ) { | |
map_freeblock_lock(); | |
@@ -1054,10 +1056,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam | |
delay = 100; | |
if (sd && pc_issit(sd)) | |
pc_setstand(sd, true); | |
- if( sce_d && (d_bl = map_id2bl(sce_d->val1)) && | |
- ((d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id) || | |
- (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce_d->val2] == bl->id)) && | |
- check_distance_bl(bl,d_bl,sce_d->val3) ) | |
+ if( (d_bl=battle_check_devotion(bl,0)) != NULL ) | |
{ //If player is target of devotion, show guard effect on the devotion caster rather than the target | |
clif_skill_nodamage(d_bl,d_bl,CR_AUTOGUARD,sce->val1,1); | |
unit_set_walkdelay(d_bl,gettick(),delay,1); | |
@@ -1205,22 +1204,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam | |
status_change_end(bl,SC_VOICEOFSIREN,INVALID_TIMER); | |
} | |
- if( sc->data[SC_DEVOTION] ) { | |
- struct status_change_entry *sce_d = sc->data[SC_DEVOTION]; | |
- struct block_list *d_bl = map_id2bl(sce_d->val1); | |
- | |
- if( d_bl && | |
- ((d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id) || | |
- (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce_d->val2] == bl->id)) && | |
- check_distance_bl(bl,d_bl,sce_d->val3) ) | |
- { | |
- struct status_change *d_sc = status_get_sc(d_bl); | |
- | |
- if( d_sc && d_sc->data[SC_DEFENDER] && (flag&(BF_LONG|BF_MAGIC)) == BF_LONG && skill_id != ASC_BREAKER && skill_id != CR_ACIDDEMONSTRATION && skill_id != NJ_ZENYNAGE && skill_id != KO_MUCHANAGE ) | |
- damage -= damage * d_sc->data[SC_DEFENDER]->val2 / 100; | |
- } | |
- } | |
- | |
// Damage reductions | |
// Assumptio doubles the def & mdef on RE mode, otherwise gives a reduction on the final damage. [Igniz] | |
#ifndef RENEWAL | |
@@ -1231,9 +1214,18 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam | |
damage >>= 1; //Receive 50% damage | |
} | |
#endif | |
- | |
- if (sc->data[SC_DEFENDER] && (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) | |
- damage -= damage * sc->data[SC_DEFENDER]->val2 / 100; | |
+ if (sc->data[SC_DEFENDER] && (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)){ | |
+ switch(skill_id){ | |
+ case ASC_BREAKER: | |
+ case CR_ACIDDEMONSTRATION: | |
+ case NJ_ZENYNAGE: | |
+ case KO_MUCHANAGE: | |
+ break; //list of skill that are not reduce | |
+ //tmp move those list into inf | |
+ default: | |
+ damage -= damage * sc->data[SC_DEFENDER]->val2 / 100; | |
+ } | |
+ } | |
if(sc->data[SC_ADJUSTMENT] && (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) | |
damage -= damage * 20 / 100; | |
@@ -4799,16 +4791,28 @@ struct Damage battle_calc_attack_left_right_hands(struct Damage wd, struct block | |
/** | |
* Check if bl is devoted by someone | |
-* @param bl | |
-* @return 'd_bl' if devoted or NULL if not devoted | |
+* @param in bl : player to check if his devoted | |
+* @param in devotiontype_check : | |
+* 0 = basic just devo | |
+* 1 = with rdammage % | |
+* 2 = rdamage_skill_only | |
+* @return 'd_bl'=devoter or NULL | |
*/ | |
-struct block_list *battle_check_devotion(struct block_list *bl) { | |
+struct block_list* battle_check_devotion(struct block_list *bl, uint32 devotiontype_check) { | |
struct block_list *d_bl = NULL; | |
- | |
- if (battle_config.devotion_rdamage && battle_config.devotion_rdamage > rnd() % 100) { | |
- struct status_change *sc = status_get_sc(bl); | |
- if (sc && sc->data[SC_DEVOTION]) | |
- d_bl = map_id2bl(sc->data[SC_DEVOTION]->val1); | |
+ struct status_change *sc = status_get_sc(bl); | |
+ if (sc && sc->data[SC_DEVOTION]) | |
+ d_bl = map_id2bl(sc->data[SC_DEVOTION]->val1); | |
+ switch (devotiontype_check) { | |
+ case 0: break; | |
+ case 1: | |
+ if (!battle_config.devotion_rdamage || battle_config.devotion_rdamage <= rnd() % 100) | |
+ d_bl = NULL; | |
+ break; | |
+ case 2: | |
+ if (!battle_config.devotion_rdamage_skill_only) | |
+ d_bl = NULL; | |
+ break; | |
} | |
return d_bl; | |
} | |
@@ -4834,8 +4838,7 @@ struct Damage battle_calc_attack_gvg_bg(struct Damage wd, struct block_list *src | |
rdamage = battle_calc_return_damage(target, src, &damage, wd.flag, skill_id, false); | |
if( rdamage > 0 ) { //Item reflect gets calculated before any mapflag reducing is applicated | |
- struct block_list *d_bl = battle_check_devotion(src); | |
- | |
+ struct block_list *d_bl = battle_check_devotion(src,1); | |
rdelay = clif_damage(src, (!d_bl) ? src : d_bl, tick, wd.amotion, sstatus->dmotion, rdamage, 1, DMG_ENDURE, 0); | |
if( tsd ) | |
battle_drain(tsd, src, rdamage, rdamage, sstatus->race, sstatus->class_, is_infinite_defense(src,wd.flag)); | |
@@ -5096,7 +5099,7 @@ void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* sr | |
// Calculate skill reflect damage separately | |
rdamage = battle_calc_return_damage(target, src, &damage, wd->flag, skill_id,true); | |
if( rdamage > 0 ) { | |
- struct block_list *d_bl = battle_check_devotion(src); | |
+ struct block_list *d_bl = battle_check_devotion(src,1); | |
if( attack_type == BF_WEAPON && tsc->data[SC_REFLECTDAMAGE] ) // Don't reflect your own damage (Grand Cross) | |
map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd->amotion,sstatus->dmotion,rdamage,wd->flag); | |
@@ -6661,16 +6664,8 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i | |
rdamage = i64max(rdamage,1); | |
} else if( status_reflect && sc && sc->count ) { | |
if( sc->data[SC_REFLECTSHIELD] ) { | |
- struct status_change_entry *sce_d; | |
- struct block_list *d_bl = NULL; | |
- | |
- if( (sce_d = sc->data[SC_DEVOTION]) && (d_bl = map_id2bl(sce_d->val1)) && | |
- ((d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id) || | |
- (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce_d->val2] == bl->id)) ) | |
- { //Don't reflect non-skill attack if has SC_REFLECTSHIELD from Devotion bonus inheritance | |
- if( (!skill_id && battle_config.devotion_rdamage_skill_only && sc->data[SC_REFLECTSHIELD]->val4) || | |
- !check_distance_bl(bl,d_bl,sce_d->val3) ) | |
- return 0; | |
+ if(!skill_id && battle_check_devotion(bl,2) && sc->data[SC_REFLECTSHIELD]->val4) { //Don't reflect non-skill attack if has SC_REFLECTSHIELD from Devotion bonus inheritance | |
+ return 0; | |
} | |
} | |
if( sc->data[SC_REFLECTDAMAGE] && !(skill_get_inf2(skill_id)&INF2_TRAP)) { | |
@@ -7117,20 +7112,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t | |
} else | |
battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion, true); | |
if( tsc ) { | |
- if( tsc->data[SC_DEVOTION] ) { | |
- struct status_change_entry *sce = tsc->data[SC_DEVOTION]; | |
- struct block_list *d_bl = map_id2bl(sce->val1); | |
- | |
- if( d_bl && ( | |
- (d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == target->id) || | |
- (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id) | |
- ) && check_distance_bl(target, d_bl, sce->val3) ) | |
- { | |
- clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0); | |
- status_fix_damage(NULL, d_bl, damage, 0); | |
- } | |
- else | |
- status_change_end(target, SC_DEVOTION, INVALID_TIMER); | |
+ struct block_list *e_bl = NULL; | |
+ if(e_bl =battle_check_devotion(target,0) ) { | |
+ clif_damage(e_bl, e_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0); | |
+ status_fix_damage(NULL, e_bl, damage, 0); | |
} | |
if( target->type == BL_PC && (wd.flag&BF_SHORT) && tsc->data[SC_CIRCLE_OF_FIRE_OPTION] ) { | |
struct elemental_data *ed = ((TBL_PC*)target)->ed; | |
diff --git a/src/map/battle.h b/src/map/battle.h | |
index 20f5852..de5c8c2 100644 | |
--- a/src/map/battle.h | |
+++ b/src/map/battle.h | |
@@ -609,4 +609,6 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int | |
**/ | |
int battle_damage_area( struct block_list *bl, va_list ap); | |
+struct block_list* battle_check_devotion(struct block_list *bl, uint32 devotiontype_check); | |
+ | |
#endif /* _BATTLE_H_ */ | |
diff --git a/src/map/clif.c b/src/map/clif.c | |
index c55f777..b411279 100644 | |
--- a/src/map/clif.c | |
+++ b/src/map/clif.c | |
@@ -4507,7 +4507,7 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d | |
if( i < MAX_DEVOTION ) | |
clif_devotion(&dstsd->bl, sd); | |
// display link (dstsd - crusader) to sd | |
- if( dstsd->sc.data[SC_DEVOTION] && (d_bl = map_id2bl(dstsd->sc.data[SC_DEVOTION]->val1)) != NULL ) | |
+ if( (d_bl=battle_check_devotion(&dstsd->bl, 0)) != NULL ) | |
clif_devotion(d_bl, sd); | |
} | |
diff --git a/src/map/map.c b/src/map/map.c | |
index 223ca65..b79aa47 100644 | |
--- a/src/map/map.c | |
+++ b/src/map/map.c | |
@@ -418,12 +418,29 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) | |
skill_unit_move(bl,tick,3); | |
- if( bl->type == BL_PC && ((TBL_PC*)bl)->shadowform_id ) {//Shadow Form Target Moving | |
+ if( bl->type == BL_PC ) { | |
struct block_list *d_bl; | |
- if( (d_bl = map_id2bl(((TBL_PC*)bl)->shadowform_id)) == NULL || !check_distance_bl(bl,d_bl,10) ) { | |
- if( d_bl ) | |
- status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER); | |
- ((TBL_PC*)bl)->shadowform_id = 0; | |
+ TBL_PC *bsd = (TBL_PC*)bl; | |
+ if(bsd->shadowform_id ){ //Shadow Form Target Moving | |
+ if( (d_bl = map_id2bl(bsd->shadowform_id)) == NULL || !check_distance_bl(bl,d_bl,10) ) { | |
+ if( d_bl ) | |
+ status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER); | |
+ bsd->shadowform_id = 0; | |
+ } | |
+ } | |
+ // (d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == target->id) || | |
+ // (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id) | |
+ if(bsd->devotion) { //we are a devoter | |
+ int i; | |
+ for (i = 0; i < MAX_DEVOTION; i++) { // See if there are devoted characters, and pass the status to them. [Skotlex] | |
+ if (bsd->devotion[i]) { | |
+ if ((d_bl = map_id2bl(bsd->devotion[i])) == NULL || !check_distance_bl(bl, d_bl, 10)) { | |
+ if (d_bl) | |
+ status_change_end(d_bl, SC_DEVOTION, INVALID_TIMER); | |
+ } | |
+ bsd->devotion[i] = 0; //free up space | |
+ } | |
+ } | |
} | |
} | |
@@ -449,6 +466,12 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) | |
status_change_end(bl,SC__SHADOWFORM,INVALID_TIMER); | |
} | |
+ if(sc->data[SC_DEVOTION]){ //we are under devotion | |
+ struct block_list *d_bl; | |
+ if( (d_bl = map_id2bl(sc->data[SC_DEVOTION]->val2)) == NULL || !check_distance_bl(bl,d_bl, sc->data[SC_DEVOTION]->val3) ) | |
+ status_change_end(bl,SC_DEVOTION,INVALID_TIMER); | |
+ } | |
+ | |
if (sc->data[SC_PROPERTYWALK] | |
&& sc->data[SC_PROPERTYWALK]->val3 < skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) | |
&& map_find_skill_unit_oncell(bl,bl->x,bl->y,SO_ELECTRICWALK,NULL,0) == NULL | |
diff --git a/src/map/skill.c b/src/map/skill.c | |
index 852fdd8..11f0fba 100755 | |
--- a/src/map/skill.c | |
+++ b/src/map/skill.c | |
@@ -911,6 +911,18 @@ struct s_skill_nounit_layout* skill_get_nounit_layout(uint16 skill_id, uint16 sk | |
return &skill_nounit_layout[0]; | |
} | |
+//search if we have place for a new devo. | |
+//search if we have already that target into our devo list | |
+//return -1 no place found, i=idx of free place in array | |
+int skill_foundDevotionPlace(TBL_PC* sd, struct block_list *bl, uint16 skill_id, uint16 skill_lv){ | |
+ int8 i, j=-1, count = min(skill_lv, MAX_DEVOTION); | |
+ //if count => min=1,com=16,max=20 vs min=2,com=14,max=22 with 2 ARR_FIND | |
+ for(i=0; sd->devotion[i] != bl->id && i<count;++i){ | |
+ if(j==-1 && sd->devotion[i] == 0) j=i; | |
+ } | |
+ return j; //-1 or idx | |
+} | |
+ | |
/*========================================== | |
* Add effect to skill when hit succesfully target | |
*------------------------------------------*/ | |
@@ -3349,13 +3361,8 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * | |
} | |
if( tsc && tsc->data[SC_DEVOTION] && skill_id != PA_PRESSURE && skill_id != HW_GRAVITATION ) { | |
- struct status_change_entry *sce = tsc->data[SC_DEVOTION]; | |
- struct block_list *d_bl = map_id2bl(sce->val1); | |
- | |
- if( d_bl && ( | |
- (d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id) || | |
- (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == bl->id) | |
- ) && check_distance_bl(bl, d_bl, sce->val3) ) | |
+ struct block_list *d_bl = map_id2bl(tsc->data[SC_DEVOTION]->val1); | |
+ if(d_bl) | |
{ | |
if(!rmdamage){ | |
clif_damage(d_bl,d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0); | |
@@ -3372,7 +3379,6 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * | |
} | |
} | |
else { | |
- status_change_end(bl, SC_DEVOTION, INVALID_TIMER); | |
if( !dmg.amotion ) | |
status_fix_damage(src,bl,damage,dmg.dmotion); | |
} | |
@@ -6540,19 +6546,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui | |
count = (sd)? min(skill_lv,MAX_DEVOTION) : 1; // Mercenary only can Devote owner | |
if( sd ) | |
{ // Player Devoting Player | |
- ARR_FIND(0, count, i, sd->devotion[i] == bl->id ); | |
- if( i == count ) | |
- { | |
- ARR_FIND(0, count, i, sd->devotion[i] == 0 ); | |
- if( i == count ) | |
- { // No free slots, skill Fail | |
- clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); | |
- map_freeblock_unlock(); | |
- return 1; | |
- } | |
+ if (-1 == skill_foundDevotionPlace(sd, bl, skill_id, skill_lv)) { //no place found | |
+ clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); | |
+ map_freeblock_unlock(); | |
+ return 1; | |
} | |
- | |
- sd->devotion[i] = bl->id; | |
+ else sd->devotion[i] = bl->id; | |
} | |
else | |
mer->devotion_flag = 1; // Mercenary Devoting Owner | |
diff --git a/src/map/skill.h b/src/map/skill.h | |
index 4d13db0..ea1f476 100644 | |
--- a/src/map/skill.h | |
+++ b/src/map/skill.h | |
@@ -2075,6 +2075,8 @@ bool skill_is_combo(uint16 skill_id); | |
void skill_combo_toogle_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); | |
+int skill_foundDevotionPlace(TBL_PC* sd, struct block_list *bl, uint16 skill_id, uint16 skill_lv); | |
+ | |
#ifdef ADJUST_SKILL_DAMAGE | |
/// Skill Damage target | |
enum e_skill_damage_caster { | |
diff --git a/src/map/status.c b/src/map/status.c | |
index 9847da8..3afc41e 100644 | |
--- a/src/map/status.c | |
+++ b/src/map/status.c | |
@@ -9039,11 +9039,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty | |
break; | |
case SC_DEFENDER: | |
- if (!(flag&SCSTART_NOAVOID)) { | |
- val2 = 5 + 15*val1; // Damage reduction | |
- val3 = 0; // Unused, previously speed adjustment | |
- val4 = 250 - 50*val1; // Aspd adjustment | |
+ val2 = 5 + 15*val1; // Damage reduction | |
+ val3 = 0; // Unused, previously speed adjustment | |
+ val4 = 250 - 50*val1; // Aspd adjustment | |
+ if (!(flag&SCSTART_NOAVOID)) { | |
if (sd) { | |
struct map_session_data *tsd; | |
int i; | |
diff --git a/src/map/unit.c b/src/map/unit.c | |
index a983355..cb8b5f9 100644 | |
--- a/src/map/unit.c | |
+++ b/src/map/unit.c | |
@@ -1643,15 +1643,9 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui | |
break; | |
case CR_DEVOTION: | |
if (target->type == BL_PC) { | |
- uint8 i = 0, count = min(skill_lv, MAX_DEVOTION); | |
- | |
- ARR_FIND(0, count, i, sd->devotion[i] == target_id); | |
- if (i == count) { | |
- ARR_FIND(0, count, i, sd->devotion[i] == 0); | |
- if (i == count) { // No free slots, skill Fail | |
- clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); | |
- return 0; | |
- } | |
+ if (-1 == skill_foundDevotionPlace(sd, target, skill_id, skill_lv)) { | |
+ clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); | |
+ return 0; | |
} | |
} | |
break; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment