📄 mob.c
字号:
if(md->lootitem_count < LOOTITEM_SIZE)
memcpy(&md->lootitem[md->lootitem_count++],&fitem->item_data,sizeof(md->lootitem[0]));
else if(battle_config.monster_loot_type == 1 && md->lootitem_count >= LOOTITEM_SIZE) {
mob_unlocktarget(md,tick);
return 0;
}
else {
if(md->lootitem[0].card[0] == (short)0xff00)
intif_delete_petdata(*((long *)(&md->lootitem[0].card[1])));
for(i=0;i<LOOTITEM_SIZE-1;i++)
memcpy(&md->lootitem[i],&md->lootitem[i+1],sizeof(md->lootitem[0]));
memcpy(&md->lootitem[LOOTITEM_SIZE-1],&fitem->item_data,sizeof(md->lootitem[0]));
}
map_clearflooritem(bl_item->id);
mob_unlocktarget(md,tick);
}
return 0;
}
}
// 曕峴帪/懸婡帪僗僉儖巊梡
if( mobskill_use(md,tick,-1) )
return 0;
// 曕峴張棟
if( mode&1 && mob_can_move(md) && // 堏摦壜擻MOB&摦偗傞忬懺偵偁傞
(md->master_id==0 || md->master_dist>10) ){ //庢傝姫偒MOB偠傖側偄
// 儔儞僟儉堏摦
if( mob_randomwalk(md,tick) )
return 0;
}
// 曕偒廔傢偭偰傞偺偱懸婡
if( md->walkpath.path_len==0 || md->walkpath.path_pos>=md->walkpath.path_len )
md->state.skillstate=MSS_IDLE;
return 0;
}
/*==========================================
* PC帇奅撪偺mob梡傑偠傔張棟(foreachclient)
*------------------------------------------
*/
static int mob_ai_sub_foreachclient(struct map_session_data *sd,va_list ap)
{
unsigned int tick;
tick=va_arg(ap,unsigned int);
map_foreachinarea(mob_ai_sub_hard,sd->bl.m,
sd->bl.x-AREA_SIZE*2,sd->bl.y-AREA_SIZE*2,
sd->bl.x+AREA_SIZE*2,sd->bl.y+AREA_SIZE*2,
BL_MOB,tick);
return 0;
}
/*==========================================
* PC帇奅撪偺mob梡傑偠傔張棟 (interval timer娭悢)
*------------------------------------------
*/
static int mob_ai_hard(int tid,unsigned int tick,int id,int data)
{
clif_foreachclient(mob_ai_sub_foreachclient,tick);
return 0;
}
/*==========================================
* 庤敳偒儌乕僪MOB AI乮嬤偔偵PC偑偄側偄乯
*------------------------------------------
*/
static int mob_ai_sub_lazy(void * key,void * data,va_list app)
{
struct mob_data *md=data;
unsigned int tick;
va_list ap;
if(md==NULL || md->bl.type!=BL_MOB)
return 0;
ap=va_arg(app,va_list);
tick=va_arg(ap,unsigned int);
if(DIFF_TICK(tick,md->last_thinktime)<MIN_MOBTHINKTIME*10)
return 0;
md->last_thinktime=tick;
if(md->bl.prev==NULL || md->skilltimer!=-1){
if(DIFF_TICK(tick,md->next_walktime)>MIN_MOBTHINKTIME*10)
md->next_walktime=tick;
return 0;
}
if(DIFF_TICK(md->next_walktime,tick)<0 &&
(mob_db[md->class].mode&1) && mob_can_move(md) ){
if( map[md->bl.m].users>0 ){
// 摨偠儅僢僾偵PC偑偄傞偺偱丄彮偟傑偟側庤敳偒張棟傪偡傞
// 帪乆堏摦偡傞
if(rand()%1000<MOB_LAZYMOVEPERC)
mob_randomwalk(md,tick);
// 彚姭MOB偱側偔丄BOSS偱傕側偄MOB偼帪乆丄暒偒側偍偡
else if( rand()%1000<MOB_LAZYWARPPERC && md->x0<=0 &&
mob_db[md->class].mexp <= 0 && !(mob_db[md->class].mode & 0x20))
mob_spawn(md->bl.id);
}else{
// 摨偠儅僢僾偵偡傜PC偑偄側偄偺偱丄偲偭偰傕揔摉側張棟傪偡傞
// 彚姭MOB偱側偄応崌丄帪乆堏摦偡傞乮曕峴偱偼側偔儚乕僾偱張棟寉尭乯
if( md->x0<=0 && rand()%1000<MOB_LAZYWARPPERC )
mob_warp(md,-1,-1,-1,-1);
}
md->next_walktime = tick+rand()%10000+5000;
}
return 0;
}
/*==========================================
* PC帇奅奜偺mob梡庤敳偒張棟 (interval timer娭悢)
*------------------------------------------
*/
static int mob_ai_lazy(int tid,unsigned int tick,int id,int data)
{
map_foreachiddb(mob_ai_sub_lazy,tick);
return 0;
}
/*==========================================
* delay晅偒item drop梡峔憿懱
* timer娭悢偵搉偣傞偺int 2偮偩偗側偺偱
* 偙偺峔憿懱偵僨乕僞傪擖傟偰搉偡
*------------------------------------------
*/
struct delay_item_drop {
int m,x,y;
int nameid,amount;
struct map_session_data *first_sd,*second_sd,*third_sd;
};
struct delay_item_drop2 {
int m,x,y;
struct item item_data;
struct map_session_data *first_sd,*second_sd,*third_sd;
};
/*==========================================
* delay晅偒item drop (timer娭悢)
*------------------------------------------
*/
static int mob_delay_item_drop(int tid,unsigned int tick,int id,int data)
{
struct delay_item_drop *ditem;
struct item temp_item;
int flag;
ditem=(struct delay_item_drop *)id;
memset(&temp_item,0,sizeof(temp_item));
temp_item.nameid = ditem->nameid;
temp_item.amount = ditem->amount;
temp_item.identify = !itemdb_isequip3(temp_item.nameid);
if(battle_config.item_auto_get){
if(ditem->first_sd && (flag = pc_additem(ditem->first_sd,&temp_item,ditem->amount))){
clif_additem(ditem->first_sd,0,0,flag);
map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
}
free(ditem);
return 0;
}
map_addflooritem(&temp_item,1,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
free(ditem);
return 0;
}
/*==========================================
* delay晅偒item drop (timer娭悢) - lootitem
*------------------------------------------
*/
static int mob_delay_item_drop2(int tid,unsigned int tick,int id,int data)
{
struct delay_item_drop2 *ditem;
int flag;
ditem=(struct delay_item_drop2 *)id;
if(battle_config.item_auto_get){
if(ditem->first_sd && (flag = pc_additem(ditem->first_sd,&ditem->item_data,ditem->item_data.amount))){
clif_additem(ditem->first_sd,0,0,flag);
map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
}
free(ditem);
return 0;
}
map_addflooritem(&ditem->item_data,ditem->item_data.amount,ditem->m,ditem->x,ditem->y,ditem->first_sd,ditem->second_sd,ditem->third_sd,0);
free(ditem);
return 0;
}
/*==========================================
* md傪徚偡
*------------------------------------------
*/
int mob_delete(struct mob_data *md)
{
if(md->bl.prev == NULL)
return 1;
mob_changestate(md,MS_DEAD,0);
clif_clearchar_area(&md->bl,1);
map_delblock(&md->bl);
if(mob_get_viewclass(md->class) <= 1000)
clif_clearchar_delay(gettick()+3000,&md->bl,0);
mob_deleteslave(md);
mob_setdelayspawn(md->bl.id);
return 0;
}
int mob_catch_delete(struct mob_data *md)
{
if(md->bl.prev == NULL)
return 1;
mob_changestate(md,MS_DEAD,0);
clif_clearchar_area(&md->bl,0);
map_delblock(&md->bl);
mob_setdelayspawn(md->bl.id);
return 0;
}
int mob_timer_delete(int tid, unsigned int tick, int id, int data)
{
struct block_list *bl=map_id2bl(id);
struct mob_data *md = (struct mob_data *)bl;
if(md) mob_catch_delete(md);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int mob_deleteslave_sub(struct block_list *bl,va_list ap)
{
struct mob_data *md = (struct mob_data *)bl;
int id;
id=va_arg(ap,int);
if(md->master_id > 0 && md->master_id == id )
mob_damage(NULL,md,md->hp,1);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int mob_deleteslave(struct mob_data *md)
{
map_foreachinarea(mob_deleteslave_sub, md->bl.m,
0,0,map[md->bl.m].xs,map[md->bl.m].ys,
BL_MOB,md->bl.id);
return 0;
}
/*==========================================
* md偵sd偐傜damage偺僟儊乕僕
*------------------------------------------
*/
int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
{
int i,count,minpos,mindmg;
struct map_session_data *sd = NULL,*tmpsd[DAMAGELOG_SIZE];
struct {
struct party *p;
int id,base_exp,job_exp;
} pt[DAMAGELOG_SIZE];
int pnum=0;
int mvp_damage,max_hp = battle_get_max_hp(&md->bl);
unsigned int tick = gettick();
struct map_session_data *mvp_sd=sd ,*second_sd = NULL,*third_sd = NULL;
double dmg_rate,tdmg,temp;
if(src && src->type == BL_PC) {
sd = (struct map_session_data *)src;
mvp_sd = sd;
}
// if(battle_config.battle_log)
// printf("mob_damage %d %d %d\n",md->hp,max_hp,damage);
if(md->bl.prev==NULL){
if(battle_config.error_log)
printf("mob_damage : BlockError!!\n");
return 0;
}
if(md->state.state==MS_DEAD || md->hp<=0) {
if(md->bl.prev != NULL) {
mob_changestate(md,MS_DEAD,0);
mobskill_use(md,tick,-1); // 巰朣帪僗僉儖
clif_clearchar_area(&md->bl,1);
map_delblock(&md->bl);
mob_setdelayspawn(md->bl.id);
}
return 0;
}
if(md->sc_data[SC_ENDURE].timer == -1)
mob_stop_walking(md,3);
if(damage > max_hp>>2)
skill_stop_dancing(&md->bl);
if(md->hp > max_hp)
md->hp = max_hp;
// over kill暘偼娵傔傞
if(damage>md->hp)
damage=md->hp;
if(!(type&2)) {
if(sd!=NULL){
for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
if(md->dmglog[i].id==sd->bl.id)
break;
if(md->dmglog[i].id==0){
minpos=i;
mindmg=0;
}
else if(md->dmglog[i].dmg<mindmg){
minpos=i;
mindmg=md->dmglog[i].dmg;
}
}
if(i<DAMAGELOG_SIZE)
md->dmglog[i].dmg+=damage;
else {
md->dmglog[minpos].id=sd->bl.id;
md->dmglog[minpos].dmg=damage;
}
if(md->attacked_id <= 0)
md->attacked_id = sd->bl.id;
}
if(src && src->type == BL_PET && battle_config.pet_attack_exp_to_master) {
struct pet_data *pd = (struct pet_data *)src;
for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
if(md->dmglog[i].id==pd->msd->bl.id)
break;
if(md->dmglog[i].id==0){
minpos=i;
mindmg=0;
}
else if(md->dmglog[i].dmg<mindmg){
minpos=i;
mindmg=md->dmglog[i].dmg;
}
}
if(i<DAMAGELOG_SIZE)
md->dmglog[i].dmg+=(damage*battle_config.pet_attack_exp_rate)/100;
else {
md->dmglog[minpos].id=pd->msd->bl.id;
md->dmglog[minpos].dmg=(damage*battle_config.pet_attack_exp_rate)/100;
}
}
if(src && src->type == BL_MOB && ((struct mob_data*)src)->state.special_mob_ai){
struct mob_data *md2 = (struct mob_data *)src;
for(i=0,minpos=0,mindmg=0x7fffffff;i<DAMAGELOG_SIZE;i++){
if(md->dmglog[i].id==md2->master_id)
break;
if(md->dmglog[i].id==0){
minpos=i;
mindmg=0;
}
else if(md->dmglog[i].dmg<mindmg){
minpos=i;
mindmg=md->dmglog[i].dmg;
}
}
if(i<DAMAGELOG_SIZE)
md->dmglog[i].dmg+=damage;
else {
md->dmglog[minpos].id=md2->master_id;
md->dmglog[minpos].dmg=damage;
}
}
}
md->hp-=damage;
if(md->option&2 )
skill_status_change_end(&md->bl, SC_HIDING, -1);
if(md->option&4 )
skill_status_change_end(&md->bl, SC_CLOAKING, -1);
if(md->state.special_mob_ai == 2){//僗僼傿傾乕儅僀儞
md->state.special_mob_ai++;
if(mob_skillid2skillidx(md->class,NPC_SELFDESTRUCTION))
mobskill_use_id(md,&md->bl,mob_skillid2skillidx(md->class,NPC_SELFDESTRUCTION));//帺敋塺彞奐巒
}
if(md->hp>0){
return 0;
}
// ----- 偙偙偐傜巰朣張棟 -----
// if(md->class == 1288 && map[md->bl.m].flag.gvg)
// guild_gvg_break_empelium(md);
map_freeblock_lock();
mob_changestate(md,MS_DEAD,0);
mobskill_use(md,tick,-1); // 巰朣帪僗僉儖
memset(tmpsd,0,sizeof(tmpsd));
memset(pt,0,sizeof(pt));
max_hp = battle_get_max_hp(&md->bl);
// map奜偵徚偊偨恖偼寁嶼偐傜彍偔偺偱
// overkill暘偼柍偄偗偳sum偼max_hp偲偼堘偆
tdmg = 0;
for(i=0,count=0,mvp_damage=0;i<DAMAGELOG_SIZE;i++){
if(md->dmglog[i].id==0)
continue;
tmpsd[i] = map_id2sd(md->dmglog[i].id);
if(tmpsd[i] == NULL)
continue;
count++;
if(tmpsd[i]->bl.m != md->bl.m || pc_isdead(tmpsd[i]))
continue;
tdmg += (double)md->dmglog[i].dmg;
if(mvp_damage<md->dmglog[i].dmg){
third_sd = second_sd;
second_sd = mvp_sd;
mvp_sd=tmpsd[i];
mvp_damage=md->dmglog[i].dmg;
}
}
if((double)max_hp < tdmg)
dmg_rate = ((double)max_hp) / tdmg;
else dmg_rate = 1;
// 宱尡抣偺暘攝
for(i=0;i<DAMAGELOG_SIZE;i++){
int pid,base_exp,job_exp,flag=1;
double per;
struct party *p;
if(tmpsd[i]==NULL || tmpsd[i]->bl.m != md->bl.m)
continue;
per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate;
temp = ((double)mob_db[md->class].base_exp * (double)battle_config.base_exp_rate / 100. * per);
base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
if(mob_db[md->class].base_exp > 0 && base_exp < 1) base_exp = 1;
if(base_exp < 0) base_exp = 0;
temp = ((double)mob_db[md->class].job_exp * (double)battle_config.job_exp_rate / 100. * per);
job_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
if(mob_db[md->class].job_exp > 0 && job_exp < 1) job_exp = 1;
if(job_exp < 0) job_exp = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -