1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "ai_outpost.h"
22 #include "continent.h"
23 #include "ai_grp_npc.h"
24 #include "game_share/people.h"
25 #include "ai_profile_npc.h"
27 #include "continent_inline.h"
28 #include "dyn_grp_inline.h"
31 using namespace NLMISC
;
32 using namespace AITYPES
;
36 CFileDisplayer
OutpostDisplayer("outposts.log");
37 CLog
OutpostDbgLog(CLog::LOG_DEBUG
), OutpostInfLog(CLog::LOG_INFO
), OutpostWrnLog(CLog::LOG_WARNING
), OutpostErrLog(CLog::LOG_ERROR
);
40 namespace OUTPOSTHELPERS
{
42 static std::map
<uint32
, uint32
> outpostFactions
;
44 bool isAttackingFaction(uint32 factionIndex
, CAIEntityPhysical
const* player
)
46 std::map
<uint32
, uint32
>::const_iterator it
= outpostFactions
.find(player
->outpostAlias());
47 return it
!=outpostFactions
.end() && it
->second
==factionIndex
;
52 //////////////////////////////////////////////////////////////////////////////
54 //////////////////////////////////////////////////////////////////////////////
56 //std::set<CContinent*> ChangedOutposts;
57 //COutpost::TOutpostIndex COutpost::_Outposts;
59 COutpost::COutpost(CContinent
* owner
, uint32 alias
, std::string
const& name
, std::string
const& filename
)
60 : CAliasChild
<CContinent
>(owner
, alias
, name
)
61 , CAliasTreeRoot(filename
)
62 , _OwnerAllianceId(InvalidAllianceId
)
63 , _AttackerAllianceId(InvalidAllianceId
)
64 , _State(OUTPOSTENUMS::UnknownOutpostState
)
67 static bool logInitDone
= false;
70 OutpostDbgLog
.addDisplayer( &OutpostDisplayer
);
71 OutpostInfLog
.addDisplayer( &OutpostDisplayer
);
72 OutpostWrnLog
.addDisplayer( &OutpostDisplayer
);
76 OUTPOST_DBG("Creating outpost %s' (%s)", name
.c_str(), getAliasFullName().c_str());
78 OUTPOST_DBG("Creating outpost '%s'", getAliasFullName().c_str());
80 _OutpostName
= getName();
81 COutpostManager
* manager
= NULL
;
82 // Create default squad manager
83 manager
= new COutpostSquadManager(this, 0, "default_squad_manager", filename
);
86 _Managers
.addChild(manager
);
89 // Create default building manager
90 manager
= new COutpostManager(this, 0, "default_building_manager", filename
);
93 _Managers
.addChild(manager
);
95 CGroupNpc
* group
= new CGroupNpc(manager
, NULL
, /*AStarFlag*/RYAI_MAP_CRUNCH::Nothing
);
98 manager
->groups().addAliasChild(group
);
99 group
->setAutoSpawn(false);
100 group
->setName("default_building_group");
101 group
->clearParameters();
102 group
->setPlayerAttackable(false);
103 group
->setBotAttackable(false);
104 group
->setBotsAreNamedFlag();
109 COutpost::~COutpost()
112 OUTPOST_DBG("Deleting outpost '%s'", getAliasFullName().c_str());
117 std::string
COutpost::getOneLineInfoString() const
119 return std::string("Outpost '") + getName() + "' " + getAliasString() + ", State=" + OUTPOSTENUMS::toString(_State
);
122 std::string
COutpost::getFullName() const
124 return std::string(getOwner()->getFullName() +":"+ getName());
127 std::string
COutpost::getIndexString() const
129 return getOwner()->getIndexString()+NLMISC::toString(":o%u", getChildIndex());
132 std::string COutpost::getPlaceOwnerFullName() const
134 return getFullName();
137 std::string COutpost::getPlaceOwnerIndexString() const
139 return getIndexString();
142 CAIInstance
* COutpost::getAIInstance() const
144 return getOwner()->getAIInstance();
147 std::string
COutpost::getManagerIndexString(CManager
const* manager
) const
149 return getIndexString()+NLMISC::toString(":m%u", manager
->getChildIndex());
152 IAliasCont
* COutpost::getAliasCont(TAIType type
)
156 case AITypeOutpostSquadFamily
:
157 OUTPOST_WRN( "Obsolete squad family node under outpost %s", getName().c_str() );
159 case AITypeOutpostSpawnZone
:
163 case AITypeOutpostManager
:
165 case AITypeOutpostBuilding
:
166 return getBuildingGroup()->getAliasCont(AITypeBot
);
173 CAliasTreeOwner
* COutpost::createChild(IAliasCont
* cont
, CAIAliasDescriptionNode
* aliasTree
)
178 CAliasTreeOwner
* child
= NULL
;
180 switch(aliasTree
->getType())
182 // create the child and adds it to the corresponding position.
183 case AITypeOutpostSpawnZone
:
184 child
= new COutpostSpawnZone(this, aliasTree
);
187 child
= new COutpostSquadManager(this, aliasTree
->getAlias(), aliasTree
->getName());
189 case AITypeOutpostManager
:
190 child
= new COutpostSquadManager(this, aliasTree
->getAlias(), aliasTree
->getName());
192 case AITypeOutpostBuilding
:
193 return getBuildingGroup()->createChild(cont
, aliasTree
);
197 cont
->addAliasChild(child
);
201 CGroup
* COutpost::getBuildingGroup()
203 COutpostManager
* manager
= _Managers
.getChildByName("default_building_manager");
204 return manager
->groups().getChildByName("default_building_group");
207 void COutpost::setTribe(const std::string
&tribeName
)
209 // The tribe is only populated by the NPCs of the squads
212 OUTPOST_DBG("setting tribe '%s' in '%s' as owner for outpost '%s'",
214 getOwner()->getName().c_str(),
215 getAliasFullName().c_str());
218 void COutpost::setOwnerAlliance( TAllianceId ownerAllianceId
)
220 if (_OwnerAllianceId
!=ownerAllianceId
)
222 // if the old owner was a tribe
223 if (_OwnerAllianceId
==InvalidAllianceId
)
225 triggerSpecialEvent(OUTPOSTENUMS::TribeOwnershipEnd
);
226 OUTPOSTHELPERS::outpostFactions
.erase(getAlias());
229 triggerSpecialEvent(OUTPOSTENUMS::GuildOwnershipEnd
);
231 std::swap(_OwnerAllianceId
, ownerAllianceId
); // 'ownerAllianceId' contains old owner alliance id
232 if (_OwnerAllianceId
!=ownerAllianceId
)
234 triggerSpecialEvent(OUTPOSTENUMS::OwnerChanged
);
235 // if the new owner is a tribe
236 if (_OwnerAllianceId
==InvalidAllianceId
)
238 OUTPOSTHELPERS::outpostFactions
.insert(make_pair(getAlias(), CStaticFames::getInstance().getFactionIndex(_Tribe
)));
239 triggerSpecialEvent(OUTPOSTENUMS::TribeOwnershipBegin
);
242 triggerSpecialEvent(OUTPOSTENUMS::GuildOwnershipBegin
);
246 void COutpost::setAttackerAlliance( TAllianceId attackerAllianceId
)
248 std::swap(_AttackerAllianceId
, attackerAllianceId
); // 'attackerAllianceId' contains old attacker alliance id
249 if (_AttackerAllianceId
!=attackerAllianceId
)
251 triggerSpecialEvent(OUTPOSTENUMS::AttackerChanged
);
254 // Update the enemies of the current squads of the outpost
255 FOREACH( im
, CAliasCont
<COutpostManager
>, _Managers
)
256 im
->setEnemies( _AttackerAllianceId
);
259 void COutpost::setState( OUTPOSTENUMS::TOutpostState state
)
263 if (_State
==OUTPOSTENUMS::Peace
)
264 triggerSpecialEvent(OUTPOSTENUMS::PeaceStateEnd
);
266 std::swap(_State
, state
); // 'state' contains old _State
269 triggerSpecialEvent(OUTPOSTENUMS::StateChanged
);
270 if (_State
==OUTPOSTENUMS::Peace
)
271 triggerSpecialEvent(OUTPOSTENUMS::PeaceStateBegin
);
275 void COutpost::update()
277 // FOREACH(it, CAliasCont<COutpostSquadFamily>, _SquadFamilies) it->update();
278 // FOREACH(it, CAliasCont<COutpostSpawnZone>, _SpawnZones) it->update();
279 FOREACH(it
, CAliasCont
<COutpostManager
>, _Managers
) it
->update();
282 void COutpost::addZone(COutpostSpawnZone
* zone
)
285 if (_ZoneList
.find(NLMISC::CStringMapper::map(zone
->getName()))!=_ZoneList
.end())
286 OUTPOST_WRN("this OutpostSpawnZone have the same name than another: %s", zone
->getName().c_str());
288 _ZoneList
[NLMISC::CStringMapper::map(zone
->getName())] = zone
;
291 void COutpost::removeZone(COutpostSpawnZone
* zone
)
293 _ZoneList
.erase(NLMISC::CStringMapper::map(zone
->getName()));
296 COutpostSpawnZone
* COutpost::getZone(NLMISC::TStringId zoneName
)
298 return _ZoneList
[zoneName
];
301 void COutpost::serviceEvent(CServiceEvent
const& info
)
303 if (info
.getServiceName()=="EGS" && info
.getEventType()==CServiceEvent::SERVICE_DOWN
)
305 // Delete all the squad groups
306 COutpostManager
* manager
= _Managers
.getChildByName("default_squad_manager");
308 manager
->groups().clear();
310 FOREACH(itManager
, CAliasCont
<COutpostManager
>, _Managers
)
312 COutpostManager
* manager
= *itManager
;
313 manager
->serviceEvent(info
);
317 bool COutpost::spawn()
319 // Spawn outpost managers
320 CCont
<COutpostManager
>::iterator itManager
, itManagerEnd(_Managers
.end());
321 for (itManager
=_Managers
.begin(); itManager
!=itManagerEnd
; ++itManager
)
323 COutpostManager
* manager
= *itManager
;
326 // We should check individual errors, but fake success here :)
330 bool COutpost::despawn()
332 // Despawn instance managers
333 CCont
<COutpostManager
>::iterator itManager
, itManagerEnd(_Managers
.end());
334 for (itManager
=_Managers
.begin(); itManager
!=itManagerEnd
; ++itManager
)
336 COutpostManager
* manager
= *itManager
;
337 manager
->despawnMgr();
339 // We should check individual errors, but fake success here :)
343 //-----------------------------------------------------------------------------
344 std::string
COutpost::getStateName() const
346 return OUTPOSTENUMS::toString(_State
);
349 //////////////////////////////////////////////////////////////////////////////
350 // COutpostSquadFamily //
351 //////////////////////////////////////////////////////////////////////////////
353 IAliasCont
* COutpostSquadFamily::getAliasCont(TAIType type
)
357 case AITypeGroupTemplate
:
358 case AITypeGroupTemplateMultiLevel
:
366 CAliasTreeOwner
* COutpostSquadFamily::createChild(IAliasCont
* cont
, CAIAliasDescriptionNode
* aliasTree
)
371 CAliasTreeOwner
* child
= NULL
;
373 switch (aliasTree
->getType())
375 case AITypeSquadTemplateVariant
:
376 child
= new CGroupDesc
<COutpostSquadFamily
>(this, aliasTree
->getAlias(), aliasTree
->getParent()->getName()+":"+aliasTree
->getName());
378 case AITypeGroupTemplate
:
379 case AITypeGroupTemplateMultiLevel
:
380 child
= new CGroupDesc
<COutpostSquadFamily
>(this, aliasTree
->getAlias(), aliasTree
->getName());
385 cont
->addAliasChild(child
);
389 std::string
COutpostSquadFamily::getFullName() const
391 // return std::string(getOwner()->getFullName() +":"+ getName());
395 std::string
COutpostSquadFamily::getIndexString() const
397 return getOwner()->getIndexString()+NLMISC::toString(":sf%u", getChildIndex());
400 //////////////////////////////////////////////////////////////////////////////
402 //////////////////////////////////////////////////////////////////////////////
404 template <> size_t const CGroupDesc
<COutpostSquadFamily
>::_MultiLevelSheetCount
= 20;
406 //////////////////////////////////////////////////////////////////////////////
408 //////////////////////////////////////////////////////////////////////////////
410 template <> size_t const CBotDesc
<COutpostSquadFamily
>::_MultiLevelSheetCount
= 20;
412 //////////////////////////////////////////////////////////////////////////////
413 // COutpostSpawnZone //
414 //////////////////////////////////////////////////////////////////////////////
416 COutpostSpawnZone::COutpostSpawnZone(COutpost
* owner
, CAIAliasDescriptionNode
* adn
)
417 : CAIPlaceXYR(owner
, adn
)
419 owner
->addZone(this);
422 COutpostSpawnZone::~COutpostSpawnZone()
424 static_cast<COutpost
*>(getOwner())->removeZone(this);
427 std::string
COutpostSpawnZone::getFullName() const
429 return std::string(getOwner()->getFullName() +":"+ getName());
432 std::string
COutpostSpawnZone::getIndexString() const
434 return getOwner()->getIndexString()+NLMISC::toString(":%u", getChildIndex());
437 //////////////////////////////////////////////////////////////////////////////
438 // COutpostManager //
439 //////////////////////////////////////////////////////////////////////////////
441 COutpostManager::COutpostManager(COutpost
* parent
, uint32 alias
, std::string
const& name
, std::string
const& filename
)
442 : CMgrNpc(parent
, alias
, name
, filename
)
448 COutpostManager::~COutpostManager()
450 unregisterEvents(); // need be called otherwise the state manager will be unhappy when the CAIEvent objects are destroyed
453 std::string
COutpostManager::getOneLineInfoString() const
455 return std::string("Outpost manager '") + getName() + "'";
458 void COutpostManager::update()
463 IAliasCont
* COutpostManager::getAliasCont(TAIType type
)
465 // IAliasCont* cont = NULL;
474 return CMgrNpc::getAliasCont(type
);
477 CAliasTreeOwner
* COutpostManager::createChild(IAliasCont
* cont
, CAIAliasDescriptionNode
* aliasTree
)
479 // CAliasTreeOwner* child = NULL;
480 // switch (aliasTree->getType())
486 // cont->addAliasChild(child);
490 return CMgrNpc::createChild(cont
, aliasTree
);
493 void COutpostManager::registerEvents()
495 _StateMachine
.addEvent( "outpost_peace_state_begin", EventOutpostPeaceStateBegin
);
496 _StateMachine
.addEvent( "outpost_peace_state_end", EventOutpostPeaceStateEnd
);
497 _StateMachine
.addEvent( "outpost_tribe_ownership_begin", EventOutpostTribeOwnershipBegin
);
498 _StateMachine
.addEvent( "outpost_tribe_ownership_end", EventOutpostTribeOwnershipEnd
);
499 _StateMachine
.addEvent( "outpost_guild_ownership_begin", EventOutpostGuildOwnershipBegin
);
500 _StateMachine
.addEvent( "outpost_guild_ownership_end", EventOutpostGuildOwnershipEnd
);
501 _StateMachine
.addEvent( "outpost_owner_changed", EventOutpostOwnerChanged
);
502 _StateMachine
.addEvent( "outpost_attacker_changed", EventOutpostAttackerChanged
);
503 _StateMachine
.addEvent( "outpost_state_changed", EventOutpostStateChanged
);
506 void COutpostManager::unregisterEvents()
508 _StateMachine
.delEvent( "outpost_peace_state_begin" );
509 _StateMachine
.delEvent( "outpost_peace_state_end" );
510 _StateMachine
.delEvent( "outpost_tribe_ownership_begin" );
511 _StateMachine
.delEvent( "outpost_tribe_ownership_end" );
512 _StateMachine
.delEvent( "outpost_guild_ownership_begin" );
513 _StateMachine
.delEvent( "outpost_guild_ownership_end" );
514 _StateMachine
.delEvent( "outpost_owner_changed" );
515 _StateMachine
.delEvent( "outpost_attacker_changed" );
516 _StateMachine
.delEvent( "outpost_state_changed" );
519 void COutpostManager::autoSpawnBegin()
523 FOREACH(itGroup
, CCont
<CGroup
>, groups())
525 CGroupNpc
* group
= static_cast<CGroupNpc
*>(*itGroup
);
528 CSpawnGroupNpc
* spawn
= group
->getSpawnObj();
535 void COutpostManager::autoSpawnEnd()
539 FOREACH(itGroup
, CCont
<CGroup
>, groups())
541 CGroupNpc
* group
= static_cast<CGroupNpc
*>(*itGroup
);
544 CSpawnGroupNpc
* spawn
= group
->getSpawnObj();
546 spawn
->despawnBots(1);
551 void COutpostManager::setEnemies( TAllianceId attackerAllianceId
)
553 FOREACH( ig
, CAliasCont
<CGroup
>, _Groups
)
555 // Attack only the declared ennemies of the outpost
556 CGroupNpc
*grp
= static_cast<CGroupNpc
*>(*ig
);
557 grp
->ennemyFaction().clearExtra();
558 grp
->ennemyFaction().addExtraProperty(attackerAllianceId
);
562 //////////////////////////////////////////////////////////////////////////////
563 // COutpostSquadManager //
564 //////////////////////////////////////////////////////////////////////////////
566 COutpostSquadManager::COutpostSquadManager(COutpost
* parent
, uint32 alias
, std::string
const& name
, std::string
const& filename
)
567 : COutpostManager(parent
, alias
, name
, filename
)
570 CAIState
* state
= new CAIStatePositional(getStateMachine(), 0, "outpost_squad_init");
571 IAIProfileFactory
* aiProfile
= lookupAIGrpProfile("squad");
572 state
->setActivityProfile(aiProfile
);
573 getStateMachine()->states().addChild(state
);
575 CAIEventDescription eventDescription
;
576 CAIEventActionNode::TSmartPtr eventAction
;
577 CAIEventReaction
* event
;
579 // Create event handler for start of state
580 eventDescription
.EventType
= "start_of_state";
581 // eventDescription.StateKeywords.push_back("");
582 // eventDescription.NamedStates.push_back("");
583 // eventDescription.GroupKeywords.push_back("");
584 // eventDescription.NamedGroups.push_back("");
586 // Create event action
587 eventAction
= new CAIEventActionNode
;
588 eventAction
->Action
= "code";
589 eventAction
->Weight
= 1;
590 eventAction
->Args
.push_back("print(\"CREATING A SQUAD\");");
591 // eventAction->Args.push_back("()setFactionProp(\"faction\", \"foo\");");
592 // eventAction->Args.push_back("()setFactionProp(\"ennemyFaction\", \"bar\");");
593 // eventAction->Args.push_back("()setFactionProp(\"friendFaction\", \"baf\");");
594 eventAction
->Args
.push_back("()setHealer(1);");
596 // Register event action
597 eventDescription
.Action
= eventAction
;
600 // Register event handler
601 // FIXME: 0 == CAIAliasDescriptionNode instance
602 event
= new CAIEventReaction(getStateMachine(), 0, eventDescription
.EventType
);
603 event
->processEventDescription(&eventDescription
, getStateMachine());
604 getStateMachine()->eventReactions().addChild(event
);
607 // Create event handler for group death
608 eventDescription
.EventType
= "group_eliminated";
609 // eventDescription.StateKeywords.push_back("");
610 // eventDescription.NamedStates.push_back("");
611 // eventDescription.GroupKeywords.push_back("");
612 // eventDescription.NamedGroups.push_back("");
614 // Create event action
615 eventAction
= new CAIEventActionNode
;
616 eventAction
->Action
= "outpost_report_squad_death";
617 eventAction
->Weight
= 1;
618 // eventAction->Args.push_back("");
620 // Register event action
621 eventDescription
.Action
= eventAction
;
624 // Register event handler
625 // FIXME: 0 == CAIAliasDescriptionNode instance
626 event
= new CAIEventReaction(getStateMachine(), 0, eventDescription
.EventType
);
627 event
->processEventDescription(&eventDescription
, getStateMachine());
628 getStateMachine()->eventReactions().addChild(event
);
631 // Create event handler for bot death
632 eventDescription
.EventType
= "bot_killed";
633 // eventDescription.StateKeywords.push_back("");
634 // eventDescription.NamedStates.push_back("");
635 // eventDescription.GroupKeywords.push_back("");
636 // eventDescription.NamedGroups.push_back("");
638 // Create event action
639 eventAction
= new CAIEventActionNode
;
640 eventAction
->Action
= "outpost_send_squad_status";
641 eventAction
->Weight
= 1;
642 // eventAction->Args.push_back("");
644 // Register event action
645 eventDescription
.Action
= eventAction
;
648 // Register event handler
649 // FIXME: 0 == CAIAliasDescriptionNode instance
650 event
= new CAIEventReaction(getStateMachine(), 0, eventDescription
.EventType
);
651 event
->processEventDescription(&eventDescription
, getStateMachine());
652 getStateMachine()->eventReactions().addChild(event
);
655 // Create event handler for bot death
656 eventDescription
.EventType
= "squad_leader_killed";
657 // eventDescription.StateKeywords.push_back("");
658 // eventDescription.NamedStates.push_back("");
659 // eventDescription.GroupKeywords.push_back("");
660 // eventDescription.NamedGroups.push_back("");
662 // Create event action
663 eventAction
= new CAIEventActionNode
;
664 eventAction
->Action
= "multi_actions";
665 eventAction
->Weight
= 1;
666 eventAction
->Children
.resize(2);
667 eventAction
->Children
[0] = new CAIEventActionNode
;
668 eventAction
->Children
[0]->Action
= "outpost_report_squad_leader_death";
669 eventAction
->Children
[0]->Weight
= 1;
670 // eventAction->Children[0]->Args.push_back("");
671 eventAction
->Children
[1] = new CAIEventActionNode
;
672 eventAction
->Children
[1]->Action
= "code";
673 eventAction
->Children
[1]->Weight
= 1;
674 eventAction
->Children
[1]->Args
.push_back("()setAutoSpawn(0);");
676 eventAction
->Children
[1]->Args
.push_back("print(\"INFINITE RESPAWN TIME FOR SQUAD\");");
679 // Register event action
680 eventDescription
.Action
= eventAction
;
683 // Register event handler
684 // FIXME: 0 == CAIAliasDescriptionNode instance
685 event
= new CAIEventReaction(getStateMachine(), 0, eventDescription
.EventType
);
686 event
->processEventDescription(&eventDescription
, getStateMachine());
687 getStateMachine()->eventReactions().addChild(event
);
691 //////////////////////////////////////////////////////////////////////////////
692 //////////////////////////////////////////////////////////////////////////////
693 //////////////////////////////////////////////////////////////////////////////
695 void COutpost::createSquad(string
const& dynGroupName
, string
const& stateMachineName
, string
const& initialStateName
, string
const& zoneName
, uint32 spawnOrder
, uint32 respawTimeGC
, OUTPOSTENUMS::TPVPSide side
)
697 IManagerParent
* const managerParent
= getOwner()->getOwner();
698 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
702 COutpostSpawnZone
const* spawnZone
= getZone(CStringMapper::map(zoneName
));
705 OUTPOST_WRN("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", stateMachineName
.c_str());
709 CGroupDesc
<COutpostSquadFamily
> const* groupDesc
= NULL
;
711 FOREACH(itGroupDesc
, CSquadLinks
, _SquadLinks
)
713 if ((*itGroupDesc
).second
->getName()==dynGroupName
)
715 groupDesc
= (*itGroupDesc
).second
;
722 OUTPOST_WRN("createSquad failed: No Group Found");
726 // Find the state machine as a manager
727 CManager
* manager
= NULL
;
728 FOREACH(itCont
, CCont
<CManager
>, aiInstance
->managers())
730 if (itCont
->getName()==stateMachineName
)
738 FOREACH(itCont
, CCont
<COutpostManager
>, managers())
740 if (itCont
->getName()==stateMachineName
)
749 OUTPOST_WRN("createSquad failed : Unknown stateMachine %s", stateMachineName
.c_str());
752 // Find the state machine as a npc manager
753 COutpostSquadManager
* outpostManager
= dynamic_cast<COutpostSquadManager
*>(manager
);
756 OUTPOST_WRN("createSquad failed : Not an outpost state machine !: ", stateMachineName
.c_str());
759 createSquad(groupDesc
, outpostManager
, initialStateName
, spawnZone
, spawnOrder
, respawTimeGC
, side
);
762 void COutpost::createSquad(uint32 dynGroupAlias
, uint32 zoneAlias
, uint32 spawnOrder
, uint32 respawTimeGC
, OUTPOSTENUMS::TPVPSide side
)
764 IManagerParent
* const managerParent
= getOwner()->getOwner();
765 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
769 COutpostSpawnZone
const* spawnZone
= spawnZones().getChildByAlias(zoneAlias
);
772 OUTPOST_WRN("createSquad failed: spawn zone %s not found", LigoConfig
.aliasToString(zoneAlias
).c_str());
776 CGroupDesc
<COutpostSquadFamily
> const* groupDesc
= NULL
;
778 // Find the group template.
779 // :TODO: Replace it with a faster map access.
780 groupDesc
= getSquad( dynGroupAlias
);
783 OUTPOST_WRN("createSquad failed: group %s not found", LigoConfig
.aliasToString(dynGroupAlias
).c_str());
787 // Find the state machine as a manager
788 COutpostSquadManager
* manager
= dynamic_cast<COutpostSquadManager
*>(managers().getChildByName("default_squad_manager"));
791 OUTPOST_WRN("createSquad failed: default state machine not found! (<- this is a code bug)");
794 createSquad(groupDesc
, manager
, "", spawnZone
, spawnOrder
, respawTimeGC
, side
);
797 void COutpost::createSquad(CGroupDesc
<COutpostSquadFamily
> const* groupDesc
, COutpostSquadManager
* manager
, string
const& initialStateName
, COutpostSpawnZone
const* spawnZone
, uint32 createOrder
, uint32 respawTimeGC
, OUTPOSTENUMS::TPVPSide side
)
799 OUTPOST_DBG("Creating a squad");
800 CAIVector
const& spawnPosition
= spawnZone
->midPos();
801 sint32 baseLevel
= -1;
802 double dispersionRadius
= spawnZone
->getRadius();
803 // Save the creator state
804 bool const savePlayerAttackable
= groupDesc
->getGDPlayerAttackable();
805 bool const saveBotAttackable
= groupDesc
->getGDBotAttackable();
806 // PlayerAttackable must be false as it it sent to the EGS in BotDescriptionMessage to set the
807 // property 'Attackable'. Squads are not attackable unless a player is in war with the owner of
808 // the outpost (using botchatprogram instead of the property 'Attackable').
809 // BotAttackable must be true, otherwise the EGS sets it as invulnerable (not attackable).
810 groupDesc
->setGDPlayerAttackable(false);
811 groupDesc
->setGDBotAttackable(true);
813 CGroupNpc
* const grp
= groupDesc
->createNpcGroup(manager
, spawnPosition
, dispersionRadius
, baseLevel
, false);
814 // Restore the creator state
815 groupDesc
->setGDPlayerAttackable(savePlayerAttackable
);
816 groupDesc
->setGDBotAttackable(saveBotAttackable
);
817 // Verify that the group was created
820 OUTPOST_WRN("createSquad failed: group %s cannot spawn", LigoConfig
.aliasToString(groupDesc
->getAlias()).c_str());
823 // Set the new group parameters
824 // Let the EGS destroys squads explicitely because when a group is destroyed in the AIS its groupId can be reused
825 // and 2 squads would have the same groupId in the EGS (it asserts)
826 grp
->autoDestroy(false);
827 grp
->setAutoSpawn(true);
828 // grp->getPersistentStateInstance()->setParentStateInstance(entity->getPersistentStateInstance());
829 grp
->initDynGrp(groupDesc
, NULL
);
831 uint8 color
= (uint8
)(grp
->getChildIndex() % 8);
832 grp
->setColour(color
);
833 // Get the state machine
834 CStateMachine
const* stateMachine
= manager
->getStateMachine();
836 // Verify that we have a state in the state machine
837 if (stateMachine
->cstStates().size()==0)
838 nlerror("no state defined for StateMachine in Manager %s", manager
->getFullName().c_str());
840 // Set the group in that state
841 CAIState
* initialState
= NULL
;
842 if (!initialStateName
.empty())
844 // FOREACH(itState, CCont<CAIState>, stateMachine->states())
845 for (size_t i
=0; i
<stateMachine
->cstStates().size(); ++i
)
847 CAIState
* state
= stateMachine
->cstStates()[(uint32
)i
];
848 if (state
->getName()==initialStateName
)
849 initialState
= state
;
852 if (initialState
==NULL
)
853 initialState
= stateMachine
->cstStates()[0]; // sets the first state (must exist!).
854 grp
->setStartState(initialState
);
856 // Do not assist friends because it would lead to exploits
857 /*if ( _OwnerGuild != InvalidGuildId )
859 //grp->faction().addExtraProperty(_OwnerGuild); // TODO: set the GuildId for the squad npcs?
860 //grp->friendFaction().addExtraProperty(_OwnerGuild); // will be defended by the squad
864 // A tribe owns the outpost and all players are ennemies
865 // CPropertyId tribeFaction(CGrpProfileFaction::fameFactionToScriptFaction(_OwnerTribe));
866 //grp->faction().addProperty(tribeFaction);
867 //grp->friendFaction().addProperty(tribeFaction); // will be defended by the squad
868 //grp->ennemyFaction().addProperty(CPropertyId("Player"));
871 // Set guild id of members of the squad (for the tribe case, these *are* the tribe as well)
872 // This was removed because CBotNpc::spawn() now uses getOwner()->getOwner()->getOwner() to access the outpsot
873 /*FOREACH(ib, CAliasCont<CBot>, grp->bots())
875 CBotNpc *bot = static_cast<CBotNpc*>(*ib);
876 bot->setOwnerOutpost(this);
879 grp
->setOutpostSide(side
);
880 grp
->setOutpostFactions(getAliasString(), side
);
882 grp
->_AggroRange
= 25;
883 grp
->_UpdateNbTicks
= 10;
884 grp
->respawnTime() = respawTimeGC
;
886 grp
->updateStateInstance(); // Directly call his first state (to retrieve associated params).
890 COutpostSquadCreatedMsg params
;
891 params
.Outpost
= this->getAlias();
892 params
.CreateOrder
= createOrder
;
893 // Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
894 //params.GroupId = reinterpret_cast<uint32>(grp);
895 params
.GroupId
= (uint32
)(size_t)(void*)grp
;
896 sendOutpostMessage("OUTPOST_SQUAD_CREATED", params
);
899 OUTPOST_DBG( "Outpost %s: squad created defending 0x%x against 0x%x, respawnTime=%u gc", getName().c_str(), _OwnerAllianceId
, _AttackerAllianceId
, respawTimeGC
);
902 void COutpost::spawnSquad(uint32 groupId
)
904 OUTPOST_DBG( "Outpost %s: Spawning squad 0x%08x", getName().c_str(), groupId
);
906 setAttackerAlliance(_AttackerAllianceId
);
909 FOREACH(itManager
, CAliasCont
<COutpostManager
>, _Managers
)
911 COutpostManager
* manager
= *itManager
;
912 FOREACH(itGroup
, CAliasCont
<CGroup
>, manager
->groups())
914 CGroup
* group
= *itGroup
;
915 CGroupNpc
* groupNpc
= static_cast<CGroupNpc
*>(group
);
916 // Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
917 //uint32 thisGroupId = reinterpret_cast<uint32>(groupNpc);
918 uint32 thisGroupId
= (uint32
)(size_t)(void*)groupNpc
;
919 if (groupId
==thisGroupId
)
921 group
->getSpawnObj()->spawnBots();
922 COutpostSquadSpawnedMsg params
;
923 params
.Outpost
= this->getAlias();
924 params
.GroupId
= groupId
;
925 sendOutpostMessage("OUTPOST_SQUAD_SPAWNED", params
);
926 OUTPOST_DBG( "\t\tSpawned" );
931 OUTPOST_WRN("No squad to spawn with group id 0x%08x. Valid group ids are:", groupId
);
932 FOREACH(itManager
, CAliasCont
<COutpostManager
>, _Managers
)
934 COutpostManager
* manager
= *itManager
;
935 FOREACH(itGroup
, CAliasCont
<CGroup
>, manager
->groups())
937 CGroup
* group
= *itGroup
;
938 CGroupNpc
* groupNpc
= static_cast<CGroupNpc
*>(group
);
939 // Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
940 //uint32 thisGroupId = reinterpret_cast<uint32>(groupNpc);
941 uint32 thisGroupId
= (uint32
)(size_t)(void*)groupNpc
;
942 OUTPOST_WRN("- 0x%08x", thisGroupId
);
947 void COutpost::despawnSquad(uint32 groupId
)
949 OUTPOST_DBG( "Outpost %s: Despawning squad 0x%08x", getName().c_str(), groupId
);
950 FOREACH(itManager
, CAliasCont
<COutpostManager
>, _Managers
)
952 COutpostManager
* manager
= *itManager
;
953 FOREACH(itGroup
, CAliasCont
<CGroup
>, manager
->groups())
955 CGroup
* group
= *itGroup
;
956 CGroupNpc
* groupNpc
= static_cast<CGroupNpc
*>(group
);
957 // Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
958 //uint32 thisGroupId = reinterpret_cast<uint32>(groupNpc);
959 uint32 thisGroupId
= (uint32
)(size_t)(void*)groupNpc
;
960 if (groupId
==thisGroupId
)
962 group
->despawnBots();
963 COutpostSquadDespawnedMsg params
;
964 params
.Outpost
= this->getAlias();
965 params
.GroupId
= groupId
;
966 sendOutpostMessage("OUTPOST_SQUAD_DESPAWNED", params
);
971 OUTPOST_WRN("No squad to despawn");
974 void COutpost::deleteSquad(uint32 groupId
)
976 OUTPOST_DBG( "Outpost %s: deleting squad 0x%08x", getName().c_str(), groupId
);
977 FOREACH(itManager
, CAliasCont
<COutpostManager
>, _Managers
)
979 COutpostManager
* manager
= *itManager
;
980 FOREACH(itGroup
, CAliasCont
<CGroup
>, manager
->groups())
982 CGroup
* group
= *itGroup
;
983 CGroupNpc
* groupNpc
= static_cast<CGroupNpc
*>(group
);
984 // Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
985 //uint32 thisGroupId = reinterpret_cast<uint32>(groupNpc);
986 uint32 thisGroupId
= (uint32
)(size_t)(void*)groupNpc
;
987 if (groupId
==thisGroupId
)
989 manager
->groups().removeChildByIndex(group
->getChildIndex());
990 // No message here since this is called by squad destructor in EGS
995 OUTPOST_WRN("No squad to delete");
998 void COutpost::sendOutpostSquadStatus(CGroupNpc
* group
)
1000 uint32 alias
= this->getAlias();
1001 // Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
1002 //uint32 groupId = reinterpret_cast<uint32>(group);
1003 uint32 groupId
= (uint32
)(size_t)(void*)group
;
1004 bool groupAlive
= false;
1005 bool leaderAlive
= group
->getSquadLeader()!=NULL
;
1006 uint32 botCount
= 0;
1007 // Persistent status
1008 // Spawn dependent status
1009 CSpawnGroup
* spawnGroup
= group
->getSpawnObj();
1012 groupAlive
= spawnGroup
->isGroupAlive();
1014 NLNET::CMessage
msgout("OUTPOST_SQUAD_STATUS");
1015 msgout
.serial(alias
);
1016 msgout
.serial(groupId
);
1017 msgout
.serial(groupAlive
);
1018 msgout
.serial(leaderAlive
);
1019 msgout
.serial(botCount
);
1020 sendMessageViaMirror("EGS", msgout
);
1023 void COutpost::squadLeaderDied(CGroupNpc
* group
)
1025 uint32 alias
= this->getAlias();
1026 // Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
1027 //uint32 groupId = reinterpret_cast<uint32>(group);
1028 uint32 groupId
= (uint32
)(size_t)(void*)group
;
1029 NLNET::CMessage
msgout("OUTPOST_SQUAD_LEADER_DIED");
1030 msgout
.serial(alias
);
1031 msgout
.serial(groupId
);
1032 sendMessageViaMirror("EGS", msgout
);
1035 void COutpost::squadDied(CGroupNpc
* group
)
1037 uint32 alias
= this->getAlias();
1038 // Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
1039 //uint32 groupId = reinterpret_cast<uint32>(group);
1040 uint32 groupId
= (uint32
)(size_t)(void*)group
;
1041 NLNET::CMessage
msgout("OUTPOST_SQUAD_DIED");
1042 msgout
.serial(alias
);
1043 msgout
.serial(groupId
);
1044 sendMessageViaMirror("EGS", msgout
);
1047 void COutpost::triggerSpecialEvent(OUTPOSTENUMS::TSpecialOutpostEvent eventId
)
1049 // Managers handlers
1050 FOREACH(itManager
, CCont
<COutpostManager
>, _Managers
)
1052 COutpostManager
* manager
= *itManager
;
1055 CAIEvent
* event
= NULL
;
1058 case OUTPOSTENUMS::PeaceStateBegin
: event
= &manager
->EventOutpostPeaceStateBegin
; break;
1059 case OUTPOSTENUMS::PeaceStateEnd
: event
= &manager
->EventOutpostPeaceStateEnd
; break;
1060 case OUTPOSTENUMS::TribeOwnershipBegin
: event
= &manager
->EventOutpostTribeOwnershipBegin
; break;
1061 case OUTPOSTENUMS::TribeOwnershipEnd
: event
= &manager
->EventOutpostTribeOwnershipEnd
; break;
1062 case OUTPOSTENUMS::GuildOwnershipBegin
: event
= &manager
->EventOutpostGuildOwnershipBegin
; break;
1063 case OUTPOSTENUMS::GuildOwnershipEnd
: event
= &manager
->EventOutpostGuildOwnershipEnd
; break;
1064 case OUTPOSTENUMS::OwnerChanged
: event
= &manager
->EventOutpostOwnerChanged
; break;
1065 case OUTPOSTENUMS::AttackerChanged
: event
= &manager
->EventOutpostAttackerChanged
; break;
1066 case OUTPOSTENUMS::StateChanged
: event
= &manager
->EventOutpostStateChanged
; break;
1070 FOREACH(itGroup
, CCont
<CGroup
>, manager
->groups())
1072 CGroupNpc
* group
= static_cast<CGroupNpc
*>(*itGroup
);
1074 group
->processStateEvent(*event
);
1082 case OUTPOSTENUMS::TribeOwnershipBegin
:
1084 FOREACH(itManager
, CCont
<COutpostManager
>, _Managers
)
1086 COutpostManager
* manager
= *itManager
;
1088 manager
->autoSpawnBegin();
1092 case OUTPOSTENUMS::TribeOwnershipEnd
:
1094 FOREACH(itManager
, CCont
<COutpostManager
>, _Managers
)
1096 COutpostManager
* manager
= *itManager
;
1098 manager
->autoSpawnEnd();
1105 void COutpost::setBuildingBotSheet(uint32 buildingAlias
, NLMISC::CSheetId sheetId
, bool autoSpawnDespawn
, const std::string
& customName
)
1107 CBot
* bot
= getBuildingBotByAlias(buildingAlias
);
1110 OUTPOST_WRN( "cannot find building bot %s", LigoConfig
.aliasToString( buildingAlias
).c_str() );
1114 AISHEETS::ICreatureCPtr
const sheet
= AISHEETS::CSheets::getInstance()->lookup(sheetId
);
1115 if (sheetId
!=NLMISC::CSheetId::Unknown
&& !sheet
.isNull())
1117 bot
->setCustomName(customName
);
1118 bot
->triggerSetSheet(sheet
);
1119 if (autoSpawnDespawn
&& !bot
->isSpawned())
1124 if (autoSpawnDespawn
&& bot
->isSpawned())
1129 void COutpost::despawnAllSquads()
1131 FOREACH(itManager
, CAliasCont
<COutpostManager
>, _Managers
)
1133 COutpostManager
* manager
= *itManager
;
1134 COutpostSquadManager
* sqManager
= dynamic_cast<COutpostSquadManager
*>(manager
);
1137 FOREACH(itGroup
, CAliasCont
<CGroup
>, sqManager
->groups())
1139 CGroup
* group
= *itGroup
;
1140 group
->despawnBots();
1147 void COutpost::sendOutpostMessage(std::string
const& msgName
, T
& paramStruct
)
1149 NLNET::CMessage
msgout(msgName
);
1150 msgout
.serial(paramStruct
);
1151 sendMessageViaMirror(std::string("EGS"), msgout
);
1154 //////////////////////////////////////////////////////////////////////////////
1156 //////////////////////////////////////////////////////////////////////////////
1158 NLMISC_COMMAND(displayOutposts
, "list the available outpost", "")
1160 if (args
.size() > 0)
1163 uint32 instanceNumber
= std::numeric_limits
<uint32
>::max();
1164 for (uint i
=0; i
<CAIS::instance().AIList().size(); ++i
)
1166 CAIInstance
*const aii
= CAIS::instance().AIList()[i
];
1169 log
.displayNL("No current ai instance, can't look for outpost");
1173 string continentName
;
1175 continentName
= args
[0];
1177 // retreive the oupost
1178 for (uint i
=0; i
<aii
->continents().size(); ++i
)
1180 CContinent
*const continent
= aii
->continents()[i
];
1182 || ( !continentName
.empty()
1183 && continentName
!=continent
->getName()))
1186 log
.displayNL("Outposts in continent '%s':", continent
->getName().c_str());
1187 for (uint j
=0; j
<continent
->outposts().size(); ++j
)
1189 COutpost
const* outpost
= continent
->outposts()[j
];
1193 log
.displayNL(" %s", outpost
->getOneLineInfoString().c_str());
1194 log
.displayNL(" - %d group descs", outpost
->squadLinks().size());
1195 for (COutpost::CSquadLinks::const_iterator isl
=outpost
->squadLinks().begin(); isl
!=outpost
->squadLinks().end(); ++isl
)
1197 CGroupDesc
<COutpostSquadFamily
> const* gd
= (*isl
).second
;
1201 log
.displayNL(" Group desc '%s' %s", gd
->getName().c_str(), gd
->getAliasString().c_str());
1204 log
.displayNL(" - %d spawn zones", outpost
->spawnZones().size());
1205 for (uint j
=0; j
<outpost
->spawnZones().size(); ++j
)
1207 COutpostSpawnZone
const* sz
= outpost
->spawnZones()[j
];
1211 log
.displayNL(" SpawnZone '%s' %s (%s)", sz
->getName().c_str(), sz
->getAliasString().c_str(), sz
->midPos().toString().c_str());
1213 log
.displayNL(" - %d state machines", outpost
->managers().size());
1214 for (uint j
=0; j
<outpost
->managers().size(); ++j
)
1216 COutpostManager
* manager
= outpost
->managers()[j
];
1220 log
.displayNL(" State machine '%s' %s", manager
->getName().c_str(), manager
->getAliasString().c_str());
1221 log
.displayNL(" - %d states", manager
->getStateMachine()->states().size());
1222 for (uint j
=0; j
<manager
->getStateMachine()->states().size(); ++j
)
1224 CAIState
const* state
= manager
->getStateMachine()->states()[j
];
1228 log
.displayNL(" State '%s' %s", state
->getName().c_str(), state
->getAliasString().c_str());
1230 log
.displayNL(" - %d groups", manager
->groups().size());
1231 for (uint j
=0; j
<manager
->groups().size(); ++j
)
1233 CGroup
const* group
= manager
->groups()[j
];
1236 log
.displayNL(" Group '%s' %s", group
->getName().c_str(), group
->getAliasString().c_str());
1237 log
.displayNL(" - %d bots", group
->bots().size());
1238 for (uint k
=0; k
<group
->bots().size(); ++k
)
1240 CBot
const* bot
= group
->bots()[k
];
1242 log
.displayNL(" Bot '%s' %s", bot
->getName().c_str(), bot
->getAliasString().c_str());
1244 log
.displayNL(" Bot <NULL>");
1248 log
.displayNL(" Group <NULL>");
1258 // outpostSpawnSquad 1 fyros outpost group machine zone
1260 NLMISC_COMMAND(outpostSpawnSquad
, "Spawns a squad in an outpost", "<instance_number> <continent> <outpost> <group_template> <state_machine> <spawn_zone> [<respawnTimeInSec>=5*60]")
1262 if (args
.size() != 6)
1265 uint32 instanceNumber
= std::numeric_limits
<uint32
>::max();
1266 fromString(args
[0], instanceNumber
);
1267 string continentName
= args
[1];
1268 string outpostName
= args
[2];
1269 string dynGroupName
= args
[3];
1270 string stateMachineName
= args
[4];
1271 string zoneName
= args
[5];
1272 uint32 respawnTimeGC
= 5*60*10;
1273 if ( args
.size() > 6 )
1275 NLMISC::fromString(args
[6], respawnTimeGC
);
1276 respawnTimeGC
*= 10;
1279 for (size_t i
=0; i
<5; ++i
)
1284 bool instanceFound
= false;
1285 bool continentFound
= false;
1286 bool outpostFound
= false;
1287 if (instanceNumber
<CAIS::instance().AIList().size())
1289 CAIInstance
* const aiinstance
= CAIS::instance().AIList()[instanceNumber
];
1292 instanceFound
= true;
1293 for (uint i
=0; i
<aiinstance
->continents().size() && !done
; ++i
)
1295 CContinent
* const continent
= aiinstance
->continents()[i
];
1296 if (!continent
|| continentName
!=continent
->getName())
1298 continentFound
= true;
1299 for (uint j
=0; j
<continent
->outposts().size() && !done
; ++j
)
1301 COutpost
* const outpost
= continent
->outposts()[j
];
1302 if (!outpost
|| outpostName
!=outpost
->getName())
1304 outpostFound
= true;
1305 outpost
->createSquad(dynGroupName
, stateMachineName
, "", zoneName
, 0, respawnTimeGC
, OUTPOSTENUMS::UnknownPVPSide
);
1313 OUTPOST_WRN("Could not spawn a new squad");
1314 log
.displayNL("Could not spawn a new squad");
1316 log
.displayNL( "Instance not found" );
1317 if (!continentFound
)
1318 log
.displayNL( "Continent not found" );
1320 log
.displayNL( "Outpost not found" );
1327 * Return the outpost corresponding to the alias, or NULL if not found (with a nlwarning)
1329 COutpost
* COutpost::getOutpostByAlias( TAIAlias outpostAlias
)
1331 bool instanceFound
= false;
1332 bool continentFound
= false;
1333 bool outpostFound
= false;
1334 for (uint i
=0; i
<CAIS::instance().AIList().size(); ++i
)
1336 CAIInstance
* const aiinstance
= CAIS::instance().AIList()[i
];
1339 instanceFound
= true;
1340 for (uint i
=0; i
<aiinstance
->continents().size(); ++i
)
1342 CContinent
* const continent
= aiinstance
->continents()[i
];
1345 continentFound
= true;
1346 for (uint j
=0; j
<continent
->outposts().size(); ++j
)
1348 COutpost
* outpost
= continent
->outposts()[j
];
1349 if (!outpost
|| outpostAlias
!=outpost
->getAlias())
1357 OUTPOST_WRN( "Instance not found" );
1358 if (!continentFound
)
1359 OUTPOST_WRN( "Continent not found" );
1361 OUTPOST_WRN( "Outpost %s not found", LigoConfig
.aliasToString( outpostAlias
).c_str() );
1366 void outpostCreateSquad(uint32 outpostAlias, uint32 dynGroupAlias, uint32 zoneAlias, uint32 spawnOrder)
1368 COutpost *outpost = COutpost::getOutpostByAlias( outpostAlias );
1370 outpost->createSquad(dynGroupAlias, zoneAlias, spawnOrder);
1373 void outpostSpawnSquad(uint32 outpostAlias, uint32 groupId)
1375 COutpost *outpost = COutpost::getOutpostByAlias( outpostAlias );
1377 outpost->spawnSquad(groupId);
1380 void outpostDespawnSquad(uint32 outpostAlias, uint32 groupId)
1382 COutpost *outpost = COutpost::getOutpostByAlias( outpostAlias );
1384 outpost->despawnSquad(groupId);
1387 void outpostDeleteSquad(uint32 outpostAlias, uint32 groupId)
1389 COutpost *outpost = COutpost::getOutpostByAlias( outpostAlias );
1391 outpost->deleteSquad(groupId);
1394 void outpostDespawnAllSquads(uint32 outpostAlias)
1396 COutpost *outpost = COutpost::getOutpostByAlias( outpostAlias );
1398 outpost->despawnAllSquads();
1402 NLMISC_COMMAND(outpostAliasSpawnSquad
, "Spawns a squad in an outpost (respawn time = 5 min)", "<outpost_alias> <group_alias> <spawn_zone_alias>")
1407 for (size_t i
=0; i
<3; ++i
)
1411 uint32 outpostAlias
= LigoConfig
.aliasFromString(args
[0]);
1412 uint32 dynGroupAlias
= LigoConfig
.aliasFromString(args
[1]);
1413 uint32 zoneAlias
= LigoConfig
.aliasFromString(args
[2]);
1414 string stateMachineName
= "default_squad_manager";
1416 COutpost
*outpost
= COutpost::getOutpostByAlias(outpostAlias
);
1418 outpost
->createSquad(dynGroupAlias
, zoneAlias
, 0, 5*60*10, OUTPOSTENUMS::UnknownPVPSide
);
1423 CBot
* COutpost::getBuildingBotByAlias(TAIAlias alias
)
1425 CGroup
* group
= getBuildingGroup();
1427 return group
->bots().getChildByAlias(alias
);
1432 NLMISC_COMMAND(outpostSetBuildingBotSheet
, "Set the sheet of an outpost building", "<outpost_alias> <building_alias> <bot_sheet>")
1437 for (size_t i
=0; i
<3; ++i
)
1441 uint32 outpostAlias
= LigoConfig
.aliasFromString(args
[0]);
1442 uint32 buildingAlias
= LigoConfig
.aliasFromString(args
[1]);
1443 NLMISC::CSheetId buildingBotSheet
= NLMISC::CSheetId(args
[2]);;
1445 COutpost
* outpost
= COutpost::getOutpostByAlias(outpostAlias
);
1447 outpost
->setBuildingBotSheet(buildingAlias
, buildingBotSheet
, true, "");
1453 // Call this macro, then do the code that will must done only if the outpost is found in this instance
1454 // The data you have access to after this macro:
1455 // - COutpost *outpost
1456 // - msgStruct params;
1457 #define IF_GET_OUTPOST_FOR_MSG( msgStruct ) \
1459 msgin.serial( params ); \
1460 COutpost *outpost = COutpost::getOutpostByAlias( params.Outpost ); \
1464 void cbOutpostCreateSquad( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1466 IF_GET_OUTPOST_FOR_MSG( COutpostCreateSquadMsg
)
1467 outpost
->createSquad(params
.Group
, params
.Zone
, params
.CreateOrder
, params
.RespawnTimeS
*10, params
.Side
);
1470 void cbOutpostSpawnSquad( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1472 IF_GET_OUTPOST_FOR_MSG( COutpostSpawnSquadMsg
)
1473 outpost
->spawnSquad(params
.GroupId
);
1476 void cbOutpostDespawnSquad( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1478 IF_GET_OUTPOST_FOR_MSG( COutpostDespawnSquadMsg
)
1479 outpost
->despawnSquad(params
.GroupId
);
1482 void cbOutpostDeleteSquad( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1484 IF_GET_OUTPOST_FOR_MSG( COutpostDeleteSquadMsg
)
1485 outpost
->deleteSquad(params
.GroupId
);
1488 void cbOutpostDespawnAllSquads( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1490 IF_GET_OUTPOST_FOR_MSG( COutpostDespawnAllSquadsMsg
)
1491 outpost
->despawnAllSquads();
1494 void cbOutpostSetOwner( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1496 IF_GET_OUTPOST_FOR_MSG( CSetOutpostOwner
)
1497 outpost
->setOwnerAlliance( params
.Owner
);
1500 void cbOutpostSetAttacker( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1502 IF_GET_OUTPOST_FOR_MSG( CSetOutpostAttacker
)
1503 outpost
->setAttackerAlliance( params
.Attacker
);
1506 void cbOutpostSetState( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1508 IF_GET_OUTPOST_FOR_MSG( COutpostSetStateMsg
)
1509 outpost
->setState( params
.State
);
1512 void cbOutpostEvent( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1514 IF_GET_OUTPOST_FOR_MSG( COutpostEventMsg
)
1515 outpost
->triggerSpecialEvent(params
.Event
);
1518 void cbOutpostSetBuildingBotSheet( NLNET::CMessage
& msgin
, const std::string
&serviceName
, NLNET::TServiceId serviceId
)
1520 IF_GET_OUTPOST_FOR_MSG( COutpostSetBuildingBotSheetMsg
)
1521 outpost
->setBuildingBotSheet(params
.Building
, params
.SheetId
, params
.AutoSpawnDespawn
, params
.CustomName
);
1525 #include "event_reaction_include.h"