-Some customisation support
--Add of skill_inf3, goal is to move out the hardcoded skill list in emulator to db. (and therefor allow user to easily modify them if they wish) -Fix of possible segfault in battle.c since r17457 (sd might be null on the camouflage bonus) --Also fixing the fact that camouflage bonus was staying permanently.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
2294
db/re/skill_db.txt
2294
db/re/skill_db.txt
File diff suppressed because it is too large
Load Diff
125
src/map/battle.c
125
src/map/battle.c
@@ -1061,7 +1061,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
|
||||
}
|
||||
if(sc->data[SC_PAIN_KILLER]){
|
||||
damage -= sc->data[SC_PAIN_KILLER]->val3;
|
||||
damage = max(0,damage);
|
||||
damage = max(1,damage);
|
||||
}
|
||||
if((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ){
|
||||
skill_castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,gettick(),0);
|
||||
@@ -1273,41 +1273,29 @@ int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int dam
|
||||
if( !damage )
|
||||
return 0;
|
||||
|
||||
if( bl->type == BL_MOB )
|
||||
{
|
||||
if( bl->type == BL_MOB ) {
|
||||
struct mob_data* md = BL_CAST(BL_MOB, bl);
|
||||
if( map[bl->m].flag.battleground && (md->class_ == MOBID_BLUE_CRYST || md->class_ == MOBID_PINK_CRYST) && flag&BF_SKILL )
|
||||
return 0; // Crystal cannot receive skill damage on battlegrounds
|
||||
}
|
||||
|
||||
switch( skill_id )
|
||||
{
|
||||
case PA_PRESSURE:
|
||||
case HW_GRAVITATION:
|
||||
case NJ_ZENYNAGE:
|
||||
case KO_MUCHANAGE:
|
||||
break;
|
||||
default:
|
||||
if( flag&BF_SKILL )
|
||||
{ //Skills get a different reduction than non-skills. [Skotlex]
|
||||
if( flag&BF_WEAPON )
|
||||
DAMAGE_RATE(battle_config.bg_weapon_damage_rate)
|
||||
if( flag&BF_MAGIC )
|
||||
DAMAGE_RATE(battle_config.bg_magic_damage_rate)
|
||||
if( flag&BF_MISC )
|
||||
DAMAGE_RATE(battle_config.bg_misc_damage_rate)
|
||||
}
|
||||
else
|
||||
{ //Normal attacks get reductions based on range.
|
||||
if( flag&BF_SHORT )
|
||||
DAMAGE_RATE(battle_config.bg_short_damage_rate)
|
||||
if( flag&BF_LONG )
|
||||
DAMAGE_RATE(battle_config.bg_long_damage_rate)
|
||||
}
|
||||
|
||||
if( !damage ) damage = 1;
|
||||
if(skill_get_inf2(skill_id)&INF2_NO_BG_DMG)
|
||||
return damage;; //skill that ignore bg map reduction
|
||||
if( flag&BF_SKILL ) { //Skills get a different reduction than non-skills. [Skotlex]
|
||||
if( flag&BF_WEAPON )
|
||||
DAMAGE_RATE(battle_config.bg_weapon_damage_rate)
|
||||
if( flag&BF_MAGIC )
|
||||
DAMAGE_RATE(battle_config.bg_magic_damage_rate)
|
||||
if( flag&BF_MISC )
|
||||
DAMAGE_RATE(battle_config.bg_misc_damage_rate)
|
||||
}
|
||||
else { //Normal attacks get reductions based on range.
|
||||
if( flag&BF_SHORT )
|
||||
DAMAGE_RATE(battle_config.bg_short_damage_rate)
|
||||
if( flag&BF_LONG )
|
||||
DAMAGE_RATE(battle_config.bg_long_damage_rate)
|
||||
}
|
||||
|
||||
damage = max(damage,1); //min 1 dammage
|
||||
return damage;
|
||||
}
|
||||
|
||||
@@ -1323,17 +1311,8 @@ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int dama
|
||||
return 0;
|
||||
|
||||
if(md && md->guardian_data) {
|
||||
if(class_ == MOBID_EMPERIUM && flag&BF_SKILL) {
|
||||
//Skill immunity.
|
||||
switch (skill_id) {
|
||||
#ifndef RENEWAL
|
||||
case MO_TRIPLEATTACK:
|
||||
#endif
|
||||
case HW_GRAVITATION:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
if(class_ == MOBID_EMPERIUM && flag&BF_SKILL && !(skill_get_inf3(skill_id)&INF3_HIT_EMP)) { //Skill immunity.
|
||||
return 0;
|
||||
}
|
||||
if(src->type != BL_MOB) {
|
||||
struct guild *g = src->type == BL_PC ? ((TBL_PC *)src)->guild : guild_search(status_get_guild_id(src));
|
||||
@@ -1345,36 +1324,27 @@ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int dama
|
||||
return 0; // [MouseJstr]
|
||||
}
|
||||
}
|
||||
|
||||
switch (skill_id) {
|
||||
//Skills with no damage reduction.
|
||||
case PA_PRESSURE:
|
||||
case HW_GRAVITATION:
|
||||
case NJ_ZENYNAGE:
|
||||
case KO_MUCHANAGE:
|
||||
case RK_DRAGONBREATH:
|
||||
break;
|
||||
default:
|
||||
/* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka]
|
||||
if (md && md->guardian_data) {
|
||||
damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100;
|
||||
}
|
||||
*/
|
||||
if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
|
||||
if (flag&BF_WEAPON)
|
||||
DAMAGE_RATE(battle_config.gvg_weapon_damage_rate)
|
||||
if (flag&BF_MAGIC)
|
||||
DAMAGE_RATE(battle_config.gvg_magic_damage_rate)
|
||||
if (flag&BF_MISC)
|
||||
DAMAGE_RATE(battle_config.gvg_misc_damage_rate)
|
||||
} else { //Normal attacks get reductions based on range.
|
||||
if (flag & BF_SHORT)
|
||||
DAMAGE_RATE(battle_config.gvg_short_damage_rate)
|
||||
if (flag & BF_LONG)
|
||||
DAMAGE_RATE(battle_config.gvg_long_damage_rate)
|
||||
}
|
||||
if(!damage) damage = 1;
|
||||
if(skill_get_inf2(skill_id)&INF2_NO_GVG_DMG) //Skills with no gvg damage reduction.
|
||||
return damage;
|
||||
/* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka]
|
||||
if (md && md->guardian_data) {
|
||||
damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100;
|
||||
}
|
||||
*/
|
||||
if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
|
||||
if (flag&BF_WEAPON)
|
||||
DAMAGE_RATE(battle_config.gvg_weapon_damage_rate)
|
||||
if (flag&BF_MAGIC)
|
||||
DAMAGE_RATE(battle_config.gvg_magic_damage_rate)
|
||||
if (flag&BF_MISC)
|
||||
DAMAGE_RATE(battle_config.gvg_misc_damage_rate)
|
||||
} else { //Normal attacks get reductions based on range.
|
||||
if (flag & BF_SHORT)
|
||||
DAMAGE_RATE(battle_config.gvg_short_damage_rate)
|
||||
if (flag & BF_LONG)
|
||||
DAMAGE_RATE(battle_config.gvg_long_damage_rate)
|
||||
}
|
||||
damage = max(damage,1);
|
||||
return damage;
|
||||
}
|
||||
|
||||
@@ -2171,14 +2141,17 @@ static bool battle_skill_stacks_masteries_vvs(uint16 skill_id)
|
||||
static int battle_calc_equip_attack(struct block_list *src, int skill_id)
|
||||
{
|
||||
if(src != NULL) {
|
||||
int eatk=0;
|
||||
struct status_data *status = status_get_status_data(src);
|
||||
struct status_change *sc = status_get_sc(src);
|
||||
struct map_session_data *sd = BL_CAST(BL_PC, src);
|
||||
if( sd->sc.data[SC_CAMOUFLAGE] )
|
||||
status->eatk += 30 * min(10,sd->sc.data[SC_CAMOUFLAGE]->val3); //max +300atk
|
||||
if(sd)
|
||||
return is_skill_using_arrow(src, skill_id) ? sd->bonus.arrow_atk + status->eatk : status->eatk; // add arrow atk if using an applicable skill
|
||||
else
|
||||
return status->eatk;
|
||||
|
||||
if(sc){
|
||||
if(sc->data[SC_CAMOUFLAGE] )
|
||||
eatk += 30 * min(10,sc->data[SC_CAMOUFLAGE]->val3); //max +300atk
|
||||
}
|
||||
if(sd) eatk += is_skill_using_arrow(src, skill_id) ? sd->bonus.arrow_atk : 0; // add arrow atk if using an applicable skill
|
||||
return eatk + status->eatk;
|
||||
}
|
||||
return 0; // shouldn't happen but just in case
|
||||
}
|
||||
|
||||
129
src/map/skill.c
129
src/map/skill.c
@@ -212,6 +212,7 @@ int skill_get_weapontype( uint16 skill_id ) { skill_get (skill_db[skill_i
|
||||
int skill_get_ammotype( uint16 skill_id ) { skill_get (skill_db[skill_id].ammo, skill_id, 1); }
|
||||
int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get (skill_db[skill_id].ammo_qty[skill_lv-1], skill_id, skill_lv); }
|
||||
int skill_get_inf2( uint16 skill_id ) { skill_get (skill_db[skill_id].inf2, skill_id, 1); }
|
||||
int skill_get_inf3( uint16 skill_id ) { skill_get (skill_db[skill_id].inf3, skill_id, 1); }
|
||||
int skill_get_castcancel( uint16 skill_id ) { skill_get (skill_db[skill_id].castcancel, skill_id, 1); }
|
||||
int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].maxcount[skill_lv-1], skill_id, skill_lv); }
|
||||
int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].blewcount[skill_lv-1], skill_id, skill_lv); }
|
||||
@@ -6425,60 +6426,61 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
|
||||
case AM_BERSERKPITCHER:
|
||||
case AM_POTIONPITCHER: {
|
||||
int i,hp = 0,sp = 0;
|
||||
if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) {
|
||||
int i,hp = 0,sp = 0;
|
||||
if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) {
|
||||
map_freeblock_unlock();
|
||||
return 1;
|
||||
}
|
||||
if( sd ) {
|
||||
int x,bonus=100;
|
||||
struct skill_condition require = skill_get_requirement(sd, skill_id, skill_lv);
|
||||
x = skill_lv%11 - 1;
|
||||
i = pc_search_inventory(sd, require.itemid[x]);
|
||||
if (i < 0 || require.itemid[x] <= 0) {
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
map_freeblock_unlock();
|
||||
return 1;
|
||||
}
|
||||
if( sd ) {
|
||||
int x,bonus=100;
|
||||
x = skill_lv%11 - 1;
|
||||
i = pc_search_inventory(sd,skill_db[skill_id].itemid[x]);
|
||||
if( i < 0 || skill_db[skill_id].itemid[x] <= 0 ) {
|
||||
if (sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < require.amount[x]) {
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
map_freeblock_unlock();
|
||||
return 1;
|
||||
}
|
||||
if( skill_id == AM_BERSERKPITCHER ) {
|
||||
if( dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv ) {
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
map_freeblock_unlock();
|
||||
return 1;
|
||||
}
|
||||
if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skill_id].amount[x]) {
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
map_freeblock_unlock();
|
||||
return 1;
|
||||
}
|
||||
potion_flag = 1;
|
||||
potion_hp = potion_sp = potion_per_hp = potion_per_sp = 0;
|
||||
potion_target = bl->id;
|
||||
run_script(sd->inventory_data[i]->script,0,sd->bl.id,0);
|
||||
potion_flag = potion_target = 0;
|
||||
if( sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ALCHEMIST )
|
||||
bonus += sd->status.base_level;
|
||||
if( potion_per_hp > 0 || potion_per_sp > 0 ) {
|
||||
hp = tstatus->max_hp * potion_per_hp / 100;
|
||||
hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
|
||||
if( dstsd ) {
|
||||
sp = dstsd->status.max_sp * potion_per_sp / 100;
|
||||
sp = sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
|
||||
}
|
||||
if( skill_id == AM_BERSERKPITCHER ) {
|
||||
if( dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv ) {
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
map_freeblock_unlock();
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if( potion_hp > 0 ) {
|
||||
hp = potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
|
||||
hp = hp * (100 + (tstatus->vit<<1)) / 100;
|
||||
if( dstsd )
|
||||
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100;
|
||||
}
|
||||
potion_flag = 1;
|
||||
potion_hp = potion_sp = potion_per_hp = potion_per_sp = 0;
|
||||
potion_target = bl->id;
|
||||
run_script(sd->inventory_data[i]->script,0,sd->bl.id,0);
|
||||
potion_flag = potion_target = 0;
|
||||
if( sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ALCHEMIST )
|
||||
bonus += sd->status.base_level;
|
||||
if( potion_per_hp > 0 || potion_per_sp > 0 ) {
|
||||
hp = tstatus->max_hp * potion_per_hp / 100;
|
||||
hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
|
||||
if( dstsd ) {
|
||||
sp = dstsd->status.max_sp * potion_per_sp / 100;
|
||||
sp = sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
|
||||
}
|
||||
} else {
|
||||
if( potion_hp > 0 ) {
|
||||
hp = potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
|
||||
hp = hp * (100 + (tstatus->vit<<1)) / 100;
|
||||
if( dstsd )
|
||||
hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100;
|
||||
}
|
||||
if( potion_sp > 0 ) {
|
||||
sp = potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
|
||||
sp = sp * (100 + (tstatus->int_<<1)) / 100;
|
||||
if( dstsd )
|
||||
sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100;
|
||||
}
|
||||
if( potion_sp > 0 ) {
|
||||
sp = potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000;
|
||||
sp = sp * (100 + (tstatus->int_<<1)) / 100;
|
||||
if( dstsd )
|
||||
sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (sd->itemgrouphealrate[IG_POTION]>0) {
|
||||
hp += hp * sd->itemgrouphealrate[IG_POTION] / 100;
|
||||
@@ -9664,9 +9666,11 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data)
|
||||
|
||||
// SC_MAGICPOWER needs to switch states before any damage is actually dealt
|
||||
skill_toggle_magicpower(src, ud->skill_id);
|
||||
if( ud->skill_id != RA_CAMOUFLAGE ) // only normal attack and auto cast skills benefit from its bonuses
|
||||
status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);
|
||||
|
||||
// only normal attack and auto cast skills benefit from its bonuses
|
||||
if(!(skill_get_inf3(ud->skill_id)&INF3_NOENDCAMOUFLAGE))
|
||||
status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);
|
||||
|
||||
if (skill_get_casttype(ud->skill_id) == CAST_NODAMAGE)
|
||||
skill_castend_nodamage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag);
|
||||
else
|
||||
@@ -9874,7 +9878,8 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data)
|
||||
// }
|
||||
// }
|
||||
unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill_get_walkdelay(ud->skill_id, ud->skill_lv), 1);
|
||||
status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);// only normal attack and auto cast skills benefit from its bonuses
|
||||
if(!(skill_get_inf3(ud->skill_id)&INF3_NOENDCAMOUFLAGE))
|
||||
status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);
|
||||
map_freeblock_lock();
|
||||
skill_castend_pos2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv,tick,0);
|
||||
|
||||
@@ -10219,13 +10224,14 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
int summons[5] = { 1589, 1579, 1575, 1555, 1590 };
|
||||
//int summons[5] = { 1020, 1068, 1118, 1500, 1368 };
|
||||
int class_ = skill_id==AM_SPHEREMINE?1142:summons[skill_lv-1];
|
||||
int ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA;
|
||||
struct mob_data *md;
|
||||
|
||||
// Correct info, don't change any of this! [celest]
|
||||
md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE);
|
||||
md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, ai);
|
||||
if (md) {
|
||||
md->master_id = src->id;
|
||||
md->special_state.ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA;
|
||||
md->special_state.ai = ai;
|
||||
if( md->deletetimer != INVALID_TIMER )
|
||||
delete_timer(md->deletetimer, mob_timer_delete);
|
||||
md->deletetimer = add_timer (gettick() + skill_get_time(skill_id,skill_lv), mob_timer_delete, md->bl.id, 0);
|
||||
@@ -10237,9 +10243,11 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
// Slim Pitcher [Celest]
|
||||
case CR_SLIMPITCHER:
|
||||
if (sd) {
|
||||
int i = skill_lv%11 - 1;
|
||||
int j = pc_search_inventory(sd,skill_db[skill_id].itemid[i]);
|
||||
if( j < 0 || skill_db[skill_id].itemid[i] <= 0 || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill_db[skill_id].amount[i] )
|
||||
int i = 0, j = 0;
|
||||
struct skill_condition require = skill_get_requirement(sd, skill_id, skill_lv);
|
||||
i = skill_lv%11 - 1;
|
||||
j = pc_search_inventory(sd, require.itemid[i]);
|
||||
if (j < 0 || require.itemid[i] <= 0 || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < require.amount[i])
|
||||
{
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
return 1;
|
||||
@@ -12148,7 +12156,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
if( battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 )
|
||||
skill_attack(skill_get_type(GN_HELLS_PLANT_ATK), ss, &src->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0);
|
||||
if( ss != bl) //The caster is the only one who can step on the Plants, without destroying them
|
||||
sg->limit = DIFF_TICK(tick, sg->tick) + 100;
|
||||
skill_delunit(sg->unit); // deleting it directly to avoid extra hits
|
||||
break;
|
||||
|
||||
case UNT_CLOUD_KILL:
|
||||
@@ -13411,7 +13419,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
|
||||
case SO_ELECTRICWALK: // Can't be casted until you've walked all cells.
|
||||
if( sc && sc->data[SC_PROPERTYWALK] &&
|
||||
sc->data[SC_PROPERTYWALK]->val3 < skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) {
|
||||
clif_skill_fail(sd,skill_id,0x0,0);
|
||||
clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
@@ -15149,7 +15157,7 @@ static int skill_cell_overlap(struct block_list *bl, va_list ap)
|
||||
return 1;
|
||||
}
|
||||
//It deletes everything except traps and barriers
|
||||
if( !(skill_get_inf2(unit->group->skill_id)&(INF2_TRAP|INF2_NOLP)) || unit->group->skill_id == WZ_FIREPILLAR ) {
|
||||
if( (!(skill_get_inf2(unit->group->skill_id)&(INF2_TRAP)) && !(skill_get_inf3(unit->group->skill_id)&(INF2_NOLP)) ) || unit->group->skill_id == WZ_FIREPILLAR ) {
|
||||
skill_delunit(unit);
|
||||
return 1;
|
||||
}
|
||||
@@ -15221,7 +15229,7 @@ static int skill_cell_overlap(struct block_list *bl, va_list ap)
|
||||
break;
|
||||
}
|
||||
|
||||
if (unit->group->skill_id == SA_LANDPROTECTOR && !(skill_get_inf2(skill_id)&(INF2_TRAP|INF2_NOLP))) { //It deletes everything except traps and barriers
|
||||
if (unit->group->skill_id == SA_LANDPROTECTOR && !(skill_get_inf2(skill_id)&(INF2_TRAP)) && !(skill_get_inf3(skill_id)&(INF3_NOLP) ) ) { //It deletes everything except traps and barriers
|
||||
(*alive) = 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -15856,7 +15864,7 @@ int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) {
|
||||
|
||||
nullpo_ret(group);
|
||||
|
||||
if( !(skill_get_inf2(group->skill_id)&(INF2_TRAP|INF2_NOLP)) && group->skill_id != NC_NEUTRALBARRIER && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) )
|
||||
if( !(skill_get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) && !(skill_get_inf3(group->skill_id)&(INF3_NOLP)) && group->skill_id != NC_NEUTRALBARRIER && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) )
|
||||
return 0; //AoE skills are ineffective. [Skotlex]
|
||||
|
||||
if( battle_check_target(&unit->bl,bl,group->target_flag) <= 0 )
|
||||
@@ -18028,8 +18036,9 @@ static bool skill_parse_row_skilldb(char* split[], int columns, int current)
|
||||
else
|
||||
skill_db[idx].skill_type = 0;
|
||||
skill_split_atoi(split[14],skill_db[idx].blewcount);
|
||||
safestrncpy(skill_db[idx].name, trim(split[15]), sizeof(skill_db[idx].name));
|
||||
safestrncpy(skill_db[idx].desc, trim(split[16]), sizeof(skill_db[idx].desc));
|
||||
skill_db[idx].inf3 = (int)strtol(split[15], NULL,0);
|
||||
safestrncpy(skill_db[idx].name, trim(split[16]), sizeof(skill_db[idx].name));
|
||||
safestrncpy(skill_db[idx].desc, trim(split[17]), sizeof(skill_db[idx].desc));
|
||||
strdb_iput(skilldb_name2id, skill_db[idx].name, skill_id);
|
||||
|
||||
return true;
|
||||
@@ -18404,7 +18413,7 @@ static void skill_readdb(void)
|
||||
safestrncpy(skill_db[0].name, "UNKNOWN_SKILL", sizeof(skill_db[0].name));
|
||||
safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc));
|
||||
|
||||
sv_readdb(db_path, DBPATH"skill_db.txt" , ',', 17, 17, MAX_SKILL_DB, skill_parse_row_skilldb);
|
||||
sv_readdb(db_path, DBPATH"skill_db.txt" , ',', 18, 18, MAX_SKILL_DB, skill_parse_row_skilldb);
|
||||
sv_readdb(db_path, DBPATH"skill_require_db.txt" , ',', 32, 32, MAX_SKILL_DB, skill_parse_row_requiredb);
|
||||
#ifdef RENEWAL_CAST
|
||||
sv_readdb(db_path, "re/skill_cast_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill_parse_row_castdb);
|
||||
|
||||
@@ -52,21 +52,32 @@ enum e_skill_nk {
|
||||
//A skill with 3 would be no damage + splash: area of effect.
|
||||
//Constants to identify a skill's inf2 value.
|
||||
enum e_skill_inf2 {
|
||||
INF2_QUEST_SKILL = 0x0001,
|
||||
INF2_NPC_SKILL = 0x0002, //NPC skills are those that players can't have in their skill tree.
|
||||
INF2_WEDDING_SKILL = 0x0004,
|
||||
INF2_SPIRIT_SKILL = 0x0008,
|
||||
INF2_GUILD_SKILL = 0x0010,
|
||||
INF2_SONG_DANCE = 0x0020,
|
||||
INF2_ENSEMBLE_SKILL = 0x0040,
|
||||
INF2_TRAP = 0x0080,
|
||||
INF2_TARGET_SELF = 0x0100, //Refers to ground placed skills that will target the caster as well (like Grandcross)
|
||||
INF2_NO_TARGET_SELF = 0x0200,
|
||||
INF2_PARTY_ONLY = 0x0400,
|
||||
INF2_GUILD_ONLY = 0x0800,
|
||||
INF2_NO_ENEMY = 0x1000,
|
||||
INF2_NOLP = 0x2000, // Spells that can ignore Land Protector
|
||||
INF2_CHORUS_SKILL = 0x4000, // Chorus skill
|
||||
INF2_QUEST_SKILL = 0x00001,
|
||||
INF2_NPC_SKILL = 0x00002, //NPC skills are those that players can't have in their skill tree.
|
||||
INF2_WEDDING_SKILL = 0x00004,
|
||||
INF2_SPIRIT_SKILL = 0x00008,
|
||||
INF2_GUILD_SKILL = 0x00010,
|
||||
INF2_SONG_DANCE = 0x00020,
|
||||
INF2_ENSEMBLE_SKILL = 0x00040,
|
||||
INF2_TRAP = 0x00080,
|
||||
INF2_TARGET_SELF = 0x00100, //Refers to ground placed skills that will target the caster as well (like Grandcross)
|
||||
INF2_NO_TARGET_SELF = 0x00200,
|
||||
INF2_PARTY_ONLY = 0x00400,
|
||||
INF2_GUILD_ONLY = 0x00800,
|
||||
INF2_NO_ENEMY = 0x01000,
|
||||
INF2_NOLP = 0x02000, // Spells that can ignore Land Protector
|
||||
INF2_CHORUS_SKILL = 0x04000, // Chorus skill
|
||||
INF2_NO_BG_DMG = 0x08000, // spell that ignore bg reduction
|
||||
INF2_NO_GVG_DMG = 0x10000, // spell that ignore gvg reduction
|
||||
};
|
||||
|
||||
enum e_skill_inf3 {
|
||||
INF3_NOLP = 0x0001, // Spells that can ignore Land Protector
|
||||
INF3_NOENDCAMOUFLAGE = 0x0002, // spell that doesn't end camouflage
|
||||
INF3_USABLE_HIDING = 0x0004, // spell that can be use in hiding
|
||||
INF3_USABLE_DANCE = 0x0008, // spell that can be use while in dancing state
|
||||
INF3_HIT_EMP = 0x0010, // spell that could hit emperium
|
||||
//... add other spell list option here
|
||||
};
|
||||
|
||||
//Walk intervals at which chase-skills are attempted to be triggered.
|
||||
@@ -99,7 +110,7 @@ struct s_skill_db {
|
||||
#endif
|
||||
int upkeep_time[MAX_SKILL_LEVEL],upkeep_time2[MAX_SKILL_LEVEL],cooldown[MAX_SKILL_LEVEL];
|
||||
int castcancel,cast_def_rate;
|
||||
int inf2,maxcount[MAX_SKILL_LEVEL],skill_type;
|
||||
int inf2,maxcount[MAX_SKILL_LEVEL],skill_type,inf3;
|
||||
int blewcount[MAX_SKILL_LEVEL];
|
||||
int hp[MAX_SKILL_LEVEL],sp[MAX_SKILL_LEVEL],mhp[MAX_SKILL_LEVEL],hp_rate[MAX_SKILL_LEVEL],sp_rate[MAX_SKILL_LEVEL],zeny[MAX_SKILL_LEVEL];
|
||||
int weapon,ammo,ammo_qty[MAX_SKILL_LEVEL],state,spiritball[MAX_SKILL_LEVEL];
|
||||
@@ -269,6 +280,7 @@ int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv );
|
||||
int skill_get_unit_flag( uint16 skill_id );
|
||||
int skill_get_unit_target( uint16 skill_id );
|
||||
int skill_tree_get_max( uint16 skill_id, int b_class ); // Celest
|
||||
int skill_get_inf3( uint16 skill_id );
|
||||
const char* skill_get_name( uint16 skill_id ); // [Skotlex]
|
||||
const char* skill_get_desc( uint16 skill_id ); // [Skotlex]
|
||||
|
||||
|
||||
@@ -1628,19 +1628,10 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
|
||||
} else if(sc->data[SC_LONGING]) { //Allow everything except dancing/re-dancing. [Skotlex]
|
||||
if (skill_id == BD_ENCORE ||
|
||||
skill_get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_ENSEMBLE_SKILL)
|
||||
)
|
||||
)
|
||||
return 0;
|
||||
} else {
|
||||
switch (skill_id) {
|
||||
case BD_ADAPTATION:
|
||||
case CG_LONGINGFREEDOM:
|
||||
case BA_MUSICALSTRIKE:
|
||||
case DC_THROWARROW:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else if(!(skill_get_inf3(skill_id)&INF3_USABLE_DANCE)) //skills that can be used in dancing state
|
||||
return 0;
|
||||
if ((sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE && skill_id == BD_ADAPTATION)
|
||||
return 0; //Can't amp out of Wand of Hermode :/ [Skotlex]
|
||||
}
|
||||
@@ -1681,21 +1672,8 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
|
||||
}
|
||||
|
||||
if (sc && sc->option) {
|
||||
if (sc->option&OPTION_HIDE) {
|
||||
switch (skill_id) { //Usable skills while hiding.
|
||||
case TF_HIDING:
|
||||
case AS_GRIMTOOTH:
|
||||
case RG_BACKSTAP:
|
||||
case RG_RAID:
|
||||
case NJ_SHADOWJUMP:
|
||||
case NJ_KIRIKAGE:
|
||||
case KO_YAMIKUMO:
|
||||
break;
|
||||
default:
|
||||
//Non players can use all skills while hidden.
|
||||
if (!skill_id || src->type == BL_PC)
|
||||
return 0;
|
||||
}
|
||||
if ((sc->option&OPTION_HIDE) && src->type == BL_PC &&( !skill_id || !(skill_get_inf3(skill_id)&INF3_USABLE_HIDING))){ //Non players can use all skills while hidden.
|
||||
return 0;
|
||||
}
|
||||
if (sc->option&OPTION_CHASEWALK && skill_id != ST_CHASEWALK)
|
||||
return 0;
|
||||
@@ -4172,7 +4150,8 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first)
|
||||
|
||||
if(b_status.rhw.atk2 != status->rhw.atk2 || b_status.lhw.atk2 != status->lhw.atk2
|
||||
#ifdef RENEWAL
|
||||
|| b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk || b_status.eatk != status->eatk
|
||||
|| b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk
|
||||
|| b_status.eatk != status->eatk
|
||||
#endif
|
||||
)
|
||||
clif_updatestatus(sd,SP_ATK2);
|
||||
|
||||
Reference in New Issue
Block a user