Bug Fixes
* Fixes #587 - Corrected Amistr Defence to properly calculate VIT for renewal and DEF for pre-renewal. * Fixes #588 - Fixed skills not being properly removed when being copied by Plagiarism or Reproduce. * Fixes #589 - Blessing no longer gives stat bonuses when Curse is active. * Fixes #599 - Fixed a possible crash by Praefatio. * Fixes #601 - Exceed Break now cancels when switching weapons and is properly removed on misses.
This commit is contained in:
parent
3a4847ebde
commit
eb0a79f1bf
@ -3300,10 +3300,6 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
|
||||
status_change_end(src,SC_CRUSHSTRIKE,INVALID_TIMER);
|
||||
skill_break_equip(src,src,EQP_WEAPON,2000,BCT_SELF);
|
||||
}
|
||||
if (sc->data[SC_EXEEDBREAK] && !skill_id) {
|
||||
skillratio += -100 + sc->data[SC_EXEEDBREAK]->val1;
|
||||
status_change_end(src,SC_EXEEDBREAK,INVALID_TIMER);
|
||||
}
|
||||
//!TODO: Verify this placement & skills that affected by these effects [Cydh]
|
||||
if (sc->data[SC_HEAT_BARREL])
|
||||
skillratio += 200;
|
||||
@ -7060,6 +7056,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
|
||||
wd = battle_calc_attack(BF_WEAPON, src, target, 0, 0, flag);
|
||||
|
||||
if( sc && sc->count ) {
|
||||
if (sc->data[SC_EXEEDBREAK]) {
|
||||
wd.damage *= sc->data[SC_EXEEDBREAK]->val1 / 100;
|
||||
status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER);
|
||||
}
|
||||
if( sc->data[SC_SPELLFIST] ) {
|
||||
if( --(sc->data[SC_SPELLFIST]->val1) >= 0 ){
|
||||
struct Damage ad = battle_calc_attack(BF_MAGIC,src,target,sc->data[SC_SPELLFIST]->val3,sc->data[SC_SPELLFIST]->val4,flag|BF_SHORT);
|
||||
|
49
src/map/pc.c
49
src/map/pc.c
@ -5480,7 +5480,7 @@ uint8 pc_checkskill(struct map_session_data *sd, uint16 skill_id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Chk if we still have the correct weapon to continue the skill (actually status)
|
||||
* Check if we still have the correct weapon to continue the skill (actually status)
|
||||
* If not ending it
|
||||
* @param sd
|
||||
* @return 0:error, 1:check done
|
||||
@ -5497,7 +5497,6 @@ static void pc_checkallowskill(struct map_session_data *sd)
|
||||
SC_ADRENALINE2,
|
||||
SC_DANCING,
|
||||
SC_GATLINGFEVER,
|
||||
SC_FEARBREEZE
|
||||
};
|
||||
uint8 i;
|
||||
nullpo_retv(sd);
|
||||
@ -9471,40 +9470,33 @@ bool pc_equipitem(struct map_session_data *sd,short n,int req_pos)
|
||||
bool pc_unequipitem(struct map_session_data *sd, int n, int flag) {
|
||||
int i, iflag;
|
||||
bool status_cacl = false;
|
||||
|
||||
nullpo_retr(false,sd);
|
||||
|
||||
if (n < 0 || n >= MAX_INVENTORY) {
|
||||
clif_unequipitemack(sd,0,0,0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sd->status.inventory[n].equip) {
|
||||
clif_unequipitemack(sd,n,0,0);
|
||||
return false; //Nothing to unequip
|
||||
}
|
||||
// status change that makes player cannot unequip equipment
|
||||
if( !(flag&2) && sd->sc.count && (
|
||||
sd->sc.data[SC_BERSERK] ||
|
||||
if (!(flag&2) && sd->sc.count &&
|
||||
(sd->sc.data[SC_BERSERK] ||
|
||||
sd->sc.data[SC_SATURDAYNIGHTFEVER] ||
|
||||
sd->sc.data[SC__BLOODYLUST] ||
|
||||
sd->sc.data[SC_KYOUGAKU] ||
|
||||
(sd->sc.data[SC_PYROCLASTIC] && sd->inventory_data[n]->type == IT_WEAPON)) ) // can't switch weapon
|
||||
(sd->sc.data[SC_PYROCLASTIC] &&
|
||||
sd->inventory_data[n]->type == IT_WEAPON))) // can't switch weapon
|
||||
{
|
||||
clif_unequipitemack(sd,n,0,0);
|
||||
return false;
|
||||
}
|
||||
if (&sd->sc) {
|
||||
if (sd->sc.data[SC_HOVERING] && sd->inventory_data[n]->type == IT_ARMOR && sd->inventory_data[n]->nameid == ITEMID_HOVERING_BOOSTER)
|
||||
status_change_end(&sd->bl, SC_HOVERING, INVALID_TIMER);
|
||||
if (sd->sc.data[SC_HEAT_BARREL])
|
||||
status_change_end(&sd->bl,SC_HEAT_BARREL,INVALID_TIMER);
|
||||
if (sd->sc.data[SC_P_ALTER] && (sd->inventory_data[n]->type == IT_WEAPON || sd->inventory_data[n]->type == IT_AMMO))
|
||||
status_change_end(&sd->bl,SC_P_ALTER,INVALID_TIMER);
|
||||
}
|
||||
|
||||
if (battle_config.battle_log)
|
||||
ShowInfo("unequip %d %x:%x\n",n,pc_equippoint(sd,n),sd->status.inventory[n].equip);
|
||||
|
||||
if(!sd->status.inventory[n].equip){ //Nothing to unequip
|
||||
clif_unequipitemack(sd,n,0,0);
|
||||
return false;
|
||||
}
|
||||
for(i = 0; i < EQI_MAX; i++) {
|
||||
if (sd->status.inventory[n].equip & equip_pos[i])
|
||||
sd->equip_index[i] = -1;
|
||||
@ -9566,16 +9558,28 @@ bool pc_unequipitem(struct map_session_data *sd,int n,int flag) {
|
||||
|
||||
clif_unequipitemack(sd,n,sd->status.inventory[n].equip,1);
|
||||
|
||||
if((sd->status.inventory[n].equip & EQP_ARMS) && sd->inventory_data[n]->type == IT_WEAPON && //On weapon change (right and left hand)
|
||||
(!sd->sc.data[SC_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!)
|
||||
status_change_end(&sd->bl,SC_HEAT_BARREL,INVALID_TIMER);
|
||||
// On weapon change (right and left hand)
|
||||
if ((sd->status.inventory[n].equip & EQP_ARMS) && sd->inventory_data[n]->type == IT_WEAPON) {
|
||||
if (!sd->sc.data[SC_SEVENWIND] || sd->sc.data[SC_ASPERSIO]) //Check for seven wind (but not level seven!)
|
||||
skill_enchant_elemental_end(&sd->bl, SC_NONE);
|
||||
status_change_end(&sd->bl, SC_FEARBREEZE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EXEEDBREAK, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_P_ALTER, INVALID_TIMER);
|
||||
}
|
||||
|
||||
// On armor change
|
||||
if (sd->status.inventory[n].equip & EQP_ARMOR) {
|
||||
// On Armor Change...
|
||||
status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER);
|
||||
if (sd->sc.data[SC_HOVERING] && sd->inventory_data[n]->nameid == ITEMID_HOVERING_BOOSTER)
|
||||
status_change_end(&sd->bl, SC_HOVERING, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER); // No longer is removed? Need confirmation
|
||||
status_change_end(&sd->bl, SC_ARMOR_RESIST, INVALID_TIMER);
|
||||
}
|
||||
|
||||
// On ammo change
|
||||
if (sd->inventory_data[n]->type == IT_AMMO)
|
||||
status_change_end(&sd->bl, SC_P_ALTER, INVALID_TIMER);
|
||||
|
||||
if( sd->state.autobonus&sd->status.inventory[n].equip )
|
||||
sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish]
|
||||
|
||||
@ -9592,6 +9596,7 @@ bool pc_unequipitem(struct map_session_data *sd,int n,int flag) {
|
||||
else {
|
||||
for( i = 0; i < sd->inventory_data[n]->slot; i++ ) {
|
||||
struct item_data *data;
|
||||
|
||||
if (!sd->status.inventory[n].card[i])
|
||||
continue;
|
||||
if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) {
|
||||
|
@ -2766,10 +2766,10 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
|
||||
case 1: //Copied by Plagiarism
|
||||
{
|
||||
if (tsd->cloneskill_idx > 0 && tsd->status.skill[tsd->cloneskill_idx].flag == SKILL_FLAG_PLAGIARIZED) {
|
||||
clif_deleteskill(tsd,tsd->status.skill[tsd->cloneskill_idx].id);
|
||||
tsd->status.skill[tsd->cloneskill_idx].id = 0;
|
||||
tsd->status.skill[tsd->cloneskill_idx].lv = 0;
|
||||
tsd->status.skill[tsd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT;
|
||||
clif_deleteskill(tsd,tsd->status.skill[tsd->cloneskill_idx].id);
|
||||
}
|
||||
|
||||
lv = min(skill_lv,pc_checkskill(tsd,RG_PLAGIARISM)); //Copied level never be > player's RG_PLAGIARISM level
|
||||
@ -2786,10 +2786,10 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
|
||||
//Skill level copied depends on Reproduce skill that used
|
||||
lv = (tsc) ? tsc->data[SC__REPRODUCE]->val1 : 1;
|
||||
if( tsd->reproduceskill_idx > 0 && tsd->status.skill[tsd->reproduceskill_idx].flag == SKILL_FLAG_PLAGIARIZED ) {
|
||||
clif_deleteskill(tsd,tsd->status.skill[tsd->reproduceskill_idx].id);
|
||||
tsd->status.skill[tsd->reproduceskill_idx].id = 0;
|
||||
tsd->status.skill[tsd->reproduceskill_idx].lv = 0;
|
||||
tsd->status.skill[tsd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT;
|
||||
clif_deleteskill(tsd,tsd->status.skill[tsd->reproduceskill_idx].id);
|
||||
}
|
||||
|
||||
//Level dependent and limitation.
|
||||
@ -8799,14 +8799,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
break;
|
||||
|
||||
case AB_PRAEFATIO:
|
||||
if( sd == NULL || sd->status.party_id == 0 || flag&1 )
|
||||
clif_skill_nodamage(bl, bl, skill_id, skill_lv, sc_start4(src, bl, type, 100, skill_lv, 0, 0, ( sd->status.party_id ? party_foreachsamemap(party_sub_count, sd, 0) : 1 ), skill_get_time(skill_id, skill_lv)));
|
||||
if( !sd || sd->status.party_id == 0 || flag&1 )
|
||||
clif_skill_nodamage(bl, bl, skill_id, skill_lv, sc_start4(src, bl, type, 100, skill_lv, 0, 0, (sd && sd->status.party_id ? party_foreachsamemap(party_sub_count, sd, 0) : 1 ), skill_get_time(skill_id, skill_lv)));
|
||||
else if( sd )
|
||||
party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
|
||||
break;
|
||||
|
||||
case AB_CHEAL:
|
||||
if( sd == NULL || sd->status.party_id == 0 || flag&1 ) {
|
||||
if( !sd || sd->status.party_id == 0 || flag&1 ) {
|
||||
if( sd && tstatus && !battle_check_undead(tstatus->race, tstatus->def_ele) && !tsc->data[SC_BERSERK] ) {
|
||||
int partycount = (sd->status.party_id ? party_foreachsamemap(party_sub_count, sd, 0) : 0);
|
||||
|
||||
@ -8822,16 +8822,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
i = ~i + 1;
|
||||
status_heal(bl, i, 0, 0);
|
||||
}
|
||||
}
|
||||
else if( sd )
|
||||
} else if( sd )
|
||||
party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
|
||||
break;
|
||||
|
||||
case AB_ORATIO:
|
||||
if( flag&1 )
|
||||
sc_start(src,bl, type, 40 + 5 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv));
|
||||
else
|
||||
{
|
||||
else {
|
||||
map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_CHAR,
|
||||
src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
|
||||
clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
|
||||
@ -8839,7 +8837,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
break;
|
||||
|
||||
case AB_LAUDAAGNUS:
|
||||
if( flag&1 || sd == NULL || !sd->status.party_id ) {
|
||||
if( flag&1 || !sd || !sd->status.party_id ) {
|
||||
if( tsc && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE] || tsc->data[SC_BLIND] ||
|
||||
tsc->data[SC_BURNING] || tsc->data[SC_FREEZING] || tsc->data[SC_CRYSTALIZE])) {
|
||||
// Success Chance: (40 + 10 * Skill Level) %
|
||||
@ -8859,7 +8857,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
break;
|
||||
|
||||
case AB_LAUDARAMUS:
|
||||
if( flag&1 || sd == NULL || !sd->status.party_id ) {
|
||||
if( flag&1 || !sd || !sd->status.party_id ) {
|
||||
if( tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] || tsc->data[SC_SILENCE] || tsc->data[SC_DEEPSLEEP]) ){
|
||||
// Success Chance: (40 + 10 * Skill Level) %
|
||||
if( rnd()%100 > 40+10*skill_lv ) break;
|
||||
@ -8877,8 +8875,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
break;
|
||||
|
||||
case AB_CLEARANCE:
|
||||
if( flag&1 || (i = skill_get_splash(skill_id, skill_lv)) < 1 )
|
||||
{ //As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie]
|
||||
if( flag&1 || (i = skill_get_splash(skill_id, skill_lv)) < 1 ) { // As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie]
|
||||
|
||||
if( bl->type != BL_MOB && battle_check_target(src,bl,BCT_PARTY) <= 0 ) // Only affect mob or party.
|
||||
break;
|
||||
|
@ -536,7 +536,12 @@ void initChangeTables(void)
|
||||
set_sc( HLIF_CHANGE , SC_CHANGE , SI_BLANK , SCB_VIT|SCB_INT );
|
||||
set_sc( HFLI_FLEET , SC_FLEET , SI_BLANK , SCB_ASPD|SCB_BATK|SCB_WATK );
|
||||
set_sc( HFLI_SPEED , SC_SPEED , SI_BLANK , SCB_FLEE );
|
||||
set_sc( HAMI_DEFENCE , SC_DEFENCE , SI_BLANK , SCB_DEF );
|
||||
set_sc( HAMI_DEFENCE , SC_DEFENCE , SI_BLANK ,
|
||||
#ifndef RENEWAL
|
||||
SCB_DEF );
|
||||
#else
|
||||
SCB_VIT );
|
||||
#endif
|
||||
set_sc( HAMI_BLOODLUST , SC_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK );
|
||||
|
||||
/* Homunculus S */
|
||||
@ -8198,6 +8203,10 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
status_change_end(bl, SC_CURSE, INVALID_TIMER);
|
||||
if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
|
||||
status_change_end(bl, SC_STONE, INVALID_TIMER);
|
||||
if (sc->data[SC_CURSE]) {
|
||||
status_change_end(bl, SC_CURSE, INVALID_TIMER);
|
||||
return 1; // End Curse and do not give stat boost
|
||||
}
|
||||
}
|
||||
if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH)
|
||||
status_change_end(bl, SC_SPIRIT, INVALID_TIMER);
|
||||
@ -9815,14 +9824,14 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
tick_time = 10000; // [GodLesZ] tick time
|
||||
break;
|
||||
case SC_EXEEDBREAK:
|
||||
{
|
||||
short idx = -1;
|
||||
val1 *= 100; // 100 * skill_lv
|
||||
if( sd && (idx = sd->equip_index[EQI_HAND_R]) >= 0 && sd->inventory_data[idx] ) {
|
||||
val1 += (sd->inventory_data[idx]->weight/10 * sd->inventory_data[idx]->wlv * status_get_lv(bl) / 100);
|
||||
val1 += 10 * sd->status.job_level;
|
||||
}
|
||||
}
|
||||
val1 = 100 * val1;
|
||||
if (sd) { // Players
|
||||
short index = sd->equip_index[EQI_HAND_R];
|
||||
|
||||
if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON)
|
||||
val1 += 10 * sd->status.job_level + sd->inventory_data[index]->weight / 10 * sd->inventory_data[index]->wlv * status_get_lv(bl) / 100;
|
||||
} else // Monster
|
||||
val1 += 500;
|
||||
break;
|
||||
case SC_PRESTIGE:
|
||||
val2 = (status->int_ + status->luk) * val1 / 20 * status_get_lv(bl) / 200 + val1; // Chance to evade magic damage.
|
||||
|
Loading…
x
Reference in New Issue
Block a user