summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/chrif.c7
-rw-r--r--src/map/clif.c18
-rw-r--r--src/map/intif.c47
-rw-r--r--src/map/intif.h2
-rw-r--r--src/map/map.c3
-rw-r--r--src/map/mercenary.c11
-rw-r--r--src/map/mercenary.h2
-rw-r--r--src/map/unit.c340
8 files changed, 277 insertions, 153 deletions
diff --git a/src/map/chrif.c b/src/map/chrif.c
index a46186fc1..8ebb88226 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -281,11 +281,12 @@ int chrif_save(struct map_session_data *sd, int flag)
WFIFOSET(char_fd, WFIFOW(char_fd,2));
- if(sd->status.pet_id > 0 && sd->pd)
+ if( sd->status.pet_id > 0 && sd->pd )
intif_save_petdata(sd->status.account_id,&sd->pd->pet);
-
- if (sd->hd && merc_is_hom_active(sd->hd))
+ if( sd->hd && merc_is_hom_active(sd->hd) )
merc_save(sd->hd);
+ if( sd->md && sd->md->mercenary.remain_life_time > 0 )
+ mercenary_save(sd->md);
return 0;
}
diff --git a/src/map/clif.c b/src/map/clif.c
index 202828788..a82495aa0 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -7056,7 +7056,8 @@ int clif_charnameack (int fd, struct block_list *bl)
WBUFW(buf,0) = cmd;
WBUFL(buf,2) = bl->id;
- switch(bl->type) {
+ switch( bl->type )
+ {
case BL_PC:
{
struct map_session_data *ssd = (struct map_session_data *)bl;
@@ -7117,6 +7118,9 @@ int clif_charnameack (int fd, struct block_list *bl)
case BL_HOM:
memcpy(WBUFP(buf,6), ((TBL_HOM*)bl)->homunculus.name, NAME_LENGTH);
break;
+ case BL_MER:
+ memcpy(WBUFP(buf,6), ((TBL_MER*)bl)->db->name, NAME_LENGTH);
+ break;
case BL_PET:
memcpy(WBUFP(buf,6), ((TBL_PET*)bl)->pet.name, NAME_LENGTH);
break;
@@ -12352,7 +12356,7 @@ void clif_mercenary_info(struct map_session_data *sd)
fd = sd->fd;
status = &md->battle_status;
- WFIFOHEAD(fd,72);
+ WFIFOHEAD(fd,80);
WFIFOW(fd,0) = 0x029b;
WFIFOL(fd,2) = md->bl.id;
WFIFOW(fd,6) = cap_value(status->rhw.atk2+status->batk, 0, SHRT_MAX);
@@ -12369,10 +12373,12 @@ void clif_mercenary_info(struct map_session_data *sd)
WFIFOL(fd,52) = status->max_hp;
WFIFOL(fd,56) = status->sp;
WFIFOL(fd,60) = status->max_sp;
- WFIFOL(fd,64) = 0; // Expiration Time
- WFIFOW(fd,68) = 0; // No documentation (Guild Rank?)
- WFIFOW(fd,70) = 0; // Times Summoned
- WFIFOSET(fd,72);
+ WFIFOL(fd,64) = 0; // Contract End
+ WFIFOW(fd,68) = 0; // Loyalty
+ WFIFOL(fd,70) = 0; // Summon Count
+ WFIFOL(fd,74) = 0; // Kill Counter
+ WFIFOW(fd,78) = 0;
+ WFIFOSET(fd,80);
}
void clif_mercenary_skillblock(struct map_session_data *sd)
diff --git a/src/map/intif.c b/src/map/intif.c
index 6a46c6d3c..8615317c8 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -38,7 +38,7 @@ static const int packet_len_table[]={
9, 9,-1,14, 0, 0, 0, 0, -1,74,-1,11, 11,-1, 0, 0, //0x3840
-1,-1, 7, 7, 7,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus]
-1,11,11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin]
- -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3870 Mercenaries [Zephyrus]
+ -1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3870 Mercenaries [Zephyrus]
11,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3880
-1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator]
};
@@ -1909,6 +1909,49 @@ int intif_mercenary_request(int merc_id, int char_id)
return 0;
}
+int intif_mercenary_delete(int merc_id)
+{
+ if (CheckForCharServer())
+ return 0;
+
+ WFIFOHEAD(inter_fd,6);
+ WFIFOW(inter_fd,0) = 0x3072;
+ WFIFOL(inter_fd,2) = merc_id;
+ WFIFOSET(inter_fd,6);
+ return 0;
+}
+
+int intif_parse_mercenary_deleted(int fd)
+{
+ if( RFIFOB(fd,2) != 1 )
+ ShowError("Mercenary data delete failure\n");
+
+ return 0;
+}
+
+int intif_mercenary_save(struct s_mercenary *merc)
+{
+ int size = sizeof(struct s_mercenary) + 4;
+
+ if( CheckForCharServer() )
+ return 0;
+
+ WFIFOHEAD(inter_fd,size);
+ WFIFOW(inter_fd,0) = 0x3073;
+ WFIFOW(inter_fd,2) = size;
+ memcpy(WFIFOP(inter_fd,4), merc, sizeof(struct s_mercenary));
+ WFIFOSET(inter_fd,size);
+ return 0;
+}
+
+int intif_parse_mercenary_saved(int fd)
+{
+ if( RFIFOB(fd,2) != 1 )
+ ShowError("Mercenary data save failure\n");
+
+ return 0;
+}
+
//-----------------------------------------------------------------
// inter serverからの通信
// エラーがあれば0(false)を返すこと
@@ -1999,6 +2042,8 @@ int intif_parse(int fd)
#endif
// Mercenary System
case 0x3870: intif_parse_mercenary_received(fd); break;
+ case 0x3871: intif_parse_mercenary_deleted(fd); break;
+ case 0x3872: intif_parse_mercenary_saved(fd); break;
case 0x3880: intif_parse_CreatePet(fd); break;
case 0x3881: intif_parse_RecvPetData(fd); break;
diff --git a/src/map/intif.h b/src/map/intif.h
index b1ee824e0..9ebbd6989 100644
--- a/src/map/intif.h
+++ b/src/map/intif.h
@@ -80,6 +80,8 @@ int intif_quest_add(int char_id, struct quest * qd);
// MERCENARY SYSTEM
int intif_mercenary_create(struct s_mercenary *merc);
int intif_mercenary_request(int merc_id, int char_id);
+int intif_mercenary_delete(int merc_id);
+int intif_mercenary_save(struct s_mercenary *merc);
#ifndef TXT_ONLY
// MAIL SYSTEM
diff --git a/src/map/map.c b/src/map/map.c
index fad39c9cd..d1605a35e 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -1584,7 +1584,8 @@ int map_quit(struct map_session_data *sd)
//Unit_free handles clearing the player related data,
//map_quit handles extra specific data which is related to quitting normally
//(changing map-servers invokes unit_free but bypasses map_quit)
- if(sd->sc.count) {
+ if( sd->sc.count )
+ {
//Status that are not saved...
if(sd->sc.data[SC_BOSSMAPINFO])
status_change_end(&sd->bl,SC_BOSSMAPINFO,-1);
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index bc91a8c60..16851d8f7 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -54,7 +54,7 @@ int merc_search_index(int class_)
bool merc_class(int class_)
{
- return (bool)(merc_search_index(class_) < 0);
+ return (bool)(merc_search_index(class_) > -1);
}
struct view_data * merc_get_viewdata(int class_)
@@ -91,6 +91,15 @@ int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime)
return 1;
}
+int mercenary_save(struct mercenary_data *md)
+{
+ md->mercenary.hp = md->battle_status.hp;
+ md->mercenary.sp = md->battle_status.sp;
+ intif_mercenary_save(&md->mercenary);
+
+ return 1;
+}
+
int merc_data_received(struct s_mercenary *merc, bool flag)
{
struct map_session_data *sd;
diff --git a/src/map/mercenary.h b/src/map/mercenary.h
index a56ecf628..a9e572f50 100644
--- a/src/map/mercenary.h
+++ b/src/map/mercenary.h
@@ -40,7 +40,9 @@ struct mercenary_data {
bool merc_class(int class_);
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);
// Homunculus DB Structures
// ===================================
diff --git a/src/map/unit.c b/src/map/unit.c
index e8d33b4c9..20cd20de6 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1772,9 +1772,9 @@ int unit_remove_map_(struct block_list *bl, int clrtype, const char* file, int l
}
case BL_HOM:
{
- struct homun_data *hd = (struct homun_data *) bl;
+ struct homun_data *hd = (struct homun_data *)bl;
ud->canact_tick = ud->canmove_tick; //It appears HOM do reset the can-act tick.
- if(!hd->homunculus.intimacy && !(hd->master && !hd->master->state.active) )
+ if( !hd->homunculus.intimacy && !(hd->master && !hd->master->state.active) )
{ //If logging out, this is deleted on unit_free
clif_emotion(bl, 28) ; //sob
clif_clearunit_area(bl,clrtype);
@@ -1786,6 +1786,20 @@ int unit_remove_map_(struct block_list *bl, int clrtype, const char* file, int l
break;
}
+ case BL_MER:
+ {
+ struct mercenary_data *md = (struct mercenary_data *)bl;
+ ud->canact_tick = ud->canmove_tick;
+ if( !md->mercenary.remain_life_time && !(md->master && !md->master->state.active) )
+ {
+ clif_clearunit_area(bl,clrtype);
+ map_delblock(bl);
+ unit_free(bl,0);
+ map_freeblock_unlock();
+ return 0;
+ }
+ break;
+ }
default: ;// do nothing
}
@@ -1805,12 +1819,15 @@ void unit_remove_map_pc(struct map_session_data *sd, int clrtype)
unit_remove_map(&sd->pd->bl, clrtype);
if(merc_is_hom_active(sd->hd))
unit_remove_map(&sd->hd->bl, clrtype);
+ if(sd->md)
+ unit_remove_map(&sd->md->bl, clrtype);
}
void unit_free_pc(struct map_session_data *sd)
{
if (sd->pd) unit_free(&sd->pd->bl,0);
if (sd->hd) unit_free(&sd->hd->bl,0);
+ if (sd->md) unit_free(&sd->md->bl,0);
unit_free(&sd->bl,3);
}
@@ -1828,171 +1845,212 @@ int unit_free(struct block_list *bl, int clrtype)
map_freeblock_lock();
if( bl->prev ) //Players are supposed to logout with a "warp" effect.
unit_remove_map(bl, clrtype);
-
- if( bl->type == BL_PC ) {
- struct map_session_data *sd = (struct map_session_data*)bl;
- if(status_isdead(bl))
- pc_setrestartvalue(sd,2);
-
- pc_delinvincibletimer(sd);
-
- pc_autoscript_clear(sd->autoscript, ARRAYLENGTH(sd->autoscript));
- pc_autoscript_clear(sd->autoscript2, ARRAYLENGTH(sd->autoscript2));
-
- if (sd->followtimer != -1)
- pc_stop_following(sd);
-
- if(sd->duel_invite > 0)
- duel_reject(sd->duel_invite, sd);
-
- // Notify friends that this char logged out. [Skotlex]
- map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0);
- party_send_logout(sd);
- guild_send_memberinfoshort(sd,0);
- pc_cleareventtimer(sd);
- pc_delspiritball(sd,sd->spiritball,1);
-
- if(sd->reg)
- { //Double logout already freed pointer fix... [Skotlex]
- aFree(sd->reg);
- sd->reg = NULL;
- sd->reg_num = 0;
- }
- if(sd->regstr)
- {
- int i;
- for( i = 0; i < sd->regstr_num; ++i )
- if( sd->regstr[i].data )
- aFree(sd->regstr[i].data);
- aFree(sd->regstr);
- sd->regstr = NULL;
- sd->regstr_num = 0;
- }
- //Tell the script to end, not delete it, it will free itself when necessary [Kevin]
- if (sd->st) {
- sd->st->rid = 0;
- sd->st->state = END;
- }
- } else if( bl->type == BL_PET ) {
- struct pet_data *pd = (struct pet_data*)bl;
- struct map_session_data *sd = pd->msd;
- pet_hungry_timer_delete(pd);
- if (pd->a_skill)
+ switch( bl->type )
+ {
+ case BL_PC:
{
- aFree(pd->a_skill);
- pd->a_skill = NULL;
+ struct map_session_data *sd = (struct map_session_data*)bl;
+ if( status_isdead(bl) )
+ pc_setrestartvalue(sd,2);
+
+ pc_delinvincibletimer(sd);
+ pc_autoscript_clear(sd->autoscript, ARRAYLENGTH(sd->autoscript));
+ pc_autoscript_clear(sd->autoscript2, ARRAYLENGTH(sd->autoscript2));
+
+ if( sd->followtimer != -1 )
+ pc_stop_following(sd);
+
+ if( sd->duel_invite > 0 )
+ duel_reject(sd->duel_invite, sd);
+
+ // Notify friends that this char logged out. [Skotlex]
+ map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0);
+ party_send_logout(sd);
+ guild_send_memberinfoshort(sd,0);
+ pc_cleareventtimer(sd);
+ pc_delspiritball(sd,sd->spiritball,1);
+
+ if( sd->reg )
+ { //Double logout already freed pointer fix... [Skotlex]
+ aFree(sd->reg);
+ sd->reg = NULL;
+ sd->reg_num = 0;
+ }
+ if( sd->regstr )
+ {
+ int i;
+ for( i = 0; i < sd->regstr_num; ++i )
+ if( sd->regstr[i].data )
+ aFree(sd->regstr[i].data);
+ aFree(sd->regstr);
+ sd->regstr = NULL;
+ sd->regstr_num = 0;
+ }
+ //Tell the script to end, not delete it, it will free itself when necessary [Kevin]
+ if( sd->st )
+ {
+ sd->st->rid = 0;
+ sd->st->state = END;
+ }
+ break;
}
- if (pd->s_skill)
+ case BL_PET:
{
- if (pd->s_skill->timer != -1) {
- if (pd->s_skill->id)
- delete_timer(pd->s_skill->timer, pet_skill_support_timer);
+ struct pet_data *pd = (struct pet_data*)bl;
+ struct map_session_data *sd = pd->msd;
+ pet_hungry_timer_delete(pd);
+ if( pd->a_skill )
+ {
+ aFree(pd->a_skill);
+ pd->a_skill = NULL;
+ }
+ if( pd->s_skill )
+ {
+ if (pd->s_skill->timer != -1) {
+ if (pd->s_skill->id)
+ delete_timer(pd->s_skill->timer, pet_skill_support_timer);
+ else
+ delete_timer(pd->s_skill->timer, pet_heal_timer);
+ }
+ aFree(pd->s_skill);
+ pd->s_skill = NULL;
+ }
+ if( pd->recovery )
+ {
+ if(pd->recovery->timer != -1)
+ delete_timer(pd->recovery->timer, pet_recovery_timer);
+ aFree(pd->recovery);
+ pd->recovery = NULL;
+ }
+ if( pd->bonus )
+ {
+ if (pd->bonus->timer != -1)
+ delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
+ aFree(pd->bonus);
+ pd->bonus = NULL;
+ }
+ if( pd->loot )
+ {
+ pet_lootitem_drop(pd,sd);
+ if (pd->loot->item)
+ aFree(pd->loot->item);
+ aFree (pd->loot);
+ pd->loot = NULL;
+ }
+ if( clrtype >= 0 )
+ {
+ if( pd->pet.intimate > 0 )
+ intif_save_petdata(pd->pet.account_id,&pd->pet);
else
- delete_timer(pd->s_skill->timer, pet_heal_timer);
+ { //Remove pet.
+ intif_delete_petdata(pd->pet.pet_id);
+ if (sd) sd->status.pet_id = 0;
+ }
}
- aFree(pd->s_skill);
- pd->s_skill = NULL;
- }
- if(pd->recovery)
- {
- if(pd->recovery->timer != -1)
- delete_timer(pd->recovery->timer, pet_recovery_timer);
- aFree(pd->recovery);
- pd->recovery = NULL;
- }
- if(pd->bonus)
- {
- if (pd->bonus->timer != -1)
- delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
- aFree(pd->bonus);
- pd->bonus = NULL;
+ if( sd )
+ sd->pd = NULL;
+ break;
}
- if (pd->loot)
+ case BL_MOB:
{
- pet_lootitem_drop(pd,sd);
- if (pd->loot->item)
- aFree(pd->loot->item);
- aFree (pd->loot);
- pd->loot = NULL;
- }
- if (clrtype >= 0) {
- if(pd->pet.intimate > 0)
- intif_save_petdata(pd->pet.account_id,&pd->pet);
- else
- { //Remove pet.
- intif_delete_petdata(pd->pet.pet_id);
- if (sd) sd->status.pet_id = 0;
+ struct mob_data *md = (struct mob_data*)bl;
+ if( md->deletetimer != -1 )
+ {
+ delete_timer(md->deletetimer,mob_timer_delete);
+ md->deletetimer = INVALID_TIMER;
}
- }
- if (sd) sd->pd = NULL;
- } else if(bl->type == BL_MOB) {
- struct mob_data *md = (struct mob_data*)bl;
- if(md->deletetimer!=-1) {
- delete_timer(md->deletetimer,mob_timer_delete);
- md->deletetimer = INVALID_TIMER;
- }
- if(md->lootitem) {
- aFree(md->lootitem);
- md->lootitem=NULL;
- }
- if( md->guardian_data )
- {
- struct guild_castle* gc = md->guardian_data->castle;
- if( md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS )
+ if( md->lootitem )
{
- gc->guardian[md->guardian_data->number].id = 0;
+ aFree(md->lootitem);
+ md->lootitem=NULL;
}
- else
+ if( md->guardian_data )
{
- int i;
- ARR_FIND(0, gc->temp_guardians_max, i, gc->temp_guardians[i] == md->bl.id);
- if( i < gc->temp_guardians_max )
- gc->temp_guardians[i] = 0;
+ struct guild_castle* gc = md->guardian_data->castle;
+ if( md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS )
+ {
+ gc->guardian[md->guardian_data->number].id = 0;
+ }
+ else
+ {
+ int i;
+ ARR_FIND(0, gc->temp_guardians_max, i, gc->temp_guardians[i] == md->bl.id);
+ if( i < gc->temp_guardians_max )
+ gc->temp_guardians[i] = 0;
+ }
+ aFree(md->guardian_data);
+ md->guardian_data = NULL;
+ }
+ if( md->spawn )
+ {
+ md->spawn->active--;
+ if( !md->spawn->state.dynamic )
+ {// permanently remove the mob
+ if( --md->spawn->num == 0 )
+ {// Last freed mob is responsible for deallocating the group's spawn data.
+ aFree(md->spawn);
+ md->spawn = NULL;
+ }
+ }
}
- aFree(md->guardian_data);
- md->guardian_data = NULL;
+ if( md->base_status)
+ {
+ aFree(md->base_status);
+ md->base_status = NULL;
+ }
+ if( mob_is_clone(md->class_) )
+ mob_clone_delete(md->class_);
+
+ break;
}
- if(md->spawn)
+ case BL_HOM:
{
- md->spawn->active--;
-
- if( !md->spawn->state.dynamic )
- {// permanently remove the mob
- if( --md->spawn->num == 0 )
- {// Last freed mob is responsible for deallocating the group's spawn data.
- aFree(md->spawn);
- md->spawn = NULL;
+ struct homun_data *hd = (TBL_HOM*)bl;
+ struct map_session_data *sd = hd->master;
+ // Desactive timers
+ merc_hom_hungry_timer_delete(hd);
+ if( clrtype >= 0 )
+ {
+ if( hd->homunculus.intimacy > 0 )
+ merc_save(hd);
+ else
+ {
+ intif_homunculus_requestdelete(hd->homunculus.hom_id);
+ if( sd )
+ sd->status.hom_id = 0;
}
}
+ if( sd )
+ sd->hd = NULL;
+ break;
}
- if(md->base_status) {
- aFree(md->base_status);
- md->base_status = NULL;
- }
- if(mob_is_clone(md->class_))
- mob_clone_delete(md->class_);
- } else if(bl->type == BL_HOM) {
- struct homun_data *hd = (TBL_HOM*)bl;
- struct map_session_data *sd = hd->master;
- // Desactive timers
- merc_hom_hungry_timer_delete(hd);
- if (clrtype >= 0) {
- if (hd->homunculus.intimacy > 0)
- merc_save(hd);
- else
+ case BL_MER:
+ {
+ struct mercenary_data *md = (TBL_MER*)bl;
+ struct map_session_data *sd = md->master;
+ /* Stop Mercenary Timer */
+ if( clrtype >= 0 )
{
- intif_homunculus_requestdelete(hd->homunculus.hom_id);
- if (sd) sd->status.hom_id = 0;
+ if( md->mercenary.remain_life_time > 0 )
+ mercenary_save(md);
+ else
+ {
+ intif_mercenary_delete(md->mercenary.mercenary_id);
+ if( sd )
+ sd->status.mer_id = 0;
+ }
}
+ if( sd )
+ sd->md = NULL;
+ break;
}
- if(sd) sd->hd = NULL;
}
skill_clear_unitgroup(bl);
status_change_clear(bl,1);
map_deliddb(bl);
- if (bl->type != BL_PC) //Players are handled by map_quit
+ if( bl->type != BL_PC ) //Players are handled by map_quit
map_freeblock(bl);
map_freeblock_unlock();
return 0;