2012-05-29 13:31:11 +00:00
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "stdpch.h"
# include "ai_outpost.h"
# include "continent.h"
# include "ai_grp_npc.h"
# include "game_share/people.h"
# include "ai_profile_npc.h"
# include "continent_inline.h"
# include "dyn_grp_inline.h"
using namespace std ;
using namespace NLMISC ;
using namespace AITYPES ;
CFileDisplayer OutpostDisplayer ( " outposts.log " ) ;
CLog OutpostDbgLog ( CLog : : LOG_DEBUG ) , OutpostInfLog ( CLog : : LOG_INFO ) , OutpostWrnLog ( CLog : : LOG_WARNING ) , OutpostErrLog ( CLog : : LOG_ERROR ) ;
namespace OUTPOSTHELPERS {
static std : : map < uint32 , uint32 > outpostFactions ;
bool isAttackingFaction ( uint32 factionIndex , CAIEntityPhysical const * player )
{
std : : map < uint32 , uint32 > : : const_iterator it = outpostFactions . find ( player - > outpostAlias ( ) ) ;
return it ! = outpostFactions . end ( ) & & it - > second = = factionIndex ;
}
}
//////////////////////////////////////////////////////////////////////////////
// COutpost //
//////////////////////////////////////////////////////////////////////////////
//std::set<CContinent*> ChangedOutposts;
//COutpost::TOutpostIndex COutpost::_Outposts;
COutpost : : COutpost ( CContinent * owner , uint32 alias , std : : string const & name , std : : string const & filename )
: CAliasChild < CContinent > ( owner , alias , name )
, CAliasTreeRoot ( filename )
, _OwnerAllianceId ( InvalidAllianceId )
, _AttackerAllianceId ( InvalidAllianceId )
, _State ( OUTPOSTENUMS : : UnknownOutpostState )
{
static bool logInitDone = false ;
if ( ! logInitDone )
{
OutpostDbgLog . addDisplayer ( & OutpostDisplayer ) ;
OutpostInfLog . addDisplayer ( & OutpostDisplayer ) ;
OutpostWrnLog . addDisplayer ( & OutpostDisplayer ) ;
logInitDone = true ;
}
OUTPOST_DBG ( " Creating outpost %s' (%s) " , name . c_str ( ) , getAliasFullName ( ) . c_str ( ) ) ;
if ( LogOutpostDebug )
OUTPOST_DBG ( " Creating outpost '%s' " , getAliasFullName ( ) . c_str ( ) ) ;
_OutpostName = getName ( ) ;
COutpostManager * manager = NULL ;
// Create default squad manager
manager = new COutpostSquadManager ( this , 0 , " default_squad_manager " , filename ) ;
if ( manager )
{
_Managers . addChild ( manager ) ;
manager - > init ( ) ;
}
// Create default building manager
manager = new COutpostManager ( this , 0 , " default_building_manager " , filename ) ;
if ( manager )
{
_Managers . addChild ( manager ) ;
manager - > init ( ) ;
CGroupNpc * group = new CGroupNpc ( manager , NULL , /*AStarFlag*/ RYAI_MAP_CRUNCH : : Nothing ) ;
if ( group )
{
manager - > groups ( ) . addAliasChild ( group ) ;
group - > setAutoSpawn ( false ) ;
group - > setName ( " default_building_group " ) ;
group - > clearParameters ( ) ;
group - > setPlayerAttackable ( false ) ;
group - > setBotAttackable ( false ) ;
group - > setBotsAreNamedFlag ( ) ;
}
}
}
COutpost : : ~ COutpost ( )
{
if ( LogOutpostDebug )
OUTPOST_DBG ( " Deleting outpost '%s' " , getAliasFullName ( ) . c_str ( ) ) ;
_SpawnZones . clear ( ) ;
}
std : : string COutpost : : getOneLineInfoString ( ) const
{
return std : : string ( " Outpost ' " ) + getName ( ) + " ' " + getAliasString ( ) + " , State= " + OUTPOSTENUMS : : toString ( _State ) ;
}
std : : string COutpost : : getFullName ( ) const
{
return std : : string ( getOwner ( ) - > getFullName ( ) + " : " + getName ( ) ) ;
}
std : : string COutpost : : getIndexString ( ) const
{
return getOwner ( ) - > getIndexString ( ) + NLMISC : : toString ( " :o%u " , getChildIndex ( ) ) ;
}
/*
std : : string COutpost : : getPlaceOwnerFullName ( ) const
{
return getFullName ( ) ;
}
std : : string COutpost : : getPlaceOwnerIndexString ( ) const
{
return getIndexString ( ) ;
}
*/
CAIInstance * COutpost : : getAIInstance ( ) const
{
return getOwner ( ) - > getAIInstance ( ) ;
}
std : : string COutpost : : getManagerIndexString ( CManager const * manager ) const
{
return getIndexString ( ) + NLMISC : : toString ( " :m%u " , manager - > getChildIndex ( ) ) ;
}
IAliasCont * COutpost : : getAliasCont ( TAIType type )
{
switch ( type )
{
case AITypeOutpostSquadFamily :
OUTPOST_WRN ( " Obsolete squad family node under outpost %s " , getName ( ) . c_str ( ) ) ;
return NULL ;
case AITypeOutpostSpawnZone :
return & _SpawnZones ;
case AITypeManager :
return & _Managers ;
case AITypeOutpostManager :
return & _Managers ;
case AITypeOutpostBuilding :
return getBuildingGroup ( ) - > getAliasCont ( AITypeBot ) ;
default :
return NULL ;
}
}
CAliasTreeOwner * COutpost : : createChild ( IAliasCont * cont , CAIAliasDescriptionNode * aliasTree )
{
if ( ! cont )
return NULL ;
CAliasTreeOwner * child = NULL ;
switch ( aliasTree - > getType ( ) )
{
// create the child and adds it to the corresponding position.
case AITypeOutpostSpawnZone :
child = new COutpostSpawnZone ( this , aliasTree ) ;
break ;
case AITypeManager :
child = new COutpostSquadManager ( this , aliasTree - > getAlias ( ) , aliasTree - > getName ( ) ) ;
break ;
case AITypeOutpostManager :
child = new COutpostSquadManager ( this , aliasTree - > getAlias ( ) , aliasTree - > getName ( ) ) ;
break ;
case AITypeOutpostBuilding :
return getBuildingGroup ( ) - > createChild ( cont , aliasTree ) ;
}
if ( child )
cont - > addAliasChild ( child ) ;
return child ;
}
CGroup * COutpost : : getBuildingGroup ( )
{
COutpostManager * manager = _Managers . getChildByName ( " default_building_manager " ) ;
return manager - > groups ( ) . getChildByName ( " default_building_group " ) ;
}
void COutpost : : setTribe ( const std : : string & tribeName )
{
// The tribe is only populated by the NPCs of the squads
_Tribe = tribeName ;
if ( LogOutpostDebug )
OUTPOST_DBG ( " setting tribe '%s' in '%s' as owner for outpost '%s' " ,
tribeName . c_str ( ) ,
getOwner ( ) - > getName ( ) . c_str ( ) ,
getAliasFullName ( ) . c_str ( ) ) ;
}
void COutpost : : setOwnerAlliance ( TAllianceId ownerAllianceId )
{
if ( _OwnerAllianceId ! = ownerAllianceId )
{
// if the old owner was a tribe
if ( _OwnerAllianceId = = InvalidAllianceId )
{
triggerSpecialEvent ( OUTPOSTENUMS : : TribeOwnershipEnd ) ;
OUTPOSTHELPERS : : outpostFactions . erase ( getAlias ( ) ) ;
}
else
triggerSpecialEvent ( OUTPOSTENUMS : : GuildOwnershipEnd ) ;
}
std : : swap ( _OwnerAllianceId , ownerAllianceId ) ; // 'ownerAllianceId' contains old owner alliance id
if ( _OwnerAllianceId ! = ownerAllianceId )
{
triggerSpecialEvent ( OUTPOSTENUMS : : OwnerChanged ) ;
// if the new owner is a tribe
if ( _OwnerAllianceId = = InvalidAllianceId )
{
OUTPOSTHELPERS : : outpostFactions . insert ( make_pair ( getAlias ( ) , CStaticFames : : getInstance ( ) . getFactionIndex ( _Tribe ) ) ) ;
triggerSpecialEvent ( OUTPOSTENUMS : : TribeOwnershipBegin ) ;
}
else
triggerSpecialEvent ( OUTPOSTENUMS : : GuildOwnershipBegin ) ;
}
}
void COutpost : : setAttackerAlliance ( TAllianceId attackerAllianceId )
{
std : : swap ( _AttackerAllianceId , attackerAllianceId ) ; // 'attackerAllianceId' contains old attacker alliance id
if ( _AttackerAllianceId ! = attackerAllianceId )
{
triggerSpecialEvent ( OUTPOSTENUMS : : AttackerChanged ) ;
}
// Update the enemies of the current squads of the outpost
FOREACH ( im , CAliasCont < COutpostManager > , _Managers )
im - > setEnemies ( _AttackerAllianceId ) ;
}
void COutpost : : setState ( OUTPOSTENUMS : : TOutpostState state )
{
if ( _State ! = state )
{
if ( _State = = OUTPOSTENUMS : : Peace )
triggerSpecialEvent ( OUTPOSTENUMS : : PeaceStateEnd ) ;
}
std : : swap ( _State , state ) ; // 'state' contains old _State
if ( _State ! = state )
{
triggerSpecialEvent ( OUTPOSTENUMS : : StateChanged ) ;
if ( _State = = OUTPOSTENUMS : : Peace )
triggerSpecialEvent ( OUTPOSTENUMS : : PeaceStateBegin ) ;
}
}
void COutpost : : update ( )
{
// FOREACH(it, CAliasCont<COutpostSquadFamily>, _SquadFamilies) it->update();
// FOREACH(it, CAliasCont<COutpostSpawnZone>, _SpawnZones) it->update();
FOREACH ( it , CAliasCont < COutpostManager > , _Managers ) it - > update ( ) ;
}
void COutpost : : addZone ( COutpostSpawnZone * zone )
{
# if !FINAL_VERSION
if ( _ZoneList . find ( NLMISC : : CStringMapper : : map ( zone - > getName ( ) ) ) ! = _ZoneList . end ( ) )
OUTPOST_WRN ( " this OutpostSpawnZone have the same name than another: %s " , zone - > getName ( ) . c_str ( ) ) ;
# endif
_ZoneList [ NLMISC : : CStringMapper : : map ( zone - > getName ( ) ) ] = zone ;
}
void COutpost : : removeZone ( COutpostSpawnZone * zone )
{
_ZoneList . erase ( NLMISC : : CStringMapper : : map ( zone - > getName ( ) ) ) ;
}
COutpostSpawnZone * COutpost : : getZone ( NLMISC : : TStringId zoneName )
{
return _ZoneList [ zoneName ] ;
}
void COutpost : : serviceEvent ( CServiceEvent const & info )
{
if ( info . getServiceName ( ) = = " EGS " & & info . getEventType ( ) = = CServiceEvent : : SERVICE_DOWN )
{
// Delete all the squad groups
COutpostManager * manager = _Managers . getChildByName ( " default_squad_manager " ) ;
if ( manager )
manager - > groups ( ) . clear ( ) ;
}
FOREACH ( itManager , CAliasCont < COutpostManager > , _Managers )
{
COutpostManager * manager = * itManager ;
manager - > serviceEvent ( info ) ;
}
}
bool COutpost : : spawn ( )
{
// Spawn outpost managers
CCont < COutpostManager > : : iterator itManager , itManagerEnd ( _Managers . end ( ) ) ;
for ( itManager = _Managers . begin ( ) ; itManager ! = itManagerEnd ; + + itManager )
{
COutpostManager * manager = * itManager ;
manager - > spawn ( ) ;
}
// We should check individual errors, but fake success here :)
return true ;
}
bool COutpost : : despawn ( )
{
// Despawn instance managers
CCont < COutpostManager > : : iterator itManager , itManagerEnd ( _Managers . end ( ) ) ;
for ( itManager = _Managers . begin ( ) ; itManager ! = itManagerEnd ; + + itManager )
{
COutpostManager * manager = * itManager ;
manager - > despawnMgr ( ) ;
}
// We should check individual errors, but fake success here :)
return true ;
}
//-----------------------------------------------------------------------------
std : : string COutpost : : getStateName ( ) const
{
return OUTPOSTENUMS : : toString ( _State ) ;
}
//////////////////////////////////////////////////////////////////////////////
// COutpostSquadFamily //
//////////////////////////////////////////////////////////////////////////////
IAliasCont * COutpostSquadFamily : : getAliasCont ( TAIType type )
{
switch ( type )
{
case AITypeGroupTemplate :
case AITypeGroupTemplateMultiLevel :
return & _GroupDescs ;
default :
return NULL ;
}
}
CAliasTreeOwner * COutpostSquadFamily : : createChild ( IAliasCont * cont , CAIAliasDescriptionNode * aliasTree )
{
if ( ! cont )
return NULL ;
CAliasTreeOwner * child = NULL ;
switch ( aliasTree - > getType ( ) )
{
case AITypeSquadTemplateVariant :
child = new CGroupDesc < COutpostSquadFamily > ( this , aliasTree - > getAlias ( ) , aliasTree - > getParent ( ) - > getName ( ) + " : " + aliasTree - > getName ( ) ) ;
break ;
case AITypeGroupTemplate :
case AITypeGroupTemplateMultiLevel :
child = new CGroupDesc < COutpostSquadFamily > ( this , aliasTree - > getAlias ( ) , aliasTree - > getName ( ) ) ;
break ;
}
if ( child )
cont - > addAliasChild ( child ) ;
return child ;
}
std : : string COutpostSquadFamily : : getFullName ( ) const
{
// return std::string(getOwner()->getFullName() +":"+ getName());
return getName ( ) ;
}
std : : string COutpostSquadFamily : : getIndexString ( ) const
{
return getOwner ( ) - > getIndexString ( ) + NLMISC : : toString ( " :sf%u " , getChildIndex ( ) ) ;
}
//////////////////////////////////////////////////////////////////////////////
// CGroupDesc //
//////////////////////////////////////////////////////////////////////////////
template < > size_t const CGroupDesc < COutpostSquadFamily > : : _MultiLevelSheetCount = 20 ;
//////////////////////////////////////////////////////////////////////////////
// CBotDesc //
//////////////////////////////////////////////////////////////////////////////
template < > size_t const CBotDesc < COutpostSquadFamily > : : _MultiLevelSheetCount = 20 ;
//////////////////////////////////////////////////////////////////////////////
// COutpostSpawnZone //
//////////////////////////////////////////////////////////////////////////////
COutpostSpawnZone : : COutpostSpawnZone ( COutpost * owner , CAIAliasDescriptionNode * adn )
: CAIPlaceXYR ( owner , adn )
{
owner - > addZone ( this ) ;
}
COutpostSpawnZone : : ~ COutpostSpawnZone ( )
{
static_cast < COutpost * > ( getOwner ( ) ) - > removeZone ( this ) ;
}
std : : string COutpostSpawnZone : : getFullName ( ) const
{
return std : : string ( getOwner ( ) - > getFullName ( ) + " : " + getName ( ) ) ;
}
std : : string COutpostSpawnZone : : getIndexString ( ) const
{
return getOwner ( ) - > getIndexString ( ) + NLMISC : : toString ( " :%u " , getChildIndex ( ) ) ;
}
//////////////////////////////////////////////////////////////////////////////
// COutpostManager //
//////////////////////////////////////////////////////////////////////////////
COutpostManager : : COutpostManager ( COutpost * parent , uint32 alias , std : : string const & name , std : : string const & filename )
: CMgrNpc ( parent , alias , name , filename )
, _AutoSpawn ( false )
{
registerEvents ( ) ;
}
COutpostManager : : ~ COutpostManager ( )
{
unregisterEvents ( ) ; // need be called otherwise the state manager will be unhappy when the CAIEvent objects are destroyed
}
std : : string COutpostManager : : getOneLineInfoString ( ) const
{
return std : : string ( " Outpost manager ' " ) + getName ( ) + " ' " ;
}
void COutpostManager : : update ( )
{
CMgrNpc : : update ( ) ;
}
IAliasCont * COutpostManager : : getAliasCont ( TAIType type )
{
// IAliasCont* cont = NULL;
// switch (type)
// {
// default:
// break;
// }
// if (cont)
// return cont;
// else
return CMgrNpc : : getAliasCont ( type ) ;
}
CAliasTreeOwner * COutpostManager : : createChild ( IAliasCont * cont , CAIAliasDescriptionNode * aliasTree )
{
// CAliasTreeOwner* child = NULL;
// switch (aliasTree->getType())
// {
// default:
// break;
// }
// if (child)
// cont->addAliasChild(child);
// if (child)
// return child;
// else
return CMgrNpc : : createChild ( cont , aliasTree ) ;
}
void COutpostManager : : registerEvents ( )
{
_StateMachine . addEvent ( " outpost_peace_state_begin " , EventOutpostPeaceStateBegin ) ;
_StateMachine . addEvent ( " outpost_peace_state_end " , EventOutpostPeaceStateEnd ) ;
_StateMachine . addEvent ( " outpost_tribe_ownership_begin " , EventOutpostTribeOwnershipBegin ) ;
_StateMachine . addEvent ( " outpost_tribe_ownership_end " , EventOutpostTribeOwnershipEnd ) ;
_StateMachine . addEvent ( " outpost_guild_ownership_begin " , EventOutpostGuildOwnershipBegin ) ;
_StateMachine . addEvent ( " outpost_guild_ownership_end " , EventOutpostGuildOwnershipEnd ) ;
_StateMachine . addEvent ( " outpost_owner_changed " , EventOutpostOwnerChanged ) ;
_StateMachine . addEvent ( " outpost_attacker_changed " , EventOutpostAttackerChanged ) ;
_StateMachine . addEvent ( " outpost_state_changed " , EventOutpostStateChanged ) ;
}
void COutpostManager : : unregisterEvents ( )
{
_StateMachine . delEvent ( " outpost_peace_state_begin " ) ;
_StateMachine . delEvent ( " outpost_peace_state_end " ) ;
_StateMachine . delEvent ( " outpost_tribe_ownership_begin " ) ;
_StateMachine . delEvent ( " outpost_tribe_ownership_end " ) ;
_StateMachine . delEvent ( " outpost_guild_ownership_begin " ) ;
_StateMachine . delEvent ( " outpost_guild_ownership_end " ) ;
_StateMachine . delEvent ( " outpost_owner_changed " ) ;
_StateMachine . delEvent ( " outpost_attacker_changed " ) ;
_StateMachine . delEvent ( " outpost_state_changed " ) ;
}
void COutpostManager : : autoSpawnBegin ( )
{
if ( ! _AutoSpawn )
return ;
FOREACH ( itGroup , CCont < CGroup > , groups ( ) )
{
CGroupNpc * group = static_cast < CGroupNpc * > ( * itGroup ) ;
if ( group )
{
CSpawnGroupNpc * spawn = group - > getSpawnObj ( ) ;
if ( spawn )
spawn - > spawnBots ( ) ;
}
}
}
void COutpostManager : : autoSpawnEnd ( )
{
if ( ! _AutoSpawn )
return ;
FOREACH ( itGroup , CCont < CGroup > , groups ( ) )
{
CGroupNpc * group = static_cast < CGroupNpc * > ( * itGroup ) ;
if ( group )
{
CSpawnGroupNpc * spawn = group - > getSpawnObj ( ) ;
if ( spawn )
spawn - > despawnBots ( 1 ) ;
}
}
}
void COutpostManager : : setEnemies ( TAllianceId attackerAllianceId )
{
FOREACH ( ig , CAliasCont < CGroup > , _Groups )
{
// Attack only the declared ennemies of the outpost
CGroupNpc * grp = static_cast < CGroupNpc * > ( * ig ) ;
grp - > ennemyFaction ( ) . clearExtra ( ) ;
grp - > ennemyFaction ( ) . addExtraProperty ( attackerAllianceId ) ;
}
}
//////////////////////////////////////////////////////////////////////////////
// COutpostSquadManager //
//////////////////////////////////////////////////////////////////////////////
COutpostSquadManager : : COutpostSquadManager ( COutpost * parent , uint32 alias , std : : string const & name , std : : string const & filename )
: COutpostManager ( parent , alias , name , filename )
{
// Create init state
CAIState * state = new CAIStatePositional ( getStateMachine ( ) , 0 , " outpost_squad_init " ) ;
IAIProfileFactory * aiProfile = lookupAIGrpProfile ( " squad " ) ;
state - > setActivityProfile ( aiProfile ) ;
getStateMachine ( ) - > states ( ) . addChild ( state ) ;
CAIEventDescription eventDescription ;
CAIEventActionNode : : TSmartPtr eventAction ;
CAIEventReaction * event ;
// Create event handler for start of state
eventDescription . EventType = " start_of_state " ;
// eventDescription.StateKeywords.push_back("");
// eventDescription.NamedStates.push_back("");
// eventDescription.GroupKeywords.push_back("");
// eventDescription.NamedGroups.push_back("");
// Create event action
eventAction = new CAIEventActionNode ;
eventAction - > Action = " code " ;
eventAction - > Weight = 1 ;
eventAction - > Args . push_back ( " print( \" CREATING A SQUAD \" ); " ) ;
// eventAction->Args.push_back("()setFactionProp(\"faction\", \"foo\");");
// eventAction->Args.push_back("()setFactionProp(\"ennemyFaction\", \"bar\");");
// eventAction->Args.push_back("()setFactionProp(\"friendFaction\", \"baf\");");
eventAction - > Args . push_back ( " ()setHealer(1); " ) ;
// Register event action
eventDescription . Action = eventAction ;
eventAction = NULL ;
// Register event handler
event = new CAIEventReaction ( getStateMachine ( ) , 0 , eventDescription . EventType ) ;
event - > processEventDescription ( & eventDescription , getStateMachine ( ) ) ;
getStateMachine ( ) - > eventReactions ( ) . addChild ( event ) ;
event = NULL ;
// Create event handler for group death
eventDescription . EventType = " group_eliminated " ;
// eventDescription.StateKeywords.push_back("");
// eventDescription.NamedStates.push_back("");
// eventDescription.GroupKeywords.push_back("");
// eventDescription.NamedGroups.push_back("");
// Create event action
eventAction = new CAIEventActionNode ;
eventAction - > Action = " outpost_report_squad_death " ;
eventAction - > Weight = 1 ;
// eventAction->Args.push_back("");
// Register event action
eventDescription . Action = eventAction ;
eventAction = NULL ;
// Register event handler
event = new CAIEventReaction ( getStateMachine ( ) , 0 , eventDescription . EventType ) ;
event - > processEventDescription ( & eventDescription , getStateMachine ( ) ) ;
getStateMachine ( ) - > eventReactions ( ) . addChild ( event ) ;
event = NULL ;
// Create event handler for bot death
eventDescription . EventType = " bot_killed " ;
// eventDescription.StateKeywords.push_back("");
// eventDescription.NamedStates.push_back("");
// eventDescription.GroupKeywords.push_back("");
// eventDescription.NamedGroups.push_back("");
// Create event action
eventAction = new CAIEventActionNode ;
eventAction - > Action = " outpost_send_squad_status " ;
eventAction - > Weight = 1 ;
// eventAction->Args.push_back("");
// Register event action
eventDescription . Action = eventAction ;
eventAction = NULL ;
// Register event handler
event = new CAIEventReaction ( getStateMachine ( ) , 0 , eventDescription . EventType ) ;
event - > processEventDescription ( & eventDescription , getStateMachine ( ) ) ;
getStateMachine ( ) - > eventReactions ( ) . addChild ( event ) ;
event = NULL ;
// Create event handler for bot death
eventDescription . EventType = " squad_leader_killed " ;
// eventDescription.StateKeywords.push_back("");
// eventDescription.NamedStates.push_back("");
// eventDescription.GroupKeywords.push_back("");
// eventDescription.NamedGroups.push_back("");
// Create event action
eventAction = new CAIEventActionNode ;
eventAction - > Action = " multi_actions " ;
eventAction - > Weight = 1 ;
eventAction - > Children . resize ( 2 ) ;
eventAction - > Children [ 0 ] = new CAIEventActionNode ;
eventAction - > Children [ 0 ] - > Action = " outpost_report_squad_leader_death " ;
eventAction - > Children [ 0 ] - > Weight = 1 ;
// eventAction->Children[0]->Args.push_back("");
eventAction - > Children [ 1 ] = new CAIEventActionNode ;
eventAction - > Children [ 1 ] - > Action = " code " ;
eventAction - > Children [ 1 ] - > Weight = 1 ;
eventAction - > Children [ 1 ] - > Args . push_back ( " ()setAutoSpawn(0); " ) ;
# ifdef NL_DEBUG
eventAction - > Children [ 1 ] - > Args . push_back ( " print( \" INFINITE RESPAWN TIME FOR SQUAD \" ); " ) ;
# endif
// Register event action
eventDescription . Action = eventAction ;
eventAction = NULL ;
// Register event handler
event = new CAIEventReaction ( getStateMachine ( ) , 0 , eventDescription . EventType ) ;
event - > processEventDescription ( & eventDescription , getStateMachine ( ) ) ;
getStateMachine ( ) - > eventReactions ( ) . addChild ( event ) ;
event = NULL ;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
void COutpost : : createSquad ( string const & dynGroupName , string const & stateMachineName , string const & initialStateName , string const & zoneName , uint32 spawnOrder , uint32 respawTimeGC , OUTPOSTENUMS : : TPVPSide side )
{
IManagerParent * const managerParent = getOwner ( ) - > getOwner ( ) ;
CAIInstance * const aiInstance = dynamic_cast < CAIInstance * > ( managerParent ) ;
if ( ! aiInstance )
return ;
COutpostSpawnZone const * spawnZone = getZone ( CStringMapper : : map ( zoneName ) ) ;
if ( ! spawnZone )
{
OUTPOST_WRN ( " newNpcChildGroup failed : spawnZone Not Found ! for StateMachine : %s " , stateMachineName . c_str ( ) ) ;
return ;
}
CGroupDesc < COutpostSquadFamily > const * groupDesc = NULL ;
FOREACH ( itGroupDesc , CSquadLinks , _SquadLinks )
{
if ( ( * itGroupDesc ) . second - > getName ( ) = = dynGroupName )
{
groupDesc = ( * itGroupDesc ) . second ;
goto groupFound ;
}
}
groupFound :
if ( ! groupDesc )
{
OUTPOST_WRN ( " createSquad failed: No Group Found " ) ;
return ;
}
// Find the state machine as a manager
CManager * manager = NULL ;
FOREACH ( itCont , CCont < CManager > , aiInstance - > managers ( ) )
{
if ( itCont - > getName ( ) = = stateMachineName )
{
manager = * itCont ;
break ;
}
}
if ( ! manager )
{
FOREACH ( itCont , CCont < COutpostManager > , managers ( ) )
{
if ( itCont - > getName ( ) = = stateMachineName )
{
manager = * itCont ;
break ;
}
}
}
if ( ! manager )
{
OUTPOST_WRN ( " createSquad failed : Unknown stateMachine %s " , stateMachineName . c_str ( ) ) ;
return ;
}
// Find the state machine as a npc manager
COutpostSquadManager * outpostManager = dynamic_cast < COutpostSquadManager * > ( manager ) ;
if ( ! outpostManager )
{
OUTPOST_WRN ( " createSquad failed : Not an outpost state machine !: " , stateMachineName . c_str ( ) ) ;
return ;
}
createSquad ( groupDesc , outpostManager , initialStateName , spawnZone , spawnOrder , respawTimeGC , side ) ;
}
void COutpost : : createSquad ( uint32 dynGroupAlias , uint32 zoneAlias , uint32 spawnOrder , uint32 respawTimeGC , OUTPOSTENUMS : : TPVPSide side )
{
IManagerParent * const managerParent = getOwner ( ) - > getOwner ( ) ;
CAIInstance * const aiInstance = dynamic_cast < CAIInstance * > ( managerParent ) ;
if ( ! aiInstance )
return ;
COutpostSpawnZone const * spawnZone = spawnZones ( ) . getChildByAlias ( zoneAlias ) ;
if ( ! spawnZone )
{
OUTPOST_WRN ( " createSquad failed: spawn zone %s not found " , LigoConfig . aliasToString ( zoneAlias ) . c_str ( ) ) ;
return ;
}
CGroupDesc < COutpostSquadFamily > const * groupDesc = NULL ;
// Find the group template.
// :TODO: Replace it with a faster map access.
groupDesc = getSquad ( dynGroupAlias ) ;
if ( ! groupDesc )
{
OUTPOST_WRN ( " createSquad failed: group %s not found " , LigoConfig . aliasToString ( dynGroupAlias ) . c_str ( ) ) ;
return ;
}
// Find the state machine as a manager
COutpostSquadManager * manager = dynamic_cast < COutpostSquadManager * > ( managers ( ) . getChildByName ( " default_squad_manager " ) ) ;
if ( ! manager )
{
OUTPOST_WRN ( " createSquad failed: default state machine not found! (<- this is a code bug) " ) ;
return ;
}
createSquad ( groupDesc , manager , " " , spawnZone , spawnOrder , respawTimeGC , side ) ;
}
void COutpost : : createSquad ( CGroupDesc < COutpostSquadFamily > const * groupDesc , COutpostSquadManager * manager , string const & initialStateName , COutpostSpawnZone const * spawnZone , uint32 createOrder , uint32 respawTimeGC , OUTPOSTENUMS : : TPVPSide side )
{
OUTPOST_DBG ( " Creating a squad " ) ;
CAIVector const & spawnPosition = spawnZone - > midPos ( ) ;
sint32 baseLevel = - 1 ;
double dispersionRadius = spawnZone - > getRadius ( ) ;
// Save the creator state
bool const savePlayerAttackable = groupDesc - > getGDPlayerAttackable ( ) ;
bool const saveBotAttackable = groupDesc - > getGDBotAttackable ( ) ;
// PlayerAttackable must be false as it it sent to the EGS in BotDescriptionMessage to set the
// property 'Attackable'. Squads are not attackable unless a player is in war with the owner of
// the outpost (using botchatprogram instead of the property 'Attackable').
// BotAttackable must be true, otherwise the EGS sets it as invulnerable (not attackable).
groupDesc - > setGDPlayerAttackable ( false ) ;
groupDesc - > setGDBotAttackable ( true ) ;
// Create the group
CGroupNpc * const grp = groupDesc - > createNpcGroup ( manager , spawnPosition , dispersionRadius , baseLevel , false ) ;
// Restore the creator state
groupDesc - > setGDPlayerAttackable ( savePlayerAttackable ) ;
groupDesc - > setGDBotAttackable ( saveBotAttackable ) ;
// Verify that the group was created
if ( ! grp )
{
OUTPOST_WRN ( " createSquad failed: group %s cannot spawn " , LigoConfig . aliasToString ( groupDesc - > getAlias ( ) ) . c_str ( ) ) ;
return ;
}
// Set the new group parameters
// Let the EGS destroys squads explicitely because when a group is destroyed in the AIS its groupId can be reused
// and 2 squads would have the same groupId in the EGS (it asserts)
grp - > autoDestroy ( false ) ;
grp - > setAutoSpawn ( true ) ;
// grp->getPersistentStateInstance()->setParentStateInstance(entity->getPersistentStateInstance());
grp - > initDynGrp ( groupDesc , NULL ) ;
// Set color
uint8 color = ( uint8 ) ( grp - > getChildIndex ( ) % 8 ) ;
grp - > setColour ( color ) ;
// Get the state machine
CStateMachine const * stateMachine = manager - > getStateMachine ( ) ;
# if !FINAL_VERSION
// Verify that we have a state in the state machine
if ( stateMachine - > cstStates ( ) . size ( ) = = 0 )
nlerror ( " no state defined for StateMachine in Manager %s " , manager - > getFullName ( ) . c_str ( ) ) ;
# endif
// Set the group in that state
CAIState * initialState = NULL ;
if ( ! initialStateName . empty ( ) )
{
// FOREACH(itState, CCont<CAIState>, stateMachine->states())
for ( size_t i = 0 ; i < stateMachine - > cstStates ( ) . size ( ) ; + + i )
{
CAIState * state = stateMachine - > cstStates ( ) [ ( uint32 ) i ] ;
if ( state - > getName ( ) = = initialStateName )
initialState = state ;
}
}
if ( initialState = = NULL )
initialState = stateMachine - > cstStates ( ) [ 0 ] ; // sets the first state (must exist!).
grp - > setStartState ( initialState ) ;
// Do not assist friends because it would lead to exploits
/*if ( _OwnerGuild != InvalidGuildId )
{
//grp->faction().addExtraProperty(_OwnerGuild); // TODO: set the GuildId for the squad npcs?
//grp->friendFaction().addExtraProperty(_OwnerGuild); // will be defended by the squad
}
else
{
// A tribe owns the outpost and all players are ennemies
// CPropertyId tribeFaction(CGrpProfileFaction::fameFactionToScriptFaction(_OwnerTribe));
//grp->faction().addProperty(tribeFaction);
//grp->friendFaction().addProperty(tribeFaction); // will be defended by the squad
//grp->ennemyFaction().addProperty(CPropertyId("Player"));
} */
// Set guild id of members of the squad (for the tribe case, these *are* the tribe as well)
// This was removed because CBotNpc::spawn() now uses getOwner()->getOwner()->getOwner() to access the outpsot
/*FOREACH(ib, CAliasCont<CBot>, grp->bots())
{
CBotNpc * bot = static_cast < CBotNpc * > ( * ib ) ;
bot - > setOwnerOutpost ( this ) ;
} */
grp - > setOutpostSide ( side ) ;
// Attack only the declared ennemies of the outpost
if ( side = = OUTPOSTENUMS : : OutpostOwner )
{
// Bots factions
grp - > faction ( ) . addProperty ( NLMISC : : toString ( " outpost:%s:bot_defender " , getAliasString ( ) . c_str ( ) ) ) ;
grp - > friendFaction ( ) . addProperty ( NLMISC : : toString ( " outpost:%s:bot_defender " , getAliasString ( ) . c_str ( ) ) ) ;
grp - > ennemyFaction ( ) . addProperty ( NLMISC : : toString ( " outpost:%s:bot_attacker " , getAliasString ( ) . c_str ( ) ) ) ;
// Players faction
grp - > ennemyFaction ( ) . addProperty ( NLMISC : : toString ( " outpost:%s:attacker " , getAliasString ( ) . c_str ( ) ) ) ;
}
if ( side = = OUTPOSTENUMS : : OutpostAttacker )
{
// Bots factions
grp - > faction ( ) . addProperty ( NLMISC : : toString ( " outpost:%s:bot_attacker " , getAliasString ( ) . c_str ( ) ) ) ;
grp - > friendFaction ( ) . addProperty ( NLMISC : : toString ( " outpost:%s:bot_attacker " , getAliasString ( ) . c_str ( ) ) ) ;
grp - > ennemyFaction ( ) . addProperty ( NLMISC : : toString ( " outpost:%s:bot_defender " , getAliasString ( ) . c_str ( ) ) ) ;
// Players faction
grp - > ennemyFaction ( ) . addProperty ( NLMISC : : toString ( " outpost:%s:defender " , getAliasString ( ) . c_str ( ) ) ) ;
}
grp - > _AggroRange = 25 ;
grp - > _UpdateNbTicks = 10 ;
grp - > respawnTime ( ) = respawTimeGC ;
grp - > updateStateInstance ( ) ; // Directly call his first state (to retrieve associated params).
if ( createOrder ! = 0 )
{
COutpostSquadCreatedMsg params ;
params . Outpost = this - > getAlias ( ) ;
params . CreateOrder = createOrder ;
// Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
//params.GroupId = reinterpret_cast<uint32>(grp);
params . GroupId = ( uint32 ) ( size_t ) ( void * ) grp ;
sendOutpostMessage ( " OUTPOST_SQUAD_CREATED " , params ) ;
}
OUTPOST_DBG ( " Outpost %s: squad created defending 0x%x against 0x%x, respawnTime=%u gc " , getName ( ) . c_str ( ) , _OwnerAllianceId , _AttackerAllianceId , respawTimeGC ) ;
}
void COutpost : : spawnSquad ( uint32 groupId )
{
OUTPOST_DBG ( " Outpost %s: Spawning squad 0x%08x " , getName ( ) . c_str ( ) , groupId ) ;
FOREACH ( itManager , CAliasCont < COutpostManager > , _Managers )
{
COutpostManager * manager = * itManager ;
FOREACH ( itGroup , CAliasCont < CGroup > , manager - > groups ( ) )
{
CGroup * group = * itGroup ;
CGroupNpc * groupNpc = static_cast < CGroupNpc * > ( group ) ;
// Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
//uint32 thisGroupId = reinterpret_cast<uint32>(groupNpc);
uint32 thisGroupId = ( uint32 ) ( size_t ) ( void * ) groupNpc ;
if ( groupId = = thisGroupId )
{
group - > getSpawnObj ( ) - > spawnBots ( ) ;
COutpostSquadSpawnedMsg params ;
params . Outpost = this - > getAlias ( ) ;
params . GroupId = groupId ;
sendOutpostMessage ( " OUTPOST_SQUAD_SPAWNED " , params ) ;
OUTPOST_DBG ( " \t \t Spawned " ) ;
return ;
}
}
}
OUTPOST_WRN ( " No squad to spawn with group id 0x%08x. Valid group ids are: " , groupId ) ;
FOREACH ( itManager , CAliasCont < COutpostManager > , _Managers )
{
COutpostManager * manager = * itManager ;
FOREACH ( itGroup , CAliasCont < CGroup > , manager - > groups ( ) )
{
CGroup * group = * itGroup ;
CGroupNpc * groupNpc = static_cast < CGroupNpc * > ( group ) ;
// Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
//uint32 thisGroupId = reinterpret_cast<uint32>(groupNpc);
uint32 thisGroupId = ( uint32 ) ( size_t ) ( void * ) groupNpc ;
OUTPOST_WRN ( " - 0x%08x " , thisGroupId ) ;
}
}
}
void COutpost : : despawnSquad ( uint32 groupId )
{
OUTPOST_DBG ( " Outpost %s: Despawning squad 0x%08x " , getName ( ) . c_str ( ) , groupId ) ;
FOREACH ( itManager , CAliasCont < COutpostManager > , _Managers )
{
COutpostManager * manager = * itManager ;
FOREACH ( itGroup , CAliasCont < CGroup > , manager - > groups ( ) )
{
CGroup * group = * itGroup ;
CGroupNpc * groupNpc = static_cast < CGroupNpc * > ( group ) ;
// Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
//uint32 thisGroupId = reinterpret_cast<uint32>(groupNpc);
uint32 thisGroupId = ( uint32 ) ( size_t ) ( void * ) groupNpc ;
if ( groupId = = thisGroupId )
{
group - > despawnBots ( ) ;
COutpostSquadDespawnedMsg params ;
params . Outpost = this - > getAlias ( ) ;
params . GroupId = groupId ;
sendOutpostMessage ( " OUTPOST_SQUAD_DESPAWNED " , params ) ;
return ;
}
}
}
OUTPOST_WRN ( " No squad to despawn " ) ;
}
void COutpost : : deleteSquad ( uint32 groupId )
{
OUTPOST_DBG ( " Outpost %s: deleting squad 0x%08x " , getName ( ) . c_str ( ) , groupId ) ;
FOREACH ( itManager , CAliasCont < COutpostManager > , _Managers )
{
COutpostManager * manager = * itManager ;
FOREACH ( itGroup , CAliasCont < CGroup > , manager - > groups ( ) )
{
CGroup * group = * itGroup ;
CGroupNpc * groupNpc = static_cast < CGroupNpc * > ( group ) ;
// Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
//uint32 thisGroupId = reinterpret_cast<uint32>(groupNpc);
uint32 thisGroupId = ( uint32 ) ( size_t ) ( void * ) groupNpc ;
if ( groupId = = thisGroupId )
{
manager - > groups ( ) . removeChildByIndex ( group - > getChildIndex ( ) ) ;
// No message here since this is called by squad destructor in EGS
return ;
}
}
}
OUTPOST_WRN ( " No squad to delete " ) ;
}
void COutpost : : sendOutpostSquadStatus ( CGroupNpc * group )
{
uint32 alias = this - > getAlias ( ) ;
// Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
//uint32 groupId = reinterpret_cast<uint32>(group);
uint32 groupId = ( uint32 ) ( size_t ) ( void * ) group ;
bool groupAlive = false ;
bool leaderAlive = group - > getSquadLeader ( ) ! = NULL ;
uint32 botCount = 0 ;
// Persistent status
// Spawn dependent status
CSpawnGroup * spawnGroup = group - > getSpawnObj ( ) ;
if ( spawnGroup )
{
groupAlive = spawnGroup - > isGroupAlive ( ) ;
}
NLNET : : CMessage msgout ( " OUTPOST_SQUAD_STATUS " ) ;
msgout . serial ( alias ) ;
msgout . serial ( groupId ) ;
msgout . serial ( groupAlive ) ;
msgout . serial ( leaderAlive ) ;
msgout . serial ( botCount ) ;
sendMessageViaMirror ( " EGS " , msgout ) ;
}
void COutpost : : squadLeaderDied ( CGroupNpc * group )
{
uint32 alias = this - > getAlias ( ) ;
// Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
//uint32 groupId = reinterpret_cast<uint32>(group);
uint32 groupId = ( uint32 ) ( size_t ) ( void * ) group ;
NLNET : : CMessage msgout ( " OUTPOST_SQUAD_LEADER_DIED " ) ;
msgout . serial ( alias ) ;
msgout . serial ( groupId ) ;
sendMessageViaMirror ( " EGS " , msgout ) ;
}
void COutpost : : squadDied ( CGroupNpc * group )
{
uint32 alias = this - > getAlias ( ) ;
// Bug #847: Just downcast the pointer to make the groupId, the collision in 64b is negligible
//uint32 groupId = reinterpret_cast<uint32>(group);
uint32 groupId = ( uint32 ) ( size_t ) ( void * ) group ;
NLNET : : CMessage msgout ( " OUTPOST_SQUAD_DIED " ) ;
msgout . serial ( alias ) ;
msgout . serial ( groupId ) ;
sendMessageViaMirror ( " EGS " , msgout ) ;
}
void COutpost : : triggerSpecialEvent ( OUTPOSTENUMS : : TSpecialOutpostEvent eventId )
{
// Managers handlers
FOREACH ( itManager , CCont < COutpostManager > , _Managers )
{
COutpostManager * manager = * itManager ;
if ( manager )
{
CAIEvent * event = NULL ;
switch ( eventId )
{
case OUTPOSTENUMS : : PeaceStateBegin : event = & manager - > EventOutpostPeaceStateBegin ; break ;
case OUTPOSTENUMS : : PeaceStateEnd : event = & manager - > EventOutpostPeaceStateEnd ; break ;
case OUTPOSTENUMS : : TribeOwnershipBegin : event = & manager - > EventOutpostTribeOwnershipBegin ; break ;
case OUTPOSTENUMS : : TribeOwnershipEnd : event = & manager - > EventOutpostTribeOwnershipEnd ; break ;
case OUTPOSTENUMS : : GuildOwnershipBegin : event = & manager - > EventOutpostGuildOwnershipBegin ; break ;
case OUTPOSTENUMS : : GuildOwnershipEnd : event = & manager - > EventOutpostGuildOwnershipEnd ; break ;
case OUTPOSTENUMS : : OwnerChanged : event = & manager - > EventOutpostOwnerChanged ; break ;
case OUTPOSTENUMS : : AttackerChanged : event = & manager - > EventOutpostAttackerChanged ; break ;
case OUTPOSTENUMS : : StateChanged : event = & manager - > EventOutpostStateChanged ; break ;
}
if ( event )
{
FOREACH ( itGroup , CCont < CGroup > , manager - > groups ( ) )
{
CGroupNpc * group = static_cast < CGroupNpc * > ( * itGroup ) ;
if ( group )
group - > processStateEvent ( * event ) ;
}
}
}
}
// Special handlers
switch ( eventId )
{
case OUTPOSTENUMS : : TribeOwnershipBegin :
{
FOREACH ( itManager , CCont < COutpostManager > , _Managers )
{
COutpostManager * manager = * itManager ;
if ( manager )
manager - > autoSpawnBegin ( ) ;
}
break ;
}
case OUTPOSTENUMS : : TribeOwnershipEnd :
{
FOREACH ( itManager , CCont < COutpostManager > , _Managers )
{
COutpostManager * manager = * itManager ;
if ( manager )
manager - > autoSpawnEnd ( ) ;
}
break ;
}
}
}
void COutpost : : setBuildingBotSheet ( uint32 buildingAlias , NLMISC : : CSheetId sheetId , bool autoSpawnDespawn , const std : : string & customName )
{
CBot * bot = getBuildingBotByAlias ( buildingAlias ) ;
if ( bot = = NULL )
{
OUTPOST_WRN ( " cannot find building bot %s " , LigoConfig . aliasToString ( buildingAlias ) . c_str ( ) ) ;
return ;
}
AISHEETS : : ICreatureCPtr const sheet = AISHEETS : : CSheets : : getInstance ( ) - > lookup ( sheetId ) ;
if ( sheetId ! = NLMISC : : CSheetId : : Unknown & & ! sheet . isNull ( ) )
{
bot - > setCustomName ( customName ) ;
bot - > triggerSetSheet ( sheet ) ;
if ( autoSpawnDespawn & & ! bot - > isSpawned ( ) )
bot - > spawn ( ) ;
}
else
{
if ( autoSpawnDespawn & & bot - > isSpawned ( ) )
bot - > despawnBot ( ) ;
}
}
void COutpost : : despawnAllSquads ( )
{
FOREACH ( itManager , CAliasCont < COutpostManager > , _Managers )
{
COutpostManager * manager = * itManager ;
COutpostSquadManager * sqManager = dynamic_cast < COutpostSquadManager * > ( manager ) ;
if ( sqManager )
{
FOREACH ( itGroup , CAliasCont < CGroup > , sqManager - > groups ( ) )
{
CGroup * group = * itGroup ;
group - > despawnBots ( ) ;
}
}
}
}
template < class T >
void COutpost : : sendOutpostMessage ( std : : string const & msgName , T & paramStruct )
{
NLNET : : CMessage msgout ( msgName ) ;
msgout . serial ( paramStruct ) ;
sendMessageViaMirror ( std : : string ( " EGS " ) , msgout ) ;
}
//////////////////////////////////////////////////////////////////////////////
// Commands //
//////////////////////////////////////////////////////////////////////////////
NLMISC_COMMAND ( displayOutposts , " list the available outpost " , " " )
{
if ( args . size ( ) > 0 )
return false ;
uint32 instanceNumber = ~ 0 ;
for ( uint i = 0 ; i < CAIS : : instance ( ) . AIList ( ) . size ( ) ; + + i )
{
CAIInstance * const aii = CAIS : : instance ( ) . AIList ( ) [ i ] ;
if ( ! aii )
{
log . displayNL ( " No current ai instance, can't look for outpost " ) ;
continue ;
}
string continentName ;
if ( ! args . empty ( ) )
continentName = args [ 0 ] ;
// retreive the oupost
for ( uint i = 0 ; i < aii - > continents ( ) . size ( ) ; + + i )
{
CContinent * const continent = aii - > continents ( ) [ i ] ;
if ( ! continent
| | ( ! continentName . empty ( )
& & continentName ! = continent - > getName ( ) ) )
continue ;
log . displayNL ( " Outposts in continent '%s': " , continent - > getName ( ) . c_str ( ) ) ;
for ( uint j = 0 ; j < continent - > outposts ( ) . size ( ) ; + + j )
{
COutpost const * outpost = continent - > outposts ( ) [ j ] ;
if ( ! outpost )
continue ;
log . displayNL ( " %s " , outpost - > getOneLineInfoString ( ) . c_str ( ) ) ;
log . displayNL ( " - %d group descs " , outpost - > squadLinks ( ) . size ( ) ) ;
for ( COutpost : : CSquadLinks : : const_iterator isl = outpost - > squadLinks ( ) . begin ( ) ; isl ! = outpost - > squadLinks ( ) . end ( ) ; + + isl )
{
CGroupDesc < COutpostSquadFamily > const * gd = ( * isl ) . second ;
if ( ! gd )
continue ;
log . displayNL ( " Group desc '%s' %s " , gd - > getName ( ) . c_str ( ) , gd - > getAliasString ( ) . c_str ( ) ) ;
}
log . displayNL ( " - %d spawn zones " , outpost - > spawnZones ( ) . size ( ) ) ;
for ( uint j = 0 ; j < outpost - > spawnZones ( ) . size ( ) ; + + j )
{
COutpostSpawnZone const * sz = outpost - > spawnZones ( ) [ j ] ;
if ( ! sz )
continue ;
log . displayNL ( " SpawnZone '%s' %s (%s) " , sz - > getName ( ) . c_str ( ) , sz - > getAliasString ( ) . c_str ( ) , sz - > midPos ( ) . toString ( ) . c_str ( ) ) ;
}
log . displayNL ( " - %d state machines " , outpost - > managers ( ) . size ( ) ) ;
for ( uint j = 0 ; j < outpost - > managers ( ) . size ( ) ; + + j )
{
COutpostManager * manager = outpost - > managers ( ) [ j ] ;
if ( ! manager )
continue ;
log . displayNL ( " State machine '%s' %s " , manager - > getName ( ) . c_str ( ) , manager - > getAliasString ( ) . c_str ( ) ) ;
log . displayNL ( " - %d states " , manager - > getStateMachine ( ) - > states ( ) . size ( ) ) ;
for ( uint j = 0 ; j < manager - > getStateMachine ( ) - > states ( ) . size ( ) ; + + j )
{
CAIState const * state = manager - > getStateMachine ( ) - > states ( ) [ j ] ;
if ( ! state )
continue ;
log . displayNL ( " State '%s' %s " , state - > getName ( ) . c_str ( ) , state - > getAliasString ( ) . c_str ( ) ) ;
}
log . displayNL ( " - %d groups " , manager - > groups ( ) . size ( ) ) ;
for ( uint j = 0 ; j < manager - > groups ( ) . size ( ) ; + + j )
{
CGroup const * group = manager - > groups ( ) [ j ] ;
if ( group )
{
log . displayNL ( " Group '%s' %s " , group - > getName ( ) . c_str ( ) , group - > getAliasString ( ) . c_str ( ) ) ;
log . displayNL ( " - %d bots " , group - > bots ( ) . size ( ) ) ;
for ( uint k = 0 ; k < group - > bots ( ) . size ( ) ; + + k )
{
CBot const * bot = group - > bots ( ) [ k ] ;
if ( bot )
log . displayNL ( " Bot '%s' %s " , bot - > getName ( ) . c_str ( ) , bot - > getAliasString ( ) . c_str ( ) ) ;
else
log . displayNL ( " Bot <NULL> " ) ;
}
}
else
log . displayNL ( " Group <NULL> " ) ;
}
}
}
}
}
return true ;
}
// outpostSpawnSquad 1 fyros outpost group machine zone
NLMISC_COMMAND ( outpostSpawnSquad , " Spawns a squad in an outpost " , " <instance_number> <continent> <outpost> <group_template> <state_machine> <spawn_zone> [<respawnTimeInSec>=5*60] " )
{
if ( args . size ( ) ! = 6 )
return false ;
uint32 instanceNumber = ~ 0 ;
fromString ( args [ 0 ] , instanceNumber ) ;
string continentName = args [ 1 ] ;
string outpostName = args [ 2 ] ;
string dynGroupName = args [ 3 ] ;
string stateMachineName = args [ 4 ] ;
string zoneName = args [ 5 ] ;
uint32 respawnTimeGC = 5 * 60 * 10 ;
if ( args . size ( ) > 6 )
{
NLMISC : : fromString ( args [ 6 ] , respawnTimeGC ) ;
respawnTimeGC * = 10 ;
}
for ( size_t i = 0 ; i < 5 ; + + i )
if ( args [ i ] = = " " )
return false ;
bool done = false ;
bool instanceFound = false ;
bool continentFound = false ;
bool outpostFound = false ;
if ( instanceNumber < CAIS : : instance ( ) . AIList ( ) . size ( ) )
{
CAIInstance * const aiinstance = CAIS : : instance ( ) . AIList ( ) [ instanceNumber ] ;
if ( aiinstance )
{
instanceFound = true ;
for ( uint i = 0 ; i < aiinstance - > continents ( ) . size ( ) & & ! done ; + + i )
{
CContinent * const continent = aiinstance - > continents ( ) [ i ] ;
if ( ! continent | | continentName ! = continent - > getName ( ) )
continue ;
continentFound = true ;
for ( uint j = 0 ; j < continent - > outposts ( ) . size ( ) & & ! done ; + + j )
{
COutpost * const outpost = continent - > outposts ( ) [ j ] ;
if ( ! outpost | | outpostName ! = outpost - > getName ( ) )
continue ;
outpostFound = true ;
outpost - > createSquad ( dynGroupName , stateMachineName , " " , zoneName , 0 , respawnTimeGC , OUTPOSTENUMS : : UnknownPVPSide ) ;
done = true ;
}
}
}
}
if ( ! done )
{
OUTPOST_WRN ( " Could not spawn a new squad " ) ;
log . displayNL ( " Could not spawn a new squad " ) ;
if ( ! instanceFound )
log . displayNL ( " Instance not found " ) ;
if ( ! continentFound )
log . displayNL ( " Continent not found " ) ;
if ( ! outpostFound )
log . displayNL ( " Outpost not found " ) ;
}
return true ;
}
/*
* Return the outpost corresponding to the alias , or NULL if not found ( with a nlwarning )
*/
COutpost * COutpost : : getOutpostByAlias ( TAIAlias outpostAlias )
{
bool instanceFound = false ;
bool continentFound = false ;
bool outpostFound = false ;
for ( uint i = 0 ; i < CAIS : : instance ( ) . AIList ( ) . size ( ) ; + + i )
{
CAIInstance * const aiinstance = CAIS : : instance ( ) . AIList ( ) [ i ] ;
if ( aiinstance )
{
instanceFound = true ;
for ( uint i = 0 ; i < aiinstance - > continents ( ) . size ( ) ; + + i )
{
CContinent * const continent = aiinstance - > continents ( ) [ i ] ;
if ( ! continent )
continue ;
continentFound = true ;
for ( uint j = 0 ; j < continent - > outposts ( ) . size ( ) ; + + j )
{
COutpost * outpost = continent - > outposts ( ) [ j ] ;
if ( ! outpost | | outpostAlias ! = outpost - > getAlias ( ) )
continue ;
return outpost ;
}
}
}
}
if ( ! instanceFound )
OUTPOST_WRN ( " Instance not found " ) ;
if ( ! continentFound )
OUTPOST_WRN ( " Continent not found " ) ;
if ( ! outpostFound )
OUTPOST_WRN ( " Outpost %s not found " , LigoConfig . aliasToString ( outpostAlias ) . c_str ( ) ) ;
return NULL ;
}
/*
void outpostCreateSquad ( uint32 outpostAlias , uint32 dynGroupAlias , uint32 zoneAlias , uint32 spawnOrder )
{
COutpost * outpost = COutpost : : getOutpostByAlias ( outpostAlias ) ;
if ( outpost )
outpost - > createSquad ( dynGroupAlias , zoneAlias , spawnOrder ) ;
}
void outpostSpawnSquad ( uint32 outpostAlias , uint32 groupId )
{
COutpost * outpost = COutpost : : getOutpostByAlias ( outpostAlias ) ;
if ( outpost )
outpost - > spawnSquad ( groupId ) ;
}
void outpostDespawnSquad ( uint32 outpostAlias , uint32 groupId )
{
COutpost * outpost = COutpost : : getOutpostByAlias ( outpostAlias ) ;
if ( outpost )
outpost - > despawnSquad ( groupId ) ;
}
void outpostDeleteSquad ( uint32 outpostAlias , uint32 groupId )
{
COutpost * outpost = COutpost : : getOutpostByAlias ( outpostAlias ) ;
if ( outpost )
outpost - > deleteSquad ( groupId ) ;
}
void outpostDespawnAllSquads ( uint32 outpostAlias )
{
COutpost * outpost = COutpost : : getOutpostByAlias ( outpostAlias ) ;
if ( outpost )
outpost - > despawnAllSquads ( ) ;
}
*/
NLMISC_COMMAND ( outpostAliasSpawnSquad , " Spawns a squad in an outpost (respawn time = 5 min) " , " <outpost_alias> <group_alias> <spawn_zone_alias> " )
{
if ( args . size ( ) ! = 3 )
return false ;
for ( size_t i = 0 ; i < 3 ; + + i )
if ( args [ i ] = = " " )
return false ;
uint32 outpostAlias = LigoConfig . aliasFromString ( args [ 0 ] ) ;
uint32 dynGroupAlias = LigoConfig . aliasFromString ( args [ 1 ] ) ;
uint32 zoneAlias = LigoConfig . aliasFromString ( args [ 2 ] ) ;
string stateMachineName = " default_squad_manager " ;
COutpost * outpost = COutpost : : getOutpostByAlias ( outpostAlias ) ;
if ( outpost )
outpost - > createSquad ( dynGroupAlias , zoneAlias , 0 , 5 * 60 * 10 , OUTPOSTENUMS : : UnknownPVPSide ) ;
return true ;
}
CBot * COutpost : : getBuildingBotByAlias ( TAIAlias alias )
{
CGroup * group = getBuildingGroup ( ) ;
if ( group )
return group - > bots ( ) . getChildByAlias ( alias ) ;
else
return NULL ;
}
NLMISC_COMMAND ( outpostSetBuildingBotSheet , " Set the sheet of an outpost building " , " <outpost_alias> <building_alias> <bot_sheet> " )
{
if ( args . size ( ) ! = 3 )
return false ;
for ( size_t i = 0 ; i < 3 ; + + i )
if ( args [ i ] = = " " )
return false ;
uint32 outpostAlias = LigoConfig . aliasFromString ( args [ 0 ] ) ;
uint32 buildingAlias = LigoConfig . aliasFromString ( args [ 1 ] ) ;
NLMISC : : CSheetId buildingBotSheet = NLMISC : : CSheetId ( args [ 2 ] ) ; ;
COutpost * outpost = COutpost : : getOutpostByAlias ( outpostAlias ) ;
if ( outpost )
outpost - > setBuildingBotSheet ( buildingAlias , buildingBotSheet , true , " " ) ;
return true ;
}
// Call this macro, then do the code that will must done only if the outpost is found in this instance
// The data you have access to after this macro:
// - COutpost *outpost
// - msgStruct params;
# define IF_GET_OUTPOST_FOR_MSG( msgStruct ) \
msgStruct params ; \
msgin . serial ( params ) ; \
COutpost * outpost = COutpost : : getOutpostByAlias ( params . Outpost ) ; \
if ( outpost )
void cbOutpostCreateSquad ( NLNET : : CMessage & msgin , const std : : string & serviceName , NLNET : : TServiceId serviceId )
{
IF_GET_OUTPOST_FOR_MSG ( COutpostCreateSquadMsg )
outpost - > createSquad ( params . Group , params . Zone , params . CreateOrder , params . RespawnTimeS * 10 , params . Side ) ;
}
void cbOutpostSpawnSquad ( NLNET : : CMessage & msgin , const std : : string & serviceName , NLNET : : TServiceId serviceId )
{
IF_GET_OUTPOST_FOR_MSG ( COutpostSpawnSquadMsg )
outpost - > spawnSquad ( params . GroupId ) ;
}
void cbOutpostDespawnSquad ( NLNET : : CMessage & msgin , const std : : string & serviceName , NLNET : : TServiceId serviceId )
{
IF_GET_OUTPOST_FOR_MSG ( COutpostDespawnSquadMsg )
outpost - > despawnSquad ( params . GroupId ) ;
}
void cbOutpostDeleteSquad ( NLNET : : CMessage & msgin , const std : : string & serviceName , NLNET : : TServiceId serviceId )
{
IF_GET_OUTPOST_FOR_MSG ( COutpostDeleteSquadMsg )
outpost - > deleteSquad ( params . GroupId ) ;
}
void cbOutpostDespawnAllSquads ( NLNET : : CMessage & msgin , const std : : string & serviceName , NLNET : : TServiceId serviceId )
{
IF_GET_OUTPOST_FOR_MSG ( COutpostDespawnAllSquadsMsg )
outpost - > despawnAllSquads ( ) ;
}
void cbOutpostSetOwner ( NLNET : : CMessage & msgin , const std : : string & serviceName , NLNET : : TServiceId serviceId )
{
IF_GET_OUTPOST_FOR_MSG ( CSetOutpostOwner )
outpost - > setOwnerAlliance ( params . Owner ) ;
}
void cbOutpostSetAttacker ( NLNET : : CMessage & msgin , const std : : string & serviceName , NLNET : : TServiceId serviceId )
{
IF_GET_OUTPOST_FOR_MSG ( CSetOutpostAttacker )
outpost - > setAttackerAlliance ( params . Attacker ) ;
}
void cbOutpostSetState ( NLNET : : CMessage & msgin , const std : : string & serviceName , NLNET : : TServiceId serviceId )
{
IF_GET_OUTPOST_FOR_MSG ( COutpostSetStateMsg )
outpost - > setState ( params . State ) ;
}
void cbOutpostEvent ( NLNET : : CMessage & msgin , const std : : string & serviceName , NLNET : : TServiceId serviceId )
{
IF_GET_OUTPOST_FOR_MSG ( COutpostEventMsg )
outpost - > triggerSpecialEvent ( params . Event ) ;
}
void cbOutpostSetBuildingBotSheet ( NLNET : : CMessage & msgin , const std : : string & serviceName , NLNET : : TServiceId serviceId )
{
IF_GET_OUTPOST_FOR_MSG ( COutpostSetBuildingBotSheetMsg )
outpost - > setBuildingBotSheet ( params . Building , params . SheetId , params . AutoSpawnDespawn , params . CustomName ) ;
}
# include "event_reaction_include.h"