Jump to content

joecalis

Members
  • Posts

    64
  • Joined

  • Last visited

  • Days Won

    7

Everything posted by joecalis

  1. Your server setting might be in Renewal, it's like that by default. If you want to change it Find: case RG_BACKSTAP: { #ifndef RENEWAL uint8 dir = map_calc_dir(src,target->x,target->y), t_dir = unit_getdir(target); if (map_check_dir(dir, t_dir)) return USESKILL_FAIL_MAX; #endif if (check_distance_bl(src, target, 0)) return USESKILL_FAIL_MAX; } break; Change to: case RG_BACKSTAP: { if (check_distance_bl(src, target, 0)) return USESKILL_FAIL_MAX; } break;
  2. Defender does reduce damage of Acid Demonstration but if you want it to not be affected, you can change that code to this:
  3. 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;
  4. 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; }
  5. 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;
  6. 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.
  7. 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.
  8. 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.
  9. 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; }
  10. 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
  11. 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.. ?
  12. 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);
  13. 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.
  14. 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
  15. 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  
  16. Version 1.5.1

    337 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
  17. *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; .@flag = 1; //If 1 removes duplicate on the same hotkey row, if 2 removes duplicate on all the rows. updatehotkey(0,501,50,1,.@flag); //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
  18. Version 1.0.1

    256 downloads

    New Script Commands gethotkeys({<char_id>}); updatehotkey(<type>,<id>,<lv>,<pos>{,<flag>,<char_id>}); clearhotkeys({<char_id>}); These are just simple commands, that gets, sets, and clears your hotkeys(skill bar). Usage Sample: hotkey_sample.txt
    Free
  19. Try this: that should still work.
  20. In-game, when you take damage does the health decrease? if not, it might be a visual thing, the client might be limiting the max health visual to 1,000,000 to prevent the numbers from overlapping other texts or graphics. if that's the case you might need to hex the client.
  21. You need the Universal Windows Platform Development and Desktop Development with C++.
  22. In status.cpp change this: case SC_BURNING: if (sce->val4 >= 0) { int64 damage = 1000 + (3 * status->max_hp) / 100; // Deals fixed (1000 + 3%*MaxHP) map_freeblock_lock(); dounlock = true; status_fix_damage(bl, bl, damage, clif_damage(bl, bl, tick, 0, 1, damage, 1, DMG_NORMAL, 0, false)); } break; to this: case SC_BURNING: if (sce->val4 >= 0) { int64 damage = 0; if (is_infinite_defense(bl, BF_MISC)) // Only does 1 damage to infinte defense(ex. Mushroom, Plant) type. damage = 1; else damage = 1000 + (3 * status->max_hp) / 100; // Deals fixed (1000 + 3%*MaxHP) map_freeblock_lock(); dounlock = true; status_fix_damage(bl, bl, damage, clif_damage(bl, bl, tick, 0, 1, damage, 1, DMG_NORMAL, 0, false)); } break;
  23. Try this: Edit: IDK why I got a down vote but ok... this patch still works you just have to apply it manually, and it's very easy to do. Just open the patch file with notepad, find the similar lines(without the "+") in the file(written in the "Index:") and copy paste the lines with the "+" sign. Then just replace this line: sc_start(bl, sc_atk, 100, skill_lv, d); clif_skill_nodamage(src,bl,skill_id,skill_lv,i); to this: clif_skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,sc_atk,100,skill_lv,d));
  24. try changing these in battle.cpp { "max_hp_lv99", &battle_config.max_hp_lv99, 330000, 100, 1000000000, }, { "max_hp_lv150", &battle_config.max_hp_lv150, 660000, 100, 1000000000, }, { "max_hp", &battle_config.max_hp, 1100000, 100, 1000000000, }, { "max_sp", &battle_config.max_sp, 32500, 100, 1000000000, }, change the values before the 100.
  25. I think there is already a mapflag like that, try noitemconsumption
×
×
  • Create New...