Skip to content

Instantly share code, notes, and snippets.

@lighta
Created December 31, 2015 09:37
Show Gist options
  • Save lighta/a5787fcb795028714792 to your computer and use it in GitHub Desktop.
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)
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