diff options
-rw-r--r-- | Changelog-Trunk.txt | 7 | ||||
-rw-r--r-- | src/map/clif.c | 66 | ||||
-rw-r--r-- | src/map/clif.h | 3 | ||||
-rw-r--r-- | src/map/map.h | 2 | ||||
-rw-r--r-- | src/map/skill.c | 24 | ||||
-rw-r--r-- | src/map/status.c | 21 |
6 files changed, 58 insertions, 65 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 23b19ff8b..11e3ad645 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,13 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. 2008/02/03 + * Fixes to Devotion (see topic:153345) [ultramage] + - removed totally fake Devotion packet from Marionette Control code + - fixed one devoted chars array management code bug which caused chars + to be included in the array multiple times, producing various problems + - the link will now re-display when coming into view range + - the link will no longer break if the devotee walks away, but instead, + if he receives damage while being out of range of Devotion * Added an iterator to map.h/c. [FlavioJS] Will be used instead of map_getallusers, which has problems with dangling pointers (returned array isn't updated). diff --git a/src/map/clif.c b/src/map/clif.c index 5dde04300..9a796b659 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -3384,7 +3384,9 @@ int clif_storageclose(struct map_session_data *sd) *------------------------------------------*/ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* dstsd) { - int len; + int gmlvl; + int i; + if(dstsd->chatID) { struct chat_data *cd; @@ -3400,10 +3402,17 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d clif_spiritball_single(sd->fd, dstsd); if((sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting. - (battle_config.disp_hpmeter && (len = pc_isGM(sd)) >= battle_config.disp_hpmeter && len >= pc_isGM(dstsd)) + (battle_config.disp_hpmeter && (gmlvl = pc_isGM(sd)) >= battle_config.disp_hpmeter && gmlvl >= pc_isGM(dstsd)) ) clif_hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp); + // display links to devoted chars for crusader + ARR_FIND( 0, 5, i, sd->devotion[i] == dstsd->bl.id ); + if( i < 5 ) clif_devotion(sd, sd); + // display links to devoted chars for others + ARR_FIND( 0, 5, i, dstsd->devotion[i] > 0 ); + if( i < 5 ) clif_devotion(dstsd, sd); + // pvp circle for duel [LuzZza] //if(dstsd->duel_group) // clif_specialeffect(&dstsd->bl, 159, 4); @@ -5283,7 +5292,7 @@ void clif_vendingreport(struct map_session_data* sd, int index, int amount) } /// Result of organizing a party. -/// S 00FA <result>.B +/// R 00FA <result>.B /// /// result=0 : opens party window and shows MsgStringTable[77]="party successfully organized" /// result=1 : MsgStringTable[78]="party name already exists" @@ -5888,49 +5897,26 @@ int clif_autospell(struct map_session_data *sd,int skilllv) } /*========================================== - * ディボーションの青い糸 + * Devotion's visual effect + * S 01cf <devoter id>.L { <devotee id>.L }[5] <max distance>.W *------------------------------------------*/ -int clif_devotion(struct map_session_data *sd) +void clif_devotion(struct map_session_data *sd, struct map_session_data *tsd) { unsigned char buf[56]; - int i,n; - - nullpo_retr(0, sd); - - WBUFW(buf,0)=0x1cf; - WBUFL(buf,2)=sd->bl.id; - for(i=0,n=0;i<5;i++) { - if (!sd->devotion[i]) - continue; - WBUFL(buf,6+4*n)=sd->devotion[i]; - n++; - } - for(;n<5;n++) - WBUFL(buf,6+4*n)=0; - - WBUFB(buf,26)=8; - WBUFB(buf,27)=0; - - clif_send(buf,packet_len(0x1cf),&sd->bl,AREA); - return 0; -} + int i; -int clif_marionette(struct block_list *src, struct block_list *target) -{ - unsigned char buf[56]; - int n; + nullpo_retv(sd); - WBUFW(buf,0)=0x1cf; - WBUFL(buf,2)=src->id; - for(n=0;n<5;n++) - WBUFL(buf,6+4*n)=0; - if (target) //The target goes on the second slot. - WBUFL(buf,6+4) = target->id; - WBUFB(buf,26)=8; - WBUFB(buf,27)=0; + WBUFW(buf,0) = 0x1cf; + WBUFL(buf,2) = sd->bl.id; + for( i = 0; i < 5; i++ ) + WBUFL(buf,6+4*i) = sd->devotion[i]; + WBUFW(buf,26) = skill_get_range2(&sd->bl,CR_DEVOTION,pc_checkskill(sd,CR_DEVOTION)); // ignored - clif_send(buf,packet_len(0x1cf),src,AREA); - return 0; + if( tsd ) + clif_send(buf,packet_len(0x1cf),&tsd->bl,SELF); + else + clif_send(buf,packet_len(0x1cf),&sd->bl,AREA); } /*========================================== diff --git a/src/map/clif.h b/src/map/clif.h index 8a0cd10a9..fd6ac02c3 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -225,8 +225,7 @@ void clif_skill_delunit(struct skill_unit *unit); void clif_01ac(struct block_list* bl); int clif_autospell(struct map_session_data *sd,int skilllv); -int clif_devotion(struct map_session_data *sd); -int clif_marionette(struct block_list *src, struct block_list *target); +void clif_devotion(struct map_session_data *sd, struct map_session_data *tsd); int clif_spiritball(struct map_session_data *sd); int clif_combo_delay(struct block_list *src,int wait); int clif_bladestop(struct block_list *src,struct block_list *dst,int bool_); diff --git a/src/map/map.h b/src/map/map.h index 81b83257c..af797b127 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -728,7 +728,7 @@ struct map_session_data { unsigned char mission_count; //Stores the bounty kill count for TK_MISSION short mission_mobid; //Stores the target mob_id for TK_MISSION int die_counter; //Total number of times you've died - int devotion[5]; //Stores the char IDs of chars devoted to. + int devotion[5]; //Stores the account IDs of chars devoted to. int reg_num; //Number of registries (type numeric) int regstr_num; //Number of registries (type string) diff --git a/src/map/skill.c b/src/map/skill.c index d579cff5e..5bd4f3aed 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -3152,7 +3152,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if (!sc->data[type] && !tsc->data[type2]) { sc_start(src,type,100,bl->id,skill_get_time(skillid,skilllv)); sc_start(bl,type2,100,src->id,skill_get_time(skillid,skilllv)); - clif_marionette(src, bl); clif_skill_nodamage(src,bl,skillid,skilllv,1); } else if (sc->data[type] && tsc->data[type2] && @@ -3444,6 +3443,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case CR_DEVOTION: if(sd && dstsd) { + int count = min(skilllv, 5); int lv = sd->status.base_level - dstsd->status.base_level; if (lv < 0) lv = -lv; if (lv > battle_config.devotion_level_difference || @@ -3453,18 +3453,24 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in map_freeblock_unlock(); return 1; } - //Look for an empty slot (or reuse in case you cast it twice in the same char. [Skotlex] - for (i = 0; i < skilllv && i < 5 && sd->devotion[i]!=bl->id && sd->devotion[i]; i++); - if (i == skilllv) - { - clif_skill_fail(sd,skillid,0,0); - map_freeblock_unlock(); - return 1; + + // check if the char isn't devoted already + ARR_FIND( 0, count, i, sd->devotion[i] == bl->id ); + if( i == count ) + {// not there, find first empty slot + ARR_FIND( 0, count, i, sd->devotion[i] == 0 ); + if( i == count ) + {// all slots full, fail + clif_skill_fail(sd,skillid,0,0); + map_freeblock_unlock(); + return 1; + } } + sd->devotion[i] = bl->id; clif_skill_nodamage(src,bl,skillid,skilllv, sc_start4(bl,type,100,src->id,i,skill_get_range2(src,skillid,skilllv),skill_get_time2(skillid, skilllv),1000)); - clif_devotion(sd); + clif_devotion(sd,NULL); } else if (sd) diff --git a/src/map/status.c b/src/map/status.c index 748be46ca..6ea757d2b 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -647,7 +647,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s if ((sce=sc->data[SC_DEVOTION]) && src && battle_getcurrentskill(src) != PA_PRESSURE) { //Devotion prevents any of the other ailments from ending. struct map_session_data *sd2 = map_id2sd(sce->val1); - if (sd2 && sd2->devotion[sce->val2] == target->id) + if (sd2 && sd2->devotion[sce->val2] == target->id && check_distance_bl(target, &sd2->bl, sce->val3)) { clif_damage(&sd2->bl, &sd2->bl, gettick(), 0, 0, hp, 0, 0, 0); status_fix_damage(NULL, &sd2->bl, hp, 0); @@ -6322,7 +6322,7 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) if (md) { md->devotion[sce->val2] = 0; - clif_devotion(md); + clif_devotion(md,NULL); } //Remove inherited status [Skotlex] if (sc->data[SC_AUTOGUARD]) @@ -6333,8 +6333,8 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) status_change_end(bl,SC_REFLECTSHIELD,-1); if (sc->data[SC_ENDURE]) status_change_end(bl,SC_ENDURE,-1); - break; } + break; case SC_BLADESTOP: if(sce->val4) { @@ -6431,8 +6431,6 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid) status_change_end(pbl, type2, -1); } } - if (type == SC_MARIONETTE) - clif_marionette(bl, 0); //Clear effect. break; case SC_BERSERK: @@ -6906,14 +6904,11 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) break; case SC_DEVOTION: - { //Check range and timeleft to preserve status [Skotlex] - //This implementation won't work for mobs because of map_id2sd, but it's a small cost in exchange of the speed of map_id2sd over map_id2bl - struct map_session_data *md = map_id2sd(sce->val1); - if (md && check_distance_bl(bl, &md->bl, sce->val3) && (sce->val4-=1000)>0) - { - sc_timer_next(1000+tick, status_change_timer, bl->id, data); - return 0; - } + //FIXME: use normal status duration instead of a looping timer + if( (sce->val4 -= 1000) > 0 ) + { + sc_timer_next(1000+tick, status_change_timer, bl->id, data); + return 0; } break; |