📄 mob.c
字号:
{
int id;
id=va_arg(ap,int);
if(sd->attacktarget==id)
pc_stopattack(sd);
return 0;
}
/*==========================================
* 尰嵼摦偄偰偄傞僞僀儅傪巭傔偰忬懺傪曄峏
*------------------------------------------
*/
int mob_changestate(struct mob_data *md,int state,int type)
{
unsigned int tick;
int i;
if(md->timer != -1)
delete_timer(md->timer,mob_timer);
md->timer=-1;
md->state.state=state;
switch(state){
case MS_WALK:
if((i=calc_next_walk_step(md))>0){
i = i>>2;
md->timer=add_timer(gettick()+i,mob_timer,md->bl.id,0);
}
else
md->state.state=MS_IDLE;
break;
case MS_ATTACK:
tick = gettick();
i=DIFF_TICK(md->attackabletime,tick);
if(i>0 && i<2000)
md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
else if(type) {
md->attackabletime = tick + battle_get_amotion(&md->bl);
md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
}
else {
md->attackabletime = tick + 1;
md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
}
break;
case MS_DELAY:
md->timer=add_timer(gettick()+type,mob_timer,md->bl.id,0);
break;
case MS_DEAD:
skill_castcancel(&md->bl,0);
// mobskill_deltimer(md);
md->state.skillstate=MSS_DEAD;
md->last_deadtime=gettick();
// 巰傫偩偺偱偙偺mob傊偺峌寕幰慡堳偺峌寕傪巭傔傞
clif_foreachclient(mob_stopattacked,md->bl.id);
skill_unit_out_all(&md->bl,gettick(),1);
skill_status_change_clear(&md->bl,2); // 僗僥乕僞僗堎忢傪夝彍偡傞
skill_clear_unitgroup(&md->bl); // 慡偰偺僗僉儖儐僯僢僩僌儖乕僾傪嶍彍偡傞
skill_cleartimerskill(&md->bl);
md->hp=md->target_id=md->attacked_id=0;
md->state.targettype = NONE_ATTACKABLE;
break;
}
return 0;
}
/*==========================================
* mob偺timer張棟 (timer娭悢)
* 曕峴偲峌寕偵暘婒
*------------------------------------------
*/
static int mob_timer(int tid,unsigned int tick,int id,int data)
{
struct mob_data *md;
md=(struct mob_data*)map_id2bl(id);
if(md==NULL || md->bl.type!=BL_MOB)
return 1;
if(md->timer != tid){
if(battle_config.error_log)
printf("mob_timer %d != %d\n",md->timer,tid);
return 0;
}
md->timer=-1;
if(md->bl.prev == NULL || md->state.state == MS_DEAD)
return 1;
map_freeblock_lock();
switch(md->state.state){
case MS_WALK:
mob_walk(md,tick,data);
break;
case MS_ATTACK:
mob_attack(md,tick,data);
break;
case MS_DELAY:
mob_changestate(md,MS_IDLE,0);
break;
default:
if(battle_config.error_log)
printf("mob_timer : %d ?\n",md->state.state);
break;
}
map_freeblock_unlock();
return 0;
}
/*==========================================
*
*------------------------------------------
*/
static int mob_walktoxy_sub(struct mob_data *md)
{
struct walkpath_data wpd;
if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,md->to_x,md->to_y,md->state.walk_easy))
return 1;
memcpy(&md->walkpath,&wpd,sizeof(wpd));
md->state.change_walk_target=0;
mob_changestate(md,MS_WALK,0);
clif_movemob(md);
return 0;
}
/*==========================================
* mob堏摦奐巒
*------------------------------------------
*/
int mob_walktoxy(struct mob_data *md,int x,int y,int easy)
{
struct walkpath_data wpd;
if(md->state.state == MS_WALK && path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,x,y,easy) )
return 1;
md->state.walk_easy = easy;
md->to_x=x;
md->to_y=y;
if(md->state.state == MS_WALK) {
md->state.change_walk_target=1;
} else {
return mob_walktoxy_sub(md);
}
return 0;
}
/*==========================================
* delay晅偒mob spawn (timer娭悢)
*------------------------------------------
*/
static int mob_delayspawn(int tid,unsigned int tick,int m,int n)
{
mob_spawn(m);
return 0;
}
/*==========================================
* spawn僞僀儈儞僌寁嶼
*------------------------------------------
*/
int mob_setdelayspawn(int id)
{
unsigned int spawntime,spawntime1,spawntime2,spawntime3;
struct mob_data *md;
md=(struct mob_data*)map_id2bl(id);
if(md==NULL || md->bl.type!=BL_MOB)
return -1;
// 暅妶偟側偄MOB偺張棟
if(md->spawndelay1==-1 && md->spawndelay2==-1 && md->n==0){
map_deliddb(&md->bl);
if(md->lootitem) {
map_freeblock(md->lootitem);
md->lootitem=NULL;
}
map_freeblock(md); // free偺偐傢傝
return 0;
}
spawntime1=md->last_spawntime+md->spawndelay1;
spawntime2=md->last_deadtime+md->spawndelay2;
spawntime3=gettick()+5000;
// spawntime = max(spawntime1,spawntime2,spawntime3);
if(DIFF_TICK(spawntime1,spawntime2)>0){
spawntime=spawntime1;
} else {
spawntime=spawntime2;
}
if(DIFF_TICK(spawntime3,spawntime)>0){
spawntime=spawntime3;
}
add_timer(spawntime,mob_delayspawn,id,0);
return 0;
}
/*==========================================
* mob弌尰丅怓乆弶婜壔傕偙偙偱
*------------------------------------------
*/
int mob_spawn(int id)
{
int x=0,y=0,i=0,c;
unsigned int tick = gettick();
struct mob_data *md;
md=(struct mob_data*)map_id2bl(id);
if(md==NULL || md->bl.type!=BL_MOB)
return -1;
md->last_spawntime=tick;
if( md->bl.prev!=NULL ){
// clif_clearchar_area(&md->bl,3);
skill_unit_out_all(&md->bl,gettick(),1);
map_delblock(&md->bl);
}
else
md->class = md->base_class;
md->bl.m =md->m;
do {
if(md->x0==0 && md->y0==0){
x=rand()%(map[md->bl.m].xs-2)+1;
y=rand()%(map[md->bl.m].ys-2)+1;
} else {
x=md->x0+rand()%(md->xs+1)-md->xs/2;
y=md->y0+rand()%(md->ys+1)-md->ys/2;
}
i++;
} while(((c=map_getcell(md->bl.m,x,y))==1 || c==5) && i<50);
if(i>=50){
// if(battle_config.error_log)
// printf("MOB spawn error %d @ %s\n",id,map[md->bl.m].name);
add_timer(tick+5000,mob_delayspawn,id,0);
return 1;
}
md->to_x=md->bl.x=x;
md->to_y=md->bl.y=y;
md->dir=0;
map_addblock(&md->bl);
memset(&md->state,0,sizeof(md->state));
md->attacked_id = 0;
md->target_id = 0;
md->move_fail_count = 0;
md->speed = mob_db[md->class].speed;
md->def_ele = mob_db[md->class].element;
md->master_id=0;
md->master_dist=0;
md->state.state = MS_IDLE;
md->state.skillstate = MSS_IDLE;
md->timer = -1;
md->last_thinktime = tick;
md->next_walktime = tick+rand()%50+5000;
md->attackabletime = tick;
md->canmove_tick = tick;
md->skilltimer=-1;
for(i=0,c=tick-1000*3600*10;i<MAX_MOBSKILL;i++)
md->skilldelay[i] = c;
md->skillid=0;
md->skilllv=0;
memset(md->dmglog,0,sizeof(md->dmglog));
if(md->lootitem)
memset(md->lootitem,0,sizeof(md->lootitem));
md->lootitem_count = 0;
for(i=0;i<MAX_MOBSKILLTIMERSKILL;i++)
md->skilltimerskill[i].timer = -1;
for(i=0;i<MAX_STATUSCHANGE;i++) {
md->sc_data[i].timer=-1;
md->sc_data[i].val1 = md->sc_data[i].val2 = md->sc_data[i].val3 = md->sc_data[i].val4 =0;
}
md->sc_count=0;
md->opt1=md->opt2=md->option=0;
memset(md->skillunit,0,sizeof(md->skillunit));
memset(md->skillunittick,0,sizeof(md->skillunittick));
md->hp = battle_get_max_hp(&md->bl);
if(md->hp<=0){
mob_makedummymobdb(md->class);
md->hp = battle_get_max_hp(&md->bl);
}
clif_spawnmob(md);
return 0;
}
/*==========================================
* 2揰娫嫍棧寁嶼
*------------------------------------------
*/
static int distance(int x0,int y0,int x1,int y1)
{
int dx,dy;
dx=abs(x0-x1);
dy=abs(y0-y1);
return dx>dy ? dx : dy;
}
/*==========================================
* MOB偺峌寕掆巭
*------------------------------------------
*/
int mob_stopattack(struct mob_data *md)
{
md->target_id=0;
md->state.targettype = NONE_ATTACKABLE;
md->attacked_id=0;
return 0;
}
/*==========================================
* MOB偺堏摦拞巭
*------------------------------------------
*/
int mob_stop_walking(struct mob_data *md,int type)
{
if(md->state.state == MS_WALK || md->state.state == MS_IDLE) {
md->walkpath.path_len=0;
md->to_x=md->bl.x;
md->to_y=md->bl.y;
mob_changestate(md,MS_IDLE,0);
}
if(type&0x01)
clif_fixmobpos(md);
if(type&0x02) {
int delay=battle_get_dmotion(&md->bl);
unsigned int tick = gettick();
if(md->canmove_tick < tick)
md->canmove_tick = tick + delay;
}
return 0;
}
/*==========================================
* 巜掕ID偺懚嵼応強傊偺摓払壜擻惈
*------------------------------------------
*/
int mob_can_reach(struct mob_data *md,struct block_list *bl,int range)
{
int dx=abs(bl->x - md->bl.x),dy=abs(bl->y - md->bl.y);
struct walkpath_data wpd;
int i;
if( md->bl.m != bl-> m) // 堘偆儅僢僾
return 0;
if( range>0 && range < ((dx>dy)?dx:dy) ) // 墦偡偓傞
return 0;
if( md->bl.x==bl->x && md->bl.y==bl->y ) // 摨偠儅僗
return 1;
// 忈奞暔敾掕
wpd.path_len=0;
wpd.path_pos=0;
wpd.path_half=0;
if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,bl->x,bl->y,0)!=-1)
return 1;
if(bl->type!=BL_PC && bl->type!=BL_MOB)
return 0;
// 椬愙壜擻偐偳偆偐敾掕
dx=(dx>0)?1:((dx<0)?-1:0);
dy=(dy>0)?1:((dy<0)?-1:0);
if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,bl->x-dx,bl->y-dy,0)!=-1)
return 1;
for(i=0;i<9;i++){
if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,bl->x-1+i/3,bl->y-1+i%3,0)!=-1)
return 1;
}
return 0;
}
/*==========================================
* 儌儞僗僞乕偺峌寕懳徾寛掕
*------------------------------------------
*/
int mob_target(struct mob_data *md,struct block_list *bl,int dist)
{
struct map_session_data *sd;
struct status_change *sc_data = battle_get_sc_data(bl);
short *option = battle_get_option(bl);
int mode=mob_db[md->class].mode,race=mob_db[md->class].race;
if(!mode) {
md->target_id = 0;
return 0;
}
// 僞僎嵪傒偱僞僎傪曄偊傞婥偑側偄側傜壗傕偟側偄
if( (md->target_id > 0 && md->state.targettype == ATTACKABLE) && ( !(mode&0x04) || rand()%100>25) )
return 0;
if(mode&0x20 || // MVPMOB側傜嫮惂
(sc_data && sc_data[SC_TRICKDEAD].timer == -1 &&
( (option && !(*option&0x06) ) || race==4 || race==6) ) ){
if(bl->type == BL_PC) {
sd = (struct map_session_data *)bl;
if(sd->invincible_timer != -1 || pc_isinvisible(sd) || mob_exclusion_check(md,sd))
return 0;
if(!(mode&0x20) && race!=4 && race!=6 && sd->state.gangsterparadise)
return 0;
}
md->target_id=bl->id; // 朩奞偑側偐偭偨偺偱儘僢僋
if(bl->type == BL_PC || bl->type == BL_MOB)
md->state.targettype = ATTACKABLE;
else
md->state.targettype = NONE_ATTACKABLE;
md->min_chase=dist+13;
if(md->min_chase>26)
md->min_chase=26;
}
return 0;
}
/*==========================================
* 傾僋僥傿僽儌儞僗僞乕偺嶔揋儖乕僥傿儞
*------------------------------------------
*/
static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
{
struct map_session_data *sd=(struct map_session_data *)bl;
struct mob_data* md;
int mode,race,dist,*pcc;
md=va_arg(ap,struct mob_data *);
pcc=va_arg(ap,int *);
mode=mob_db[md->class].mode;
// 傾僋僥傿僽偱僞乕僎僢僩幩掱撪偵偄傞側傜丄儘僢僋偡傞
if( mode&0x04 && !mob_exclusion_check(md,sd)){
if( !pc_isdead(sd) && sd->bl.m == md->bl.m && sd->invincible_timer == -1 && !pc_isinvisible(sd) &&
(dist=distance(md->bl.x,md->bl.y,sd->bl.x,sd->bl.y))<9){
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) ) ){ // 朩奞偑側偄偐敾掕
if( mob_can_reach(md,bl,12) && // 摓払壜擻惈敾掕
rand()%1000<1000/(++(*pcc)) ){ // 斖埻撪PC偱摍妋棪偵偡傞
md->target_id=sd->bl.id;
md->state.targettype = ATTACKABLE;
md->min_chase=13;
}
}
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -