- Cleanup/typo on homunc's code

- Modified @reloadmobdb & @reloadskilldb to reload homunc's db too

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@8476 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
toms 2006-08-24 23:49:05 +00:00
parent ea4513e726
commit 4233fe5c11
8 changed files with 210 additions and 204 deletions

View File

@ -4,6 +4,8 @@ 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. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2006/08/24 2006/08/24
* Little cleanup on homunc's code [Toms]
* Modified @reloadmobdb & @reloadskilldb to reload homunc's db too [Toms]
* Now when a mob's adelay is set to be less than the amotion, both values * Now when a mob's adelay is set to be less than the amotion, both values
will be swapped (this is an attempt to understand how those mobs actually will be swapped (this is an attempt to understand how those mobs actually
work on aegis) [Skotlex] work on aegis) [Skotlex]

View File

@ -121,6 +121,8 @@
#define HM_SKILLBASE 8000 #define HM_SKILLBASE 8000
#define MAX_HOMUNSKILL 16 #define MAX_HOMUNSKILL 16
#define MAX_HOMUNCULUS_CLASS 16 //[orn] #define MAX_HOMUNCULUS_CLASS 16 //[orn]
#define HM_CLASS_BASE 6001
#define HM_CLASS_MAX 6099
struct item { struct item {
int id; int id;

View File

@ -5484,6 +5484,7 @@ int atcommand_reloadmobdb(
mob_reload(); mob_reload();
do_final_pet(); do_final_pet();
read_petdb(); read_petdb();
merc_reload();
clif_displaymessage(fd, msg_txt(98)); // Monster database reloaded. clif_displaymessage(fd, msg_txt(98)); // Monster database reloaded.
return 0; return 0;
@ -5499,6 +5500,7 @@ int atcommand_reloadskilldb(
{ {
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
skill_reload(); skill_reload();
merc_skill_reload();
clif_displaymessage(fd, msg_txt(99)); // Skill database reloaded. clif_displaymessage(fd, msg_txt(99)); // Skill database reloaded.
return 0; return 0;
@ -9823,11 +9825,11 @@ atcommand_makehomun(
nullpo_retr(-1, sd); nullpo_retr(-1, sd);
if(sscanf(message, "%d", &homunid)<1) if(sscanf(message, "%d", &homunid)<1)
return -1; return -1;
if( homunid < 6001 || homunid > 6016 ) if( homunid < HM_CLASS_BASE || homunid > HM_CLASS_BASE + MAX_HOMUNCULUS_CLASS - 1 )
return -1; return -1;
if(sd->status.hom_id == 0) if(sd->status.hom_id == 0)
{ {
merc_create_homunculus(sd,homunid); merc_create_homunculus_request(sd,homunid);
} }
else else
{ {

View File

@ -986,7 +986,7 @@ struct homun_data {
struct map_session_data *master; //pointer back to its master struct map_session_data *master; //pointer back to its master
int hungry_timer; //[orn] int hungry_timer; //[orn]
int target_id,attacked_id; int target_id,attacked_id;
unsigned long exp_next; unsigned int exp_next;
char blockskill[MAX_SKILL]; // [orn] char blockskill[MAX_SKILL]; // [orn]
}; };

View File

@ -40,71 +40,12 @@
struct homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; //[orn] struct homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; //[orn]
struct skill_tree_entry hskill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE]; struct skill_tree_entry hskill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE];
void merc_load_exptables(void);
int mercskill_castend_id( int tid, unsigned int tick, int id,int data );
static int merc_hom_hungry(int tid,unsigned int tick,int id,int data); static int merc_hom_hungry(int tid,unsigned int tick,int id,int data);
static unsigned long hexptbl[MAX_LEVEL+1]; static unsigned int hexptbl[MAX_LEVEL];
void merc_load_exptables(void)
{
FILE *fp;
char line[1024];
int i,k;
int j=0;
int lines;
char *filename[]={"exp_homun.txt","exp_homun2.txt"};
char *str[32],*h,*nh;
j = 0;
memset(hexptbl,0,sizeof(hexptbl));
for(i=0;i<2;i++){
sprintf(line, "%s/%s", db_path, filename[i]);
fp=fopen(line,"r");
if(fp==NULL){
if(i>0)
continue;
ShowError("can't read %s\n",line);
return ;
}
lines = 0;
while(fgets(line,sizeof(line)-1,fp) && j <= MAX_LEVEL){
lines++;
if(line[0] == '/' && line[1] == '/')
continue;
for(k=0,h=line;k<20;k++){
if((nh=strchr(h,','))!=NULL){
str[k]=h;
*nh=0;
h=nh+1;
} else {
str[k]=h;
h+=strlen(h);
}
}
hexptbl[j]= atoi(str[0]);
j++;
}
if (j >= MAX_LEVEL)
ShowWarning("read_hexptbl: Reached max level in exp_homun [%d]. Remaining lines were not read.\n ", MAX_HOMUNCULUS_CLASS);
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",filename[i]);
}
return ;
}
void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp) void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp)
{ {
nullpo_retv(hd);
clif_hominfo(hd->master,hd,0); clif_hominfo(hd->master,hd,0);
} }
@ -121,13 +62,16 @@ int merc_hom_dead(struct homun_data *hd, struct block_list *src)
sd->homunculus.hp = 0 ; sd->homunculus.hp = 0 ;
clif_hominfo(sd,hd,0); // Send dead flag clif_hominfo(sd,hd,0); // Send dead flag
if(!merc_hom_decrease_intimacy(hd, 100)) // Intimacy was < 100 if(!merc_hom_decrease_intimacy(hd, 100)) // Intimacy was <= 100
clif_emotion(&sd->bl, 23) ; //omg clif_emotion(&sd->bl, 23) ; //omg
else { else {
clif_emotion(&sd->bl, 28) ; //sob clif_emotion(&sd->bl, 28) ; //sob
clif_send_homdata(hd->master,SP_INTIMATE,hd->master->homunculus.intimacy / 100); // Not needed because the status window will be closed until resurect homun and then
// Intimacy will be sent
//clif_send_homdata(hd->master,SP_INTIMATE,hd->master->homunculus.intimacy / 100);
} }
merc_save(hd);
//Remove from map (if it has no intimacy, it is auto-removed from memory) //Remove from map (if it has no intimacy, it is auto-removed from memory)
return 3; return 3;
} }
@ -187,16 +131,19 @@ int merc_hom_calc_skilltree(struct map_session_data *sd)
int c=0; int c=0;
nullpo_retr(0, sd); nullpo_retr(0, sd);
c = sd->homunculus.class_ - 6001 ; c = sd->homunculus.class_ - HM_CLASS_BASE;
for(i=0;i < MAX_SKILL_TREE && (id = hskill_tree[c][i].id) > 0;i++){ for(i=0;i < MAX_SKILL_TREE && (id = hskill_tree[c][i].id) > 0;i++)
{
if(sd->homunculus.hskill[id-HM_SKILLBASE-1].id) if(sd->homunculus.hskill[id-HM_SKILLBASE-1].id)
continue; //Skill already known. continue; //Skill already known.
if(!battle_config.skillfree) { if(!battle_config.skillfree)
for(j=0;j<5;j++) { {
for(j=0;j<5;j++)
{
if( hskill_tree[c][i].need[j].id && if( hskill_tree[c][i].need[j].id &&
merc_hom_checkskill(sd,hskill_tree[c][i].need[j].id) < merc_hom_checkskill(sd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv)
hskill_tree[c][i].need[j].lv) { {
f=0; f=0;
break; break;
} }
@ -206,14 +153,14 @@ int merc_hom_calc_skilltree(struct map_session_data *sd)
sd->homunculus.hskill[id-HM_SKILLBASE-1].id = id ; sd->homunculus.hskill[id-HM_SKILLBASE-1].id = id ;
} }
} }
return 0; return 0;
} }
int merc_hom_checkskill(struct map_session_data *sd,int skill_id) int merc_hom_checkskill(struct map_session_data *sd,int skill_id)
{ {
int i = skill_id - HM_SKILLBASE - 1 ; int i = skill_id - HM_SKILLBASE - 1;
if(sd == NULL) return 0; if(!sd)
return 0;
if(sd->homunculus.hskill[i].id == skill_id) if(sd->homunculus.hskill[i].id == skill_id)
return (sd->homunculus.hskill[i].lv); return (sd->homunculus.hskill[i].lv);
@ -223,9 +170,11 @@ int merc_hom_checkskill(struct map_session_data *sd,int skill_id)
int merc_skill_tree_get_max(int id, int b_class){ int merc_skill_tree_get_max(int id, int b_class){
int i, skillid; int i, skillid;
for(i=0;(skillid=hskill_tree[b_class-6001][i].id)>0;i++) b_class -= HM_CLASS_BASE;
if (id == skillid) return hskill_tree[b_class-6001][i].max; for(i=0;(skillid=hskill_tree[b_class][i].id)>0;i++)
return skill_get_max (id); if (id == skillid)
return hskill_tree[b_class][i].max;
return skill_get_max(id);
} }
void merc_hom_skillup(struct homun_data *hd,int skillnum) void merc_hom_skillup(struct homun_data *hd,int skillnum)
@ -233,11 +182,12 @@ void merc_hom_skillup(struct homun_data *hd,int skillnum)
int i = 0 ; int i = 0 ;
nullpo_retv(hd); nullpo_retv(hd);
if( hd->master->homunculus.vaporize == 0) { if(!hd->master->homunculus.vaporize)
{
i = skillnum - HM_SKILLBASE - 1 ; i = skillnum - HM_SKILLBASE - 1 ;
if( hd->master->homunculus.skillpts > 0 && if( hd->master->homunculus.skillpts > 0 &&
hd->master->homunculus.hskill[i].id && hd->master->homunculus.hskill[i].id &&
( hd->master->homunculus.hskill[i].flag == 0 ) && //Don't allow raising while you have granted skills. [Skotlex] hd->master->homunculus.hskill[i].flag == 0 && //Don't allow raising while you have granted skills. [Skotlex]
hd->master->homunculus.hskill[i].lv < merc_skill_tree_get_max(skillnum, hd->master->homunculus.class_) hd->master->homunculus.hskill[i].lv < merc_skill_tree_get_max(skillnum, hd->master->homunculus.class_)
) )
{ {
@ -257,10 +207,12 @@ int merc_hom_levelup(struct homun_data *hd)
int growth_max_hp, growth_max_sp ; int growth_max_hp, growth_max_sp ;
char output[256] ; char output[256] ;
if (hd->master->homunculus.level == MAX_LEVEL) return 0 ; if (hd->master->homunculus.level == MAX_LEVEL || !hd->exp_next || hd->master->homunculus.exp < hd->exp_next)
return 0 ;
hd->master->homunculus.level++ ; hd->master->homunculus.level++ ;
if ( ( (hd->master->homunculus.level) % 3 ) == 0 ) hd->master->homunculus.skillpts++ ; //1 skillpoint each 3 base level if (!(hd->master->homunculus.level % 3))
hd->master->homunculus.skillpts++ ; //1 skillpoint each 3 base level
hd->master->homunculus.exp -= hd->exp_next ; hd->master->homunculus.exp -= hd->exp_next ;
hd->exp_next = hexptbl[hd->master->homunculus.level - 1] ; hd->exp_next = hexptbl[hd->master->homunculus.level - 1] ;
@ -314,9 +266,6 @@ int merc_hom_levelup(struct homun_data *hd)
"Growth : hp:%d sp:%d str(%.2f) agi(%.2f) vit(%.2f) int(%.2f) dex(%.2f) luk(%.2f) ", growth_max_hp, growth_max_sp, growth_str/(float)10, growth_agi/(float)10, growth_vit/(float)10, growth_int/(float)10, growth_dex/(float)10, growth_luk/(float)10 ) ; "Growth : hp:%d sp:%d str(%.2f) agi(%.2f) vit(%.2f) int(%.2f) dex(%.2f) luk(%.2f) ", growth_max_hp, growth_max_sp, growth_str/(float)10, growth_agi/(float)10, growth_vit/(float)10, growth_int/(float)10, growth_dex/(float)10, growth_luk/(float)10 ) ;
clif_disp_onlyself(hd->master,output,strlen(output)); clif_disp_onlyself(hd->master,output,strlen(output));
} }
// merc_save(hd) ; //not necessary
return 1 ; return 1 ;
} }
@ -345,7 +294,8 @@ int merc_hom_evolution(struct homun_data *hd)
return 0 ; return 0 ;
} }
sd = hd->master; sd = hd->master;
if (!sd) return 0; if (!sd)
return 0;
merc_hom_vaporize(sd, 0); merc_hom_vaporize(sd, 0);
@ -353,7 +303,7 @@ int merc_hom_evolution(struct homun_data *hd)
ShowError("merc_hom_evolution: Can't evoluate homunc from %d to %d", hd->master->homunculus.class_, hd->homunculusDB->evo_class); ShowError("merc_hom_evolution: Can't evoluate homunc from %d to %d", hd->master->homunculus.class_, hd->homunculusDB->evo_class);
merc_call_homunculus(sd, hd->bl.x, hd->bl.y); merc_call_homunculus(sd, hd->bl.x, hd->bl.y);
clif_emotion(&sd->bl, 21) ; //no1 clif_emotion(&sd->bl, 21); //no1
clif_misceffect2(&hd->bl,568); clif_misceffect2(&hd->bl,568);
return 1 ; return 1 ;
} }
@ -391,7 +341,7 @@ int merc_hom_gainexp(struct homun_data *hd,int exp)
return 0; return 0;
} }
// Return then new value // Return the new value
int merc_hom_increase_intimacy(struct homun_data * hd, unsigned int value) int merc_hom_increase_intimacy(struct homun_data * hd, unsigned int value)
{ {
if (battle_config.homunculus_friendly_rate != 100) if (battle_config.homunculus_friendly_rate != 100)
@ -513,15 +463,15 @@ int merc_menu(struct map_session_data *sd,int menunum)
int merc_hom_food(struct map_session_data *sd, struct homun_data *hd) int merc_hom_food(struct map_session_data *sd, struct homun_data *hd)
{ {
int i, k, emotion; int i, foodID, emotion;
if(sd->homunculus.vaporize) if(sd->homunculus.vaporize)
return 1 ; return 1 ;
k=hd->homunculusDB->foodID; foodID = hd->homunculusDB->foodID;
i=pc_search_inventory(sd,k); i = pc_search_inventory(sd,foodID);
if(i < 0) { if(i < 0) {
clif_hom_food(sd,k,0); clif_hom_food(sd,foodID,0);
return 1; return 1;
} }
pc_delitem(sd,i,1,0); pc_delitem(sd,i,1,0);
@ -550,7 +500,7 @@ int merc_hom_food(struct map_session_data *sd, struct homun_data *hd)
clif_emotion(&hd->bl,emotion) ; clif_emotion(&hd->bl,emotion) ;
clif_send_homdata(sd,SP_HUNGRY,sd->homunculus.hunger); clif_send_homdata(sd,SP_HUNGRY,sd->homunculus.hunger);
clif_send_homdata(sd,SP_INTIMATE,sd->homunculus.intimacy / 100); clif_send_homdata(sd,SP_INTIMATE,sd->homunculus.intimacy / 100);
clif_hom_food(sd,hd->homunculusDB->foodID,1); clif_hom_food(sd,foodID,1);
// Too much food :/ // Too much food :/
if(sd->homunculus.intimacy == 0) if(sd->homunculus.intimacy == 0)
@ -568,14 +518,13 @@ static int merc_hom_hungry(int tid,unsigned int tick,int id,int data)
if(!sd) if(!sd)
return 1; return 1;
if(!sd->status.hom_id || !sd->hd) if(!sd->status.hom_id || !(hd=sd->hd))
return 1; return 1;
hd = sd->hd;
if(hd->hungry_timer != tid){ if(hd->hungry_timer != tid){
if(battle_config.error_log) if(battle_config.error_log)
ShowError("merc_hom_hungry_timer %d != %d\n",hd->hungry_timer,tid); ShowError("merc_hom_hungry_timer %d != %d\n",hd->hungry_timer,tid);
return 0 ; return 0;
} }
hd->hungry_timer = -1; hd->hungry_timer = -1;
@ -609,7 +558,6 @@ int merc_hom_hungry_timer_delete(struct homun_data *hd)
delete_timer(hd->hungry_timer,merc_hom_hungry); delete_timer(hd->hungry_timer,merc_hom_hungry);
hd->hungry_timer = -1; hd->hungry_timer = -1;
} }
return 1; return 1;
} }
@ -637,7 +585,7 @@ int search_homunculusDB_index(int key,int type)
} }
// Create homunc structure // Create homunc structure
int merc_hom_create(struct map_session_data *sd) int merc_hom_alloc(struct map_session_data *sd)
{ {
struct homun_data *hd; struct homun_data *hd;
int i = 0 ; int i = 0 ;
@ -649,23 +597,24 @@ int merc_hom_create(struct map_session_data *sd)
i = search_homunculusDB_index(sd->homunculus.class_,HOMUNCULUS_CLASS); i = search_homunculusDB_index(sd->homunculus.class_,HOMUNCULUS_CLASS);
if(i < 0) { if(i < 0) {
sd->status.hom_id = 0; sd->status.hom_id = 0;
ShowError("merc_hom_alloc: unknown homunculus class [%d]", sd->homunculus.class_);
return 1; return 1;
} }
sd->hd = hd = (struct homun_data *)aCalloc(1,sizeof(struct homun_data)); sd->hd = hd = (struct homun_data *)aCalloc(1,sizeof(struct homun_data));
hd->homunculusDB = &homunculus_db[i]; hd->homunculusDB = &homunculus_db[i];
hd->master = sd; hd->master = sd;
hd->bl.m=sd->bl.m; hd->bl.m = sd->bl.m;
hd->bl.x=sd->bl.x; hd->bl.x = sd->bl.x;
hd->bl.y=sd->bl.y - 1 ; hd->bl.y = sd->bl.y - 1 ;
hd->bl.subtype = MONS; hd->bl.subtype = MONS;
hd->bl.type=BL_HOM; hd->bl.type = BL_HOM;
hd->bl.id= npc_get_new_npc_id(); hd->bl.id = npc_get_new_npc_id();
hd->bl.prev=NULL; hd->bl.prev = NULL;
hd->bl.next=NULL; hd->bl.next = NULL;
hd->exp_next=hexptbl[hd->master->homunculus.level - 1]; hd->exp_next = hexptbl[sd->homunculus.level - 1];
status_set_viewdata(&hd->bl, hd->master->homunculus.class_); status_set_viewdata(&hd->bl, sd->homunculus.class_);
status_change_init(&hd->bl); status_change_init(&hd->bl);
unit_dataset(&hd->bl); unit_dataset(&hd->bl);
hd->ud.dir = sd->ud.dir; hd->ud.dir = sd->ud.dir;
@ -691,14 +640,14 @@ int merc_call_homunculus(struct map_session_data *sd, short x, short y)
struct homun_data *hd; struct homun_data *hd;
if (!sd->status.hom_id) //Create a new homun. if (!sd->status.hom_id) //Create a new homun.
return merc_create_homunculus(sd, 6000 + rand(1, 8)) ; return merc_create_homunculus_request(sd, HM_CLASS_BASE + rand(0, 7)) ;
if (!sd->homunculus.vaporize) if (!sd->homunculus.vaporize)
return 0; //Can't use this if homun wasn't vaporized. return 0; //Can't use this if homun wasn't vaporized.
// If homunc not yet loaded, load it // If homunc not yet loaded, load it
if (!sd->hd) if (!sd->hd)
merc_hom_create(sd); merc_hom_alloc(sd);
else else
merc_hom_init_timers(sd->hd); merc_hom_init_timers(sd->hd);
@ -722,25 +671,24 @@ int merc_call_homunculus(struct map_session_data *sd, short x, short y)
return 1; return 1;
} }
// Albator // Recv homunculus data from char server
// Recv data of an homunculus after it loading
int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag) int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag)
{ {
struct map_session_data *sd ; struct map_session_data *sd ;
sd = map_id2sd(account_id); sd = map_id2sd(account_id);
if(sd == NULL) if(!sd)
return 0; return 0;
if(flag == 0) { if(!flag) { // Failed to load
sd->status.hom_id = 0; sd->status.hom_id = 0;
return 0; return 0;
} }
memcpy(&sd->homunculus, sh, sizeof(struct s_homunculus)); memcpy(&sd->homunculus, sh, sizeof(struct s_homunculus));
if(sd->homunculus.hp && sd->homunculus.vaporize!=1) if(sd->homunculus.hp && !sd->homunculus.vaporize)
{ {
merc_hom_create(sd); merc_hom_alloc(sd);
if ( sd->hd && sd->bl.prev != NULL) { if ( sd->hd && sd->bl.prev != NULL) {
map_addblock(&sd->hd->bl); map_addblock(&sd->hd->bl);
@ -752,14 +700,13 @@ int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag)
clif_send_homdata(sd,SP_ACK,0); clif_send_homdata(sd,SP_ACK,0);
} }
} }
return 1; return 1;
} }
int merc_create_homunculus(struct map_session_data *sd, int class_) // Ask homunculus creation to char server
int merc_create_homunculus_request(struct map_session_data *sd, int class_)
{ {
int i=0 ; int i;
nullpo_retr(1, sd); nullpo_retr(1, sd);
@ -768,7 +715,7 @@ int merc_create_homunculus(struct map_session_data *sd, int class_)
sd->status.hom_id = 0; sd->status.hom_id = 0;
return 0; return 0;
} }
memcpy(sd->homunculus.name, homunculus_db[i].name, NAME_LENGTH-1); strncpy(sd->homunculus.name, homunculus_db[i].name, NAME_LENGTH-1);
sd->homunculus.class_ = class_; sd->homunculus.class_ = class_;
sd->homunculus.level=1; sd->homunculus.level=1;
@ -778,7 +725,7 @@ int merc_create_homunculus(struct map_session_data *sd, int class_)
sd->homunculus.rename_flag = 0; sd->homunculus.rename_flag = 0;
sd->homunculus.skillpts = 0; sd->homunculus.skillpts = 0;
sd->homunculus.char_id = sd->status.char_id; sd->homunculus.char_id = sd->status.char_id;
sd->homunculus.vaporize = 0; // albator sd->homunculus.vaporize = 0;
sd->homunculus.hp = sd->homunculus.max_hp = homunculus_db[i].basemaxHP ; sd->homunculus.hp = sd->homunculus.max_hp = homunculus_db[i].basemaxHP ;
sd->homunculus.sp = sd->homunculus.max_sp = homunculus_db[i].basemaxSP ; sd->homunculus.sp = sd->homunculus.max_sp = homunculus_db[i].basemaxSP ;
@ -789,15 +736,16 @@ int merc_create_homunculus(struct map_session_data *sd, int class_)
sd->homunculus.dex = homunculus_db[i].baseDEX * 10; sd->homunculus.dex = homunculus_db[i].baseDEX * 10;
sd->homunculus.luk = homunculus_db[i].baseLUK * 10; sd->homunculus.luk = homunculus_db[i].baseLUK * 10;
// Clear all skills
for(i=0;i<MAX_HOMUNSKILL;i++) for(i=0;i<MAX_HOMUNSKILL;i++)
sd->homunculus.hskill[i].id = sd->homunculus.hskill[i].lv = sd->homunculus.hskill[i].flag = 0; sd->homunculus.hskill[i].id = sd->homunculus.hskill[i].lv = sd->homunculus.hskill[i].flag = 0;
intif_homunculus_create(sd->status.account_id, &sd->homunculus); // request homunculus creation // Request homunculus creation
intif_homunculus_create(sd->status.account_id, &sd->homunculus);
return 1; return 1;
} }
int merc_revive_homunculus(struct map_session_data *sd, unsigned char per, short x, short y) int merc_resurrect_homunculus(struct map_session_data *sd, unsigned char per, short x, short y)
{ {
struct homun_data *hd; struct homun_data *hd;
nullpo_retr(0, sd); nullpo_retr(0, sd);
@ -805,7 +753,7 @@ int merc_revive_homunculus(struct map_session_data *sd, unsigned char per, short
return 0; return 0;
if (!sd->hd) //Load homun data; if (!sd->hd) //Load homun data;
merc_hom_create(sd); merc_hom_alloc(sd);
else else
merc_hom_init_timers(sd->hd); merc_hom_init_timers(sd->hd);
@ -827,10 +775,11 @@ int merc_revive_homunculus(struct map_session_data *sd, unsigned char per, short
return 1; return 1;
} }
void merc_homun_revive(struct homun_data *hd, unsigned int hp, unsigned int sp) void merc_hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp)
{ {
struct map_session_data *sd = hd->master; struct map_session_data *sd = hd->master;
if (!sd) return; if (!sd)
return;
clif_send_homdata(sd,SP_ACK,0); clif_send_homdata(sd,SP_ACK,0);
clif_hominfo(sd,hd,1); clif_hominfo(sd,hd,1);
clif_hominfo(sd,hd,0); clif_hominfo(sd,hd,0);
@ -841,50 +790,46 @@ int read_homunculusdb()
{ {
FILE *fp; FILE *fp;
char line[1024], *p; char line[1024], *p;
int i,k,l; int i, k, classid;
int j=0; int j = 0;
int c = 0 ;
int lines;
char *filename[]={"homunculus_db.txt","homunculus_db2.txt"}; char *filename[]={"homunculus_db.txt","homunculus_db2.txt"};
char *str[36],*h,*nh; char *str[36];
j = 0;
memset(homunculus_db,0,sizeof(homunculus_db)); memset(homunculus_db,0,sizeof(homunculus_db));
for(i=0;i<2;i++){ for(i = 0; i<2; i++)
{
sprintf(line, "%s/%s", db_path, filename[i]); sprintf(line, "%s/%s", db_path, filename[i]);
fp=fopen(line,"r"); fp = fopen(line,"r");
if(fp==NULL){ if(!fp){
if(i>0) if(i != 0)
continue; continue;
ShowError("can't read %s\n",line); ShowError("read_homunculusdb : can't read %s\n", line);
return -1; return -1;
} }
lines = 0;
while(fgets(line,sizeof(line)-1,fp) && j < MAX_HOMUNCULUS_CLASS){
lines++;
while(fgets(line,sizeof(line)-1,fp) && j < MAX_HOMUNCULUS_CLASS)
{
if(line[0] == '/' && line[1] == '/') if(line[0] == '/' && line[1] == '/')
continue; continue;
for(k=0,h=line;k<36;k++){ k = 0;
if((nh=strchr(h,','))!=NULL){ p = strtok (line,",");
str[k]=h; while (p != NULL && k < 36)
*nh=0; {
h=nh+1; str[k++] = p;
} else { p = strtok (NULL, ",");
str[k]=h;
h+=strlen(h);
}
} }
if(atoi(str[0]) < 6001 || atoi(str[0]) > 6099) classid = atoi(str[0]);
if (k != 36 || classid < HM_CLASS_BASE || classid > HM_CLASS_MAX)
{
ShowError("read_homunculusdb : Error reading %s", filename[i]);
continue; continue;
}
//Class,Homunculus,HP,SP,ATK,MATK,HIT,CRI,DEF,MDEF,FLEE,ASPD,STR,AGI,VIT,INT,DEX,LUK //Class,Homunculus,HP,SP,ATK,MATK,HIT,CRI,DEF,MDEF,FLEE,ASPD,STR,AGI,VIT,INT,DEX,LUK
homunculus_db[j].class_ = atoi(str[0]); homunculus_db[j].class_ = classid;
memcpy(homunculus_db[j].name,str[1],NAME_LENGTH-1); strncpy(homunculus_db[j].name,str[1],NAME_LENGTH-1);
homunculus_db[j].basemaxHP = atoi(str[2]); homunculus_db[j].basemaxHP = atoi(str[2]);
homunculus_db[j].basemaxSP = atoi(str[3]); homunculus_db[j].basemaxSP = atoi(str[3]);
homunculus_db[j].baseSTR = atoi(str[4]); homunculus_db[j].baseSTR = atoi(str[4]);
@ -919,7 +864,6 @@ int read_homunculusdb()
homunculus_db[j].race = atoi(str[33]); homunculus_db[j].race = atoi(str[33]);
homunculus_db[j].element = atoi(str[34]); homunculus_db[j].element = atoi(str[34]);
homunculus_db[j].accessID = atoi(str[35]); homunculus_db[j].accessID = atoi(str[35]);
j++; j++;
} }
if (j > MAX_HOMUNCULUS_CLASS) if (j > MAX_HOMUNCULUS_CLASS)
@ -927,6 +871,16 @@ int read_homunculusdb()
fclose(fp); fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' homunculus in '"CL_WHITE"db/%s"CL_RESET"'.\n",j,filename[i]); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' homunculus in '"CL_WHITE"db/%s"CL_RESET"'.\n",j,filename[i]);
} }
return 0;
}
int read_homunculus_skilldb()
{
FILE *fp;
char line[1024], *p;
int k, classid;
int j = 0;
char *split[15];
memset(hskill_tree,0,sizeof(hskill_tree)); memset(hskill_tree,0,sizeof(hskill_tree));
sprintf(line, "%s/homun_skill_tree.txt", db_path); sprintf(line, "%s/homun_skill_tree.txt", db_path);
@ -936,58 +890,113 @@ int read_homunculusdb()
return 1; return 1;
} }
while(fgets(line, sizeof(line)-1, fp)){ while(fgets(line, sizeof(line)-1, fp))
char *split[50]; {
int f=0, m=3; int minJobLevelPresent = 0;
if(line[0]=='/' && line[1]=='/') if(line[0]=='/' && line[1]=='/')
continue; continue;
for(j=0,p=line;j<14 && p;j++){
split[j]=p; k = 0;
p=strchr(p,','); p = strtok(line,",");
if(p) *p++=0; while (p != NULL && k < 15)
{
split[k++] = p;
p = strtok(NULL, ",");
} }
if(j<13)
if(k < 13)
continue; continue;
if (j == 14) {
f=1; // MinJobLvl has been added if (k == 14)
m++; minJobLevelPresent = 1; // MinJobLvl has been added
}
// check for bounds [celest] // check for bounds [celest]
c = atoi(split[0]) ; classid = atoi(split[0]) - HM_CLASS_BASE;
l = c - 6001 ; if ( classid >= MAX_HOMUNCULUS_CLASS )
if ( l >= MAX_HOMUNCULUS_CLASS )
continue; continue;
k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex] k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex]
for(j = 0; j < MAX_SKILL_TREE && hskill_tree[l][j].id && hskill_tree[l][j].id != k; j++); // Search an empty line or a line with the same skill_id (stored in j)
for(j = 0; j < MAX_SKILL_TREE && hskill_tree[classid][j].id && hskill_tree[classid][j].id != k; j++);
if (j == MAX_SKILL_TREE) if (j == MAX_SKILL_TREE)
{ {
ShowWarning("Unable to load skill %d into homunculus %d's tree. Maximum number of skills per class has been reached.\n", k, l); ShowWarning("Unable to load skill %d into homunculus %d's tree. Maximum number of skills per class has been reached.\n", k, classid);
continue; continue;
} }
hskill_tree[l][j].id=k;
hskill_tree[l][j].max=atoi(split[2]); hskill_tree[classid][j].id=k;
if (f) hskill_tree[l][j].joblv=atoi(split[3]); hskill_tree[classid][j].max=atoi(split[2]);
if (minJobLevelPresent)
hskill_tree[classid][j].joblv=atoi(split[3]);
for(k=0;k<5;k++){ for(k=0;k<5;k++){
hskill_tree[l][j].need[k].id=atoi(split[k*2+m]); hskill_tree[classid][j].need[k].id=atoi(split[3+k*2+minJobLevelPresent]);
hskill_tree[l][j].need[k].lv=atoi(split[k*2+m+1]); hskill_tree[classid][j].need[k].lv=atoi(split[3+k*2+minJobLevelPresent+1]);
} }
} }
fclose(fp); fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","homun_skill_tree.txt"); ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","homun_skill_tree.txt");
return 0; return 0;
} }
int do_init_merc (void) void read_homunculus_expdb()
{ {
merc_load_exptables(); FILE *fp;
memset(homunculus_db,0,sizeof(homunculus_db)); //[orn] char line[1024];
read_homunculusdb(); //[orn] int i, j=0;
char *filename[]={"exp_homun.txt","exp_homun2.txt"};
memset(hexptbl,0,sizeof(hexptbl));
for(i=0; i<2; i++){
sprintf(line, "%s/%s", db_path, filename[i]);
fp=fopen(line,"r");
if(fp == NULL){
if(i != 0)
continue;
ShowError("can't read %s\n",line);
return;
}
while(fgets(line,sizeof(line)-1,fp) && j < MAX_LEVEL)
{
if(line[0] == '/' && line[1] == '/')
continue;
hexptbl[j] = strtoul(line, NULL, 10);
if (!hexptbl[j++])
break;
}
if (!feof(fp) || hexptbl[MAX_LEVEL - 1])
{
ShowWarning("read_hexptbl: Reached max level in exp_homun [%d]. Remaining lines were not read.\n ", MAX_LEVEL);
hexptbl[MAX_LEVEL - 1] = 0;
}
fclose(fp);
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' levels in '"CL_WHITE"%s"CL_RESET"'.\n", j, filename[i]);
}
}
void merc_reload()
{
read_homunculusdb();
read_homunculus_expdb();
}
void merc_skill_reload()
{
read_homunculus_skilldb();
}
int do_init_merc()
{
read_homunculusdb();
read_homunculus_expdb();
read_homunculus_skilldb();
// Add homunc timer function to timer func list [Toms] // Add homunc timer function to timer func list [Toms]
add_timer_func_list(merc_hom_hungry, "merc_hom_hungry"); add_timer_func_list(merc_hom_hungry, "merc_hom_hungry");
return 0; return 0;
} }
int do_final_merc (void); int do_final_merc();

View File

@ -33,10 +33,7 @@ struct homunculus_db {
int gmaxLUK ; int gmaxLUK ;
int evo_class ; int evo_class ;
int baseASPD ; int baseASPD ;
//short size ; unsigned char element, race, size;
//short race ;
//short element ;
unsigned char element, race, size; // albator
int accessID ; int accessID ;
}; };
extern struct homunculus_db homuncumlus_db[MAX_HOMUNCULUS_CLASS]; extern struct homunculus_db homuncumlus_db[MAX_HOMUNCULUS_CLASS];
@ -63,19 +60,21 @@ int merc_hom_levelup(struct homun_data *hd) ;
int merc_hom_evolution(struct homun_data *hd) ; int merc_hom_evolution(struct homun_data *hd) ;
void merc_hom_heal(struct homun_data *hd,int hp,int sp); void merc_hom_heal(struct homun_data *hd,int hp,int sp);
int merc_hom_vaporize(struct map_session_data *sd, int flag); int merc_hom_vaporize(struct map_session_data *sd, int flag);
int merc_revive_homunculus(struct map_session_data *sd, unsigned char per, short x, short y); int merc_resurrect_homunculus(struct map_session_data *sd, unsigned char per, short x, short y);
void merc_homun_revive(struct homun_data *hd, unsigned int hp, unsigned int sp); void merc_hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp);
void merc_save(struct homun_data *hd); void merc_save(struct homun_data *hd);
int merc_call_homunculus(struct map_session_data *sd, short x, short y); int merc_call_homunculus(struct map_session_data *sd, short x, short y);
int merc_create_homunculus(struct map_session_data *sd, int class_); int merc_create_homunculus_request(struct map_session_data *sd, int class_);
int search_homunculusDB_index(int key,int type); int search_homunculusDB_index(int key,int type);
int merc_menu(struct map_session_data *sd,int menunum); int merc_menu(struct map_session_data *sd,int menunum);
int merc_hom_food(struct map_session_data *sd, struct homun_data *hd); int merc_hom_food(struct map_session_data *sd, struct homun_data *hd);
int merc_hom_hungry_timer_delete(struct homun_data *hd); int merc_hom_hungry_timer_delete(struct homun_data *hd);
#define merc_stop_walking(hd, type) { if((hd)->ud.walktimer != -1) unit_stop_walking(&(hd)->bl, type); } #define merc_stop_walking(hd, type) { if((hd)->ud.walktimer != -1) unit_stop_walking(&(hd)->bl, type); }
#define merc_stop_attack(hd) { if((hd)->ud.attacktimer != -1) unit_stop_attack(&(hd)->bl); hd->ud.target = 0; } #define merc_stop_attack(hd) { if((hd)->ud.attacktimer != -1) unit_stop_attack(&(hd)->bl); hd->ud.target = 0; }
int read_homunculusdb(void);
int merc_hom_increase_intimacy(struct homun_data * hd, unsigned int value); 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_hom_decrease_intimacy(struct homun_data * hd, unsigned int value);
int merc_skill_tree_get_max(int id, int b_class); int merc_skill_tree_get_max(int id, int b_class);
void merc_hom_init_timers(struct homun_data * hd); void merc_hom_init_timers(struct homun_data * hd);
void merc_skill_reload();
void merc_reload();

