⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mob.c

📁 最新的仙镜传说服务器C语言源码
💻 C
📖 第 1 页 / 共 5 页
字号:
// $Id: mob.c,v 1.14 2003/06/30 14:45:10 lemit Exp $
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>

#include "timer.h"
#include "socket.h"
#include "db.h"
#include "map.h"
#include "clif.h"
#include "intif.h"
#include "pc.h"
#include "mob.h"
#include "guild.h"
#include "itemdb.h"
#include "skill.h"
#include "battle.h"
#include "party.h"
#include "npc.h"

#ifdef MEMWATCH
#include "memwatch.h"
#endif

#define MIN_MOBTHINKTIME 100

#define MOB_LAZYMOVEPERC 50		// 庤敳偒儌乕僪MOB偺堏摦妋棪乮愮暘棪乯
#define MOB_LAZYWARPPERC 20		// 庤敳偒儌乕僪MOB偺儚乕僾妋棪乮愮暘棪乯

struct mob_db mob_db[2001];

/*==========================================
 * 儘乕僇儖僾儘僩僞僀僾愰尵 (昁梫側暔偺傒)
 *------------------------------------------
 */
static int distance(int,int,int,int);
static int mob_makedummymobdb(int);
static int mob_timer(int,unsigned int,int,int);
int mobskill_use(struct mob_data *md,unsigned int tick,int event);
int mobskill_deltimer(struct mob_data *md );
int mob_skillid2skillidx(int class,int skillid);
int mobskill_use_id(struct mob_data *md,struct block_list *target,int skill_idx);

/*==========================================
 * mob傪柤慜偱専嶕
 *------------------------------------------
 */
int mobdb_searchname(const char *str)
{
	int i;
	for(i=0;i<sizeof(mob_db)/sizeof(mob_db[0]);i++){
		if( strcmpi(mob_db[i].name,str)==0 || strcmp(mob_db[i].jname,str)==0 ||
			memcmp(mob_db[i].name,str,24)==0 || memcmp(mob_db[i].jname,str,24)==0)
			return i;
	}
	return 0;
}
/*==========================================
 * MOB弌尰梡偺嵟掅尷偺僨乕僞僙僢僩
 *------------------------------------------
 */
int mob_spawn_dataset(struct mob_data *md,const char *mobname,int class)
{
	md->bl.prev=NULL;
	md->bl.next=NULL;
	if(strcmp(mobname,"--en--")==0)
		memcpy(md->name,mob_db[class].name,24);
	else if(strcmp(mobname,"--ja--")==0)
		memcpy(md->name,mob_db[class].jname,24);
	else
		memcpy(md->name,mobname,24);

	md->n = 0;
	md->base_class = md->class = class;
	md->bl.id= npc_get_new_npc_id();

	memset(&md->state,0,sizeof(md->state));
	md->timer = -1;
	md->target_id=0;
	md->attacked_id=0;
	md->speed=mob_db[class].speed;

	return 0;
}


/*==========================================
 * 堦敪MOB弌尰(僗僋儕僾僩梡)
 *------------------------------------------
 */
int mob_once_spawn(struct map_session_data *sd,char *mapname,
	int x,int y,const char *mobname,int class,int amount,const char *event)
{
	struct mob_data *md=NULL;
	int m,count,lv=255;
	
	if( sd )
		lv=sd->status.base_level;

	if(strcmp(mapname,"this")==0)
		m=sd->bl.m;
	else
		m=map_mapname2mapid(mapname);

	if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>2000)	// 抣偑堎忢側傜彚姭傪巭傔傞
		return 0;

	if(class<0){	// 儔儞僟儉偵彚姭
		int i=0;
		int j=-class-1;
		int k;
		if(j>=0 && j<MAX_RANDOMMONSTER){
			do{
				class=rand()%1000+1001;
				k=rand()%1000000;
			}while((mob_db[class].max_hp <= 0 || mob_db[class].summonper[j] <= k ||
				 (lv<mob_db[class].lv && battle_config.random_monster_checklv)) && (i++) < 2000);
			if(i>=2000){
				class=mob_db[0].summonper[j];
			}
		}else{
			return 0;
		}
//		if(battle_config.etc_log)
//			printf("mobclass=%d try=%d\n",class,i);
	}
	if(sd){
		if(x<=0) x=sd->bl.x;
		if(y<=0) y=sd->bl.y;
	}else if(x<=0 || y<=0){
		printf("mob_once_spawn: ??\n");
	}

	for(count=0;count<amount;count++){
		md=calloc(sizeof(struct mob_data), 1);
		if(md==NULL){
			printf("mob_once_spawn: out of memory !\n");
			exit(1);
		}
		memset(md, '\0', sizeof *md);
		if(mob_db[class].mode&0x02) {
			md->lootitem=calloc(sizeof(struct item)*LOOTITEM_SIZE, 1);
			if(md->lootitem==NULL){
				printf("mob_once_spawn: out of memory !\n");
				exit(1);
			}
		}
		else
			md->lootitem=NULL;

		mob_spawn_dataset(md,mobname,class);
		md->bl.m=m;
		md->bl.x=x;
		md->bl.y=y;

		md->m =m;
		md->x0=x;
		md->y0=y;
		md->xs=0;
		md->ys=0;
		md->spawndelay1=-1;	// 堦搙偺傒僼儔僌
		md->spawndelay2=-1;	// 堦搙偺傒僼儔僌

		memcpy(md->npc_event,event,sizeof(md->npc_event));

		md->bl.type=BL_MOB;
		map_addiddb(&md->bl);
		mob_spawn(md->bl.id);

	}
	return (amount>0)?md->bl.id:0;
}
/*==========================================
 * 堦敪MOB弌尰(僗僋儕僾僩梡仌僄儕傾巜掕)
 *------------------------------------------
 */
