• 🏆 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!

Spells & Systems Mini-Contest #20

Status
Not open for further replies.
Level 37
Joined
Mar 6, 2006
Messages
9,240
. . . WHY WON'T THIS WORK, WHY!! It's all your fault baassee, you made me use hashtables again.

  • (1 is stored as a Handle of SL_ID in SL_Hashtable) Equal to False
->
  • (0 is stored as a Handle of Key(Picked unit) in SL_Hashtable) Equal to False
  • Hashtable - Save Handle Of(Last created special effect) as 0 of (Key (Load 1 of SL_ID from SL_Hashtable)) in SL_Hashtable
->
  • Hashtable - Save Handle Of(Last created special effect) as 0 of (Key (Picked unit))) in SL_Hashtable
  • Set SL_Effect = (Load 0 of (Key (Load 1 of SL_ID from SL_Hashtable)) in SL_Hashtable)
->
  • Set SL_Effect = (Load 0 of (Key (Picked unit)) in SL_Hashtable)
There are a few other things I'd like to point out but that would be helping too much. What the heck:
*Unnecessary conversion
*Unnecessary AND
*Leak
*Unnecessary array
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
Why don't you show all the triggers as you said that it only is the "hashtable part"?

Yet I hate hashtables in GUI and you leak a bit in your triggers and there are a few more improvement points there!

I might even come up with a wip this weekend (I will probably regret that I wrote this).
 
Better?
  • Sages Lore Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Sage's Lore
    • Actions
      • -------- Setup Spell --------
      • Set SL_ID = (Key (Triggering Unit))
      • -------- The Casting Unit --------
      • Set SL_Caster = (Triggering unit)
      • -------- The Amount of Damage dealt to the target --------
      • Set SL_Damage = (25 + (5 x (Level of Sage's Lore for (Triggering unit))))
      • -------- Area of ability being cast at --------
      • Set SL_Point = (Target point of ability being cast)
      • -------- Setup Spell --------
      • -------- Sounds --------
      • Sound - Play DispelMagicTarget <gen> at 100.00% volume, located at SL_Point with Z offset 0.00
      • Sound - Destroy (Last played sound)
      • -------- Sounds --------
      • -------- Effects --------
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Human\DispelMagic\DispelMagicTarget.mdl
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Items\TomeOfRetraining\TomeOfRetrainingCaster.mdl
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Other\Charm\CharmTarget.mdl
      • Special Effect - Destroy (Last created special effect)
      • -------- Effects --------
      • -------- Add Units at SL_Point[0] to a unit group --------
      • Unit Group - Pick every unit in (Units within 256.00 of SL_Point matching (((Matching unit) belongs to an enemy of (Owner of SL_Caster)) Equal to True)) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • And - All (Conditions) are true
                • Conditions
                  • ((Picked unit) is A structure) Equal to False
                  • (0 is stored as a Handle of (Key (Picked Unit)) in SL_Hashtable) Equal to False
            • Then - Actions
              • Unit Group - Add (Picked unit) to SL_UnitGroup
              • Special Effect - Create a special effect attached to the overhead of (Picked unit) using Abilities\Spells\Human\Banish\BanishTarget.mdl
              • Hashtable - Save Handle Of(Last created special effect) as 0 of (Key (Picked Unit)) in SL_Hashtable
            • Else - Actions
      • -------- Add Units at SL_Point[0] to a unit group --------
      • -------- Remove leaks --------
      • Custom script: call RemoveLocation(udg_SL_Point)
  • Sages Lore Over Time
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in SL_UnitGroup and do (Actions)
        • Loop - Actions
          • -------- Units that still have the Sage's Lore Buff will take damage --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Sage's Lore ) Equal to True
            • Then - Actions
              • -------- Position of unit that has buff --------
              • Set SL_Point = (Position of (Picked unit))
              • -------- Effects --------
              • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Other\Silence\SilenceAreaBirth.mdl
              • Special Effect - Destroy (Last created special effect)
              • -------- Effects --------
              • -------- Damage --------
              • Unit - Cause SL_Caster to damage (Picked unit), dealing (Real(SL_Damage)) damage of attack type Spells and damage type Normal
              • Unit - Set mana of (Picked unit) to ((Mana of (Picked unit)) - (Real(SL_Damage)))
              • -------- Damage --------
              • -------- Sounds --------
              • Sound - Play Feedback <gen> at 100.00% volume, attached to (Picked unit)
              • Sound - Destroy (Last played sound)
              • -------- Sounds --------
              • -------- Remove Leaks --------
              • Custom script: call RemoveLocation(udg_SL_Point)
            • Else - Actions
              • Set SL_Effect = (Load 0 of (Key (Picked Unit)) in SL_Hashtable)
              • Special Effect - Destroy SL_Effect
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (SL_UnitGroup is empty) Equal to True
        • Then - Actions
          • Custom script: call DestroyGroup(udg_SL_UnitGroup)
        • Else - Actions
  • Sages Lore Unit Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • ((Triggering unit) is in SL_UnitGroup) Equal to True
    • Actions
      • -------- Remove unit from SL Unit group when ability is cast --------
      • Unit Group - Remove (Triggering unit) from SL_UnitGroup
      • Unit - Remove Sage's Lore buff from (Triggering unit)
      • -------- Remove unit from SL Unit group when ability is cast --------
      • -------- Position of the casting unit --------
      • Set SL_Point = (Position of (Triggering unit))
      • -------- Effects --------
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Human\Slow\SlowCaster.mdl
      • Special Effect - Destroy (Last created special effect)
      • -------- Sounds --------
      • Sound - Play DefendCaster <gen> at 100.00% volume, attached to (Triggering unit)
      • Sound - Destroy (Last played sound)
      • -------- Sounds --------
      • -------- Remove Leaks --------
      • Set SL_Effect = (Load 0 of (Key (Picked Unit)) in SL_Hashtable)
      • Special Effect - Destroy SL_Effect
      • Custom script: call RemoveLocation(udg_SL_Point)
      • -------- Remove Leaks --------

Edit: Oh wait it's not even working lol
 
*Fixed, but only the first use of the spell works
(made the damage source mui and flushed child hashtable?)
  • Sages Lore Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Sage's Lore
    • Actions
      • -------- Setup Spell --------
      • Set SL_ID = (Key (Triggering Unit))
      • -------- The Casting Unit --------
      • Hashtable - Save Handle Of(Triggering unit) as 0 of (Load 1 of SL_ID from SL_CasterHashtable) in (Last created hashtable)
      • Set SL_Caster = (Load 0 of (Key (Triggering Unit)) in SL_CasterHashtable)
      • -------- The Amount of Damage dealt to the target --------
      • Set SL_Damage = (25 + (5 x (Level of Sage's Lore for (Triggering unit))))
      • -------- Area of ability being cast at --------
      • Set SL_Point = (Target point of ability being cast)
      • -------- Setup Spell --------
      • -------- Sounds --------
      • Sound - Play DispelMagicTarget <gen> at 100.00% volume, located at SL_Point with Z offset 0.00
      • Sound - Destroy (Last played sound)
      • -------- Sounds --------
      • -------- Effects --------
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Human\DispelMagic\DispelMagicTarget.mdl
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Items\TomeOfRetraining\TomeOfRetrainingCaster.mdl
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Other\Charm\CharmTarget.mdl
      • Special Effect - Destroy (Last created special effect)
      • -------- Effects --------
      • -------- Add Units at SL_Point[0] to a unit group --------
      • Unit Group - Pick every unit in (Units within 256.00 of SL_Point matching (((Matching unit) belongs to an enemy of (Owner of SL_Caster)) Equal to True)) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • And - All (Conditions) are true
                • Conditions
                  • ((Picked unit) is A structure) Equal to False
                  • (0 is stored as a Handle of (Key (Picked Unit)) in SL_Hashtable) Equal to False
            • Then - Actions
              • Unit Group - Add (Picked unit) to SL_UnitGroup
              • Special Effect - Create a special effect attached to the overhead of (Picked unit) using Abilities\Spells\Human\Banish\BanishTarget.mdl
              • Hashtable - Save Handle Of(Last created special effect) as 0 of (Key (Picked Unit)) in SL_Hashtable
            • Else - Actions
      • -------- Add Units at SL_Point[0] to a unit group --------
      • -------- Remove leaks --------
      • Custom script: call RemoveLocation(udg_SL_Point)
  • Sages Lore Over Time
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in SL_UnitGroup and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (SL_UnitGroup is empty) Equal to True
            • Then - Actions
              • Custom script: call DestroyGroup(udg_SL_UnitGroup)
              • Hashtable - Clear all child hashtables of child (Load (Key (Picked Unit)) of SL_ID from SL_Hashtable) in SL_Hashtable
            • Else - Actions
          • -------- Units that still have the Sage's Lore Buff will take damage --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Sage's Lore ) Equal to True
            • Then - Actions
              • -------- Position of unit that has buff --------
              • Set SL_Point = (Position of (Picked unit))
              • -------- Effects --------
              • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Other\Silence\SilenceAreaBirth.mdl
              • Special Effect - Destroy (Last created special effect)
              • -------- Effects --------
              • -------- Damage --------
              • Set SL_Caster = (Load 0 of (Load 1 of SL_ID from SL_CasterHashtable) in SL_CasterHashtable)
              • Unit - Cause SL_Caster to damage (Picked unit), dealing (Real(SL_Damage)) damage of attack type Spells and damage type Normal
              • Unit - Set mana of (Picked unit) to ((Mana of (Picked unit)) - (Real(SL_Damage)))
              • -------- Damage --------
              • -------- Sounds --------
              • Sound - Play Feedback <gen> at 100.00% volume, attached to (Picked unit)
              • Sound - Destroy (Last played sound)
              • -------- Sounds --------
              • -------- Remove Leaks --------
              • Custom script: call RemoveLocation(udg_SL_Point)
            • Else - Actions
              • Set SL_Effect = (Load 0 of (Key (Picked Unit)) in SL_Hashtable)
              • Special Effect - Destroy SL_Effect
  • Sages Lore Unit Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • ((Triggering unit) is in SL_UnitGroup) Equal to True
    • Actions
      • -------- Remove unit from SL Unit group when ability is cast --------
      • Unit Group - Remove (Triggering unit) from SL_UnitGroup
      • Unit - Remove Sage's Lore buff from (Triggering unit)
      • -------- Remove unit from SL Unit group when ability is cast --------
      • -------- Position of the casting unit --------
      • Set SL_Point = (Position of (Triggering unit))
      • -------- Effects --------
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Human\Slow\SlowCaster.mdl
      • Special Effect - Destroy (Last created special effect)
      • -------- Sounds --------
      • Sound - Play DefendCaster <gen> at 100.00% volume, attached to (Triggering unit)
      • Sound - Destroy (Last played sound)
      • -------- Sounds --------
      • -------- Remove Leaks --------
      • Set SL_Effect = (Load 0 of (Key (Triggering Unit)) in SL_Hashtable)
      • Special Effect - Destroy SL_Effect
      • Custom script: call RemoveLocation(udg_SL_Point)
      • -------- Remove Leaks --------
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Berb, you could potentially check if a unit is still casting the ability...

(Current order of Caster_Gun) Equal to (Order(GunORDERID))
True, then do actions
False, then stop...
________________

It isn't quite that simple. The unit, up until the point where it casts the spell, is constantly having its orders canceled (its targeting orders). This yields the unit's "current order" in most cases to be 0. I am still trying to play around with the concept.
 
Level 16
Joined
Jun 24, 2009
Messages
1,409
When I try to change a dummy's size it disappears :/
Why?
  • Then - Actions
    • Unit Group - Pick every unit in SBChannelGroup[SBInteger] and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • SBScale[SBInteger] Less than 0.51
          • Then - Actions
            • Set SBScale[SBInteger] = 4.00
          • Else - Actions
            • Set SBScale[SBInteger] = (SBScale[SBInteger] - 0.50)
        • Animation - Change (Picked unit)'s size to (SBScale[SBInteger]%, SBScale[SBInteger]%, SBScale[SBInteger]%) of its original size
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
Venge

Hashtable - Save Handle Of(Triggering unit) as 0 of (Load 1 of SL_ID from SL_CasterHashtable) in (Last created hashtable)

Yet your spell will not be 100% MUI if you use the id of the caster, what happens if he casts twice? It will be overwritten? Same with the picked units.

Also why are you using two hashtables?
 
Pharaoh_ already helped me fix the trigger, thanks.
Edit: Hopefully the final version.
Final
Based on:
Sages-Lore.png
The Vindicator unleashes forgotten lore,
causing enemy units to lose health and mana until they cast a spell.
  • Sages Lore Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Sage's Lore
    • Actions
      • -------- Setup Spell --------
      • -------- The Amount of Damage dealt to the target --------
      • Set SL_Damage = (25.00 + (5.00 + (Real((Level of (Ability being cast) for (Triggering unit))))))
      • -------- Area of ability being cast at --------
      • Set SL_Point = (Target point of ability being cast)
      • -------- Duration --------
      • Set SL_Duration = 6.00
      • -------- Effects --------
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Human\DispelMagic\DispelMagicTarget.mdl
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Other\Charm\CharmTarget.mdl
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Other\Doom\DoomDeath.mdl
      • Special Effect - Destroy (Last created special effect)
      • -------- Effects --------
      • -------- Add Units at SL_Point[0] to a unit group --------
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 256.00 of SL_Point matching ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) belongs to an enemy of (Owner of SL_Caster)) Equal to True) and (((Matching unit) is in SL_UnitGroup) Equal to False)))) and do (Actions)
        • Loop - Actions
          • Hashtable - Save Handle Of(Triggering unit) as 0 of (Key (Picked unit)) in SL_CasterHashtable
          • Hashtable - Save SL_Duration as 1 of (Key (Picked unit)) in SL_CasterHashtable
          • Hashtable - Save SL_Damage as 2 of (Key (Picked unit)) in SL_CasterHashtable
          • Unit Group - Add (Picked unit) to SL_UnitGroup
          • Set SL_EnemyPoint = (Position of (Picked unit))
          • Unit - Create 1 Footman for (Owner of (Triggering unit)) at SL_EnemyPoint facing Default building facing degrees
          • Unit - Hide (Last created unit)
          • Unit - Add Sage's Lore Buff to (Last created unit)
          • Unit - Order (Last created unit) to Orc Shaman - Bloodlust (Picked unit)
          • Unit - Add a 2.00 second Generic expiration timer to (Last created unit)
          • Custom script: call RemoveLocation(udg_SL_EnemyPoint)
      • Trigger - Turn on Sages Lore Over Time <gen>
      • -------- Remove leaks --------
      • Custom script: call RemoveLocation(udg_SL_Point)
  • Sages Lore Over Time
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (SL_UnitGroup is empty) Equal to False
        • Then - Actions
          • Unit Group - Pick every unit in SL_UnitGroup and do (Actions)
            • Loop - Actions
              • Set SL_LoadDuration = (Load 1 of (Key (Picked unit)) from SL_CasterHashtable)
              • -------- Units that still have the Sage's Lore Buff will take damage --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • SL_LoadDuration Greater than 0.00
                • Then - Actions
                  • Hashtable - Save (SL_LoadDuration - 1.00) as 1 of (Key (Picked unit)) in SL_CasterHashtable
                  • -------- Position of unit that has buff --------
                  • Set SL_Point = (Position of (Picked unit))
                  • -------- Effects --------
                  • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Other\Silence\SilenceAreaBirth.mdl
                  • Special Effect - Destroy (Last created special effect)
                  • -------- Effects --------
                  • -------- Damage --------
                  • Set SL_DamageLoad = (Load 2 of (Key (Picked unit)) from SL_CasterHashtable)
                  • Set SL_Caster = (Load 0 of (Key (Picked unit)) in SL_CasterHashtable)
                  • Unit - Cause SL_Caster to damage (Picked unit), dealing SL_DamageLoad damage of attack type Spells and damage type Normal
                  • Unit - Set mana of (Picked unit) to ((Mana of (Picked unit)) - SL_DamageLoad)
                  • -------- Damage --------
                  • -------- Remove Leaks --------
                  • Custom script: call RemoveLocation(udg_SL_Point)
                • Else - Actions
                  • Unit Group - Remove (Picked unit) from SL_UnitGroup
                  • Custom script: call UnitRemoveAbility (GetEnumUnit(), udg_SL_ABILITYID)
                  • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in SL_CasterHashtable
        • Else - Actions
          • Trigger - Turn off (This trigger)

  • Sages Lore Unit Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • ((Triggering unit) is in SL_UnitGroup) Equal to True
    • Actions
      • Set SL_ID = (Key (Triggering Unit))
      • -------- Remove unit from SL Unit group when ability is cast --------
      • Unit Group - Remove (Triggering unit) from SL_UnitGroup
      • Custom script: call UnitRemoveAbility (GetTriggerUnit(), udg_SL_ABILITYID)
      • -------- Remove unit from SL Unit group when ability is cast --------
      • -------- Position of the casting unit --------
      • Set SL_Point = (Position of (Triggering unit))
      • -------- Effects --------
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Human\Slow\SlowCaster.mdl
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect at SL_Point using Abilities\Spells\Other\Doom\DoomDeath.mdl
      • Special Effect - Destroy (Last created special effect)
      • -------- Sounds --------
      • -------- Sounds --------
      • -------- Remove Leaks --------
      • Custom script: call RemoveLocation(udg_SL_Point)
      • Hashtable - Clear all child hashtables of child SL_ID in SL_CasterHashtable
      • -------- Remove Leaks --------

