Meh. there is too much stuff to post in a thread. Ill just post the map then. There are a bunch of irrelevant stuff in there. What you should look for in the data editor is my unit Beam Tower, and the ability on it. Also, in the effects you will find the Beam Tower Persistent which I call from the trigger.
And in the trigger editor.. You can start at the Beam Tower Link trigger and see what functions it uses.
Have you tried setting the training time with catalog field value set?
I think that should do the trick.. It's not all fields that can be written, but is just a number, so I think it can..
You can set a flag on the unit. "Unselectable". If you set that, you should be able to click through it.
You might need Untargetable too.. I'm not sure, and I dont want to test now..
Why don't you want to write the cost in the tooltip? You can make it look very similar to the real thing. Except, the text won't go red if the player doesn't have the minerals
<img path="Assets\Textures\icon-mineral-terran.dds" height="17" width="17"/> 100<n/>Some tooltip text
Alternativly, you can make a trigger that gives the player the minerals/gas back once the ability has been used
Perhaps you could make a buff, and set the Modification->Unit->Time scale to something low. Then apply that buff to every unit in the map.. I suppose it wouldn't change wait times in the trigger editor, but it should make all units slow.
I dont see how it wouldn't work for a td map.. I dont think you understand me.
Ill try and post my trigger.
Beam Tower Link
Events
Unit - Any Unit uses Link at Generic3 - Execute stage (Ignore shared abilities)
Local Variables
distance = 0.0 <Real>
damage = 0.0 <Real>
region = No Region <Region>
Conditions
Actions
//Make the units face eachother (not important for the effect ur after)
Unit - Make (Triggering unit) face (Position of (Triggering ability target unit)) over 0.0 seconds
Unit - Make (Triggering ability target unit) face (Position of (Triggering unit)) over 0.0 seconds
//This is an effect that will cause some actors to make a beam between the two towers
Environment - Execute Beam Tower Persistent on (Triggering unit) from (Triggering ability target unit)
//I want the damage to be a function of the distance between the towers.
//Since getting the distance involves taking the squareroot, which is a bit slow, I save this to a varible
Variable - Set distance = (Distance between (Position of (Triggering unit)) and (Position of (Triggering ability target unit)))
//I made this function that will return a new region if I give it the center, width and height
General - Custom Script: lv_region = gf_RegionFromPoint(
gf_AvgPoints(UnitGetPosition(EventUnit()), UnitGetPosition(EventUnitTargetUnit())),
(AbsF((PointGetY(UnitGetPosition(EventUnit())) - PointGetY(UnitGetPosition(EventUnitTargetUnit())))) + 2.0),
(AbsF((PointGetX(UnitGetPosition(EventUnit())) - PointGetX(UnitGetPosition(EventUnitTargetUnit())))) + 2.0));
General - While (Conditions) are true, do (Actions)
Conditions
((Triggering unit) is alive) == true
((Triggering ability target unit) is alive) == true
Actions
Variable - Set damage = 20.0
Variable - Modify damage: / distance
//Like I talked about.. Pick each enemy unit in the region
Unit Group - Pick each unit in (Units in region having alliance Enemy with player (Triggering player) matching Excluded: Missile, Dead, Hidden, with at most Any Amount) and do (Actions)
Actions
General - If (Conditions) then do (Actions) else do (Actions)
If
//And if the point is in the square as illustrated by the picture, damage it
(Point In Square((Position of (Picked unit)), ((Position of (Triggering unit)) offset by 1.0 towards ((Facing of (Triggering unit)) + 90.0) degrees), ((Position of (Triggering unit)) offset by 1.0 towards ((Facing of (Triggering unit)) - 90.0) degrees), ( == true
Then
DamageUnit((Picked unit), (Triggering unit), damage)
Else
//My beam will hit two times pr second
General - Wait 0.5 Game Time seconds
First of all, in my map, you put two towers down, and then you use an ability to link one to the other. This trigger then fires when that ability is used.
I commented a bit to explain what happens.
Im calling some custom functions..I hope it's clear what they do.
I know it looks a bit messy, but hopfully it can clarify something you might have missed
There are triggers to create a region at runtime. You can also add an event such as a unit enters region at runtime, but that is not how I use it. I create the smallest square region that contain both towers (at runtime), and then I periodically pick every enemy unit in this region, and deal damage to them if they are inside this square im talking about.
You can raytrace from the camera target to the camera viewpoint, and check if you hit the ground before you reach your camera distance.
You can do the same, looking for units instead. Here you can check the unit's distance to the ray, compared to their radius and a hight you will have to hardcode.
It's not the simplest solution, but I think it is the only way forth.
As for finding units inside the beam, that is just math.
First of all I made a region that covers the square between the two towers.
Then every x seconds, I pick every unit in this region, and check if it is within the rotated square where the beam is going.
This is done by splitting the square up into triangles, and checking if the unit is inside one of those, and to do that...
Point In Triangle
Options: Function
Return Type: Boolean
Parameters
point = No Point <Point>
s1 = No Point <Point>
s2 = No Point <Point>
s3 = No Point <Point>
Grammar Text: Point In Triangle(point, s1, s2, s3)
Hint Text: (None)
Custom Script Code
Local Variables
i = 0 <Integer>
j = 0 <Integer>
v = No Point <Point[2]>
dot = 0.0 <Real[1][2]>
d = 0.0 <Real>
x = 0.0 <Real>
y = 0.0 <Real>
Actions
Variable - Set v[0] = (Subtract Points(s3, s1))
Variable - Set v[1] = (Subtract Points(s2, s1))
Variable - Set v[2] = (Subtract Points(point, s1))
General - For each integer i from 0 to 1 with increment 1, do (Actions)
Actions
General - For each integer j from 0 to 2 with increment 1, do (Actions)
Actions
Variable - Set dot[i][j] = (Dot(v[i], v[j]))
Variable - Set d = ((dot[0][0] * dot[1][1]) - (dot[0][1] * dot[0][1]))
Variable - Set x = (lv_dot[1][1] * lv_dot[0][2] - lv_dot[0][1] * lv_dot[1][2]) / lv_d
Variable - Set y = (lv_dot[0][0] * lv_dot[1][2] - lv_dot[0][1] * lv_dot[0][2]) / lv_d
General - Return (lv_x >= 0) && (lv_y >= 0) && (lv_x + lv_y <= 1)
SubtractPoints({x1, x2, x3}, {y1, y2, y3}) just returns {x1 - y1, x2 - y2, x3 - y3}, and Dot(x, y) returns the dot product betwen the two "vectors".
To make them auto connect to nearby towers, just make a trigger that fires when one of your towers are created. Then you search for nearby towers, and for each of those, you do the above.
You tell the actor to link to the ability, or the effect.
Most actors has an events+ field (I cant think of an actor that doesnt). This is kind of a list of small triggers containing one event, zero or more conditions, and one action. Usually, there is an event with the action Create.
Take the cursor effect "PsiStormCursorSplat (Unnamed)" for example. It has the following event
Abil.PsiStorm.Cursor
Create
This is responsible for creating the actor at the right time. You would then need to make an actor with
Abil.<Your ability>.Cursor
Create
Also, in your cursor splat actor, remember to set the model field to whatever model you want to be displayed at the cursor.
If we take the "High Templar Psi Storm Model" actor instead, it also has a create event
Effect.PsiStormPersistent.Start
Create
This event creates the actor. Then there is another event that fires when the actor is created
ActorCreation
AnimBracketStart BSD Birth Stand Death
This will make sure that the model plays the correct animations (First birth, then stand (looping), then death)
Effect.PsiStormPersistent.End
AnimBracketStop BSD
Will make the animation bracket play the death animation, and then close.
And finally,
Will destroy the actor after an animation bracket called BSD closes
So to make something similar, you need to replace PsiStormPersistent with your persistent effect (Or you can use other events to create/destroy the actor).
I don't know if there is an easy way of setting handicap at runtime, but you can use the catalog to modify the health/shields/damage done by a specific unit type for a specific player, so I assume that doing that for every unit type that player can get would be the equivalent of setting handicap.
As for the cursor, you need an actor of type Splat -> Cursor Splat. Like the "PsiStormCursorSplat (Unnamed)" actor for Psi Storm.
Note: in your ability, you also need to set the field Cursor Effect to your search area effect, so the splat know which radius it should be at.
As for the lightning effect in Psi Storm, this is done by the actor "High Templar Psi Storm Model". I assume you can use them as a refference, and do something similar with your ability.
If you have a maximum number of caravans, I would use a global array of structs that contain all the variables needed. You could then set a custom value of the caravan unit to point to the index in the array that belongs to that caravan.
If you have no maximum number of caravans, you can just use the data table to implement a dynamic struct array.
0
Meh. there is too much stuff to post in a thread. Ill just post the map then. There are a bunch of irrelevant stuff in there. What you should look for in the data editor is my unit Beam Tower, and the ability on it. Also, in the effects you will find the Beam Tower Persistent which I call from the trigger.
And in the trigger editor.. You can start at the Beam Tower Link trigger and see what functions it uses.
0
Have you tried setting the training time with catalog field value set?
I think that should do the trick.. It's not all fields that can be written, but is just a number, so I think it can..
0
You can set a flag on the unit. "Unselectable". If you set that, you should be able to click through it.
You might need Untargetable too.. I'm not sure, and I dont want to test now..
0
Why don't you want to write the cost in the tooltip? You can make it look very similar to the real thing. Except, the text won't go red if the player doesn't have the minerals
<img path="Assets\Textures\icon-mineral-terran.dds" height="17" width="17"/> 100<n/>Some tooltip text
Alternativly, you can make a trigger that gives the player the minerals/gas back once the ability has been used
0
Perhaps you could make a buff, and set the Modification->Unit->Time scale to something low. Then apply that buff to every unit in the map.. I suppose it wouldn't change wait times in the trigger editor, but it should make all units slow.
0
I dont see how it wouldn't work for a td map.. I dont think you understand me.
Ill try and post my trigger.
Beam Tower Link
Events
Unit - Any Unit uses Link at Generic3 - Execute stage (Ignore shared abilities)
Local Variables
distance = 0.0 <Real>
damage = 0.0 <Real>
region = No Region <Region>
Conditions
Actions
//Make the units face eachother (not important for the effect ur after)
Unit - Make (Triggering unit) face (Position of (Triggering ability target unit)) over 0.0 seconds
Unit - Make (Triggering ability target unit) face (Position of (Triggering unit)) over 0.0 seconds
//This is an effect that will cause some actors to make a beam between the two towers
Environment - Execute Beam Tower Persistent on (Triggering unit) from (Triggering ability target unit)
//I want the damage to be a function of the distance between the towers.
//Since getting the distance involves taking the squareroot, which is a bit slow, I save this to a varible
Variable - Set distance = (Distance between (Position of (Triggering unit)) and (Position of (Triggering ability target unit)))
//I made this function that will return a new region if I give it the center, width and height
General - Custom Script: lv_region = gf_RegionFromPoint(
gf_AvgPoints(UnitGetPosition(EventUnit()), UnitGetPosition(EventUnitTargetUnit())),
(AbsF((PointGetY(UnitGetPosition(EventUnit())) - PointGetY(UnitGetPosition(EventUnitTargetUnit())))) + 2.0),
(AbsF((PointGetX(UnitGetPosition(EventUnit())) - PointGetX(UnitGetPosition(EventUnitTargetUnit())))) + 2.0));
General - While (Conditions) are true, do (Actions)
Conditions
((Triggering unit) is alive) == true
((Triggering ability target unit) is alive) == true
Actions
Variable - Set damage = 20.0
Variable - Modify damage: / distance
//Like I talked about.. Pick each enemy unit in the region
Unit Group - Pick each unit in (Units in region having alliance Enemy with player (Triggering player) matching Excluded: Missile, Dead, Hidden, with at most Any Amount) and do (Actions)
Actions
General - If (Conditions) then do (Actions) else do (Actions)
If
//And if the point is in the square as illustrated by the picture, damage it
(Point In Square((Position of (Picked unit)), ((Position of (Triggering unit)) offset by 1.0 towards ((Facing of (Triggering unit)) + 90.0) degrees), ((Position of (Triggering unit)) offset by 1.0 towards ((Facing of (Triggering unit)) - 90.0) degrees), ( == true
Then
DamageUnit((Picked unit), (Triggering unit), damage)
Else
//My beam will hit two times pr second
General - Wait 0.5 Game Time seconds
First of all, in my map, you put two towers down, and then you use an ability to link one to the other. This trigger then fires when that ability is used.
I commented a bit to explain what happens.
Im calling some custom functions..I hope it's clear what they do.
I know it looks a bit messy, but hopfully it can clarify something you might have missed
0
There are triggers to create a region at runtime. You can also add an event such as a unit enters region at runtime, but that is not how I use it. I create the smallest square region that contain both towers (at runtime), and then I periodically pick every enemy unit in this region, and deal damage to them if they are inside this square im talking about.
Edit: made a small image of it ;)
0
You can raytrace from the camera target to the camera viewpoint, and check if you hit the ground before you reach your camera distance.
You can do the same, looking for units instead. Here you can check the unit's distance to the ray, compared to their radius and a hight you will have to hardcode.
It's not the simplest solution, but I think it is the only way forth.
0
There has been other threads about closing gates. Did they not help? Take http://forums.sc2mapster.com/development/triggers/9298-gates-open-close-through-triggers/ for example
0
Perhaps this thread can help. He uses a local offset site actor to place an archon on the back of a zergling
http://forums.sc2mapster.com/development/map-development/2049-psionic-zergling-effect/#p2
0
I have created such a tower in one of my maps. First of all, to make the beam.. Look here http://forums.sc2mapster.com/development/map-development/8589-solved-data-creating-a-permenent-beam/
As for finding units inside the beam, that is just math.
First of all I made a region that covers the square between the two towers.
Then every x seconds, I pick every unit in this region, and check if it is within the rotated square where the beam is going.
This is done by splitting the square up into triangles, and checking if the unit is inside one of those, and to do that...
Point In Triangle
Options: Function
Return Type: Boolean
Parameters
point = No Point <Point>
s1 = No Point <Point>
s2 = No Point <Point>
s3 = No Point <Point>
Grammar Text: Point In Triangle(point, s1, s2, s3)
Hint Text: (None)
Custom Script Code
Local Variables
i = 0 <Integer>
j = 0 <Integer>
v = No Point <Point[2]>
dot = 0.0 <Real[1][2]>
d = 0.0 <Real>
x = 0.0 <Real>
y = 0.0 <Real>
Actions
Variable - Set v[0] = (Subtract Points(s3, s1))
Variable - Set v[1] = (Subtract Points(s2, s1))
Variable - Set v[2] = (Subtract Points(point, s1))
General - For each integer i from 0 to 1 with increment 1, do (Actions)
Actions
General - For each integer j from 0 to 2 with increment 1, do (Actions)
Actions
Variable - Set dot[i][j] = (Dot(v[i], v[j]))
Variable - Set d = ((dot[0][0] * dot[1][1]) - (dot[0][1] * dot[0][1]))
Variable - Set x = (lv_dot[1][1] * lv_dot[0][2] - lv_dot[0][1] * lv_dot[1][2]) / lv_d
Variable - Set y = (lv_dot[0][0] * lv_dot[1][2] - lv_dot[0][1] * lv_dot[0][2]) / lv_d
General - Return (lv_x >= 0) && (lv_y >= 0) && (lv_x + lv_y <= 1)
SubtractPoints({x1, x2, x3}, {y1, y2, y3}) just returns {x1 - y1, x2 - y2, x3 - y3}, and Dot(x, y) returns the dot product betwen the two "vectors".
To make them auto connect to nearby towers, just make a trigger that fires when one of your towers are created. Then you search for nearby towers, and for each of those, you do the above.
0
You tell the actor to link to the ability, or the effect.
Most actors has an events+ field (I cant think of an actor that doesnt). This is kind of a list of small triggers containing one event, zero or more conditions, and one action. Usually, there is an event with the action Create.
Take the cursor effect "PsiStormCursorSplat (Unnamed)" for example. It has the following event
Abil.PsiStorm.Cursor
Create
This is responsible for creating the actor at the right time. You would then need to make an actor with
Abil.<Your ability>.Cursor
Create
Also, in your cursor splat actor, remember to set the model field to whatever model you want to be displayed at the cursor.
If we take the "High Templar Psi Storm Model" actor instead, it also has a create event
Effect.PsiStormPersistent.Start
Create
This event creates the actor. Then there is another event that fires when the actor is created
ActorCreation
AnimBracketStart BSD Birth Stand Death
This will make sure that the model plays the correct animations (First birth, then stand (looping), then death)
Effect.PsiStormPersistent.End
AnimBracketStop BSD
Will make the animation bracket play the death animation, and then close.
And finally,
AnimBracketState.*.AfterClosing
AnimName BSD
Destroy
Will destroy the actor after an animation bracket called BSD closes
So to make something similar, you need to replace PsiStormPersistent with your persistent effect (Or you can use other events to create/destroy the actor).
0
I don't know if there is an easy way of setting handicap at runtime, but you can use the catalog to modify the health/shields/damage done by a specific unit type for a specific player, so I assume that doing that for every unit type that player can get would be the equivalent of setting handicap.
0
As for the cursor, you need an actor of type Splat -> Cursor Splat. Like the "PsiStormCursorSplat (Unnamed)" actor for Psi Storm.
Note: in your ability, you also need to set the field Cursor Effect to your search area effect, so the splat know which radius it should be at.
As for the lightning effect in Psi Storm, this is done by the actor "High Templar Psi Storm Model". I assume you can use them as a refference, and do something similar with your ability.
0
If you have a maximum number of caravans, I would use a global array of structs that contain all the variables needed. You could then set a custom value of the caravan unit to point to the index in the array that belongs to that caravan.
If you have no maximum number of caravans, you can just use the data table to implement a dynamic struct array.