int elemental_clean_single_effect (struct elemental_data *ed, int skill_num) { struct block_list *bl; sc_type type = status_skill2sc (skill_num); nullpo_ret (ed); bl = battle_get_master (&ed->bl); if (type) { switch (type) { // Just remove status change. case SC_PYROTECHNIC_OPTION: case SC_HEATER_OPTION: case SC_TROPIC_OPTION: case SC_FIRE_CLOAK_OPTION: case SC_AQUAPLAY_OPTION: case SC_WATER_SCREEN_OPTION: case SC_COOLER_OPTION: case SC_CHILLY_AIR_OPTION: case SC_GUST_OPTION: case SC_WIND_STEP_OPTION: case SC_BLAST_OPTION: case SC_WATER_DROP_OPTION: case SC_WIND_CURTAIN_OPTION: case SC_WILD_STORM_OPTION: case SC_PETROLOGY_OPTION: case SC_SOLID_SKIN_OPTION: case SC_CURSED_SOIL_OPTION: case SC_STONE_SHIELD_OPTION: case SC_UPHEAVAL_OPTION: case SC_CIRCLE_OF_FIRE_OPTION: case SC_TIDAL_WEAPON_OPTION: if (bl) status_change_end (bl, type, INVALID_TIMER); // Master status_change_end (&ed->bl, type - 1, INVALID_TIMER); // Elemental Spirit break; case SC_ZEPHYR: if (bl) status_change_end (bl, type, INVALID_TIMER); break; default: ShowWarning ("Invalid SC=%d in elemental_clean_single_effect\n", type); break; } } if (skill_get_unit_id (skill_num, 0)) skill_clear_unitgroup (&ed->bl); return 1; }
int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick) { struct skill_condition req; uint16 skill_id, skill_lv; int i; nullpo_ret(ed); nullpo_ret(bl); if( !ed->master ) return 0; if( ed->target_id ) elemental_unlocktarget(ed); // Remove previous target. ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&EL_SKILLMODE_AGGRESSIVE)); if( i == MAX_ELESKILLTREE ) return 0; skill_id = ed->db->skill[i].id; skill_lv = ed->db->skill[i].lv; if( elemental_skillnotok(skill_id, ed) ) return 0; if( ed->ud.skilltimer != INVALID_TIMER ) return 0; else if( DIFF_TICK(tick, ed->ud.canact_tick) < 0 ) return 0; ed->target_id = ed->ud.skilltarget = bl->id; // Set new target ed->last_thinktime = tick; // Not in skill range. if( !battle_check_range(&ed->bl,bl,skill_get_range(skill_id,skill_lv)) ) { // Try to walk to the target. if( !unit_walktobl(&ed->bl, bl, skill_get_range(skill_id,skill_lv), 2) ) elemental_unlocktarget(ed); else { // Walking, waiting to be in range. Client don't handle it, then we must handle it here. int walk_dist = distance_bl(&ed->bl,bl) - skill_get_range(skill_id,skill_lv); ed->ud.skill_id = skill_id; ed->ud.skill_lv = skill_lv; if( skill_get_inf(skill_id) & INF_GROUND_SKILL ) ed->ud.skilltimer = add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill_castend_pos, ed->bl.id, 0 ); else ed->ud.skilltimer = add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill_castend_id, ed->bl.id, 0 ); } return 1; } req = elemental_skill_get_requirements(skill_id, skill_lv); if(req.hp || req.sp){ struct map_session_data *sd = BL_CAST(BL_PC, battle_get_master(&ed->bl)); if( sd ){ if( sd->skill_id_old != SO_EL_ACTION && //regardless of remaining HP/SP it can be cast (status_get_hp(&ed->bl) < req.hp || status_get_sp(&ed->bl) < req.sp) ) return 1; else status_zap(&ed->bl, req.hp, req.sp); } } //Otherwise, just cast the skill. if( skill_get_inf(skill_id) & INF_GROUND_SKILL ) unit_skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv); else unit_skilluse_id(&ed->bl, bl->id, skill_id, skill_lv); // Reset target. ed->target_id = 0; return 1; }