summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c20
-rw-r--r--src/char/inter.c17
-rw-r--r--src/common/mapindex.c2
-rw-r--r--src/map/atcommand.c25
-rw-r--r--src/map/battle.c168
-rw-r--r--src/map/battle.h3
-rw-r--r--src/map/chrif.c3
-rw-r--r--src/map/clif.c17
-rw-r--r--src/map/homunculus.c2
-rw-r--r--src/map/mercenary.c2
-rw-r--r--src/map/mob.c9
-rw-r--r--src/map/mob.h4
-rw-r--r--src/map/npc.c2
-rw-r--r--src/map/pc.c3
-rw-r--r--src/map/script.c70
-rw-r--r--src/map/skill.c256
-rw-r--r--src/map/status.c244
-rw-r--r--src/map/status.h22
-rw-r--r--src/map/unit.c15
19 files changed, 547 insertions, 337 deletions
diff --git a/src/char/char.c b/src/char/char.c
index 863692492..0d96d40cb 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -4750,8 +4750,7 @@ int parse_char(int fd)
// checks the entered pin
case 0x8b8:
- if( RFIFOREST(fd) < 10 )
- return 0;
+ FIFOSD_CHECK(10);
if( RFIFOL(fd,2) == sd->account_id )
pincode->check( fd, sd );
@@ -4761,8 +4760,8 @@ int parse_char(int fd)
// request for PIN window
case 0x8c5:
- if( RFIFOREST(fd) < 6 )
- return 0;
+ FIFOSD_CHECK(6);
+
if( RFIFOL(fd,2) == sd->account_id )
pincode->sendstate( fd, sd, PINCODE_NOTSET );
@@ -4771,8 +4770,8 @@ int parse_char(int fd)
// pincode change request
case 0x8be:
- if( RFIFOREST(fd) < 14 )
- return 0;
+ FIFOSD_CHECK(14);
+
if( RFIFOL(fd,2) == sd->account_id )
pincode->change( fd, sd );
@@ -4781,8 +4780,8 @@ int parse_char(int fd)
// activate PIN system and set first PIN
case 0x8ba:
- if( RFIFOREST(fd) < 10 )
- return 0;
+ FIFOSD_CHECK(10);
+
if( RFIFOL(fd,2) == sd->account_id )
pincode->setnew( fd, sd );
RFIFOSKIP(fd,10);
@@ -4790,9 +4789,8 @@ int parse_char(int fd)
/* 0x8d4 <from>.W <to>.W <unused>.W (2+2+2+2) */
case 0x8d4:
- if( RFIFOREST(fd) < 8 )
- return 0;
- else {
+ FIFOSD_CHECK(8);
+ {
bool ret;
ret = char_slotchange(sd, fd, RFIFOW(fd, 2), RFIFOW(fd, 4));
WFIFOHEAD(fd, 8);
diff --git a/src/char/inter.c b/src/char/inter.c
index a7794c9c9..e5a7d411c 100644
--- a/src/char/inter.c
+++ b/src/char/inter.c
@@ -694,7 +694,11 @@ void mapif_parse_accinfo2(bool success, int map_fd, int u_fd, int u_aid, int acc
void inter_savereg(int account_id, int char_id, const char *key, unsigned int index, intptr_t val, bool is_string) {
/* to login server we go! */
if( key[0] == '#' && key[1] == '#' ) {/* global account reg */
- global_accreg_to_login_add(key,index,val,is_string);
+ if( session_isValid(login_fd) )
+ global_accreg_to_login_add(key,index,val,is_string);
+ else {
+ ShowError("Login server unavailable, cant perform update on '%s' variable for AID:%d CID:%d\n",key,account_id,char_id);
+ }
} else if ( key[0] == '#' ) {/* local account reg */
if( is_string ) {
if( val ) {
@@ -1301,8 +1305,10 @@ int mapif_parse_Registry(int fd)
int cursor = 14, i;
char key[32], sval[254];
unsigned int index;
-
- global_accreg_to_login_start(account_id,char_id);
+ bool isLoginActive = session_isActive(login_fd);
+
+ if( isLoginActive )
+ global_accreg_to_login_start(account_id,char_id);
for(i = 0; i < count; i++) {
safestrncpy(key, (char*)RFIFOP(fd, cursor + 1), RFIFOB(fd, cursor));
@@ -1336,8 +1342,9 @@ int mapif_parse_Registry(int fd)
}
}
-
- global_accreg_to_login_send();
+
+ if( isLoginActive )
+ global_accreg_to_login_send();
}
return 0;
}
diff --git a/src/common/mapindex.c b/src/common/mapindex.c
index f540c98d8..0873b3e59 100644
--- a/src/common/mapindex.c
+++ b/src/common/mapindex.c
@@ -138,7 +138,7 @@ int mapindex_init(void) {
char line[1024];
int last_index = -1;
int index, total = 0;
- char map_name[12];
+ char map_name[13];
if( ( fp = fopen(mapindex->config_file,"r") ) == NULL ){
ShowFatalError("Unable to read mapindex config file %s!\n", mapindex->config_file);
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index b5e8fa797..299ee321a 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -1915,11 +1915,11 @@ ACMD(monster)
number = battle_config.atc_spawn_quantity_limit;
if (strcmpi(info->command, "monstersmall") == 0)
- size = SZ_SMALL;
+ size = SZ_MEDIUM;
else if (strcmpi(info->command, "monsterbig") == 0)
size = SZ_BIG;
else
- size = SZ_MEDIUM;
+ size = SZ_SMALL;
if (battle_config.etc_log)
ShowInfo("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, sd->bl.x, sd->bl.y);
@@ -5469,7 +5469,8 @@ ACMD(autotrade) {
sd->state.autotrade = 1;
if( battle_config.at_timeout ) {
int timeout = atoi(message);
- status->change_start(NULL,&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0);
+ status->change_start(NULL,&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0,
+ ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, SCFLAG_NONE);
}
/* currently standalone is not supporting buyingstores, so we rely on the previous method */
@@ -6252,7 +6253,7 @@ ACMD(summon)
return false;
}
- md = mob->once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, "--ja--", mob_id, "", SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, "--ja--", mob_id, "", SZ_SMALL, AI_NONE);
if(!md)
return false;
@@ -7312,15 +7313,15 @@ ACMD(size)
{
int size = 0;
- size = cap_value(atoi(message),SZ_MEDIUM,SZ_BIG);
+ size = cap_value(atoi(message),SZ_SMALL,SZ_BIG);
if(sd->state.size) {
- sd->state.size = SZ_MEDIUM;
+ sd->state.size = SZ_SMALL;
pc->setpos(sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_TELEPORT);
}
sd->state.size = size;
- if( size == SZ_SMALL )
+ if( size == SZ_MEDIUM )
clif->specialeffect(&sd->bl,420,AREA);
else if( size == SZ_BIG )
clif->specialeffect(&sd->bl,422,AREA);
@@ -7342,12 +7343,12 @@ ACMD(sizeall)
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) {
if( pl_sd->state.size != size ) {
if( pl_sd->state.size ) {
- pl_sd->state.size = SZ_MEDIUM;
+ pl_sd->state.size = SZ_SMALL;
pc->setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT);
}
pl_sd->state.size = size;
- if( size == SZ_SMALL )
+ if( size == SZ_MEDIUM )
clif->specialeffect(&pl_sd->bl,420,AREA);
else if( size == SZ_BIG )
clif->specialeffect(&pl_sd->bl,422,AREA);
@@ -7378,17 +7379,17 @@ ACMD(sizeguild)
return false;
}
- size = cap_value(size,SZ_MEDIUM,SZ_BIG);
+ size = cap_value(size,SZ_SMALL,SZ_BIG);
for( i = 0; i < g->max_member; i++ ) {
if( (pl_sd = g->member[i].sd) && pl_sd->state.size != size ) {
if( pl_sd->state.size ) {
- pl_sd->state.size = SZ_MEDIUM;
+ pl_sd->state.size = SZ_SMALL;
pc->setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT);
}
pl_sd->state.size = size;
- if( size == SZ_SMALL )
+ if( size == SZ_MEDIUM )
clif->specialeffect(&pl_sd->bl,420,AREA);
else if( size == SZ_BIG )
clif->specialeffect(&pl_sd->bl,422,AREA);
diff --git a/src/map/battle.c b/src/map/battle.c
index 945d52c64..544d53a1c 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -252,12 +252,16 @@ int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) {
struct delay_damage *dat;
struct status_change *sc;
+ struct block_list *d_tbl = NULL;
nullpo_ret(src);
nullpo_ret(target);
sc = status->get_sc(target);
- if( sc && sc->data[SC_DEVOTION] && damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD )
+ if (sc && sc->data[SC_DEVOTION] && sc->data[SC_DEVOTION]->val1)
+ d_tbl = map->id2bl(sc->data[SC_DEVOTION]->val1);
+
+ if( d_tbl && check_distance_bl(target, d_tbl, sc->data[SC_DEVOTION]->val3) && damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD )
damage = 0;
if ( !battle_config.delay_battle_damage || amotion <= 1 ) {
@@ -279,7 +283,7 @@ int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct
dat->damage = damage;
dat->dmg_lv = dmg_lv;
dat->delay = ddelay;
- dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported.
+ dat->distance = distance_bl(src, target) + (battle_config.snap_dodge ? 10 : battle_config.area_size);
dat->additional_effects = additional_effects;
dat->src_type = src->type;
if (src->type != BL_PC && amotion > 1000)
@@ -500,8 +504,13 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u
int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2) {
int64 damage, batk;
struct status_data *st = status->get_status_data(src);
-
- batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, status->get_sc(src), st->batk, false), nk, n_ele, ELE_NEUTRAL, ELE_NEUTRAL, false, flag);
+ struct status_change *sc = status->get_sc(src);
+
+ // Property from mild wind bypasses it
+ if (sc && sc->data[SC_TK_SEVENWIND])
+ batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, sc, st->batk, false), nk, n_ele, s_ele, s_ele_, false, flag);
+ else
+ batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, sc, st->batk, false), nk, n_ele, ELE_NEUTRAL, ELE_NEUTRAL, false, flag);
if( type == EQI_HAND_L )
damage = batk + 3 * battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->lhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2) / 4;
@@ -771,18 +780,18 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target,
if(sc->data[SC_IMPOSITIO])
damage += sc->data[SC_IMPOSITIO]->val2;
if(sc->data[SC_DRUMBATTLE]){
- if(tstatus->size == SZ_MEDIUM)
+ if(tstatus->size == SZ_SMALL)
damage += sc->data[SC_DRUMBATTLE]->val2;
- else if(tstatus->size == SZ_SMALL)
+ else if(tstatus->size == SZ_MEDIUM)
damage += 10 * sc->data[SC_DRUMBATTLE]->val1;
//else no bonus for large target
}
if(sc->data[SC_GS_MADNESSCANCEL])
damage += 100;
if(sc->data[SC_GS_GATLINGFEVER]){
- if(tstatus->size == SZ_MEDIUM)
+ if(tstatus->size == SZ_SMALL)
damage += 10 * sc->data[SC_GS_GATLINGFEVER]->val1;
- else if(tstatus->size == SZ_SMALL)
+ else if(tstatus->size == SZ_MEDIUM)
damage += -5 * sc->data[SC_GS_GATLINGFEVER]->val1;
else
damage += sc->data[SC_GS_GATLINGFEVER]->val1;
@@ -2197,17 +2206,17 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
case NC_VULCANARM:
skillratio = 70 * skill_lv + status_get_dex(src);
- RE_LVL_DMOD(100);
+ RE_LVL_DMOD(120);
break;
case NC_FLAMELAUNCHER:
case NC_COLDSLOWER:
- skillratio += 200 + 100 * skill_lv + status_get_str(src);
- RE_LVL_DMOD(100);
+ skillratio += 200 + 300 * skill_lv;
+ RE_LVL_DMOD(150);
break;
case NC_ARMSCANNON:
switch( tst->size ) {
- case SZ_MEDIUM: skillratio = 300 + 350 * skill_lv; break; // Medium
- case SZ_SMALL: skillratio = 300 + 400 * skill_lv; break; // Small
+ case SZ_SMALL: skillratio = 300 + 350 * skill_lv; break; // Medium
+ case SZ_MEDIUM: skillratio = 300 + 400 * skill_lv; break; // Small
case SZ_BIG: skillratio = 300 + 300 * skill_lv; break; // Large
}
RE_LVL_DMOD(120);
@@ -2233,13 +2242,16 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio = skillratio * 75 / 100;
break;
case SC_FATALMENACE:
- skillratio = 100 * (skill_lv+1) * status->get_lv(src) / 100;
+ skillratio = 100 * (skill_lv+1);
+ RE_LVL_DMOD(100);
break;
case SC_TRIANGLESHOT:
- skillratio = ( 300 + (skill_lv-1) * status_get_agi(src)/2 ) * status->get_lv(src) / 120;
+ skillratio = ( 300 + (skill_lv-1) * status_get_agi(src)/2 );
+ RE_LVL_DMOD(120);
break;
case SC_FEINTBOMB:
- skillratio = (skill_lv+1) * (st->dex/2) * (sd?sd->status.job_level:50)/10 * status->get_lv(src) / 120;
+ skillratio = (skill_lv+1) * (st->dex/2) * (sd?sd->status.job_level:50)/10;
+ RE_LVL_DMOD(120);
break;
case LG_CANNONSPEAR:
skillratio = (50 + st->str) * skill_lv;
@@ -2283,15 +2295,15 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(100);
break;
case LG_OVERBRAND:
- skillratio += -100 + 50 * (((sd) ? pc->checkskill(sd,CR_SPEARQUICKEN) : 1) + 8 * skill_lv);
- RE_LVL_DMOD(150);
+ skillratio += -100 + 400 * skill_lv + 50 * ((sd) ? pc->checkskill(sd,CR_SPEARQUICKEN) : 1);
+ RE_LVL_DMOD(100);
break;
case LG_OVERBRAND_BRANDISH:
skillratio += -100 + 300 * skill_lv + status_get_str(src) + status_get_dex(src);
- RE_LVL_DMOD(150);
+ RE_LVL_DMOD(100);
break;
case LG_OVERBRAND_PLUSATK:
- skillratio += -100 + 100 * skill_lv;
+ skillratio = 200 * skill_lv + rnd_value( 10, 100);
RE_LVL_DMOD(100);
break;
case LG_RAYOFGENESIS:
@@ -2307,7 +2319,14 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(100);
break;
case LG_HESPERUSLIT:
- skillratio += 120 * skill_lv - 100;
+ skillratio = 120 * skill_lv;
+ if( sc && sc->data[SC_BANDING] )
+ skillratio += 200 * sc->data[SC_BANDING]->val2;
+ if( sc && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 5 )
+ skillratio = skillratio * 150 / 100;
+ if( sc && sc->data[SC_INSPIRATION] )
+ skillratio += 600;
+ RE_LVL_DMOD(100);
break;
case SR_DRAGONCOMBO:
skillratio += 40 * skill_lv;
@@ -2692,22 +2711,11 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
d->dmg_lv = ATK_BLOCK;
return 0;
}
- if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2 )
- {
+ if ((sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2) {
int delay;
- struct block_list *d_bl;
- struct status_change_entry *sce_d;
- bool devoted = false;
-
- if ((sce_d = sc->data[SC_DEVOTION]) && (d_bl = map->id2bl(sce_d->val1)) &&
- ((d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id) || //
- (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce_d->val2] == bl->id))) {
- // if player is target of devotion, show guard effect on the devotion caster rather than the target
- devoted = true;
- clif->skill_nodamage(d_bl, d_bl, CR_AUTOGUARD, sce->val1, 1);
- } else
- clif->skill_nodamage(bl, bl, CR_AUTOGUARD,sce->val1, 1);
-
+ struct block_list *d_bl = NULL;
+ struct status_change_entry *sce_d = sc->data[SC_DEVOTION];
+
// different delay depending on skill level [celest]
if (sce->val1 <= 5)
delay = 300;
@@ -2716,12 +2724,30 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
else
delay = 100;
- unit->set_walkdelay((devoted ? d_bl : bl), timer->gettick(), delay, 1);
+ if (sce_d) {
+ // If the target is too far away from the devotion caster, autoguard has no effect
+ // Autoguard will be disabled later on
+ if ((d_bl = map->id2bl(sce_d->val1)) && check_distance_bl(bl, d_bl, sce_d->val3)
+ && ((d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id)
+ || (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce_d->val2] == bl->id))
+ ) {
+ // if player is target of devotion, show guard effect on the devotion caster rather than the target
+ clif->skill_nodamage(d_bl, d_bl, CR_AUTOGUARD, sce->val1, 1);
+ unit->set_walkdelay(d_bl, timer->gettick(), delay, 1);
- if(sc->data[SC_CR_SHRINK] && rnd()%100<5*sce->val1)
- skill->blown(bl,src,skill->get_blewcount(CR_SHRINK,1),-1,0);
- d->dmg_lv = ATK_MISS;
- return 0;
+ d->dmg_lv = ATK_MISS;
+ return 0;
+ }
+ } else {
+ clif->skill_nodamage(bl, bl, CR_AUTOGUARD, sce->val1, 1);
+ unit->set_walkdelay(bl, timer->gettick(), delay, 1);
+
+ if(sc->data[SC_CR_SHRINK] && rnd()%100<5*sce->val1)
+ skill->blown(bl,src,skill->get_blewcount(CR_SHRINK,1),-1,0);
+
+ d->dmg_lv = ATK_MISS;
+ return 0;
+ }
}
if( (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 ) {
@@ -2798,7 +2824,11 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
}
//Now damage increasing effects
- if( sc->data[SC_LEXAETERNA] && skill_id != PF_SOULBURN )
+ if( sc->data[SC_LEXAETERNA] && skill_id != PF_SOULBURN
+#ifdef RENEWAL
+ && skill_id != CR_ACIDDEMONSTRATION && skill_id != ASC_BREAKER
+#endif
+ )
{
if( src->type != BL_MER || skill_id == 0 )
damage <<= 1; // Lex Aeterna only doubles damage of regular attacks from mercenaries
@@ -3763,6 +3793,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage >>= 1;
}
md.damage -= totaldef;
+ if( tsc && tsc->data[SC_LEXAETERNA] ) {
+ md.damage <<= 1;
+ status_change_end(target, SC_LEXAETERNA, INVALID_TIMER);
+ }
}
#else
// updated the formula based on a Japanese formula found to be exact [Reddozen]
@@ -3817,6 +3851,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
ratio >>= 1;
md.damage = (matk + atk) * ratio / 100;
md.damage -= totaldef;
+ if( tsc && tsc->data[SC_LEXAETERNA] ) {
+ md.damage <<= 1;
+ status_change_end(target, SC_LEXAETERNA, INVALID_TIMER);
+ }
#endif
}
break;
@@ -3879,7 +3917,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage = 100 + 200 * skill_lv + sstatus->int_;
break;
case GN_HELLS_PLANT_ATK:
- md.damage = skill_lv * status->get_lv(src) * 10 + sstatus->int_ * 7 / 2 * (18 + (sd ? sd->status.job_level : 0) / 4) * (5 / (10 - (sd ? pc->checkskill(sd, AM_CANNIBALIZE) : 0)));
+ md.damage = skill_lv * status->get_lv(target) * 10 + sstatus->int_ * 7 / 2 * (18 + (sd ? sd->status.job_level : 0) / 4) * (5 / (10 - (sd ? pc->checkskill(sd, AM_CANNIBALIZE) : 0)));
md.damage = md.damage*(1000 + tstatus->mdef) / (1000 + tstatus->mdef * 10) - tstatus->mdef2;
break;
case KO_HAPPOKUNAI:
@@ -4177,6 +4215,12 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
case LK_SPIRALPIERCE:
if (!sd) wd.flag=(wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC;
break;
+
+ //When in banding, the number of hits is equal to the number of Royal Guards in banding.
+ case LG_HESPERUSLIT:
+ if( sc && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 3 )
+ wd.div_ = sc->data[SC_BANDING]->val2;
+ break;
case MO_INVESTIGATE:
flag.pdef = flag.pdef2 = 2;
@@ -4228,6 +4272,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
case LK_SPIRALPIERCE:
if (!sd) n_ele = false; //forced neutral for monsters
break;
+ case LG_HESPERUSLIT:
+ if ( sc && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 == 5 )
+ s_ele = ELE_HOLY; // Banding with 5 RGs: change atk element to Holy.
+ break;
}
if (!(nk & NK_NO_ELEFIX) && !n_ele)
@@ -4533,13 +4581,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADD(-totaldef);
if( is_boss(target) )
ATK_RATE(50);
- RE_SKILL_REDUCTION();
}
break;
case NJ_SYURIKEN: // [malufett]
GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) );
wd.damage += battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon) - status->get_total_def(target);
- RE_SKILL_REDUCTION();
break;
case MO_EXTREMITYFIST: // [malufett]
{
@@ -4549,7 +4595,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.damage = (250 + 150 * skill_lv) + (10 * (status_get_sp(src)+1) * wd.damage / 100) + (8 * wd.damage);
ATK_ADD(-totaldef);
}
- RE_SKILL_REDUCTION();
}
#endif
break;
@@ -4571,10 +4616,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
i*=i;
ATK_ADD(i); //Add str bonus.
switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection?
- case SZ_MEDIUM: //Medium: 125%
+ case SZ_SMALL: //Small: 125%
ATK_RATE(125);
break;
- //case SZ_SMALL: //Medium: 100%
+ //case SZ_MEDIUM: //Medium: 100%
case SZ_BIG: //Large: 75%
ATK_RATE(75);
break;
@@ -4688,9 +4733,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
#endif
switch(skill_id){
case SR_GATEOFHELL:
- #ifdef RENEWAL
- RE_SKILL_REDUCTION();
- #endif // RENEWAL
if (wd.dmg_lv != ATK_FLEE)
ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
else
@@ -4713,7 +4755,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADD(sd->inventory_data[index]->weight * 7 / 100);
switch (tstatus->size) {
- case SZ_MEDIUM: //Medium: 115%
+ case SZ_SMALL: //Small: 115%
ATK_RATE(115);
break;
case SZ_BIG: //Large: 85%
@@ -5063,7 +5105,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
#endif
-#ifndef RENEWAL
if (sd) {
if (skill_id != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus.
ATK_ADD2(wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star);
@@ -5085,11 +5126,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADD(10*sd->status.inventory[index].refine);
}
}
+
//Card Fix, tsd side
if(tsd){ //if player on player then it was already measured above
wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, (flag.lh?1:0), wd.flag);
}
-#endif
if( flag.infdef ) { //Plants receive 1 damage when hit
short class_ = status->get_class(target);
if( flag.hit || wd.damage > 0 )
@@ -5357,8 +5398,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st
sc = NULL;
if( sc ) {
- if (sc->data[SC_DEVOTION] && !(wd->flag & BF_SKILL))
- return; // No reflect for basic attacks on devoted characters
+
if (wd->flag & BF_SHORT && !(skill->get_inf(skill_id) & (INF_GROUND_SKILL | INF_SELF_SKILL))) {
if( sc->data[SC_CRESCENTELBOW] && !is_boss(src) && rnd()%100 < sc->data[SC_CRESCENTELBOW]->val2 ){
@@ -5425,9 +5465,18 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st
if( wd->dmg_lv >= ATK_BLOCK ) {/* yes block still applies, somehow gravity thinks it makes sense. */
if( sc ) {
- if( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) {
- NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100);
+ struct status_change_entry *sce_d = sc->data[SC_DEVOTION];
+ struct block_list *d_bl = NULL;
+
+ if (sce_d && sce_d->val1)
+ d_bl = map->id2bl(sce_d->val1);
+
+ if( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION && skill_id != GS_DESPERADO
+ && !(d_bl && !(wd->flag&BF_SKILL)) // It should not be a basic attack if the target is under devotion
+ && !(d_bl && sce_d && !check_distance_bl(target, d_bl, sce_d->val3)) // It should not be out of range if the target is under devotion
+ ) {
+ NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100);
#ifndef RENEWAL
rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
#else
@@ -6734,6 +6783,7 @@ static const struct battle_data {
{ "mail_show_status", &battle_config.mail_show_status, 0, 0, 2, },
{ "client_limit_unit_lv", &battle_config.client_limit_unit_lv, 0, 0, BL_ALL, },
{ "client_emblem_max_blank_percent", &battle_config.client_emblem_max_blank_percent, 100, 0, 100, },
+
// BattleGround Settings
{ "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, },
{ "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, },
@@ -6774,6 +6824,8 @@ static const struct battle_data {
{ "case_sensitive_aegisnames", &battle_config.case_sensitive_aegisnames, 1, 0, 1, },
{ "guild_castle_invite", &battle_config.guild_castle_invite, 0, 0, 1, },
{ "guild_castle_expulsion", &battle_config.guild_castle_expulsion, 0, 0, 1, },
+ { "song_timer_reset", &battle_config.song_timer_reset, 0, 0, 1, },
+ { "snap_dodge", &battle_config.snap_dodge, 0, 0, 1, },
};
#ifndef STATS_OPT_OUT
/**
diff --git a/src/map/battle.h b/src/map/battle.h
index 8d1a3cd39..734a6187d 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -474,6 +474,9 @@ struct Battle_Config {
int case_sensitive_aegisnames;
int guild_castle_invite;
int guild_castle_expulsion;
+
+ int song_timer_reset; // [csnv]
+ int snap_dodge; // Enable or disable dodging damage snapping away [csnv]
};
extern struct Battle_Config battle_config;
diff --git a/src/map/chrif.c b/src/map/chrif.c
index ebdace226..34e92bee0 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -1178,7 +1178,8 @@ bool chrif_load_scdata(int fd) {
for (i = 0; i < count; i++) {
data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data));
- status->change_start(NULL, &sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 7);
+ status->change_start(NULL, &sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4,
+ data->tick, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_LOADED|SCFLAG_FIXEDRATE);
}
pc->scdata_received(sd);
diff --git a/src/map/clif.c b/src/map/clif.c
index d9acf0792..308f419a7 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -1348,7 +1348,7 @@ bool clif_spawn(struct block_list *bl)
clif->spiritball(&sd->bl);
if(sd->state.size==SZ_BIG) // tiny/big players [Valaris]
clif->specialeffect(bl,423,AREA);
- else if(sd->state.size==SZ_SMALL)
+ else if(sd->state.size==SZ_MEDIUM)
clif->specialeffect(bl,421,AREA);
if( sd->bg_id && map->list[sd->bl.m].flag.battleground )
clif->sendbgemblem_area(sd);
@@ -1368,7 +1368,7 @@ bool clif_spawn(struct block_list *bl)
TBL_MOB *md = ((TBL_MOB*)bl);
if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris]
clif->specialeffect(&md->bl,423,AREA);
- else if(md->special_state.size==SZ_SMALL)
+ else if(md->special_state.size==SZ_MEDIUM)
clif->specialeffect(&md->bl,421,AREA);
}
break;
@@ -1377,7 +1377,7 @@ bool clif_spawn(struct block_list *bl)
TBL_NPC *nd = ((TBL_NPC*)bl);
if( nd->size == SZ_BIG )
clif->specialeffect(&nd->bl,423,AREA);
- else if( nd->size == SZ_SMALL )
+ else if( nd->size == SZ_MEDIUM )
clif->specialeffect(&nd->bl,421,AREA);
}
break;
@@ -1585,7 +1585,7 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u
// clif_movepc(sd);
if(sd->state.size==SZ_BIG) // tiny/big players [Valaris]
clif->specialeffect(&sd->bl,423,AREA);
- else if(sd->state.size==SZ_SMALL)
+ else if(sd->state.size==SZ_MEDIUM)
clif->specialeffect(&sd->bl,421,AREA);
}
break;
@@ -1594,7 +1594,7 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u
TBL_MOB *md = ((TBL_MOB*)bl);
if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris]
clif->specialeffect(&md->bl,423,AREA);
- else if(md->special_state.size==SZ_SMALL)
+ else if(md->special_state.size==SZ_MEDIUM)
clif->specialeffect(&md->bl,421,AREA);
}
break;
@@ -4326,7 +4326,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
clif->getareachar_pc(sd, tsd);
if(tsd->state.size==SZ_BIG) // tiny/big players [Valaris]
clif->specialeffect_single(bl,423,sd->fd);
- else if(tsd->state.size==SZ_SMALL)
+ else if(tsd->state.size==SZ_MEDIUM)
clif->specialeffect_single(bl,421,sd->fd);
if( tsd->bg_id && map->list[tsd->bl.m].flag.battleground )
clif->sendbgemblem_single(sd->fd,tsd);
@@ -4345,7 +4345,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
clif->dispchat((struct chat_data*)map->id2bl(nd->chat_id),sd->fd);
if( nd->size == SZ_BIG )
clif->specialeffect_single(bl,423,sd->fd);
- else if( nd->size == SZ_SMALL )
+ else if( nd->size == SZ_MEDIUM )
clif->specialeffect_single(bl,421,sd->fd);
}
break;
@@ -4354,7 +4354,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
TBL_MOB* md = (TBL_MOB*)bl;
if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris]
clif->specialeffect_single(bl,423,sd->fd);
- else if(md->special_state.size==SZ_SMALL)
+ else if(md->special_state.size==SZ_MEDIUM)
clif->specialeffect_single(bl,421,sd->fd);
#if PACKETVER >= 20120404
if( !(md->status.mode&MD_BOSS) ){
@@ -10173,6 +10173,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
if (sd->sc.count && (
sd->sc.data[SC_DANCING] ||
+ sd->sc.data[SC_ANKLESNARE] ||
(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF)
)) //No sitting during these states either.
break;
diff --git a/src/map/homunculus.c b/src/map/homunculus.c
index 0f76fcf5f..f4ffc62a6 100644
--- a/src/map/homunculus.c
+++ b/src/map/homunculus.c
@@ -1126,7 +1126,7 @@ bool homunculus_read_db_sub(char* str[], int columns, int current) {
void homunculus_read_db(void) {
int i;
- const char *filename[]={"homunculus_db.txt","homunculus_db2.txt"};
+ const char *filename[]={DBPATH"homunculus_db.txt","homunculus_db2.txt"};
memset(homun->db,0,sizeof(homun->db));
for(i = 0; i<ARRAYLENGTH(filename); i++) {
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index 80bcfdf05..a1503e97a 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -362,7 +362,7 @@ int mercenary_killbonus(struct mercenary_data *md)
const enum sc_type scs[] = { SC_MER_FLEE, SC_MER_ATK, SC_MER_HP, SC_MER_SP, SC_MER_HIT };
int index = rnd() % ARRAYLENGTH(scs);
- sc_start(NULL,&md->bl, scs[index], 100, rnd() % 5, 600000);
+ sc_start(NULL,&md->bl, scs[index], 100, rnd() % 5, 600000);
return 0;
}
diff --git a/src/map/mob.c b/src/map/mob.c
index 3f1769d37..ffab804a6 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -418,7 +418,8 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) {
return true;
} while(0);
- status->change_start(NULL, target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks, sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, 0);
+ status->change_start(NULL, target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks,
+ sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, SCFLAG_NONE);
return false;
}
@@ -2203,7 +2204,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
// change experience for different sized monsters [Valaris]
if (battle_config.mob_size_influence) {
switch( md->special_state.size ) {
- case SZ_SMALL:
+ case SZ_MEDIUM:
per /= 2.;
break;
case SZ_BIG:
@@ -2324,7 +2325,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
// change drops depending on monsters size [Valaris]
if (battle_config.mob_size_influence)
{
- if (md->special_state.size == SZ_SMALL && drop_rate >= 2)
+ if (md->special_state.size == SZ_MEDIUM && drop_rate >= 2)
drop_rate /= 2;
else if( md->special_state.size == SZ_BIG)
drop_rate *= 2;
@@ -3508,7 +3509,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
sd->fd = fd;
//Finally, spawn it.
- md = mob->once_spawn_sub(&sd->bl, m, x, y, "--en--", class_, event, SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, m, x, y, "--en--", class_, event, SZ_SMALL, AI_NONE);
if (!md) return 0; //Failed?
md->special_state.clone = 1;
diff --git a/src/map/mob.h b/src/map/mob.h
index c8d43dbb2..728f3d81c 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -62,8 +62,8 @@ enum MobDamageLogFlag
};
enum size {
- SZ_MEDIUM = 0,
- SZ_SMALL,
+ SZ_SMALL = 0,
+ SZ_MEDIUM,
SZ_BIG,
};
diff --git a/src/map/npc.c b/src/map/npc.c
index f1c6f4fbd..f4f20a60d 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -3447,7 +3447,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
// w4=<mob id>,<amount>,<delay1>,<delay2>,<event>{,<mob size>,<mob ai>}
if( sscanf(w1, "%31[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 3
|| sscanf(w3, "%23[^,],%d", mobname, &mob_lv) < 1
- || sscanf(w4, "%d,%d,%u,%u,%127[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 2
+ || sscanf(w4, "%d,%d,%u,%u,%50[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 2
) {
ShowError("npc_parse_mob: Invalid mob definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
if (retval) *retval = EXIT_FAILURE;
diff --git a/src/map/pc.c b/src/map/pc.c
index 2372d3105..25a15ce84 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -262,9 +262,6 @@ int pc_check_banding( struct block_list *bl, va_list ap ) {
sc = status->get_sc(bl);
- if( bl == src )
- return 0;
-
if( sc && sc->data[SC_BANDING] )
{
b_sd[(*c)++] = tsd->bl.id;
diff --git a/src/map/script.c b/src/map/script.c
index 26072cf66..3b5264de9 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -7407,6 +7407,49 @@ BUILDIN(getguildmasterid)
}
/*==========================================
+ * Get the information of the members of a guild by type.
+ * getguildmember <guild_id>{,<type>};
+ * @param guild_id: ID of guild
+ * @param type:
+ * 0 : name (default)
+ * 1 : character ID
+ * 2 : account ID
+ *------------------------------------------*/
+BUILDIN(getguildmember)
+{
+ struct guild *g = NULL;
+ int j = 0;
+
+ g = guild->search(script_getnum(st,2));
+
+ if (g) {
+ int i, type = 0;
+
+ if (script_hasdata(st,3))
+ type = script_getnum(st,3);
+
+ for ( i = 0; i < MAX_GUILD; i++ ) {
+ if ( g->member[i].account_id ) {
+ switch (type) {
+ case 2:
+ mapreg->setreg(reference_uid(script->add_str("$@guildmemberaid"), j),g->member[i].account_id);
+ break;
+ case 1:
+ mapreg->setreg(reference_uid(script->add_str("$@guildmembercid"), j), g->member[i].char_id);
+ break;
+ default:
+ mapreg->setregstr(reference_uid(script->add_str("$@guildmembername$"), j), g->member[i].name);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ mapreg->setreg(script->add_str("$@guildmembercount"), j);
+ return true;
+}
+
+/*==========================================
* Get char string information by type :
* Return by @type :
* 0 : char_name
@@ -9029,7 +9072,7 @@ BUILDIN(monster)
int class_ = script_getnum(st,6);
int amount = script_getnum(st,7);
const char *event = "";
- unsigned int size = SZ_MEDIUM;
+ unsigned int size = SZ_SMALL;
unsigned int ai = AI_NONE;
int mob_id;
@@ -9138,7 +9181,7 @@ BUILDIN(areamonster) {
int class_ = script_getnum(st,8);
int amount = script_getnum(st,9);
const char *event = "";
- unsigned int size = SZ_MEDIUM;
+ unsigned int size = SZ_SMALL;
unsigned int ai = AI_NONE;
int mob_id;
@@ -10044,14 +10087,9 @@ BUILDIN(hideonnpc)
* sc_start <effect_id>,<duration>,<val1>{,<rate>,<flag>,{<unit_id>}};
* sc_start2 <effect_id>,<duration>,<val1>,<val2>{,<rate,<flag>,{<unit_id>}};
* sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<rate,<flag>,{<unit_id>}};
- * <flag>
- * &1: Cannot be avoided (it has to start)
- * &2: Tick should not be reduced (by vit, luk, lv, etc)
- * &4: sc_data loaded, no value has to be altered.
- * &8: rate should not be reduced
+ * <flag>: @see enum scstart_flag
*/
-BUILDIN(sc_start)
-{
+BUILDIN(sc_start) {
TBL_NPC * nd = map->id2nd(st->oid);
struct block_list* bl;
enum sc_type type;
@@ -10070,11 +10108,11 @@ BUILDIN(sc_start)
tick = script_getnum(st,3);
val1 = script_getnum(st,4);
- //If from NPC we make default flag 1 to be unavoidable
+ //If from NPC we make default flag SCFLAG_NOAVOID to be unavoidable
if(nd && nd->bl.id == npc->fake_nd->bl.id)
- flag = script_hasdata(st,5+start_type)?script_getnum(st,5+start_type):2;
+ flag = script_hasdata(st,5+start_type) ? script_getnum(st,5+start_type) : SCFLAG_FIXEDTICK;
else
- flag = script_hasdata(st,5+start_type)?script_getnum(st,5+start_type):1;
+ flag = script_hasdata(st,5+start_type) ? script_getnum(st,5+start_type) : SCFLAG_NOAVOID;
rate = script_hasdata(st,4+start_type)?min(script_getnum(st,4+start_type),10000):10000;
@@ -10177,7 +10215,7 @@ BUILDIN(getscrate) {
bl = map->id2bl(st->rid);
if (bl)
- rate = status->get_sc_def(bl, bl, (sc_type)type, 10000, 10000, 0);
+ rate = status->get_sc_def(bl, bl, (sc_type)type, 10000, 10000, SCFLAG_NONE);
script_pushint(st,rate);
return true;
@@ -13458,7 +13496,7 @@ BUILDIN(summon)
clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick);
- md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, class_, event, SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, class_, event, SZ_SMALL, AI_NONE);
if (md) {
md->master_id=sd->bl.id;
md->special_state.ai = AI_ATTACK;
@@ -16020,7 +16058,7 @@ BUILDIN(mercenary_sc_start) {
tick = script_getnum(st,3);
val1 = script_getnum(st,4);
- status->change_start(NULL, &sd->md->bl, type, 10000, val1, 0, 0, 0, tick, 2);
+ status->change_start(NULL, &sd->md->bl, type, 10000, val1, 0, 0, 0, tick, SCFLAG_FIXEDTICK);
return true;
}
@@ -18800,6 +18838,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getguildname,"i"),
BUILDIN_DEF(getguildmaster,"i"),
BUILDIN_DEF(getguildmasterid,"i"),
+ BUILDIN_DEF(getguildmember,"i?"),
BUILDIN_DEF(strcharinfo,"i"),
BUILDIN_DEF(strnpcinfo,"i"),
BUILDIN_DEF(getequipid,"i"),
@@ -19282,6 +19321,7 @@ void script_hardcoded_constants(void) {
script->set_constant("MAX_ZENY",MAX_ZENY,false);
script->set_constant("MAX_BG_MEMBERS",MAX_BG_MEMBERS,false);
script->set_constant("MAX_CHAT_USERS",MAX_CHAT_USERS,false);
+ script->set_constant("MAX_REFINE",MAX_REFINE,false);
/* status options */
script->set_constant("Option_Nothing",OPTION_NOTHING,false);
diff --git a/src/map/skill.c b/src/map/skill.c
index 9f008d65b..393c88df2 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -433,16 +433,12 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b
return 0;
// Couldn't preserve 3rd Class skills except only when using Reproduce skill. [Jobbie]
- if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= SR_RIDEINLIGHTNING) || (skill_id >= KO_YAMIKUMO && skill_id <= OB_AKAITSUKI)))
+ if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= LG_OVERBRAND_PLUSATK) || (skill_id >= RL_GLITTERING_GREED && skill_id <= OB_AKAITSUKI) || (skill_id >= GC_DARKCROW && skill_id <= NC_MAGMA_ERUPTION_DOTDAMAGE)))
return 0;
// Reproduce will only copy skills according on the list. [Jobbie]
else if( sd->sc.data[SC__REPRODUCE] && !skill->reproduce_db[skill->get_index(skill_id)] )
return 0;
- //Never copy new 3rd class skills By OmegaRed
- if(skill_id >= GC_DARKCROW && skill_id <= ALL_FULL_THROTTLE)
- return 0;
-
return 1;
}
@@ -695,10 +691,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
temp = skill->get_time2(status->sc2skill(type),7);
if (sd->addeff[i].flag&ATF_TARGET)
- status->change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,0);
+ status->change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,SCFLAG_NONE);
if (sd->addeff[i].flag&ATF_SELF)
- status->change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,0);
+ status->change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,SCFLAG_NONE);
}
}
@@ -713,9 +709,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
temp = skill->get_time2(status->sc2skill(type),7);
if( sd->addeff3[i].target&ATF_TARGET )
- status->change_start(src,bl,type,sd->addeff3[i].rate,7,0,0,0,temp,0);
+ status->change_start(src,bl,type,sd->addeff3[i].rate,7,0,0,0,temp,SCFLAG_NONE);
if( sd->addeff3[i].target&ATF_SELF )
- status->change_start(src,src,type,sd->addeff3[i].rate,7,0,0,0,temp,0);
+ status->change_start(src,src,type,sd->addeff3[i].rate,7,0,0,0,temp,SCFLAG_NONE);
}
}
}
@@ -782,7 +778,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
// Enchant Poison gives a chance to poison attacked enemies
if((sce=sc->data[SC_ENCHANTPOISON])) //Don't use sc_start since chance comes in 1/10000 rate.
status->change_start(src,bl,SC_POISON,sce->val2, sce->val1,src->id,0,0,
- skill->get_time2(AS_ENCHANTPOISON,sce->val1),0);
+ skill->get_time2(AS_ENCHANTPOISON,sce->val1),SCFLAG_NONE);
// Enchant Deadly Poison gives a chance to deadly poison attacked enemies
if((sce=sc->data[SC_EDP]))
sc_start4(src,bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0,
@@ -794,7 +790,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
case SM_BASH:
if( sd && skill_lv > 5 && pc->checkskill(sd,SM_FATALBLOW)>0 )
status->change_start(src,bl,SC_STUN,500*(skill_lv-5)*sd->status.base_level/50,
- skill_lv,0,0,0,skill->get_time2(SM_FATALBLOW,skill_lv),0);
+ skill_lv,0,0,0,skill->get_time2(SM_FATALBLOW,skill_lv),SCFLAG_NONE);
break;
case MER_CRASH:
@@ -842,9 +838,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
#ifdef RENEWAL
sc_start(src,bl,SC_FREEZE,65-(5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
#else
- // [Tharis] pointed out that this is normal freeze chance with a base of 300%
+ //On third hit, there is a 150% to freeze the target
if(tsc->sg_counter >= 3 &&
- sc_start(src,bl,SC_FREEZE,300,skill_lv,skill->get_time2(skill_id,skill_lv)))
+ sc_start(src,bl,SC_FREEZE,150,skill_lv,skill->get_time2(skill_id,skill_lv)))
tsc->sg_counter = 0;
/**
* being it only resets on success it'd keep stacking and eventually overflowing on mvps, so we reset at a high value
@@ -1010,7 +1006,8 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
case LK_SPIRALPIERCE:
case ML_SPIRALPIERCE:
- sc_start(src,bl,SC_ANKLESNARE,100,0,skill->get_time2(skill_id,skill_lv));
+ if( dstsd || ( dstmd && !is_boss(bl) ) ) //Does not work on bosses
+ sc_start(src,bl,SC_STOP,100,0,skill_get_time2(skill_id,skill_lv));
break;
case ST_REJECTSWORD:
@@ -1082,7 +1079,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break;
case GS_BULLSEYE: //0.1% coma rate.
if(tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN)
- status->change_start(src,bl,SC_COMA,10,skill_lv,0,src->id,0,0,0);
+ status->change_start(src,bl,SC_COMA,10,skill_lv,0,src->id,0,0,SCFLAG_NONE);
break;
case GS_PIERCINGSHOT:
sc_start2(src,bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
@@ -1192,7 +1189,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break;
case NC_POWERSWING:
// Use flag=2, the stun duration is not vit-reduced.
- status->change_start(src, bl, SC_STUN, 5*skill_lv*100, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 2);
+ status->change_start(src, bl, SC_STUN, 5*skill_lv*100, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), SCFLAG_FIXEDTICK);
if( rnd()%100 < 5*skill_lv )
skill->castend_damage_id(src, bl, NC_AXEBOOMERANG, pc->checkskill(sd, NC_AXEBOOMERANG), tick, 1);
break;
@@ -1210,6 +1207,14 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
rate = 30 + 8 * skill_lv + sstatus->dex / 10 + (sd? sd->status.job_level:0) / 4;
sc_start(src, bl, SC_STUN, rate, skill_lv, skill->get_time(skill_id,skill_lv));
break;
+ case LG_HESPERUSLIT:
+ if ( sc && sc->data[SC_BANDING] ) {
+ if ( sc->data[SC_BANDING]->val2 == 4 ) // 4 banding RGs: Targets will be stunned at 100% chance for 4 ~ 8 seconds, irreducible by STAT.
+ status->change_start(src, bl, SC_STUN, 10000, skill_lv, 0, 0, 0, 1000*(4+rand()%4), SCFLAG_FIXEDTICK);
+ else if ( sc->data[SC_BANDING]->val2 == 6 ) // 6 banding RGs: activate Pinpoint Attack Lv1-5
+ skill->castend_damage_id(src,bl,LG_PINPOINTATTACK,1+rand()%5,tick,0);
+ }
+ break;
case LG_PINPOINTATTACK:
rate = 30 + 5 * (sd ? pc->checkskill(sd,LG_PINPOINTATTACK) : 1) + (sstatus->agi + status->get_lv(src)) / 10;
switch( skill_lv ) {
@@ -1351,7 +1356,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
rate += sd->weapon_coma_race[tstatus->race];
rate += sd->weapon_coma_race[tstatus->mode&MD_BOSS?RC_BOSS:RC_NONBOSS];
if (rate)
- status->change_start(src, bl, SC_COMA, rate, 0, 0, src->id, 0, 0, 0);
+ status->change_start(src, bl, SC_COMA, rate, 0, 0, src->id, 0, 0, SCFLAG_NONE);
}
if( sd && battle_config.equip_self_break_rate )
{ // Self weapon breaking
@@ -1391,10 +1396,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
if (sd && !skill_id && bl->type == BL_PC) { // This effect does not work with skills.
if (sd->def_set_race[tstatus->race].rate)
status->change_start(src,bl, SC_DEFSET, sd->def_set_race[tstatus->race].rate, sd->def_set_race[tstatus->race].value,
- 0, 0, 0, sd->def_set_race[tstatus->race].tick, 2);
+ 0, 0, 0, sd->def_set_race[tstatus->race].tick, SCFLAG_FIXEDTICK);
if (sd->def_set_race[tstatus->race].rate)
status->change_start(src,bl, SC_MDEFSET, sd->mdef_set_race[tstatus->race].rate, sd->mdef_set_race[tstatus->race].value,
- 0, 0, 0, sd->mdef_set_race[tstatus->race].tick, 2);
+ 0, 0, 0, sd->mdef_set_race[tstatus->race].tick, SCFLAG_FIXEDTICK);
}
}
@@ -1667,6 +1672,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
int rate;
struct map_session_data *sd=NULL;
struct map_session_data *dstsd=NULL;
+ struct status_change *sc;
nullpo_ret(src);
nullpo_ret(bl);
@@ -1675,6 +1681,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
sd = BL_CAST(BL_PC, src);
dstsd = BL_CAST(BL_PC, bl);
+ sc = status->get_sc(src);
if(dstsd && attack_type&BF_WEAPON) {
//Counter effects.
@@ -1696,10 +1703,10 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
time = skill->get_time2(status->sc2skill(type),7);
if (dstsd->addeff2[i].flag&ATF_TARGET)
- status->change_start(bl,src,type,rate,7,0,0,0,time,0);
+ status->change_start(bl,src,type,rate,7,0,0,0,time,SCFLAG_NONE);
if (dstsd->addeff2[i].flag&ATF_SELF && !status->isdead(bl))
- status->change_start(bl,bl,type,rate,7,0,0,0,time,0);
+ status->change_start(bl,bl,type,rate,7,0,0,0,time,SCFLAG_NONE);
}
}
@@ -1723,6 +1730,13 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
case NPC_GRANDDARKNESS:
attack_type |= BF_WEAPON;
break;
+ case LG_HESPERUSLIT:
+ if ( sc && sc->data[SC_FORCEOFVANGUARD] && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 6 ) {
+ char i;
+ for( i = 0; i < sc->data[SC_FORCEOFVANGUARD]->val3 && sc->fv_counter <= sc->data[SC_FORCEOFVANGUARD]->val3 ; i++)
+ clif->millenniumshield(bl, sc->fv_counter++);
+ }
+ break;
}
if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
@@ -1754,15 +1768,12 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
if( attack_type&BF_MAGIC ) {
sp += sd->bonus.magic_sp_gain_value;
hp += sd->bonus.magic_hp_gain_value;
- if( skill_id == WZ_WATERBALL ) {// (bugreport:5303)
- struct status_change *sc = NULL;
- if( ( sc = status->get_sc(src) ) ) {
- if( sc->data[SC_SOULLINK]
- && sc->data[SC_SOULLINK]->val2 == SL_WIZARD
- && sc->data[SC_SOULLINK]->val3 == WZ_WATERBALL
- )
- sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check.
- }
+ if( skill_id == WZ_WATERBALL ) {// (bugreport:5303)
+ if( sc->data[SC_SOULLINK]
+ && sc->data[SC_SOULLINK]->val2 == SL_WIZARD
+ && sc->data[SC_SOULLINK]->val3 == WZ_WATERBALL
+ )
+ sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check.
}
}
if( hp || sp ) {
@@ -4068,7 +4079,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case SL_STIN:
case SL_STUN:
if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
- status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,2);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
@@ -4507,7 +4518,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
tsc->data[SC_MELODYOFSINK] || tsc->data[SC_BEYOND_OF_WARCRY] || tsc->data[SC_UNLIMITED_HUMMING_VOICE] ) &&
rnd()%100 < 4 * skill_lv + 2 * (sd ? pc->checkskill(sd,WM_LESSON) : 10) + 10 * battle->calc_chorusbonus(sd)) {
skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag);
- status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),0);
+ status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),SCFLAG_FIXEDRATE);
status_change_end(bl, SC_SWING, INVALID_TIMER);
status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
@@ -5184,7 +5195,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case RK_FIGHTINGSPIRIT:
case RK_ABUNDANCE:
if( sd && !pc->checkskill(sd, RK_RUNEMASTERY) ){
- if( status->change_start(src,&sd->bl, (sc_type)(rnd()%SC_CONFUSION), 1000, 1, 0, 0, 0, skill->get_time2(skill_id,skill_lv),0) ){
+ if( status->change_start(src,&sd->bl, (sc_type)(rnd()%SC_CONFUSION), 1000, 1, 0, 0, 0, skill->get_time2(skill_id,skill_lv),SCFLAG_FIXEDRATE) ){
skill->consume_requirement(sd,skill_id,skill_lv,2);
map->freeblock_unlock();
return 0;
@@ -5445,7 +5456,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case SA_SUMMONMONSTER:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if (sd) mob->once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_MEDIUM, AI_NONE);
+ if (sd) mob->once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_SMALL, AI_NONE);
break;
case SA_LEVELUP:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -6213,7 +6224,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
|| dstsd->status.char_id == sd->status.child
)
) {
- status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,0);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,SCFLAG_FIXEDRATE);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
@@ -6261,25 +6272,24 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case GC_CLOAKINGEXCEED:
case LG_FORCEOFVANGUARD:
case SC_REPRODUCE:
+ case RA_CAMOUFLAGE:
if (tsce) {
int failure = status_change_end(bl, type, INVALID_TIMER);
if( failure )
clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure);
else if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- if ( skill_id == LG_FORCEOFVANGUARD )
+ if ( skill_id == LG_FORCEOFVANGUARD || skill_id == RA_CAMOUFLAGE )
break;
map->freeblock_unlock();
return 0;
+ } else {
+ int failure = sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ if( failure )
+ clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure);
+ else if( sd )
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
}
- case RA_CAMOUFLAGE:
- {
- int failure = sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- if( failure )
- clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure);
- else if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- }
break;
case BD_ADAPTATION:
@@ -6360,7 +6370,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (tsc->data[SC_STONE]) {
status_change_end(bl, SC_STONE, INVALID_TIMER);
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
}
if (sc_start4(src,bl,SC_STONE,(skill_lv*4+20)+brate,
@@ -6417,7 +6427,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( battle->check_undead(tstatus->race,tstatus->def_ele) ) {
status->change_start(src, bl, SC_BLIND,
100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), 1,0,0,0,
- skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0);
+ skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,SCFLAG_NONE);
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
if(dstmd)
@@ -6732,7 +6742,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
sp += sp * i / 100;
}
} else {
- hp = (1 + rnd()%400) * (100 + skill_lv*10) / 100;
+ //Maybe replace with potion_hp, but I'm unsure how that works [Playtester]
+ switch (skill_lv) {
+ case 1: hp = 45; break;
+ case 2: hp = 105; break;
+ case 3: hp = 175; break;
+ default: hp = 325; break;
+ }
+ hp = (hp + rnd()%(skill_lv*20+1)) * (150 + skill_lv*10) / 100;
hp = hp * (100 + (tstatus->vit<<1)) / 100;
if( dstsd )
hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10) / 100;
@@ -7265,7 +7282,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
return 0;
}
else
- status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),0);
+ status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),SCFLAG_FIXEDRATE);
}
break;
@@ -7671,7 +7688,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (tsce) {
if(sd)
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,0);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,SCFLAG_FIXEDRATE);
status_change_end(bl, SC_SWOO, INVALID_TIMER);
break;
}
@@ -7679,7 +7696,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SL_SKE:
if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,2);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
@@ -8410,7 +8427,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( tsc && tsc->data[SC_STONE] )
status_change_end(bl,SC_STONE,INVALID_TIMER);
else
- status->change_start(src,bl,SC_STONE,10000,skill_lv,0,0,500,skill->get_time(skill_id, skill_lv),2);
+ status->change_start(src,bl,SC_STONE,10000,skill_lv,0,0,500,skill->get_time(skill_id, skill_lv),SCFLAG_FIXEDTICK);
} else {
int rate = 45 + 5 * skill_lv;
if( rnd()%100 < rate ){
@@ -8646,13 +8663,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
//If the target was successfully inflected with the Unlucky status, give 1 of 3 random status's.
switch(rnd()%3) {//Targets in the Unlucky status will be affected by one of the 3 random status's regardless of resistance.
case 0:
- status->change_start(src,bl,SC_POISON,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),2);
+ status->change_start(src,bl,SC_POISON,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
break;
case 1:
- status->change_start(src,bl,SC_SILENCE,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),2);
+ status->change_start(src,bl,SC_SILENCE,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
break;
case 2:
- status->change_start(src,bl,SC_BLIND,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),2);
+ status->change_start(src,bl,SC_BLIND,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
}
}
} else if( sd )
@@ -9410,7 +9427,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if(sd) {
struct mob_data *summon_md;
- summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), 2308, "", SZ_MEDIUM, AI_NONE);
+ summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), 2308, "", SZ_SMALL, AI_NONE);
if( summon_md ) {
summon_md->master_id = src->id;
summon_md->special_state.ai = AI_ZANZOU;
@@ -9445,10 +9462,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
&& rand()%100 < (10 * (5 * skill_lv - status_get_int(bl) / 2 + 45 + 5 * skill_lv))
) {
clif->skill_nodamage(src, bl, skill_id, skill_lv,
- status->change_start(src, bl, type, 10000, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 1));
+ status->change_start(src, bl, type, 10000, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), SCFLAG_NOAVOID));
status_zap(bl, tstatus->max_hp * skill_lv * 5 / 100 , 0);
if( status->get_lv(bl) <= status->get_lv(src) )
- status->change_start(src, bl, SC_COMA, skill_lv, skill_lv, 0, src->id, 0, 0, 0);
+ status->change_start(src, bl, SC_COMA, skill_lv, skill_lv, 0, src->id, 0, 0, SCFLAG_NONE);
} else if( sd )
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
break;
@@ -9547,8 +9564,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->battle_status, status->get_lv(&hd->bl));
status->heal(bl, heal, 0, 0);
clif->skill_nodamage(src, src, skill_id, skill_lv, clif->skill_nodamage(src, bl, AL_HEAL, heal, 1));
- status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2);
- status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2);
+ status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
+ status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
}
break;
@@ -9584,7 +9601,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
for(i=0; i<qty[skill_lv - 1]; i++){ //easy way
- summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), summons[skill_lv - 1], "", SZ_MEDIUM, AI_ATTACK);
+ summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK);
if (summon_md) {
summon_md->master_id = src->id;
if (summon_md->deletetimer != INVALID_TIMER)
@@ -9717,9 +9734,11 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) {
if( sd )
{
- if( ud->skill_id != AL_WARP && !skill->check_condition_castend(sd, ud->skill_id, ud->skill_lv) )
+ if( ud->skill_id != AL_WARP && !skill->check_condition_castend(sd, ud->skill_id, ud->skill_lv) ) {
+ if( ud->skill_id == SA_LANDPROTECTOR )
+ clif->skill_poseffect(&sd->bl,ud->skill_id,ud->skill_lv,sd->bl.x,sd->bl.y,tick);
break;
- else
+ }else
skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,1);
}
@@ -10268,7 +10287,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
struct mob_data *md;
// Correct info, don't change any of this! [Celest]
- md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_SMALL, AI_NONE);
if (md) {
md->master_id = src->id;
md->special_state.ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA;
@@ -10366,7 +10385,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
if (rnd()%100 < 50) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
} else {
- TBL_MOB* md = mob->once_spawn_sub(src, src->m, x, y, "--ja--",(skill_lv < 2 ? 1084+rnd()%2 : 1078+rnd()%6),"", SZ_MEDIUM, AI_NONE);
+ TBL_MOB* md = mob->once_spawn_sub(src, src->m, x, y, "--ja--",(skill_lv < 2 ? 1084+rnd()%2 : 1078+rnd()%6),"", SZ_SMALL, AI_NONE);
int i;
if (!md) break;
if ((i = skill->get_time(skill_id, skill_lv)) > 0)
@@ -10513,7 +10532,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
int class_ = 2042;
struct mob_data *md;
- md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_SMALL, AI_NONE);
if( md ) {
md->master_id = src->id;
md->special_state.ai = AI_FLORA;
@@ -11013,19 +11032,21 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
val1 = 15+skill_lv+(st->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed
val2 = 20+3*skill_lv+(st->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
+ val1 += (pc->checkskill(sd,DC_DANCINGLESSON) + 1) / 2;
+ val2 += (pc->checkskill(sd,DC_DANCINGLESSON) + 1) / 2;
}
break;
case BA_ASSASSINCROSS:
-#ifdef RENEWAL
- val1 = 10 + skill_lv + (st->agi/10); // ASPD increase
if(sd)
- val1 += 4*pc->checkskill(sd,BA_MUSICALLESSON);
+ val1 = (pc->checkskill(sd,BA_MUSICALLESSON) + 1) / 2;
+#ifdef RENEWAL
+ // This formula was taken from a RE calculator
+ // and the changes published on irowiki
+ // Luckily, official tests show it's the right one
+ val1 += skill_lv + (st->agi/20);
#else
- val1 = 100+(10*skill_lv)+(st->agi/10); // ASPD increase
- if(sd)
- val1 += 5*pc->checkskill(sd,BA_MUSICALLESSON);
+ val1 += 10 + skill_lv + (st->agi/10); // ASPD increase
+ val1 *= 10; // ASPD works with 1000 as 100%
#endif
break;
case DC_FORTUNEKISS:
@@ -11141,6 +11162,10 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
case SO_WARMER:
skill->clear_group(src, 8);
break;
+ case SO_VACUUM_EXTREME:
+ val1 = x;
+ val2 = y;
+ break;
case GN_WALLOFTHORN:
if( flag&1 )
limit = 3000;
@@ -11346,7 +11371,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
break;
} else if( sc && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) {
int sec = skill->get_time2(sg->skill_id,sg->skill_lv);
- if( status->change_start(ss, bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,0) ) {
+ if( status->change_start(ss, bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,SCFLAG_FIXEDRATE) ) {
const struct TimerData* td = sc->data[type]?timer->get(sc->data[type]->timer):NULL;
if( td )
sec = DIFF_TICK32(td->tick, tick);
@@ -11444,10 +11469,10 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if (!sce)
sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit);
break;
+ case UNT_APPLEIDUN:
case UNT_WHISTLE:
case UNT_ASSASSINCROSS:
case UNT_POEMBRAGI:
- case UNT_APPLEIDUN:
case UNT_HUMMING:
case UNT_DONTFORGETME:
case UNT_FORTUNEKISS:
@@ -11458,12 +11483,13 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if (!sc) return 0;
if (!sce)
sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit);
- else if (sce->val4 == 1) {
+ else if (battle_config.song_timer_reset && sce->val4 == 1) {
//Readjust timers since the effect will not last long.
sce->val4 = 0;
timer->delete(sce->timer, status->change_timer);
sce->timer = timer->add(tick+sg->limit, status->change_timer, bl->id, type);
}
+
break;
case UNT_FOGWALL:
@@ -11727,7 +11753,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_MANHOLE:
if( sg->val2 == 0 && tsc && (sg->unit_id == UNT_ANKLESNARE || bl->id != sg->src_id) ) {
int sec = skill->get_time2(sg->skill_id,sg->skill_lv);
- if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 0) ) {
+ if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, SCFLAG_FIXEDRATE) ) {
const struct TimerData* td = tsc->data[type]?timer->get(tsc->data[type]->timer):NULL;
if( td )
sec = DIFF_TICK32(td->tick, tick);
@@ -11757,7 +11783,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
if( bl->id != ss->id ) {
if( status_get_mode(bl)&MD_BOSS )
break;
- if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id, sg->skill_lv), 0) ) {
+ if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id, sg->skill_lv), SCFLAG_FIXEDRATE) ) {
map->moveblock(bl, src->bl.x, src->bl.y, tick);
clif->fixpos(bl);
@@ -11770,7 +11796,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_VENOMDUST:
if(tsc && !tsc->data[type])
- status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),0);
+ status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),SCFLAG_NONE);
break;
@@ -11839,16 +11865,16 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
if( md && md->class_ == MOBID_EMPERIUM )
break;
#endif
- if( sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER) )
- break; // affects self only when soullinked
+ if( (sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER))
+ || (!(battle_config.song_timer_reset) && tsc && tsc->data[type] && tsc->data[type]->val4 == 1))
+ break;
heal = skill->calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true);
if( tsc->data[SC_AKAITSUKI] && heal )
heal = ~heal + 1;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
status->heal(bl, heal, 0, 0);
- break;
}
-
+ break;
case UNT_TATAMIGAESHI:
case UNT_DEMONSTRATION:
skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
@@ -12117,12 +12143,12 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_CLOUD_KILL:
if(tsc && !tsc->data[type])
- status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),0);
+ status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),SCFLAG_FIXEDRATE);
skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
case UNT_WARMER:
- if( bl->type == BL_PC && !battle->check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON ) {
+ { // It has effect on everything, including monsters, undead property and demon
int hp = 0;
if( ssc && ssc->data[SC_HEATER_OPTION] )
hp = tstatus->max_hp * 3 * sg->skill_lv / 100;
@@ -12134,10 +12160,9 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
if( tsc && tsc->data[SC_AKAITSUKI] && hp )
hp = ~hp + 1;
status->heal(bl, hp, 0, 0);
- sc_start(ss, bl, SC_WARMER, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv));
+ sc_start(ss, bl, type, 100, sg->skill_lv, sg->interval + 100);
}
break;
-
case UNT_FIRE_INSIGNIA:
case UNT_WATER_INSIGNIA:
case UNT_WIND_INSIGNIA:
@@ -12163,11 +12188,16 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
break;
case UNT_VACUUM_EXTREME:
- if ( tsc && tsc->data[SC_HALLUCINATIONWALK] ) {
+ if (tsc && (tsc->data[SC_HALLUCINATIONWALK] || tsc->data[SC_VACUUM_EXTREME])) {
return 0;
} else {
sg->limit -= 100 * tstatus->str/20;
sc_start(ss, bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit);
+
+ if (unit->movepos(bl, sg->val1, sg->val2, 0, 0)) {
+ clif->slide(bl, sg->val1, sg->val2);
+ clif->fixpos(bl);
+ }
}
break;
@@ -12212,7 +12242,8 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_POISON_MIST:
skill->attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
- status->change_start(ss, bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill->get_time2(sg->skill_id, sg->skill_lv), 2);
+ status->change_start(ss, bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0,
+ skill->get_time2(sg->skill_id, sg->skill_lv), SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
break;
}
@@ -12245,10 +12276,8 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick)
switch(sg->unit_id){
case UNT_SAFETYWALL:
case UNT_PNEUMA:
- case UNT_EPICLESIS://Arch Bishop
case UNT_NEUTRALBARRIER:
case UNT_STEALTHFIELD:
- case UNT_WARMER:
if (sce)
status_change_end(bl, type, INVALID_TIMER);
break;
@@ -12273,6 +12302,16 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick)
}
}
break;
+ case UNT_WHISTLE:
+ case UNT_ASSASSINCROSS:
+ case UNT_POEMBRAGI:
+ case UNT_APPLEIDUN:
+ case UNT_HUMMING:
+ case UNT_DONTFORGETME:
+ case UNT_FORTUNEKISS:
+ case UNT_SERVICEFORYOU:
+ if (sg->src_id==bl->id && !(sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER))
+ return -1;
}
return sg->skill_id;
}
@@ -12350,7 +12389,7 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) {
case DC_DONTFORGETME:
case DC_FORTUNEKISS:
case DC_SERVICEFORYOU:
- if (sce) {
+ if ((battle_config.song_timer_reset && sce) || (!battle_config.song_timer_reset && sce && sce->val4 != 1)) {
timer->delete(sce->timer, status->change_timer);
//NOTE: It'd be nice if we could get the skill_lv for a more accurate extra time, but alas...
//not possible on our current implementation.
@@ -12413,8 +12452,8 @@ int skill_unit_effect(struct block_list* bl, va_list ap) {
} else {
if( flag&1 )
skill->unit_onplace(su,bl,tick);
- else
- skill->unit_onout(su,bl,tick);
+ else if (skill->unit_onout(su,bl,tick) == -1)
+ return 0; // Don't let a Bard/Dancer update their own song timer
if( flag&4 )
skill->unit_onleft(skill_id, bl, tick);
@@ -12794,6 +12833,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case RA_WUGSTRIKE:
// Other
case BS_GREED:
+ case ALL_FULL_THROTTLE:
break;
default: // in official there is no message.
return 0;
@@ -12803,12 +12843,26 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
// Check the skills that can be used whiled using mado
if( pc_ismadogear(sd) ) {
- if( !(skill_id > NC_MADOLICENCE && skill_id <= NC_DISJOINT)
- && skill_id != NC_MAGMA_ERUPTION
- && skill_id != BS_GREED ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR,0);
- return 0;
- }
+ switch ( skill_id ) {
+ case BS_GREED: case NC_BOOSTKNUCKLE:
+ case NC_PILEBUNKER: case NC_VULCANARM:
+ case NC_FLAMELAUNCHER: case NC_COLDSLOWER:
+ case NC_ARMSCANNON: case NC_ACCELERATION:
+ case NC_HOVERING: case NC_F_SIDESLIDE:
+ case NC_B_SIDESLIDE: case NC_SELFDESTRUCTION:
+ case NC_SHAPESHIFT: case NC_EMERGENCYCOOL:
+ case NC_INFRAREDSCAN: case NC_ANALYZE:
+ case NC_MAGNETICFIELD: case NC_NEUTRALBARRIER:
+ case NC_STEALTHFIELD: case NC_REPAIR:
+ case NC_AXEBOOMERANG: case NC_POWERSWING:
+ case NC_AXETORNADO: case NC_SILVERSNIPER:
+ case NC_MAGICDECOY: case NC_DISJOINT:
+ case NC_MAGMA_ERUPTION: case ALL_FULL_THROTTLE:
+ case NC_MAGMA_ERUPTION_DOTDAMAGE:
+ break;
+ default:
+ return 0;
+ }
}
if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL )
@@ -17154,7 +17208,7 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) {
class_ = (nameid == ITEMID_BOODY_RED || nameid == ITEMID_CRYSTAL_BLUE) ? 2043 + nameid - ITEMID_BOODY_RED : (nameid == ITEMID_WIND_OF_VERDURE) ? 2046 : 2045;
- md = mob->once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE);
if( md ) {
md->master_id = sd->bl.id;
md->special_state.ai = AI_FLORA;
diff --git a/src/map/status.c b/src/map/status.c
index 718deaefc..746ca51e2 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -677,7 +677,7 @@ void initChangeTables(void) {
set_sc_with_vfx( SO_DIAMONDDUST , SC_COLD , SI_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it.
set_sc( SO_CLOUD_KILL , SC_POISON , SI_CLOUDKILL , SCB_NONE );
set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI );
- set_sc( SO_WARMER , SC_WARMER , SI_WARMER , SCB_NONE );
+ add_sc( SO_WARMER , SC_WARMER ); // At the moment, no icon on officials
set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE );
set_sc( SO_ARRULLO , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE );
set_sc( SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SI_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
@@ -1004,6 +1004,7 @@ void initChangeTables(void) {
status->ChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN;
status->ChangeFlagTable[SC_DEFSET] |= SCB_DEF|SCB_DEF2;
status->ChangeFlagTable[SC_MDEFSET] |= SCB_MDEF|SCB_MDEF2;
+ status->ChangeFlagTable[SC_MYSTERIOUS_POWDER] |= SCB_MAXHP;
status->ChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED;
status->ChangeFlagTable[SC_WEDDING] = SCB_SPEED;
@@ -1789,17 +1790,10 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
//If targeting, cloak+hide protect you, otherwise only hiding does.
hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK);
- //You cannot hide from ground skills.
- if( skill->get_ele(skill_id,1) == ELE_EARTH ) //TODO: Need Skill Lv here :/
+ // There is no NF for ground skills, but every earth type skill out there
+ // affects hidding except Stone Curse
+ if( skill->get_ele(skill_id,1) == ELE_EARTH && skill_id != MG_STONECURSE)
hide_flag &= ~OPTION_HIDE;
- else {
- switch ( skill_id ) {
- case MO_ABSORBSPIRITS: // it works when already casted and target suddenly hides.
- case SA_DISPELL:
- hide_flag &= ~OPTION_HIDE;
- break;
- }
- }
switch( target->type ) {
case BL_PC: {
@@ -1810,6 +1804,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
return 0;
if( tsc ) {
if (tsc->option&hide_flag && !is_boss &&
+ !(flag&1 && skill->get_nk(skill_id)&NK_NO_DAMAGE) && // Buff/debuff skills that started casting before hiding still applies
((sd->special_state.perfect_hiding || !is_detect) ||
(tsc->data[SC_CLOAKINGEXCEED] && is_detect)))
return 0;
@@ -1974,6 +1969,10 @@ unsigned short status_base_atk(const struct block_list *bl, const struct status_
//Normally only players have base-atk, but homunc have a different batk
// equation, hinting that perhaps non-players should use this for batk.
// [Skotlex]
+#ifdef RENEWAL
+ if (bl->type == BL_HOM)
+ str = (int)(floor((rstr + dex + st->luk) / 3) + floor(((TBL_HOM*)bl)->homunculus.level / 10));
+#endif
dstr = str/10;
str += dstr*dstr;
if (bl->type == BL_PC)
@@ -2010,11 +2009,16 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level)
st->cri = st->flee2 = 0;
#ifdef RENEWAL // renewal formulas
- st->matk_min = st->matk_max = bl->type == BL_PC ? status->base_matk(st, level) : level + st->int_;
- st->hit += level + st->dex + (bl->type == BL_PC ? st->luk/3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175
- st->flee += level + st->agi + (bl->type == BL_PC ? st->luk/5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100
- st->def2 += (int)(((float)level + st->vit)/2 + ( bl->type == BL_PC ? ((float)st->agi/5) : 0 )); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def)
- st->mdef2 += (int)( bl->type == BL_PC ?(st->int_ + ((float)level/4) + ((float)(st->dex+st->vit)/5)):((float)(st->int_ + level)/4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
+ if (bl->type == BL_HOM) {
+ st->hit = level + st->dex + 150; //base level + dex + 150
+ st->flee = level + st->agi + level/10; //base level + agi + base level/10
+ } else {
+ st->matk_min = st->matk_max = bl->type == BL_PC ? status->base_matk(st, level) : level + st->int_;
+ st->hit += level + st->dex + (bl->type == BL_PC ? st->luk/3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175
+ st->flee += level + st->agi + (bl->type == BL_PC ? st->luk/5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100
+ st->def2 += (int)(((float)level + st->vit)/2 + ( bl->type == BL_PC ? ((float)st->agi/5) : 0 )); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def)
+ st->mdef2 += (int)( bl->type == BL_PC ?(st->int_ + ((float)level/4) + ((float)(st->dex+st->vit)/5)):((float)(st->int_ + level)/4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
+ }
#else // not RENEWAL
st->matk_min = status_base_matk_min(st);
st->matk_max = status_base_matk_max(st);
@@ -2169,7 +2173,7 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
if (flag&2 && battle_config.mob_size_influence) {
// change for sized monsters [Valaris]
- if (md->special_state.size==SZ_SMALL) {
+ if (md->special_state.size==SZ_MEDIUM) {
mstatus->max_hp>>=1;
mstatus->max_sp>>=1;
if (!mstatus->max_hp) mstatus->max_hp = 1;
@@ -2475,13 +2479,13 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
//Give them all modes except these (useful for clones)
bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
- bstatus->size = (sd->class_&JOBL_BABY)?SZ_MEDIUM:SZ_SMALL;
+ bstatus->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM;
if (battle_config.character_size && (pc_isriding(sd) || pc_isridingdragon(sd)) ) { //[Lupus]
if (sd->class_&JOBL_BABY) {
if (battle_config.character_size&SZ_BIG)
bstatus->size++;
} else
- if(battle_config.character_size&SZ_SMALL)
+ if(battle_config.character_size&SZ_MEDIUM)
bstatus->size++;
}
bstatus->aspd_rate = 1000;
@@ -3293,11 +3297,26 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) {
hstatus->hp = 1;
hstatus->sp = 1;
}
+
+ hstatus->aspd_rate = 1000;
+
+#ifdef RENEWAL
+ hstatus->def = (hstatus->vit + (hom->level / 10)) + ((hstatus->agi + (hom->level / 10)) / 2);
+ hstatus->mdef = hstatus->int_ + ((hstatus->int_ + hstatus->dex + hstatus->luk) / 3) + (hom->level / 10) * 2;
+
+ amotion = (1000 -2*hstatus->agi -hstatus->dex) * hd->homunculusDB->baseASPD/1000;
+#else
skill_lv = hom->level/10 + hstatus->vit/5;
hstatus->def = cap_value(skill_lv, 0, 99);
skill_lv = hom->level/10 + hstatus->int_/5;
hstatus->mdef = cap_value(skill_lv, 0, 99);
+ amotion = (1000 -4*hstatus->agi - hstatus->dex) * hd->homunculusDB->baseASPD/1000;
+#endif
+
+ hstatus->amotion = cap_value(amotion,battle_config.max_aspd,2000);
+ hstatus->adelay = hstatus->amotion; //It seems adelay = amotion for Homunculus.
+
hstatus->max_hp = hom->max_hp;
hstatus->max_sp = hom->max_sp;
@@ -3323,14 +3342,10 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) {
hd->battle_status.sp = hom->sp;
}
+#ifndef RENEWAL
hstatus->rhw.atk = hstatus->dex;
hstatus->rhw.atk2 = hstatus->str + hom->level;
-
- hstatus->aspd_rate = 1000;
-
- amotion = (1000 -4*hstatus->agi -hstatus->dex) * hd->homunculusDB->baseASPD/1000;
- hstatus->amotion = cap_value(amotion,battle_config.max_aspd,2000);
- hstatus->adelay = hstatus->amotion; //It seems adelay = amotion for Homunculus.
+#endif
status->calc_misc(&hd->bl, hstatus, hom->level);
@@ -3699,12 +3714,12 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
}
}
- if( bl->type&BL_HOM ) {
+ /*if( bl->type&BL_HOM ) {
st->rhw.atk += (st->dex - bst->dex);
st->rhw.atk2 += (st->str - bst->str);
if( st->rhw.atk2 < st->rhw.atk )
st->rhw.atk2 = st->rhw.atk;
- }
+ }*/
}
if(flag&SCB_HIT) {
@@ -3917,7 +3932,11 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
st->adelay = 2*st->amotion;
} else if( bl->type&BL_HOM ) {
+#ifdef RENEWAL
+ amotion = (1000 - 2*st->agi - st->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD/1000;
+#else
amotion = (1000 - 4*st->agi - st->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD/1000;
+#endif
st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate);
if(st->aspd_rate != 1000)
@@ -4006,8 +4025,12 @@ void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_ca
if( bl->type == BL_PET )
return; // pets are not affected by statuses
- if( opt&SCO_FIRST && bl->type == BL_MOB )
+ if( opt&SCO_FIRST && bl->type == BL_MOB ) {
+#ifdef RENEWAL
+ status->update_matk(bl); // Otherwise, the mob will spawn with lower MATK values
+#endif
return; // assume there will be no statuses active
+ }
status->calc_bl_main(bl, flag);
@@ -4591,7 +4614,7 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc,
watk += sc->data[SC_SHIELDSPELL_DEF]->val2;
if(sc->data[SC_INSPIRATION])
watk += sc->data[SC_INSPIRATION]->val2;
- if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 )
+ if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 )
watk += (10 + 10 * sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2);
if( sc->data[SC_TROPIC_OPTION] )
watk += sc->data[SC_TROPIC_OPTION]->val2;
@@ -4684,8 +4707,6 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc,
if( !viewable ){
/* some statuses that are hidden in the status window */
- if (sc->data[SC_MINDBREAKER])
- matk += matk * sc->data[SC_MINDBREAKER]->val2/100;
return (unsigned short)cap_value(matk,0,USHRT_MAX);
}
@@ -4710,6 +4731,8 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc,
if (sc->data[SC_IZAYOI])
matk += 25 * sc->data[SC_IZAYOI]->val1;
#endif
+ if (sc->data[SC_MINDBREAKER])
+ matk += matk * sc->data[SC_MINDBREAKER]->val2/100;
if( sc->data[SC_ZANGETSU] )
matk += sc->data[SC_ZANGETSU]->val3;
if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4)
@@ -5047,7 +5070,7 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i
return 0;
if(sc->data[SC_SUN_COMFORT])
def2 += sc->data[SC_SUN_COMFORT]->val2;
- if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 )
+ if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 )
def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2);
if(sc->data[SC_ANGELUS])
#ifdef RENEWAL //in renewal only the VIT stat bonus is boosted by angelus
@@ -5402,7 +5425,25 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl
skills1 = 5;
}
- if((sc->data[SC_BERSERK]) && skills1 < 15)
+ if( sc->data[SC_ASSNCROS] && skills1 < sc->data[SC_ASSNCROS]->val2){
+ if (bl->type!=BL_PC)
+ skills1 = sc->data[SC_ASSNCROS]->val2;
+ else
+ switch(((TBL_PC*)bl)->status.weapon)
+ {
+ case W_BOW:
+ case W_REVOLVER:
+ case W_RIFLE:
+ case W_GATLING:
+ case W_SHOTGUN:
+ case W_GRENADE:
+ break;
+ default:
+ skills1 = sc->data[SC_ASSNCROS]->val2;
+ }
+ }
+
+ if((sc->data[SC_BERSERK]) && skills1 < 15)
skills1 = 15;
else if(sc->data[SC_GS_MADNESSCANCEL] && skills1 < 20)
skills1 = 20;
@@ -5448,7 +5489,7 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl
if( sc->data[SC_PAIN_KILLER] )
skills2 -= sc->data[SC_PAIN_KILLER]->val2;
- if( sc->data[SC_SWING] )
+ if( sc->data[SC_SWING] ) // TODO: SC_SWING shouldn't stack with skill1 modifiers
skills2 += sc->data[SC_SWING]->val3;
if( sc->data[SC_DANCE_WITH_WUG] )
skills2 += sc->data[SC_DANCE_WITH_WUG]->val3;
@@ -5464,23 +5505,7 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl
skills2 += sc->data[SC_GS_GATLINGFEVER]->val1;
if( sc->data[SC_STAR_COMFORT] )
skills2 += 3 * sc->data[SC_STAR_COMFORT]->val1;
- if( sc->data[SC_ASSNCROS] && !skills1){
- if (bl->type!=BL_PC)
- skills2 += sc->data[SC_ASSNCROS]->val2;
- else
- switch(((TBL_PC*)bl)->status.weapon)
- {
- case W_BOW:
- case W_REVOLVER:
- case W_RIFLE:
- case W_GATLING:
- case W_SHOTGUN:
- case W_GRENADE:
- break;
- default:
- skills2 += sc->data[SC_ASSNCROS]->val2;
- }
- }
+
return ( flag&1? (skills1 + pots) : skills2 );
#else
return 0;
@@ -5569,6 +5594,7 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int
max = sc->data[SC_ASSNCROS]->val2;
}
}
+
aspd_rate -= max;
if(sc->data[SC_BERSERK])
@@ -6285,9 +6311,12 @@ void status_change_init(struct block_list *bl) {
memset(sc, 0, sizeof (struct status_change));
}
-//Applies SC defense to a given status change.
-//Returns the adjusted duration based on flag values.
-//the flag values are the same as in status->change_start.
+/**
+ * Applies SC defense to a given status change.
+ *
+ * @see status_change_start for the expected parameters.
+ * @return the adjusted duration based on flag values.
+ */
int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag) {
//Percentual resistance: 10000 = 100% Resist
//Example: 50% -> sc_def=5000 -> 25%; 5000ms -> tick_def=5000 -> 2500ms
@@ -6336,12 +6365,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
case SC_QUAGMIRE:
case SC_NJ_SUITON:
case SC_SWING:
- case SC__ENERVATION:
- case SC__GROOMY:
- case SC__IGNORANCE:
- case SC__LAZINESS:
- case SC__UNLUCKY:
- case SC__WEAKNESS:
return 0;
}
@@ -6381,9 +6404,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
case SC_STUN:
sc_def = st->vit*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
-#ifdef RENEWAL
tick_def2 = st->luk*10;
-#endif
break;
case SC_POISON:
case SC_DPOISON:
@@ -6403,24 +6424,29 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
#ifdef RENEWAL
sc_def = st->int_*100;
sc_def2 = (st->vit + st->luk) * 5 + SCDEF_LVL_DIFF(bl, src, 99, 10);
- tick_def2 = st->luk * 10;
#else
sc_def = st->vit*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
#endif
+ tick_def2 = st->luk * 10;
break;
case SC_BLOODING:
#ifdef RENEWAL
sc_def = st->agi*100;
- tick_def2 = st->luk*10;
#else
sc_def = st->vit*100;
#endif
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+ tick_def2 = st->luk*10;
break;
case SC_SLEEP:
+#ifdef RENEWAL
+ sc_def = st->agi*100;
+ sc_def2 = (st->int_ + st->luk) * 5 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#else
sc_def = st->int_*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#endif
tick_def2 = st->luk*10;
break;
case SC_DEEP_SLEEP:
@@ -6434,7 +6460,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
sc_def = st->mdef*100;
#ifndef RENEWAL
sc_def2 = st->luk*10;
- tick_def2 = 0; //No duration reduction
#endif
tick_def = 0; //No duration reduction
break;
@@ -6452,11 +6477,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
// Special property: immunity when luk is zero
if (st->luk == 0)
return 0;
-#ifndef RENEWAL
- // Special property: immunity when luk is greater than level
- if (st->luk > status->get_lv(bl))
- return 0;
-#endif
sc_def = st->luk*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(NULL, src, 99, 10); // Curse only has a level penalty and no resistance
tick_def = st->vit*100;
@@ -6589,7 +6609,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
tick_def = sc_def;
//Natural resistance
- if (!(flag&8)) {
+ if (!(flag&SCFLAG_FIXEDRATE)) {
rate -= rate*sc_def/10000;
rate -= sc_def2;
@@ -6623,7 +6643,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
if (tick < 1) return 1;
//Rate reduction
- if (flag&2)
+ if (flag&SCFLAG_FIXEDTICK)
return tick;
tick -= tick*tick_def/10000;
@@ -6710,17 +6730,23 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) {
}
}
}
-/*==========================================
-* Starts a status change.
-* 'type' = type, 'val1~4' depend on the type.
-* 'rate' = base success rate. 10000 = 100%
-* 'tick' is base duration
-* 'flag':
-* &1: Cannot be avoided (it has to start)
-* &2: Tick should not be reduced (by vit, luk, lv, etc)
-* &4: sc_data loaded, no value has to be altered.
-* &8: SI will not be sent to the client
-*------------------------------------------*/
+/**
+ * Starts a status change.
+ *
+ * @param src Status change source bl.
+ * @param bl Status change target bl.
+ * @param type Status change type.
+ * @param rate Base success rate. 1 means 0.01%, 10000 means 100%.
+ * @param val1 Additional value (meaning depends on type).
+ * @param val2 Additional value (meaning depends on type).
+ * @param val3 Additional value (meaning depends on type).
+ * @param val4 Additional value (meaning depends on type).
+ * @param tick Base duration (milliseconds).
+ * @param flag Special flags (@see enum scstart_flag).
+ *
+ * @retval 0 if no status change happened.
+ * @retval 1 if the status change was successfully applied.
+ */
int status_change_start(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag) {
struct map_session_data *sd = NULL;
struct status_change* sc;
@@ -6823,7 +6849,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
sd = BL_CAST(BL_PC, bl);
//Adjust tick according to status resistances
- if( !(flag&(1|4)) ) {
+ if( !(flag&(SCFLAG_NOAVOID|SCFLAG_LOADED)) ) {
tick = status->get_sc_def(src, bl, type, rate, tick, flag);
if( !tick ) return 0;
}
@@ -6853,7 +6879,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0;
case SC_FREEZE:
//Undead are immune to Freeze/Stone
- if (undead_flag && !(flag&1))
+ if (undead_flag && !(flag&SCFLAG_NOAVOID))
return 0;
case SC_SLEEP:
case SC_STUN:
@@ -6962,7 +6988,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
//Strip skills, need to divest something or it fails.
case SC_NOEQUIPWEAPON:
- if (sd && !(flag&4)) { //apply sc anyway if loading saved sc_data
+ if (sd && !(flag&SCFLAG_LOADED)) { //apply sc anyway if loading saved sc_data
int i;
opt_flag = 0; //Reuse to check success condition.
if(sd->bonus.unstripable_equip&EQP_WEAPON)
@@ -6980,7 +7006,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_NOEQUIPSHIELD:
if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off..
else
- if (sd && !(flag&4)) {
+ if (sd && !(flag&SCFLAG_LOADED)) {
int i;
if(sd->bonus.unstripable_equip&EQP_SHIELD)
return 0;
@@ -6992,7 +7018,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
break;
case SC_NOEQUIPARMOR:
- if (sd && !(flag&4)) {
+ if (sd && !(flag&SCFLAG_LOADED)) {
int i;
if(sd->bonus.unstripable_equip&EQP_ARMOR)
return 0;
@@ -7004,7 +7030,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
break;
case SC_NOEQUIPHELM:
- if (sd && !(flag&4)) {
+ if (sd && !(flag&SCFLAG_LOADED)) {
int i;
if(sd->bonus.unstripable_equip&EQP_HELM)
return 0;
@@ -7117,7 +7143,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
//Check for BOSS resistances
- if(st->mode&MD_BOSS && !(flag&1)) {
+ if(st->mode&MD_BOSS && !(flag&SCFLAG_NOAVOID)) {
if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX)
return 0;
switch (type) {
@@ -7515,7 +7541,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
vd = status->get_viewdata(bl);
calc_flag = status->ChangeFlagTable[type];
- if(!(flag&4)) { //&4 - Do not parse val settings when loading SCs
+ if(!(flag&SCFLAG_LOADED)) { // Do not parse val settings when loading SCs
switch(type) {
case SC_ADORAMUS:
sc_start(src,bl,SC_BLIND,100,val1,skill->get_time(status->sc2skill(type),val1));
@@ -7526,16 +7552,16 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_ENDURE:
val2 = 7; // Hit-count [Celest]
- if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground && !val4 ) {
+ if( !(flag&SCFLAG_NOAVOID) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground && !val4 ) {
struct map_session_data *tsd;
if( sd ) {
int i;
for( i = 0; i < 5; i++ ) {
if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, 9);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL);
}
} else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, 9);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL);
}
//val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk)
if( val4 )
@@ -7623,16 +7649,16 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_REFLECTSHIELD:
val2=10+val1*3; // %Dmg reflected
- if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) ) {
+ if( !(flag&SCFLAG_NOAVOID) && (bl->type&(BL_PC|BL_MER)) ) {
struct map_session_data *tsd;
if( sd ) {
int i;
for( i = 0; i < 5; i++ ) {
if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 9);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
}
} else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 9);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
}
break;
case SC_NOEQUIPWEAPON:
@@ -7875,7 +7901,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_AUTOGUARD:
- if( !(flag&1) ) {
+ if( !(flag&SCFLAG_NOAVOID) ) {
struct map_session_data *tsd;
int i,t;
for( i = val2 = 0; i < val1; i++) {
@@ -7887,17 +7913,17 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if( sd ) {
for( i = 0; i < 5; i++ ) {
if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 9);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
}
}
else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 9);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
}
}
break;
case SC_DEFENDER:
- if (!(flag&1)) {
+ if (!(flag&SCFLAG_NOAVOID)) {
val2 = 5 + 15*val1; //Damage reduction
val3 = 0; // unused, previously speed adjustment
val4 = 250 - 50*val1; //Aspd adjustment
@@ -7908,7 +7934,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
for (i = 0; i < 5; i++) {
//See if there are devoted characters, and pass the status to them. [Skotlex]
if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])))
- status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1);
+ status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,SCFLAG_NOAVOID);
}
}
}
@@ -8035,7 +8061,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
while( i >= 0 ) {
type2 = types[i];
if( d_sc->data[type2] )
- status->change_start(bl, bl, type2, 10000, d_sc->data[type2]->val1, 0, 0, 0, skill->get_time(status->sc2skill(type2),d_sc->data[type2]->val1), (type2 != SC_DEFENDER) ? 8 : 0);
+ status->change_start(bl, bl, type2, 10000, d_sc->data[type2]->val1, 0, 0, 0,
+ skill->get_time(status->sc2skill(type2),d_sc->data[type2]->val1),
+ (type2 != SC_DEFENDER) ? SCFLAG_NOICON : SCFLAG_NONE);
i--;
}
}
@@ -8434,7 +8462,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
tick_time = 4000; // [GodLesZ] tick time
break;
case SC_PYREXIA:
- status->change_start(src, bl,SC_BLIND,10000,val1,0,0,0,30000,3); // Blind status that last for 30 seconds
+ status->change_start(src, bl,SC_BLIND,10000,val1,0,0,0,30000,SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE); // Blind status that last for 30 seconds
val4 = tick / 3000;
tick_time = 3000; // [GodLesZ] tick time
break;
@@ -8753,7 +8781,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
struct block_list * src2;
val3 = st->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] %
if( (src2 = map->id2bl(val2)) ){
- val4 = ( 200/status_get_int(src2) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level]
+ val4 = ( 200/status_get_int(src2)?status_get_int(src2):1 ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level]
val2 = ( status_get_dex(src2)/4 + status_get_str(src2)/2 ) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5]
}
}
@@ -9032,7 +9060,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
}
- /* values that must be set regardless of flag&4 e.g. val_flag */
+ /* values that must be set regardless of SCFLAG_LOADED e.g. val_flag */
switch(type) {
case SC_FIGHTINGSPIRIT:
val_flag |= 1|2;
@@ -9444,7 +9472,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
calc_flag&=~SCB_DYE;
}
- if(!(flag&8) && !(flag&4 && status->DisplayType[type]))
+ if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->DisplayType[type]))
clif->status_change(bl,status->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0);
/**
@@ -11637,7 +11665,7 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) {
data.val2 = sc->data[i]->val2;
data.val3 = sc->data[i]->val3;
data.val4 = sc->data[i]->val4;
- status->change_start(src,bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,1|2);
+ status->change_start(src,bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
flag = 1;
}
}
diff --git a/src/map/status.h b/src/map/status.h
index 942f86d7c..623ba7eb3 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -67,6 +67,20 @@ typedef enum sc_conf_type {
SC_NO_CLEAR = 0x80,
} sc_conf_type;
+/**
+ * Flags to be used with status->change_start
+ */
+enum scstart_flag {
+ // Note: When updating this enum, also update the documentation in doc/script_commands.txt and the constants in db/const.txt
+ SCFLAG_NONE = 0x00, ///< No special behavior.
+ SCFLAG_NOAVOID = 0x01, ///< Cannot be avoided (it has to start).
+ SCFLAG_FIXEDTICK = 0x02, ///< Tick should not be reduced (by vit, luk, lv, etc).
+ SCFLAG_LOADED = 0x04, ///< sc_data was loaded, no value has to be altered.
+ SCFLAG_FIXEDRATE = 0x08, ///< rate should not be reduced (not evaluated in status_change_start, but in some calls to other functions).
+ SCFLAG_NOICON = 0x10, ///< Status icon (SI) should not be sent.
+ SCFLAG_ALL = SCFLAG_NONE|SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_LOADED|SCFLAG_FIXEDRATE|SCFLAG_NOICON
+};
+
// Status changes listing. These code are for use by the server.
typedef enum sc_type {
SC_NONE = -1,
@@ -1185,7 +1199,7 @@ enum si_type {
SI_ECHOSONG = 443,
SI_HARMONIZE = 444,
SI_STRIKING = 445,
- SI_WARMER = 446,
+ //SI_WARMER = 446,
SI_MOONLITSERENADE = 447,
SI_SATURDAYNIGHTFEVER = 448,
SI_SITDOWN_FORCE = 449,
@@ -1921,9 +1935,9 @@ struct status_change {
#define status_get_mode(bl) (status->get_status_data(bl)->mode)
//Short version, receives rate in 1->100 range, and does not uses a flag setting.
-#define sc_start(src, bl, type, rate, val1, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),0,0,0,(tick),0))
-#define sc_start2(src, bl, type, rate, val1, val2, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),0,0,(tick),0))
-#define sc_start4(src, bl, type, rate, val1, val2, val3, val4, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),(val3),(val4),(tick),0))
+#define sc_start(src, bl, type, rate, val1, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),0,0,0,(tick),SCFLAG_NONE))
+#define sc_start2(src, bl, type, rate, val1, val2, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),0,0,(tick),SCFLAG_NONE))
+#define sc_start4(src, bl, type, rate, val1, val2, val3, val4, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),(val3),(val4),(tick),SCFLAG_NONE))
#define status_change_end(bl,type,tid) (status->change_end_((bl),(type),(tid),__FILE__,__LINE__))
diff --git a/src/map/unit.c b/src/map/unit.c
index af0c0a948..12df6ab1f 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -316,7 +316,7 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
unit->attack(bl, tbl->id, ud->state.attack_continue);
}
} else { //Update chase-path
- unit->walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy|(ud->state.attack_continue?2:0));
+ unit->walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy|(ud->state.attack_continue? 1 : 0));
return 0;
}
} else {
@@ -1241,6 +1241,19 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
casttime = -1;
temp = 1;
break;
+ case CR_DEVOTION:
+ if (sd) {
+ int i = 0, count = min(skill_lv, 5);
+ ARR_FIND(0, count, i, sd->devotion[i] == target_id);
+ if (i == count) {
+ ARR_FIND(0, count, i, sd->devotion[i] == 0);
+ if(i == count) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ return 0; // Can't cast on other characters when limit is reached
+ }
+ }
+ }
+ break;
case SR_GATEOFHELL:
case SR_TIGERCANNON:
if (sc && sc->data[SC_COMBOATTACK] &&