1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 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_instance.h"
21 #include "ais_actions.h"
23 using namespace AITYPES
;
25 using namespace CAISActionEnums
;
28 extern CAIInstance
* currentInstance
;
30 DEFINE_ACTION(ContextGlobal
, SPIREMGR
)
32 nlassertex(currentInstance
!= NULL
, ("No AIInstance created !"));
33 CAIInstance
* aiInstance
= currentInstance
;
34 CWorkPtr::aiInstance(aiInstance
); // set the current AIInstance.
36 // get hold of the manager's slot id - note that managers are identified by slot and not by alias!
41 if (!getArgs(args
, name(), alias
, spireName
, mapName
, filename
))
44 string mgrName
= "spire_manager_"+spireName
;
46 // see whether the manager is already loaded
47 CManager
* mgr
= aiInstance
->managers().getChildByName(mgrName
);
49 // not found so look for a free slot
51 aiInstance
->newMgr(MgrTypeNpc
, 0, mgrName
, mapName
, filename
);
53 mgr
->registerForFile(filename
);
55 mgr
= aiInstance
->managers().getChildByName(mgrName
);
56 CMgrNpc
* mgrNpc
= dynamic_cast<CMgrNpc
*>(mgr
);
60 // setup the working manager pointer and exit
61 CWorkPtr::mgr(mgrNpc
);
62 CWorkPtr::eventReactionContainer(mgrNpc
->getStateMachine());
64 // set workptr state to this state
65 CContextStack::setContext(ContextNpcMgr
);
68 DEFINE_ACTION(ContextEventContainer
, SPIRSTAT
) // spire state
70 CStateMachine
* container
= CWorkPtr::eventReactionContainer();
76 if (!getArgs(args
, name(), alias
, spireName
))
79 string stateName
= "spire_state_"+spireName
;
81 CAIStatePositional
* state
= new CAIStatePositional(container
, alias
, stateName
);
82 container
->states().addAliasChild(state
);
83 // set workptr::state to this state
84 CWorkPtr::stateState(container
->states()[0]);
85 if (!CWorkPtr::stateState())
87 nlwarning("Failed to select state %s", LigoConfig
.aliasToString(alias
).c_str());
91 // set workptr state to this state
92 CContextStack::setContext(ContextPositionalState
);
95 DEFINE_ACTION(ContextNpcMgr
, SPIREGRP
)
97 CMgrNpc
* mgr
= CWorkPtr::mgrNpc();
103 if (!getArgs(args
, name(), alias
, spireName
))
106 string grpName
= "spire_group_"+spireName
;
108 CGroupNpc
* grp
= new CGroupNpc(mgr
, alias
, grpName
, RYAI_MAP_CRUNCH::Nothing
);
109 grp
->setAutoSpawn(false);
110 mgr
->groups().addChild(grp
);
112 if (!CWorkPtr::grpNpc())
114 nlwarning("Failed to select spire group %s as not found in manager: %s",
116 CWorkPtr::mgrNpc()->getName().c_str());
119 CStateMachine
* stateMachine
= CWorkPtr::eventReactionContainer();
121 grp
->setStartState(stateMachine
->cstStates()[0]);
123 CContextStack::setContext(ContextNpcGrp
);
126 DEFINE_ACTION(ContextNpcGrp
, SPIREBOT
)
128 CGroupNpc
* grp
= CWorkPtr::grpNpc();
134 if (!getArgs(args
, name(), alias
, spireName
))
137 string botName
= "spire_bot_"+spireName
;
139 CBotNpc
* bot
= new CBotNpc(grp
, alias
, botName
);
140 grp
->bots().addChild(bot
);
142 if (!CWorkPtr::botNpc())
144 nlwarning("Failed to select spire bot %s as not found in group: %s",
146 CWorkPtr::grpNpc()->getName().c_str());
150 if (bot
->getChat().isNull())
152 bot
->getChat()->add(bot
->getAIInstance(), "op:spire");
156 // set workptr state to this state
157 CContextStack::setContext(ContextNpcBot
);
160 DEFINE_ACTION(ContextNpcBot
, SPIRSHTS
)
162 CGroupNpc
* grp
= CWorkPtr::grpNpc();
166 CBotNpc
* bot
= CWorkPtr::botNpc();
170 FOREACHC(itArg
, std::vector
<CAIActions::CArg
>, args
)
172 string str
, name
, sheet
;
174 AI_SHARE::stringToKeywordAndTail(str
, name
, sheet
);
175 grp
->setStrLogicVar(NLMISC::CStringMapper::map("$sheet_spire_"+name
), sheet
);
184 #include "continent.h"
185 #include "ai_grp_npc.h"
186 #include "game_share/people.h"
187 #include "ai_profile_npc.h"
189 #include "continent_inline.h"
190 #include "dyn_grp_inline.h"
193 using namespace NLMISC
;
197 CFileDisplayer
SpireDisplayer("spires.log");
198 CLog
SpireDbgLog(CLog::LOG_DEBUG
), SpireInfLog(CLog::LOG_INFO
), SpireWrnLog(CLog::LOG_WARNING
), SpireErrLog(CLog::LOG_ERROR
);
201 namespace SPIREHELPERS
{
203 static std::map
<uint32
, uint32
> spireFactions
;
205 bool isAttackingFaction(uint32 factionIndex
, CAIEntityPhysical
const* player
)
207 std::map
<uint32
, uint32
>::const_iterator it
= spireFactions
.find(player
->spireAlias());
208 return it
!=spireFactions
.end() && it
->second
==factionIndex
;
213 //////////////////////////////////////////////////////////////////////////////
215 //////////////////////////////////////////////////////////////////////////////
217 //std::set<CContinent*> ChangedSpires;
218 //CSpire::TSpireIndex CSpire::_Spires;
220 CSpire::CSpire(CContinent
* owner
, uint32 alias
, std::string
const& name
, std::string
const& filename
)
221 : CAliasChild
<CContinent
>(owner
, alias
, name
)
222 , CAliasTreeRoot(filename
)
223 , _OwnerAllianceId(InvalidAllianceId
)
224 , _AttackerAllianceId(InvalidAllianceId
)
225 , _State(SPIREENUMS::UnknownSpireState
)
228 static bool logInitDone
= false;
231 SpireDbgLog
.addDisplayer( &SpireDisplayer
);
232 SpireInfLog
.addDisplayer( &SpireDisplayer
);
233 SpireWrnLog
.addDisplayer( &SpireDisplayer
);
237 SPIRE_DBG("Creating spire %s' (%s)", name
.c_str(), getAliasFullName().c_str());
239 SPIRE_DBG("Creating spire '%s'", getAliasFullName().c_str());
241 _SpireName
= getName();
242 CSpireManager
* manager
= NULL
;
243 // Create default squad manager
244 manager
= new CSpireSquadManager(this, 0, "default_squad_manager", filename
);
247 _Managers
.addChild(manager
);
250 // Create default building manager
251 manager
= new CSpireManager(this, 0, "default_building_manager", filename
);
254 _Managers
.addChild(manager
);
256 CGroupNpc
* group
= new CGroupNpc(manager
, NULL
, /*AStarFlag*/RYAI_MAP_CRUNCH::Nothing
);
259 manager
->groups().addAliasChild(group
);
260 group
->setAutoSpawn(false);
261 group
->setName("default_building_group");
262 group
->clearParameters();
263 group
->setPlayerAttackable(false);
264 group
->setBotAttackable(false);
265 group
->setBotsAreNamedFlag();
273 SPIRE_DBG("Deleting spire '%s'", getAliasFullName().c_str());
278 std::string
CSpire::getOneLineInfoString() const
280 return std::string("Spire '") + getName() + "' " + getAliasString() + ", State=" + SPIREENUMS::toString(_State
);
283 std::string
CSpire::getFullName() const
285 return std::string(getOwner()->getFullName() +":"+ getName());
288 std::string
CSpire::getIndexString() const
290 return getOwner()->getIndexString()+NLMISC::toString(":o%u", getChildIndex());
293 std::string CSpire::getPlaceOwnerFullName() const
295 return getFullName();
298 std::string CSpire::getPlaceOwnerIndexString() const
300 return getIndexString();
303 CAIInstance
* CSpire::getAIInstance() const
305 return getOwner()->getAIInstance();
308 std::string
CSpire::getManagerIndexString(CManager
const* manager
) const
310 return getIndexString()+NLMISC::toString(":m%u", manager
->getChildIndex());
313 IAliasCont
* CSpire::getAliasCont(TAIType type
)
317 case AITypeSpireSquadFamily
:
318 SPIRE_WRN( "Obsolete squad family node under spire %s", getName().c_str() );
320 case AITypeSpireSpawnZone
:
324 case AITypeSpireManager
:
326 case AITypeSpireBuilding
:
327 return getBuildingGroup()->getAliasCont(AITypeBot
);
334 CAliasTreeOwner
* CSpire::createChild(IAliasCont
* cont
, CAIAliasDescriptionNode
* aliasTree
)
339 CAliasTreeOwner
* child
= NULL
;
341 switch(aliasTree
->getType())
343 // create the child and adds it to the corresponding position.
344 case AITypeSpireSpawnZone
:
345 child
= new CSpireSpawnZone(this, aliasTree
);
348 child
= new CSpireSquadManager(this, aliasTree
->getAlias(), aliasTree
->getName());
350 case AITypeSpireManager
:
351 child
= new CSpireSquadManager(this, aliasTree
->getAlias(), aliasTree
->getName());
353 case AITypeSpireBuilding
:
354 return getBuildingGroup()->createChild(cont
, aliasTree
);
358 cont
->addAliasChild(child
);
362 CGroup
* CSpire::getBuildingGroup()
364 CSpireManager
* manager
= _Managers
.getChildByName("default_building_manager");
365 return manager
->groups().getChildByName("default_building_group");
368 void CSpire::setTribe(const std::string
&tribeName
)
370 // The tribe is only populated by the NPCs of the squads
373 SPIRE_DBG("setting tribe '%s' in '%s' as owner for spire '%s'",
375 getOwner()->getName().c_str(),
376 getAliasFullName().c_str());
379 void CSpire::setOwnerAlliance( TAllianceId ownerAllianceId
)
381 if (_OwnerAllianceId
!=ownerAllianceId
)
383 // if the old owner was a tribe
384 if (_OwnerAllianceId
==InvalidAllianceId
)
386 triggerSpecialEvent(SPIREENUMS::TribeOwnershipEnd
);
387 SPIREHELPERS::spireFactions
.erase(getAlias());
390 triggerSpecialEvent(SPIREENUMS::GuildOwnershipEnd
);
392 std::swap(_OwnerAllianceId
, ownerAllianceId
); // 'ownerAllianceId' contains old owner alliance id
393 if (_OwnerAllianceId
!=ownerAllianceId
)
395 triggerSpecialEvent(SPIREENUMS::OwnerChanged
);
396 // if the new owner is a tribe
397 if (_OwnerAllianceId
==InvalidAllianceId
)
399 SPIREHELPERS::spireFactions
.insert(make_pair(getAlias(), CStaticFames::getInstance().getFactionIndex(_Tribe
)));
400 triggerSpecialEvent(SPIREENUMS::TribeOwnershipBegin
);
403 triggerSpecialEvent(SPIREENUMS::GuildOwnershipBegin
);
407 void CSpire::setAttackerAlliance( TAllianceId attackerAllianceId
)
409 std::swap(_AttackerAllianceId
, attackerAllianceId
); // 'attackerAllianceId' contains old attacker alliance id
410 if (_AttackerAllianceId
!=attackerAllianceId
)
412 triggerSpecialEvent(SPIREENUMS::AttackerChanged
);
415 // Update the enemies of the current squads of the spire
416 FOREACH( im
, CAliasCont
<CSpireManager
>, _Managers
)
417 im
->setEnemies( _AttackerAllianceId
);
420 void CSpire::setState( SPIREENUMS::TSpireState state
)
424 if (_State
==SPIREENUMS::Peace
)
425 triggerSpecialEvent(SPIREENUMS::PeaceStateEnd
);
427 std::swap(_State
, state
); // 'state' contains old _State
430 triggerSpecialEvent(SPIREENUMS::StateChanged
);
431 if (_State
==SPIREENUMS::Peace
)
432 triggerSpecialEvent(SPIREENUMS::PeaceStateBegin
);
436 void CSpire::update()
438 // FOREACH(it, CAliasCont<CSpireSquadFamily>, _SquadFamilies) it->update();
439 // FOREACH(it, CAliasCont<CSpireSpawnZone>, _SpawnZones) it->update();
440 FOREACH(it
, CAliasCont
<CSpireManager
>, _Managers
) it
->update();
443 void CSpire::addZone(CSpireSpawnZone
* zone
)
446 if (_ZoneList
.find(NLMISC::CStringMapper::map(zone
->getName()))!=_ZoneList
.end())
447 SPIRE_WRN("this SpireSpawnZone have the same name than another: %s", zone
->getName().c_str());
449 _ZoneList
[NLMISC::CStringMapper::map(zone
->getName())] = zone
;
452 void CSpire::removeZone(CSpireSpawnZone
* zone
)
454 _ZoneList
.erase(NLMISC::CStringMapper::map(zone
->getName()));
457 CSpireSpawnZone
* CSpire::getZone(NLMISC::TStringId zoneName
)
459 return _ZoneList
[zoneName
];
462 void CSpire::serviceEvent(CServiceEvent
const& info
)
464 if (info
.getServiceName()=="EGS" && info
.getEventType()==CServiceEvent::SERVICE_DOWN
)
466 // Delete all the squad groups
467 CSpireManager
* manager
= _Managers
.getChildByName("default_squad_manager");
469 manager
->groups().clear();
471 FOREACH(itManager
, CAliasCont
<CSpireManager
>, _Managers
)
473 CSpireManager
* manager
= *itManager
;
474 manager
->serviceEvent(info
);
480 // Spawn spire managers
481 CCont
<CSpireManager
>::iterator itManager
, itManagerEnd(_Managers
.end());
482 for (itManager
=_Managers
.begin(); itManager
!=itManagerEnd
; ++itManager
)
484 CSpireManager
* manager
= *itManager
;
487 // We should check individual errors, but fake success here :)
491 bool CSpire::despawn()
493 // Despawn instance managers
494 CCont
<CSpireManager
>::iterator itManager
, itManagerEnd(_Managers
.end());
495 for (itManager
=_Managers
.begin(); itManager
!=itManagerEnd
; ++itManager
)
497 CSpireManager
* manager
= *itManager
;
498 manager
->despawnMgr();
500 // We should check individual errors, but fake success here :)
504 //-----------------------------------------------------------------------------
505 std::string
CSpire::getStateName() const
507 return SPIREENUMS::toString(_State
);
510 //////////////////////////////////////////////////////////////////////////////
511 // CSpireSquadFamily //
512 //////////////////////////////////////////////////////////////////////////////
514 IAliasCont
* CSpireSquadFamily::getAliasCont(TAIType type
)
518 case AITypeGroupTemplate
:
519 case AITypeGroupTemplateMultiLevel
:
527 CAliasTreeOwner
* CSpireSquadFamily::createChild(IAliasCont
* cont
, CAIAliasDescriptionNode
* aliasTree
)
532 CAliasTreeOwner
* child
= NULL
;
534 switch (aliasTree
->getType())
536 case AITypeSquadTemplateVariant
:
537 child
= new CGroupDesc
<CSpireSquadFamily
>(this, aliasTree
->getAlias(), aliasTree
->getParent()->getName()+":"+aliasTree
->getName());
539 case AITypeGroupTemplate
:
540 case AITypeGroupTemplateMultiLevel
:
541 child
= new CGroupDesc
<CSpireSquadFamily
>(this, aliasTree
->getAlias(), aliasTree
->getName());
546 cont
->addAliasChild(child
);
550 std::string
CSpireSquadFamily::getFullName() const
552 // return std::string(getOwner()->getFullName() +":"+ getName());
556 std::string
CSpireSquadFamily::getIndexString() const
558 return getOwner()->getIndexString()+NLMISC::toString(":sf%u", getChildIndex());
561 //////////////////////////////////////////////////////////////////////////////
563 //////////////////////////////////////////////////////////////////////////////
565 template <> size_t const CGroupDesc
<CSpireSquadFamily
>::_MultiLevelSheetCount
= 20;
567 //////////////////////////////////////////////////////////////////////////////
569 //////////////////////////////////////////////////////////////////////////////
571 template <> size_t const CBotDesc
<CSpireSquadFamily
>::_MultiLevelSheetCount
= 20;
573 //////////////////////////////////////////////////////////////////////////////
574 // CSpireSpawnZone //
575 //////////////////////////////////////////////////////////////////////////////
577 CSpireSpawnZone::CSpireSpawnZone(CSpire
* owner
, CAIAliasDescriptionNode
* adn
)
578 : CAIPlaceXYR(owner
, adn
)
580 owner
->addZone(this);
583 CSpireSpawnZone::~CSpireSpawnZone()
585 static_cast<CSpire
*>(getOwner())->removeZone(this);
588 std::string
CSpireSpawnZone::getFullName() const
590 return std::string(getOwner()->getFullName() +":"+ getName());
593 std::string
CSpireSpawnZone::getIndexString() const
595 return getOwner()->getIndexString()+NLMISC::toString(":%u", getChildIndex());
598 //////////////////////////////////////////////////////////////////////////////
600 //////////////////////////////////////////////////////////////////////////////
602 CSpireManager::CSpireManager(CSpire
* parent
, uint32 alias
, std::string
const& name
, std::string
const& filename
)
603 : CMgrNpc(parent
, alias
, name
, filename
)
609 CSpireManager::~CSpireManager()
611 unregisterEvents(); // need be called otherwise the state manager will be unhappy when the CAIEvent objects are destroyed
614 std::string
CSpireManager::getOneLineInfoString() const
616 return std::string("Spire manager '") + getName() + "'";
619 void CSpireManager::update()
624 IAliasCont
* CSpireManager::getAliasCont(TAIType type
)
626 // IAliasCont* cont = NULL;
635 return CMgrNpc::getAliasCont(type
);
638 CAliasTreeOwner
* CSpireManager::createChild(IAliasCont
* cont
, CAIAliasDescriptionNode
* aliasTree
)
640 // CAliasTreeOwner* child = NULL;
641 // switch (aliasTree->getType())
647 // cont->addAliasChild(child);
651 return CMgrNpc::createChild(cont
, aliasTree
);
654 void CSpireManager::registerEvents()
656 _StateMachine
.addEvent( "spire_peace_state_begin", EventSpirePeaceStateBegin
);
657 _StateMachine
.addEvent( "spire_peace_state_end", EventSpirePeaceStateEnd
);
658 _StateMachine
.addEvent( "spire_tribe_ownership_begin", EventSpireTribeOwnershipBegin
);
659 _StateMachine
.addEvent( "spire_tribe_ownership_end", EventSpireTribeOwnershipEnd
);
660 _StateMachine
.addEvent( "spire_guild_ownership_begin", EventSpireGuildOwnershipBegin
);
661 _StateMachine
.addEvent( "spire_guild_ownership_end", EventSpireGuildOwnershipEnd
);
662 _StateMachine
.addEvent( "spire_owner_changed", EventSpireOwnerChanged
);
663 _StateMachine
.addEvent( "spire_attacker_changed", EventSpireAttackerChanged
);
664 _StateMachine
.addEvent( "spire_state_changed", EventSpireStateChanged
);
667 void CSpireManager::unregisterEvents()
669 _StateMachine
.delEvent( "spire_peace_state_begin" );
670 _StateMachine
.delEvent( "spire_peace_state_end" );
671 _StateMachine
.delEvent( "spire_tribe_ownership_begin" );
672 _StateMachine
.delEvent( "spire_tribe_ownership_end" );
673 _StateMachine
.delEvent( "spire_guild_ownership_begin" );
674 _StateMachine
.delEvent( "spire_guild_ownership_end" );
675 _StateMachine
.delEvent( "spire_owner_changed" );
676 _StateMachine
.delEvent( "spire_attacker_changed" );
677 _StateMachine
.delEvent( "spire_state_changed" );
680 void CSpireManager::autoSpawnBegin()
684 FOREACH(itGroup
, CCont
<CGroup
>, groups())
686 CGroupNpc
* group
= static_cast<CGroupNpc
*>(*itGroup
);
689 CSpawnGroupNpc
* spawn
= group
->getSpawnObj();
696 void CSpireManager::autoSpawnEnd()
700 FOREACH(itGroup
, CCont
<CGroup
>, groups())
702 CGroupNpc
* group
= static_cast<CGroupNpc
*>(*itGroup
);
705 CSpawnGroupNpc
* spawn
= group
->getSpawnObj();
707 spawn
->despawnBots(1);
712 void CSpireManager::setEnemies( TAllianceId attackerAllianceId
)
714 FOREACH( ig
, CAliasCont
<CGroup
>, _Groups
)
716 // Attack only the declared ennemies of the spire
717 CGroupNpc
*grp
= static_cast<CGroupNpc
*>(*ig
);
718 grp
->ennemyFaction().clearExtra();
719 grp
->ennemyFaction().addExtraProperty(attackerAllianceId
);
723 //////////////////////////////////////////////////////////////////////////////
724 // CSpireSquadManager //
725 //////////////////////////////////////////////////////////////////////////////
727 CSpireSquadManager::CSpireSquadManager(CSpire
* parent
, uint32 alias
, std::string
const& name
, std::string
const& filename
)
728 : CSpireManager(parent
, alias
, name
, filename
)
731 CAIState
* state
= new CAIStatePositional(getStateMachine(), 0, "spire_squad_init");
732 IAIProfileFactory
* aiProfile
= lookupAIGrpProfile("squad");
733 state
->setActivityProfile(aiProfile
);
734 getStateMachine()->states().addChild(state
);
736 CAIEventDescription eventDescription
;
737 CAIEventActionNode::TSmartPtr eventAction
;
738 CAIEventReaction
* event
;
740 // Create event handler for start of state
741 eventDescription
.EventType
= "start_of_state";
742 // eventDescription.StateKeywords.push_back("");
743 // eventDescription.NamedStates.push_back("");
744 // eventDescription.GroupKeywords.push_back("");
745 // eventDescription.NamedGroups.push_back("");
747 // Create event action
748 eventAction
= new CAIEventActionNode
;
749 eventAction
->Action
= "code";
750 eventAction
->Weight
= 1;
751 eventAction
->Args
.push_back("print(\"CREATING A SQUAD\");");
752 // eventAction->Args.push_back("()setFactionProp(\"faction\", \"foo\");");
753 // eventAction->Args.push_back("()setFactionProp(\"ennemyFaction\", \"bar\");");
754 // eventAction->Args.push_back("()setFactionProp(\"friendFaction\", \"baf\");");
755 eventAction
->Args
.push_back("()setHealer(1);");
757 // Register event action
758 eventDescription
.Action
= eventAction
;
761 // Register event handler
762 // FIXME: 0 == CAIAliasDescriptionNode instance
763 event
= new CAIEventReaction(getStateMachine(), 0, eventDescription
.EventType
);
764 event
->processEventDescription(&eventDescription
, getStateMachine());
765 getStateMachine()->eventReactions().addChild(event
);
768 // Create event handler for group death
769 eventDescription
.EventType
= "group_eliminated";
770 // eventDescription.StateKeywords.push_back("");
771 // eventDescription.NamedStates.push_back("");
772 // eventDescription.GroupKeywords.push_back("");
773 // eventDescription.NamedGroups.push_back("");
775 // Create event action
776 eventAction
= new CAIEventActionNode
;
777 eventAction
->Action
= "spire_report_squad_death";
778 eventAction
->Weight
= 1;
779 // eventAction->Args.push_back("");
781 // Register event action
782 eventDescription
.Action
= eventAction
;
785 // Register event handler
786 // FIXME: 0 == CAIAliasDescriptionNode instance
787 event
= new CAIEventReaction(getStateMachine(), 0, eventDescription
.EventType
);
788 event
->processEventDescription(&eventDescription
, getStateMachine());
789 getStateMachine()->eventReactions().addChild(event
);
792 // Create event handler for bot death
793 eventDescription
.EventType
= "bot_killed";
794 // eventDescription.StateKeywords.push_back("");
795 // eventDescription.NamedStates.push_back("");
796 // eventDescription.GroupKeywords.push_back("");
797 // eventDescription.NamedGroups.push_back("");
799 // Create event action
800 eventAction
= new CAIEventActionNode
;
801 eventAction
->Action
= "spire_send_squad_status";
802 eventAction
->Weight
= 1;
803 // eventAction->Args.push_back("");
805 // Register event action
806 eventDescription
.Action
= eventAction
;
809 // Register event handler
810 // FIXME: 0 == CAIAliasDescriptionNode instance
811 event
= new CAIEventReaction(getStateMachine(), 0, eventDescription
.EventType
);
812 event
->processEventDescription(&eventDescription
, getStateMachine());
813 getStateMachine()->eventReactions().addChild(event
);
816 // Create event handler for bot death
817 eventDescription
.EventType
= "squad_leader_killed";
818 // eventDescription.StateKeywords.push_back("");
819 // eventDescription.NamedStates.push_back("");
820 // eventDescription.GroupKeywords.push_back("");
821 // eventDescription.NamedGroups.push_back("");
823 // Create event action
824 eventAction
= new CAIEventActionNode
;
825 eventAction
->Action
= "multi_actions";
826 eventAction
->Weight
= 1;
827 eventAction
->Children
.resize(2);
828 eventAction
->Children
[0] = new CAIEventActionNode
;
829 eventAction
->Children
[0]->Action
= "spire_report_squad_leader_death";
830 eventAction
->Children
[0]->Weight
= 1;
831 // eventAction->Children[0]->Args.push_back("");
832 eventAction
->Children
[1] = new CAIEventActionNode
;
833 eventAction
->Children
[1]->Action
= "code";
834 eventAction
->Children
[1]->Weight
= 1;
835 eventAction
->Children
[1]->Args
.push_back("()setAutoSpawn(0);");
837 eventAction
->Children
[1]->Args
.push_back("print(\"INFINITE RESPAWN TIME FOR SQUAD\");");
840 // Register event action
841 eventDescription
.Action
= eventAction
;
844 // Register event handler
845 // FIXME: 0 == CAIAliasDescriptionNode instance
846 event
= new CAIEventReaction(getStateMachine(), 0, eventDescription
.EventType
);
847 event
->processEventDescription(&eventDescription
, getStateMachine());
848 getStateMachine()->eventReactions().addChild(event
);
852 //////////////////////////////////////////////////////////////////////////////
853 //////////////////////////////////////////////////////////////////////////////
854 //////////////////////////////////////////////////////////////////////////////
856 void CSpire::createSquad(string
const& dynGroupName
, string
const& stateMachineName
, string
const& initialStateName
, string
const& zoneName
, uint32 spawnOrder
, uint32 respawTimeGC
, SPIREENUMS::TPVPSide side
)
858 IManagerParent
* const managerParent
= getOwner()->getOwner();
859 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
863 CSpireSpawnZone
const* spawnZone
= getZone(CStringMapper::map(zoneName
));
866 SPIRE_WRN("newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s", stateMachineName
.c_str());
870 CGroupDesc
<CSpireSquadFamily
> const* groupDesc
= NULL
;
872 FOREACH(itGroupDesc
, CSquadLinks
, _SquadLinks
)
874 if ((*itGroupDesc
).second
->getName()==dynGroupName
)
876 groupDesc
= (*itGroupDesc
).second
;
883 SPIRE_WRN("createSquad failed: No Group Found");
887 // Find the state machine as a manager
888 CManager
* manager
= NULL
;
889 FOREACH(itCont
, CCont
<CManager
>, aiInstance
->managers())
891 if (itCont
->getName()==stateMachineName
)
899 FOREACH(itCont
, CCont
<CSpireManager
>, managers())
901 if (itCont
->getName()==stateMachineName
)
910 SPIRE_WRN("createSquad failed : Unknown stateMachine %s", stateMachineName
.c_str());
913 // Find the state machine as a npc manager
914 CSpireSquadManager
* spireManager
= dynamic_cast<CSpireSquadManager
*>(manager
);
917 SPIRE_WRN("createSquad failed : Not an spire state machine !: ", stateMachineName
.c_str());
920 createSquad(groupDesc
, spireManager
, initialStateName
, spawnZone
, spawnOrder
, respawTimeGC
, side
);
923 void CSpire::createSquad(uint32 dynGroupAlias
, uint32 zoneAlias
, uint32 spawnOrder
, uint32 respawTimeGC
, SPIREENUMS::TPVPSide side
)
925 IManagerParent
* const managerParent
= getOwner()->getOwner();
926 CAIInstance
* const aiInstance
= dynamic_cast<CAIInstance
*>(managerParent
);
930 CSpireSpawnZone
const* spawnZone
= spawnZones().getChildByAlias(zoneAlias
);
933 SPIRE_WRN("createSquad failed: spawn zone %s not found", LigoConfig
.aliasToString(zoneAlias
).c_str());
937 CGroupDesc
<CSpireSquadFamily
> const* groupDesc
= NULL
;
939 // Find the group template.
940 // :TODO: Replace it with a faster map access.
941 groupDesc
= getSquad( dynGroupAlias
);
944 SPIRE_WRN("createSquad failed: group %s not found", LigoConfig
.aliasToString(dynGroupAlias
).c_str());
948 // Find the state machine as a manager
949 CSpireSquadManager
* manager
= dynamic_cast<CSpireSquadManager
*>(managers().getChildByName("default_squad_manager"));
952 SPIRE_WRN("createSquad failed: default state machine not found! (<- this is a code bug)");
955 createSquad(groupDesc
, manager
, "", spawnZone
, spawnOrder
, respawTimeGC
, side
);
958 void CSpire::createSquad(CGroupDesc
<CSpireSquadFamily
> const* groupDesc
, CSpireSquadManager
* manager
, string
const& initialStateName
, CSpireSpawnZone
const* spawnZone
, uint32 createOrder
, uint32 respawTimeGC
, SPIREENUMS::TPVPSide side
)
960 SPIRE_DBG("Creating a squad");
961 CAIVector
const& spawnPosition
= spawnZone
->midPos();
962 sint32 baseLevel
= -1;
963 double dispersionRadius
= spawnZone
->getRadius();
964 // Save the creator state
965 bool const savePlayerAttackable
= groupDesc
->getGDPlayerAttackable();
966 bool const saveBotAttackable
= groupDesc
->getGDBotAttackable();
967 // PlayerAttackable must be false as it it sent to the EGS in BotDescriptionMessage to set the
968 // property 'Attackable'. Squads are not attackable unless a player is in war with the owner of
969 // the spire (using botchatprogram instead of the property 'Attackable').
970 // BotAttackable must be true, otherwise the EGS sets it as invulnerable (not attackable).
971 groupDesc
->setGDPlayerAttackable(false);
972 groupDesc
->setGDBotAttackable(true);
974 CGroupNpc
* const grp
= groupDesc
->createNpcGroup(manager
, spawnPosition
, dispersionRadius
, baseLevel
, false);
975 // Restore the creator state
976 groupDesc
->setGDPlayerAttackable(savePlayerAttackable
);
977 groupDesc
->setGDBotAttackable(saveBotAttackable
);
978 // Verify that the group was created
981 SPIRE_WRN("createSquad failed: group %s cannot spawn", LigoConfig
.aliasToString(groupDesc
->getAlias()).c_str());
984 // Set the new group parameters
985 // Let the EGS destroys squads explicitely because when a group is destroyed in the AIS its groupId can be reused
986 // and 2 squads would have the same groupId in the EGS (it asserts)
987 grp
->autoDestroy(false);
988 grp
->setAutoSpawn(true);
989 // grp->getPersistentStateInstance()->setParentStateInstance(entity->getPersistentStateInstance());
990 grp
->initDynGrp(groupDesc
, NULL
);
992 uint8 color
= (uint8
)(grp
->getChildIndex() % 8);
993 grp
->setColour(color
);
994 // Get the state machine
995 CStateMachine
const* stateMachine
= manager
->getStateMachine();
997 // Verify that we have a state in the state machine
998 if (stateMachine
->cstStates().size()==0)
999 nlerror("no state defined for StateMachine in Manager %s", manager
->getFullName().c_str());
1001 // Set the group in that state
1002 CAIState
* initialState
= NULL
;
1003 if (!initialStateName
.empty())
1005 // FOREACH(itState, CCont<CAIState>, stateMachine->states())
1006 for (size_t i
=0; i
<stateMachine
->cstStates().size(); ++i
)
1008 CAIState
* state
= stateMachine
->cstStates()[i
];
1009 if (state
->getName()==initialStateName
)
1010 initialState
= state
;
1013 if (initialState
==NULL
)
1014 initialState
= stateMachine
->cstStates()[0]; // sets the first state (must exist!).
1015 grp
->setStartState(initialState
);
1017 // Do not assist friends because it would lead to exploits
1018 /*if ( _OwnerGuild != InvalidGuildId )
1020 //grp->faction().addExtraProperty(_OwnerGuild); // TODO: set the GuildId for the squad npcs?
1021 //grp->friendFaction().addExtraProperty(_OwnerGuild); // will be defended by the squad
1025 // A tribe owns the spire and all players are ennemies
1026 // CPropertyId tribeFaction(CGrpProfileFaction::fameFactionToScriptFaction(_OwnerTribe));
1027 //grp->faction().addProperty(tribeFaction);
1028 //grp->friendFaction().addProperty(tribeFaction); // will be defended by the squad
1029 //grp->ennemyFaction().addProperty(CPropertyId("Player"));
1032 // Set guild id of members of the squad (for the tribe case, these *are* the tribe as well)
1033 // This was removed because CBotNpc::spawn() now uses getOwner()->getOwner()->getOwner() to access the outpsot
1034 /*FOREACH(ib, CAliasCont<CBot>, grp->bots())
1036 CBotNpc *bot = static_cast<CBotNpc*>(*ib);
1037 bot->setOwnerSpire(this);
1040 grp
->setSpireSide(side
);
1041 // Attack only the declared ennemies of the spire
1042 if (side
==SPIREENUMS::SpireOwner
)
1044 // grp->faction ().addProperty(NLMISC::toString("spire:%s:defender", getAliasString().c_str()));
1045 // grp->friendFaction().addProperty(NLMISC::toString("spire:%s:defender", getAliasString().c_str()));
1046 grp
->ennemyFaction().addProperty(NLMISC::toString("spire:%s:attacker", getAliasString().c_str()));
1048 if (side
==SPIREENUMS::SpireAttacker
)
1050 // grp->faction ().addProperty(NLMISC::toString("spire:%s:attacker", getAliasString().c_str()));
1051 // grp->friendFaction().addProperty(NLMISC::toString("spire:%s:attacker", getAliasString().c_str()));
1052 grp
->ennemyFaction().addProperty(NLMISC::toString("spire:%s:defender", getAliasString().c_str()));
1054 grp
->_AggroRange
= 25;
1055 grp
->_UpdateNbTicks
= 10;
1056 grp
->respawnTime() = respawTimeGC
;
1058 grp
->updateStateInstance(); // Directly call his first state (to retrieve associated params).
1062 CSpireSquadCreatedMsg params
;
1063 params
.Spire
= this->getAlias();
1064 params
.CreateOrder
= createOrder
;
1065 params
.GroupId
= reinterpret_cast<uint32
>(grp
);
1066 sendSpireMessage("SPIRE_SQUAD_CREATED", params
);
1069 SPIRE_DBG( "Spire %s: squad created defending 0x%x against 0x%x, respawnTime=%u gc", getName().c_str(), _OwnerAllianceId
, _AttackerAllianceId
, respawTimeGC
);
1072 void CSpire::spawnSquad(uint32 groupId
)
1074 SPIRE_DBG( "Spire %s: Spawning squad 0x%08x", getName().c_str(), groupId
);
1075 FOREACH(itManager
, CAliasCont
<CSpireManager
>, _Managers
)
1077 CSpireManager
* manager
= *itManager
;
1078 FOREACH(itGroup
, CAliasCont
<CGroup
>, manager
->groups())
1080 CGroup
* group
= *itGroup
;
1081 CGroupNpc
* groupNpc
= static_cast<CGroupNpc
*>(group
);
1082 uint32 thisGroupId
= reinterpret_cast<uint32
>(groupNpc
);
1083 if (groupId
==thisGroupId
)
1085 group
->getSpawnObj()->spawnBots();
1086 CSpireSquadSpawnedMsg params
;
1087 params
.Spire
= this->getAlias();
1088 params
.GroupId
= groupId
;
1089 sendSpireMessage("SPIRE_SQUAD_SPAWNED", params
);
1090 SPIRE_DBG( "\t\tSpawned" );
1095 SPIRE_WRN("No squad to spawn with group id 0x%08x. Valid group ids are:", groupId
);
1096 FOREACH(itManager
, CAliasCont
<CSpireManager
>, _Managers
)
1098 CSpireManager
* manager
= *itManager
;
1099 FOREACH(itGroup
, CAliasCont
<CGroup
>, manager
->groups())
1101 CGroup
* group
= *itGroup
;
1102 CGroupNpc
* groupNpc
= static_cast<CGroupNpc
*>(group
);
1103 uint32 thisGroupId
= reinterpret_cast<uint32
>(groupNpc
);
1104 SPIRE_WRN("- 0x%08x", thisGroupId
);
1109 void CSpire::despawnSquad(uint32 groupId
)
1111 SPIRE_DBG( "Spire %s: Despawning squad 0x%08x", getName().c_str(), groupId
);
1112 FOREACH(itManager
, CAliasCont
<CSpireManager
>, _Managers
)
1114 CSpireManager
* manager
= *itManager
;
1115 FOREACH(itGroup
, CAliasCont
<CGroup
>, manager
->groups())
1117 CGroup
* group
= *itGroup
;
1118 CGroupNpc
* groupNpc
= static_cast<CGroupNpc
*>(group
);
1119 uint32 thisGroupId
= reinterpret_cast<uint32
>(groupNpc
);
1120 if (groupId
==thisGroupId
)
1122 group
->despawnBots();
1123 CSpireSquadDespawnedMsg params
;
1124 params
.Spire
= this->getAlias();
1125 params
.GroupId
= groupId
;
1126 sendSpireMessage("SPIRE_SQUAD_DESPAWNED", params
);
1131 SPIRE_WRN("No squad to despawn");
1134 void CSpire::deleteSquad(uint32 groupId
)
1136 SPIRE_DBG( "Spire %s: deleting squad 0x%08x", getName().c_str(), groupId
);
1137 FOREACH(itManager
, CAliasCont
<CSpireManager
>, _Managers
)
1139 CSpireManager
* manager
= *itManager
;
1140 FOREACH(itGroup
, CAliasCont
<CGroup
>, manager
->groups())
1142 CGroup
* group
= *itGroup
;
1143 CGroupNpc
* groupNpc
= static_cast<CGroupNpc
*>(group
);
1144 uint32 thisGroupId
= reinterpret_cast<uint32
>(groupNpc
);
1145 if (groupId
==thisGroupId
)
1147 manager
->groups().removeChildByIndex(group
->getChildIndex());
1148 // No message here since this is called by squad destructor in EGS
1153 SPIRE_WRN("No squad to delete");
1156 void CSpire::sendSpireSquadStatus(CGroupNpc
* group
)
1158 uint32 alias
= this->getAlias();
1159 uint32 groupId
= reinterpret_cast<uint32
>(group
);
1160 bool groupAlive
= false;
1161 bool leaderAlive
= group
->getSquadLeader()!=NULL
;
1162 uint32 botCount
= 0;
1163 // Persistent status
1164 // Spawn dependent status
1165 CSpawnGroup
* spawnGroup
= group
->getSpawnObj();
1168 groupAlive
= spawnGroup
->isGroupAlive();
1170 NLNET::CMessage
msgout("SPIRE_SQUAD_STATUS");
1171 msgout
.serial(alias
);
1172 msgout
.serial(groupId
);
1173 msgout
.serial(groupAlive
);
1174 msgout
.serial(leaderAlive
);
1175 msgout
.serial(botCount
);
1176 sendMessageViaMirror("EGS", msgout
);
1179 void CSpire::squadLeaderDied(CGroupNpc
* group
)
1181 uint32 alias
= this->getAlias();
1182 uint32 groupId
= reinterpret_cast<uint32
>(group
);
1183 NLNET::CMessage
msgout("SPIRE_SQUAD_LEADER_DIED");
1184 msgout
.serial(alias
);
1185 msgout
.serial(groupId
);
1186 sendMessageViaMirror("EGS", msgout
);
1189 void CSpire::squadDied(CGroupNpc
* group
)
1191 uint32 alias
= this->getAlias();
1192 uint32 groupId
= reinterpret_cast<uint32
>(group
);
1193 NLNET::CMessage
msgout("SPIRE_SQUAD_DIED");
1194 msgout
.serial(alias
);
1195 msgout
.serial(groupId
);
1196 sendMessageViaMirror("EGS", msgout
);
1199 void CSpire::triggerSpecialEvent(SPIREENUMS::TSpecialSpireEvent eventId
)
1201 // Managers handlers
1202 FOREACH(itManager
, CCont
<CSpireManager
>, _Managers
)
1204 CSpireManager
* manager
= *itManager
;
1207 CAIEvent
* event
= NULL
;
1210 case SPIREENUMS::PeaceStateBegin
: event
= &manager
->EventSpirePeaceStateBegin
; break;
1211 case SPIREENUMS::PeaceStateEnd
: event
= &manager
->EventSpirePeaceStateEnd
; break;
1212 case SPIREENUMS::TribeOwnershipBegin
: event
= &manager
->EventSpireTribeOwnershipBegin
; break;
1213 case SPIREENUMS::TribeOwnershipEnd
: event
= &manager
->EventSpireTribeOwnershipEnd
; break;
1214 case SPIREENUMS::GuildOwnershipBegin
: event
= &manager
->EventSpireGuildOwnershipBegin
; break;
1215 case SPIREENUMS::GuildOwnershipEnd
: event
= &manager
->EventSpireGuildOwnershipEnd
; break;
1216 case SPIREENUMS::OwnerChanged
: event
= &manager
->EventSpireOwnerChanged
; break;
1217 case SPIREENUMS::AttackerChanged
: event
= &manager
->EventSpireAttackerChanged
; break;
1218 case SPIREENUMS::StateChanged
: event
= &manager
->EventSpireStateChanged
; break;
1222 FOREACH(itGroup
, CCont
<CGroup
>, manager
->groups())
1224 CGroupNpc
* group
= static_cast<CGroupNpc
*>(*itGroup
);
1226 group
->processStateEvent(*event
);
1234 case SPIREENUMS::TribeOwnershipBegin
:
1236 FOREACH(itManager
, CCont
<CSpireManager
>, _Managers
)
1238 CSpireManager
* manager
= *itManager
;
1240 manager
->autoSpawnBegin();
1244 case SPIREENUMS::TribeOwnershipEnd
:
1246 FOREACH(itManager
, CCont
<CSpireManager
>, _Managers
)
1248 CSpireManager
* manager
= *itManager
;
1250 manager
->autoSpawnEnd();
1257 void CSpire::setBuildingBotSheet(uint32 buildingAlias
, NLMISC::CSheetId sheetId
, bool autoSpawnDespawn
, const std::string
& customName
)
1259 CBot
* bot
= getBuildingBotByAlias(buildingAlias
);
1262 SPIRE_WRN( "cannot find building bot %s", LigoConfig
.aliasToString( buildingAlias
).c_str() );
1266 AISHEETS::ICreatureCPtr
const sheet
= AISHEETS::CSheets::getInstance()->lookup(sheetId
);
1267 if (sheetId
!=NLMISC::CSheetId::Unknown
&& !sheet
.isNull())
1269 bot
->setCustomName(customName
);
1270 bot
->triggerSetSheet(sheet
);
1271 if (autoSpawnDespawn
&& !bot
->isSpawned())
1276 if (autoSpawnDespawn
&& bot
->isSpawned())
1281 void CSpire::despawnAllSquads()
1283 FOREACH(itManager
, CAliasCont
<CSpireManager
>, _Managers
)
1285 CSpireManager
* manager
= *itManager
;
1286 CSpireSquadManager
* sqManager
= dynamic_cast<CSpireSquadManager
*>(manager
);
1289 FOREACH(itGroup
, CAliasCont
<CGroup
>, sqManager
->groups())
1291 CGroup
* group
= *itGroup
;
1292 group
->despawnBots();
1299 void CSpire::sendSpireMessage(std::string
const& msgName
, T
& paramStruct
)
1301 NLNET::CMessage
msgout(msgName
);
1302 msgout
.serial(paramStruct
);
1303 sendMessageViaMirror(std::string("EGS"), msgout
);
1306 //////////////////////////////////////////////////////////////////////////////
1308 //////////////////////////////////////////////////////////////////////////////
1310 NLMISC_COMMAND(displaySpires
, "list the available spire", "")
1312 if (args
.size() > 0)
1315 uint32 instanceNumber
= std::numeric_limits
<uint32
>::max();
1316 for (uint i
=0; i
<CAIS::instance().AIList().size(); ++i
)
1318 CAIInstance
*const aii
= CAIS::instance().AIList()[i
];
1321 log
.displayNL("No current ai instance, can't look for spire");
1325 string continentName
;
1327 continentName
= args
[0];
1329 // retreive the oupost
1330 for (uint i
=0; i
<aii
->continents().size(); ++i
)
1332 CContinent
*const continent
= aii
->continents()[i
];
1334 || ( !continentName
.empty()
1335 && continentName
!=continent
->getName()))
1338 log
.displayNL("Spires in continent '%s':", continent
->getName().c_str());
1339 for (uint j
=0; j
<continent
->spires().size(); ++j
)
1341 CSpire
const* spire
= continent
->spires()[j
];
1345 log
.displayNL(" %s", spire
->getOneLineInfoString().c_str());
1346 log
.displayNL(" - %d group descs", spire
->squadLinks().size());
1347 for (CSpire::CSquadLinks::const_iterator isl
=spire
->squadLinks().begin(); isl
!=spire
->squadLinks().end(); ++isl
)
1349 CGroupDesc
<CSpireSquadFamily
> const* gd
= (*isl
).second
;
1353 log
.displayNL(" Group desc '%s' %s", gd
->getName().c_str(), gd
->getAliasString().c_str());
1356 log
.displayNL(" - %d spawn zones", spire
->spawnZones().size());
1357 for (uint j
=0; j
<spire
->spawnZones().size(); ++j
)
1359 CSpireSpawnZone
const* sz
= spire
->spawnZones()[j
];
1363 log
.displayNL(" SpawnZone '%s' %s (%s)", sz
->getName().c_str(), sz
->getAliasString().c_str(), sz
->midPos().toString().c_str());
1365 log
.displayNL(" - %d state machines", spire
->managers().size());
1366 for (uint j
=0; j
<spire
->managers().size(); ++j
)
1368 CSpireManager
* manager
= spire
->managers()[j
];
1372 log
.displayNL(" State machine '%s' %s", manager
->getName().c_str(), manager
->getAliasString().c_str());
1373 log
.displayNL(" - %d states", manager
->getStateMachine()->states().size());
1374 for (uint j
=0; j
<manager
->getStateMachine()->states().size(); ++j
)
1376 CAIState
const* state
= manager
->getStateMachine()->states()[j
];
1380 log
.displayNL(" State '%s' %s", state
->getName().c_str(), state
->getAliasString().c_str());
1382 log
.displayNL(" - %d groups", manager
->groups().size());
1383 for (uint j
=0; j
<manager
->groups().size(); ++j
)
1385 CGroup
const* group
= manager
->groups()[j
];
1388 log
.displayNL(" Group '%s' %s", group
->getName().c_str(), group
->getAliasString().c_str());
1389 log
.displayNL(" - %d bots", group
->bots().size());
1390 for (uint k
=0; k
<group
->bots().size(); ++k
)
1392 CBot
const* bot
= group
->bots()[k
];
1394 log
.displayNL(" Bot '%s' %s", bot
->getName().c_str(), bot
->getAliasString().c_str());
1396 log
.displayNL(" Bot <NULL>");
1400 log
.displayNL(" Group <NULL>");
1410 // spireSpawnSquad 1 fyros spire group machine zone
1412 NLMISC_COMMAND(spireSpawnSquad
, "Spawns a squad in an spire", "<instance_number> <continent> <spire> <group_template> <state_machine> <spawn_zone> [<respawnTimeInSec>=5*60]")
1414 if (args
.size() != 6)
1417 uint32 instanceNumber
= std::numeric_limits
<uint32
>::max();
1418 fromString(args
[0], instanceNumber
);
1419 string continentName
= args
[1];
1420 string spireName
= args
[2];
1421 string dynGroupName
= args
[3];
1422 string stateMachineName
= args
[4];
1423 string zoneName
= args
[5];
1424 uint32 respawnTimeGC
= 5*60*10;
1425 if ( args
.size() > 6 )
1427 NLMISC::fromString(args
[6], respawnTimeGC
);
1428 respawnTimeGC
*= 10;
1431 for (size_t i
=0; i
<5; ++i
)
1436 bool instanceFound
= false;
1437 bool continentFound
= false;
1438 bool spireFound
= false;
1439 if (instanceNumber
<CAIS::instance().AIList().size())
1441 CAIInstance
* const aiinstance
= CAIS::instance().AIList()[instanceNumber
];
1444 instanceFound
= true;
1445 for (uint i
=0; i
<aiinstance
->continents().size() && !done
; ++i
)
1447 CContinent
* const continent
= aiinstance
->continents()[i
];
1448 if (!continent
|| continentName
!=continent
->getName())
1450 continentFound
= true;
1451 for (uint j
=0; j
<continent
->spires().size() && !done
; ++j
)
1453 CSpire
* const spire
= continent
->spires()[j
];
1454 if (!spire
|| spireName
!=spire
->getName())
1457 spire
->createSquad(dynGroupName
, stateMachineName
, "", zoneName
, 0, respawnTimeGC
, SPIREENUMS::UnknownPVPSide
);
1465 SPIRE_WRN("Could not spawn a new squad");
1466 log
.displayNL("Could not spawn a new squad");
1468 log
.displayNL( "Instance not found" );
1469 if (!continentFound
)
1470 log
.displayNL( "Continent not found" );
1472 log
.displayNL( "Spire not found" );
1479 * Return the spire corresponding to the alias, or NULL if not found (with a nlwarning)
1481 CSpire
* CSpire::getSpireByAlias( TAIAlias spireAlias
)
1483 bool instanceFound
= false;
1484 bool continentFound
= false;
1485 bool spireFound
= false;
1486 for (uint i
=0; i
<CAIS::instance().AIList().size(); ++i
)
1488 CAIInstance
* const aiinstance
= CAIS::instance().AIList()[i
];
1491 instanceFound
= true;
1492 for (uint i
=0; i
<aiinstance
->continents().size(); ++i
)
1494 CContinent
* const continent
= aiinstance
->continents()[i
];
1497 continentFound
= true;
1498 for (uint j
=0; j
<continent
->spires().size(); ++j
)
1500 CSpire
* spire
= continent
->spires()[j
];
1501 if (!spire
|| spireAlias
!=spire
->getAlias())
1509 SPIRE_WRN( "Instance not found" );
1510 if (!continentFound
)
1511 SPIRE_WRN( "Continent not found" );
1513 SPIRE_WRN( "Spire %s not found", LigoConfig
.aliasToString( spireAlias
).c_str() );
1518 void spireCreateSquad(uint32 spireAlias, uint32 dynGroupAlias, uint32 zoneAlias, uint32 spawnOrder)
1520 CSpire *spire = CSpire::getSpireByAlias( spireAlias );
1522 spire->createSquad(dynGroupAlias, zoneAlias, spawnOrder);
1525 void spireSpawnSquad(uint32 spireAlias, uint32 groupId)
1527 CSpire *spire = CSpire::getSpireByAlias( spireAlias );
1529 spire->spawnSquad(groupId);
1532 void spireDespawnSquad(uint32 spireAlias, uint32 groupId)
1534 CSpire *spire = CSpire::getSpireByAlias( spireAlias );
1536 spire->despawnSquad(groupId);
1539 void spireDeleteSquad(uint32 spireAlias, uint32 groupId)
1541 CSpire *spire = CSpire::getSpireByAlias( spireAlias );
1543 spire->deleteSquad(groupId);
1546 void spireDespawnAllSquads(uint32 spireAlias)
1548 CSpire *spire = CSpire::getSpireByAlias( spireAlias );
1550 spire->despawnAllSquads();
1554 NLMISC_COMMAND(spireAliasSpawnSquad
, "Spawns a squad in an spire (respawn time = 5 min)", "<spire_alias> <group_alias> <spawn_zone_alias>")
1559 for (size_t i
=0; i
<3; ++i
)
1563 uint32 spireAlias
= LigoConfig
.aliasFromString(args
[0]);
1564 uint32 dynGroupAlias
= LigoConfig
.aliasFromString(args
[1]);
1565 uint32 zoneAlias
= LigoConfig
.aliasFromString(args
[2]);
1566 string stateMachineName
= "default_squad_manager";
1568 CSpire
*spire
= CSpire::getSpireByAlias(spireAlias
);
1570 spire
->createSquad(dynGroupAlias
, zoneAlias
, 0, 5*60*10, SPIREENUMS::UnknownPVPSide
);
1575 CBot
* CSpire::getBuildingBotByAlias(TAIAlias alias
)
1577 CGroup
* group
= getBuildingGroup();
1579 return group
->bots().getChildByAlias(alias
);
1584 NLMISC_COMMAND(spireSetBuildingBotSheet
, "Set the sheet of an spire building", "<spire_alias> <building_alias> <bot_sheet>")
1589 for (size_t i
=0; i
<3; ++i
)
1593 uint32 spireAlias
= LigoConfig
.aliasFromString(args
[0]);
1594 uint32 buildingAlias
= LigoConfig
.aliasFromString(args
[1]);
1595 NLMISC::CSheetId buildingBotSheet
= NLMISC::CSheetId(args
[2]);;
1597 CSpire
* spire
= CSpire::getSpireByAlias(spireAlias
);
1599 spire
->setBuildingBotSheet(buildingAlias
, buildingBotSheet
, true, "");
1605 // Call this macro, then do the code that will must done only if the spire is found in this instance
1606 // The data you have access to after this macro:
1608 // - msgStruct params;
1609 #define IF_GET_SPIRE_FOR_MSG( msgStruct ) \
1611 msgin.serial( params ); \
1612 CSpire *spire = CSpire::getSpireByAlias( params.Spire ); \
1616 void cbSpireCreateSquad( NLNET::CMessage
& msgin
, const std::string
&serviceName
, uint16 serviceId
)
1618 IF_GET_SPIRE_FOR_MSG( CSpireCreateSquadMsg
)
1619 spire
->createSquad(params
.Group
, params
.Zone
, params
.CreateOrder
, params
.RespawnTimeS
*10, params
.Side
);
1622 void cbSpireSpawnSquad( NLNET::CMessage
& msgin
, const std::string
&serviceName
, uint16 serviceId
)
1624 IF_GET_SPIRE_FOR_MSG( CSpireSpawnSquadMsg
)
1625 spire
->spawnSquad(params
.GroupId
);
1628 void cbSpireDespawnSquad( NLNET::CMessage
& msgin
, const std::string
&serviceName
, uint16 serviceId
)
1630 IF_GET_SPIRE_FOR_MSG( CSpireDespawnSquadMsg
)
1631 spire
->despawnSquad(params
.GroupId
);
1634 void cbSpireDeleteSquad( NLNET::CMessage
& msgin
, const std::string
&serviceName
, uint16 serviceId
)
1636 IF_GET_SPIRE_FOR_MSG( CSpireDeleteSquadMsg
)
1637 spire
->deleteSquad(params
.GroupId
);
1640 void cbSpireDespawnAllSquads( NLNET::CMessage
& msgin
, const std::string
&serviceName
, uint16 serviceId
)
1642 IF_GET_SPIRE_FOR_MSG( CSpireDespawnAllSquadsMsg
)
1643 spire
->despawnAllSquads();
1646 void cbSpireSetOwner( NLNET::CMessage
& msgin
, const std::string
&serviceName
, uint16 serviceId
)
1648 IF_GET_SPIRE_FOR_MSG( CSetSpireOwner
)
1649 spire
->setOwnerAlliance( params
.Owner
);
1652 void cbSpireSetAttacker( NLNET::CMessage
& msgin
, const std::string
&serviceName
, uint16 serviceId
)
1654 IF_GET_SPIRE_FOR_MSG( CSetSpireAttacker
)
1655 spire
->setAttackerAlliance( params
.Attacker
);
1658 void cbSpireSetState( NLNET::CMessage
& msgin
, const std::string
&serviceName
, uint16 serviceId
)
1660 IF_GET_SPIRE_FOR_MSG( CSpireSetStateMsg
)
1661 spire
->setState( params
.State
);
1664 void cbSpireEvent( NLNET::CMessage
& msgin
, const std::string
&serviceName
, uint16 serviceId
)
1666 IF_GET_SPIRE_FOR_MSG( CSpireEventMsg
)
1667 spire
->triggerSpecialEvent(params
.Event
);
1670 void cbSpireSetBuildingBotSheet( NLNET::CMessage
& msgin
, const std::string
&serviceName
, uint16 serviceId
)
1672 IF_GET_SPIRE_FOR_MSG( CSpireSetBuildingBotSheetMsg
)
1673 spire
->setBuildingBotSheet(params
.Building
, params
.SheetId
, params
.AutoSpawnDespawn
, params
.CustomName
);
1676 #include "event_reaction_include.h"