You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

391 lines
11 KiB

//
// Copyright (c) 2010-2011 Matthew Jack and Doug Binks
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
#include "IBlackboardManager.h"
#include "IGameObject.h"
#include "IGameManager.h"
#include "IObjectUtils.h"
#include "GlobalParameters.h"
#include "IObjectUtils.h"
#include "BB_Individual_WBC.h"
#include "BB_Individual_RBC.h"
#include "BB_Individual_Virus.h"
#include "BB_Individual_Infected.h"
#include "BB_Individual_Common.h"
#include "BB_Team_Immune.h"
#include "BB_Team_Infection.h"
#include "BB_Group_WBC.h"
#include "BB_Group_RBC.h"
#include "BB_Group_Virus.h"
#include "BB_Group_Infected.h"
#include "BB_Global.h"
#include "../../RuntimeObjectSystem/ObjectInterfacePerModule.h"
#include "../../Systems/SystemTable.h"
#include "../../RuntimeObjectSystem/IObjectFactorySystem.h"
#include "../../Systems/ILogSystem.h"
#include "../../RuntimeObjectSystem/ISimpleSerializer.h"
#include <assert.h>
#include <map>
#include <vector>
class BlackboardManager: public IBlackboardManager, public IGameEventListener
{
public:
BlackboardManager()
{
m_pGameManager = 0;
m_pGlobalParameters = 0;
m_pBlackboardGlobal = 0;
m_BlackboardTeam.resize(EGT_COUNT);
m_BlackboardGroup.resize(EGO_COUNT);
}
virtual ~BlackboardManager()
{
((IGameManager*)IObjectUtils::GetUniqueInterface( "GameManager", IID_IGAMEMANAGER ))->RemoveListener(this);
if (!IsRuntimeDelete())
{
DestroyAllBlackboards();
}
}
// IObject
virtual void Serialize(ISimpleSerializer *pSerializer)
{
SERIALIZEIOBJPTR(m_pBlackboardGlobal);
SERIALIZE(m_BlackboardTeam);
SERIALIZE(m_BlackboardGroup);
SERIALIZE(m_BlackboardIndividual);
SERIALIZE(m_BlackboardIndividualCommon);
}
virtual void Init( bool isFirstInit )
{
IGameManager* pGameManager = (IGameManager*)IObjectUtils::GetUniqueInterface( "GameManager", IID_IGAMEMANAGER );
pGameManager->AddListener(this);
m_pGlobalParameters = pGameManager->GetGlobalParameters();
if (isFirstInit)
{
CreateSharedBlackboards();
}
}
// ~IObject
// IGameEventListener
virtual void OnGameObjectCreated( IGameObject* pGameObject )
{
EGameTeam team = pGameObject->GetGameTeam();
EGameObject type = pGameObject->GetGameObjectType();
CreateIndividualBlackboards(pGameObject);
// Set/Modify appropriate blackboard values
SetInitialCommonValues( pGameObject );
ModifyGlobalTeamCount( team, 1 );
ModifyTeamCount( team, 1 );
ModifyGroupCount( type, 1 );
}
virtual void OnGameObjectAboutToDestroy( IGameObject* pGameObject )
{
EGameTeam team = pGameObject->GetGameTeam();
EGameObject type = pGameObject->GetGameObjectType();
ModifyGlobalTeamCount( team, -1 );
ModifyTeamCount( team, -1 );
ModifyGroupCount( type, -1 );
DestroyBlackboardIndividual(pGameObject->GetObjectId());
DestroyBlackboardIndividualCommon(pGameObject->GetObjectId());
}
// ~IGameEventListener
// IBlackboardManager
virtual IBlackboard* GetBlackboardGlobal() const
{
return m_pBlackboardGlobal;
}
virtual IBlackboard* GetBlackboardTeam( EGameTeam team ) const
{
IBlackboard* pBlackboard = 0;
if (m_BlackboardTeam[team].IsValid())
{
IObjectUtils::GetObject( &pBlackboard, m_BlackboardTeam[team] );
}
return pBlackboard;
}
virtual IBlackboard* GetBlackboardGroup( EGameObject type ) const
{
IBlackboard* pBlackboard = 0;
if (m_BlackboardGroup[type].IsValid())
{
IObjectUtils::GetObject( &pBlackboard, m_BlackboardGroup[type] );
}
return pBlackboard;
}
virtual IBlackboard* GetBlackboardIndividual( const IGameObject* pGameObject ) const
{
IBlackboard* pBlackboard = 0;
TIndividualMap::const_iterator it = m_BlackboardIndividual.find( pGameObject->GetObjectId() );
if (it != m_BlackboardIndividual.end())
{
IObjectUtils::GetObject( &pBlackboard, it->second );
}
return pBlackboard;
}
virtual IBlackboard* GetBlackboardIndividualCommon( const IGameObject* pGameObject ) const
{
IBlackboard* pBlackboard = 0;
TIndividualMap::const_iterator it = m_BlackboardIndividualCommon.find( pGameObject->GetObjectId() );
if (it != m_BlackboardIndividualCommon.end())
{
IObjectUtils::GetObject( &pBlackboard, it->second );
}
return pBlackboard;
}
virtual void ResetBlackboards()
{
DestroyAllBlackboards();
CreateSharedBlackboards();
}
// ~IBlackboardManager
private:
void CreateSharedBlackboards()
{
// Global
AU_ASSERT(!m_pBlackboardGlobal);
IObjectUtils::CreateObject( &m_pBlackboardGlobal, "BB_Global" );
// Team
m_BlackboardTeam[EGT_IMMUNE] = IObjectUtils::CreateObject( "BB_Team_Immune" )->GetObjectId();
m_BlackboardTeam[EGT_INFECTION] = IObjectUtils::CreateObject( "BB_Team_Infection" )->GetObjectId();
// Group
m_BlackboardGroup[EGO_WBC] = IObjectUtils::CreateObject( "BB_Group_WBC" )->GetObjectId();
m_BlackboardGroup[EGO_RBC] = IObjectUtils::CreateObject( "BB_Group_RBC" )->GetObjectId();
m_BlackboardGroup[EGO_VIRUS] = IObjectUtils::CreateObject( "BB_Group_Virus" )->GetObjectId();
m_BlackboardGroup[EGO_INFECTED] = IObjectUtils::CreateObject( "BB_Group_Infected" )->GetObjectId();
}
void CreateIndividualBlackboards( IGameObject* pGameObject )
{
ObjectId id = pGameObject->GetObjectId();
// Individual
TIndividualMap::iterator it = m_BlackboardIndividual.find(id);
AU_ASSERT(it == m_BlackboardIndividual.end());
if (it == m_BlackboardIndividual.end())
{
const char* text = 0;
switch (pGameObject->GetGameObjectType())
{
case EGO_WBC: text = "BB_Individual_WBC"; break;
case EGO_RBC: text = "BB_Individual_RBC"; break;
case EGO_VIRUS: text = "BB_Individual_Virus"; break;
case EGO_INFECTED: text = "BB_Individual_Infected"; break;
default: AU_ASSERT(false);
}
m_BlackboardIndividual[id] = IObjectUtils::CreateObject( text )->GetObjectId();
}
// IndividualCommon
it = m_BlackboardIndividualCommon.find(id);
AU_ASSERT(it == m_BlackboardIndividualCommon.end());
if (it == m_BlackboardIndividualCommon.end())
{
m_BlackboardIndividualCommon[id] = IObjectUtils::CreateObject( "BB_Individual_Common" )->GetObjectId();
}
}
void DestroyBlackboardIndividual( ObjectId id )
{
TIndividualMap::iterator it = m_BlackboardIndividual.find(id);
if (it != m_BlackboardIndividual.end())
{
IObjectFactorySystem* pFactory = PerModuleInterface::g_pSystemTable->pObjectFactorySystem;
IObject* pObj = pFactory->GetObject(it->second);
delete pObj;
m_BlackboardIndividual.erase(it);
}
}
void DestroyBlackboardIndividualCommon( ObjectId id )
{
TIndividualMap::iterator it = m_BlackboardIndividualCommon.find(id);
if (it != m_BlackboardIndividualCommon.end())
{
IObjectFactorySystem* pFactory = PerModuleInterface::g_pSystemTable->pObjectFactorySystem;
IObject* pObj = pFactory->GetObject(it->second);
delete pObj;
m_BlackboardIndividualCommon.erase(it);
}
}
void DestroyAllBlackboards()
{
IObjectFactorySystem* pFactory = PerModuleInterface::g_pSystemTable->pObjectFactorySystem;
IObject* pObj = 0;
delete m_pBlackboardGlobal;
m_pBlackboardGlobal = 0;
for (int i=0; i<EGT_COUNT; ++i)
{
pObj = pFactory->GetObject(m_BlackboardTeam[i]);
delete pObj;
m_BlackboardTeam[i] = ObjectId();
}
for (int i=0; i<EGO_COUNT; ++i)
{
pObj = pFactory->GetObject(m_BlackboardGroup[i]);
delete pObj;
m_BlackboardGroup[i] = ObjectId();
}
TIndividualMap::iterator it = m_BlackboardIndividual.begin();
TIndividualMap::iterator itEnd = m_BlackboardIndividual.end();
while (it != itEnd)
{
pObj = pFactory->GetObject(it->second);
delete pObj;
++it;
}
m_BlackboardIndividual.clear();
it = m_BlackboardIndividualCommon.begin();
itEnd = m_BlackboardIndividualCommon.end();
while (it != itEnd)
{
pObj = pFactory->GetObject(it->second);
delete pObj;
++it;
}
m_BlackboardIndividualCommon.clear();
}
void ModifyTeamCount( EGameTeam team, int delta )
{
IBlackboard* pTeam = GetBlackboardTeam(team);
switch (team)
{
case EGT_IMMUNE: ((BB_Team_Immune*)pTeam)->team_size += delta; break;
case EGT_INFECTION: ((BB_Team_Infection*)pTeam)->team_size += delta; break;
default: AU_ASSERT(false);
}
}
void ModifyGroupCount( EGameObject type, int delta )
{
IBlackboard* pGroup = GetBlackboardGroup(type);
switch (type)
{
case EGO_WBC: ((BB_Group_WBC*)pGroup)->group_size += delta; break;
case EGO_RBC: ((BB_Group_RBC*)pGroup)->group_size += delta; break;
case EGO_VIRUS: ((BB_Group_Virus*)pGroup)->group_size += delta; break;
case EGO_INFECTED: ((BB_Group_Infected*)pGroup)->group_size += delta; break;
default: AU_ASSERT(false);
}
}
void ModifyGlobalTeamCount( EGameTeam team, int delta )
{
BB_Global* pBBGlobal = (BB_Global*)GetBlackboardGlobal();
if (team == EGT_IMMUNE)
{
pBBGlobal->immune_count += delta;
}
else
{
pBBGlobal->infection_count += delta;
}
}
void SetInitialCommonValues( IGameObject* pGameObject )
{
BB_Individual_Common* pCommon = (BB_Individual_Common*)GetBlackboardIndividualCommon( pGameObject );
GameObjectParams& params = m_pGlobalParameters->go[pGameObject->GetGameObjectType()];
pCommon->current_health = params.initial_health;
pCommon->max_speed = params.max_speed;
pCommon->current_position = pGameObject->GetEntity()->GetPosition();
}
// Private Members
typedef std::map<ObjectId, ObjectId> TIndividualMap;
typedef std::vector<ObjectId> TObjectList;
IGameManager* m_pGameManager;
GlobalParameters* m_pGlobalParameters;
IBlackboard* m_pBlackboardGlobal;
TObjectList m_BlackboardTeam;
TObjectList m_BlackboardGroup;
TIndividualMap m_BlackboardIndividual;
TIndividualMap m_BlackboardIndividualCommon;
};
REGISTERCLASS(BlackboardManager);
// Register all blackboard classes here, since they're defined in headers
// And we get a link error if they get registered in more than one place
REGISTERCLASS(BB_Global);
REGISTERCLASS(BB_Team_Infection);
REGISTERCLASS(BB_Team_Immune);
REGISTERCLASS(BB_Group_WBC);
REGISTERCLASS(BB_Group_Virus);
REGISTERCLASS(BB_Group_RBC);
REGISTERCLASS(BB_Group_Infected);
REGISTERCLASS(BB_Individual_Common);
REGISTERCLASS(BB_Individual_WBC);
REGISTERCLASS(BB_Individual_RBC);
REGISTERCLASS(BB_Individual_Virus);
REGISTERCLASS(BB_Individual_Infected);