summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c20
-rw-r--r--src/common/mapindex.c2
-rw-r--r--src/map/battle.c60
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/chrif.c2
-rw-r--r--src/map/clif.c1
-rw-r--r--src/map/npc.c2
-rw-r--r--src/map/pc.c3
-rw-r--r--src/map/script.c44
-rw-r--r--src/map/skill.c144
-rw-r--r--src/map/status.c111
-rw-r--r--src/map/unit.c13
12 files changed, 270 insertions, 133 deletions
diff --git a/src/char/char.c b/src/char/char.c
index 9abb17257..abebc5ff9 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -4749,8 +4749,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 );
@@ -4760,8 +4759,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 );
@@ -4770,8 +4769,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 );
@@ -4780,8 +4779,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);
@@ -4789,9 +4788,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/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/battle.c b/src/map/battle.c
index 30b358492..07a195503 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -500,8 +500,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;
@@ -2197,12 +2202,12 @@ 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 ) {
@@ -2233,13 +2238,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;
@@ -2307,7 +2315,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;
@@ -2797,7 +2812,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
@@ -3762,6 +3781,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]
@@ -3816,6 +3839,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;
@@ -4176,6 +4203,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;
@@ -4227,6 +4260,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)
@@ -5424,7 +5461,7 @@ 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 ) {
+ if( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION && skill_id != GS_DESPERADO ) {
NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100);
#ifndef RENEWAL
@@ -6733,6 +6770,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, },
+ { "song_timer_reset", &battle_config.song_timer_reset, 0, 0, 1, },
// 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, },
diff --git a/src/map/battle.h b/src/map/battle.h
index 8d1a3cd39..161ddebc4 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -169,6 +169,7 @@ struct Battle_Config {
int emergency_call;
int guild_aura;
int pc_invincible_time;
+ int song_timer_reset;
int pet_catch_rate;
int pet_rename;
diff --git a/src/map/chrif.c b/src/map/chrif.c
index ebdace226..4c8cd747b 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -1178,7 +1178,7 @@ 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, 15);
}
pc->scdata_received(sd);
diff --git a/src/map/clif.c b/src/map/clif.c
index d9acf0792..26462afba 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -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/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 2c893219c..cbea20e55 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
@@ -18800,6 +18843,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"),
diff --git a/src/map/skill.c b/src/map/skill.c
index d0325fc4e..7d5f0d021 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;
}
@@ -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:
@@ -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), 2);
+ 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 ) {
@@ -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.
@@ -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; i++ && sc->fv_counter <= sc->data[SC_FORCEOFVANGUARD]->val3 )
+ clif->millenniumshield(bl, sc->fv_counter++);
+ }
+ break;
}
if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
@@ -4068,7 +4082,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,10);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
@@ -4507,7 +4521,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),8);
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 +5198,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),8) ){
skill->consume_requirement(sd,skill_id,skill_lv,2);
map->freeblock_unlock();
return 0;
@@ -6213,7 +6227,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,8);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
@@ -6261,25 +6275,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 +6373,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,
@@ -6732,7 +6745,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 +7285,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),8);
}
break;
@@ -7671,7 +7691,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,8);
status_change_end(bl, SC_SWOO, INVALID_TIMER);
break;
}
@@ -7679,7 +7699,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,10);
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)));
@@ -8646,13 +8666,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),10);
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),10);
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),10);
}
}
} else if( sd )
@@ -9547,8 +9567,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), 1|2|8);
+ status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2|8);
}
break;
@@ -11018,9 +11038,17 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
}
break;
case BA_ASSASSINCROSS:
- val1 = 10 + skill_lv + (st->agi/10); // ASPD increase
if(sd)
- val1 += (pc->checkskill(sd,BA_MUSICALLESSON) + 1) / 2;
+ 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 += 10 + skill_lv + (st->agi/10); // ASPD increase
+ val1 *= 10; // ASPD works with 1000 as 100%
+#endif
break;
case DC_FORTUNEKISS:
val1 = 10+skill_lv+(st->luk/10); // Critical increase
@@ -11135,6 +11163,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;
@@ -11340,7 +11372,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,8) ) {
const struct TimerData* td = sc->data[type]?timer->get(sc->data[type]->timer):NULL;
if( td )
sec = DIFF_TICK32(td->tick, tick);
@@ -11438,10 +11470,12 @@ 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: // Apple of idun gets it from skill_unit_onplace_timer
+ if (!battle_config.song_timer_reset)
+ break;
case UNT_WHISTLE:
case UNT_ASSASSINCROSS:
case UNT_POEMBRAGI:
- case UNT_APPLEIDUN:
case UNT_HUMMING:
case UNT_DONTFORGETME:
case UNT_FORTUNEKISS:
@@ -11452,12 +11486,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:
@@ -11721,7 +11756,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, 8) ) {
const struct TimerData* td = tsc->data[type]?timer->get(tsc->data[type]->timer):NULL;
if( td )
sec = DIFF_TICK32(td->tick, tick);
@@ -11751,7 +11786,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), 8) ) {
map->moveblock(bl, src->bl.x, src->bl.y, tick);
clif->fixpos(bl);
@@ -11840,6 +11875,12 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
heal = ~heal + 1;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
status->heal(bl, heal, 0, 0);
+
+ if (!(battle_config.song_timer_reset) // songs don't reset prior timers
+ && !(sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) // Don't affect itself
+ && (!(tsc->data[type]) || (tsc->data[type] && tsc->data[type]->val4 != 1))) // Check for 20 seconds song effect
+ sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->interval + 100);
+
break;
}
@@ -12111,7 +12152,7 @@ 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),8);
skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
@@ -12156,11 +12197,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;
@@ -12205,7 +12251,7 @@ 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), 2|8);
break;
}
@@ -12264,6 +12310,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;
}
@@ -12341,7 +12397,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.
@@ -12404,8 +12460,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);
diff --git a/src/map/status.c b/src/map/status.c
index 86be2e252..188b952ef 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -1003,6 +1003,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,16 +1790,8 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
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 :/
+ 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: {
@@ -1809,6 +1802,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;
@@ -4590,7 +4584,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;
@@ -4683,8 +4677,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);
}
@@ -4709,6 +4701,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)
@@ -5046,7 +5040,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
@@ -5401,7 +5395,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;
@@ -5447,7 +5459,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;
@@ -5463,23 +5475,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;
@@ -5568,7 +5564,8 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int
max = sc->data[SC_ASSNCROS]->val2;
}
}
- aspd_rate -= 10 * max; // let's multiply here for consistency
+
+ aspd_rate -= max;
if(sc->data[SC_BERSERK])
aspd_rate -= 300;
@@ -6335,12 +6332,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;
}
@@ -6380,9 +6371,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:
@@ -6402,24 +6391,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:
@@ -6433,7 +6427,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;
@@ -6451,11 +6444,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;
@@ -6718,7 +6706,8 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) {
* &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
+* &8: rate should not be reduced (not evaluated here, but in some calls to other functions)
+* &16: SI will not be sent to the client
*------------------------------------------*/
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;
@@ -7531,10 +7520,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
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, 17);
}
} 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, 17);
}
//val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk)
if( val4 )
@@ -7628,10 +7617,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
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, 17);
}
} 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, 17);
}
break;
case SC_NOEQUIPWEAPON:
@@ -7886,11 +7875,11 @@ 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, 17);
}
}
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, 17);
}
}
break;
@@ -8034,7 +8023,7 @@ 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) ? 16 : 0);
i--;
}
}
@@ -8433,7 +8422,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,11); // Blind status that last for 30 seconds
val4 = tick / 3000;
tick_time = 3000; // [GodLesZ] tick time
break;
@@ -8752,7 +8741,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]
}
}
@@ -9443,7 +9432,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&16) && !(flag&4 && 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);
/**
@@ -11636,7 +11625,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,1|2|8);
flag = 1;
}
}
diff --git a/src/map/unit.c b/src/map/unit.c
index af0c0a948..8b74ff80c 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -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] &&