View File

@ -6257,16 +6257,8 @@ int skill_castend_pos2 (struct block_list *src, int x, int y, int skillid, int s
case AM_RESURRECTHOMUN: //[orn] case AM_RESURRECTHOMUN: //[orn]
if (sd) if (sd)
{ {
/* According to Tharis, the correct % SHOULD be 20*lv%
int p;
// If skilllv = 1, range = 1~4%, lv 2 : 5~25%, lv 3 : 25~45%, ...
if (skilllv == 1)
p = 1 + rand() % 4;
else
p = 5 + 20 * (skilllv - 2) + rand() % 21;
*/
if (map_flag_gvg(src->m) || //No reviving in WoE grounds! if (map_flag_gvg(src->m) || //No reviving in WoE grounds!
!merc_revive_homunculus(sd, 20*skilllv, x, y)) !merc_resurrect_homunculus(sd, 20*skilllv, x, y))
{ {
clif_skill_fail(sd,skillid,0,0); clif_skill_fail(sd,skillid,0,0);
break; break;

View File

@ -897,7 +897,7 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per
pc_revive((TBL_PC*)bl, hp, sp); pc_revive((TBL_PC*)bl, hp, sp);
break; break;
case BL_HOM: //[orn] case BL_HOM: //[orn]
merc_homun_revive((TBL_HOM*)bl, hp, sp); merc_hom_revive((TBL_HOM*)bl, hp, sp);
break; break;
} }
return 1; return 1;