Jump to content

joecalis

Members
  • Content Count

    37
  • Avg. Content Per Day

    0
  • Joined

  • Last visited

  • Days Won

    1

joecalis last won the day on October 26 2019

joecalis had the most liked content!

Community Reputation

16 Good

About joecalis

  • Rank
    Drops

Profile Information

  • Gender
    Male
  • Location
    Your Heart
  • Interests
    Games, Anime, K-Pop

Recent Profile Visitors

1,985 profile views
  1. Change it to this: case ALL_ODINS_POWER: if( sd != NULL ) { if(skill_id == ALL_ODINS_POWER){ clif_specialeffect(bl, 75, AREA); clif_specialeffect(bl, 99, AREA); } clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); } break;
  2. Here you go: int64 skill_attack (int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) { struct Damage dmg; struct status_data *sstatus, *tstatus; struct status_change *sc, *tsc; struct map_session_data *sd, *tsd; int64 damage; int8 rmdamage = 0;//magic reflected int type; enum e_damage_type dmg_type; bool shadow_flag = false; bool additional_effects = true; if(skill_id > 0 && !skill_lv) return 0; nullpo_ret(src); //Source is the master behind the attack (player/mob/pet) nullpo_ret(dsrc); //dsrc is the actual originator of the damage, can be the same as src, or a skill casted by src. nullpo_ret(bl); //Target to be attacked. if (status_bl_has_mode(bl,MD_SKILL_IMMUNE) || (status_get_class(bl) == MOBID_EMPERIUM && !(skill_get_inf3(skill_id)&INF3_HIT_EMP))) return 0; if (src != dsrc) { //When caster is not the src of attack, this is a ground skill, and as such, do the relevant target checking. [Skotlex] if (!status_check_skilluse(battle_config.skill_caster_check?src:NULL, bl, skill_id, 2)) return 0; } else if ((flag&SD_ANIMATION) && skill_get_nk(skill_id)&NK_SPLASH) { //Note that splash attacks often only check versus the targetted mob, those around the splash area normally don't get checked for being hidden/cloaked/etc. [Skotlex] if (!status_check_skilluse(src, bl, skill_id, 2)) return 0; } sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, bl); sstatus = status_get_status_data(src); tstatus = status_get_status_data(bl); sc= status_get_sc(src); tsc= status_get_sc(bl); if (tsc && !tsc->count) tsc = NULL; //Don't need it. //Trick Dead protects you from damage, but not from buffs and the like, hence it's placed here. if (tsc && tsc->data[SC_TRICKDEAD]) return 0; //When Gravitational Field is active, damage can only be dealt by Gravitational Field and Autospells if(sd && sc && sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF && skill_id != HW_GRAVITATION && !sd->state.autocast) return 0; dmg = battle_calc_attack(attack_type,src,bl,skill_id,skill_lv,flag&0xFFF); //If the damage source is a unit, the damage is not delayed if (src != dsrc && skill_id != GS_GROUNDDRIFT) dmg.amotion = 0; //! CHECKME: This check maybe breaks the battle_calc_attack, and maybe need better calculation. // Adjusted to the new system [Skotlex] if( src->type == BL_PET ) { // [Valaris] struct pet_data *pd = (TBL_PET*)src; if (pd->a_skill && pd->a_skill->div_ && pd->a_skill->id == skill_id) { //petskillattack2 if (battle_config.pet_ignore_infinite_def || !is_infinite_defense(bl,dmg.flag)) { int element = skill_get_ele(skill_id, skill_lv); /*if (skill_id == -1) Does it ever worked? element = sstatus->rhw.ele;*/ if (element != ELE_NEUTRAL || !(battle_config.attack_attr_none&BL_PET)) dmg.damage = battle_attr_fix(src, bl, pd->a_skill->damage, element, tstatus->def_ele, tstatus->ele_lv); else dmg.damage = pd->a_skill->damage; // Fixed damage } else dmg.damage = 1*pd->a_skill->div_; dmg.damage2 = 0; dmg.div_= pd->a_skill->div_; } } if( dmg.flag&BF_MAGIC && ( skill_id != NPC_EARTHQUAKE || (battle_config.eq_single_target_reflectable && (flag&0xFFF) == 1) ) ) { // Earthquake on multiple targets is not counted as a target skill. [Inkfish] if( (dmg.damage || dmg.damage2) && (type = skill_magic_reflect(src, bl, src==dsrc)) ) { //Magic reflection, switch caster/target struct block_list *tbl = bl; rmdamage = 1; bl = src; src = tbl; dsrc = tbl; sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, bl); tsc = status_get_sc(bl); if (tsc && !tsc->count) tsc = NULL; //Don't need it. /* bugreport:2564 flag&2 disables double casting trigger */ flag |= 2; //Reflected magic damage will not cause the caster to be knocked back [Playtester] flag |= 4; //Spirit of Wizard blocks Kaite's reflection if( type == 2 && tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_WIZARD ) { //Consume one Fragment per hit of the casted skill? [Skotlex] type = tsd?pc_search_inventory (tsd, ITEMID_FRAGMENT_OF_CRYSTAL):0; if (type >= 0) { if ( tsd ) pc_delitem(tsd, type, 1, 0, 1, LOG_TYPE_CONSUME); dmg.damage = dmg.damage2 = 0; dmg.dmg_lv = ATK_MISS; tsc->data[SC_SPIRIT]->val3 = skill_id; tsc->data[SC_SPIRIT]->val4 = dsrc->id; } } else if( type != 2 ) /* Kaite bypasses */ additional_effects = false; if( type != 0 ) dsrc = bl; // Official Magic Reflection Behavior : damage reflected depends on gears caster wears, not target #if MAGIC_REFLECTION_TYPE #ifdef RENEWAL if( dmg.dmg_lv != ATK_MISS ) { //Wiz SL cancelled and consumed fragment #else // issue:6415 in pre-renewal Kaite reflected the entire damage received // regardless of caster's equipment (Aegis 11.1) if( dmg.dmg_lv != ATK_MISS && type == 1 ) { //Wiz SL cancelled and consumed fragment #endif short s_ele = skill_get_ele(skill_id, skill_lv); if (s_ele == -1) // the skill takes the weapon's element s_ele = sstatus->rhw.ele; 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_ALL; dmg.damage = battle_attr_fix(bl, bl, dmg.damage, s_ele, status_get_element(bl), status_get_element_level(bl)); if( tsc && tsc->data[SC_ENERGYCOAT] ) { struct status_data *status = status_get_status_data(bl); int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval per /=20; //Uses 20% SP intervals. //SP Cost: 1% + 0.5% per every 20% SP if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000)) status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER); //Reduction: 6% + 6% every 20% dmg.damage -= dmg.damage * (6 * (1+per)) / 100; } } #endif } if(tsc && tsc->data[SC_MAGICROD] && src == dsrc) { int sp = skill_get_sp(skill_id,skill_lv); #ifndef RENEWAL clif_skill_nodamage(bl,bl,SA_MAGICROD,skill_lv,1); #endif dmg.damage = dmg.damage2 = 0; dmg.dmg_lv = ATK_MISS; //This will prevent skill additional effect from taking effect. [Skotlex] sp = sp * tsc->data[SC_MAGICROD]->val2 / 100; if(skill_id == WZ_WATERBALL && skill_lv > 1) sp = sp/((skill_lv|1)*(skill_lv|1)); //Estimate SP cost of a single water-ball status_heal(bl, 0, sp, 2); } if( (dmg.damage || dmg.damage2) && tsc && tsc->data[SC_HALLUCINATIONWALK] && rnd()%100 < tsc->data[SC_HALLUCINATIONWALK]->val3 ) { dmg.damage = dmg.damage2 = 0; dmg.dmg_lv = ATK_MISS; } } damage = dmg.damage + dmg.damage2; if( (skill_id == AL_INCAGI || skill_id == AL_BLESSING || skill_id == CASH_BLESSING || skill_id == CASH_INCAGI || skill_id == MER_INCAGI || skill_id == MER_BLESSING) && tsd->sc.data[SC_CHANGEUNDEAD] ) damage = 1; if( damage && tsc && tsc->data[SC_GENSOU] && dmg.flag&BF_MAGIC ){ struct block_list *nbl; nbl = battle_getenemyarea(bl,bl->x,bl->y,2,BL_CHAR,bl->id); if( nbl ){ // Only one target is chosen. damage = damage / 2; // Deflect half of the damage to a target nearby clif_skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,damage,0), dmg.div_, OB_OBOROGENSOU_TRANSITION_ATK, -1, DMG_SKILL); } } //Skill hit type dmg_type = (skill_id == 0) ? DMG_SPLASH : skill_get_hit(skill_id); switch( skill_id ) { case WL_HELLINFERNO: if (dmg.dmg_lv == ATK_DEF && !(flag&ELE_DARK)) // Burning only starts if the fire attack successfully lands sc_start4(src, bl, SC_BURNING, 55 + 5 * skill_lv, skill_lv, 1000, src->id, 0, skill_get_time(skill_id, skill_lv)); break; case SC_TRIANGLESHOT: if( rnd()%100 > (1 + skill_lv) ) dmg.blewcount = 0; break; default: if (damage < dmg.div_ && skill_id != CH_PALMSTRIKE) dmg.blewcount = 0; //only pushback when it hit for other break; } switch( skill_id ) { case CR_GRANDCROSS: case NPC_GRANDDARKNESS: if( battle_config.gx_disptype) dsrc = src; if( src == bl) dmg_type = DMG_ENDURE; else flag|= SD_ANIMATION; break; case NJ_TATAMIGAESHI: //For correct knockback. dsrc = src; flag|= SD_ANIMATION; break; case TK_COUNTER: { //bonus from SG_FRIEND [Komurka] int level; if( sd && sd->status.party_id > 0 && (level = pc_checkskill(sd,SG_FRIEND)) ) party_skill_check(sd, sd->status.party_id, TK_COUNTER,level); } break; case SL_STIN: case SL_STUN: if (skill_lv >= 7) { struct status_change *sc_cur = status_get_sc(src); if (sc_cur && !sc_cur->data[SC_SMA]) sc_start(src,src,SC_SMA,100,skill_lv,skill_get_time(SL_SMA, skill_lv)); } break; case GS_FULLBUSTER: if (sd) //Can't attack nor use items until skill's delay expires. [Skotlex] sd->ud.attackabletime = sd->canuseitem_tick = sd->ud.canact_tick; break; } //combo handling skill_combo(src,dsrc,bl,skill_id,skill_lv,tick); //Display damage. switch( skill_id ) { case PA_GOSPEL: //Should look like Holy Cross [Skotlex] dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, DMG_SPLASH); break; //Skills that need be passed as a normal attack for the client to display correctly. case HVAN_EXPLOSION: case NPC_SELFDESTRUCTION: if(src->type == BL_PC) dmg.blewcount = 10; dmg.amotion = 0; //Disable delay or attack will do no damage since source is dead by the time it takes effect. [Skotlex] // fall through case KN_AUTOCOUNTER: case NPC_CRITICALSLASH: case TF_DOUBLE: case GS_CHAINACTION: dmg.dmotion = clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2,false); break; case AS_SPLASHER: if( flag&SD_ANIMATION ) // the surrounding targets dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, DMG_SPLASH); // needs -1 as skill level else // the central target doesn't display an animation dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -2, DMG_SPLASH); // needs -2(!) as skill level break; case GN_SPORE_EXPLOSION: dmg.dmotion = clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, DMG_SPLASH); break; case WL_HELLINFERNO: case SR_EARTHSHAKER: dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,-2,DMG_SKILL); break; case WL_SOULEXPANSION: case WL_COMET: case NPC_COMET: case KO_MUCHANAGE: case NJ_HUUMA: dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,DMG_MULTI_HIT); break; case WL_CHAINLIGHTNING_ATK: dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING_ATK,-2,DMG_SKILL); break; case WL_TETRAVORTEX_FIRE: dmg.dmotion = clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, WL_TETRAVORTEX_WIND, -1, DMG_SPLASH); break; case LG_SHIELDPRESS: dmg.dmotion = clif_skill_damage(dsrc, bl, tick, status_get_amotion(src), dmg.dmotion, damage, dmg.div_, skill_id, -1, DMG_SKILL); break; case LG_OVERBRAND: case LG_OVERBRAND_BRANDISH: dmg.amotion = status_get_amotion(src) * 2; case LG_OVERBRAND_PLUSATK: dmg.dmotion = clif_skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,DMG_SPLASH); break; case EL_FIRE_BOMB: case EL_FIRE_BOMB_ATK: case EL_FIRE_WAVE: case EL_FIRE_WAVE_ATK: case EL_FIRE_MANTLE: case EL_CIRCLE_OF_FIRE: case EL_FIRE_ARROW: case EL_ICE_NEEDLE: case EL_WATER_SCREW: case EL_WATER_SCREW_ATK: case EL_WIND_SLASH: case EL_TIDAL_WEAPON: case EL_ROCK_CRUSHER: case EL_ROCK_CRUSHER_ATK: case EL_HURRICANE: case EL_HURRICANE_ATK: case KO_BAKURETSU: case GN_CRAZYWEED_ATK: case NC_MAGMA_ERUPTION: case SU_SV_ROOTTWIST_ATK: dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,DMG_SPLASH); break; case GN_FIRE_EXPANSION_ACID: dmg.dmotion = clif_skill_damage(dsrc, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, CR_ACIDDEMONSTRATION, skill_lv, DMG_MULTI_HIT); break; case GN_SLINGITEM_RANGEMELEEATK: dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,DMG_SKILL); break; case EL_STONE_RAIN: dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?DMG_MULTI_HIT:DMG_SPLASH); break; case WM_SEVERE_RAINSTORM_MELEE: dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,-2,DMG_SPLASH); break; case SR_TIGERCANNON: dmg.dmotion = clif_skill_damage(src, bl, tick, status_get_amotion(bl), dmg.dmotion, damage, dmg.div_, skill_id, skill_lv, DMG_SKILL); break; case HT_CLAYMORETRAP: case HT_BLASTMINE: case HT_FLASHER: case HT_FREEZINGTRAP: case RA_CLUSTERBOMB: case RA_FIRINGTRAP: case RA_ICEBOUNDTRAP: dmg.dmotion = clif_skill_damage(src, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, DMG_SPLASH); if( dsrc != src ) // avoid damage display redundancy break; //Fall through case HT_LANDMINE: dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, dmg_type); break; case WZ_SIGHTBLASTER: //Sightblaster should never call clif_skill_damage twice dmg.dmotion = clif_skill_damage(src, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, DMG_SPLASH); break; case RL_R_TRIP_PLUSATK: case RL_S_STORM: dmg.dmotion = clif_skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,DMG_SPLASH); break; case AB_DUPLELIGHT_MELEE: case AB_DUPLELIGHT_MAGIC: dmg.amotion = 300;/* makes the damage value not overlap with previous damage (when displayed by the client) */ default: if( flag&SD_ANIMATION && dmg.div_ < 2 ) //Disabling skill animation doesn't works on multi-hit. dmg_type = DMG_SPLASH; if (src->type == BL_SKILL) { TBL_SKILL *su = (TBL_SKILL*)src; if (su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP) { // show damage on trap targets clif_skill_damage(src, bl, tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL ? -1 : skill_lv, DMG_SPLASH); break; } } dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, dmg_type); break; } map_freeblock_lock(); if (bl->type == BL_PC && skill_id && skill_get_index(skill_id) > 0 && skill_db[skill_get_index(skill_id)]->copyable.option && //Only copy skill that copyable [Cydh] dmg.flag&BF_SKILL && dmg.damage+dmg.damage2 > 0 && damage < status_get_hp(bl)) //Cannot copy skills if the blow will kill you. [Skotlex] skill_do_copy(src,bl,skill_id,skill_lv); if (dmg.dmg_lv >= ATK_MISS && (type = skill_get_walkdelay(skill_id, skill_lv)) > 0) { //Skills with can't walk delay also stop normal attacking for that //duration when the attack connects. [Skotlex] struct unit_data *ud = unit_bl2ud(src); if (ud && DIFF_TICK(ud->attackabletime, tick + type) < 0) ud->attackabletime = tick + type; } shadow_flag = skill_check_shadowform(bl, damage, dmg.div_); // Instant damage if( !dmg.amotion ) { if( (!tsc || (!tsc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD && !tsc->data[SC_WATER_SCREEN_OPTION]) || skill_id == HW_GRAVITATION || skill_id == NPC_EVILLAND) && !shadow_flag ) status_fix_damage(src,bl,damage,dmg.dmotion); //Deal damage before knockback to allow stuff like firewall+storm gust combo. if( !status_isdead(bl) && additional_effects ) skill_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick); if( damage > 0 ) //Counter status effects [Skotlex] skill_counter_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,tick); } // Blow! if (!(flag&4)) skill_attack_blow(src, dsrc, bl, (uint8)dmg.blewcount, skill_id, skill_lv, damage, tick, flag); // Delayed damage must be dealt after the knockback (it needs to know actual position of target) if( dmg.amotion ) { if( shadow_flag ) { if( !status_isdead(bl) && additional_effects ) skill_additional_effect(src, bl, skill_id, skill_lv, dmg.flag, dmg.dmg_lv, tick); if( dmg.flag > ATK_BLOCK ) skill_counter_additional_effect(src, bl, skill_id, skill_lv, dmg.flag, tick); } else battle_delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects, false); } if (tsc && skill_id != PA_PRESSURE && skill_id != HW_GRAVITATION && skill_id != NPC_EVILLAND) { if (tsc->data[SC_DEVOTION]) { struct status_change_entry *sce = tsc->data[SC_DEVOTION]; struct block_list *d_bl = map_id2bl(sce->val1); if (d_bl && ( (d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id) || (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == bl->id) ) && check_distance_bl(bl, d_bl, sce->val3) ) { if (!rmdamage) { clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0, false); status_fix_damage(NULL, d_bl, damage, 0); } else { bool isDevotRdamage = false; if (battle_config.devotion_rdamage && battle_config.devotion_rdamage > rnd()%100) isDevotRdamage = true; // If !isDevotRdamage, reflected magics are done directly on the target not on paladin // This check is only for magical skill. // For BF_WEAPON skills types track var rdamage and function battle_calc_return_damage clif_damage(bl, (!isDevotRdamage) ? bl : d_bl, gettick(), 0, 0, damage, 0, DMG_NORMAL, 0, false); status_fix_damage(bl, (!isDevotRdamage) ? bl : d_bl, damage, 0); } } else { status_change_end(bl, SC_DEVOTION, INVALID_TIMER); if (!dmg.amotion) status_fix_damage(src, bl, damage, dmg.dmotion); } } if (tsc->data[SC_WATER_SCREEN_OPTION]) { struct status_change_entry *sce = tsc->data[SC_WATER_SCREEN_OPTION]; struct block_list *e_bl = map_id2bl(sce->val1); if (e_bl) { if (!rmdamage) { clif_skill_damage(e_bl, e_bl, gettick(), 0, 0, damage, dmg.div_, skill_id, -1, skill_get_hit(skill_id)); status_fix_damage(NULL, e_bl, damage, 0); } else { clif_skill_damage(bl, bl, gettick(), 0, 0, damage, dmg.div_, skill_id, -1, skill_get_hit(skill_id)); status_fix_damage(bl, bl, damage, 0); } } } } if(damage > 0 && !status_has_mode(tstatus,MD_STATUS_IMMUNE)) { if( skill_id == RG_INTIMIDATE ) { int rate = 50 + skill_lv * 5; rate = rate + (status_get_lv(src) - status_get_lv(bl)); if(rnd()%100 < rate) skill_addtimerskill(src,tick + 800,bl->id,0,0,skill_id,skill_lv,0,flag); } else if( skill_id == SC_FATALMENACE ) { int16 x = skill_area_temp[4], y = skill_area_temp[5]; map_search_freecell(NULL, bl->m, &x, &y, 2, 2, 1); skill_addtimerskill(bl,tick + 800,bl->id,x,y,skill_id,skill_lv,0,flag); } } if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS) dmg.flag |= BF_WEAPON; if( sd && src != bl && damage > 0 && ( dmg.flag&BF_WEAPON || (dmg.flag&BF_MISC && (skill_id == RA_CLUSTERBOMB || skill_id == RA_FIRINGTRAP || skill_id == RA_ICEBOUNDTRAP)) ) ) { if (battle_config.left_cardfix_to_right) battle_drain(sd, bl, dmg.damage, dmg.damage, tstatus->race, tstatus->class_); else battle_drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->class_); } if( damage > 0 ) { // Post-damage effects switch( skill_id ) { case GC_VENOMPRESSURE: { struct status_change *ssc = status_get_sc(src); if( ssc && ssc->data[SC_POISONINGWEAPON] && rnd()%100 < 70 + 5*skill_lv ) { sc_start(src,bl,(enum sc_type)ssc->data[SC_POISONINGWEAPON]->val2,100,ssc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1)); status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER); clif_skill_nodamage(src,bl,skill_id,skill_lv,1); } } break; case WM_METALICSOUND: status_zap(bl, 0, damage*100/(100*(110-((sd) ? pc_checkskill(sd,WM_LESSON) : skill_get_max(WM_LESSON))*10))); break; case SR_TIGERCANNON: status_zap(bl, 0, damage * 10 / 100); break; } if( sd ) skill_onskillusage(sd, bl, skill_id, tick); } if (!(flag&2) && ( skill_id == MG_COLDBOLT || skill_id == MG_FIREBOLT || skill_id == MG_LIGHTNINGBOLT ) && (tsc = status_get_sc(src)) && tsc->data[SC_DOUBLECAST] && rnd() % 100 < tsc->data[SC_DOUBLECAST]->val2) { // skill_addtimerskill(src, tick + dmg.div_*dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2); skill_addtimerskill(src, tick + dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2); } map_freeblock_unlock(); if ((flag&0x1000000) && rmdamage == 1) return 0; //Should return 0 when damage was reflected return damage; }
  3. I tried it with mine and it shows for me. did you revert these? if ((dmg.damage || dmg.damage2) && (type = skill_magic_reflect(src, bl, src == dsrc))) { //Magic reflection, switch caster/target struct block_list *tbl = bl; rmdamage = 1; bl = src; src = tbl; dsrc = tbl;
  4. Try to revert it to the original then find this line: else if (type != 2) /* Kaite bypasses */ additional_effects = false; // Official Magic Reflection Behavior : damage reflected depends on gears caster wears, not target change it to this: else if (type != 2) /* Kaite bypasses */ additional_effects = false; if(type != 0) dsrc = bl; // Official Magic Reflection Behavior : damage reflected depends on gears caster wears, not target BTW the original reflect is only visual. It makes the player reflecting the magic look like they were the ones who casted the skill, but the stats and damage still depend on the original caster.
  5. The code you posted was from skill.h It's at skill.c at int64 skill_attack function if you search for the code skill_magic_reflect, you'll find it.
  6. It's at this line in skill.cpp if (dmg.flag&BF_MAGIC && (skill_id != NPC_EARTHQUAKE || (battle_config.eq_single_target_reflectable && (flag & 0xFFF) == 1))) { // Earthquake on multiple targets is not counted as a target skill. [Inkfish] if ((dmg.damage || dmg.damage2) && (type = skill_magic_reflect(src, bl, src == dsrc))) { //Magic reflection, switch caster/target struct block_list *tbl = bl; rmdamage = 1; bl = src; src = tbl; <----- Right Here dsrc = tbl; it changes the source of the attack to the original target of the skill. try to uncomment the line to see if it works.
  7. I'm guessing your server is pre-renewal since renewal already ignores kaite reflect for AoE's. To enable this in pre-renewal just uncomment or delete the #ifdef RENEWAL and #endif in the code crazyarashi posted and change the return value back to 2. It should look like this: if( sc->data[SC_KAITE] && (src->type == BL_PC || status_get_lv(src) <= 80) //#ifdef RENEWAL && type // Does not reflect AoE //#endif ) { // Kaite only works against non-players if they are low-level. // Kyomu doesn't disable Kaite, but the "skill fail chance" part of Kyomu applies to it. clif_specialeffect(bl, EF_ATTACKENERGY2, AREA); if( --sc->data[SC_KAITE]->val2 <= 0 ) status_change_end(bl, SC_KAITE, INVALID_TIMER); return 2; }
  8. Here ya go I made a thing just like you asked. Script command is called pcblockall It prevents the target to move/use items/attack/cast skills/click npc You use it like pcblockmove like this: pcblockall getcharid(3),1; //Will block movement/item use/normal attack/skill cast/npc click pcblockall getcharid(3),0; //Will unblock. I made it for the latest revision, try if it works for you. pcblockall.patch
  9. The sole purpose of clif_scriptmes is to open a dialog box with the set message, so I don't get what you mean by producing "mes clif without opening mes box". Can you please elaborate a little more..
  10. Are you running renewal cast? I ran the code myself and it works for me, very little difference though, because it's 0.2% per int, you need 500 int to reduce 100%. Also this reduces only variable cast time, it doesn't reduce fixed casting time and normal cast time. Edit: Ahh! I found why, i changed my code but I posted the first code I was trying hehe change it to this time = time * (1 - (float)min(status_get_int(bl)*0.2, 100) / 100);
  11. In battle.cpp search for void battle_drain under uint8 i = 0; add the code: struct status_change *sc; sc = status_get_sc(&sd->bl); it should look like this now: uint8 i = 0; struct status_change *sc; sc = status_get_sc(&sd->bl); if (!CHK_RACE(race) && !CHK_CLASS(class_)) return; now after the line battle_vanish(sd, tbl, &d); add this code: if (sc && sc->count){ if (sc->data[SC_BERSERK]) return; } it should now look like this: // Check for vanish HP/SP. !CHECKME: Which first, drain or vanish? battle_vanish(sd, tbl, &d); if (sc && sc->count){ if (sc->data[SC_BERSERK]) return; } // Check for drain HP/SP and there you go, no more lifesteal.
  12. in skill.cpp at skill_vfcastfix change this: if (!(flag&1)) time = time * (1 - sqrt(((float)(status_get_dex(bl) * 2 + status_get_int(bl)) / battle_config.vcast_stat_scale))); time = time * (1 - (float)min(reduce_cast_rate, 100) / 100); time = max(time, 0) + (1 - (float)min(fixcast_r, 100) / 100) * max(fixed, 0); //Underflow checking/capping to this: if (!(flag&1)) time = time * (1 - sqrt(((float)(status_get_dex(bl) * 2 + status_get_int(bl)) / battle_config.vcast_stat_scale))); time = time * (1 - (float)min(status_get_int(bl)*0.2, 100) / 100); time = time * (1 - (float)min(reduce_cast_rate, 100) / 100); time = max(time, 0) + (1 - (float)min(fixcast_r, 100) / 100) * max(fixed, 0); //Underflow checking/capping
  13. View File OnPCLootEvent New NPC Label OnPCLootEvent: This label triggers when a player picks up an item from the ground in a map marked with the 'lootevent' mapflag. This works with @autoloot and @alootid, this does not work for items given by script. When in a party with shared loot, only the player who looted the item from the ground will trigger this label. The information of the item picked up will be stored in an array called '@looted_data', check the script_commands.txt for the order of the data stored. Usage Sample: lootevent_sample.txt Submitter joecalis Submitted 05/27/2018 Category Source Modifications Video Content Author joecalis  
  14. Version 1.5.1

    235 downloads

    New NPC Label OnPCLootEvent: This label triggers when a player picks up an item from the ground in a map marked with the 'lootevent' mapflag. This works with @autoloot and @alootid, this does not work for items given by script. When in a party with shared loot, only the player who looted the item from the ground will trigger this label. The information of the item picked up will be stored in an array called '@looted_data', check the script_commands.txt for the order of the data stored. Usage Sample: lootevent_sample.txt

    Free

  15. *gethotkeys({<char_id>}); Gets all the target's current hotkeys. If <char_id> is not specified, will attach to the current player. Sets the following arrays: @hotkey_type - Type of data in hotkey, 0 for items and 1 for skills @hotkey_id - ID of the skill/item @hotkey_lv - Skill Level/Item Amount @hotkey_pos - Hotkey position @hotkey_count - Returns the max hotkey count. --------------------------------------- *updatehotkey(<type>,<id>,<lv>,<pos>{,<flag>,<char_id>}); Updates a player's hotkey. <type> - 0 for item, 1 for skill <id> - Skill Name/Skill ID/Item ID(will only store skills/items you have) <lv> - Skill Level/Item Amount(will always store item amount player is holding) <pos> - Position of the Hotkey(0 is the first hotkey) <flag> - (Optional) 0 = Default 1 = Delete duplicate on the same row 2 = Delete duplicate on all rows <char_id> - (Optional)Target's Character ID. If not specified, will attach to the current player --------------------------------------- *clearhotkeys({<char_id>}); Clears the target's hotkeys. If <char_id> is not specified, will attach to the current player. Very useful for storing skill builds, can be used for custom atcommand to instantly change hotkey setup. Can also be used to immediately equip given skills/items, for example: NPC: prontera,150,150,4 script InstantEquip 80,{ skill "SM_BASH",10,0; updatehotkey(1,"SM_BASH",10,0); //Will Equip Bash to the first Hotkey getitem 501,50; [email protected] = 1; //If 1 removes duplicate on the same hotkey row, if 2 removes duplicate on all the rows. updatehotkey(0,501,50,1,[email protected]); //Will Equip Item: Red Potion to the second Hotkey end; } Items/Cards: 4044,Smokie_Card,Smokie Card,6,20,,10,,,,,,,,136,,,,,{ skill "TF_HIDING",1; updatehotkey(1,"TF_HIDING",1,2,1); },{},{ sc_end SC_HIDING; } //Sets Hide Lv1 skill on 3rd Hotkey 1135,Cutlas,Cutlus,5,20,,900,150,,1,0,0x000654E2,63,2,2,4,40,1,2,{ skill "SM_BASH",5; updatehotkey(1,"SM_BASH",5,1,1); bonus bStr,2; bonus bDef,1; },{},{} //Sets Bash Lv5 skill on 2nd Hotkey The player must have the Skill or Item in order to show in the hotkey bar. The max hotkey positions depend on your server's MAX_HOTKEYS, the default for client versions above 2009-06-17 is 38. 38 = 9 skills x 4 bars & 2 Quickslots Manual Download: hotkey_scripts.rar
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.