ef2gamesource/dlls/game/groupcoordinator.cpp

945 lines
20 KiB
C++
Raw Normal View History

2012-12-30 16:37:54 +00:00
//-----------------------------------------------------------------------------
//
// $Logfile:: /Code/DLLs/game/groupcoordinator.cpp $
// $Revision:: 22 $
// $Author:: Steven $
// $Date:: 5/17/03 10:29p $
//
// Copyright (C) 2001 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
//------------------------------------------------------------------------------
#include "_pch_cpp.h"
#include "groupcoordinator.hpp"
#include "actor.h"
//==============================================================================
// Group
//==============================================================================
CLASS_DECLARATION( Listener, Group, "group" )
{
{ NULL, NULL }
};
//--------------------------------------------------------------
// Name: Group()
// Class: Group
//
// Description: Constructor
//
// Parameters: None
//
// Returns: None
//--------------------------------------------------------------
Group::Group()
{
}
//--------------------------------------------------------------
// Name: ~Group()
// Class: Group()
//
// Description: Destructor
//
// Parameters: None
//
// Returns: None
//--------------------------------------------------------------
Group::~Group()
{
ClearList();
}
//--------------------------------------------------------------
// Name: AddMember()
// Class: Group
//
// Description: First Checks if entity to be added is already in
// the list, if it is not, then it adds it.
// After it adds it to the list, it sets that entity's
// group number
//
// Parameters: Entity *entity
//
// Returns: None
//--------------------------------------------------------------
void Group::AddMember( Entity *entity )
{
// First Check if entity is in the list -- There might be
// a faster way to do this inside the Container Class
Entity *checkEntity;
for ( int i = 1 ; i <= _memberList.NumObjects() ; i++ )
{
checkEntity = _memberList.ObjectAt( i );
if ( !checkEntity )
continue;
if ( checkEntity == entity )
return;
}
// We didn't find a match, so we'll add it.
_memberList.AddObject( entity );
entity->SetGroupID( _id );
}
//--------------------------------------------------------------
// Name: RemoveMember( Entity *entity )
// Class: Group
//
// Description: Removes the entity from the list
//
// Parameters: Entity *entity
//
// Returns: None
//--------------------------------------------------------------
void Group::RemoveMember( Entity *entity )
{
if ( _memberList.ObjectInList( entity ) )
{
_memberList.RemoveObject( entity );
}
}
//--------------------------------------------------------------
// Name: ClearList()
// Class: Group
//
// Description: Clears the member list
//
// Parameters: None
//
// Returns: None
//--------------------------------------------------------------
void Group::ClearList()
{
_memberList.FreeObjectList();
}
//--------------------------------------------------------------
// Name: IsThisTargetNameInGroup()
// Class: Group
//
// Description: Checks if an entity with the specified target name
// is in the group
//
// Parameters: const str &name
//
// Returns: true or false
//--------------------------------------------------------------
bool Group::IsThisTargetNameInGroup( const str &name )
{
Entity *checkEntity;
str checkName;
for ( int i = 1 ; i <= _memberList.NumObjects() ; i++ )
{
checkEntity = _memberList.ObjectAt( i );
if ( !checkEntity )
continue;
if ( !stricmp( name.c_str() , checkEntity->TargetName() ) )
return true;
}
return false;
}
//--------------------------------------------------------------
// Name: IsThisEntityInGroup()
// Class: Group
//
// Description: Checks if this entity is in the group
//
// Parameters: Entity *entity
//
// Returns: true or false
//--------------------------------------------------------------
bool Group::IsThisEntityInGroup( Entity *entity )
{
Entity *checkEntity;
for ( int i = 1 ; i <= _memberList.NumObjects() ; i++ )
{
checkEntity = _memberList.ObjectAt( i );
if ( !checkEntity )
continue;
if ( checkEntity == entity )
return true;
}
return false;
}
//--------------------------------------------------------------
// Name: SendEventToGroup()
// Class: Group
//
// Description: Sends the specified event to every member of the
// group
//
// Parameters: Event *ev -- The event to send
//
// Returns: None
//--------------------------------------------------------------
void Group::SendEventToGroup( Event *ev )
{
Entity *entity;
Event *copiedEvent;
for ( int i = 1 ; i <= _memberList.NumObjects() ; i++ )
{
entity = _memberList.ObjectAt( i );
if ( !entity )
continue;
copiedEvent = new Event( ev );
entity->ProcessEvent( copiedEvent );
}
}
//--------------------------------------------------------------
// Name: SendEventToGroup()
// Class: Group
//
// Description: Sends the specified event to every member of the
// group
//
// Parameters: Event &ev -- The event to send
//
// Returns: None
//--------------------------------------------------------------
void Group::SendEventToGroup( Event &ev )
{
Entity *entity;
Event *copiedEvent;
for ( int i = 1 ; i <= _memberList.NumObjects() ; i++ )
{
entity = _memberList.ObjectAt( i );
if ( !entity )
continue;
copiedEvent = new Event( ev );
entity->ProcessEvent( copiedEvent );
}
}
//--------------------------------------------------------------
// Name: GroupCancelEventsOfType()
// Class: Group
//
// Description: Has each memeber of the group cancel its events
// of the specified type
//
// Parameters: Event *ev
//
// Returns: None
//--------------------------------------------------------------
void Group::GroupCancelEventsOfType( Event *ev )
{
Entity *entity;
for ( int i = 1 ; i <= _memberList.NumObjects() ; i++ )
{
entity = _memberList.ObjectAt( i );
if ( !entity )
continue;
entity->CancelEventsOfType( ev );
}
}
//--------------------------------------------------------------
// Name: Archive()
// Class: Group
//
// Description: Archives the class
//
// Parameters: Archive &arc
//
// Returns: None
//----------------------------------------------------------
void Group::Archive( Archiver &arc )
{
int num , i;
EntityPtr ent;
EntityPtr *entityPointer;
Listener::Archive( arc );
ent = NULL;
if ( arc.Saving() )
{
num = _memberList.NumObjects();
arc.ArchiveInteger( &num );
for ( i = 1 ; i <= num ; i++ )
{
ent = _memberList.ObjectAt( i );
arc.ArchiveSafePointer( &ent );
}
}
else
{
arc.ArchiveInteger( &num );
_memberList.ClearObjectList();
_memberList.Resize( num );
for ( i = 1 ; i <= num ; i++ )
{
_memberList.AddObject( ent );
entityPointer = &_memberList.ObjectAt( i );
arc.ArchiveSafePointer( entityPointer );
}
}
arc.ArchiveInteger( &_id );
arc.ArchiveString( &_groupDeathThread );
}
//--------------------------------------------------------------
// Name: GetNextMember()
// Class: Group
//
// Description: For return the next entity in the list after
// the entity passed in
//
// Parameters: Entity *entity -- The entity to use as a base index
//
// Returns: Entity*
//--------------------------------------------------------------
Entity* Group::GetNextMember( Entity *entity )
{
Entity *ent;
if ( _memberList.NumObjects() == 0 )
return NULL;
if ( !entity )
return _memberList.ObjectAt( 1 );
for ( int i = 1 ; i <= _memberList.NumObjects() ; i++ )
{
ent = _memberList.ObjectAt( i );
if ( i == _memberList.NumObjects() )
return NULL;
if ( ent == entity )
return _memberList.ObjectAt( i + 1 );
}
return NULL;
}
//--------------------------------------------------------------
// Name: GetPreviousMember
// Class: Group
//
// Description: Returns the entity in the list that occurs
// just previous to the entity passed in
//
// Parameters: Entity *entity
//
// Returns: Entity*
//--------------------------------------------------------------
Entity* Group::GetPreviousMember( Entity *entity )
{
Entity *ent;
if ( _memberList.NumObjects() == 0 )
return NULL;
if ( !entity )
return _memberList.ObjectAt( _memberList.NumObjects() );
for ( int i = _memberList.NumObjects() ; i > 0 ; i-- )
{
ent = _memberList.ObjectAt( i );
if ( i == 1 )
return NULL;
if ( ent == entity )
return _memberList.ObjectAt( i - 1 );
}
return NULL;
}
void Group::RunGroupDeathThread(Entity *entity)
{
if ( !_groupDeathThread.length() )
return;
ExecuteThread(_groupDeathThread, true, entity );
}
//==============================================================================
// Actor Group
//==============================================================================
CLASS_DECLARATION( Group, ActorGroup, "actorgroup" )
{
{ NULL, NULL }
};
//--------------------------------------------------------------
// Name: ActorGroup()
// Class: ActorGroup
//
// Description: Constructor
//
// Parameters: None
//
// Returns: None
//--------------------------------------------------------------
ActorGroup::ActorGroup()
{
}
//--------------------------------------------------------------
// Name: ~ActorGroup()
// Class: ActorGroup
//
// Description: Destructor
//
// Parameters: None
//
// Returns: None
//--------------------------------------------------------------
ActorGroup::~ActorGroup()
{
}
//--------------------------------------------------------------
// Name: CountMembersWithThisName( const str &name )
// Class: ActorGroup
//
// Description: Loops through the group list and returns a count
// of how many have a name that matches the passed
// in name
//
// Parameters: const str &name
//
// Returns: int
//--------------------------------------------------------------
int ActorGroup::CountMembersWithThisName( const str &name )
{
Entity *entity = 0;
Actor *actor = 0;
int count = 0;
entity = GetNextMember( entity );
if ( !entity )
return 0;
if ( !entity->isSubclassOf( Actor ) )
return 0;
while ( entity != NULL )
{
// Safeguard
if ( entity->isSubclassOf( Actor ) )
{
actor = (Actor*)entity;
if (!stricmp(name.c_str() , actor->name.c_str() ) )
count++;
}
entity = GetNextMember( entity );
}
return count;
}
//--------------------------------------------------------------
//
// Name: CountMembersAttackingEnemy
// Class: ActorGroup
//
// Description: Counts the number of actors in this group attacking
// the specified enemy. If the enemy is NULL, it counts
// all actors in this group with the ACTOR_FLAG_ATTACKING_ENEMY
// set.
//
// Parameters: Entity *enemy -- Enemy to test against
//
// Returns: int
//
//--------------------------------------------------------------
int ActorGroup::CountMembersAttackingEnemy( Entity *enemy )
{
Entity *entity = 0;
Actor *actor = 0;
int count = 0;
entity = GetNextMember( entity );
if ( !entity )
return 0;
if ( !entity->isSubclassOf( Actor ) )
return 0;
while ( entity != NULL )
{
// Safeguard
if ( entity->isSubclassOf( Actor ) )
{
// This actor isn't attacking... NEXT!
actor = (Actor*)entity;
if ( !actor->GetActorFlag(ACTOR_FLAG_ATTACKING_ENEMY) )
{
entity = GetNextMember( entity );
continue;
}
// If we were not supplied an enemy to check against, just
// increment the count, otherwise check to see if the enemy
// matches.
if ( !enemy )
count++;
else if ( actor->enemyManager->GetCurrentEnemy() == enemy )
count++;
}
entity = GetNextMember( entity );
}
return count;
}
//==============================================================================
// Group Coordinator
//==============================================================================
CLASS_DECLARATION( Listener, GroupCoordinator, "groupcoordinator" )
{
{ NULL, NULL }
};
//Global Safe Pointer
GroupCoordinatorPtr groupcoordinator;
//--------------------------------------------------------------
// Name: GroupCoordinator()
// Class: GroupCoordinator
//
// Description: Constructor
//
// Parameters: None
//
// Returns: None
//--------------------------------------------------------------
GroupCoordinator::GroupCoordinator()
{
}
//--------------------------------------------------------------
// Name: ~GroupCoordinator()
// Class: GroupCoordinator
//
// Description: Destructor
//
// Parameters: None
//
// Returns: None
//--------------------------------------------------------------
GroupCoordinator::~GroupCoordinator()
{
ClearGroupList();
}
//--------------------------------------------------------------
// Name: GetGroup()
// Class: GroupCoordinator
//
// Description: Returns a group pointer to the group with the
// specified ID
//
// Parameters: int ID
//
// Returns: Group*
//--------------------------------------------------------------
Group* GroupCoordinator::GetGroup( int ID )
{
Group *group;
group = NULL;
for ( int i = 1; i <= _groupList.NumObjects() ; i++ )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
if ( group->GetGroupID() == ID )
return group;
}
return NULL;
}
void GroupCoordinator::MemberDied( Entity *entity , int ID )
{
Group *group;
str threadName;
int i;
// Now see if the requested group exists
for ( i = 1; i <= _groupList.NumObjects() ; i++ )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
if ( group->GetGroupID() == ID )
{
if (group->CountMembers() == 1 )
{
group->RunGroupDeathThread(entity);
break;
}
}
}
RemoveEntityFromGroup( entity , ID );
}
void GroupCoordinator::SetGroupDeathThread( const str &threadName , int ID )
{
Group *group;
int i;
// Now see if the requested group exists
for ( i = 1; i <= _groupList.NumObjects() ; i++ )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
if ( group->GetGroupID() == ID )
{
group->SetGroupDeathThread( threadName );
return;
}
}
}
//--------------------------------------------------------------
// Name: AddEntityToGroup()
// Class: GroupCoordinator
//
// Description: If the group exists, it tells the the group to
// add the specified entity, if it does not exist
// a new group is created and is then told to
// add the specified entity
//
// Parameters: Entity *ent
// int ID
//
// Returns: None
//--------------------------------------------------------------
void GroupCoordinator::AddEntityToGroup( Entity *ent , int ID )
{
Group *group;
int i;
// First see if the entity is in any other group
for ( i = 1; i <= _groupList.NumObjects() ; i++ )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
if ( group->IsThisEntityInGroup( ent ) && group->GetGroupID() != ID )
group->RemoveMember( ent );
}
// Now see if the requested group exists
for ( i = 1; i <= _groupList.NumObjects() ; i++ )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
if ( group->GetGroupID() == ID )
{
group->AddMember( ent );
return;
}
}
// Group didn't already exist, so lets make a new one
group = new Group;
group->SetGroupID( ID );
group->AddMember( ent );
_groupList.AddObject( group );
}
void GroupCoordinator::RemoveEntityFromGroup( Entity *ent , int ID )
{
Group *group;
int i;
// Now see if the requested group exists
for ( i = 1; i <= _groupList.NumObjects() ; i++ )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
if ( group->GetGroupID() == ID )
{
group->RemoveMember( ent );
return;
}
}
}
//--------------------------------------------------------------
// Name: RemoveGroup()
// Class: GroupCoordinator
//
// Description: Removes a group from the group list
//
// Parameters: int ID
//
// Returns: None
//--------------------------------------------------------------
void GroupCoordinator::RemoveGroup( int ID )
{
Group *group;
for ( int i = _groupList.NumObjects(); i > 0 ; i-- )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
if ( group->GetGroupID() == ID )
{
_groupList.RemoveObjectAt( i );
delete group;
group = NULL;
return;
}
}
}
//--------------------------------------------------------------
// Name: ClearGroupList()
// Class: GroupCoordinator
//
// Description: Clears the Group List
//
// Parameters: None
//
// Returns: None
//--------------------------------------------------------------
void GroupCoordinator::ClearGroupList()
{
Group *group;
for ( int i = _groupList.NumObjects(); i > 0 ; i-- )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
RemoveGroup( group->GetGroupID() );
}
}
//--------------------------------------------------------------
// Name: SendEventToGroup
// Class: GroupCoordinator
//
// Description: Sends the specified event to the group
// so that the group will send it to everyone. This function
// always deletes the original event when it's done with it.
//
// Parameters: Event *ev
// int ID
//
// Returns: None
//--------------------------------------------------------------
void GroupCoordinator::SendEventToGroup( Event *ev , int ID)
{
Group *group;
if ( !ev )
return;
for ( int i = 1; i <= _groupList.NumObjects() ; i++ )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
if ( group->GetGroupID() == ID )
{
group->SendEventToGroup( ev );
break;
}
}
// Clean up the event;
delete ev;
ev = NULL;
}
//--------------------------------------------------------------
// Name: SendEventToGroup
// Class: GroupCoordinator
//
// Description: Sends the specified event to the group
// so that the group will send it to everyone
//
// Parameters: Event &ev
// int ID
//
// Returns: None
//--------------------------------------------------------------
void GroupCoordinator::SendEventToGroup( Event &ev , int ID )
{
Group *group;
for ( int i = 1; i <= _groupList.NumObjects() ; i++ )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
if ( group->GetGroupID() == ID )
{
group->SendEventToGroup( ev );
return;
}
}
}
//--------------------------------------------------------------
// Name: GroupCancelEventsOfType()
// Class: GroupCoordinator
//
// Description: Gets the appropriate group, and has the
// group cancel events of the specified type
//
// Parameters: Event *ev
// int ID
//
// Returns: None
//--------------------------------------------------------------
void GroupCoordinator::GroupCancelEventsOfType( Event *ev , int ID )
{
Group *group;
if ( !ev )
return;
for ( int i = 1; i <= _groupList.NumObjects() ; i++ )
{
group = _groupList.ObjectAt( i );
if ( !group )
continue;
if ( group->GetGroupID() == ID )
{
group->GroupCancelEventsOfType( ev );
break;
}
}
delete ev;
}
//--------------------------------------------------------------
// Name: Archive()
// Class: GroupCoordinator
//
// Description: Archives the class
//
// Parameters: Archiver &arc
//
// Returns: None
//----------------------------------------------------------
void GroupCoordinator::Archive( Archiver &arc )
{
int num , i;
Group *group;
//Group **groupPointer;
Listener::Archive( arc );
group = NULL;
if ( arc.Saving() )
{
num = _groupList.NumObjects();
arc.ArchiveInteger( &num );
for ( i = 1 ; i <= num ; i++ )
{
group = _groupList.ObjectAt( i );
arc.ArchiveObject( group );
}
}
else
{
arc.ArchiveInteger( &num );
_groupList.ClearObjectList();
_groupList.Resize( num );
for ( i = 1 ; i <= num ; i++ )
{
group = new Group;
_groupList.AddObject( group );
arc.ArchiveObject( group );
}
}
}