From a2e01e40c9e60b8b2d75e4faf41d80a7041e8f93 Mon Sep 17 00:00:00 2001 From: shennetsind Date: Thu, 10 Oct 2013 18:19:16 -0300 Subject: Homun-S Quest Updated Partial Merge of 0b68607 Quest Changelog: - 1.2 Replaced with official script. [Euphy] Closes #177 Closes #178 Signed-off-by: shennetsind --- src/map/atcommand.c | 2 +- src/map/clif.c | 2 +- src/map/homunculus.c | 22 ++++----- src/map/homunculus.h | 10 ++++- src/map/itemdb.h | 1 + src/map/pc.c | 6 +-- src/map/script.c | 124 ++++++++++++++++++++++++++++++++++----------------- src/map/skill.c | 2 +- src/map/status.c | 2 +- 9 files changed, 111 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 3d04a6bff..4933256a2 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -6869,7 +6869,7 @@ ACMD(makehomun) { homunid = atoi(message); if( homunid == -1 && sd->status.hom_id && !homun_alive(sd->hd) ) { - if( !sd->hd->homunculus.vaporize ) + if( sd->hd->homunculus.vaporize ) homun->ressurect(sd, 100, sd->bl.x, sd->bl.y); else homun->call(sd); diff --git a/src/map/clif.c b/src/map/clif.c index 57830478d..0c21c796c 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1379,7 +1379,7 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) WBUFW(buf,0)=0x22e; memcpy(WBUFP(buf,2),hd->homunculus.name,NAME_LENGTH); // Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true) - WBUFB(buf,26)=(battle_config.hom_rename?0:hd->homunculus.rename_flag) | (hd->homunculus.vaporize << 1) | (hd->homunculus.hp?0:4); + WBUFB(buf,26)=(battle_config.hom_rename && hd->homunculus.rename_flag ? 0x1 : 0x0) | (hd->homunculus.vaporize == HOM_ST_REST ? 0x2 : 0) | (hd->homunculus.hp > 0 ? 0x4 : 0); WBUFW(buf,27)=hd->homunculus.level; WBUFW(buf,29)=hd->homunculus.hunger; WBUFW(buf,31)=(unsigned short) (hd->homunculus.intimacy / 100) ; diff --git a/src/map/homunculus.c b/src/map/homunculus.c index 45e9af2b0..1e47053fe 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -134,25 +134,25 @@ int homunculus_dead(struct homun_data *hd) { } //Vaporize a character's homun. If flag, HP needs to be 80% or above. -int homunculus_vaporize(struct map_session_data *sd, int flag) { +int homunculus_vaporize(struct map_session_data *sd, enum homun_state flag) { struct homun_data *hd; nullpo_ret(sd); hd = sd->hd; - if (!hd || hd->homunculus.vaporize) + if (!hd || hd->homunculus.vaporize != HOM_ST_ACTIVE) return 0; if (status->isdead(&hd->bl)) return 0; //Can't vaporize a dead homun. - if (flag && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80) + if (flag == HOM_ST_REST && get_percentage(hd->battle_status.hp, hd->battle_status.max_hp) < 80) return 0; hd->regen.state.block = 3; //Block regen while vaporized. //Delete timers when vaporized. homun->hunger_timer_delete(hd); - hd->homunculus.vaporize = 1; + hd->homunculus.vaporize = flag; if(battle_config.hom_setting&0x40) memset(hd->blockskill, 0, sizeof(hd->blockskill)); clif->hominfo(sd, sd->hd, 0); @@ -260,7 +260,7 @@ void homunculus_skillup(struct homun_data *hd,uint16 skill_id) { int i = 0 ; nullpo_retv(hd); - if(hd->homunculus.vaporize) + if(hd->homunculus.vaporize != HOM_ST_ACTIVE) return; i = skill_id - HM_SKILLBASE; @@ -471,7 +471,7 @@ bool homunculus_mutate(struct homun_data *hd, int homun_id) { int homunculus_gainexp(struct homun_data *hd,unsigned int exp) { enum homun_type htype; - if(hd->homunculus.vaporize) + if(hd->homunculus.vaporize != HOM_ST_ACTIVE) return 1; if( (htype = homun->class2type(hd->homunculus.class_)) == HT_INVALID ) { @@ -571,7 +571,7 @@ unsigned char homunculus_menu(struct map_session_data *sd,unsigned char menu_num bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) { int i, foodID, emotion; - if(hd->homunculus.vaporize) + if(hd->homunculus.vaporize == HOM_ST_REST) return false; foodID = hd->homunculusDB->foodID; @@ -781,11 +781,11 @@ bool homunculus_call(struct map_session_data *sd) { hd = sd->hd; - if (!hd->homunculus.vaporize) + if (hd->homunculus.vaporize != HOM_ST_REST) return false; //Can't use this if homun wasn't vaporized. homun->init_timers(hd); - hd->homunculus.vaporize = 0; + hd->homunculus.vaporize = HOM_ST_ACTIVE; if (hd->bl.prev == NULL) { //Spawn him hd->bl.x = sd->bl.x; hd->bl.y = sd->bl.y; @@ -833,7 +833,7 @@ bool homunculus_recv_data(int account_id, struct s_homunculus *sh, int flag) { homun->create(sd, sh); hd = sd->hd; - if(hd && hd->homunculus.hp && !hd->homunculus.vaporize && hd->bl.prev == NULL && sd->bl.prev != NULL) { + if(hd && hd->homunculus.hp && hd->homunculus.vaporize == HOM_ST_ACTIVE && hd->bl.prev == NULL && sd->bl.prev != NULL) { enum homun_type htype = homun->class2type(hd->homunculus.class_); map->addblock(&hd->bl); @@ -908,7 +908,7 @@ bool homunculus_ressurect(struct map_session_data* sd, unsigned char per, short hd = sd->hd; - if (hd->homunculus.vaporize) + if (hd->homunculus.vaporize != HOM_ST_ACTIVE) return false; // vaporized homunculi need to be 'called' if (!status->isdead(&hd->bl)) diff --git a/src/map/homunculus.h b/src/map/homunculus.h index 9562ed5c3..2cb558930 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -11,7 +11,7 @@ #define MAX_HOM_SKILL_REQUIRE 5 #define homdb_checkid(id) (id >= HM_CLASS_BASE && id <= HM_CLASS_MAX) -#define homun_alive(x) ((x) && (x)->homunculus.vaporize != 1 && (x)->battle_status.hp > 0) +#define homun_alive(x) ((x) && (x)->homunculus.vaporize == HOM_ST_ACTIVE && (x)->battle_status.hp > 0) struct h_stats { unsigned int HP, SP; @@ -44,6 +44,12 @@ enum { SP_HUNGRY = 0x2, }; +enum homun_state { + HOM_ST_ACTIVE = 0,/* either alive or dead */ + HOM_ST_REST = 1,/* is resting (vaporized) */ + HOM_ST_MORPH = 2,/* in morph state */ +}; + struct homun_data { struct block_list bl; struct unit_data ud; @@ -94,7 +100,7 @@ struct homunculus_interface { enum homun_type (*class2type) (int class_); void (*damaged) (struct homun_data *hd); int (*dead) (struct homun_data *hd); - int (*vaporize) (struct map_session_data *sd, int flag); + int (*vaporize) (struct map_session_data *sd, enum homun_state flag); int (*delete) (struct homun_data *hd, int emote); int (*checkskill) (struct homun_data *hd, uint16 skill_id); int (*calc_skilltree) (struct homun_data *hd, int flag_evolve); diff --git a/src/map/itemdb.h b/src/map/itemdb.h index fe67ebbef..0f46c1c01 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -40,6 +40,7 @@ enum item_itemid { ITEMID_RED_GEMSTONE = 716, ITEMID_BLUE_GEMSTONE = 717, ITEMID_TRAP = 1065, + ITEMID_STRANGE_EMBRYO = 6415, ITEMID_FACE_PAINT = 6120, ITEMID_STONE = 7049, ITEMID_SKULL_ = 7420, diff --git a/src/map/pc.c b/src/map/pc.c index ffc3427c7..157d9e28a 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -6438,7 +6438,7 @@ int pc_resetskill(struct map_session_data* sd, int flag) pc->setoption(sd, i); if( homun_alive(sd->hd) && pc->checkskill(sd, AM_CALLHOMUN) ) - homun->vaporize(sd, 0); + homun->vaporize(sd, HOM_ST_ACTIVE); } for( i = 1; i < MAX_SKILL; i++ ) { @@ -6663,7 +6663,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { if (sd->status.hom_id > 0){ if(battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE]) - homun->vaporize(sd, 0); + homun->vaporize(sd, HOM_ST_ACTIVE); } if( sd->md ) @@ -7588,7 +7588,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) pc->setoption(sd, i); if(homun_alive(sd->hd) && !pc->checkskill(sd, AM_CALLHOMUN)) - homun->vaporize(sd, 0); + homun->vaporize(sd, HOM_ST_ACTIVE); if(sd->status.manner < 0) clif->changestatus(sd,SP_MANNER,sd->status.manner); diff --git a/src/map/script.c b/src/map/script.c index 8460b23b0..1bedb78b6 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -6780,7 +6780,7 @@ BUILDIN(strnpcinfo) { } /*========================================== - * GetEquipID(Pos); Pos: 1-10 + * GetEquipID(Pos); Pos: 1-SCRIPT_EQUIP_TABLE_SIZE *------------------------------------------*/ BUILDIN(getequipid) { @@ -9564,44 +9564,82 @@ BUILDIN(homunculus_evolution) /*========================================== * [Xantara] + * Checks for vaporized morph state + * and deletes ITEMID_STRANGE_EMBRYO. *------------------------------------------*/ BUILDIN(homunculus_mutate) { int homun_id; enum homun_type m_class, m_id; TBL_PC *sd; + bool success = false; sd = script->rid2sd(st); if( sd == NULL || sd->hd == NULL ) return true; - - if( script_hasdata(st,2) ) - homun_id = script_getnum(st,2); - else - homun_id = 6048 + (rnd() % 4); - - if( homun_alive(sd->hd) ) { + + if( sd->hd->homunculus.vaporize == HOM_ST_MORPH ) { + int i = pc->search_inventory(sd, ITEMID_STRANGE_EMBRYO); + if( script_hasdata(st,2) ) + homun_id = script_getnum(st,2); + else + homun_id = 6048 + (rnd() % 4); + m_class = homun->class2type(sd->hd->homunculus.class_); m_id = homun->class2type(homun_id); - if( m_class != HT_INVALID && m_id != HT_INVALID && m_class == HT_EVO && m_id == HT_S && sd->hd->homunculus.level >= 99 ) + if( m_class == HT_EVO && m_id == HT_S && + sd->hd->homunculus.level >= 99 && i >= 0 && + !pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_SCRIPT) ) { + sd->hd->homunculus.vaporize = HOM_ST_REST; // Remove morph state. + homun->call(sd); // Respawn homunculus. homun->mutate(sd->hd, homun_id); - else + success = true; + } else clif->emotion(&sd->hd->bl, E_SWT); - } + } else + clif->emotion(&sd->hd->bl, E_SWT); + + script_pushint(st,success?1:0); return true; } -// [Zephyrus] -BUILDIN(homunculus_shuffle) { +/*========================================== + * Puts homunculus into morph state + * and gives ITEMID_STRANGE_EMBRYO. + *------------------------------------------*/ +BUILDIN(homunculus_morphembryo) { + enum homun_type m_class; + int i = 0; TBL_PC *sd; + bool success = false; - sd=script->rid2sd(st); - if( sd == NULL ) + sd = script->rid2sd(st); + if( sd == NULL || sd->hd == NULL ) return true; - if(homun_alive(sd->hd)) - homun->shuffle(sd->hd); + if( homun_alive(sd->hd) ) { + m_class = homun->class2type(sd->hd->homunculus.class_); + + if ( m_class == HT_EVO && sd->hd->homunculus.level >= 99 ) { + struct item item_tmp; + + memset(&item_tmp, 0, sizeof(item_tmp)); + item_tmp.nameid = ITEMID_STRANGE_EMBRYO; + item_tmp.identify = 1; + + if( (i = pc->additem(sd, &item_tmp, 1, LOG_TYPE_SCRIPT)) ) { + clif->additem(sd, 0, 0, i); + clif->emotion(&sd->hd->bl, E_SWT); + } else { + homun->vaporize(sd, HOM_ST_MORPH); + success = true; + } + } else + clif->emotion(&sd->hd->bl, E_SWT); + } else + clif->emotion(&sd->hd->bl, E_SWT); + script_pushint(st, success?1:0); return true; } @@ -9612,21 +9650,29 @@ BUILDIN(homunculus_shuffle) { * 1 = Homunculus is vaporized (rest) * 2 = Homunculus is in morph state *------------------------------------------*/ -BUILDIN(checkhomcall) -{ +BUILDIN(homunculus_checkcall) { TBL_PC *sd = script->rid2sd(st); - TBL_HOM *hd; - if( sd == NULL ) - return false; - - hd = sd->hd; - - if( !hd ) + if( sd == NULL || !sd->hd ) script_pushint(st, -1); else - script_pushint(st, hd->homunculus.vaporize); + script_pushint(st, sd->hd->homunculus.vaporize); + + return true; +} + +// [Zephyrus] +BUILDIN(homunculus_shuffle) { + TBL_PC *sd; + + sd=script->rid2sd(st); + if( sd == NULL ) + return true; + + if(homun_alive(sd->hd)) + homun->shuffle(sd->hd); + return true; } @@ -12166,12 +12212,9 @@ BUILDIN(getpetinfo) BUILDIN(gethominfo) { TBL_PC *sd=script->rid2sd(st); - TBL_HOM *hd; - int type=script_getnum(st,2); + int type = script_getnum(st,2); - hd = sd?sd->hd:NULL; - if(!homun_alive(hd)) - { + if(!sd || !sd->hd) { if (type == 2) script_pushconststr(st,"null"); else @@ -12180,13 +12223,13 @@ BUILDIN(gethominfo) } switch(type){ - case 0: script_pushint(st,hd->homunculus.hom_id); break; - case 1: script_pushint(st,hd->homunculus.class_); break; - case 2: script_pushstrcopy(st,hd->homunculus.name); break; - case 3: script_pushint(st,hd->homunculus.intimacy); break; - case 4: script_pushint(st,hd->homunculus.hunger); break; - case 5: script_pushint(st,hd->homunculus.rename_flag); break; - case 6: script_pushint(st,hd->homunculus.level); break; + case 0: script_pushint(st,sd->hd->homunculus.hom_id); break; + case 1: script_pushint(st,sd->hd->homunculus.class_); break; + case 2: script_pushstrcopy(st,sd->hd->homunculus.name); break; + case 3: script_pushint(st,sd->hd->homunculus.intimacy); break; + case 4: script_pushint(st,sd->hd->homunculus.hunger); break; + case 5: script_pushint(st,sd->hd->homunculus.rename_flag); break; + case 6: script_pushint(st,sd->hd->homunculus.level); break; default: script_pushint(st,0); break; @@ -17655,8 +17698,9 @@ void script_parse_builtin(void) { BUILDIN_DEF(warpportal,"iisii"), BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn] BUILDIN_DEF2(homunculus_mutate,"hommutate","?"), + BUILDIN_DEF2(homunculus_morphembryo,"morphembryo",""), + BUILDIN_DEF2(homunculus_checkcall,"checkhomcall",""), BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus] - BUILDIN_DEF(checkhomcall,""), BUILDIN_DEF(eaclass,"?"), //[Skotlex] BUILDIN_DEF(roclass,"i?"), //[Skotlex] BUILDIN_DEF(checkvending,"?"), diff --git a/src/map/skill.c b/src/map/skill.c index 248e19e77..82a584ce2 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -7516,7 +7516,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case AM_REST: if (sd) { - if (homun->vaporize(sd,1)) + if (homun->vaporize(sd,HOM_ST_REST)) clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); else clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); diff --git a/src/map/status.c b/src/map/status.c index 497d02bbf..ae900e04d 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -8230,7 +8230,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if( pc_isridingwug(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_WUGRIDER); if( pc_isfalcon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_FALCON); if( sd->status.pet_id > 0 ) pet->menu(sd, 3); - if( homun_alive(sd->hd) ) homun->vaporize(sd,1); + if( homun_alive(sd->hd) ) homun->vaporize(sd,HOM_ST_REST); if( sd->md ) mercenary->delete(sd->md,3); } break; -- cgit v1.2.3-70-g09d2