summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzephyrus <zephyrus@54d463be-8e91-2dee-dedb-b68131a5f0ec>2008-08-31 18:37:00 +0000
committerzephyrus <zephyrus@54d463be-8e91-2dee-dedb-b68131a5f0ec>2008-08-31 18:37:00 +0000
commit690ef2ae18deedd44bf4670eaf751c3888cb5a37 (patch)
treeb062e4bbb763f3a1cec82ed85e84ceb8550f256d
parentf1f46c5b4ba04d590ff2ffbf28d84c3888ff3399 (diff)
downloadhercules-690ef2ae18deedd44bf4670eaf751c3888cb5a37.tar.gz
hercules-690ef2ae18deedd44bf4670eaf751c3888cb5a37.tar.bz2
hercules-690ef2ae18deedd44bf4670eaf751c3888cb5a37.tar.xz
hercules-690ef2ae18deedd44bf4670eaf751c3888cb5a37.zip
* More mercenary updates.
- Implemented Mercenary Die, Damage, Run Away when master dies. - Log mercenary damage and gives exp to Master. - Some little bugs. * Fixed Bubble Gums effect works on mvp_sd not sd (according to Doddler). NOTE: Now you can summon a mercenary, make it attack (not skills), follow you even on map change. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13158 54d463be-8e91-2dee-dedb-b68131a5f0ec
-rw-r--r--src/map/clif.c77
-rw-r--r--src/map/clif.h1
-rw-r--r--src/map/mercenary.c16
-rw-r--r--src/map/mercenary.h2
-rw-r--r--src/map/mob.c127
-rw-r--r--src/map/pc.c29
-rw-r--r--src/map/status.c6
-rw-r--r--src/map/unit.c63
8 files changed, 197 insertions, 124 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index 674770e4a..c56fc3f26 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -7881,19 +7881,28 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
}
//homunculus [blackhole89]
- if(merc_is_hom_active(sd->hd)) {
+ if( merc_is_hom_active(sd->hd) )
+ {
map_addblock(&sd->hd->bl);
clif_spawn(&sd->hd->bl);
clif_send_homdata(sd,0,0);
clif_hominfo(sd,sd->hd,1);
clif_hominfo(sd,sd->hd,0); //for some reason, at least older clients want this sent twice
clif_homskillinfoblock(sd);
- if (battle_config.hom_setting&0x8)
+ if( battle_config.hom_setting&0x8 )
status_calc_bl(&sd->hd->bl, SCB_SPEED); //Homunc mimic their master's speed on each map change
- if (!(battle_config.hom_setting&0x2))
+ if( !(battle_config.hom_setting&0x2) )
skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately
}
+ if( sd->md )
+ {
+ map_addblock(&sd->md->bl);
+ clif_spawn(&sd->md->bl);
+ clif_mercenary_info(sd);
+ clif_mercenary_skillblock(sd);
+ }
+
if(sd->state.connect_new) {
int lv;
sd->state.connect_new = 0;
@@ -12364,6 +12373,35 @@ void clif_send_quest_status(struct map_session_data * sd, int quest_id, bool act
/*==========================================
* Mercenary System
*==========================================*/
+void clif_mercenary_updatestatus(struct map_session_data *sd, int type)
+{
+ struct mercenary_data *md;
+ int fd;
+ if( sd == NULL || (md = sd->md) == NULL )
+ return;
+
+ fd = sd->fd;
+ WFIFOHEAD(fd,8);
+ WFIFOW(fd,0) = 0x02a2;
+ WFIFOW(fd,2) = type;
+ switch( type )
+ {
+ case SP_HP:
+ WFIFOL(fd,4) = md->battle_status.hp;
+ break;
+ case SP_MAXHP:
+ WFIFOL(fd,4) = md->battle_status.max_hp;
+ break;
+ case SP_SP:
+ WFIFOL(fd,4) = md->battle_status.sp;
+ break;
+ case SP_MAXSP:
+ WFIFOL(fd,4) = md->battle_status.max_sp;
+ break;
+ }
+ WFIFOSET(fd,8);
+}
+
void clif_mercenary_info(struct map_session_data *sd)
{
int fd;
@@ -12389,7 +12427,7 @@ void clif_mercenary_info(struct map_session_data *sd)
WFIFOW(fd,14) = status->def + (status->vit/2);
WFIFOW(fd,16) = status->mdef;
WFIFOW(fd,18) = status->flee;
- WFIFOW(fd,20) = status->aspd_rate;
+ WFIFOW(fd,20) = status->amotion;
safestrncpy((char*)WFIFOP(fd,22), md->db->name, NAME_LENGTH);
WFIFOW(fd,46) = md->db->lv;
WFIFOL(fd,48) = status->hp;
@@ -12400,7 +12438,7 @@ void clif_mercenary_info(struct map_session_data *sd)
WFIFOW(fd,68) = 0; // Loyalty
WFIFOL(fd,70) = 0; // Summon Count
WFIFOL(fd,74) = md->mercenary.kill_count;
- WFIFOW(fd,78) = 0;
+ WFIFOW(fd,78) = md->battle_status.rhw.range;
WFIFOSET(fd,80);
}
@@ -12435,35 +12473,6 @@ void clif_mercenary_skillblock(struct map_session_data *sd)
WFIFOSET(fd,len);
}
-void clif_mercenary_updatestatus(struct map_session_data *sd, int type)
-{
- struct mercenary_data *md;
- int fd;
- if( sd == NULL || (md = sd->md) == NULL )
- return;
-
- fd = sd->fd;
- WFIFOHEAD(fd,8);
- WFIFOW(fd,0) = 0x02a2;
- WFIFOW(fd,2) = type;
- switch( type )
- {
- case SP_HP:
- WFIFOL(fd,4) = md->battle_status.hp;
- break;
- case SP_MAXHP:
- WFIFOL(fd,4) = md->battle_status.max_hp;
- break;
- case SP_SP:
- WFIFOL(fd,4) = md->battle_status.sp;
- break;
- case SP_MAXSP:
- WFIFOL(fd,4) = md->battle_status.max_sp;
- break;
- }
- WFIFOSET(fd,8);
-}
-
void clif_parse_mercenary_action(int fd, struct map_session_data* sd)
{
int option = RFIFOB(fd,2);
diff --git a/src/map/clif.h b/src/map/clif.h
index 5bd7ca67a..dc9f4ef52 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -443,5 +443,6 @@ void clif_Adopt_reply(struct map_session_data *sd, int type);
void clif_mercenary_info(struct map_session_data *sd);
void clif_mercenary_skillblock(struct map_session_data *sd);
void clif_mercenary_message(int fd, int message);
+void clif_mercenary_updatestatus(struct map_session_data *sd, int type);
#endif /* _CLIF_H_ */
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index dc49f5e21..740b8d85e 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -132,10 +132,10 @@ int merc_delete(struct mercenary_data *md, int reply)
merc_contract_stop(md);
if( !sd )
- return unit_free(&md->bl, 1);
+ return unit_free(&md->bl, 0);
clif_mercenary_message(sd->fd, reply);
- return unit_remove_map(&md->bl, 1);
+ return unit_remove_map(&md->bl, 0);
}
void merc_contract_stop(struct mercenary_data *md)
@@ -213,6 +213,17 @@ int merc_data_received(struct s_mercenary *merc, bool flag)
return 1;
}
+void mercenary_damage(struct mercenary_data *md, struct block_list *src, int hp, int sp)
+{
+ clif_mercenary_updatestatus(md->master, SP_HP);
+}
+
+int mercenary_dead(struct mercenary_data *md, struct block_list *src)
+{
+ merc_delete(md, 1);
+ return 0;
+}
+
int read_mercenarydb(void)
{
FILE *fp;
@@ -292,6 +303,7 @@ int read_mercenarydb(void)
status->ele_lv = 1;
}
+ status->aspd_rate = 1000;
status->speed = atoi(str[22]);
status->adelay = atoi(str[23]);
status->amotion = atoi(str[24]);
diff --git a/src/map/mercenary.h b/src/map/mercenary.h
index bc2046dc7..93c894dda 100644
--- a/src/map/mercenary.h
+++ b/src/map/mercenary.h
@@ -41,6 +41,8 @@ struct view_data * merc_get_viewdata(int class_);
int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime);
int merc_data_received(struct s_mercenary *merc, bool flag);
int mercenary_save(struct mercenary_data *md);
+void mercenary_damage(struct mercenary_data *md, struct block_list *src, int hp, int sp);
+int mercenary_dead(struct mercenary_data *md, struct block_list *src);
int do_init_mercenary(void);
int merc_delete(struct mercenary_data *md, int reply);
void merc_contract_stop(struct mercenary_data *md);
diff --git a/src/map/mob.c b/src/map/mob.c
index 141fc697b..ff5ee6a8e 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -21,6 +21,7 @@
#include "status.h"
#include "mob.h"
#include "homunculus.h"
+#include "mercenary.h"
#include "guild.h"
#include "itemdb.h"
#include "skill.h"
@@ -1293,9 +1294,9 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
}
}
else
- if( (abl= map_id2bl(md->attacked_id)) && (!tbl || mob_can_changetarget(md, abl, mode)) )
+ if( (abl = map_id2bl(md->attacked_id)) && (!tbl || mob_can_changetarget(md, abl, mode)) )
{
- if (md->bl.m != abl->m || abl->prev == NULL
+ if( md->bl.m != abl->m || abl->prev == NULL
|| (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE
|| battle_check_target(&md->bl, abl, BCT_ENEMY) <= 0
|| (battle_config.mob_ai&0x2 && !status_check_skilluse(&md->bl, abl, 0, 0)) //Retaliate check
@@ -1740,63 +1741,78 @@ int mob_respawn(int tid, unsigned int tick, int id, intptr data)
void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
{
int char_id = 0, flag = 0;
- if(damage < 0) return; //Do nothing for absorbed damage.
- if(!damage && !(src->type&DEFAULT_ENEMY_TYPE(md)))
+ if( damage < 0 )
+ return; //Do nothing for absorbed damage.
+ if( !damage && !(src->type&DEFAULT_ENEMY_TYPE(md)) )
return; //Do not log non-damaging effects from non-enemies.
- switch (src->type) {
- case BL_PC:
+ switch( src->type )
{
- struct map_session_data *sd = (TBL_PC*)src;
- char_id = sd->status.char_id;
- if (damage)
- md->attacked_id = src->id;
- break;
- }
- case BL_HOM: //[orn]
- {
- struct homun_data *hd = (TBL_HOM*)src;
- flag = 1;
- if (hd->master)
- char_id = hd->master->status.char_id;
- if (damage)
- md->attacked_id = src->id;
- break;
- }
- case BL_PET:
- {
- struct pet_data *pd = (TBL_PET*)src;
- if (battle_config.pet_attack_exp_to_master && pd->msd) {
- char_id = pd->msd->status.char_id;
- damage=(damage*battle_config.pet_attack_exp_rate)/100; //Modify logged damage accordingly.
+ case BL_PC:
+ {
+ struct map_session_data *sd = (TBL_PC*)src;
+ char_id = sd->status.char_id;
+ if( damage )
+ md->attacked_id = src->id;
+ break;
}
- //Let mobs retaliate against the pet's master [Skotlex]
- if(pd->msd && damage)
- md->attacked_id = pd->msd->bl.id;
- break;
- }
- case BL_MOB:
- {
- struct mob_data* md2 = (TBL_MOB*)src;
- if(md2->special_state.ai && md2->master_id) {
- struct map_session_data* msd = map_id2sd(md2->master_id);
- if (msd) char_id = msd->status.char_id;
+ case BL_HOM:
+ {
+ struct homun_data *hd = (TBL_HOM*)src;
+ flag = 1;
+ if( hd->master )
+ char_id = hd->master->status.char_id;
+ if( damage )
+ md->attacked_id = src->id;
+ break;
}
- if (!damage)
+ case BL_MER:
+ {
+ struct mercenary_data *mer = (TBL_MER*)src;
+ if( mer->master )
+ char_id = mer->master->status.char_id;
+ if( damage )
+ md->attacked_id = src->id;
break;
- //Let players decide whether to retaliate versus the master or the mob. [Skotlex]
- if (md2->master_id && battle_config.retaliate_to_master)
- md->attacked_id = md2->master_id;
- else
+ }
+ case BL_PET:
+ {
+ struct pet_data *pd = (TBL_PET*)src;
+ if( battle_config.pet_attack_exp_to_master && pd->msd )
+ {
+ char_id = pd->msd->status.char_id;
+ damage = (damage*battle_config.pet_attack_exp_rate)/100; //Modify logged damage accordingly.
+ }
+ //Let mobs retaliate against the pet's master [Skotlex]
+ if( pd->msd && damage )
+ md->attacked_id = pd->msd->bl.id;
+ break;
+ }
+ case BL_MOB:
+ {
+ struct mob_data* md2 = (TBL_MOB*)src;
+ if( md2->special_state.ai && md2->master_id )
+ {
+ struct map_session_data* msd = map_id2sd(md2->master_id);
+ if( msd )
+ char_id = msd->status.char_id;
+ }
+ if( !damage )
+ break;
+ //Let players decide whether to retaliate versus the master or the mob. [Skotlex]
+ if( md2->master_id && battle_config.retaliate_to_master )
+ md->attacked_id = md2->master_id;
+ else
+ md->attacked_id = src->id;
+ break;
+ }
+ default: //For all unhandled types.
md->attacked_id = src->id;
- break;
- }
- default: //For all unhandled types.
- md->attacked_id = src->id;
}
- //Log damage...
- if(char_id) {
+
+ if( char_id )
+ { //Log damage...
int i,minpos;
unsigned int mindmg;
for(i=0,minpos=DAMAGELOG_SIZE-1,mindmg=UINT_MAX;i<DAMAGELOG_SIZE;i++){
@@ -1881,14 +1897,14 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
unsigned int mvp_damage, tick = gettick();
unsigned short flaghom = 1; // [Zephyrus] Does the mob only received damage from homunculus?
- if(src && src->type == BL_PC)
+ status = &md->status;
+
+ if( src && src->type == BL_PC )
{
sd = (struct map_session_data *)src;
mvp_sd = sd;
}
- status = &md->status;
-
if( md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS )
guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0);
@@ -2132,14 +2148,15 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
// attempt to drop the item
if (rand() % 10000 >= drop_rate)
{ // Double try by Bubble Gum
- if (!(sd && sd->sc.data[SC_ITEMBOOST] && rand() % 10000 < drop_rate))
+ if (!(mvp_sd && mvp_sd->sc.data[SC_ITEMBOOST] && rand() % 10000 < drop_rate))
continue;
}
ditem = mob_setdropitem(md->db->dropitem[i].nameid, 1);
//A Rare Drop Global Announce by Lupus
- if(drop_rate<=battle_config.rare_drop_announce) {
+ if( drop_rate <= battle_config.rare_drop_announce )
+ {
struct item_data *i_data;
char message[128];
i_data = itemdb_search(ditem->item_data.nameid);
diff --git a/src/map/pc.c b/src/map/pc.c
index 0c8af18d3..5e4954eeb 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -873,7 +873,7 @@ int pc_reg_received(struct map_session_data *sd)
sd->cashPoints = pc_readaccountreg(sd,"#CASHPOINTS");
sd->kafraPoints = pc_readaccountreg(sd,"#KAFRAPOINTS");
- if ((sd->class_&MAPID_BASEMASK)==MAPID_TAEKWON)
+ if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON )
{ //Better check for class rather than skill to prevent "skill resets" from unsetting this
sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID");
sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT");
@@ -3571,32 +3571,42 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
//Tag player for rewarping after map-loading is done. [Skotlex]
sd->state.rewarp = 1;
- sd->mapindex = mapindex;
+ sd->mapindex = mapindex;
sd->bl.m = m;
sd->bl.x = sd->ud.to_x = x;
sd->bl.y = sd->ud.to_y = y;
- if (sd->status.guild_id > 0 && map[m].flag.gvg_castle)
+ if( sd->status.guild_id > 0 && map[m].flag.gvg_castle )
{ // Increased guild castle regen [Valaris]
struct guild_castle *gc = guild_mapindex2gc(sd->mapindex);
if(gc && gc->guild_id == sd->status.guild_id)
sd->regen.state.gc = 1;
}
- if(sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0) {
+ if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 )
+ {
sd->pd->bl.m = m;
sd->pd->bl.x = sd->pd->ud.to_x = x;
sd->pd->bl.y = sd->pd->ud.to_y = y;
sd->pd->ud.dir = sd->ud.dir;
}
- if(merc_is_hom_active(sd->hd)) { //orn
+ if( merc_is_hom_active(sd->hd) )
+ {
sd->hd->bl.m = m;
sd->hd->bl.x = sd->hd->ud.to_x = x;
sd->hd->bl.y = sd->hd->ud.to_y = y;
sd->hd->ud.dir = sd->ud.dir;
}
+ if( sd->md )
+ {
+ sd->md->bl.m = m;
+ sd->md->bl.x = sd->hd->ud.to_x = x;
+ sd->md->bl.y = sd->hd->ud.to_y = y;
+ sd->md->ud.dir = sd->ud.dir;
+ }
+
return 0;
}
@@ -4925,9 +4935,12 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
pet_unlocktarget(sd->pd);
}
- if(sd->status.hom_id > 0 && battle_config.homunculus_auto_vapor) //orn
+ if( sd->status.hom_id > 0 && battle_config.homunculus_auto_vapor )
merc_hom_vaporize(sd, 0);
+ if( sd->md )
+ merc_delete(sd->md, 3); // Your mercenary soldier has ran away.
+
// Leave duel if you die [LuzZza]
if(battle_config.duel_autoleave_when_die) {
if(sd->duel_group > 0)
@@ -4968,6 +4981,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
status_calc_mob(md, 0);
status_percent_heal(src,10,0);
}
+ src = battle_get_master(src); // Maybe Player Summon
}
break;
case BL_PET: //Pass on to master...
@@ -4976,6 +4990,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
case BL_HOM:
src = &((TBL_HOM*)src)->master->bl;
break;
+ case BL_MER:
+ src = &((TBL_MER*)src)->master->bl;
+ break;
}
if (src && src->type == BL_PC)
diff --git a/src/map/status.c b/src/map/status.c
index f11096d7b..5f05296cc 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -698,6 +698,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
case BL_PC: pc_damage((TBL_PC*)target,src,hp,sp); break;
case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); break;
case BL_HOM: merc_damage((TBL_HOM*)target,src,hp,sp); break;
+ case BL_MER: mercenary_damage((TBL_MER*)target,src,hp,sp); break;
}
if (status->hp)
@@ -717,6 +718,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
case BL_PC: flag = pc_dead((TBL_PC*)target,src); break;
case BL_MOB: flag = mob_dead((TBL_MOB*)target, src, flag&4?3:0); break;
case BL_HOM: flag = merc_hom_dead((TBL_HOM*)target,src); break;
+ case BL_MER: flag = mercenary_dead((TBL_MER*)target,src); break;
default: //Unhandled case, do nothing to object.
flag = 0;
break;
@@ -2394,9 +2396,9 @@ int status_calc_mercenary(struct mercenary_data *md, int first)
}
status_calc_misc(&md->bl, status, md->db->lv);
- status_cpy(&md->base_status, status);
+ status_cpy(&md->battle_status, status);
status_calc_bl(&md->bl, SCB_ALL);
-
+
return 0;
}
diff --git a/src/map/unit.c b/src/map/unit.c
index 6299175d6..c1fb60031 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1238,20 +1238,23 @@ int unit_attack(struct block_list *src,int target_id,int continuous)
nullpo_retr(0, ud = unit_bl2ud(src));
- target=map_id2bl(target_id);
- if(target==NULL || status_isdead(target)) {
+ target = map_id2bl(target_id);
+ if( target==NULL || status_isdead(target) )
+ {
unit_unattackable(src);
return 1;
}
- if( src->type == BL_PC ){
+ if( src->type == BL_PC )
+ {
TBL_PC* sd = (TBL_PC*)src;
if( target->type == BL_NPC )
- {// monster npcs [Valaris]
+ { // monster npcs [Valaris]
npc_click(sd,(TBL_NPC*)target); // submitted by leinsirk10 [Celest]
return 0;
- } else if( pc_is90overweight(sd) )
- {// overwheight - stop attacking and walking
+ }
+ else if( pc_is90overweight(sd) )
+ { // overwheight - stop attacking and walking
unit_stop_attack(src);
unit_stop_walking(src,1);
return 0;
@@ -1427,42 +1430,46 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
struct mob_data *md = NULL;
int range;
- if((ud=unit_bl2ud(src))==NULL)
+ if( (ud=unit_bl2ud(src))==NULL )
return 0;
- if(ud->attacktimer != tid){
+ if( ud->attacktimer != tid )
+ {
ShowError("unit_attack_timer %d != %d\n",ud->attacktimer,tid);
return 0;
}
+
sd = BL_CAST(BL_PC, src);
md = BL_CAST(BL_MOB, src);
ud->attacktimer = INVALID_TIMER;
target=map_id2bl(ud->target);
- if(src == NULL || src->prev == NULL || target==NULL || target->prev == NULL)
+ if( src == NULL || src->prev == NULL || target==NULL || target->prev == NULL )
return 0;
- if(status_isdead(src) || status_isdead(target) || !status_check_skilluse(src, target, 0, 0))
+ if( status_isdead(src) || status_isdead(target) || !status_check_skilluse(src, target, 0, 0) )
return 0; // can't attack under these conditions
- if (src->m != target->m)
+ if( src->m != target->m )
{
- if (src->type == BL_MOB && mob_warpchase((TBL_MOB*)src, target))
+ if( src->type == BL_MOB && mob_warpchase((TBL_MOB*)src, target) )
return 1; // Follow up.
return 0;
}
- if(ud->skilltimer != -1 && !(sd && pc_checkskill(sd,SA_FREECAST) > 0))
+ if( ud->skilltimer != -1 && !(sd && pc_checkskill(sd,SA_FREECAST) > 0) )
return 0; // can't attack while casting
- if(!battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick,tick) > 0 && !(sd && pc_checkskill(sd,SA_FREECAST) > 0))
- { // attacking when under cast delay has restrictions:
- if (tid == -1) { //requested attack.
+ if( !battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick,tick) > 0 && !(sd && pc_checkskill(sd,SA_FREECAST) > 0) )
+ { // attacking when under cast delay has restrictions:
+ if( tid == -1 )
+ { //requested attack.
if(sd) clif_skill_fail(sd,1,4,0);
return 0;
}
//Otherwise, we are in a combo-attack, delay this until your canact time is over. [Skotlex]
- if(ud->state.attack_continue) {
- if (DIFF_TICK(ud->canact_tick, ud->attackabletime) > 0)
+ if( ud->state.attack_continue )
+ {
+ if( DIFF_TICK(ud->canact_tick, ud->attackabletime) > 0 )
ud->attackabletime = ud->canact_tick;
ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,src->id,0);
}
@@ -1472,20 +1479,24 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
sstatus = status_get_status_data(src);
range = sstatus->rhw.range;
- if(!sd || sd->status.weapon != W_BOW) range++; //Dunno why everyone but bows gets this extra range...
- if(unit_is_walking(target)) range++; //Extra range when chasing
+ if( !sd || sd->status.weapon != W_BOW )
+ range++; //Dunno why everyone but bows gets this extra range...
+ if( unit_is_walking(target) )
+ range++; //Extra range when chasing
- if(!check_distance_bl(src,target,range) ) {
- //Chase if required.
+ if( !check_distance_bl(src,target,range) )
+ { //Chase if required.
if(sd)
clif_movetoattack(sd,target);
else if(ud->state.attack_continue)
unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2);
return 1;
}
- if(!battle_check_range(src,target,range)) {
+ if( !battle_check_range(src,target,range) )
+ {
//Within range, but no direct line of attack
- if(ud->state.attack_continue) {
+ if( ud->state.attack_continue )
+ {
if(ud->chaserange > 2) ud->chaserange-=2;
unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2);
}
@@ -1496,7 +1507,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t
//Non-players use the sync packet on the walk timer. [Skotlex]
if (tid == -1 && sd) clif_fixpos(src);
- if(DIFF_TICK(ud->attackabletime,tick) <= 0)
+ if( DIFF_TICK(ud->attackabletime,tick) <= 0 )
{
if (battle_config.attack_direction_change && (src->type&battle_config.attack_direction_change)) {
ud->dir = map_calc_dir(src, target->x,target->y );
@@ -2097,6 +2108,8 @@ int unit_free(struct block_list *bl, int clrtype)
}
if( sd )
sd->md = NULL;
+
+ merc_contract_stop(md);
break;
}
}