diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/map/map.c | 2 | ||||
-rw-r--r-- | src/map/mercenary.c | 156 | ||||
-rw-r--r-- | src/map/mercenary.h | 4 | ||||
-rw-r--r-- | src/map/skill.c | 8 | ||||
-rw-r--r-- | src/map/unit.c | 34 |
5 files changed, 125 insertions, 79 deletions
diff --git a/src/map/map.c b/src/map/map.c index 71af45530..1f4a2ec4b 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1669,7 +1669,7 @@ int map_quit(struct map_session_data *sd) { sd->state.waitingdisconnect = 1; if (sd->pd) unit_free(&sd->pd->bl); if(sd->status.hom_id > 0 && sd->hd) //[orn] - merc_hom_delete(sd->hd, 0) ; + merc_hom_delete(sd->hd, 2) ; unit_free(&sd->bl); chrif_save(sd,1); } else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex] diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 47c2ca686..6304f7f7d 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -113,7 +113,7 @@ void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp) int merc_hom_dead(struct homun_data *hd, struct block_list *src)
{
- hd->master->homunculus.hp = 0 ;
+ hd->battle_status.hp = hd->master->homunculus.hp = 0 ;
clif_hominfo(hd->master,hd,0); // Send dead flag
if(!merc_hom_decrease_intimacy(hd, 100)) { // Intimacy was < 100
merc_stop_walking(hd, 1);
@@ -122,16 +122,24 @@ int merc_hom_dead(struct homun_data *hd, struct block_list *src) merc_hom_delete(hd,1) ;
return 1 ;
}
+ clif_send_homdata(hd->master,SP_INTIMATE,hd->master->homunculus.intimacy / 100);
clif_emotion(&hd->bl, 16) ; //wah
clif_emotion(&hd->master->bl, 28) ; //sob
merc_hom_delete(hd, 0);
- return 3; //Remove it from map.
+ return 1; // Removing is handled by merc_hom_delete
}
int merc_hom_delete(struct homun_data *hd, int flag)
{
nullpo_retr(0, hd);
+
+ if ((flag & 2) && hd->bl.prev == NULL)
+ {
+ // Homunc was already removed from map, so just free the bl
+ return unit_free(&hd->bl);
+ }
+
// Delete homunculus
if ( flag&1 ) { //sabbath
intif_homunculus_requestdelete(hd->master->homunculus.hom_id) ;
@@ -140,9 +148,9 @@ int merc_hom_delete(struct homun_data *hd, int flag) hd->master->homunculus.hom_id = 0;
chrif_save(hd->master,0);
} else
- merc_save(hd) ;
+ merc_save(hd);
- return unit_free(&hd->bl);
+ return unit_remove_map(&hd->bl, 0);
}
int merc_hom_calc_skilltree(struct map_session_data *sd)
@@ -456,23 +464,32 @@ static int merc_natural_heal_sub(struct homun_data *hd,int tick) { int merc_natural_heal(int tid,unsigned int tick,int id,int data)
{
struct map_session_data *sd;
+ struct homun_data * hd;
sd=map_id2sd(id);
+ if(!sd)
+ return 1;
- nullpo_retr(0, sd);
-
- sd->hd->natural_heal_timer = -1;
+ if(!sd->status.hom_id || !(hd = sd->hd))
+ return 1;
- if(sd->homunculus.vaporize)
+ if(hd->natural_heal_timer != tid){
+ if(battle_config.error_log)
+ ShowError("merc_natural_heal %d != %d\n",hd->natural_heal_timer,tid);
return 1;
+ }
- if(sd && sd->hd) {
- natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick);
- merc_natural_heal_sub(sd->hd, tick);
+ hd->natural_heal_timer = -1;
+
+ if(sd->homunculus.vaporize || sd->homunculus.hp == 0)
+ return 1;
- natural_heal_prev_tick = tick;
- sd->hd->natural_heal_timer = add_timer(gettick()+battle_config.natural_healhp_interval, merc_natural_heal,sd->bl.id,0);
- }
+ natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick);
+ merc_natural_heal_sub(hd, tick);
+
+ natural_heal_prev_tick = tick;
+ sd->hd->natural_heal_timer = add_timer(gettick()+battle_config.natural_healhp_interval, merc_natural_heal,sd->bl.id,0);
+
return 0;
}
@@ -721,7 +738,8 @@ int search_homunculusDB_index(int key,int type) return -1;
}
-int merc_hom_data_init(struct map_session_data *sd)
+// Create homunc structure
+int merc_hom_create(struct map_session_data *sd)
{
struct homun_data *hd;
int i = 0 ;
@@ -737,12 +755,16 @@ int merc_hom_data_init(struct map_session_data *sd) }
sd->hd = hd = (struct homun_data *)aCalloc(1,sizeof(struct homun_data));
hd->homunculusDB = &homunculus_db[i];
- merc_calc_pos(hd,sd->bl.x,sd->bl.y,sd->ud.dir);
- hd->bl.x = hd->ud.to_x;
- hd->bl.y = hd->ud.to_y;
hd->master = sd;
+ return merc_hom_data_init(sd);
+}
+
+int merc_hom_data_init(struct map_session_data *sd)
+{
+ struct homun_data * hd = sd->hd;
+ int i;
- sd->status.hom_id = sd->homunculus.hom_id ;
+ nullpo_retr(1, hd);
hd->bl.m=sd->bl.m;
hd->bl.x=sd->bl.x;
@@ -782,48 +804,56 @@ int merc_hom_data_init(struct map_session_data *sd) map_addiddb(&hd->bl);
status_calc_homunculus(hd,1);
- //timer
- hd->hungry_timer = add_timer(gettick()+hd->homunculusDB->hungryDelay,merc_hom_hungry,sd->bl.id,0);
- natural_heal_prev_tick = gettick();
- hd->natural_heal_timer = add_timer(gettick()+battle_config.natural_healhp_interval, merc_natural_heal,sd->bl.id,0);
-
+
+ // Timers
+ hd->hungry_timer = add_timer(gettick()+hd->homunculusDB->hungryDelay,merc_hom_hungry,hd->master->bl.id,0);
+ natural_heal_prev_tick = gettick();
+ hd->natural_heal_timer = add_timer(gettick()+battle_config.natural_healhp_interval, merc_natural_heal,hd->master->bl.id,0);
return 0;
}
+
// FIX call_homunculus [albator]
int merc_call_homunculus(struct map_session_data *sd)
{
int class_ = 0 ;
nullpo_retr(0, sd);
+ if (!sd->status.hom_id)
+ {
+ class_ = 6000 + rand(1, 8) ;
+ return merc_create_homunculus(sd, class_) ;
+ }
+
+ // If homunc not yet loaded, load it, else just activate it
+ if (!sd->hd)
+ merc_hom_create(sd);
+ else
+ merc_hom_data_init(sd);
+
// call vaporized homunculus [albator]
if(sd->homunculus.vaporize == 1)
{
sd->homunculus.vaporize = 0;
- merc_hom_data_init(sd);
-
- if ( sd->homunculus.hp && sd->hd && sd->bl.prev != NULL) {
- map_addblock(&sd->hd->bl);
- clif_spawn(&sd->hd->bl);
- clif_send_homdata(sd,SP_ACK,0);
- clif_hominfo(sd,sd->hd,1);
- clif_hominfo(sd,sd->hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
- clif_homskillinfoblock(sd);
- }
- // save
- merc_save(sd->hd);
- return 1;
-
}
-
- if ( sd->status.hom_id ) {
- return merc_hom_recv_data(sd->status.account_id, &sd->homunculus, 1 ) ;
- } else {
- class_ = 6000 + rand(1, 8) ;
- return merc_create_homunculus(sd, class_) ;
+ else
+ {
+ // Homunc was dead, set hp to 1
+ sd->homunculus.hp = 1 ;
}
-
+ if ( sd->homunculus.hp && sd->hd && sd->bl.prev != NULL) {
+ map_addblock(&sd->hd->bl);
+ clif_spawn(&sd->hd->bl);
+ clif_send_homdata(sd,SP_ACK,0);
+ clif_hominfo(sd,sd->hd,1);
+ clif_hominfo(sd,sd->hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
+ clif_homskillinfoblock(sd);
+ }
+ // save
+ merc_save(sd->hd);
+ return 1;
}
+
// Albator
// Recv data of an homunculus after it loading
int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag)
@@ -840,13 +870,9 @@ int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag) }
memcpy(&sd->homunculus, sh, sizeof(struct s_homunculus));
- if ( flag == 2 ) {
- sh->hp = 1 ;
- sd->homunculus.hp = 1 ;
- }
- if(sd->homunculus.hp && sh->vaporize!=1)
+ if(sd->homunculus.hp && sd->homunculus.vaporize!=1)
{
- merc_hom_data_init(sd);
+ merc_hom_create(sd);
if ( sd->hd && sd->bl.prev != NULL) {
map_addblock(&sd->hd->bl);
@@ -907,19 +933,23 @@ int merc_hom_revive(struct map_session_data *sd, int per) {
nullpo_retr(0, sd);
- merc_hom_data_init(sd);
+ // Homunc not already loaded, load it, else just init timers
+ if (!sd->hd)
+ merc_hom_create(sd);
+ else
+ merc_hom_data_init(sd);
- if ( sd->hd && sd->bl.prev != NULL) {
- sd->homunculus.hp = sd->hd->base_status.hp = sd->hd->battle_status.hp = 1 ;
- status_heal(&sd->hd->bl, sd->homunculus.max_hp*per/100, 0, 1) ;
- map_addblock(&sd->hd->bl);
- clif_spawn(&sd->hd->bl);
- clif_send_homdata(sd,SP_ACK,0);
- clif_hominfo(sd,sd->hd,1);
- clif_hominfo(sd,sd->hd,0);
- clif_homskillinfoblock(sd);
- clif_specialeffect(&sd->hd->bl,77,AREA) ; //resurrection angel
- }
+ if ( sd->hd && sd->bl.prev != NULL) {
+ sd->homunculus.hp = sd->hd->base_status.hp = sd->hd->battle_status.hp = 1 ;
+ status_heal(&sd->hd->bl, sd->homunculus.max_hp*per/100, 0, 1) ;
+ map_addblock(&sd->hd->bl);
+ clif_spawn(&sd->hd->bl);
+ clif_send_homdata(sd,SP_ACK,0);
+ clif_hominfo(sd,sd->hd,1);
+ clif_hominfo(sd,sd->hd,0);
+ clif_homskillinfoblock(sd);
+ clif_specialeffect(&sd->hd->bl,77,AREA) ; //resurrection angel
+ }
return 1 ;
}
diff --git a/src/map/mercenary.h b/src/map/mercenary.h index d81cb9be7..aa07538ff 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -46,7 +46,8 @@ enum { SP_INTIMATE = 0x100,
SP_HUNGRY = 0x200
};
-
+// merc_is_hom_alive(struct homun_data *)
+#define merc_is_hom_active(x) (x && x->master && x->master->homunculus.vaporize != 1 && x->battle_status.hp != 0)
int do_init_merc(void);
int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag); //albator
void merc_load_sub(struct homun_data *hd, struct map_session_data *sd);
@@ -79,3 +80,4 @@ int read_homunculusdb(void); int merc_hom_increase_intimacy(struct homun_data * hd, unsigned int value);
int merc_hom_decrease_intimacy(struct homun_data * hd, unsigned int value);
int merc_skill_tree_get_max(int id, int b_class);
+int merc_hom_data_init(struct map_session_data *sd);
diff --git a/src/map/skill.c b/src/map/skill.c index 8691aaff0..0e90ee189 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -5489,7 +5489,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case AM_CALLHOMUN: //[orn] if (sd) { - if ((sd->status.hom_id == 0 || sd->homunculus.vaporize == 1)) { + if (sd->status.hom_id == 0 || sd->homunculus.vaporize == 1) { if (sd->status.hom_id == 0) { i = pc_search_inventory(sd,7142); if(i < 0) { @@ -5509,12 +5509,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in { if (sd) { - if (sd->hd && ( sd->hd->battle_status.hp >= (sd->hd->battle_status.max_hp * 80 / 100 ) ) ) { + if (sd->hd && !sd->homunculus.vaporize && ( sd->hd->battle_status.hp >= (sd->hd->battle_status.max_hp * 80 / 100 ) ) ) { sd->homunculus.vaporize = 1; clif_hominfo(sd, sd->hd, 0); merc_hom_delete(sd->hd, 0) ; - } - clif_skill_fail(sd,skillid,0,0); + } else + clif_skill_fail(sd,skillid,0,0); } break; } diff --git a/src/map/unit.c b/src/map/unit.c index c9a7c5176..d7c512714 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1605,6 +1605,30 @@ int unit_remove_map(struct block_list *bl, int clrtype) { map_freeblock_unlock(); return 0; } + } else if (bl->type == BL_HOM) { + struct homun_data *hd = (struct homun_data *) bl; + struct map_session_data *sd = hd->master; + + // Desactive timers + merc_hom_hungry_timer_delete(hd); + merc_natural_heal_timer_delete(hd); + + if(!sd) { + map_delblock(bl); + unit_free(bl); + map_freeblock_unlock(); + return 0; + } + + // Homunc was deleted or player is leaving the server, remove it from memory + if (sd->homunculus.hom_id == 0 || sd->state.waitingdisconnect) + { //Remove pet. + map_delblock(bl); + unit_free(bl); + sd->hd = NULL; + map_freeblock_unlock(); + return 1; + } } map_delblock(bl); map_freeblock_unlock(); @@ -1770,16 +1794,6 @@ int unit_free(struct block_list *bl) { } if(mob_is_clone(md->class_)) mob_clone_delete(md->class_); - } else if( bl->type == BL_HOM ) { //[orn] - struct homun_data *hd = (struct homun_data*)bl; - struct map_session_data *sd = hd->master; - merc_hom_hungry_timer_delete(hd); - merc_natural_heal_timer_delete(hd) ; - if (sd) { -// if(hd->intimacy > 0) -// intif_save_mercdata(sd->status.account_id,&sd->hom); - sd->hd = NULL; - } } skill_clear_unitgroup(bl); |