/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU 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 General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/Combat/basecontroller.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 11/29/01 11:58a $*
* *
* $Revision:: 31 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "basecontroller.h"
#include "gameobjmanager.h"
#include "scriptzone.h"
#include "radar.h"
#include "vehicle.h"
#include "rendobj.h"
#include "crandom.h"
#include "playerdata.h"
#include "soldier.h"
#include "playertype.h"
#include "combat.h"
#include "powerup.h"
#include "combatchunkid.h"
#include "refinerygameobj.h"
#include "vehiclefactorygameobj.h"
#include "beacongameobj.h"
#include "spawn.h"
#include "apppackettypes.h"
#include "TranslateObj.h"
#include "TranslateDB.h"
#include "WWAudio.h"
#include "MessageWindow.h"
#include "CNCModeSettings.h"
////////////////////////////////////////////////////////////////
// Namespaces
////////////////////////////////////////////////////////////////
using namespace BuildingConstants;
////////////////////////////////////////////////////////////////
// Static member initialization
////////////////////////////////////////////////////////////////
BaseControllerClass * BaseControllerClass::CurrentBases[BuildingConstants::BASE_COUNT] = { 0 };
////////////////////////////////////////////////////////////////
//
// BaseControllerClass
//
////////////////////////////////////////////////////////////////
BaseControllerClass::BaseControllerClass (void) :
BasePowered (true),
PlayerType (PLAYERTYPE_NOD),
OperationTimeFactor (1.0F),
CanGenerateSoldiers (false),
CanGenerateVehicles (false),
IsRadarEnabled (true),
IsBaseDestroyed (false),
DidBeaconDestroyBase (false),
BeaconZone (Vector3 (0, 0, 0), Vector3 (0, 0, 0)),
AnnounceInterval(0),
AnnouncedAlliedBldgDamageTime(0.0f),
AnnouncedEnemyBldgDamageTime(0.0f),
AnnouncedAlliedVehicleDamageTime(0.0f),
AnnouncedEnemyVehicleDamageTime(0.0f)
{
Initialize_Building_List ();
Set_App_Packet_Type(APPPACKETTYPE_BASECONTROLLER);
return ;
}
////////////////////////////////////////////////////////////////
//
// ~BaseControllerClass
//
////////////////////////////////////////////////////////////////
BaseControllerClass::~BaseControllerClass (void)
{
WWASSERT ( PlayerType == PLAYERTYPE_GDI || PlayerType == PLAYERTYPE_NOD );
if (CurrentBases[PlayerType] == this) {
CurrentBases[PlayerType] = NULL;
}
Reset_Building_List ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Shutdown
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Shutdown (void)
{
Reset_Building_List ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Initialize
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Initialize (int player_type)
{
WWASSERT ( player_type == PLAYERTYPE_GDI || player_type == PLAYERTYPE_NOD );
//
// Remember which team this base belongs to
//
PlayerType = player_type;
CurrentBases[PlayerType] = this;
Set_Can_Generate_Soldiers( false );
Set_Can_Generate_Vehicles( false );
CNCModeSettingsDef* cncDef = CNCModeSettingsDef::Get_Instance();
if (cncDef) {
AnnounceInterval = cncDef->Get_Announcement_Interval();
} else {
AnnounceInterval = 0;
}
//
// Setup the network ID
//
if (PlayerType == PLAYERTYPE_GDI) {
Set_Network_ID (NETID_GDI_BASE_CONTROLLER);
} else {
WWASSERT(PlayerType == PLAYERTYPE_NOD);
Set_Network_ID (NETID_NOD_BASE_CONTROLLER);
}
Check_Base_Power ();
Set_Base_Destroyed( false );
Set_Beacon_Destroyed_Base( false );
return ;
}
////////////////////////////////////////////////////////////////
//
// Initialize_Building_List
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Initialize_Building_List (void)
{
Reset_Building_List ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Reset_Building_List
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Reset_Building_List (void)
{
//
// Simply reset the list
//
BuildingList.Delete_All ();
return ;
}
////////////////////////////////////////////////////////////////
//
// On_Building_Damaged
//
////////////////////////////////////////////////////////////////
void BaseControllerClass::On_Building_Damaged(BuildingGameObj* building)
{
const BuildingGameObjDef& def = building->Get_Definition();
// Annouce the damage report if we haven't done so recently.
if (AnnounceInterval > 0) {
if (COMBAT_STAR) {
int playersTeam = COMBAT_STAR->Get_Player_Type();
bool isAllied = (playersTeam == PlayerType);
float seconds = TimeManager::Get_Total_Seconds();
int elapsed = 0;
if (isAllied) {
elapsed = (int)(seconds - AnnouncedAlliedBldgDamageTime);
} else {
elapsed = (int)(seconds - AnnouncedEnemyBldgDamageTime);
}
if (elapsed >= AnnounceInterval) {
Play_Announcement(def.Get_Damage_Report(playersTeam));
if (isAllied) {
AnnouncedAlliedBldgDamageTime = seconds;
} else {
AnnouncedEnemyBldgDamageTime = seconds;
}
}
}
}
// Notify the team that the base is under attack
Notify_Team(BASE_UNDER_ATTACK, def.Get_Type());
}
////////////////////////////////////////////////////////////////
//
// On_Building_Destroyed
//
////////////////////////////////////////////////////////////////
void BaseControllerClass::On_Building_Destroyed(BuildingGameObj* building)
{
const BuildingGameObjDef& def = building->Get_Definition();
if (COMBAT_STAR) {
int playersTeam = COMBAT_STAR->Get_Player_Type();
Play_Announcement(def.Get_Destroy_Report(playersTeam));
}
// Let the team know that a building was destroyed
Notify_Team(BUILDING_DESTROYED, def.Get_Type ());
// Check a victory condition
if (Are_All_Buildings_Destroyed()) {
Set_Base_Destroyed(true);
}
}
////////////////////////////////////////////////////////////////
//
// On_Vehicle_Generated
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::On_Vehicle_Generated (VehicleGameObj *vehicle)
{
//
// Find our refinery (if we have one)
//
BuildingGameObj* building = Find_Building(TYPE_REFINERY);
if (building) {
RefineryGameObj* refinery = building->As_RefineryGameObj();
//
// Check to see if the refinery needs a harvester and if
// the vehicle we just generated was a harvester.
//
int def_id = vehicle->Get_Definition().Get_ID();
if (refinery->Needs_Harvester() && def_id == refinery->Get_Harvester_Def_ID()) {
refinery->Set_Harvester_Vehicle(vehicle);
}
}
return ;
}
void BaseControllerClass::On_Vehicle_Delivered(VehicleGameObj *vehicle)
{
SoldierGameObj* thePlayer = COMBAT_STAR;
bool isAllied = (thePlayer && (thePlayer->Get_Player_Type() == PlayerType));
// Only the allied player who purchased the vehicle should hear this.
if (isAllied) {
// Play unit ready report for the current player.
CNCModeSettingsDef* cncDef = CNCModeSettingsDef::Get_Instance();
if (cncDef) {
Play_Announcement(cncDef->Get_Unit_Ready_Report(PlayerType));
}
}
}
void BaseControllerClass::On_Vehicle_Damaged(VehicleGameObj* vehicle)
{
// Annouce the damage report if we haven't done so recently.
if (AnnounceInterval > 0) {
if (COMBAT_STAR) {
int playersTeam = COMBAT_STAR->Get_Player_Type();
bool isAllied = (playersTeam == PlayerType);
float seconds = TimeManager::Get_Total_Seconds();
int elapsed = 0;
if (isAllied) {
elapsed = (int)(seconds - AnnouncedAlliedBldgDamageTime);
} else {
elapsed = (int)(seconds - AnnouncedEnemyBldgDamageTime);
}
if (elapsed >= AnnounceInterval) {
const VehicleGameObjDef& def = vehicle->Get_Definition();
Play_Announcement(def.Get_Damage_Report(playersTeam));
if (isAllied) {
AnnouncedAlliedBldgDamageTime = seconds;
} else {
AnnouncedEnemyBldgDamageTime = seconds;
}
}
}
}
}
void BaseControllerClass::On_Vehicle_Destroyed(VehicleGameObj* vehicle)
{
if (COMBAT_STAR) {
const VehicleGameObjDef& def = vehicle->Get_Definition();
int playersTeam = COMBAT_STAR->Get_Player_Type();
Play_Announcement(def.Get_Destroy_Report(playersTeam));
}
}
void BaseControllerClass::On_Beacon_Armed(BeaconGameObj* beacon)
{
CNCModeSettingsDef* cncDef = CNCModeSettingsDef::Get_Instance();
if (cncDef) {
bool isNuke = beacon->Get_Definition().Is_Nuke();
if (COMBAT_STAR != NULL) {
int team = COMBAT_STAR->Get_Player_Type();
if (isNuke) {
int report = cncDef->Get_Nuke_Beacon_Deployed_Report(team);
Play_Announcement(report);
} else {
int report = cncDef->Get_Ion_Beacon_Deployed_Report(team);
Play_Announcement(report);
}
}
}
}
void BaseControllerClass::On_Beacon_Disarmed(BeaconGameObj* beacon)
{
CNCModeSettingsDef* cncDef = CNCModeSettingsDef::Get_Instance();
if (cncDef) {
bool isNuke = beacon->Get_Definition().Is_Nuke();
if (COMBAT_STAR != NULL) {
int team = COMBAT_STAR->Get_Player_Type();
if (isNuke) {
int report = cncDef->Get_Nuke_Beacon_Disarmed_Report(team);
Play_Announcement(report);
} else {
int report = cncDef->Get_Ion_Beacon_Disarmed_Report(team);
Play_Announcement(report);
}
}
}
}
void BaseControllerClass::On_Beacon_Warning(BeaconGameObj* beacon)
{
CNCModeSettingsDef* cncDef = CNCModeSettingsDef::Get_Instance();
if (cncDef) {
bool isNuke = beacon->Get_Definition().Is_Nuke();
if (COMBAT_STAR != NULL) {
int team = COMBAT_STAR->Get_Player_Type();
if (isNuke) {
int report = cncDef->Get_Nuke_Beacon_Warning_Report(team);
Play_Announcement(report);
} else {
int report = cncDef->Get_Ion_Beacon_Warning_Report(team);
Play_Announcement(report);
}
}
}
}
////////////////////////////////////////////////////////////////
//
// Are_All_Buildings_Destroyed
//
////////////////////////////////////////////////////////////////
bool
BaseControllerClass::Are_All_Buildings_Destroyed (void)
{
bool retval = true;
//
// Are all the buildings destroyed?
//
for (int index = 0; index < BuildingList.Count (); index ++) {
BuildingGameObj *building = BuildingList[index];
//
// If this building has any health left, then the base is not
// completely destroyed.
//
if (building->Is_Destroyed () == false) {
retval = false;
break;
}
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Notify_Team
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Notify_Team (Notification event, BuildingType type)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// Check_Base_Power
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Check_Base_Power (void)
{
bool is_powered = true;
// Search through each building
int count = BuildingList.Count();
for (int index = 0; index < count; ++index) {
BuildingGameObj* building = BuildingList[index];
// Is this a power-plant?
if (building->Get_Definition().Get_Type() == TYPE_POWER_PLANT) {
// The base is NOT powered if all power-plants are destoryed.
// However, the base IS powered if there are NO power plants
if (BuildingList[index]->Is_Destroyed()) {
is_powered = false;
} else {
is_powered = true;
break;
}
}
}
// Change the powered state of the base
Power_Base(is_powered);
}
////////////////////////////////////////////////////////////////
//
// Power_Base
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Power_Base (bool onoff)
{
if (CombatManager::I_Am_Server () == false) {
return ;
}
if (BasePowered != onoff) {
Set_Base_Powered( onoff );
Set_Operation_Time_Factor( BasePowered ? 1.0F : 2.0F );
//
// Switch the powered state of each building
//
for (int index = 0; index < BuildingList.Count (); index ++) {
BuildingGameObj *building = BuildingList[index];
//
// Only change the power state of this building if it makes sense
//
if ((BasePowered == false) || (building->Is_Destroyed () == false)) {
building->Enable_Power (BasePowered);
}
}
// Notify that the base
if (!BasePowered) {
const CNCModeSettingsDef* def = CNCModeSettingsDef::Get_Instance();
if (def) {
Play_Announcement(def->Get_Power_Offline_Report(PlayerType));
}
}
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Set_Operation_Time_Factor
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Set_Operation_Time_Factor (float factor)
{
OperationTimeFactor = factor;
Set_Object_Dirty_Bit( NetworkObjectClass::BIT_OCCASIONAL, true );
}
////////////////////////////////////////////////////////////////
//
// Set_Base_Powered
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Set_Base_Powered (bool onoff)
{
BasePowered = onoff;
Set_Object_Dirty_Bit( NetworkObjectClass::BIT_OCCASIONAL, true );
}
////////////////////////////////////////////////////////////////
//
// Set_Can_Generate_Soldiers
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Set_Can_Generate_Soldiers (bool onoff)
{
CanGenerateSoldiers = onoff;
Set_Object_Dirty_Bit( NetworkObjectClass::BIT_OCCASIONAL, true );
}
////////////////////////////////////////////////////////////////
//
// Set_Can_Generate_Vehicles
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Set_Can_Generate_Vehicles (bool onoff)
{
CanGenerateVehicles = onoff;
Set_Object_Dirty_Bit( NetworkObjectClass::BIT_OCCASIONAL, true );
}
////////////////////////////////////////////////////////////////
//
// Request_Harvester
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Request_Harvester (int def_id)
{
if (CombatManager::I_Am_Server () == false) {
return ;
}
//
// Find our vehicle factory
//
BuildingGameObj *building = Find_Building (TYPE_VEHICLE_FACTORY);
if (building != NULL) {
VehicleFactoryGameObj *factory = building->As_VehicleFactoryGameObj ();
//
// If we have a vehicle factory that isn't busy, then start building a harvester
//
if (factory->Is_Available ()) {
float time = 8.0F;
factory->Request_Vehicle (def_id, time * OperationTimeFactor);
}
} else {
// Find our refinery (if we have one)
//
BuildingGameObj *building = Find_Building (TYPE_REFINERY);
if (building != NULL) {
RefineryGameObj *refinery = building->As_RefineryGameObj ();
//
// If there is no vehicle factory in this level, then
// try to find a spawner that will create this type of harvester
// for us.
//
DynamicVectorClass spawner_list = SpawnManager::Get_Spawner_List ();
for (int index = 0; index < spawner_list.Count (); index ++) {
SpawnerClass *spawner = spawner_list[index];
if (spawner != NULL && spawner->Can_Spawn_Object (def_id)) {
//
// Try to spawn the harvester
//
PhysicalGameObj *new_obj = spawner->Spawn_Object (def_id);
if (new_obj != NULL && new_obj->As_VehicleGameObj () != NULL) {
refinery->Set_Harvester_Vehicle (new_obj->As_VehicleGameObj ());
break;
}
}
}
}
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Check_Radar
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Check_Radar (void)
{
bool enable_radar = false;
//
// Search through each building
//
for (int index = 0; index < BuildingList.Count (); index ++) {
BuildingGameObj *building = BuildingList[index];
//
// Is this a com center?
//
if (building->Get_Definition ().Get_Type () == TYPE_COM_CENTER) {
//
// The base has radar if there is even one active com-center
//
if (BuildingList[index]->Is_Destroyed () == false) {
enable_radar = true;
break;
}
}
}
//
// Update the radar
//
Enable_Radar (enable_radar);
return ;
}
////////////////////////////////////////////////////////////////
//
// Think
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Think (void)
{
return ;
}
////////////////////////////////////////////////////////////////
//
// Find_Building
//
////////////////////////////////////////////////////////////////
BuildingGameObj *
BaseControllerClass::Find_Building (BuildingConstants::BuildingType type)
{
BuildingGameObj *building = NULL;
//
// Search through each building
//
for (int index = 0; index < BuildingList.Count (); index ++) {
//
// Is this the type of building we are looking for?
//
if (BuildingList[index]->Get_Definition ().Get_Type () == type) {
building = BuildingList[index];
break;
}
}
return building;
}
////////////////////////////////////////////////////////////////
//
// Distribute_Funds_To_Each_Teammate
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Distribute_Funds_To_Each_Teammate (int funds)
{
//
// Only let the server assign money
//
if (CombatManager::I_Am_Server () == false) {
return ;
}
//
// Loop over all the players in the game
//
SList *list = GameObjManager::Get_Star_Game_Obj_List ();
SLNode *node = NULL;
for (node = list->Head(); node != NULL; node = node->Next()) {
SoldierGameObj *player = node->Data();
//
// Is this a player on our team?
//
if ( player != NULL &&
(player->Get_Player_Type () == PlayerType) )
{
//
// Get the data associated with this player
//
PlayerDataClass *player_data = player->Get_Player_Data ();
if (player_data != NULL) {
//
// Add the money to this player's total
//
player_data->Increment_Money (funds);
}
}
}
return ;
}
/*
////////////////////////////////////////////////////////////////
//
// Deposit_Funds
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Deposit_Funds (int funds)
{
//
// Only let the server assign money
//
if (CombatManager::I_Am_Server () == false) {
return ;
}
DynamicVectorClass team_players;
//
// Loop over all the players in the game
//
SList *list = GameObjManager::Get_Star_Game_Obj_List ();
SLNode *node = NULL;
for (node = list->Head(); node != NULL; node = node->Next()) {
SoldierGameObj *player = node->Data();
//
// Is this a player on our team?
//
if ( player != NULL &&
(player->Get_Player_Type () == PLAYERTYPE_GDI && Team == TEAM_GDI) ||
(player->Get_Player_Type () == PLAYERTYPE_NOD && Team == TEAM_NOD))
{
//
// Add the player to our list
//
team_players.Add (player);
}
}
if (team_players.Count () > 0) {
//
// Now distribute the funds to each player
//
int funds_per_player = funds / team_players.Count ();
for (int index = 0; index < team_players.Count (); index ++) {
PlayerDataClass *player_data = team_players[index]->Get_Player_Data ();
if (player_data != NULL) {
//
// Add the money to this player's total
//
player_data->Increment_Money (funds_per_player);
funds -= funds_per_player;
}
}
//
// If there is any money left over, then give it to a random teammate
//
if (funds > 0) {
index = FreeRandom.Get_Int ( team_players.Count () );
PlayerDataClass *player_data = team_players[index]->Get_Player_Data ();
if (player_data != NULL) {
//
// Add the money to this player's total
//
player_data->Increment_Money (funds);
}
}
}
return ;
}
*/
////////////////////////////////////////////////////////////////
//
// Find_Base
//
////////////////////////////////////////////////////////////////
BaseControllerClass *
BaseControllerClass::Find_Base ( int player_type )
{
BaseControllerClass *base = NULL;
//
// Try to find a base of the appropriate team in our list
//
for (int index = 0; index < BASE_COUNT; index ++) {
if (CurrentBases[index] != NULL && CurrentBases[index]->Get_Player_Type () == player_type ) {
base = CurrentBases[index];
break;
}
}
return base;
}
////////////////////////////////////////////////////////////////
//
// Find_Base_For_Star
//
////////////////////////////////////////////////////////////////
BaseControllerClass *
BaseControllerClass::Find_Base_For_Star (void)
{
int player_type = PLAYERTYPE_GDI;
if ( COMBAT_STAR != NULL ) {
player_type = COMBAT_STAR->Get_Player_Type ();
}
return Find_Base (player_type);
}
////////////////////////////////////////////////////////////////
//
// Set_Base_Destroyed
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Set_Base_Destroyed ( bool onoff )
{
IsBaseDestroyed = onoff;
Set_Object_Dirty_Bit( NetworkObjectClass::BIT_OCCASIONAL, true );
}
////////////////////////////////////////////////////////////////
//
// Destroy_Base
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Destroy_Base (void)
{
for (int index = 0; index < BuildingList.Count (); index ++) {
//
// Destroy this building
//
BuildingGameObj *building = BuildingList[index];
building->Set_Normalized_Health (0);
}
//
// Disable everything
//
Set_Base_Powered( false );
Set_Can_Generate_Soldiers( false );
Set_Can_Generate_Vehicles( false );
Set_Base_Destroyed( true );
Set_Operation_Time_Factor( 2.0F );
return ;
}
////////////////////////////////////////////////////////////////
//
// Set_Beacon_Destroyed_Base
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Set_Beacon_Destroyed_Base ( bool onoff )
{
DidBeaconDestroyBase = onoff;
Set_Object_Dirty_Bit( NetworkObjectClass::BIT_OCCASIONAL, true );
}
////////////////////////////////////////////////////////////////
//
// Add_Building
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Add_Building (BuildingGameObj *building)
{
//
// Add the building to our list (if its not already there)
//
if (building != NULL) {
if (BuildingList.ID (building) == -1) {
//
// Add the building to our list
//
building->CnC_Initialize (this);
BuildingList.Add (building);
//
// Find the beacon zone if this is the first building added...
//
if (BuildingList.Count () == 1) {
//
// Get the position of the first building in our list
//
Vector3 pos;
BuildingList[0]->Get_Position (&pos);
//
// Find the closest beacon zone to the building
//
ScriptZoneGameObj *zone = NULL;
zone = ScriptZoneGameObj::Find_Closest_Zone (pos, ZoneConstants::TYPE_BEACON);
if (zone != NULL) {
BeaconZone = zone->Get_Bounding_Box ();
//
// Get rid of the zone (if the game doesn't need it anymore)
//
if (zone->Get_Observers ().Count () == 0) {
zone->Set_Delete_Pending();
}
}
}
//
// Update the state of the base
//
Check_Base_Power ();
Check_Radar ();
}
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Import_Occasional
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Import_Occasional (BitStreamClass &packet)
{
//
// Read the state variables from the server
//
packet.Get (OperationTimeFactor);
bool wasBasePowered = BasePowered;
packet.Get(BasePowered);
packet.Get(CanGenerateSoldiers);
packet.Get(CanGenerateVehicles);
packet.Get(IsBaseDestroyed);
packet.Get(DidBeaconDestroyBase);
bool is_radar_enabled = packet.Get(is_radar_enabled);
Enable_Radar(is_radar_enabled);
// If the base was powered but now is not then report that
// power is offline.
if (wasBasePowered && !BasePowered) {
const CNCModeSettingsDef* cncDef = CNCModeSettingsDef::Get_Instance();
if (cncDef) {
Play_Announcement(cncDef->Get_Power_Offline_Report(PlayerType));
}
}
}
////////////////////////////////////////////////////////////////
//
// Export_Occasional
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Export_Occasional (BitStreamClass &packet)
{
//
// Send the state variables to the client
//
packet.Add (OperationTimeFactor);
packet.Add (BasePowered);
packet.Add (CanGenerateSoldiers);
packet.Add (CanGenerateVehicles);
packet.Add (IsBaseDestroyed);
packet.Add (DidBeaconDestroyBase);
packet.Add (IsRadarEnabled);
}
////////////////////////////////////////////////////////////////
//
// Enable_Radar
//
////////////////////////////////////////////////////////////////
void
BaseControllerClass::Enable_Radar (bool onoff)
{
if (IsRadarEnabled != onoff) {
IsRadarEnabled = onoff;
//
// Check to see if the current player belongs to this base
//
if ( COMBAT_STAR != NULL &&
(COMBAT_STAR->Get_Player_Type () == PlayerType) )
{
//
// Show or hide the radar
//
RadarManager::Set_Hidden (!IsRadarEnabled);
}
Set_Object_Dirty_Bit( NetworkObjectClass::BIT_OCCASIONAL, true );
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Harvester_Vehicle
//
////////////////////////////////////////////////////////////////
VehicleGameObj *
BaseControllerClass::Get_Harvester_Vehicle (void)
{
VehicleGameObj *retval = NULL;
//
// Find our refinery (if we have one)
//
BuildingGameObj *building = Find_Building (TYPE_REFINERY);
if (building != NULL) {
RefineryGameObj *refinery = building->As_RefineryGameObj ();
//
// Return the harvester to the caller
//
retval = refinery->Get_Harvester_Vehicle ();
}
return retval;
}
void BaseControllerClass::Play_Announcement(int text_id)
{
if (text_id == 0) {
return;
}
// Lookup the translation object from the strings database
TDBObjClass* translate_obj = TranslateDBClass::Find_Object(text_id);
if (translate_obj) {
// Display the text on the screen
const WCHAR* string = translate_obj->Get_String();
if (string) {
CombatManager::Get_Message_Window()->Add_Message(string, Vector3(1, 1, 1));
}
// Play the sound effect
int soundID = (int)translate_obj->Get_Sound_ID();
if (soundID > 0) {
WWAudioClass::Get_Instance()->Create_Instant_Sound(soundID, Matrix3D(1));
}
}
}