diff options
author | shennetsind <shennetsind@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-04-20 18:05:14 +0000 |
---|---|---|
committer | shennetsind <shennetsind@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-04-20 18:05:14 +0000 |
commit | 92249d9f8e219916670589ba6c5f9fce47808ed8 (patch) | |
tree | 0d1b0aa06c3490b3dbf7140bebd8bda126bfd65e /src/map/clif.c | |
parent | 1b3bd9ff1725a68d66fd4015c60d6fe28e4b2334 (diff) | |
download | hercules-92249d9f8e219916670589ba6c5f9fce47808ed8.tar.gz hercules-92249d9f8e219916670589ba6c5f9fce47808ed8.tar.bz2 hercules-92249d9f8e219916670589ba6c5f9fce47808ed8.tar.xz hercules-92249d9f8e219916670589ba6c5f9fce47808ed8.zip |
Initial support for Genetic, Sorcerer and Elemental Summons. Special Thanks to 3CeAM for the base.
Notice this revision onwards requires you to update your char sql table and add the elemental sql table (check sql-files/upgrade_svn15885_log.sql)
If you step by any bugs, let us know at http://rathena.org/board/tracker/ Thank you very much.
ARRIBA ARRIBA.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@15885 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map/clif.c')
-rw-r--r-- | src/map/clif.c | 305 |
1 files changed, 218 insertions, 87 deletions
diff --git a/src/map/clif.c b/src/map/clif.c index 3533c7eff..bfe78a58d 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -36,6 +36,7 @@ #include "homunculus.h" #include "instance.h" #include "mercenary.h" +#include "elemental.h" #include "log.h" #include "clif.h" #include "mail.h" @@ -273,7 +274,7 @@ static inline unsigned char clif_bl_type(struct block_list *bl) { case BL_PET: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE case BL_HOM: return 0x8; //NPC_HOM_TYPE case BL_MER: return 0x9; //NPC_MERSOL_TYPE -// case BL_ELEM: return 0xA; //NPC_ELEMENTAL_TYPE + case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE default: return 0x1; //NPC_TYPE } } @@ -5193,44 +5194,60 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skillid , int /// 4 = GN_MIX_COOKING /// 5 = GN_MAKEBOMB /// 6 = GN_S_PHARMACY -void clif_cooking_list(struct map_session_data *sd, int trigger) +void clif_cooking_list(struct map_session_data *sd, int trigger, int skill_id, int qty, int list_type) { int fd; int i, c; int view; - + nullpo_retv(sd); fd = sd->fd; - - WFIFOHEAD(fd, 6 + 2*MAX_SKILL_PRODUCE_DB); + + WFIFOHEAD(fd, 6 + 2 * MAX_SKILL_PRODUCE_DB); WFIFOW(fd,0) = 0x25a; - WFIFOW(fd,4) = 1; // list type - + WFIFOW(fd,4) = list_type; // list type + c = 0; - for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) - { - if( !skill_can_produce_mix(sd,skill_produce_db[i].nameid,trigger, 1) ) + for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) { + if( !skill_can_produce_mix(sd,skill_produce_db[i].nameid,trigger, qty) ) continue; - + if( (view = itemdb_viewid(skill_produce_db[i].nameid)) > 0 ) - WFIFOW(fd, 6+2*c)= view; + WFIFOW(fd, 6 + 2 * c) = view; else - WFIFOW(fd, 6+2*c)= skill_produce_db[i].nameid; - + WFIFOW(fd, 6 + 2 * c) = skill_produce_db[i].nameid; + c++; } - - WFIFOW(fd,2) = 6 + 2*c; - WFIFOSET(fd,WFIFOW(fd,2)); - - //TODO: replace with proper solution - if( c > 0 ) - { - sd->menuskill_id = AM_PHARMACY; + + if( skill_id == AM_PHARMACY ) { // Only send it while Cooking else check for c. + WFIFOW(fd,2) = 6 + 2 * c; + WFIFOSET(fd,WFIFOW(fd,2)); + } + + if( c > 0 ) { + sd->menuskill_id = skill_id; sd->menuskill_val = trigger; + if( skill_id != AM_PHARMACY ) { + sd->menuskill_val2 = qty; // amount. + WFIFOW(fd,2) = 6 + 2 * c; + WFIFOSET(fd,WFIFOW(fd,2)); + } + } else { + clif_menuskill_clear(sd); + if( skill_id != AM_PHARMACY ) { // AM_PHARMACY is used to Cooking. + // It fails. +#if PACKETVER >= 20090922 + clif_msg_skill(sd,skill_id,0x625); +#else + WFIFOW(fd,2) = 6 + 2 * c; + WFIFOSET(fd,WFIFOW(fd,2)); +#endif + } } } + /// Notifies clients of a status change. /// 0196 <index>.W <id>.L <state>.B (ZC_MSG_STATE_CHANGE) [used for ending status changes and starting them on non-pc units (when needed)] /// 043f <index>.W <id>.L <state>.B <remain msec>.L { <val>.L }*3 (ZC_MSG_STATE_CHANGE2) [used exclusively for starting statuses on pcs] @@ -8107,11 +8124,12 @@ void clif_refresh(struct map_session_data *sd) clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); if(merc_is_hom_active(sd->hd)) clif_send_homdata(sd,SP_ACK,0); - if( sd->md ) - { + if( sd->md ) { clif_mercenary_info(sd); clif_mercenary_skillblock(sd); } + if( sd->ed ) + clif_elemental_info(sd); map_foreachinrange(clif_getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd); clif_weather_check(sd); if( sd->chatID ) @@ -8255,6 +8273,9 @@ void clif_charnameack (int fd, struct block_list *bl) // memcpy(WBUFP(buf,6), (struct chat*)->title, NAME_LENGTH); // break; return; + case BL_ELEM: + memcpy(WBUFP(buf,6), ((TBL_ELEM*)bl)->db->name, NAME_LENGTH); + break; default: ShowError("clif_charnameack: bad type %d(%d)\n", bl->type, bl->id); return; @@ -9082,14 +9103,22 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately } - if( sd->md ) - { + if( sd->md ) { map_addblock(&sd->md->bl); clif_spawn(&sd->md->bl); clif_mercenary_info(sd); clif_mercenary_skillblock(sd); } + if( sd->ed ) { + map_addblock(&sd->ed->bl); + clif_spawn(&sd->ed->bl); + clif_elemental_info(sd); + clif_elemental_updatestatus(sd,SP_HP); + clif_hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.matk_max); + clif_elemental_updatestatus(sd,SP_SP); + } + if(sd->state.connect_new) { int lv; sd->state.connect_new = 0; @@ -10587,15 +10616,13 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) ) return; // On basilica only caster can use Basilica again to stop it. - if( sd->menuskill_id ) - { - if( sd->menuskill_id == SA_TAMINGMONSTER ) - sd->menuskill_id = sd->menuskill_val = 0; //Cancel pet capture. - else if( sd->menuskill_id != SA_AUTOSPELL ) + if( sd->menuskill_id ) { + if( sd->menuskill_id == SA_TAMINGMONSTER ) { + clif_menuskill_clear(sd); //Cancel pet capture. + } else if( sd->menuskill_id != SA_AUTOSPELL ) return; //Can't use skills while a menu is open. } - if( sd->skillitem == skillnum ) - { + if( sd->skillitem == skillnum ) { if( skilllv != sd->skillitemlv ) skilllv = sd->skillitemlv; if( !(tmp&INF_SELF_SKILL) ) @@ -10606,15 +10633,12 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) sd->skillitem = sd->skillitemlv = 0; - if( skillnum >= GD_SKILLBASE ) - { + if( skillnum >= GD_SKILLBASE ) { if( sd->state.gmaster_flag ) skilllv = guild_checkskill(sd->state.gmaster_flag, skillnum); else skilllv = 0; - } - else - { + } else { tmp = pc_checkskill(sd, skillnum); if( skilllv > tmp ) skilllv = tmp; @@ -10661,10 +10685,8 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, sho if( sd->ud.skilltimer != INVALID_TIMER ) return; - if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) - { - if( sd->skillitem != skillnum ) - { + if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) { + if( sd->skillitem != skillnum ) { clif_skill_fail(sd, skillnum, USESKILL_FAIL_SKILLINTERVAL, 0); return; } @@ -10676,28 +10698,23 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, sho if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) ) return; // On basilica only caster can use Basilica again to stop it. - if( sd->menuskill_id ) - { - if( sd->menuskill_id == SA_TAMINGMONSTER ) - sd->menuskill_id = sd->menuskill_val = 0; //Cancel pet capture. - else if( sd->menuskill_id != SA_AUTOSPELL ) + if( sd->menuskill_id ) { + if( sd->menuskill_id == SA_TAMINGMONSTER ) { + clif_menuskill_clear(sd); //Cancel pet capture. + } else if( sd->menuskill_id != SA_AUTOSPELL ) return; //Can't use skills while a menu is open. } pc_delinvincibletimer(sd); - if( sd->skillitem == skillnum ) - { + if( sd->skillitem == skillnum ) { if( skilllv != sd->skillitemlv ) skilllv = sd->skillitemlv; unit_skilluse_pos(&sd->bl, x, y, skillnum, skilllv); - } - else - { + } else { int lv; sd->skillitem = sd->skillitemlv = 0; - if( (lv = pc_checkskill(sd, skillnum)) > 0 ) - { + if( (lv = pc_checkskill(sd, skillnum)) > 0 ) { if( skilllv > lv ) skilllv = lv; unit_skilluse_pos(&sd->bl, x, y, skillnum,skilllv); @@ -10759,9 +10776,8 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) if(skill_num != sd->menuskill_id) return; - if( pc_cant_act(sd) ) - { - sd->menuskill_id = sd->menuskill_val = 0; + if( pc_cant_act(sd) ) { + clif_menuskill_clear(sd); return; } @@ -10795,12 +10811,12 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd) if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); return; } if( skill_can_produce_mix(sd,RFIFOW(fd,2),sd->menuskill_val, 1) ) skill_produce_mix(sd,0,RFIFOW(fd,2),RFIFOW(fd,4),RFIFOW(fd,6),RFIFOW(fd,8), 1); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); } @@ -10813,24 +10829,22 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd) /// 4 = GN_MIX_COOKING /// 5 = GN_MAKEBOMB /// 6 = GN_S_PHARMACY -void clif_parse_Cooking(int fd,struct map_session_data *sd) -{ - //int type = RFIFOW(fd,2); +void clif_parse_Cooking(int fd,struct map_session_data *sd) { + int type = RFIFOW(fd,2); int nameid = RFIFOW(fd,4); - - if( sd->menuskill_id != AM_PHARMACY ) { + int amount = sd->menuskill_val2?sd->menuskill_val2:1; + if( type == 6 && sd->menuskill_id != GN_MIX_COOKING && sd->menuskill_id != GN_S_PHARMACY ) return; - } - + if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); return; } - if( skill_can_produce_mix(sd,nameid,sd->menuskill_val, 1) ) - skill_produce_mix(sd,0,nameid,0,0,0,1); - sd->menuskill_val = sd->menuskill_id = 0; + if( skill_can_produce_mix(sd,nameid,sd->menuskill_val, amount) ) + skill_produce_mix(sd,sd->menuskill_id,nameid,0,0,0,amount); + clif_menuskill_clear(sd); } @@ -10843,11 +10857,11 @@ void clif_parse_RepairItem(int fd, struct map_session_data *sd) if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); return; } skill_repairweapon(sd,RFIFOW(fd,2)); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); } @@ -10862,12 +10876,12 @@ void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); return; } idx = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); skill_weaponrefine(sd, idx-2); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); } @@ -10952,13 +10966,12 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd) if (sd->menuskill_id != MC_IDENTIFY) return; - if( idx == -1 ) - {// cancel pressed - sd->menuskill_val = sd->menuskill_id = 0; + if( idx == -1 ) {// cancel pressed + clif_menuskill_clear(sd); return; } skill_identify(sd,idx-2); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); } @@ -10969,7 +10982,7 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd) if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); return; } switch( sd->menuskill_id ) { @@ -10990,7 +11003,7 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd) break; } - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); } @@ -11001,7 +11014,7 @@ void clif_parse_AutoSpell(int fd,struct map_session_data *sd) if (sd->menuskill_id != SA_AUTOSPELL) return; skill_autospell(sd,RFIFOL(fd,2)); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); } @@ -12074,7 +12087,7 @@ void clif_parse_SelectEgg(int fd, struct map_session_data *sd) return; } pet_select_egg(sd,RFIFOW(fd,2)-2); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); } @@ -13038,7 +13051,7 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd) // clif_misceffect2(&sd->bl, 0x1b0); // clif_misceffect2(&sd->bl, 0x21f); clif_feel_info(sd, i, 0); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); } @@ -15051,6 +15064,94 @@ void clif_parse_LessEffect(int fd, struct map_session_data* sd) sd->state.lesseffect = ( isLess != 0 ); } +/// S 07e4 <length>.w <option>.l <val>.l {<index>.w <amount>.w).4b* +void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) { + int n = (RFIFOW(fd,2)-12) / 4; + int type = RFIFOL(fd,4); + int flag = RFIFOL(fd,8); // Button clicked: 0 = Cancel, 1 = OK + unsigned short* item_list = (unsigned short*)RFIFOP(fd,12); + + if( sd->state.trading || sd->npc_shopid ) + return; + + if( flag == 0 || n == 0) { + clif_menuskill_clear(sd); + return; // Canceled by player. + } + + if( sd->menuskill_id != SO_EL_ANALYSIS && sd->menuskill_id != GN_CHANGEMATERIAL ) { + clif_menuskill_clear(sd); + return; // Prevent hacking. + } + + switch( type ) { + case 0: // Change Material + skill_changematerial(sd,n,item_list); + break; + case 1: // Level 1: Pure to Rough + case 2: // Level 2: Rough to Pure + skill_elementalanalysis(sd,n,type,item_list); + break; + } + clif_menuskill_clear(sd); + + return; +} + +/*========================================== + * Elemental System + *==========================================*/ +void clif_elemental_updatestatus(struct map_session_data *sd, int type) { + struct elemental_data *ed; + struct status_data *status; + int fd; + + if( sd == NULL || (ed = sd->ed) == NULL ) + return; + + fd = sd->fd; + status = &ed->battle_status; + WFIFOHEAD(fd,8); + WFIFOW(fd,0) = 0x81e; + WFIFOW(fd,2) = type; + switch( type ) { + case SP_HP: + WFIFOL(fd,4) = status->hp; + break; + case SP_MAXHP: + WFIFOL(fd,4) = status->max_hp; + break; + case SP_SP: + WFIFOL(fd,4) = status->sp; + break; + case SP_MAXSP: + WFIFOL(fd,4) = status->max_sp; + break; + } + WFIFOSET(fd,8); +} + +void clif_elemental_info(struct map_session_data *sd) { + int fd; + struct elemental_data *ed; + struct status_data *status; + + if( sd == NULL || (ed = sd->ed) == NULL ) + return; + + fd = sd->fd; + status = &ed->battle_status; + + WFIFOHEAD(fd,22); + WFIFOW(fd, 0) = 0x81d; + WFIFOL(fd, 2) = ed->bl.id; + WFIFOL(fd, 6) = status->hp; + WFIFOL(fd,10) = status->max_hp; + WFIFOL(fd,14) = status->sp; + WFIFOL(fd,18) = status->max_sp; + WFIFOSET(fd,22); +} + /// Buying Store System /// @@ -15762,6 +15863,35 @@ int clif_autoshadowspell_list(struct map_session_data *sd) { return 1; } +/*=========================================== + * Skill list for Four Elemental Analysis + * and Change Material skills. + *------------------------------------------*/ +int clif_skill_itemlistwindow( struct map_session_data *sd, int skill_id, int skill_lv ) +{ +#if PACKETVER >= 20090922 + int fd; + + nullpo_ret(sd); + + sd->menuskill_id = skill_id; // To prevent hacking. + sd->menuskill_val = skill_lv; + + if( skill_id == GN_CHANGEMATERIAL ) + skill_lv = 0; // Changematerial + + fd = sd->fd; + WFIFOHEAD(fd,packet_len(0x7e3)); + WFIFOW(fd,0) = 0x7e3; + WFIFOL(fd,2) = skill_lv; + WFIFOL(fd,4) = 0; + WFIFOSET(fd,packet_len(0x7e3)); + +#endif + + return 1; + +} /** * Sends a new status without a tick (currently used by the new mounts) **/ @@ -15826,11 +15956,11 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) { if( pc_istrading(sd) ) { clif_skill_fail(sd,sd->ud.skillid,0,0); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); return; } skill_select_menu(sd,RFIFOL(fd,2),RFIFOW(fd,6)); - sd->menuskill_val = sd->menuskill_id = 0; + clif_menuskill_clear(sd); } /*========================================== @@ -16202,13 +16332,13 @@ static int packetdb_readdb(void) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //#0x07C0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, #if PACKETVER < 20090617 6, 2, -1, 4, 4, 4, 4, 8, 8,254, 6, 8, 6, 54, 30, 54, #else // 0x7d9 changed 6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54, #endif - 0, 15, 8, 0, 0, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0, + 0, 15, 8, 6, -1, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 25, 0, 0, 26, 0, //#0x0800 #if PACKETVER < 20091229 @@ -16406,6 +16536,7 @@ static int packetdb_readdb(void) {clif_parse_mercenary_action,"mermenu"}, {clif_parse_progressbar,"progressbar"}, {clif_parse_SkillSelectMenu,"skillselectmenu"}, + {clif_parse_ItemListWindowSelected,"itemlistwindowselected"}, #if PACKETVER >= 20091229 {clif_parse_PartyBookingRegisterReq,"bookingregreq"}, {clif_parse_PartyBookingSearchReq,"bookingsearchreq"}, |