* Implemented first version of rebalanced Rune Knight skills.
* Implemented the rebalancing of most Archbishop skills. * As a result, merged r14979 from trunk. (act/notify packet update) * Added pc_isUseitem_check_runeskill care of Meyrawr (blocks rune usage based on skill delay.) * Added more status effects that do NOT save on log out. A whole slew of them. * Now only level 11 Dec. AGI will take the new config settings into account. * Fixed Level 11 Dec. AGI duration faux pas, where it was multiplying it by 100. * Added script command: setdragon: See documentation for details. * Added script command: successruneuse: Will return 0 or 1. Handles runestone backfire effects. * Modified script command: produce, now accepts <item id> as a second parameter. * Corrected message that is displayed when attempting to generate items when that item has a limit. * GM Item commands will no longer display 'Item created' messages on failure. git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/renewal@14983 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
1ccf4e3dc3
commit
f6b46546b1
@ -1,5 +1,18 @@
|
||||
Date Added
|
||||
|
||||
2011/10/26
|
||||
* Rev. 14982 Implemented first version of rebalanced Rune Knight skills. [L0ne_W0lf]
|
||||
* Implemented the rebalancing of most Archbishop skills.
|
||||
* As a result, merged r14979 from trunk. (act/notify packet update)
|
||||
* Added pc_isUseitem_check_runeskill care of Meyrawr (blocks rune usage based on skill delay.)
|
||||
* Added more status effects that do NOT save on log out. A whole slew of them.
|
||||
* Now only level 11 Dec. AGI will take the new config settings into account.
|
||||
* Fixed Level 11 Dec. AGI duration faux pas, where it was multiplying it by 100.
|
||||
* Added script command: setdragon: See documentation for details.
|
||||
* Added script command: successruneuse: Will return 0 or 1. Handles runestone backfire effects.
|
||||
* Modified script command: produce, now accepts <item id> as a second parameter.
|
||||
* Corrected message that is displayed when attempting to generate items when that item has a limit.
|
||||
* GM Item commands will no longer display 'Item created' messages on failure.
|
||||
2011/10/07
|
||||
* Merged changes from trunk [14895:14966/trunk]. [Ai4rei]
|
||||
2011/09/30
|
||||
|
@ -87,3 +87,11 @@ gtb_sc_immunity: 50
|
||||
// NOTE: Different cards that grant the same skill will both
|
||||
// always work independently of each other regardless of setting.
|
||||
autospell_stacking: no
|
||||
|
||||
// Rune consumption is blocked by the skill's cooldown (note 1)
|
||||
rune_block_by_skill: yes
|
||||
|
||||
// Rune consumption is blocked by previously activated status effect (Note 1)
|
||||
// associated with the skill the rune stone being used would cast.
|
||||
// ie: if SC_REFRESH is active, then the Nosiege Runestone is unuseable.
|
||||
rune_block_by_status: no
|
||||
|
@ -1828,7 +1828,7 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
|
||||
WBUFW(buf,50) = DEFAULT_WALK_SPEED; // p->speed;
|
||||
WBUFW(buf,52) = p->class_;
|
||||
WBUFW(buf,54) = p->hair;
|
||||
WBUFW(buf,56) = p->option&0x20 ? 0 : p->weapon; //When the weapon is sent and your option is riding, the client crashes on login!?
|
||||
WBUFW(buf,56) = p->option&0x7E80020 ? 0 : p->weapon; //When the weapon is sent and your option is riding, the client crashes on login!?
|
||||
WBUFW(buf,58) = p->base_level;
|
||||
WBUFW(buf,60) = min(p->skill_point, INT16_MAX);
|
||||
WBUFW(buf,62) = p->head_bottom;
|
||||
|
@ -1626,7 +1626,7 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p)
|
||||
WBUFW(buf,50) = DEFAULT_WALK_SPEED; // p->speed;
|
||||
WBUFW(buf,52) = p->class_;
|
||||
WBUFW(buf,54) = p->hair;
|
||||
WBUFW(buf,56) = p->option&0x20 ? 0 : p->weapon; //When the weapon is sent and your option is riding, the client crashes on login!?
|
||||
WBUFW(buf,56) = p->option&0x7E80020 ? 0 : p->weapon; //When the weapon is sent and your option is riding, the client crashes on login!?
|
||||
WBUFW(buf,58) = p->base_level;
|
||||
WBUFW(buf,60) = min(p->skill_point, INT16_MAX);
|
||||
WBUFW(buf,62) = p->head_bottom;
|
||||
|
@ -1710,7 +1710,8 @@ ACMD_FUNC(item)
|
||||
if(log_config.enable_logs&0x400)
|
||||
log_pick_pc(sd, "A", item_id, number, NULL);
|
||||
|
||||
clif_displaymessage(fd, msg_txt(18)); // Item created.
|
||||
if (!flag)
|
||||
clif_displaymessage(fd, msg_txt(18)); // Item created.
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1785,7 +1786,8 @@ ACMD_FUNC(item2)
|
||||
if(log_config.enable_logs&0x400)
|
||||
log_pick_pc(sd, "A", item_tmp.nameid, number, &item_tmp);
|
||||
|
||||
clif_displaymessage(fd, msg_txt(18)); // Item created.
|
||||
if (!flag)
|
||||
clif_displaymessage(fd, msg_txt(18)); // Item created.
|
||||
} else {
|
||||
clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name.
|
||||
return -1;
|
||||
|
204
src/map/battle.c
204
src/map/battle.c
@ -361,7 +361,26 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
|
||||
clif_skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if((sce=sc->data[SC_MILLENNIUMSHIELD]) && damage > 0) {
|
||||
if(sce->val2 > 0)
|
||||
{
|
||||
sce->val3 -= damage;
|
||||
if( sce->val3 <= 0 )
|
||||
{ // Reduce remaining shields and create new one.
|
||||
sc_start(bl,SC_STUN,15,0,1000);
|
||||
sce->val3 = 1000;
|
||||
sce->val2--;
|
||||
if( sd )
|
||||
clif_millenniumshield(sd,sce->val2);
|
||||
}
|
||||
|
||||
damage = 0; // Nullify damage even if shield is destroyed.
|
||||
}
|
||||
if(sce->val2 <= 0)
|
||||
status_change_end(bl, SC_MILLENNIUMSHIELD, INVALID_TIMER);
|
||||
}
|
||||
|
||||
if(sc->data[SC_DODGE] && !sc->opt1 &&
|
||||
(flag&BF_LONG || sc->data[SC_SPURT])
|
||||
&& rand()%100 < 20) {
|
||||
@ -415,7 +434,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
|
||||
}
|
||||
|
||||
//Finally damage reductions....
|
||||
if( sc->data[SC_ASSUMPTIO] )
|
||||
if( sc->data[SC_ASSUMPTIO] && skill_num != RK_DRAGONBREATH )
|
||||
{
|
||||
if( map_flag_vs(bl->m) )
|
||||
damage = damage*2/3; //Receive 66% damage
|
||||
@ -428,10 +447,11 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
|
||||
damage=damage*(100-sc->data[SC_DEFENDER]->val2)/100;
|
||||
|
||||
if(sc->data[SC_ADJUSTMENT] &&
|
||||
(flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
|
||||
(flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON) &&
|
||||
skill_num != RK_DRAGONBREATH)
|
||||
damage -= 20*damage/100;
|
||||
|
||||
if(sc->data[SC_FOGWALL]) {
|
||||
if(sc->data[SC_FOGWALL] && skill_num != RK_DRAGONBREATH) {
|
||||
if(flag&BF_SKILL) //25% reduction
|
||||
damage -= 25*damage/100;
|
||||
else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
|
||||
@ -493,7 +513,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
|
||||
//Finally Kyrie because it may, or not, reduce damage to 0.
|
||||
if((sce = sc->data[SC_KYRIE]) && damage > 0){
|
||||
sce->val2-=damage;
|
||||
if(flag&BF_WEAPON || skill_num == TF_THROWSTONE){
|
||||
if(flag&BF_WEAPON || skill_num == TF_THROWSTONE || skill_num == RK_DRAGONBREATH){
|
||||
if(sce->val2>=0)
|
||||
damage=0;
|
||||
else
|
||||
@ -503,6 +523,13 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
|
||||
status_change_end(bl, SC_KYRIE, INVALID_TIMER);
|
||||
}
|
||||
|
||||
if((sce = sc->data[SC_STONEHARDSKIN]) && damage > 0)
|
||||
{
|
||||
sce->val2-=damage; // Reduce Stone Skin's HP by damage taken.
|
||||
if( sce->val2 <= 0 )
|
||||
status_change_end(bl, SC_STONEHARDSKIN, INVALID_TIMER);
|
||||
}
|
||||
|
||||
if (!damage) return 0;
|
||||
|
||||
//Probably not the most correct place, but it'll do here
|
||||
@ -601,6 +628,7 @@ int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int dam
|
||||
case PA_PRESSURE:
|
||||
case HW_GRAVITATION:
|
||||
case NJ_ZENYNAGE:
|
||||
case RK_DRAGONBREATH:
|
||||
break;
|
||||
default:
|
||||
if( flag&BF_SKILL )
|
||||
@ -662,6 +690,7 @@ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int dama
|
||||
case PA_PRESSURE:
|
||||
case HW_GRAVITATION:
|
||||
case NJ_ZENYNAGE:
|
||||
case RK_DRAGONBREATH:
|
||||
break;
|
||||
default:
|
||||
if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
|
||||
@ -743,10 +772,13 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int
|
||||
case W_1HSPEAR:
|
||||
case W_2HSPEAR:
|
||||
if((skill = pc_checkskill(sd,KN_SPEARMASTERY)) > 0) {
|
||||
if(!pc_isriding(sd))
|
||||
if(!pc_isriding(sd) && !pc_isdragon(sd))
|
||||
damage += (skill * 4);
|
||||
else
|
||||
damage += (skill * 5);
|
||||
// increase damage by level of KN_SPEARMASTERY * 10
|
||||
if (pc_checkskill(sd,RK_DRAGONTRAINING) > 0)
|
||||
damage += (skill * 10);
|
||||
}
|
||||
break;
|
||||
case W_1HAXE:
|
||||
@ -990,7 +1022,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
|
||||
wd.type=0; //Normal attack
|
||||
wd.div_=skill_num?skill_get_num(skill_num,skill_lv):1;
|
||||
wd.amotion=(skill_num && skill_get_inf(skill_num)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills.
|
||||
if(skill_num == KN_AUTOCOUNTER)
|
||||
if(skill_num == KN_AUTOCOUNTER || skill_num == RK_DEATHBOUND)
|
||||
wd.amotion >>= 1;
|
||||
wd.dmotion=tstatus->dmotion;
|
||||
wd.blewcount=skill_get_blewcount(skill_num,skill_lv);
|
||||
@ -1063,6 +1095,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
|
||||
break;
|
||||
|
||||
case KN_AUTOCOUNTER:
|
||||
case RK_DEATHBOUND:
|
||||
wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL;
|
||||
break;
|
||||
|
||||
@ -1403,6 +1436,15 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
|
||||
if( (i = party_foreachsamemap(party_sub_count, sd, 0)) > 1 ) // exclude the player himself [Inkfish]
|
||||
ATK_ADDRATE(2*skill*i);
|
||||
}
|
||||
if(sd->status.party_id && sc && sc->data[SC_FIGHTINGSPIRIT])
|
||||
{
|
||||
i = party_foreachsamemap(party_sub_count, sd, 0);
|
||||
if( (sc->data[SC_FIGHTINGSPIRIT]->val2) > 0){
|
||||
ATK_ADDRATE(7*i); //Caster gets full effect.
|
||||
}else{
|
||||
ATK_ADDRATE(7*i/4); //Party members get 1/4.
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} //End default case
|
||||
@ -1725,6 +1767,62 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
|
||||
case NPC_VAMPIRE_GIFT:
|
||||
skillratio += ((skill_lv-1)%5+1)*100;
|
||||
break;
|
||||
case RK_SONICWAVE:
|
||||
skillratio += ((skill_lv + 5) * 100) * (1 + (status_get_lv(src) -100) / 200);
|
||||
break;
|
||||
case RK_HUNDREDSPEAR:
|
||||
{
|
||||
int weight = 1, dmg = 0;
|
||||
if (sd) {
|
||||
short index = sd->equip_index[EQI_HAND_R];
|
||||
|
||||
if (index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON)
|
||||
weight = sd->inventory_data[index]->weight; //80% of weight
|
||||
}
|
||||
|
||||
dmg = (600 + (skill_lv * 80) + (1000 - (weight>1000?1000:weight)) * ((1 + status_get_lv(src) - 100) / 200));
|
||||
|
||||
if(sd) // Add clashing spiral bonus damage (Skill level * 50% damage)
|
||||
dmg += pc_checkskill(sd,LK_SPIRALPIERCE) * (dmg * 50 /100);
|
||||
|
||||
skillratio = dmg;
|
||||
break;
|
||||
}
|
||||
case RK_WINDCUTTER:
|
||||
skillratio += ((skill_lv + 2) * 50) * status_get_lv(src) / 100;
|
||||
break;
|
||||
case RK_IGNITIONBREAK:
|
||||
{
|
||||
int dmg = 300; // Base maximum damage at less than 3 cells.
|
||||
i = distance_bl(src,target);
|
||||
if( i > 7 )
|
||||
dmg -= 100; // Greather than 7 cells. (200 damage)
|
||||
else if( i > 3 )
|
||||
dmg -= 50; // Greater than 3 cells, less than 7. (250 damage)
|
||||
|
||||
dmg = (dmg * skill_lv) * (1+ (status_get_lv(src) - 100) / 120);
|
||||
|
||||
// Elemental check, +100% damage if your element is fire.
|
||||
if( sstatus->rhw.ele == ELE_FIRE )
|
||||
dmg += skill_lv * 100 / 100;
|
||||
|
||||
skillratio = dmg;
|
||||
break;
|
||||
}
|
||||
case RK_CRUSHSTRIKE:
|
||||
if(sd)
|
||||
{
|
||||
short index = sd->equip_index[EQI_HAND_R];
|
||||
if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
|
||||
skillratio = (sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6) * 100) + sd->inventory_data[index]->atk + sd->inventory_data[index]->weight;
|
||||
}
|
||||
break;
|
||||
case RK_STORMBLAST:
|
||||
skillratio = ((sd?pc_checkskill(sd,RK_RUNEMASTERY):1) + (sstatus->int_ / 8)) * 100;
|
||||
break;
|
||||
case RK_PHANTOMTHRUST:
|
||||
skillratio = ((skill_lv * 50) + (sd?pc_checkskill(sd,KN_SPEARMASTERY):0) * 10) * status_get_lv(src) / 150;
|
||||
break;
|
||||
case AB_DUPLELIGHT_MELEE:
|
||||
skillratio += 10 * skill_lv;
|
||||
break;
|
||||
@ -2302,18 +2400,50 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
|
||||
wd.damage += md.damage;
|
||||
}
|
||||
|
||||
//SG_FUSION hp penalty [Komurka]
|
||||
if (sc && sc->data[SC_FUSION])
|
||||
{
|
||||
int hp= sstatus->max_hp;
|
||||
if (sd && tsd) {
|
||||
hp = 8*hp/100;
|
||||
if (100*sstatus->hp <= 20*sstatus->max_hp)
|
||||
hp = sstatus->hp;
|
||||
} else
|
||||
hp = 2*hp/100; //2% hp loss per hit
|
||||
status_zap(src, hp, 0);
|
||||
}
|
||||
if ( sc )
|
||||
{ // I don't see the point in repeating the SC check now that there are more things that use it. [L0ne_W0lf]
|
||||
if (sc->data[SC_FUSION])
|
||||
{ //SG_FUSION hp penalty [Komurka]
|
||||
int hp= sstatus->max_hp;
|
||||
if (sd && tsd) {
|
||||
hp = 8*hp/100;
|
||||
if (100*sstatus->hp <= 20*sstatus->max_hp)
|
||||
hp = sstatus->hp;
|
||||
} else
|
||||
hp = 2*hp/100; //2% hp loss per hit
|
||||
status_zap(src, hp, 0);
|
||||
}
|
||||
|
||||
if(sc->data[SC_ENCHANTBLADE] && !skill_num && wd.flag&BF_SHORT )
|
||||
{
|
||||
if (tsc && tsc->data[SC_SAFETYWALL])
|
||||
; // Although this is suposed to be considered a magic atttack, Safety Wall still blocks it? May be impemented wrong.
|
||||
else
|
||||
{
|
||||
struct Damage ebd = battle_calc_attack(BF_MAGIC,src,target,RK_ENCHANTBLADE,sc->data[SC_ENCHANTBLADE]->val1,wd.flag);
|
||||
wd.damage += (sc->data[SC_ENCHANTBLADE]->val1 * 20 + 100) * (status_get_lv(src) / 150) + sstatus->int_ + ebd.damage;
|
||||
}
|
||||
}
|
||||
|
||||
if(sc->data[SC_GIANTGROWTH] && !skill_num )
|
||||
{
|
||||
int rate = battle_config.equip_natural_break_rate;
|
||||
rate += 10;
|
||||
skill_break_equip(src, EQP_WEAPON, rate, BCT_SELF);
|
||||
if( rand() % 100 <= 10 )
|
||||
ATK_RATE(300);
|
||||
}
|
||||
|
||||
if(sc->data[SC_STONEHARDSKIN] && !skill_num)
|
||||
{ // SC_STRIPWEAPON will reduce damage by 25% so piggyback off that since there is no offensive status for this.
|
||||
int rate = battle_config.equip_natural_break_rate;
|
||||
rate += 300; //chance to break gear, or reduce attack by 25% in hte case of monsters.
|
||||
if( sd )
|
||||
skill_break_equip(src,EQP_WEAPON,rate,BCT_ENEMY);
|
||||
if (!sd && !(status_get_mode(src)&MD_BOSS))
|
||||
status_change_start(src,SC_STRIPWEAPON,rate,0,0,0,0,10000,0);
|
||||
}
|
||||
}
|
||||
|
||||
return wd;
|
||||
}
|
||||
@ -2526,17 +2656,13 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
||||
skillratio += 100 +100*skill_lv +100*(skill_lv/2);
|
||||
break;
|
||||
case AB_JUDEX:
|
||||
skillratio += ((skill_lv < 5)?180 + 20 * skill_lv:300); // Possible RE-Formula
|
||||
if( status_get_lv(src) >= 100 )
|
||||
skillratio = skillratio * status_get_lv(src) / 100;
|
||||
skillratio += ((skill_lv * 20) + 300) * status_get_lv(src) / 100;
|
||||
break;
|
||||
case AB_ADORAMUS:
|
||||
skillratio += 100 * (skill_lv + 5);
|
||||
if( status_get_lv(src) >= 100 )
|
||||
skillratio = skillratio * status_get_lv(src) / 100;
|
||||
skillratio += ((skill_lv * 100) + 500) * status_get_lv(src) / 100;
|
||||
break;
|
||||
case AB_DUPLELIGHT_MAGIC:
|
||||
skillratio += 100 + 20 * skill_lv;
|
||||
skillratio = 200 + 20 * skill_lv;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2830,6 +2956,8 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
|
||||
case NPC_EVILLAND:
|
||||
md.damage = skill_calc_heal(src,target,skill_num,skill_lv,false);
|
||||
break;
|
||||
case RK_DRAGONBREATH:
|
||||
md.damage = (sstatus->hp / 50 + sstatus->max_sp / 4) * (skill_lv * status_get_lv(src)/150) * (95 + 5 * (sd?pc_checkskill(sd,RK_DRAGONTRAINING):10)) / 100;
|
||||
}
|
||||
|
||||
if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
|
||||
@ -3198,7 +3326,19 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
|
||||
skill_addtimerskill(src,tick+status_get_adelay(src) / 2,target->id,0,0,AB_DUPLELIGHT_MAGIC,skilllv,BF_MAGIC,flag);
|
||||
}
|
||||
|
||||
rdamage = battle_calc_return_damage(target, damage, wd.flag);
|
||||
if(tsc && tsc->data[SC_DEATHBOUND] && !is_boss(src) && map_check_dir(map_calc_dir(src,target->x,target->y),unit_getdir(target)))
|
||||
{
|
||||
int skilllv = tsc->data[SC_DEATHBOUND]->val1;
|
||||
clif_skill_damage(src,src, tick, 0, 0, 0, 0, RK_DEATHBOUND,-1, 1);
|
||||
rdamage = wd.damage * ((500 + 100*skilllv) / 100);
|
||||
wd.damage = rdamage * 30 / 100;
|
||||
status_zap(target, wd.damage, 0);
|
||||
skill_blown(src, src, skill_get_blewcount(RK_DEATHBOUND,skilllv), unit_getdir(src), 0);
|
||||
status_change_end(target,SC_DEATHBOUND,INVALID_TIMER);
|
||||
}
|
||||
else
|
||||
rdamage = battle_calc_return_damage(target, damage, wd.flag);
|
||||
|
||||
if( rdamage > 0 )
|
||||
{
|
||||
rdelay = clif_damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0);
|
||||
@ -3259,6 +3399,11 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sc && sc->data[SC_CRUSHSTRIKE])
|
||||
{
|
||||
skill_castend_damage_id(src, target, RK_CRUSHSTRIKE, 1, tick, flag);
|
||||
status_change_end(src,SC_CRUSHSTRIKE, INVALID_TIMER);
|
||||
}
|
||||
if (sd) {
|
||||
if (wd.flag & BF_WEAPON && src != target && damage > 0) {
|
||||
if (battle_config.left_cardfix_to_right)
|
||||
@ -4055,10 +4200,13 @@ static const struct _battle_data {
|
||||
{ "bg_magic_attack_damage_rate", &battle_config.bg_magic_damage_rate, 60, 0, INT_MAX, },
|
||||
{ "bg_misc_attack_damage_rate", &battle_config.bg_misc_damage_rate, 60, 0, INT_MAX, },
|
||||
{ "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, },
|
||||
//MVP Decrease AGI
|
||||
// MVP Decrease AGI
|
||||
{ "max_decagi_lv", &battle_config.max_decagi_lv, 11, 1, INT_MAX, },
|
||||
{ "max_decagi_dur", &battle_config.max_decagi_dur, 120000, 1, INT_MAX, },
|
||||
{ "max_decagi", &battle_config.max_decagi, 50, 0, INT_MAX, },
|
||||
// Third jobs
|
||||
{ "rune_block_by_skill", &battle_config.rune_block_by_skill, 1, 0, 1, },
|
||||
{ "rune_block_by_status", &battle_config.rune_block_by_status, 0, 0, 1, },
|
||||
};
|
||||
|
||||
|
||||
|
@ -499,6 +499,8 @@ extern struct Battle_Config
|
||||
int max_decagi_lv;
|
||||
int max_decagi_dur;
|
||||
int max_decagi;
|
||||
int rune_block_by_skill;
|
||||
int rune_block_by_status;
|
||||
} battle_config;
|
||||
|
||||
void do_init_battle(void);
|
||||
|
@ -1193,6 +1193,8 @@ int clif_spawn(struct block_list *bl)
|
||||
clif_specialeffect(bl,421,AREA);
|
||||
if( sd->bg_id && map[sd->bl.m].flag.battleground )
|
||||
clif_sendbgemblem_area(sd);
|
||||
if(sd->sc.data[SC_MILLENNIUMSHIELD] && sd->sc.data[SC_MILLENNIUMSHIELD]->val2 > 0) // Ensure that we have shields to display.
|
||||
clif_millenniumshield(sd,sd->sc.data[SC_MILLENNIUMSHIELD]->val2);
|
||||
}
|
||||
break;
|
||||
case BL_MOB:
|
||||
@ -3819,8 +3821,8 @@ static int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int da
|
||||
|
||||
/*==========================================
|
||||
* Sends a 'damage' packet (src performs action on dst)
|
||||
* R 008a <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.W <div>.W <type>.B <damage2>.W
|
||||
* R 02e1 <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.L <div>.W <type>.B <damage2>.L
|
||||
* R 008a <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.W <div>.W <type>.B <damage2>.W (ZC_NOTIFY_ACT)
|
||||
* R 02e1 <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.L <div>.W <type>.B <damage2>.L (ZC_NOTIFY_ACT2)
|
||||
*
|
||||
* type=00 damage [param1: total damage, param2: div, param3: assassin dual-wield damage]
|
||||
* type=01 pick up item
|
||||
@ -3834,8 +3836,13 @@ static int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int da
|
||||
*------------------------------------------*/
|
||||
int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int damage, int div, int type, int damage2)
|
||||
{
|
||||
unsigned char buf[256];
|
||||
unsigned char buf[33];
|
||||
struct status_change *sc;
|
||||
#if PACKETVER < 20071113
|
||||
const int cmd = 0x8a;
|
||||
#else
|
||||
const int cmd = 0x2e1;
|
||||
#endif
|
||||
|
||||
nullpo_ret(src);
|
||||
nullpo_ret(dst);
|
||||
@ -3849,12 +3856,13 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic
|
||||
}
|
||||
}
|
||||
|
||||
WBUFW(buf,0)=0x8a;
|
||||
WBUFW(buf,0)=cmd;
|
||||
WBUFL(buf,2)=src->id;
|
||||
WBUFL(buf,6)=dst->id;
|
||||
WBUFL(buf,10)=tick;
|
||||
WBUFL(buf,14)=sdelay;
|
||||
WBUFL(buf,18)=ddelay;
|
||||
#if PACKETVER < 20071113
|
||||
if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) {
|
||||
WBUFW(buf,22)=damage?div:0;
|
||||
WBUFW(buf,27)=damage2?div:0;
|
||||
@ -3864,20 +3872,35 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic
|
||||
}
|
||||
WBUFW(buf,24)=div;
|
||||
WBUFB(buf,26)=type;
|
||||
#else
|
||||
if (battle_config.hide_woe_damage && map_flag_gvg(src->m)) {
|
||||
WBUFL(buf,22)=damage?div:0;
|
||||
WBUFL(buf,29)=damage2?div:0;
|
||||
} else {
|
||||
WBUFL(buf,22)=damage;
|
||||
WBUFL(buf,29)=damage2;
|
||||
}
|
||||
WBUFW(buf,26)=div;
|
||||
WBUFB(buf,28)=type;
|
||||
#endif
|
||||
if(disguised(dst)) {
|
||||
clif_send(buf,packet_len(0x8a),dst,AREA_WOS);
|
||||
clif_send(buf,packet_len(cmd),dst,AREA_WOS);
|
||||
WBUFL(buf,6) = -dst->id;
|
||||
clif_send(buf,packet_len(0x8a),dst,SELF);
|
||||
clif_send(buf,packet_len(cmd),dst,SELF);
|
||||
} else
|
||||
clif_send(buf,packet_len(0x8a),dst,AREA);
|
||||
clif_send(buf,packet_len(cmd),dst,AREA);
|
||||
|
||||
if(disguised(src)) {
|
||||
WBUFL(buf,2) = -src->id;
|
||||
if (disguised(dst))
|
||||
WBUFL(buf,6) = dst->id;
|
||||
if(damage > 0) WBUFW(buf,22) = -1;
|
||||
#if PACKETVER < 20071113
|
||||
if(damage2 > 0) WBUFW(buf,27) = -1;
|
||||
clif_send(buf,packet_len(0x8a),src,SELF);
|
||||
#else
|
||||
if(damage2 > 0) WBUFW(buf,29) = -1;
|
||||
#endif
|
||||
clif_send(buf,packet_len(cmd),src,SELF);
|
||||
}
|
||||
//Return adjusted can't walk delay for further processing.
|
||||
return clif_calc_walkdelay(dst,ddelay,type,damage+damage2,div);
|
||||
@ -8688,6 +8711,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
|
||||
if (sd->sc.option&OPTION_RIDING)
|
||||
clif_status_load(&sd->bl, SI_RIDING, 1);
|
||||
|
||||
if (sd->sc.option&OPTION_DRAGON)
|
||||
clif_status_load(&sd->bl, SI_RIDING, 1);
|
||||
|
||||
if(sd->status.manner < 0)
|
||||
sc_start(&sd->bl,SC_NOCHAT,100,0,0);
|
||||
|
||||
@ -8906,7 +8932,7 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd)
|
||||
return;
|
||||
}
|
||||
|
||||
if (sd->sc.opt1 && sd->sc.opt1 == OPT1_STONEWAIT)
|
||||
if (sd->sc.opt1 && (sd->sc.opt1 == OPT1_STONEWAIT || sd->sc.opt1 == OPT1_BURNING))
|
||||
; //You CAN walk on this OPT1 value.
|
||||
else if( sd->progressbar.npc_id )
|
||||
clif_progressbar_abort(sd);
|
||||
@ -9156,7 +9182,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
|
||||
if (sd->sc.count &&
|
||||
(sd->sc.data[SC_TRICKDEAD] ||
|
||||
sd->sc.data[SC_AUTOCOUNTER] ||
|
||||
sd->sc.data[SC_BLADESTOP]))
|
||||
sd->sc.data[SC_BLADESTOP] ||
|
||||
sd->sc.data[SC_DEATHBOUND]))
|
||||
return;
|
||||
|
||||
pc_stop_walking(sd, 1);
|
||||
@ -9202,7 +9229,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
|
||||
return;
|
||||
}
|
||||
|
||||
if (sd->ud.skilltimer != INVALID_TIMER || sd->sc.opt1)
|
||||
if (sd->ud.skilltimer != INVALID_TIMER || (sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING))
|
||||
break;
|
||||
|
||||
if (sd->sc.count && (
|
||||
@ -9498,6 +9525,7 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd)
|
||||
if (sd->sc.count && (
|
||||
sd->sc.data[SC_AUTOCOUNTER] ||
|
||||
sd->sc.data[SC_BLADESTOP] ||
|
||||
sd->sc.data[SC_DEATHBOUND] ||
|
||||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM)
|
||||
))
|
||||
break;
|
||||
@ -9524,7 +9552,7 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd)
|
||||
return;
|
||||
}
|
||||
|
||||
if (sd->sc.opt1 > 0 && sd->sc.opt1 != OPT1_STONEWAIT)
|
||||
if (sd->sc.opt1 > 0 && sd->sc.opt1 != OPT1_STONEWAIT && sd->sc.opt1 != OPT1_BURNING)
|
||||
return;
|
||||
|
||||
//This flag enables you to use items while in an NPC. [Skotlex]
|
||||
@ -9563,7 +9591,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd)
|
||||
if(sd->npc_id) {
|
||||
if (sd->npc_id != sd->npc_item_flag)
|
||||
return;
|
||||
} else if (sd->state.storage_flag || sd->sc.opt1)
|
||||
} else if (sd->state.storage_flag || (sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING))
|
||||
; //You can equip/unequip stuff while storage is open/under status changes
|
||||
else if (pc_cant_act(sd))
|
||||
return;
|
||||
@ -9919,7 +9947,7 @@ void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd)
|
||||
void clif_parse_RemoveOption(int fd,struct map_session_data *sd)
|
||||
{
|
||||
//Can only remove Cart/Riding/Falcon.
|
||||
pc_setoption(sd,sd->sc.option&~(OPTION_CART|OPTION_RIDING|OPTION_FALCON));
|
||||
pc_setoption(sd,sd->sc.option&~(OPTION_CART|OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON));
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
@ -14785,6 +14813,19 @@ void clif_search_store_info_click_ack(struct map_session_data* sd, short x, shor
|
||||
WFIFOSET(fd,packet_len(0x83d));
|
||||
}
|
||||
|
||||
// Correct packet for RK_MILLENIUMSHIELD. Shows spirit spheres.
|
||||
void clif_millenniumshield(struct map_session_data *sd, int num)
|
||||
{
|
||||
#if PACKETVER >= 20081217
|
||||
unsigned char buf[10];
|
||||
|
||||
WBUFW(buf,0)=0x440;
|
||||
WBUFL(buf,2)=sd->bl.id;
|
||||
WBUFW(buf,6)=num;
|
||||
WBUFW(buf,8)=0;
|
||||
clif_send(buf,packet_len(0x440),&sd->bl,AREA);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Parse function for packet debugging
|
||||
void clif_parse_debug(int fd,struct map_session_data *sd)
|
||||
@ -15088,7 +15129,7 @@ static int packetdb_readdb(void)
|
||||
//#0x02C0
|
||||
0, 0, 0, 0, 0, 30, 30, 0, 0, 3, 0, 65, 4, 71, 10, 0,
|
||||
0, 0, 0, 0, 29, 0, 6, -1, 10, 10, 3, 0, -1, 32, 6, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 59, 60, 8,
|
||||
0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 59, 60, 8,
|
||||
10, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
//#0x0300
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@ -15116,7 +15157,7 @@ static int packetdb_readdb(void)
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 25,
|
||||
//#0x0440
|
||||
0, 4, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
10, 4, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -626,4 +626,7 @@ void clif_search_store_info_failed(struct map_session_data* sd, unsigned char re
|
||||
void clif_open_search_store_info(struct map_session_data* sd);
|
||||
void clif_search_store_info_click_ack(struct map_session_data* sd, short x, short y);
|
||||
|
||||
// Third jobs
|
||||
void clif_millenniumshield(struct map_session_data *sd, int num);
|
||||
|
||||
#endif /* _CLIF_H_ */
|
||||
|
@ -1584,6 +1584,9 @@ int map_quit(struct map_session_data *sd)
|
||||
status_change_end(&sd->bl, SC_WEIGHT50, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WEIGHT90, INVALID_TIMER);
|
||||
if (battle_config.debuff_on_logout&1) {
|
||||
status_change_end(&sd->bl, SC_DECREASEAGI, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_AETERNA, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_ORCISH, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STRIPWEAPON, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STRIPARMOR, INVALID_TIMER);
|
||||
@ -1591,6 +1594,8 @@ int map_quit(struct map_session_data *sd)
|
||||
status_change_end(&sd->bl, SC_STRIPHELM, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EXTREMITYFIST, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_JOINTBEAT, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_MINDBREAKER, INVALID_TIMER);
|
||||
if(sd->sc.data[SC_REGENERATION] && sd->sc.data[SC_REGENERATION]->val4)
|
||||
status_change_end(&sd->bl, SC_REGENERATION, INVALID_TIMER);
|
||||
//TO-DO Probably there are way more NPC_type negative status that are removed
|
||||
@ -1601,12 +1606,61 @@ int map_quit(struct map_session_data *sd)
|
||||
}
|
||||
if (battle_config.debuff_on_logout&2)
|
||||
{
|
||||
status_change_end(&sd->bl, SC_MAGNIFICAT, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_MAXIMIZEPOWER, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_MAXOVERTHRUST, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_AURABLADE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_PARRYING, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CONCENTRATION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_MAGICPOWER, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_EDP, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_TRUESIGHT, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_WINDWALK, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_MELTDOWN, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_CARTBOOST, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_MEMORIZE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_DEVOTION, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SACRIFICE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STEELBODY, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_PRESERVE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_KAAHI, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_KAUPE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_DOUBLECAST, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SHRINK, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SIGHTBLASTER, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SPIRIT, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_KAITE, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_UTSUSEMI, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_BUNSINJYUTSU, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_SUITON, INVALID_TIMER);
|
||||
// Third jobs
|
||||
status_change_end(&sd->bl, SC_MILLENNIUMSHIELD, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_DEATHBOUND, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_REFRESH, INVALID_TIMER);
|
||||
status_change_end(&sd->bl, SC_STONEHARDSKIN, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_HALLUCINATIONWALK_POSTDELAY, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_WEAPONBLOCKING_POSTDELAY, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_ROLLINGCUTTER, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_ELECTRICSHOCKER, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_WUGDASH, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_WUGBITE, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_CAMOUFLAGE, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_MAGNETICFIELD, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_NEUTRALBARRIER, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_NEUTRALBARRIER_MASTER, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_STEALTHFIELD_MASTER, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_SHADOWFORM, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_INVISIBILITY, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_RAISINGDRAGON, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_NOEQUIPACCESSARY, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_MANHOLE, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_PROPERTYWALK, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_DEEP_SLEEP, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_WARMER, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_GN_TRAINING_SWORD, INVALID_TIMER);
|
||||
//status_change_end(&sd->bl, SC_GN_REMODELING_CART, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1311,7 +1311,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
|
||||
return false;
|
||||
|
||||
// Abnormalities
|
||||
if((md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT) || md->sc.data[SC_BLADESTOP])
|
||||
if((md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING) || md->sc.data[SC_BLADESTOP])
|
||||
{ //Should reset targets.
|
||||
md->target_id = md->attacked_id = 0;
|
||||
return false;
|
||||
|
82
src/map/pc.c
82
src/map/pc.c
@ -395,7 +395,7 @@ int pc_makesavestatus(struct map_session_data *sd)
|
||||
|
||||
//Only copy the Cart/Peco/Falcon options, the rest are handled via
|
||||
//status change load/saving. [Skotlex]
|
||||
sd->status.option = sd->sc.option&(OPTION_CART|OPTION_FALCON|OPTION_RIDING);
|
||||
sd->status.option = sd->sc.option&(OPTION_CART|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON);
|
||||
|
||||
if (sd->sc.data[SC_JAILED])
|
||||
{ //When Jailed, do not move last point.
|
||||
@ -3414,7 +3414,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount)
|
||||
|
||||
if( data->stack.inventory && amount > data->stack.amount )
|
||||
{// item stack limitation
|
||||
return 5;
|
||||
return 7;
|
||||
}
|
||||
|
||||
w = data->weight*amount;
|
||||
@ -3694,7 +3694,6 @@ int pc_isUseitem(struct map_session_data *sd,int n)
|
||||
if( nameid == 12243 && sd->md->db->lv < 80 )
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case 12213: //Neuralizer
|
||||
if( !map[sd->bl.m].flag.reset )
|
||||
return 0;
|
||||
@ -3704,6 +3703,9 @@ int pc_isUseitem(struct map_session_data *sd,int n)
|
||||
if( nameid >= 12153 && nameid <= 12182 && sd->md != NULL )
|
||||
return 0; // Mercenary Scrolls
|
||||
|
||||
if (nameid >= 12725 && nameid <= 12733 && !pc_isUseitem_check_runeskill(sd, sd->status.inventory[n].nameid) )
|
||||
return 0;
|
||||
|
||||
//added item_noequip.txt items check by Maya&[Lupus]
|
||||
if (
|
||||
(!map_flag_vs(sd->bl.m) && item->flag.no_equip&1) || // Normal
|
||||
@ -3742,6 +3744,45 @@ int pc_isUseitem(struct map_session_data *sd,int n)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int pc_isUseitem_check_runeskill(TBL_PC *sd, int nameid)
|
||||
{
|
||||
struct {
|
||||
int runeid;
|
||||
int skillid;
|
||||
} rune2skill_table[] = {
|
||||
{ 12725, RK_REFRESH },
|
||||
{ 12726, RK_CRUSHSTRIKE },
|
||||
{ 12727, RK_MILLENNIUMSHIELD },
|
||||
{ 12728, RK_VITALITYACTIVATION },
|
||||
{ 12729, RK_FIGHTINGSPIRIT },
|
||||
{ 12730, RK_ABUNDANCE },
|
||||
{ 12731, RK_GIANTGROWTH },
|
||||
{ 12732, RK_STORMBLAST },
|
||||
{ 12733, RK_STONEHARDSKIN },
|
||||
};
|
||||
|
||||
int i;
|
||||
int skillid;
|
||||
|
||||
nullpo_retr(0, sd);
|
||||
|
||||
ARR_FIND(0, ARRAYLENGTH(rune2skill_table), i, rune2skill_table[i].runeid == nameid);
|
||||
if ( i == ARRAYLENGTH(rune2skill_table) ) {
|
||||
ShowError("pc_isUseitem_check_runeskill: rune %d skill not found.\n", nameid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
skillid = rune2skill_table[i].skillid;
|
||||
if ( battle_config.rune_block_by_skill && skillnotok(skillid, sd) )
|
||||
return 0;
|
||||
if ( battle_config.rune_block_by_status && status_skill2sc(skillid) != SC_NONE && sd->sc.data[status_skill2sc(skillid)] )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*==========================================
|
||||
* アイテムを使う
|
||||
*------------------------------------------*/
|
||||
@ -5748,6 +5789,8 @@ int pc_resetskill(struct map_session_data* sd, int flag)
|
||||
i &= ~OPTION_CART;
|
||||
if( i&OPTION_FALCON && pc_checkskill(sd, HT_FALCON) )
|
||||
i &= ~OPTION_FALCON;
|
||||
if( i&OPTION_DRAGON && pc_checkskill(sd, KN_RIDING) ) //RK_DRAGONTRAINING not needed for riding (bug?), assuming KN_RIDING is.
|
||||
i&=~OPTION_DRAGON;
|
||||
|
||||
if( i != sd->sc.option )
|
||||
pc_setoption(sd, i);
|
||||
@ -6522,6 +6565,13 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
|
||||
sp -= sp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100;
|
||||
}
|
||||
|
||||
if (sd->sc.data[SC_VITALITYACTIVATION])
|
||||
{
|
||||
hp += hp * sd->sc.data[SC_VITALITYACTIVATION]->val2 / 100; //HP +50%
|
||||
sp -= sp * sd->sc.data[SC_VITALITYACTIVATION]->val3 / 100; //SP -50%
|
||||
}
|
||||
|
||||
|
||||
return status_heal(&sd->bl, hp, sp, 1);
|
||||
}
|
||||
|
||||
@ -6676,6 +6726,8 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
|
||||
i&=~OPTION_CART;
|
||||
if(i&OPTION_FALCON && !pc_checkskill(sd, HT_FALCON))
|
||||
i&=~OPTION_FALCON;
|
||||
if(i&OPTION_DRAGON && !pc_checkskill(sd, KN_RIDING)) //RK_DRAGONTRAINING not needed for riding (bug?), assuming KN_RIDING is.
|
||||
i&=~OPTION_DRAGON;
|
||||
|
||||
if(i != sd->sc.option)
|
||||
pc_setoption(sd, i);
|
||||
@ -6804,12 +6856,16 @@ int pc_setoption(struct map_session_data *sd,int type)
|
||||
sd->sc.option=type;
|
||||
clif_changeoption(&sd->bl);
|
||||
|
||||
if (type&OPTION_RIDING && !(p_type&OPTION_RIDING) && (sd->class_&MAPID_BASEMASK) == MAPID_SWORDMAN)
|
||||
if (((type&OPTION_RIDING && !(p_type&OPTION_RIDING)) // Knight and Crusader/Royal Guard
|
||||
|| (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON))) // Rune Knight Dragon
|
||||
&& (sd->class_&MAPID_BASEMASK) == MAPID_SWORDMAN)
|
||||
{ //We are going to mount. [Skotlex]
|
||||
clif_status_load(&sd->bl,SI_RIDING,1);
|
||||
status_calc_pc(sd,0); //Mounting/Umounting affects walk and attack speeds.
|
||||
}
|
||||
else if (!(type&OPTION_RIDING) && p_type&OPTION_RIDING && (sd->class_&MAPID_BASEMASK) == MAPID_SWORDMAN)
|
||||
else if (((!(type&OPTION_RIDING) && p_type&OPTION_RIDING) //Knight and Crusader/Royal Guard
|
||||
|| (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON)) // Rune Knight Dragon
|
||||
&& (sd->class_&MAPID_BASEMASK) == MAPID_SWORDMAN)
|
||||
{ //We are going to dismount.
|
||||
clif_status_load(&sd->bl,SI_RIDING,0);
|
||||
status_calc_pc(sd,0); //Mounting/Umounting affects walk and attack speeds.
|
||||
@ -6926,6 +6982,22 @@ int pc_setriding(TBL_PC* sd, int flag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Enable Riding Dragons for Rune Knight class.
|
||||
*------------------------------------------*/
|
||||
int pc_setdragon(TBL_PC* sd, int flag, int color)
|
||||
{
|
||||
int dragon[5] = {OPTION_DRAGON1,OPTION_DRAGON2,OPTION_DRAGON3,OPTION_DRAGON4,OPTION_DRAGON5};
|
||||
|
||||
if( flag ){
|
||||
if( pc_checkskill(sd,KN_RIDING) > 0 ) //Possible to rent dragons without RK_DRAGONTRAINING; Source, iRO. (Bug?)
|
||||
pc_setoption(sd, sd->sc.option|dragon[color]);
|
||||
} else if( pc_isdragon(sd) ){
|
||||
pc_setoption(sd, sd->sc.option&~OPTION_DRAGON);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*==========================================
|
||||
* アイテムドロップ可不可判定
|
||||
*------------------------------------------*/
|
||||
|
@ -420,6 +420,8 @@ struct map_session_data {
|
||||
unsigned int bg_id;
|
||||
unsigned short user_font;
|
||||
|
||||
int produce_itemusedid; //used to determine the type of item used when creating items via script.
|
||||
|
||||
// temporary debugging of bug #3504
|
||||
const char* delunit_prevfile;
|
||||
int delunit_prevline;
|
||||
@ -526,7 +528,7 @@ enum equip_index {
|
||||
#define pc_issit(sd) ( (sd)->vd.dead_sit == 2 )
|
||||
#define pc_isidle(sd) ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share )
|
||||
#define pc_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading )
|
||||
#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || (sd)->sc.opt1 || (sd)->state.trading || (sd)->state.storage_flag )
|
||||
#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag )
|
||||
#define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) )
|
||||
#define pc_setchatid(sd,n) ( (sd)->chatID = n )
|
||||
#define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) )
|
||||
@ -539,6 +541,7 @@ enum equip_index {
|
||||
#define pc_is50overweight(sd) ( (sd)->weight*100 >= (sd)->max_weight*battle_config.natural_heal_weight_rate )
|
||||
#define pc_is90overweight(sd) ( (sd)->weight*10 >= (sd)->max_weight*9 )
|
||||
#define pc_maxparameter(sd) ( ((sd)->class_&JOBL_3 ? ((sd)->class_&JOBL_BABY ? battle_config.max_baby_third_parameter : battle_config.max_third_parameter) : ((sd)->class_&JOBL_BABY ? battle_config.max_baby_parameter : battle_config.max_parameter)) )
|
||||
#define pc_isdragon(sd) ( (sd)->sc.option&OPTION_DRAGON )
|
||||
|
||||
#define pc_stop_walking(sd, type) unit_stop_walking(&(sd)->bl, type)
|
||||
#define pc_stop_attack(sd) unit_stop_attack(&(sd)->bl)
|
||||
@ -664,6 +667,7 @@ int pc_equipitem(struct map_session_data*,int,int);
|
||||
int pc_unequipitem(struct map_session_data*,int,int);
|
||||
int pc_checkitem(struct map_session_data*);
|
||||
int pc_useitem(struct map_session_data*,int);
|
||||
int pc_isUseitem_check_runeskill(TBL_PC *sd, int nameid);
|
||||
|
||||
int pc_skillatk_bonus(struct map_session_data *sd, int skill_num);
|
||||
int pc_skillheal_bonus(struct map_session_data *sd, int skill_num);
|
||||
@ -682,6 +686,7 @@ int pc_setfalcon(struct map_session_data* sd, int flag);
|
||||
int pc_setriding(struct map_session_data* sd, int flag);
|
||||
int pc_changelook(struct map_session_data *,int,int);
|
||||
int pc_equiplookall(struct map_session_data *sd);
|
||||
int pc_setdragon(struct map_session_data* sd, int flag, int color);
|
||||
|
||||
int pc_readparam(struct map_session_data*,int);
|
||||
int pc_setparam(struct map_session_data*,int,int);
|
||||
|
134
src/map/script.c
134
src/map/script.c
@ -7426,7 +7426,7 @@ BUILDIN_FUNC(setoption)
|
||||
flag = script_getnum(st,3);
|
||||
else if( !option ){// Request to remove everything.
|
||||
flag = 0;
|
||||
option = OPTION_CART|OPTION_FALCON|OPTION_RIDING;
|
||||
option = OPTION_CART|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON;
|
||||
}
|
||||
if( flag ){// Add option
|
||||
if( option&OPTION_WEDDING && !battle_config.wedding_modifydisplay )
|
||||
@ -7542,7 +7542,7 @@ BUILDIN_FUNC(checkriding)
|
||||
if( sd == NULL )
|
||||
return 0;// no player attached, report source
|
||||
|
||||
if( pc_isriding(sd) )
|
||||
if( pc_isriding(sd) || pc_isdragon(sd) )
|
||||
script_pushint(st, 1);
|
||||
else
|
||||
script_pushint(st, 0);
|
||||
@ -7571,6 +7571,31 @@ BUILDIN_FUNC(setriding)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Sets if the player is riding a dragon.
|
||||
/// <flag> defaults to 1
|
||||
/// <color> defaults to 0
|
||||
///
|
||||
/// setdragon <flag>{,<color>};
|
||||
/// setdragon <flag>;
|
||||
/// setdragon;
|
||||
BUILDIN_FUNC(setdragon)
|
||||
{
|
||||
int flag = 1, color = 0;
|
||||
TBL_PC* sd;
|
||||
|
||||
sd = script_rid2sd(st);
|
||||
if( sd == NULL )
|
||||
return 0;// no player attached, report source
|
||||
|
||||
if( script_hasdata(st,2) )
|
||||
flag = script_getnum(st,2);
|
||||
if( script_hasdata(st,3) )
|
||||
color = cap_value(script_getnum(st,3),0,4);
|
||||
|
||||
pc_setdragon(sd, flag, color);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Sets the save point of the player.
|
||||
///
|
||||
/// save "<map name>",<x>,<y>
|
||||
@ -7762,6 +7787,28 @@ BUILDIN_FUNC(produce)
|
||||
sd = script_rid2sd(st);
|
||||
if( sd == NULL )
|
||||
return 0;
|
||||
|
||||
if( script_hasdata(st,3) )
|
||||
{ // only used with Rune Knights RK_RUNEMASTERY as part of the calculation.
|
||||
struct item_data* id = NULL;
|
||||
struct script_data* data;
|
||||
|
||||
data = script_getdata(st,3);
|
||||
get_val(st, data);
|
||||
|
||||
if( data_isstring(data) )
|
||||
id = itemdb_searchname(conv_str(st, data));
|
||||
else
|
||||
id = itemdb_exists(conv_num(st, data));
|
||||
|
||||
if( id == NULL )
|
||||
{
|
||||
ShowError("buildin_produce: Invalid item '%s'.\n", script_getstr(st,3));
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
sd->produce_itemusedid = id->nameid;
|
||||
}
|
||||
|
||||
trigger=script_getnum(st,2);
|
||||
clif_skill_produce_mix_list(sd, trigger);
|
||||
@ -14945,6 +14992,85 @@ BUILDIN_FUNC(searchstores)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Returns the successful use of a Rune Knight Runestone.
|
||||
///
|
||||
/// SuccessRuneUse()
|
||||
///
|
||||
BUILDIN_FUNC(successruneuse)
|
||||
{
|
||||
struct item_data* id = NULL;
|
||||
struct map_session_data* sd;
|
||||
struct script_data* data;
|
||||
|
||||
if( ( sd = script_rid2sd(st) ) == NULL )
|
||||
return 0; // no player attached, report source
|
||||
|
||||
data = script_getdata(st,2);
|
||||
get_val(st, data); // convert into value in case of a variable
|
||||
|
||||
if( data_isstring(data) )
|
||||
id = itemdb_searchname(conv_str(st, data));
|
||||
else
|
||||
id = itemdb_exists(conv_num(st, data));
|
||||
|
||||
if( id == NULL )
|
||||
{
|
||||
ShowError("buildin_successruneuse: Invalid item '%s'.\n", script_getstr(st,2));
|
||||
script_pushint(st,0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( (sd->class_&~(JOBL_UPPER|JOBL_BABY)) == MAPID_RUNE_KNIGHT )
|
||||
{
|
||||
int skilllv = pc_checkskill(sd,RK_RUNEMASTERY);
|
||||
int i = (sd->status.dex + sd->status.luk ) / 20 + (skilllv?55+skilllv:0) + 30;
|
||||
|
||||
if (rand() % 100 < i)
|
||||
script_pushint(st, 1);
|
||||
else
|
||||
{
|
||||
script_pushint(st, 0);
|
||||
|
||||
i = rand() % 100; // reroll for fail effects
|
||||
if( i < 3 )
|
||||
{
|
||||
long damage = (1000 * id->weight) - (sd->battle_status.mdef + sd->battle_status.mdef2);
|
||||
clif_damage(&sd->bl, &sd->bl, gettick(), 0, 0, damage, 0, 0, 0);
|
||||
status_damage(&sd->bl, &sd->bl, damage, 0, 0, 0);
|
||||
}
|
||||
else if( i < 13 )
|
||||
{ // Random status effect
|
||||
struct {
|
||||
sc_type type;
|
||||
int duration;
|
||||
} effects[] = {
|
||||
{ SC_FREEZE, 30000 },
|
||||
{ SC_STUN, 5000 },
|
||||
{ SC_SLEEP, 20000 },
|
||||
{ SC_SILENCE, 20000 },
|
||||
{ SC_BLIND, 20000 },
|
||||
};
|
||||
i = rand()%ARRAYLENGTH(effects); // redesignate i to random status effect+duration.
|
||||
sc_start(&sd->bl, effects[i].type, 100, 1, effects[i].duration);
|
||||
}
|
||||
else if( i < 15 )
|
||||
pc_randomwarp(sd, CLR_TELEPORT);
|
||||
else if( i < 18 )
|
||||
; // Unknown effect, however weight of the item used is taken into account.
|
||||
else if( i < 19 )
|
||||
{
|
||||
if (!status_isimmune(&sd->bl))
|
||||
status_percent_heal(&sd->bl, 100, 100);
|
||||
}
|
||||
else if( i >= 20 )
|
||||
; // Unknown effect
|
||||
}
|
||||
}
|
||||
else
|
||||
script_pushint(st, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// declarations that were supposed to be exported from npc_chat.c
|
||||
#ifdef PCRE_SUPPORT
|
||||
@ -15054,6 +15180,7 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(setfalcon,"?"),
|
||||
BUILDIN_DEF(checkfalcon,""),
|
||||
BUILDIN_DEF(setriding,"?"),
|
||||
BUILDIN_DEF(setdragon,"??"),
|
||||
BUILDIN_DEF(checkriding,""),
|
||||
BUILDIN_DEF2(savepoint,"save","sii"),
|
||||
BUILDIN_DEF(savepoint,"sii"),
|
||||
@ -15063,7 +15190,7 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(openstorage,""),
|
||||
BUILDIN_DEF(guildopenstorage,""),
|
||||
BUILDIN_DEF(itemskill,"vi"),
|
||||
BUILDIN_DEF(produce,"i"),
|
||||
BUILDIN_DEF(produce,"i?"),
|
||||
BUILDIN_DEF(cooking,"i"),
|
||||
BUILDIN_DEF(monster,"siisii?"),
|
||||
BUILDIN_DEF(getmobdrops,"i"),
|
||||
@ -15310,6 +15437,7 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(pushpc,"ii"),
|
||||
BUILDIN_DEF(buyingstore,"i"),
|
||||
BUILDIN_DEF(searchstores,"ii"),
|
||||
BUILDIN_DEF(successruneuse,"?"),
|
||||
// WoE SE
|
||||
BUILDIN_DEF(agitstart2,""),
|
||||
BUILDIN_DEF(agitend2,""),
|
||||
|
276
src/map/skill.c
276
src/map/skill.c
@ -311,7 +311,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, int skill
|
||||
// Calculate base heal rate
|
||||
hp = ( ( ( status_get_lv(src) + status_get_int(src) ) / 5) * 30 ) * skill / 10;
|
||||
|
||||
// Increment skill and status based modifiers
|
||||
// Increment heal by skill/type modifiers
|
||||
if( sd && ((skill = pc_checkskill(sd, HP_MEDITATIO)) > 0) )
|
||||
mod += skill * 2;
|
||||
else if( src->type == BL_HOM && (skill = merc_hom_checkskill(((TBL_HOM*)src), HLIF_BRAIN)) > 0 )
|
||||
@ -319,7 +319,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, int skill
|
||||
break;
|
||||
}
|
||||
|
||||
// Increment skill and status based modifiers
|
||||
// Increment heal by item-based modifiers
|
||||
if( sd && (skill = pc_skillheal_bonus(sd, skill_id)) )
|
||||
mod += skill;
|
||||
if( tsd && (skill = pc_skillheal2_bonus(tsd, skill_id)) )
|
||||
@ -332,8 +332,8 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, int skill
|
||||
mod -= sc->data[SC_CRITICALWOUND]->val2;
|
||||
if( sc->data[SC_INCHEALRATE] && skill_id != NPC_EVILLAND && skill_id != BA_APPLEIDUN )
|
||||
mod += sc->data[SC_INCHEALRATE]->val1; // Only affects Heal, Sanctuary and PotionPitcher.(like bHealPower) [Inkfish]
|
||||
// if( sc->data[SC_VITALITYACTIVATION] && heal && skill_id != BA_APPLEIDUN )
|
||||
// mod += sc->data[SC_VITALITYACTIVATION]->val2;
|
||||
if( sc->data[SC_VITALITYACTIVATION] && heal && skill_id != BA_APPLEIDUN )
|
||||
mod += sc->data[SC_VITALITYACTIVATION]->val2;
|
||||
}
|
||||
|
||||
// Adjust the HP recovered rate by adding all of the modifiers together.
|
||||
@ -981,9 +981,19 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
|
||||
case NPC_CRITICALWOUND:
|
||||
sc_start(bl,SC_CRITICALWOUND,100,skilllv,skill_get_time2(skillid,skilllv));
|
||||
break;
|
||||
case RK_WINDCUTTER:
|
||||
sc_start(bl,SC_FEAR,3+2*skilllv,skilllv,skill_get_time(skillid,skilllv));
|
||||
break;
|
||||
case RK_DRAGONBREATH:
|
||||
sc_start4(bl,SC_BURNING,15,skilllv,src->id,0,0,skill_get_time(skillid,skilllv));
|
||||
break;
|
||||
case AB_ADORAMUS:
|
||||
sc_start(bl, SC_BLIND, 100, skilllv, skill_get_time(skillid, skilllv));
|
||||
sc_start(bl, SC_ADORAMUS, 100, skilllv, skill_get_time2(skillid, skilllv));
|
||||
if ( sd )
|
||||
{
|
||||
int rate = (skilllv*4) + sd->status.job_level / 2;
|
||||
sc_start(bl, SC_BLIND, rate, skilllv, skill_get_time(skillid, skilllv));
|
||||
sc_start(bl, SC_ADORAMUS, rate, skilllv, skill_get_time2(skillid, skilllv));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1734,8 +1744,19 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
|
||||
|
||||
if( damage > 0 && dmg.flag&BF_WEAPON && src != bl && ( src == dsrc || ( dsrc->type == BL_SKILL && ( skillid == SG_SUN_WARM || skillid == SG_MOON_WARM || skillid == SG_STAR_WARM ) ) )
|
||||
&& skillid != WS_CARTTERMINATION )
|
||||
rdamage = battle_calc_return_damage(bl, damage, dmg.flag);
|
||||
|
||||
{
|
||||
if( sc && sc->data[SC_DEATHBOUND] && !is_boss(bl) && map_check_dir(map_calc_dir(src,bl->x,bl->y),unit_getdir(bl)))
|
||||
{
|
||||
int skilllv = sc->data[SC_DEATHBOUND]->val1;
|
||||
clif_skill_damage(src,src, tick, 0, 0, 0, 0, RK_DEATHBOUND,-1, 1);
|
||||
rdamage = damage * ((500 + 100*skilllv) / 100);
|
||||
damage = rdamage * 70 / 100;
|
||||
skill_blown(src, src, skill_get_blewcount(skillid,skilllv), unit_getdir(src), 0);
|
||||
status_change_end(dsrc,SC_DEATHBOUND,INVALID_TIMER);
|
||||
}
|
||||
else
|
||||
rdamage = battle_calc_return_damage(bl, damage, dmg.flag);
|
||||
}
|
||||
//Skill hit type
|
||||
type=(skillid==0)?5:skill_get_hit(skillid);
|
||||
|
||||
@ -1851,6 +1872,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
|
||||
case NPC_CRITICALSLASH:
|
||||
case TF_DOUBLE:
|
||||
case GS_CHAINACTION:
|
||||
case RK_DEATHBOUND:
|
||||
dmg.dmotion = clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2);
|
||||
break;
|
||||
|
||||
@ -1994,6 +2016,9 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
|
||||
skill_additional_effect(bl, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
|
||||
}
|
||||
|
||||
if( damage > 0 && skillid == RK_CRUSHSTRIKE )
|
||||
skill_break_equip(src,EQP_WEAPON,2000,BCT_SELF);
|
||||
|
||||
if (!(flag&2) &&
|
||||
(
|
||||
skillid == MG_COLDBOLT || skillid == MG_FIREBOLT || skillid == MG_LIGHTNINGBOLT
|
||||
@ -2402,6 +2427,16 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case RK_HUNDREDSPEAR:
|
||||
if(src->type == BL_PC)
|
||||
{
|
||||
int skill_lv = pc_checkskill((struct map_session_data *)src,KN_SPEARBOOMERANG);
|
||||
if(skill_lv > 0)
|
||||
skill_attack(BF_WEAPON,src,src,target,KN_SPEARBOOMERANG,skill_lv,tick,skl->flag);
|
||||
}
|
||||
else
|
||||
skill_attack(BF_WEAPON,src,src,target,KN_SPEARBOOMERANG,1,tick,skl->flag);
|
||||
break;
|
||||
default:
|
||||
skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
|
||||
break;
|
||||
@ -2625,6 +2660,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
|
||||
case NPC_BLEEDING:
|
||||
case NPC_CRITICALWOUND:
|
||||
case NPC_HELLPOWER:
|
||||
case RK_SONICWAVE:
|
||||
case RK_WINDCUTTER:
|
||||
case AB_DUPLELIGHT_MELEE:
|
||||
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
|
||||
break;
|
||||
@ -3068,6 +3105,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
|
||||
case NPC_SMOKING:
|
||||
case GS_FLING:
|
||||
case NJ_ZENYNAGE:
|
||||
case RK_DRAGONBREATH:
|
||||
skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
|
||||
break;
|
||||
|
||||
@ -3124,6 +3162,18 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
|
||||
status_change_end(src, SC_HIDING, INVALID_TIMER);
|
||||
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
|
||||
break;
|
||||
|
||||
case RK_HUNDREDSPEAR:
|
||||
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
|
||||
if(rand()%100 < (10 + 3*skilllv)) {
|
||||
skill_blown(src,bl,6,-1,0);
|
||||
skill_addtimerskill(src,tick+800,bl->id,0,0,skillid,skilllv,BF_WEAPON,flag);
|
||||
}
|
||||
break;
|
||||
case RK_CRUSHSTRIKE:
|
||||
if( sd )
|
||||
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
|
||||
break;
|
||||
case 0:
|
||||
if(sd) {
|
||||
if (flag & 3){
|
||||
@ -3371,9 +3421,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
|
||||
case AL_DECAGI:
|
||||
case MER_DECAGI:
|
||||
if (skilllv >= battle_config.max_decagi_lv)
|
||||
if (skilllv = battle_config.max_decagi_lv)
|
||||
clif_skill_nodamage (src, bl, skillid, skilllv,
|
||||
sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), (battle_config.max_decagi - 2), (battle_config.max_decagi_dur * 100)));
|
||||
sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), (battle_config.max_decagi - 2), battle_config.max_decagi_dur));
|
||||
else
|
||||
clif_skill_nodamage (src, bl, skillid, skilllv,
|
||||
sc_start(bl, type, (40 + skilllv * 2 + (status_get_lv(src) + sstatus->int_)/5), skilllv, skill_get_time(skillid,skilllv)));
|
||||
@ -3729,6 +3779,13 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
case ST_PRESERVE:
|
||||
case NPC_INVINCIBLE:
|
||||
case NPC_INVINCIBLEOFF:
|
||||
case RK_DEATHBOUND:
|
||||
case RK_MILLENNIUMSHIELD:
|
||||
case RK_CRUSHSTRIKE:
|
||||
case RK_GIANTGROWTH:
|
||||
case RK_STONEHARDSKIN:
|
||||
case RK_VITALITYACTIVATION:
|
||||
case RK_ABUNDANCE:
|
||||
case AB_RENOVATIO:
|
||||
case AB_EXPIATIO:
|
||||
case AB_DUPLELIGHT:
|
||||
@ -4099,6 +4156,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
case BS_ADRENALINE2:
|
||||
case BS_WEAPONPERFECT:
|
||||
case BS_OVERTHRUST:
|
||||
case RK_FIGHTINGSPIRIT: //Splash range in skill_db is 0, should be map-wide according to party_foreachsamemap
|
||||
if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) {
|
||||
clif_skill_nodamage(bl,bl,skillid,skilllv,
|
||||
sc_start2(bl,type,100,skilllv,(src == bl)? 1:0,skill_get_time(skillid,skilllv)));
|
||||
@ -5743,6 +5801,74 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
clif_skill_nodamage(src, bl, skillid, skilllv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS));
|
||||
}
|
||||
break;
|
||||
case RK_ENCHANTBLADE:
|
||||
i = status_get_int(src) + status_get_lv(src) / 10;
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,
|
||||
sc_start(bl,type,100,i,skill_get_time(skillid,skilllv)));
|
||||
break;
|
||||
case RK_IGNITIONBREAK:
|
||||
if(flag&1)
|
||||
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
|
||||
else
|
||||
{
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
||||
map_foreachinrange(skill_area_sub, bl,
|
||||
skill_get_splash(skillid, skilllv),BL_CHAR,
|
||||
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
|
||||
skill_castend_nodamage_id);
|
||||
}
|
||||
break;
|
||||
case RK_DRAGONHOWLING:
|
||||
if(flag&1)
|
||||
sc_start(bl,SC_FEAR,50 + skilllv * 6,skilllv,skill_get_time2(skillid,skilllv));
|
||||
else
|
||||
{
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
||||
map_foreachinrange(skill_area_sub, bl,
|
||||
skill_get_splash(skillid, skilllv),BL_CHAR,
|
||||
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
|
||||
skill_castend_nodamage_id);
|
||||
}
|
||||
break;
|
||||
case RK_REFRESH:
|
||||
{
|
||||
int heal = sstatus->max_hp * 25 / 100;
|
||||
status_heal(bl,heal,0,0);
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,
|
||||
sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
|
||||
status_change_clear_buffs(bl,6);
|
||||
}
|
||||
break;
|
||||
case RK_STORMBLAST:
|
||||
if( flag&1 )
|
||||
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
|
||||
else
|
||||
{
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
||||
map_foreachinrange(skill_area_sub, bl,
|
||||
skill_get_splash(skillid, skilllv),BL_CHAR,
|
||||
src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
|
||||
skill_castend_nodamage_id);
|
||||
}
|
||||
break;
|
||||
case RK_PHANTOMTHRUST:
|
||||
if(battle_check_target(src,bl,BCT_ENEMY) > 0 || battle_check_target(src,bl,BCT_PARTY) > 0)
|
||||
{
|
||||
if(!map[bl->m].flag.gvg && !map[bl->m].flag.battleground && !(status_get_mode(bl)&MD_BOSS))
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
if(bl->x > src->x) x = 1;
|
||||
else if(bl->x < src->x) x = -1;
|
||||
if(bl->y >= src->y) y = 1;
|
||||
else if(bl->y < src->y) y = -1;
|
||||
unit_movepos(bl, src->x+x, src->y+y, 1, 0);
|
||||
clif_slide(bl,src->x+x, src->y+y);
|
||||
}
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
||||
if (battle_check_target(src,bl,BCT_ENEMY) > 0 )
|
||||
skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
|
||||
}
|
||||
break;
|
||||
case AB_ANCILLA:
|
||||
if(sd) {
|
||||
if (skill_produce_mix(sd, skillid, 12333, 0, 0, 0, 1))
|
||||
@ -5774,6 +5900,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
int heal = skill_calc_heal(src, bl, AL_HEAL, lv, true);
|
||||
if( status_isimmune(bl) )
|
||||
heal = 0;
|
||||
|
||||
if( sd->status.party_id && (i = party_foreachsamemap(party_sub_count, sd, 0)) > 1 )
|
||||
heal += ((heal / 100) * (i * 10) / 4);
|
||||
|
||||
clif_skill_nodamage(bl, bl, skillid, heal, 1);
|
||||
status_heal(bl, heal, 0, 0);
|
||||
}
|
||||
@ -5786,15 +5916,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
{
|
||||
if( dstsd && dstsd->special_state.no_magic_damage )
|
||||
break;
|
||||
clif_skill_nodamage(bl, bl, skillid, skilllv,
|
||||
sc_start4(bl, type, 100, skilllv, 0, 0, 1, skill_get_time(skillid, skilllv)));
|
||||
|
||||
if ( sd && sd->status.party_id && (i = party_foreachsamemap(party_sub_count, sd, 0)) > 0)
|
||||
{
|
||||
clif_skill_nodamage(bl, bl, skillid, skilllv,
|
||||
sc_start4(bl, type, 100, skilllv, 0, 0, i, skill_get_time(skillid, skilllv)));
|
||||
}
|
||||
}
|
||||
else
|
||||
party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv), src, skillid, skilllv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id);
|
||||
break;
|
||||
case AB_ORATIO:
|
||||
if (flag&1)
|
||||
sc_start(bl, type, 40+skilllv*5, skilllv, skill_get_time(skillid, skilllv));
|
||||
sc_start(bl, type, 40+5*skilllv, skilllv, skill_get_time(skillid, skilllv));
|
||||
else
|
||||
{
|
||||
clif_skill_nodamage(src, bl, skillid, skilllv, 1);
|
||||
@ -5808,30 +5942,32 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
case AB_LAUDARAMUS:
|
||||
if( (flag&1) || sd == NULL || sd->status.party_id == 0 )
|
||||
{
|
||||
if( tsc && (rand()%100 < 30+5*skilllv) )
|
||||
if( tsc && (rand()%100 < 40+10*skilllv) )
|
||||
{
|
||||
switch(skillid)
|
||||
{
|
||||
case AB_LAUDAAGNUS:
|
||||
if( tsc->data[SC_STONE] || tsc->data[SC_FREEZE] || tsc->data[SC_BLIND] )
|
||||
if( tsc->data[SC_STONE] || tsc->data[SC_FREEZE] || tsc->data[SC_BLIND] ) //TODO: Freezing, Crystallization and Burning
|
||||
{
|
||||
status_change_end(bl, SC_STONE, INVALID_TIMER);
|
||||
status_change_end(bl, SC_FREEZE, INVALID_TIMER);
|
||||
status_change_end(bl, SC_BLIND, INVALID_TIMER);
|
||||
}
|
||||
else
|
||||
clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)));
|
||||
break;
|
||||
case AB_LAUDARAMUS:
|
||||
if( tsc->data[SC_STUN] || tsc->data[SC_SLEEP] || tsc->data[SC_SILENCE] )
|
||||
if( tsc->data[SC_STUN] || tsc->data[SC_SLEEP] || tsc->data[SC_SILENCE] ) // TODO: Howling of Mandragora, and Deep Sleep
|
||||
{
|
||||
status_change_end(bl, SC_STUN, INVALID_TIMER);
|
||||
status_change_end(bl, SC_SLEEP, INVALID_TIMER);
|
||||
status_change_end(bl, SC_SILENCE, INVALID_TIMER);
|
||||
}
|
||||
else
|
||||
clif_skill_nodamage(bl, bl, skillid, skilllv, sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
clif_skill_nodamage(bl, bl, skillid, skilllv,
|
||||
sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv)));
|
||||
}
|
||||
else if( sd )
|
||||
party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skillid, skilllv),
|
||||
@ -5839,7 +5975,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
break;
|
||||
case AB_CLEARANCE:
|
||||
clif_skill_nodamage(src,bl,skillid,skilllv,1);
|
||||
if( rand()%100 >= 50+10*skilllv )
|
||||
if( rand()%100 >= 60+10*skilllv )
|
||||
{
|
||||
if (sd)
|
||||
clif_skill_fail(sd,skillid,0,0);
|
||||
@ -5903,7 +6039,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
|
||||
case SC_ASSNCROS: case SC_POEMBRAGI: case SC_APPLEIDUN:
|
||||
case SC_HUMMING: case SC_DONTFORGETME: case SC_FORTUNE:
|
||||
case SC_SERVICE4U: case SC_PARTYFLEE: /*case SC_ANGEL_PROTECT:*/
|
||||
case SC_EPICLESIS:
|
||||
case SC_EPICLESIS: case SC_DEATHBOUND: case SC_FIGHTINGSPIRIT:
|
||||
case SC_ABUNDANCE: case SC_MILLENNIUMSHIELD:
|
||||
// not implemented
|
||||
//case SC_BUCHEDENOEL: case SC_POPECOOKIE:
|
||||
//case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: case SC_MINOR_BBQ:
|
||||
@ -6801,6 +6938,23 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
|
||||
}
|
||||
break;
|
||||
|
||||
case RK_WINDCUTTER:
|
||||
i = skill_get_splash(skillid, skilllv);
|
||||
clif_skill_damage(src, src, tick, 0, 0, -1, 1, skillid, -1, 0);
|
||||
map_foreachinarea(skill_area_sub,
|
||||
src->m,x-i,y-i,x+i,y+i,(BL_CHAR|BL_SKILL),
|
||||
src,skillid,skilllv,tick,flag|BCT_ENEMY|1,
|
||||
skill_castend_damage_id);
|
||||
break;
|
||||
|
||||
case RK_DRAGONBREATH:
|
||||
i = skill_get_splash(skillid, skilllv);
|
||||
map_foreachinarea(skill_area_sub,
|
||||
src->m,x-i,y-i,x+i,y+i,(BL_CHAR|BL_SKILL),
|
||||
src,skillid,skilllv,tick,flag|BCT_ENEMY|1,
|
||||
skill_castend_damage_id);
|
||||
break;
|
||||
|
||||
case AB_EPICLESIS:
|
||||
if( skill_unitsetting(src, skillid, skilllv, x, y, 0) )
|
||||
{
|
||||
@ -6862,7 +7016,8 @@ int skill_castend_map (struct map_session_data *sd, short skill_num, const char
|
||||
sd->sc.data[SC_DANCING] ||
|
||||
sd->sc.data[SC_BERSERK] ||
|
||||
sd->sc.data[SC_BASILICA] ||
|
||||
sd->sc.data[SC_MARIONETTE]
|
||||
sd->sc.data[SC_MARIONETTE] ||
|
||||
sd->sc.data[SC_DEATHBOUND]
|
||||
)) {
|
||||
skill_failed(sd);
|
||||
return 0;
|
||||
@ -8960,13 +9115,13 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
|
||||
clif_skill_fail(sd,skill,0,0);
|
||||
return 0;
|
||||
break;
|
||||
/*
|
||||
case ST_DRAGON:
|
||||
if(!pc_isdragon(sd)) {
|
||||
clif_skill_fail(sd,skill,25,0);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case ST_WARG:
|
||||
if(!pc_iswarg(sd)) {
|
||||
clif_skill_fail(sd,skill,0,0);
|
||||
@ -11274,12 +11429,32 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in
|
||||
}
|
||||
}
|
||||
|
||||
if(skill_id == RK_RUNEMASTERY)
|
||||
{ // Now we figure out how many runes we're going to make. :3
|
||||
int skill_lv = pc_checkskill(sd,skill_id);
|
||||
if( skill_lv > 4 && skill_lv < 10) // level 5~9 can make 1~2 runes
|
||||
qty=(rand()%2)+1;
|
||||
else if( skill_lv == 10 ) // Level 10 can make 1~3 runes
|
||||
qty=(rand()%3)+1;
|
||||
|
||||
// Check to see if the amount of runes will exceed 20.
|
||||
i = pc_search_inventory(sd,nameid);
|
||||
if( i >= 0 && sd->status.inventory[i].amount+qty > 20 ) // Cancel creation if created stones will exceed 20.
|
||||
{
|
||||
clif_msg(sd,0x61b);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<MAX_PRODUCE_RESOURCE;i++){
|
||||
int j,id,x;
|
||||
if( (id=skill_produce_db[idx].mat_id[i]) <= 0 )
|
||||
continue;
|
||||
num++;
|
||||
x=qty*skill_produce_db[idx].mat_amount[i];
|
||||
if (skill_id == RK_RUNEMASTERY)
|
||||
x=skill_produce_db[idx].mat_amount[i]; // RK_RUNEMASTERY only uses one set of required items, even if making more than 1 item
|
||||
else
|
||||
x=qty*skill_produce_db[idx].mat_amount[i];
|
||||
do{
|
||||
int y=0;
|
||||
j = pc_search_inventory(sd,id);
|
||||
@ -11372,8 +11547,57 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in
|
||||
make_per = make_per * battle_config.pp_rate / 100;
|
||||
break;
|
||||
case SA_CREATECON: // Elemental Converter Creation
|
||||
case AB_ANCILLA: // Ancilla Creation
|
||||
make_per = 100000; // should be 100% success rate
|
||||
break;
|
||||
case RK_RUNEMASTERY: //Information from iROWiki and RuneItemInfo.lua
|
||||
{
|
||||
int skill_lv = pc_checkskill(sd,skill_id);
|
||||
|
||||
make_per = 5100 + 20 * skill_lv; // Base chance.
|
||||
|
||||
//Take stats into account before applying non-modified values.
|
||||
make_per += (status->dex / 30 + status->luk / 10) + sd->status.job_level / 10 * 100;
|
||||
|
||||
switch(sd->produce_itemusedid)
|
||||
{ // Add success rate based on what type of stone is used.
|
||||
case 12737:
|
||||
make_per += 200; break;
|
||||
case 12734:
|
||||
make_per += 500; break;
|
||||
case 12738:
|
||||
make_per += 800; break;
|
||||
case 12735:
|
||||
make_per += 1100; break;
|
||||
case 12736:
|
||||
make_per += 1400; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sd->produce_itemusedid = 0;
|
||||
|
||||
switch(nameid)
|
||||
{ // Reduce success rate based on what rank stone we're making.
|
||||
case 12727: // Runstone_Verkana
|
||||
make_per -= 2000; // S Class
|
||||
break;
|
||||
case 12725: // Runstone_Nosiege
|
||||
case 12730: // Runstone_Urj
|
||||
make_per -= 1500; // A Rank
|
||||
break;
|
||||
case 12728: // Runstone_Isia
|
||||
case 12732: // Runstone_Pertz
|
||||
make_per -= 1000; // B Rank
|
||||
break;
|
||||
case 12726: // Runstone_Rhydo
|
||||
case 12729: // Runstone_Asir
|
||||
case 12731: // Runstone_Turisus
|
||||
case 12733: // Runstone_Hagalas
|
||||
make_per -= 500; // C Rank
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (sd->menuskill_id == AM_PHARMACY &&
|
||||
sd->menuskill_val > 10 && sd->menuskill_val <= 20)
|
||||
@ -11412,7 +11636,6 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in
|
||||
|
||||
if(make_per < 1) make_per = 1;
|
||||
|
||||
|
||||
if(rand()%10000 < make_per || qty > 1){ //Success, or crafting multiple items.
|
||||
struct item tmp_item;
|
||||
memset(&tmp_item,0,sizeof(tmp_item));
|
||||
@ -11512,6 +11735,7 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in
|
||||
case AM_TWILIGHT2:
|
||||
case AM_TWILIGHT3:
|
||||
case ASC_CDP:
|
||||
case RK_RUNEMASTERY:
|
||||
clif_produceeffect(sd,2,nameid);
|
||||
clif_misceffect(&sd->bl,5);
|
||||
break;
|
||||
@ -11565,6 +11789,10 @@ int skill_produce_mix (struct map_session_data *sd, int skill_id, int nameid, in
|
||||
clif_produceeffect(sd,1,nameid);
|
||||
clif_misceffect(&sd->bl,2);
|
||||
break;
|
||||
case RK_RUNEMASTERY:
|
||||
clif_produceeffect(sd,3,nameid);
|
||||
clif_misceffect(&sd->bl,6);
|
||||
break;
|
||||
default:
|
||||
if( skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20 )
|
||||
{ //Cooking items.
|
||||
|
235
src/map/status.c
235
src/map/status.c
@ -413,6 +413,17 @@ void initChangeTables(void)
|
||||
add_sc( SA_ELEMENTGROUND , SC_ELEMENTALCHANGE );
|
||||
add_sc( SA_ELEMENTWIND , SC_ELEMENTALCHANGE );
|
||||
|
||||
set_sc( RK_ENCHANTBLADE , SC_ENCHANTBLADE , SI_ENCHANTBLADE , SCB_NONE );
|
||||
set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SI_DEATHBOUND , SCB_NONE );
|
||||
set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_BLANK , SCB_NONE );
|
||||
set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SI_CRUSHSTRIKE , SCB_NONE );
|
||||
set_sc( RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE );
|
||||
set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR );
|
||||
set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_DEF2|SCB_MDEF2 );
|
||||
set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION , SI_VITALITYACTIVATION , SCB_REGEN );
|
||||
set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_ASPD );
|
||||
set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE );
|
||||
|
||||
set_sc( AB_ADORAMUS , SC_ADORAMUS , SI_ADORAMUS , SCB_AGI|SCB_SPEED );
|
||||
add_sc( AB_CLEMENTIA , SC_BLESSING );
|
||||
add_sc( AB_CANTO , SC_INCREASEAGI );
|
||||
@ -503,7 +514,7 @@ void initChangeTables(void)
|
||||
StatusIconChangeTable[SC_SPL_DEF] = SI_SPL_DEF;
|
||||
StatusIconChangeTable[SC_MANU_MATK] = SI_MANU_MATK;
|
||||
StatusIconChangeTable[SC_SPL_MATK] = SI_SPL_MATK;
|
||||
//StatusIconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY; // Causes client to crash when mousing over state icon?
|
||||
|
||||
//Cash Items
|
||||
StatusIconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH;
|
||||
StatusIconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH;
|
||||
@ -575,7 +586,7 @@ void initChangeTables(void)
|
||||
StatusChangeFlagTable[SC_SPCOST_RATE] |= SCB_ALL;
|
||||
StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED;
|
||||
StatusChangeFlagTable[SC_ITEMSCRIPT] |= SCB_ALL;
|
||||
//StatusChangeFlagTable[SC_MOVHASTE_INFINITY] = SCB_SPEED;
|
||||
StatusChangeFlagTable[SC_FEAR] |= SCB_HIT|SCB_FLEE;
|
||||
|
||||
// Cash Items
|
||||
StatusChangeFlagTable[SC_FOOD_STR_CASH] = SCB_STR;
|
||||
@ -906,6 +917,9 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag)
|
||||
}
|
||||
|
||||
if(sp) {
|
||||
if (sc && sc->data[SC_BERSERK] && sc->data[SC_ABUNDANCE]) // SP does not regenerate during Frenzy.
|
||||
sp = 0;
|
||||
|
||||
if((unsigned int)sp > status->max_sp - status->sp)
|
||||
sp = status->max_sp - status->sp;
|
||||
}
|
||||
@ -1758,7 +1772,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
|
||||
sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100;
|
||||
sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100;
|
||||
sd->regen.state.block = 0;
|
||||
sd->fixedcastrate=0;
|
||||
sd->fixedcastrate=100;
|
||||
sd->weapon_matk = 0;
|
||||
sd->equipment_matk = 0;
|
||||
|
||||
@ -1804,7 +1818,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
|
||||
status->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
|
||||
|
||||
status->size = (sd->class_&JOBL_BABY)?0:1;
|
||||
if (battle_config.character_size && pc_isriding(sd)) { //[Lupus]
|
||||
if (battle_config.character_size && (pc_isriding(sd) || pc_isdragon(sd))) { //[Lupus]
|
||||
if (sd->class_&JOBL_BABY) {
|
||||
if (battle_config.character_size&2)
|
||||
status->size++;
|
||||
@ -2089,7 +2103,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
|
||||
sd->left_weapon.atkmods[1] = atkmods[1][sd->weapontype2];
|
||||
sd->left_weapon.atkmods[2] = atkmods[2][sd->weapontype2];
|
||||
|
||||
if(pc_isriding(sd) &&
|
||||
if((pc_isriding(sd) || pc_isdragon(sd)) &&
|
||||
(sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR))
|
||||
{ //When Riding with spear, damage modifier to mid-class becomes
|
||||
//same as versus large size.
|
||||
@ -2348,7 +2362,8 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
|
||||
status->aspd_rate -= ((skill+1)/2) * 10;
|
||||
if(pc_isriding(sd))
|
||||
status->aspd_rate += 500-100*pc_checkskill(sd,KN_CAVALIERMASTERY);
|
||||
|
||||
if(pc_isdragon(sd))
|
||||
status->aspd_rate += 750-75*pc_checkskill(sd,RK_DRAGONTRAINING); // Officiak is rumoured to be 75+5*skilllv...giving you 125% ASPD?
|
||||
status->adelay = 2*status->amotion;
|
||||
|
||||
|
||||
@ -2366,6 +2381,8 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
|
||||
sd->max_weight += 2000*skill;
|
||||
if(pc_isriding(sd) && pc_checkskill(sd,KN_RIDING)>0)
|
||||
sd->max_weight += 10000;
|
||||
if(pc_isdragon(sd) && (skill=pc_checkskill(sd,RK_DRAGONTRAINING))>0)
|
||||
sd->max_weight += 5000+2000*skill; //+200 weight per level of RK_DRAGINTRAINING
|
||||
if(sc->data[SC_KNOWLEDGE])
|
||||
sd->max_weight += sd->max_weight*sc->data[SC_KNOWLEDGE]->val1/10;
|
||||
if((skill=pc_checkskill(sd,ALL_INCCARRY))>0)
|
||||
@ -2775,6 +2792,8 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
|
||||
} else
|
||||
regen->flag&=~sce->val4; //Remove regen as specified by val4
|
||||
}
|
||||
if( sc->data[SC_VITALITYACTIVATION] )
|
||||
regen->flag &=~RGN_SP;
|
||||
}
|
||||
|
||||
/// Recalculates parts of an object's battle status according to the specified flags.
|
||||
@ -3324,6 +3343,8 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang
|
||||
str += ((sc->data[SC_MARIONETTE2]->val3)>>16)&0xFF;
|
||||
if(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_HIGH && str < 50)
|
||||
str = 50;
|
||||
if(sc->data[SC_GIANTGROWTH])
|
||||
str += 30;
|
||||
|
||||
return (unsigned short)cap_value(str,0,USHRT_MAX);
|
||||
}
|
||||
@ -3658,6 +3679,8 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
|
||||
hit += 20; // RockmanEXE; changed based on updated [Reddozen]
|
||||
if(sc->data[SC_MERC_HITUP])
|
||||
hit += sc->data[SC_MERC_HITUP]->val2;
|
||||
if(sc->data[SC_FEAR])
|
||||
hit -= hit * 20/100;
|
||||
|
||||
return (short)cap_value(hit,1,SHRT_MAX);
|
||||
}
|
||||
@ -3707,6 +3730,8 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
|
||||
flee += sc->data[SC_PARTYFLEE]->val1 * 10;
|
||||
if(sc->data[SC_MERC_FLEEUP])
|
||||
flee += sc->data[SC_MERC_FLEEUP]->val2;
|
||||
if(sc->data[SC_FEAR])
|
||||
flee -= flee * 20/100;
|
||||
|
||||
return (short)cap_value(flee,1,SHRT_MAX);
|
||||
}
|
||||
@ -3795,6 +3820,8 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change
|
||||
+ def2 * ( sc->data[SC_JOINTBEAT]->val2&BREAK_WAIST ? 25 : 0 ) / 100;
|
||||
if(sc->data[SC_FLING])
|
||||
def2 -= def2 * (sc->data[SC_FLING]->val3)/100;
|
||||
if (sc->data[SC_STONEHARDSKIN])
|
||||
def2 += sc->data[SC_STONEHARDSKIN]->val3;
|
||||
|
||||
return (short)cap_value(def2,1,SHRT_MAX);
|
||||
}
|
||||
@ -3835,6 +3862,8 @@ static signed short status_calc_mdef2(struct block_list *bl, struct status_chang
|
||||
return 0;
|
||||
if(sc->data[SC_MINDBREAKER])
|
||||
mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100;
|
||||
if (sc->data[SC_STONEHARDSKIN])
|
||||
mdef2 += sc->data[SC_STONEHARDSKIN]->val3;
|
||||
|
||||
return (short)cap_value(mdef2,1,SHRT_MAX);
|
||||
}
|
||||
@ -3864,6 +3893,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
|
||||
else
|
||||
if( sd && pc_isriding(sd) )
|
||||
val = 25;
|
||||
if( sd && pc_isdragon(sd) )
|
||||
val = 25;
|
||||
|
||||
speed_rate -= val;
|
||||
}
|
||||
@ -3946,8 +3977,6 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
|
||||
val = max( val, 10 * sc->data[SC_AVOID]->val1 );
|
||||
if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
|
||||
val = max( val, 75 );
|
||||
//if( sc->data[SC_MOVHASTE_INFINITY] )
|
||||
// val = max( val, 25 );
|
||||
|
||||
//FIXME: official items use a single bonus for this [ultramage]
|
||||
if( sc->data[SC_SPEEDUP0] ) // temporary item-based speedup
|
||||
@ -4078,6 +4107,9 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
|
||||
if( sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE )
|
||||
aspd_rate += 100;
|
||||
}
|
||||
if(sc->data[SC_FIGHTINGSPIRIT])
|
||||
aspd_rate -= sc->data[SC_FIGHTINGSPIRIT]->val3;
|
||||
|
||||
|
||||
return (short)cap_value(aspd_rate,0,SHRT_MAX);
|
||||
}
|
||||
@ -4857,6 +4889,34 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
if( !sc )
|
||||
return 0; //Unable to receive status changes
|
||||
|
||||
if( sc->data[SC_REFRESH] )
|
||||
{
|
||||
if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX && type != SC_STUN ) // Immune to all common status ailments except stun (iROWiki)
|
||||
return 0;
|
||||
switch( type )
|
||||
{
|
||||
case SC_FEAR:
|
||||
case SC_BURNING:
|
||||
// Not implemented yet. (kRO 3-x balance update)
|
||||
//case SC_POISONINGWEAPON:
|
||||
//case SC_TOXIN:
|
||||
//case SC_PARALYSE:
|
||||
//case SC_VENOMBLEED:
|
||||
//case SC_MAGICMUSHROOM:
|
||||
//case SC_DEATHHURT:
|
||||
//case SC_PYREXIA:
|
||||
//case SC_OBLIVIONCURSE:
|
||||
//case SC_LEECHESEND:
|
||||
//case SC_FROSTMISTY:
|
||||
//case SC_MARSHOFABYSS:
|
||||
//case SC_DEEP_SLEEP:
|
||||
//case SC_COLD:
|
||||
//case SC_FREEZE_SP:
|
||||
//case SC_MANDRAGORA:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( status_isdead(bl) )
|
||||
return 0;
|
||||
|
||||
@ -4887,6 +4947,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
return 0;
|
||||
case SC_SLEEP:
|
||||
case SC_STUN:
|
||||
case SC_BURNING:
|
||||
if (sc->opt1)
|
||||
return 0; //Cannot override other opt1 status changes. [Skotlex]
|
||||
break;
|
||||
@ -5251,6 +5312,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
case SC_FOOD_LUK_CASH:
|
||||
status_change_end(bl, SC_LUKFOOD, INVALID_TIMER);
|
||||
break;
|
||||
case SC_FIGHTINGSPIRIT:
|
||||
if (sc->data[SC_FIGHTINGSPIRIT])
|
||||
status_change_end(bl, SC_FIGHTINGSPIRIT, INVALID_TIMER);
|
||||
break;
|
||||
}
|
||||
|
||||
//Check for overlapping fails
|
||||
@ -5290,6 +5355,8 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
case SC_MARIONETTE2:
|
||||
case SC_NOCHAT:
|
||||
case SC_CHANGE: //Otherwise your Hp/Sp would get refilled while still within effect of the last invocation.
|
||||
case SC_FEAR:
|
||||
case SC_BURNING:
|
||||
return 0;
|
||||
case SC_COMBO:
|
||||
case SC_DANCING:
|
||||
@ -5399,12 +5466,15 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
break;
|
||||
case SC_KYRIE:
|
||||
val2 = status->max_hp * (val1 * 2 + 10) / 100; //%Max HP to absorb
|
||||
// val4 determines if status is casued by Kyrie or Praefatio,
|
||||
// as Praefatio blocks more hits than Kyrie Elesion.
|
||||
if( !val4 ) //== PR_KYRIE
|
||||
// val4 holds current about of party memebers when casting AB_PRAEFATIO,
|
||||
// as Praefatio's barrier has more health and blocks more hits than Kyrie Elesion.
|
||||
if( val4 < 1 ) //== PR_KYRIE
|
||||
val3 = (val1 / 2 + 5);
|
||||
else //== AB_PRAEFATIO
|
||||
else
|
||||
{ //== AB_PRAEFATIO
|
||||
val2 += val4 * 2; //Increase barrier strength per party member.
|
||||
val3 = 6 + val1;
|
||||
}
|
||||
if( sd )
|
||||
val1 = min(val1,pc_checkskill(sd,PR_KYRIE)); // use skill level to determine barrier health.
|
||||
break;
|
||||
@ -6143,6 +6213,34 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
case SC_KAIZEL:
|
||||
val2 = 10*val1; //% of life to be revived with
|
||||
break;
|
||||
case SC_MILLENNIUMSHIELD:
|
||||
val2 = (rand()%100<20) ? 4 : ((rand()%100<30) ? 3 : ((rand()%100<50) ? 2 : 0)); // 20% for 4, 30% for 3, 50% for 2
|
||||
val3 = 1000; // Initial Sheild health. (Additional sheilds health are set in battle.c when shield is broken.)
|
||||
if( sd && val2 > 0)
|
||||
clif_millenniumshield(sd,val2);
|
||||
break;
|
||||
case SC_STONEHARDSKIN:
|
||||
val2 = (status->hp * 20 / 100);
|
||||
if( val2 > 0 )
|
||||
status_heal(bl, -val2, 0, 0); // Reduce health by 20%
|
||||
if ( sd )
|
||||
val3 = (sd->status.job_level * pc_checkskill(sd,RK_RUNEMASTERY)) / 4;
|
||||
break;
|
||||
case SC_VITALITYACTIVATION:
|
||||
val2 = 50; // Increase HP recovery effects by 50%
|
||||
val3 = 50; // Reduce SP recovery effects by 50%
|
||||
break;
|
||||
case SC_FIGHTINGSPIRIT: // attack is handled in battle.c
|
||||
//val2 holds the source of the skill (1 = caster, 0 = party member.)
|
||||
//official ASPD bonus appears to be (Rune Mastery Level / 10 x 4).
|
||||
val3 = 10 * (sd?pc_checkskill(sd,RK_RUNEMASTERY):1); //Kind of dirty means to implement 4aspd increase.
|
||||
break;
|
||||
case SC_ABUNDANCE:
|
||||
val3 = tick / 10000;
|
||||
if(val3 < 1)
|
||||
val3 = 1;
|
||||
tick = 10000;
|
||||
break;
|
||||
case SC_EPICLESIS:
|
||||
val2 = 5 * val1; // % HP gained * level of Epiclesis cast.
|
||||
break;
|
||||
@ -6161,13 +6259,24 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
val2 = 5*val1; // DEF reduced by 5*Skill Level percent.
|
||||
break;
|
||||
case SC_DUPLELIGHT:
|
||||
val2 = 10+val1*2; //Chance of MELEE proc
|
||||
val3 = 10+val1*2; //Chance of MAGIC proc
|
||||
val2 = 10+2*val1; //Chance of MELEE proc
|
||||
val3 = 10+2*val1; //Chance of MAGIC proc
|
||||
break;
|
||||
|
||||
case SC_AB_SECRAMENT:
|
||||
val2 = 10*val1; //Fixed cast time reduced by 10*Skill Level
|
||||
break;
|
||||
case SC_FEAR:
|
||||
if (tick < 2000)
|
||||
val3 = 2000;
|
||||
else
|
||||
val3 = tick - 2000;
|
||||
tick = 2000;
|
||||
break;
|
||||
case SC_BURNING:
|
||||
val4 = tick/2000;
|
||||
tick = 3000;
|
||||
break;
|
||||
// case SC_ARMOR_ELEMENT:
|
||||
// case SC_ARMOR_RESIST:
|
||||
// Mod your resistance against elements:
|
||||
@ -6232,6 +6341,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
case SC_STUN:
|
||||
case SC_SLEEP:
|
||||
case SC_STONE:
|
||||
case SC_BURNING:
|
||||
if (sd && pc_issit(sd)) //Avoid sprite sync problems.
|
||||
pc_setstand(sd);
|
||||
case SC_TRICKDEAD:
|
||||
@ -6246,6 +6356,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
case SC_CLOSECONFINE2:
|
||||
case SC_ANKLE:
|
||||
case SC_SPIDERWEB:
|
||||
case SC_FEAR:
|
||||
unit_stop_walking(bl,1);
|
||||
break;
|
||||
case SC_HIDING:
|
||||
@ -6265,10 +6376,11 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
switch(type)
|
||||
{
|
||||
//OPT1
|
||||
case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break;
|
||||
case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break;
|
||||
case SC_STUN: sc->opt1 = OPT1_STUN; break;
|
||||
case SC_SLEEP: sc->opt1 = OPT1_SLEEP; break;
|
||||
case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break;
|
||||
case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break;
|
||||
case SC_STUN: sc->opt1 = OPT1_STUN; break;
|
||||
case SC_SLEEP: sc->opt1 = OPT1_SLEEP; break;
|
||||
case SC_BURNING: sc->opt1 = OPT1_BURNING; break;
|
||||
//OPT2
|
||||
case SC_POISON: sc->opt2 |= OPT2_POISON; break;
|
||||
case SC_CURSE: sc->opt2 |= OPT2_CURSE; break;
|
||||
@ -6278,6 +6390,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
|
||||
case SC_ANGELUS: sc->opt2 |= OPT2_ANGELUS; break;
|
||||
case SC_BLEEDING: sc->opt2 |= OPT2_BLEEDING; break;
|
||||
case SC_DPOISON: sc->opt2 |= OPT2_DPOISON; break;
|
||||
case SC_FEAR: sc->opt2 |= OPT2_FEAR; break;
|
||||
//OPT3
|
||||
case SC_TWOHANDQUICKEN:
|
||||
case SC_ONEHAND:
|
||||
@ -6612,7 +6725,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
||||
return 0;
|
||||
|
||||
if (tid == INVALID_TIMER) {
|
||||
if( (type == SC_ENDURE /*|| type == SC_MOVHASTE_INFINITY*/ ) && sce->val4 )
|
||||
if( (type == SC_ENDURE) && sce->val4 )
|
||||
//Do not end infinite endure or speed adjustment.
|
||||
return 0;
|
||||
if (sce->timer != INVALID_TIMER) //Could be a SC with infinite duration
|
||||
@ -6943,6 +7056,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
||||
status_change_end(tbl, SC_STOP, INVALID_TIMER);
|
||||
}
|
||||
break;
|
||||
case SC_MILLENNIUMSHIELD:
|
||||
if ( sd )
|
||||
clif_millenniumshield(sd,0);
|
||||
break;
|
||||
}
|
||||
|
||||
opt_flag = 1;
|
||||
@ -6951,6 +7068,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
||||
case SC_FREEZE:
|
||||
case SC_STUN:
|
||||
case SC_SLEEP:
|
||||
case SC_BURNING:
|
||||
sc->opt1 = 0;
|
||||
break;
|
||||
|
||||
@ -6966,6 +7084,9 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
||||
case SC_SIGNUMCRUCIS:
|
||||
sc->opt2 &= ~OPT2_SIGNUMCRUCIS;
|
||||
break;
|
||||
case SC_FEAR:
|
||||
sc->opt2 &= ~OPT2_FEAR;
|
||||
break;
|
||||
|
||||
case SC_HIDING:
|
||||
sc->option &= ~OPTION_HIDE;
|
||||
@ -7495,8 +7616,24 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case SC_ABUNDANCE:
|
||||
if((--sce->val3) > 0)
|
||||
{
|
||||
int sp = 60;
|
||||
if(sd) {
|
||||
if( sd->status.sp < sd->status.max_sp )
|
||||
{
|
||||
if( sd->status.sp + sp > sd->status.max_sp ) //No overhealing SP.
|
||||
sp = sd->status.max_sp - sd->status.sp;
|
||||
clif_heal(sd->fd,SP_SP,sp);
|
||||
status_heal(bl, 0, sp, 0);
|
||||
}
|
||||
}
|
||||
sc_timer_next(10000+tick, status_change_timer, bl->id, data);
|
||||
}
|
||||
break;
|
||||
case SC_RENOVATIO:
|
||||
if((--sc->data[type]->val2) > 0) {
|
||||
if((--sce->val2) > 0) {
|
||||
int heal = status->max_hp * 3 / 100;
|
||||
if( status->hp + heal > status->max_hp )
|
||||
heal = status->max_hp - status->hp;
|
||||
@ -7509,6 +7646,31 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case SC_FEAR:
|
||||
if(sce->val3 > 0)
|
||||
{
|
||||
sc_timer_next(sce->val3+tick, status_change_timer, bl->id, data);
|
||||
sce->val3 = 0;
|
||||
}
|
||||
break;
|
||||
case SC_BURNING:
|
||||
if(--(sce->val4) >= 0)
|
||||
{
|
||||
int flag, hp = 0;
|
||||
struct block_list *src = map_id2bl(sce->val2);
|
||||
|
||||
hp = 1000+(status->max_hp*3 /100);
|
||||
map_freeblock_lock();
|
||||
clif_damage(bl,bl,tick,status->amotion,0,hp,1,9,0);
|
||||
status_damage(src, bl, hp, 0, 0, 1);
|
||||
|
||||
flag = !sc->data[type];
|
||||
map_freeblock_unlock();
|
||||
if(!flag)
|
||||
sc_timer_next( 3000 + tick, status_change_timer, bl->id, data);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// default for all non-handled control paths is to end the status
|
||||
@ -7569,7 +7731,7 @@ int status_change_timer_sub(struct block_list* bl, va_list ap)
|
||||
|
||||
/*==========================================
|
||||
* Clears buffs/debuffs of a character.
|
||||
* type&1 -> buffs, type&2 -> debuffs
|
||||
* type&1 -> buffs, type&2 -> debuffs, type&4 -> sc_refresh
|
||||
*------------------------------------------*/
|
||||
int status_change_clear_buffs (struct block_list* bl, int type)
|
||||
{
|
||||
@ -7628,6 +7790,13 @@ int status_change_clear_buffs (struct block_list* bl, int type)
|
||||
case SC_EXPBOOST:
|
||||
case SC_JEXPBOOST:
|
||||
case SC_ITEMBOOST:
|
||||
case SC_GIANTGROWTH:
|
||||
case SC_REFRESH:
|
||||
case SC_STONEHARDSKIN:
|
||||
case SC_VITALITYACTIVATION:
|
||||
case SC_FIGHTINGSPIRIT:
|
||||
case SC_ABUNDANCE:
|
||||
case SC_MILLENNIUMSHIELD:
|
||||
continue;
|
||||
|
||||
//Debuffs that can be removed.
|
||||
@ -7644,9 +7813,33 @@ int status_change_clear_buffs (struct block_list* bl, int type)
|
||||
case SC_STRIPSHIELD:
|
||||
case SC_STRIPARMOR:
|
||||
case SC_STRIPHELM:
|
||||
//Cannot be removed by Refresh.
|
||||
if (type&4)
|
||||
continue;
|
||||
case SC_ADORAMUS:
|
||||
if (!(type&2))
|
||||
continue;
|
||||
|
||||
//Debuffs that can be removed by Refresh..
|
||||
case SC_FEAR:
|
||||
case SC_BURNING:
|
||||
//case SC_POISONINGWEAPON:
|
||||
//case SC_TOXIN:
|
||||
//case SC_PARALYSE:
|
||||
//case SC_VENOMBLEED:
|
||||
//case SC_MAGICMUSHROOM:
|
||||
//case SC_DEATHHURT:
|
||||
//case SC_PYREXIA:
|
||||
//case SC_OBLIVIONCURSE:
|
||||
//case SC_LEECHESEND:
|
||||
//case SC_FROSTMISTY:
|
||||
//case SC_MARSHOFABYSS:
|
||||
//case SC_DEEP_SLEEP:
|
||||
//case SC_COLD:
|
||||
//case SC_FREEZE_SP:
|
||||
//case SC_MANDRAGORA:
|
||||
if (!(type&4))
|
||||
continue;
|
||||
break;
|
||||
//The rest are buffs that can be removed.
|
||||
case SC_BERSERK:
|
||||
|
@ -330,11 +330,21 @@ typedef enum sc_type {
|
||||
SC_FOOD_DEX_CASH,
|
||||
SC_FOOD_INT_CASH,
|
||||
SC_FOOD_LUK_CASH,
|
||||
//SC_MOVHASTE_INFINITY,
|
||||
SC_PARTYFLEE = 310,
|
||||
//SC_ENDURE_MDEF, //311
|
||||
|
||||
SC_PARTYFLEE,
|
||||
|
||||
// Third Jobs - Maintaining SI order for SCs.
|
||||
SC_FEAR, // 310,
|
||||
SC_BURNING,
|
||||
SC_ENCHANTBLADE,
|
||||
SC_DEATHBOUND,
|
||||
SC_REFRESH,
|
||||
SC_GIANTGROWTH, //315
|
||||
SC_STONEHARDSKIN,
|
||||
SC_VITALITYACTIVATION,
|
||||
SC_FIGHTINGSPIRIT,
|
||||
SC_ABUNDANCE,
|
||||
SC_MILLENNIUMSHIELD, // 320
|
||||
//
|
||||
SC_EPICLESIS = 325,
|
||||
SC_ORATIO,
|
||||
SC_LAUDAAGNUS,
|
||||
@ -344,7 +354,11 @@ typedef enum sc_type {
|
||||
SC_DUPLELIGHT,
|
||||
SC_ADORAMUS = 380,
|
||||
SC_AB_SECRAMENT = 451,
|
||||
|
||||
// SC_ALL_RIDING = 472,
|
||||
|
||||
SC_CRUSHSTRIKE = 599,
|
||||
|
||||
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
|
||||
} sc_type;
|
||||
|
||||
@ -666,8 +680,7 @@ enum si_type {
|
||||
SI_CASH_PLUSONLYJOBEXP = 312,
|
||||
SI_PARTYFLEE = 313,
|
||||
// SI_ANGEL_PROTECT = 314,
|
||||
/*
|
||||
SI_ENDURE_MDEF = 315,
|
||||
// SI_ENDURE_MDEF = 315,
|
||||
SI_ENCHANTBLADE = 316,
|
||||
SI_DEATHBOUND = 317,
|
||||
SI_REFRESH = 318,
|
||||
@ -676,12 +689,11 @@ enum si_type {
|
||||
SI_VITALITYACTIVATION = 321,
|
||||
SI_FIGHTINGSPIRIT = 322,
|
||||
SI_ABUNDANCE = 323,
|
||||
SI_REUSE_MILLENNIUMSHIELD = 324,
|
||||
SI_REUSE_CRUSHSTRIKE = 325,
|
||||
SI_REUSE_REFRESH = 326,
|
||||
SI_REUSE_STORMBLAST = 327,
|
||||
SI_VENOMIMPRESS = 328,
|
||||
*/
|
||||
// SI_REUSE_MILLENNIUMSHIELD = 324,
|
||||
// SI_REUSE_CRUSHSTRIKE = 325,
|
||||
// SI_REUSE_REFRESH = 326,
|
||||
// SI_REUSE_STORMBLAST = 327,
|
||||
// SI_VENOMIMPRESS = 328,
|
||||
SI_EPICLESIS = 329,
|
||||
SI_ORATIO = 330,
|
||||
SI_LAUDAAGNUS = 331,
|
||||
@ -973,7 +985,9 @@ enum si_type {
|
||||
SI_BEER_BOTTLE_CAP = 617,
|
||||
SI_OVERLAPEXPUP = 618,
|
||||
SI_PC_IZ_DUN05 = 619,
|
||||
*/
|
||||
SI_CRUSHSTRIKE = 620,
|
||||
/*
|
||||
SI_MONSTER_TRANSFORM = 621,
|
||||
SI_SIT = 622,
|
||||
SI_ONAIR = 623,
|
||||
@ -1111,6 +1125,7 @@ enum {
|
||||
OPTION_DRAGON3 = 0x01000000,
|
||||
OPTION_DRAGON4 = 0x02000000,
|
||||
OPTION_DRAGON5 = 0x04000000,
|
||||
OPTION_ALL_RIDING= 0x08000000,
|
||||
// compound constants
|
||||
OPTION_CART = OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5,
|
||||
OPTION_DRAGON = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5,
|
||||
|
@ -837,6 +837,8 @@ int unit_can_move(struct block_list *bl)
|
||||
sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1))
|
||||
|| sc->data[SC_MADNESSCANCEL]
|
||||
|| (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF)
|
||||
|| (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val3 > 0)
|
||||
|| sc->data[SC_DEATHBOUND]
|
||||
))
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user