This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Commando/vendor.cpp

498 lines
14 KiB
C++

/*
** 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 <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** 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 : Commmando *
* *
* $Archive:: /Commando/Code/Commando/vendor.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/28/02 11:17a $*
* *
* $Revision:: 23 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "vendor.h"
#include "gameobjmanager.h"
#include "playerdata.h"
#include "soldier.h"
#include "playertype.h"
#include "combat.h"
#include "powerup.h"
#include "refinerygameobj.h"
#include "vehiclefactorygameobj.h"
#include "definitionmgr.h"
#include "vehicle.h"
#include "combatchunkid.h"
#include "cnetwork.h"
#include "purchaserequestevent.h"
#include "purchasesettings.h"
#include "teampurchasesettings.h"
#include "weaponbag.h"
#include "weapons.h"
#include "purchaseresponseevent.h"
////////////////////////////////////////////////////////////////
// Namespaces
////////////////////////////////////////////////////////////////
using namespace BuildingConstants;
////////////////////////////////////////////////////////////////
//
// Purchase_Vehicle
//
////////////////////////////////////////////////////////////////
VendorClass::PURCHASE_ERROR
VendorClass::Purchase_Vehicle
(
BaseControllerClass * base,
SoldierGameObj * player,
int cost,
int vehicle_id
)
{
PURCHASE_ERROR retval = PERR_NOT_IN_STOCK;
//
// Check to see if this vehicle is available to build
//
VehicleGameObjDef *definition = NULL;
definition = (VehicleGameObjDef *)DefinitionMgrClass::Find_Definition (vehicle_id);
if (definition != NULL) {
PlayerDataClass *player_data = NULL;
bool has_funds = true;
//
// Check to see if the player has sufficient funds to purchase the vehicle
//
if (player != NULL && player->Get_Player_Data () != NULL) {
player_data = player->Get_Player_Data ();
has_funds = (player_data->Get_Money () >= cost);
}
if (has_funds) {
retval = PERR_NO_FACTORY;
//
// Find our vehicle factory
//
BuildingGameObj *building = base->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 the vehicle
//
if (factory->Is_Available ()) {
float time = 5.0F * base->Get_Operation_Time_Factor ();
factory->Request_Vehicle (vehicle_id, time, player);
retval = PERR_SUCCESS;
//
// If a player is purcahsing the vehicle, then debit
// the player's account
//
if (player_data != NULL) {
player_data->Purchase_Item (cost);
}
}
}
} else {
retval = PERR_NO_FUNDS;
}
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Purchase_Powerup
//
////////////////////////////////////////////////////////////////
VendorClass::PURCHASE_ERROR
VendorClass::Purchase_Powerup
(
BaseControllerClass * base,
SoldierGameObj * player,
int cost,
int powerup_id
)
{
PURCHASE_ERROR retval = PERR_NO_FUNDS;
//
// Sanity check
//
if (player == NULL) {
return retval;
}
//
// Lookup the powerup's definition
//
DefinitionClass *definition = DefinitionMgrClass::Find_Definition (powerup_id);
if (definition != NULL && definition->Get_Class_ID () == CLASSID_GAME_OBJECT_DEF_POWERUP) {
PowerUpGameObjDef *powerup_def = reinterpret_cast<PowerUpGameObjDef *> (definition);
//
// If a player is purcahsing the powerup, then debit
// the player's account
//
bool has_funds = false;
PlayerDataClass *player_data = player->Get_Player_Data ();
if (player_data != NULL) {
//
// Try to purchase the powerup
//
has_funds = player_data->Purchase_Item (cost);
}
//
// If the player has the cash, then grant him the powerup
//
if (has_funds) {
powerup_def->Grant (player);
retval = PERR_SUCCESS;
}
} else {
retval = PERR_NOT_IN_STOCK;
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Purchase_Character
//
////////////////////////////////////////////////////////////////
VendorClass::PURCHASE_ERROR
VendorClass::Purchase_Character
(
BaseControllerClass * base,
SoldierGameObj * player,
int cost,
int definition_id
)
{
PURCHASE_ERROR retval = PERR_NO_FUNDS;
//
// Sanity check
//
if (player == NULL) {
return retval;
}
//
// Check to see if the player has sufficient funds to purchase the upgrade
//
PlayerDataClass *player_data = player->Get_Player_Data ();
bool has_funds = (player_data->Get_Money () >= cost);
if (has_funds) {
retval = PERR_NO_FACTORY;
//
// Check to see if our soldier factory is operational
//
BuildingGameObj *building = base->Find_Building (TYPE_SOLDIER_FACTORY);
if ((building != NULL && building->Is_Destroyed () == false) || cost == 0) {
//
// Lookup the new definition for the soldier
//
DefinitionClass *definition = DefinitionMgrClass::Find_Definition (definition_id);
if (definition != NULL && definition->Get_Class_ID () == CLASSID_GAME_OBJECT_DEF_SOLDIER) {
//
// Upgrade the player
//
SoldierGameObjDef *soldier_def = reinterpret_cast<SoldierGameObjDef *> (definition);
player->Re_Init (*soldier_def);
player->Post_Re_Init();
retval = PERR_SUCCESS;
//
// Debit the player's account
//
player_data->Purchase_Item (cost);
}
}
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Purchase_Powerup
//
////////////////////////////////////////////////////////////////
VendorClass::PURCHASE_ERROR
VendorClass::Purchase_Item
(
SoldierGameObj * player,
PURCHASE_TYPE type,
int item_index,
int alt_skin_index,
bool is_from_server
)
{
PURCHASE_ERROR retval = PERR_NO_FUNDS;
//
// Sanity check
//
if (player == NULL) {
return retval;
}
if (CombatManager::I_Am_Server () == false) {
//
// Request this purchase from the server
//
cPurchaseRequestEvent *purchase_request = new cPurchaseRequestEvent;
purchase_request->Init (type, item_index, alt_skin_index);
//
// Let the user know the operation is pending
//
retval = PERR_OPERATION_PENDING;
} else {
//
// Determine which base controller to purchase from
//
BaseControllerClass *base = NULL;
if (player->Get_Player_Type () == PLAYERTYPE_NOD) {
base = BaseControllerClass::Find_Base ( PLAYERTYPE_NOD );
} else {
base = BaseControllerClass::Find_Base ( PLAYERTYPE_GDI );
}
//
// Lookup information about this purchase
//
int cost = 0;
int definition_id = 0;
Get_Merchandise_Information (player, type, item_index, alt_skin_index, cost, definition_id);
//
// Cost is doubled if the base isn't powered
//
//if (base != NULL && base->Is_Base_Powered () == false) {
if (type != TYPE_BEACON && base != NULL && base->Is_Base_Powered () == false) {
cost = cost * 2;
}
if (type == TYPE_CHARACTER || type == TYPE_ENLISTED_CHARACTER || type == TYPE_SECRET_CHARACTER) {
//
// Purchase the character
//
retval = Purchase_Character (base, player, cost, definition_id);
} else if (type == TYPE_VEHICLE || type == TYPE_SECRET_VEHICLE) {
//
// Purchase the vehicle
//
retval = Purchase_Vehicle (base, player, cost, definition_id);
} else if (type == TYPE_BEACON) {
//
// Purchase the beacon powerup
//
retval = Purchase_Powerup (base, player, cost, definition_id);
} else if (type == TYPE_SUPPLY) {
//
// Grant full health, armor and ammo
//
Grant_Supplies (player);
retval = PERR_SUCCESS;
}
//
// Send the response to the server locally as necessary
//
if (is_from_server) {
cPurchaseResponseEvent *event = new cPurchaseResponseEvent;
event->Init ((int)retval, cNetwork::Get_My_Id ());
}
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Grant_Supplies
//
////////////////////////////////////////////////////////////////
void
VendorClass::Grant_Supplies (SoldierGameObj *player)
{
//
// Grant ammo
//
WeaponBagClass *weapon_bag = player->Get_Weapon_Bag ();
for (int weapon_index = 0; weapon_index < weapon_bag->Get_Count (); weapon_index ++) {
WeaponClass *weapon = weapon_bag->Peek_Weapon (weapon_index);
if (weapon != NULL && weapon->Get_Definition ()->CanReceiveGenericCnCAmmo) {
//
// Restore full ammo
//
weapon->Set_Inventory_Rounds (weapon->Get_Definition ()->MaxInventoryRounds);
weapon->Set_Clip_Rounds (weapon->Get_Definition ()->ClipSize);
}
}
//
// Grant full health and armor
//
DefenseObjectClass *defense_obj = player->Get_Defense_Object ();
defense_obj->Set_Health (defense_obj->Get_Health_Max ());
defense_obj->Set_Shield_Strength (defense_obj->Get_Shield_Strength_Max ());
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Merchandise_Information
//
////////////////////////////////////////////////////////////////
void
VendorClass::Get_Merchandise_Information
(
SoldierGameObj * player,
PURCHASE_TYPE type,
int item_index,
int alt_skin_index,
int & cost,
int & definition_id
)
{
//
// Determine which team to use...
//
PurchaseSettingsDefClass::TEAM team = PurchaseSettingsDefClass::TEAM_GDI;
if (player->Get_Player_Type () == PLAYERTYPE_NOD) {
team = PurchaseSettingsDefClass::TEAM_NOD;
}
//
// Lookup the definition
//
if (type == TYPE_CHARACTER || type == TYPE_VEHICLE) {
//
// Determine which purchase type to use
//
PurchaseSettingsDefClass::TYPE purchase_type = PurchaseSettingsDefClass::TYPE_CLASSES;
if (type == TYPE_VEHICLE) {
purchase_type = PurchaseSettingsDefClass::TYPE_VEHICLES;
}
//
// Lookup the information from this purchase definition
//
PurchaseSettingsDefClass *definition = PurchaseSettingsDefClass::Find_Definition (purchase_type, team);
if (definition != NULL) {
cost = definition->Get_Cost (item_index);
//
// Either get the default skin or the alternate skin
//
if (alt_skin_index != -1) {
definition_id = definition->Get_Alt_Definition (item_index, alt_skin_index);
} else {
definition_id = definition->Get_Definition (item_index);
}
}
} else if (type == TYPE_SECRET_CHARACTER || type == TYPE_SECRET_VEHICLE) {
//
// Only allow cheats in non-laddered games!
//
if (The_Game()->IsLaddered.Is_False()) {
//
// Determine which purchase type to use
//
PurchaseSettingsDefClass::TYPE purchase_type = PurchaseSettingsDefClass::TYPE_SECRET_CLASSES;
if (type == TYPE_SECRET_VEHICLE) {
purchase_type = PurchaseSettingsDefClass::TYPE_SECRET_VEHICLES;
}
//
// Lookup the information from this purchase definition
//
PurchaseSettingsDefClass *definition = PurchaseSettingsDefClass::Find_Definition (purchase_type, team);
if (definition != NULL) {
cost = definition->Get_Cost (item_index);
definition_id = definition->Get_Definition (item_index);
}
}
} else if (type == TYPE_ENLISTED_CHARACTER) {
//
// For enlisted characters, lookup the team purchase definition
//
cost = 0;
TeamPurchaseSettingsDefClass *definition = TeamPurchaseSettingsDefClass::Get_Definition ((TeamPurchaseSettingsDefClass::TEAM)team);
if (definition != NULL) {
definition_id = definition->Get_Enlisted_Definition (item_index);
}
} else if (type == TYPE_BEACON) {
//
// For beacons, lookup the team purchase definition
//
TeamPurchaseSettingsDefClass *definition = TeamPurchaseSettingsDefClass::Get_Definition ((TeamPurchaseSettingsDefClass::TEAM)team);
if (definition != NULL) {
cost = definition->Get_Beacon_Cost ();
definition_id = definition->Get_Beacon_Definition ();
}
}
return ;
}