Jump to content

[Tutorial] Mutating the Purchase System


NodSaibot

Recommended Posts

  • Totem Arts Staff

For this tutorial, it is expected that you have at least a little bit of knowledge of UScript and programming.

There are many reasons you may want to change, interact with or edit the Purchase System. A few good examples would be to add new vehicles, replacing the vehicles with custom versions or for changing prices. 

The recent patch has made adding new vehicles slightly easier than before. For this specific example, I will be showing you 2 different classes for a single mutator. Our first class will be the "main" class, which will replace the original Purchase System, with a new one. The second class will be the extended Purchase System.

Replacing the PurchaseSystem class in the game is actually quite easy. All you need to do is use the CheckReplacement function.

class Rx_Mutator_NewPurchaseSystem extends Rx_Mutator;

function bool CheckReplacement(Actor Other)
{ 	
	if(Other.IsA('Rx_TeamInfo')) 
	{ 
		Rx_Game(WorldInfo.Game).PurchaseSystem = class'Rx_NewPurchaseSystem'; 
	} 
	return true;
}

No real fancy work is done here, it's very self explanatory.

We will look at Rx_PurchaseSystem and search for the things we need to change to get the results we want. We are going to:

  • change the price of items (beacon, airstrike and repair tool)
  • replace a vehicle
  • give ion cannon beacons to Nod

Most of this starts at the DefaultProperties. The classes that can be purchased are defined here. However, the prices for the items are controlled via config files. We will be using the DefaultProperties instead of a config file for prices, for the sake of simplicity. However, if this was a mutator, it would be advised to set it via config, as this would allow you to change the price in the config file, instead of creating a whole new version of the mutator.

For the vehicles, all we need to do is change one of the items in the arrays of NodVehicleClasses or GDIVehicleClasses. We will also replace the Nuclear Strike beacon with the Ion Cannon Strike beacon. However, the button for Nod will still be the nuke, they'll just receive the ion beacon. Unfortunately, items do not have PTInfos, and the way they are displayed is hard coded in a HUD class, and I don't care to go into that sort of detail for this tutorial.

var array<class<Rx_Vehicle_PTInfo> > NewNodVehicles;

simulated event PostBeginPlay()
{
    super.PostBeginPlay();
  
    ReplaceVehicleClasses();
    GiveNodIonCannon();
}

simulated function ReplaceVehicleClasses() {
    for(i=0; i < NewNodVehicles.Length; i++)
        NodVehicleClasses[i] = NewNodVehicles[i];
}

simulated function GiveNodIonCannon() {
    NodItemClasses[0] = class'Rx_Weapon_IonCannonBeacon'
}

DefaultProperties
{
    NewNodVehicles[0]   = class'RenX_Game.Rx_Vehicle_Nod_Buggy_PTInfo'
    NewNodVehicles[1]   = class'RenX_Game.Rx_Vehicle_Nod_APC_PTInfo'
    NewNodVehicles[2]   = class'RenX_Game.Rx_Vehicle_Nod_Artillery_PTInfo'
    NewNodVehicles[3]   = class'RenX_Game.Rx_Vehicle_Nod_FlameTank_PTInfo'
    NewNodVehicles[4]   = class'Rx_NewPurchaseSystem.Rx_Vehicle_Nod_LightTank_PTInfo' // Assuming these 2 classes exist in your mutator
    NewNodVehicles[5]   = class'Rx_NewPurchaseSystem.Rx_Vehicle_Nod_StealthTank_PTInfo'
    NewNodVehicles[6]   = class'RenX_Game.Rx_Vehicle_Nod_Chinook_PTInfo'
    NewNodVehicles[7]   = class'RenX_Game.Rx_Vehicle_Nod_Apache_PTInfo'
}

To break this down quickly, we call ReplaceVehicleClasses in PostBeginPlay because the function UpdateMapSpecificVehicleClasses is called there, and if the map has different than default vehicles, it would override our custom vehicle classes. Also note how super is called before we call our function, so that ReplaceVehicleClasses will be called after UpdateMapSpecificVehicleClasses.

ReplaceVehicleClasses is just a simple for loop that calls the NodVehicleClasses array from the default properties.

 

To change the prices, all we need to do is define a new array of prices and change the function that is called to get the prices. 

var int NewGDIItemPrices[8];
var int NewNodItemPrices[8];

simulated function int GetItemPrices(byte teamID, int charid)
{
	if (teamID == TEAM_GDI)
		return NewGDIItemPrices[charid];
	else
		return NewNodItemPrices[charid];
}

DefaultProperties
{
	NewGDIItemPrices[0] = 700 // (Beacon)
	NewGDIItemPrices[1] = 400 // (Airstrike)
	NewGDIItemPrices[2] = 0 // (Repair Tool)
	NewGDIItemPrices[3] = 150 
	NewGDIItemPrices[4] = 150 
	NewGDIItemPrices[5] = 200 
	NewGDIItemPrices[6] = 300 
	NewGDIItemPrices[7] = 300 

	NewNodItemPrices[0] = 1500 // (Beacon)
	NewNodItemPrices[1] = 2000 // (Airstrike)
	NewNodItemPrices[2] = 100 // (Repair Tool)
	NewNodItemPrices[3] = 150
	NewNodItemPrices[4] = 150
	NewNodItemPrices[5] = 200
	NewNodItemPrices[6] = 300
	NewNodItemPrices[7] = 300
}

This is also extremely cut and dry. Simply define new prices and overwrite the original function with one that returns the prices from your new array. Only worry about the first 3 , the last 5 aren't used for anything currently. 

 

You will need to combine the last 2 code blocks into 1 class, Rx_NewPurchaseSystem

class Rx_NewPurchaseSystem extends Rx_PurchaseSystem;
...

 

Feel free to ask any questions if you don't understand something, or if it doesn't compile/work for you.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...