summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/battle.c22
-rw-r--r--src/map/map.c90
-rw-r--r--src/map/map.h12
-rw-r--r--src/map/npc.c40
-rw-r--r--src/map/pc.c1344
-rw-r--r--src/map/script.c8
-rw-r--r--src/map/skill.c687
7 files changed, 1219 insertions, 984 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index 2ad066d33..5bc3df6f8 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -1606,7 +1606,20 @@ static int battle_range_type(
return BF_SHORT;
return BF_LONG;
}
+static inline int battle_adjust_skill_damage(int m, unsigned short skill_id) {
+ if( map[m].skill_count ) {
+ int i;
+ ARR_FIND(0, map[m].skill_count, i, map[m].skills[i]->skill_id == skill_id );
+
+ if( i < map[m].skill_count ) {
+ return map[m].skills[i]->modifier;
+ }
+
+ }
+
+ return 0;
+}
static int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id)
{
int i;
@@ -3094,6 +3107,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
if (skill_id && (i = pc_skillatk_bonus(sd, skill_id)))
ATK_ADDRATE(i);
+ if( (i = battle_adjust_skill_damage(sd->bl.m,skill_id)) )
+ ATK_RATE(i);
+
if( skill_id != PA_SACRIFICE && skill_id != MO_INVESTIGATE && skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS && skill_id != PA_SHIELDCHAIN && !flag.cri )
{ //Elemental/Racial adjustments
if( sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) ||
@@ -4075,6 +4091,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
//Damage bonuses
if ((i = pc_skillatk_bonus(sd, skill_id)))
ad.damage += ad.damage*i/100;
+
+ if( (i = battle_adjust_skill_damage(sd->bl.m,skill_id)) )
+ MATK_RATE(i);
//Ignore Defense?
if (!flag.imdef && (
@@ -4456,6 +4475,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
if (sd && (i = pc_skillatk_bonus(sd, skill_id)))
md.damage += md.damage*i/100;
+ if( (i = battle_adjust_skill_damage(sd->bl.m,skill_id)) )
+ md.damage = md.damage * i / 100;
+
if(md.damage < 0)
md.damage = 0;
else if(md.damage && tstatus->mode&MD_PLANT){
diff --git a/src/map/map.c b/src/map/map.c
index 6f9401dad..dde922f39 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -2894,13 +2894,54 @@ int map_delmap(char* mapname)
return 0;
}
+void do_final_maps(void) {
+ int i, v = 0;
+
+ 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 ) {
+ for(v = 0; v < map[i].unit_count; v++) {
+ aFree(map[i].units[v]);
+ }
+ if( map[i].units ) {
+ aFree(map[i].units);
+ map[i].units = NULL;
+ }
+ map[i].unit_count = 0;
+ }
+
+ if( map[i].skill_count ) {
+ for(v = 0; v < map[i].skill_count; v++) {
+ aFree(map[i].skills[v]);
+ }
+ if( map[i].skills ) {
+ aFree(map[i].skills);
+ map[i].skills = NULL;
+ }
+ map[i].skill_count = 0;
+ }
+
+ }
+
+}
+
/// Initializes map flags and adjusts them depending on configuration.
-void map_flags_init(void)
-{
- int i;
+void map_flags_init(void) {
+ int i, v = 0;
- 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 +2952,24 @@ 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 ) {
+ for(v = 0; v < map[i].unit_count; v++) {
+ aFree(map[i].units[v]);
+ }
+ aFree(map[i].units);
+ }
+ map[i].units = NULL;
+ map[i].unit_count = 0;
+
+ if( map[i].skill_count ) {
+ for(v = 0; v < map[i].skill_count; v++) {
+ aFree(map[i].skills[v]);
+ }
+ aFree(map[i].skills);
+ }
+ map[i].skills = NULL;
+ map[i].skill_count = 0;
+
// adjustments
if( battle_config.pk_mode )
map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
@@ -3552,7 +3611,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;
@@ -3600,21 +3659,10 @@ void do_final(void)
do_final_battleground();
do_final_duel();
do_final_elemental();
-
+ do_final_maps();
+
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]);
- }
- }
-
+
mapindex_final();
if(enable_grf)
grfio_final();
@@ -3939,6 +3987,8 @@ int do_init(int argc, char *argv[])
ShowStatus("Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port);
+ Sql_HerculesUpdateCheck(mmysql_handle);
+
if( runflag != CORE_ST_STOP )
{
shutdown_callback = do_shutdown;
diff --git a/src/map/map.h b/src/map/map.h
index 73f8e694b..861a55d0a 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -496,6 +496,11 @@ struct iwall_data {
bool shootable;
};
+struct mapflag_skill_adjust {
+ unsigned short 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,13 @@ struct map_data {
// Instance Variables
int instance_id;
int instance_src_map;
+
+ /* adjust_unit_duration mapflag */
+ struct mapflag_skill_adjust **units;
+ unsigned short unit_count;
+ /* adjust_skill_damage mapflag */
+ struct mapflag_skill_adjust **skills;
+ unsigned short skill_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..671b4485a 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -3398,7 +3398,45 @@ 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 mapflag_skill_adjust*, ++map[m].unit_count);
+ CREATE(map[m].units[idx],struct mapflag_skill_adjust,1);
+ map[m].units[idx]->skill_id = (unsigned short)skill_id;
+ map[m].units[idx]->modifier = (unsigned short)atoi(mod);
+ }
+ } else if (!strcmpi(w3,"adjust_skill_damage")) {
+ 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_skill_damage' 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) ) ) {
+ ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_skill_damage' 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_skill_damage' 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].skill_count;
+ RECREATE(map[m].skills, struct mapflag_skill_adjust*, ++map[m].skill_count);
+ CREATE(map[m].skills[idx],struct mapflag_skill_adjust,1);
+ map[m].skills[idx]->skill_id = (unsigned short)skill_id;
+ map[m].skills[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/pc.c b/src/map/pc.c
index 0dd210394..ad779a268 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1058,9 +1058,16 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
if( !changing_mapservers ) {
- if (battle_config.display_version == 1){
+ if (battle_config.display_version == 1) {
+ const char* svn = get_svn_revision();
+ const char* git = get_git_hash();
char buf[256];
- sprintf(buf, "SVN version: %s", get_svn_revision());
+ if( git[0] != HERC_UNKNOWN_VER )
+ sprintf(buf,"Git Hash: %s", git);
+ else if( svn[0] != HERC_UNKNOWN_VER )
+ sprintf(buf,"SVN Revision: %s", svn);
+ else
+ sprintf(buf,"Unknown Version");
clif_displaymessage(sd->fd, buf);
}
@@ -1253,7 +1260,7 @@ static int pc_calc_skillpoint(struct map_session_data* sd)
if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
skill_point += skill;
else
- if(sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0)
+ if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0)
skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
}
}
@@ -1283,13 +1290,13 @@ int pc_calc_skilltree(struct map_session_data *sd)
for( i = 0; i < MAX_SKILL; i++ )
{
- if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) //Don't touch plagiarized skills
+ if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these
sd->status.skill[i].id = 0; //First clear skills.
}
for( i = 0; i < MAX_SKILL; i++ )
{
- if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED )
+ if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED )
{ // Restore original level of skills after deleting earned skills.
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
@@ -1509,7 +1516,7 @@ int pc_clean_skilltree(struct map_session_data *sd)
sd->status.skill[i].flag = 0;
}
else
- if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0){
+ if (sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0){
sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = 0;
}
@@ -2013,604 +2020,604 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
status = &sd->base_status;
switch(type){
- case SP_STR:
- case SP_AGI:
- case SP_VIT:
- case SP_INT:
- case SP_DEX:
- case SP_LUK:
- if(sd->state.lr_flag != 2)
- sd->param_bonus[type-SP_STR]+=val;
- break;
- case SP_ATK1:
- if(!sd->state.lr_flag) {
- bonus = status->rhw.atk + val;
- status->rhw.atk = cap_value(bonus, 0, USHRT_MAX);
- }
- else if(sd->state.lr_flag == 1) {
- bonus = status->lhw.atk + val;
- status->lhw.atk = cap_value(bonus, 0, USHRT_MAX);
- }
- break;
- case SP_ATK2:
- if(!sd->state.lr_flag) {
- bonus = status->rhw.atk2 + val;
- status->rhw.atk2 = cap_value(bonus, 0, USHRT_MAX);
- }
- else if(sd->state.lr_flag == 1) {
- bonus = status->lhw.atk2 + val;
- status->lhw.atk2 = cap_value(bonus, 0, USHRT_MAX);
- }
- break;
- case SP_BASE_ATK:
- if(sd->state.lr_flag != 2) {
-//#ifdef RENEWAL
-// sd->bonus.eatk += val;
-//#else
- bonus = status->batk + val;
- status->batk = cap_value(bonus, 0, USHRT_MAX);
-//#endif
- }
- break;
- case SP_DEF1:
- if(sd->state.lr_flag != 2) {
- bonus = status->def + val;
-#ifdef RENEWAL
- status->def = cap_value(bonus, SHRT_MIN, SHRT_MAX);
-#else
- status->def = cap_value(bonus, CHAR_MIN, CHAR_MAX);
-#endif
- }
- break;
- case SP_DEF2:
- if(sd->state.lr_flag != 2) {
- bonus = status->def2 + val;
- status->def2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
- }
- break;
- case SP_MDEF1:
- if(sd->state.lr_flag != 2) {
- bonus = status->mdef + val;
-#ifdef RENEWAL
- status->mdef = cap_value(bonus, SHRT_MIN, SHRT_MAX);
-#else
- status->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX);
-#endif
- if( sd->state.lr_flag == 3 ) {//Shield, used for royal guard
- sd->bonus.shieldmdef += bonus;
+ case SP_STR:
+ case SP_AGI:
+ case SP_VIT:
+ case SP_INT:
+ case SP_DEX:
+ case SP_LUK:
+ if(sd->state.lr_flag != 2)
+ sd->param_bonus[type-SP_STR]+=val;
+ break;
+ case SP_ATK1:
+ if(!sd->state.lr_flag) {
+ bonus = status->rhw.atk + val;
+ status->rhw.atk = cap_value(bonus, 0, USHRT_MAX);
+ }
+ else if(sd->state.lr_flag == 1) {
+ bonus = status->lhw.atk + val;
+ status->lhw.atk = cap_value(bonus, 0, USHRT_MAX);
}
- }
- break;
- case SP_MDEF2:
- if(sd->state.lr_flag != 2) {
- bonus = status->mdef2 + val;
- status->mdef2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
- }
- break;
- case SP_HIT:
- if(sd->state.lr_flag != 2) {
- bonus = status->hit + val;
- status->hit = cap_value(bonus, SHRT_MIN, SHRT_MAX);
- } else
- sd->bonus.arrow_hit+=val;
- break;
- case SP_FLEE1:
- if(sd->state.lr_flag != 2) {
- bonus = status->flee + val;
- status->flee = cap_value(bonus, SHRT_MIN, SHRT_MAX);
- }
- break;
- case SP_FLEE2:
- if(sd->state.lr_flag != 2) {
- bonus = status->flee2 + val*10;
- status->flee2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
- }
- break;
- case SP_CRITICAL:
- if(sd->state.lr_flag != 2) {
- bonus = status->cri + val*10;
- status->cri = cap_value(bonus, SHRT_MIN, SHRT_MAX);
- } else
- sd->bonus.arrow_cri += val*10;
- break;
- case SP_ATKELE:
- if(val >= ELE_MAX) {
- ShowError("pc_bonus: SP_ATKELE: Invalid element %d\n", val);
break;
- }
- switch (sd->state.lr_flag)
- {
- case 2:
- switch (sd->status.weapon) {
- case W_BOW:
- case W_REVOLVER:
- case W_RIFLE:
- case W_GATLING:
- case W_SHOTGUN:
- case W_GRENADE:
- //Become weapon element.
- status->rhw.ele=val;
- break;
- default: //Become arrow element.
- sd->bonus.arrow_ele=val;
- break;
+ case SP_ATK2:
+ if(!sd->state.lr_flag) {
+ bonus = status->rhw.atk2 + val;
+ status->rhw.atk2 = cap_value(bonus, 0, USHRT_MAX);
+ }
+ else if(sd->state.lr_flag == 1) {
+ bonus = status->lhw.atk2 + val;
+ status->lhw.atk2 = cap_value(bonus, 0, USHRT_MAX);
}
break;
- case 1:
- status->lhw.ele=val;
+ case SP_BASE_ATK:
+ if(sd->state.lr_flag != 2) {
+ //#ifdef RENEWAL
+ // sd->bonus.eatk += val;
+ //#else
+ bonus = status->batk + val;
+ status->batk = cap_value(bonus, 0, USHRT_MAX);
+ //#endif
+ }
break;
- default:
- status->rhw.ele=val;
+ case SP_DEF1:
+ if(sd->state.lr_flag != 2) {
+ bonus = status->def + val;
+ #ifdef RENEWAL
+ status->def = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ #else
+ status->def = cap_value(bonus, CHAR_MIN, CHAR_MAX);
+ #endif
+ }
break;
- }
- break;
- case SP_DEFELE:
- if(val >= ELE_MAX) {
- ShowError("pc_bonus: SP_DEFELE: Invalid element %d\n", val);
+ case SP_DEF2:
+ if(sd->state.lr_flag != 2) {
+ bonus = status->def2 + val;
+ status->def2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ }
break;
- }
- if(sd->state.lr_flag != 2)
- status->def_ele=val;
- break;
- case SP_MAXHP:
- if(sd->state.lr_flag == 2)
+ case SP_MDEF1:
+ if(sd->state.lr_flag != 2) {
+ bonus = status->mdef + val;
+ #ifdef RENEWAL
+ status->mdef = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ #else
+ status->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX);
+ #endif
+ if( sd->state.lr_flag == 3 ) {//Shield, used for royal guard
+ sd->bonus.shieldmdef += bonus;
+ }
+ }
break;
- val += (int)status->max_hp;
- //Negative bonuses will underflow, this will be handled in status_calc_pc through casting
- //If this is called outside of status_calc_pc, you'd better pray they do not underflow and end with UINT_MAX max_hp.
- status->max_hp = (unsigned int)val;
- break;
- case SP_MAXSP:
- if(sd->state.lr_flag == 2)
+ case SP_MDEF2:
+ if(sd->state.lr_flag != 2) {
+ bonus = status->mdef2 + val;
+ status->mdef2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ }
break;
- val += (int)status->max_sp;
- status->max_sp = (unsigned int)val;
- break;
-#ifndef RENEWAL_CAST
- case SP_VARCASTRATE:
-#endif
- case SP_CASTRATE:
- if(sd->state.lr_flag != 2)
- sd->castrate+=val;
- break;
- case SP_MAXHPRATE:
- if(sd->state.lr_flag != 2)
- sd->hprate+=val;
- break;
- case SP_MAXSPRATE:
- if(sd->state.lr_flag != 2)
- sd->sprate+=val;
- break;
- case SP_SPRATE:
- if(sd->state.lr_flag != 2)
- sd->dsprate+=val;
- break;
- case SP_ATTACKRANGE:
- switch (sd->state.lr_flag) {
- case 2:
- switch (sd->status.weapon) {
- case W_BOW:
- case W_REVOLVER:
- case W_RIFLE:
- case W_GATLING:
- case W_SHOTGUN:
- case W_GRENADE:
- status->rhw.range += val;
+ case SP_HIT:
+ if(sd->state.lr_flag != 2) {
+ bonus = status->hit + val;
+ status->hit = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ } else
+ sd->bonus.arrow_hit+=val;
+ break;
+ case SP_FLEE1:
+ if(sd->state.lr_flag != 2) {
+ bonus = status->flee + val;
+ status->flee = cap_value(bonus, SHRT_MIN, SHRT_MAX);
}
break;
- case 1:
- status->lhw.range += val;
+ case SP_FLEE2:
+ if(sd->state.lr_flag != 2) {
+ bonus = status->flee2 + val*10;
+ status->flee2 = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ }
break;
- default:
- status->rhw.range += val;
+ case SP_CRITICAL:
+ if(sd->state.lr_flag != 2) {
+ bonus = status->cri + val*10;
+ status->cri = cap_value(bonus, SHRT_MIN, SHRT_MAX);
+ } else
+ sd->bonus.arrow_cri += val*10;
break;
- }
- break;
- case SP_SPEED_RATE: //Non stackable increase
- if(sd->state.lr_flag != 2)
- sd->bonus.speed_rate = min(sd->bonus.speed_rate, -val);
- break;
- case SP_SPEED_ADDRATE: //Stackable increase
- if(sd->state.lr_flag != 2)
- sd->bonus.speed_add_rate -= val;
- break;
- case SP_ASPD: //Raw increase
- if(sd->state.lr_flag != 2)
- sd->bonus.aspd_add -= 10*val;
- break;
- case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone
- if(sd->state.lr_flag != 2)
-#ifndef RENEWAL_ASPD
- status->aspd_rate -= 10*val;
-#else
- status->aspd_rate2 += val;
-#endif
- break;
- case SP_HP_RECOV_RATE:
- if(sd->state.lr_flag != 2)
- sd->hprecov_rate += val;
- break;
- case SP_SP_RECOV_RATE:
- if(sd->state.lr_flag != 2)
- sd->sprecov_rate += val;
- break;
- case SP_CRITICAL_DEF:
- if(sd->state.lr_flag != 2)
- sd->bonus.critical_def += val;
- break;
- case SP_NEAR_ATK_DEF:
- if(sd->state.lr_flag != 2)
- sd->bonus.near_attack_def_rate += val;
- break;
- case SP_LONG_ATK_DEF:
- if(sd->state.lr_flag != 2)
- sd->bonus.long_attack_def_rate += val;
- break;
- case SP_DOUBLE_RATE:
- if(sd->state.lr_flag == 0 && sd->bonus.double_rate < val)
- sd->bonus.double_rate = val;
- break;
- case SP_DOUBLE_ADD_RATE:
- if(sd->state.lr_flag == 0)
- sd->bonus.double_add_rate += val;
- break;
- case SP_MATK_RATE:
- if(sd->state.lr_flag != 2)
- sd->matk_rate += val;
- break;
- case SP_IGNORE_DEF_ELE:
- if(val >= ELE_MAX) {
- ShowError("pc_bonus: SP_IGNORE_DEF_ELE: Invalid element %d\n", val);
+ case SP_ATKELE:
+ if(val >= ELE_MAX) {
+ ShowError("pc_bonus: SP_ATKELE: Invalid element %d\n", val);
+ break;
+ }
+ switch (sd->state.lr_flag)
+ {
+ case 2:
+ switch (sd->status.weapon) {
+ case W_BOW:
+ case W_REVOLVER:
+ case W_RIFLE:
+ case W_GATLING:
+ case W_SHOTGUN:
+ case W_GRENADE:
+ //Become weapon element.
+ status->rhw.ele=val;
+ break;
+ default: //Become arrow element.
+ sd->bonus.arrow_ele=val;
+ break;
+ }
+ break;
+ case 1:
+ status->lhw.ele=val;
+ break;
+ default:
+ status->rhw.ele=val;
+ break;
+ }
break;
- }
- if(!sd->state.lr_flag)
- sd->right_weapon.ignore_def_ele |= 1<<val;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.ignore_def_ele |= 1<<val;
- break;
- case SP_IGNORE_DEF_RACE:
- if(!sd->state.lr_flag)
- sd->right_weapon.ignore_def_race |= 1<<val;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.ignore_def_race |= 1<<val;
- break;
- case SP_ATK_RATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.atk_rate += val;
- break;
- case SP_MAGIC_ATK_DEF:
- if(sd->state.lr_flag != 2)
- sd->bonus.magic_def_rate += val;
- break;
- case SP_MISC_ATK_DEF:
- if(sd->state.lr_flag != 2)
- sd->bonus.misc_def_rate += val;
- break;
- case SP_IGNORE_MDEF_RATE:
- if(sd->state.lr_flag != 2) {
- sd->ignore_mdef[RC_NONBOSS] += val;
- sd->ignore_mdef[RC_BOSS] += val;
- }
- break;
- case SP_IGNORE_MDEF_ELE:
- if(val >= ELE_MAX) {
- ShowError("pc_bonus: SP_IGNORE_MDEF_ELE: Invalid element %d\n", val);
+ case SP_DEFELE:
+ if(val >= ELE_MAX) {
+ ShowError("pc_bonus: SP_DEFELE: Invalid element %d\n", val);
+ break;
+ }
+ if(sd->state.lr_flag != 2)
+ status->def_ele=val;
break;
- }
- if(sd->state.lr_flag != 2)
- sd->bonus.ignore_mdef_ele |= 1<<val;
- break;
- case SP_IGNORE_MDEF_RACE:
- if(sd->state.lr_flag != 2)
- sd->bonus.ignore_mdef_race |= 1<<val;
- break;
- case SP_PERFECT_HIT_RATE:
- if(sd->state.lr_flag != 2 && sd->bonus.perfect_hit < val)
- sd->bonus.perfect_hit = val;
- break;
- case SP_PERFECT_HIT_ADD_RATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.perfect_hit_add += val;
- break;
- case SP_CRITICAL_RATE:
- if(sd->state.lr_flag != 2)
- sd->critical_rate+=val;
- break;
- case SP_DEF_RATIO_ATK_ELE:
- if(val >= ELE_MAX) {
- ShowError("pc_bonus: SP_DEF_RATIO_ATK_ELE: Invalid element %d\n", val);
+ case SP_MAXHP:
+ if(sd->state.lr_flag == 2)
+ break;
+ val += (int)status->max_hp;
+ //Negative bonuses will underflow, this will be handled in status_calc_pc through casting
+ //If this is called outside of status_calc_pc, you'd better pray they do not underflow and end with UINT_MAX max_hp.
+ status->max_hp = (unsigned int)val;
break;
- }
- if(!sd->state.lr_flag)
- sd->right_weapon.def_ratio_atk_ele |= 1<<val;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.def_ratio_atk_ele |= 1<<val;
- break;
- case SP_DEF_RATIO_ATK_RACE:
- if(val >= RC_MAX) {
- ShowError("pc_bonus: SP_DEF_RATIO_ATK_RACE: Invalid race %d\n", val);
+ case SP_MAXSP:
+ if(sd->state.lr_flag == 2)
+ break;
+ val += (int)status->max_sp;
+ status->max_sp = (unsigned int)val;
break;
- }
- if(!sd->state.lr_flag)
- sd->right_weapon.def_ratio_atk_race |= 1<<val;
- else if(sd->state.lr_flag == 1)
- sd->left_weapon.def_ratio_atk_race |= 1<<val;
- break;
- case SP_HIT_RATE:
- if(sd->state.lr_flag != 2)
- sd->hit_rate += val;
- break;
- case SP_FLEE_RATE:
- if(sd->state.lr_flag != 2)
- sd->flee_rate += val;
- break;
- case SP_FLEE2_RATE:
- if(sd->state.lr_flag != 2)
- sd->flee2_rate += val;
- break;
- case SP_DEF_RATE:
- if(sd->state.lr_flag != 2)
- sd->def_rate += val;
- break;
- case SP_DEF2_RATE:
- if(sd->state.lr_flag != 2)
- sd->def2_rate += val;
- break;
- case SP_MDEF_RATE:
- if(sd->state.lr_flag != 2)
- sd->mdef_rate += val;
- break;
- case SP_MDEF2_RATE:
- if(sd->state.lr_flag != 2)
- sd->mdef2_rate += val;
- break;
- case SP_RESTART_FULL_RECOVER:
- if(sd->state.lr_flag != 2)
- sd->special_state.restart_full_recover = 1;
- break;
- case SP_NO_CASTCANCEL:
- if(sd->state.lr_flag != 2)
- sd->special_state.no_castcancel = 1;
- break;
- case SP_NO_CASTCANCEL2:
- if(sd->state.lr_flag != 2)
- sd->special_state.no_castcancel2 = 1;
- break;
- case SP_NO_SIZEFIX:
- if(sd->state.lr_flag != 2)
- sd->special_state.no_sizefix = 1;
- break;
- case SP_NO_MAGIC_DAMAGE:
- if(sd->state.lr_flag == 2)
+ #ifndef RENEWAL_CAST
+ case SP_VARCASTRATE:
+ #endif
+ case SP_CASTRATE:
+ if(sd->state.lr_flag != 2)
+ sd->castrate+=val;
break;
- val+= sd->special_state.no_magic_damage;
- sd->special_state.no_magic_damage = cap_value(val,0,100);
- break;
- case SP_NO_WEAPON_DAMAGE:
- if(sd->state.lr_flag == 2)
+ case SP_MAXHPRATE:
+ if(sd->state.lr_flag != 2)
+ sd->hprate+=val;
break;
- val+= sd->special_state.no_weapon_damage;
- sd->special_state.no_weapon_damage = cap_value(val,0,100);
- break;
- case SP_NO_MISC_DAMAGE:
- if(sd->state.lr_flag == 2)
+ case SP_MAXSPRATE:
+ if(sd->state.lr_flag != 2)
+ sd->sprate+=val;
break;
- val+= sd->special_state.no_misc_damage;
- sd->special_state.no_misc_damage = cap_value(val,0,100);
- break;
- case SP_NO_GEMSTONE:
- if(sd->state.lr_flag != 2)
- sd->special_state.no_gemstone = 1;
- break;
- case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG]
- if(sd->state.lr_flag != 2) {
- sd->special_state.intravision = 1;
- clif_status_load(&sd->bl, SI_INTRAVISION, 1);
- }
- break;
- case SP_NO_KNOCKBACK:
- if(sd->state.lr_flag != 2)
- sd->special_state.no_knockback = 1;
- break;
- case SP_SPLASH_RANGE:
- if(sd->bonus.splash_range < val)
- sd->bonus.splash_range = val;
- break;
- case SP_SPLASH_ADD_RANGE:
- sd->bonus.splash_add_range += val;
- break;
- case SP_SHORT_WEAPON_DAMAGE_RETURN:
- if(sd->state.lr_flag != 2)
- sd->bonus.short_weapon_damage_return += val;
- break;
- case SP_LONG_WEAPON_DAMAGE_RETURN:
- if(sd->state.lr_flag != 2)
- sd->bonus.long_weapon_damage_return += val;
- break;
- case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here
- if(sd->state.lr_flag != 2)
- sd->bonus.magic_damage_return += val;
- break;
- case SP_ALL_STATS: // [Valaris]
- if(sd->state.lr_flag!=2) {
- sd->param_bonus[SP_STR-SP_STR]+=val;
- sd->param_bonus[SP_AGI-SP_STR]+=val;
- sd->param_bonus[SP_VIT-SP_STR]+=val;
- sd->param_bonus[SP_INT-SP_STR]+=val;
- sd->param_bonus[SP_DEX-SP_STR]+=val;
- sd->param_bonus[SP_LUK-SP_STR]+=val;
- }
- break;
- case SP_AGI_VIT: // [Valaris]
- if(sd->state.lr_flag!=2) {
- sd->param_bonus[SP_AGI-SP_STR]+=val;
- sd->param_bonus[SP_VIT-SP_STR]+=val;
- }
- break;
- case SP_AGI_DEX_STR: // [Valaris]
- if(sd->state.lr_flag!=2) {
- sd->param_bonus[SP_AGI-SP_STR]+=val;
- sd->param_bonus[SP_DEX-SP_STR]+=val;
- sd->param_bonus[SP_STR-SP_STR]+=val;
- }
- break;
- case SP_PERFECT_HIDE: // [Valaris]
- if(sd->state.lr_flag!=2)
- sd->special_state.perfect_hiding=1;
- break;
- case SP_UNBREAKABLE:
- if(sd->state.lr_flag!=2)
- sd->bonus.unbreakable += val;
- break;
- case SP_UNBREAKABLE_WEAPON:
- if(sd->state.lr_flag != 2)
- sd->bonus.unbreakable_equip |= EQP_WEAPON;
- break;
- case SP_UNBREAKABLE_ARMOR:
- if(sd->state.lr_flag != 2)
- sd->bonus.unbreakable_equip |= EQP_ARMOR;
- break;
- case SP_UNBREAKABLE_HELM:
- if(sd->state.lr_flag != 2)
- sd->bonus.unbreakable_equip |= EQP_HELM;
- break;
- case SP_UNBREAKABLE_SHIELD:
- if(sd->state.lr_flag != 2)
- sd->bonus.unbreakable_equip |= EQP_SHIELD;
- break;
- case SP_UNBREAKABLE_GARMENT:
- if(sd->state.lr_flag != 2)
- sd->bonus.unbreakable_equip |= EQP_GARMENT;
- break;
- case SP_UNBREAKABLE_SHOES:
- if(sd->state.lr_flag != 2)
- sd->bonus.unbreakable_equip |= EQP_SHOES;
- break;
- case SP_CLASSCHANGE: // [Valaris]
- if(sd->state.lr_flag !=2)
- sd->bonus.classchange=val;
- break;
- case SP_LONG_ATK_RATE:
- if(sd->state.lr_flag != 2) //[Lupus] it should stack, too. As any other cards rate bonuses
- sd->bonus.long_attack_atk_rate+=val;
- break;
- case SP_BREAK_WEAPON_RATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.break_weapon_rate+=val;
- break;
- case SP_BREAK_ARMOR_RATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.break_armor_rate+=val;
- break;
- case SP_ADD_STEAL_RATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.add_steal_rate+=val;
- break;
- case SP_DELAYRATE:
- if(sd->state.lr_flag != 2)
- sd->delayrate+=val;
- break;
- case SP_CRIT_ATK_RATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.crit_atk_rate += val;
- break;
- case SP_NO_REGEN:
- if(sd->state.lr_flag != 2)
- sd->regen.state.block|=val;
- break;
- case SP_UNSTRIPABLE_WEAPON:
- if(sd->state.lr_flag != 2)
- sd->bonus.unstripable_equip |= EQP_WEAPON;
- break;
- case SP_UNSTRIPABLE:
- case SP_UNSTRIPABLE_ARMOR:
- if(sd->state.lr_flag != 2)
- sd->bonus.unstripable_equip |= EQP_ARMOR;
- break;
- case SP_UNSTRIPABLE_HELM:
- if(sd->state.lr_flag != 2)
- sd->bonus.unstripable_equip |= EQP_HELM;
- break;
- case SP_UNSTRIPABLE_SHIELD:
- if(sd->state.lr_flag != 2)
- sd->bonus.unstripable_equip |= EQP_SHIELD;
- break;
- case SP_HP_DRAIN_VALUE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.hp_drain[RC_NONBOSS].value += val;
- sd->right_weapon.hp_drain[RC_BOSS].value += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.hp_drain[RC_NONBOSS].value += val;
- sd->left_weapon.hp_drain[RC_BOSS].value += val;
- }
- break;
- case SP_SP_DRAIN_VALUE:
- if(!sd->state.lr_flag) {
- sd->right_weapon.sp_drain[RC_NONBOSS].value += val;
- sd->right_weapon.sp_drain[RC_BOSS].value += val;
- }
- else if(sd->state.lr_flag == 1) {
- sd->left_weapon.sp_drain[RC_NONBOSS].value += val;
- sd->left_weapon.sp_drain[RC_BOSS].value += val;
- }
- break;
- case SP_SP_GAIN_VALUE:
- if(!sd->state.lr_flag)
- sd->bonus.sp_gain_value += val;
- break;
- case SP_HP_GAIN_VALUE:
- if(!sd->state.lr_flag)
- sd->bonus.hp_gain_value += val;
- break;
- case SP_MAGIC_SP_GAIN_VALUE:
- if(!sd->state.lr_flag)
- sd->bonus.magic_sp_gain_value += val;
- break;
- case SP_MAGIC_HP_GAIN_VALUE:
- if(!sd->state.lr_flag)
- sd->bonus.magic_hp_gain_value += val;
- break;
- case SP_ADD_HEAL_RATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.add_heal_rate += val;
- break;
- case SP_ADD_HEAL2_RATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.add_heal2_rate += val;
- break;
- case SP_ADD_ITEM_HEAL_RATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.itemhealrate2 += val;
- break;
- case SP_EMATK:
- if(sd->state.lr_flag != 2)
- sd->bonus.ematk += val;
- break;
- case SP_FIXCASTRATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.fixcastrate -= val;
- break;
- case SP_ADD_FIXEDCAST:
- if(sd->state.lr_flag != 2)
- sd->bonus.add_fixcast += val;
+ case SP_SPRATE:
+ if(sd->state.lr_flag != 2)
+ sd->dsprate+=val;
+ break;
+ case SP_ATTACKRANGE:
+ switch (sd->state.lr_flag) {
+ case 2:
+ switch (sd->status.weapon) {
+ case W_BOW:
+ case W_REVOLVER:
+ case W_RIFLE:
+ case W_GATLING:
+ case W_SHOTGUN:
+ case W_GRENADE:
+ status->rhw.range += val;
+ }
+ break;
+ case 1:
+ status->lhw.range += val;
+ break;
+ default:
+ status->rhw.range += val;
+ break;
+ }
+ break;
+ case SP_SPEED_RATE: //Non stackable increase
+ if(sd->state.lr_flag != 2)
+ sd->bonus.speed_rate = min(sd->bonus.speed_rate, -val);
+ break;
+ case SP_SPEED_ADDRATE: //Stackable increase
+ if(sd->state.lr_flag != 2)
+ sd->bonus.speed_add_rate -= val;
+ break;
+ case SP_ASPD: //Raw increase
+ if(sd->state.lr_flag != 2)
+ sd->bonus.aspd_add -= 10*val;
+ break;
+ case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone
+ if(sd->state.lr_flag != 2)
+ #ifndef RENEWAL_ASPD
+ status->aspd_rate -= 10*val;
+ #else
+ status->aspd_rate2 += val;
+ #endif
+ break;
+ case SP_HP_RECOV_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->hprecov_rate += val;
+ break;
+ case SP_SP_RECOV_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->sprecov_rate += val;
+ break;
+ case SP_CRITICAL_DEF:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.critical_def += val;
+ break;
+ case SP_NEAR_ATK_DEF:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.near_attack_def_rate += val;
+ break;
+ case SP_LONG_ATK_DEF:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.long_attack_def_rate += val;
+ break;
+ case SP_DOUBLE_RATE:
+ if(sd->state.lr_flag == 0 && sd->bonus.double_rate < val)
+ sd->bonus.double_rate = val;
+ break;
+ case SP_DOUBLE_ADD_RATE:
+ if(sd->state.lr_flag == 0)
+ sd->bonus.double_add_rate += val;
+ break;
+ case SP_MATK_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->matk_rate += val;
+ break;
+ case SP_IGNORE_DEF_ELE:
+ if(val >= ELE_MAX) {
+ ShowError("pc_bonus: SP_IGNORE_DEF_ELE: Invalid element %d\n", val);
+ break;
+ }
+ if(!sd->state.lr_flag)
+ sd->right_weapon.ignore_def_ele |= 1<<val;
+ else if(sd->state.lr_flag == 1)
+ sd->left_weapon.ignore_def_ele |= 1<<val;
+ break;
+ case SP_IGNORE_DEF_RACE:
+ if(!sd->state.lr_flag)
+ sd->right_weapon.ignore_def_race |= 1<<val;
+ else if(sd->state.lr_flag == 1)
+ sd->left_weapon.ignore_def_race |= 1<<val;
+ break;
+ case SP_ATK_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.atk_rate += val;
+ break;
+ case SP_MAGIC_ATK_DEF:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.magic_def_rate += val;
+ break;
+ case SP_MISC_ATK_DEF:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.misc_def_rate += val;
+ break;
+ case SP_IGNORE_MDEF_RATE:
+ if(sd->state.lr_flag != 2) {
+ sd->ignore_mdef[RC_NONBOSS] += val;
+ sd->ignore_mdef[RC_BOSS] += val;
+ }
+ break;
+ case SP_IGNORE_MDEF_ELE:
+ if(val >= ELE_MAX) {
+ ShowError("pc_bonus: SP_IGNORE_MDEF_ELE: Invalid element %d\n", val);
+ break;
+ }
+ if(sd->state.lr_flag != 2)
+ sd->bonus.ignore_mdef_ele |= 1<<val;
+ break;
+ case SP_IGNORE_MDEF_RACE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.ignore_mdef_race |= 1<<val;
+ break;
+ case SP_PERFECT_HIT_RATE:
+ if(sd->state.lr_flag != 2 && sd->bonus.perfect_hit < val)
+ sd->bonus.perfect_hit = val;
+ break;
+ case SP_PERFECT_HIT_ADD_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.perfect_hit_add += val;
+ break;
+ case SP_CRITICAL_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->critical_rate+=val;
+ break;
+ case SP_DEF_RATIO_ATK_ELE:
+ if(val >= ELE_MAX) {
+ ShowError("pc_bonus: SP_DEF_RATIO_ATK_ELE: Invalid element %d\n", val);
+ break;
+ }
+ if(!sd->state.lr_flag)
+ sd->right_weapon.def_ratio_atk_ele |= 1<<val;
+ else if(sd->state.lr_flag == 1)
+ sd->left_weapon.def_ratio_atk_ele |= 1<<val;
+ break;
+ case SP_DEF_RATIO_ATK_RACE:
+ if(val >= RC_MAX) {
+ ShowError("pc_bonus: SP_DEF_RATIO_ATK_RACE: Invalid race %d\n", val);
+ break;
+ }
+ if(!sd->state.lr_flag)
+ sd->right_weapon.def_ratio_atk_race |= 1<<val;
+ else if(sd->state.lr_flag == 1)
+ sd->left_weapon.def_ratio_atk_race |= 1<<val;
+ break;
+ case SP_HIT_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->hit_rate += val;
+ break;
+ case SP_FLEE_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->flee_rate += val;
+ break;
+ case SP_FLEE2_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->flee2_rate += val;
+ break;
+ case SP_DEF_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->def_rate += val;
+ break;
+ case SP_DEF2_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->def2_rate += val;
+ break;
+ case SP_MDEF_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->mdef_rate += val;
+ break;
+ case SP_MDEF2_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->mdef2_rate += val;
+ break;
+ case SP_RESTART_FULL_RECOVER:
+ if(sd->state.lr_flag != 2)
+ sd->special_state.restart_full_recover = 1;
+ break;
+ case SP_NO_CASTCANCEL:
+ if(sd->state.lr_flag != 2)
+ sd->special_state.no_castcancel = 1;
+ break;
+ case SP_NO_CASTCANCEL2:
+ if(sd->state.lr_flag != 2)
+ sd->special_state.no_castcancel2 = 1;
+ break;
+ case SP_NO_SIZEFIX:
+ if(sd->state.lr_flag != 2)
+ sd->special_state.no_sizefix = 1;
+ break;
+ case SP_NO_MAGIC_DAMAGE:
+ if(sd->state.lr_flag == 2)
+ break;
+ val+= sd->special_state.no_magic_damage;
+ sd->special_state.no_magic_damage = cap_value(val,0,100);
+ break;
+ case SP_NO_WEAPON_DAMAGE:
+ if(sd->state.lr_flag == 2)
+ break;
+ val+= sd->special_state.no_weapon_damage;
+ sd->special_state.no_weapon_damage = cap_value(val,0,100);
+ break;
+ case SP_NO_MISC_DAMAGE:
+ if(sd->state.lr_flag == 2)
+ break;
+ val+= sd->special_state.no_misc_damage;
+ sd->special_state.no_misc_damage = cap_value(val,0,100);
+ break;
+ case SP_NO_GEMSTONE:
+ if(sd->state.lr_flag != 2)
+ sd->special_state.no_gemstone = 1;
+ break;
+ case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG]
+ if(sd->state.lr_flag != 2) {
+ sd->special_state.intravision = 1;
+ clif_status_load(&sd->bl, SI_INTRAVISION, 1);
+ }
+ break;
+ case SP_NO_KNOCKBACK:
+ if(sd->state.lr_flag != 2)
+ sd->special_state.no_knockback = 1;
+ break;
+ case SP_SPLASH_RANGE:
+ if(sd->bonus.splash_range < val)
+ sd->bonus.splash_range = val;
+ break;
+ case SP_SPLASH_ADD_RANGE:
+ sd->bonus.splash_add_range += val;
+ break;
+ case SP_SHORT_WEAPON_DAMAGE_RETURN:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.short_weapon_damage_return += val;
+ break;
+ case SP_LONG_WEAPON_DAMAGE_RETURN:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.long_weapon_damage_return += val;
+ break;
+ case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here
+ if(sd->state.lr_flag != 2)
+ sd->bonus.magic_damage_return += val;
+ break;
+ case SP_ALL_STATS: // [Valaris]
+ if(sd->state.lr_flag!=2) {
+ sd->param_bonus[SP_STR-SP_STR]+=val;
+ sd->param_bonus[SP_AGI-SP_STR]+=val;
+ sd->param_bonus[SP_VIT-SP_STR]+=val;
+ sd->param_bonus[SP_INT-SP_STR]+=val;
+ sd->param_bonus[SP_DEX-SP_STR]+=val;
+ sd->param_bonus[SP_LUK-SP_STR]+=val;
+ }
+ break;
+ case SP_AGI_VIT: // [Valaris]
+ if(sd->state.lr_flag!=2) {
+ sd->param_bonus[SP_AGI-SP_STR]+=val;
+ sd->param_bonus[SP_VIT-SP_STR]+=val;
+ }
+ break;
+ case SP_AGI_DEX_STR: // [Valaris]
+ if(sd->state.lr_flag!=2) {
+ sd->param_bonus[SP_AGI-SP_STR]+=val;
+ sd->param_bonus[SP_DEX-SP_STR]+=val;
+ sd->param_bonus[SP_STR-SP_STR]+=val;
+ }
+ break;
+ case SP_PERFECT_HIDE: // [Valaris]
+ if(sd->state.lr_flag!=2)
+ sd->special_state.perfect_hiding=1;
+ break;
+ case SP_UNBREAKABLE:
+ if(sd->state.lr_flag!=2)
+ sd->bonus.unbreakable += val;
+ break;
+ case SP_UNBREAKABLE_WEAPON:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.unbreakable_equip |= EQP_WEAPON;
+ break;
+ case SP_UNBREAKABLE_ARMOR:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.unbreakable_equip |= EQP_ARMOR;
+ break;
+ case SP_UNBREAKABLE_HELM:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.unbreakable_equip |= EQP_HELM;
+ break;
+ case SP_UNBREAKABLE_SHIELD:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.unbreakable_equip |= EQP_SHIELD;
+ break;
+ case SP_UNBREAKABLE_GARMENT:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.unbreakable_equip |= EQP_GARMENT;
+ break;
+ case SP_UNBREAKABLE_SHOES:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.unbreakable_equip |= EQP_SHOES;
+ break;
+ case SP_CLASSCHANGE: // [Valaris]
+ if(sd->state.lr_flag !=2)
+ sd->bonus.classchange=val;
+ break;
+ case SP_LONG_ATK_RATE:
+ if(sd->state.lr_flag != 2) //[Lupus] it should stack, too. As any other cards rate bonuses
+ sd->bonus.long_attack_atk_rate+=val;
+ break;
+ case SP_BREAK_WEAPON_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.break_weapon_rate+=val;
+ break;
+ case SP_BREAK_ARMOR_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.break_armor_rate+=val;
+ break;
+ case SP_ADD_STEAL_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.add_steal_rate+=val;
+ break;
+ case SP_DELAYRATE:
+ if(sd->state.lr_flag != 2)
+ sd->delayrate+=val;
+ break;
+ case SP_CRIT_ATK_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.crit_atk_rate += val;
+ break;
+ case SP_NO_REGEN:
+ if(sd->state.lr_flag != 2)
+ sd->regen.state.block|=val;
+ break;
+ case SP_UNSTRIPABLE_WEAPON:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.unstripable_equip |= EQP_WEAPON;
+ break;
+ case SP_UNSTRIPABLE:
+ case SP_UNSTRIPABLE_ARMOR:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.unstripable_equip |= EQP_ARMOR;
+ break;
+ case SP_UNSTRIPABLE_HELM:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.unstripable_equip |= EQP_HELM;
+ break;
+ case SP_UNSTRIPABLE_SHIELD:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.unstripable_equip |= EQP_SHIELD;
+ break;
+ case SP_HP_DRAIN_VALUE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.hp_drain[RC_NONBOSS].value += val;
+ sd->right_weapon.hp_drain[RC_BOSS].value += val;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.hp_drain[RC_NONBOSS].value += val;
+ sd->left_weapon.hp_drain[RC_BOSS].value += val;
+ }
+ break;
+ case SP_SP_DRAIN_VALUE:
+ if(!sd->state.lr_flag) {
+ sd->right_weapon.sp_drain[RC_NONBOSS].value += val;
+ sd->right_weapon.sp_drain[RC_BOSS].value += val;
+ }
+ else if(sd->state.lr_flag == 1) {
+ sd->left_weapon.sp_drain[RC_NONBOSS].value += val;
+ sd->left_weapon.sp_drain[RC_BOSS].value += val;
+ }
+ break;
+ case SP_SP_GAIN_VALUE:
+ if(!sd->state.lr_flag)
+ sd->bonus.sp_gain_value += val;
+ break;
+ case SP_HP_GAIN_VALUE:
+ if(!sd->state.lr_flag)
+ sd->bonus.hp_gain_value += val;
+ break;
+ case SP_MAGIC_SP_GAIN_VALUE:
+ if(!sd->state.lr_flag)
+ sd->bonus.magic_sp_gain_value += val;
+ break;
+ case SP_MAGIC_HP_GAIN_VALUE:
+ if(!sd->state.lr_flag)
+ sd->bonus.magic_hp_gain_value += val;
+ break;
+ case SP_ADD_HEAL_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.add_heal_rate += val;
+ break;
+ case SP_ADD_HEAL2_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.add_heal2_rate += val;
+ break;
+ case SP_ADD_ITEM_HEAL_RATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.itemhealrate2 += val;
+ break;
+ case SP_EMATK:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.ematk += val;
+ break;
+ case SP_FIXCASTRATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.fixcastrate -= val;
+ break;
+ case SP_ADD_FIXEDCAST:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.add_fixcast += val;
- break;
-#ifdef RENEWAL_CAST
- case SP_VARCASTRATE:
- if(sd->state.lr_flag != 2)
- sd->bonus.varcastrate -= val;
- break;
- case SP_ADD_VARIABLECAST:
- if(sd->state.lr_flag != 2)
+ break;
+ #ifdef RENEWAL_CAST
+ case SP_VARCASTRATE:
+ if(sd->state.lr_flag != 2)
+ sd->bonus.varcastrate -= val;
+ break;
+ case SP_ADD_VARIABLECAST:
+ if(sd->state.lr_flag != 2)
- sd->bonus.add_varcast += val;
+ sd->bonus.add_varcast += val;
- break;
-#endif
- default:
- ShowWarning("pc_bonus: unknown type %d %d !\n",type,val);
- break;
+ break;
+ #endif
+ default:
+ ShowWarning("pc_bonus: unknown type %d %d !\n",type,val);
+ break;
}
return 0;
}
@@ -3442,7 +3449,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag)
case 0: //Set skill data overwriting whatever was there before.
sd->status.skill[id].id = id;
sd->status.skill[id].lv = level;
- sd->status.skill[id].flag = SKILL_FLAG_PERMANENT;
+ sd->status.skill[id].flag = SKILL_FLAG_PERM_GRANTED;
if( level == 0 ) //Remove skill.
{
sd->status.skill[id].id = 0;
@@ -6056,7 +6063,7 @@ int pc_allskillup(struct map_session_data *sd)
nullpo_ret(sd);
for(i=0;i<MAX_SKILL;i++){
- if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) {
+ if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) {
sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0;
sd->status.skill[i].flag = SKILL_FLAG_PERMANENT;
if (sd->status.skill[i].lv == 0)
@@ -6329,6 +6336,9 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE )
continue;
+ if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED )
+ continue;
+
if( flag&4 && !skill_ischangesex(i) )
continue;
@@ -6344,7 +6354,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT )
skill_point += lv;
else
- if( sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0 )
+ if( sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0 )
skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0);
if( !(flag&2) )
@@ -6865,39 +6875,139 @@ int pc_readparam(struct map_session_data* sd,int type)
nullpo_ret(sd);
switch(type) {
- case SP_SKILLPOINT: val = sd->status.skill_point; break;
- case SP_STATUSPOINT: val = sd->status.status_point; break;
- case SP_ZENY: val = sd->status.zeny; break;
- case SP_BASELEVEL: val = sd->status.base_level; break;
- case SP_JOBLEVEL: val = sd->status.job_level; break;
- case SP_CLASS: val = sd->status.class_; break;
- case SP_BASEJOB: val = pc_mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex); break; //Base job, extracting upper type.
- case SP_UPPER: val = sd->class_&JOBL_UPPER?1:(sd->class_&JOBL_BABY?2:0); break;
- case SP_BASECLASS: val = pc_mapid2jobid(sd->class_&MAPID_BASEMASK, sd->status.sex); break; //Extract base class tree. [Skotlex]
- case SP_SEX: val = sd->status.sex; break;
- case SP_WEIGHT: val = sd->weight; break;
- case SP_MAXWEIGHT: val = sd->max_weight; break;
- case SP_BASEEXP: val = sd->status.base_exp; break;
- case SP_JOBEXP: val = sd->status.job_exp; break;
- case SP_NEXTBASEEXP: val = pc_nextbaseexp(sd); break;
- case SP_NEXTJOBEXP: val = pc_nextjobexp(sd); break;
- case SP_HP: val = sd->battle_status.hp; break;
- case SP_MAXHP: val = sd->battle_status.max_hp; break;
- case SP_SP: val = sd->battle_status.sp; break;
- case SP_MAXSP: val = sd->battle_status.max_sp; break;
- case SP_STR: val = sd->status.str; break;
- case SP_AGI: val = sd->status.agi; break;
- case SP_VIT: val = sd->status.vit; break;
- case SP_INT: val = sd->status.int_; break;
- case SP_DEX: val = sd->status.dex; break;
- case SP_LUK: val = sd->status.luk; break;
- case SP_KARMA: val = sd->status.karma; break;
- case SP_MANNER: val = sd->status.manner; break;
- case SP_FAME: val = sd->status.fame; break;
- case SP_KILLERRID: val = sd->killerrid; break;
- case SP_KILLEDRID: val = sd->killedrid; break;
- case SP_CRITICAL: val = sd->battle_status.cri/10; break;
- case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break;
+ case SP_SKILLPOINT: val = sd->status.skill_point; break;
+ case SP_STATUSPOINT: val = sd->status.status_point; break;
+ case SP_ZENY: val = sd->status.zeny; break;
+ case SP_BASELEVEL: val = sd->status.base_level; break;
+ case SP_JOBLEVEL: val = sd->status.job_level; break;
+ case SP_CLASS: val = sd->status.class_; break;
+ case SP_BASEJOB: val = pc_mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex); break; //Base job, extracting upper type.
+ case SP_UPPER: val = sd->class_&JOBL_UPPER?1:(sd->class_&JOBL_BABY?2:0); break;
+ case SP_BASECLASS: val = pc_mapid2jobid(sd->class_&MAPID_BASEMASK, sd->status.sex); break; //Extract base class tree. [Skotlex]
+ case SP_SEX: val = sd->status.sex; break;
+ case SP_WEIGHT: val = sd->weight; break;
+ case SP_MAXWEIGHT: val = sd->max_weight; break;
+ case SP_BASEEXP: val = sd->status.base_exp; break;
+ case SP_JOBEXP: val = sd->status.job_exp; break;
+ case SP_NEXTBASEEXP: val = pc_nextbaseexp(sd); break;
+ case SP_NEXTJOBEXP: val = pc_nextjobexp(sd); break;
+ case SP_HP: val = sd->battle_status.hp; break;
+ case SP_MAXHP: val = sd->battle_status.max_hp; break;
+ case SP_SP: val = sd->battle_status.sp; break;
+ case SP_MAXSP: val = sd->battle_status.max_sp; break;
+ case SP_STR: val = sd->status.str; break;
+ case SP_AGI: val = sd->status.agi; break;
+ case SP_VIT: val = sd->status.vit; break;
+ case SP_INT: val = sd->status.int_; break;
+ case SP_DEX: val = sd->status.dex; break;
+ case SP_LUK: val = sd->status.luk; break;
+ case SP_KARMA: val = sd->status.karma; break;
+ case SP_MANNER: val = sd->status.manner; break;
+ case SP_FAME: val = sd->status.fame; break;
+ case SP_KILLERRID: val = sd->killerrid; break;
+ case SP_KILLEDRID: val = sd->killedrid; break;
+ case SP_CRITICAL: val = sd->battle_status.cri/10; break;
+ case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break;
+ case SP_BASE_ATK: val = sd->battle_status.batk; break;
+ case SP_DEF1: val = sd->battle_status.def; break;
+ case SP_DEF2: val = sd->battle_status.def2; break;
+ case SP_MDEF1: val = sd->battle_status.mdef; break;
+ case SP_MDEF2: val = sd->battle_status.mdef2; break;
+ case SP_HIT: val = sd->battle_status.hit; break;
+ case SP_FLEE1: val = sd->battle_status.flee; break;
+ case SP_FLEE2: val = sd->battle_status.flee2; break;
+ case SP_DEFELE: val = sd->battle_status.def_ele; break;
+#ifndef RENEWAL_CAST
+ case SP_VARCASTRATE:
+#endif
+ case SP_CASTRATE:
+ val = sd->castrate+=val;
+ break;
+ case SP_MAXHPRATE: val = sd->hprate; break;
+ case SP_MAXSPRATE: val = sd->sprate; break;
+ case SP_SPRATE: val = sd->dsprate; break;
+ case SP_SPEED_RATE: val = sd->bonus.speed_rate; break;
+ case SP_SPEED_ADDRATE: val = sd->bonus.speed_add_rate; break;
+ case SP_ASPD_RATE:
+#ifndef RENEWAL_ASPD
+ val = sd->battle_status.aspd_rate;
+#else
+ val = sd->battle_status.aspd_rate2;
+#endif
+ break;
+ case SP_HP_RECOV_RATE: val = sd->hprecov_rate; break;
+ case SP_SP_RECOV_RATE: val = sd->sprecov_rate; break;
+ case SP_CRITICAL_DEF: val = sd->bonus.critical_def; break;
+ case SP_NEAR_ATK_DEF: val = sd->bonus.near_attack_def_rate; break;
+ case SP_LONG_ATK_DEF: val = sd->bonus.long_attack_def_rate; break;
+ case SP_DOUBLE_RATE: val = sd->bonus.double_rate; break;
+ case SP_DOUBLE_ADD_RATE: val = sd->bonus.double_add_rate; break;
+ case SP_MATK_RATE: val = sd->matk_rate; break;
+ case SP_ATK_RATE: val = sd->bonus.atk_rate; break;
+ case SP_MAGIC_ATK_DEF: val = sd->bonus.magic_def_rate; break;
+ case SP_MISC_ATK_DEF: val = sd->bonus.misc_def_rate; break;
+ case SP_PERFECT_HIT_RATE:val = sd->bonus.perfect_hit; break;
+ case SP_PERFECT_HIT_ADD_RATE: val = sd->bonus.perfect_hit_add; break;
+ case SP_CRITICAL_RATE: val = sd->critical_rate; break;
+ case SP_HIT_RATE: val = sd->hit_rate; break;
+ case SP_FLEE_RATE: val = sd->flee_rate; break;
+ case SP_FLEE2_RATE: val = sd->flee2_rate; break;
+ case SP_DEF_RATE: val = sd->def_rate; break;
+ case SP_DEF2_RATE: val = sd->def2_rate; break;
+ case SP_MDEF_RATE: val = sd->mdef_rate; break;
+ case SP_MDEF2_RATE: val = sd->mdef2_rate; break;
+ case SP_RESTART_FULL_RECOVER: val = sd->special_state.restart_full_recover?1:0; break;
+ case SP_NO_CASTCANCEL: val = sd->special_state.no_castcancel?1:0; break;
+ case SP_NO_CASTCANCEL2: val = sd->special_state.no_castcancel2?1:0; break;
+ case SP_NO_SIZEFIX: val = sd->special_state.no_sizefix?1:0; break;
+ case SP_NO_MAGIC_DAMAGE: val = sd->special_state.no_magic_damage; break;
+ case SP_NO_WEAPON_DAMAGE:val = sd->special_state.no_weapon_damage; break;
+ case SP_NO_MISC_DAMAGE: val = sd->special_state.no_misc_damage; break;
+ case SP_NO_GEMSTONE: val = sd->special_state.no_gemstone?1:0; break;
+ case SP_INTRAVISION: val = sd->special_state.intravision?1:0; break;
+ case SP_NO_KNOCKBACK: val = sd->special_state.no_knockback?1:0; break;
+ case SP_SPLASH_RANGE: val = sd->bonus.splash_range; break;
+ case SP_SPLASH_ADD_RANGE:val = sd->bonus.splash_add_range; break;
+ case SP_SHORT_WEAPON_DAMAGE_RETURN: val = sd->bonus.short_weapon_damage_return; break;
+ case SP_LONG_WEAPON_DAMAGE_RETURN: val = sd->bonus.long_weapon_damage_return; break;
+ case SP_MAGIC_DAMAGE_RETURN: val = sd->bonus.magic_damage_return; break;
+ case SP_PERFECT_HIDE: val = sd->special_state.perfect_hiding?1:0; break;
+ case SP_UNBREAKABLE: val = sd->bonus.unbreakable; break;
+ case SP_UNBREAKABLE_WEAPON: val = (sd->bonus.unbreakable_equip&EQP_WEAPON)?1:0; break;
+ case SP_UNBREAKABLE_ARMOR: val = (sd->bonus.unbreakable_equip&EQP_ARMOR)?1:0; break;
+ case SP_UNBREAKABLE_HELM: val = (sd->bonus.unbreakable_equip&EQP_HELM)?1:0; break;
+ case SP_UNBREAKABLE_SHIELD: val = (sd->bonus.unbreakable_equip&EQP_SHIELD)?1:0; break;
+ case SP_UNBREAKABLE_GARMENT: val = (sd->bonus.unbreakable_equip&EQP_GARMENT)?1:0; break;
+ case SP_UNBREAKABLE_SHOES: val = (sd->bonus.unbreakable_equip&EQP_SHOES)?1:0; break;
+ case SP_CLASSCHANGE: val = sd->bonus.classchange; break;
+ case SP_LONG_ATK_RATE: val = sd->bonus.long_attack_atk_rate; break;
+ case SP_BREAK_WEAPON_RATE: val = sd->bonus.break_weapon_rate; break;
+ case SP_BREAK_ARMOR_RATE: val = sd->bonus.break_armor_rate; break;
+ case SP_ADD_STEAL_RATE: val = sd->bonus.add_steal_rate; break;
+ case SP_DELAYRATE: val = sd->delayrate; break;
+ case SP_CRIT_ATK_RATE: val = sd->bonus.crit_atk_rate; break;
+ case SP_UNSTRIPABLE_WEAPON: val = (sd->bonus.unstripable_equip&EQP_WEAPON)?1:0; break;
+ case SP_UNSTRIPABLE:
+ case SP_UNSTRIPABLE_ARMOR:
+ val = (sd->bonus.unstripable_equip&EQP_ARMOR)?1:0;
+ break;
+ case SP_UNSTRIPABLE_HELM: val = (sd->bonus.unstripable_equip&EQP_HELM)?1:0; break;
+ case SP_UNSTRIPABLE_SHIELD: val = (sd->bonus.unstripable_equip&EQP_SHIELD)?1:0; break;
+ case SP_SP_GAIN_VALUE: val = sd->bonus.sp_gain_value; break;
+ case SP_HP_GAIN_VALUE: val = sd->bonus.hp_gain_value; break;
+ case SP_MAGIC_SP_GAIN_VALUE: val = sd->bonus.magic_sp_gain_value; break;
+ case SP_MAGIC_HP_GAIN_VALUE: val = sd->bonus.magic_hp_gain_value; break;
+ case SP_ADD_HEAL_RATE: val = sd->bonus.add_heal_rate; break;
+ case SP_ADD_HEAL2_RATE: val = sd->bonus.add_heal2_rate; break;
+ case SP_ADD_ITEM_HEAL_RATE: val = sd->bonus.itemhealrate2; break;
+ case SP_EMATK: val = sd->bonus.ematk; break;
+ case SP_FIXCASTRATE: val = sd->bonus.fixcastrate; break;
+ case SP_ADD_FIXEDCAST: val = sd->bonus.add_fixcast; break;
+#ifdef RENEWAL_CAST
+ case SP_VARCASTRATE: val = sd->bonus.varcastrate; break;
+ case SP_ADD_VARIABLECAST:val = sd->bonus.add_varcast; break;
+#endif
+
}
return val;
diff --git a/src/map/script.c b/src/map/script.c
index b89121ee4..fe00599a6 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -7347,7 +7347,7 @@ BUILDIN_FUNC(strnpcinfo)
// aegis->athena slot position conversion table
-static unsigned int equip[] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW};
+static unsigned int equip[] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP};
/*==========================================
* GetEquipID(Pos); Pos: 1-10
@@ -16992,10 +16992,10 @@ BUILDIN_FUNC(is_function) {
* get_revision() -> retrieves the current svn revision (if available)
**/
BUILDIN_FUNC(get_revision) {
- const char * revision;
+ const char *svn = get_svn_revision();
- if ( (revision = get_svn_revision()) != 0 )
- script_pushint(st,atoi(revision));
+ if ( svn[0] != HERC_UNKNOWN_VER )
+ script_pushint(st,atoi(svn));
else
script_pushint(st,-1);//unknown
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.