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

📄 gameautofight.cpp

📁 是一个基于热血战国协议的网络游戏。现在脱机客户端先放出来给大家研究
💻 CPP
📖 第 1 页 / 共 2 页
字号:

/*
 * name: GameAutoFight.cpp
 *
* desc: 自动战斗,自动打怪的控制,目前只做了战士的自动战斗
 *
*/

#include "stdafx.h"
#include "..\TurboMir.h"
#include "gamemir.h"
#include "..\MainFrm.h"
#include ".\gamemir.h"


/*
=======================================================================
函数名       : CGameAutoFight
功能描述     : 标准构造函数
参数         : void
返回值       : NULL
=======================================================================
*/
CGameAutoFight::CGameAutoFight(CGameMir &game)
: m_Game(game)
//, m_TargetId(0)
, m_HasNewActor(false)
, m_EnableAutoFight(false)
//, m_LastFierHitTick(0)
{
	InitializeCriticalSection(&m_RunSC);
	this->pThread_ = NULL;
}

/*
=======================================================================
函数名       : ~CGameAutoFight
功能描述     : 标准拆函数
参数         : void
返回值       : NULL
=======================================================================
*/
CGameAutoFight::~CGameAutoFight()
{
	DeleteCriticalSection(&m_RunSC);
}

/*
=======================================================================
函数名       : Fight
功能描述     : 战斗
参数         : void
返回值       : BOOL
=======================================================================
*/
//BOOL CGameMir::CAutoFight::Fight()
//{
//	//m_Game.m_FrameWnd.AddLog(crMessage,"Fight "__FILE__"\n");
//	if ( m_TargetId==0 )
//	{
//		//m_Game.m_FrameWnd.AddLog(crRed,"没有目标\n");
//		return FALSE;
//	}
//	std::vector<POINT> Path;
//	POINT pntLastPos;
//	while ( m_EnableAutoFight )
//	{
//		if ( m_Game.m_Self.Ability.Mp>10 && m_Game.m_Sets.AutoFireHit && (GetTickCount()-m_LastFierHitTick)>m_Game.m_Sets.FireHitDelay )
//		{
//			itClientMagic magic=m_Game.FindMagic("烈火剑法");
//			if ( magic!=m_Game.m_Magics.end() )
//			{
//				m_Game.m_Action.SendSpell(CM_SPELL,0,0,magic->Def.MagicId,0);
//				while ( !m_Game.m_Action.CanAction() )
//				{
//					Sleep(10);
//				}
//			}
//			m_LastFierHitTick=GetTickCount();
//		}
//
//		itActor actor=m_Game.FindActor(m_TargetId);
//		if ( m_Game.isOverEnd(actor) )
//		{
//			return FALSE;
//		}
//
//		//if ( actor->Death )
//		//{
//		//	return FALSE;
//		//}
//
//		//m_Game.m_FrameWnd.m_wndLeftView.SetTarget(actor);
//
//		POINT pntSelf,pntMonst;
//		pntSelf.x=m_Game.m_Self.xx;
//		pntSelf.y=m_Game.m_Self.yy;
//		pntMonst.x=actor->xx;
//		pntMonst.y=actor->yy;
//		//m_Game.m_FrameWnd.AddLog(crRed,"(%d,%d)->(%d,%d)\n",pntSelf.x,pntSelf.y,pntMonst.x,pntMonst.y);
//		BYTE dir,run;
//		bool action=false;
//		itActor HasMonster[0x10];
//		for ( int i=0; i<0x10; i++ ) HasMonster[i]=m_Game.m_ActorList.end();
//		for ( itActor pos=m_Game.m_ActorList.begin(); pos!=m_Game.m_ActorList.end(); pos++ )
//		{
//			if ( pos->Type!=AT_Monst ) continue;
//			//if ( pos->Death ) continue;
//			POINT tp;
//			tp.x=pos->xx;
//			tp.y=pos->yy;
//			dir=GetDirect(pntSelf,tp);
//			if( (dir>>4)==0 )
//			{
//				dir&=0xf;
//				HasMonster[dir]=pos;
//			}
//		}
//		dir=GetDirect(pntSelf,pntMonst);
//		if( (dir>>4)!=0 ) // 如果目标不在攻击范围 算上刺杀位
//		{
//			for ( int i=0; i<0x10; i++ )
//			{
//				if ( !m_Game.isOverEnd(HasMonster[i]) )
//				{
//					m_TargetId=HasMonster[i]->ServerId;
//					actor=HasMonster[i];
//					m_Game.m_FrameWnd.m_wndLeftView.SetTarget(actor);
//					pntMonst.x=actor->xx;
//					pntMonst.y=actor->yy;
//					dir=i;
//					break;
//				}
//			}
//		}
//		if( (dir>>4)==0 ) // 如果目标在攻击范围 算上刺杀位
//		{
//			CActionManager&ActionMgr=m_Game.m_Action;
//			run=(dir>>3)&1;
//			dir&=7;
//			if(run!=0) // 在刺杀位
//			{
//				if ( ActionMgr.CanLongHit() ) // 刺杀打开了吗?
//				{
//					action=true;
//					ActionMgr.SendHit(dir,CM_LONGHIT);
//				}
//			}
//			else
//			{
//				if ( ActionMgr.CanFireHit() )
//				{
//					action=true;
//					ActionMgr.SendHit(dir,CM_FIREHIT);
//					m_Game.m_FrameWnd.AddLog(crGreen,"烈火\n");
//				}
//				else if ( ActionMgr.CanPowerHit() ) // 可以攻杀
//				{
//					action=true;
//					ActionMgr.SendHit(dir,CM_POWERHIT);
//				}
//				else
//				{
//					int mcnt=1;
//					if (!m_Game.isOverEnd(HasMonster[(dir-1)&7]))
//						mcnt++;
//					if (!m_Game.isOverEnd(HasMonster[(dir+1)&7]))
//						mcnt++;
//					if (!m_Game.isOverEnd(HasMonster[(dir+2)&7]))
//						mcnt++;
//					if ( m_Game.m_Self.Ability.Mp>10
//						&& ActionMgr.CanWideHit()
//						&& m_Game.m_Sets.AutoWideHit
//						&& mcnt>=m_Game.m_Sets.WideHitLevel  ) // 半月攻击位上有至少2个怪物
//					{
//						action=true;
//						//m_Game.m_FrameWnd.AddLog(crSkyBlue,"半月%d\n",mcnt);
//						ActionMgr.SendHit(dir,CM_WIDEHIT); // 半月
//					}
//					else if ( m_Game.m_Sets.AlwaysLongHit && ActionMgr.CanLongHit() ) // 刀刀刺杀打开
//					{
//						action=true;
//						ActionMgr.SendHit(dir,CM_LONGHIT); // 刺杀
//					}
//					else
//					{
//						action=true;
//						ActionMgr.SendHit(dir,CM_HEAVYHIT); // 平砍
//					}
//				}
//			}
//		}
//		if(!action)
//		{
//			if ( Path.empty() || !(pntLastPos==pntMonst))
//			{
//				pntLastPos=pntMonst;
//				if(!FindPathAStar(m_Game,pntSelf,pntMonst,Path))
//				{
//					m_Game.m_FrameWnd.AddLog(crRed,"寻路失败\n");
//					return FALSE;
//				}
//				m_Game.m_FrameWnd.m_wndMap.SetPath(Path);
//			}
//			//在路径中查找英雄当前所在点
//			POINT pntNext;
//			std::vector<POINT>::iterator pos=std::find(Path.begin(),Path.end(),pntSelf);
//			if(pos!=Path.end()) // 是否找到
//			{
//				pos++;
//				if(pos!=Path.end()) // 是否最后一个节点
//				{
//					pntNext=*pos;
//					dir=GetDirect(pntSelf,pntNext);
//					if( (dir&0xf0)==0 )
//					{
//						run=dir>>3;
//						dir&=7;
//						if(run!=0)
//						{
//							if( m_Game.CanRun(pntSelf,dir) )
//							{
//								action=true;
//								m_Game.m_Action.SendRun(dir);
//							}
//							else
//							{
//								// 在这个函数中 A*的终点就是目标怪物的坐标
//								// 所以当终点不可及时 一般认为目标怪物就在那
//								// 所以 走过去
//								pos++;
//								if(pos!=Path.end())
//								{
//									action=true;
//									m_Game.m_Action.SendWalk(dir);
//								}
//							}
//						}
//						else
//						{
//							if( m_Game.CanWalk(pntSelf,dir) )
//							{
//								action=true;
//								m_Game.m_Action.SendWalk(dir);
//							}
//						}
//					}
//				}
//			}
//		}
//		if(action)
//		{
//			while(!m_Game.m_Action.CanAction())
//				Sleep(50);
//		}
//		else
//		{
//			Sleep(100);
//			//说明我们的英雄已经偏离了路线 或者路原来的路径上被人站了 重新查找路径
//			Path.clear();
//		}
//	}
//	//m_Game.m_FrameWnd.AddLog(crRed,"攻击结束\n");
//	return TRUE;
//}
//