Thanks to Pharaoh_ , Maker and baassee
 

Attachments

  • K_Spells20b.w3x
    44.1 KB · Views: 58
Level 19
Joined
Feb 4, 2009
Messages
1,313
Using no custom models will make that beam rather tricky, but if someone can pull it off well done in advance!

maybe we are allowed to modify the lightning data slk by hex editing the w3x file :p

the "no imports" rule reduces the quality of the spell and I therefore think it's stupid

and I don't play other games (actually I even don't play wc3 anymore) and stealing spells from other games is stupid
reminds me of the spell section with <random dota spell>, <random dota spell>, <random dota spell>, ...

I won't take part (only contest I waited for :(
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
maybe we are allowed to modify the lightning data slk by hex editing the w3x file :p

Not sure why you would Hex-edit an SLK file but go ahead...

the "no imports" rule reduces the quality of the spell and I therefore think it's stupid

This is a Triggers & Scripts contest, not a Resources contest. I don't know where you find the lack of rationality there.

and I don't play other games (actually I even don't play wc3 anymore) and stealing spells from other games is ridiculous
all spell-ideas but mine are stupid so how can I make good spells by stealing others!

I don't really play games either, but I came up with a pretty random idea based on a Call of Duty game ability. That's where the creativity comes into play. There are a lot of cool abilities you could take from Diablo II.

I won't take part (only contest I waited for :(

I don't get it. You waited for this contest but since it has a theme and you're not allowed to artificially spice it with imports you're not going to take part in it. That's not a very good attitude!
 
Level 20
Joined
Jul 6, 2009
Messages
1,885
and I don't play other games (actually I even don't play wc3 anymore) and stealing spells from other games is stupid
reminds me of the spell section with <random dota spell>, <random dota spell>, <random dota spell>, ...
I'm making a spell from a game i didn't even play D:
A vid on youtube + googling the spell name for description helped tho.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
D4RK_G4ND4LF said:
and I don't play other games (actually I even don't play wc3 anymore) and stealing spells from other games is stupid
reminds me of the spell section with <random dota spell>, <random dota spell>, <random dota spell>, ...

D4RK_G4ND4LF said:
and I don't play other games (actually I even don't play wc3 anymore) and stealing spells from other games is ridiculous
all spell-ideas but mine are stupid so how can I make good spells by stealing others!

Now you're changing your story! So which is it!
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
Now you're changing your story! So which is it!

both
and I edited before you posted just in case you think was because of that

This is a Triggers & Scripts contest, not a Resources contest. I don't know where you find the lack of rationality there.

you can't deal damage with models and most people don't know how to move units with them so they still have to know how to trigger

also if it improves the quality of the spell why forbid it?
of course the people who know stuff about modeling have an advantage but people who are better at triggering have an advantage as well so it's even

That's where the creativity comes into play.

creativity?

I don't get it. You waited for this contest but since it has a theme and you're not allowed to artificially spice it with imports you're not going to take part in it. That's not a very good attitude!

it's not that it HAS a theme but that it has THIS theme
actually I wouldn't even call it a theme
it's more like a rule which steals the most important (imho) part of spellmaking which is to think of a spell
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
if it improves the quality of the spell why forbid it?

If steroids improves the quality of athletes then why forbid it. It unbalances the playing field. Not everybody is going to use nice imported models so those who do are going to have an obvious advantage. In addition custom models play a different role in every spell, so the advantages between people using imported models is going to vary. Why add all these margins of error when you don't need to...

creativity?

Google said:
The use of the imagination or original ideas, esp. in the production of an artistic work

Google #2 said:
Creativity is a mental process involving the discovery of new ideas or concepts, or new associations of the existing ideas or concepts, fueled by the process of either conscious or unconscious insight.

it's not that it HAS a theme but that it has THIS theme

It's still not a good attitude.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
If steroids improves the quality of athletes then why forbid it. It unbalances the playing field.

because it has negative side effects to take drugs
but mechanical enhancements which would have no side effects wouldn't be fair either because they require money to be developed
modeling requires tools, too but there also are free alternatives (of course the ones that cost money are better but for effects war3modeleditor is enough most of the time and is free)

Not everybody is going to use nice imported models so those who do are going to have an obvious advantage. In addition custom models play a different role in every spell, so the advantages between people using imported models is going to vary.

everyone has the same advantages because everyone can choose their spells themselves

Why add all these margins of error when you don't need to...

to get better spells

It's still not a good attitude.

why should I take part if I don't like the "theme" and am not allowed to use my full potential?


and your google quotes about creativity explain why this "theme" has none imho
the only "creative" part which is left is the coding but this is plain boring
most of the time is creating some indexing stuff and managing variables
there are not many spells in games which require thinking of cool mechanisms to solve a problem
 
imports are not allowed because making the spell look good using the default models is a part of spell making... and for me it actually shows the maker's creativity more... because making something look good without using AWESOME models is far more creative than making it look good just because you used something that is already good looking...
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
imports are not allowed because making the spell look good using the default models is a part of spell making... and for me it actually shows the maker's creativity more... because making something look good without using AWESOME models is far more creative than making it look good just because you used something that is already good looking...

so why doesn't everyone code in GUI because it is much more challenging?
 
because there is a difference between inducing your talents and putting a barrier... and because the impact of no imports is considerably less than the impact of forcing everyone to use GUI... and allowing imports will increase the map file size...

and yeah, if you don't like the rules, then don't join... no one forces you to join...
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
because there is a difference between inducing your talents and putting a barrier...and because the impact of no imports is considerably less than the impact of forcing everyone to use GUI...

pretty much everything done in JASS could be done in GUI
but you can't have every effect with the standard models

and allowing imports will increase the map file size...

vJASS increases mapsize, too

and yeah, if you don't like the rules, then don't join... no one forces you to join...

don't worry
I won't
 
Level 15
Joined
Feb 15, 2006
Messages
851
Fierce Armor

Ok, I did this spell just to remember old times. This one is based in Torchlight Destroyer ability "Shadow Armor" which summons an armor spirit and adds some chance to evade an attack. I changed the name and the block chances percentages just to make it more "compatible" with the style art in WC3 (and for testing purposes ofc).

This spell requires Timedloop by Vexorian, Timed Effects by me and UnitDamage by me.

image011.png
Shadow ArmorShadow Armor summons a spirit to protect your character by attacking nearby foes, and increasing your block chance. The chance to evade an attack and armor duration increases with the level of attack


[jass=Actual code (10/06/2011)]
library FierceArmor initializer init requires TimedLoop, TimedEffects, UnitDamage
//Configuration part...
globals
private constant integer unitid = 'nFAR' //this is the rawcode of the unit that will represent the armor
private constant integer abilid = 'A000' //this is the rawcode for the Ability
private constant integer buffid = 'B000' //this is the rawcode for the buff
private constant real scale = 2. // sets the armor scale on armor unit
private constant integer transp = 40 // sets a value between 0 and 255 which makes the transparency of the armor unit
private constant string attach = "origin" //sets where the block effect will appear on unit
endglobals

private constant function evasion takes integer lvl returns real
return lvl * 10.
endfunction

// from here, you shouldn't be touching the code unless you know what you're doing....
globals
private group G = CreateGroup()
endglobals

private struct data
static trigger DD = CreateTrigger()
static group Active = CreateGroup()
static hashtable T = InitHashtable()
unit u
unit s //armor unit
real life

private static method DoEv takes nothing returns nothing
local thistype d = thistype(LoadInteger(thistype.T, abilid, GetHandleId(GetExpiredTimer())))
call SetWidgetLife(d.u, d.life)
call DestroyTimer(GetExpiredTimer())
endmethod

static method DoEvasion takes nothing returns boolean
local real d = GetEventDamage()// Damage dealt normally
local unit u = GetTriggerUnit()// unit that receives the damage
local real l = GetWidgetLife(u)// unit life
local timer tm
local texttag t = CreateTextTag()
local thistype dt = thistype(LoadInteger(thistype.T, abilid, GetHandleId(u)))
if IsUnitInGroup(u, thistype.Active) and GetRandomInt(0, 100) <= evasion(GetUnitAbilityLevel(u, abilid)) and d > 0 then
if l-d < 0.405 then
call SetWidgetLife(u, d + 1)
endif
// Eyecandy part :)
call SetTextTagText(t, "BLOCKED!", 0.024) //Showed as in torchlight...
call SetTextTagPos(t, GetUnitX(u), GetUnitY(u), 0.00)
call SetTextTagColor(t, 255, 0, 255, 255)
call SetTextTagVelocity(t, 0, 0.04)
call SetTextTagVisibility(t, true)
call SetTextTagFadepoint(t, 2)
call SetTextTagLifespan(t, 5)
call SetTextTagPermanent(t, false)
set dt.life = l
set tm = CreateTimer()
call SaveInteger(thistype.T, abilid, GetHandleId(tm), integer(dt))
call TimerStart(tm, 0., false, function thistype.DoEv)
call StartTimedEffect(AddSpellEffectTargetById(buffid, EFFECT_TYPE_TARGET, dt.s, attach), 1.)
else
call DestroyTextTag(t)
endif
set u = null
set tm = null
set t = null
return false
endmethod

method destroy takes nothing returns nothing
call KillUnit(.s)
call GroupRemoveUnit(thistype.Active, .u)
endmethod

private method onTimedLoop takes nothing returns boolean
call SetUnitX(.s, GetUnitX(.u))
call SetUnitY(.s, GetUnitY(.u))
call SetUnitFacing(.s, GetUnitFacing(.u))
if GetUnitAbilityLevel(.u, buffid) < 1 then
return TimedLoop_STOP
endif
return TimedLoop_CONTINUE
endmethod

implement TimedLoop

static method create takes unit u returns thistype
local thistype D = thistype.allocate()
set D.u = u
if not IsUnitInGroup(u, G) then
//adds damage detection...
call TriggerRegisterUnitEvent(DD, u, EVENT_UNIT_DAMAGED)
call GroupAddUnit(G, u)
endif
call GroupAddUnit(thistype.Active, u)
set D.s = CreateUnit(GetOwningPlayer(u), unitid, GetUnitX(u), GetUnitY(u), GetUnitFacing(u))
call SetUnitVertexColor(D.s, 255,255,255,transp)
call SetUnitScale(D.s, scale, scale, scale)
call SaveInteger(thistype.T, abilid, GetHandleId(u), integer(D))
call D.startTimedLoop()
return D
endmethod
endstruct

private function ActivateSpell takes nothing returns boolean
if GetSpellAbilityId() == abilid and not IsUnitInGroup(GetTriggerUnit(), data.Active) then
call data.create(GetTriggerUnit())
endif
return false
endfunction

private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function ActivateSpell))
// preload unitid...
call RemoveUnit(CreateUnit(Player(15), unitid, 0,0,0))
// loads Damage Detection stuff
call AddDamageCondition(function data.DoEvasion)
endfunction

endlibrary

[/code]

~ [03/06/2011] updated code.
~ [10/06/2011] fixed a stupid bug. Eyecandy improved
 

Attachments

  • WC3ScrnShot_052911_182208_01_1.png
    WC3ScrnShot_052911_182208_01_1.png
    1.5 MB · Views: 122
  • WC3ScrnShot_052911_182249_05_1.png
    WC3ScrnShot_052911_182249_05_1.png
    1.5 MB · Views: 107
  • FireArmorSpell.w3x
    38.8 KB · Views: 86
Last edited:
Level 29
Joined
Mar 10, 2009
Messages
5,016
Here's the Spell I made for entry to this contest...

Name: Meteor Shower


Calls multiple meteors from the sky that ripples the ground and damages nearby enemy ground units.

|cffffcc00Level 1|r - Damages 150, AoE 400, lasts 10 seconds.
|cffffcc00Level 2|r - Damages 200, AoE 500, lasts 17 seconds.
|cffffcc00Level 3|r - Damages 250, AoE 600, lasts 24 seconds.
|cffffcc00Level 4|r - Damages 300, AoE 700, lasts 31 seconds.
|cffffcc00Level 5|r - Damages 350, AoE 800, lasts 38 seconds.

This is based on this video skip 0.14


JASS:
//=======================Meteor Shower========================
//============================================================
//====================Made by: Mckill2009=====================
//============================================================
//=======Entry for: Spells & Systems Mini-Contest #20=========

//===HOW TO USE:
//- Make a new trigger and convert to custom text via EDIT >>> CONVERT CUSTOM TEXT
//- The trigger name MUST be >>> MeteorShower (see the name below)
//- Copy ALL that is written here and overwrite the existing texts in the custom text
//- Copy the Dummy/custom abilities/buffs etc... to your object editor
//- Make sure you inputed the correct raw codes of the base spell/buffs/dummy etc...
//- If your raw code is different, you MUST CHANGE IT...
//- You can view the raw codes by pressing CTRL+B in the object editor
//- Examples of raw codes are 'A000', 'h000' etc... 

//===REQUIRED VARIABLES:
//-HASH = Hashtable
//-Caster = Unit
//-Damage = Real

//===CONFIGURABLES:
//=====IMPORTANT NOTICE: Raw codes MUST BE CHANGED if your raw code has changed as indicated below
constant function MS_SPELLID takes nothing returns integer
    return 'A000' //raw code
endfunction

constant function MS_METEORID takes nothing returns integer
    return 'h001' //raw code
endfunction

constant function MS_ATT takes nothing returns attacktype
    return ATTACK_TYPE_CHAOS
endfunction

constant function MS_DAM takes nothing returns damagetype
    return DAMAGE_TYPE_FIRE
endfunction

function MS_HASH takes nothing returns nothing
    set udg_HASH = InitHashtable()
endfunction

function MS_DAMAGE takes integer i returns real
    return 100. + i * 50
endfunction

function MS_AOE takes integer i returns real
    return 300. + i * 100 
endfunction

function MS_DURATION takes integer i returns real
    return 3. + i * 7 
endfunction

//===END OF CONFIGURABLES

function MS_FILTERDAMAGE takes nothing returns boolean
    local unit u = GetFilterUnit()
    if IsUnitEnemy(u, GetOwningPlayer(udg_Caster)) and GetWidgetLife(u) > 0.405 and IsUnitType(u, UNIT_TYPE_FLYING)==false then
        call UnitDamageTarget(udg_Caster, u, udg_Damage, false, false, MS_ATT(), MS_DAM(), null)                
    endif    
    set u = null
    return false
endfunction

function MS_METEORDEATH takes nothing returns boolean
    local unit u
    local integer dummyID    
    if GetUnitTypeId(GetTriggerUnit())==MS_METEORID() then
        set u = GetTriggerUnit() 
        set dummyID = GetHandleId(u)
        set udg_Caster = LoadUnitHandle(udg_HASH, dummyID, 1)
        set udg_Damage = LoadReal(udg_HASH, dummyID, 2)
        call GroupEnumUnitsInRange(bj_lastCreatedGroup, GetUnitX(u), GetUnitY(u), 250, Filter(function MS_FILTERDAMAGE)) 
        call TerrainDeformRipple(GetUnitX(u), GetUnitY(u), 10000, 30, 1, 1000, 0, 0.5, 3, false) 
        call FlushChildHashtable(udg_HASH, dummyID) 
    endif 
    set u = null
    return false
