Triggered Custom Spell
Spoiler:
This is my first tutorial so say if something is missing.
I did this for the people who don't know how to make triggered abilities work of course. You should know few things about triggering before doing this.
1.
First of all, create new map, size of 32x32. It should be big enough for this spell. This spell is going to be a "nova" like spell, so it needs space.
Now, go to object editor, to the Units category.
Make here the hero who casts the ability.
I created new custom unit from paladin and deleted his abilities.
2.
After that, go to Abilities category and make new custom ability from Fan of Knives. Now we need to remove missile art and effect from it. Then set damage per target and maximum total damage to 0.
I did some other changes to it that you don't need to do.
3.
Now, go to trigger editor and create new category and new trigger. Then make variables called:
Name - Type
Nova_Caster = Unit
Nova_Dummy = Unit (array 12)
Nova_Group = Unit Group
Nova_Point = Point
Nova_Angle = Real
Nova_Distance = Real
Nova_Around = Real (array 12)
After that we are going to start the triggering!
First we need event that responds to our need
Without this condition it does the actions when you cast any spell. Make sure that you put your ability to the condition
4.
Hold it! Back to object editor, to the units category! Are you going to do the nova without dummy unit? If you don't know what are dummy units I won't tell that in this tutorial. However, we are going to make one.
Now, create new unit based of a Footman and name it to Dummy Ball.
Remove all the abilites of our new dummy and add there abilities called:Invulnerable (Neutral) and Locust.
We use locust because we don't want to have dummy that you can select or dummy that stop going when wall comes to its way.
Changes in dummy:
Art - Model File = Chain Lighning <Missile.
Art - Shadow Image (Unit) = None.
Combat - Attacks Enabled = None.
Movement - Speed Base = 522
Movement - Type = Fly
Pathing - Collision Size = 0
Stats - Food Cost = 0
Stats - Sight Radius (Day) = 100
Stats - Sight Radius (Night) = 100
5.
Now the Dummy Ball should be ready for use. So, back to the trigger Editor.
Let's begin our trigger.
Now we use my style of creating dummies to the game (We use loop ).
There you see, it creates 12 balls to the point. But now we have to move the units to their own places. Just wait and read.
There you see, it moves the Dummies to their points (from 0 to 360)
360/12 = 30 and we have 12 dummies created, so now they are there "systematically". Lets continue.
Now it sets variable Nova_Around to different for all arrays. We need that variable when we are making Dummy Balls to move. Now we have to stop making this trigger for a while.
6.
Now we are making the balls to move so, create new trigger. And lets start from the event of course. Turn the Initially off for this trigger.
We are going to make the Dummy Balls to move every 0.01 second.
No conditions are needed for this trigger.
So, we can go to the actions right away:
7.
Okay, so now it moves unit away from the Nova_Point and it makes them move around it too.
That trigger is ready, but it doesn't go when you test? Of course not! Initially is off, so what we'll do now is open the first trigger. Okay.. The last thing we made to this trigger was the unpausing caster? Lets continue it:
Hold it again! That loop kills every Nova_Dummy [Every array from 1 to 12. But, something isn't right here... Oh! Memory leaks? Say idiot if im not right please! I'll show you all what I have in my pocket! Lets continue this:
8.
This have been too easy... Something is missing again, I thought that it was a perfect spell with all those long codes and things. What we have to do now is damaging? So, make new trigger again. Initially off for this trigger too.
Event for this trigger is:
We are making it to damage the enemy units every 0.05 seconds of game time.
In this trigger there are not conditions yet. Im not so sure about custom script that is waiting us in future, but say if Im not right. We use loop again to pick nearby enemy units.
This is the part where Im not sure what I do, but lets continue:
We used loop because of this... There is 12 dummies so we have to pick every nearby units of them. Continue
Okay.. So there it checks if the unit is ally of the caster or if it is magic immune. If it is either of them, then actions won't affect to them. Continue again:
That trigger is ready, now it damages all enemy units that aren't magic immunes. That damage thing is kinda simple, distance is about 600 at the end of the ability.
Level 1: 1 x (Nova_Distance / 20.00) = 30
Level 2: 2 x (Nova_Distance / 20.00) = 60
Level 3: 3 x (Nova_Distance / 20.00) = 90
The damage depends on the distance of the balls from the Nova_Point to the Dummy Balls. Now it's ready and we can go to the first trigger again.
9.
Now we have to turn on the trigger that we made and destroy group of course.
I did this for the people who don't know how to make triggered abilities work of course. You should know few things about triggering before doing this.
1.
First of all, create new map, size of 32x32. It should be big enough for this spell. This spell is going to be a "nova" like spell, so it needs space.
Now, go to object editor, to the Units category.
Make here the hero who casts the ability.
I created new custom unit from paladin and deleted his abilities.
2.
After that, go to Abilities category and make new custom ability from Fan of Knives. Now we need to remove missile art and effect from it. Then set damage per target and maximum total damage to 0.
I did some other changes to it that you don't need to do.
3.
Now, go to trigger editor and create new category and new trigger. Then make variables called:
Name - Type
Nova_Caster = Unit
Nova_Dummy = Unit (array 12)
Nova_Group = Unit Group
Nova_Point = Point
Nova_Angle = Real
Nova_Distance = Real
Nova_Around = Real (array 12)
After that we are going to start the triggering!
First we need event that responds to our need
Code: Select all
Events
Unit - Unit Starts the effect of an ability
Code: Select all
Conditions
(Ability being cast) Equal to Lighning Nova
Hold it! Back to object editor, to the units category! Are you going to do the nova without dummy unit? If you don't know what are dummy units I won't tell that in this tutorial. However, we are going to make one.
Now, create new unit based of a Footman and name it to Dummy Ball.
Remove all the abilites of our new dummy and add there abilities called:Invulnerable (Neutral) and Locust.
We use locust because we don't want to have dummy that you can select or dummy that stop going when wall comes to its way.
Changes in dummy:
Art - Model File = Chain Lighning <Missile.
Art - Shadow Image (Unit) = None.
Combat - Attacks Enabled = None.
Movement - Speed Base = 522
Movement - Type = Fly
Pathing - Collision Size = 0
Stats - Food Cost = 0
Stats - Sight Radius (Day) = 100
Stats - Sight Radius (Night) = 100
5.
Now the Dummy Ball should be ready for use. So, back to the trigger Editor.
Let's begin our trigger.
Now we use my style of creating dummies to the game (We use loop ).
Code: Select all
Actions
Wait 0.20 seconds
Set Nova_Caster = (Casting unit)
Set Nova_Point = (Position of Nova_Caster)
Set Nova_Angle = 0.00
Set Nova_Distance = 0.00
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
Code: Select all
Actions
Wait 0.20 seconds
Set Nova_Caster = (Casting unit)
Set Nova_Point = (Position of Nova_Caster)
Set Nova_Angle = 0.00
Set Nova_Distance = 0.00
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
Set Nova_Dummy[(Integer A)] = (Last created unit)
Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
Set Nova_Angle = (Nova_Angle + 30.00)
360/12 = 30 and we have 12 dummies created, so now they are there "systematically". Lets continue.
Code: Select all
Actions
Wait 0.20 seconds
Set Nova_Caster = (Casting unit)
Set Nova_Point = (Position of Nova_Caster)
Set Nova_Angle = 0.00
Set Nova_Distance = 0.00
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
Set Nova_Dummy[(Integer A)] = (Last created unit)
Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
Set Nova_Angle = (Nova_Angle + 30.00)
Unit - Pause Nova_Caster
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Set Variable Nova_Around[(Integer A)] = (Angle from (Position of Nova_Caster) to (Position of Nova_Dummy[(Integer A)]))
Wait for 0.20 seconds
Unit - Unpause Nova_Caster
6.
Now we are making the balls to move so, create new trigger. And lets start from the event of course. Turn the Initially off for this trigger.
Code: Select all
Events
Time - Every 0.01 seconds of game time
No conditions are needed for this trigger.
So, we can go to the actions right away:
Code: Select all
Actions
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Unit - Move Nova_Dummy[(Integer A)] instantly to (Nova_Point offset by Nova_Distance towards Nova_Around[(Integer A)] degrees
Set Nova_Distance = (Nova_Distance + 0.10)
Set Nova_Around[(Integer A)] = (Nova_Around[(Integer A)] + 1.00)
Okay, so now it moves unit away from the Nova_Point and it makes them move around it too.
That trigger is ready, but it doesn't go when you test? Of course not! Initially is off, so what we'll do now is open the first trigger. Okay.. The last thing we made to this trigger was the unpausing caster? Lets continue it:
Code: Select all
Actions
Wait 0.20 seconds
Set Nova_Caster = (Casting unit)
Set Nova_Point = (Position of Nova_Caster)
Set Nova_Angle = 0.00
Set Nova_Distance = 0.00
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
Set Nova_Dummy[(Integer A)] = (Last created unit)
Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
Set Nova_Angle = (Nova_Angle + 30.00)
Unit - Pause Nova_Caster
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Set Variable Nova_Around[(Integer A)] = (Angle from (Position of Nova_Caster) to (Position of Nova_Dummy[(Integer A)]))
Wait for 0.20 seconds
Unit - Unpause Nova_Caster
Trigger - Turn on "The trigger that you made a while ago" <gen>
Wait for 6.00 seconds
Trigger - Turn off "The trigger that you made a while ago" <gen>
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Unit - Kill Nova_Dummy[(Integer A)]
Code: Select all
Actions
Wait 0.20 seconds
Set Nova_Caster = (Casting unit)
Set Nova_Point = (Position of Nova_Caster)
Set Nova_Angle = 0.00
Set Nova_Distance = 0.00
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
Set Nova_Dummy[(Integer A)] = (Last created unit)
Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
Set Nova_Angle = (Nova_Angle + 30.00)
Unit - Pause Nova_Caster
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Set Variable Nova_Around[(Integer A)] = (Angle from (Position of Nova_Caster) to (Position of Nova_Dummy[(Integer A)]))
Wait for 0.20 seconds
Unit - Unpause Nova_Caster
Trigger - Turn on "The trigger that you made a while ago" <gen>
Wait for 6.00 seconds
Trigger - Turn off "The trigger that you made a while ago" <gen>
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Unit - Kill Nova_Dummy[(Integer A)]
Custom script: call RemoveLocation (udg_Nova_Point)
Set Nova_Distance = 0.00
Set Nova_Angle = 0.00
Set Nova_Caster = No unit
This have been too easy... Something is missing again, I thought that it was a perfect spell with all those long codes and things. What we have to do now is damaging? So, make new trigger again. Initially off for this trigger too.
Event for this trigger is:
Code: Select all
Events
Time - Every 0.05 seconds of game time
In this trigger there are not conditions yet. Im not so sure about custom script that is waiting us in future, but say if Im not right. We use loop again to pick nearby enemy units.
Code: Select all
For each (Integer A) from 1 to12, do (Actions)
Loop - Actions
Code: Select all
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Custom script set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 50.00 of (Position of Nova_Dummy[(Integer A)])) and do (Actions)
Code: Select all
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Custom script set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 50.00 of (Position of Nova_Dummy[(Integer A)])) and do (Actions)
Loop - Actions
Set Nova_Group = (Last created unit group)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) Magic Immune) Equal to False
((Picked unit) belongs to an ally of (Owner of Nova_Caster)) Equal to False
Code: Select all
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Custom script set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 50.00 of (Position of Nova_Dummy[(Integer A)])) and do (Actions)
Loop - Actions
Set Nova_Group = (Last created unit group)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) Magic Immune) Equal to False
((Picked unit) belongs to an ally of (Owner of Nova_Caster)) Equal to False
Then - Actions
Unit - Cause Nova_Caster to damage (Picked unit), dealing ((Real((Level of Lighning Nova for Nova_Caster))) x (Nova_Distance / 20.00)) damage of attack type Spells and damage type Normal
Else - Actions
Do Nothing
Level 1: 1 x (Nova_Distance / 20.00) = 30
Level 2: 2 x (Nova_Distance / 20.00) = 60
Level 3: 3 x (Nova_Distance / 20.00) = 90
The damage depends on the distance of the balls from the Nova_Point to the Dummy Balls. Now it's ready and we can go to the first trigger again.
9.
Now we have to turn on the trigger that we made and destroy group of course.
Code: Select all
Wait 0.20 seconds
Set Nova_Caster = (Casting unit)
Set Nova_Point = (Position of Nova_Caster)
Set Nova_Angle = 0.00
Set Nova_Distance = 0.00
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
Set Nova_Dummy[(Integer A)] = (Last created unit)
Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
Set Nova_Angle = (Nova_Angle + 30.00)
Unit - Pause Nova_Caster
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Set Variable Nova_Around[(Integer A)] = (Angle from (Position of Nova_Caster) to (Position of Nova_Dummy[(Integer A)]))
Wait for 0.20 seconds
Unit - Unpause Nova_Caster
Trigger - Turn on "The trigger that you made a while ago" <gen>
Trigger - Turn on "The trigger that we just made" <gen>
Wait for 6.00 seconds
Trigger - Turn off "The trigger that you made a while ago" <gen>
Trigger - Turn off "The trigger that we just made" <gen>
For each (Integer A) from 1 to 12, do (Actions)
Loop - Actions
Unit - Kill Nova_Dummy[(Integer A)]
Custom script: call RemoveLocation (udg_Nova_Point)
Custom script: call DestroyGroup (udg_Nova_Group)
Set Nova_Distance = 0.00
Set Nova_Angle = 0.00
Set Nova_Caster = No unit
Jass to GUI (Very Very Helpful!)
Spoiler:
For all you people like me that want to learn JASS, and know the GUI pretty well, I am working on a small little list/guide which will show you how to convert a little bit to JASS.
1. Abilities
2. Attack Types
3. Integers
4. Points/Locations
5. Units
6. Unit Groups
1. Abilities
2. Attack Types
3. Integers
4. Points/Locations
5. Units
6. Unit Groups
Code: Select all
______________________________________________
\ GUI -- JASS Function Names /
\ /
\ /
/ \
\ /
/ Created By: Darthfett \
\ /
/ \
/ \
/____________________________________________\
______________________________________________
\ Abilities /
/____________________________________________\
Ability being cast - GetSpellAbilityId()
______________________________________________
\ Attack Types /
/____________________________________________\
Spells - ATTACK_TYPE_NORMAL
-
Normal - ATTACK_TYPE_MELEE
-
Pierce - ATTACK_TYPE_PIERCE
-
Siege - ATTACK_TYPE_SIEGE
-
Magic - ATTACK_TYPE_MAGIC
-
Chaos - ATTACK_TYPE_CHAOS
-
Hero - ATTACK_TYPE_HERO
______________________________________________
\ Integers /
/____________________________________________\
Integer functions are extremely easy in Jass. Many do not even call a function, and use symbols.
Arithmetic (Addition) - *Integer* + *Integer*
-
Arithmetic (Subtraction) - *Integer* - *Integer*
-
Arithmetic (Multiplication) - *Integer* * *Integer*
-
Arithmetic (Division) - *Integer* / *Integer*
-
Integer A - bj_forLoopAIndex
-
Integer B - bj_forLoopBIndex
-
String Length - StringLength(*String*)
-
Conversion - Convert Real to Integer - R2I(*Real*)
-
Conversion - Convert String to Integer - S2I(*String*)
-
Destructible - Elevator Height - GetElevatorHeight(*Destructible {Has to be an elevator}*)
-
Environment - Terrain Cliff Level - GetTerrainCliffLevelBJ(*Location*)
-
Environment - Terrain Variance - GetTerrainVarianceBJ(*Location*)
-
Learned SKill Level - GetLearnedSkillLevel()
-
Game - Number of Players - GetPlayers()
-
Game - Number of Teams - GetTeams()
-
Ally Color Filter Setting - GetAllyColorFilterState()
-
Tournament Finish Rule - GetTournamentFinishNowRule()
-
Tournament Melee Score for (Player) - GetTournamentScore(*Player*)
-
Game Cache - Load Integer Value - GetStoredIntegerBJ(*String*,*String {Category}*, *Game Cache*)
-
Hero Level - GetHeroLevel(*Unit {Hero}*)
-
Hero Experience - GetHeroXP(*unit {Hero}*)
-
Hero Attribute - GetHeroStatBJ(*Integer {The Stat type (Agi = 1, Str = 0,Int = 2)},*Unit {Hero}*,*Boolean {true if you want to exclude bonuses}*)
-
-
- GetHeroStr(*Unit {whichHero}*,*Boolean {includeBonuses}*)
-
- GetHeroAgi(*Unit {whichHero}*,*Boolean {includeBonuses}*)
-
- GetHeroInt(*Unit {whichHero}*,*Boolean {includeBonuses}*)
-
-
-
Unspent Skill Points - GetHeroSkillPoints(*Unit{Hero}*)
-
Item Level - GetItemLevel(*Item*)
-
Item Charges Remaining - GetItemCharges(*Item*)
-
Custom Value of Item - GetItemUserData(*Item*)
-
Leaderboard - Leaderboard Position - LeaderboardGetPlayerIndexBJ(*Player*,*Leaderboard*)
-
Math - Random Integer - GetRandomInt(*Integer {Start #}*,*Integer {End #}*)
-
Math - Min - IMinBJ(*Integer*,*Integer*)
-
Math - Max - IMaxBJ(*Integer*,*Integer*)
-
Math - Abs(olute Value) - IAbsBJ(*Integer*)
-
Math - Sign - ISignBJ(*Integer*)
-
Math - Modulo - ModuloInteger(*Integer*,*Integer*)
-
Multiboard - Row Count - MultiboardGetRowCount(*Multiboard*)
-
Multiboard - Column Count - MultiboardGetColumnCount(*Multiboard*)
-
Neutral Building - Gold Remaining - GetResourceAmount(*Unit{Gold Mines only}*)
-
Player - Current Property - GetPlayerState(*Player*,*Player State*)
-
Player - Tax Rate - GetPlayerTaxRateBJ(*Player State*,*Player{Player giving gold}*, *Player{Player receiving gold})
-
Player - Score - GetPlayerScore(*Player*,*Player Score {The Type of Score}*)
-
Player - Player Number - GetConvertedPlayerId(*Player*)
-
Player - Count Structures - GetPlayerStructureCount(*Player*,*Boolean {Exclude Incomplete Structures?}*)
-
Player - Count Non-Structures - GetPlayerUnitCount(*Player*, *Boolean {Exclude Incomplete Units?}*)
-
Player - Current Research Level - GetPlayerTechCountSimple(*Research/Tech*,*Player*)
-
Player - Max Research Level - GetPlayerTechMaxAllowedSwap(*Research/Tech*,*Player*)
-
Player - Player Team - GetPlayerTeam(*Player*) //Will return the Team NUMBER the player is in.
-
Player - Count Players in Player Group - CountPlayersInForceBJ(*Force*)
-
Unit - Count Units in Unit Group - CountUnitsInGroup
-
Unit - Count Living Units Owned by Player - CountLivingPlayerUnitsOfTypeId(*Unit Type Id*,*Player*)
-
Unit - Supply Used by Unit - GetUnitFoodUsed(*Unit*)
-
Unit - Supply Provided - GetUnitFoodMade(*Unit*)
-
Unit - Supply Used by Unit-Type - GetFoodUsed(*Unit Type Id*)
-
Unit - Supply Provided by Unit-Type - GetFoodMade(*Unit Type Id*)
-
Unit - Point Value of Unit - GetUnitPointValue(*Unit*)
-
Unit - Point Value of Unit-Type - GetUnitPointValueByType(*Unit Type Id*)
-
Unit - Custom Value of Unit - GetUnitUserData(*Unit*)
-
Unit - Level of Unit - GetUnitLevel(*Unit*)
-
Unit - Level of Ability for Unit - GetUnitAbilityLevelSwapped(*Ability Id*,*Unit*)
-
Unit - Count Items Carried - UnitInventoryCount(*Unit*)
-
Unit - Size of Inventory - UnitInventorySizeBJ(*Unit*)
-
Unit - Count Buffs of Type - UnitCountBuffsExBJ(*Buff Type {Magic and/or Physical}*,*Buff Type*,*Unit*,*Boolean {Include Expiration Timers}*,*Boolean {Include Auras}*)
-
Trigger - Evaluation Count - GetTriggerEvalCount(*Trigger*)
-
Trigger - Execution Count - GetTriggerExecCount(*Trigger*)
-
Trigger - Count Triggers in Trigger Queue - QueuedTriggerCountBJ()
______________________________________________
\ Points/Locations /
/____________________________________________\
Center of (Region) - GetRectCenter(*Region*)
-
Random point in (Region) - GetRandomLocInRect(*Region*)
-
Center of (Region) offset by (X, Y) - OffsetLocation(*Region*, *Real {X}*, *Real {Y}*)
-
Center of (Region) offset by (Distance) towards (Degrees) degrees - PolarProjectionBJ(*Region*, *Distance*, *Angle*)
-
Target of (Camera) *1 player games only* - CameraSetupGetDestPositionLoc(*Camera*)
-
Target of current camera view *1 player games only* - GetCameraTargetPositionLoc()
-
Source of current camera view *1 player games only* - GetCameraEyePositionLoc()
-
Point(*X*, *Y*) *Coordinates* - Location(*Real {X}*, *Real {Y}*)
-
Position of (Destructible) - GetDestructableLoc(*Destructible*)
-
Target point of issued order *Event Response* - GetOrderPointLoc()
-
Target point of ability being cast *Event Response* - GetSpellTargetLoc()
-
Position of (Item) - GetItemLoc(*Item*)
-
Destination of (Waygate) - WaygateGetDestinationLocBJ(*Unit*)
-
(Player) start location - GetPlayerStartLocationLoc(*Player*)
-
Position of (Unit) - GetUnitLoc(*Unit*)
-
Rally point of (Unit) as a point - GetUnitRallyPoint(*Unit*)
______________________________________________
\ Units /
/____________________________________________\
GUI Usage JASS Usage
Last Created Unit - bj_lastCreatedUnit
-
Last Restored Unit - bj_lastLoadedUnit
-
Last Replaced Unit - bj_lastReplacedUnit
-
Last Haunted Gold Mine - bj_lastHauntedGoldMine
-
Picked Unit - GetEnumUnit()
-
Matching Unit - GetFilterUnit()
-
Random Unit from Unit Group - GroupPickRandomUnit(*UnitGroup*)
-
Attacked Unit - GetTriggerUnit()
-
Attacking Unit - GetAttacker()
-
Buying Unit - GetBuyingUnit()
-
Cancelled Structure - GetCancelledStructure()
-
Casting Unit - GetSpellAbilityUnit()
-
Constructing Structure - GetConstructingStructure()
-
Constructed Structure - GetConstructedStructure()
-
Damage Source - GetEventDamageSource()
-
Decaying Unit - GetDecayingUnit()
-
Dying Unit - GetTriggerUnit()
-
Entering Unit - GetEnteringUnit()
-
Hero Manipulating Item - GetManipulatingUnit()
-
Killing Unit - GetKillingUnit()
-
Learning Hero - GetLearningUnit()
-
Leaving Unit - GetLeavingUnit()
-
Leveling Hero - GetLevelingUnit()
-
Loading Unit - GetLoadedUnit()
-
Ordered Unit - GetOrderedUnit()
-
Ownership-changed unit - GetChangingUnit()
-
Researching Unit - GetResearchingUnit()
-
Revivable Hero - GetRevivableUnit()
-
Reviving Hero - GetRevivingUnit()
-
Selling Unit - GetSellingUnit()
-
Sold Unit - GetSoldUnit()
-
Summoned Unit - GetSummonedUnit()
-
Summoning Unit - GetSummoningUnit()
-
Target unit of issued order - GetOrderTargetUnit()
-
Target unit of ability being cast - GetSpellTargetUnit()
-
Targeted unit - GetEventTargetUnit()
-
Trained unit - GetTrainedUnit()
-
Transporting unit - GetTransportUnit()
-
Triggering unit - GetTriggerUnit()
-
Rally-Point of (Unit) as a Unit - GetUnitRallyUnit(*Unit*)
______________________________________________
\ Unit Groups /
/____________________________________________\
Last Created Unit Group - GetLastCreatedGroup()
-
Random N Units from Unit Group - GetRandomSubGroup(*N*, *Unit Group*)
-
Units in Region - GetUnitsInRectAll(*Region*)
-
Units in Region owned by Player - GetUnitsInRectOfPlayer(*Region*, *Player*)
-
Units in Region matching condition - GetUnitsInRectMatching(*Region*, *Condition*)
-
Units in Range - GetUnitsInRangeOfLocAll(*Real {Range Amount}*, *Region*)
-
Units in Range matching condition - GetUnitsInRangeOfLocMatching(*Real {Range Amount}*, *Region*, *Condition*)
-
Units owned by Player - GetUnitsOfPlayerAll(*Player*)
-
Units owned by Player of type - GetUnitsOfPlayerAndTypeId(*Player*, *UnitTypeID*)
-
Units owned by Player matching condition - GetUnitsOfPlayerMatching(*Player*, *Condition*)
-
Units of Type - GetUnitsOfTypeIdAll(*UnitTypeID*)
-
Units Selected by Player - GetUnitsSelectedAll(*Player*)
Simple GUI Triggers
Spoiler:
Part 1
Part 2
Part 3
Part 4
Part 5
part 6
Spoiler:
The fallowing was taken off another website, The pictures could not come...
Mapping for Beginners
Learning to make maps in Warcraft is not that difficult. Playing around with the editor is the best way to learn, but some people may feel more comfortable with guidance. This thread serves as a jump-start for your mapping journey. It is just an overview, but it should push you in the right direction. Good luck!
Note: If you have any questions, post them in a separate thread. This thread is reserved for suggestions and tips.
How do I make a map!?
If you are completely new to Warcraft map-making, you will find that messing around with the editor will teach you a lot. The rule of thumb is that you should start small - a beginner is not going to make the next DotA without practice. World Editor Tutorials gives some excellent advice on how to start mapping:
How do I make a campaign?
All campaigns start off with the Campaign Editor. Assuming that you can make maps, the Campaign Editor is self-explanatory. After filling in the various text boxes with the corresponding information, click on the "Add Map" icon in the toolbar, and add the maps that you have created, with their corresponding buttons. If you have experience with the Object Editor, then the Campaign Editor's analogous features should be straightforward, the only difference being the color of the edited objects' texts. In addition, you can import files much like in regular maps, except that the path to the file is wc3campimported\file, not wc3mapimported\file.
If you want to save your character between maps, you will have to use the Game Cache triggers in the Trigger Editor.
How do I make a TD (Tower Defense) Map?
TDs are very difficult maps to create. Tossing aside the technical aspects for a moment, making an original, fun-to-play map requires a huge commitment. Because of the high standards in the mapping community on TDs, your map needs to be both well-polished and entertaining.
First, you will need to terrain your map. This includes doodads and other static aspects, such as the paths for the creeps to walk.
Second, you will need to create the towers. This is self-explanatory - if you've played a TD, you probably have tons of ideas bouncing around in your head. See some unprotected TDs for more details on making the towers.
Third, you will need to make the creeps, who walk through the paths. Again, as with the towers, you probably have many ideas.
There are many excellent tutorials on the internet about making TDs, so if you're stuck you can search for more detailed information.
Mapping for Beginners
Learning to make maps in Warcraft is not that difficult. Playing around with the editor is the best way to learn, but some people may feel more comfortable with guidance. This thread serves as a jump-start for your mapping journey. It is just an overview, but it should push you in the right direction. Good luck!
Note: If you have any questions, post them in a separate thread. This thread is reserved for suggestions and tips.
How do I make a map!?
If you are completely new to Warcraft map-making, you will find that messing around with the editor will teach you a lot. The rule of thumb is that you should start small - a beginner is not going to make the next DotA without practice. World Editor Tutorials gives some excellent advice on how to start mapping:
If you're not willing to invest the time and effort to learn how to make maps, then don't expect to succeed. Learning how to make maps is hard work, and it doesn't come overnight. That said, don't expect to get much help if you post a thread saying "help me! I want to make a map!"Our best advice for the new mapmaker is to open an existing melee map from Warcraft III. Add a few special events that can occur. Add a quest or two, and create some custom units. Change the terrain a little to learn about the terrain editor. When you know your way around the editor a little, create a few custom abilities, and maybe even a custom hero.
How do I make a campaign?
All campaigns start off with the Campaign Editor. Assuming that you can make maps, the Campaign Editor is self-explanatory. After filling in the various text boxes with the corresponding information, click on the "Add Map" icon in the toolbar, and add the maps that you have created, with their corresponding buttons. If you have experience with the Object Editor, then the Campaign Editor's analogous features should be straightforward, the only difference being the color of the edited objects' texts. In addition, you can import files much like in regular maps, except that the path to the file is wc3campimported\file, not wc3mapimported\file.
If you want to save your character between maps, you will have to use the Game Cache triggers in the Trigger Editor.
How do I make a TD (Tower Defense) Map?
TDs are very difficult maps to create. Tossing aside the technical aspects for a moment, making an original, fun-to-play map requires a huge commitment. Because of the high standards in the mapping community on TDs, your map needs to be both well-polished and entertaining.
First, you will need to terrain your map. This includes doodads and other static aspects, such as the paths for the creeps to walk.
Second, you will need to create the towers. This is self-explanatory - if you've played a TD, you probably have tons of ideas bouncing around in your head. See some unprotected TDs for more details on making the towers.
Third, you will need to make the creeps, who walk through the paths. Again, as with the towers, you probably have many ideas.
There are many excellent tutorials on the internet about making TDs, so if you're stuck you can search for more detailed information.
Spoiler:
>> Using Local Variables for Easy Triggering <<
A Tutorial by Sid
Many of the times when we make Trigger Enhanced Systems or Spells, We make a System or Spell, But while testing it we realize that We've lost
the MUI. How to fix it?
Example : Consider this spell...
Pulse Of Darkness : Marks target for Pulse of Darkness, Target will take damage equal to 5% of it's base hp per second for next 3 seconds.
Making such a spell in GUI is tough challange. Specially if you don't know anything of JASS.
Now, I hope you can make this spell, Let's create a basic trigger that will explain basic ideaa of the spell's function.
Code:
Trigger Pulse Of Darkness
Event :
- A unit starts effect of an ability
Conditions
- Ability being cast is equal to Pulse of Darkness
Actions
- Cause (Casting Unit) to Damage (Target Unit of Ability being Cast) for (((Max HP of (Target unit of Ability being Cast) / (100)) * (5)) using
Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (Casting Unit) to Damage (Target Unit of Ability being Cast) for (((Max HP of (Target unit of Ability being Cast) / (100)) * (5)) using
Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (Casting Unit) to Damage (Target Unit of Ability being Cast) for (((Max HP of (Target unit of Ability being Cast) / (100)) * (5)) using
Attack Type Magic and Damage type Spells.
Ok, So now you have an idea. But test it out in a map, It won't work!
Why?
Because the fnction - Target unit of Ability being cast - becomes "Reset" after the - Wait X.xx Seconds - action!
So, Only the first Action is executed. Now, How to tackle that? Well, We can use Variables.
So, here's a trigger that takes one step ahed.
Code:
Variables
CastingUnit - unit
TargetUnit - unit
Here's Trigger...
Code:
Trigger Pulse Of Darkness
Event :
- A unit starts effect of an ability
Conditions
- Ability being cast is equal to Pulse of Darkness
Actions
- Set CastingUnit = (Casting Unit)
- Set TargetUnit = (Target Unit of Ability being Cast)
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
Now you have a trigger that is "Working", But what will happen if One unit casts this spell and second one also casts it before first is in
effect? Well, Don't bet that everything will go on normally. I can say that you'll lose the Bet. Since we are using two "Global Vars", It will
OverWrite the second target on the first one and before the effecton First one completes, it will aply damage to second one. It's a Major
Problem with the spell, Called loss of MUI.
Now how to fix it?
Answer is the title of the Tutorial, Usage of Local Variables.
Now comes the Trick.
If you define a Variable globally called "VariableName", it is called "udg_VariableName" in JASS.
Just Remember this.
Now, I presume you've still retained the CasterUnit and TargetUnit variables we created earlier.
Here, If you are smart enough, Tell me what these variables will be called in JASS?
Right, "udg_CasterUnit" and "udg_TargetUnit"
Now, I want you to make a little modification to the Last Step We've taken, Our Second Trigger.
Just Add these two Actions above all the Actions in the Trigger.
Code:
Actions :
- Custom Script : local unit udg_CasterUnit
- Custom Script : local unit udg_TargetUnit
So, here's the Final Trigger...
Code:
Trigger Pulse Of Darkness
Event :
- A unit starts effect of an ability
Conditions
- Ability being cast is equal to Pulse of Darkness
Actions
- Custom Script : local unit udg_CasterUnit
- Custom Script : local unit udg_TargetUnit
- Set CastingUnit = (Casting Unit)
- Set TargetUnit = (Target Unit of Ability being Cast)
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
Now, Try it out... This is the one that works smoothly and without any Glitch!
Why?
Remember what we wrote above all? We've declared two Local Variables, For the Simplicity in GUI, We set the names of out Locals to the same
names that of the Globals. Thus we can access the Variables from the Drop Down Menu of "Set Variable" action. There we select the Global
Variable's name, But when the Script compiles, it actually refers to Local Variables.Thus We "Override" the Globals by Locals.
How to implement it further?
Simple, For every Spell Trigger you create. Always use the Variables instead of GUI Functions while writing the Actions part. Then simply
define the locals of Same name and Same trype to that of the Globals you used in the Trigger Actions.
Hope this will help a map maker while making Trigger Enhanced Triggers.
Quote:Note:
Also, It's 100% safe to use Loops and Wait functions inside Loops, if you're using Locals. Remember Not to access Global accidently if you're
using Wait inside Loop.
Thanks for Reading through the post and Tolerating this Long Post.
And Don't forget my Reward... A Reputation point will do!
A Tutorial by Sid
Many of the times when we make Trigger Enhanced Systems or Spells, We make a System or Spell, But while testing it we realize that We've lost
the MUI. How to fix it?
Example : Consider this spell...
Pulse Of Darkness : Marks target for Pulse of Darkness, Target will take damage equal to 5% of it's base hp per second for next 3 seconds.
Making such a spell in GUI is tough challange. Specially if you don't know anything of JASS.
Now, I hope you can make this spell, Let's create a basic trigger that will explain basic ideaa of the spell's function.
Code:
Trigger Pulse Of Darkness
Event :
- A unit starts effect of an ability
Conditions
- Ability being cast is equal to Pulse of Darkness
Actions
- Cause (Casting Unit) to Damage (Target Unit of Ability being Cast) for (((Max HP of (Target unit of Ability being Cast) / (100)) * (5)) using
Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (Casting Unit) to Damage (Target Unit of Ability being Cast) for (((Max HP of (Target unit of Ability being Cast) / (100)) * (5)) using
Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (Casting Unit) to Damage (Target Unit of Ability being Cast) for (((Max HP of (Target unit of Ability being Cast) / (100)) * (5)) using
Attack Type Magic and Damage type Spells.
Ok, So now you have an idea. But test it out in a map, It won't work!
Why?
Because the fnction - Target unit of Ability being cast - becomes "Reset" after the - Wait X.xx Seconds - action!
So, Only the first Action is executed. Now, How to tackle that? Well, We can use Variables.
So, here's a trigger that takes one step ahed.
Code:
Variables
CastingUnit - unit
TargetUnit - unit
Here's Trigger...
Code:
Trigger Pulse Of Darkness
Event :
- A unit starts effect of an ability
Conditions
- Ability being cast is equal to Pulse of Darkness
Actions
- Set CastingUnit = (Casting Unit)
- Set TargetUnit = (Target Unit of Ability being Cast)
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
Now you have a trigger that is "Working", But what will happen if One unit casts this spell and second one also casts it before first is in
effect? Well, Don't bet that everything will go on normally. I can say that you'll lose the Bet. Since we are using two "Global Vars", It will
OverWrite the second target on the first one and before the effecton First one completes, it will aply damage to second one. It's a Major
Problem with the spell, Called loss of MUI.
Now how to fix it?
Answer is the title of the Tutorial, Usage of Local Variables.
Now comes the Trick.
If you define a Variable globally called "VariableName", it is called "udg_VariableName" in JASS.
Just Remember this.
Now, I presume you've still retained the CasterUnit and TargetUnit variables we created earlier.
Here, If you are smart enough, Tell me what these variables will be called in JASS?
Right, "udg_CasterUnit" and "udg_TargetUnit"
Now, I want you to make a little modification to the Last Step We've taken, Our Second Trigger.
Just Add these two Actions above all the Actions in the Trigger.
Code:
Actions :
- Custom Script : local unit udg_CasterUnit
- Custom Script : local unit udg_TargetUnit
So, here's the Final Trigger...
Code:
Trigger Pulse Of Darkness
Event :
- A unit starts effect of an ability
Conditions
- Ability being cast is equal to Pulse of Darkness
Actions
- Custom Script : local unit udg_CasterUnit
- Custom Script : local unit udg_TargetUnit
- Set CastingUnit = (Casting Unit)
- Set TargetUnit = (Target Unit of Ability being Cast)
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
- Wait 1.00 seconds
- Cause (CastingUnit) to Damage (TargetUnit) for (((Max HP of (TargetUnit) / (100)) * (5)) using Attack Type Magic and Damage type Spells.
Now, Try it out... This is the one that works smoothly and without any Glitch!
Why?
Remember what we wrote above all? We've declared two Local Variables, For the Simplicity in GUI, We set the names of out Locals to the same
names that of the Globals. Thus we can access the Variables from the Drop Down Menu of "Set Variable" action. There we select the Global
Variable's name, But when the Script compiles, it actually refers to Local Variables.Thus We "Override" the Globals by Locals.
How to implement it further?
Simple, For every Spell Trigger you create. Always use the Variables instead of GUI Functions while writing the Actions part. Then simply
define the locals of Same name and Same trype to that of the Globals you used in the Trigger Actions.
Hope this will help a map maker while making Trigger Enhanced Triggers.
Quote:Note:
Also, It's 100% safe to use Loops and Wait functions inside Loops, if you're using Locals. Remember Not to access Global accidently if you're
using Wait inside Loop.
Thanks for Reading through the post and Tolerating this Long Post.
And Don't forget my Reward... A Reputation point will do!
Spoiler:
=> What is this?
Demonstrates how to track effects, Create, record and destroy them periodically without any problem.
=> Requirements
This requires the Frozen Throne Expansion, At least ver.1.07. This will not work with RoC as it involves Custom Scripts functions.
=> Main
To start off, You'll need a variable,
Fx (Special Effect Variable)
Now, Create a trigger as follows..
...
Trigger HandleFx
Events :
- None
Conditions :
- None
Actions :
- Custom Script : Local Effect Eff
- Custom Script : set Eff = udg_Fx
- Wait 5.00 seconds.
- Custom Script : set udg_Fx = Eff
- Special Effect : Destroy Special Effect Fx
...
Now How to Implement that?
Now you have your Effect Handle, You can implement it!
Use it this way...
...
- Special Effect : Create Special Effect : <Whatever Path of Effect>
- Set Fx = Last Created Special Effect
- Trigger : Run HandleFx (Ignoring Conditions)
...
Hooray! You've made your own Special Effect Tracker!
=> Customization
You can customize this further, Like setting up Delay to 10.00 seconds rather than 5.00 seconds.. It won't hurt, You can safely create whatever effects you want...
=> Advanced Customization
I've found how to enhance it further according to your needs, Cause normaly, making a Triggered spell, you need to always adjust the values for how much time you'll need to display the effects.
=> How to start?
Let's again look at the old effect tracker we made...
here it is...
...
Trigger HandleFx
Events :
- None
Conditions :
- None
Actions :
- Custom Script : Local Effect Eff
- Custom Script : set Eff = udg_Fx
- Wait 5.00 seconds.
- Custom Script : set udg_Fx = Eff
- Special Effect : Destroy Special Effect : Fx
...
You found that you've plainly used the 5.00 seconds constant delay... Now the question comes, how to customize it for each effect?
You'll need another variable,
FxDur ...Real Variable.
Now, convert the HandleFx into Custom script and modify it's Action functions like this..
...
function Trig_HandleFx_Actions takes nothing returns nothing
local effect Eff
local real EffDur
set Eff = udg_Fx
set EffDur = udg_FxDur
call TriggerSleepAction( EffDur )
set udg_Fx = Eff
call DestroyEffectBJ( udg_Fx )
endfunction
...
Now, your entire trigger looks like this...
...
function Trig_HandleFx_Actions takes nothing returns nothing
local effect Eff
local real EffDur
set Eff = udg_Fx
set EffDur = udg_FxDur
call TriggerSleepAction( EffDur )
set udg_Fx = Eff
call DestroyEffectBJ( udg_Fx )
endfunction
function InitTrig_HandleFx takes nothing returns nothing
set gg_trg_HandleFx = CreateTrigger( )
call TriggerAddAction( gg_trg_HandleFx, function Trig_HandleFx_Actions )
endfunction
...
=> How to Implement this now?
Same way we did before, but now one more variable to set before running this trigger!
like this..
...
- Special Effect : Create Special Effect : <Whatever Path of Effect>
- Set Fx = Last Created Special Effect
- Set FxDur = 6.00
- Trigger : Run HandleFx (Ignoring Conditions) => What is this?
Demonstrates how to track effects, Create, record and destroy them periodically without any problem.
=> Requirements
This requires the Frozen Throne Expansion, At least ver.1.07. This will not work with RoC as it involves Custom Scripts functions.
=> Main
To start off, You'll need a variable,
Fx (Special Effect Variable)
Now, Create a trigger as follows..
...
Trigger HandleFx
Events :
- None
Conditions :
- None
Actions :
- Custom Script : Local Effect Eff
- Custom Script : set Eff = udg_Fx
- Wait 5.00 seconds.
- Custom Script : set udg_Fx = Eff
- Special Effect : Destroy Special Effect Fx
...
Now How to Implement that?
Now you have your Effect Handle, You can implement it!
Use it this way...
...
- Special Effect : Create Special Effect : <Whatever Path of Effect>
- Set Fx = Last Created Special Effect
- Trigger : Run HandleFx (Ignoring Conditions)
...
Hooray! You've made your own Special Effect Tracker!
=> Customization
You can customize this further, Like setting up Delay to 10.00 seconds rather than 5.00 seconds.. It won't hurt, You can safely create whatever effects you want...
=> Advanced Customization
I've found how to enhance it further according to your needs, Cause normaly, making a Triggered spell, you need to always adjust the values for how much time you'll need to display the effects.
=> How to start?
Let's again look at the old effect tracker we made...
here it is...
...
Trigger HandleFx
Events :
- None
Conditions :
- None
Actions :
- Custom Script : Local Effect Eff
- Custom Script : set Eff = udg_Fx
- Wait 5.00 seconds.
- Custom Script : set udg_Fx = Eff
- Special Effect : Destroy Special Effect : Fx
...
You found that you've plainly used the 5.00 seconds constant delay... Now the question comes, how to customize it for each effect?
You'll need another variable,
FxDur ...Real Variable.
Now, convert the HandleFx into Custom script and modify it's Action functions like this..
...
function Trig_HandleFx_Actions takes nothing returns nothing
local effect Eff
local real EffDur
set Eff = udg_Fx
set EffDur = udg_FxDur
call TriggerSleepAction( EffDur )
set udg_Fx = Eff
call DestroyEffectBJ( udg_Fx )
endfunction
...
Now, your entire trigger looks like this...
...
function Trig_HandleFx_Actions takes nothing returns nothing
local effect Eff
local real EffDur
set Eff = udg_Fx
set EffDur = udg_FxDur
call TriggerSleepAction( EffDur )
set udg_Fx = Eff
call DestroyEffectBJ( udg_Fx )
endfunction
function InitTrig_HandleFx takes nothing returns nothing
set gg_trg_HandleFx = CreateTrigger( )
call TriggerAddAction( gg_trg_HandleFx, function Trig_HandleFx_Actions )
endfunction
...
=> How to Implement this now?
Same way we did before, but now one more variable to set before running this trigger!
like this..
...
- Special Effect : Create Special Effect : <Whatever Path of Effect>
- Set Fx = Last Created Special Effect
- Set FxDur = 6.00
- Trigger : Run HandleFx (Ignoring Conditions)
Demonstrates how to track effects, Create, record and destroy them periodically without any problem.
=> Requirements
This requires the Frozen Throne Expansion, At least ver.1.07. This will not work with RoC as it involves Custom Scripts functions.
=> Main
To start off, You'll need a variable,
Fx (Special Effect Variable)
Now, Create a trigger as follows..
...
Trigger HandleFx
Events :
- None
Conditions :
- None
Actions :
- Custom Script : Local Effect Eff
- Custom Script : set Eff = udg_Fx
- Wait 5.00 seconds.
- Custom Script : set udg_Fx = Eff
- Special Effect : Destroy Special Effect Fx
...
Now How to Implement that?
Now you have your Effect Handle, You can implement it!
Use it this way...
...
- Special Effect : Create Special Effect : <Whatever Path of Effect>
- Set Fx = Last Created Special Effect
- Trigger : Run HandleFx (Ignoring Conditions)
...
Hooray! You've made your own Special Effect Tracker!
=> Customization
You can customize this further, Like setting up Delay to 10.00 seconds rather than 5.00 seconds.. It won't hurt, You can safely create whatever effects you want...
=> Advanced Customization
I've found how to enhance it further according to your needs, Cause normaly, making a Triggered spell, you need to always adjust the values for how much time you'll need to display the effects.
=> How to start?
Let's again look at the old effect tracker we made...
here it is...
...
Trigger HandleFx
Events :
- None
Conditions :
- None
Actions :
- Custom Script : Local Effect Eff
- Custom Script : set Eff = udg_Fx
- Wait 5.00 seconds.
- Custom Script : set udg_Fx = Eff
- Special Effect : Destroy Special Effect : Fx
...
You found that you've plainly used the 5.00 seconds constant delay... Now the question comes, how to customize it for each effect?
You'll need another variable,
FxDur ...Real Variable.
Now, convert the HandleFx into Custom script and modify it's Action functions like this..
...
function Trig_HandleFx_Actions takes nothing returns nothing
local effect Eff
local real EffDur
set Eff = udg_Fx
set EffDur = udg_FxDur
call TriggerSleepAction( EffDur )
set udg_Fx = Eff
call DestroyEffectBJ( udg_Fx )
endfunction
...
Now, your entire trigger looks like this...
...
function Trig_HandleFx_Actions takes nothing returns nothing
local effect Eff
local real EffDur
set Eff = udg_Fx
set EffDur = udg_FxDur
call TriggerSleepAction( EffDur )
set udg_Fx = Eff
call DestroyEffectBJ( udg_Fx )
endfunction
function InitTrig_HandleFx takes nothing returns nothing
set gg_trg_HandleFx = CreateTrigger( )
call TriggerAddAction( gg_trg_HandleFx, function Trig_HandleFx_Actions )
endfunction
...
=> How to Implement this now?
Same way we did before, but now one more variable to set before running this trigger!
like this..
...
- Special Effect : Create Special Effect : <Whatever Path of Effect>
- Set Fx = Last Created Special Effect
- Set FxDur = 6.00
- Trigger : Run HandleFx (Ignoring Conditions) => What is this?
Demonstrates how to track effects, Create, record and destroy them periodically without any problem.
=> Requirements
This requires the Frozen Throne Expansion, At least ver.1.07. This will not work with RoC as it involves Custom Scripts functions.
=> Main
To start off, You'll need a variable,
Fx (Special Effect Variable)
Now, Create a trigger as follows..
...
Trigger HandleFx
Events :
- None
Conditions :
- None
Actions :
- Custom Script : Local Effect Eff
- Custom Script : set Eff = udg_Fx
- Wait 5.00 seconds.
- Custom Script : set udg_Fx = Eff
- Special Effect : Destroy Special Effect Fx
...
Now How to Implement that?
Now you have your Effect Handle, You can implement it!
Use it this way...
...
- Special Effect : Create Special Effect : <Whatever Path of Effect>
- Set Fx = Last Created Special Effect
- Trigger : Run HandleFx (Ignoring Conditions)
...
Hooray! You've made your own Special Effect Tracker!
=> Customization
You can customize this further, Like setting up Delay to 10.00 seconds rather than 5.00 seconds.. It won't hurt, You can safely create whatever effects you want...
=> Advanced Customization
I've found how to enhance it further according to your needs, Cause normaly, making a Triggered spell, you need to always adjust the values for how much time you'll need to display the effects.
=> How to start?
Let's again look at the old effect tracker we made...
here it is...
...
Trigger HandleFx
Events :
- None
Conditions :
- None
Actions :
- Custom Script : Local Effect Eff
- Custom Script : set Eff = udg_Fx
- Wait 5.00 seconds.
- Custom Script : set udg_Fx = Eff
- Special Effect : Destroy Special Effect : Fx
...
You found that you've plainly used the 5.00 seconds constant delay... Now the question comes, how to customize it for each effect?
You'll need another variable,
FxDur ...Real Variable.
Now, convert the HandleFx into Custom script and modify it's Action functions like this..
...
function Trig_HandleFx_Actions takes nothing returns nothing
local effect Eff
local real EffDur
set Eff = udg_Fx
set EffDur = udg_FxDur
call TriggerSleepAction( EffDur )
set udg_Fx = Eff
call DestroyEffectBJ( udg_Fx )
endfunction
...
Now, your entire trigger looks like this...
...
function Trig_HandleFx_Actions takes nothing returns nothing
local effect Eff
local real EffDur
set Eff = udg_Fx
set EffDur = udg_FxDur
call TriggerSleepAction( EffDur )
set udg_Fx = Eff
call DestroyEffectBJ( udg_Fx )
endfunction
function InitTrig_HandleFx takes nothing returns nothing
set gg_trg_HandleFx = CreateTrigger( )
call TriggerAddAction( gg_trg_HandleFx, function Trig_HandleFx_Actions )
endfunction
...
=> How to Implement this now?
Same way we did before, but now one more variable to set before running this trigger!
like this..
...
- Special Effect : Create Special Effect : <Whatever Path of Effect>
- Set Fx = Last Created Special Effect
- Set FxDur = 6.00
- Trigger : Run HandleFx (Ignoring Conditions)
Spoiler:
Note: I did not discover this code, the original author is "Tennis" from http://www.wc3jass.com. All credits go to him, this is only a guide on how you implement it.
Description
Many maps uses the "player1 (red) = guy who decides everything", that is annoying because the host might not want to play as red but still wants to control the stuff which the host sometimes can do (as an example, difficulty settings, player 1 (red) is in a large number of maps able to set the difficulty of the game through a dialog or something similar).
But what most people probably didn't knew is that with just a very small amount of custom scripts (Jass) and 1 variable you can detect who is the host.
So here it goes, the 3 easy steps on how to create the variable and make the custom scripts.
Step 1: The Variable
Create a new variable, name it "Host", set the variable type to "Player (player)", do not check out the Aray box and leave the initial value at none like I have done in the picture below.
Step 2: Custom Script Header
Right, you have your variable now it is time to get the hardest part done. In the Trigger Editor you click at the top at the maps name like if it was any other trigger, in there you paste these lines of code (Make sure you paste it at the top):
[jass]function GetHost takes nothing returns nothing
local gamecache g = InitGameCache("Map.w3v")
call StoreInteger ( g, "Map", "Host", GetPlayerId(GetLocalPlayer ())+1)
call TriggerSyncStart ()
call SyncStoredInteger ( g, "Map", "Host" )
call TriggerSyncReady ()
set udg_Host = Player( GetStoredInteger ( g, "Map", "Host" )-1)
call FlushGameCache( g )
set g = null
endfunction[/jass]
Step 3 Getting The Host
Now that you have the most of the work done you just need to make a last simple trigger where you set the event to Map initialization, conditions you leave untouched and in the actions you make a custom script like this: "Custom script: call GetHost()". Now it has checked who is the host and stored it in the variable, for further use you just need to address everything to the "Host" variable like you would usually do to Player 1 (red), it is as simple as that.
Description
Many maps uses the "player1 (red) = guy who decides everything", that is annoying because the host might not want to play as red but still wants to control the stuff which the host sometimes can do (as an example, difficulty settings, player 1 (red) is in a large number of maps able to set the difficulty of the game through a dialog or something similar).
But what most people probably didn't knew is that with just a very small amount of custom scripts (Jass) and 1 variable you can detect who is the host.
So here it goes, the 3 easy steps on how to create the variable and make the custom scripts.
Step 1: The Variable
Create a new variable, name it "Host", set the variable type to "Player (player)", do not check out the Aray box and leave the initial value at none like I have done in the picture below.
Step 2: Custom Script Header
Right, you have your variable now it is time to get the hardest part done. In the Trigger Editor you click at the top at the maps name like if it was any other trigger, in there you paste these lines of code (Make sure you paste it at the top):
[jass]function GetHost takes nothing returns nothing
local gamecache g = InitGameCache("Map.w3v")
call StoreInteger ( g, "Map", "Host", GetPlayerId(GetLocalPlayer ())+1)
call TriggerSyncStart ()
call SyncStoredInteger ( g, "Map", "Host" )
call TriggerSyncReady ()
set udg_Host = Player( GetStoredInteger ( g, "Map", "Host" )-1)
call FlushGameCache( g )
set g = null
endfunction[/jass]
Step 3 Getting The Host
Now that you have the most of the work done you just need to make a last simple trigger where you set the event to Map initialization, conditions you leave untouched and in the actions you make a custom script like this: "Custom script: call GetHost()". Now it has checked who is the host and stored it in the variable, for further use you just need to address everything to the "Host" variable like you would usually do to Player 1 (red), it is as simple as that.
Spoiler:
Note: In this tutorial we will show you how you create a simple multiply choice dialog for 1 player. Keep in mind that this is directed towards the beginners within the Trigger Editor and is in no way meant to teach the experienced modders anything that they probably didn't knew already.
1) What is a dialog?
A "Dialog" is a litle window that pops up which contains some buttons that you can click. An example of what a Dialog can be used for is a simple thing like if you would like to have a 100 gold. Instead of having the choice based on chat commands where you write -yes or -no it is (and looks) better to have a Dialog window apearing asking you if you would like to have a 100 gold and then having 2 buttons which says "Yes" or "No".
We will now show you how you make a Dialog like I just told you about in the simpliest way (that we know of).
2) Getting Started.
To get started you should (ofcourse) open up the World Editor and enter the Trigger Editor (Hotkey for it is F4), the icon for it is located inbetween the Terrain Editor & the Sound Editor.
3) Creating The Variables.
Once you entered the Trigger Editor the first thing to do is finding the Variable Editor (Hotkey for it is Ctrl+B), the icon for it is located to the left of the New Category icon.
When you are inside the Variable Editor you click on the green x with a + infront of it to create a new variable, then you make the two variables needed for the Dialog as shown below.
4) Creating The Dialog Window.
Once you made your two variables you can start with the actual triggers for getting the Dialog Window to apear.
First you create a new trigger and do as shown below.
The Dialog Window
Code:
Events
Time - Elapsed game time is 1.00 seconds
Conditions
None
Actions
Dialog - Clear MyDialog
Dialog - Change the title of MyDialog to Do you want a 100 gold?
Dialog - Create a dialog button for MyDialog labelled Yes
Set DialogButton[1] = (Last created dialog Button)
Dialog - Create a dialog button for MyDialog labelled No
Set DialogButton[2] = (Last created dialog Button)
Dialog - Show MyDialog for Player 1 (Red)
Once this is done the Dialog will apear perfectly but there will be no effect when clicking the buttons.
5) Creating The Buttons.
To make the buttons actually do something you create two triggers as shown below.
Yes Button
Code:
Events
Dialog - A dialog button is clicked for MyDialog
Conditions
(Clicked dialog button) Equal to DialogButton[1]
Actions
Player - Add 100 to Player 1 (Red) Current gold
Game - Display to Player Group - Player 1 (Red) the text: You have recieved 100 gold
No Button
Code:
Events
Dialog - A dialog button is clicked for MyDialog
Conditions
(Clicked dialog button) Equal to DialogButton[2]
Actions
Game - Display to Player Group - Player 1 (Red) the text: You didn't want any gold
1) What is a dialog?
A "Dialog" is a litle window that pops up which contains some buttons that you can click. An example of what a Dialog can be used for is a simple thing like if you would like to have a 100 gold. Instead of having the choice based on chat commands where you write -yes or -no it is (and looks) better to have a Dialog window apearing asking you if you would like to have a 100 gold and then having 2 buttons which says "Yes" or "No".
We will now show you how you make a Dialog like I just told you about in the simpliest way (that we know of).
2) Getting Started.
To get started you should (ofcourse) open up the World Editor and enter the Trigger Editor (Hotkey for it is F4), the icon for it is located inbetween the Terrain Editor & the Sound Editor.
3) Creating The Variables.
Once you entered the Trigger Editor the first thing to do is finding the Variable Editor (Hotkey for it is Ctrl+B), the icon for it is located to the left of the New Category icon.
When you are inside the Variable Editor you click on the green x with a + infront of it to create a new variable, then you make the two variables needed for the Dialog as shown below.
4) Creating The Dialog Window.
Once you made your two variables you can start with the actual triggers for getting the Dialog Window to apear.
First you create a new trigger and do as shown below.
The Dialog Window
Code:
Events
Time - Elapsed game time is 1.00 seconds
Conditions
None
Actions
Dialog - Clear MyDialog
Dialog - Change the title of MyDialog to Do you want a 100 gold?
Dialog - Create a dialog button for MyDialog labelled Yes
Set DialogButton[1] = (Last created dialog Button)
Dialog - Create a dialog button for MyDialog labelled No
Set DialogButton[2] = (Last created dialog Button)
Dialog - Show MyDialog for Player 1 (Red)
Once this is done the Dialog will apear perfectly but there will be no effect when clicking the buttons.
5) Creating The Buttons.
To make the buttons actually do something you create two triggers as shown below.
Yes Button
Code:
Events
Dialog - A dialog button is clicked for MyDialog
Conditions
(Clicked dialog button) Equal to DialogButton[1]
Actions
Player - Add 100 to Player 1 (Red) Current gold
Game - Display to Player Group - Player 1 (Red) the text: You have recieved 100 gold
No Button
Code:
Events
Dialog - A dialog button is clicked for MyDialog
Conditions
(Clicked dialog button) Equal to DialogButton[2]
Actions
Game - Display to Player Group - Player 1 (Red) the text: You didn't want any gold
Spoiler:
Basics of a TD
by ragingspeedhorn
Note: This tutorial will explain you the very basics of making a TD. This is in no way geared towards experienced modders but is made for the beginners within Warcraft III modding.
What is a TD?
TD stands for Tower Defense and is a genre of maps developed for the Warcraft III engine. In a TD your goal is to build towers to prevent creeps of reaching a certain destination.
So.. How do I create one?
A good way of starting on a TD is to firstly make the terrain you find fitting for your map and then determine the lanes and setting up the pathing system (the creeps movement).
Uhh right, so how do I do that?
To get the creeps to move from 1 place to another you will need to make regions at the desired locations and then trigger the movement like this (the Trigger Editor is located inbetween the Terrain Editor and the Sound Editor):
Movement Region 1
Code:
Events
Unit - A unit enters Spawn Region
Conditions
None
Actions
Unit - Order (Entering unit) to Move To (Center of Region1)
Movement Region 2
Code:
Events
Unit - A unit enters Region1
Conditions
None
Actions
Unit - Order (Entering unit) to Move To (Center of Region2)
Movement Region 3
Code:
Events
Unit - A unit enters Region2
Conditions
None
Actions
Unit - Order (Entering unit) to Move To (Center of Region3)
Movement Region 4
Code:
Events
Unit - A unit enters Region3
Conditions
None
Actions
Unit - Order (Entering unit) to Move To (Center of Region4)
Movement Region 5
Code:
Events
Unit - A unit enters Region4
Conditions
None
Actions
Unit - Order (Entering unit) to Move To (Center of End Region)
Ok done, now what?
Next is the actual trigger that spawns the "waves" as the levels of units is often called. It can be done like this:
Wave 1
Code:
Events
Time - Elapsed game time is 30.00 seconds
Conditions
None
Actions
Unit - Create 40 Footman for Player 12 (Brown) at (Center of Spawn Region) facing 0.00 degrees
Right, so the regions and spawning is made, now what's next?
Next on the list should be finding out what to make of builders, towers and making the creeps, this is done within the Object Editor which is located inbetwen the Sound Editor and the Campaign Editor. You can also make triggered abilities for the towers but if you need help from this tutorial I suggest you wait with that untill a later time.
Right-o, I have made some towers, a builder and all the creeps, now what?
Adding the "lives" function is something that almost every td has, atleast it is only a few which doesent, so that is also included in here. Now I will show how you create the basic Leaderboard and putting in the lives function. Before you make the actual Leaderboard you have to make a variable like this one shown below to set the lives initial value.
Now when that is done you can move on to creating the Leaderboard and setting up everything that has to with lives and updating the Leaderboard.
Setup Leaderboard
Code:
Events
Time - Elapsed game time is 0.10 seconds
Conditions
None
Actions
Leaderboard - Create a leaderboard for (All players) titled Lives
Leaderboard - Add Player 1 (Red) to (Last created leaderboard) with label Lives and value Lives
Leaderboard - Change the color of all labels for (Last created leaderboard) to (0.00%, 100.00%, 0.00%) with 0.00% transparency
Leaderboard - Show (Last created leaderboard)
Life Lost
Code:
Events
Unit - A unit enters End Region
Conditions
(Owner of (Entering unit)) Equal to Player 12 (Brown)
Actions
Set Lives = (Lives - 1)
Unit - Remove (Entering unit) from the game Leaderboard - Change the value for Player 1 (Red) in (Last created leaderboard) to Lives
Game - Display to Lives the text: (( + ((Name of (Entering unit)) + has reached the end! )) + ((String(Lives)) + chances left))
Trigger - Run Defeat (checking conditions)
Defeat Trigger
Code:
Events
None (it is a trigger that is run by the 'Life Lost' trigger)
Conditions
None
Lives Less than or equal to 0
Actions
Unit Group - Pick every unit in (Units in (Playable map area)) and do (Unit - Remove (Picked unit) from the game)
Game - Defeat Player 1 (Red) with the message: Defeat!
Leaderboard made, is there anything more?
Most td maps (atleast the decent ones) has it so you are able to sell your towers so here I will show a way it can be done.
Tower Selling
Code:
Events
Unit - A unit Begins casting an ability
Conditions
(Ability being cast) Equal to Sell Tower
Actions
Player - Add ((Point-value of (Casting unit)) / xxx) to (Owner of (Casting unit)) Current gold
Unit - Remove (Casting unit) from the game
Ability done, what's next?
Once you have succesfully made the Tower Selling ability I think you are covered in with the basic triggers, now you only need to make it so you win once the last wave of units have been defeated. Good luck with your td map!
by ragingspeedhorn
Note: This tutorial will explain you the very basics of making a TD. This is in no way geared towards experienced modders but is made for the beginners within Warcraft III modding.
What is a TD?
TD stands for Tower Defense and is a genre of maps developed for the Warcraft III engine. In a TD your goal is to build towers to prevent creeps of reaching a certain destination.
So.. How do I create one?
A good way of starting on a TD is to firstly make the terrain you find fitting for your map and then determine the lanes and setting up the pathing system (the creeps movement).
Uhh right, so how do I do that?
To get the creeps to move from 1 place to another you will need to make regions at the desired locations and then trigger the movement like this (the Trigger Editor is located inbetween the Terrain Editor and the Sound Editor):
Movement Region 1
Code:
Events
Unit - A unit enters Spawn Region
Conditions
None
Actions
Unit - Order (Entering unit) to Move To (Center of Region1)
Movement Region 2
Code:
Events
Unit - A unit enters Region1
Conditions
None
Actions
Unit - Order (Entering unit) to Move To (Center of Region2)
Movement Region 3
Code:
Events
Unit - A unit enters Region2
Conditions
None
Actions
Unit - Order (Entering unit) to Move To (Center of Region3)
Movement Region 4
Code:
Events
Unit - A unit enters Region3
Conditions
None
Actions
Unit - Order (Entering unit) to Move To (Center of Region4)
Movement Region 5
Code:
Events
Unit - A unit enters Region4
Conditions
None
Actions
Unit - Order (Entering unit) to Move To (Center of End Region)
Ok done, now what?
Next is the actual trigger that spawns the "waves" as the levels of units is often called. It can be done like this:
Wave 1
Code:
Events
Time - Elapsed game time is 30.00 seconds
Conditions
None
Actions
Unit - Create 40 Footman for Player 12 (Brown) at (Center of Spawn Region) facing 0.00 degrees
Right, so the regions and spawning is made, now what's next?
Next on the list should be finding out what to make of builders, towers and making the creeps, this is done within the Object Editor which is located inbetwen the Sound Editor and the Campaign Editor. You can also make triggered abilities for the towers but if you need help from this tutorial I suggest you wait with that untill a later time.
Right-o, I have made some towers, a builder and all the creeps, now what?
Adding the "lives" function is something that almost every td has, atleast it is only a few which doesent, so that is also included in here. Now I will show how you create the basic Leaderboard and putting in the lives function. Before you make the actual Leaderboard you have to make a variable like this one shown below to set the lives initial value.
Now when that is done you can move on to creating the Leaderboard and setting up everything that has to with lives and updating the Leaderboard.
Setup Leaderboard
Code:
Events
Time - Elapsed game time is 0.10 seconds
Conditions
None
Actions
Leaderboard - Create a leaderboard for (All players) titled Lives
Leaderboard - Add Player 1 (Red) to (Last created leaderboard) with label Lives and value Lives
Leaderboard - Change the color of all labels for (Last created leaderboard) to (0.00%, 100.00%, 0.00%) with 0.00% transparency
Leaderboard - Show (Last created leaderboard)
Life Lost
Code:
Events
Unit - A unit enters End Region
Conditions
(Owner of (Entering unit)) Equal to Player 12 (Brown)
Actions
Set Lives = (Lives - 1)
Unit - Remove (Entering unit) from the game Leaderboard - Change the value for Player 1 (Red) in (Last created leaderboard) to Lives
Game - Display to Lives the text: (( + ((Name of (Entering unit)) + has reached the end! )) + ((String(Lives)) + chances left))
Trigger - Run Defeat (checking conditions)
Defeat Trigger
Code:
Events
None (it is a trigger that is run by the 'Life Lost' trigger)
Conditions
None
Lives Less than or equal to 0
Actions
Unit Group - Pick every unit in (Units in (Playable map area)) and do (Unit - Remove (Picked unit) from the game)
Game - Defeat Player 1 (Red) with the message: Defeat!
Leaderboard made, is there anything more?
Most td maps (atleast the decent ones) has it so you are able to sell your towers so here I will show a way it can be done.
Tower Selling
Code:
Events
Unit - A unit Begins casting an ability
Conditions
(Ability being cast) Equal to Sell Tower
Actions
Player - Add ((Point-value of (Casting unit)) / xxx) to (Owner of (Casting unit)) Current gold
Unit - Remove (Casting unit) from the game
Ability done, what's next?
Once you have succesfully made the Tower Selling ability I think you are covered in with the basic triggers, now you only need to make it so you win once the last wave of units have been defeated. Good luck with your td map!