/*
=======================================================================
函数名       : Go
功能描述     : 开始
参数         : void
返回值       : void
=======================================================================
*/
void CGameAutoFight::Go( void )
{
	this->pThread_ = AfxBeginThread(AutoFightThread,(LPVOID)this,0,0,0,0);
}	


void CGameAutoFight::Stop( )
{
	if (NULL != this->pThread_)
	{
		// !!! notify thread to die !!! 
		m_EnableAutoFight = false;

		DWORD dwRet = ::WaitForSingleObject(this->pThread_->m_hThread, INFINITE);
		if ( WAIT_TIMEOUT == dwRet )
		{
			::TerminateThread(this->pThread_->m_hThread, 0);
			delete this->pThread_;
		}

		// pThread_ is auto deleteed ...
	
		this->pThread_ = NULL;
	}

}


//struct sAStarNode
typedef struct tag_TASTARNODE
{
	POINT p;
	long G,H,F;
	//F = G + H
	//这里:
	//	* G = 从起点A,沿着产生的路径,移动到网格上指定方格的移动耗费。
	//	* H = 从网格上那个方格移动到终点B的预估移动耗费。
	//unsigned char dir,run;
	bool operator<( const tag_TASTARNODE &elem ) const
	{
		return this->F < elem.F;
	}
}_TASTARNODE,*_LPTASTARNODE;

