*Added Skill Damage Adjustment!

- Disabled by default on src/config/core.h. Uncomment '#define ADJUST_SKILL_DAMAGE' to enable this skill damage adjustment
- Added skill_damage_db.txt (thank Lilith for 'Manage Skill Damage')
- Added new mapflag: 'skill_damage'. Please read 'doc/mapflags.txt' for more details
*Fixed bugreport:8029 (thank exneval for testing and reporting) (Akinari)
*Follow-up 647f99f (Akinari)
*Follow-up 15074d8: optimized item_isNoEquip check parts
*and some mirror changes
This commit is contained in:
Cahyadi Ramadhan Togihon 2013-08-30 02:55:11 +07:00
parent da390cae2f
commit cd9a776f23
17 changed files with 496 additions and 82 deletions

View File

@ -887,7 +887,8 @@
1049: Weather Flags:
1050: Other Flags:
1051: Other Flags2:
//1052-1064 free
1052: Skill Damage Adjustments:
//1053-1064 free
1065: No Exp Penalty: %s | No Zeny Penalty: %s
1066: On
1067: Off

46
db/skill_damage_db.txt Normal file
View File

@ -0,0 +1,46 @@
// Manage skill damage database
// ----------------------------------------------
// rAthena dev team
// ----------------------------------------------
// Credits:
// [Lilith]
// [Cydh]
// ----------------------------------------------
// <SkillName>,<Caster>,<Map>,<Damage against Players>{,<Damage against Mobs>{,<Damage against Bosses>{,<Damage against Other>}}}
// ----------------------------------------------
// Caster: The adjustment only works if the caster is (bitmask)
// 1 = Player
// 2 = Monster
// 4 = Pet
// 8 = Homunculus
// 16 = Mercenary
// 32 = Elemental
// Map:
// 1 - Normal (the maps that aren't classified as these maps below)
// 2 - PVP
// 4 - GVG
// 8 - Battlegrounds
// 16 - 'skill_damage' mapflag
// Restricted zones - they're configured by 'restricted <numberCastermapflag
// 32 - Zone 1
// 64 - Zone 2
// 128 - Zone 3
// 256 - Zone 4
// 512 - Zone 5
// 1024 - Zone 6
// 2048 - Zone 7
// Damage adjustments:
// Using value between -100 and 100000
// minus value that mean normal damage will be decreased, and positive is
// otherwise. 0 = no additional rate
// ----------------------------------------------
// Examples:
// 1. Mammonite: Normal maps, +50% player vs players, nothing else
//MC_MAMMONITE,1,1,50
// 2. Adoramus: PvP & GvG maps, if the caster is player: +50% vs player, +0% vs
// mob, +10% vs boss mob, +15% vs other
//AB_ADORAMUS,1,6,50,0,10,15
// 3. Asura Strike: Only deals half damage (-50%) if player vs player at PvP &
// GvG maps
//MO_EXTREMITYFIST,1,6,-50
// ----------------------------------------------

View File

@ -283,6 +283,39 @@ Notes:
---------------------------------------
*skill_damage {<skill_name>,<caster>,<damage1>,<damage2>,<damage3>,<damage4>}
Enable skill damage adjustment on this map that used for 'Map' field on
skill_damage_db.txt.
For advanced settings, this mapflag can be used to adjust damage of 'skill' if the caster
is 'caster', the damage will be added or reduced 'damage'% from normal damage.
<skill> is name of skill, look at skill_db.txt, not the skill id. Example SM_BASH.
<caster> is to decide who can trigger this adjustment, the invoker not only for player.
Using bitmask, and the available casters are:
1 = Player
2 = Monster
4 = Pet
8 = Homunculus
16 = Mercenary
32 = Elemental
<damage1> addition rate to against player
<damage2> addition rate to against normal monster
<damage3> addition rate to against boss monster
<damage4> addition rate to against other (homunculus, mercenary, pet, and elemetal)
Notes:
- If you want to adjust X skill, you need at least define 'skill' (skill name), 'caster',
and 'damage1'
- This mapflag can be used to adjust all skill damages, put "all" (without quotes) at
'skill' column
- Please put the damages value between -100 and 100000. 0 means no addition.
- One map can contains up to 5 skills adjustment
(max. value is defined on map.h, MAX_MAP_SKILL_MODIFIER)
---------------------------------------
==================
| 3. Map Effects |
==================
@ -327,7 +360,7 @@ Allows usage of item Neuralizer (ID 12213).
*jexp <rate>
Changes the base and job experience rates on a map.
<rate> is given as a percentage (i.e. 100 = 1x EXP). This takes into account the modifiers
<ratecasters given as a percentage (i.e. 100 = 1x EXP). This takes into account the modifiers
'base_exp_rate' and 'job_exp_rate' in '/conf/battle/exp.conf'.
---------------------------------------

View File

@ -0,0 +1,3 @@
//============================================================
//<mapname> mapflag skill_damage {<skill_name>,<caster>,<damage1>,<damage2>,<damage3>,<damage4>}
//------------------------------------------------------------

View File

