khanat-opennel-code/code/ryzom/server/src/ai_service/ai_generic_fight.h

378 lines
10 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef RYAI_GENERIC_FIGHT_H
#define RYAI_GENERIC_FIGHT_H
#include "profile.h"
#include "sheets.h"
#include "path_behaviors.h"
// Forward declarations
class CAIEntityPhysical;
class CModEntityPhysical;
class CBotPlayer;
// a big bad global var !
extern CAIEntityPhysical *TempSpeaker;
extern CBotPlayer *TempPlayer;
extern float getDistBetWeen(CAIEntityPhysical& creat1, CAIEntityPhysical& creat2);
template <class TVectorSrc, class TVectorDst>
float buildDecalage(TVectorSrc const& src, TVectorDst const& dst, CAIVector* decalage)
{
if (decalage!=NULL)
{
CAIVector& vect = *decalage;
vect = dst;
vect -= src;
float normXY = (float)vect.norm();
float normZ = (dst.h()-src.h())/1000.f;
// :KLUDGE: This is a dirty dirty hack
// As z precision is 2m, entities can be near contact but considered 2m away if they are on differents PACS planes.
// So we bring back all z dists 2m closer to 0.
if (normZ > 2.f) normZ -= 2.f;
else if (normZ < -2.f) normZ += 2.f;
else normZ = 0.f;
// End of hack
float normXYZ = (float)sqrt(normXY*normXY + normZ*normZ);
return normXYZ;
}
else
{
CAIVector vect;
return buildDecalage(src, dst, &vect);
}
}
//////////////////////////////////////////////////////////////////////////////
// CBotProfileFightHeal //
//////////////////////////////////////////////////////////////////////////////
class CBotProfileFightHeal
: public CAIBaseProfile
{
public:
CBotProfileFightHeal() : CAIBaseProfile() { }
virtual void eventTargetKilled() = 0;
virtual void noMoreTarget() = 0;
public:
/// @name Fight ranges/distances parameters
//@{
static float fightDists[AISHEETS::FIGHTCFG_MAX];
static float fightDefaultMinRange;
static float fightDefaultMaxRange;
static float fightMeleeMinRange;
static float fightMeleeMaxRange;
static float fightRangeMinRange;
static float fightRangeMaxRange;
static float fightMixedMinRange;
static float fightMixedMaxRange;
static float giveUpDistance;
static bool fleeUnreachableTargets;
//@}
};
//////////////////////////////////////////////////////////////////////////////
// CBotProfileFight //
//////////////////////////////////////////////////////////////////////////////
/// Generic fight profile class
class CBotProfileFight
: public CBotProfileFightHeal
, public NLMISC::IDbgPtrData
{
public:
/// @name Constructors, destructor
//@{
CBotProfileFight(CProfileOwner* owner, CAIEntityPhysical* ennemy);
virtual ~CBotProfileFight();
//@}
/// @name Event handlers
//@{
virtual void eventBeginFight() = 0;
virtual void eventTargetKilled() = 0;
//@}
/// @name IAIProfile implementation
//@{
virtual void beginProfile();
virtual void resumeProfile();
virtual void endProfile();
virtual void updateProfile(uint ticksSinceLastUpdate);
virtual std::string getOneLineInfoString() const;
//@}
virtual void noMoreTarget() = 0;
public:
/// @name Accessors
//@{
bool isHitting() const { return _Bot->isHitting(); }
bool atAttackDist() const { return _AtAttackDist; }
virtual AITYPES::TProfiles getAIProfileType() const { return AITYPES::BOT_FIGHT; }
//@}
protected:
NLMISC::CDbgPtr<CSpawnBot> _Bot;
NLMISC::CRefPtr<CAIEntityPhysical> _Ennemy;
bool _Engaged;
CPathPosition _PathPos;
CPathCont _PathCont;
bool _RangeCalculated;
bool _UseFightConfig;
float _RangeMin;
float _RangeMax;
bool _AtAttackDist;
bool _SearchAlternativePath;
};
//////////////////////////////////////////////////////////////////////////////
// CBotProfileHeal //
//////////////////////////////////////////////////////////////////////////////
/// Generic fight profile class
class CBotProfileHeal
: public CBotProfileFightHeal
{
public:
/// @name Constructors, destructor
//@{
CBotProfileHeal(TDataSetRow const& row, CProfileOwner* owner);
virtual ~CBotProfileHeal();
//@}
/// @name Event handlers
//@{
// virtual void eventBeginFight() = 0;
virtual void eventTargetKilled() { nlwarning("eventTargetKilled called on a heal profile"); }
//@}
/// @name IAIProfile implementation
//@{
virtual void beginProfile();
virtual void resumeProfile();
virtual void endProfile();
virtual void updateProfile(uint ticksSinceLastUpdate);
virtual std::string getOneLineInfoString() const;
//@}
virtual void noMoreTarget() = 0;
public:
/// @name Accessors
//@{
bool isHitting() const { return (_Bot->getActionFlags()&RYZOMACTIONFLAGS::Attacks)!=0; }
bool atAttackDist() const { return _AtAttackDist; }
virtual AITYPES::TProfiles getAIProfileType() const { return AITYPES::BOT_HEAL; }
//@}
protected:
NLMISC::CDbgPtr<CSpawnBot> _Bot;
bool _Engaged;
CPathPosition _PathPos;
CPathCont _PathCont;
TDataSetRow _Row;
bool _RangeCalculated;
bool _UseFightConfig;
float _RangeMin;
float _RangeMax;
bool _AtAttackDist;
bool _SearchAlternativePath;
};
//////////////////////////////////////////////////////////////////////////////
// CBotProfileFlee //
//////////////////////////////////////////////////////////////////////////////
class CBotProfileFlee
: public CAIBaseProfile
{
public:
/// @name Constructor and destructor
//@{
CBotProfileFlee(CProfileOwner *owner);
virtual ~CBotProfileFlee();
//@}
/// @name IAIProfile implementation
//@{
virtual void beginProfile();
virtual void updateProfile(uint ticksSinceLastUpdate);
virtual void endProfile() { }
virtual AITYPES::TProfiles getAIProfileType () const { return AITYPES::BOT_FLEE; }
virtual std::string getOneLineInfoString() const;
//@}
private:
RYAI_MAP_CRUNCH::CDirection _LastDir;
RYAI_MAP_CRUNCH::CMapPosition _LastStartPos;
RYAI_MAP_CRUNCH::TAStarFlag _DenyFlags;
CPathPosition _PathPos;
CPathCont _fightFleePathContainer;
public:
/// @name Flee ranges/distances parameters
//@{
static float giveUpDistanceUnreachable;
//@}
protected:
NLMISC::CDbgPtr<CSpawnBot> _Bot;
};
//////////////////////////////////////////////////////////////////////////////
// CBotProfileReturnAfterFight //
//////////////////////////////////////////////////////////////////////////////
class CBotProfileFollowPos;
class CBotProfileReturnAfterFight
: public CAIBaseProfile
{
public:
/// @name Constructor and destructor
//@{
CBotProfileReturnAfterFight(CProfileOwner *owner);
virtual ~CBotProfileReturnAfterFight();
//@}
/// @name IAIProfile implementation
//@{
virtual void beginProfile();
virtual void updateProfile(uint ticksSinceLastUpdate);
virtual void endProfile();
virtual AITYPES::TProfiles getAIProfileType () const { return AITYPES::BOT_RETURN_AFTER_FIGHT; }
virtual std::string getOneLineInfoString() const;
virtual void stateChangeProfile();
//@}
private:
/*
RYAI_MAP_CRUNCH::CDirection _LastDir;
RYAI_MAP_CRUNCH::CMapPosition _LastStartPos;
RYAI_MAP_CRUNCH::TAStarFlag _DenyFlags;
CPathPosition _PathPos;
CPathCont _fightFleePathContainer;
*/
// CPathCont _PathCont;
// NLMISC::CSmartPtr<CBotProfileFollowPos> _MoveProfile;
public:
/// @name Flee ranges/distances parameters
//@{
// static float giveUpDistanceUnreachable;
//@}
protected:
NLMISC::CDbgPtr<CSpawnBot> _Bot;
};
//////////////////////////////////////////////////////////////////////////////
// CFightOrganizer //
//////////////////////////////////////////////////////////////////////////////
class CFightOrganizer
{
public:
CFightOrganizer();
template <class TContainerIterator>
void reorganize(TContainerIterator const& first, TContainerIterator const& last)
{
H_AUTO(CFightOrganizer_reorganize);
_HaveEnnemy = false;
for (TContainerIterator it=first, itEnd=last;it!=itEnd;++it)
{
CBot* bot = (*it);
if (!reorganizeIteration(bot))
break;
}
}
/// @name Virtual interface
//@{
virtual void setFight(CSpawnBot* bot, CAIEntityPhysical* ennemy) = 0;
virtual void setHeal(CSpawnBot* bot, CAIEntityPhysical* target) = 0;
virtual void setNoFight(CSpawnBot* bot) = 0;
virtual void setFlee(CSpawnBot* bot, CAIVector& fleeVect) = 0;
virtual void setReturnAfterFight(CSpawnBot* bot) = 0;
//@}
private:
bool healIteration(CBot* bot, CBot* otherBot);
bool reorganizeIteration(CBot* bot);
protected:
bool _HaveEnnemy;
};
/****************************************************************************/
/* Profile factories */
/****************************************************************************/
//////////////////////////////////////////////////////////////////////////////
// CBotProfileFightFactory //
//////////////////////////////////////////////////////////////////////////////
class CBotProfileFightFactory
: public IAIProfileFactory
{
public:
NLMISC::CSmartPtr<IAIProfile> createAIProfile(CProfileOwner* owner)
{
nlassert(false);
return NULL;
}
};
RYAI_DECLARE_PROFILE_FACTORY(CBotProfileFightFactory);
//////////////////////////////////////////////////////////////////////////////
// CBotProfileFleeFactory //
//////////////////////////////////////////////////////////////////////////////
class CBotProfileFleeFactory
: public IAIProfileFactory
{
public:
NLMISC::CSmartPtr<IAIProfile> createAIProfile(CProfileOwner* owner)
{
nlassert(false);
return NULL;
}
};
RYAI_DECLARE_PROFILE_FACTORY(CBotProfileFleeFactory);
#endif