Loot and Resources
What is battle loot?
In the City Building Kit battles, like popular free-to-play strategy games, players gain resources when attacking other player bases.
This resource gained is called loot, because it's removed -- stolen -- from the enemy player's base. When the enemy player downloads their base from the server, they'll also download the battle results file which updates them on the result of the battle that occurred while they were gone and deduct the resources lost from their total resources.
That's why it's important to build defense structures to prevent players from stealing more of their loot resources.
How do players get loot?
Players get loot during battle. By default, attacking any building awards loot. If you would like to restrict gaining loot to only certain special buildings in your game, read below for how to change this function.
Do players actually lose their resources when attacked?
Yes, the Script/Save/SaveLoadWWW.cs has a function called DownloadMyMapAttack() which is triggered when downloading the users map using the Server Load function.
DownloadMyMapAttack() checks the server for a battle results file to see if there was an attack while the player was gone - and if there was a battle, it sends the results file to Scripts/Save/SaveLoadMap.cs LoadAttackFromServer() which processes the battle results and remove the resources the player lost during battle when the game loads.
Here is an excerpt of that function:
// Excerpt from SaveLoadWWW.cs
// Checks the server for a battle results file
// and if it exists, sends it to SaveLoadMap.cs LoadAttackFromServer()
// to process the battle results and show the user the attack menu
IEnumerator DownloadMyMapAttack()
{
WWWForm form = new WWWForm();
form.AddField("savefile","file");
// Connect to the online server scripts which sync all player and battle data
// If you don't have these server scripts yet, please contact
// us to get download access to CityBuildingKit.com/download
// and get your copy of the server scripts
//
WWW w2 = new WWW(serverAddress + matchAddress + "?get_user_map=1&mapid=" + myMapIDCode + attackExt+"&license="+license);
yield return w2;
if(w2.error != null)
{
// If a problem connecting online
((Messenger)statusMsg).DisplayMessage("Attack file download failed.");
print("Server load error" + w2.error);
}
else
{
//then if the retrieval was successful, validate its content to ensure the map file integrity is intact
if(w2.text != null && w2.text != "")
{
if(w2.text.Contains("###StartofFile###") && w2.text.Contains("###EndofFile###"))
{
// There was a battle file found, and it has the correct formatting
// So process what is inside and show the attack results menu
//
print ( "Your map ID "+ myMapIDCode + attackExt +" contents are: \n\n" + w2.text);
WriteMyMapAttackFromServer(w2.text);
((SaveLoadMap)saveLoadMap).LoadAttackFromServer();
StartCoroutine("EraseAttackFromServer");
((Messenger)statusMsg).DisplayMessage("Attack results downloaded.");
}
else
{
// In case an error occurs during download, we will print out
// the materials in the Unity console for you to troubleshoot
print ( "Your map file is invalid. Contents are: \n\n" + w2.text);
//although file is broken, prints the content of the retrieved file
((Messenger)statusMsg).DisplayMessage("Attack results corrupted. Download failed.");
}
}
else
{
print ( "Attack file is empty");
((Messenger)statusMsg).DisplayMessage("Your town was not attacked.");
}
}
}
The following function LoadAttackFromServer() in Scripts/Save/SaveLoadMap.cs is called by Scripts/Save/SaveLoadWWW.cs when DownloadMyMapAttack() downloads a battle attack file.
As mentioned above, LoadAttackFromServer() processes the battle results and remove the resources the player lost during battle when the game loads.
// The following functions parse the battle results from the server
// and remove the resources from the player's base
// Then afterwards opens the Damage Panel to show the total damage
public void LoadAttackFromServer()
{
// StreamReader
sReader = new StreamReader(filePath + fileNameAttack + fileExt);
// Now we call the AttackDamage function does all of the processing
AttackDamage (sReader);
}
// The following AttackDamage function will read the battle data
// and remove the resources
private void AttackDamage(StreamReader sReader)
{
currentLine = "";
currentLine = sReader.ReadLine();//skip header
currentLine = sReader.ReadLine();//read gold/mana
string[] losses = currentLine.Split(","[0]);
// Parse the battle results for the total
int goldLost = int.Parse(losses[0]);
int manaLost = int.Parse(losses[1]);
int buildingsLost = int.Parse(losses[2]);
int unitsLost = int.Parse(losses[3]);
// Nothing was lost during the battle, so we don't need to deduct resources
if (goldLost == 0 && manaLost == 0)
{
return;//the file exists, but has been loaded and reset
}
// Else, resources were lost so we will set the Attack damage panel data
// And update the UI.
goldLostLb.text = goldLost.ToString ();
manaLostLb.text = manaLost.ToString ();
buildingsLostLb.text = buildingsLost.ToString ();
unitsLostLb.text = unitsLost.ToString ();
((Stats)stats).gold -= goldLost;
((Stats)stats).mana -= manaLost;
((Stats)stats).UpdateUI();
//menuMain.OnCloseSettings();
StartCoroutine("ActivateDamagePanel");
}
If there was resources lost, the user will see a "Attack Damage" panel when the game loads from the server. Should the game take longer to load and the player already has another menu open, this attack results panel will show once the player has closed the menu or finished the task they are doing.
// SaveLoadMap.cs
// Show the attack results panel
// keeps trying to launch the damage panel, waiting fot the user to finish other tasks, if any
// otherwise the panel is superimposed on other panels
private IEnumerator ActivateDamagePanel()
{
yield return new WaitForSeconds (2);
if(!((Relay)relay).pauseInput)
{
//((Relay)relay).pauseInput = true;
if(GhostHelper.activeSelf){ ((GhostHelper)ghostHelper).ResetHelper();}
menuMain.OnDamage();
}
else
StartCoroutine("ActivateDamagePanel");
}
Afterwards, the function EraseAttackFromServer() in Scripts/Save/SaveLoadWWW.cs will connect to the server scripts and issue a request to erase the attack results file from the server since they were downloaded and the resources removed from the player's total.
How can I change what loot is awarded?
By default, the City Building Kit Complete Strategy Kit attacking player will receive loot based on what building they are attacking and what currency the original player paid for that building. This allows for loot to be gained from attacking every building. The PrepareLoot() function in Scripts/Helios/Helios.cs demonstrates how this is assigned.
Note: if you don't customize the PrepareLoot() function then by default, attacking any of your buildings will award the second currency (Mana) because of the following line in that function:
else
allLootMana += value;
If you would like your gameplay to model popular free-to-play strategy games and only reward loot based on attacking resource mines or resource storage buildings - then you'll want to edit the following function to only add total battle value for your resource buildings and ignore all others.
// Excerpt from Helios.cs
// Which is the main battle control script.
// The following PrepareLoot function calculates the total value of the base
// which is later used to distribute the earnings per building
private void PrepareLoot(string buidingType)
{
int i = 0;
//0 Gold 1 Mana 2 Crystals
// This is the list of buildings in the game
// To the right of each of the items in this list
// we specify what currency was used to buy them
// This is the currency that players will gain
foreach(BuildingCategoryLevels b in ShopData.Instance.BuildingsCategoryData.category){
if(b.name.Contains(buidingType)){
i = b.id;
break;
}
}
foreach(MilitaryCategoryLevels b in ShopData.Instance.MilitaryCategoryData.category){
if(b.name.Contains(buidingType)){
i = b.id;
break;
}
}
string currency = ((TransData)transData).buildingCurrency [i];
int value = ((TransData)transData).buildingValues [i];
// If you do not want to add currency for all buildings
// you will need to add an if/else below to prevent all
// building value and currency from being added to the total
BuildingValues.Add(value);
BuildingCurrency.Add(currency);
if(currency=="Gold")
allLootGold += value;
else if(currency=="Crystals")
allLootGold += value;
else
allLootMana += value;
}
And also, in the Scripts/Helios/Helios.cs Update() function you will want to edit the gain value (what the player gains in resources) to
// If you do not want to add currency for all buildings
// you will need to add an if/else below to
// gain = ... and gainPerBuilding[k] = ...
// to prevent all buildings from awarding the
// their original purchase currency assigned in PrepareLoot()
int[] gainPerBuilding = new int[Buildings.Count];//same count as Buildings
for (int i = 0; i <= instantiationGroupIndex; i++)
{
if (!pauseAttack [i] && currentDamage[i]>0)
{
int k = GetBuildingListIndex(targetBuildingIndex [i]);
//print(k.ToString());
gain = (currentDamage [i]*BuildingValues[k])/100;
gainPerBuilding[k] += gain;
BuildingsHealth [k] -= 1 * currentDamage [i];
DamageBars[k].GetComponent<UISlider>().value = BuildingsHealth [k]*0.01f;//since full building health was 100
}
}
Updated less than a minute ago