@ -1,17 +1,19 @@
// --------------------------------------------------------------
// - Map Flags -
// --------------------------------------------------------------
npc: npc/mapflag/nopvp.txt
npc: npc/mapflag/battleground.txt
npc: npc/mapflag/gvg.txt
npc: npc/mapflag/jail.txt
npc: npc/mapflag/night.txt
npc: npc/mapflag/nightmare.txt
npc: npc/mapflag/nobranch.txt
npc: npc/mapflag/noicewall.txt
npc: npc/mapflag/nomemo.txt
npc: npc/mapflag/nopenalty.txt
npc: npc/mapflag/nopvp.txt
npc: npc/mapflag/noreturn.txt
npc: npc/mapflag/nosave.txt
npc: npc/mapflag/noteleport.txt
npc: npc/mapflag/noreturn.txt
npc: npc/mapflag/noskill.txt
npc: npc/mapflag/nowarp.txt
npc: npc/mapflag/nowarpto.txt
@ -19,8 +21,7 @@ npc: npc/mapflag/nowarpto.txt
npc: npc/mapflag/pvp.txt
npc: npc/mapflag/pvp_noparty.txt
npc: npc/mapflag/pvp_noguild.txt
npc: npc/mapflag/night.txt
npc: npc/mapflag/restricted.txt
npc: npc/mapflag/battleground.txt
npc: npc/mapflag/town.txt
npc: npc/mapflag/reset.txt
npc: npc/mapflag/skill_damage.txt
npc: npc/mapflag/town.txt

View File

@ -59,6 +59,16 @@
/// Uncomment to enable real-time server stats (in and out data and ram usage).
//#define SHOW_SERVER_STATS
/// Uncomment to enable skill's damage adjustments [Cydh]
/// By enabling this, db/skill_damage.txt and skill_damage mapflag will be active to add
/// damage rate of specified skill againts player, monster, boss-monster, or other.
/// skill_damage mapflag is used to adjust damage of specified skill at specified map
//#define ADJUST_SKILL_DAMAGE
/// This MAX_SKILL_DAMAGE_RATE is used to cap max the rate
#ifdef ADJUST_SKILL_DAMAGE
#define MAX_SKILL_DAMAGE_RATE 100000
#endif
/**
* No settings past this point
**/

View File

@ -3846,6 +3846,38 @@ ACMD_FUNC(mapinfo) {
sprintf(atcmd_output, msg_txt(sd,1045),map[m_id].flag.battleground); // Battlegrounds ON (type %d)
clif_displaymessage(fd, atcmd_output);
}
/* Skill damage adjustment info [Cydh] */
#ifdef ADJUST_SKILL_DAMAGE
if (map[m_id].flag.skill_damage) {
int j;
clif_displaymessage(fd,msg_txt(sd,1052)); // Skill Damage Adjustments:
sprintf(atcmd_output," > [Map] %d%%, %d%%, %d%%, %d%% | Caster:%d"
,map[m_id].adjust.damage.pc
,map[m_id].adjust.damage.mob
,map[m_id].adjust.damage.boss
,map[m_id].adjust.damage.other
,map[m_id].adjust.damage.caster);
clif_displaymessage(fd, atcmd_output);
if (map[m_id].skill_damage[0].skill_id) {
clif_displaymessage(fd," > [Map Skill] Name : Player, Monster, Boss Monster, Other | Caster");
for (j = 0; j < MAX_MAP_SKILL_MODIFIER; j++) {
if (map[m_id].skill_damage[j].skill_id) {
sprintf(atcmd_output," %d. %s : %d%%, %d%%, %d%%, %d%% | %d"
,j+1
,skill_db[skill_get_index(map[m_id].skill_damage[j].skill_id)].name
,map[m_id].skill_damage[j].pc
,map[m_id].skill_damage[j].mob
,map[m_id].skill_damage[j].boss
,map[m_id].skill_damage[j].other
,map[m_id].skill_damage[j].caster);
clif_displaymessage(fd,atcmd_output);
}
}
}
}
#endif
strcpy(atcmd_output,msg_txt(sd,1046)); // PvP Flags:
if (map[m_id].flag.pvp)
strcat(atcmd_output, " Pvp ON |");
@ -7677,6 +7709,9 @@ ACMD_FUNC(mapflag) {
checkflag(partylock); checkflag(guildlock); checkflag(reset); checkflag(chmautojoin);
checkflag(nousecart); checkflag(noitemconsumption); checkflag(nosumstarmiracle); checkflag(nomineeffect);
checkflag(nolockon); checkflag(notomb);
#ifdef ADJUST_SKILL_DAMAGE
checkflag(skill_damage);
#endif
clif_displaymessage(sd->fd," ");
clif_displaymessage(sd->fd,msg_txt(sd,1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
clif_displaymessage(sd->fd,msg_txt(sd,1313)); // Type "@mapflag available" to list the available mapflags.
@ -7698,6 +7733,9 @@ ACMD_FUNC(mapflag) {
setflag(partylock); setflag(guildlock); setflag(reset); setflag(chmautojoin);
setflag(nousecart); setflag(noitemconsumption); setflag(nosumstarmiracle); setflag(nomineeffect);
setflag(nolockon); setflag(notomb);
#ifdef ADJUST_SKILL_DAMAGE
setflag(skill_damage);
#endif
clif_displaymessage(sd->fd,msg_txt(sd,1314)); // Invalid flag name or flag.
clif_displaymessage(sd->fd,msg_txt(sd,1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
@ -7710,6 +7748,9 @@ ACMD_FUNC(mapflag) {
clif_displaymessage(sd->fd,"fog, fireworks, sakura, leaves, nogo, nobaseexp, nojobexp, nomobloot, nomvploot,");
clif_displaymessage(sd->fd,"nightenabled, restricted, nodrop, novending, loadevent, nochat, partylock, guildlock,");
clif_displaymessage(sd->fd,"reset, chmautojoin, nousecart, noitemconsumption, nosumstarmiracle, nolockon, notomb");
#ifdef ADJUST_SKILL_DAMAGE
clif_displaymessage(sd->fd,"skill_damage");
#endif
#undef checkflag
#undef setflag

View File

@ -1698,6 +1698,128 @@ static int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id)
return 0;
}
/*==========================================
* Damage calculation for adjusting skill damage
* Credits:
[Lilith] for the first release of this
[Cydh] finishing and adding mapflag
* battle_skill_damage_skill() - skill_id based
* battle_skill_damage_map() - map based
*------------------------------------------*/
#ifdef ADJUST_SKILL_DAMAGE
bool battle_skill_damage_iscaster(uint8 caster, enum bl_type type)
{
if (caster == 0)
return false;
while (1) {
if (caster&SDC_PC && type == BL_PC) break;
if (caster&SDC_MOB && type == BL_MOB) break;
if (caster&SDC_PET && type == BL_PET) break;
if (caster&SDC_HOM && type == BL_HOM) break;
if (caster&SDC_MER && type == BL_MER) break;
if (caster&SDC_ELEM && type == BL_ELEM) break;
return false;
}
return true;
}
int battle_skill_damage_skill(struct block_list *src, struct block_list *target, uint16 skill_id)
{
unsigned short m = src->m;
int idx;
struct s_skill_damage *damage = NULL;
if ((idx = skill_get_index(skill_id)) < 0 || !skill_db[idx].damage.map)
return 0;
damage = &skill_db[idx].damage;
//check the adjustment works for specified type
if (!battle_skill_damage_iscaster(damage->caster,src->type))
return 0;
if ((damage->map&1 && (!map[m].flag.pvp && !map_flag_gvg(m) && !map[m].flag.battleground && !map[m].flag.skill_damage && !map[m].flag.restricted)) ||
(damage->map&2 && map[m].flag.pvp) ||
(damage->map&4 && map_flag_gvg(m)) ||
(damage->map&8 && map[m].flag.battleground) ||
(damage->map&16 && map[m].flag.skill_damage) ||
(map[m].flag.restricted && skill_db[idx].damage.map&(8*map[m].zone)))
{
switch (target->type) {
case BL_PC:
return damage->pc;
case BL_MOB:
if (is_boss(target))
return damage->boss;
else
return damage->mob;
default:
return damage->other;
}
}
return 0;
}
int battle_skill_damage_map(struct block_list *src, struct block_list *target, uint16 skill_id)
{
int rate = 0;
uint16 m = src->m;
uint8 i;
if (!map[m].flag.skill_damage)
return 0;
/* modifier for all skills */
if (battle_skill_damage_iscaster(map[m].adjust.damage.caster,src->type)) {
switch (target->type) {
case BL_PC:
rate = map[m].adjust.damage.pc;
break;
case BL_MOB:
if (is_boss(target))
rate = map[m].adjust.damage.boss;
else
rate = map[m].adjust.damage.mob;
break;
default:
rate = map[m].adjust.damage.other;
break;
}
}
/* modifier for specified map */
ARR_FIND(0,MAX_MAP_SKILL_MODIFIER,i,map[m].skill_damage[i].skill_id == skill_id);
if (i < MAX_MAP_SKILL_MODIFIER) {
if (battle_skill_damage_iscaster(map[m].skill_damage[i].caster,src->type)) {
switch (target->type) {
case BL_PC:
rate += map[m].skill_damage[i].pc;
break;
case BL_MOB:
if (is_boss(target))
rate += map[m].skill_damage[i].boss;
else
rate += map[m].skill_damage[i].mob;
break;
default:
rate += map[m].skill_damage[i].other;
break;
}
}
}
return rate;
}
int battle_skill_damage(struct block_list *src, struct block_list *target, uint16 skill_id)
{
if (!target)
return 0;
return battle_skill_damage_skill(src,target,skill_id) + battle_skill_damage_map(src,target,skill_id);
}
#endif
struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag);
struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag);
@ -4057,7 +4179,7 @@ struct Damage battle_calc_attack_gvg_bg(struct Damage wd, struct block_list *src
if( map_flag_gvg2(target->m) )
wd.damage2 = battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag);
else if( map[target->m].flag.battleground )
wd.damage = battle_calc_bg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag);
wd.damage2 = battle_calc_bg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag);
}
else
{
@ -4263,7 +4385,9 @@ static struct Damage initialize_weapon_data(struct block_list *src, struct block
static struct Damage battle_calc_weapon_attack(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int wflag)
{
int i;
#ifdef ADJUST_SKILL_DAMAGE
int skill_damage;
#endif
struct map_session_data *sd, *tsd;
struct Damage wd;
struct status_change *sc = status_get_sc(src);
@ -4386,8 +4510,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
}
#endif
if(sd)
{
if(sd) {
if (skill_id != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus.
ATK_ADD2(wd.damage, wd.damage2, wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star);
if (skill_id==MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex]
@ -4462,6 +4585,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
wd = battle_calc_attack_gvg_bg(wd, src, target, skill_id, skill_lv);
}
/* Skill damage adjustment */
#ifdef ADJUST_SKILL_DAMAGE
if ((skill_damage = battle_skill_damage(src, target, skill_id)) != 0)
ATK_ADDRATE(wd.damage, wd.damage2, skill_damage);
#endif
return wd;
}
@ -4475,6 +4604,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag)
{
int i, nk;
#ifdef ADJUST_SKILL_DAMAGE
int skill_damage;
#endif
short s_ele = 0;
unsigned int skillratio = 100; //Skill dmg modifiers.
@ -5137,6 +5269,12 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
//case HM_ERASER_CUTTER:
}
/* Skill damage adjustment */
#ifdef ADJUST_SKILL_DAMAGE
if ((skill_damage = battle_skill_damage(src,target,skill_id)) != 0)
MATK_ADDRATE(skill_damage);
#endif
return ad;
}
@ -5150,6 +5288,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag)
{
int skill;
#ifdef ADJUST_SKILL_DAMAGE
int skill_damage;
#endif
short i, nk;
short s_ele;
@ -5522,6 +5663,12 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
break;
}
/* Skill damage adjustment */
#ifdef ADJUST_SKILL_DAMAGE
if ((skill_damage = battle_skill_damage(src,target,skill_id)) != 0)
md.damage += (int64)md.damage * skill_damage / 100;
#endif
if(tstatus->mode&MD_IGNOREMISC && md.flag&(BF_MISC) ) //misc @TODO optimize me
md.damage = md.damage2 = 1;
@ -5584,11 +5731,10 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i
status_change_end(bl,SC_REFLECTDAMAGE,INVALID_TIMER);
}
} else if (flag & BF_SHORT) {//Bounces back part of the damage.
if ( sd && sd->bonus.short_weapon_damage_return ) {
if ( !status_reflect && sd && sd->bonus.short_weapon_damage_return ) {
rdamage += damage * sd->bonus.short_weapon_damage_return / 100;
if(rdamage < 1) rdamage = 1;
}
if( status_reflect && sc && sc->count ) {
} else if( status_reflect && sc && sc->count ) {
if ( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) {
rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100;
if (rdamage < 1) rdamage = 1;
@ -5608,7 +5754,7 @@ int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, i
}
}
} else {
if (sd && sd->bonus.long_weapon_damage_return) {
if (!status_reflect && sd && sd->bonus.long_weapon_damage_return) {
rdamage += damage * sd->bonus.long_weapon_damage_return / 100;
if (rdamage < 1) rdamage = 1;
}

View File

@ -1687,10 +1687,10 @@ int map_quit(struct map_session_data *sd) {
}
}
for( i = 0; i < EQI_MAX; i++ ) {
if( sd->equip_index[ i ] >= 0 )
if( !pc_isequip( sd , sd->equip_index[ i ] ) )
pc_unequipitem( sd , sd->equip_index[ i ] , 2 );
for (i = 0; i < EQI_MAX; i++) {
if (sd->equip_index[i] >= 0)
if (!pc_isequip(sd,sd->equip_index[i]))
pc_unequipitem(sd,sd->equip_index[i],2);
}
// Return loot to owner
@ -3050,12 +3050,18 @@ void map_flags_init(void)
memset(&map[i].flag, 0, sizeof(map[i].flag));
// additional mapflag data
map[i].zone = 0; // restricted mapflag zone
map[i].nocommand = 0; // nocommand mapflag level
map[i].bexp = 100; // per map base exp multiplicator
map[i].jexp = 100; // per map job exp multiplicator
map[i].zone = 0; // restricted mapflag zone
map[i].nocommand = 0; // nocommand mapflag level
map[i].adjust.bexp = 100; // per map base exp multiplicator
map[i].adjust.jexp = 100; // per map job exp multiplicator
memset(map[i].drop_list, 0, sizeof(map[i].drop_list)); // pvp nightmare drop list
// skill damage
#ifdef ADJUST_SKILL_DAMAGE
memset(map[i].skill_damage, 0, sizeof(map[i].skill_damage));
memset(&map[i].adjust.damage, 0, sizeof(map[i].adjust.damage));
#endif
// adjustments
if( battle_config.pk_mode )
map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]

View File

@ -516,6 +516,19 @@ struct iwall_data {
bool shootable;
};
#ifdef ADJUST_SKILL_DAMAGE
struct s_skill_damage {
uint16 map, skill_id;
/* additional rates */
int pc,
mob,
boss,
other;
uint8 caster; /* caster type */
};
#define MAX_MAP_SKILL_MODIFIER 5
#endif
struct map_data {
char name[MAP_NAME_LENGTH];
uint16 index; // The map index used by the mapindex* functions.
@ -585,6 +598,9 @@ struct map_data {
unsigned nomineeffect : 1; //allow /mineeffect
unsigned nolockon : 1;
unsigned notomb : 1;
#ifdef ADJUST_SKILL_DAMAGE
unsigned skill_damage : 1;
#endif
} flag;
struct point save;
struct npc_data *npc[MAX_NPC_PER_MAP];
@ -597,9 +613,17 @@ struct map_data {
struct spawn_data *moblist[MAX_MOB_LIST_PER_MAP]; // [Wizputer]
int mob_delete_timer; // [Skotlex]
int zone; // zone number (for item/skill restrictions)
int jexp; // map experience multiplicator
int bexp; // map experience multiplicator
int nocommand; //Blocks @/# commands for non-gms. [Skotlex]
struct {
int jexp; // map experience multiplicator
int bexp; // map experience multiplicator
#ifdef ADJUST_SKILL_DAMAGE
struct s_skill_damage damage;
#endif
} adjust;
#ifdef ADJUST_SKILL_DAMAGE
struct s_skill_damage skill_damage[MAX_MAP_SKILL_MODIFIER];
#endif
/**
* Ice wall reference counter for bugreport:3574
* - since there are a thounsand mobs out there in a lot of maps checking on,

View File

@ -2250,12 +2250,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
if (map[m].flag.nobaseexp || !md->db->base_exp)
base_exp = 0;
else
base_exp = (unsigned int)cap_value(md->db->base_exp * per * bonus/100. * map[m].bexp/100., 1, UINT_MAX);
base_exp = (unsigned int)cap_value(md->db->base_exp * per * bonus/100. * map[m].adjust.bexp/100., 1, UINT_MAX);
if (map[m].flag.nojobexp || !md->db->job_exp || md->dmglog[i].flag == MDLF_HOMUN) //Homun earned job-exp is always lost.
job_exp = 0;
else
job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].jexp/100., 1, UINT_MAX);
job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].adjust.jexp/100., 1, UINT_MAX);
if ( ( temp = tmpsd[i]->status.party_id)>0 ) {
int j;

View File

@ -3417,14 +3417,14 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
}
}
else if (!strcmpi(w3,"jexp")) {
map[m].jexp = (state) ? atoi(w4) : 100;
if( map[m].jexp < 0 ) map[m].jexp = 100;
map[m].flag.nojobexp = (map[m].jexp==0)?1:0;
map[m].adjust.jexp = (state) ? atoi(w4) : 100;
if( map[m].adjust.jexp < 0 ) map[m].adjust.jexp = 100;
map[m].flag.nojobexp = (map[m].adjust.jexp==0)?1:0;
}
else if (!strcmpi(w3,"bexp")) {
map[m].bexp = (state) ? atoi(w4) : 100;
if( map[m].bexp < 0 ) map[m].bexp = 100;
map[m].flag.nobaseexp = (map[m].bexp==0)?1:0;
map[m].adjust.bexp = (state) ? atoi(w4) : 100;
if( map[m].adjust.bexp < 0 ) map[m].adjust.bexp = 100;
map[m].flag.nobaseexp = (map[m].adjust.bexp==0)?1:0;
}
else if (!strcmpi(w3,"loadevent"))
map[m].flag.loadevent=state;
@ -3450,6 +3450,49 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
map[m].flag.nolockon = state;
else if (!strcmpi(w3,"notomb"))
map[m].flag.notomb = state;
else if (!strcmpi(w3,"skill_damage")) {
#ifdef ADJUST_SKILL_DAMAGE
char skill[NAME_LENGTH];
int pc = 0, mob = 0, boss = 0, other = 0, caster = 0;
memset(skill,0,sizeof(skill));
map[m].flag.skill_damage = state; //set the mapflag
if (sscanf(w4,"%24[^,],%d,%d,%d,%d,%d[^\n]",skill,&caster,&pc,&mob,&boss,&other) >= 3) {
caster = (!caster) ? SDC_ALL : caster;
pc = cap_value(pc,-100,MAX_SKILL_DAMAGE_RATE);
mob = cap_value(mob,-100,MAX_SKILL_DAMAGE_RATE);
boss = cap_value(boss,-100,MAX_SKILL_DAMAGE_RATE);
other = cap_value(other,-100,MAX_SKILL_DAMAGE_RATE);
if (strcmp(skill,"all") == 0) { //adjust damages for all skills
map[m].adjust.damage.caster = caster;
map[m].adjust.damage.pc = pc;
map[m].adjust.damage.mob = mob;
map[m].adjust.damage.boss = boss;
map[m].adjust.damage.other = other;
}
else if (skill_name2id(skill) <= 0)
ShowWarning("npc_parse_mapflag: skill_damage: Invalid skill name '%s'. Skipping (file '%s', line '%d')\n",skill,filepath,strline(buffer,start-buffer));
else { //damages for specified skill
int i;
ARR_FIND(0,MAX_MAP_SKILL_MODIFIER,i,map[m].skill_damage[i].skill_id <= 0);
if (i >= MAX_SKILL)
ShowWarning("npc_parse_mapflag: skill_damage: Skill damage for map '%s' is overflow.\n",map[m].name);
else {
map[m].skill_damage[i].skill_id = skill_name2id(skill);
map[m].skill_damage[i].caster = caster;
map[m].skill_damage[i].pc = pc;
map[m].skill_damage[i].mob = mob;
map[m].skill_damage[i].boss = boss;
map[m].skill_damage[i].other = other;
}
}
}
#else
ShowInfo("npc_parse_mapflag: skill_damage: ADJUST_SKILL_DAMAGE is inactive (core.h). Skipping this mapflag..\n");
#endif
}
else
ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer));

View File

@ -949,7 +949,7 @@ int pc_isequip(struct map_session_data *sd,int n)
}
//fail to equip if item is restricted
if (itemdb_isNoEquip(item, sd->bl.m) && !battle_config.allow_equip_restricted_item)
if (!battle_config.allow_equip_restricted_item && itemdb_isNoEquip(item, sd->bl.m))
return 0;
//Not equipable by class. [Skotlex]
@ -4888,10 +4888,10 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
status_change_end(&sd->bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(&sd->bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
}
for( i = 0; i < EQI_MAX; i++ ) {
if( sd->equip_index[ i ] >= 0 )
if( !pc_isequip( sd , sd->equip_index[ i ] ) )
pc_unequipitem( sd , sd->equip_index[ i ] , 2 );
for (i = 0; i < EQI_MAX; i++) {
if (sd->equip_index[i] >= 0)
if (!pc_isequip(sd,sd->equip_index[i]))
pc_unequipitem(sd,sd->equip_index[i],2);
}
if (battle_config.clear_unit_onwarp&BL_PC)
skill_clear_unitgroup(&sd->bl);
@ -8797,7 +8797,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
//OnEquip script [Skotlex]
if (id) {
//only run the script if item isn't restricted
if (id->equip_script && (!id->flag.no_equip || (id->flag.no_equip && itemdb_isNoEquip(id, sd->bl.m) && pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))))
if (id->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(id,sd->bl.m)))
run_script(id->equip_script,0,sd->bl.id,fake_nd->bl.id);
if(itemdb_isspecial(sd->status.inventory[n].card[0]))
; //No cards
@ -8807,7 +8807,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
if (!sd->status.inventory[n].card[i])
continue;
if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
if( data->equip_script && (!data->flag.no_equip || (data->flag.no_equip && itemdb_isNoEquip(data, sd->bl.m) && pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))))
if (data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data,sd->bl.m)))
run_script(data->equip_script,0,sd->bl.id,fake_nd->bl.id);
}
}

View File

@ -414,7 +414,8 @@ enum {
MF_SUMSTARTMIRACLE,
MF_NOMINEEFFECT,
MF_NOLOCKON,
MF_NOTOMB
MF_NOTOMB,
MF_SKILL_DAMAGE //60
};
const char* script_op2name(int op)
@ -10780,11 +10781,12 @@ BUILDIN_FUNC(setmapflagnosave)
BUILDIN_FUNC(getmapflag)
{
int16 m,i;
int16 m,i,type=0;
const char *str;
str=script_getstr(st,2);
i=script_getnum(st,3);
FETCH(4,type);
m = map_mapname2mapid(str);
if(m >= 0) {
@ -10826,8 +10828,8 @@ BUILDIN_FUNC(getmapflag)
case MF_RESTRICTED: script_pushint(st,map[m].flag.restricted); break;
case MF_NOCOMMAND: script_pushint(st,map[m].nocommand); break;
case MF_NODROP: script_pushint(st,map[m].flag.nodrop); break;
case MF_JEXP: script_pushint(st,map[m].jexp); break;
case MF_BEXP: script_pushint(st,map[m].bexp); break;
case MF_JEXP: script_pushint(st,map[m].adjust.jexp); break;
case MF_BEXP: script_pushint(st,map[m].adjust.bexp); break;
case MF_NOVENDING: script_pushint(st,map[m].flag.novending); break;
case MF_LOADEVENT: script_pushint(st,map[m].flag.loadevent); break;
case MF_NOCHAT: script_pushint(st,map[m].flag.nochat); break;
@ -10847,6 +10849,21 @@ BUILDIN_FUNC(getmapflag)
case MF_NOMINEEFFECT: script_pushint(st,map[m].flag.nomineeffect); break;
case MF_NOLOCKON: script_pushint(st,map[m].flag.nolockon); break;
case MF_NOTOMB: script_pushint(st,map[m].flag.notomb); break;
#ifdef ADJUST_SKILL_DAMAGE
case MF_SKILL_DAMAGE:
{
int ret_val = 0;
switch (type) {
case 1: ret_val = map[m].adjust.damage.pc; break;
case 2: ret_val = map[m].adjust.damage.mob; break;
case 3: ret_val = map[m].adjust.damage.boss; break;
case 4: ret_val = map[m].adjust.damage.other; break;
case 5: ret_val = map[m].adjust.damage.caster; break;
default: ret_val = map[m].flag.skill_damage; break;
}
script_pushint(st,ret_val); break;
} break;
#endif
}
}
@ -10869,15 +10886,14 @@ static int script_mapflag_pvp_sub(struct block_list *bl,va_list ap) {
}
BUILDIN_FUNC(setmapflag)
{
int16 m,i;
int16 m,i,type=0;
const char *str;
int val=0;
str=script_getstr(st,2);
i=script_getnum(st,3);
if(script_hasdata(st,4)){
val=script_getnum(st,4);
}
FETCH(4,val);
FETCH(5,type);
m = map_mapname2mapid(str);
if(m >= 0) {
switch(i) {
@ -10934,8 +10950,8 @@ BUILDIN_FUNC(setmapflag)
break;
case MF_NOCOMMAND: map[m].nocommand = (val <= 0) ? 100 : val; break;
case MF_NODROP: map[m].flag.nodrop = 1; break;
case MF_JEXP: map[m].jexp = (val <= 0) ? 100 : val; break;
case MF_BEXP: map[m].bexp = (val <= 0) ? 100 : val; break;
case MF_JEXP: map[m].adjust.jexp = (val <= 0) ? 100 : val; break;
case MF_BEXP: map[m].adjust.bexp = (val <= 0) ? 100 : val; break;
case MF_NOVENDING: map[m].flag.novending = 1; break;
case MF_LOADEVENT: map[m].flag.loadevent = 1; break;
case MF_NOCHAT: map[m].flag.nochat = 1; break;
@ -10955,6 +10971,19 @@ BUILDIN_FUNC(setmapflag)
case MF_NOMINEEFFECT: map[m].flag.nomineeffect = 1 ; break;
case MF_NOLOCKON: map[m].flag.nolockon = 1 ; break;
case MF_NOTOMB: map[m].flag.notomb = 1; break;
#ifdef ADJUST_SKILL_DAMAGE
case MF_SKILL_DAMAGE:
{
switch (type) {
case 1: map[m].adjust.damage.pc = val; break;
case 2: map[m].adjust.damage.mob = val; break;
case 3: map[m].adjust.damage.boss = val; break;
case 4: map[m].adjust.damage.other = val; break;
case 5: map[m].adjust.damage.caster = val; break;
}
map[m].flag.skill_damage = 1;
} break;
#endif
}
}
@ -10969,9 +10998,7 @@ BUILDIN_FUNC(removemapflag)
str=script_getstr(st,2);
i=script_getnum(st,3);
if(script_hasdata(st,4)){
val=script_getnum(st,4);
}
FETCH(4,val);
m = map_mapname2mapid(str);
if(m >= 0) {
switch(i) {
@ -11033,8 +11060,8 @@ BUILDIN_FUNC(removemapflag)
break;
case MF_NOCOMMAND: map[m].nocommand = 0; break;
case MF_NODROP: map[m].flag.nodrop = 0; break;
case MF_JEXP: map[m].jexp = 0; break;
case MF_BEXP: map[m].bexp = 0; break;
case MF_JEXP: map[m].adjust.jexp = 0; break;
case MF_BEXP: map[m].adjust.bexp = 0; break;
case MF_NOVENDING: map[m].flag.novending = 0; break;
case MF_LOADEVENT: map[m].flag.loadevent = 0; break;
case MF_NOCHAT: map[m].flag.nochat = 0; break;
@ -11054,6 +11081,13 @@ BUILDIN_FUNC(removemapflag)
case MF_NOMINEEFFECT: map[m].flag.nomineeffect = 0 ; break;
case MF_NOLOCKON: map[m].flag.nolockon = 0 ; break;
case MF_NOTOMB: map[m].flag.notomb = 0; break;
#ifdef ADJUST_SKILL_DAMAGE
case MF_SKILL_DAMAGE:
{
map[m].flag.skill_damage = 0;
memset(&map[m].adjust.damage,0,sizeof(map[m].adjust.damage));
} break;
#endif
}
}
@ -18143,8 +18177,8 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(detachrid,""),
BUILDIN_DEF(isloggedin,"i?"),
BUILDIN_DEF(setmapflagnosave,"ssii"),
BUILDIN_DEF(getmapflag,"si"),
BUILDIN_DEF(setmapflag,"si?"),
BUILDIN_DEF(getmapflag,"si?"),
BUILDIN_DEF(setmapflag,"si??"),
BUILDIN_DEF(removemapflag,"si?"),
BUILDIN_DEF(pvpon,"s"),
BUILDIN_DEF(pvpoff,"s"),

View File

@ -2311,7 +2311,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
struct status_data *sstatus, *tstatus;
struct status_change *tsc;
struct map_session_data *sd, *tsd;
int64 damage,rdamage=0;
int64 damage;
int type;
int8 rmdamage=0;//magic reflected
bool additional_effects = true;
@ -2443,11 +2443,6 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
skill_id == MER_INCAGI || skill_id == MER_BLESSING) && tsd->sc.data[SC_CHANGEUNDEAD] )
damage = 1;
if( damage > 0 && (( dmg.flag&BF_WEAPON && src != bl && ( src == dsrc || ( dsrc->type == BL_SKILL &&
( skill_id == SG_SUN_WARM || skill_id == SG_MOON_WARM || skill_id == SG_STAR_WARM ) ) ))
|| ((tsc && tsc->data[SC_REFLECTDAMAGE]) && !(dmg.flag&(BF_MAGIC|BF_LONG)) && !(skill_get_inf2(skill_id)&INF2_TRAP)) ) )
rdamage = battle_calc_return_damage(bl,src, &damage, dmg.flag, skill_id, 1);
if( damage && tsc && tsc->data[SC_GENSOU] && dmg.flag&BF_MAGIC ){
struct block_list *nbl;
nbl = battle_getenemyarea(bl,bl->x,bl->y,2,BL_CHAR,bl->id);
@ -2821,22 +2816,6 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
battle_drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->mode&MD_BOSS);
}
if( rdamage > 0 ) {
if( tsc && tsc->data[SC_REFLECTDAMAGE] ) {
if( src != bl )// Don't reflect your own damage (Grand Cross)
map_foreachinshootrange(battle_damage_area,bl,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,bl,dmg.amotion,sstatus->dmotion,rdamage,tstatus->race);
} else {
if( dmg.amotion )
battle_delay_damage(tick, dmg.amotion,bl,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,0,additional_effects);
else
status_fix_damage(bl,src,rdamage,0);
clif_damage(src,src,tick, dmg.amotion,0,rdamage,1,4,0); // in aegis damage reflected is shown in single hit.
//Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
if( tsd && src != bl )
battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src));
skill_additional_effect(bl, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
}
}
if( damage > 0 ) {
/**
* Post-damage effects
@ -18305,6 +18284,33 @@ static bool skill_parse_row_changematerialdb(char* split[], int columns, int cur
return true;
}
/*==========================================
* Manage Skill Damage database
* Credits:
[Lilith]
*------------------------------------------*/
#ifdef ADJUST_SKILL_DAMAGE
static bool skill_parse_row_skilldamage(char* split[], int columns, int current)
{
uint16 skill_id = skill_name2id(split[0]), idx;
if ((idx = skill_get_index(skill_id)) < 0) { // invalid skill id
ShowWarning("skill_parse_row_skilldamage: Invalid skill '%s'. Skipping..",split[0]);
return false;
}
memset(&skill_db[idx].damage,0,sizeof(struct s_skill_damage));
skill_db[idx].damage.caster |= atoi(split[1]);
skill_db[idx].damage.map |= atoi(split[2]);
skill_db[idx].damage.pc = cap_value(atoi(split[3]),-100,MAX_SKILL_DAMAGE_RATE);
if (split[3])
skill_db[idx].damage.mob = cap_value(atoi(split[4]),-100,MAX_SKILL_DAMAGE_RATE);
if (split[4])
skill_db[idx].damage.boss = cap_value(atoi(split[5]),-100,MAX_SKILL_DAMAGE_RATE);
if (split[5])
skill_db[idx].damage.other = cap_value(atoi(split[6]),-100,MAX_SKILL_DAMAGE_RATE);
return true;
}
#endif
/*===============================
* DB reading.
* skill_db.txt
@ -18357,7 +18363,9 @@ static void skill_readdb(void)
sv_readdb(db_path, "skill_reproduce_db.txt", ',', 1, 1, MAX_SKILL_DB, skill_parse_row_reproducedb);
sv_readdb(db_path, "skill_improvise_db.txt" , ',', 2, 2, MAX_SKILL_IMPROVISE_DB, skill_parse_row_improvisedb);
sv_readdb(db_path, "skill_changematerial_db.txt" , ',', 4, 4+2*5, MAX_SKILL_PRODUCE_DB, skill_parse_row_changematerialdb);
#ifdef ADJUST_SKILL_DAMAGE
sv_readdb(db_path, "skill_damage_db.txt" , ',', 4, 7, MAX_SKILL_DB, skill_parse_row_skilldamage);
#endif
}
void skill_reload (void) {

View File

@ -133,6 +133,9 @@ struct s_skill_db {
int unit_interval;
int unit_target;
int unit_flag;
#ifdef ADJUST_SKILL_DAMAGE
struct s_skill_damage damage;
#endif
};
extern struct s_skill_db skill_db[MAX_SKILL_DB];
@ -1924,4 +1927,19 @@ int skill_get_elemental_type(uint16 skill_id, uint16 skill_lv);
void skill_combo_toogle_inf(struct block_list* bl, uint16 skill_id, int inf);
void skill_combo(struct block_list* src,struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int tick);
/**
* Skill Damage target
**/
#ifdef ADJUST_SKILL_DAMAGE
enum e_skill_damage_caster {
SDC_PC = 0x01,
SDC_MOB = 0x02,
SDC_PET = 0x04,
SDC_HOM = 0x08,
SDC_MER = 0x10,
SDC_ELEM = 0x20,
SDC_ALL = SDC_PC|SDC_MOB|SDC_PET|SDC_HOM|SDC_MER|SDC_ELEM,
};
#endif
#endif /* _SKILL_H_ */

View File

@ -2461,7 +2461,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
if(!sd->inventory_data[index])
continue;
if(!pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT) && sd->inventory_data[index]->flag.no_equip && itemdb_isNoEquip(sd->inventory_data[index], sd->bl.m)) // Items may be equipped, their effects however are nullified.
if(!pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m)) // Items may be equipped, their effects however are nullified.
continue;
status->def += sd->inventory_data[index]->def;
@ -2605,7 +2605,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
}
if(!data->script)
continue;
if(!pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT) && data->flag.no_equip && itemdb_isNoEquip(data, sd->bl.m)) //Card restriction checks.
if(!pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) && itemdb_isNoEquip(data,sd->bl.m)) //Card restriction checks.
continue;
if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L)
{ //Left hand status.