endfunction

function MS_LOOP takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer tID = GetHandleId(t)
    local integer dummyID
    local unit u = LoadUnitHandle(udg_HASH, tID, 1)
    local unit dummy
    local real damage = LoadReal(udg_HASH, tID, 2)
    local real AoE = LoadReal(udg_HASH, tID, 3)
    local real duration = LoadReal(udg_HASH, tID, 4)
    local real x = LoadReal(udg_HASH, tID, 5) 
    local real y = LoadReal(udg_HASH, tID, 6) 
    local real offset = GetRandomReal(75, AoE)
    local real angle = GetRandomReal(0, 360)
    local real x1
    local real y1
    if duration > 0 and GetWidgetLife(u) > 0.405 then
        call SaveReal(udg_HASH, tID, 4, duration - 0.5)
        set x1 = x + offset * Cos(angle * bj_DEGTORAD) 
        set y1 = y + offset * Sin(angle * bj_DEGTORAD)
        set dummy = CreateUnit(GetOwningPlayer(u),MS_METEORID(), x1, y1, 0)
        set dummyID = GetHandleId(dummy) //This will be used for damage
        call SaveUnitHandle(udg_HASH, dummyID, 1, u) //Saves the Caster
        call SaveReal(udg_HASH, dummyID, 2, damage) //Saves the damage
        call SetUnitFlyHeight(dummy, 0, 1000)
        call UnitApplyTimedLife(dummy, 'BTLF', 1)
    else
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(udg_HASH, tID)        
    endif
    set t = null
    set u = null
    set dummy = null
endfunction

function MS_CAST takes nothing returns boolean
    local timer t
    local unit u
    local integer tID
    local integer level
    if GetSpellAbilityId()==MS_SPELLID() then
        set t = CreateTimer()
        set tID = GetHandleId(t)
        set u = GetTriggerUnit()
        set level = GetUnitAbilityLevel(u, MS_SPELLID())
        call SaveUnitHandle(udg_HASH, tID, 1, u) 
        call SaveReal(udg_HASH, tID, 2, MS_DAMAGE(level))
        call SaveReal(udg_HASH, tID, 3, MS_AOE(level))
        call SaveReal(udg_HASH, tID, 4, MS_DURATION(level))
        call SaveReal(udg_HASH, tID, 5, GetUnitX(u))
        call SaveReal(udg_HASH, tID, 6, GetUnitY(u))
        call TimerStart(t, 0.5, true, function MS_LOOP)
    endif
    set t = null
    return false
endfunction

