From b385fd048a6872b0fbd2562f619c51bf75f47599 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Thu, 29 Oct 2015 18:09:36 -0400 Subject: [PATCH] Follow up to c48133c and d8d5489 * Fixes #616 - Status effects that damage monsters will now give players their EXP. --- doc/status_change.txt | 112 +++++++++++++++++++++++++++++------------- src/map/battle.c | 2 +- src/map/skill.c | 38 +++++++------- src/map/status.c | 32 +++++++++++- 4 files changed, 129 insertions(+), 55 deletions(-) diff --git a/doc/status_change.txt b/doc/status_change.txt index 70bcf6e362..5867c915f9 100644 --- a/doc/status_change.txt +++ b/doc/status_change.txt @@ -3,7 +3,7 @@ //===== By: ================================================== //= rAthena Dev Team //===== Last Updated: ======================================== -//= 20150331 +//= 20151030 //===== Description: ========================================= //= List of all Status Changes and theirs val1, val2, val3, and //= val4 usage in source. Providing easier guide to use @@ -25,6 +25,9 @@ SC_STONE () desc: DEF -50%; if HP>25% lose 1% HP/5 sec; MDEF +25%; change element to Earth Lv 1; ignore Steal & Lex Aeterna; can't move/attack/pick item/use item/use skill/sit/logout val1: + val2: Caster's object ID (for mob_log_damage) + val3: Tick + val4: Petrifying tick SC_FREEZE () desc: DEF -50%; FLEE = 0; MDEF +25%; ignore Steal, Lex Aeterna, Storm Gust, Falling Ice Pillar; change element to Water Lv 1; can't move/attack/pick item/use item/sit/logout @@ -40,7 +43,10 @@ SC_SLEEP () SC_POISON () desc: DEF -25%; if HP>25% lose 1.5% + 2 HP/sec; SP Regeneration is disabled - val1: + val1: Skill Level + val2: Caster's object ID (for mob_log_damage) + val3: Tick + val4: HP Damage SC_CURSE () desc: ATK-25%; LUK = 0; Movement speed -300 @@ -60,11 +66,17 @@ SC_BLIND () SC_BLEEDING (SI_BLEEDING) desc: HP Regeneration is disabled; SP Regeneration is disabled; Lose HP overtime - val1: + val1: Skill Level + val2: Caster's object ID (for mob_log_damage) + val3: + val4: Tick SC_DPOISON () desc: DEF -25%; if HP>25% lose 10/15% HP/sec - val1: + val1: Skill Level + val2: Caster's object ID (for mob_log_damage) + val3: Tick + val4: HP Damage SC_PROVOKE (SI_PROVOKE) desc: Decrease DEF by (5+(5*Skill Lv))%; Increase ATK by (2+(3*Skill lv))% @@ -752,8 +764,10 @@ SC_SPIRIT () SC_COMA () desc: Vanish HP to 1 and SP to 0 - val1: (meaningless) + val1: Skill Level val2: If 1 means do not remove SP + val3: Caster's object ID (for mob_log_damage) + val4: SC_INTRAVISION () desc: @@ -1264,9 +1278,12 @@ SC_FEAR () desc: val1: -SC_BURNING () - desc: - val1: +SC_BURNING (SI_BURNT) + desc: MDEF -25%; Deals fixed (1000 + 3%*MaxHP) damage every 3 seconds; Damage can not be reduced + val1: Skill Level + val2: 1000 + val3: Caster's object ID (for mob_log_damage) + val4: Tick SC_FREEZING () desc: @@ -1472,9 +1489,12 @@ SC_VENOMIMPRESS () desc: val1: -SC_POISONINGWEAPON () - desc: - val1: +SC_POISONINGWEAPON (SI_POISONINGWEAPON) + desc: Coat the user's equipped weapon with a new poison temporarily, which grants a chance of leaving the target infected with the current poison while physically attacking. + val1: GC_WEAPONRESEARCH Skill Level + val2: Poison Type + val3: Success Rate + val4: Caster's object ID (for mob_log_damage) SC_WEAPONBLOCKING () desc: @@ -1496,37 +1516,61 @@ SC_ROLLINGCUTTER () desc: val1: -SC_TOXIN () - desc: - val1: +SC_TOXIN (SI_TOXIN) + desc: Inflict damage, which causes the affected entity to flinch every 10 seconds; This will interrupt the skill casting, even if protected against it + val1: GC_WEAPONRESEARCH Skill Level + val2: Caster's object ID (for mob_log_damage) + val3: + val4: Tick -SC_PARALYSE () - desc: - val1: +SC_PARALYSE (SI_PARALYSE) + desc: Decrease both ASPD and Flee Rate by 10% and halve Movement Speed, which does not stack with Decrease AGI, Quagmire, Marsh Of Abyss or Freezing status + val1: GC_WEAPONRESEARCH Skill Level + val2: + val3: + val4: Tick SC_VENOMBLEED (SI_VENOMBLEED) - desc: - val1: + desc: Decrease Max HP by 15% + val1: GC_WEAPONRESEARCH Skill Level + val2: + val3: + val4: Tick -SC_MAGICMUSHROOM () - desc: - val1: +SC_MAGICMUSHROOM (SI_MAGICMUSHROOM) + desc: Force the affected entity to use /heh emote, to randomly use skills and drain 3% of Max HP every 4 seconds + val1: GC_WEAPONRESEARCH Skill Level + val2: Caster's object ID (for mob_log_damage) + val3: + val4: Tick -SC_DEATHHURT () - desc: - val1: +SC_DEATHHURT (SI_DEATHHURT) + desc: Drop the healing effectiveness by 20%; This effect stacks with Critical Wounds + val1: GC_WEAPONRESEARCH Skill Level + val2: + val3: + val4: Tick -SC_PYREXIA () - desc: - val1: +SC_PYREXIA (SI_PYREXIA) + desc: Cause Blind and Hallucination statuses; If the affected entity takes damage while under the effects of this poison, it will remain in flinching motion, which will interrupt the skill casting + val1: GC_WEAPONRESEARCH Skill Level + val2: + val3: + val4: Tick -SC_OBLIVIONCURSE () - desc: - val1: +SC_OBLIVIONCURSE (SI_OBLIVIONCURSE) + desc: Force the affected entity to use /? emote, block SP Recovery and cause Oblivion status; There is a chance (100% - (Target INT * 0.8)%) of being inflicted, with a minimum of 5% + val1: GC_WEAPONRESEARCH Skill Level + val2: + val3: + val4: Tick -SC_LEECHESEND () - desc: - val1: +SC_LEECHESEND (SI_LEECHESEND) + desc: Drain (Target VIT * (SkillLv - 3)) + (Target HP / 100) HP each second + val1: GC_WEAPONRESEARCH Skill Level + val2: Caster's object ID (for mob_log_damage) + val3: + val4: Tick SC_REFLECTDAMAGE () desc: diff --git a/src/map/battle.c b/src/map/battle.c index e3edc19239..b4fed245e3 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1443,7 +1443,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc->data[SC_POISONINGWEAPON] && ((flag&BF_WEAPON) && (!skill_id || skill_id == GC_VENOMPRESSURE)) //check skill type poison_smoke is a unit && (damage > 0 && rnd()%100 < sc->data[SC_POISONINGWEAPON]->val3 )) //did some damage and chance ok (why no additional effect ??) - sc_start(src,bl,(enum sc_type)sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1)); + sc_start2(src,bl,(enum sc_type)sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,sc->data[SC_POISONINGWEAPON]->val4,skill_get_time2(GC_POISONINGWEAPON, 1)); if( sc->data[SC__DEADLYINFECT] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 ) status_change_spread(src, bl, 0); diff --git a/src/map/skill.c b/src/map/skill.c index 7a3a0630b7..0f7cab3d77 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1688,7 +1688,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 break; case RL_MASS_SPIRAL: - sc_start(src,bl,SC_BLEEDING,10 * skill_lv + rnd()%50,skill_lv,skill_get_time2(skill_id,skill_lv)); //(custom) + sc_start2(src,bl,SC_BLEEDING,10 * skill_lv + rnd()%50,skill_lv,src->id,skill_get_time2(skill_id,skill_lv)); //(custom) break; case RL_SLUGSHOT: if (bl->type != BL_PC) @@ -6949,7 +6949,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui break; } if (sc_start4(src,bl,SC_STONE,(skill_lv*4+20)+brate, - skill_lv, 0, 0, skill_get_time(skill_id, skill_lv), + skill_lv, src->id, 0, skill_get_time(skill_id, skill_lv), skill_get_time2(skill_id,skill_lv))) clif_skill_nodamage(src,bl,skill_id,skill_lv,1); else if(sd) { @@ -8208,13 +8208,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case 7: // stop freeze or stoned { enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE }; - sc_start(src,bl,sc[rnd()%3],100,skill_lv,skill_get_time2(skill_id,skill_lv)); + uint8 rand_eff = rnd()%3; + + sc_start2(src,bl,sc[rand_eff],100,skill_lv,(rand_eff == 2 ? src->id : 0),skill_get_time2(skill_id,skill_lv)); } break; case 8: // curse coma and poison - sc_start(src,bl,SC_COMA,100,skill_lv,skill_get_time2(skill_id,skill_lv)); + status_change_start(src, bl, SC_COMA, 100, skill_lv, 0, src->id, 0, 0, SCSTART_NONE); sc_start(src,bl,SC_CURSE,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - sc_start(src,bl,SC_POISON,100,skill_lv,skill_get_time2(skill_id,skill_lv)); + sc_start2(src,bl,SC_POISON,100,skill_lv,src->id,skill_get_time2(skill_id,skill_lv)); break; case 9: // confusion sc_start(src,bl,SC_CONFUSION,100,skill_lv,skill_get_time2(skill_id,skill_lv)); @@ -9103,13 +9105,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui 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,1000,skill_get_time(skill_id, skill_lv),SCSTART_NOTICKDEF); + status_change_start(src,bl,SC_STONE,10000,skill_lv,src->id,0,1000,skill_get_time(skill_id, skill_lv),SCSTART_NOTICKDEF); } else { int rate = 45 + 5 * skill_lv + ( sd? sd->status.job_level : 50 ) / 4; // IroWiki says Rate should be reduced by target stats, but currently unknown if( rnd()%100 < rate ) { // Success on First Target if( !tsc->data[SC_STONE] ) - rate = status_change_start(src,bl,SC_STONE,10000,skill_lv,0,0,1000,skill_get_time(skill_id, skill_lv),SCSTART_NOTICKDEF); + rate = status_change_start(src,bl,SC_STONE,10000,skill_lv,src->id,0,1000,skill_get_time(skill_id, skill_lv),SCSTART_NOTICKDEF); else { rate = 1; status_change_end(bl,SC_STONE,INVALID_TIMER); @@ -13365,7 +13367,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns sc_start(ss, bl,SC_BLIND,100,1,time); break; case 3: // Poison - sc_start(ss, bl,SC_POISON,100,1,time); + sc_start2(ss, bl,SC_POISON,100,1,ss->id,time); break; case 4: // Level 10 Provoke sc_start(ss, bl,SC_PROVOKE,100,10,time); @@ -13509,7 +13511,7 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns switch( sg->val2 ) { case 1: default: - sc_start(ss, bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start4(ss, bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, 1000, ss->id, 0, skill_get_time2(sg->skill_id, sg->skill_lv)); skill_attack(skill_get_type(skill_id), ss, &unit->bl, bl, sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0); break; } @@ -13615,15 +13617,15 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns case UNT_ZENKAI_LAND: switch (rnd()%2 + 1) { case 1: - sc_start(ss, bl, SC_STONE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start2(ss, bl, SC_STONE, sg->val1*5, sg->skill_lv, ss->id, skill_get_time2(sg->skill_id, sg->skill_lv)); break; case 2: - sc_start(ss, bl, SC_POISON, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start2(ss, bl, SC_POISON, sg->val1*5, sg->skill_lv, ss->id, skill_get_time2(sg->skill_id, sg->skill_lv)); break; } break; case UNT_ZENKAI_FIRE: - sc_start(ss, bl, SC_BURNING, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start4(ss, bl, SC_BURNING, sg->val1*5, sg->skill_lv, 1000, ss->id, 0, skill_get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_ZENKAI_WIND: switch (rnd()%3 + 1) { @@ -16937,7 +16939,7 @@ static int skill_trap_splash(struct block_list *bl, va_list ap) break; case UNT_GROUNDDRIFT_POISON: if(skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(ss,bl,SC_POISON,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start2(ss,bl,SC_POISON,5,sg->skill_lv,ss->id,skill_get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_GROUNDDRIFT_WATER: if(skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) @@ -18943,7 +18945,7 @@ bool skill_arrow_create(struct map_session_data *sd, unsigned short nameid) int skill_poisoningweapon(struct map_session_data *sd, unsigned short nameid) { sc_type type; - int chance, i; + int chance, i, val4 = 0; //uint16 msg = 1443; //Official is using msgstringtable.txt char output[CHAT_SIZE_MAX]; const char *msg; @@ -18959,10 +18961,10 @@ int skill_poisoningweapon(struct map_session_data *sd, unsigned short nameid) case ITEMID_PARALYSE: type = SC_PARALYSE; /*msg = 1444;*/ msg = "Paralyze"; break; case ITEMID_PYREXIA: type = SC_PYREXIA; /*msg = 1448;*/ msg = "Pyrexia"; break; case ITEMID_DEATHHURT: type = SC_DEATHHURT; /*msg = 1447;*/ msg = "Deathhurt"; break; - case ITEMID_LEECHESEND: type = SC_LEECHESEND; /*msg = 1450;*/ msg = "Leech End"; break; + case ITEMID_LEECHESEND: type = SC_LEECHESEND; /*msg = 1450;*/ msg = "Leech End"; val4 = sd->bl.id; break; case ITEMID_VENOMBLEED: type = SC_VENOMBLEED; /*msg = 1445;*/ msg = "Venom Bleed"; break; - case ITEMID_TOXIN: type = SC_TOXIN; /*msg = 1443;*/ msg = "Toxin"; break; - case ITEMID_MAGICMUSHROOM: type = SC_MAGICMUSHROOM; /*msg = 1446;*/ msg = "Magic Mushroom"; break; + case ITEMID_TOXIN: type = SC_TOXIN; /*msg = 1443;*/ msg = "Toxin"; val4 = sd->bl.id; break; + case ITEMID_MAGICMUSHROOM: type = SC_MAGICMUSHROOM; /*msg = 1446;*/ msg = "Magic Mushroom"; val4 = sd->bl.id; break; case ITEMID_OBLIVIONCURSE: type = SC_OBLIVIONCURSE; /*msg = 1449;*/ msg = "Oblivion Curse"; break; default: clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); @@ -18971,7 +18973,7 @@ int skill_poisoningweapon(struct map_session_data *sd, unsigned short nameid) chance = 2 + 2 * sd->menuskill_val; // 2 + 2 * skill_lv sc_start4(&sd->bl,&sd->bl, SC_POISONINGWEAPON, 100, pc_checkskill(sd, GC_RESEARCHNEWPOISON), //in Aegis it store the level of GC_RESEARCHNEWPOISON in val1 - type, chance, 0, skill_get_time(GC_POISONINGWEAPON, sd->menuskill_val)); + type, chance, val4, skill_get_time(GC_POISONINGWEAPON, sd->menuskill_val)); sprintf(output, msg_txt(sd,721), msg); clif_colormes(sd->fd,color_table[COLOR_WHITE],output); diff --git a/src/map/status.c b/src/map/status.c index df2c0272e1..08a5b46721 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -9688,7 +9688,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty default: rand_eff = SC_POISON; break; } val2 = 10 * val1; // Crit and Flee2 Reduction - status_change_start(src,bl,rand_eff,10000,val1,0,0,0,tick,SCSTART_NOTICKDEF|SCSTART_NORATEDEF); + status_change_start(src,bl,rand_eff,10000,val1,0,(rand_eff == SC_POISON ? src->id : 0),0,tick,SCSTART_NOTICKDEF|SCSTART_NORATEDEF); break; } case SC__WEAKNESS: @@ -11718,8 +11718,15 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) return 0; } if(--(sce->val3) > 0) { - if(++(sce->val4)%5 == 0 && status->hp > status->max_hp/4) + if(++(sce->val4)%5 == 0 && status->hp > status->max_hp/4) { + if (sce->val2 && bl->type == BL_MOB) { + struct block_list *src = map_id2bl(sce->val2); + + if (src) + mob_log_damage((TBL_MOB*)bl, src, apply_rate(status->hp, 1)); + } status_percent_damage(NULL, bl, 1, 0, false); + } sc_timer_next(1000+tick,status_change_timer, bl->id, data ); return 0; } @@ -11959,6 +11966,12 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) if( --(sce->val4) >= 0 ) { int damage = status->vit * (sce->val1 - 3) + status->max_hp / 100; // {Target VIT x (New Poison Research Skill Level - 3)} + (Target HP/100) + if (sce->val2 && bl->type == BL_MOB) { + struct block_list *src2 = map_id2bl(sce->val2); + + if (src2) + mob_log_damage((TBL_MOB*)bl, src2, damage); + } map_freeblock_lock(); status_damage(bl, bl, damage, 0, clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,DMG_NORMAL,0), 0); unit_skillcastcancel(bl, 2); @@ -11984,6 +11997,13 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) map_freeblock_unlock(); } + if (sce->val2 && bl->type == BL_MOB) { + struct block_list *src2 = map_id2bl(sce->val2); + + if (src2) + mob_log_damage((TBL_MOB*)bl, src2, damage); + } + if( !flag ) { // Random Skill Cast if (skill_magicmushroom_count && sd && !pc_issit(sd)) { // Can't cast if sit int mushroom_skill_id = 0, checked = 0, checked_max = MAX_SKILL_MAGICMUSHROOM_DB * 3; @@ -12020,6 +12040,12 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) case SC_TOXIN: if( --(sce->val4) >= 0 ) { // Damage is every 10 seconds including 3%sp drain. + if (sce->val2 && bl->type == BL_MOB) { + struct block_list *src2 = map_id2bl(sce->val2); + + if (src2) + mob_log_damage((TBL_MOB*)bl, src2, 1); + } map_freeblock_lock(); clif_damage(bl,bl,tick,status_get_amotion(bl),1,1,0,DMG_NORMAL,0); status_damage(NULL, bl, 1, status->max_sp * 3 / 100, 0, 0); // Cancel dmg only if cancelable @@ -12070,6 +12096,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) struct block_list *src = map_id2bl(sce->val3); int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP) + if (src && bl->type == BL_MOB) + mob_log_damage((TBL_MOB*)bl, src, damage); map_freeblock_lock(); clif_damage(bl,bl,tick,0,0,damage,1,DMG_MULTI_HIT_ENDURE,0); // Damage is like endure effect with no walk delay status_damage(src, bl, damage, 0, 0, 1);