summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt7
-rw-r--r--src/map/clif.c66
-rw-r--r--src/map/clif.h3
-rw-r--r--src/map/map.h2
-rw-r--r--src/map/skill.c24
-rw-r--r--src/map/status.c21
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;