• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Starfury - Public Version 2.98

Special thanks goes to IcemanBo because without him I wouldn't be submitting this today. Another thanks goes to the people who kept finding my little errors in the triggers.



Dat-C3 Presents

Starfury - Demo Map
Spell Created by Tal0n


Features:

Fun
-------------------------------------------------------------------------------------------------
It's a fun spell I thought up while thinking about stars, the effect might be rather blinding however it doesn't lag. =) Enjoy and hope everyone can find this useful.

I also put together a little fun map for you guys to play around in with the spell, see if you can win.

[TRIGGER=]
Events
Time - Elapsed game time is 0.00 seconds
ConditionsActions
-------- The model for the rotating units --------
Set QQSEffectOnDummyUnits = Abilities\Weapons\WitchDoctorMissile\WitchDoctorMissile.mdl
-------- The model for the effect over the terrain --------
Set QQSEffectOnGround = Abilities\Spells\Undead\ReplenishHealth\ReplenishHealthCasterOverhead.mdl
-------- --------
-------- This will let you decide which attack type you'll use --------
Set QQSAttackType = Spells
-------- This is what makes it decide to go through armor or not. --------
Set QQSDamageType = Magic
-------- ^ Change it to normal if you want the spell to be affected by armor --------
-------- This is where we choose the ability to be used so the entire spell functions --------
Set QQSAbility = Starfury

[/TRIGGER]



[TRIGGER=]
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to QQSAbility
Actions
-------- Index Starter --------
Set QQSFindex = (QQSFindex + 1)
-------- Who the caster unit is --------
Set QQSFcaster[QQSFindex] = (Triggering unit)
-------- --------
-------- The player of the unit that casts this spell --------
Set QQStarFuryOwner[QQSFindex] = (Owner of QQSFcaster[QQSFindex])
-------- --------
Set QQSFlevel[QQSFindex] = (Level of QQSAbility for QQSFcaster[QQSFindex])
-------- --------
-------- This is where we set the size of each circleing projectile --------
Set QQSFSize[QQSFindex] = (300.00 + ((Real(QQSFlevel[QQSFindex])) x 5.00))
-------- Where the caster unit is --------
Set QQSFp = (Position of QQSFcaster[QQSFindex])
-------- --------
-------- How long the spell will last --------
Set QQSFtime[QQSFindex] = (80 x QQSFlevel[QQSFindex])
-------- --------
-------- First dummy unit --------
Unit - Create 1 Dummy for (Owner of QQSFcaster[QQSFindex]) at QQSFp facing Default building facing degrees
Set QQSFstarunit1[QQSFindex] = (Last created unit)
-------- --------
Special Effect - Create a special effect attached to the origin of QQSFstarunit1[QQSFindex] using QQSEffectOnDummyUnits
Set QQSFfx[QQSFindex] = (Last created special effect)
-------- this is where we set the size of the main rotating units --------
Animation - Change QQSFstarunit1[QQSFindex]'s size to (QQSFSize[QQSFindex]%, 100.00%, 100.00%) of its original size
-------- This is so they dont look like they are on the ground. --------
Animation - Change QQSFstarunit1[QQSFindex] flying height to 75.00 at 0.00
-------- --------
-------- Second dummy unit --------
Unit - Create 1 Dummy for (Owner of QQSFcaster[QQSFindex]) at QQSFp facing Default building facing degrees
Set QQSFstarunit2[QQSFindex] = (Last created unit)
-------- --------
Special Effect - Create a special effect attached to the origin of QQSFstarunit2[QQSFindex] using QQSEffectOnDummyUnits
Set QQSFfx2[QQSFindex] = (Last created special effect)
-------- --------
-------- this is where we set the size of the main rotating units --------
Animation - Change QQSFstarunit2[QQSFindex]'s size to (QQSFSize[QQSFindex]%, 100.00%, 100.00%) of its original size
-------- This is so they dont look like they are on the ground. --------
Animation - Change QQSFstarunit2[QQSFindex] flying height to 75.00 at 0.00
-------- --------
-------- This is the damage that is dealt every 0.07 seconds --------
Set QQSFDamage[QQSFindex] = (35.00 x (Real(QQSFlevel[QQSFindex])))
-------- This is the amount that is healed every 0.07 seconds --------
Set QQSFHeal[QQSFindex] = (10.00 x (Real(QQSFlevel[QQSFindex])))
-------- --------
-------- This is the distance away from the caster the two dummy units start at --------
Set QQSReal2[QQSFindex] = 50.00
-------- As well it is what lets them move outward and inward --------
-------- --------
-------- This is the area of space that is checked for to damage units inside it --------
Set QQSRadius[QQSFindex] = (90.00 + (10.00 x (Real(QQSFlevel[QQSFindex]))))
-------- --------
Set QQSOffset[QQSFindex] = 5.00
-------- ^ This is the speed it travels at outwards --------
-------- --------
Set QQSOffset2[QQSFindex] = 2.00
-------- ^ This is the speed it travels back inwards --------
-------- --------
-------- --------
Set QQSMaxDistanceInward[QQSFindex] = 100.00
-------- --------
Set QQSMaxDistanceOutward[QQSFindex] = 400.00
-------- --------
Set QQSFTimeCheckOutwards[QQSFindex] = (QQSFlevel[QQSFindex] x 50)
-------- --------
Set QQSFTimeCheckInwards[QQSFindex] = (QQSFlevel[QQSFindex] x 30)
-------- --------
Set QQSRotationSpeed[QQSFindex] = 25.00
-------- --------
-------- The timer/event in Starfury LoopQQ can be changed however that is the only configurable in the last part --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
QQSFindex Equal to 1
Then - Actions
Trigger - Turn on Starfury LoopQQ <gen>
Else - Actions
-------- --------
Custom script: call RemoveLocation(udg_QQSFp)
[/TRIGGER]


[TRIGGER=]
Events
Time - Every 0.07 seconds of game time
Conditions
Actions
-------- ^ The event runs on a 0.07 seconds timer to allow for smooth executions of this spell --------
-------- If you need faster/smoother then use any number below 0.07 except for 0.01 and 0.02 --------
-------- 0.01 and 0.02 are not visible to the human eye --------
-------- Here we begin the loop because this is how I chose to index so it could be MUI --------
-------- --------
-------- Nothing past here should be configurable --------
For each (Integer QQSFi) from 1 to QQSFindex, do (Actions)
Loop - Actions
-------- --------
Set QQSFtime[QQSFi] = (QQSFtime[QQSFi] - 1)
-------- ^ is the counter that keeps counting downwards to know when to finish the spell --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
QQSFtime[QQSFi] Greater than or equal to QQSFTimeCheckOutwards[QQSFi]
QQSReal2[QQSFi] Less than or equal to QQSMaxDistanceOutward[QQSFi]
Then - Actions
-------- This is how the dummy units/orbs of light travel outwards --------
Set QQSReal2[QQSFi] = (QQSReal2[QQSFi] + QQSOffset[QQSFi])
Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
QQSFtime[QQSFi] Less than or equal to QQSFTimeCheckInwards[QQSFi]
QQSReal2[QQSFi] Greater than or equal to QQSMaxDistanceInward[QQSFi]
Then - Actions
Set QQSReal2[QQSFi] = (QQSReal2[QQSFi] - QQSOffset2[QQSFi])
-------- This is how the dummy units/orbs of light travel back inwards --------
Else - Actions
Set QQSReal1[QQSFi] = (QQSReal1[QQSFi] + QQSRotationSpeed[QQSFi])
-------- ^ This is how we rotate the two balls of light/dummy units --------
Set QQSFp = (Position of QQSFcaster[QQSFi])
Set QQSFp1 = (QQSFp offset by QQSReal2[QQSFi] towards QQSReal1[QQSFi] degrees)
Set QQSFp2 = (QQSFp offset by (QQSReal2[QQSFi] x -1.00) towards QQSReal1[QQSFi] degrees)
-------- ^ This is where we set the locations for the spell to work --------
Unit - Move QQSFstarunit1[QQSFi] instantly to QQSFp1
Unit - Move QQSFstarunit2[QQSFi] instantly to QQSFp2
-------- ^ movement of the dummy units --------
-------- --------
Special Effect - Create a special effect at QQSFp1 using QQSEffectOnGround
Special Effect - Destroy (Last created special effect)
-------- --------
Special Effect - Create a special effect at QQSFp2 using QQSEffectOnGround
Special Effect - Destroy (Last created special effect)
-------- ^ This is where we create the effects --------
-------- --------
Set QQSGroup = (Units within QQSRadius[QQSFi] of QQSFp1 matching ((((Matching unit) is Magic Immune) Not equal to True) and ((((Matching unit) is dead) Not equal to True) and (((Matching unit) is hidden) Not equal to True))))
Unit Group - Pick every unit in QQSGroup and do (Actions)
Loop - Actions
Set QQSPickedUnit = (Picked unit)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(QQSPickedUnit belongs to an enemy of QQStarFuryOwner[QQSFi]) Equal to True
Then - Actions
Unit - Cause QQSFcaster[QQSFi] to damage QQSPickedUnit, dealing QQSFDamage[QQSFi] damage of attack type QQSAttackType and damage type QQSDamageType
Set QQSPickedUnit = No unit
Else - Actions
Unit - Set life of QQSPickedUnit to ((Life of QQSPickedUnit) + QQSFHeal[QQSFi])
Set QQSPickedUnit = No unit
Custom script: call DestroyGroup(udg_QQSGroup)
-------- --------
Set QQSGroup = (Units within QQSRadius[QQSFi] of QQSFp2 matching ((((Matching unit) is Magic Immune) Not equal to True) and ((((Matching unit) is dead) Not equal to True) and (((Matching unit) is hidden) Not equal to True))))
Unit Group - Pick every unit in QQSGroup and do (Actions)
Loop - Actions
Set QQSPickedUnit = (Picked unit)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Picked unit) belongs to an enemy of QQStarFuryOwner[QQSFi]) Equal to True
Then - Actions
Unit - Cause QQSFcaster[QQSFi] to damage QQSPickedUnit, dealing QQSFDamage[QQSFi] damage of attack type QQSAttackType and damage type QQSDamageType
Set QQSPickedUnit = No unit
Else - Actions
Unit - Set life of QQSPickedUnit to ((Life of QQSPickedUnit) + QQSFHeal[QQSFi])
Set QQSPickedUnit = No unit
Custom script: call DestroyGroup(udg_QQSGroup)
-------- --------
Custom script: call RemoveLocation(udg_QQSFp)
Custom script: call RemoveLocation(udg_QQSFp1)
Custom script: call RemoveLocation(udg_QQSFp2)
-------- --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
Or - Any (Conditions) are true
Conditions
QQSFtime[QQSFi] Equal to 0
(QQSFcaster[QQSFi] is dead) Equal to True
Then - Actions
Special Effect - Destroy QQSFfx[QQSFi]
Special Effect - Destroy QQSFfx2[QQSFi]
-------- --------
Unit - Kill QQSFstarunit1[QQSFi]
Unit - Kill QQSFstarunit2[QQSFi]
-------- --------
Set QQSFcaster[QQSFi] = QQSFcaster[QQSFindex]
Set QQSFcaster[QQSFindex] = No unit
-------- --------
Set QQSFstarunit1[QQSFi] = QQSFstarunit1[QQSFindex]
-------- --------
Set QQSFstarunit1[QQSFindex] = No unit
Set QQSFstarunit2[QQSFi] = QQSFstarunit2[QQSFindex]
-------- --------
Set QQSFstarunit2[QQSFindex] = No unit
Set QQSFlevel[QQSFi] = QQSFlevel[QQSFindex]
-------- --------
Set QQSFDamage[QQSFi] = QQSFDamage[QQSFindex]
-------- --------
Set QQSFHeal[QQSFi] = QQSFHeal[QQSFindex]
-------- --------
Set QQSReal2[QQSFi] = QQSReal2[QQSFindex]
-------- --------
Set QQSRadius[QQSFi] = QQSRadius[QQSFindex]
-------- --------
Set QQSOffset[QQSFi] = QQSOffset[QQSFindex]
-------- --------
Set QQSOffset2[QQSFi] = QQSOffset2[QQSFindex]
-------- --------
Set QQSFtime[QQSFi] = QQSFtime[QQSFindex]
-------- --------
Set QQSRotationSpeed[QQSFi] = QQSRotationSpeed[QQSFindex]
-------- --------
Set QQSFTimeCheckInwards[QQSFi] = QQSFTimeCheckInwards[QQSFindex]
-------- --------
Set QQSFTimeCheckOutwards[QQSFi] = QQSFTimeCheckOutwards[QQSFindex]
-------- --------
Set QQSMaxDistanceInward[QQSFi] = QQSMaxDistanceInward[QQSFindex]
-------- --------
Set QQSMaxDistanceOutward[QQSFi] = QQSMaxDistanceOutward[QQSFindex]
-------- --------
Set QQStarFuryOwner[QQSFi] = QQStarFuryOwner[QQSFindex]
Custom script: set udg_QQStarFuryOwner[udg_QQSFindex] = null
-------- --------
-------- --------
Set QQSFindex = (QQSFindex - 1)
Set QQSFi = (QQSFi - 1)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
QQSFindex Equal to 0
Then - Actions
Trigger - Turn off (This trigger)
Else - Actions
Else - Actions
-------- --------

[/TRIGGER]


Description of spell;

As you find a enemy to try this new spell you stole from one of the horde leaders you find yourself surrounded by an unknown enemy.

As they charge towards you, you use the hotkey "Q" to create a damaging and healing nova that circles yourself traveling a little outwards then returning inwards.

Map Description Template Created by -Kobas-
Find more here: Map Description - Templates


Keywords:
star,nova,cool,epic,dat-c3,dat,c-3,tal,tal0n,cpr,cpr7,7,starfury,fury,jedi,star wars,knight,lol,rofl,fun,epic,physics
Contents

itsa starfury Public V = 2.9 (Map)

Reviews
16:53 12th Jun 2014 BPower: Looks good to me. Approved. 08:44, 7th May 2014 BPower: Awaiting a few small updates, mentioned in the last comments.

Moderator

M

Moderator

16:53 12th Jun 2014
BPower:
Looks good to me. Approved.

08:44, 7th May 2014
BPower:
Awaiting a few small updates, mentioned in the last comments.
 
Fair enough. I'll go through it once the Triggers are up :)

Tuh da :thumbs_up:

Triggers Showing System Now Online!


Hope there's enough customization possible for it to get approved, I know you guys like your customizations.

If you can spot anything that can be removed or taken out to reduce the count of variables, I would definitely appreciate anyone mentioning it if they spot it.
Nobody likes variable fests when trying to make use of the spell/system. Well maybe only the makers of the stuff you used would.

I will also update this once more in the future hopefully sometime soon to maybe add extra functions in like stunning and stuff as well replace some of the functions with more efficient ones so until someone bugs me about it... :grin:yeah =P
 
Level 6
Joined
Dec 9, 2010
Messages
121
My review:

Point #1: You did not give a full description using a template by Kobas, and it is lacking videos and a full credits list. Zomg.

Point #2: You wrote "As you find a enemy to try this new spell you stole from one of the horde leaders you find yourself surrounded by an unknown enemy." This sentence structure is iffy and unclear, and it should be "an" enemy.

Point #3: You put your own name or variations of it in the list of search keys like 5x.

End score: .000001/5. Voting for rejection, not useful spell at all, because clearly the aforementioned things are far more important than the actual spell.[/sarcasm]

Ahem... great spell Dat-C3, it actually works very well, without any lag (as promised). I'm fairly sure Normal Type Damage applies Armor % reduction, was that intended?

Edit: Oops, you do have customizing options, well done!
Edit 2: For anyone interested in triggered damage via spells, here's a link to what I was talking about: http://www.wc3c.net/showpost.php?p=1030046&postcount=19
 
Last edited:
Level 29
Joined
Oct 24, 2012
Messages
6,543
Anything used twice or more should be stored in a variable and the variable should be used.

Example: owner of triggering unit

Also you store triggering unit in a variable use that variable instead of triggering unit.

Store this also.
(Owner of QQSFcaster[QQSFi])

You store both of these things already so you should switch them out.
  • ((Level of (Ability being cast) for (Triggering unit)) x 30)
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
  • Set QQSEffectOnDummyUnits = Abilities\Weapons\WitchDoctorMissile\WitchDoctorMissile.mdl
you dont need to set it at every cast, just set it once :grin:

EDIT
  • Special Effect - Create a special effect attached to the origin of (Last created unit) using QQSEffectOnDummyUnits
set lcu to QQSFstarunit1[QQSFindex]

this still needs many fixes :p good luck
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
oh, did I say many? sorry XD
yeah, there are some lines that only need to be initialized once..

EDIT,
not some :p
only these
  • Set QQSEffectOnGround = Abilities\Spells\Undead\ReplenishHealth\ReplenishHealthCasterOverhead.mdl
    • -------- --------
    • Set QQSDamageType = Spells
and I think AttackType should be configurable too, since it's more important than DamageType..

EDIT 2:
it's better to use if..then..else more than those long lines. so that the code will be neater and it's easy for user to configure it by themselves
  • Unit Group - Pick every unit in (Units within QQSRadius[QQSFi] of QQSFp2 matching ((((Matching unit) belongs to an enemy of (Owner of QQSFcaster[QQSFi])) Equal to True) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) is hidden) Not equal to True)))) and do (Actions)
EDIT 3:
oh, you should notice this thing. :p
DamageType != AttackType

EDIT 4:
what for? :/
  • Set QQSFp1 = QQSFp
  • Set QQSFp3 = QQSFp
EDIT 5:
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
  • If - Conditions
  • QQSFindex Equal to 0
  • Then - Actions
  • Trigger - Turn off (This trigger)
dont check it every 0.07 seconds o.0
 
Last edited:
My name so big wtf :D
  • (Life of QQSFcaster[QQSFi]) <= 0.41
Should be changed to boolean if unit is dead. Checking for life can fail in some cases.

Using a periodic timer would be cooler. Then you also could stop the timer itself instead of turning off the trigger. And then start timer again.
  • Custom script: call ResumeTimer(udg_Timer)
  • Custom script: call PauseTimer(udg_Timer)

But as maybe most GUI-spells are using same methode, this won't be a problem.

The thing with function calls was mentioned already.

@Dalvengyr, your post stretches page for me :(

Cool spell. Also code seems fair and it's easy to read. (except the ugly prefix, .. but thats more a GUI-related issue :S)
 
I think you should you only one comment text tag because it very hard to see and you don't need to put ^ in front.

  • StarfuryQQ
    • Events
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • QQSFindex Equal to 1
        • Then - Actions
          • Trigger - Turn on Starfury LoopQQ <gen>
          • -------- ^ Don't touch this line --------
        • Else - Actions
      • -------- ^ Don't touch this line --------
      • -------- --------
      • Custom script: call RemoveLocation(udg_QQSFp)
      • -------- ^ Don't touch this line --------
How about this

  • StarfuryQQ
    • Events
    • Conditions
    • Actions
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • QQSFindex Equal to 1
        • Then - Actions
          • Trigger - Turn on Starfury LoopQQ <gen>
        • Else - Actions
      • Custom script: call RemoveLocation(udg_QQSFp)
      • -------- --------
Some people they really don't want too much useless comment (Like me) because it's very glitzy.

And you should use: call DestroyGroup() instead of set bj_wantDestroyGroup = true because it's safer than.

In period trigger.

You should put
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • QQSFindex Equal to 0
    • Then - Actions
      • Trigger - Turn off (This trigger)
    • Else - Actions
Inside the Recycler conditions

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • QQSFtime[QQSFi] Equal to 0
          • (Life of QQSFcaster[QQSFi]) Less than or equal to 0.41
    • Then - Actions
      • Special Effect - Destroy QQSFfx[QQSFi]
      • Special Effect - Destroy QQSFfx2[QQSFi]
      • -------- --------
      • Unit - Kill QQSFstarunit1[QQSFi]
      • Unit - Kill QQSFstarunit2[QQSFi]
      • -------- --------
      • Set QQSFcaster[QQSFi] = QQSFcaster[QQSFindex]
      • -------- --------
      • Set QQSFcaster[QQSFindex] = No unit
      • Set QQSFstarunit1[QQSFi] = QQSFstarunit1[QQSFindex]
      • -------- --------
      • Set QQSFstarunit1[QQSFindex] = No unit
      • Set QQSFstarunit2[QQSFi] = QQSFstarunit2[QQSFindex]
      • -------- --------
      • Set QQSFstarunit2[QQSFindex] = No unit
      • Set QQSFlevel[QQSFi] = QQSFlevel[QQSFindex]
      • -------- --------
      • Set QQSFDamage[QQSFi] = QQSFDamage[QQSFindex]
      • -------- --------
      • Set QQSReal2[QQSFi] = QQSReal2[QQSFindex]
      • Set QQSReal2[QQSFindex] = 0.00
      • -------- --------
      • Set QQSRadius[QQSFi] = QQSRadius[QQSFindex]
      • Set QQSRadius[QQSFindex] = 0.00
      • -------- --------
      • Set QQSOffset[QQSFi] = QQSOffset[QQSFindex]
      • Set QQSOffset[QQSFindex] = 0.00
      • -------- --------
      • Set QQSOffset2[QQSFi] = QQSOffset2[QQSFindex]
      • Set QQSOffset2[QQSFindex] = 0.00
      • -------- --------
      • Set QQSFtime[QQSFi] = QQSFtime[QQSFindex]
      • Set QQSFtime[QQSFindex] = 0
      • -------- --------
      • Set QQSRotationSpeed[QQSFi] = QQSRotationSpeed[QQSFindex]
      • Set QQSRotationSpeed[QQSFindex] = 0.00
      • -------- --------
      • Set QQSFTimeCheckInwards[QQSFi] = QQSFTimeCheckInwards[QQSFindex]
      • Set QQSFTimeCheckInwards[QQSFindex] = 0
      • -------- --------
      • Set QQSFTimeCheckOutwards[QQSFi] = QQSFTimeCheckOutwards[QQSFindex]
      • Set QQSFTimeCheckOutwards[QQSFindex] = 0
      • -------- --------
      • Set QQSMaxDistanceInward[QQSFi] = QQSMaxDistanceInward[QQSFindex]
      • Set QQSMaxDistanceInward[QQSFindex] = 0.00
      • -------- --------
      • Set QQSMaxDistanceOutward[QQSFi] = QQSMaxDistanceOutward[QQSFindex]
      • Set QQSMaxDistanceOutward[QQSFindex] = 0.00
      • -------- --------
      • Set QQSFindex = (QQSFindex - 1)
      • Set QQSFi = (QQSFi - 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • QQSFindex Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
    • Else - Actions
Because it's doesn't need to Check the conditions every periodic.

And I think use timer window faster than trigger timer ;).

And this can be optimize
  • Actions
    • Set QQSFp = (Position of QQSFcaster[QQSFi])
    • Set QQSFp1 = QQSFp
    • Set QQSFp2 = (QQSFp1 offset by QQSReal2[QQSFi] towards QQSReal1[QQSFi] degrees)
    • Set QQSFp3 = QQSFp
    • Set QQSFp4 = (QQSFp3 offset by (QQSReal2[QQSFi] x -1.00) towards QQSReal1[QQSFi] degrees)
=>

  • Actions
    • Set QQSFp = (Position of QQSFcaster[QQSFi])
    • Set QQSFp2 = (QQSFp offset by QQSReal2[QQSFi] towards QQSReal1[QQSFi] degrees)
    • Set QQSFp4 = (QQSFp offset by (QQSReal2[QQSFi] x -1.00) towards QQSReal1[QQSFi] degrees)
  • Unit Group - Pick every unit in (Units within QQSRadius[QQSFi] of QQSFp2 matching ((((Matching unit) belongs to an enemy of (Owner of QQSFcaster[QQSFi])) Equal to True) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) is hidden) Not equal to True)))) and do (Actions)
    • Loop - Actions
      • Unit - Cause QQSFcaster[QQSFi] to damage (Picked unit), dealing QQSFDamage[QQSFi] damage of attack type QQSDamageType and damage type Magic
Save Owner of QQSFcaster[QQSFi] into player variable

And you forgot to disable Starfury LoopQQ trigger.

And how about this
  • Animation - Change (Last created unit) flying height to 75.00 at 75.00
0.0 => instantly change unit flying height to 75.00.
75.00 => Fly low to high (This is cooler) (Well it's not important, I just contributed the ideas)
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Any protectiles should run at least on a constant timeout of 0.03.
Any values above will look edged. This has not so much to do with game perfomance, but with the capability of human brain areas (mainly Br 17, 18, 19) which are responsible for evaluating visual stimuli.
If the timeout surpases a certain interval the movement isn't smooth anymore.

The configuration trigger should cover:
  • Ability variable. In GUI this is a variable of type "ability". Basically it's just an integer.
    You will also get rid of the function call Ability beeing cast, as you can compare it directly with the ability variable.
    .
  • Normally everything which is set to variables in the cast trigger (distance, base damage, increment damage, duration ..).
In the loop picked unit could be stored into a variable.
Nulling array's which hold an handle is something I rarely see in GUI. :thumbs_up: BUT you don't have to set variables of type real to 0.00 :thumbs_down:.
Reals, Integers and booleans are not handles and there is no reference, which could be reset.

You set the player to neutal passive. Any deeper thoughts behind it?
Player variables are nulled this way --> set Player = null. However players are constant information set on map init and don't have to be nulled at all.
 
Then anyone should be able to easily modify that, well I will add a comment later to let them know to change it if needed.
I think it looks good, have you tried it in-game BPower?

Well I wanted to be sure, will upload 2.9 soon with fixes.
There is already so many variables, I will see about it though.
I kind of couldn't remember or find how to null a player so I made a quick-fix of my own... =)
Doesn't it leak if you don't null a player array?

I don't understand the ability part(Is it faster?) however everything else is already configurable.

Thank you for taking your time to review and check it over. =)
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
I've put this in JASS tags, because I think it is very easy to understand.
If you are using an ability variable you get rid of the hexadecimal conversion 'A001' and the
second GetSpellAbilityId() function call. Feel free to ask questions if this is not clear to you.

In its current state it is:
JASS:
function Trig_StarfuryQQ_Copy_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A001' ) ) then
        return false
    endif
    return true
endfunction
and I want it to be
JASS:
function Trig_StarfuryQQ_Copy_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == udg_QQSFAbility ) ) then
        return false
    endif
    return true
endfunction
Furthermore this set udg_QQSFlevel[udg_QQSFindex] = GetUnitAbilityLevelSwapped(GetSpellAbilityId(), udg_QQSFcaster[udg_QQSFindex]) will become
set udg_QQSFlevel[udg_QQSFindex] = GetUnitAbilityLevelSwapped(udg_QQSFAbility, udg_QQSFcaster[udg_QQSFindex])
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
StarFuryInitQQ should run on map init.
The timeout should be 0.03 and not 0.07. (0.01/0.02 are of course visible for human eyes but you can't really tell a difference)
Player variables don't have to be nulled, they are constant handles.
The tooltips are the same for each level. You can use the Blizzard default tooltip as template (You don't have to provide 5 levels, 3 are totally fine)

All together the code looks good. Concept and effects are okay. The name doesn't really fit to the spell concept (my opinion here)

Please fix the tooltips and we are good to go.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
As you already know anything used twice or more should be stored into a variable and the variable should be used.

Picked unit in this will always be used twice and it should be stored.
  • Unit Group - Pick every unit in QQSGroup and do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Picked unit) belongs to an enemy of QQStarFuryOwner[QQSFi]) Equal to True
        • Then - Actions
          • Unit - Cause QQSFcaster[QQSFi] to damage (Picked unit), dealing QQSFDamage[QQSFi] damage of attack type QQSAttackType and damage type QQSDamageType
        • Else - Actions
          • Unit - Set life of (Picked unit) to ((Life of (Picked unit)) + QQSFHeal[QQSFi])
You store last created unit but don't use it in the actions that follow.

  • Set QQSFstarunit2[QQSFindex] = (Last created unit)
  • -------- --------
  • Special Effect - Create a special effect attached to the origin of QQSFstarunit2[QQSFindex] using QQSEffectOnDummyUnits
  • Set QQSFfx2[QQSFindex] = (Last created special effect)
  • -------- --------
  • -------- this is where we set the size of the main rotating units --------
  • Animation - Change (Last created unit)'s size to (300.00%, 100.00%, 100.00%) of its original size
  • -------- This is so they dont look like they are on the ground. --------
  • Animation - Change (Last created unit) flying height to 75.00 at 0.00
 
Ah nice catch, thanks death. Yeah I know, it is just I don't get to stuff fast. Thanks again for catching my little flaws. =)

Edit: Everything is currently fixed, and I won't change the timer, that is up to whoever uses my spell. It works exactly as I made it and pictured it so I kind of want it to stay that way. However I did provide instructions on how to change it if they want it faster/smoother.
 
Last edited:

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
have you updated the trigger? if so, then here is more:

  • Time - Elapsed game time is 0.00 seconds
configuration must be run in map initialization


  • (Ability being cast) Equal to Starfury
Starfury (ability) must be stored in a variable, and allow user to edit it at configuration as well.


  • Set QQSFlevel[QQSFindex] = (Level of QQSAbility for QQSFcaster[QQSFindex])
I think it's bugged, what's QQSAbility? you never define it


  • Animation - Change QQSFstarunit1[QQSFindex]'s size to (300.00%, 100.00%, 100.00%) of its original size
how bout if the scale is configurable for user?


  • -------- This is the damage that is dealt every 0.07 seconds --------
  • Set QQSFDamage[QQSFindex] = (35.00 x (Real(QQSFlevel[QQSFindex])))
  • -------- This is the amount that is healed every 0.07 seconds --------
  • Set QQSFHeal[QQSFindex] = (10.00 x (Real(QQSFlevel[QQSFindex])))
  • -------- --------
  • -------- This is the distance away from the caster the two dummy units start at --------
  • Set QQSReal2[QQSFindex] = 50.00
  • -------- As well it is what lets them move outward and inward --------
  • -------- --------
  • -------- This is the area of space that is checked for to damage units inside it --------
  • Set QQSRadius[QQSFindex] = (90.00 + (10.00 x (Real(QQSFlevel[QQSFindex]))))
  • -------- --------
  • Set QQSOffset[QQSFindex] = 5.00
  • -------- ^ This is the speed it travels at outwards --------
  • -------- --------
  • Set QQSOffset2[QQSFindex] = 2.00
  • -------- ^ This is the speed it travels back inwards --------
  • -------- --------
  • -------- --------
  • Set QQSMaxDistanceInward[QQSFindex] = 100.00
  • -------- --------
  • Set QQSMaxDistanceOutward[QQSFindex] = 400.00
  • -------- --------
  • Set QQSFTimeCheckOutwards[QQSFindex] = (QQSFlevel[QQSFindex] x 50)
  • -------- --------
  • Set QQSFTimeCheckInwards[QQSFindex] = (QQSFlevel[QQSFindex] x 30)
  • -------- --------
  • Set QQSRotationSpeed[QQSFindex] = 25.00
I think those line could be configurable? since your configuration trigger is a bit too short..

  • Set QQStarFuryOwner[QQSFindex] = (Triggering player)
put it at the top then:
  • Unit - Create 1 Dummy for QQStarFuryOwner[QQSFindex] at QQSFp facing Default building facing degrees

  • Set QQSPickedUnit = No unit
that's unneeded since it's global variable


also, as BPower have said, run the loop every 0.03 second
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
have you updated the trigger? if so, then here is more:

  • Time - Elapsed game time is 0.00 seconds
configuration must be run in map initialization

That is not true. 0.00 is fine to run initialization for a spell / system.

  • (Ability being cast) Equal to Starfury
Starfury (ability) must be stored in a variable, and allow user to edit it at configuration as well.

That is not needed as it is easy to find at top of trigger.

  • -------- This is the damage that is dealt every 0.07 seconds --------
  • Set QQSFDamage[QQSFindex] = (35.00 x (Real(QQSFlevel[QQSFindex])))
  • -------- This is the amount that is healed every 0.07 seconds --------
  • Set QQSFHeal[QQSFindex] = (10.00 x (Real(QQSFlevel[QQSFindex])))
  • -------- --------
  • -------- This is the distance away from the caster the two dummy units start at --------
  • Set QQSReal2[QQSFindex] = 50.00
  • -------- As well it is what lets them move outward and inward --------
  • -------- --------
  • -------- This is the area of space that is checked for to damage units inside it --------
  • Set QQSRadius[QQSFindex] = (90.00 + (10.00 x (Real(QQSFlevel[QQSFindex]))))
  • -------- --------
  • Set QQSOffset[QQSFindex] = 5.00
  • -------- ^ This is the speed it travels at outwards --------
  • -------- --------
  • Set QQSOffset2[QQSFindex] = 2.00
  • -------- ^ This is the speed it travels back inwards --------
  • -------- --------
  • -------- --------
  • Set QQSMaxDistanceInward[QQSFindex] = 100.00
  • -------- --------
  • Set QQSMaxDistanceOutward[QQSFindex] = 400.00
  • -------- --------
  • Set QQSFTimeCheckOutwards[QQSFindex] = (QQSFlevel[QQSFindex] x 50)
  • -------- --------
  • Set QQSFTimeCheckInwards[QQSFindex] = (QQSFlevel[QQSFindex] x 30)
  • -------- --------
  • Set QQSRotationSpeed[QQSFindex] = 25.00
I think those line could be configurable? since your configuration trigger is a bit too short..

They are configurable. But I think it should say above them that they can be configured and after the last configurable one say nothing past here is configurable.

  • Set QQSPickedUnit = No unit
that's unneeded since it's global variable

Actually this is fine. It releases the handle that the global uses. That is why in my tutorial I say to null every global.

also, as BPower have said, run the loop every 0.03 second

This should definitely be changed.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
That is not true. 0.00 is fine to run initialization for a spell / system.
it must be run on map init. somehow it's better.
That is not needed as it is easy to find at top of trigger.
it's quite important, in case user want to use another base ability. so they can easily change the variable in configuration part and no need to touch the main code
They are configurable. But I think it should say above them that they can be configured and after the last configurable one say nothing past here is configurable.
again, put it in configuration part so that users dont have any doubt and worries to edit it. you should separate which one is editable and not editable, so that user wont mess everything up. remember not all users here are coder :)
Actually this is fine. It releases the handle that the global uses. That is why in my tutorial I say to null every global.
I guess it does leak for local, but not for global
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
it must be run on map init. somehow it's better.

No this is not true. All of my systems and spells run at 0.00 not at map init.
There is not a problem.

it's quite important, in case user want to use another base ability. so they can easily change the variable in configuration part and no need to touch the main code

