📄 gameautofight.cpp
字号:
/*
* 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 + -