-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:
lighta
2013-08-17 09:42:01 -04:00
parent ba6b57bdf3
commit a9b48baad5
6 changed files with 2399 additions and 2412 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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
}

View File

@@ -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);

View File

@@ -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]

View File

@@ -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);