📄 skill.c
字号:
if(battle_config.combo_delay_rate != 100)
delay = delay * battle_config.combo_delay_rate /100;
if(pc_checkskill(sd, MO_EXTREMITYFIST) > 0 && sd->spiritball >= 4 && sd->sc_data[SC_EXPLOSIONSPIRITS].timer != -1)
delay += 300;
else
delay = 300;
skill_status_change_start(src,SC_COMBO,MO_COMBOFINISH,skilllv,0,0,delay,0);
}
sd->attackabletime = sd->canmove_tick = tick + delay;
clif_combo_delay(src,delay);
}
}
if(attack_type&BF_WEAPON && damage > 0 && src != bl && src == dsrc) {
if(dmg.flag&BF_SHORT) {
if(bl->type == BL_PC) {
struct map_session_data *tsd = (struct map_session_data *)bl;
if(tsd->short_weapon_damage_return > 0) {
rdamage += damage * tsd->short_weapon_damage_return / 100;
if(rdamage < 1) rdamage = 1;
}
}
if(sc_data && sc_data[SC_REFLECTSHIELD].timer != -1) {
rdamage += damage * sc_data[SC_REFLECTSHIELD].val2 / 100;
if(rdamage < 1) rdamage = 1;
}
}
else if(dmg.flag&BF_LONG) {
if(bl->type == BL_PC) {
struct map_session_data *tsd = (struct map_session_data *)bl;
if(tsd->long_weapon_damage_return > 0) {
rdamage += damage * tsd->long_weapon_damage_return / 100;
if(rdamage < 1) rdamage = 1;
}
}
}
if(rdamage > 0)
clif_damage(src,src,tick, dmg.amotion,0,rdamage,1,4,0);
}
if(skillid == WZ_SIGHTRASHER)
clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,
damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, 5);
else
clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,
damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, (skillid==0)? 5:type );
if(dmg.blewcount > 0 && !map[src->m].flag.gvg) { /* 悂偒旘偽偟張棟偲偦偺僷働僢僩 */
if(skillid == WZ_SIGHTRASHER)
skill_blown(src,bl,dmg.blewcount);
else
skill_blown(dsrc,bl,dmg.blewcount);
if(bl->type == BL_MOB)
clif_fixmobpos((struct mob_data *)bl);
else if(bl->type == BL_PET)
clif_fixpetpos((struct pet_data *)bl);
else
clif_fixpos(bl);
}
map_freeblock_lock();
/* 幚嵺偵僟儊乕僕張棟傪峴偆 */
if(skillid != KN_BOWLINGBASH || flag)
battle_damage(src,bl,damage,0);
if(skillid == RG_INTIMIDATE && damage > 0 && !(battle_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) {
int s_lv = battle_get_lv(src),t_lv = battle_get_lv(bl);
int rate = 50 + skilllv * 5;
rate = rate + (s_lv - t_lv);
if(rand()%100 < rate)
skill_addtimerskill(src,tick + 800,bl->id,0,0,skillid,skilllv,0,flag);
}
if(damage > 0 && dmg.flag&BF_SKILL && bl->type==BL_PC && pc_checkskill((struct map_session_data *)bl,RG_PLAGIARISM)){
struct map_session_data *tsd = (struct map_session_data *)bl;
if(!tsd->status.skill[skillid].id && !tsd->status.skill[skillid].id
&& !(skillid > NPC_PIERCINGATT && skillid < NPC_SUMMONMONSTER) ){
//婛偵搻傫偱偄傞僗僉儖偑偁傟偽奩摉僗僉儖傪徚偡
if (tsd->cloneskill_id && tsd->cloneskill_lv && tsd->status.skill[tsd->cloneskill_id].flag==13){
tsd->status.skill[tsd->cloneskill_id].id=0;
tsd->status.skill[tsd->cloneskill_id].lv=0;
tsd->status.skill[tsd->cloneskill_id].flag=0;
}
tsd->cloneskill_id=skillid;
tsd->cloneskill_lv=skilllv;
tsd->status.skill[skillid].id=skillid;
tsd->status.skill[skillid].lv=(pc_checkskill(tsd,RG_PLAGIARISM) > skill_get_max(skillid))?
skill_get_max(skillid):pc_checkskill(tsd,RG_PLAGIARISM);
tsd->status.skill[skillid].flag=13;//cloneskill flag
clif_skillinfoblock(tsd);
}
}
/* 僟儊乕僕偑偁傞側傜捛壛岠壥敾掕 */
if(bl->prev != NULL &&
(bl->type != BL_PC || (bl->type == BL_PC && !pc_isdead((struct map_session_data *)bl) ) ) ) {
if(damage > 0)
skill_additional_effect(src,bl,skillid,skilllv,attack_type,tick);
if(bl->type==BL_MOB && src!=bl) /* 僗僉儖巊梡忦審偺MOB僗僉儖 */
{
if(battle_config.mob_changetarget_byskill == 1)
{
int target=((struct mob_data *)bl)->target_id;
if(src->type == BL_PC)
((struct mob_data *)bl)->target_id=src->id;
mobskill_use((struct mob_data *)bl,tick,MSC_SKILLUSED|(skillid<<16));
((struct mob_data *)bl)->target_id=target;
}
else
mobskill_use((struct mob_data *)bl,tick,MSC_SKILLUSED|(skillid<<16));
}
}
if(src->type == BL_PC && dmg.flag&BF_WEAPON && src != bl && src == dsrc && damage > 0) {
struct map_session_data *sd = (struct map_session_data *)src;
int hp = 0,sp = 0;
if(sd->hp_drain_rate && sd->hp_drain_per > 0 && dmg.damage > 0 && rand()%100 < sd->hp_drain_rate) {
hp += (dmg.damage * sd->hp_drain_per)/100;
if(sd->hp_drain_rate > 0 && hp < 1) hp = 1;
else if(sd->hp_drain_rate < 0 && hp > -1) hp = -1;
}
if(sd->hp_drain_rate_ && sd->hp_drain_per_ > 0 && dmg.damage2 > 0 && rand()%100 < sd->hp_drain_rate_) {
hp += (dmg.damage2 * sd->hp_drain_per_)/100;
if(sd->hp_drain_rate_ > 0 && hp < 1) hp = 1;
else if(sd->hp_drain_rate_ < 0 && hp > -1) hp = -1;
}
if(sd->sp_drain_rate > 0 && sd->sp_drain_per > 0 && dmg.damage > 0 && rand()%100 < sd->sp_drain_rate) {
sp += (dmg.damage * sd->sp_drain_per)/100;
if(sd->sp_drain_rate > 0 && sp < 1) sp = 1;
else if(sd->sp_drain_rate < 0 && sp > -1) sp = -1;
}
if(sd->sp_drain_rate_ > 0 && sd->sp_drain_per_ > 0 && dmg.damage2 > 0 && rand()%100 < sd->sp_drain_rate_) {
sp += (dmg.damage2 * sd->sp_drain_per_)/100;
if(sd->sp_drain_rate_ > 0 && sp < 1) sp = 1;
else if(sd->sp_drain_rate_ < 0 && sp > -1) sp = -1;
}
if(hp || sp) pc_heal(sd,hp,sp);
}
if((skillid != KN_BOWLINGBASH || flag) && rdamage > 0)
battle_damage(bl,src,rdamage,0);
if(attack_type&BF_WEAPON && sc_data && sc_data[SC_AUTOCOUNTER].timer != -1 && sc_data[SC_AUTOCOUNTER].val4 > 0) {
if(sc_data[SC_AUTOCOUNTER].val3 == dsrc->id)
battle_weapon_attack(bl,dsrc,tick,0x8000|sc_data[SC_AUTOCOUNTER].val1);
skill_status_change_end(bl,SC_AUTOCOUNTER,-1);
}
map_freeblock_unlock();
return (dmg.damage+dmg.damage2); /* 梌僟儊傪曉偡 */
}
/*==========================================
* 僗僉儖斖埻峌寕梡(map_foreachinarea偐傜屇偽傟傞)
* flag偵偮偄偰丗16恑恾傪妋擣
* MSB <- 00fTffff ->LSB
* T =僞乕僎僢僩慖戰梡(BCT_*)
* ffff=帺桼偵巊梡壜擻
* 0 =梊栺丅0偵屌掕
*------------------------------------------
*/
static int skill_area_temp[8]; /* 堦帪曄悢丅昁梫側傜巊偆丅 */
typedef int (*SkillFunc)(struct block_list *,struct block_list *,int,int,unsigned int,int);
int skill_area_sub( struct block_list *bl,va_list ap )
{
struct block_list *src;
int skill_id,skill_lv,flag;
unsigned int tick;
SkillFunc func;
if(bl->type!=BL_PC && bl->type!=BL_MOB && bl->type!=BL_SKILL)
return 0;
src=va_arg(ap,struct block_list *);
skill_id=va_arg(ap,int);
skill_lv=va_arg(ap,int);
tick=va_arg(ap,unsigned int);
flag=va_arg(ap,int);
func=va_arg(ap,SkillFunc);
if(battle_check_target(src,bl,flag) > 0)
func(src,bl,skill_id,skill_lv,tick,flag);
return 0;
}
static int skill_check_unit_range_sub( struct block_list *bl,va_list ap )
{
struct skill_unit *unit;
int *c,x,y,range,sx[4],sy[4];
int t_range,tx[4],ty[4];
int i,r_flag,skillid;
if(bl->prev == NULL || bl->type != BL_SKILL)
return 0;
unit = (struct skill_unit *)bl;
if(!unit->alive) return 0;
c = va_arg(ap,int *);
x = va_arg(ap,int);
y = va_arg(ap,int);
range = va_arg(ap,int);
skillid = va_arg(ap,int);
if(skillid == MG_SAFETYWALL || skillid == AL_PNEUMA) {
if(unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85)
return 0;
}
else if(skillid == AL_WARP) {
if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92)
return 0;
}
else if((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP) || skillid == HT_TALKIEBOX) {
if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92)
return 0;
}
else if(skillid == WZ_FIREPILLAR) {
if(unit->group->unit_id != 0x87)
return 0;
}
else return 0;
t_range=(unit->range!=0)? unit->range:unit->group->range;
tx[0] = tx[3] = unit->bl.x - t_range;
tx[1] = tx[2] = unit->bl.x + t_range;
ty[0] = ty[1] = unit->bl.y - t_range;
ty[2] = ty[3] = unit->bl.y + t_range;
sx[0] = sx[3] = x - range;
sx[1] = sx[2] = x + range;
sy[0] = sy[1] = y - range;
sy[2] = sy[3] = y + range;
for(i=r_flag=0;i<4;i++) {
if(sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0] && sy[i] <= ty[2]) {
r_flag = 1;
break;
}
if(tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0] && ty[i] <= sy[2]) {
r_flag = 1;
break;
}
}
if(r_flag) (*c)++;
return 0;
}
int skill_check_unit_range(int m,int x,int y,int range,int skillid)
{
int c = 0;
map_foreachinarea(skill_check_unit_range_sub,m,x-10,y-10,x+10,y+10,BL_SKILL,&c,x,y,range,skillid);
return c;
}
static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap )
{
int *c;
c = va_arg(ap,int *);
if(bl->prev == NULL || (bl->type != BL_PC && bl->type != BL_MOB))
return 0;
if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
return 0;
(*c)++;
return 0;
}
int skill_check_unit_range2(int m,int x,int y,int range)
{
int c = 0;
map_foreachinarea(skill_check_unit_range2_sub,m,x-range,y-range,x+range,y+range,0,&c);
return c;
}
/*=========================================================================
* 斖埻僗僉儖巊梡張棟彫暘偗偙偙偐傜
*/
/* 懳徾偺悢傪僇僂儞僩偡傞丅乮skill_area_temp[0]傪弶婜壔偟偰偍偔偙偲乯 */
int skill_area_sub_count(struct block_list *src,struct block_list *target,int skillid,int skilllv,unsigned int tick,int flag)
{
if(skill_area_temp[0] < 0xffff)
skill_area_temp[0]++;
return 0;
}
/*==========================================
*
*------------------------------------------
*/
static int skill_timerskill(int tid, unsigned int tick, int id,int data )
{
struct map_session_data *sd = NULL;
struct mob_data *md = NULL;
struct block_list *src,*target;
struct skill_timerskill *skl = NULL;
int range;
src = map_id2bl(id);
if(src == NULL || src->prev == NULL)
return 0;
if(src->type == BL_PC) {
sd = (struct map_session_data *)src;
skl = &sd->skilltimerskill[data];
}
else if(src->type == BL_MOB) {
md = (struct mob_data *)src;
skl = &md->skilltimerskill[data];
}
else
return 0;
skl->timer = -1;
if(skl->target_id) {
struct block_list tbl;
target = map_id2bl(skl->target_id);
if(skl->skill_id == RG_INTIMIDATE) {
if(target == NULL) {
target = &tbl;
target->type = BL_NUL;
target->m = src->m;
target->prev = target->next = NULL;
}
}
if(target == NULL)
return 0;
if(target->prev == NULL && skl->skill_id != RG_INTIMIDATE)
return 0;
if(src->m != target->m)
return 0;
if(sd && pc_isdead(sd))
return 0;
if(target->type == BL_PC && pc_isdead((struct map_session_data *)target) && skl->skill_id != RG_INTIMIDATE)
return 0;
switch(skl->skill_id) {
case TF_BACKSLIDING:
clif_skill_nodamage(src,src,skl->skill_id,skl->skill_lv,1);
break;
case RG_INTIMIDATE:
if(src->type == BL_PC && !map[src->m].flag.noteleport) {
int x,y,i,j,c;
pc_randomwarp(sd,3);
for(i=0;i<16;i++) {
j = rand()%8;
x = sd->bl.x + dirx[j];
y = sd->bl.y + diry[j];
if((c=map_getcell(sd->bl.m,x,y)) != 1 && c != 5)
break;
}
if(i >= 16) {
x = sd->bl.x;
y = sd->bl.y;
}
if(target->prev != NULL) {
if(target->type == BL_PC && !pc_isdead((struct map_session_data *)target))
pc_setpos((struct map_session_data *)target,map[sd->bl.m].name,x,y,3);
else if(target->type == BL_MOB)
mob_warp((struct mob_data *)target,-1,x,y,3);
}
}
else if(src->type == BL_MOB && !map[src->m].flag.monster_noteleport) {
int x,y,i,j,c;
mob_warp(md,-1,-1,-1,3);
for(i=0;i<16;i++) {
j = rand()%8;
x = md->bl.x + dirx[j];
y = md->bl.y + diry[j];
if((c=map_getcell(md->bl.m,x,y)) != 1 && c != 5)
break;
}
if(i >= 16) {
x = md->bl.x;
y = md->bl.y;
}
if(target->prev != NULL) {
if(target->type == BL_PC && !pc_isdead((struct map_session_data *)target))
pc_setpos((struct map_session_data *)target,map[md->bl.m].name,x,y,3);
else if(target->type == BL_MOB)
mob_warp((struct mob_data *)target,-1,x,y,3);
}
}
break;
case BA_FROSTJOKE: /* 姦偄僕儑乕僋 */
case DC_SCREAM: /* 僗僋儕乕儉 */
range=15; //帇奅慡懱
map_foreachinarea(skill_frostjoke_scream,src->m,src->x-range,src->y-range,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -