1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "ai_generic_fight.h"
21 #include "ai_player.h"
22 #include "server_share/msg_brick_service.h"
23 #include "ai_profile_npc.h"
25 extern bool simulateBug(int bugId
);
27 RYZOMID::TTypeId ai_generic_fight_debugCheckedType
= RYZOMID::unknown
;
28 #define debugCheckedType ai_generic_fight_debugCheckedType
30 RYAI_REGISTER_PROFILE_FACTORY(CBotProfileFleeFactory
, "bot_flee");
31 RYAI_REGISTER_PROFILE_FACTORY(CBotProfileFightFactory
, "bot_fight");
33 using namespace NLMISC
;
34 //using namespace std;
36 std::string
CBotProfileFlee::getOneLineInfoString() const
38 return std::string("flee profile: bot="+_Bot
->dataSetRow().toString()+" "+CMirrors::getEntityId(_Bot
->dataSetRow()).toString());
41 std::string
CBotProfileFight::getOneLineInfoString() const
43 return std::string("fight profile: bot="+_Bot
->dataSetRow().toString()+" ennemy="+_Ennemy
->dataSetRow().toString()+", Hitting: "+toString(isHitting())+" SearchPath: "+toString(_SearchAlternativePath
));
46 std::string
CBotProfileHeal::getOneLineInfoString() const
48 return std::string("heal profile: bot="+_Row
.toString()+" "+CMirrors::getEntityId(_Row
).toString()+", Hitting: "+toString(isHitting())+" SearchPath: "+toString(_SearchAlternativePath
));
51 //////////////////////////////////////////////////////////////////////////////
52 // CBotProfileFight //
53 //////////////////////////////////////////////////////////////////////////////
55 void CBotProfileFight::beginProfile()
58 _Bot
->setTarget(_Ennemy
);
62 void CBotProfileFight::resumeProfile()
65 _Bot
->setTarget(_Ennemy
);
68 CBotProfileFight::CBotProfileFight(CProfileOwner
* owner
, CAIEntityPhysical
* ennemy
)
69 : CBotProfileFightHeal()
70 , _Bot(NLMISC::safe_cast
<CSpawnBot
*>(owner
))
72 , _PathPos(NLMISC::safe_cast
<CSpawnBot
*>(owner
)->theta())
73 , _PathCont(NLMISC::safe_cast
<CSpawnBot
*>(owner
)->getAStarFlag())
74 , _RangeCalculated(false)
75 , _SearchAlternativePath(false)
82 CBotProfileFight::~CBotProfileFight()
88 AISHEETS::ICreature::TScriptCompList
const& scriptList
= _Bot
->getPersistent().getSheet()->DeathScriptList();
89 FOREACHC(it
, AISHEETS::ICreature::TScriptCompList
, scriptList
)
93 float CBotProfileFightHeal::fightDists
[AISHEETS::FIGHTCFG_MAX
] = { 0.5f
, 80.f
, 80.f
, 80.f
};
94 float CBotProfileFightHeal::fightDefaultMinRange
= 0.01f
;
95 float CBotProfileFightHeal::fightDefaultMaxRange
= 0.5f
;
96 float CBotProfileFightHeal::fightMeleeMinRange
= 0.01f
;
97 float CBotProfileFightHeal::fightMeleeMaxRange
= 0.5f
;
98 float CBotProfileFightHeal::fightRangeMinRange
= 0.4f
;
99 float CBotProfileFightHeal::fightRangeMaxRange
= 80.f
;
100 float CBotProfileFightHeal::fightMixedMinRange
= 0.01f
;
101 float CBotProfileFightHeal::fightMixedMaxRange
= 45.f
;
102 float CBotProfileFightHeal::giveUpDistance
= 100.f
;
103 bool CBotProfileFightHeal::fleeUnreachableTargets
= true;
106 NLMISC_COMMAND(fightMeleeDist
, "Generic fight melee attack range","")
108 if(args
.size()>1) return false;
109 if(args
.size()==1) CBotProfileFightHeal::fightDists
[AISHEETS::FIGHTCFG_MELEE
] = (float)atof(args
[0].c_str());
110 log
.displayNL("Melee fight range is %f", CBotProfileFightHeal::fightDists
[AISHEETS::FIGHTCFG_MELEE
]);
113 NLMISC_COMMAND(fightRangeDist
, "Generic fight range attack range","")
115 if(args
.size()>1) return false;
116 if(args
.size()==1) CBotProfileFightHeal::fightDists
[AISHEETS::FIGHTCFG_RANGE
] = (float)atof(args
[0].c_str());
117 log
.displayNL("Range fight range is %f", CBotProfileFightHeal::fightDists
[AISHEETS::FIGHTCFG_RANGE
]);
120 NLMISC_COMMAND(fightNukeDist
, "Generic fight nuke attack range","")
122 if(args
.size()>1) return false;
123 if(args
.size()==1) CBotProfileFightHeal::fightDists
[AISHEETS::FIGHTCFG_NUKE
] = (float)atof(args
[0].c_str());
124 log
.displayNL("Nuke fight range is %f", CBotProfileFightHeal::fightDists
[AISHEETS::FIGHTCFG_NUKE
]);
127 NLMISC_COMMAND(fightHealDist
, "Generic fight heal range","")
129 if(args
.size()>1) return false;
130 if(args
.size()==1) CBotProfileFightHeal::fightDists
[AISHEETS::FIGHTCFG_HEAL
] = (float)atof(args
[0].c_str());
131 log
.displayNL("Heal fight range is %f", CBotProfileFightHeal::fightDists
[AISHEETS::FIGHTCFG_HEAL
]);
134 NLMISC_COMMAND(fightDefaultRange
, "Generic default fight range","")
136 if (args
.size()==0 || args
.size()==2)
140 NLMISC::fromString(args
[0], CBotProfileFightHeal::fightDefaultMinRange
);
141 NLMISC::fromString(args
[1], CBotProfileFightHeal::fightDefaultMaxRange
);
143 log
.displayNL("Generic default fight range is [%f;%f]", CBotProfileFightHeal::fightDefaultMinRange
, CBotProfileFightHeal::fightDefaultMaxRange
);
148 NLMISC_COMMAND(fightMeleeRange
, "Generic melee fight range","")
150 if (args
.size()==0 || args
.size()==2)
154 CBotProfileFightHeal::fightMeleeMinRange
= (float)atof(args
[0].c_str());
155 CBotProfileFightHeal::fightMeleeMaxRange
= (float)atof(args
[1].c_str());
157 log
.displayNL("Generic melee fight range is [%f;%f]", CBotProfileFightHeal::fightMeleeMinRange
, CBotProfileFightHeal::fightMeleeMaxRange
);
162 NLMISC_COMMAND(fightRangeRange
, "Generic range fight range","")
164 if (args
.size()==0 || args
.size()==2)
168 CBotProfileFightHeal::fightRangeMinRange
= (float)atof(args
[0].c_str());
169 CBotProfileFightHeal::fightRangeMaxRange
= (float)atof(args
[1].c_str());
171 log
.displayNL("Generic range fight range is [%f;%f]", CBotProfileFightHeal::fightRangeMinRange
, CBotProfileFightHeal::fightRangeMaxRange
);
176 NLMISC_COMMAND(fightMixedRange
, "Generic mixed fight range","")
178 if (args
.size()==0 || args
.size()==2)
182 CBotProfileFightHeal::fightMixedMinRange
= (float)atof(args
[0].c_str());
183 CBotProfileFightHeal::fightMixedMaxRange
= (float)atof(args
[1].c_str());
185 log
.displayNL("Generic mixed fight range is [%f;%f]", CBotProfileFightHeal::fightMixedMinRange
, CBotProfileFightHeal::fightMixedMaxRange
);
190 NLMISC_COMMAND(fightGiveUpDistance
, "Generic fight give up distance","")
192 if(args
.size()>1) return false;
193 if(args
.size()==1) CBotProfileFightHeal::giveUpDistance
= (float)atof(args
[0].c_str());
194 log
.displayNL("Give up distance is %f", CBotProfileFightHeal::giveUpDistance
);
197 NLMISC_COMMAND(fleeUnreachableTargets
, "Tells if creatures flee an unreachable player","")
199 if(args
.size()>1) return false;
203 fromString(args
[0], b
);
204 CBotProfileFightHeal::fleeUnreachableTargets
= b
;
206 log
.displayNL("Creatures do%s flee unreachable targets", CBotProfileFightHeal::fleeUnreachableTargets
?"":" not");
210 //////////////////////////////////////////////////////////////////////////////
211 // CBotProfileHeal //
212 //////////////////////////////////////////////////////////////////////////////
214 void CBotProfileHeal::beginProfile()
217 _Bot
->setTarget(CAIS::instance().getEntityPhysical(_Row
));
218 // eventBeginFight(); // :TODO: Reactivate this
221 void CBotProfileHeal::resumeProfile()
224 _Bot
->setTarget(CAIS::instance().getEntityPhysical(_Row
));
227 CBotProfileHeal::CBotProfileHeal(const TDataSetRow
&row
, CProfileOwner
*owner
)
228 : CBotProfileFightHeal()
229 , _Bot(NLMISC::safe_cast
<CSpawnBot
*>(owner
))
230 , _PathPos(NLMISC::safe_cast
<CSpawnBot
*>(owner
)->theta())
231 , _PathCont(NLMISC::safe_cast
<CSpawnBot
*>(owner
)->getAStarFlag())
233 , _RangeCalculated(false)
234 , _SearchAlternativePath(false)
238 CBotProfileHeal::~CBotProfileHeal()
244 AISHEETS::ICreature::TScriptCompList
const& scriptList
= _Bot
->getPersistent().getSheet()->DeathScriptList();
245 for (AISHEETS::ICreature::TScriptCompList::const_iterator it
=scriptList
.begin(), itEnd
=scriptList
.end(); it
!=itEnd
; ++it
)
246 (*it
)->update(*_Bot
);
249 //////////////////////////////////////////////////////////////////////////////
250 // CBotProfileFlee //
251 //////////////////////////////////////////////////////////////////////////////
253 CBotProfileFlee::CBotProfileFlee(CProfileOwner
*owner
)
255 , _DenyFlags(NLMISC::safe_cast
<CSpawnBot
*>(owner
)->getAStarFlag())
256 , _PathPos(NLMISC::safe_cast
<CSpawnBot
*>(owner
)->theta())
257 , _fightFleePathContainer(NLMISC::safe_cast
<CSpawnBot
*>(owner
)->getAStarFlag())
258 , _Bot(NLMISC::safe_cast
<CSpawnBot
*>(owner
))
262 CBotProfileFlee::~CBotProfileFlee()
266 void CBotProfileFlee::beginProfile()
268 _LastDir
= RYAI_MAP_CRUNCH::CDirection(RYAI_MAP_CRUNCH::CDirection::UNDEFINED
);
271 void CBotProfileFlee::updateProfile(uint ticksSinceLastUpdate
)
273 H_AUTO(BotFleeProfileUpdate
);
274 CFollowPathContext
fpcBotFleeProfileUpdate("BotFleeProfileUpdate");
276 if (!_Bot
->getUnreachableTarget().isNULL())
278 CAIVector delta
= CAIVector(_Bot
->getUnreachableTarget()->aipos());
279 delta
-= CAIVector(_Bot
->pos());
280 if (delta
.quickNorm()>giveUpDistanceUnreachable
)
281 _Bot
->setUnreachableTarget((CAIEntityPhysical
*)NULL
);
283 if (!_Bot
->canMove())
288 CAIVector
fleeVector(_Bot
->moveDecalage());
289 _Bot
->resetDecalage();
290 if (fleeVector
.isNull())
291 fleeVector
.setX(1+fleeVector
.x()); // hum ..
292 RYAI_MAP_CRUNCH::CDirection
startDir(fleeVector
.x(), fleeVector
.y(), true);
294 // if we need to change our destination.
295 if ( startDir
!=_LastDir
296 || !_LastStartPos
.hasSameFullCellId(_Bot
->wpos()))
298 const RYAI_MAP_CRUNCH::CWorldMap
&worldMap
=CWorldContainer::getWorldMap();
301 for (sint nbStep
=0;nbStep
<8;nbStep
++)
303 // try to find a direction around startDir.
304 RYAI_MAP_CRUNCH::CDirection
dir(startDir
);
305 dir
.addStep((RYAI_MAP_CRUNCH::CDirection::TDeltaDirection
) ((nbStep
&1)?(nbStep
>>1):(-(nbStep
>>1))));
307 const RYAI_MAP_CRUNCH::CRootCell
*rootCell
=worldMap
.getRootCellCst(_Bot
->wpos().stepCell(dir
.dx(),dir
.dy()));
310 RYAI_MAP_CRUNCH::CWorldPosition wpos
=rootCell
->getWorldPosition(_Bot
->getPersistent().getChildIndex()&3);
312 && (wpos
.getFlags()&_DenyFlags
)==0 ) // verify that we got some compatible flags ..
315 _LastStartPos
=_Bot
->wpos();
318 _fightFleePathContainer
.setDestination(/*AITYPES::vp_auto, */wpos
);
328 // if we found somewhere to go, then go there ..
331 float dist
=_Bot
->runSpeed()*ticksSinceLastUpdate
;
332 CFollowPath::TFollowStatus
const status
= CFollowPath::getInstance()->followPath(
335 _fightFleePathContainer
,
339 if (status
==CFollowPath::FOLLOW_NO_PATH
)
341 // :KLUDGE: Warning has been removed to avoid flooding, without solving the problem
342 // nlwarning("Flee problem with destination properties (Water, Nogo)");
343 // :TODO: Rework that case
344 _LastDir
=RYAI_MAP_CRUNCH::CDirection(RYAI_MAP_CRUNCH::CDirection::UNDEFINED
);
349 _LastDir
=RYAI_MAP_CRUNCH::CDirection(RYAI_MAP_CRUNCH::CDirection::UNDEFINED
);
354 float CBotProfileFlee::giveUpDistanceUnreachable
= 75.f
;
356 NLMISC_COMMAND(fleeGiveUpDistanceUnreachable
, "Generic flee give up distance when fleeing an unreachable player","")
358 if(args
.size()>1) return false;
359 if(args
.size()==1) CBotProfileFlee::giveUpDistanceUnreachable
= (float)atof(args
[0].c_str());
360 log
.displayNL("Give up distance is %f", CBotProfileFlee::giveUpDistanceUnreachable
);
364 //////////////////////////////////////////////////////////////////////////////
365 // CFightOrganizer //
366 //////////////////////////////////////////////////////////////////////////////
368 CFightOrganizer::CFightOrganizer()
373 bool CFightOrganizer::healIteration(CBot
* bot
, CBot
* otherBot
)
377 CSpawnBot
* spBot
= bot
->getSpawnObj();
378 CSpawnBot
* otherSpBot
= otherBot
->getSpawnObj();
379 if (spBot
&& otherSpBot
&& otherSpBot
->isAlive())
381 float hp
= otherSpBot
->hpPercentage();
382 int neededHealers
= 0;
383 if (hp
<.90f
) ++neededHealers
;
384 if (hp
<.75f
) ++neededHealers
;
385 if (hp
<.50f
) ++neededHealers
;
386 if (hp
<.25f
) ++neededHealers
;
387 if (neededHealers
> otherSpBot
->getHealerCount())
389 IAIProfile
* profile
= spBot
->getAIProfile();
390 AITYPES::TProfiles profileType
= profile
?profile
->getAIProfileType():AITYPES::BAD_TYPE
;
391 if (profileType
!=AITYPES::BOT_HEAL
)
392 setHeal(spBot
, otherSpBot
);
393 spBot
->setTarget(otherSpBot
);
401 bool CFightOrganizer::reorganizeIteration(CBot
* bot
)
403 CSpawnBot
*spawnBot
=bot
->getSpawnObj();
405 || !spawnBot
->isAlive ())
408 IAIProfile
*profile
=spawnBot
->getAIProfile();
409 AITYPES::TProfiles profileType
=profile
?profile
->getAIProfileType():AITYPES::BAD_TYPE
;
411 // special comp if feared bypass every other comp .. (panic mode !)
412 if (spawnBot
->isFeared())
415 CAIEntityPhysical
* aggroer
= spawnBot
->firstVisualTargeter();
416 while (aggroer
!=NULL
)
418 CAIVector
delta(spawnBot
->aipos());
419 delta
-= aggroer
->aipos();
421 aggroer
= aggroer
->nextTargeter();
424 CAIS
& inst
= CAIS::instance();
426 FOREACHC(itEntry
, CBotAggroOwner::TBotAggroList
, spawnBot
->getBotAggroList())
428 CAIEntityPhysical
* const phys
= inst
.getEntityPhysical(itEntry
->second
->getBot());
431 CAIVector
delta(spawnBot
->aipos());
432 delta
-= phys
->aipos();
436 fleeVect
.normalize(1000);
437 CAIVector toGroup
= spawnBot
->spawnGrp().getCenterPos();
438 toGroup
-= spawnBot
->aipos();
439 toGroup
.normalize(1000);
441 // :TODO: Uncomment following line and test extensively (may reduce flee speed or dist, but is more correct)
442 // toGroup.normalize(1000);
443 setFlee(spawnBot
, fleeVect
);
446 // special comp if healer bypass every other comp
447 if (profileType
==AITYPES::BOT_HEAL
)
449 CBotProfileHeal
* healProfile
= NLMISC::safe_cast
<CBotProfileHeal
*>(profile
);
450 if (healProfile
->isHitting())
458 CGroup
* group
= bot
->getOwner();
459 CBot
* otherBot
= NULL
;
460 CSpawnBot
* otherSp
= NULL
;
462 if (spawnBot
->canHeal() && healIteration(bot
, group
->getSquadLeader(true)))
465 if (spawnBot
->canSelfHeal() && healIteration(bot
, bot
))
468 if (spawnBot
->canHeal())
470 FOREACH(itBot
, CCont
<CBot
>, group
->bots())
472 if (*itBot
&& bot
!=*itBot
&& (*itBot
)->isHealer())
473 if (healIteration(bot
, *itBot
))
478 FOREACH(itBot
, CCont
<CBot
>, group
->bots())
480 if (*itBot
&& bot
!=*itBot
)
481 if (healIteration(bot
, *itBot
))
485 // Heal others groups
486 CGroupNpc
* npcGroup
= NLMISC::safe_cast
<CGroupNpc
*>(group
);
488 std::vector
<CGroupNpc
*> grps
= npcGroup
->getHealGroups();
489 for (uint i
=0; i
<grps
.size(); ++i
)
491 FOREACH(itBot
, CCont
<CBot
>, grps
[i
]->bots())
493 if (*itBot
&& bot
!=*itBot
)
494 if (healIteration(bot
, *itBot
)) {
503 if (profileType
==AITYPES::BOT_FIGHT
)
505 CBotProfileFight
*fightProfile
=NLMISC::safe_cast
<CBotProfileFight
*>(profile
);
506 if (fightProfile
->isHitting())
514 std::vector
<CAIEntityPhysical
*> botList
;
515 AISHEETS::ICreatureCPtr botSheet
= bot
->getSheet();
517 float grpAggroCoef
= 0.5f
*botSheet
->GroupCohesionModulator();
519 spawnBot
->updateListAndMarkBot(botList
, 1.f
-grpAggroCoef
);
521 // unmarkBot list and choose target.
522 double BestChooseScore
=0; //botSheet.ScoreModulator;
524 CAIEntityPhysical
* ennemy
= NULL
;
525 CAIEntityPhysical
const * fleeEnnemy
= NULL
;
526 double BestFleeScore
=0; //botSheet.FearModulator;
528 CAIVector movingVector
;
531 CAIEntityPhysical
* target
= (CAIEntityPhysical
*)spawnBot
->getTarget();
533 FOREACH(it
, std::vector
<CAIEntityPhysical
*>, botList
)
535 CAIEntityPhysical
*const entity
=(*it
);
537 if (!entity
->isAlive())
539 if (ai_profile_npc_VerboseLog
)
541 nldebug("<FIGHT>Entity %s have aggro for dead entity %s, forgetting it.", spawnBot
->getEntityId().toString().c_str(), entity
->getEntityId().toString().c_str());
544 spawnBot
->forgetAggroFor(entity
->dataSetRow());
547 if (!entity
->isBotAttackable())
549 if (ai_profile_npc_VerboseLog
)
551 nldebug("<FIGHT>Entity %s have aggro for non bot attackable entity %s, forgetting it.", spawnBot
->getEntityId().toString().c_str(), entity
->getEntityId().toString().c_str());
554 spawnBot
->forgetAggroFor(entity
->dataSetRow());
558 // is there a problem.
559 if (entity
->_AggroScore
>0)
561 CAIVector
targetToPos(spawnBot
->aipos());
562 targetToPos
-= entity
->aipos();
567 slotCoef
= 1.f
/(1.f
+targetToPos
.quickNorm()*botSheet
->DistModulator()); // melee consideration. (don't know correct dist for caster or range may be in munition sheet !?).
569 if (((CAIEntityPhysical
*)entity
->getTarget())!=spawnBot
)
571 int nbOtherTargeter
= entity
->targeterCount();
572 if (entity
==((CAIEntityPhysical
*)spawnBot
->getTarget()))
574 float targetCoef
= 1.f
/(1.f
+nbOtherTargeter
*nbOtherTargeter
*botSheet
->TargetModulator());
575 slotCoef
*= targetCoef
;
577 slotCoef
*= entity
->getFreeFightSpaceRatio();
580 //////////////////////////////////////////////////////////////////////////////
582 float score
= (float)(entity
->_AggroScore
*slotCoef
);
584 if (target
&& target
->getRyzomType() == RYZOMID::player
)
586 if (entity
!= target
)
588 CBotPlayer
const* const ptarget
= NLMISC::safe_cast
<CBotPlayer
const*>(target
);
589 if (entity
->getRyzomType() == RYZOMID::player
)
591 CBotPlayer
const* const player
= NLMISC::safe_cast
<CBotPlayer
const*>(entity
);
592 if ( ptarget
&& player
&& spawnBot
->getAggroFor(entity
->dataSetRow()) <= spawnBot
->getAggroFor(ptarget
->dataSetRow()) && (
593 ptarget
->getCurrentTeamId() == CTEAM::InvalidTeamId
||
594 player
->getCurrentTeamId() == CTEAM::InvalidTeamId
||
595 player
->getCurrentTeamId() != ptarget
->getCurrentTeamId()
605 if (score
>=BestChooseScore
) // add distance and bot profile compatibility.
607 BestChooseScore
=score
;
611 entity
->_ChooseLastTime
= std::numeric_limits
<uint32
>::max();
614 if (fleeEnnemy
==NULL
&& !spawnBot
->getUnreachableTarget().isNULL())
616 fleeEnnemy
= spawnBot
->getUnreachableTarget();
622 nlassert(ennemy
->getRyzomType()!=debugCheckedType
);
623 if (target
== ennemy
)
628 // set the correct profile, if its not the case, otherwise, just change the target.
629 if (profileType
!=AITYPES::BOT_FIGHT
)
631 setFight(spawnBot
, ennemy
);
633 spawnBot
->setTarget(ennemy
);
637 CAIVector
fleeVect(spawnBot
->aipos());
638 fleeVect
-= fleeEnnemy
->aipos();
639 // :TODO: Check if following block is wanted by game design
641 CAIVector toGroup = spawnBot->spawnGrp().getCenterPos();
642 toGroup -= spawnBot->aipos();
645 fleeVect
.normalize(1000);
646 setFlee(spawnBot
, fleeVect
);
648 else if (spawnBot
->isReturning())
651 setReturnAfterFight(spawnBot
);
655 setNoFight(spawnBot
);
660 //////////////////////////////////////////////////////////////////////////////
661 // CBotProfileReturnAfterFight //
662 //////////////////////////////////////////////////////////////////////////////
664 CBotProfileReturnAfterFight::CBotProfileReturnAfterFight(CProfileOwner
* owner
)
666 //, _PathCont(NLMISC::safe_cast<CSpawnBot*>(owner)->getPersistent().getOwner()->getAStarFlag())
668 _Bot
= static_cast<CSpawnBot
*>(owner
);
669 // PROFILE_LOG("bot", "return_after_fight", "ctor", "");
670 // CSpawnBot* spawnBot = static_cast<CSpawnBot*>(owner);
671 // _PathCont.setDestination(spawnBot->getReturnPos());
672 // _MoveProfile = new CBotProfileFollowPos(&_PathCont, owner);
675 CBotProfileReturnAfterFight::~CBotProfileReturnAfterFight()
677 // PROFILE_LOG("bot", "return_after_fight", "dtor", "");
680 void CBotProfileReturnAfterFight::beginProfile()
682 // PROFILE_LOG("bot", "return_after_fight", "begin", "");
683 // _MoveProfile->beginProfile();
684 _Bot
->ignoreReturnAggro(true);
687 void CBotProfileReturnAfterFight::endProfile()
689 // PROFILE_LOG("bot", "return_after_fight", "end", "");
690 // _MoveProfile->endProfile();
691 _Bot
->ignoreReturnAggro(false);
694 void CBotProfileReturnAfterFight::stateChangeProfile()
696 // _MoveProfile->stateChangeProfile();
699 void CBotProfileReturnAfterFight::updateProfile(uint ticksSinceLastUpdate
)
701 H_AUTO(CBotProfileReturnAfterFightUpdate
);
702 // _MoveProfile->updateProfile(ticksSinceLastUpdate);
705 std::string
CBotProfileReturnAfterFight::getOneLineInfoString() const
707 std::string info
= "return_after_fight bot profile";
709 // info += _MoveProfile?_MoveProfile->getOneLineInfoString():std::string("<no move profile>");