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

BladeMaster's Den v1.3.9

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
  • Like
Reactions: Yours Truly
[trigger=Configuration]BMD Config
Events
Map initialization
Conditions
Actions
-------- Slashes --------
Set BMD_Slashes[1] = 10
Set BMD_Slashes[2] = 15
Set BMD_Slashes[3] = 20
Set BMD_Slashes[4] = 25
-------- Damage --------
Set BMD_Damage[1] = 20
Set BMD_Damage[2] = 30
Set BMD_Damage[3] = 40
Set BMD_Damage[4] = 50
-------- Clones --------
Set BMD_Clones[1] = 1
Set BMD_Clones[2] = 2
Set BMD_Clones[3] = 3
Set BMD_Clones[4] = 4
-------- Area Of Effect --------
Set BMD_Aoe[1] = 500.00
Set BMD_Aoe[2] = 600.00
Set BMD_Aoe[3] = 700.00
Set BMD_Aoe[4] = 800.00
-------- Transparency --------
Set BMD_UnitTransparency = 50.00
-------- Animation Speed --------
Set BMD_AnimationSpeed = 200.00
-------- Attachment Caster/Dummy --------
Set BMD_AttachmentWeapon = Abilities\Weapons\PhoenixMissile\Phoenix_Missile.mdl
Set BMD_AttachmentChest = Abilities\Spells\Human\Polymorph\PolyMorphDoneGround.mdl
-------- Attachment Enemies --------
Set BMD_AttachmentEnemy = Abilities\Spells\Other\Stampede\StampedeMissileDeath.mdl[/trigger]

[trigger=Cast]BMD Cast
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to BladeMaster's Den
Actions
-------- Indexing --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
BMD_Index Equal to 0
Then - Actions
Trigger - Turn on BMD Loop <gen>
Else - Actions
-------- Increasing the MUI --------
Set BMD_Index = (BMD_Index + 1)
-------- Indexing --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
BMD_Index Greater than BMD_IndexLoop
Then - Actions
Set BMD_IndexArray[BMD_Index] = BMD_Index
Set BMD_Full_Index = BMD_Index
Else - Actions
-------- To Make It Easier --------
Set BMD_Main_Index = BMD_IndexArray[BMD_Index]
-------- Setting The Caster,Slashes,Damage,Clones,etc --------
Set BMD_CastingUnit[BMD_Main_Index] = (Triggering unit)
Set BMD_Ability_Level[BMD_Main_Index] = (Level of BladeMaster's Den for BMD_CastingUnit[BMD_Main_Index])
Set BMD_Slashes[BMD_Main_Index] = BMD_Slashes[BMD_Ability_Level[BMD_Main_Index]]
Set BMD_Damage[BMD_Main_Index] = BMD_Damage[BMD_Ability_Level[BMD_Main_Index]]
Set BMD_Clones[BMD_Main_Index] = BMD_Clones[BMD_Ability_Level[BMD_Main_Index]]
Set BMD_Aoe[BMD_Main_Index] = BMD_Aoe[BMD_Ability_Level[BMD_Main_Index]]
Set BMD_Counter[BMD_Main_Index] = 0
-------- Setting The Target Point --------
Set BMD_Point[1] = (Target point of ability being cast)
-------- Setting The Dummy --------
Unit - Create 1 Dummy Caster for (Owner of BMD_CastingUnit[BMD_Main_Index]) at BMD_Point[1] facing Default building facing degrees
Set BMD_Unit_Dummy[BMD_Main_Index] = (Last created unit)
Unit - Add a (0.30 x (Real(BMD_Slashes[BMD_Main_Index]))) second Generic expiration timer to BMD_Unit_Dummy[BMD_Main_Index]
-------- Adding The Dummy Spells --------
Unit - Add Blademaster's Curse[1] to BMD_Unit_Dummy[BMD_Main_Index]
Unit - Add Blademaster's Curse[2] to BMD_Unit_Dummy[BMD_Main_Index]
-------- Pausing The Unit --------
Unit - Pause BMD_CastingUnit[BMD_Main_Index]
-------- Setting The Speed and Transparency Of The Caster --------
Animation - Change BMD_CastingUnit[BMD_Main_Index]'s animation speed to BMD_AnimationSpeed% of its original speed
Animation - Change BMD_CastingUnit[BMD_Main_Index]'s vertex coloring to (100.00%, 100.00%, 100.00%) with BMD_UnitTransparency% transparency
Special Effect - Create a special effect attached to the weapon of BMD_CastingUnit[BMD_Main_Index] using BMD_AttachmentWeapon
Set BMD_SpecialEffect[BMD_Main_Index] = (Last created special effect)
-------- Setting The Clones --------
For each (Integer Dummy_Index[BMD_Main_Index]) from 1 to BMD_Clones[BMD_Main_Index], do (Actions)
Loop - Actions
Unit - Create 1 Blademaster for (Owner of BMD_CastingUnit[BMD_Main_Index]) at BMD_Point[1] facing Default building facing degrees
Unit - Add a ((Real(BMD_Slashes[BMD_Main_Index])) x 0.30) second Generic expiration timer to BMD_Blademaster_Dummy
Set BMD_Blademaster_Dummy = (Last created unit)
Animation - Change BMD_Blademaster_Dummy's animation speed to BMD_AnimationSpeed% of its original speed
Animation - Change BMD_Blademaster_Dummy's vertex coloring to (100.00%, 100.00%, 100.00%) with BMD_UnitTransparency% transparency
Special Effect - Create a special effect attached to the weapon of BMD_Blademaster_Dummy using BMD_AttachmentWeapon
Set BMD_SpecialEffectDummy[Dummy_Index[BMD_Main_Index]] = (Last created special effect)
-------- Setting The Blades. You Can Remove It If You Want To --------
For each (Integer A) from 1 to 40, do (Actions)
Loop - Actions
Unit - Create 1 Dummy Sword[1] for (Owner of BMD_CastingUnit[BMD_Main_Index]) at (BMD_Point[1] offset by BMD_Aoe[BMD_Main_Index] towards ((Real((Integer A))) x 10.00) degrees) facing Default building facing degrees
Unit - Add a (0.30 x (Real(BMD_Slashes[BMD_Main_Index]))) second Generic expiration timer to (Last created unit)
-------- Removing The Leak --------
Custom script: call RemoveLocation(udg_BMD_Point[1])
[/trigger]

[trigger=Loop]BMD Loop
Events
Time - Every 0.30 seconds of game time
Conditions
Actions
-------- Indexing --------
For each (Integer BMD_IndexLoop) from 1 to BMD_Index, do (Actions)
Loop - Actions
-------- To Make It Easier --------
Set BMD_Main_Index = BMD_IndexArray[BMD_IndexLoop]
-------- Setting The Counter --------
Set BMD_Counter[BMD_Main_Index] = (BMD_Counter[BMD_Main_Index] + 1)
-------- Setting Points,And Group --------
Set BMD_Point[3] = (Position of BMD_Unit_Dummy[BMD_Main_Index])
Set BMD_Group[1] = (Units within BMD_Aoe[BMD_Main_Index] of BMD_Point[3] matching ((((Matching unit) is A structure) Not equal to True) and ((((Matching unit) is Magic Immune) Not equal to True) and ((((Matching unit) is A flying unit) Not equal to True) and ((((Matching unit)
Set BMD_Group[2] = (Units within BMD_Aoe[BMD_Main_Index] of BMD_Point[3] matching (((Unit-type of (Matching unit)) Equal to Blademaster) and ((Owner of (Matching unit)) Equal to (Owner of BMD_CastingUnit[BMD_Main_Index]))))
Set BMD_Point[2] = (Position of (Random unit from BMD_Group[1]))
-------- Killing Trees --------
Destructible - Pick every destructible within BMD_Aoe[BMD_Main_Index] of BMD_Point[3] and do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Destructible-type of (Matching destructible)) Equal to Summer Tree Wall
Then - Actions
Set BMD_Tree = (Picked destructible)
Destructible - Kill BMD_Tree
Else - Actions
-------- Checking Conditions --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Number of units in BMD_Group[1]) Greater than 0
BMD_Counter[BMD_Main_Index] Less than or equal to BMD_Slashes[BMD_Main_Index]
(BMD_CastingUnit[BMD_Main_Index] is alive) Equal to True
Then - Actions
-------- Making The Caster Move And Play The Animation --------
Special Effect - Create a special effect attached to the chest of BMD_CastingUnit[BMD_Main_Index] using BMD_AttachmentChest
Special Effect - Destroy (Last created special effect)
Animation - Play BMD_CastingUnit[BMD_Main_Index]'s attack animation
Unit - Move BMD_CastingUnit[BMD_Main_Index] instantly to BMD_Point[2], facing (Random angle) degrees
Unit - Make BMD_CastingUnit[BMD_Main_Index] face BMD_Point[2] over 0.10 seconds
-------- Making The Dummy Blademaster To Move And Play The Animation --------
Unit Group - Pick every unit in BMD_Group[2] and do (Actions)
Loop - Actions
Animation - Play (Picked unit)'s attack animation
Special Effect - Create a special effect attached to the chest of (Picked unit) using BMD_AttachmentChest
Special Effect - Destroy (Last created special effect)
Unit - Move (Picked unit) instantly to (Position of (Random unit from BMD_Group[1])), facing (Random angle) degrees
Unit - Make (Picked unit) face BMD_Point[2] over 0.10 seconds
-------- Damaging The Enemies --------
Unit Group - Pick every unit in BMD_Group[1] and do (Actions)
Loop - Actions
Special Effect - Create a special effect attached to the chest of (Picked unit) using BMD_AttachmentEnemy
Special Effect - Destroy (Last created special effect)
Unit - Order BMD_Unit_Dummy[BMD_Main_Index] to Undead Banshee - Curse (Picked unit)
Unit - Cause BMD_CastingUnit[BMD_Main_Index] to damage (Picked unit), dealing (Real(BMD_Damage[BMD_Main_Index])) damage of attack type Spells and damage type Normal
Else - Actions
-------- Removing The Special Effects --------
Special Effect - Destroy BMD_SpecialEffect[BMD_Main_Index]
For each (Integer Dummy_Index[BMD_Main_Index]) from 1 to BMD_Clones[BMD_Main_Index], do (Actions)
Loop - Actions
Special Effect - Destroy BMD_SpecialEffectDummy[Dummy_Index[BMD_Main_Index]]
-------- Removing The Dummy --------
Unit - Remove BMD_Unit_Dummy[BMD_Main_Index] from the game
Unit Group - Pick every unit in BMD_Group[2] and do (Actions)
Loop - Actions
Unit - Remove (Picked unit) from the game
-------- Making The Caster Normal --------
Animation - Change BMD_CastingUnit[BMD_Main_Index]'s vertex coloring to (100.00%, 100.00%, 100.00%) with 0.00% transparency
Unit - Unpause BMD_CastingUnit[BMD_Main_Index]
-------- Recycling The Indexes --------
Set BMD_IndexArray[BMD_IndexLoop] = BMD_IndexArray[BMD_Index]
Set BMD_IndexArray[BMD_Index] = BMD_Main_Index
Set BMD_Index = (BMD_Index - 1)
Set BMD_IndexLoop = (BMD_IndexLoop - 1)
-------- Turnng Off This Trigger --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
BMD_Index Equal to 0
Then - Actions
Trigger - Turn off (This trigger)
Else - Actions
-------- Removing The Leaks --------
Custom script: call DestroyGroup(udg_BMD_Group[1])
Custom script: call DestroyGroup(udg_BMD_Group[2])
Custom script: call RemoveLocation(udg_BMD_Point[2])
Custom script: call RemoveLocation(udg_BMD_Point[3])
-------- Removing The Leaks --------
[/trigger]


Blademaster's Den v1.0.0
- Release
Blademaster's Den v1.2.0
- MUI
- I followed what Tank-Commander said. TNX to Him
- 3 Blademasters Removed
- can cut trees
- there's a few changes at the map ----- not really important XD
- there's few changes at the skill
Blademaster's Den v1.2.5
- I followed what Tank-Commander said. Thanks it really helped me :)
- Creates 1 Blademaster
Blademaster's Den v1.3.0
- I fixed some problems
- Some changes in the spell
- I made it cleaner
Blademaster's Den v1.3.5
- I add some special effects
- I add some details at the spell
- Fixed The Lag
Blademaster's Den v1.3.7
- I add a few details to this spell
- I Remove The Leaks that Tank-Commander Said (Thanks to him)
Blademaster's Den 1.3.8
- I remove the leaks that Tank-Commander Said (as always thanks for your help)
Blademaster's Den 1.3.9
- I removed some leaks
- I Followed what Tank-Commander Said :)


Makes a field of blades,makes phantom illusions and,slashing them multiple times,also he will stop slashing if there are no enemies in that area.
Level 1 - 20 damage per slash and 10 slashes creates 1 phantom illusion.
Level 2 - 30 damage per slash and 15 slashes creates 2 phantom illusions.
Level 3 - 40 damage per slash and 20 slashes creates 3 phantom illusions.
Level 4 - 50 damage per slash and 25 slashes creates 4 phantom illusions.




[highlight]Tank-Commander[/code] - For Helping Me On This Spell

Please Give Credit For My Work If You Use It
Enjoy =)

Keywords:
Simple,Omnislash,Slash,"/",Illuminati,Blink,MLG,Shrek's Swamp,John Cena,Chuck Norris,etc
Contents

BladeMaster's Den v.1.3.9 (Map)

Reviews
22:43, 14th May 2016 Tank-Commander: V1.3.9 - I left this post a while back addressing some issues, since they haven't been resolved I'm setting this back to needs fix. If you didn't notice it was there you can subscribe to your thread using the...

Moderator

M

Moderator

22:43, 14th May 2016
Tank-Commander: V1.3.9 - I left this post a while back addressing some issues, since they haven't been resolved I'm setting this back to needs fix. If you didn't notice it was there you can subscribe to your thread using the thread tools and you'll know when there's a new post


14:16, 1st May 2016
Tank-Commander: V1.3.7 - It's nearly there, but there's still some leaks (see: the same post as before) - I'd also suggest compiling a list of merits of this entry over the other Omnislash abilities on the site since once it's cleaned up we'll need to compare and contrast before we can decide to approve or not and it'd make approving this easier

07:05, 30th Apr 2016
Tank-Commander: V1.3.5 - still leaks as with the previous versions, set back to needs fix

23 April 2016
Bribe

This is loaded with memory leaks. I advise seeking help with this resource in the Triggers & Scripts forum. We also have at least 6 billion omnislash spells.

17:07, 21st Apr 2016
Tank-Commander: V1.2.0 - There still some major issues to be addressed, the ability has some notable memory leaks and confusing behaviours: see my post for details

11:52, 19th Apr 2016
Tank-Commander: V1.0.1 - Thanks for the submission - I gave the ability a quick once-over and found a few things that need changing. Please see my post for details
 
There's quite a few things to address with this ability but I'll stick to the major issues since other problems may be solved by first solving them:

Major:
- The ability is not MUI (Multi-Unit-Instable)
- The structure is inefficient: The same code is repeated for each blademaster created by the ability, by utilising a proper indexing method and loops, all of the duplication could be removed
- If the ability is used in an undead player's base then all the blight within the base will be removed: Don't modify terrain with an ability
- Lacks a configuration
 
Alright now the ability is starting to resemble something we can use here's some more pointers over what is still left to do:

Major:
- BMD_Unit[0] is not indexed, a dummy is leaked whenever more than one instance is active
- There's no variable use for values commonly used: for example you used "Owner Of BMD Unit[]" 71 times by my count in the cast trigger, you could store this in a variable and just refer to that and it'll run much faster (the same goes for other values referred to in this way)
- Your destructible killing doesn't differentiate between things like trees and things like bridges: We don't want to kill bridges - there are methods on how to avoid this and systems which do it you can find in the spell section.
- AOE and amount of swords are things that should be configurable (amongst other things)

- You reference "Random Unit from BMD_Group[Main_Index]" however at no point is that Group set to anything unless the index happens to be 1 (also if that's meant to be Group 1 then it would pick random units from the whole group rather than those close enough to damage.

  • Unit Group - Pick every unit in BMD_Group[1] and do (Actions)
    • Loop - Actions
      • Animation - Play BMD_Unit[Main_Index]'s Animation[Main_Index] animation
      • Special Effect - Create a special effect attached to the chest of BMD_Unit[Main_Index] using Abilities\Spells\Human\Polymorph\PolyMorphDoneGround.mdl
      • Unit - Move BMD_Unit[Main_Index] instantly to BMD_Point[2], facing (Random angle) degrees
      • Unit - Make BMD_Unit[Main_Index] face (Picked unit) over 0.10 seconds
      • Unit - Order BMD_Unit[0] to Undead Banshee - Curse (Picked unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between BMD_Point[3] and BMD_Point[2]) Less than or equal to 200.00
        • Then - Actions
          • Unit - Cause BMD_Unit[Main_Index] to damage (Random unit from BMD_Group[Main_Index]), dealing (Real(BMD_Damage[Main_Index])) damage of attack type Spells and damage type Normal
          • Special Effect - Create a special effect attached to the chest of (Random unit from BMD_Group[1]) using Abilities\Spells\Other\Stampede\StampedeMissileDeath.mdl
        • Else - Actions
      • -------- Removing Leaks --------
      • Custom script: call RemoveLocation(udg_BMD_Point[2])
      • Custom script: call RemoveLocation(udg_BMD_Point[3])
- You repeatedly move the unit and set information about it's animations (etc.) for every unit in the group (though it is always the same location and creates a new random angle every time - also spamming effects
- All those special effects leak as they're never destroyed
- You check if point 3 and point 2 are close together, and if that's true proceed to damage any unit from the group? not ones that are close to point 3?

- What's the point in selecting units randomly if you want to damage all valid targets? (since you pick every unit in the group and run the actions for each one)
- Why do you have multiple sword dummy types when they're basically identical?

Minor:
- The indexing method you're using is very weird to me I'll need to go over it at another point when I have a bit more time on my hands (this may amount to nothing if all is good but would be a major problem if something is wrong)
- Your variable names don't follow a standard convention, while some of them start with BMD_ a lot of the others don't, please fix this

I may add more to this list once I've had a bit more time to go over the code
 
While this has undergone a lot of improvements - you're still leaking a lot of special effects
  • Special Effect - Create a special effect attached to the chest of (Picked unit) using BMD_AttachmentChest
these effects are created a lot of times and are never get destroyed, these and all other effects you make like this leak and the spell can never be approved until these are all resolved, and that's before considering this one's merits vs the other omnislash type abilities we have

Edit: V1.3.7 - You've cleared up most of them a few persist though
  • For each (Integer Dummy_Index[BMD_Main_Index]) from 1 to BMD_Clones[BMD_Main_Index], do (Actions)
    • (...)
    • Special Effect - Create a special effect attached to the weapon of BMD_Blademaster_Dummy using BMD_AttachmentWeapon
    • Set BMD_SpecialEffectDummy = (Last created special effect)
BMD_SpeciaEffectDummy isn't indexed and as such it leaks

you also have
  • Special Effect - Create a special effect attached to the chest of BMD_CastingUnit[BMD_Main_Index] using BMD_AttachmentChest
in the loop that never gets destroyed
 
Last edited:
The spell should be in an approvable condition after these two key things are fixed:

the tree detection doesn't fit requirements (as it can only detect summer tree walls, there's a method we use to detect any kind of tree (including non default ones)

1) Create an invisible, unkillable dummy unit (use the same one as you do for the spell) and the config trigger (as you only need one and you never get rid of it)
2) Give it harvest (ghoul) and store it in a variable (say BMD_TreeDetector or something to that effect)
3) When you want to detect a tree order the unit to harvest the picked destructible
4) Check the current order of the Tree Detector, if it is still harvest then the destructible is a tree

it looks something like this
  • Destructible - Pick every destructible within BMD_Aoe[BMD_Main_Index] of BMD_Point[3] and do (Actions)
    • Loop - Actions
      • Set BMD_Tree = (Picked destructible)
      • Unit - Order (BMD_TreeChecker) to (Harvest) (BMD_Tree)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Current Order of (BMD_TreeChecker) equal to Harvest
        • Then - Actions
          • Destructible - Kill BMD_Tree


Your spell isn't truly MUI - that is to say, your spell instances can interfere with each other. When you remove Group 2 units in the spell it's possible that some of those units belong to a different cast of the spell, you need to make sure that this does not happen

You could resolve this a number of ways - indexing all the dummy units, using indexed unit groups, expiration timers (though that would require knowing how long the spell takes in advance), basically any method you can think of which achieves this is fine, but it is necessary


Also I notice you're still leaking with this line:
  • Unit - Move (Picked unit) instantly to (Position of (Random unit from BMD_Group[1])), facing (Random angle) degrees
I strongly recommend looking carefully over your own work for leaks before submitting - Mods can't/don't notice everything the first run through the code (particularly when there's a lot of leaks) and it leads to a lot of reviews stating that it leaks still
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Some other minor things to add onto Tank's review:
  • With Tank's tree detection example, make sure to order the harvester to stop at the end of the loop
  • You have two abilities currently hardcoded into your spell. Users will need to manually change all of them if they import this into your map. You can just use 2 ability variables that can be changed from the config trigger
  • It's kind of pointless to cache variables like Damage[], Slashes[], Clones[], and AoE when you can just reference them directly like: Damage[Ability_Level[Index]]
  • Store the owner of the caster into an indexed variable on cast
  • I'd make the attack and damage type configurable
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
It's kind of pointless to cache variables like Damage[], Slashes[], Clones[], and AoE when you can just reference them directly like: Damage[Ability_Level[Index]]

I don't think pointless is a fair description. If the extra variable improves readability or maintainability, it is an improvement. Equally, if it makes those properties worse, it is detrimental.

My main concern is that this suggestion might be being made because it's considered a performance penalty. This is dangerous. Don't think about this!

If the ability has some performance hit and you want to optimize it, never start with micro-optimisations. In general, 90% of the execution time is being spent on 10% of the code. In the olden days the term "hot spot" was thrown around a lot - https://en.wikipedia.org/wiki/Hot_spot_(computer_programming)

With I/O bound programs, I/O is usually the expensive part. JASS is not the case. But the 90/10 rule still applies to JASS.

The rest of the suggestions look good.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
My main concern is that this suggestion might be being made because it's considered a performance penalty.
I was just stating that I personally thought it was pointless. I never like having to come up with two variable names that represent the configurable + the one used in the code, so I just stick with referencing it directly.
 
Top