The other configurables are already in that function anyways. It is a quick and easy thing as it is now.

again, put it in configuration part so that users dont have any doubt and worries to edit it. you should separate which one is editable and not editable, so that user wont mess everything up. remember not all users here are coder :)

If it goes into configuration it would require a function call which means a lot of custom script added. It is fine the way it is. He just needs to highlight what is and is not configurable.

I guess it does leak for local, but not for global

It does not leak for global but it stops the handle from being recycled. That means that if that variable is never used after it is unnecessarily using handles. It is good to null them but not required.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
so why most moderators always point that out, so I guess it's important

no need custom script & extra functions, but anyway, nevermind.

To keep a formula which all of those use it does need to be in a function. Then that function can be called. But since GUI has no way to create / call functions other than custom script. That is why custom script is needed.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
you forgot about variable array? don't talk about memory waste on GUI :D oh, nevermind. I just think that user-friendliness is more important than anything, after efficiency..

User friendliness is good yes. But I believe that it is very easy to figure out what is and is not configurable if it says they are / are not configurable.
 
Thanks for the defence death as well glad you liked my spell Wrda. =)

I won't change to map init and I won't change the timer my spell runs on, I have already commented on how to change it if the user decides so.

By using map init your causing extra strain on load time in the loading screen.
It's best to load short little spells/systems once the game starts.

Will upload fixed version with fixed triggers in post shortly.
Thanks again death as well thanks for pointing out I missed a few configurables Dalvengyr.


Sadly I named my variables horribly HOWEVER this way it will never get mixed up or messed up within another spell or system whenever you import my spell.
 
Last edited:
Starfury - Public Version 2.98 by Dat-C3 - Reviewed by IcemanBo

  • -------- This is what makes it decide to go through armor or not. --------
  • Set QQSDamageType = Magic
From the comment it looks like it would make more sense to use a boolean here.

  • -------- How long the spell will last --------
  • Set QQSFtime[QQSFindex] = (80 x QQSFlevel[QQSFindex])
Actually it is how often the periodic event will operate with it, and just indirectly 80x. ( user could think 80 seconds)

  • Set QQSFTimeCheckOutwards[QQSFindex] = (QQSFlevel[QQSFindex] x 50)
  • -------- --------
  • Set QQSFTimeCheckInwards[QQSFindex] = (QQSFlevel[QQSFindex] x 30)
Are these really needed? I saw you already use minimum and maximum range config, which is quite cool.
Something like this:


If currentDistance <= min distance
--> set offset positive

Else If currentDistance >= max
--> set offset negative

Set position = position + offset
(After the If/Then/Else)

  • ((Picked unit) belongs to an enemy of QQStarFuryOwner[QQSFi]) Equal to True
You could use "QQSPickedUnit" here, instead of "Picked unit". :p

I'm also for .03 as interval, it's just more smooth. But this anyway was mentioned already and it's your choice.

Me don't see much sense in nulling global unit variables, because you will re-use it in all but one case, but it's not really a problem I guess.
__________________________________________________

If you would change the changing-offset method, like I made in an my example and use the variable instead of "Picked unit" I vote for approval. It look's cool :thumbs_up:
 
Booleans don't work with damage types and the user doesn't need more variables.

Set QQSFtime[QQSFi] = (QQSFtime[QQSFi] - 1) every 0.07 seconds is not a second therefore I did not want to misinform people. There is no exact/specific ability to tell how long it'll last yet. Will work on that.

Yes those are needed, spell won't work without them going outwards then inwards. Your thinking is smart, but at the same time I don't think it will work.

Yet another little error I missed, thanks. =)

You do not need .03 all the time for a interval for the timer event. More smooth yet again isn't needed because this was exactly what I was going for and pictured, thanks though. Null all possible leaks, obliterate all enemies.

Changing a few things such as that hidden picked unit error. The offset method I might look into, but I really doubt I will change that.

Thanks for the review IcemanBo. =)
 
Hm with the boolean I actually meant a bit different. You say in comment something like choose "magic" to ignore armor, or "normal" not to ignore armor.

And I suggested to use a boolean "IgnoreArmor". If it's true, then you automatically use "magic" for demage, else you use "normal" in your code.

This way it would be a bit safer for the user maybe, because he can't really modify it to other attack types.

For the 0.07 timeout. If you think all is good enough, and it would not be smoother with 0.03 then just let it as it is I suggest. :)

But I'm pretty sure my method with offset changing would work fine. Good luck with it.
 
That is an extra un-needed variable still however good idea, I will add that into comments later. I don't see how your offset method would work, what I did are time checkers because I wanted it to stay moving outwards at a certain area for so long which is why your suggestion won't work. Thanks for the idea about that comment-suggestion though.

death the problem is your missing my point. This spell I decided to make was made to fit 0.07 and it will actually lag less then a 0.03 at the same time so it is a bonus for the user of my spell. Smoother is not always better, especially in WC3. Best time period for visual yes, however not to performance. An example being if you don't understand would be well run 30-50 or maybe even 90 spells/things at 0.03 for about five minutes with /fps. Has to have a special effect of some kind, can't be a no-sfx damage type. =P
 
Top