function InitTrig_MeteorShower takes nothing returns nothing
    local trigger t1 = CreateTrigger()          
    local trigger t2 = CreateTrigger() 
    call TriggerRegisterAnyUnitEventBJ(t1, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerRegisterAnyUnitEventBJ(t2, EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(t1, Condition(function MS_CAST))
    call TriggerAddCondition(t2, Condition(function MS_METEORDEATH))
    set t1 = null
    set t2 = null
    call MS_HASH()
endfunction



167625-albums4356-picture47073.jpg

167625-albums4356-picture47074.jpg

 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
Moyack its nice to see you. I suppose. Your submission looks pretty good. I like the effect of the faded Firelord. I was hoping that you were going to detail the "evasion" a little more but you don't really notice in normal circumstances whether lethal damage ~can~ be evaded. If you kill the unit with 600 damage or something though the unit will still die, because a dead unit cannot be revived simply by adding hit points. Unfortunately.

In fact, the evasion does not work at all. Instead of EVENT_UNIT_DAMAGED you use EVENT_UNIT_ATTACKED. That's funny. You must've typed this up in a hurry. If you change it the evasion seems to work properly, but lethal damage still isn't prevented.

In cases where the damage amount exceeds the unit's life capacity, you'll need to fiddle with the BonusMod library by EarthFury I believe. If the damage is still within the unit's life amount then you simply need to adjust the unit's life before hand. The problem when you fiddle around in these areas is that you realize 0-second timers aren't so instant.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
To prevent death when the attack is fatal just add the ability 'Invu' to the unit in the event and then run a 0 second timer and remove the ability when the timer expires. Problem solved :D

this might cancel attack orders
is it better to add a big health bonus instead and removing it after timer expired of course
but sometimes the attacks happen faster than a 0-timer can expire one should also remove the bonus on next attack and reset everything

edit:
like this
http://www.hiveworkshop.com/forums/...7d1288007706-snippet-rangedaccuracy-block.w3m
 
Last edited:
Level 16
Joined
Apr 4, 2011
Messages
995
Ok, here we go

The caster creates an icy orb, which slowly moves in the direction it is cast. The orb will constantly emit ice shards which travel away from the orb. A unit hit with an ice shard is slowed for 3 seconds. The orb lasts 3 seconds.

This is a diablo 2 spell, it is used by the sorceress character

View attachment 102309
The original spell from Diablo 2

View attachment 102310
My version of the spell


  • Events
  • Map initialization
  • Conditions
  • Actions
  • Hashtable - Create a hashtable
  • Set FO_Hash = (Last created hashtable)
  • Set FO_Move = 16.00
  • Set FO_OrbMove = 12.33
  • Set FO_Time = 3.00
  • Events
  • Unit - A unit Starts the effect of an ability
  • Conditions
  • (Ability being cast) Equal to Frozen Orb
  • Actions
  • Sound - Play FrostArmorTarget1 <gen>
  • Set FO_Caster = (Triggering unit)
  • Set FO_Point1 = (Position of FO_Caster)
  • Set FO_Facing = (Facing of FO_Caster)
  • Set FO_Angle = FO_Facing
  • Set FO_Player = (Owner of FO_Caster)
  • Unit - Create 1 Frozen Orb for FO_Player at FO_Point1 facing FO_Facing degrees
  • Set FO_Orb = (Last created unit)
  • Unit - Add a 3.00 second Generic expiration timer to FO_Orb
  • Unit Group - Add FO_Orb to FO_Orb_Group
  • Hashtable - Save Handle OfFO_Caster as 0 of (Key (Last created unit)) in FO_Hash
  • Hashtable - Save FO_Facing as 1 of (Key (Last created unit)) in FO_Hash
  • Hashtable - Save FO_Angle as 2 of (Key (Last created unit)) in FO_Hash
  • Hashtable - Save FO_Time as 3 of (Key (Last created unit)) in FO_Hash
  • Custom script: call RemoveLocation(udg_FO_Point1)
  • Trigger - Turn on Frozen Orb Move <gen>
  • Events
  • Time - Every 0.06 seconds of game time
  • Conditions
  • Actions
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
  • If - Conditions
  • ((Number of units in FO_Orb_Group) Equal to 0) and ((Number of units in FO_Missile_Group) Equal to 0)
  • Then - Actions
  • Trigger - Turn off (This trigger)
  • Else - Actions
  • Unit Group - Pick every unit in FO_Orb_Group and do (Actions)
  • Loop - Actions
  • Set FO_Time = (Load 3 of (Key (Picked unit)) from FO_Hash)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
  • If - Conditions
  • FO_Time Greater than 0.00
  • Then - Actions
  • Sound - Play SpiritTouch <gen>
  • Set FO_Orb = (Picked unit)
  • Set FO_Caster = (Load 0 of (Key (Picked unit)) in FO_Hash)
  • Set FO_Facing = (Load 1 of (Key (Picked unit)) from FO_Hash)
  • Set FO_Angle = (Load 2 of (Key (Picked unit)) from FO_Hash)
  • Set FO_Player = (Owner of FO_Caster)
  • Set FO_Point1 = (Position of FO_Orb)
  • Set FO_Point2 = (FO_Point1 offset by FO_OrbMove towards (Facing of FO_Orb) degrees)
  • Unit - Move FO_Orb instantly to FO_Point2, facing FO_Facing degrees
  • Unit - Create 1 Frost Missile for FO_Player at FO_Point2 facing FO_Angle degrees
  • Unit - Set level of Frozen Orb Unit for (Last created unit) to (Level of Frozen Orb for FO_Caster)
  • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
  • Unit Group - Add (Last created unit) to FO_Missile_Group
  • Hashtable - Save (FO_Angle + (360.00 / 16.00)) as 2 of (Key (Picked unit)) in (Last created hashtable)
  • Custom script: call RemoveLocation(udg_FO_Point1)
  • Custom script: call RemoveLocation(udg_FO_Point2)
  • Hashtable - Save (FO_Time - (1.00 / 16.00)) as 3 of (Key (Last created unit)) in FO_Hash
  • Else - Actions
  • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in FO_Hash
  • Unit Group - Remove (Picked unit) from FO_Orb_Group
  • Events
  • Time - Every 0.02 seconds of game time
  • Conditions
  • Actions
  • Unit Group - Pick every unit in FO_Missile_Group and do (Actions)
  • Loop - Actions
  • Set FO_PickedMissile = (Picked unit)
  • Set FO_Point1 = (Position of FO_PickedMissile)
  • Set FO_Point2 = (FO_Point1 offset by FO_Move towards (Facing of FO_PickedMissile) degrees)
  • Unit - Move FO_PickedMissile instantly to FO_Point2, facing (Facing of FO_PickedMissile) degrees
  • Unit Group - Pick every unit in (Units within 150.00 of FO_Point2 matching (((Matching unit) belongs to an enemy of (Owner of FO_PickedMissile)) Equal to True)) and do (Actions)
  • Loop - Actions
  • Unit - Order FO_PickedMissile to Undead Lich - Frost Nova (Picked unit)
  • Custom script: call RemoveLocation(udg_FO_Point1)
  • Custom script: call RemoveLocation(udg_FO_Point2)
 
Last edited:
  • Equilibrium Strike
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Equilibrium Strike
    • Actions
      • -------- --- --------
      • Set ES_Caster = (Triggering unit)
      • Set ES_Target = (Target unit of ability being cast)
      • Set ES_Ability_Level = (Level of (Ability being cast) for ES_Caster)
      • Set ES_Owner = (Owner of ES_Caster)
      • -------- --- --------
      • Set ES_Base_Damage = 60.00
      • Set ES_Level_Damage = 40.00
      • Set ES_Atribute_Factor = 0.30
      • Set ES_Atribute_Damage = (Agility of ES_Caster (Include bonuses))
      • -------- --- --------
      • Set ES_Dummy_Ability_Slow = Equilibrium Strike(dummy slow)
      • Set ES_Dummy_Ability_Stun = Equilibrium Strike(dummy stun)
      • -------- --- --------
      • Set ES_Spell_Loc = (Position of ES_Target)
      • Set ES_Spell_Loc_2 = (Position of ES_Caster)
      • Set ES_Facing_Angle = (Angle from ES_Spell_Loc to ES_Spell_Loc_2)
      • Set ES_SFX_Offset = 200.00
      • Set ES_SFX_Angle = 50.00
      • Set ES_SFX_Duration = 1.00
      • Set ES_SFX_Loc = (ES_Spell_Loc_2 offset by ES_SFX_Offset towards (ES_Facing_Angle + ES_SFX_Angle) degrees)
      • Set ES_SFX_Loc_2 = (ES_Spell_Loc_2 offset by ES_SFX_Offset towards (ES_Facing_Angle - ES_SFX_Angle) degrees)
      • -------- --- --------
      • Set ES_Damage_Calculation = (ES_Base_Damage + ((Real(ES_Ability_Level)) x ES_Level_Damage))
      • Set ES_Atribute_Damage_Calculation = ((Real(ES_Ability_Level)) x (ES_Atribute_Factor x (Real(ES_Atribute_Damage))))
      • -------- --- --------
      • Set ES_Total_Damage = (ES_Atribute_Damage_Calculation + ES_Damage_Calculation)
      • -------- --- --------
      • Special Effect - Create a special effect attached to the weapon of ES_Caster using Abilities\Spells\Orc\Shockwave\ShockwaveMissile.mdl
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect attached to the origin of ES_Target using Abilities\Spells\Other\Stampede\StampedeMissileDeath.mdl
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect attached to the origin of ES_Target using Abilities\Spells\Orc\Disenchant\DisenchantSpecialArt.mdl
      • Special Effect - Destroy (Last created special effect)
      • -------- --- --------
      • For each (Integer A) from 1 to 25, do (Actions)
        • Loop - Actions
          • -------- --- --------
          • Set ES_SFX_Value = ((Real((Integer A))) x 13.00)
          • Set ES_SFX_Value_1 = (100.00 - ((Real((Integer A))) x 2.50))
          • Set ES_SFX_Value_2 = ((Real((Integer A))) x 8.00)
          • Set ES_SFX_Value_3 = ((Real((Integer A))) x 3.00)
          • Set ES_SFX_Offset_Calculation = (ES_SFX_Offset - ES_SFX_Value)
          • -------- --- --------
          • Set ES_SFX_Loc_3 = (ES_SFX_Loc offset by ES_SFX_Offset_Calculation towards (ES_Facing_Angle + ES_SFX_Angle) degrees)
          • -------- --- --------
          • Unit - Create 1 Dummy_SFX for ES_Owner at ES_SFX_Loc_3 facing ES_Facing_Angle degrees
          • Unit - Add a ES_SFX_Duration second Generic expiration timer to (Last created unit)
          • Unit - Order (Last created unit) to Move To ES_Spell_Loc
          • Animation - Change (Last created unit) flying height to ((Current flying height of (Last created unit)) - ES_SFX_Value_2) at 0.00
          • Animation - Play (Last created unit)'s birth animation
          • Animation - Change (Last created unit)'s size to (ES_SFX_Value_1%, ES_SFX_Value_1%, ES_SFX_Value_1%) of its original size
          • Custom script: call RemoveLocation(udg_ES_SFX_Loc_4)
          • -------- --- --------
          • -------- --- --------
          • Set ES_SFX_Loc_4 = (ES_SFX_Loc_2 offset by ES_SFX_Offset_Calculation towards (ES_Facing_Angle - ES_SFX_Angle) degrees)
          • -------- --- --------
          • Unit - Create 1 Dummy_SFX for ES_Owner at ES_SFX_Loc_4 facing ES_Facing_Angle degrees
          • Unit - Add a ES_SFX_Duration second Generic expiration timer to (Last created unit)
          • Unit - Order (Last created unit) to Move To ES_Spell_Loc
          • Animation - Change (Last created unit) flying height to ((Current flying height of (Last created unit)) - ES_SFX_Value_2) at 0.00
          • Animation - Play (Last created unit)'s birth animation
          • Animation - Change (Last created unit)'s size to (ES_SFX_Value_1%, ES_SFX_Value_1%, ES_SFX_Value_1%) of its original size
          • Custom script: call RemoveLocation(udg_ES_SFX_Loc_3)
          • Custom script: call RemoveLocation(udg_ES_SFX_Loc_4)
      • -------- --- --------
      • Floating Text - Create floating text that reads ((String((Integer(ES_Total_Damage)))) + !) above ES_Target with Z offset 0.00, using font size 10.00, color (100.00%, 5.00%, 0.00%), and 0.00% transparency
      • Floating Text - Change (Last created floating text): Disable permanence
      • Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
      • Floating Text - Change the fading age of (Last created floating text) to 0.75 seconds
      • Floating Text - Change the lifespan of (Last created floating text) to 2.00 seconds
      • -------- --- --------
      • Unit - Create 1 Dummy for ES_Owner at ES_Spell_Loc facing Default building facing degrees
      • Unit - Add a 0.75 second Generic expiration timer to (Last created unit)
      • Unit - Make (Last created unit) face ES_Target over 0.00 seconds
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Life of ES_Caster) Greater than or equal to (Life of ES_Target)
        • Then - Actions
          • Unit - Add ES_Dummy_Ability_Slow to (Last created unit)
          • Unit - Set level of ES_Dummy_Ability_Slow for (Last created unit) to ES_Ability_Level
          • Unit - Order (Last created unit) to Human Sorceress - Slow ES_Target
        • Else - Actions
          • Unit - Add Equilibrium Strike(dummy stun) to (Last created unit)
          • Unit - Set level of ES_Dummy_Ability_Stun for (Last created unit) to ES_Ability_Level
          • Unit - Order (Last created unit) to Human Mountain King - Storm Bolt ES_Target
      • -------- --- --------
      • Unit - Cause ES_Caster to damage ES_Target, dealing ES_Total_Damage damage of attack type Spells and damage type Unknown
      • -------- --- --------
      • Custom script: call RemoveLocation(udg_ES_Spell_Loc)
      • Custom script: call RemoveLocation(udg_ES_Spell_Loc_2)
      • Custom script: call RemoveLocation(udg_ES_SFX_Loc)
      • Custom script: call RemoveLocation(udg_ES_SFX_Loc_2)
Work in progress, i'm pretty much done here, just some trigger comments, tooltips and some nice terrain.
*code needs some cleaning doe to unused vars.
 
Level 22
Joined
Nov 14, 2008
Messages
3,256
@moyack

There are a few major improvements that can be done but either way it looks awesome!

@mckill

No need to credit me, it's so simple so anyone can create it :p

A few things that might get your score even higher:

-In the MS_FILTERCLOCK you leak a timer if it doesnt meet up the conditions. You should instead call NTimer() after the condition check and also put the null inside it as well (at last before endif).

-In the MS_METEORDEATH function you can store the x and y coordinate of u, set them after the if

-In the MS_CAST you should null the timer after the nested if (the if that checks chance)

Just a rough check though but might be helpful!
 
Level 12
Joined
Mar 28, 2005
Messages
160
in case I don't get around to re-taking a look at this, here is my current WIP

1000 Needles

The trademark ability native to the Cactuar, which sprays a steady stream of deadly needles towards the target, dealing exactly 1,000 HP damage, regardless of armor.

1000Needles.jpg


For comparison:


It's not FF7, but I could not find a good video, so this will have to do, and is pretty close anywho.

The script for all those interested:

JASS:
scope ThousandNeedles

// 1,000 Needles
// Made by emjlr3 for THN Spell Contest #20
// Requires nothing other than this script.

//CONFIG. FUNCTIONS:
//============================================================================
private function Buffer takes integer lvl returns real
    return 25. // buffer mana required to continue channeling
endfunction
private function Cost takes integer lvl returns real
    return 25. // mana cost per second
endfunction
private function Count takes integer lvl returns integer
    return 100 // needles spawned per second
endfunction
private function Damage takes integer lvl returns real
    return 1. // on collision
endfunction
private function Radius takes integer lvl returns real
    return 100. // aoe circle radius to target
endfunction
private function Range takes integer lvl returns real
    return 105. // collision size of needles
endfunction

//CONFIG. GLOBALS:
//============================================================================
globals
           constant     boolean             PIERCE      = true // needles pierce targets?
           constant     boolean             TEXTAG      = true // create damage texttags?
           constant     boolean             TREES       = true // kill trees?
endglobals
private struct needles    
    static constant     attacktype          ATTACK      = ATTACK_TYPE_CHAOS // damage attacktype
    
    static constant     damagetype          DAMAGE      = DAMAGE_TYPE_UNIVERSAL // damage damagetype
    
    static constant     integer             ABIL        = 'NEED' // 1000 Needles ability id 
    static constant     integer             ORDER       = 852089 // channel order id
    static constant     integer             DUMMY       = 'n000' // projectile dummy unit id   
    static constant     integer             FLYTRICK    = 'Amrf' // crow form ability id
    
    static constant     real                CTIMESCALE  = 7. // caster time scale during channeling
    static constant     real                DTIMESCALE  = 1. // default caster time scale
    static constant     real                FLYHEIGHT   = 75. // needle fly height
    static constant     real                SIZE        = 1. // needle scale
    static constant     real                TIMEOUT     = .05 // periodic timer interval in seconds (movement and spawning)
    static constant     real                VELOCITY    = 600. // needle velocity per second
    
    static constant     string              COLOR       = "" // textag string color
    static constant     string              DUMSFX      = "Abilities\\Weapons\\BristleBackMissile\\BristleBackMissile.mdl"  // needle model
    static constant     string              HITATTACH   = "chest" // attachment point for HITSFX    
    static constant     string              HITSFX      = "" // model on target following a needle collision    
    
//END CONFIG.
//============================================================================
    static              boolexpr            TBOOL       = null
    static              group               GROUP       = CreateGroup()
    // you can replace this with a global hashtable if you want
    // but be aware, I attach directly to caster units, and flush the data later
    static              hashtable           HT          = InitHashtable()
    static              real                RVEL        = VELOCITY*TIMEOUT
    static              real                TWOPI       = bj_PI*2.
    static              rect                RECT        = null
    static              timer               TIMER       = CreateTimer()
    static              unit                T           = null
    
    // linked list attachment
    thistype prev
    thistype next
    
    // 0=channel
    // 1=needle
    integer t=0
    
    // the spell basics
    unit cast
    player p
    unit dum
    effect sfx
    
    // setup needle
    real x
    real y
    real xtarg
    real ytarg
    real ang
    real cos
    real sin
    real dist
    
    // group addition delay
    real time=1.
    
    // collision/movement related
    trigger trig
    group g
    integer ticks
    
    // requisite data
    integer lvl
    integer count
    // the spell is called 1000 Needles, so no config. option for that
    // if you really want to change the spell that much, here you go
    integer total=1000 // total needles
    real damage
    real range
    real radius
    real mana
    real buffer
    string Sdamage
        
    method destroy takes nothing returns nothing    
        if .t==0  then // channel
            call GroupRemoveUnit(GROUP,.cast)
            call FlushChildHashtable(HT,GetHandleId(.cast))
            call SetUnitTimeScale(.cast,DTIMESCALE)
            // ran out of needles or mana
            if GetUnitCurrentOrder(.cast)==ORDER then
                call PauseUnit(.cast,true)
                call IssueImmediateOrder(.cast,"stop")
                call PauseUnit(.cast,false)
            endif
        elseif .t==1 then // needle
            call FlushChildHashtable(HT,GetHandleId(.trig))
            call DestroyTrigger(.trig)
            call DestroyEffect(.sfx)
            //call KillUnit(.dum)
            // usually you can't remove the unit and still get the sfx death animation to play
            // in this case I can
            // also, this produced much less lag, and when you have so many at once
            // its a welcome boost
            call RemoveUnit(.dum)
            static if PIERCE then
                call ReleaseGroup(.g)
            endif
        endif
    
        set .prev.next=.next
        set .next.prev=.prev
        set .prev=0     
        call .deallocate()
    endmethod
    
    static method updateList takes thistype this returns nothing
        set thistype(0).next.prev=this
        set .next=thistype(0).next
        set thistype(0).next=this
        set .prev=thistype(0)
    endmethod
    static method treeBool takes nothing returns boolean
        if GetDestructableLife(GetFilterDestructable())>0. then
            call KillDestructable(GetFilterDestructable())
        endif
        
        return false
    endmethod
    static method onCollision takes nothing returns boolean
        local thistype this=LoadInteger(HT,GetHandleId(GetTriggeringTrigger()),0)
        local boolean b=true
        local texttag tt
        set T=GetTriggerUnit()
        
        static if PIERCE then
            set b=not IsUnitInGroup(T,.g)
        endif
        
        if UnitAlive(T) and IsUnitEnemy(T,.p) and b then   
            // by using dum as the damager, if you are far enough away
            // the targets can't fight back, and instead run for the hills
            // this may or may not be desireable, you can always update that here
            call UnitDamageTarget(.dum,T,.damage,false,false,ATTACK,DAMAGE,null)
            // too many sfx!!!  i like it better without any
            if HITSFX!="" then
                call DestroyEffect(AddSpecialEffectTarget(HITSFX,T,HITATTACH)) 
            endif
            
            // stupid texttag limit!!!
            static if TEXTAG then
                // if you want to edit the texttag intricacies, do so here
                set tt=CreateTextTag()
                call SetTextTagText(tt,.Sdamage,.024)
                // sort of randomly, somewhere on the target
                call SetTextTagPos(tt,GetUnitX(T)+GetRandomReal(-15.,15.),GetUnitY(T)+GetRandomReal(-15.,15),16.)
                call SetTextTagVelocity(tt,.0,.04)
                call SetTextTagVisibility(tt,true)
                call SetTextTagFadepoint(tt,2.5)
                call SetTextTagLifespan(tt,4.)
                call SetTextTagPermanent(tt,false)    
                set tt=null
            endif
            
            static if PIERCE then
                call GroupAddUnit(.g,T)
            else
                // probably don't need this to avoid further enumeration
                // but for shits 'n' giggles
                call DisableTrigger(.trig)            
                call .destroy()
            endif            
        endif   
        
        return false
    endmethod
    static method createNeedle takes thistype t, real x, real y, real face returns nothing
        local thistype this=thistype.allocate()
        local real angle=GetRandomReal(0.,TWOPI)
        local real dist=GetRandomReal(0.,t.radius)
        
        set .cast=t.cast
        set .p=t.p
        set .damage=t.damage
        static if TEXTAG then
            set .Sdamage=COLOR+I2S(R2I(.damage))
        endif
        // somewhere a random polar projection out from the cast loc
        // taking into consideration the radius set point
        set .xtarg=x+t.dist*Cos(face)+dist*Cos(angle)
        set .ytarg=y+t.dist*Sin(face)+dist*Sin(angle)
        set .ang=Atan2(.ytarg-y,.xtarg-x)
        set .cos=RVEL*Cos(.ang)
        set .sin=RVEL*Sin(.ang)
        set .dum=CreateUnit(.p,DUMMY,x+.cos,y+.sin,.ang*bj_RADTODEG)
        call SetUnitScale(.dum,SIZE,SIZE,SIZE)
        // just incase
        call UnitAddAbility(.dum,FLYTRICK)
        call SetUnitFlyHeight(.dum,FLYHEIGHT,0.)
        set .sfx=AddSpecialEffectTarget(DUMSFX,.dum,"origin")
        // needle
        set .t=1
        // makes it easy to tell when the needle reaches its destination
        set .ticks=R2I(SquareRoot(Pow(.xtarg-x,2)+Pow(.ytarg-y,2))/(RVEL))
        // if we want needles to travel through all targets
        static if PIERCE then
            set .g=NewGroup()
        endif
        // unitinrange triggers are fun, and remove the mundane groupenumunitsinrange overhead
        // using them with trigger conditions removes the possiblity of handle stack corruption
        // hashtables have given us a convenient and relatively fast way to attach our struct
        set .trig=CreateTrigger()
        call TriggerRegisterUnitInRange(.trig,.dum,t.range,null)
        call TriggerAddCondition(.trig,Condition(function thistype.onCollision))
        call SaveInteger(HT,GetHandleId(.trig),0,this)
        
        call thistype.updateList(this)
    endmethod
    static method periodic takes nothing returns nothing
        local thistype this=thistype(0).next
        local integer i
        local real r
        local real face
        
        loop
            exitwhen this==0
            
            if .t==0 then // channel
                // make sure we have enough needles left to cast
                // but not too many now, mind you
                set .total=.total-.count
                if .total<0 then
                    set i=.count-.total
                else
                    set i=.count
                endif
                // try pushing this up higher and see the real power of the spell!
                set face=GetUnitFacing(.cast)*bj_DEGTORAD
                loop
                    exitwhen i<=0                    
                    call thistype.createNeedle(this,GetUnitX(.cast),GetUnitY(.cast),face)
                    set i=i-1
                endloop
                
                // it just so happens that successional casts trigger just about every PLAYER_UNIT_SPELL_XXXX there is
                // so we can differentiate between first channel and subsequent channels while still channeling
                // FYI, this delay should be lower than the spells cooldown                
                set .time=.time-TIMEOUT
                if .time<=0. and not IsUnitInGroup(.cast,GROUP) then
                    call GroupAddUnit(GROUP,.cast)
                endif             
                
                call SetUnitState(.cast,UNIT_STATE_MANA,GetUnitState(.cast,UNIT_STATE_MANA)-.mana)
                
                // no longer channeling, not enough mana or out of needles
                // I remember there was a reason I didn't usually check it like this
                // and instead used an SPELL_ENDCAST event
                // but can't remember now why
                // might have had something to do with the order id remaining
                // while a unit is stunned, or some other such nonsense
                // though in this map that doesn't happen when the hero is stunned
                // so meh
                if GetUnitState(.cast,UNIT_STATE_MANA)<.buffer or .total<=0 or GetUnitCurrentOrder(.cast)!=ORDER then
                    call .destroy()
                endif
            elseif .t==1 then // needle
                set .ticks=.ticks-1
                // reached its destination
                if .ticks==0 then
                    call .destroy()
                else
                // room still to go
                    call SetUnitX(.dum,GetUnitX(.dum)+.cos)
                    call SetUnitY(.dum,GetUnitY(.dum)+.sin)
                    static if TREES then
                        call MoveRectTo(RECT,GetUnitX(.dum),GetUnitY(.dum))
                        call EnumDestructablesInRect(RECT,TBOOL,null)
                    endif
                endif
            endif
            
            set this=.next
        endloop
        
        // linked list is empty :(
        if thistype(0).next==0 then
            call PauseTimer(TIMER)
        endif
    endmethod
    static method create takes nothing returns thistype
        local thistype this=thistype.allocate()
        
        set .cast=GetTriggerUnit()
        call SaveInteger(HT,GetHandleId(.cast),0,this)
        call SetUnitTimeScale(.cast,CTIMESCALE)
        set .p=GetTriggerPlayer()
        set .lvl=GetUnitAbilityLevel(.cast,ABIL)
        set .count=R2I(Count(.lvl)*TIMEOUT)
        set .damage=Damage(.lvl)
        set .range=Range(.lvl)
        set .radius=Radius(.lvl)
        set .mana=Cost(.lvl)*TIMEOUT
        set .buffer=Buffer(.lvl)
        set .x=GetUnitX(.cast)
        set .y=GetUnitY(.cast)
        set .xtarg=GetSpellTargetX()
        set .ytarg=GetSpellTargetY()
        set .dist=SquareRoot(Pow(.x-.xtarg,2)+Pow(.y-.ytarg,2))
        if .dist<=0. then
            set .dist=100.
        endif
        // channel
        set .t=0
        
        // linked list is empty :)
        if thistype(0).next==0 then
            call TimerStart(TIMER,TIMEOUT,true,function thistype.periodic)
        endif
        call thistype.updateList(this)
        
        return this
    endmethod
    
    static method conditions takes nothing returns boolean
        local thistype this
        
        if GetTriggerEventId()==EVENT_PLAYER_UNIT_SPELL_CHANNEL then
            if GetSpellAbilityId()==ABIL and not IsUnitInGroup(GetTriggerUnit(),GROUP) then
                call thistype.create()
            endif
        elseif GetTriggerEventId()==EVENT_PLAYER_UNIT_SPELL_EFFECT then
            if GetSpellAbilityId()==ABIL and IsUnitInGroup(GetTriggerUnit(),GROUP) then
                set this=LoadInteger(HT,GetHandleId(GetTriggerUnit()),0)   
                set .dist=SquareRoot(Pow(GetUnitX(.cast)-GetSpellTargetX(),2)+Pow(GetUnitY(.cast)-GetSpellTargetY(),2))
                if .dist<=0. then
                    set .dist=100.
                endif
            endif
        elseif GetIssuedOrderId()!=ORDER and IsUnitInGroup(GetTriggerUnit(),GROUP) then
            //call BJDebugMsg(I2S(GetIssuedOrderId()))
            set this=LoadInteger(HT,GetHandleId(GetTriggerUnit()),0)   
            call .destroy()
        endif
        
        return false
    endmethod    
    static method onInit takes nothing returns nothing
        local trigger trig=CreateTrigger()
        local integer index=0

        loop
            call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_SPELL_CHANNEL,null)
            call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
            // to my suprise learning an ability fires a unit event, and each ability has a unique learn id
            // otherwise this might be full proof
            //call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_ISSUED_ORDER,null)
            //call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER,null)
            //call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER,null)
            //call TriggerRegisterPlayerUnitEvent(trig,Player(index),EVENT_PLAYER_UNIT_ISSUED_UNIT_ORDER,null)
            set index=index+1
            exitwhen index==bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition(trig,Condition(function thistype.conditions))
        static if TREES then
            // lets assume the range settings don't change, or atleast don't change much
            set index=R2I(Range(1))
            set RECT=Rect(-index,-index,index,index)
            set TBOOL=Condition(function thistype.treeBool)
        endif
    endmethod
endstruct

endscope
 

Attachments

  • emjlr3 - 1000 Needles.w3x
    79.4 KB · Views: 132
Last edited:
Status
Not open for further replies.
Top