📄 mob.c
字号:
/*==========================================
* loot monster item search
*------------------------------------------
*/
static int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
{
struct mob_data* md;
int mode,dist,*itc;
md=va_arg(ap,struct mob_data *);
itc=va_arg(ap,int *);
mode=mob_db[md->class].mode;
if( !md->target_id && mode&0x02){
if(!md->lootitem || (battle_config.monster_loot_type == 1 && md->lootitem_count >= LOOTITEM_SIZE) )
return 0;
if(bl->m == md->bl.m && (dist=distance(md->bl.x,md->bl.y,bl->x,bl->y))<9){
if( mob_can_reach(md,bl,12) && // 摓払壜擻惈敾掕
rand()%1000<1000/(++(*itc)) ){ // 斖埻撪PC偱摍妋棪偵偡傞
md->target_id=bl->id;
md->state.targettype = NONE_ATTACKABLE;
md->min_chase=13;
}
}
}
return 0;
}
/*==========================================
* 儕儞僋儌儞僗僞乕偺嶔揋儖乕僥傿儞
*------------------------------------------
*/
static int mob_ai_sub_hard_linksearch(struct block_list *bl,va_list ap)
{
struct mob_data *tmd=(struct mob_data *)bl;
struct mob_data* md;
struct block_list *target;
md=va_arg(ap,struct mob_data *);
target=va_arg(ap,struct block_list *);
// 儕儞僋儌儞僗僞乕偱幩掱撪偵壣側摨懓MOB偑偄傞側傜丄儘僢僋偝偣傞
/* if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && mob_db[md->class].mode&0x08){
if( tmd->class==md->class && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE) && tmd->bl.m == md->bl.m){
if( mob_can_reach(tmd,target,12) ){ // 摓払壜擻惈敾掕
tmd->target_id=md->target_id;
tmd->state.targettype = ATTACKABLE;
tmd->min_chase=13;
}
}
}*/
if( md->attacked_id > 0 && mob_db[md->class].mode&0x08){
if( tmd->class==md->class && tmd->bl.m == md->bl.m && (!tmd->target_id || md->state.targettype == NONE_ATTACKABLE)){
if( mob_can_reach(tmd,target,12) ){ // 摓払壜擻惈敾掕
tmd->target_id=md->attacked_id;
tmd->state.targettype = ATTACKABLE;
tmd->min_chase=13;
}
}
}
return 0;
}
/*==========================================
* 庢傝姫偒儌儞僗僞乕偺張棟
*------------------------------------------
*/
static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
{
struct mob_data *mmd=(struct mob_data *)map_id2bl(md->master_id);
int mode,race,old_dist;
mode=mob_db[md->class].mode;
// 庡偱偼側偄
if(!mmd || mmd->bl.type!=BL_MOB || mmd->bl.id!=md->master_id)
return 0;
// 庡偑堘偆儅僢僾偵偄傞偺偱僥儗億乕僩偟偰捛偄偐偗傞
if( mmd->bl.m != md->bl.m ){
mob_warp(md,mmd->bl.m,mmd->bl.x,mmd->bl.y,3);
md->state.master_check = 1;
return 0;
}
// 庡偲偺嫍棧傪應傞
old_dist=md->master_dist;
md->master_dist=distance(md->bl.x,md->bl.y,mmd->bl.x,mmd->bl.y);
// 捈慜傑偱庡偑嬤偔偵偄偨偺偱僥儗億乕僩偟偰捛偄偐偗傞
if( old_dist<10 && md->master_dist>18){
mob_warp(md,-1,mmd->bl.x,mmd->bl.y,3);
md->state.master_check = 1;
return 0;
}
// 庡偑偄傞偑丄彮偟墦偄偺偱嬤婑傞
if((!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mob_can_move(md) &&
(md->walkpath.path_pos>=md->walkpath.path_len || md->walkpath.path_len==0) && md->master_dist<15){
int i=0,dx,dy,ret;
if(md->master_dist>4) {
do {
if(i<=5){
dx=mmd->bl.x - md->bl.x;
dy=mmd->bl.y - md->bl.y;
if(dx<0) dx+=(rand()%( (dx<-3)?3:-dx )+1);
else if(dx>0) dx-=(rand()%( (dx>3)?3:dx )+1);
if(dy<0) dy+=(rand()%( (dy<-3)?3:-dy )+1);
else if(dy>0) dy-=(rand()%( (dy>3)?3:dy )+1);
}else{
dx=mmd->bl.x - md->bl.x + rand()%7 - 3;
dy=mmd->bl.y - md->bl.y + rand()%7 - 3;
}
ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
i++;
} while(ret && i<10);
}
else {
do {
dx = rand()%9 - 5;
dy = rand()%9 - 5;
if( dx == 0 && dy == 0) {
dx = (rand()%1)? 1:-1;
dy = (rand()%1)? 1:-1;
}
dx += mmd->bl.x;
dy += mmd->bl.y;
ret=mob_walktoxy(md,mmd->bl.x+dx,mmd->bl.y+dy,0);
i++;
} while(ret && i<10);
}
md->next_walktime=tick+500;
md->state.master_check = 1;
}
// 庡偑偄偰丄庡偑儘僢僋偟偰偄偰帺暘偼儘僢僋偟偰偄側偄
if( (mmd->target_id>0 && mmd->state.targettype == ATTACKABLE) && (!md->target_id || md->state.targettype == NONE_ATTACKABLE) ){
struct map_session_data *sd=map_id2sd(mmd->target_id);
if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd) && !mob_exclusion_check(md,sd)){
race=mob_db[md->class].race;
if(mode&0x20 ||
(sd->sc_data[SC_TRICKDEAD].timer == -1 &&
( (!pc_ishiding(sd) && !sd->state.gangsterparadise) || race==4 || race==6) ) ){ // 朩奞偑側偄偐敾掕
md->target_id=sd->bl.id;
md->state.targettype = ATTACKABLE;
md->min_chase=5+distance(md->bl.x,md->bl.y,sd->bl.x,sd->bl.y);
md->state.master_check = 1;
}
}
}
// 庡偑偄偰丄庡偑儘僢僋偟偰側偔偰帺暘偼儘僢僋偟偰偄傞
/* if( (md->target_id>0 && mmd->state.targettype == ATTACKABLE) && (!mmd->target_id || mmd->state.targettype == NONE_ATTACKABLE) ){
struct map_session_data *sd=map_id2sd(md->target_id);
if(sd!=NULL && !pc_isdead(sd) && sd->invincible_timer == -1 && !pc_isinvisible(sd)){
race=mob_db[mmd->class].race;
if(mode&0x20 ||
(sd->sc_data[SC_TRICKDEAD].timer == -1 &&
(!(sd->status.option&0x06) || race==4 || race==6)
) ){ // 朩奞偑側偄偐敾掕
mmd->target_id=sd->bl.id;
mmd->state.targettype = ATTACKABLE;
mmd->min_chase=5+distance(mmd->bl.x,mmd->bl.y,sd->bl.x,sd->bl.y);
}
}
}*/
return 0;
}
/*==========================================
* 儘僢僋傪巭傔偰懸婡忬懺偵堏傞丅
*------------------------------------------
*/
static int mob_unlocktarget(struct mob_data *md,int tick)
{
md->target_id=0;
md->state.targettype = NONE_ATTACKABLE;
md->state.skillstate=MSS_IDLE;
md->next_walktime=tick+rand()%3000+3000;
return 0;
}
/*==========================================
* 儔儞僟儉曕峴
*------------------------------------------
*/
static int mob_randomwalk(struct mob_data *md,int tick)
{
const int retrycount=20;
int speed=battle_get_speed(&md->bl);
if(DIFF_TICK(md->next_walktime,tick)<0){
int i,x,y,c,d=12-md->move_fail_count;
if(d<5) d=5;
for(i=0;i<retrycount;i++){ // 堏摦偱偒傞応強偺扵嶕
int r=rand();
x=md->bl.x+r%(d*2+1)-d;
y=md->bl.y+r/(d*2+1)%(d*2+1)-d;
if((c=map_getcell(md->bl.m,x,y))!=1 && c!=5 && mob_walktoxy(md,x,y,1)==0){
md->move_fail_count=0;
break;
}
if(i+1>=retrycount){
md->move_fail_count++;
if(md->move_fail_count>1000){
if(battle_config.error_log)
printf("MOB cant move. random spawn %d, class = %d\n",md->bl.id,md->class);
md->move_fail_count=0;
mob_spawn(md->bl.id);
}
}
}
for(i=c=0;i<md->walkpath.path_len;i++){ // 師偺曕峴奐巒帪崗傪寁嶼
if(md->walkpath.path[i]&1)
c+=speed*14/10;
else
c+=speed;
}
md->next_walktime = tick+rand()%3000+3000+c;
md->state.skillstate=MSS_WALK;
return 1;
}
return 0;
}
/*==========================================
* PC偑嬤偔偵偄傞MOB偺AI
*------------------------------------------
*/
static int mob_ai_sub_hard(struct block_list *bl,va_list ap)
{
struct mob_data *md;
struct map_session_data *sd;
struct block_list *bl_item;
struct flooritem_data *fitem;
unsigned int tick;
int i,dx,dy,ret,dist;
int attack_type=0;
int mode,race;
md=(struct mob_data*)bl;
tick=va_arg(ap,unsigned int);
if(DIFF_TICK(tick,md->last_thinktime)<MIN_MOBTHINKTIME)
return 0;
md->last_thinktime=tick;
if( md->skilltimer!=-1 || md->bl.prev==NULL ){ // 僗僉儖塺彞拞偐巰朣拞
if(DIFF_TICK(tick,md->next_walktime)>MIN_MOBTHINKTIME)
md->next_walktime=tick;
return 0;
}
mode=mob_db[md->class].mode;
race=mob_db[md->class].race;
// 堎忢
if((md->opt1 > 0 && md->opt1 != 6) || md->state.state==MS_DELAY || md->sc_data[SC_BLADESTOP].timer != -1){
return 0;
}
if(!mode && md->target_id > 0)
md->target_id = 0;
if(md->attacked_id > 0 && mode&0x08){ // 儕儞僋儌儞僗僞乕
sd=map_id2sd(md->attacked_id);
if(sd) {
if(sd->invincible_timer == -1 && !pc_isinvisible(sd) && !mob_exclusion_check(md,sd)) {
map_foreachinarea(mob_ai_sub_hard_linksearch,md->bl.m,
md->bl.x-13,md->bl.y-13,
md->bl.x+13,md->bl.y+13,
BL_MOB,md,&sd->bl);
}
}
}
// 傑偢峌寕偝傟偨偐妋擣乮傾僋僥傿僽側傜25%偺妋棪偱僞乕僎僢僩曄峏乯
if( mode>0 && md->attacked_id>0 && (!md->target_id || md->state.targettype == NONE_ATTACKABLE
|| (mob_db[md->class].mode&0x04 && rand()%100<25 ) )){
sd=map_id2sd(md->attacked_id);
if(sd==NULL || md->bl.m != sd->bl.m || sd->bl.prev == NULL || sd->invincible_timer != -1 || pc_isinvisible(sd) || mob_exclusion_check(md,sd) ||
(dist=distance(md->bl.x,md->bl.y,sd->bl.x,sd->bl.y))>=32){
md->attacked_id=0;
}
else {
md->target_id=md->attacked_id; // set target
md->state.targettype = ATTACKABLE;
attack_type = 1;
md->attacked_id=0;
md->min_chase=dist+13;
if(md->min_chase>26)
md->min_chase=26;
}
}
md->state.master_check = 0;
// 庢傝姫偒儌儞僗僞乕偺張棟
if( md->master_id > 0 )
mob_ai_sub_hard_slavemob(md,tick);
// 傾僋僥傿償儌儞僗僞乕偺嶔揋
if( (!md->target_id || md->state.targettype == NONE_ATTACKABLE) && mode&0x04 && !md->state.master_check &&
battle_config.monster_active_enable){
i=0;
map_foreachinarea(mob_ai_sub_hard_activesearch,md->bl.m,
md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
BL_PC,md,&i);
}
// 儖乕僩儌儞僗僞乕偺傾僀僥儉僒乕僠
if( !md->target_id && mode&0x02 && !md->state.master_check){
i=0;
map_foreachinarea(mob_ai_sub_hard_lootsearch,md->bl.m,
md->bl.x-AREA_SIZE*2,md->bl.y-AREA_SIZE*2,
md->bl.x+AREA_SIZE*2,md->bl.y+AREA_SIZE*2,
BL_ITEM,md,&i);
}
// 峌寕懳徾偑嫃傞側傜峌寕
if(md->target_id > 0){
sd=map_id2sd(md->target_id);
if(sd) {
if(sd->bl.m != md->bl.m || sd->bl.prev == NULL ||
(dist=distance(md->bl.x,md->bl.y,sd->bl.x,sd->bl.y))>=md->min_chase){
// 暿儅僢僾偐丄帇奅奜
mob_unlocktarget(md,tick);
} else if( !(mode&0x20) &&
(sd->sc_data[SC_TRICKDEAD].timer != -1 ||
((pc_ishiding(sd) || sd->state.gangsterparadise) && race!=4 && race!=6)
) ){
// 僗僉儖側偳偵傛傞嶔揋朩奞
mob_unlocktarget(md,tick);
} else if(!battle_check_range(&md->bl,&sd->bl,mob_db[md->class].range)){
// 峌寕斖埻奜側偺偱堏摦
if(!(mode&1)){ // 堏摦偟側偄儌乕僪
mob_unlocktarget(md,tick);
return 0;
}
if( !mob_can_move(md) ) // 摦偗側偄忬懺偵偁傞
return 0;
md->state.skillstate=MSS_CHASE; // 撍寕帪僗僉儖
mobskill_use(md,tick,-1);
// if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,sd->bl.x,sd->bl.y)<2) )
if(md->timer != -1 && md->state.state!=MS_ATTACK && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,sd->bl.x,sd->bl.y)<2) )
return 0; // 婛偵堏摦拞
if( !mob_can_reach(md,&sd->bl,(md->min_chase>13)?md->min_chase:13) ){
// 堏摦偱偒側偄偺偱僞僎夝彍乮IW偲偐丠乯
mob_unlocktarget(md,tick);
}else{
// 捛愓
md->next_walktime=tick+500;
i=0;
do {
if(i==0){ // 嵟弶偼AEGIS偲摨偠曽朄偱専嶕
dx=sd->bl.x - md->bl.x;
dy=sd->bl.y - md->bl.y;
if(dx<0) dx++;
else if(dx>0) dx--;
if(dy<0) dy++;
else if(dy>0) dy--;
}else{ // 偩傔側傜Athena幃(儔儞僟儉)
dx=sd->bl.x - md->bl.x + rand()%3 - 1;
dy=sd->bl.y - md->bl.y + rand()%3 - 1;
}
/* if(path_search(&md->walkpath,md->bl.m,md->bl.x,md->bl.y,md->bl.x+dx,md->bl.y+dy,0)){
dx=sd->bl.x - md->bl.x;
dy=sd->bl.y - md->bl.y;
if(dx<0) dx--;
else if(dx>0) dx++;
if(dy<0) dy--;
else if(dy>0) dy++;
}*/
ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
i++;
} while(ret && i<5);
if(ret){ // 堏摦晄壜擻側強偐傜偺峌寕側傜2曕壓傞
if(dx<0) dx=2;
else if(dx>0) dx=-2;
if(dy<0) dy=2;
else if(dy>0) dy=-2;
mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
}
}
} else { // 峌寕幩掱斖埻撪
md->state.skillstate=MSS_ATTACK;
if(md->state.state==MS_WALK){ // 曕峴拞側傜掆巭
mob_stop_walking(md,1);
}
if(md->state.state==MS_ATTACK)
return 0; // 婛偵峌寕拞
mob_changestate(md,MS_ATTACK,attack_type);
/* if(mode&0x08){ // 儕儞僋儌儞僗僞乕
map_foreachinarea(mob_ai_sub_hard_linksearch,md->bl.m,
md->bl.x-13,md->bl.y-13,
md->bl.x+13,md->bl.y+13,
BL_MOB,md,&sd->bl);
}*/
}
return 0;
}
else { // 儖乕僩儌儞僗僞乕張棟
bl_item = map_id2bl(md->target_id);
if(bl_item == NULL || bl_item->type != BL_ITEM ||bl_item->m != md->bl.m ||
(dist=distance(md->bl.x,md->bl.y,bl_item->x,bl_item->y))>=md->min_chase || !md->lootitem){
// 墦偡偓傞偐傾僀僥儉偑側偔側偭偨
mob_unlocktarget(md,tick);
}
else if(dist){
if(!(mode&1)){ // 堏摦偟側偄儌乕僪
mob_unlocktarget(md,tick);
return 0;
}
if( !mob_can_move(md) ) // 摦偗側偄忬懺偵偁傞
return 0;
md->state.skillstate=MSS_LOOT; // 儖乕僩帪僗僉儖巊梡
mobskill_use(md,tick,-1);
// if(md->timer != -1 && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,bl_item->x,bl_item->y)<2) )
if(md->timer != -1 && md->state.state!=MS_ATTACK && (DIFF_TICK(md->next_walktime,tick)<0 || distance(md->to_x,md->to_y,bl_item->x,bl_item->y) <= 0))
return 0; // 婛偵堏摦拞
md->next_walktime=tick+500;
dx=bl_item->x - md->bl.x;
dy=bl_item->y - md->bl.y;
/* if(path_search(&md->walkpath,md->bl.m,md->bl.x,md->bl.y,md->bl.x+dx,md->bl.y+dy,0)){
dx=bl_item->x - md->bl.x;
dy=bl_item->y - md->bl.y;
}*/
ret=mob_walktoxy(md,md->bl.x+dx,md->bl.y+dy,0);
if(ret){
// 堏摦偱偒側偄偺偱僞僎夝彍乮IW偲偐丠乯
mob_unlocktarget(md,tick);
}
} else { // 傾僀僥儉傑偱偨偳傝拝偄偨
if(md->state.state==MS_ATTACK)
return 0; // 峌寕拞
if(md->state.state==MS_WALK){ // 曕峴拞側傜掆巭
mob_stop_walking(md,1);
}
fitem = (struct flooritem_data *)bl_item;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -