From f0dfdf9219f6467ceda819879b9ab0d85bcabf2e Mon Sep 17 00:00:00 2001 From: Aleos Date: Mon, 24 Sep 2018 14:51:51 -0400 Subject: [PATCH] Cleaned up equipment stripping skills (#3493) * Fixes #3476. * Centralized all equipment stripping skills to skill_strip_equip. * Updated success rates and durations to match official. Thanks to @mrjnumber1! --- src/map/skill.cpp | 200 +++++++++++++++++++++++++++++----------------- 1 file changed, 125 insertions(+), 75 deletions(-) diff --git a/src/map/skill.cpp b/src/map/skill.cpp index e6e56c24f4..30363a2edc 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -130,6 +130,7 @@ int overbrand_brandish_nounit_pos; static char dir_ka = -1; // Holds temporary direction to the target for SR_KNUCKLEARROW //Early declaration +bool skill_strip_equip(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv); int skill_block_check(struct block_list *bl, enum sc_type type, uint16 skill_id); static int skill_check_unit_range (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv); static int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv, bool isNearNPC); @@ -1529,9 +1530,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 sc_start(src,bl,SC_FLING,100, sd?sd->spiritball_old:5,skill_get_time(skill_id,skill_lv)); break; case GS_DISARM: - rate = sstatus->dex / (4 * (7 - skill_lv)) + sstatus->luk / (4 * (6 - skill_lv)); - rate = rate + status_get_lv(src) - (tstatus->agi * rate / 100) - tstatus->luk - status_get_lv(bl); - skill_strip_equip(src,bl, EQP_WEAPON, rate, skill_lv, skill_get_time(skill_id,skill_lv)); + skill_strip_equip(src, bl, skill_id, skill_lv); clif_skill_nodamage(src,bl,skill_id,skill_lv,1); break; case NPC_EVILLAND: @@ -1563,15 +1562,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 sc_start4(src,bl,SC_BURNING,100,skill_lv,1000,src->id,0,skill_get_time(skill_id,skill_lv)); break; case WL_EARTHSTRAIN: - { - uint16 i; - const int pos[5] = { EQP_WEAPON, EQP_HELM, EQP_SHIELD, EQP_ARMOR, EQP_ACC }; + if (dmg_lv != ATK_DEF) // Only strip if we make a successful hit. + break; - if (dmg_lv != ATK_DEF) // Only strip if we make a successful hit. - break; - for (i = 0; i < skill_lv; i++) - skill_strip_equip(src, bl, pos[i], 5 * skill_lv, skill_lv, skill_get_time2(skill_id, skill_lv)); - } + skill_strip_equip(src, bl, skill_id, skill_lv); break; case WL_JACKFROST: case NPC_JACKFROST: @@ -2623,32 +2617,135 @@ int skill_break_equip(struct block_list *src, struct block_list *bl, unsigned sh return where; //Return list of pieces broken. } -int skill_strip_equip(struct block_list *src,struct block_list *bl, unsigned short where, int rate, int lv, int time) +/** + * Strip equipment from a target + * @param src: Source of call + * @param target: Target to strip + * @param skill_id: Skill used + * @param skill_lv: Skill level used + * @return True on successful strip or false otherwise + */ +bool skill_strip_equip(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv) { - struct status_change *sc; + nullpo_retr(false, src); + nullpo_retr(false, target); + + struct status_change *tsc = status_get_sc(target); + + if (!tsc || tsc->option&OPTION_MADOGEAR) // Mado Gear cannot be divested [Ind] + return false; + const int pos[5] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM, EQP_ACC}; const enum sc_type sc_atk[5] = {SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC__STRIPACCESSORY}; const enum sc_type sc_def[5] = {SC_CP_WEAPON, SC_CP_SHIELD, SC_CP_ARMOR, SC_CP_HELM, SC_NONE}; - int i; + struct status_data *sstatus = status_get_status_data(src), *tstatus = status_get_status_data(target); + int rate, time, location; + + switch (skill_id) { // Rate + case RG_STRIPWEAPON: + case RG_STRIPARMOR: + case RG_STRIPSHIELD: + case RG_STRIPHELM: + case GC_WEAPONCRUSH: + rate = 50 * (skill_lv + 1) + 2 * (sstatus->dex - tstatus->dex); + break; + case ST_FULLSTRIP: { + int min_rate = 50 + 20 * skill_lv; + + rate = min_rate + 2 * (sstatus->dex - tstatus->dex); + rate = max(min_rate, rate); + break; + } + case GS_DISARM: + rate = sstatus->dex / (4 * (7 - skill_lv)) + sstatus->luk / (4 * (6 - skill_lv)); + rate = rate + status_get_lv(src) - (tstatus->agi * rate / 100) - tstatus->luk - status_get_lv(target); + break; + case WL_EARTHSTRAIN: { + int job_lv = 0; + + if (src->type == BL_PC) + job_lv = ((TBL_PC*)src)->status.job_level; + rate = 6 * skill_lv + job_lv / 4 + sstatus->dex / 10; + break; + } + case SC_STRIPACCESSARY: + rate = 12 + 2 * skill_lv; + break; + default: + return false; + } if (rnd()%100 >= rate) - return 0; + return false; - sc = status_get_sc(bl); - if (!sc || sc->option&OPTION_MADOGEAR ) //Mado Gear cannot be divested [Ind] - return 0; + switch (skill_id) { // Duration + case SC_STRIPACCESSARY: + case GS_DISARM: + time = skill_get_time(skill_id, skill_lv); + break; + case WL_EARTHSTRAIN: + case RG_STRIPWEAPON: + case RG_STRIPARMOR: + case RG_STRIPSHIELD: + case RG_STRIPHELM: + case GC_WEAPONCRUSH: + case ST_FULLSTRIP: + if (skill_id == WL_EARTHSTRAIN) + time = skill_get_time2(skill_id, skill_lv); + else + time = skill_get_time(skill_id, skill_lv); - for (i = 0; i < ARRAYLENGTH(pos); i++) { - if (where&pos[i] && sc_def[i] > SC_NONE && sc->data[sc_def[i]]) - where&=~pos[i]; + if (target->type == BL_PC) + time += skill_lv + 500 * (sstatus->dex - tstatus->dex); + else { + time += 15000; + time += skill_lv + 500 * (sstatus->dex - tstatus->dex); + } + break; } - if (!where) return 0; - for (i = 0; i < ARRAYLENGTH(pos); i++) { - if (where&pos[i] && !sc_start(src,bl, sc_atk[i], 100, lv, time)) - where&=~pos[i]; + switch (skill_id) { // Location + case GC_WEAPONCRUSH: + case RG_STRIPWEAPON: + case GS_DISARM: + location = EQP_WEAPON; + break; + case RG_STRIPARMOR: + location = EQP_ARMOR; + break; + case RG_STRIPSHIELD: + location = EQP_SHIELD; + break; + case RG_STRIPHELM: + location = EQP_HELM; + break; + case ST_FULLSTRIP: + location = EQP_WEAPON|EQP_SHIELD|EQP_ARMOR|EQP_HELM; + break; + case SC_STRIPACCESSARY: + location = EQP_ACC; + break; + case WL_EARTHSTRAIN: + location = EQP_SHIELD|EQP_ARMOR|EQP_HELM; + if (skill_lv >= 4) + location |= EQP_WEAPON; + if (skill_lv >= 5) + location |= EQP_ACC; + break; } - return where?1:0; + + for (uint8 i = 0; i < ARRAYLENGTH(pos); i++) { + if (location&pos[i] && sc_def[i] > SC_NONE && tsc->data[sc_def[i]]) + location &=~ pos[i]; + } + if (!location) + return false; + + for (uint8 i = 0; i < ARRAYLENGTH(pos); i++) { + if (location&pos[i] && !sc_start(src, target, sc_atk[i], 100, skill_lv, time)) + location &=~ pos[i]; + } + return location ? true : false; } /** @@ -7594,53 +7691,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case ST_FULLSTRIP: case GC_WEAPONCRUSH: case SC_STRIPACCESSARY: { - unsigned short location = 0; - int d = 0; - - //Rate in percent - if ( skill_id == ST_FULLSTRIP ) { - i = 5 + 2*skill_lv + (sstatus->dex - tstatus->dex)/5; - } else if( skill_id == SC_STRIPACCESSARY ) { - i = 12 + 2 * skill_lv + (sstatus->dex - tstatus->dex)/5; - } else { - i = 5 + 5*skill_lv + (sstatus->dex - tstatus->dex)/5; - } - - if (i < 5) i = 5; //Minimum rate 5% - - //Duration in ms - if( skill_id == GC_WEAPONCRUSH){ - d = skill_get_time(skill_id,skill_lv); - if(bl->type == BL_PC) - d += skill_lv * 15 + (sstatus->dex - tstatus->dex); - else - d += skill_lv * 30 + (sstatus->dex - tstatus->dex) / 2; - }else - d = skill_get_time(skill_id,skill_lv) + (sstatus->dex - tstatus->dex)*500; - - if (d < 0) d = 0; //Minimum duration 0ms - - switch (skill_id) { - case RG_STRIPWEAPON: - case GC_WEAPONCRUSH: - location = EQP_WEAPON; - break; - case RG_STRIPSHIELD: - location = EQP_SHIELD; - break; - case RG_STRIPARMOR: - location = EQP_ARMOR; - break; - case RG_STRIPHELM: - location = EQP_HELM; - break; - case ST_FULLSTRIP: - location = EQP_WEAPON|EQP_SHIELD|EQP_ARMOR|EQP_HELM; - break; - case SC_STRIPACCESSARY: - location = EQP_ACC; - break; - } + bool i; //Special message when trying to use strip on FCP [Jobbie] if( sd && skill_id == ST_FULLSTRIP && tsc && tsc->data[SC_CP_WEAPON] && tsc->data[SC_CP_HELM] && tsc->data[SC_CP_ARMOR] && tsc->data[SC_CP_SHIELD]) @@ -7649,8 +7700,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui break; } - //Attempts to strip at rate i and duration d - if( (i = skill_strip_equip(src,bl, location, i, skill_lv, d)) || (skill_id != ST_FULLSTRIP && skill_id != GC_WEAPONCRUSH ) ) + if( (i = skill_strip_equip(src, bl, skill_id, skill_lv)) || (skill_id != ST_FULLSTRIP && skill_id != GC_WEAPONCRUSH ) ) clif_skill_nodamage(src,bl,skill_id,skill_lv,i); //Nothing stripped.