typedef std::multiset<_TASTARNODE> OPEN_LIST;

class find_equal
{
private:
	POINT m_pnt;

public:
	find_equal(const POINT& pnt):m_pnt(pnt){}
	bool operator()(const _TASTARNODE &node)const{ return (node.p==m_pnt); }
};

/*
=======================================================================
函数名       : FindPathAStar
功能描述     : A*寻路
参数         : CGameMir& game
参数         : const POINT& from
参数         : const POINT& to
参数         : std::vector<POINT>& path 
返回值       : BOOL
=======================================================================
*/
BOOL CGameAutoFight::FindPathAStar(CGameMir& game, const POINT& from, const POINT& to, std::vector<POINT>& path )
{
	//测试地图
	if ( !game.m_Map.TestMap(from.x,from.y) )
	{
		game.m_FrameWnd.AddLog(crMessage,"%d\n",__LINE__);
		return FALSE;
	}
	if ( !game.m_Map.TestMap(to.x,to.y) )
	{
		game.m_FrameWnd.AddLog(crMessage,"%d\n",__LINE__);
		return FALSE;
	}
	DWORD w,h;
	game.m_Map.GetSize(w,h);
	std::auto_ptr<BYTE>OpenClose_auto(new BYTE[w*h]);
	BYTE *OpenClose=OpenClose_auto.get();
	ZeroMemory(OpenClose,w*h);

	OPEN_LIST OpenList;


	_TASTARNODE node;
	node.p=from;
	node.G=0;
	node.H=(max(abs(from.x-to.x),abs(from.y-to.y))+1)<<1;
	node.F=node.G+node.H;
	OpenList.insert(node);
	OpenClose[node.p.x+node.p.y*w]=0x10;
	bool found=false;
	int i,j;
	POINT search;
	_TASTARNODE temp;
	OPEN_LIST::iterator itorNode;
	BYTE bOpenClose;
	while ( !OpenList.empty() )
	{
		itorNode=OpenList.begin();
		node=*itorNode;
		OpenList.erase(itorNode);
		//把它放入封闭列表。
		OpenClose[node.p.x+node.p.y*w]=(OpenClose[node.p.x+node.p.y*w]&0x0f)|0x20;

		for ( i=0; i<8; i++ )
		{
			search=node.p;
			for( j=0; j<2; j++ )
			{
				search.x+=xofs_walk[i];
				search.y+=yofs_walk[i];
				if ( search == to )
				{
					found=true;
					OpenClose[search.x+search.y*w]=(((i&7)^4)+(j<<3))|0x10;
					goto break_while;
				}
				if(game.CanMove(search.x,search.y))
				{
					// * 如果它不可通过或者已经在关闭列表中,略过它。
					bOpenClose=OpenClose[search.x+search.y*w];
					switch (bOpenClose&0xf0)
					{
					case 0x00: // 如果它不在开启列表中,把它添加进去。
						temp.p=search;
						temp.G=node.G+1;
						temp.H=(max(abs(search.x-to.x),abs(search.y-to.y))+1)<<1;
						temp.F=temp.G+temp.H;
						OpenClose[search.x+search.y*w]=(((i&7)^4)+(j<<3))|0x10;
						OpenList.insert(temp);
						break;
					case 0x10:
						itorNode=std::find_if(OpenList.begin(),OpenList.end(),find_equal(search));
						if(itorNode!=OpenList.end())
						{
							if ( itorNode->G > node.G+1 )
							{
								// 如果它已经在开启列表中,用G值为参考检查新的路径是否更好。
								// 更低的G值意味着更好的路径。
								temp=*itorNode;
								OpenList.erase(itorNode);
								temp.G=node.G+1;
								temp.F=temp.G+temp.H;
								OpenClose[search.x+search.y*w]=(((i&7)^4)+(j<<3))|0x10;
								OpenList.insert(temp);
							}
						}
						break;
					}
				}
				else
				{ // 跑位不能到达
					break;
				}
			}
		}
	}
break_while:
	if(!found)
	{
		game.m_FrameWnd.AddLog(crMessage,"%d\n",__LINE__);
		return FALSE;
	}

	// 保存路径。
	std::vector<POINT> _path;
	_path.push_back(to);
	BYTE dir,run;
	bOpenClose=OpenClose[to.x+to.y*w];
	if ((bOpenClose&0xf0)==0)
	{
		game.m_FrameWnd.AddLog(crMessage,"%d\n",__LINE__);
		return FALSE;
	}
	dir=bOpenClose&0x7;
	run=(bOpenClose&0x8)>>3;
	search.x=to.x+(xofs_walk[dir]<<run);
	search.y=to.y+(yofs_walk[dir]<<run);
	while ( !(search==from) )
	{ // 查找父节点
		if(!game.CanMove(search.x,search.y))
		{
			game.m_FrameWnd.AddLog(crMessage,"%d\n",__LINE__);
			return FALSE;
		}
		_path.push_back(search);
		//dc.LineTo(search);
		bOpenClose=OpenClose[search.x+search.y*w];
		if ((bOpenClose&0xf0)==0)
		{
			game.m_FrameWnd.AddLog(crMessage,"%d\n",__LINE__);
			return FALSE;
		}
		dir=bOpenClose&0x7;
		run=(bOpenClose&0x8)>>3;

		search.x+=(xofs_walk[dir]<<run);
		search.y+=(yofs_walk[dir]<<run);
	}
	_path.push_back(from);
	path.clear();
	{
		std::vector<POINT>::iterator itor=_path.end();
		do 
		{
			--itor;
			path.push_back(*itor);
		} while (itor!=_path.begin());
	}
	return TRUE;
}

