summaryrefslogtreecommitdiff
path: root/src/map/skill.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/skill.c')
-rw-r--r--src/map/skill.c117
1 files changed, 79 insertions, 38 deletions
diff --git a/src/map/skill.c b/src/map/skill.c
index 1431d27a7..dc89f3170 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -46,7 +46,7 @@
#define SKILLUNITTIMER_INTERVAL 100
// ranges reserved for mapping skill ids to skilldb offsets
-#define HM_SKILLRANGEMIN 700
+#define HM_SKILLRANGEMIN 750
#define HM_SKILLRANGEMAX HM_SKILLRANGEMIN + MAX_HOMUNSKILL
#define MC_SKILLRANGEMIN HM_SKILLRANGEMAX + 1
#define MC_SKILLRANGEMAX MC_SKILLRANGEMIN + MAX_MERCSKILL
@@ -64,20 +64,6 @@ static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Sko
DBMap* skillunit_db = NULL; // int id -> struct skill_unit*
/**
- * Skill Cool Down Delay Saving
- * Struct skill_cd is not a member of struct map_session_data
- * to keep cooldowns in memory between player log-ins.
- * All cooldowns are reset when server is restarted.
- **/
-DBMap* skillcd_db = NULL; // char_id -> struct skill_cd
-struct skill_cd {
- int duration[MAX_SKILL_TREE];//milliseconds
- short skidx[MAX_SKILL_TREE];//the skill index entries belong to
- short nameid[MAX_SKILL_TREE];//skill id
- unsigned char cursor;
-};
-
-/**
* Skill Unit Persistency during endack routes (mostly for songs see bugreport:4574)
**/
DBMap* skillusave_db = NULL; // char_id -> struct skill_usave
@@ -118,6 +104,9 @@ struct s_skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT];
int firewall_unit_pos;
int icewall_unit_pos;
int earthstrain_unit_pos;
+
+struct skill_interface skill_s;
+
//Since only mob-casted splash skills can hit ice-walls
static inline int splash_target(struct block_list* bl) {
#ifndef RENEWAL
@@ -851,11 +840,9 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
break;
case SM_BASH:
- if( sd && skill_lv > 5 && pc->checkskill(sd,SM_FATALBLOW)>0 ){
- //TODO: How much % per base level it actually is?
- sc_start(bl,SC_STUN,(5*(skill_lv-5)+(int)sd->status.base_level/10),
- skill_lv,skill->get_time2(SM_FATALBLOW,skill_lv));
- }
+ if( sd && skill_lv > 5 && pc->checkskill(sd,SM_FATALBLOW)>0 )
+ status_change_start(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);
break;
case MER_CRASH:
@@ -949,8 +936,8 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
break;
case TF_THROWSTONE:
- sc_start(bl,SC_STUN,3,skill_lv,skill->get_time(skill_id,skill_lv));
- sc_start(bl,SC_BLIND,3,skill_lv,skill->get_time2(skill_id,skill_lv));
+ if( !sc_start(bl,SC_STUN,3,skill_lv,skill->get_time(skill_id,skill_lv)) )
+ sc_start(bl,SC_BLIND,3,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
case NPC_DARKCROSS:
@@ -1182,7 +1169,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
sc_start4(bl,SC_BURNING,5+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv));
break;
case RK_DRAGONBREATH_WATER:
- sc_start4(bl,SC_FROSTMISTY,5+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv));
+ sc_start(bl,SC_FROSTMISTY,5+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv));
break;
case AB_ADORAMUS:
if( tsc && !tsc->data[SC_DEC_AGI] ) //Prevent duplicate agi-down effect.
@@ -1344,7 +1331,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
rate = 5 + 5 * skill_lv;
if( sc && sc->data[SC_COOLER_OPTION] )
rate += rate * sc->data[SC_COOLER_OPTION]->val2 / 100;
- sc_start(bl, SC_CRYSTALIZE, rate, skill_lv, skill->get_time2(skill_id, skill_lv));
+ sc_start(bl, SC_COLD, rate, skill_lv, skill->get_time2(skill_id, skill_lv));
break;
case SO_VARETYR_SPEAR:
sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv));
@@ -7676,9 +7663,24 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case NPC_WIDESTUN:
case NPC_SLOWCAST:
case NPC_WIDEHELLDIGNITY:
- if (flag&1)
- sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
- else {
+ case NPC_WIDEHEALTHFEAR:
+ case NPC_WIDEBODYBURNNING:
+ case NPC_WIDEFROSTMISTY:
+ case NPC_WIDECOLD:
+ case NPC_WIDE_DEEP_SLEEP:
+ case NPC_WIDESIREN:
+ if (flag&1){
+ switch( type ){
+ case SC_BURNING:
+ sc_start4(bl,type,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv));
+ break;
+ case SC_SIREN:
+ sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
+ break;
+ default:
+ sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
+ }
+ }else {
skill_area_temp[2] = 0; //For SD_PREAMBLE
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
iMap->foreachinrange(skill->area_sub, bl,
@@ -7939,7 +7941,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case AB_LAUDAAGNUS:
if( flag&1 || sd == NULL ) {
if( tsc && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE] || tsc->data[SC_BLIND] ||
- tsc->data[SC_BURNING] || tsc->data[SC_FROSTMISTY] || tsc->data[SC_CRYSTALIZE])) {
+ tsc->data[SC_BURNING] || tsc->data[SC_FROSTMISTY] || tsc->data[SC_COLD])) {
// Success Chance: (40 + 10 * Skill Level) %
if( rnd()%100 > 40+10*skill_lv ) break;
status_change_end(bl, SC_FREEZE, INVALID_TIMER);
@@ -7947,7 +7949,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
status_change_end(bl, SC_BLIND, INVALID_TIMER);
status_change_end(bl, SC_BURNING, INVALID_TIMER);
status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER);
- status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER);
+ status_change_end(bl, SC_COLD, INVALID_TIMER);
}else //Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets
clif->skill_nodamage(bl, bl, skill_id, skill_lv,
sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
@@ -8037,9 +8039,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
else if(bl->type == BL_PC) rate += 20 + 10 * skill_lv; // On Players, (20 + 10 * Skill Level) %
else rate += 40 + 10 * skill_lv; // On Monsters, (40 + 10 * Skill Level) %
- if( sd )
- skill->blockpc_start(sd,skill_id,4000, false);
-
if( !(tsc && tsc->data[type]) ){
i = sc_start2(bl,type,rate,skill_lv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill->get_time(skill_id,skill_lv):skill->get_time2(skill_id, skill_lv));
clif->skill_nodamage(src,bl,skill_id,skill_lv,i);
@@ -8451,7 +8450,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
case SC_BLOODING: case SC_CURSE:
case SC_CONFUSION: case SC_ILLUSION:
case SC_SILENCE: case SC_BURNING:
- case SC_CRYSTALIZE: case SC_FROSTMISTY:
+ case SC_COLD: case SC_FROSTMISTY:
case SC_DEEP_SLEEP: case SC_FEAR:
case SC_MANDRAGORA:
status_change_end(bl, (sc_type)i, INVALID_TIMER);
@@ -8556,7 +8555,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
status_change_end(bl, SC_POISON, INVALID_TIMER);
status_change_end(bl, SC_SILENCE, INVALID_TIMER);
status_change_end(bl, SC_BLIND, INVALID_TIMER);
- status_change_end(bl, SC_ILLUSION, INVALID_TIMER);
+ status_change_end(bl, SC_ILLUSION, INVALID_TIMER);
status_change_end(bl, SC_BURNING, INVALID_TIMER);
status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER);
}
@@ -11801,7 +11800,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
if( battle->check_target(&src->bl,bl,BCT_ENEMY) > 0 ){
switch( sg->unit_id ){
case UNT_ZENKAI_WATER:
- sc_start(bl, SC_CRYSTALIZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
+ sc_start(bl, SC_COLD, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
sc_start(bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
sc_start(bl, SC_FROSTMISTY, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv));
break;
@@ -16875,16 +16874,24 @@ int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) {
int i,cursor;
ARR_FIND( 0, cd->cursor+1, cursor, cd->skidx[cursor] == data );
cd->duration[cursor] = 0;
+#if PACKETVER >= 20120604
+ cd->total[cursor] = 0;
+#endif
cd->skidx[cursor] = 0;
cd->nameid[cursor] = 0;
+ cd->started[cursor] = 0;
// compact the cool down list
for( i = 0, cursor = 0; i < cd->cursor; i++ ) {
if( cd->duration[i] == 0 )
continue;
if( cursor != i ) {
cd->duration[cursor] = cd->duration[i];
+#if PACKETVER >= 20120604
+ cd->total[cursor] = cd->total[i];
+#endif
cd->skidx[cursor] = cd->skidx[i];
cd->nameid[cursor] = cd->nameid[i];
+ cd->started[cursor] = cd->started[i];
}
cursor++;
}
@@ -16920,7 +16927,7 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick,
return -1;
}
- if( battle_config.display_status_timers )
+ if( !load && battle_config.display_status_timers )
clif->skill_cooldown(sd, skill_id, tick);
if( !load ) {// not being loaded initially so ensure the skill delay is recorded
@@ -16931,8 +16938,12 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick,
// record the skill duration in the database map
cd->duration[cd->cursor] = tick;
+#if PACKETVER >= 20120604
+ cd->total[cd->cursor] = tick;
+#endif
cd->skidx[cd->cursor] = idx;
cd->nameid[cd->cursor] = skill_id;
+ cd->started[cd->cursor] = iTimer->gettick();
cd->cursor++;
}
@@ -17425,13 +17436,37 @@ int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) {
}
/**
+ * update stored skill cooldowns for player logout
+ * @param sd the affected player structure
+ */
+void skill_cooldown_save(struct map_session_data * sd) {
+ int i;
+ struct skill_cd* cd = NULL;
+ unsigned int now = 0;
+
+ // always check to make sure the session properly exists
+ nullpo_retv(sd);
+
+ if( !(cd = idb_get(skillcd_db, sd->status.char_id)) ) {// no skill cooldown is associated with this character
+ return;
+ }
+
+ now = iTimer->gettick();
+
+ // process each individual cooldown associated with the character
+ for( i = 0; i < cd->cursor; i++ ) {
+ cd->duration[i] = DIFF_TICK(cd->started[i]+cd->duration[i],now);
+ }
+}
+
+/**
* reload stored skill cooldowns when a player logs in.
* @param sd the affected player structure
*/
-void skill_cooldown_load(struct map_session_data * sd)
-{
+void skill_cooldown_load(struct map_session_data * sd) {
int i;
struct skill_cd* cd = NULL;
+ unsigned int now = 0;
// always check to make sure the session properly exists
nullpo_retv(sd);
@@ -17440,8 +17475,13 @@ void skill_cooldown_load(struct map_session_data * sd)
return;
}
+ clif->cooldown_list(sd->fd,cd);
+
+ now = iTimer->gettick();
+
// process each individual cooldown associated with the character
for( i = 0; i < cd->cursor; i++ ) {
+ cd->started[i] = now;
// block the skill from usage but ensure it is not recorded (load = true)
skill->blockpc_start( sd, cd->nameid[i], cd->duration[i], true );
}
@@ -18132,5 +18172,6 @@ void skill_defaults(void) {
skill->elementalanalysis = skill_elementalanalysis;
skill->changematerial = skill_changematerial;
skill->get_elemental_type = skill_get_elemental_type;
+ skill->cooldown_save = skill_cooldown_save;
}