int mob_once_spawn_area(struct map_session_data *sd,char *mapname,
	int x0,int y0,int x1,int y1,
	const char *mobname,int class,int amount,const char *event)
{
	int x,y,i,c,max,lx=-1,ly=-1,id=0;
	int m=map_mapname2mapid(mapname);

	max=(y1-y0+1)*(x1-x0+1)*3;
	if(max>1000)max=1000;

	if(m<0 || amount<=0 || (class>=0 && class<=1000) || class>2000)	// 抣偑堎忢側傜彚姭傪巭傔傞
		return 0;

	for(i=0;i<amount;i++){
		int j=0;
		do{
			x=rand()%(x1-x0+1)+x0;
			y=rand()%(y1-y0+1)+y0;
		}while( ( (c=map_getcell(m,x,y))==1 || c==5)&& (++j)<max );
		if(j>=max){
			if(lx>=0){	// 専嶕偵幐攕偟偨偺偱埲慜偵暒偄偨応強傪巊偆
				x=lx;
				y=ly;
			}else
				return 0;	// 嵟弶偵暒偔応強偺専嶕傪幐攕偟偨偺偱傗傔傞
		}
		id=mob_once_spawn(sd,mapname,x,y,mobname,class,1,event);
		lx=x;
		ly=y;
	}
	return id;
}
/*==========================================
 * mob偵僞僎柍帇ID傪晅壛
 *------------------------------------------
 */
int mob_exclusion_add(struct mob_data *md,int type,int id)
{
	if(md){
		if(type==1)
			md->exclusion_src=id;
		if(type==2)
			md->exclusion_party=id;
		if(type==3)
			md->exclusion_guild=id;
	}
	return 0;
}
/*==========================================
 * mob偺僞僎柍帇ID傪僠僃僢僋
 *------------------------------------------
 */
int mob_exclusion_check(struct mob_data *md,struct map_session_data *sd)
{
	if(md && sd && sd->bl.type==BL_PC){
		if(md->exclusion_src && md->exclusion_src==sd->bl.id)
			return 1;
		if(md->exclusion_party && md->exclusion_party==sd->status.party_id)
			return 2;
		if(md->exclusion_guild && md->exclusion_guild==sd->status.guild_id)
			return 3;
	}
	return 0;
}

/*==========================================
 * mob偺尒偐偗強摼
 *------------------------------------------
 */
int mob_get_viewclass(int class)
{
	return mob_db[class].view_class;
}
int mob_get_sex(int class)
{
	return mob_db[class].sex;
}
short mob_get_hair(int class)
{
	return mob_db[class].hair;
}
short mob_get_hair_color(int class)
{
	return mob_db[class].hair_color;
}
short mob_get_weapon(int class)
{
	return mob_db[class].weapon;
}
short mob_get_shield(int class)
{
	return mob_db[class].shield;
}
short mob_get_head_top(int class)
{
	return mob_db[class].head_top;
}
short mob_get_head_mid(int class)
{
	return mob_db[class].head_mid;
}
short mob_get_head_buttom(int class)
{
	return mob_db[class].head_buttom;
}

/*==========================================
 * MOB偑尰嵼堏摦壜擻側忬懺偵偁傞偐偳偆偐
 *------------------------------------------
 */
int mob_can_move(struct mob_data *md)
{
	if(md->canmove_tick > gettick() || (md->opt1 > 0 && md->opt1 != 6) || md->option&2)
		return 0;
	if( md->sc_data[SC_ANKLE].timer != -1 || md->sc_data[SC_AUTOCOUNTER].timer != -1 || md->sc_data[SC_BLADESTOP].timer != -1)	// 傾儞僋儖拞偱摦偗側偄
		return 0;

	return 1;
}

/*==========================================
 * mob偺師偺1曕偵偐偐傞帪娫寁嶼
 *------------------------------------------
 */
static int calc_next_walk_step(struct mob_data *md)
{
	if(md->walkpath.path_pos>=md->walkpath.path_len)
		return -1;
	if(md->walkpath.path[md->walkpath.path_pos]&1)
		return battle_get_speed(&md->bl)*14/10;
	return battle_get_speed(&md->bl);
}

static int mob_walktoxy_sub(struct mob_data *md);

/*==========================================
 * mob曕峴張棟
 *------------------------------------------
 */
