From ae57ff81700dbe6714ef107b34510457e9c9c5b6 Mon Sep 17 00:00:00 2001 From: glighta Date: Mon, 12 Nov 2012 00:06:25 +0000 Subject: -Add Homon-S skills, 1st implementation (all done except Eleanors) --Upd Skill conf to set land-limit for homonculus by default (ground skill limit) --Mv MH_HEILIGE_STANGE and MH_ANGRIFFS_MODUS skill from Eleanor to Bayeri -Enforce all zeny transaction to use pc_payzeny and pc_getzeny handlers, (auto log and clif) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16914 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/skill.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 183 insertions(+), 39 deletions(-) (limited to 'src/map/skill.c') diff --git a/src/map/skill.c b/src/map/skill.c index 65ea0b600..5ebb7a59c 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -615,6 +615,22 @@ int skillnotok_hom(int skillid, struct homun_data *hd) if (hd->blockskill[i] > 0) return 1; + switch(skillid){ + case MH_LIGHT_OF_REGENE: + if(hd->homunculus.intimacy <= 750) //if not cordial + return 1; + break; + case MH_OVERED_BOOST: + if(hd->homunculus.hunger <= 1) //if we starving + return 1; + case MH_GOLDENE_FERSE: //can be used with angriff + if(hd->sc.data[SC_ANGRIFFS_MODUS]) + return 1; + case MH_ANGRIFFS_MODUS: + if(hd->sc.data[SC_GOLDENE_FERSE]) + return 1; + break; + } //Use master's criteria. return skillnotok(skillid, hd->master); @@ -796,17 +812,18 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int sc_start(src,SC_COMBO, 15, TK_TURNKICK, (2000 - 4*sstatus->agi - 2*sstatus->dex))) ; //Stance triggered - else if(sc->data[SC_READYCOUNTER]) - { //additional chance from SG_FRIEND [Komurka] + else if (sc->data[SC_READYCOUNTER]) { //additional chance from SG_FRIEND [Komurka] rate = 20; if (sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == TK_COUNTER) { rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100; status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); } - sc_start4(src,SC_COMBO, rate, TK_COUNTER, bl->id,0,0, + sc_start2(src, SC_COMBO, rate, TK_COUNTER, bl->id, (2000 - 4*sstatus->agi - 2*sstatus->dex)); } } + if(sc && sc->data[SC_PYROCLASTIC] && (rnd() % 1000 <= sstatus->luk * 10 / 3 + 1) ) + skill_castend_pos2(src, bl->x, bl->y, BS_HAMMERFALL,sc->data[SC_PYROCLASTIC]->val1, tick, 0); } if (sc) { @@ -1350,18 +1367,21 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int case EL_TYPOON_MIS: sc_start(bl,SC_SILENCE,10*skilllv,skilllv,skill_get_time(skillid,skilllv)); break; - case MH_LAVA_SLIDE: - sc_start4(bl,SC_BURNING,10*skilllv,skilllv,1000,src->id,0,skill_get_time(skillid,skilllv)); - break; - case MH_STAHL_HORN: - sc_start(bl,SC_STUN,(20 + 4 * skilllv),skilllv,skill_get_time2(skillid,skilllv)); - break; case KO_JYUMONJIKIRI: // needs more info sc_start(bl,SC_JYUMONJIKIRI,25,skilllv,skill_get_time(skillid,skilllv)); break; case KO_MAKIBISHI: sc_start(bl, SC_STUN, 100, skilllv, skill_get_time2(skillid,skilllv)); break; + case MH_LAVA_SLIDE: + if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skilllv, skilllv, 1000, src->id, 0, skill_get_time(skillid, skilllv)); + break; + case MH_STAHL_HORN: + sc_start(bl, SC_STUN, (20 + 4 * (skilllv-1)), skilllv, skill_get_time(skillid, skilllv)); + break; + case MH_NEEDLE_OF_PARALYZE: + sc_start(bl, SC_PARALYSIS, 40 + (5*skilllv), skilllv, skill_get_time(skillid, skilllv)); + break; } if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) @@ -2787,10 +2807,11 @@ static int skill_check_unit_range_sub (struct block_list *bl, va_list ap) g_skillid = unit->group->skill_id; switch (skillid) { + case MH_STEINWAND: case MG_SAFETYWALL: case AL_PNEUMA: case SC_MAELSTROM: - if(g_skillid != MG_SAFETYWALL && g_skillid != AL_PNEUMA && g_skillid != SC_MAELSTROM) + if(g_skillid != MH_STEINWAND && g_skillid != MG_SAFETYWALL && g_skillid != AL_PNEUMA && g_skillid != SC_MAELSTROM) return 0; break; case AL_WARP: @@ -3483,7 +3504,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case WM_SEVERE_RAINSTORM_MELEE: case WM_GREAT_ECHO: case GN_SLINGITEM_RANGEMELEEATK: - case MH_STAHL_HORN: case KO_JYUMONJIKIRI: case KO_SETSUDAN: case KO_KAIHOU: @@ -3720,7 +3740,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case SO_VARETYR_SPEAR: case GN_CART_TORNADO: case GN_CARTCANNON: - case MH_LAVA_SLIDE: case KO_HAPPOKUNAI: case KO_HUUMARANKA: case KO_MUCHANAGE: @@ -4528,6 +4547,21 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int break; + //recursive homon skill + case MH_MAGMA_FLOW: + case MH_XENO_SLASHER: + case MH_HEILIGE_STANGE: + if(flag & 1) + skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag); + else { + map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id); + } + break; + case MH_STAHL_HORN: + case MH_NEEDLE_OF_PARALYZE: + skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag); + break; + case 0:/* no skill - basic/normal attack */ if(sd) { if (flag & 3){ @@ -4545,11 +4579,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int break; default: - if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) { - if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd ) - clif_colormes(((TBL_HOM*)src)->master, COLOR_RED, "This skill is not yet supported"); - } else /* temporary until all the homun-s skills are supported otherwise console would fill up with pointless warnings */ - ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skillid); + ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skillid); clif_skill_damage(src, bl, tick, status_get_amotion(src), tstatus->dmotion, 0, abs(skill_get_num(skillid, skilllv)), skillid, skilllv, skill_get_hit(skillid)); @@ -4660,6 +4690,18 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex] return skill_castend_damage_id (src, bl, skillid, skilllv, tick, flag); + case MH_STEINWAND: { + struct block_list *s_src = battle_get_master(src); + short ret; + if(!skill_check_unit_range(src, src->x, src->y, skillid, skilllv)) //prevent reiteration + ret = skill_castend_pos2(src,src->x,src->y,skillid,skilllv,tick,flag); //cast on homon + if(s_src && !skill_check_unit_range(s_src, s_src->x, s_src->y, skillid, skilllv)) + ret |= skill_castend_pos2(s_src,s_src->x,s_src->y,skillid,skilllv,tick,flag); //cast on master + if (hd) + skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + return ret; + } + break; default: //Skill is actually ground placed. if (src == bl && skill_get_unit_id(skillid,0)) @@ -4961,7 +5003,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case SA_FORTUNE: clif_skill_nodamage(src,bl,skillid,skilllv,1); - if(sd) pc_getzeny(sd,status_get_lv(bl)*100); + if(sd) pc_getzeny(sd,status_get_lv(bl)*100,LOG_TYPE_OTHER,NULL); break; case SA_TAMINGMONSTER: clif_skill_nodamage(src,bl,skillid,skilllv,1); @@ -7213,12 +7255,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); } break; - case MH_STAHL_HORN: - if (sd) { - if( skillid == MH_GOLDENE_FERSE ) - clif_skill_fail(sd,skillid,USESKILL_FAIL_CONDITION,0); - } - break; + case HAMI_CASTLE: //[orn] if(rnd()%100 < 20*skilllv && src != bl) { @@ -7370,7 +7407,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case RK_IGNITIONBREAK: case LG_EARTHDRIVE: - case MH_LAVA_SLIDE: clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); i = skill_get_splash(skillid,skilllv); if( skillid == LG_EARTHDRIVE ) { @@ -8830,12 +8866,98 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_nodamage_id); } break; + + case MH_SILENT_BREEZE: { + struct status_change *ssc = status_get_sc(src); + struct block_list *m_bl = battle_get_master(src); + const enum sc_type scs[] = { + SC_MANDRAGORA, SC_HARMONIZE, SC_DEEPSLEEP, SC_VOICEOFSIREN, SC_SLEEP, SC_CONFUSION, SC_HALLUCINATION + }; + int heal; + if(tsc){ + for (i = 0; i < ARRAYLENGTH(scs); i++) { + if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); + } + if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target + status_change_start(bl, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8); + } + heal = status_get_matk_min(src)*4; + status_heal(bl, heal, 0, 7); + + //now inflict silence on everyone + if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun + status_change_start(src, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8); + if(m_bl){ + struct status_change *msc = status_get_sc(m_bl); + if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master + status_change_start(m_bl, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8); + } + if (hd) + skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + } + break; + case MH_OVERED_BOOST: + if (hd){ + struct block_list *s_bl = battle_get_master(src); + if(hd->homunculus.hunger>50) //reduce hunger + hd->homunculus.hunger = hd->homunculus.hunger/2; + else + hd->homunculus.hunger = min(1,hd->homunculus.hunger); + if(s_bl && s_bl->type==BL_PC){ + status_set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp + clif_send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info + sc_start(s_bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); //gene bonus + } + sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); + skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + } + break; + case MH_GRANITIC_ARMOR: + case MH_PYROCLASTIC: { + struct block_list *s_bl = battle_get_master(src); + if(s_bl) sc_start2(s_bl, type, 100, skilllv, hd->homunculus.level, skill_get_time(skillid, skilllv)); //start on master + sc_start2(bl, type, 100, skilllv, hd->homunculus.level, skill_get_time(skillid, skilllv)); + if (hd) skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + } + break; + + case MH_LIGHT_OF_REGENE: + if(hd){ + hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750) + if(sd) clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info + } + //don't break need to start status and start block timer + case MH_STYLE_CHANGE: + case MH_MAGMA_FLOW: + case MH_PAIN_KILLER: + sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); + if (hd) + skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + break; + case MH_SUMMON_LEGION: + { + int summons[5] = {1004, 1303, 1303, 1994, 1994}; + int qty[5] = {3 , 3 , 4 , 4 , 5}; + struct mob_data *md; + int i; + + for(i=0; im, src->x, src->y, status_get_name(src), summons[skilllv - 1], "", SZ_SMALL, AI_ATTACK); + if (md) { + md->master_id = src->id; + if (md->deletetimer != INVALID_TIMER) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer(gettick() + skill_get_time(skillid, skilllv), mob_timer_delete, md->bl.id, 0); + mob_spawn(md); //Now it is ready for spawning. + sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_ASSIST, 0, 60000); + } + } + if (hd) + skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv)); + } + break; default: - if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) { - if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd ) - clif_colormes(((TBL_HOM*)src)->master, COLOR_RED, "This skill is not yet supported"); - } else /* temporary until all the homun-s skills are supported otherwise console would fill up with pointless warnings */ - ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid); + ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid); clif_skill_nodamage(src,bl,skillid,skilllv,1); map_freeblock_unlock(); return 1; @@ -9548,11 +9670,15 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk case SO_WATER_INSIGNIA: case SO_WIND_INSIGNIA: case SO_EARTH_INSIGNIA: - case MH_POISON_MIST: case KO_HUUMARANKA: case KO_MUCHANAGE: case KO_BAKURETSU: case KO_ZENKAI: + case MH_LAVA_SLIDE: + case MH_VOLCANIC_ASH: + case MH_POISON_MIST: + case MH_STEINWAND: + case MH_XENO_SLASHER: flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). case GS_GROUNDDRIFT: //Ammo should be deleted right away. skill_unitsetting(src,skillid,skilllv,x,y,0); @@ -10018,15 +10144,12 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk for( i = 0; i < (skilllv+2); i++ ) { x = src->x - 1 + rnd()%3; y = src->y - 1 + rnd()%3; - skill_unitsetting(src,skillid,skilllv,x,y,0); + skill_unitsetting(src,skillid,skilllv,x,y,0); } break; + default: - if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) { - if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd ) - clif_colormes(((TBL_HOM*)src)->master, COLOR_RED, "This skill is not yet supported"); - } else /* temporary until all the homun-s skills are supported otherwise console would fill up with pointless warnings */ - ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid); + ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid); return 1; } @@ -10335,6 +10458,9 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli sc = status_get_sc(src); // for traps, firewall and fogwall - celest switch( skillid ) { + case MH_STEINWAND: + val2 = 4 + skilllv; //nb of attack blocked + break; case MG_SAFETYWALL: #ifdef RENEWAL /** @@ -10841,7 +10967,7 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un break; case UNT_SAFETYWALL: if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->group_id,sg->group_id,0,sg->limit); + sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit); break; case UNT_PNEUMA: @@ -10991,6 +11117,11 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); break; + case UNT_VOLCANIC_ASH: + if (!sce) + sc_start(bl, SC_ASH, 50, sg->skill_lv, skill_get_time(MH_VOLCANIC_ASH, sg->skill_lv)); //50% chance + break; + case UNT_GD_LEADERSHIP: case UNT_GD_GLORYWOUNDS: case UNT_GD_SOULCOLD: @@ -11703,6 +11834,16 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns sg->limit = DIFF_TICK(tick, sg->tick); sg->unit_id = UNT_USED_TRAPS; break; + + case UNT_LAVA_SLIDE: + skill_attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + if(++sg->val1 > 4) //after 5 stop hit and destroy me + sg->limit = DIFF_TICK(tick, sg->tick); + break; + case UNT_POISON_MIST: + skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + status_change_start(bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), 2|8); + break; } if (bl->type == BL_MOB && ss != bl) @@ -11807,6 +11948,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int //your own. Let's pray that scenario is pretty unlikely and noone will complain too much about it. status_change_end(bl, SC_DANCING, INVALID_TIMER); } + case MH_STEINWAND: case MG_SAFETYWALL: case AL_PNEUMA: case SA_VOLCANO: @@ -13139,7 +13281,7 @@ int skill_consume_requirement( struct map_session_data *sd, short skill, short l req.zeny = 0; //Zeny is reduced on skill_attack. if( sd->status.zeny < req.zeny ) req.zeny = sd->status.zeny; - pc_payzeny(sd,req.zeny); + pc_payzeny(sd,req.zeny,LOG_TYPE_OTHER,NULL); //@Need proper type } } @@ -13489,6 +13631,8 @@ int skill_castfix_sc (struct block_list *bl, int time) if (sc && sc->count) { if (sc->data[SC_SLOWCAST]) time += time * sc->data[SC_SLOWCAST]->val2 / 100; + if (sc->data[SC_PARALYSIS]) + time += sc->data[SC_PARALYSIS]->val3; if (sc->data[SC_SUFFRAGIUM]) { time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100; status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER); -- cgit v1.2.3-70-g09d2