diff options
author | rud0lp20 <rud0lp20@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-07-28 13:20:00 +0000 |
---|---|---|
committer | rud0lp20 <rud0lp20@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2012-07-28 13:20:00 +0000 |
commit | b746ecdef2ed9b57db672f43842f2434da4c79f8 (patch) | |
tree | d806065951ebba476cf5bb45bbf4380f29db6598 /src/map | |
parent | 3071aad50f5cab693678372c5d7c2285800bb5d9 (diff) | |
download | hercules-b746ecdef2ed9b57db672f43842f2434da4c79f8.tar.gz hercules-b746ecdef2ed9b57db672f43842f2434da4c79f8.tar.bz2 hercules-b746ecdef2ed9b57db672f43842f2434da4c79f8.tar.xz hercules-b746ecdef2ed9b57db672f43842f2434da4c79f8.zip |
Updated some skills to its RE behavior(AL_ANGELUS, RG_BACKSTAP, WZ_GRAVITATION, NJ_RAIGEKISAI).(bugreport:6342, bugreport:6336, bugreport:6339, bugreport:6331)
Added some Kagerou/Oboro skills. Special mega thanks to Judas :)
(KO_HUUMARANKA,KO_MEIKYOUSISUI,KO_ZANZOU,KO_KYOUGAKU,KO_JYUSATSU,KO_KAHU_ENTEN,KO_HYOUHU_HUBUKI,KO_KAZEHU_SEIRAN,KO_DOHU_KOUKAI)
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16520 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/battle.c | 41 | ||||
-rw-r--r-- | src/map/clif.c | 44 | ||||
-rw-r--r-- | src/map/clif.h | 2 | ||||
-rw-r--r-- | src/map/map.c | 1 | ||||
-rw-r--r-- | src/map/mob.h | 5 | ||||
-rw-r--r-- | src/map/pc.c | 112 | ||||
-rw-r--r-- | src/map/pc.h | 5 | ||||
-rw-r--r-- | src/map/skill.c | 96 | ||||
-rw-r--r-- | src/map/status.c | 65 | ||||
-rw-r--r-- | src/map/unit.c | 3 |
10 files changed, 353 insertions, 21 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index 34946aec6..a4f5985bd 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -351,6 +351,19 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER); } } + if( src->type == BL_PC || target->type == BL_PC ){ + struct map_session_data *sd = BL_CAST(BL_PC, src); + struct map_session_data *tsd = BL_CAST(BL_PC, target); + int s, t; + + ARR_FIND(1, 6, s, sd->talisman[s] > 0); + ARR_FIND(1, 6, t, tsd->talisman[t] > 0); + + if( s < 5 && atk_elem == s ) + ratio += sd->talisman[s] * 2; // +2% custom value + if( t < 5 && atk_elem == t ) + damage -= damage * tsd->talisman[t] * 3 / 100; // -3% custom value + } return damage*ratio/100; } @@ -705,6 +718,10 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag status_change_end(bl, SC_KYRIE, INVALID_TIMER); } + if( sc->data[SC_MEIKYOUSISUI] && rand()%100 < 40 ) // custom value + damage = 0; + + if (!damage) return 0; if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1 ) { @@ -1398,6 +1415,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo { //Take weapon's element s_ele = sstatus->rhw.ele; s_ele_ = sstatus->lhw.ele; + if( sd ){ //Summoning 10 talisman will endow your weapon. + ARR_FIND(1, 6, i, sd->talisman[i] >= 10); + if( i < 5) s_ele = s_ele_ = i; + } if( flag.arrow && sd && sd->bonus.arrow_ele ) s_ele = sd->bonus.arrow_ele; if( battle_config.attack_attr_none&src->type ) @@ -3310,9 +3331,13 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list //Initialize variables that will be used afterwards s_ele = skill_get_ele(skill_num, skill_lv); - if (s_ele == -1) // pl=-1 : the skill takes the weapon's element + if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element s_ele = sstatus->rhw.ele; - else if (s_ele == -2) //Use status element + if( sd ){ //Summoning 10 talisman will endow your weapon + ARR_FIND(1, 6, i, sd->talisman[i] > 0); + if( i < 5) s_ele = i; + } + }else if (s_ele == -2) //Use status element s_ele = status_get_attack_sc_element(src,status_get_sc(src)); else if( s_ele == -3 ) //Use random element s_ele = rnd()%ELE_MAX; @@ -4173,6 +4198,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * md.damage -= totaldef; } break; + case KO_MAKIBISHI: + md.damage = 20 * skill_lv; + break; } if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets @@ -4928,9 +4956,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f } break; case BL_MOB: - if((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres + if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres (((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras - s_bl->type == BL_PC && src->type != BL_MOB) + s_bl->type == BL_PC && src->type != BL_MOB) || ((TBL_MOB*)target)->special_state.ai == 4) //Zanzoe { //Targettable by players state |= BCT_ENEMY; strip_enemy = 0; @@ -5094,8 +5122,9 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f return 0; // Disable guardians/emperium owned by Guilds on non-woe times. if( !md->special_state.ai ) - { //Normal mobs. - if( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai ) + { //Normal mobs + if( (target->type == BL_MOB && t_bl->type == BL_PC && ((TBL_MOB*)target)->special_state.ai < 4) || + ( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai ) ) state |= BCT_PARTY; //Normal mobs with no ai are friends. else state |= BCT_ENEMY; //However, all else are enemies. diff --git a/src/map/clif.c b/src/map/clif.c index 25b53686a..13d4ebe8f 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1255,6 +1255,18 @@ static void clif_spiritball_single(int fd, struct map_session_data *sd) WFIFOSET(fd, packet_len(0x1e1)); } +/*========================================== + * Kagerou/Oboro amulet spirit + *------------------------------------------*/ +static void clif_talisman_single(int fd, struct map_session_data *sd, short type) +{ + WFIFOHEAD(fd, packet_len(0x08cf)); + WFIFOW(fd,0)=0x08cf; + WFIFOL(fd,2)=sd->bl.id; + WFIFOW(fd,6)=type; + WFIFOW(fd,8)=sd->talisman[type]; + WFIFOSET(fd, packet_len(0x08cf)); +} /*========================================== * Run when player changes map / refreshes @@ -1348,6 +1360,7 @@ int clif_spawn(struct block_list *bl) case BL_PC: { TBL_PC *sd = ((TBL_PC*)bl); + int i; if (sd->spiritball > 0) clif_spiritball(sd); if(sd->state.size==2) // tiny/big players [Valaris] @@ -1360,6 +1373,10 @@ int clif_spawn(struct block_list *bl) //New Mounts are not complaint to the original method, so we gotta tell this guy that he is mounting. clif_status_load_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0); } + for(i = 1; i < 5; i++){ + if( sd->talisman[i] > 0 ) + clif_talisman(sd, i); + } #ifdef NEW_CARTS if( sd->sc.data[SC_PUSH_CART] ) clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2, sd->sc.data[SC_PUSH_CART]->val1, 0, 0); @@ -4031,6 +4048,10 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d if(dstsd->spiritball > 0) clif_spiritball_single(sd->fd, dstsd); + for(i = 1; i < 5; i++){ + if( dstsd->talisman[i] > 0 ) + clif_talisman_single(sd->fd, dstsd, i); + } if( dstsd->sc.option&OPTION_MOUNTING ) { //New Mounts are not complaint to the original method, so we gotta tell this guy that I'm mounting. clif_status_load_single(sd->fd,dstsd->bl.id,SI_ALL_RIDING,2,1,0,0); @@ -8195,6 +8216,7 @@ void clif_message(struct block_list* bl, const char* msg) // refresh the client's screen, getting rid of any effects void clif_refresh(struct map_session_data *sd) { + int i; nullpo_retv(sd); clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y); @@ -8213,6 +8235,10 @@ void clif_refresh(struct map_session_data *sd) clif_updatestatus(sd,SP_LUK); if (sd->spiritball) clif_spiritball_single(sd->fd, sd); + for(i = 1; i < 5; i++){ + if( sd->talisman[i] > 0 ) + clif_talisman_single(sd->fd, sd, i); + } if (sd->vd.cloth_color) clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); if(merc_is_hom_active(sd->hd)) @@ -16123,7 +16149,21 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) { skill_select_menu(sd,RFIFOL(fd,2),RFIFOW(fd,6)); clif_menuskill_clear(sd); } +/*========================================== + * Kagerou/Oboro amulet spirit + *------------------------------------------*/ +void clif_talisman(struct map_session_data *sd,short type) +{ + unsigned char buf[8]; + + nullpo_retv(sd); + WBUFW(buf,0)=0x08cf; + WBUFL(buf,2)=sd->bl.id; + WBUFW(buf,6)=type; + WBUFW(buf,8)=sd->talisman[type]; + clif_send(buf,packet_len(0x08cf),&sd->bl,AREA); +} /// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE] /// 0907 <index>.W /// @@ -16549,7 +16589,7 @@ 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, //#0x08C0 - 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, 10, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -16557,7 +16597,7 @@ static int packetdb_readdb(void) 0, 0, 0, 0, 0, 0, 0, 0, 5, 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, 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, 0, 0, 0, 0, 0, 0, 0, }; struct { void (*func)(int, struct map_session_data *); diff --git a/src/map/clif.h b/src/map/clif.h index b6993a46b..ef404cee5 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -736,6 +736,8 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, int skill_id, int sk void clif_elemental_info(struct map_session_data *sd); void clif_elemental_updatestatus(struct map_session_data *sd, int type); +void clif_talisman(struct map_session_data *sd, short type); + /** * Color Table **/ diff --git a/src/map/map.c b/src/map/map.c index da2826c26..2239a2f23 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1707,6 +1707,7 @@ int map_quit(struct map_session_data *sd) { status_change_end(&sd->bl, SC_ENDURE, INVALID_TIMER); //No need to save infinite endure. status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER); status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER); + status_change_end(&sd->bl, SC_KYOUGAKU, INVALID_TIMER); if (battle_config.debuff_on_logout&1) { status_change_end(&sd->bl, SC_ORCISH, INVALID_TIMER); status_change_end(&sd->bl, SC_STRIPWEAPON, INVALID_TIMER); diff --git a/src/map/mob.h b/src/map/mob.h index 4a77a3abb..adbf65d5c 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -36,7 +36,7 @@ #define MOB_CLONE_END MAX_MOB_DB //Used to determine default enemy type of mobs (for use in eachinrange calls) -#define DEFAULT_ENEMY_TYPE(md) (md->special_state.ai?BL_CHAR:BL_PC|BL_HOM|BL_MER) +#define DEFAULT_ENEMY_TYPE(md) (md->special_state.ai?BL_CHAR:BL_MOB|BL_PC|BL_HOM|BL_MER) //Externals for the status effects. [Epoque] extern const int mob_manuk[8]; @@ -121,11 +121,12 @@ struct mob_data { char name[NAME_LENGTH]; struct { unsigned int size : 2; //Small/Big monsters. - unsigned int ai : 2; //Special ai for summoned monsters. + unsigned int ai : 3; //Special ai for summoned monsters. //0: Normal mob. //1: Standard summon, attacks mobs. //2: Alchemist Marine Sphere //3: Alchemist Summon Flora + //4: Summon Zanzou unsigned int clone : 1;/* is clone? 1:0 */ } special_state; //Special mob information that does not needs to be zero'ed on mob respawn. struct { diff --git a/src/map/pc.c b/src/map/pc.c index 0f04cc017..d7cfe66e1 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -878,6 +878,8 @@ int pc_isequip(struct map_session_data *sd,int n) return 0; if(item->equip & EQP_ACC && sd->sc.data[SC__STRIPACCESSORY]) return 0; + if(item->equip && sd->sc.data[SC_KYOUGAKU]) + return 0; if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SUPERNOVICE) { //Spirit of Super Novice equip bonuses. [Skotlex] @@ -6382,6 +6384,9 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if ( sd && sd->spiritball ) pc_delspiritball(sd,sd->spiritball,0); + for(i = 1; i < 5; i++) + pc_del_talisman(sd, sd->talisman[i], i); + if (src) switch (src->type) { case BL_MOB: @@ -8237,6 +8242,12 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) return 0; } + if( !(flag&2) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] ) + { + clif_unequipitemack(sd,n,0,0); + return 0; + } + if(battle_config.battle_log) ShowInfo("unequip %d %x:%x\n",n,pc_equippoint(sd,n),sd->status.inventory[n].equip); @@ -8846,6 +8857,106 @@ bool pc_should_log_commands(struct map_session_data *sd) return pc_group_should_log_commands(pc_get_group_id(sd)); } +static int pc_talisman_timer(int tid, unsigned int tick, int id, intptr_t data) +{ + struct map_session_data *sd; + int i, type; + + if( (sd=(struct map_session_data *)map_id2sd(id)) == NULL || sd->bl.type!=BL_PC ) + return 1; + + ARR_FIND(1, 5, type, sd->talisman[type] > 0); + + if( sd->talisman[type] <= 0 ) + { + ShowError("pc_talisman_timer: %d talisman's available. (aid=%d cid=%d tid=%d)\n", sd->talisman[type], sd->status.account_id, sd->status.char_id, tid); + sd->talisman[type] = 0; + return 0; + } + + ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == tid); + if( i == sd->talisman[type] ) + { + ShowError("pc_talisman_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid); + return 0; + } + + sd->talisman[type]--; + if( i != sd->talisman[type] ) + memmove(sd->talisman_timer[type]+i, sd->talisman_timer[type]+i+1, (sd->talisman[type]-i)*sizeof(int)); + sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER; + + clif_talisman(sd, type); + + return 0; +} + +int pc_add_talisman(struct map_session_data *sd,int interval,int max,int type) +{ + int tid, i; + + nullpo_ret(sd); + + if(max > 10) + max = 10; + if(sd->talisman[type] < 0) + sd->talisman[type] = 0; + + if( sd->talisman[type] && sd->talisman[type] >= max ) + { + if(sd->talisman_timer[type][0] != INVALID_TIMER) + delete_timer(sd->talisman_timer[type][0],pc_talisman_timer); + sd->talisman[type]--; + if( sd->talisman[type] != 0 ) + memmove(sd->talisman_timer[type]+0, sd->talisman_timer[type]+1, (sd->talisman[type])*sizeof(int)); + sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER; + } + + tid = add_timer(gettick()+interval, pc_talisman_timer, sd->bl.id, 0); + ARR_FIND(0, sd->talisman[type], i, sd->talisman_timer[type][i] == INVALID_TIMER || DIFF_TICK(get_timer(tid)->tick, get_timer(sd->talisman_timer[type][i])->tick) < 0); + if( i != sd->talisman[type] ) + memmove(sd->talisman_timer[type]+i+1, sd->talisman_timer[type]+i, (sd->talisman[type]-i)*sizeof(int)); + sd->talisman_timer[type][i] = tid; + sd->talisman[type]++; + + clif_talisman(sd, type); + return 0; +} + +int pc_del_talisman(struct map_session_data *sd,int count,int type) +{ + int i; + + nullpo_ret(sd); + + if( sd->talisman[type] <= 0 ) { + sd->talisman[type] = 0; + return 0; + } + + if( count <= 0 ) + return 0; + if( count > sd->talisman[type] ) + count = sd->talisman[type]; + sd->talisman[type] -= count; + if( count > 10 ) + count = 10; + + for(i = 0; i < count; i++) { + if(sd->talisman_timer[type][i] != INVALID_TIMER) { + delete_timer(sd->talisman_timer[type][i],pc_talisman_timer); + sd->talisman_timer[type][i] = INVALID_TIMER; + } + } + for(i = count; i < 10; i++) { + sd->talisman_timer[type][i-count] = sd->talisman_timer[type][i]; + sd->talisman_timer[type][i] = INVALID_TIMER; + } + + clif_talisman(sd, type); + return 0; +} + int pc_split_str(char *str,char **val,int num) { int i; @@ -9262,6 +9373,7 @@ int do_init_pc(void) { add_timer_func_list(pc_spiritball_timer, "pc_spiritball_timer"); add_timer_func_list(pc_follow_timer, "pc_follow_timer"); add_timer_func_list(pc_endautobonus, "pc_endautobonus"); + add_timer_func_list(pc_talisman_timer, "pc_talisman_timer"); add_timer(gettick() + autosave_interval, pc_autosave, 0, 0); diff --git a/src/map/pc.h b/src/map/pc.h index 269bc65dc..05ffb0c72 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -332,6 +332,8 @@ struct map_session_data { short spiritball, spiritball_old; int spirit_timer[MAX_SKILL_LEVEL]; + short talisman[5]; + int talisman_timer[5][10]; unsigned char potion_success_counter; //Potion successes in row counter unsigned char mission_count; //Stores the bounty kill count for TK_MISSION @@ -918,4 +920,7 @@ void pc_itemcd_do(struct map_session_data *sd, bool load); int pc_load_combo(struct map_session_data *sd); +int pc_add_talisman(struct map_session_data *sd,int interval,int max,int type); +int pc_del_talisman(struct map_session_data *sd,int count,int type); + #endif /* _PC_H_ */ diff --git a/src/map/skill.c b/src/map/skill.c index ce3d9df25..f93d5b772 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -953,6 +953,10 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int #ifdef RENEWAL sc_start(bl,SC_RAID,100,7,5000); + break; + + case RG_BACKSTAP: + sc_start(bl,SC_STUN,(5+2*skilllv),skilllv,skill_get_time(skillid,skilllv)); #endif break; @@ -1345,6 +1349,9 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int 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; } if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) @@ -3663,6 +3670,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case MH_LAVA_SLIDE: case KO_HAPPOKUNAI: case KO_HUUMARANKA: + case KO_MUCHANAGE: + case KO_BAKURETSU: if( flag&1 ) {//Recursive invocation // skill_area_temp[0] holds number of targets in area // skill_area_temp[1] holds the id of the original target @@ -5163,7 +5172,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SR_CRESCENTELBOW: case SR_LIGHTNINGWALK: case SR_GENTLETOUCH_ENERGYGAIN: - case GN_CARTBOOST: + case GN_CARTBOOST: + case KO_MEIKYOUSISUI: clif_skill_nodamage(src,bl,skillid,skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); break; @@ -8660,7 +8670,57 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in } } break; - + + case KO_KAHU_ENTEN: + case KO_HYOUHU_HUBUKI: + case KO_KAZEHU_SEIRAN: + case KO_DOHU_KOUKAI: + if(sd) { + int ttype = skill_get_ele(skillid, skilllv); + clif_skill_nodamage(src, bl, skillid, skilllv, 1); + pc_add_talisman(sd, skill_get_time(skillid, skilllv), 10, ttype); + } + break; + + case KO_ZANZOU: + if(sd){ + struct mob_data *md; + + md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), 2308, ""); + if( md ) + { + md->master_id = src->id; + md->special_state.ai = 4; + 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 ); + pc_setinvincibletimer(sd,500);// unlock target lock + clif_skill_nodamage(src,bl,skillid,skilllv,1); + skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),unit_getdir(bl),0); + } + } + break; + + case KO_KYOUGAKU: + if( dstsd && tsc && !tsc->data[type] && rand()%100 < tstatus->int_/2 ){ + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + }else if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + + case KO_JYUSATSU: + if( dstsd && tsc && !tsc->data[type] && rand()%100 < tstatus->int_/2 ){ + clif_skill_nodamage(src,bl,skillid,skilllv, + status_change_start(bl,type,10000,skilllv,0,0,0,skill_get_time(skillid,skilllv),1)); + status_zap(bl, tstatus->max_hp*skilllv*5/100 , 0); + if( status_get_lv(bl) <= status_get_lv(src) ) + status_change_start(bl,SC_COMA,10,skilllv,0,src->id,0,0,0); + }else if( sd ) + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); + break; + default: if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) { if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd ) @@ -9383,6 +9443,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk case KO_HUUMARANKA: case KO_MUCHANAGE: case KO_BAKURETSU: + //case KO_MAKIBISHI: 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); @@ -10961,8 +11022,6 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns default: skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); } - if( skill_get_unit_interval(sg->skill_id) >= skill_get_time(sg->skill_id,sg->skill_lv) ) - sg->unit_id = UNT_USED_TRAPS; break; case UNT_FIREPILLAR_WAITING: @@ -11050,6 +11109,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_FLASHER: case UNT_FREEZINGTRAP: case UNT_FIREPILLAR_ACTIVE: + case UNT_MAKIBISHI: map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); if (sg->unit_id != UNT_FIREPILLAR_ACTIVE) clif_changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); @@ -11817,7 +11877,7 @@ static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list skill=va_arg(ap,int); c=va_arg(ap,int *); - if( md->master_id != src_id || md->special_state.ai != (unsigned)(skill == AM_SPHEREMINE?2:3) ) + if( md->master_id != src_id || md->special_state.ai != (unsigned)(skill == AM_SPHEREMINE?2:skill == KO_ZANZOU?4:3) ) return 0; //Non alchemist summoned mobs have nothing to do here. if(md->class_==mob_class) @@ -12460,7 +12520,20 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh clif_skill_fail(sd,skill,USESKILL_FAIL_LEVEL,0); return 0; } - break; + break; + case KO_KAHU_ENTEN: + case KO_HYOUHU_HUBUKI: + case KO_KAZEHU_SEIRAN: + case KO_DOHU_KOUKAI: + { + int ttype = skill_get_ele(skill, lv); + ARR_FIND(1, 5, i, sd->talisman[i] > 0 && i != ttype); + if( (i < 5 && i != ttype) || sd->talisman[ttype] >= 10 ){ + clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0); + return 0; + } + } + break; } switch(require.state) { @@ -12722,6 +12795,17 @@ int skill_check_condition_castend(struct map_session_data* sd, short skill, shor } } break; + case KO_ZANZOU: + { + int c = 0; + i = map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, 2308, skill, &c); + if( c >= skill_get_maxcount(skill,lv) || c != i) + { + clif_skill_fail(sd , skill, USESKILL_FAIL_LEVEL, 0); + return 0; + } + } + break; } status = &sd->battle_status; diff --git a/src/map/status.c b/src/map/status.c index 5b401d87f..fbeb7214f 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -286,7 +286,10 @@ void initChangeTables(void) { set_sc( NPC_HALLUCINATION , SC_HALLUCINATION , SI_HALLUCINATION , SCB_NONE ); add_sc( NPC_REBIRTH , SC_REBIRTH ); add_sc( RG_RAID , SC_STUN ); +#ifdef RENEWAL add_sc( RG_RAID , SC_RAID ); + add_sc( RG_BACKSTAP , SC_STUN ); +#endif set_sc( RG_STRIPWEAPON , SC_STRIPWEAPON , SI_STRIPWEAPON , SCB_WATK ); set_sc( RG_STRIPSHIELD , SC_STRIPSHIELD , SI_STRIPSHIELD , SCB_DEF ); set_sc( RG_STRIPARMOR , SC_STRIPARMOR , SI_STRIPARMOR , SCB_VIT ); @@ -705,9 +708,14 @@ void initChangeTables(void) { set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_NONE ); set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL ); set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF ); - set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED ); + set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED ); + add_sc( KO_YAMIKUMO , SC_HIDING ); set_sc( KO_JYUMONJIKIRI , SC_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE ); + add_sc( KO_MAKIBISHI , SC_STUN ); + set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE ); + set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + add_sc( KO_JYUSATSU , SC_CURSE ); add_sc( MH_STAHL_HORN , SC_STUN ); set_sc( MH_ANGRIFFS_MODUS , SC_ANGRIFFS_MODUS , SI_ANGRIFFS_MODUS , SCB_BATK|SCB_WATK|SCB_DEF|SCB_FLEE ); @@ -985,7 +993,8 @@ void initChangeTables(void) { StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOMOVE|SCS_NOMOVECOND; StatusChangeStateTable[SC_NETHERWORLD] |= SCS_NOMOVE; StatusChangeStateTable[SC_CAMOUFLAGE] |= SCS_NOMOVE|SCS_NOMOVECOND; - + StatusChangeStateTable[SC_MEIKYOUSISUI] |= SCS_NOMOVE; + /* StatusChangeState (SCS_) NOPICKUPITEMS */ StatusChangeStateTable[SC_HIDING] |= SCS_NOPICKITEM; StatusChangeStateTable[SC_CLOAKING] |= SCS_NOPICKITEM; @@ -1895,7 +1904,7 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev #ifdef RENEWAL // renewal formulas status->hit += level + status->dex + status->luk/3 + 175; //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175 status->flee += level + status->agi + status->luk/5 + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 - status->def2 += (int)(((float)level + status->vit)/2 + ((float)status->agi/5)); //base level + (every 2 agi = +1 def) + (every 5 agi = +1 def) + status->def2 += (int)(((float)level + status->vit)/2 + ((float)status->agi/5)); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def) status->mdef2 += (int)(status->int_ + ((float)level/4) + ((float)status->dex/5) + ((float)status->vit/5)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef) #else status->hit += level + status->dex; @@ -2009,6 +2018,8 @@ int status_calc_mob_(struct mob_data* md, bool first) { // different levels of HP according to skill level if (ud->skillid == AM_SPHEREMINE) { status->max_hp = 2000 + 400*ud->skilllv; + } else if(ud->skillid == KO_ZANZOU){ + status->max_hp = 3000 + 3000 * ud->skilllv; } else { //AM_CANNIBALIZE status->max_hp = 1500 + 200*ud->skilllv + 10*status_get_lv(mbl); status->mode|= MD_CANATTACK|MD_AGGRESSIVE; @@ -4054,6 +4065,8 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang str += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) str -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_KYOUGAKU]) + str -= sc->data[SC_KYOUGAKU]->val2; return (unsigned short)cap_value(str,0,USHRT_MAX); } @@ -4103,7 +4116,8 @@ static unsigned short status_calc_agi(struct block_list *bl, struct status_chang agi += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) agi -= sc->data[SC_STOMACHACHE]->val1; - + if(sc->data[SC_KYOUGAKU]) + agi -= sc->data[SC_KYOUGAKU]->val2; return (unsigned short)cap_value(agi,0,USHRT_MAX); } @@ -4145,6 +4159,8 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang vit += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) vit -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_KYOUGAKU]) + vit -= sc->data[SC_KYOUGAKU]->val2; return (unsigned short)cap_value(vit,0,USHRT_MAX); } @@ -4196,6 +4212,8 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang int_ += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) int_ -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_KYOUGAKU]) + int_ -= sc->data[SC_KYOUGAKU]->val2; return (unsigned short)cap_value(int_,0,USHRT_MAX); } @@ -4247,6 +4265,8 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang dex += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) dex -= sc->data[SC_STOMACHACHE]->val1; + if(sc->data[SC_KYOUGAKU]) + dex -= sc->data[SC_KYOUGAKU]->val2; return (unsigned short)cap_value(dex,0,USHRT_MAX); } @@ -4290,7 +4310,8 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang luk -= sc->data[SC_STOMACHACHE]->val1; if(sc->data[SC_BANANA_BOMB]) luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100; - + if(sc->data[SC_KYOUGAKU]) + luk -= sc->data[SC_KYOUGAKU]->val2; return (unsigned short)cap_value(luk,0,USHRT_MAX); } @@ -4736,8 +4757,13 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change return 0; if(sc->data[SC_SUN_COMFORT]) def2 += sc->data[SC_SUN_COMFORT]->val2; + if(sc->data[SC_ANGELUS]) +#ifdef RENEWAL //in renewal only the VIT stat bonus is boosted by angelus + def2 += status_get_vit(bl) / 2 * sc->data[SC_ANGELUS]->val2/100; +#else def2 += def2 * sc->data[SC_ANGELUS]->val2/100; +#endif if(sc->data[SC_CONCENTRATION]) def2 -= def2 * sc->data[SC_CONCENTRATION]->val4/100; if(sc->data[SC_POISON]) @@ -6063,6 +6089,9 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti case SC_MANDRAGORA: sc_def = (status->vit+status->luk)/5; break; + case SC_KYOUGAKU: + tick -= 30*status->int_; + break; default: //Effect that cannot be reduced? Likely a buff. if (!(rnd()%10000 < rate)) @@ -6696,6 +6725,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_FIGHTINGSPIRIT: status_change_end(bl, type, INVALID_TIMER); // Remove previous one. break; + case SC_MARSHOFABYSS: + status_change_end(bl, SC_INCAGI, INVALID_TIMER); + status_change_end(bl, SC_WINDWALK, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION0, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION1, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION3, INVALID_TIMER); + break; case SC_SWINGDANCE: case SC_SYMPHONYOFLOVER: case SC_MOONLITSERENADE: @@ -7847,6 +7884,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_ELECTRICSHOCKER: case SC_CRYSTALIZE: + case SC_MEIKYOUSISUI: val4 = tick / 1000; if( val4 < 1 ) val4 = 1; @@ -8219,6 +8257,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val4 = tick / 10000; tick_time = 10000; // [GodLesZ] tick time break; + case SC_KYOUGAKU: + val2 = 2*val1 + rand()%val1; + clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); // Temporarily shows Poring need official [malufett] + break; default: if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 ) @@ -8275,6 +8317,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_CURSEDCIRCLE_TARGET: case SC_FEAR: case SC_NETHERWORLD: + case SC_MEIKYOUSISUI: unit_stop_walking(bl,1); break; case SC_HIDING: @@ -9139,6 +9182,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } } break; + case SC_KYOUGAKU: + clif_status_load(bl, SI_KYOUGAKU, 0); // Avoid client crash + clif_status_load(bl, SI_ACTIVE_MONSTER_TRANSFORM, 0); + break; } opt_flag = 1; @@ -10142,6 +10189,14 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) /* they only end by status_change_end */ sc_timer_next(600000 + tick, status_change_timer, bl->id, data); return 0; + case SC_MEIKYOUSISUI: + if( --(sce->val4) > 0 ) + { + status_heal(bl, status->max_hp * (sce->val1+1) / 100, status->max_sp * sce->val1 / 100, 0); + sc_timer_next(1000 + tick, status_change_timer, bl->id, data); + return 0; + } + break; } // default for all non-handled control paths is to end the status diff --git a/src/map/unit.c b/src/map/unit.c index a65aafb97..26ff0f0fe 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2231,6 +2231,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) case BL_PC: { struct map_session_data *sd = (struct map_session_data*)bl; + int i; if( status_isdead(bl) ) pc_setrestartvalue(sd,2); @@ -2253,6 +2254,8 @@ int unit_free(struct block_list *bl, clr_type clrtype) pc_cleareventtimer(sd); pc_inventory_rental_clear(sd); pc_delspiritball(sd,sd->spiritball,1); + for(i = 1; i < 5; i++) + pc_del_talisman(sd, sd->talisman[i], i); if( sd->reg ) { //Double logout already freed pointer fix... [Skotlex] aFree(sd->reg); |