/* ** 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 : 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 (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 (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 ; }