Defense Weapons

👍

Reminder - Keep Daily Backups

When working on a strategy game with a kit as big as the Complete Kit - always keep a working daily backup! Save yourself the trouble of rolling-back changes and losing work.

What are defense weapons?

When playing battle strategy games you'll always be able to build some sort of structure that defends your village or base from attacking players. In this case we've added a category in the store for you to place these defensive buildings.

The demo includes a few of these general buildings like the Archer tower or the Cannon. During gameplay they don't have much purpose but when you're attacking other players or other players are attacking your base - they play a huge role in defending your resources from being stolen.

686

Click to view larger.

Battle defense

During battle, defensive weapon buildings are the only ones which can actively protect your village and destroy enemy troops.

The animations for directional weapons are synchronized.
The weapons have the following states:
-Clockwise Rotation
-Counter-Clockwise Rotation
-Fire

While firing the weapons instantiate a null GameObject as a 3D reference point for the projectiles to calculate the correct direction to the target.
Basically they calculate the angle to the target and then run the rotation and fire animation. The projectiles themselves are 3D boxes. When these boxes collide with the enemy, the damage is calculated.

589

Battle defense preview.

There are six examples included in the game, however the three main examples we recommend learning from are the Cannon, Archer Tower, and Catapult.

748

Click to view larger.

Weapon settings file example (ScriptableObject - WeaponCategory)

Here's an example of the simple cannon weapon in the XML. The Assets/CityBuildingKit/Resources/Assets/WeaponCategory.asset will use these settings.

571

WeaponCategory example.

A closer look at WeaponCategory.asset above (ScriptableObject)

If you look closely in the above file, you'll see the building costs 100 of of the Gold currency. You could use whatever currency you want in your game, in the demo we have two placeholders called Gold and Mana. (Plus one rare currency called Crystal Gems)

In addition, you'll notice that like other buildings it has an HP value for battle and a time to build (measured in minutes) for construction plus a 100 XP award if the player builds this structure.

There are more interesting values to customise your weapon as you desire (damage, fire rate, etc..)

BaseCreator.cs - Where the ScriptableObject "WeaponCategory" is loaded into

In Scripts/Creators/BaseCreator.cs the building data from your SO file (seen above) is loaded using a common system for all the buildings like resource buildings, defense buildings, walls, decorations, and other buildings. Here's an excerpt from BaseCreator.cs of the SO data load:

protected void GetWeaponsXML()//reads buildings XML
	{
		List<WeaponCategoryLevels> weaponCategoryLevels = ShopData.Instance.WeaponCategoryData.category;
		List<WeaponCategory> weaponCategoryData = weaponCategoryLevels.SelectMany(level => level.levels).Where(c => c.level == _structuressWithLevel).ToList();
		
		
		foreach (WeaponCategory structureItem in weaponCategoryData)
		{
			dictionary = new Dictionary<string, string>();
			dictionary.Add("Name", structureItem.GetName()); // put this in the dictionary.
			dictionary.Add("Description", structureItem.Description); // put this in the dictionary.
			dictionary.Add("Currency", structureItem.Currency.ToString());
			dictionary.Add("Price", structureItem.Price.ToString());
			dictionary.Add("TimeToBuild", structureItem.TimeToBuild.ToString());
			dictionary.Add("HP", structureItem.HP.ToString());
			dictionary.Add("Range", structureItem.range.ToString());
			dictionary.Add("FireRate", structureItem.fireRate.ToString());
			dictionary.Add("DamageType", structureItem.damageType.ToString());
			dictionary.Add("TargetType", structureItem.targetType.ToString());
			dictionary.Add("PreferredTarget", structureItem.preferredTarget.ToString());
			dictionary.Add("DamageBonus", structureItem.damageBonus.ToString());
			dictionary.Add("XpAward", structureItem.XpAward.ToString());
			dictionary.Add("UpRatio", structureItem.UpRatio.ToString());
			structures.Add(dictionary);
		}
	}

When the data is loaded, the store panels are updated with the appropriate information.

Construction limits with XP levels

Read the Gameplay > XP and Levels documentation page for more details about how the Assets/CityBuildingKit/Resources/Assets/BuildingsCategory.asset file limits the number of certain Building structures per level. Although the following example is not a defensive weapon, it's a good example to show since the store elements all act the same.

For example, game players could have a maximum of two gold mines at level one until the player reaches level two, in which the maximum increases to five (or whatever value you choose -- read XP and Levels documentation for more details)

158

1/2 gold mines built. Maximum not reached.

161

2/2 maximum reached, can't build more

This is relevant to mention now because the menu items are greyed out for buildings that the player can no longer build until they increase their base level through other ways of gaining XP.

VerifyConditions()

Can the player build this structure? In Scripts/Creators/BaseCreator.cs the VerifyConditions() script takes over once the store button has been pushed to determine if the following conditions are met and canBuild is set to true.

VerifyConditions() Test #1 - Maximum structures reached?

First, we check if the player's level restricts the structure from being made. Have they exceeded the number of structures allowed by their level in XML/EvolutionBuildings.xml?(DEPRECATED - UNUSED) (See Gameplay > XP and Levels documentation for more information on this)

141

0 of 1 maximum structures built for the player's current level.

//max allowed structures ok?
		if (existingStructures[id] >= maxCount)//max already reached
		{					
			canBuild = false;
			MessageController.Instance.DisplayMessage("Maximum " + maxCount + 
				" structures of type " + structureName+". " + "Upgrade Summoning Circle to build more."); //displays the hint - you can have only 3 structures of this type
		}

VerifyConditions() Test #2 - Do they have enough funds?

The second test the player data must pass is their funds - do they have enough of the currency the building requires to be constructed?

//enough gold?
		if (currencyType == CurrencyType.Gold) //this needs gold
		{
			int existingGold = ((Stats)stats).gold + ((Stats)stats).deltaGoldPlus - ((Stats)stats).deltaGoldMinus;

			if (existingGold < priceOfStructure) 
			{
				canBuild = false;
				MessageController.Instance.DisplayMessage("Not enough gold.");//updates hint text
			}
		} 
		else  if (currencyType == CurrencyType.Mana)
		{
			int existingMana = ((Stats)stats).mana + ((Stats)stats).deltaManaPlus - ((Stats)stats).deltaManaMinus;

			if(existingMana < priceOfStructure)
			{
				canBuild = false;
				MessageController.Instance.DisplayMessage("Not enough mana.");//updates hint text
			}
		}
		else
		{
			int existingCrystals = ((Stats)stats).crystals + ((Stats)stats).deltaCrystalsPlus - ((Stats)stats).deltaCrystalsMinus;

			if(existingCrystals < priceOfStructure)
			{
				canBuild = false;
				MessageController.Instance.DisplayMessage("Not enough crystals.");//updates hint text
			}
		}

VerifyConditions() Test #3 - Do they have an available builder?

In the City Building Kit each building under construction takes one builder. Players get a certain number of builders to start with (default is 1 in the demo) and you can adjust this for your game. It costs extra rare gems to get additional builders like games such as Clash of Clans. (The builder hut is called a dobbit hut in the demo, read the Shop Menu > Resource Generators section on builders for more details.)

if (((Stats)stats).occupiedDobbits >= ((Stats)stats).dobbits) //dobbit available?
		{
			canBuild = false;
			MessageController.Instance.DisplayMessage("You need more dobbits.");
		}

VerifyConditions() - If all tests pass, greenlight construction.

If the player's data passes all 3 tests and canBuild still is set to true, then the script adjusts the player data awarding the XP they get from the building SO(ScriptableObject file) (if any) and deducting the costs involved from the building currency and price.

if (canBuild)
		{
			if (callback != null)
			{
				callback.Invoke();
			}
			
			
			((MenuMain)menuMain).constructionGreenlit = true;//ready to close menus and place the building; 
			//constructionGreenlit bool necessary because the command is sent by pressing the button anyway

			((Stats)stats).experience += xwAward; //incre	ases Stats experience  // move this to building finished 

			if(((Stats)stats).experience>((Stats)stats).maxExperience)
			{
				((Stats)stats).level++;
				((Stats)stats).experience-=((Stats)stats).maxExperience;
				((Stats)stats).maxExperience+=100;
			}

			//pays the gold/mana price to Stats
			if(currencyType == CurrencyType.Gold)
			{
				((Stats)stats).SubstractResources (priceOfStructure, 0, 0);
			}
			else if(currencyType == CurrencyType.Mana)
			{
				((Stats)stats).SubstractResources (0, priceOfStructure, 0);
			}
			else
			{
				
				((Stats)stats).SubstractResources (0, 0, priceOfStructure);

			}

			UpdateButtons ();//payments are made, update all

			((Stats)stats).UpdateUI();//tells stats to update the interface - otherwise new numbers are updated but not displayed

			if (!isField || buildingFields) 
			{
				if (needToDeleteBeforeUpgrade)
				{
					CancelObject();
					needToDeleteBeforeUpgrade = false;
				}
				UpdateExistingStructures (+1); //an array that keeps track of how many structures of each type exist
				InstantiateStructure (isUpgrade);
			}
		} 
		else 
		{
			((MenuMain)menuMain).constructionGreenlit = false;//halts construction - the button message is sent anyway, but ignored
		}

ConstructionGreenlit = true is sent the MenuMain script which then deactivates the store panel the player was just on and waits for the building to be placed.

((MenuMain)menuMain).constructionGreenlit = true;
// ready to close menus and place the building; 
// constructionGreenlit bool necessary because the command is sent by pressing the button anyway