* 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:
L0neW0lf.eAthena 2011-10-26 19:44:18 +00:00
parent 1ccf4e3dc3
commit f6b46546b1
18 changed files with 1029 additions and 115 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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, },
};

View File

@ -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);

View File

@ -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,

View File

@ -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_ */

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
}
/*==========================================
*
*------------------------------------------*/

View File

@ -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);

View File

@ -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,""),

View File

@ -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.

View File

@ -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:

View File

@ -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,

View File

@ -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;
}