diff options
author | shennetsind <ind@henn.et> | 2013-02-14 21:12:18 -0200 |
---|---|---|
committer | shennetsind <ind@henn.et> | 2013-02-14 21:12:18 -0200 |
commit | 7d33212f95653edd621961487f5622611d62ae88 (patch) | |
tree | b992a814eeefc27de512231c5bf5eaf0c2efa111 /src/map | |
parent | 82005a99f5b1cca68e9fb1ac6b1614c815e4bd45 (diff) | |
download | hercules-7d33212f95653edd621961487f5622611d62ae88.tar.gz hercules-7d33212f95653edd621961487f5622611d62ae88.tar.bz2 hercules-7d33212f95653edd621961487f5622611d62ae88.tar.xz hercules-7d33212f95653edd621961487f5622611d62ae88.zip |
New Mapflag adjust_unit_duration
Made as a improvement of the original ADJUST_TRAP_DURATION -- special thanks to Muad_Dib! .
This mapflag allows you to control the duration of unit skills in any map, for example.
"prontera mapflag adjust_unit_duration PR_SANCTUARY 50"
halves the duration of sanctuary in prontera
Another Example:
"prontera mapflag adjust_unit_duration WZ_QUAGMIRE 250"
Increases duration of quagmire by 2.5 times in prontera map.
Be aware that some skill units have their visual effect durations not controlled by the server (e.g. storm gust).
Signed-off-by: shennetsind <ind@henn.et>
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/map.c | 61 | ||||
-rw-r--r-- | src/map/map.h | 8 | ||||
-rw-r--r-- | src/map/npc.c | 21 | ||||
-rw-r--r-- | src/map/skill.c | 687 |
4 files changed, 417 insertions, 360 deletions
diff --git a/src/map/map.c b/src/map/map.c index a42d7abca..1ffffdf59 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -2894,13 +2894,41 @@ int map_delmap(char* mapname) return 0; } +void map_data_clean(void) { + int i; + + for( i = 0; i < map_num; i++ ) { + + if(map[i].cell) aFree(map[i].cell); + if(map[i].block) aFree(map[i].block); + if(map[i].block_mob) aFree(map[i].block_mob); + + if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random] + int j; + if(map[i].mob_delete_timer != INVALID_TIMER) + delete_timer(map[i].mob_delete_timer, map_removemobs_timer); + for (j=0; j<MAX_MOB_LIST_PER_MAP; j++) + if (map[i].moblist[j]) aFree(map[i].moblist[j]); + } + + if( map[i].unit_count ) { + int v; + for(v = 0; v < map[i].unit_count; v++) { + aFree(map[i].units[v]); + } + aFree(map[i].units); + map[i].unit_count = 0; + } + + } + +} + /// Initializes map flags and adjusts them depending on configuration. -void map_flags_init(void) -{ +void map_flags_init(void) { int i; - for( i = 0; i < map_num; i++ ) - { + for( i = 0; i < map_num; i++ ) { // mapflags memset(&map[i].flag, 0, sizeof(map[i].flag)); @@ -2911,6 +2939,15 @@ void map_flags_init(void) map[i].jexp = 100; // per map job exp multiplicator memset(map[i].drop_list, 0, sizeof(map[i].drop_list)); // pvp nightmare drop list + if( map[i].unit_count ) { + int v; + for(v = 0; v < map[i].unit_count; v++) { + aFree(map[i].units[v]); + } + aFree(map[i].units); + map[i].unit_count = 0; + } + // adjustments if( battle_config.pk_mode ) map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris] @@ -3552,7 +3589,7 @@ static int cleanup_db_sub(DBKey key, DBData *data, va_list va) *------------------------------------------*/ void do_final(void) { - int i, j; + int i; struct map_session_data* sd; struct s_mapiterator* iter; @@ -3603,18 +3640,8 @@ void do_final(void) map_db->destroy(map_db, map_db_final); - for (i=0; i<map_num; i++) { - if(map[i].cell) aFree(map[i].cell); - if(map[i].block) aFree(map[i].block); - if(map[i].block_mob) aFree(map[i].block_mob); - if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random] - if(map[i].mob_delete_timer != INVALID_TIMER) - delete_timer(map[i].mob_delete_timer, map_removemobs_timer); - for (j=0; j<MAX_MOB_LIST_PER_MAP; j++) - if (map[i].moblist[j]) aFree(map[i].moblist[j]); - } - } - + map_data_clean(); + mapindex_final(); if(enable_grf) grfio_final(); diff --git a/src/map/map.h b/src/map/map.h index 73f8e694b..a9699efc2 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -496,6 +496,11 @@ struct iwall_data { bool shootable; }; +struct adjust_unit_duration { + int skill_id; + unsigned short modifier; +}; + struct map_data { char name[MAP_NAME_LENGTH]; uint16 index; // The map index used by the mapindex* functions. @@ -588,6 +593,9 @@ struct map_data { // Instance Variables int instance_id; int instance_src_map; + + struct adjust_unit_duration **units; + unsigned short unit_count; }; /// Stores information about a remote map (for multi-mapserver setups). diff --git a/src/map/npc.c b/src/map/npc.c index ba476e810..265fbb01f 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -3398,7 +3398,26 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con map[m].flag.guildlock=state; else if (!strcmpi(w3,"reset")) map[m].flag.reset=state; - else + else if (!strcmpi(w3,"adjust_unit_duration")) { + char *mod; + int skill_id; + + strtok(w4,"\t");/* makes w4 contain only 4th param */ + + if( !(mod = strtok(NULL,"\t")) ) {/* makes mod contain only the 5th param */ + ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); + } else if( !( skill_id = skill_name2id(w4) ) || !skill_get_unit_id( skill_name2id(w4), 0) ) { + ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n", w4, map[m].name, filepath, strline(buffer,start-buffer)); + } else if ( atoi(mod) < 1 || atoi(mod) > USHRT_MAX ) { + ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n", atoi(mod), w4, map[m].name, filepath, strline(buffer,start-buffer)); + } else { + int idx = map[m].unit_count; + RECREATE(map[m].units, struct adjust_unit_duration*, ++map[m].unit_count); + CREATE(map[m].units[idx],struct adjust_unit_duration,1); + map[m].units[idx]->skill_id = skill_id; + map[m].units[idx]->modifier = (unsigned short)atoi(mod); + } + } else ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// continue diff --git a/src/map/skill.c b/src/map/skill.c index ba720da42..b37d28e3c 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -10570,308 +10570,316 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill unit_flag = skill_get_unit_flag(skill_id); layout = skill_get_unit_layout(skill_id,skill_lv,src,x,y); + if( map[src->m].unit_count ) { + ARR_FIND(0, map[src->m].unit_count, i, map[src->m].units[i]->skill_id == skill_id ); + + if( i < map[src->m].unit_count ) { + limit = limit * map[src->m].units[i]->modifier / 100; + } + } + sd = BL_CAST(BL_PC, src); status = status_get_status_data(src); sc = status_get_sc(src); // for traps, firewall and fogwall - celest switch( skill_id ) { - case MH_STEINWAND: - val2 = 4 + skill_lv; //nb of attack blocked - break; - case MG_SAFETYWALL: - #ifdef RENEWAL - /** - * According to data provided in RE, SW life is equal to 3 times caster's health - **/ - val2 = status_get_max_hp(src) * 3; - #else - val2 = skill_lv+1; - #endif - break; - case MG_FIREWALL: - if(sc && sc->data[SC_VIOLENTGALE]) - limit = limit*3/2; - val2=4+skill_lv; - break; + case MH_STEINWAND: + val2 = 4 + skill_lv; //nb of attack blocked + break; + case MG_SAFETYWALL: + #ifdef RENEWAL + /** + * According to data provided in RE, SW life is equal to 3 times caster's health + **/ + val2 = status_get_max_hp(src) * 3; + #else + val2 = skill_lv+1; + #endif + break; + case MG_FIREWALL: + if(sc && sc->data[SC_VIOLENTGALE]) + limit = limit*3/2; + val2=4+skill_lv; + break; - case AL_WARP: - val1=skill_lv+6; - if(!(flag&1)) - limit=2000; - else // previous implementation (not used anymore) - { //Warp Portal morphing to active mode, extract relevant data from src. [Skotlex] - if( src->type != BL_SKILL ) return NULL; - group = ((TBL_SKILL*)src)->group; - src = map_id2bl(group->src_id); - if( !src ) return NULL; - val2 = group->val2; //Copy the (x,y) position you warp to - val3 = group->val3; //as well as the mapindex to warp to. - } - break; - case HP_BASILICA: - val1 = src->id; // Store caster id. - break; + case AL_WARP: + val1=skill_lv+6; + if(!(flag&1)) + limit=2000; + else // previous implementation (not used anymore) + { //Warp Portal morphing to active mode, extract relevant data from src. [Skotlex] + if( src->type != BL_SKILL ) return NULL; + group = ((TBL_SKILL*)src)->group; + src = map_id2bl(group->src_id); + if( !src ) return NULL; + val2 = group->val2; //Copy the (x,y) position you warp to + val3 = group->val3; //as well as the mapindex to warp to. + } + break; + case HP_BASILICA: + val1 = src->id; // Store caster id. + break; - case PR_SANCTUARY: - case NPC_EVILLAND: - val1=(skill_lv+3)*2; - break; + case PR_SANCTUARY: + case NPC_EVILLAND: + val1=(skill_lv+3)*2; + break; - case WZ_FIREPILLAR: - if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) - return NULL; - if((flag&1)!=0) - limit=1000; - val1=skill_lv+2; - break; - case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex] - case AM_DEMONSTRATION: - case GN_HELLS_PLANT: - if (map_flag_vs(src->m) && battle_config.vs_traps_bctall - && (src->type&battle_config.vs_traps_bctall)) - target = BCT_ALL; - break; - case HT_SHOCKWAVE: - val1=skill_lv*15+10; - case HT_SANDMAN: - case MA_SANDMAN: - case HT_CLAYMORETRAP: - case HT_SKIDTRAP: - case MA_SKIDTRAP: - case HT_LANDMINE: - case MA_LANDMINE: - case HT_ANKLESNARE: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - case HT_BLASTMINE: - /** - * Ranger - **/ - case RA_ELECTRICSHOCKER: - case RA_CLUSTERBOMB: - case RA_MAGENTATRAP: - case RA_COBALTTRAP: - case RA_MAIZETRAP: - case RA_VERDURETRAP: - case RA_FIRINGTRAP: - 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)); - if( req.itemid[i] ) - req_item = req.itemid[i]; - if( map_flag_gvg(src->m) || map[src->m].flag.battleground ) - limit *= 4; // longer trap times in WOE [celest] - if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) ) + case WZ_FIREPILLAR: + if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) + return NULL; + if((flag&1)!=0) + limit=1000; + val1=skill_lv+2; + break; + case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex] + case AM_DEMONSTRATION: + case GN_HELLS_PLANT: + if (map_flag_vs(src->m) && battle_config.vs_traps_bctall + && (src->type&battle_config.vs_traps_bctall)) target = BCT_ALL; - } - break; + break; + case HT_SHOCKWAVE: + val1=skill_lv*15+10; + case HT_SANDMAN: + case MA_SANDMAN: + case HT_CLAYMORETRAP: + case HT_SKIDTRAP: + case MA_SKIDTRAP: + case HT_LANDMINE: + case MA_LANDMINE: + case HT_ANKLESNARE: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + case HT_BLASTMINE: + /** + * Ranger + **/ + case RA_ELECTRICSHOCKER: + case RA_CLUSTERBOMB: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: + case RA_FIRINGTRAP: + 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)); + if( req.itemid[i] ) + req_item = req.itemid[i]; + if( map_flag_gvg(src->m) || map[src->m].flag.battleground ) + limit *= 4; // longer trap times in WOE [celest] + if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) ) + target = BCT_ALL; + } + break; - case SA_LANDPROTECTOR: - case SA_VOLCANO: - case SA_DELUGE: - case SA_VIOLENTGALE: - { - struct skill_unit_group *old_sg; - if ((old_sg = skill_locate_element_field(src)) != NULL) - { //HelloKitty confirmed that these are interchangeable, - //so you can change element and not consume gemstones. - if (( - old_sg->skill_id == SA_VOLCANO || - old_sg->skill_id == SA_DELUGE || - old_sg->skill_id == SA_VIOLENTGALE - ) && old_sg->limit > 0) - { //Use the previous limit (minus the elapsed time) [Skotlex] - limit = old_sg->limit - DIFF_TICK(gettick(), old_sg->tick); - if (limit < 0) //This can happen... - limit = skill_get_time(skill_id,skill_lv); + case SA_LANDPROTECTOR: + case SA_VOLCANO: + case SA_DELUGE: + case SA_VIOLENTGALE: + { + struct skill_unit_group *old_sg; + if ((old_sg = skill_locate_element_field(src)) != NULL) + { //HelloKitty confirmed that these are interchangeable, + //so you can change element and not consume gemstones. + if (( + old_sg->skill_id == SA_VOLCANO || + old_sg->skill_id == SA_DELUGE || + old_sg->skill_id == SA_VIOLENTGALE + ) && old_sg->limit > 0) + { //Use the previous limit (minus the elapsed time) [Skotlex] + limit = old_sg->limit - DIFF_TICK(gettick(), old_sg->tick); + if (limit < 0) //This can happen... + limit = skill_get_time(skill_id,skill_lv); + } + skill_clear_group(src,1); } - skill_clear_group(src,1); + break; } - break; - } - case BA_DISSONANCE: - case DC_UGLYDANCE: - val1 = 10; //FIXME: This value is not used anywhere, what is it for? [Skotlex] - break; - case BA_WHISTLE: - val1 = skill_lv +status->agi/10; // Flee increase - val2 = ((skill_lv+1)/2)+status->luk/10; // Perfect dodge increase - if(sd){ - val1 += pc_checkskill(sd,BA_MUSICALLESSON); - val2 += pc_checkskill(sd,BA_MUSICALLESSON); - } - break; - case DC_HUMMING: - val1 = 2*skill_lv+status->dex/10; // Hit increase + case BA_DISSONANCE: + case DC_UGLYDANCE: + val1 = 10; //FIXME: This value is not used anywhere, what is it for? [Skotlex] + break; + case BA_WHISTLE: + val1 = skill_lv +status->agi/10; // Flee increase + val2 = ((skill_lv+1)/2)+status->luk/10; // Perfect dodge increase + if(sd){ + val1 += pc_checkskill(sd,BA_MUSICALLESSON); + val2 += pc_checkskill(sd,BA_MUSICALLESSON); + } + break; + case DC_HUMMING: + val1 = 2*skill_lv+status->dex/10; // Hit increase + #ifdef RENEWAL + val1 *= 2; + #endif + if(sd) + val1 += pc_checkskill(sd,DC_DANCINGLESSON); + break; + case BA_POEMBRAGI: + val1 = 3*skill_lv+status->dex/10; // Casting time reduction + //For some reason at level 10 the base delay reduction is 50%. + val2 = (skill_lv<10?3*skill_lv:50)+status->int_/5; // After-cast delay reduction + if(sd){ + val1 += 2*pc_checkskill(sd,BA_MUSICALLESSON); + val2 += 2*pc_checkskill(sd,BA_MUSICALLESSON); + } + break; + case DC_DONTFORGETME: + val1 = status->dex/10 + 3*skill_lv + 5; // ASPD decrease + val2 = status->agi/10 + 3*skill_lv + 5; // Movement speed adjustment. + if(sd){ + val1 += pc_checkskill(sd,DC_DANCINGLESSON); + val2 += pc_checkskill(sd,DC_DANCINGLESSON); + } + break; + case BA_APPLEIDUN: + val1 = 5+2*skill_lv+status->vit/10; // MaxHP percent increase + if(sd) + val1 += pc_checkskill(sd,BA_MUSICALLESSON); + break; + case DC_SERVICEFORYOU: + val1 = 15+skill_lv+(status->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed + val2 = 20+3*skill_lv+(status->int_/10); // SP cost reduction + if(sd){ + val1 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO This bonus value is guessed + val2 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO Should be half this value + } + break; + case BA_ASSASSINCROSS: + val1 = 100+(10*skill_lv)+(status->agi/10); // ASPD increase + if(sd) + val1 += 5*pc_checkskill(sd,BA_MUSICALLESSON); + break; + case DC_FORTUNEKISS: + val1 = 10+skill_lv+(status->luk/10); // Critical increase + if(sd) + val1 += pc_checkskill(sd,DC_DANCINGLESSON); + val1*=10; //Because every 10 crit is an actual cri point. + break; + case BD_DRUMBATTLEFIELD: #ifdef RENEWAL - val1 *= 2; + val1 = (skill_lv+5)*25; //Watk increase + val2 = skill_lv*10; //Def increase + #else + val1 = (skill_lv+1)*25; //Watk increase + val2 = (skill_lv+1)*2; //Def increase #endif - if(sd) - val1 += pc_checkskill(sd,DC_DANCINGLESSON); - break; - case BA_POEMBRAGI: - val1 = 3*skill_lv+status->dex/10; // Casting time reduction - //For some reason at level 10 the base delay reduction is 50%. - val2 = (skill_lv<10?3*skill_lv:50)+status->int_/5; // After-cast delay reduction - if(sd){ - val1 += 2*pc_checkskill(sd,BA_MUSICALLESSON); - val2 += 2*pc_checkskill(sd,BA_MUSICALLESSON); - } - break; - case DC_DONTFORGETME: - val1 = status->dex/10 + 3*skill_lv + 5; // ASPD decrease - val2 = status->agi/10 + 3*skill_lv + 5; // Movement speed adjustment. - if(sd){ - val1 += pc_checkskill(sd,DC_DANCINGLESSON); - val2 += pc_checkskill(sd,DC_DANCINGLESSON); - } - break; - case BA_APPLEIDUN: - val1 = 5+2*skill_lv+status->vit/10; // MaxHP percent increase - if(sd) - val1 += pc_checkskill(sd,BA_MUSICALLESSON); - break; - case DC_SERVICEFORYOU: - val1 = 15+skill_lv+(status->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed - val2 = 20+3*skill_lv+(status->int_/10); // SP cost reduction - if(sd){ - val1 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO This bonus value is guessed - val2 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO Should be half this value - } - break; - case BA_ASSASSINCROSS: - val1 = 100+(10*skill_lv)+(status->agi/10); // ASPD increase - if(sd) - val1 += 5*pc_checkskill(sd,BA_MUSICALLESSON); - break; - case DC_FORTUNEKISS: - val1 = 10+skill_lv+(status->luk/10); // Critical increase - if(sd) - val1 += pc_checkskill(sd,DC_DANCINGLESSON); - val1*=10; //Because every 10 crit is an actual cri point. - break; - case BD_DRUMBATTLEFIELD: - #ifdef RENEWAL - val1 = (skill_lv+5)*25; //Watk increase - val2 = skill_lv*10; //Def increase - #else - val1 = (skill_lv+1)*25; //Watk increase - val2 = (skill_lv+1)*2; //Def increase - #endif - break; - case BD_RINGNIBELUNGEN: - val1 = (skill_lv+2)*25; //Watk increase - break; - case BD_RICHMANKIM: - val1 = 25 + 11*skill_lv; //Exp increase bonus. - break; - case BD_SIEGFRIED: - val1 = 55 + skill_lv*5; //Elemental Resistance - val2 = skill_lv*10; //Status ailment resistance - break; - case WE_CALLPARTNER: - if (sd) val1 = sd->status.partner_id; - break; - case WE_CALLPARENT: - if (sd) { - val1 = sd->status.father; - val2 = sd->status.mother; - } - break; - case WE_CALLBABY: - if (sd) val1 = sd->status.child; - break; - case NJ_KAENSIN: - skill_clear_group(src, 1); //Delete previous Kaensins/Suitons - val2 = (skill_lv+1)/2 + 4; - break; - case NJ_SUITON: - skill_clear_group(src, 1); - break; + break; + case BD_RINGNIBELUNGEN: + val1 = (skill_lv+2)*25; //Watk increase + break; + case BD_RICHMANKIM: + val1 = 25 + 11*skill_lv; //Exp increase bonus. + break; + case BD_SIEGFRIED: + val1 = 55 + skill_lv*5; //Elemental Resistance + val2 = skill_lv*10; //Status ailment resistance + break; + case WE_CALLPARTNER: + if (sd) val1 = sd->status.partner_id; + break; + case WE_CALLPARENT: + if (sd) { + val1 = sd->status.father; + val2 = sd->status.mother; + } + break; + case WE_CALLBABY: + if (sd) val1 = sd->status.child; + break; + case NJ_KAENSIN: + skill_clear_group(src, 1); //Delete previous Kaensins/Suitons + val2 = (skill_lv+1)/2 + 4; + break; + case NJ_SUITON: + skill_clear_group(src, 1); + break; - case GS_GROUNDDRIFT: - { - int element[5]={ELE_WIND,ELE_DARK,ELE_POISON,ELE_WATER,ELE_FIRE}; + case GS_GROUNDDRIFT: + { + int element[5]={ELE_WIND,ELE_DARK,ELE_POISON,ELE_WATER,ELE_FIRE}; - val1 = status->rhw.ele; - if (!val1) - val1=element[rnd()%5]; + val1 = status->rhw.ele; + if (!val1) + val1=element[rnd()%5]; - switch (val1) - { - case ELE_FIRE: - subunt++; - case ELE_WATER: - subunt++; - case ELE_POISON: - subunt++; - case ELE_DARK: - subunt++; - case ELE_WIND: - break; - default: - subunt=rnd()%5; - break; - } + switch (val1) + { + case ELE_FIRE: + subunt++; + case ELE_WATER: + subunt++; + case ELE_POISON: + subunt++; + case ELE_DARK: + subunt++; + case ELE_WIND: + break; + default: + subunt=rnd()%5; + break; + } - break; - } - case GC_POISONSMOKE: - if( !(sc && sc->data[SC_POISONINGWEAPON]) ) - return NULL; - val2 = sc->data[SC_POISONINGWEAPON]->val2; // Type of Poison - val3 = sc->data[SC_POISONINGWEAPON]->val1; - limit = 4000 + 2000 * skill_lv; - break; - case GD_LEADERSHIP: - case GD_GLORYWOUNDS: - case GD_SOULCOLD: - case GD_HAWKEYES: - limit = 1000000;//it doesn't matter - break; - case LG_BANDING: - limit = -1; - break; - case WM_REVERBERATION: - interval = limit; - val2 = 1; - case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector. - if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) - return NULL; - break; - case SO_CLOUD_KILL: - skill_clear_group(src, 4); - break; - case SO_WARMER: - skill_clear_group(src, 8); - break; - case SO_VACUUM_EXTREME: - range++; + break; + } + case GC_POISONSMOKE: + if( !(sc && sc->data[SC_POISONINGWEAPON]) ) + return NULL; + val2 = sc->data[SC_POISONINGWEAPON]->val2; // Type of Poison + val3 = sc->data[SC_POISONINGWEAPON]->val1; + limit = 4000 + 2000 * skill_lv; + break; + case GD_LEADERSHIP: + case GD_GLORYWOUNDS: + case GD_SOULCOLD: + case GD_HAWKEYES: + limit = 1000000;//it doesn't matter + break; + case LG_BANDING: + limit = -1; + break; + case WM_REVERBERATION: + interval = limit; + val2 = 1; + case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector. + if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) + return NULL; + break; + case SO_CLOUD_KILL: + skill_clear_group(src, 4); + break; + case SO_WARMER: + skill_clear_group(src, 8); + break; + case SO_VACUUM_EXTREME: + range++; - break; - case SC_BLOODYLUST: - skill_clear_group(src, 32); - break; - case GN_WALLOFTHORN: - if( flag&1 ) - limit = 3000; - val3 = (x<<16)|y; - break; - case KO_ZENKAI: - if( sd ){ - ARR_FIND(1, 6, i, sd->talisman[i] > 0); - if( i < 5 ){ - val1 = sd->talisman[i]; // no. of aura - val2 = i; // aura type - limit += val1 * 1000; - subunt = i - 1; - pc_del_talisman(sd, sd->talisman[i], i); + break; + case SC_BLOODYLUST: + skill_clear_group(src, 32); + break; + case GN_WALLOFTHORN: + if( flag&1 ) + limit = 3000; + val3 = (x<<16)|y; + break; + case KO_ZENKAI: + if( sd ){ + ARR_FIND(1, 6, i, sd->talisman[i] > 0); + if( i < 5 ){ + val1 = sd->talisman[i]; // no. of aura + val2 = i; // aura type + limit += val1 * 1000; + subunt = i - 1; + pc_del_talisman(sd, sd->talisman[i], i); + } } - } - break; + break; } nullpo_retr(NULL, group=skill_initunitgroup(src,layout->count,skill_id,skill_lv,skill_get_unit_id(skill_id,flag&1)+subunt, limit, interval)); @@ -10910,8 +10918,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill } limit = group->limit; - for( i = 0; i < layout->count; i++ ) - { + for( i = 0; i < layout->count; i++ ) { struct skill_unit *unit; int ux = x + layout->dx[i]; int uy = y + layout->dy[i]; @@ -10924,65 +10931,61 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill if( battle_config.skill_wall_check && skill_get_unit_flag(skill_id)&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) ) continue; // no path between cell and center of casting. - switch( skill_id ) - { - case MG_FIREWALL: - case NJ_KAENSIN: - val2=group->val2; - break; - case WZ_ICEWALL: - val1 = (skill_lv <= 1) ? 500 : 200 + 200*skill_lv; - val2 = map_getcell(src->m, ux, uy, CELL_GETTYPE); - break; - case HT_LANDMINE: - case MA_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case MA_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - case HT_TALKIEBOX: - case HT_SKIDTRAP: - case MA_SKIDTRAP: - case HT_CLAYMORETRAP: - case HT_BLASTMINE: - /** - * Ranger - **/ - case RA_ELECTRICSHOCKER: - case RA_CLUSTERBOMB: - case RA_MAGENTATRAP: - case RA_COBALTTRAP: - case RA_MAIZETRAP: - case RA_VERDURETRAP: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - val1 = 3500; - break; - case GS_DESPERADO: - val1 = abs(layout->dx[i]); - val2 = abs(layout->dy[i]); - if (val1 < 2 || val2 < 2) { //Nearby cross, linear decrease with no diagonals - if (val2 > val1) val1 = val2; - if (val1) val1--; - val1 = 36 -12*val1; - } else //Diagonal edges - val1 = 28 -4*val1 -4*val2; - if (val1 < 1) val1 = 1; - val2 = 0; - break; - case WM_REVERBERATION: - val1 = 1 + skill_lv; - break; - case GN_WALLOFTHORN: - val1 = 1000 * skill_lv; // Need official value. [LimitLine] - break; - default: - if (group->state.song_dance&0x1) - val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance - break; + switch( skill_id ) { + case MG_FIREWALL: + case NJ_KAENSIN: + val2=group->val2; + break; + case WZ_ICEWALL: + val1 = (skill_lv <= 1) ? 500 : 200 + 200*skill_lv; + val2 = map_getcell(src->m, ux, uy, CELL_GETTYPE); + break; + case HT_LANDMINE: + case MA_LANDMINE: + case HT_ANKLESNARE: + case HT_SHOCKWAVE: + case HT_SANDMAN: + case MA_SANDMAN: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + case HT_TALKIEBOX: + case HT_SKIDTRAP: + case MA_SKIDTRAP: + case HT_CLAYMORETRAP: + case HT_BLASTMINE: + case RA_ELECTRICSHOCKER: + case RA_CLUSTERBOMB: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + val1 = 3500; + break; + case GS_DESPERADO: + val1 = abs(layout->dx[i]); + val2 = abs(layout->dy[i]); + if (val1 < 2 || val2 < 2) { //Nearby cross, linear decrease with no diagonals + if (val2 > val1) val1 = val2; + if (val1) val1--; + val1 = 36 -12*val1; + } else //Diagonal edges + val1 = 28 -4*val1 -4*val2; + if (val1 < 1) val1 = 1; + val2 = 0; + break; + case WM_REVERBERATION: + val1 = 1 + skill_lv; + break; + case GN_WALLOFTHORN: + val1 = 1000 * skill_lv; // Need official value. [LimitLine] + break; + default: + if (group->state.song_dance&0x1) + val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance + break; } if (skill_get_unit_flag(skill_id) & UF_RANGEDSINGLEUNIT && i == (layout->count / 2)) val2 |= UF_RANGEDSINGLEUNIT; // center. |