2. Designing your first Tower First, get a vJASS compiler and a World Editor (I recommend the JassNewGenPack).
Warning: The latest JNGP uses an outdated vJASS
compiler, so YouTD will no longer compile on this JNGP. You have to
update JassHelper, if you want to use it. The alternative is to download
the YouTD developement kit that also contains the latest compiler.
Then, you won't have that trouble! Just unzip the .rar archive. You will find the CCM In the folder /YouTD. It is named "YouTD_TowerTemplate <VERSION>.w3x". Open it via the NewGenWE.exe program available with the devkit download and save again. If you receive an error when saving it, you haven't met all prerequisites (you might not have vJASS for example, or maybe your vJASS compiler is too old). If you can save the map without errors we can start creating your first Tower. Save the map using another name, so the template stays untouched for other towers you will create (but don't save it in another folder, since it needs the paths for GMSI script lookup things). In YouTD, towers can level up like heros. They start at level 0 and can get up to level 25. A Tower's abilities should get stronger the higher its level is and it can even gain new abilities when it reaches a specific level. I tell you this now at the very beginning, because I will often talk about "That adds XXX per tower level" or something like that. Then you know what I mean. In addition, creeps in YouTD are sorted into categories and sizes. The categories, or races are the following
The sizes are:
The special thing about YouTD is that you can check if a creep is from a specific category/size and modify your reactions. You could make a chainlightning that hits only undeads or bosses or whatever. In addition, towers and spells have damage tables, that means they can do different damage to different sizes and categories. There could be a tower that deals 200% damage to champions or a spell that deals 150% damage to magical creeps. Cool stuff, isn't it? Okay, let's start with tower creation. In a normal TD you would have just chosen the model of your tower and that's it. But YouTD offers you the chance to combine the model of your tower from different other models in wc3. For example you could plant bushes around your main tower model. When you check the CCM, you will see a watch tower model with two braziers in front of it. If you export the tower like this, every new built tower will have these braziers in front of it. So lets see how you can combine your model. First you have to choose the main model for your tower. You do this
by entering the object editor and searching the unit "YOUR TOWER". Since
it is the only custom unit in the map, you should find it fast. This part was easy. Fortunately, creating the additional effects is also easy :). Before adding your own effects remove the braziers. They are doodads, I hope you know how to remove these from the map. Now, in your Object Editor check the "Doodads" tab. You will see one
custom doodad called !EFFECT (It starts with an exclamation mark, that
it is always on top of any doodad list and you find it fast in your
palette). When you want your own effect, derive it from !EFFECT (i.e.
copy paste !EFFECT). Choose a model and tinting for your effect. Note
that the "Minimap Color 3" value will be taken as alpha value, so if
you need transparent effects, just alter this value. The max pitch value
will be interpreted by the engine as real pitch value, so you can place
lying doodads for example. The pitch angle is in radians, it can
be set from -2 Pi (around -6.28) to + 2 PI (around 6.28). 2 Pi is a
full rotation. So for example 1 Pi (around 3.14) will make your tower
stand upside down. Note that you must hold shift while clicking on its
value to enter negative values. Further note that you won't see positive
values in the Content Creation Map (the effect will stand there like it
had pitch == 0), however the engine will do the necessary stuff, so on
the testmap, you will see the positive pitch. Now, place instances of
your effect where you want. You can scale it and also set its z value
using ctrl + page up / page down. But check if all your effects are in the region "tower"
(display regions, then you see it). Only effects in that region will be
exported. This is to ensure that your tower doesn't overuse space. Small notes:
You can also set the alpha (transparency) value of your main model by changing the @alpha value in your tower's config trigger. After you have created and placed the effects you wanted, the visuals of your tower are ready. So, lets get to its values then. (Skip this chapter for your first tower, it only explains advanced model stuff for certain towers) Besides the normal effects that were just explained, an effect doodad can also be "advanced". You set a doodad to advanced by setting its "Animate in Fog" (raw value: animInFog) field to true in the object editor. Advanced effects offer some more features than normal effects, however, some other features are not available for them. The first and main feature that advanced effects have is that they display no build animation. So they can be used for models with a long build animation. Beside to that, you can also explicitly state the animation that this effect should play. You do this by setting the "Pathing Texture" (raw: pathTex) field to the animation that you want. Hold shift while altering the field, then you can insert an arbitrary string value. For example inserting "walk" would play the walk animation for this effect. Note that you will not see this animation in the editor, only in the test map when you test your tower. You can also state the animation speed for advanced effects by setting "Visiblity Radius" (raw: visRadius) to a specific value other than 50.0 (as long as you leave it at 50.0, it will not be used). There is one limitation for advanced effects: You cannot use custom pitch for advanced effects. You can just choose the values for your tower by altering it in the object editor. However, note that certain values like the build time or requirements are forbidden to be changed, since they will be the same for all towers. After you have chosen the values for your tower (mainly for its attack and its goldcost), you have a playable tower. But that tower is boring. It needs cool abilities of course! Before I tell you how to do it let me tell you a few restrictions that had to be done: You
can just add passive abilities to your tower as you wish. They will all
be ported.
One thing now: If you have passive abilities that do damage, don't give
them to your tower. Rather create a non-timed dummy on the tower and
give it to him (see next sections for information on how to do this).
The reason for this is the following: The engine determines if a dealt
damage was spell or attackdamage just by checking WHO dealt it. It
assumes that towers never deal spell damage and dummies always deal
spell damage. So if you put that ability onto a dummy will make full use
of the spell amplification and critical system in the map's engine. If
you just put that ability plain into the tower, this system will not
work for it. Your tower may also have an active ability, which is autocasted automatically. However this is not made by really adding an ability to your tower, but by using the autocast trigger. You will see how it is done in the API section on autocasts. YouTD allows your tower to alter additional Tower Values that are controlled by the engine. Lets watch the trigger called "Modification Table" in the category "YOUR TOWER CONFIG" in your CCM first:
//This is the modification table of your tower
//You can alter it, then your tower have some values altered.
//base is the value the tower has when it is built
//add is the value that is added every time the tower gains one level
//Do not change anything here except for the values, or the script
//will not be able to parse the tower correctly.
//TO CHANGE A VALUE, UNCOMMENT THE LINE IT IS IN AND SET THE VALUE
//The values that are in this file are the default values which are applied unless you change them
//(so for example ever tower gains 5% attack damage per level (see: MOD_DAMAGE_BASE_PERC add: 0.05))
//This is NO JASS CODE, so don't enable this trigger or try to use
//any jass code as values. Use only constants, like 0.4 -0.25 or 2.5
//******** DAMAGE MODIFICATION ************
//These modify the tower's attack damage against certain categories of creeps
//Creep size
//MOD_DMG_TO_MASS base: 1.0 add: 0.0 //Mass creeps (very unhealthy)
//MOD_DMG_TO_NORMAL base: 1.0 add: 0.0 //Normal creeps (the ones that spawn in normal levels)
//MOD_DMG_TO_CHAMPION base: 1.0 add: 0.0 //Champions are larger units that spawn with normal creeps
//MOD_DMG_TO_BOSS base: 1.0 add: 0.0 //Bosses are even mightier than champions (they will probably spawn alone)
//MOD_DMG_TO_AIR base: 1.0 add: 0.0 //Flying creeps
//Creep categorization
//MOD_DMG_TO_UNDEAD base: 1.0 add: 0.0 //Undead creeps
//MOD_DMG_TO_MAGIC base: 1.0 add: 0.0 //Magical creeps
//MOD_DMG_TO_NATURE base: 1.0 add: 0.0 //Nature creeps
//MOD_DMG_TO_ORC base: 1.0 add: 0.0 //Orc creeps
//MOD_DMG_TO_HUMANOID base: 1.0 add: 0.0 //Humanoid creeps
//********* OTHER MODIFICATIONS ***********
//MOD_ATK_CRIT_CHANCE base: 0.0125 add: 0.0015 //Critical strike chance on attacks
//MOD_ATK_CRIT_DAMAGE base: 1.25 add: 0.02 //Critical strike damage on attacks
//MOD_MULTICRIT_COUNT base: 1 add: 0 //How many crits a unit can do on attack
//MOD_SPELL_CRIT_CHANCE base: 0.0125 add: 0.0015 //Critical strike chance on spell casts
//MOD_SPELL_CRIT_DAMAGE base: 1.25 add: 0.02 //Critical strike damage on spell casts
//MOD_EXP_RECEIVED base: 1.0 add: 0.0 //How much experience this tower gains
//MOD_BOUNTY_RECEIVED base: 1.0 add: 0.0 //How much bounty this tower gains
//MOD_ITEM_CHANCE_ON_KILL base: 1.0 add: 0.0 //Modifies the chance for creeps killed by this tower to drop an item
//MOD_ITEM_QUALITY_ON_KILL base: 1.0 add: 0.0 //Modifies the quality of items dropped by creeps killed by this tower
//MOD_DEBUFF_DURATION base: 1.0 add: 0.0 //Modifies the duration of negative buffs cast onto this tower
//********** PER LEVEL ONLY MODIFICATIONS *********
//MOD_ATTACKSPEED add: 0.02 //Attackspeed of this tower in %IAS per level (0.01 == 1% damage per level)
//MOD_DAMAGE_BASE add: 0.0 //Damage of this tower (1.0 == 1 damage per level)
//MOD_DAMAGE_BASE_PERC add: 0.05 //Damage % of this tower (0.01 == 1% damage per level)
//MOD_MANA add: 0.0 //Mana of this tower (1.0 == 1 mana per level)
//MOD_MANA_PERC add: 0.0 //Mana % of this tower (0.01 == 1% mana per level)
//MOD_MANA_REGEN add: 0.0 //Mana regeneration in 1/sec (2.0 == 2 mana pro sec per level regenerated)
//MOD_MANA_REGEN_PERC add: 0.0 //Mana regeneration in percent of the base regen (0.01 = 1% faster regen)
//MOD_SPELL_DAMAGE_DEALT add: 0.0 //Modifies the spell damage (0.01 == 1% bonus spell damage per level)
//MOD_TRIGGER_CHANCES add: 0.0 //Increases the chance for percentage based abilities of this tower (0.01 = 1% higher chance to trigger)
//MOD_BUFF_DURATION add: 0.0 //Duration modification for buffs cast by this tower (0.01 = 1% longer duration)
The most stuff is already explained in the comments. This table allows you to alter different values of your tower.
MOD_DMG_TO_UNDEAD base: 0.5 add: 0.1 Then the tower will only deal 50% damage to undead units at the beginning. However, for each level it gains it will deal 10% more damage to undead. So at level 5 it will deal 100% and finally at level 25 it will deal 300% damage to undead units. To be said again: The modification table is split in three main categories: This allows you to change the damage of your tower. As you can see you can alter the damage against different sizes (normal, boss,...) and against different categories (undead, mechanical, humanoid...). By just setting one of the base values to, let's say, 0.6 then your tower will deal only 60% damage to creeps of that type at the beginning. Note: The damage modifications done here will apply to both: Attack and spell damage of this tower. Here you can alter other stuff of your tower, like its crit chance and the exp/bounty it gains. You can alter additional stuff here, but as you see, you can only edit the adds, i.e. the value that is added each level. This makes sense: It is no use to alter for example the base damage of the tower in this table since you can also just alter it in the object editor. Same goes for attackspeed and mana. Okay, up to now, you didn't have the chance to create great stuff. By triggering, you will be able to do the great stuff I have promised you. Again, you will need good JASS knowledge and a bit of vJASS knowledge. So lets start. Open your trigger editor and check the folder "YOUR TOWER SCRIPT". It contains a list of deactivated triggers. Rule number 1: Only triggers that are enabled will be exported, so if you don't want to respond to an event, just leave its trigger disabled, it won't be in your final tower.
Rule number 2: If your map doesn't compile correctly in the CCM (i.e. you get an error when saving your map), then your tower will also not compile correctly in the real map. So make sure you don't get any errors when saving your map. The triggers will not work in that map as the whole API is only made of stubs there. However, upon porting the map, a test map will be created which contains running triggers and allows you to test your tower's triggers. Rule number 3: You may not use GUI globals (udg_). These will not be ported. If you need global variables put them in the globals block in the header library. As stated above you have to enable the event trigger of the event you want to catch. Let me now explain you how it works exactly.
function onXXX takes Tower tower returns nothing
endfunction This is the event handling function. It will be called whenever the specific event happens. The parameter tower is your Tower. It can be used to gather information about your tower or alter it. There are some events in which another unit is involved into the event. For these events you can call Event.getTarget(), to get the other unit that is involved in it. Event.getTarget() will get the following units for the different events:
For the events Periodic, On Level Up, On Tower Creation, On Tower Destruction Event.getTarget() is undefined since no other units are involved in these events. There are some events that need additional parameters. You have to fill in these parameters.
globals
constant real ONDAMAGE_chance = 1.0
constant real ONDAMAGE_chanceLevelAdd = 0.0
endglobals The meaning of these parameters is explained in the comments above them. So just read the comments, then you know what to fill in. You cannot use these parameters anywhere else, since they won't be in the final map and you may only use constant values for them. Now you have a coarse overview of what events you can react to. However, to start efficient coding, you should know the API, which is in the next chapter. But before introducing it to you, I would like to finish the creation of your first tower. So lets assume you wrote some event reaction, lets move on to the next step. Let's
assume you reacted to the event On Kill and gave the tower two
additional experience each time it kills a unit. A nice ability. But the
user won't see that the tower has this ability! You could now write a
dummy ability with a tooltip and give it to your tower, but that SUCKS!
Hey, we have GMSI, let the tool add that dummy ability and add a
description of this ability to the tower's tooltip! Check the event
reaction triggers. Everyone of them has a trigger comment that looks
like this: If you set visible to true, then the final tower will have a dummy explaining ability with the icon @icon, named @name and the tooltip @long_explain.
So, if you want an icon for this event that tells what it does, set visible to true, insert a path to an icon behind icon and write a text behind comment.
Note that the ability will also show up in the tower's tooltip with its @name and a shortened tooltip which should be included in @short_explain.
You can delete this text if you want (but don't delete any of the parameters below).
@visible=false
@icon=
@name=
@short_explain=
@long_explain= As already explained there, you can enable auto tooltip creation for your event reaction by setting @visible to true. Then you have to add some tooltip stuff in the comment. First insert an icon that the dummy ability that displays the tooltip for your tower will have. Just browse the WC3 icons and find a matching one. Copy&paste; its path behind icon= and don't escape any backslashes. Then give your event reaction a name, a short explanation and a long explanation. The short explanation will be put into the tower's build tooltip. The long explanation will be put as the tooltip of the dummy ability. Example:
@visible=true
@icon=ReplaceableTextures\CommandButtons\BTNInvisibility.blp
@name=Scavenger
@short_explain=This tower gains extra exp whenever it kills a creep
@long_explain=Whenever this tower kills a creep it gains 2 extra experience
Note that you shouldn't use color codes in the explanations, since the tooltips will be colored by the engine. If the previous chapters already confused you, better skip this chapter, it just adds cool stuff but isn't necessary! The balance constants table is the trigger called "Balance Constants"
in the "YOUR TOWER CONFIG" category. Open it! By default, it contains
only one test value:
@test=0.0 The format is like in the header comments for tooltips:
@NAME=VALUE You can add NAME,VALUE pairs as you wish. You can quickly change the balance of your tower with it, as its values can be used in your triggers and even in object editor fields. To make more clear what it is useful for, imagine the following ability: "A chainlightning that deals 200 damage and has a 30% chance to trigger upon each attack." If you now want to alter one of these values you have to search where they are. The 30% would be a global in the onAttack trigger, the 200 would be an Object Editor value of your chainlightning abilty. In addition you want these values also stated in the ability tooltip. As those balance constants get more, you might lose the overview what is where. Then you change one of them, but forget changing it in the tooltip, so the tooltip gets wrong. The solution: Just define them all here, and just reference them in your triggers/ObjectEditor/tooltips, then you can change the balance anytime you wish by altering just one value. Let me show you the way they work on our chainlightning example. First we would define those balance constants, so put this in the table:
@A000.DataA1=200
@chance=0.3 As you see, we wrote "A000.DataA1" assuming that the chainlightning ability has the id "A000" (DataA1 is the damage of the chainlightning). So you see, we can just write OBJECTNAME.ATTRIBUTENAME here, then the script will automatically alter these object editor values. No more changes in the Object Editor needed! What is with "chance" from the above example? We have to get it into our jass code! The solution is using the functions S2R for real values and S2I for integer values. We hand a string to them that is only the name with a leading @. So we would write
S2R("@chance") to get the value in our jass code. For our chainlightning, we would add it here (in the on attack trigger):
globals
constant real ONDAMAGE_chance = S2R("@chance")
constant real ONDAMAGE_chanceLevelAdd = 0.0
endglobals Now, the transformation script will replace it with the real chance 0.3. We have changed the values in the tooltip and in the jass code. So the last step is to insert it into our tooltip. As you should remember, the tooltip is just made by inserting the correct values into the header comment of the on attack trigger. These would look like that for our chainlightning:
@visible=true
@icon=ReplaceableTextures\PassiveButtons\PASBTNStormHammer.blp
@name=Chainlightning
@short_explain=This tower has a chance on each attack to release a chainlightning
@long_explain=This tower has a 30% chance on each attack to release 200 damage chainlightning onto the attacked creep As you can see, the numbers are still coded rawly into the comment (at line @long_explain). In EVERY STRING in the map (not only these comments, but also tooltips and jass strings!) we can use the syntax
#NAME# to insert the corresponding balance table entry, or we can use
#OBJECTNAME.ATTRIBUTENAME# to refer to the values of an object editor attribute. By adding a % behind the name, we can tell the script to treat the value as a percent value, i.e. multiply it with 100, we need this to make a 30% out of our 0.3 from the balance table. So we do this in the tooltip, the line will look like that:
@long_explain=This tower has a #chance%# chance on each attack to release #A000.DataA1# damage chainlightning onto the attacked creep Now the values will always be correct. We might want to do some calculations before writing values into our tooltip. We can do calculations between # #. Example: We want to multiply the balance value "chance" with 10
before writing it into the tooltip. So we would basically write
#chance*10#. This will not work, since chance is internally treated as a
string, not a number. So we first have to treat it as decimal number by
using (float) or as integer number by using (int). So the working
solution would be:
#(float)chance*10# This would multiply the chance with 10 and then insert the result. So if chance was 0.03, the finally displayed result would be 0.3 We can still add a percent sign at the end to make the value be
treated as percen (multiplied with 100 and added a % sign). So if we use
#(float)chance*10%# and still assume that chance was set to 0.03, the result will be 30% (0.03 * 10 = 0.3 = 30%).
This was the usage of the balance constants table. Now let's move on, to finish your first tower. One last thing you should do is filling out the "Tower Config" trigger. This is no real jass trigger but just a configuration file, that will be parsed by GMSI. Enter your name and other stuff here that the script will give you proper credits for your tower. After doing that, you are basically finished with your tower. So let's export it and test it. Save your map now. When the script creates the tower archive to upload your tower to the web page, it asks you for a .png image of your tower. Now open GMSI by executing "GMSI.jar" in the main folder. You will see a file tree in GMSI. In this tree, select your map and double click it. You will first be asked if the tower should be added to an existing test map. Hit "No" to create a new test map to test your tower. Then, you will be asked to specify an image in the .png format for your tower. Choose the screenshot you have made from your tower (check the last chapter). GMSI will export the tower and create a test map. If everything works well you will see a script output like this:
--- Executing map YouTD_TowerTemplate.w3x ---
Extracting tower...
-> Found 2 effects nearby the tower
Writing Tower to XML file: YouTD/YouTD_Tower YOUR TOWER.xml...
Opening test map...
Reading Tower from XML file...
injecting Tower into test map...
Saving test map...
DONE!
Next steps for you: Test your tower by opening YouTD/test/YouTD_Tower_Test YOUR TOWER.w3x in your WorldEdit,
saving it again(so vJass gets compiled) and then testing it. Have fun :)
--- Finished execution of YouTD_TowerTemplate.w3x. Time: 2.902 sec ---
As you can see there, a testmap was built with your tower in it in
the /YouTD/test folder named "YouTD_Tower_Test <FIRST TWELFE LETTERS
OF YOUR TOWER'S NAME>.w3x".
Open it with your Editor, save it again (that vJASS gets compiled)
and then test it. You will have a worker that is able to build your
tower. You can start test creep level by typing "spawn" in your warcraft
chat or using the ability on your worker. If your tower is working well, you have just created your first YouTD tower :). In addition to the test map, a towerarchive has been created (*.twrarc). You can upload this tower archive to the YouTD web page to get your tower into the map. However, only high quality towers are accepted, so you will need some practice to create a tower that will make its way into the map, so read on. |