/*
=======================================================================
函数名       : AutoFightThread
功能描述     : 自动战斗线程
参数         : LPVOID pParam 
返回值       : UINT
=======================================================================
*/
UINT CGameAutoFight::AutoFightThread( LPVOID pParam )
{
	CGameAutoFight& af=*static_cast<CGameAutoFight*>(pParam);
	if(TryEnterCriticalSection(&af.m_RunSC))
	{
		af.m_EnableAutoFight=true;
		af._AutoFightThread();
		LeaveCriticalSection(&af.m_RunSC);
	}
	return 0;
}

/*
=======================================================================
函数名       : _AutoFightThread
功能描述     : 自动战斗线程
参数         : void
返回值       : void
=======================================================================
*/
void CGameAutoFight::_AutoFightThread( void )
{
	srand( (unsigned)time( NULL ) );
	m_Target.type=0;
	
	POINT Cruise=GetCruisePoint();
	std::vector<POINT> Path;//路径
	CGameDStar DStar(m_Game.m_Map,m_Game);
	m_Game.m_FrameWnd.AddLog(crRed,"自动战斗开始\n");
	while ( m_EnableAutoFight )
	{
		POINT self;
		self.x = m_Game.m_Self.xx;
		self.y = m_Game.m_Self.yy;
		itActor actr;
		itDropedItem item;
		if ( m_Target.type==1 ) // 怪物
		{
			actr=m_Game.FindActor(m_Target.ServerId);
			if ( m_Game.isOverEnd(actr) ) // 目标怪物不存在了
			{
				//m_Game.m_FrameWnd.AddLog(crRed,"目标怪物不存在了\n"); 梁健雄 2007-08-19
				m_Target.type=0; // 取消目标
			}
		}
		if ( m_Target.type==2 ) // 地面物品
		{

⌨️ 快捷键说明

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