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.c1
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/npc.c2
-rw-r--r--src/map/skill.c58
-rw-r--r--src/map/status.c52
-rw-r--r--src/map/unit.c13
8 files changed, 89 insertions, 60 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..8930d3a7e 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -6733,6 +6733,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/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/skill.c b/src/map/skill.c
index 9f008d65b..9046ff975 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -6360,7 +6360,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,
@@ -11013,19 +11013,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:
@@ -11456,13 +11458,15 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
return 0;
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) {
- //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);
+ if (battle_config.song_timer_reset) { // Aegis like behaviour goes on skill_unit_onplace_timer
+ if (!sce)
+ sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit);
+ else if (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;
@@ -11846,6 +11850,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;
}
@@ -12273,6 +12283,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 +12370,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 +12433,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 718deaefc..ac89f2a07 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -1790,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: {
@@ -1810,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;
@@ -5402,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;
@@ -5448,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;
@@ -5464,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;
@@ -5569,6 +5564,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])
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] &&