static int mob_walk(struct mob_data *md,unsigned int tick,int data)
{
	int moveblock;
	int i,ctype;
	static int dirx[8]={0,-1,-1,-1,0,1,1,1};
	static int diry[8]={1,1,0,-1,-1,-1,0,1};
	int x,y,dx,dy;

	md->state.state=MS_IDLE;
	if(md->walkpath.path_pos>=md->walkpath.path_len || md->walkpath.path_pos!=data)
		return 0;

	md->walkpath.path_half ^= 1;
	if(md->walkpath.path_half==0){
		md->walkpath.path_pos++;
		if(md->state.change_walk_target){
			mob_walktoxy_sub(md);
			return 0;
		}
	}
	else {
		if(md->walkpath.path[md->walkpath.path_pos]>=8)
			return 1;

		x = md->bl.x;
		y = md->bl.y;
		ctype = map_getcell(md->bl.m,x,y);
		if(ctype == 1 || ctype == 5) {
			mob_stop_walking(md,1);
			return 0;
		}
		md->dir=md->walkpath.path[md->walkpath.path_pos];
		dx = dirx[md->dir];
		dy = diry[md->dir];

		ctype = map_getcell(md->bl.m,x+dx,y+dy);
		if(ctype == 1 || ctype == 5) {
			mob_walktoxy_sub(md);
			return 0;
		}

		moveblock = ( x/BLOCK_SIZE != (x+dx)/BLOCK_SIZE || y/BLOCK_SIZE != (y+dy)/BLOCK_SIZE);

		md->state.state=MS_WALK;
		map_foreachinmovearea(clif_moboutsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,dx,dy,BL_PC,md);

		x += dx;
		y += dy;
		if(md->min_chase>13)
			md->min_chase--;

		if(moveblock) map_delblock(&md->bl);
		md->bl.x = x;
		md->bl.y = y;
		if(moveblock) map_addblock(&md->bl);

		map_foreachinmovearea(clif_mobinsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,-dx,-dy,BL_PC,md);
		md->state.state=MS_IDLE;

		if(md->option&4)
			skill_check_cloaking(&md->bl);

		skill_unit_move(&md->bl,tick,1);	// 僗僉儖儐僯僢僩偺専嵏
	}
	if((i=calc_next_walk_step(md))>0){
		i = i>>1;
		if(i < 1 && md->walkpath.path_half == 0)
			i = 1;
		md->timer=add_timer(tick+i,mob_timer,md->bl.id,md->walkpath.path_pos);
		md->state.state=MS_WALK;

		if(md->walkpath.path_pos>=md->walkpath.path_len)
			clif_fixmobpos(md);	// 偲傑偭偨偲偒偵埵抲偺嵞憲怣
	}
	return 0;
}

/*==========================================
 * mob偺峌寕張棟
 *------------------------------------------
 */
static int mob_attack(struct mob_data *md,unsigned int tick,int data)
{
	struct map_session_data *sd;
	int mode,race,range;

	md->min_chase=13;
	md->state.state=MS_IDLE;
	md->state.skillstate=MSS_IDLE;

	if( md->skilltimer!=-1 )	// 僗僉儖巊梡拞
		return 0;

	if(md->opt1>0 || md->option&2)
		return 0;

	if(md->sc_data[SC_AUTOCOUNTER].timer != -1)
		return 0;

	if(md->sc_data[SC_BLADESTOP].timer != -1)
		return 0;

	sd=map_id2sd(md->target_id);
	if(sd==NULL || pc_isdead(sd) || md->bl.m != sd->bl.m || sd->bl.prev == NULL || sd->invincible_timer != -1 ||
		distance(md->bl.x,md->bl.y,sd->bl.x,sd->bl.y)>=13 || pc_isinvisible(sd) || mob_exclusion_check(md,sd)){
		md->target_id=0;
		md->state.targettype = NONE_ATTACKABLE;
		return 0;
	}

	mode=mob_db[md->class].mode;
	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=0;
		md->state.targettype = NONE_ATTACKABLE;
		return 0;
	}

	range = mob_db[md->class].range;
	if(mode&1)
		range++;
	if(distance(md->bl.x,md->bl.y,sd->bl.x,sd->bl.y) > range)
		return 0;
	if(battle_config.monster_attack_direction_change)
		md->dir=map_calc_dir(&md->bl, sd->bl.x,sd->bl.y );	// 岦偒愝掕

	clif_fixmobpos(md);

	md->state.skillstate=MSS_ATTACK;
	if( mobskill_use(md,tick,-2) )	// 僗僉儖巊梡
		return 0;

	battle_weapon_attack(&md->bl,&sd->bl,tick,0);
	if(!(battle_config.monster_cloak_check_type&2) && md->sc_data[SC_CLOAKING].timer != -1)
		skill_status_change_end(&md->bl,SC_CLOAKING,-1);

	md->attackabletime = tick + battle_get_adelay(&md->bl);

	md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0);
	md->state.state=MS_ATTACK;

	return 0;
}


/*==========================================
 * id傪峌寕偟偰偄傞PC偺峌寕傪掆巭
 * clif_foreachclient偺callback娭悢
 *------------------------------------------
 */
int mob_stopattacked(struct map_session_data *sd,va_list ap)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -