diff options
Diffstat (limited to 'src/map/skill.c')
-rw-r--r-- | src/map/skill.c | 764 |
1 files changed, 608 insertions, 156 deletions
diff --git a/src/map/skill.c b/src/map/skill.c index 40001659c..b2d788b57 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -86,6 +86,7 @@ struct skill_interface *skill; //Since only mob-casted splash skills can hit ice-walls int skill_splash_target(struct block_list* bl) { + nullpo_retr(BL_CHAR, bl); #ifndef RENEWAL return ( bl->type == BL_MOB ) ? BL_SKILL|BL_CHAR : BL_CHAR; #else // Some skills can now hit ground skills(traps, ice wall & etc.) @@ -94,7 +95,8 @@ int skill_splash_target(struct block_list* bl) } /// Returns the id of the skill, or 0 if not found. -int skill_name2id(const char* name) { +int skill_name2id(const char* name) +{ if( name == NULL ) return 0; @@ -103,7 +105,8 @@ int skill_name2id(const char* name) { /// Maps skill ids to skill db offsets. /// Returns the skill's array index, or 0 (Unknown Skill). -int skill_get_index( uint16 skill_id ) { +int skill_get_index (uint16 skill_id) +{ // avoid ranges reserved for mapping guild/homun/mercenary skills if( (skill_id >= GD_SKILLRANGEMIN && skill_id <= GD_SKILLRANGEMAX) || (skill_id >= HM_SKILLRANGEMIN && skill_id <= HM_SKILLRANGEMAX) @@ -128,7 +131,7 @@ int skill_get_index( uint16 skill_id ) { skill_id = (1077) + skill_id - 2201; else if ( skill_id < 3036 ) // 2549 - 3000 are empty - 1020+57+348 skill_id = (1425) + skill_id - 3001; - else if ( skill_id < 5019 ) // 3036 - 5000 are empty - 1020+57+348+35 + else if ( skill_id < 5044 ) // 3036 - 5000 are empty - 1020+57+348+35 skill_id = (1460) + skill_id - 5001; else ShowWarning("skill_get_index: skill id '%d' is not being handled!\n",skill_id); @@ -215,6 +218,7 @@ int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ) { return 0; #endif } + int skill_tree_get_max(uint16 skill_id, int b_class) { int i; @@ -227,7 +231,8 @@ int skill_tree_get_max(uint16 skill_id, int b_class) return skill->get_max(skill_id); } -int skill_get_casttype (uint16 skill_id) { +int skill_get_casttype(uint16 skill_id) +{ int inf = skill->get_inf(skill_id); if (inf&(INF_GROUND_SKILL)) return CAST_GROUND; @@ -243,8 +248,11 @@ int skill_get_casttype (uint16 skill_id) { return CAST_DAMAGE; } -int skill_get_casttype2 (uint16 index) { - int inf = skill->dbs->db[index].inf; +int skill_get_casttype2(uint16 index) +{ + int inf; + Assert_retr(CAST_NODAMAGE, index < MAX_SKILL_DB); + inf = skill->dbs->db[index].inf; if (inf&(INF_GROUND_SKILL)) return CAST_GROUND; if (inf&INF_SUPPORT_SKILL) @@ -260,7 +268,8 @@ int skill_get_casttype2 (uint16 index) { } //Returns actual skill range taking into account attack range and AC_OWL [Skotlex] -int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { +int skill_get_range2(struct block_list *bl, uint16 skill_id, uint16 skill_lv) +{ int range; struct map_session_data *sd = BL_CAST(BL_PC, bl); if( bl->type == BL_MOB && battle_config.mob_ai&0x400 ) @@ -356,7 +365,10 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk nullpo_ret(src); - switch( skill_id ) { + switch (skill_id) { + case SU_TUNABELLY: + hp = status_get_max_hp(target) * ((20 * skill_lv) - 10) / 100; + break; case BA_APPLEIDUN: #ifdef RENEWAL hp = 100+5*skill_lv+5*(status_get_vit(src)/10); // HP recovery @@ -388,6 +400,11 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk hp += hp * skill2_lv * 2 / 100; else if (src->type == BL_HOM && (skill2_lv = homun->checkskill(BL_UCAST(BL_HOM, src), HLIF_BRAIN)) > 0) hp += hp * skill2_lv * 2 / 100; + if (sd != NULL && ((skill2_lv = pc->checkskill(sd, SU_POWEROFSEA)) > 0)) { + hp += hp * 10 / 100; + if (pc->checkskill(sd, SU_TUNABELLY) == 5 && pc->checkskill(sd, SU_TUNAPARTY) == 5 && pc->checkskill(sd, SU_BUNCHOFSHRIMP) == 5 && pc->checkskill(sd, SU_FRESHSHRIMP) == 5) + hp += hp * 20 / 100; + } break; } @@ -437,6 +454,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk // Making plagiarize check its own function [Aru] int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* bl) { + nullpo_ret(sd); // Never copy NPC/Wedding Skills if (skill->get_inf2(skill_id)&(INF2_NPC_SKILL|INF2_WEDDING_SKILL)) return 0; @@ -456,8 +474,11 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b skill_id == MER_INCAGI || skill_id == MER_BLESSING)) return 0; - // Couldn't preserve 3rd Class skills except only when using Reproduce skill. [Jobbie] - if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= LG_OVERBRAND_PLUSATK) || (skill_id >= RL_GLITTERING_GREED && skill_id <= OB_AKAITSUKI) || (skill_id >= GC_DARKCROW && skill_id <= NC_MAGMA_ERUPTION_DOTDAMAGE))) + // Couldn't preserve 3rd Class/Summoner skills except only when using Reproduce skill. [Jobbie] + if (!(sd->sc.data[SC__REPRODUCE]) && + ((skill_id >= RK_ENCHANTBLADE && skill_id <= LG_OVERBRAND_PLUSATK) || + (skill_id >= RL_GLITTERING_GREED && skill_id <= OB_AKAITSUKI) || + (skill_id >= GC_DARKCROW && skill_id <= SU_FRESHSHRIMP))) return 0; // Reproduce will only copy skills according on the list. [Jobbie] else if( sd->sc.data[SC__REPRODUCE] && !skill->dbs->reproduce_db[skill->get_index(skill_id)] ) @@ -547,6 +568,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_THERE_ARE_NPC_AROUND,0); return 1; } + FALLTHROUGH case MC_IDENTIFY: return 0; // always allowed case WZ_ICEWALL: @@ -631,6 +653,7 @@ int skillnotok_hom(uint16 skill_id, struct homun_data *hd) int skillnotok_hom_unknown(uint16 skill_id, struct homun_data *hd) { + nullpo_retr(1, hd); //Use master's criteria. return skill->not_ok(skill_id, hd->master); } @@ -648,10 +671,12 @@ int skillnotok_mercenary(uint16 skill_id, struct mercenary_data *md) return skill->not_ok(skill_id, md->master); } -struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill_lv, struct block_list* src, int x, int y) { +struct s_skill_unit_layout* skill_get_unit_layout(uint16 skill_id, uint16 skill_lv, struct block_list* src, int x, int y) +{ int pos = skill->get_unit_layout_type(skill_id,skill_lv); uint8 dir; + nullpo_retr(&skill->dbs->unit_layout[0], src); if (pos < -1 || pos >= MAX_SKILL_UNIT_LAYOUT) { ShowError("skill_get_unit_layout: unsupported layout type %d for skill %d (level %d)\n", pos, skill_id, skill_lv); pos = cap_value(pos, 0, MAX_SQUARE_LAYOUT); // cap to nearest square layout @@ -888,6 +913,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; #endif + case WZ_HEAVENDRIVE: + status_change_end(bl, SC_SV_ROOTTWIST, INVALID_TIMER); + break; + case WZ_STORMGUST: /** * Storm Gust counter was dropped in renewal @@ -1401,6 +1430,25 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 case MH_XENO_SLASHER: sc_start2(src, bl, SC_BLOODING, 10 * skill_lv, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); break; + /** + * Summoner + */ + case SU_SCRATCH: + sc_start2(src, bl, SC_BLOODING, (skill_lv * 3), skill_lv, src->id, skill->get_time(skill_id, skill_lv)); // TODO: What's the chance/time? + break; + case SU_SV_STEMSPEAR: + sc_start2(src, bl, SC_BLOODING, 10, skill_lv, src->id, skill->get_time(skill_id, skill_lv)); + break; + case SU_CN_METEOR: + sc_start(src, bl, SC_CURSE, 10, skill_lv, skill->get_time2(skill_id, skill_lv)); // TODO: What's the chance/time? + break; + case SU_SCAROFTAROU: + sc_start(src, bl, SC_STUN, 10, skill_lv, skill->get_time2(skill_id, skill_lv)); // TODO: What's the chance/time? + break; + case SU_LUNATICCARROTBEAT: + if (skill->area_temp[3] == 1) + sc_start(src, bl, SC_STUN, 10, skill_lv, skill_get_time(skill_id, skill_lv)); // TODO: What's the chance/time? + break; default: skill->additional_effect_unknown(src, bl, &skill_id, &skill_lv, &attack_type, &dmg_lv, &tick); break; @@ -2036,7 +2084,8 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in return where; //Return list of pieces broken. } -int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time) { +int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time) +{ struct status_change *sc; const int pos[5] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM, EQP_ACC}; const enum sc_type sc_atk[5] = {SC_NOEQUIPWEAPON, SC_NOEQUIPSHIELD, SC_NOEQUIPARMOR, SC_NOEQUIPHELM, SC__STRIPACCESSARY}; @@ -2062,6 +2111,7 @@ int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int } return where?1:0; } + /*========================================================================= * Used to knock back players, monsters, traps, etc * 'count' is the number of squares to knock back @@ -2072,11 +2122,14 @@ int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int int skill_blown(struct block_list* src, struct block_list* target, int count, int8 dir, int flag) { int dx = 0, dy = 0; + struct status_change *tsc = status->get_sc(target); nullpo_ret(src); if (src != target && map->list[src->m].flag.noknockback) return 0; // No knocking + + nullpo_ret(target); if (count == 0) return 0; // Actual knockback distance is 0. @@ -2117,6 +2170,9 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in dy = -diry[dir]; } + if (tsc != NULL && tsc->data[SC_SU_STOOP]) // Any knockback will cancel it. + status_change_end(target, SC_SU_STOOP, INVALID_TIMER); + return unit->blown(target, dx, dy, count, flag); // send over the proper flag } @@ -2127,10 +2183,12 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in 1 - Regular reflection (Maya) 2 - SL_KAITE reflection */ -int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) { +int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) +{ struct status_change *sc = status->get_sc(bl); struct map_session_data* sd = BL_CAST(BL_PC, bl); + nullpo_ret(src); if( sc && sc->data[SC_KYOMU] ) // Nullify reflecting ability return 0; @@ -2174,7 +2232,8 @@ int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) * client (causes player characters to not scream skill name) * flag&0x4000 - Return 0 if damage was reflected *-------------------------------------------------------------------------*/ -int skill_attack(int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { +int skill_attack(int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) +{ struct Damage dmg; struct status_data *sstatus, *tstatus; struct status_change *sc; @@ -2488,6 +2547,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case KO_MUCHANAGE: if( dmg.dmg_lv == ATK_FLEE ) break; + FALLTHROUGH case WL_SOULEXPANSION: case WL_COMET: case NJ_HUUMA: @@ -2500,6 +2560,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr case LG_OVERBRAND: /* Fall through */ dmg.amotion = status_get_amotion(src) * 2; + FALLTHROUGH case LG_OVERBRAND_PLUSATK: dmg.dmotion = clif->skill_damage(dsrc,bl,tick,status_get_amotion(src),dmg.dmotion,damage,dmg.div_,skill_id,-1,BDT_SPLASH); break; @@ -2558,6 +2619,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, (flag&SD_LEVEL) ? -1 : skill_lv, BDT_SPLASH); if( dsrc != src ) // avoid damage display redundancy break; + FALLTHROUGH case HT_LANDMINE: dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, type); break; @@ -2570,6 +2632,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr 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) */ + FALLTHROUGH default: skill->attack_display_unknown(&attack_type, src, dsrc, bl, &skill_id, &skill_lv, &tick, &flag, &type, &dmg, &damage); break; @@ -2865,15 +2928,27 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr return (int)cap_value(damage,INT_MIN,INT_MAX); } -void skill_attack_combo1_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, struct status_change_entry *sce, int *combo) { +void skill_attack_combo1_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, struct status_change_entry *sce, int *combo) +{ if (src == dsrc) // Ground skills are exceptions. [Inkfish] status_change_end(src, SC_COMBOATTACK, INVALID_TIMER); } -void skill_attack_combo2_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *combo) { +void skill_attack_combo2_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *combo) +{ } -void skill_attack_display_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage) { +void skill_attack_display_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage) +{ + nullpo_retv(bl); + nullpo_retv(dmg); + nullpo_retv(tick); + nullpo_retv(flag); + nullpo_retv(damage); + nullpo_retv(skill_id); + nullpo_retv(skill_lv); + nullpo_retv(type); + if (*flag & SD_ANIMATION && dmg->div_ < 2) //Disabling skill animation doesn't works on multi-hit. *type = BDT_SPLASH; if (bl->type == BL_SKILL) { @@ -2884,15 +2959,24 @@ void skill_attack_display_unknown(int *attack_type, struct block_list* src, stru dmg->dmotion = clif->skill_damage(dsrc, bl, *tick, dmg->amotion, dmg->dmotion, *damage, dmg->div_, *skill_id, (*flag & SD_LEVEL) ? -1 : *skill_lv, *type); } -int skill_attack_copy_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) { +int skill_attack_copy_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) +{ + nullpo_ret(skill_id); return *skill_id; } -int skill_attack_dir_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) { +int skill_attack_dir_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) +{ return -1; } -void skill_attack_blow_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage, int8 *dir) { +void skill_attack_blow_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage, int8 *dir) +{ + nullpo_retv(bl); + nullpo_retv(dmg); + nullpo_retv(dir); + nullpo_retv(damage); + skill->blown(dsrc, bl, dmg->blewcount, *dir, 0x0); if (!dmg->blewcount && bl->type == BL_SKILL && *damage > 0){ struct skill_unit *su = BL_UCAST(BL_SKILL, bl); @@ -2901,7 +2985,8 @@ void skill_attack_blow_unknown(int *attack_type, struct block_list* src, struct } } -void skill_attack_post_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) { +void skill_attack_post_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) +{ } /*========================================== @@ -2909,7 +2994,8 @@ void skill_attack_post_unknown(int *attack_type, struct block_list* src, struct * Checking bl battle flag and display damage * then call func with source,target,skill_id,skill_lv,tick,flag *------------------------------------------*/ -int skill_area_sub(struct block_list *bl, va_list ap) { +int skill_area_sub(struct block_list *bl, va_list ap) +{ struct block_list *src; uint16 skill_id,skill_lv; int flag; @@ -2960,6 +3046,7 @@ int skill_check_unit_range_sub(struct block_list *bl, va_list ap) case AL_PNEUMA: if(g_skill_id == SA_LANDPROTECTOR) break; + FALLTHROUGH case MG_SAFETYWALL: case MH_STEINWAND: case SC_MAELSTROM: @@ -3382,6 +3469,7 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { skill->blown(src,target,skill->get_blewcount(skl->skill_id, skl->skill_lv), -1, 0x0 ); break; } + FALLTHROUGH } default: skill->timerskill_target_unknown(tid, tick, src, target, ud, skl); @@ -3392,7 +3480,8 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { break; switch( skl->skill_id ) { case WZ_METEOR: - if( skl->type >= 0 ) { + case SU_CN_METEOR: + if (skl->type >= 0) { int x = skl->type>>16, y = skl->type&0xFFFF; if( path->search_long(NULL, src, src->m, src->x, src->y, x, y, CELL_CHKWALL) ) skill->unitsetting(src,skl->skill_id,skl->skill_lv,x,y,skl->flag); @@ -3408,6 +3497,7 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { map->foreachinarea(skill->cell_overlap,src->m,skl->x-i,skl->y-i,skl->x+i,skl->y+i,BL_SKILL,skl->skill_id,&dummy,src); } + FALLTHROUGH // fall through ... case WL_EARTHSTRAIN: skill->unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,(skl->type<<16)|skl->flag); @@ -3435,6 +3525,7 @@ bool skill_timerskill_dead_unknown(struct block_list *src, struct unit_data *ud, void skill_timerskill_target_unknown(int tid, int64 tick, struct block_list *src, struct block_list *target, struct unit_data *ud, struct skill_timerskill *skl) { + nullpo_retv(skl); skill->attack(skl->type, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag); } @@ -3445,7 +3536,8 @@ void skill_timerskill_notarget_unknown(int tid, int64 tick, struct block_list *s /*========================================== * *------------------------------------------*/ -int skill_addtimerskill(struct block_list *src, int64 tick, int target, int x,int y, uint16 skill_id, uint16 skill_lv, int type, int flag) { +int skill_addtimerskill(struct block_list *src, int64 tick, int target, int x,int y, uint16 skill_id, uint16 skill_lv, int type, int flag) +{ int i; struct unit_data *ud; nullpo_retr(1, src); @@ -3553,6 +3645,7 @@ void skill_castend_type(int type, struct block_list *src, struct block_list *bl, { switch (type) { case CAST_GROUND: + nullpo_retv(bl); skill->castend_pos2(src, bl->x, bl->y, skill_id, skill_lv, tick, flag); break; case CAST_NODAMAGE: @@ -3568,7 +3661,8 @@ void skill_castend_type(int type, struct block_list *src, struct block_list *bl, * * *------------------------------------------*/ -int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { +int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) +{ struct map_session_data *sd = NULL; struct status_data *tstatus; struct status_change *sc; @@ -3906,11 +4000,22 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); break; - //Splash attack skills. + case SU_BITE: + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); + if (status->get_lv(src) >= 30 && (rnd() % 100 < (int)(status->get_lv(src) / 30) + 10)) // TODO: Need activation chance. + skill->addtimerskill(src, tick + skill->get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); + break; + + case SU_PICKYPECK: + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + break; + + // Splash attack skills. case AS_GRIMTOOTH: case MC_CARTREVOLUTION: case NPC_SPLASHATTACK: flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit + FALLTHROUGH case AS_SPLASHER: case HT_BLITZBEAT: case AC_SHOWER: @@ -3958,7 +4063,9 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 case KO_BAKURETSU: case GN_ILLUSIONDOPING: case MH_XENO_SLASHER: - if( flag&1 ) {//Recursive invocation + case SU_SCRATCH: + case SU_LUNATICCARROTBEAT: + 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 // skill->area_temp[2] counts how many targets have already been processed @@ -3973,15 +4080,19 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 break; heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, sflag); - if( skill_id == NPC_VAMPIRE_GIFT && heal > 0 ) { + if (skill_id == NPC_VAMPIRE_GIFT && heal > 0) { clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1); status->heal(src,heal,0,0); } + if (skill_id == SU_SCRATCH && status->get_lv(src) >= 30 && (rnd() % 100 < (int)(status->get_lv(src) / 30) + 10)) // TODO: Need activation chance. + skill->addtimerskill(src, tick + skill->get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); } else { switch ( skill_id ) { case NJ_BAKUENRYU: case LG_EARTHDRIVE: case GN_CARTCANNON: + case SU_SCRATCH: + case SU_LUNATICCARROTBEAT: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; case SR_TIGERCANNON: @@ -4000,13 +4111,19 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 skill->area_temp[0] = 0; skill->area_temp[1] = bl->id; skill->area_temp[2] = 0; - if( skill_id == WL_CRIMSONROCK ) { + if (skill_id == WL_CRIMSONROCK) { skill->area_temp[4] = bl->x; skill->area_temp[5] = bl->y; } + if (skill_id == SU_LUNATICCARROTBEAT) { + skill->area_temp[3] = 0; + } - if( skill_id == NC_VULCANARM ) - if (sd) pc->overheat(sd,1); + if (skill_id == NC_VULCANARM) { + if (sd != NULL) { + pc->overheat(sd,1); + } + } // if skill damage should be split among targets, count them //SD_LEVEL -> Forced splash damage for Auto Blitz-Beat -> count targets @@ -4016,6 +4133,15 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 // recursive invocation of skill->castend_damage_id() with flag|1 map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); + + if (sd && skill_id == SU_LUNATICCARROTBEAT) { + short item_idx = pc->search_inventory(sd, ITEMID_CARROT); + + if (item_idx >= 0) { + pc->delitem(sd, item_idx, 1, 0, 1, LOG_TYPE_CONSUME); + skill->area_temp[3] = 1; + } + } } break; @@ -4291,6 +4417,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 if( (tsc = status->get_sc(bl)) && tsc->data[SC_HIDING] ) break; } + FALLTHROUGH case HVAN_EXPLOSION: if (src != bl) skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); @@ -4548,6 +4675,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 } break; } + FALLTHROUGH case RA_WUGBITE: if( path->search(NULL,src,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH) ) { skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); @@ -4571,7 +4699,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) { struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = sg->item_id?sg->item_id:ITEMID_TRAP; + item_tmp.nameid = sg->item_id ? sg->item_id : ITEMID_BOOBY_TRAP; item_tmp.identify = 1; if( item_tmp.nameid ) map->addflooritem(bl, &item_tmp, 1, bl->m, bl->x, bl->y, 0, 0, 0, 0); @@ -4823,6 +4951,15 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); break; + case SU_SV_STEMSPEAR: + skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); + if (status->get_lv(src) >= 30 && (rnd() % 100 < (int)(status->get_lv(src) / 30) + 10)) // TODO: Need activation chance. + skill->addtimerskill(src, tick + skill->get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, (skill_id == SU_SV_STEMSPEAR) ? BF_MAGIC : BF_WEAPON, flag); + break; + case SU_SCAROFTAROU: + sc_start(src, bl, status->skill2sc(skill_id), 10, skill_lv, skill->get_time(skill_id, skill_lv)); // TODO: What's the activation chance for the effect? + break; + case 0:/* no skill - basic/normal attack */ if(sd) { if (flag & 3){ @@ -4868,6 +5005,10 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 bool skill_castend_damage_id_unknown(struct block_list* src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, struct status_data *tstatus, struct status_change *sc) { + nullpo_retr(true, skill_id); + nullpo_retr(true, skill_lv); + nullpo_retr(true, tick); + nullpo_retr(true, tstatus); ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n", *skill_id); clif->skill_damage(src, bl, *tick, status_get_amotion(src), tstatus->dmotion, 0, abs(skill->get_num(*skill_id, *skill_lv)), @@ -4879,7 +5020,8 @@ bool skill_castend_damage_id_unknown(struct block_list* src, struct block_list * /*========================================== * *------------------------------------------*/ -int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { +int skill_castend_id(int tid, int64 tick, int id, intptr_t data) +{ struct block_list *target, *src; struct map_session_data *sd; struct mob_data *md; @@ -4955,6 +5097,8 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { ud->skilltimer=tid; return skill->castend_pos(tid,tick,id,data); case GN_WALLOFTHORN: + case SU_CN_POWDERING: + case SU_SV_ROOTTWIST: ud->skillx = target->x; ud->skilly = target->y; ud->skilltimer = tid; @@ -5223,7 +5367,8 @@ bool skill_castend_id_unknown(struct unit_data *ud, struct block_list *src, stru /*========================================== * *------------------------------------------*/ -int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { +int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) +{ struct map_session_data *sd, *dstsd; struct mob_data *md, *dstmd; struct homun_data *hd; @@ -5300,6 +5445,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0) ; break ; } + FALLTHROUGH case AL_HEAL: /** @@ -5415,6 +5561,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin * Arch Bishop **/ case AB_HIGHNESSHEAL: + /** + * Summoner + */ + case SU_TUNABELLY: { int heal = skill->calc_heal(src, bl, (skill_id == AB_HIGHNESSHEAL)?AL_HEAL:skill_id, (skill_id == AB_HIGHNESSHEAL)?10:skill_lv, true); int heal_get_jobexp; @@ -5444,6 +5594,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin else if (tsc->data[SC_BERSERK]) heal = 0; //Needed so that it actually displays 0 when healing. } + if (skill_id == AL_HEAL) { + status_change_end(bl, SC_BITESCAR, INVALID_TIMER); + } clif->skill_nodamage (src, bl, skill_id, heal, 1); if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL ) heal = ~heal + 1; @@ -5823,6 +5976,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case PR_KYRIE: case MER_KYRIE: + case SU_TUNAPARTY: clif->skill_nodamage(bl, bl, skill_id, -1, sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); break; @@ -5939,9 +6093,18 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case RK_ABUNDANCE: case RK_CRUSHSTRIKE: case ALL_ODINS_POWER: + case SU_FRESHSHRIMP: + case SU_ARCLOUSEDASH: clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; + // Works just like the above list of skills, except animation caused by + // status must trigger AFTER the skill cast animation or it will cancel + // out the status's animation. + case SU_STOOP: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + break; case KN_AUTOCOUNTER: sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); skill->addtimerskill(src, tick + 100, bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); @@ -6166,7 +6329,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin sd->devotion[i] = bl->id; } - else + else if (mer != NULL) mer->devotion_flag = 1; // Mercenary Devoting Owner clif->skill_nodamage(src, bl, skill_id, skill_lv, @@ -6539,7 +6702,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case RG_STEALCOIN: if(sd) { int amount = pc->steal_coin(sd, bl, skill_lv); - if( amount > 0 ) { + if (amount > 0 && dstmd != NULL) { dstmd->state.provoke_flag = src->id; mob->target(dstmd, src, skill->get_range2(src, skill_id, skill_lv)); clif->skill_nodamage(src, bl, skill_id, amount, 1); @@ -6596,7 +6759,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin status_change_end(bl, SC_SILENCE, INVALID_TIMER); status_change_end(bl, SC_BLIND, INVALID_TIMER); status_change_end(bl, SC_CONFUSION, INVALID_TIMER); - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_change_end(bl, SC_BITESCAR, INVALID_TIMER); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); break; case TF_DETOXIFY: @@ -7513,7 +7677,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin // get back 1 trap struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP; + item_tmp.nameid = su->group->item_id ? su->group->item_id : ITEMID_BOOBY_TRAP; item_tmp.identify = 1; if (item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SKILL)) != 0) { clif->additem(sd,0,0,flag); @@ -7539,6 +7703,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin // remove trap should be used instead break; // otherwise fall through to below + FALLTHROUGH case UNT_BLASTMINE: case UNT_SKIDTRAP: case UNT_LANDMINE: @@ -7576,7 +7741,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start4(src,bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000)); #ifndef RENEWAL - if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000); + if (sd) + skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv) + 3000); #endif break; @@ -8388,7 +8554,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case AB_ANCILLA: if( sd ) { clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - skill->produce_mix(sd, skill_id, ITEMID_ANCILLA, 0, 0, 0, 1); + skill->produce_mix(sd, skill_id, ITEMID_ANSILA, 0, 0, 0, 1); } break; @@ -8856,6 +9022,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case LG_TRAMPLE: clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->destroy_trap,bl,skill->get_splash(skill_id,skill_lv),BL_SKILL,tick); + status_change_end(bl, SC_SV_ROOTTWIST, INVALID_TIMER); break; case LG_REFLECTDAMAGE: @@ -9385,6 +9552,25 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, 0, 1, skill_id, -2, BDT_SKILL); break; + case SU_HIDE: + if (tsce != NULL) { + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + status_change_end(bl, type, INVALID_TIMER); + map->freeblock_unlock(); + return 0; + } + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + break; + + case SU_BUNCHOFSHRIMP: + if (sd == NULL || sd->status.party_id == 0 || flag&1) { + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + } else if (sd != NULL) { + party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + } + break; + case GM_SANDMAN: if( tsc ) { if( tsc->opt1 == OPT1_SLEEP ) @@ -9791,6 +9977,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin SC_MANDRAGORA, SC_HARMONIZE, SC_DEEP_SLEEP, SC_SIREN, SC_SLEEP, SC_CONFUSION, SC_ILLUSION }; int heal; + if (hd == NULL) + break; if(tsc){ int i; for (i = 0; i < ARRAYLENGTH(scs); i++) { @@ -9912,6 +10100,8 @@ bool skill_castend_nodamage_id_mado_unknown(struct block_list *src, struct block bool skill_castend_nodamage_id_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) { + nullpo_retr(true, skill_id); + nullpo_retr(true, skill_lv); ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n", *skill_id); clif->skill_nodamage(src, bl, *skill_id, *skill_lv, 1); map->freeblock_unlock(); @@ -9928,6 +10118,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) struct unit_data *ud = unit->bl2ud(src); struct mob_data *md; + nullpo_ret(src); nullpo_ret(ud); sd = BL_CAST(BL_PC , src); @@ -10094,10 +10285,13 @@ int skill_check_npc_chaospanic(struct block_list *bl, va_list args) return 1; } + /* skill count without self */ int skill_count_wos(struct block_list *bl, va_list ap) { struct block_list* src = va_arg(ap, struct block_list*); + nullpo_retr(1, bl); + nullpo_retr(1, src); if( src->id != bl->id ) { return 1; } @@ -10107,8 +10301,10 @@ int skill_count_wos(struct block_list *bl, va_list ap) /*========================================== * *------------------------------------------*/ -int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char *mapname) { +int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char *mapname) +{ nullpo_ret(sd); + nullpo_ret(mapname); //Simplify skill_failed code. #define skill_failed(sd) ( (sd)->menuskill_id = (sd)->menuskill_val = 0 ) @@ -10245,7 +10441,8 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char /*========================================== * *------------------------------------------*/ -int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { +int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) +{ struct map_session_data* sd; struct status_change* sc; struct status_change_entry *sce; @@ -10274,6 +10471,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case HW_GANBANTEIN: case LG_EARTHDRIVE: case SC_ESCAPE: + case SU_CN_METEOR: break; //Effect is displayed on respective switch case. default: skill->castend_pos2_effect_unknown(src, &x, &y, &skill_id, &skill_lv, &tick, &flag); @@ -10342,6 +10540,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } + FALLTHROUGH case MG_SAFETYWALL: { @@ -10351,6 +10550,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui return 0; // Don't consume gems if cast on LP } } + FALLTHROUGH case MG_FIREWALL: case MG_THUNDERSTORM: @@ -10460,7 +10660,10 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case SO_ELEMENTAL_SHIELD: case RL_B_TRAP: case MH_XENO_SLASHER: - flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). + case SU_CN_POWDERING: + case SU_SV_ROOTTWIST: + flag |= 1; // Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). + FALLTHROUGH case GS_GROUNDDRIFT: //Ammo should be deleted right away. if ( skill_id == WM_SEVERE_RAINSTORM ) sc_start(src,src,SC_NO_SWITCH_EQUIP,100,0,skill->get_time(skill_id,skill_lv)); @@ -10512,11 +10715,24 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui break; case WZ_METEOR: + case SU_CN_METEOR: { int area = skill->get_splash(skill_id, skill_lv); short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0; int i; +#if 0 + // The Meteor should inflict curse if Catnip fruit is consumed. + // Currently Catnip fruit is added as requirement. + if (sd && skill_id == SU_CN_METEOR) { + short item_idx = pc->search_inventory(sd, ITEMID_CATNIP_FRUIT); + if (item_idx >= 0) { + pc->delitem(sd, item_idx, 1, 0, 1, LOG_TYPE_SKILL); + flag |= 1; + } + } +#endif + for( i = 0; i < 2 + (skill_lv>>1); i++ ) { // Creates a random Cell in the Splash Area tmpx = x - area + rnd()%(area * 2 + 1); @@ -10568,6 +10784,19 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui } status_change_end(src, SC_HIDING, INVALID_TIMER); break; + case SU_LOPE: + { + if (map->list[src->m].flag.noteleport && !(map->list[src->m].flag.battleground || map_flag_gvg2(src->m))) { + x = src->x; + y = src->y; + } + clif->skill_nodamage(src, src, SU_LOPE, skill_lv, 1); + if(!map->count_oncell(src->m, x, y, BL_PC | BL_NPC | BL_MOB, 0) && map->getcell(src->m, src, x, y, CELL_CHKREACH)) { + clif->slide(src, x, y); + unit->movepos(src, x, y, 1, 0); + } + } + break; case AM_SPHEREMINE: case AM_CANNIBALIZE: { @@ -11037,7 +11266,8 @@ int skill_dance_overlap_sub(struct block_list *bl, va_list ap) //Does the song/dance overlapping -> dissonance check. [Skotlex] //When flag is 0, this unit is about to be removed, cancel the dissonance effect //When 1, this unit has been positioned, so start the cancel effect. -int skill_dance_overlap(struct skill_unit* su, int flag) { +int skill_dance_overlap(struct skill_unit* su, int flag) +{ if (!su || !su->group || !(su->group->state.song_dance&0x1)) return 0; @@ -11059,7 +11289,8 @@ int skill_dance_overlap(struct skill_unit* su, int flag) { * @param flag 1 Revert * @retval true success **/ -bool skill_dance_switch(struct skill_unit* su, int flag) { +bool skill_dance_switch(struct skill_unit* su, int flag) +{ static int prevflag = 1; // by default the backup is empty static struct skill_unit_group backup; struct skill_unit_group* group; @@ -11115,7 +11346,8 @@ bool skill_dance_switch(struct skill_unit* su, int flag) { * Initializes and sets a ground skill. * flag&1 is used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active) *------------------------------------------*/ -struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_id, uint16 skill_lv, int16 x, int16 y, int flag) { +struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_id, uint16 skill_lv, int16 x, int16 y, int flag) +{ struct skill_unit_group *group; int i,limit,val1=0,val2=0,val3=0; int target,interval,range,unit_flag,req_item=0; @@ -11145,9 +11377,10 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ sd = BL_CAST(BL_PC, src); st = status->get_status_data(src); + nullpo_retr(NULL, st); sc = status->get_sc(src); // for traps, firewall and fogwall - celest - switch( skill_id ) { + switch (skill_id) { case SO_ELEMENTAL_SHIELD: val2 = 300 * skill_lv + 65 * (st->int_ + status->get_lv(src)) + st->max_sp; break; @@ -11216,8 +11449,10 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ case HT_ANKLESNARE: if( flag&2 ) val3 = SC_ESCAPE; + FALLTHROUGH case HT_SHOCKWAVE: val1=skill_lv*15+10; + FALLTHROUGH case HT_SANDMAN: case MA_SANDMAN: case HT_CLAYMORETRAP: @@ -11242,7 +11477,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ case RA_ICEBOUNDTRAP: { struct skill_condition req = skill->get_requirement(sd,skill_id,skill_lv); - ARR_FIND(0, MAX_SKILL_ITEM_REQUIRE, i, req.itemid[i] && (req.itemid[i] == ITEMID_TRAP || req.itemid[i] == ITEMID_TRAP_ALLOY)); + ARR_FIND(0, MAX_SKILL_ITEM_REQUIRE, i, req.itemid[i] && (req.itemid[i] == ITEMID_BOOBY_TRAP || req.itemid[i] == ITEMID_SPECIAL_ALLOY_TRAP)); if( i != MAX_SKILL_ITEM_REQUIRE && req.itemid[i] ) req_item = req.itemid[i]; if( map_flag_gvg2(src->m) || map->list[src->m].flag.battleground ) @@ -11402,12 +11637,16 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ { case ELE_FIRE: subunt++; + FALLTHROUGH case ELE_WATER: subunt++; + FALLTHROUGH case ELE_POISON: subunt++; + FALLTHROUGH case ELE_DARK: subunt++; + FALLTHROUGH case ELE_WIND: break; default: @@ -11444,6 +11683,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ target = BCT_ALL; val1 = skill_lv + 1; val2 = 1; + FALLTHROUGH case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector. case SO_WATER_INSIGNIA: case SO_FIRE_INSIGNIA: @@ -11486,6 +11726,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ break; } + nullpo_retr(NULL, layout); nullpo_retr(NULL, group=skill->init_unitgroup(src,layout->count,skill_id,skill_lv,skill->get_unit_id(skill_id,flag&1)+subunt, limit, interval)); group->val1=val1; group->val2=val2; @@ -11626,10 +11867,15 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_ return group; } -void skill_unitsetting1_unknown(struct block_list *src, uint16 *skill_id, uint16 *skill_lv, int16 *x, int16 *y, int *flag, int *val1, int *val2, int *val3) { +void skill_unitsetting1_unknown(struct block_list *src, uint16 *skill_id, uint16 *skill_lv, int16 *x, int16 *y, int *flag, int *val1, int *val2, int *val3) +{ } -void skill_unitsetting2_unknown(struct block_list *src, uint16 *skill_id, uint16 *skill_lv, int16 *x, int16 *y, int *flag, int *unit_flag, int *val1, int *val2, int *val3, struct skill_unit_group *group) { +void skill_unitsetting2_unknown(struct block_list *src, uint16 *skill_id, uint16 *skill_lv, int16 *x, int16 *y, int *flag, int *unit_flag, int *val1, int *val2, int *val3, struct skill_unit_group *group) +{ + nullpo_retv(group); + nullpo_retv(val2); + nullpo_retv(unit_flag); if (group->state.song_dance & 0x1) *val2 = *unit_flag & (UF_DANCE | UF_SONG); //Store whether this is a song/dance } @@ -11637,7 +11883,8 @@ void skill_unitsetting2_unknown(struct block_list *src, uint16 *skill_id, uint16 /*========================================== * *------------------------------------------*/ -int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick) { +int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick) +{ struct skill_unit_group *sg; struct block_list *ss; struct status_change *sc; @@ -11761,6 +12008,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick case UNT_HERMODE: if (sg->src_id!=bl->id && battle->check_target(&src->bl,bl,BCT_PARTY|BCT_GUILD) > 0) status->change_clear_buffs(bl,1); //Should dispell only allies. + FALLTHROUGH case UNT_RICHMANKIM: case UNT_ETERNALCHAOS: case UNT_DRUMBATTLEFIELD: @@ -11779,6 +12027,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick if (!battle_config.song_timer_reset && sc && sce) return 0; // Let it fall through + FALLTHROUGH case UNT_WHISTLE: case UNT_ASSASSINCROSS: case UNT_POEMBRAGI: @@ -11868,6 +12117,13 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick sc_start(ss, bl, SC_VOLCANIC_ASH, 100, sg->skill_lv, skill->get_time(MH_VOLCANIC_ASH, sg->skill_lv)); break; + case UNT_CATNIPPOWDER: + if (sg->src_id == bl->id || (status_get_mode(bl)&MD_BOSS)) + break; // Does not affect the caster or Boss. + if (sce == NULL && battle->check_target(&src->bl, bl, BCT_ENEMY) > 0) + sc_start(ss, bl, type, 100, sg->skill_lv, skill->get_time(sg->skill_id, sg->skill_lv)); + break; + case UNT_GD_LEADERSHIP: case UNT_GD_GLORYWOUNDS: case UNT_GD_SOULCOLD: @@ -11889,7 +12145,8 @@ void skill_unit_onplace_unknown(struct skill_unit *src, struct block_list *bl, i /*========================================== * *------------------------------------------*/ -int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int64 tick) { +int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int64 tick) +{ struct skill_unit_group *sg; struct block_list *ss; struct map_session_data *tsd; @@ -11917,7 +12174,9 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 return 0; tstatus = status->get_status_data(bl); + nullpo_ret(tstatus); bst = status->get_base_status(bl); + nullpo_ret(bst); type = status->skill2sc(sg->skill_id); skill_id = sg->skill_id; @@ -12074,12 +12333,12 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 tsc->sg_counter++; //SG hit counter. if (skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc) tsc->sg_counter=0; //Attack absorbed. - break; + break; #endif case GS_DESPERADO: if (rnd()%100 < src->val1) skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - break; + break; default: skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); } @@ -12160,11 +12419,13 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_VERDURETRAP: if( bl->type == BL_PC )// it won't work on players break; + FALLTHROUGH case UNT_FIRINGTRAP: case UNT_ICEBOUNDTRAP: case UNT_CLUSTERBOMB: if( bl->id == ss->id )// it won't trigger on caster break; + FALLTHROUGH case UNT_LANDMINE: case UNT_BLASTMINE: case UNT_SHOCKWAVE: @@ -12456,6 +12717,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_STEALTHFIELD: if( bl->id == sg->src_id ) break; // Don't work on Self (video shows that) + FALLTHROUGH case UNT_NEUTRALBARRIER: sc_start(ss,bl,type,100,sg->skill_lv,sg->interval + 100); break; @@ -12646,6 +12908,30 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 status->change_start(ss, bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill->get_time2(sg->skill_id, sg->skill_lv), SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE); break; + case UNT_SV_ROOTTWIST: + if (status_get_mode(bl)&MD_BOSS) { + break; + } + if (tsc) { + if (!sg->val2) { + int sec = skill->get_time(sg->skill_id, sg->skill_lv); + + if (sc_start2(ss, bl, type, 100, sg->skill_lv, sg->group_id, sec)) { + const struct TimerData* td = ((tsc->data[type])? timer->get(tsc->data[type]->timer) : NULL); + + if (td != NULL) + sec = DIFF_TICK32(td->tick, tick); + clif->fixpos(bl); + sg->val2 = bl->id; + } else { // Couldn't trap it? + sec = 7000; + } + sg->limit = DIFF_TICK32(tick, sg->tick) + sec; + } else if (tsc->data[type] && bl->id == sg->val2) { + skill->attack(skill->get_type(SU_SV_ROOTTWIST_ATK), ss, &src->bl, bl, SU_SV_ROOTTWIST_ATK, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION); + } + } + break; default: skill->unit_onplace_timer_unknown(src, bl, &tick); break; @@ -12664,7 +12950,8 @@ void skill_unit_onplace_timer_unknown(struct skill_unit *src, struct block_list /*========================================== * Triggered when a char steps out of a skill cell *------------------------------------------*/ -int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick) { +int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick) +{ struct skill_unit_group *sg; struct status_change *sc; struct status_change_entry *sce; @@ -12729,7 +13016,8 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick) /*========================================== * Triggered when a char steps out of a skill group (entirely) [Skotlex] *------------------------------------------*/ -int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) { +int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) +{ struct status_change *sc; struct status_change_entry *sce; enum sc_type type; @@ -12814,7 +13102,8 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) { case PF_FOGWALL: if (sce) { status_change_end(bl, type, INVALID_TIMER); - if ((sce=sc->data[SC_BLIND])) { + nullpo_retb(sc); + if ((sce = sc->data[SC_BLIND])) { if (bl->type == BL_PC) //Players get blind ended immediately, others have it still for 30 secs. [Skotlex] status_change_end(bl, SC_BLIND, INVALID_TIMER); else { @@ -12842,14 +13131,19 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) { * flag&1: Invoke onplace function (otherwise invoke onout) * flag&4: Invoke a onleft call (the unit might be scheduled for deletion) *------------------------------------------*/ -int skill_unit_effect(struct block_list* bl, va_list ap) { +int skill_unit_effect(struct block_list* bl, va_list ap) +{ struct skill_unit* su = va_arg(ap,struct skill_unit*); - struct skill_unit_group* group = su->group; + struct skill_unit_group* group; int64 tick = va_arg(ap,int64); unsigned int flag = va_arg(ap,unsigned int); uint16 skill_id; bool dissonance; + nullpo_ret(bl); + nullpo_ret(su); + group = su->group; + if( (!su->alive && !(flag&4)) || bl->prev == NULL ) return 0; @@ -12881,7 +13175,8 @@ int skill_unit_effect(struct block_list* bl, va_list ap) { /*========================================== * *------------------------------------------*/ -int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, int64 damage, int64 tick) { +int skill_unit_ondamaged(struct skill_unit *src, struct block_list *bl, int64 damage, int64 tick) +{ struct skill_unit_group *sg; nullpo_ret(src); @@ -13002,12 +13297,16 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap) /*========================================== * Checks and stores partners for ensemble skills [Skotlex] *------------------------------------------*/ -int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, uint16* skill_lv, int range, int cast_flag) { +int skill_check_pc_partner(struct map_session_data *sd, uint16 skill_id, uint16* skill_lv, int range, int cast_flag) +{ static int c=0; static int p_sd[2] = { 0, 0 }; int i; bool is_chorus = ( skill->get_inf2(skill_id)&INF2_CHORUS_SKILL ); + nullpo_ret(sd); + nullpo_ret(skill_lv); + if (!battle_config.player_skill_partner_check || pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL)) return is_chorus ? MAX_PARTY : 99; //As if there were infinite partners. @@ -13084,6 +13383,7 @@ int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap) *------------------------------------------*/ int skill_isammotype (struct map_session_data *sd, int skill_id) { + nullpo_ret(sd); return ( battle_config.arrow_decrement==2 && (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) && @@ -13123,7 +13423,8 @@ bool skill_is_combo( int skill_id ) return false; } -int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) { +int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) +{ struct status_data *st; struct status_change *sc; struct skill_condition require; @@ -13220,8 +13521,10 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case SG_FUSION: case RA_WUGDASH: case KO_YAMIKUMO: - if( sc && sc->data[status->skill2sc(skill_id)] ) + case SU_HIDE: + if (sc && sc->data[status->skill2sc(skill_id)]) return 1; + FALLTHROUGH default: { int ret = skill->check_condition_castbegin_off_unknown(sc, &skill_id); @@ -13328,6 +13631,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } + FALLTHROUGH case SA_CASTCANCEL: if(sd->ud.skilltimer == INVALID_TIMER) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -13577,6 +13881,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } + FALLTHROUGH case GD_EMERGENCYCALL: // other checks were already done in skillnotok() if (!sd->status.guild_id || !sd->state.gmaster_flag) @@ -13599,6 +13904,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } + FALLTHROUGH case NJ_BUNSINJYUTSU: if (!(sc && sc->data[SC_NJ_NEN])) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -13637,7 +13943,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id { int count = 0, i; for( i = 0; i < MAX_INVENTORY; i ++ ) - if( sd->status.inventory[i].nameid == ITEMID_ANCILLA ) + if (sd->status.inventory[i].nameid == ITEMID_ANSILA) count += sd->status.inventory[i].amount; if( count >= 3 ) { clif->skill_fail(sd, skill_id, USESKILL_FAIL_ANCILLA_NUMOVER, 0); @@ -13925,6 +14231,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } + FALLTHROUGH case ST_CART: if(!pc_iscarton(sd)) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_CART,0); @@ -14018,11 +14325,13 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } + FALLTHROUGH case ST_MH_GRAPPLING: if (!(sc && sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val2 == MH_MD_GRAPPLING)){ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } + FALLTHROUGH case ST_PECO: if (!pc_isridingpeco(sd)) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); @@ -14089,7 +14398,8 @@ int skill_check_condition_castbegin_unknown(struct status_change *sc, uint16 *sk return -1; } -int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) { +int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) +{ struct skill_condition require; struct status_data *st; int i; @@ -14266,7 +14576,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, cause = USESKILL_FAIL_BLUEJAMSTONE; break; case ITEMID_HOLY_WATER: cause = USESKILL_FAIL_HOLYWATER; break; - case ITEMID_ANCILLA: + case ITEMID_ANSILA: cause = USESKILL_FAIL_ANCILLA; break; case ITEMID_ACCELERATOR: case ITEMID_HOVERING_BOOSTER: @@ -14293,12 +14603,14 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, return 1; } -void skill_check_condition_castend_unknown(struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv) { +void skill_check_condition_castend_unknown(struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv) +{ } // type&2: consume items (after skill was used) // type&1: consume the others (before skill was used) -int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type) { +int skill_consume_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type) +{ struct skill_condition req; nullpo_ret(sd); @@ -14379,7 +14691,8 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin return 1; } -struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) { +struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) +{ struct skill_condition req; struct status_data *st; struct status_change *sc; @@ -14421,7 +14734,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 case TK_READYTURN: case SG_FUSION: case KO_YAMIKUMO: - if( sc && sc->data[status->skill2sc(skill_id)] ) + case SU_HIDE: + if (sc && sc->data[status->skill2sc(skill_id)]) return req; /* Fall through */ default: @@ -14577,7 +14891,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 if ((item_index = pc->search_inventory(sd, req.itemid[i])) == INDEX_NOT_FOUND || sd->status.inventory[item_index].amount < req.amount[i] ) { - req.itemid[i] = ITEMID_TRAP_ALLOY; + req.itemid[i] = ITEMID_SPECIAL_ALLOY_TRAP; req.amount[i] = 1; } break; @@ -14604,14 +14918,14 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 switch(skill_lv) { case 1: case 2: - req.itemid[1] = ITEMID_REPAIR_A; + req.itemid[1] = ITEMID_REPAIRA; break; case 3: case 4: - req.itemid[1] = ITEMID_REPAIR_B; + req.itemid[1] = ITEMID_REPAIRB; break; case 5: - req.itemid[1] = ITEMID_REPAIR_C; + req.itemid[1] = ITEMID_REPAIRC; break; } req.amount[1] = 1; @@ -14724,7 +15038,8 @@ void skill_get_requirement_unknown(struct status_change *sc, struct map_session_ /*========================================== * Does cast-time reductions based on dex, item bonuses and config setting *------------------------------------------*/ -int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { +int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) +{ int time = skill->get_cast(skill_id, skill_lv); nullpo_ret(bl); @@ -14774,11 +15089,13 @@ int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { /*========================================== * Does cast-time reductions based on sc data. *------------------------------------------*/ -int skill_castfix_sc (struct block_list *bl, int time) { +int skill_castfix_sc (struct block_list *bl, int time) +{ struct status_change *sc = status->get_sc(bl); if( time < 0 ) return 0; + nullpo_ret(bl); if( bl->type == BL_MOB ) // mobs casttime is fixed nothing to alter. return time; @@ -14807,7 +15124,9 @@ int skill_castfix_sc (struct block_list *bl, int time) { //ShowInfo("Castime castfix_sc = %d\n",time); return time; } -int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv) { + +int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv) +{ #ifdef RENEWAL_CAST struct status_change *sc = status->get_sc(bl); struct map_session_data *sd = BL_CAST(BL_PC,bl); @@ -14815,6 +15134,7 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 if( time < 0 ) return 0; + nullpo_ret(bl); if( bl->type == BL_MOB ) // mobs casttime is fixed nothing to alter. return (int)time; @@ -14886,6 +15206,7 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 case WZ_FIREPILLAR: if(skill_lv < 5) break; + FALLTHROUGH case HW_GRAVITATION: case MG_SAFETYWALL: case MG_STONECURSE: @@ -14947,7 +15268,8 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 /*========================================== * Does delay reductions based on dex/agi, sc data, item bonuses, ... *------------------------------------------*/ -int skill_delay_fix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { +int skill_delay_fix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) +{ int delaynodex = skill->get_delaynodex(skill_id, skill_lv); int time = skill->get_delay(skill_id, skill_lv); struct map_session_data *sd; @@ -15046,7 +15368,8 @@ struct square { int val2[5]; }; -void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y) { +void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y) +{ nullpo_retv(tc); if(dir == 0){ @@ -15141,7 +15464,8 @@ void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y) } -void skill_brandishspear_dir (struct square* tc, uint8 dir, int are) { +void skill_brandishspear_dir (struct square* tc, uint8 dir, int are) +{ int c; nullpo_retv(tc); @@ -15159,11 +15483,17 @@ void skill_brandishspear_dir (struct square* tc, uint8 dir, int are) { } } -void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) { +void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) +{ int c,n=4; - uint8 dir = map->calc_dir(src,bl->x,bl->y); + uint8 dir; struct square tc; - int x=bl->x,y=bl->y; + int x, y; + + nullpo_retv(bl); + x = bl->x; + y = bl->y; + dir = map->calc_dir(src, x, y); skill->brandishspear_first(&tc,dir,x,y); skill->brandishspear_dir(&tc,dir,4); skill->area_temp[1] = bl->id; @@ -15208,7 +15538,8 @@ void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 s /*========================================== * Weapon Repair [Celest/DracoRPG] *------------------------------------------*/ -void skill_repairweapon (struct map_session_data *sd, int idx) { +void skill_repairweapon (struct map_session_data *sd, int idx) +{ int material; int materials[4] = { ITEMID_IRON_ORE, @@ -15552,10 +15883,12 @@ int skill_frostjoke_scream(struct block_list *bl, va_list ap) /*========================================== * *------------------------------------------*/ -void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag) { +void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag) +{ int range = skill->get_unit_range(skill_id,skill_lv); int x,y; + nullpo_retv(src); for( y = src->bl.y - range; y <= src->bl.y + range; ++y ) for( x = src->bl.x - range; x <= src->bl.x + range; ++x ) map->list[src->bl.m].setcell(src->bl.m, x, y, cell, flag); @@ -15564,11 +15897,14 @@ void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill /*========================================== * *------------------------------------------*/ -int skill_attack_area(struct block_list *bl, va_list ap) { +int skill_attack_area(struct block_list *bl, va_list ap) +{ struct block_list *src,*dsrc; int atk_type,skill_id,skill_lv,flag,type; int64 tick; + nullpo_ret(bl); + if(status->isdead(bl)) return 0; @@ -15648,7 +15984,8 @@ int skill_clear_group (struct block_list *bl, int flag) /*========================================== * Returns the first element field found [Skotlex] *------------------------------------------*/ -struct skill_unit_group *skill_locate_element_field(struct block_list *bl) { +struct skill_unit_group *skill_locate_element_field(struct block_list *bl) +{ struct unit_data *ud = unit->bl2ud(bl); int i; nullpo_ret(bl); @@ -15986,7 +16323,8 @@ int skill_trap_splash(struct block_list *bl, va_list ap) /*========================================== * *------------------------------------------*/ -int skill_enchant_elemental_end (struct block_list *bl, int type) { +int skill_enchant_elemental_end(struct block_list *bl, int type) +{ struct status_change *sc; const enum sc_type scs[] = { SC_ENCHANTPOISON, SC_ASPERSIO, SC_PROPERTYFIRE, SC_PROPERTYWATER, SC_PROPERTYWIND, SC_PROPERTYGROUND, SC_PROPERTYDARK, SC_PROPERTYTELEKINESIS, SC_ENCHANTARMS }; int i; @@ -16006,6 +16344,7 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce { bool wall = true; + nullpo_retr(false, bl); if( (bl->type == BL_PC && battle_config.pc_cloak_check_type&1) || (bl->type != BL_PC && battle_config.monster_cloak_check_type&1) ) { @@ -16040,7 +16379,8 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce /** * Verifies if an user can use SC_CLOAKING **/ -bool skill_can_cloak(struct map_session_data *sd) { +bool skill_can_cloak(struct map_session_data *sd) +{ nullpo_retr(false, sd); //Avoid cloaking with no wall and low skill level. [Skotlex] @@ -16071,6 +16411,7 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s { bool wall = true; + nullpo_retr(false, bl); if( bl->type == BL_PC ) { //Check for walls. static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1}; static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1}; @@ -16133,7 +16474,8 @@ bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit) /*========================================== * *------------------------------------------*/ -struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2) { +struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2) +{ struct skill_unit *su; nullpo_retr(NULL, group); @@ -16185,7 +16527,8 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int /*========================================== * *------------------------------------------*/ -int skill_delunit (struct skill_unit* su) { +int skill_delunit (struct skill_unit* su) +{ struct skill_unit_group *group; nullpo_ret(su); @@ -16506,6 +16849,7 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list struct skill_unit_group_tickset *set; nullpo_ret(bl); + nullpo_ret(group); if (group->interval==-1) return NULL; @@ -16540,10 +16884,16 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list /*========================================== * *------------------------------------------*/ -int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) { - struct skill_unit* su = va_arg(ap,struct skill_unit *); - struct skill_unit_group* group = su->group; - int64 tick = va_arg(ap,int64); +int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) +{ + struct skill_unit* su; + struct skill_unit_group* group; + int64 tick; + + su = va_arg(ap,struct skill_unit *); + nullpo_ret(su); + group = su->group; + tick = va_arg(ap,int64); if( !su->alive || bl->prev == NULL ) return 0; @@ -16566,11 +16916,16 @@ int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) { */ int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap) { - struct skill_unit* su = DB->data2ptr(data); - struct skill_unit_group* group = su->group; + struct skill_unit* su; + struct skill_unit_group* group; int64 tick = va_arg(ap,int64); bool dissonance; - struct block_list* bl = &su->bl; + struct block_list* bl; + + su = DB->data2ptr(data); + nullpo_ret(su); + group = su->group; + bl = &su->bl; if( !su->alive ) return 0; @@ -16603,6 +16958,7 @@ int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap) skill->delunit(su); break; } + FALLTHROUGH case UNT_SKIDTRAP: case UNT_LANDMINE: case UNT_SHOCKWAVE: @@ -16627,7 +16983,7 @@ int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap) // revert unit back into a trap struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = group->item_id?group->item_id:ITEMID_TRAP; + item_tmp.nameid = group->item_id ? group->item_id : ITEMID_BOOBY_TRAP; item_tmp.identify = 1; map->addflooritem(bl, &item_tmp, 1, bl->m, bl->x, bl->y, 0, 0, 0, 0); } @@ -16778,7 +17134,8 @@ int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap) /*========================================== * Executes on all skill units every SKILLUNITTIMER_INTERVAL milliseconds. *------------------------------------------*/ -int skill_unit_timer(int tid, int64 tick, int id, intptr_t data) { +int skill_unit_timer(int tid, int64 tick, int id, intptr_t data) +{ map->freeblock_lock(); skill->unit_db->foreach(skill->unit_db, skill->unit_timer_sub, tick); @@ -16804,6 +17161,7 @@ int skill_unit_move_sub(struct block_list* bl, va_list ap) uint16 skill_id; int i; + nullpo_ret(target); nullpo_ret(bl); Assert_ret(bl->type == BL_SKILL); su = BL_UCAST(BL_SKILL, bl); @@ -16890,7 +17248,8 @@ int skill_unit_move_sub(struct block_list* bl, va_list ap) * units to figure out when they have left a group. * flag&4: Force a onleft event (triggered when the bl is killed, for example) *------------------------------------------*/ -int skill_unit_move(struct block_list *bl, int64 tick, int flag) { +int skill_unit_move(struct block_list *bl, int64 tick, int flag) +{ nullpo_ret(bl); if( bl->prev == NULL ) @@ -16915,7 +17274,8 @@ int skill_unit_move(struct block_list *bl, int64 tick, int flag) { /*========================================== * *------------------------------------------*/ -int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx, int16 dy) { +int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx, int16 dy) +{ int i,j; int64 tick = timer->gettick(); int *m_flag; @@ -17067,7 +17427,8 @@ int skill_can_produce_mix (struct map_session_data *sd, int nameid, int trigger, /*========================================== * *------------------------------------------*/ -int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty) { +int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty) +{ int slot[3]; int i,sc,ele,idx,equip,wlv,make_per = 0,flag = 0,skill_lv = 0; int num = -1; // exclude the recipe @@ -17262,12 +17623,15 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid, case ITEMID_HAGALAZ: case ITEMID_OTHILA: D -= 500; //Rank C + FALLTHROUGH case ITEMID_ISA: case ITEMID_WYRD: D -= 500; //Rank B + FALLTHROUGH case ITEMID_NAUTHIZ: case ITEMID_URUZ: D -= 500; //Rank A + FALLTHROUGH case ITEMID_BERKANA: case ITEMID_LUX_ANIMA: D -= 500; //Rank S @@ -17712,7 +18076,9 @@ int skill_arrow_create (struct map_session_data *sd, int nameid) return 0; } -int skill_poisoningweapon( struct map_session_data *sd, int nameid) { + +int skill_poisoningweapon(struct map_session_data *sd, int nameid) +{ sc_type type; int chance, i; nullpo_ret(sd); @@ -17743,7 +18109,8 @@ int skill_poisoningweapon( struct map_session_data *sd, int nameid) { return 0; } -void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) { +void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) +{ struct status_change *sc = status->get_sc(bl); // non-offensive and non-magic skills do not affect the status @@ -17767,7 +18134,8 @@ void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) { } } -int skill_magicdecoy(struct map_session_data *sd, int nameid) { +int skill_magicdecoy(struct map_session_data *sd, int nameid) +{ int x, y, i, class_ = 0, skill_id; struct mob_data *md; nullpo_ret(sd); @@ -17789,16 +18157,16 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) { sd->menuskill_val = 0; switch (nameid) { - case ITEMID_SCARLET_POINT: + case ITEMID_SCARLET_PTS: class_ = MOBID_MAGICDECOY_FIRE; break; - case ITEMID_INDIGO_POINT: + case ITEMID_INDIGO_PTS: class_ = MOBID_MAGICDECOY_WATER; break; - case ITEMID_LIME_GREEN_POINT: + case ITEMID_LIME_GREEN_PTS: class_ = MOBID_MAGICDECOY_WIND; break; - case ITEMID_YELLOW_WISH_POINT: + case ITEMID_YELLOW_WISH_PTS: class_ = MOBID_MAGICDECOY_EARTH; break; } @@ -17818,7 +18186,8 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) { } // Warlock Spellbooks. [LimitLine/3CeAM] -int skill_spellbook (struct map_session_data *sd, int nameid) { +int skill_spellbook(struct map_session_data *sd, int nameid) +{ int i, max_preserve, skill_id, point; struct status_change *sc; @@ -17866,7 +18235,9 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { return 1; } -int skill_select_menu(struct map_session_data *sd,uint16 skill_id) { + +int skill_select_menu(struct map_session_data *sd,uint16 skill_id) +{ int id, lv, prob, aslvl = 0, idx = 0; nullpo_ret(sd); @@ -18012,6 +18383,7 @@ int skill_changematerial(struct map_session_data *sd, const struct itemlist *ite return 0; } + /** * for Royal Guard's LG_TRAMPLE **/ @@ -18047,10 +18419,12 @@ int skill_destroy_trap(struct block_list *bl, va_list ap) } return 0; } + /*========================================== * *------------------------------------------*/ -int skill_blockpc_end(int tid, int64 tick, int id, intptr_t data) { +int skill_blockpc_end(int tid, int64 tick, int id, intptr_t data) +{ struct map_session_data *sd = map->id2sd(id); struct skill_cd * cd = NULL; @@ -18102,7 +18476,8 @@ int skill_blockpc_end(int tid, int64 tick, int id, intptr_t data) { * @param tick the length of time the delay should last * @return 0 if successful, -1 otherwise */ -int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick) { +int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick) +{ struct skill_cd* cd = NULL; uint16 idx = skill->get_index(skill_id); int64 now = timer->gettick(); @@ -18197,7 +18572,9 @@ int skill_blockhomun_end(int tid, int64 tick, int id, intptr_t data) return 1; } -int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { // [orn] +// [orn] +int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) +{ uint16 idx = skill->get_index(skill_id); nullpo_retr (-1, hd); @@ -18239,12 +18616,15 @@ int skill_blockmerc_start(struct mercenary_data *md, uint16 skill_id, int tick) md->blockskill[idx] = 1; return timer->add(timer->gettick() + tick, skill->blockmerc_end, md->bl.id, idx); } + /** * Adds a new skill unit entry for this player to recast after map load **/ -void skill_usave_add(struct map_session_data * sd, uint16 skill_id, uint16 skill_lv) { +void skill_usave_add(struct map_session_data * sd, uint16 skill_id, uint16 skill_lv) +{ struct skill_unit_save * sus = NULL; + nullpo_retv(sd); if( idb_exists(skill->usave_db,sd->status.char_id) ) { idb_remove(skill->usave_db,sd->status.char_id); } @@ -18257,9 +18637,12 @@ void skill_usave_add(struct map_session_data * sd, uint16 skill_id, uint16 skill return; } -void skill_usave_trigger(struct map_session_data *sd) { + +void skill_usave_trigger(struct map_session_data *sd) +{ struct skill_unit_save * sus = NULL; + nullpo_retv(sd); if( ! (sus = idb_get(skill->usave_db,sd->status.char_id)) ) { return; } @@ -18277,6 +18660,8 @@ int skill_split_atoi(char *str, int *val) { int i, j, step = 1; + nullpo_ret(val); + for (i=0; i<MAX_SKILL_LEVEL; i++) { if (!str) break; val[i] = atoi(str); @@ -18595,7 +18980,8 @@ void skill_init_unit_layout_unknown(int skill_idx) ShowError("unknown unit layout at skill %d\n", skill_idx); } -int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) { +int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) +{ int inf = 0; struct status_change *sc = status->get_sc(bl); @@ -18742,7 +19128,8 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) { return 0; } -int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) { +int skill_get_elemental_type(uint16 skill_id , uint16 skill_lv) +{ int type = 0; switch (skill_id) { @@ -18761,7 +19148,8 @@ int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) { * update stored skill cooldowns for player logout * @param sd the affected player structure */ -void skill_cooldown_save(struct map_session_data * sd) { +void skill_cooldown_save(struct map_session_data * sd) +{ int i; struct skill_cd* cd = NULL; int64 now = 0; @@ -18789,7 +19177,8 @@ void skill_cooldown_save(struct map_session_data * sd) { * reload stored skill cooldowns when a player logs in. * @param sd the affected player structure */ -void skill_cooldown_load(struct map_session_data * sd) { +void skill_cooldown_load(struct map_session_data * sd) +{ int i; struct skill_cd* cd = NULL; int64 now = 0; @@ -18813,11 +19202,14 @@ void skill_cooldown_load(struct map_session_data * sd) { } } -bool skill_parse_row_producedb(char* split[], int columns, int current) { +bool skill_parse_row_producedb(char* split[], int columns, int current) +{ // ProduceItemID,ItemLV,RequireSkill,Requireskill_lv,MaterialID1,MaterialAmount1,...... int x,y; + int i; - int i = atoi(split[0]); + nullpo_retr(false, split); + i = atoi(split[0]); if( !i ) return false; @@ -18834,11 +19226,14 @@ bool skill_parse_row_producedb(char* split[], int columns, int current) { return true; } -bool skill_parse_row_createarrowdb(char* split[], int columns, int current) { +bool skill_parse_row_createarrowdb(char* split[], int columns, int current) +{ // SourceID,MakeID1,MakeAmount1,...,MakeID5,MakeAmount5 int x,y; - int i = atoi(split[0]); + int i; + nullpo_retr(false, split); + i = atoi(split[0]); if( !i ) return false; @@ -18851,12 +19246,19 @@ bool skill_parse_row_createarrowdb(char* split[], int columns, int current) { return true; } -bool skill_parse_row_spellbookdb(char* split[], int columns, int current) { + +bool skill_parse_row_spellbookdb(char* split[], int columns, int current) +{ // skill_id,PreservePoints - uint16 skill_id = atoi(split[0]); - int points = atoi(split[1]); - int nameid = atoi(split[2]); + uint16 skill_id; + int points; + int nameid; + + nullpo_retr(false, split); + skill_id = atoi(split[0]); + points = atoi(split[1]); + nameid = atoi(split[2]); if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) ShowError("spellbook_db: Invalid skill ID %d\n", skill_id); @@ -18874,10 +19276,16 @@ bool skill_parse_row_spellbookdb(char* split[], int columns, int current) { return false; } -bool skill_parse_row_improvisedb(char* split[], int columns, int current) { + +bool skill_parse_row_improvisedb(char* split[], int columns, int current) +{ // SkillID,Rate - uint16 skill_id = atoi(split[0]); - short j = atoi(split[1]); + uint16 skill_id; + short j; + + nullpo_retr(false, split); + skill_id = atoi(split[0]); + j = atoi(split[1]); if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) { ShowError("skill_improvise_db: Invalid skill ID %d\n", skill_id); @@ -18900,10 +19308,14 @@ bool skill_parse_row_improvisedb(char* split[], int columns, int current) { return true; } -bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) { + +bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) +{ // SkillID - uint16 skill_id = atoi(split[0]); + uint16 skill_id; + nullpo_retr(false, split); + skill_id = atoi(split[0]); if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) { ShowError("magicmushroom_db: Invalid skill ID %d\n", skill_id); return false; @@ -18918,9 +19330,13 @@ bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) { return true; } -bool skill_parse_row_reproducedb(char* split[], int column, int current) { - uint16 skill_id = atoi(split[0]); - uint16 idx = skill->get_index(skill_id); +bool skill_parse_row_reproducedb(char* split[], int column, int current) +{ + uint16 skill_id; + uint16 idx; + nullpo_retr(false, split); + skill_id = atoi(split[0]); + idx = skill->get_index(skill_id); if( !idx ) return false; @@ -18929,9 +19345,12 @@ bool skill_parse_row_reproducedb(char* split[], int column, int current) { return true; } -bool skill_parse_row_abradb(char* split[], int columns, int current) { +bool skill_parse_row_abradb(char* split[], int columns, int current) +{ // skill_id,DummyName,RequiredHocusPocusLevel,Rate - uint16 skill_id = atoi(split[0]); + uint16 skill_id; + nullpo_retr(false, split); + skill_id = atoi(split[0]); if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) { ShowError("abra_db: Invalid skill ID %d\n", skill_id); return false; @@ -18948,12 +19367,16 @@ bool skill_parse_row_abradb(char* split[], int columns, int current) { return true; } -bool skill_parse_row_changematerialdb(char* split[], int columns, int current) { +bool skill_parse_row_changematerialdb(char* split[], int columns, int current) +{ // ProductID,BaseRate,MakeAmount1,MakeAmountRate1...,MakeAmount5,MakeAmountRate5 - uint16 skill_id = atoi(split[0]); - short j = atoi(split[1]); + uint16 skill_id; + short j; int x,y; + nullpo_retr(false, split); + skill_id = atoi(split[0]); + j = atoi(split[1]); for(x=0; x<MAX_SKILL_PRODUCE_DB; x++){ if( skill->dbs->produce_db[x].nameid == skill_id ) if( skill->dbs->produce_db[x].req_skill == GN_CHANGEMATERIAL ) @@ -18993,9 +19416,10 @@ void skill_config_set_level(struct config_setting_t *conf, int *arr) { int i=0; + nullpo_retv(arr); if (config_setting_is_group(conf)) { for (i=0; i<MAX_SKILL_LEVEL; i++) { - char level[5]; + char level[6]; // enough to contain "Lv100" in case of custom MAX_SKILL_LEVEL sprintf(level, "Lv%d", i+1); libconfig->setting_lookup_int(conf, level, &arr[i]); } @@ -19020,7 +19444,8 @@ void skill_config_set_level(struct config_setting_t *conf, int *arr) void skill_level_set_value(int *arr, int value) { int i=0; - + + nullpo_retv(arr); for(i=0; i<MAX_SKILL_LEVEL; i++) { arr[i] = value; } @@ -19030,6 +19455,7 @@ void skill_validate_hittype(struct config_setting_t *conf, struct s_skill_db *sk { const char *type = NULL; + nullpo_retv(sk); if (libconfig->setting_lookup_string(conf, "Hit", &type)) { if (strcmpi(type, "BDT_SKILL") == 0) { sk->hit = BDT_SKILL; @@ -19054,6 +19480,7 @@ void skill_validate_skilltype(struct config_setting_t *conf, struct s_skill_db * { struct config_setting_t *t = NULL, *tt = NULL; + nullpo_retv(sk); if((t=libconfig->setting_get_member(conf, "SkillType")) && config_setting_is_group(t)) { int j=0; while ((tt = libconfig->setting_get_elem(t, j++))) { @@ -19107,6 +19534,7 @@ void skill_validate_skillinfo(struct config_setting_t *conf, struct s_skill_db * { struct config_setting_t *t = NULL, *tt = NULL; + nullpo_retv(sk); if ((t=libconfig->setting_get_member(conf, "SkillInfo")) && config_setting_is_group(t)) { int j=0; while ((tt = libconfig->setting_get_elem(t, j++))) { @@ -19232,6 +19660,7 @@ void skill_validate_attacktype(struct config_setting_t *conf, struct s_skill_db { const char *type = NULL; + nullpo_retv(sk); if (libconfig->setting_lookup_string(conf, "AttackType", &type)) { if (!strcmpi(type, "Weapon")) { sk->skill_type = BF_WEAPON; @@ -19257,9 +19686,10 @@ void skill_validate_element(struct config_setting_t *conf, struct s_skill_db *sk const char *type = NULL; struct config_setting_t *t = NULL; + nullpo_retv(sk); if ((t=libconfig->setting_get_member(conf, "Element")) && config_setting_is_group(t)) { int j = 0; - char lv[5]; + char lv[6]; // enough to contain "Lv100" in case of custom MAX_SKILL_LEVEL for (j=0; j < MAX_SKILL_LEVEL; j++) { sprintf(lv, "Lv%d",j+1); @@ -19303,6 +19733,7 @@ void skill_validate_damagetype(struct config_setting_t *conf, struct s_skill_db { struct config_setting_t *t = NULL, *tt = NULL; + nullpo_retv(sk); if ((t=libconfig->setting_get_member(conf, "DamageType")) && config_setting_is_group(t)) { int j=0; while ((tt = libconfig->setting_get_elem(t, j++))) { @@ -19375,6 +19806,7 @@ void skill_validate_castnodex(struct config_setting_t *conf, struct s_skill_db * { struct config_setting_t *t = NULL, *tt = NULL; + nullpo_retv(sk); if ((t=libconfig->setting_get_member(conf, delay?"SkillDelayOptions":"CastTimeOptions")) && config_setting_is_group(t)) { int j = 0, tmpopt = 0; while ((tt = libconfig->setting_get_elem(t, j++)) && j < 4) { @@ -19417,8 +19849,9 @@ void skill_validate_castnodex(struct config_setting_t *conf, struct s_skill_db * * @param *sk struct, pointer to s_skill_db * @return void */ -int skill_validate_weapontype_sub(const char *type, bool on, struct s_skill_db *sk ) +int skill_validate_weapontype_sub(const char *type, bool on, struct s_skill_db *sk) { + nullpo_ret(sk); if (strcmpi(type, "NoWeapon") == 0) { if (on) { sk->weapon |= 1<<W_FIST; @@ -19624,15 +20057,16 @@ void skill_validate_weapontype(struct config_setting_t *conf, struct s_skill_db struct config_setting_t *tt = NULL; const char *type = NULL; + nullpo_retv(sk); if ((tt = libconfig->setting_get_member(conf, "WeaponTypes")) && config_setting_is_group(tt)) { int j = 0; struct config_setting_t *wpt = NULL; while ((wpt = libconfig->setting_get_elem(tt, j++)) != NULL) { - if (skill_validate_weapontype_sub(config_setting_name(wpt), libconfig->setting_get_bool_real(wpt), sk)) + if (skill->validate_weapontype_sub(config_setting_name(wpt), libconfig->setting_get_bool_real(wpt), sk)) skilldb_invalid_error(config_setting_name(wpt), config_setting_name(tt), sk->nameid); } } else if (libconfig->setting_lookup_string(conf, "WeaponTypes", &type)) { - if (skill_validate_weapontype_sub(type, true, sk)) + if (skill->validate_weapontype_sub(type, true, sk)) skilldb_invalid_error(type, "WeaponTypes", sk->nameid); } } @@ -19647,6 +20081,7 @@ void skill_validate_weapontype(struct config_setting_t *conf, struct s_skill_db */ int skill_validate_ammotype_sub(const char *type, bool on, struct s_skill_db *sk) { + nullpo_ret(sk); if (strcmpi(type, "A_ARROW") == 0) { if (on) { sk->ammo |= 1<<A_ARROW; @@ -19726,15 +20161,16 @@ void skill_validate_ammotype(struct config_setting_t *conf, struct s_skill_db *s struct config_setting_t *tt = NULL; const char *tstr = NULL; + nullpo_retv(sk); if ((tt = libconfig->setting_get_member(conf, "AmmoTypes")) && config_setting_is_group(tt)) { int j = 0; struct config_setting_t *amt = { 0 }; while ((amt = libconfig->setting_get_elem(tt, j++))) { - if (skill_validate_ammotype_sub(config_setting_name(amt), libconfig->setting_get_bool_real(amt), sk)) + if (skill->validate_ammotype_sub(config_setting_name(amt), libconfig->setting_get_bool_real(amt), sk)) skilldb_invalid_error(config_setting_name(amt), config_setting_name(tt), sk->nameid); } } else if( libconfig->setting_lookup_string(conf, "AmmoTypes", &tstr)) { - if (skill_validate_ammotype_sub(tstr, true, sk)) + if (skill->validate_ammotype_sub(tstr, true, sk)) skilldb_invalid_error(tstr, "AmmoTypes", sk->nameid); } } @@ -19750,6 +20186,7 @@ void skill_validate_state(struct config_setting_t *conf, struct s_skill_db *sk) { const char *type = NULL; + nullpo_retv(sk); if (libconfig->setting_lookup_string(conf, "State", &type) && strcmpi(type,"None") != ST_NONE) { if ( strcmpi(type,"Hiding") == 0 ) sk->state = ST_HIDING; else if (strcmpi(type,"Cloaking") == 0 ) sk->state = ST_CLOAKING; @@ -19790,6 +20227,7 @@ void skill_validate_item_requirements(struct config_setting_t *conf, struct s_sk { struct config_setting_t *tt = NULL; + nullpo_retv(sk); if ((tt=libconfig->setting_get_member(conf, "Items")) && config_setting_is_group(conf)) { int itx=-1; struct config_setting_t *it; @@ -19826,6 +20264,7 @@ void skill_validate_unit_target(struct config_setting_t *conf, struct s_skill_db { const char *type = NULL; + nullpo_retv(sk); if(libconfig->setting_lookup_string(conf, "Target", &type)) { if(!strcmpi(type,"NotEnemy")) sk->unit_target = BCT_NOENEMY; @@ -19865,6 +20304,8 @@ void skill_validate_unit_target(struct config_setting_t *conf, struct s_skill_db */ int skill_validate_unit_flag_sub(const char *type, bool on, struct s_skill_db *sk) { + nullpo_ret(type); + nullpo_ret(sk); if (strcmpi(type, "UF_DEFNOTENEMY") == 0) { if (on) { sk->unit_flag |= UF_DEFNOTENEMY; @@ -19961,13 +20402,14 @@ void skill_validate_unit_flag(struct config_setting_t *conf, struct s_skill_db * { struct config_setting_t *t = NULL; + nullpo_retv(sk); if ((t=libconfig->setting_get_member(conf, "Flag")) && config_setting_is_group(t)) { int j=0; struct config_setting_t *tt = NULL; while ((tt = libconfig->setting_get_elem(t, j++))) { const char *name = config_setting_name(tt); - if (skill_validate_unit_flag_sub(name, libconfig->setting_get_bool_real(tt), sk)) + if (skill->validate_unit_flag_sub(name, libconfig->setting_get_bool_real(tt), sk)) skilldb_invalid_error(name, config_setting_name(t), sk->nameid); } } @@ -19992,8 +20434,10 @@ void skill_validate_additional_fields(struct config_setting_t *conf, struct s_sk */ bool skill_validate_skilldb(struct s_skill_db *sk, const char *source) { - int idx = skill->get_index(sk->nameid); + int idx; + nullpo_retr(false, sk); + idx = skill->get_index(sk->nameid); if (idx == 0) { ShowWarning("skill_validate_skilldb: Invalid skill Id %d provided in '%s'! ... skipping\n", sk->nameid, source); ShowInfo("It is possible that the skill Id is 0 or unavailable (interferes with guild/homun/mercenary skill mapping).\n"); @@ -20276,7 +20720,8 @@ bool skill_read_skilldb(const char *filename) * create_arrow_db.txt * abra_db.txt *------------------------------*/ -void skill_readdb(bool minimal) { +void skill_readdb(bool minimal) +{ // init skill db structures db_clear(skill->name2id_db); @@ -20348,7 +20793,8 @@ void skill_reload(void) /*========================================== * *------------------------------------------*/ -int do_init_skill(bool minimal) { +int do_init_skill(bool minimal) +{ skill->name2id_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, MAX_SKILL_NAME_LENGTH); skill->read_db(minimal); @@ -20381,7 +20827,8 @@ int do_init_skill(bool minimal) { return 0; } -int do_final_skill(void) { +int do_final_skill(void) +{ db_destroy(skill->name2id_db); db_destroy(skill->group_db); db_destroy(skill->unit_db); @@ -20394,8 +20841,10 @@ int do_final_skill(void) { ers_destroy(skill->cd_entry_ers); return 0; } + /* initialize the interface */ -void skill_defaults(void) { +void skill_defaults(void) +{ const int skill_enchant_eff[5] = { 10, 14, 17, 19, 20 }; const int skill_deluge_eff[5] = { 5, 9, 12, 14, 15 }; @@ -20605,6 +21054,9 @@ void skill_defaults(void) { skill->validate_unit_flag = skill_validate_unit_flag; skill->validate_additional_fields = skill_validate_additional_fields; skill->validate_skilldb = skill_validate_skilldb; + skill->validate_weapontype_sub = skill_validate_weapontype_sub; + skill->validate_ammotype_sub = skill_validate_ammotype_sub; + skill->validate_unit_flag_sub = skill_validate_unit_flag_sub; skill->read_skilldb = skill_read_skilldb; skill->config_set_level = skill_config_set_level; skill->level_set_value = skill_level_set_value; |