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

Icon/Model/Spell Team Contest - Hive Member[+100 Rep]

Status
Not open for further replies.
The Hero model is done.

artisandone-gif.287829
 
Previous:
The scourge may be lacking, but it still has the passion for destruction.
Similarly, the team may lack a modeler, but we are one in creating the model.


model-wip_01-png.287909

model-wip_01-png.287087


EDIT: Sorry for the confusion earlierearly.
#Message 441 - 460

@IcemanBo

Would the image above suffice as a WIP on the model?

Now:
I would be showing the second WIP here, what it looks like as of now (I understand some complaints on violation, but we'll do our best to remake the skin of the spider itself.


model-wip_02-png.287910

 
Last edited:
Level 37
Joined
Jul 22, 2015
Messages
3,485
Welp I guess it's my turn to post WIPs.

Our Hero basically has a sub-ability that lets them switch the color of their paint. The color of the paint will decide the mechanic of the primary ability. As you can see below, when they learn the ability, they start off a default color.

giphy.gif


This shouldn't have been the case, but the Switch Paint mechanic took forever to make ._.

  • SPaint Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to SPaint_ABILITY
    • Actions
      • -------- SPaint Cast --------
      • -------- this trigger will switch the "color mode" for the unit --------
      • -------- if the unit reaches the end of the color palette, it will moved back to color #1 --------
      • -------- --------
      • -------- --------
      • Set SPaint_TempUnit = (Triggering unit)
      • Custom script: set udg_SPaint_UnitId = GetHandleId(udg_SPaint_TempUnit)
      • Set SPaint_CurrentColor = (Load PBomb_KEY_CURRENT_COLOR of SPaint_UnitId from PBomb_Hash)
      • Unit - Remove SPaint_SFX_ABILITY[SPaint_CurrentColor] from SPaint_TempUnit
      • Unit - Remove SPaint_SFX_BUFF[SPaint_CurrentColor] buff from SPaint_TempUnit
      • -------- --------
      • -------- checking which color the unit will now have --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SPaint_CurrentColor Not equal to SPaint_TOTAL_COLORS
        • Then - Actions
          • -------- unit is not at the end of the color palette; move up one --------
          • Set SPaint_CurrentColor = (SPaint_CurrentColor + 1)
        • Else - Actions
          • -------- unit is at the end of the color palette; move back to the beginning --------
          • Set SPaint_CurrentColor = 1
      • -------- --------
      • Unit - Add SPaint_SFX_ABILITY[SPaint_CurrentColor] to SPaint_TempUnit
      • -------- --------
      • Hashtable - Save SPaint_CurrentColor as PBomb_KEY_CURRENT_COLOR of SPaint_UnitId in PBomb_Hash
 
Welp I guess it's my turn to post WIPs.

Our Hero basically has a sub-ability that lets them switch the color of their paint. The color of the paint will decide the mechanic of the primary ability. As you can see below, when they learn the ability, they start off a default color.

giphy.gif


This shouldn't have been the case, but the Switch Paint mechanic took forever to make ._.

  • SPaint Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to SPaint_ABILITY
    • Actions
      • -------- SPaint Cast --------
      • -------- this trigger will switch the "color mode" for the unit --------
      • -------- if the unit reaches the end of the color palette, it will moved back to color #1 --------
      • -------- --------
      • -------- --------
      • Set SPaint_TempUnit = (Triggering unit)
      • Custom script: set udg_SPaint_UnitId = GetHandleId(udg_SPaint_TempUnit)
      • Set SPaint_CurrentColor = (Load PBomb_KEY_CURRENT_COLOR of SPaint_UnitId from PBomb_Hash)
      • Unit - Remove SPaint_SFX_ABILITY[SPaint_CurrentColor] from SPaint_TempUnit
      • Unit - Remove SPaint_SFX_BUFF[SPaint_CurrentColor] buff from SPaint_TempUnit
      • -------- --------
      • -------- checking which color the unit will now have --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • SPaint_CurrentColor Not equal to SPaint_TOTAL_COLORS
        • Then - Actions
          • -------- unit is not at the end of the color palette; move up one --------
          • Set SPaint_CurrentColor = (SPaint_CurrentColor + 1)
        • Else - Actions
          • -------- unit is at the end of the color palette; move back to the beginning --------
          • Set SPaint_CurrentColor = 1
      • -------- --------
      • Unit - Add SPaint_SFX_ABILITY[SPaint_CurrentColor] to SPaint_TempUnit
      • -------- --------
      • Hashtable - Save SPaint_CurrentColor as PBomb_KEY_CURRENT_COLOR of SPaint_UnitId in PBomb_Hash

It's quite impressive, even if the preview of the sfx-es are just the placeholder equivalents of the final spell.

It would have been difficult to maintain the overall idea in creating such a behaviour (spell mechanic, not the switch) in vJASS alone, even more so in JASS, but you did it in GUI, which is another level altogether.

Just a suggestion, you could use less than as a comparison instead of not equal to just to be safe.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
It would have been difficult to maintain the overall idea in creating such a behaviour (spell mechanic, not the switch) in vJASS alone, even more so in JASS, but you did it in GUI, which is another level altogether.
Thank you, but I only finished the switch xD I haven't started on the primary ability yet. Although, I do already have something in mind that should make it really easy.

Just a suggestion, you could use less than as a comparison instead of not equal to just to be safe.
Out of curiousity, why would a < b be safer than a != b?
 
^^ I think that somewhere out there, there will be a user who would not understand enough of the spell to change the current colour to something higher than the total. If it does happen, the counter will always increase without ever returning to the preset of colours.

Example:
Wurst:
Total=4
Current_color=5

If Current_color != Total
    Current_color++
else
    Current_color = 1
 
Last edited:
Level 37
Joined
Jul 22, 2015
Messages
3,485
@Kyrbi0 turns out my team members are too good for me. They already finished the effects for it, but I didnt see it :p (its much more visible ingame)
giphy.gif


I think that somewhere out there, there will be a user who would not understand enough of the spell to change the current colour to something higher than the total.
Ahh okay. CurrentColor acts as a private member basically. The user would have to physically go into the code to change the current color.
 
Would the image above suffice as a WIP on the model?

Now:
I would be showing the second WIP here
Literally no interaction happened from your side after any of these ...
@MyPad it's cool you code, but... do you even have a team concept and a modeler? ;s
Joining multiple teams won't work. But @MyPad @Darkfang , it's your team, guys, you could have asked if it's ok to work on without modeler, or just initiate a talk, but nothing happened.. You probably will do hard to start find a new one, now, but that should be the goal, I believe.
Your ignorance is welcome as always.
... nor any attempt or statement to solve the issue anyhow, or to talk with Murloc, or me.

I don't believe it's valid WIP for model.
 
Literally no interaction happened from your side after any of these ...



... nor any attempt or statement to solve the issue anyhow, or to talk with Murloc, or me.

I don't believe it's valid WIP for model.

It is what I had done, freely choosing not to discuss with either of you about the modeller problem because I had thought that the problem would be easily resolved, (assuming that a modeller will be available). I would only request, therefore that we may be allowed to proceed with the contest, as @Darkfang and I are also the modellers in the Scourge team.

The models which you saw are partially done by both @Darkfang and I, and I express guilt for any misunderstanding that I have caused inasmuch as I prefer actions to words.


After realizing this problem would not be so easily resolved, we decided to do the modelling ourselves, and how fun it was to make a model. The intricacy of every procedure confounds and interests me, who is firstly a coder.
 
Last edited:
Yes, but this exactly is the problem that you decided yourself even I explicitly mentioned it to you, and implied to look for dicussion in case something won't work as planned. But as in mostly all other situations between us both, you just ignore.

I'm passionless with the outcome now when it's already pretty the end of contest. @Murlocologist , could you make some statement towards the situation - and then we will make it.
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,492
I must admit, the conversation has been... difficult to follow. But as far as I've read, the Rules only state that it has to stay in the team. As long as the team members get together & make it themselves, I don't see why there should be an issue. The detriment of not having a dedicated modeler will naturally be found in the final Judging.
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,492
OK, so that's a Rule that would generally preclude going *into* a situation like this, that way.

So the question is: how (again; wasn't paying attention) did this come about? Did they intentionally start a team with only 2 members? Or did they lose their modeler? If the latter, it's not uncommon to extend them the mercy of allowing them to continue (with the innate handicap).
 
Level 50
Joined
Mar 22, 2016
Messages
588
It is what I had done, freely choosing not to discuss with either of you about the modeller problem because I had thought that the problem would be easily resolved, (assuming that a modeller will be available).

How many modelers have you asked to join your team? Or have you just waited for some to approach you? Team consists of three members. What part about that isn't clear? Or you think rules listed in first post are only a decoration? Where did then the trolling with ''no where in rules it is listed that one member can't join two teams'' come from, as it seems that rules are irrelevant for your team?

Instead of asking us earlier or asking someone to join your team, you continued to work on entry, even the model. If the two of you can create model, than one would take role of modeler and look for icon or spell maker. But you obviously didn't care to find third member.

IcemanBo and I have discussed this situation earlier and even though there is no excuse for not finding or even not looking for third member, we'll let your team enter the contest with the penalty points for not having three members. IcemanBo will announce how many points will be taken in the poll thread.
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
Ayyyy all that is left is to make the mechanics for the 3 different paint colors ;_; starting to regret agreeing to this spell concept.
WIP.gif

Hoorah for error messages!


Obligatory code WIP
  • PBomb Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- --------
      • -------- CONFIG START --------
      • -------- --------
      • -------- --------
      • -------- imported object editor data --------
      • Set PBomb_ABILITY = Paint Bomb
      • -------- --------
      • -------- imported triggers --------
      • Set PBomb_TRIGGER_LOOP = PBomb Loop <gen>
      • Set PBomb_TRIGGER_PLAY_ERROR = PBomb Error Msg <gen>
      • -------- --------
      • -------- order string for PBomb_ABILITY --------
      • Set PBomb_ORDER_ID = channel
      • -------- --------
      • -------- minimum cast range PBomb_ABILITY can be casted at (NEVER make this value 0) --------
      • Set PBomb_MIN_CAST_RANGE = 200.00
      • -------- --------
      • -------- maximum height the missile can reach --------
      • Set PBomb_MaxHeight = 275.00
      • -------- time (in seconds) it will take for the missile to reach the target location --------
      • Set PBomb_TRAVEL_TIME = 0.75
      • Set PBomb_TRAVEL_TIME_PER_LEVEL = 0.00
      • -------- --------
      • -------- other --------
      • Set PBomb_PERIODIC_TIMER = 0.03
      • -------- error message that will display to the player if they cast PBomb_ABILITY inside PBomb_MIN_CAST_RANGE --------
      • Set PBomb_ERROR_MSG1 = Target is inside minimum cast range.
      • -------- error message that will display if the player tries to cast more puddles than they are allowed to --------
      • Set PBomb_ERROR_MSG2 = You cannot create any more puddles of that color.
      • -------- --------
      • -------- --------
      • -------- CONFIG END --------
      • -------- --------
      • Trigger - Add to PBomb_TRIGGER_LOOP the event (Time - Every PBomb_PERIODIC_TIMER seconds of game time)
      • Custom script: set udg_PBomb_ERROR_SOUND = CreateSoundFromLabel("InterfaceError", false, false, false, 10, 10)
      • Hashtable - Create a hashtable
      • Set PBomb_Hash = (Last created hashtable)
      • Set PBomb_KEY_CURRENT_COLOR = 0
      • -------- child keys for active puddle count in CPalete Config --------
      • Set PBomb_LocZ = (Center of (Playable map area))
      • -------- preload --------
      • Custom script: set udg_PBomb_TempUnit = GetRecycledDummyAnyAngle(0.00, 0.00, 0.00)
      • For each (Integer PBomb_TempInt) from 1 to SPaint_TOTAL_COLORS, do (Actions)
        • Loop - Actions
          • Special Effect - Create a special effect attached to the PBomb_SFX_MISSILE_AP[PBomb_TempInt] of PBomb_TempUnit using PBomb_SFX_MISSILE[PBomb_TempInt]
          • Special Effect - Destroy (Last created special effect)
      • Custom script: call RecycleDummy(udg_PBomb_TempUnit)


  • PBomb Order
    • Events
      • Unit - A unit Is issued an order targeting a point
    • Conditions
      • (Issued order) Equal to (Order(PBomb_ORDER_ID))
    • Actions
      • -------- PBomb Order --------
      • -------- this trigger will ensure that the caster does not cast the spell inside PBomb_MIN_CAST_RANGE --------
      • -------- and that they cant create another puddle if they reached the MAX_PUDDLES for that color --------
      • -------- if the caster casts the spell too close, the order will be interrupted --------
      • -------- --------
      • -------- --------
      • -------- there can be multiple spells in a map with the same order id. to ensure it's the one we are looking for, check for the level of the PBomb_ABILITY on the triggering unit --------
      • Set PBomb_TempUnit = (Triggering unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of PBomb_ABILITY for PBomb_TempUnit) Greater than or equal to 1
        • Then - Actions
          • -------- PBomb_ABILITY was casted; check if the distance meets the minimum requirement --------
          • -------- --------
          • Set PBomb_TempLoc1 = (Position of PBomb_TempUnit)
          • Set PBomb_TempLoc2 = (Target point of issued order)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between PBomb_TempLoc1 and PBomb_TempLoc2) Less than PBomb_MIN_CAST_RANGE
            • Then - Actions
              • -------- PBomb_ABILITY was casted too close; interrupt cast order --------
              • -------- --------
              • Unit - Pause PBomb_TempUnit
              • Unit - Order PBomb_TempUnit to Stop
              • Unit - Unpause PBomb_TempUnit
              • -------- play error message --------
              • Set PBomb_TempPlayer = (Triggering player)
              • Set PBomb_ErrorMsg = PBomb_ERROR_MSG1
              • Trigger - Run PBomb_TRIGGER_PLAY_ERROR (ignoring conditions)
            • Else - Actions
              • -------- PBomb_ABILITY met the minimum cast range requirement; check to make sure that caster hasn't reached MAX_PUDDLES for active color --------
              • -------- --------
              • Custom script: set udg_PBomb_UnitId = GetHandleId(udg_PBomb_TempUnit)
              • Set SPaint_CurrentColor = (Load PBomb_KEY_CURRENT_COLOR of PBomb_UnitId from PBomb_Hash)
              • Set PBomb_TempInt = (PBomb_MAX_PUDDLES[SPaint_CurrentColor] + (PBomb_MAX_PUDDLES_PER_LEVEL[SPaint_CurrentColor] x (Level of PBomb_ABILITY for PBomb_TempUnit)))
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Load PBomb_KEY_ACTIVE_COUNT[SPaint_CurrentColor] of PBomb_UnitId from PBomb_Hash) Greater than or equal to PBomb_TempInt
                • Then - Actions
                  • -------- caster is already at maximum puddle count; interrupt cast order --------
                  • -------- --------
                  • Unit - Pause PBomb_TempUnit
                  • Unit - Order PBomb_TempUnit to Stop
                  • Unit - Unpause PBomb_TempUnit
                  • -------- play error message --------
                  • Set PBomb_ErrorMsg = PBomb_ERROR_MSG2
                  • Set PBomb_TempPlayer = (Triggering player)
                  • Trigger - Run PBomb_TRIGGER_PLAY_ERROR (ignoring conditions)
                • Else - Actions
                  • -------- caster has not reached the maximum puddle count for the color; do nothing --------
          • -------- --------
          • Custom script: call RemoveLocation(udg_PBomb_TempLoc1)
          • Custom script: call RemoveLocation(udg_PBomb_TempLoc2)
        • Else - Actions
          • -------- not PBomb_ABILITY; do nothing --------
  • PBomb Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to PBomb_ABILITY
    • Actions
      • -------- PBomb Cast --------
      • -------- this trigger will create a new instance to move the missile to the targeted location --------
      • -------- --------
      • -------- members --------
      • -------- Caster[] = unit that casted the spell --------
      • -------- Owner[] = player that owns Caster[] --------
      • -------- AbilityLvl[] = current ability level of PBomb_ABILITY for Caster[] --------
      • -------- CurrentColor[] = current color selected for Caster[] --------
      • -------- MissileUnit[] = dummy unit with special effect --------
      • -------- Cos[] = cosine of the angle MissileUnit[] will move towards --------
      • -------- Sin[] = sine of the angle MissileUnit[] will move towards --------
      • -------- DistanceTraveled[] = total distance moved by MissileUnit[] --------
      • -------- MoveRate[] = how fast MissileUnit[] will move per iteration --------
      • -------- --------
      • -------- --------
      • Set PBomb_SpellCount = (PBomb_SpellCount + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • PBomb_SpellCount Equal to 1
        • Then - Actions
          • Trigger - Turn on PBomb_TRIGGER_LOOP
        • Else - Actions
          • -------- do nothing --------
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • PBomb_RecycledSize Equal to 0
        • Then - Actions
          • Set PBomb_MaxIndex = (PBomb_MaxIndex + 1)
          • Set PBomb_SpellId = PBomb_MaxIndex
        • Else - Actions
          • Set PBomb_RecycledSize = (PBomb_RecycledSize - 1)
          • Set PBomb_SpellId = PBomb_RecycledStack[PBomb_RecycledSize]
      • Set PBomb_NodeNext[PBomb_SpellId] = 0
      • Set PBomb_NodePrev[PBomb_SpellId] = PBomb_NodePrev[0]
      • Set PBomb_NodeNext[PBomb_NodePrev[0]] = PBomb_SpellId
      • Set PBomb_NodePrev[0] = PBomb_SpellId
      • -------- --------
      • Set PBomb_Caster[PBomb_SpellId] = (Triggering unit)
      • Set PBomb_Owner[PBomb_SpellId] = (Triggering player)
      • Set PBomb_AbilityLvl[PBomb_SpellId] = (Level of PBomb_ABILITY for PBomb_Caster[PBomb_SpellId])
      • Set PBomb_CurrentColor[PBomb_SpellId] = (Load PBomb_KEY_CURRENT_COLOR of (Key (Triggering unit)) from PBomb_Hash)
      • -------- --------
      • Set PBomb_TempLoc1 = (Position of PBomb_Caster[PBomb_SpellId])
      • Set PBomb_TempLoc2 = (Target point of ability being cast)
      • Set PBomb_TempReal1 = (Angle from PBomb_TempLoc1 to PBomb_TempLoc2)
      • Set PBomb_TempReal2 = (Current flying height of PBomb_Caster[PBomb_SpellId])
      • Custom script: set udg_PBomb_StartZ[udg_PBomb_SpellId] = GetLocationZ(udg_PBomb_TempLoc1) + udg_PBomb_TempReal2
      • Custom script: set udg_PBomb_EndZ[udg_PBomb_SpellId] = GetLocationZ(udg_PBomb_TempLoc2)
      • -------- --------
      • Custom script: set udg_PBomb_MissileUnit[udg_PBomb_SpellId] = GetRecycledDummy(GetLocationX(udg_PBomb_TempLoc1), GetLocationY(udg_PBomb_TempLoc1), udg_PBomb_TempReal2, udg_PBomb_TempReal1)
      • Special Effect - Create a special effect attached to the PBomb_SFX_MISSILE_AP[PBomb_CurrentColor[PBomb_SpellId]] of PBomb_MissileUnit[PBomb_SpellId] using PBomb_SFX_MISSILE[PBomb_CurrentColor[PBomb_SpellId]]
      • Set PBomb_MissileSfx[PBomb_SpellId] = (Last created special effect)
      • -------- --------
      • Set PBomb_Cos[PBomb_SpellId] = (Cos(PBomb_TempReal1))
      • Set PBomb_Sin[PBomb_SpellId] = (Sin(PBomb_TempReal1))
      • Set PBomb_DistanceTraveled[PBomb_SpellId] = 0.00
      • Set PBomb_TotalDistance[PBomb_SpellId] = (Distance between PBomb_TempLoc1 and PBomb_TempLoc2)
      • Set PBomb_MoveRate[PBomb_SpellId] = (PBomb_TotalDistance[PBomb_SpellId] / ((PBomb_TRAVEL_TIME + (PBomb_TRAVEL_TIME_PER_LEVEL x (Real(PBomb_AbilityLvl[PBomb_SpellId])))) / PBomb_PERIODIC_TIMER))
      • -------- --------
      • Custom script: call RemoveLocation(udg_PBomb_TempLoc1)
      • Custom script: call RemoveLocation(udg_PBomb_TempLoc2)
  • PBomb Loop
    • Events
    • Conditions
    • Actions
      • Custom script: local real newX
      • Custom script: local real newY
      • Custom script: local real currentD
      • Custom script: local real totalD
      • Custom script: local real originZ
      • Custom script: local real aimZ
      • Custom script: local real adjustZ
      • -------- --------
      • Set PBomb_SpellId = 0
      • For each (Integer PBomb_LoopInt) from 1 to PBomb_SpellCount, do (Actions)
        • Loop - Actions
          • Set PBomb_SpellId = PBomb_NodeNext[PBomb_SpellId]
          • -------- --------
          • -------- xy adjustment --------
          • Custom script: set newX = GetUnitX(udg_PBomb_MissileUnit[udg_PBomb_SpellId]) + udg_PBomb_MoveRate[udg_PBomb_SpellId] * udg_PBomb_Cos[udg_PBomb_SpellId]
          • Custom script: set newY = GetUnitY(udg_PBomb_MissileUnit[udg_PBomb_SpellId]) + udg_PBomb_MoveRate[udg_PBomb_SpellId] * udg_PBomb_Sin[udg_PBomb_SpellId]
          • Set PBomb_DistanceTraveled[PBomb_SpellId] = (PBomb_DistanceTraveled[PBomb_SpellId] + PBomb_MoveRate[PBomb_SpellId])
          • -------- z adjustment (need to use locals or else editor will crash from lengthy custom script) --------
          • Custom script: call MoveLocation(udg_PBomb_LocZ, newX, newY)
          • Custom script: set currentD = udg_PBomb_DistanceTraveled[udg_PBomb_SpellId]
          • Custom script: set totalD = udg_PBomb_TotalDistance[udg_PBomb_SpellId]
          • Custom script: set originZ = udg_PBomb_StartZ[udg_PBomb_SpellId]
          • Custom script: set aimZ = udg_PBomb_EndZ[udg_PBomb_SpellId]
          • Custom script: set adjustZ = originZ - GetLocationZ(udg_PBomb_LocZ)
          • Custom script: set udg_PBomb_Height = adjustZ + 4 * udg_PBomb_MaxHeight * currentD * (totalD-currentD) / (totalD*totalD) + currentD * (aimZ-originZ) / totalD
          • -------- apply adjustment --------
          • Custom script: call SetUnitX(udg_PBomb_MissileUnit[udg_PBomb_SpellId], newX)
          • Custom script: call SetUnitY(udg_PBomb_MissileUnit[udg_PBomb_SpellId], newY)
          • Animation - Change PBomb_MissileUnit[PBomb_SpellId] flying height to PBomb_Height at 0.00
          • -------- --------
          • -------- checking if missile reached target location --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • PBomb_DistanceTraveled[PBomb_SpellId] Greater than or equal to PBomb_TotalDistance[PBomb_SpellId]
            • Then - Actions
              • -------- missile has reached target location; begin phase 2 --------
              • Trigger - Run PBomb_TRIGGER_INDEX_COLOR[PBomb_CurrentColor[PBomb_SpellId]] (ignoring conditions)
              • -------- --------
              • Special Effect - Destroy PBomb_MissileSfx[PBomb_SpellId]
              • Custom script: call DummyAddRecycleTimer(udg_PBomb_MissileUnit[udg_PBomb_SpellId], udg_PBomb_SFX_DEATH_TIMER[udg_PBomb_CurrentColor[udg_PBomb_SpellId]])
              • -------- --------
              • Set PBomb_RecycledStack[PBomb_RecycledSize] = PBomb_SpellId
              • Set PBomb_RecycledSize = (PBomb_RecycledSize + 1)
              • Set PBomb_NodeNext[PBomb_NodePrev[PBomb_SpellId]] = PBomb_NodeNext[PBomb_SpellId]
              • Set PBomb_NodePrev[PBomb_NodeNext[PBomb_SpellId]] = PBomb_NodePrev[PBomb_SpellId]
              • -------- --------
              • Set PBomb_SpellCount = (PBomb_SpellCount - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • PBomb_SpellCount Equal to 0
                • Then - Actions
                  • Trigger - Turn off PBomb_TRIGGER_LOOP
                • Else - Actions
                  • -------- do nothing --------
            • Else - Actions
              • -------- missile has not reached target location; continue moving missile --------
Bonus image of what my trigger editor looks like ;D
Capture.PNG
 
we'll let your team enter the contest with the penalty points for not having three members. IcemanBo will announce how many points will be taken in the poll thread.

Seems okay to me, as long as we get to submit our entries. Thank you.

EDIT:

I hope this one can be considered as WIP.


model-wip_03-png.287963

 
Last edited:
Speaking of lacking teammates, unfortunately our team won't be able to submit anything (lack of communication) thus we're withdrawing from the contest.
What?.. what's the current state or exact lack? Or there's just absolutly nothing?
The deadline is 30 November 23:59 GMT right? I want to confirm the time left.
Is there an issue with the info from main post? It's clearly stated 30th Dec GMT (day included) ...
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
@IcemanBo @Murlocologist just in case it was missed, I posted my 2nd code WIP.

Thank you for using GUI, I was afraid I'm the old guy here :D
GUI always and forever.

EDIT
===

Going to keep this thread alive for the last few days, so here is my 3rd WIP! I finished the "red paint" mechanic :D

WIP.gif


Two more to go ;_;


  • RPaint Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- --------
      • -------- CONFIG START --------
      • -------- --------
      • -------- --------
      • -------- imported triggers --------
      • Set RPaint_TRIGGER_LOOP = RPaint Loop <gen>
      • -------- --------
      • -------- damage dealt to nearby enemy units when the bubble explodes --------
      • Set RPaint_DAMAGE = 50.00
      • Set RPaint_DAMAGE_PER_LEVEL = 25.00
      • -------- --------
      • -------- how close a unit must be to the bubble to take damage --------
      • Set RPaint_AOE = 250.00
      • Set RPaint_AOE_PER_LEVEL = 0.00
      • -------- --------
      • -------- time (in seconds) it takes for the bubble to pop and deal damage --------
      • Set RPaint_POP_DELAY = 2.00
      • Set RPaint_POP_DELAY_PER_LEVEL = 0.00
      • -------- --------
      • -------- time (in seconds) it takes for the bubble to pop and deal damage --------
      • Set RPaint_POP_DELAY = 2.00
      • Set RPaint_POP_DELAY_PER_LEVEL = 0.00
      • -------- --------
      • -------- special effect for puddle --------
      • Set RPaint_SFX_PUDDLE = PaintBombPuddle_Red.mdl
      • Set RPaint_SFX_PUDDLE_AP = origin
      • Set RPaint_SFX_PUDDLE_SIZE = 1.00
      • Set RPaint_SFX_PUDDLE_DEATH_TIMER = 0.25
      • -------- ^ how much time (in seconds) is needed for death sfx to play --------
      • -------- --------
      • -------- special effect for bubble --------
      • Set RPaint_SFX_BUBBLE = PaintBombBubble.mdl
      • Set RPaint_SFX_BUBBLE_AP = origin
      • Set RPaint_SFX_BUBBLE_START_SIZE = 1.00
      • Set RPaint_SFX_BUBBLE_FINAL_SIZE = 2.50
      • Set RPaint_SFX_BUBBLE_DEATH_TIMER = 1.00
      • -------- ^ how much time (in seconds) is needed for death sfx to play --------
      • -------- --------
      • -------- other --------
      • Set RPaint_ATTACK_TYPE = Spells
      • Set RPaint_DAMAGE_TYPE = Magic
      • Set RPaint_PERIODIC_TIMER = 0.03
      • -------- --------
      • -------- --------
      • -------- CONFIG END --------
      • -------- --------
      • Trigger - Add to RPaint_TRIGGER_LOOP the event (Time - Every RPaint_PERIODIC_TIMER seconds of game time)
      • -------- preload --------
      • Custom script: set udg_RPaint_TempUnit = GetRecycledDummyAnyAngle(0.00, 0.00, 0.00)
      • Special Effect - Create a special effect attached to the RPaint_SFX_PUDDLE_AP of RPaint_TempUnit using RPaint_SFX_PUDDLE
      • Special Effect - Destroy (Last created special effect)
      • Special Effect - Create a special effect attached to the RPaint_SFX_BUBBLE_AP of RPaint_TempUnit using RPaint_SFX_BUBBLE
      • Special Effect - Destroy (Last created special effect)
      • Custom script: call RecycleDummy(udg_RPaint_TempUnit)
      • -------- math calculations --------
      • Set RPaint_SFX_PUDDLE_SIZE = (RPaint_SFX_PUDDLE_SIZE x 100.00)
      • Set RPaint_SFX_BUBBLE_START_SIZE = (RPaint_SFX_BUBBLE_START_SIZE x 100.00)
      • Set RPaint_SFX_BUBBLE_FINAL_SIZE = (RPaint_SFX_BUBBLE_FINAL_SIZE x 100.00)
      • Set RPaint_BubbleSizeSfx = (RPaint_SFX_BUBBLE_FINAL_SIZE - RPaint_SFX_BUBBLE_START_SIZE)
  • RPaint Index
    • Events
    • Conditions
    • Actions
      • -------- PBomb Index Red --------
      • -------- this trigger will create a new instance for the Red Paint Mechanic --------
      • -------- --------
      • -------- members --------
      • -------- Caster[] - unit that will deal the damage when the paint bubble explodes --------
      • -------- Owner[] - player who owns Caster[] --------
      • -------- CurrentColor[] - the color the caster had selected when they threw the paint bomb --------
      • -------- CurrentSize[] - the current size of the bubble as it grows periodically --------
      • -------- Damage[] - damage dealt to nearby enemy units when the bubble explodes --------
      • -------- PuddleLoc[] - center of the explosion --------
      • -------- Radius[] - distance units must be from PuddleLoc[] to take damage --------
      • -------- PuddleUnit[] - dummy unit with the puddle special effect --------
      • -------- PuddleSfx[] - the special effect for the puddle left on the ground --------
      • -------- BubbleUnit[] - dummy unit with the bubble special effect --------
      • -------- BubbleSfx[] - the special effect for the bubble --------
      • -------- GrowRate[] - how fast BubbleUnit[] will change in size per iteration --------
      • -------- --------
      • -------- --------
      • Custom script: local real x
      • Custom script: local real y
      • -------- --------
      • Set RPaint_SpellCount = (RPaint_SpellCount + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RPaint_SpellCount Equal to 1
        • Then - Actions
          • Trigger - Turn on RPaint_TRIGGER_LOOP
        • Else - Actions
          • -------- do nothing --------
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RPaint_RecycledSize Equal to 0
        • Then - Actions
          • Set RPaint_MaxIndex = (RPaint_MaxIndex + 1)
          • Set RPaint_SpellId = RPaint_MaxIndex
        • Else - Actions
          • Set RPaint_RecycledSize = (RPaint_RecycledSize - 1)
          • Set RPaint_SpellId = RPaint_RecycledStack[RPaint_RecycledSize]
      • Set RPaint_NodeNext[RPaint_SpellId] = 0
      • Set RPaint_NodePrev[RPaint_SpellId] = RPaint_NodePrev[0]
      • Set RPaint_NodeNext[RPaint_NodePrev[0]] = RPaint_SpellId
      • Set RPaint_NodePrev[0] = RPaint_SpellId
      • -------- --------
      • Set RPaint_Caster[RPaint_SpellId] = PBomb_Caster[PBomb_SpellId]
      • Set RPaint_Owner[RPaint_SpellId] = PBomb_Owner[PBomb_SpellId]
      • Set RPaint_CurrentColor[RPaint_SpellId] = PBomb_CurrentColor[PBomb_SpellId]
      • Set RPaint_CurrentSize[RPaint_SpellId] = RPaint_SFX_BUBBLE_START_SIZE
      • -------- --------
      • Set RPaint_TempReal = (Real(PBomb_AbilityLvl[PBomb_SpellId]))
      • Set RPaint_Damage[RPaint_SpellId] = (RPaint_DAMAGE + (RPaint_DAMAGE_PER_LEVEL x RPaint_TempReal))
      • Set RPaint_Radius[RPaint_SpellId] = (RPaint_AOE + (RPaint_AOE_PER_LEVEL x RPaint_TempReal))
      • Set RPaint_GrowRate[RPaint_SpellId] = (RPaint_BubbleSizeSfx / ((RPaint_POP_DELAY + (RPaint_POP_DELAY_PER_LEVEL x RPaint_TempReal)) / RPaint_PERIODIC_TIMER))
      • -------- --------
      • Set RPaint_PuddleLoc[RPaint_SpellId] = (Position of PBomb_MissileUnit[PBomb_SpellId])
      • Custom script: set x = GetLocationX(udg_RPaint_PuddleLoc[udg_RPaint_SpellId])
      • Custom script: set y = GetLocationY(udg_RPaint_PuddleLoc[udg_RPaint_SpellId])
      • Custom script: set udg_RPaint_PuddleUnit[udg_RPaint_SpellId] = GetRecycledDummyAnyAngle(x, y, 0.00)
      • Animation - Change RPaint_PuddleUnit[RPaint_SpellId]'s size to (RPaint_SFX_PUDDLE_SIZE%, 100.00%, 100.00%) of its original size
      • Special Effect - Create a special effect attached to the RPaint_SFX_PUDDLE_AP of RPaint_PuddleUnit[RPaint_SpellId] using RPaint_SFX_PUDDLE
      • Set RPaint_PuddleSfx[RPaint_SpellId] = (Last created special effect)
      • -------- --------
      • Custom script: set udg_RPaint_BubbleUnit[udg_RPaint_SpellId] = GetRecycledDummyAnyAngle(x, y, 0.00)
      • Animation - Change RPaint_BubbleUnit[RPaint_SpellId]'s size to (RPaint_SFX_BUBBLE_START_SIZE%, 100.00%, 100.00%) of its original size
      • Special Effect - Create a special effect attached to the RPaint_SFX_BUBBLE_AP of RPaint_BubbleUnit[RPaint_SpellId] using RPaint_SFX_BUBBLE
      • Set RPaint_BubbleSfx[RPaint_SpellId] = (Last created special effect)
  • RPaint Loop
    • Events
    • Conditions
    • Actions
      • -------- RPaint Loop --------
      • -------- this trigger will periodically grow the bubble --------
      • -------- once the bubble reaches the max size, it will explode, and deal damage to nearby enemy units --------
      • -------- --------
      • -------- members --------
      • -------- Caster[] - unit that will deal the damage when the paint bubble explodes --------
      • -------- Owner[] - player who owns Caster[] --------
      • -------- CurrentColor[] - the color the caster had selected when they threw the paint bomb --------
      • -------- CurrentSize[] - the current size of the bubble as it grows periodically --------
      • -------- Damage[] - damage dealt to nearby enemy units when the bubble explodes --------
      • -------- PuddleLoc[] - center of the explosion --------
      • -------- Radius[] - distance units must be from PuddleLoc[] to take damage --------
      • -------- PuddleUnit[] - dummy unit with the puddle special effect --------
      • -------- PuddleSfx[] - the special effect for the puddle left on the ground --------
      • -------- BubbleUnit[] - dummy unit with the bubble special effect --------
      • -------- BubbleSfx[] - the special effect for the bubble --------
      • -------- GrowRate[] - how fast BubbleUnit[] will change in size per iteration --------
      • -------- --------
      • -------- --------
      • Set RPaint_SpellId = 0
      • For each (Integer RPaint_LoopInt) from 1 to RPaint_SpellCount, do (Actions)
        • Loop - Actions
          • Set RPaint_SpellId = RPaint_NodeNext[RPaint_SpellId]
          • -------- --------
          • -------- checking if the bubble has reached the max size --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • RPaint_CurrentSize[RPaint_SpellId] Greater than or equal to RPaint_SFX_BUBBLE_FINAL_SIZE
            • Then - Actions
              • -------- bubble has reached max size; damage nearby enemy units and deallocate --------
              • -------- --------
              • -------- using GroupEnumUnitsInRangeOfLoc because GetUnitsInRangeOfLoc has a reference handle leak --------
              • Custom script: call GroupEnumUnitsInRangeOfLoc(udg_PBomb_InRangeGroup, udg_RPaint_PuddleLoc[udg_RPaint_SpellId], udg_RPaint_Radius[udg_RPaint_SpellId], null)
              • Unit Group - Pick every unit in PBomb_InRangeGroup and do (Actions)
                • Loop - Actions
                  • Set RPaint_TempUnit = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (RPaint_TempUnit is A structure) Equal to False
                      • (RPaint_TempUnit is Magic Immune) Equal to False
                      • (RPaint_TempUnit is alive) Equal to True
                      • (RPaint_TempUnit belongs to an enemy of RPaint_Owner[RPaint_SpellId]) Equal to True
                    • Then - Actions
                      • Unit - Cause RPaint_Caster[RPaint_SpellId] to damage RPaint_TempUnit, dealing RPaint_Damage[RPaint_SpellId] damage of attack type RPaint_ATTACK_TYPE and damage type RPaint_DAMAGE_TYPE
                    • Else - Actions
                      • -------- do nothing --------
                  • Unit Group - Remove RPaint_TempUnit from PBomb_InRangeGroup
              • -------- --------
              • Custom script: set udg_SPaint_UnitId = GetHandleId(udg_RPaint_Caster[udg_RPaint_SpellId])
              • Hashtable - Save ((Load PBomb_KEY_ACTIVE_COUNT[RPaint_CurrentColor[RPaint_SpellId]] of SPaint_UnitId from PBomb_Hash) - 1) as PBomb_KEY_ACTIVE_COUNT[RPaint_CurrentColor[RPaint_SpellId]] of SPaint_UnitId in PBomb_Hash
              • -------- --------
              • Custom script: call RemoveLocation(udg_RPaint_PuddleLoc[udg_RPaint_SpellId])
              • Special Effect - Destroy RPaint_PuddleSfx[RPaint_SpellId]
              • Special Effect - Destroy RPaint_BubbleSfx[RPaint_SpellId]
              • Custom script: call DummyAddRecycleTimer(udg_RPaint_PuddleUnit[udg_RPaint_SpellId], udg_RPaint_SFX_PUDDLE_DEATH_TIMER)
              • Custom script: call DummyAddRecycleTimer(udg_RPaint_BubbleUnit[udg_RPaint_SpellId], udg_RPaint_SFX_BUBBLE_DEATH_TIMER)
              • Set RPaint_RecycledStack[RPaint_RecycledSize] = RPaint_SpellId
              • Set RPaint_RecycledSize = (RPaint_RecycledSize + 1)
              • Set RPaint_NodeNext[RPaint_NodePrev[RPaint_SpellId]] = RPaint_NodeNext[RPaint_SpellId]
              • Set RPaint_NodePrev[RPaint_NodeNext[RPaint_SpellId]] = RPaint_NodePrev[RPaint_SpellId]
              • -------- --------
              • Set RPaint_SpellCount = (RPaint_SpellCount - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • RPaint_SpellCount Equal to 0
                • Then - Actions
                  • Trigger - Turn off RPaint_TRIGGER_LOOP
                • Else - Actions
                  • -------- do nothing --------
            • Else - Actions
              • -------- bubble has not reached max size; continue to grow --------
              • Set RPaint_CurrentSize[RPaint_SpellId] = (RPaint_CurrentSize[RPaint_SpellId] + RPaint_GrowRate[RPaint_SpellId])
              • Animation - Change RPaint_BubbleUnit[RPaint_SpellId]'s size to (RPaint_CurrentSize[RPaint_SpellId]%, 100.00%, 100.00%) of its original size
 
Last edited:
Is it okay to use lua script? I kind of went out of my way and also created one for the spell.

JASS:
//! externalblock extension=lua ObjectMerger $FILENAME$
        //! i ID = "e002"
      
        //! i ATTACK_SPEED = 1.0
        //! i MOVE_SPEED = 500
        //! i NAME = "Fel Spiderling"
      
        //! i function declare_spider(atkSpeed, mvSpeed, paramName)
        //! i setobjecttype("units")
          
        //! i createobject("nspd", ID)

        //! i makechange(current, "uico", "ReplaceableTextures\CommandButtons\BTNSpiderBlack.blp")
        //! i makechange(current, "umdl", "units\creeps\SpiderBlack\SpiderBlack.mdl")
         
        //! i makechange(current, "usca", 0.4)
        //! i makechange(current, "ussc", 0.9)
         
        //! i makechange(current, "ushx", 15)
        //! i makechange(current, "ushy", 15)
        //! i makechange(current, "ushh", 40)
        //! i makechange(current, "ushw", 40)
       
        //! i makechange(current, "ua1t", "chaos")
        //! i makechange(current, "ua1c", math.min(math.max(atkSpeed, 0.1), 5.0))
        //! i makechange(current, "ua1b", 0)
        //! i makechange(current, "ua1s", 1)
        //! i makechange(current, "ua1d", 1)
        //! i makechange(current, "ua1r", 90)
       
        //! i makechange(current, "umvs", math.min(mvSpeed, 522))
        //! i makechange(current, "umas", math.min(mvSpeed, 522))
        //! i makechange(current, "umis", math.min(mvSpeed - 1, 100))
       
        //! i makechange(current, "uhpm", 250)
        //! i makechange(current, "urac", "undead")
       
        //! i makechange(current, "unam", paramName)
        //! i makechange(current, "utip", "Summon " .. paramName)
        //! i makechange(current, "utub", "Light melee unit. Deals damage based on attribute. |n|n|cffffcc00Attacks land units.|r")
    //! i end
      
    //! i declare_spider(ATTACK_SPEED, MOVE_SPEED, NAME)
//! endexternalblock

Also, this is the final code WIP before submission.

JASS:
library OvermindSpellThree initializer Init requires /*

    *   ----------------------
    */  AllocationAndLinks, /*  https://www.hiveworkshop.com/threads/allocation-and-links.293621/
    *   ----------------------
    *
    *       -   Contains the doubly linked list and custom allocation which is preferred by the coder.
    *       -   If you don't want extends array syntax, just change AllocLinkBundle to DoubleLink
    *           
    *   ----------------------
    */  TimerUtils,         /*  http://www.wc3c.net/showthread.php?t=101322 
    *   ----------------------
    *
    *       -   Too lazy to create a timer library that allows attachment of data,
    *           but not too lazy to completely rewrite it.
    *
    *   ----------------------------
    */  CustomFunctions,          /*
    *   ----------------------------
    *
    *       -   Allows a nice not-red debug setting, and allows the instant generation of a search function.
    *           Technically not useless.
    *
    *   --------------------------------
    */  DamageEvent,   DamageModify,  /*    https://www.hiveworkshop.com/threads/damagepackage.287101/
    *   --------------------------------
    *
    *       -   Allows the manipulation of damage
    *       -   DamageModify is the takeaway here. (Modifies the damage dealt by the spiderlings).
    *
    *   --------------------------------
    */  optional TextTag              /*    https://www.hiveworkshop.com/threads/library-text-tag.290924/page-2#post-3138916
    *   --------------------------------
    *       -   Optionally displays the amount restored to the hive creator.
    *       -   Can be used informationally.
    *
    */
   
    /* 
    *   __________________________
    *       
    *       OvermindSpellThree
    *   __________________________
    *
    *       ______________
    *       
    *          The Hive
    *       ______________
    *
    *           -   A spell based on Pocket Factory that plants a targeted location with a hive mind.
    *           -   This spell is active, and has a sub-spell component, namely Ravage Hive.
    *
    *       __________________
    *                       
    *          How it goes 
    *       __________________
    *
    *           -   The spell is cast, triggering a spell-effect trigger and creating an associated
    *               struct instance of type Data.
    *
    *           -   The Data struct instance then activates a timer, which is set to expire based on
    *               the speed of the missile created by the ability and the distance therefrom.
    *
    *           -   After expiration, the hive is created with a delay in its' timed life. During this
    *               time, the hive is rendered invulnerable.
    *
    *           -   After the delay, the expiration timer for the hive is started. The hive may or may
    *               not be harmed based on the data flag section.
    *
    *           -   If it dies, its' expiration timer expires, or a Ravage Hive sub-spell has taken effect,
    *               the hive will execute its' death-related event. This may bug out with certain scripts,
    *               which remove units on death.
    *
    *       ____________
    *       
    *           API
    *       ____________
    *
    *           native functions:
    *               -   UnitAlive(unit id) returns boolean
    *
    *           external functions:
    *               -   external func:
    *                       exe:    ObjectMerger.exe
    *                       type:   w3u / units
    *                       base id:    'hfoo'  /   footman
    *                       new id:     '!000'  /   footman derivative.
    *                       
    *                       model:  "dummy.mdx"
    *
    *           globals:
    *               private constant group ENUM_GROUP
    *                   -   Enumerator group
    *               private unit enum_unit
    *                   -   Enumerator unit variable.
    *
    *           configurable functions:
    *               function SPELL_ID() returns integer
    *                   -   Returns the raw code of the spell. (See in Object Editor (Ctrl + D))
    *               function RAW_ID(int i) returns integer
    *                   -   Returns some raw code based on request. (Defaults to 0)
    *               function DATA(int i, int lev) returns real
    *                   -   Returns the necessary soft-coded data field. (Defaults to 0)
    *
    *       External scripts:
    *           -   Used mostly for the generation of the spiderling with the added speed properties.
    *               Can be modified to a certain extent by script.
    *
    */
       
    native UnitAlive takes unit id returns boolean
   
   
    /*  The following scripts are external lua scripts which generate the necessary unit data.
    *   Since I wanted to make this configurable (to a certain extent), the script for declaring
    *   a spider is given below.
    *   
    *   This line of code has been deemed redundant due to the pathing script being removed.
    *   ___________________________________________________________
    *
    *   ///! external ObjectMerger w3u hfoo "!000" umdl "dummy.mdx"
    *   ___________________________________________________________
    *
    *   The code below may be commented out by adding a delimited comment.
    *   Delimited comments look like this:
    *
    *   /*
    *       Put some stuff here.
    *   */
    *
    *   To enable the script again, just remove the delimiters.
    *
    *   ___________
    *
    *       API
    *   ___________
    *
    *       ID = "char"
    *           -   The rawcode of the spider.
    *
    *       ATTACK_SPEED = float r
    *           -   The attack speed defined as a float.
    *       MOVE_SPEED = float r
    *           -   The movement speed of the spider defined as an integer.
    *       NAME = string nam
    *           -   The name of the spider. If you like, you can change it.
    *
    *       function declare_spider(real atkSpeed, int mvSpeed, string paramName)
    *           - Due to the lack of explicit type definition, the type of the parameters have been
    *             supplied for you.
    *
    *           - Generates a spider with a certain raw id based on the ID variable (string)
    *           - The only configurable parts are the attack speed, move speed and name
    *             Even then, the attack speed is capped off at 5.0 and 0.1.
    *
    *           - Will cause the Typecasting library to fail if the external script is not delimited.
    */
   
    /*
    //! externalblock extension=lua ObjectMerger $FILENAME$
        //! i ID = "e002"
       
        //! i ATTACK_SPEED = 1.0
        //! i MOVE_SPEED = 500
        //! i NAME = "Fel Spiderling"
       
        //! i function declare_spider(atkSpeed, mvSpeed, paramName)
            //! i setobjecttype("units")
           
            //! i createobject("nspd", ID)
           
            //! i makechange(current, "uico", "ReplaceableTextures\\CommandButtons\\BTNSpiderBlack.blp")
            //! i makechange(current, "umdl", "units\\creeps\\SpiderBlack\\SpiderBlack.mdl")
           
            //! i makechange(current, "usca", 0.4)
            //! i makechange(current, "ussc", 0.9)
           
            //! i makechange(current, "ushx", 15)
            //! i makechange(current, "ushy", 15)
            //! i makechange(current, "ushh", 40)
            //! i makechange(current, "ushw", 40)
           
            //! i makechange(current, "ua1t", "chaos")
            //! i makechange(current, "ua1c", math.min(math.max(atkSpeed, 0.1), 5.0))
            //! i makechange(current, "ua1b", 0)
            //! i makechange(current, "ua1s", 1)
            //! i makechange(current, "ua1d", 1)
            //! i makechange(current, "ua1r", 90)
           
            //! i makechange(current, "umvs", math.min(mvSpeed, 522))
            //! i makechange(current, "umas", math.min(mvSpeed, 522))
            //! i makechange(current, "umis", math.min(mvSpeed - 1, 100))
           
            //! i makechange(current, "uhpm", 250)
            //! i makechange(current, "urac", "undead")
           
            //! i makechange(current, "unam", paramName)
            //! i makechange(current, "utip", "Summon " .. paramName)
            //! i makechange(current, "utub", "Light melee unit. Deals damage based on attribute. |n|n|cffffcc00Attacks land units.|r")
        //! i end
       
        //! i declare_spider(ATTACK_SPEED, MOVE_SPEED, NAME)
    //! endexternalblock
    */
   
    globals
        private constant group ENUM_GROUP = CreateGroup()
        private unit enum_unit = null
    endglobals
   
    private constant function SPELL_ID takes nothing returns integer
        return 'A002'
    endfunction
   
    private constant function RAW_ID takes integer request returns integer
        if request == 0 then
            //  Returns the ID of the hatchery.
            return 'e001'
        elseif request == 1 then
            //  Returns the ID of the fel spiderlings
            return 'e002'
        elseif request == 2 then
            //  Returns the ID of the sub-spell
            return '1001'
        endif
        return 0
    endfunction
   
    private constant function DATA takes integer request, integer level returns real
        if request == 0 then
            //  Returns the duration of the hive
            if level == 1 then
                return 50.
            elseif level == 2 then
                return 75.
            elseif level == 3 then
                return 100.
            endif
        elseif request == 1 then
            //  Returns the effective detection range.
            if level == 1 then
                return 150.
            elseif level == 2 then
                return 250.
            elseif level == 3 then
                return 350.
            endif
        elseif request == 2 then
            //  Returns the tick rate.
            //  Defaults to 1.
            return 1.
        elseif request == 3 then
            //  Returns the amount of mana burned around the hive
            if level == 1 then
                return 5.
            elseif level == 2 then
                return 7.
            elseif level == 3 then
                return 10.
            endif
        elseif request == 4 then
            //  Returns the amount of health rejuvenated by ratio.
            //  Only takes effect when used as a nydus canal.
            if level == 1 then
                return 0.1
            elseif level == 2 then
                return 0.12
            elseif level == 3 then
                return 0.16
            endif
        elseif request == 5 then
            //  Returns the range field for allowing mana burn
            //  Defaults to 500.
            return 500.
        elseif request == 6 then
            //  Returns the flag for allowing the hive to be invulnerable.
            //  Defaults to true (not equal to 0.)
            return 0.
        elseif request == 7 then
            //  Returns the damage dealt when hive (simulating death or actually dying)
            if level == 1 then
                return 85.
            elseif level == 2 then
                return 150.
            elseif level == 3 then
                return 220.
            endif
        elseif request == 8 then
            //  Returns the amount of spiders that will spawn.
            if level == 1 then
                return 4.
            elseif level == 2 then
                return 5.
            elseif level == 3 then
                return 6.
            endif
        elseif request == 9 then
            //  Returns the speed of the missile
            //  Must correspond to the object data equivalent.
            return 1000.
        elseif request == 10 then
            //  Returns the frequency of the global timer
            //  Cannot be configured to the level of the unit
            return 1/32.
        elseif request == 11 then
            //  Returns the fade-in total duration.
            //  Cannot be configured to the level of the unit
            return 2.5
        elseif request == 12 then
            //  Returns the duration of the death animation
            //  Cannot be configured to the level of the unit
            return 5.
        elseif request == 13 then
            //  Returns the main attribute to follow
            //  Higher values will return modulo of 3.
            //  Strength: 1
            //  Agility: 2
            //  Intelligence: 3
            return 3.
        elseif request == 14 then
            //  Returns damage dealt based on percentage
            if level == 1 then
                return 0.1
            elseif level == 2 then
                return 0.14
            elseif level == 3 then
                return 0.18
            endif
        elseif request == 15 then
            //  Returns the amount of mana rejuvenated by ratio.
            //  Only takes effect when used as a nydus canal.
            if level == 1 then
                return 0.12
            elseif level == 2 then
                return 0.16
            elseif level == 3 then
                return 0.2
            endif
        endif
        return 0.
    endfunction
   
    /*  Generated boolean comparison (inlined) */
    globals
        private constant boolean REG_11_BOOL = 2.5 <= 0.
    endglobals
   
    /*  The strings which will be used for projecting certain effects and such */
    private constant function MDL_FILE takes integer request returns string
        if request == 0 then
            return "Abilities\\Weapons\\ChimaeraAcidMissile\\ChimaeraAcidMissile.mdl"
        elseif request == 1 then
            return "Abilities\\Spells\\NightElf\\ManaBurn\\ManaBurnTarget.mdl"
        elseif request == 2 then
            return "Abilities\\Weapons\\snapMissile\\snapMissile.mdl"
        elseif request == 3 then
            return "Units\\NightElf\\Wisp\\WispExplode.mdl"
        endif
        return ""
    endfunction
   
    private function real_GetDist takes real x1, real y1, real x2, real y2 returns real
        return SquareRoot((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2))
    endfunction
   
    private function echo takes string s returns nothing
        static if DEBUG_MODE then
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 16, s)
        endif
    endfunction
    //  Generates a module with the name DoubleLink_local. It has the property of a private module.
    //  Same with the next textmacro. A private module DoubleLink_active is generated.
    //! runtextmacro link_module("local", "private")
    //! runtextmacro link_module("active", "private")
   
    private struct Data extends array
        implement AllocLinkBundle
        implement DoubleLink_local
        implement DoubleLink_active
       
        private static constant timer ACTIVE_TIMER = CreateTimer()
        private static constant group STORED_SPIDERS = CreateGroup()
       
        //  Assistant to the stored spider group
        private static integer stored_spider_count = 0
       
        //  Counter for a forGroupEx call
        private static integer spider_group_count = 0
       
        //  Mode checker
        private integer mode
        private real mode_data
       
        /*  Part One
        *       -   This will store the unit, level, timer, target x, and target y for
        *           the successful creation of the hive. */
       
        private unit unit
        private unit hive
       
        private integer level
       
        private timer timer
       
        private real tx
        private real ty
       
        //  Part Two
        /*      -   This will be the main part of the spell, the mechanics of which will
        *           be the main focus and intention of this spell. */
       
        //  For speed purposes
        private static player feedback_player
        private static thistype hive_this
        private static thistype spider_this
       
        private real stored
        private integer eventtype
       
        private unit target
        private trigger detector
       
        private group spider_group
       
        /*
            These textmacros can be found at CustomFunctions. It's easy to port them to this library, though.
            They generate a searching algorithm for finding a certain instance.
           
            If not fully explained, the parameters are defined as follows:
                search_list(encapsulation-keyword, name, searched type, iterator variable, conditional statement)
        */
       
        //! runtextmacro search_list("private", "get", "unit", "next", "unit == id")
        //! runtextmacro search_list("private", "get_hive", "unit", "active_next", "hive == id")
        //! runtextmacro search_list("private", "get_targ", "unit", "active_next", "target == id")
        //! runtextmacro search_list("private", "get_trig", "trigger", "active_next", "detector == id")
        //! runtextmacro search_list("private", "get_group", "unit", "active_next", "IsUnitInGroup(id, spider_group)")
       
        //  Detaches a certain instance from a global list if it is found and in the local list.
        //  Pushes the next local instance to the global list if there exists at least one more.
        private method detach takes nothing returns nothing
            if head != 0 then
                if local_next != this then
                    set local_next.head = 1
                   
                    call local_next.insert(next)
                endif
                set head = 0
                call pop()
            endif
            call local_pop()
        endmethod
       
        /*  Mimics death for the spiders    */
        private static method spider_preDestroy_enum takes nothing returns nothing
            set enum_unit = GetEnumUnit()
           
            call PauseUnit(enum_unit, true)
            call SetUnitAnimation(enum_unit, "death")
        endmethod
       
        private method spider_preDestroy takes nothing returns nothing
            call ForGroup(spider_group, function thistype.spider_preDestroy_enum)
           
            set enum_unit = null
        endmethod
       
        /*  Resets the animation for the next group */
        private static method spider_onDestroy_enum takes nothing returns nothing
            set enum_unit = GetEnumUnit()
           
            call QueueUnitAnimation(enum_unit, "stand")
            call SetUnitX(enum_unit, 0)
            call SetUnitY(enum_unit, 0)
           
            call SetUnitOwner(enum_unit, Player(15), true)
            call ShowUnit(enum_unit, false)
        endmethod
       
        private method spider_onDestroy takes nothing returns nothing
            call ForGroup(spider_group, function thistype.spider_onDestroy_enum)
           
            set enum_unit = null
        endmethod
       
        /*  Check if the hive is still alive. If not, attempt to nullify hive and prepare a new one.    */
        private method preDestroy takes nothing returns nothing
            if not UnitAlive(hive) then
                call RemoveUnit(hive)
                set hive = null
            else
                call PauseUnit(hive, true)
                call ShowUnit(hive, false)
               
                call SetUnitX(hive, 0)
                call SetUnitY(hive, 0)
               
                call SetWidgetLife(hive, GetUnitState(hive, UNIT_STATE_MAX_LIFE))
                call SetUnitOwner(hive, Player(15), false)
               
                if not (DATA(6, level) != 0) then
                    call echo("Unit is vulnerable")
                    call UnitRemoveAbility(hive, 'Aloc')
                debug else
                    call echo("Unit is invulnerable")
                endif
            endif
        endmethod
       
        private method destroy takes nothing returns nothing
            call spider_onDestroy()
            call preDestroy()
            call ReleaseTimer(timer)
           
            call DestroyTrigger(detector)
           
            set unit = null
            set target = null
           
            set timer = null
            set detector = null
           
            set tx = 0.
            set ty = 0.
            set mode_data = 0.
            set stored = 0.
           
            set head = 0
            set mode = 0
            set eventtype = 0
           
            call active_pop()
           
            set active_head = 0
            set thistype(0).active_head = thistype(0).active_head - 1
           
            call deallocate()
        endmethod
       
        //  Part two
        private static method target_attack_enum takes nothing returns nothing
            local thistype this = spider_this
            set enum_unit = GetEnumUnit()
           
            if target != null then
                if GetUnitTypeId(target) != 0 or UnitAlive(target) then
                    call IssueTargetOrder(enum_unit, "attack", target)
                else
                    call IssuePointOrder(enum_unit, "move", GetUnitX(hive) + GetRandomReal(-DATA(1, level), DATA(1, level)), GetUnitY(spider_this.hive) + GetRandomReal(-DATA(1, level), DATA(1, level)))
                endif
            else
                call IssuePointOrder(enum_unit, "move", GetUnitX(hive) + GetRandomReal(-DATA(1, level), DATA(1, level)), GetUnitY(hive) + GetRandomReal(-DATA(1, level), DATA(1, level)))
            endif
        endmethod
       
        private method target_attack takes nothing returns nothing
            set spider_this = this
           
            call ForGroup(spider_group, function thistype.target_attack_enum)
               
            set spider_this = 0
        endmethod
       
        private method target_search takes nothing returns nothing
            set feedback_player = GetOwningPlayer(hive)
           
            call GroupEnumUnitsInRange(ENUM_GROUP, GetUnitX(hive), GetUnitY(hive), DATA(1, level), null)
            call GroupRemoveUnit(ENUM_GROUP, target)
            loop
                set enum_unit = FirstOfGroup(ENUM_GROUP)
                exitwhen enum_unit == null
               
                if UnitAlive(enum_unit) and IsUnitEnemy(enum_unit, feedback_player) and UnitDamageTarget(enum_unit, enum_unit, 0, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null) then
                    set target = enum_unit
                   
                    exitwhen true
                endif
               
                call GroupRemoveUnit(ENUM_GROUP, enum_unit)
            endloop
            if enum_unit == null then
                set target = null
                call echo("No valid target found")
            else
                call echo("Target was discovered: " + GetUnitName(target))
            endif
        endmethod
       
        private static method target_onDeathEvent takes nothing returns nothing
            local thistype this = get_targ(GetTriggerUnit())
           
            if this != 0 then
                call target_search()
                call target_attack()
            endif
        endmethod
       
        private static method hive_onDeathProxy takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            call destroy()
        endmethod
       
        private static method hive_onErupt takes nothing returns nothing
            local thistype this = hive_this
            set hive_this = 0
           
            set feedback_player = GetOwningPlayer(hive)
            call GroupEnumUnitsInRange(ENUM_GROUP, GetUnitX(hive), GetUnitY(hive), DATA(5, level), null)
            loop
                set enum_unit = FirstOfGroup(ENUM_GROUP)
                exitwhen enum_unit == null
               
                if UnitAlive(enum_unit) and IsUnitEnemy(enum_unit, feedback_player) then
                    if UnitDamageTarget(hive, enum_unit, DATA(7, level), true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_UNIVERSAL, null) then
                        call DestroyEffect(AddSpecialEffectTarget(MDL_FILE(1), enum_unit, "chest"))
                    endif
                endif
                call GroupRemoveUnit(ENUM_GROUP, enum_unit)
            endloop
        endmethod
       
        private method hive_onDeath takes nothing returns nothing
            call PauseTimer(timer)
            call TimerStart(timer, DATA(12, 0), false, function thistype.hive_onDeathProxy)
           
            set mode = 3
           
            if eventtype != 1 then
                call SetUnitAnimation(hive, "death")
            endif
           
            if local_next == this then
                call echo("Last reserved instance!")
                call UnitRemoveAbility(unit, RAW_ID(2))
            debug else
                call echo("Current instance: " + I2S(this))
                call echo("Next instance: " + I2S(local_next) + "\n")
                call echo("There are some instances left!")
            endif
           
            call detach()
           
            set hive_this = this
            call ForForce(bj_FORCE_PLAYER[0], function thistype.hive_onErupt)
            call spider_preDestroy()
        endmethod
       
        private method overmind_onTeleport takes nothing returns nothing
            local real rx = GetUnitX(unit)
            local real ry = GetUnitX(unit)
           
            local player p = GetOwningPlayer(unit)
           
            if this == 0 then
                call echo("thistype.overmind_onTeleport: Invalid instance!")
                return
            endif
           
            call SetWidgetLife(unit, GetWidgetLife(unit) + stored*DATA(4, level))
            call SetUnitState(unit, UNIT_STATE_MANA, GetUnitState(unit, UNIT_STATE_MANA) + stored*DATA(15, level))
           
            static if LIBRARY_TextTag then
                call CreateTextTagBJ(p, rx, ry, 75, 0, 255, 255, "+" + I2S(R2I(stored*(DATA(4, level)))) + " health!\n+" + I2S(R2I(stored*(DATA(15, level)))) + " mana!")
                set vj_lastCreatedTextTag.duration = 3.0
                set vj_lastCreatedTextTag.fade = 2.25
            endif
           
            //  For boolean consistency
            set eventtype = 3
            if not (DATA(6, level) != 0) then
                call echo("Removing timed life buffs")
                call UnitRemoveBuffsEx(hive, true, true, false, false, true, false, false)               
            endif
           
            call DestroyEffect(AddSpecialEffect(MDL_FILE(3), rx, ry))
            call DestroyEffect(AddSpecialEffect(MDL_FILE(0), rx, ry))
           
            call SetUnitX(unit, GetUnitX(hive))
            call SetUnitY(unit, GetUnitX(hive))
       
            //  Unimportant to deallocate players (hear-say)
        endmethod
       
        private static method hive_onDeathEvent takes nothing returns nothing
            local thistype this = get_hive(GetTriggerUnit())
           
            if this != 0 then
                if eventtype == 0 then
                    set eventtype = 1
                endif
                call hive_onDeath()
            endif
        endmethod
       
        private static method hive_onFeedback_loop takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
           
            set mode_data = mode_data - DATA(2, level)
           
            if mode_data > 0. then
                call target_attack()
               
                set feedback_player = GetOwningPlayer(hive)
                call GroupEnumUnitsInRange(ENUM_GROUP, GetUnitX(hive), GetUnitY(hive), DATA(5, level), null)               
                loop
                    set enum_unit = FirstOfGroup(ENUM_GROUP)
                    exitwhen enum_unit == null
                   
                    if UnitAlive(enum_unit) and IsUnitEnemy(enum_unit, feedback_player) then
                        if GetUnitState(enum_unit, UNIT_STATE_MAX_MANA) != 0 then
                            call DestroyEffect(AddSpecialEffectTarget(MDL_FILE(1), enum_unit, "chest"))
                           
                            call SetUnitState(enum_unit, UNIT_STATE_MANA, GetUnitState(enum_unit, UNIT_STATE_MANA) - DATA(3, level))
                            call UnitDamageTarget(hive, enum_unit, DATA(3, level), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null)
                           
                            set stored = stored + DATA(3, level)
                        endif
                    endif
                   
                    call GroupRemoveUnit(ENUM_GROUP, enum_unit)
                endloop
            else
                set eventtype = 2
                call hive_onDeath()
            endif
        endmethod
       
        private static method hive_onDetectEnemy takes nothing returns nothing
            local thistype this = get_trig(GetTriggeringTrigger())
           
            if IsUnitEnemy(GetTriggerUnit(), GetOwningPlayer(hive)) then
                if target == null then
                    set target = GetTriggerUnit()
                    call target_attack()
                endif
            endif
        endmethod
       
        private static method spider_forGroupEx_enum takes nothing returns nothing
            local thistype this = spider_this
           
            set enum_unit = GetEnumUnit()
            set spider_group_count = spider_group_count + 1
           
            call SetUnitOwner(enum_unit, feedback_player, true)
            call SetUnitPosition(enum_unit, tx, ty)
            call SetUnitFacing(enum_unit, GetRandomReal(0, 360))
                   
            call PauseUnit(enum_unit, false)
            call ShowUnit(enum_unit, true)
                   
            call UnitRemoveAbility(enum_unit, 'Aloc')
            call UnitAddAbility(enum_unit, 'Aloc')
        endmethod
       
        private method spider_forGroupEx takes nothing returns integer
            set spider_this = this
            set spider_group_count = 0
           
            call ForGroup(spider_group, function thistype.spider_forGroupEx_enum)
           
            set enum_unit = null
            return spider_group_count
        endmethod
       
        private method hive_spider_init takes nothing returns nothing
            local integer int = R2I(DATA(8, level))
           
            set feedback_player = GetOwningPlayer(unit)
            if spider_group == null then
                set spider_group = CreateGroup()
            endif
           
            set int = int - spider_forGroupEx()
           
            if int < 0 then
                loop
                    set enum_unit = FirstOfGroup(spider_group)
                    exitwhen int >= 0
                   
                    call SetUnitOwner(enum_unit, Player(15), true)
                    call SetUnitX(enum_unit, 0)
                    call SetUnitY(enum_unit, 0)
                   
                    call PauseUnit(enum_unit, true)
                    call ShowUnit(enum_unit, false)
                   
                    call UnitRemoveAbility(enum_unit, 'Aloc')
                    call UnitAddAbility(enum_unit, 'Aloc')
                   
                    call GroupRemoveUnit(spider_group, enum_unit)
                    call GroupAddUnit(STORED_SPIDERS, enum_unit)
                   
                    set stored_spider_count = stored_spider_count + 1
                    set int = int + 1
                endloop
            else
                //  We check if there are any free spiders in the group.
                loop
                    set enum_unit = FirstOfGroup(STORED_SPIDERS)
                    exitwhen enum_unit == null or int <= 0 or stored_spider_count <= 0
                   
                    call SetUnitOwner(enum_unit, feedback_player, true)
                    call SetUnitPosition(enum_unit, tx, ty)
                    call SetUnitFacing(enum_unit, GetRandomReal(0, 360))
                   
                    call PauseUnit(enum_unit, false)
                    call ShowUnit(enum_unit, true)
                   
                    call UnitRemoveAbility(enum_unit, 'Aloc')
                    call UnitAddAbility(enum_unit, 'Aloc')
                   
                    call GroupRemoveUnit(STORED_SPIDERS, enum_unit)
                    call GroupAddUnit(spider_group, enum_unit)
                   
                    set stored_spider_count = stored_spider_count - 1
                    set int = int - 1
                endloop
               
                //  If there are none, proceed to the next loop
                loop
                    exitwhen int <= 0
                   
                    set bj_lastCreatedUnit = CreateUnit(feedback_player, RAW_ID(1), tx, ty, GetRandomReal(0, 360))
                   
                    call SetUnitAcquireRange(bj_lastCreatedUnit, DATA(1, level))
                    call UnitAddAbility(bj_lastCreatedUnit, 'Aloc')
                    call Damage.add(bj_lastCreatedUnit)
                   
                    call GroupAddUnit(spider_group, bj_lastCreatedUnit)
                    set int = int - 1
                endloop
            endif
           
            call echo("Number of spiders: " + I2S(CountUnitsInGroup(spider_group)))
        endmethod
       
        private method hive_addDetection takes nothing returns nothing
            set detector = CreateTrigger()
           
            call TriggerRegisterUnitInRange(detector, hive, DATA(1, level), null)
            call TriggerAddCondition(detector, function thistype.hive_onDetectEnemy)
        endmethod
       
        private method hive_addFeedback takes nothing returns nothing
            if not (DATA(6, level) != 0) then
                call SetUnitInvulnerable(hive, false)
                call UnitApplyTimedLife(hive, 'BTLF', mode_data)
                call UnitPauseTimedLife(hive, false)
            endif
           
            call hive_addDetection()
            call hive_spider_init()
            call TimerStart(timer, DATA(2, level), true, function thistype.hive_onFeedback_loop)
        endmethod
       
        private static method hive_runList takes nothing returns nothing
            local thistype this = thistype(0).active_next
           
            if thistype(0).active_head == 0 then
                call PauseTimer(ACTIVE_TIMER)
                return
            endif
           
            loop
                exitwhen this == 0
                if mode == 1 then
                    call DestroyEffect(AddSpecialEffect(MDL_FILE(0), GetUnitX(hive), GetUnitY(hive)))
                   
                    static if REG_11_BOOL then
                        call SetUnitVertexColor(hive, 255, 255, 255, 255)
                       
                        set mode = 2
                        call hive_addFeedback()
                    else
                        set mode_data = mode_data + (255)*DATA(10, 0)/DATA(11, 0)
                       
                        if mode_data >= 255 then
                            call SetUnitVertexColor(hive, 255, 255, 255, 255)
                           
                            set mode = 2
                            set mode_data = DATA(0, level)
                           
                            call hive_addFeedback()
                        else
                            call SetUnitVertexColor(hive, 255, 255, 255, R2I(mode_data))
                        endif
                    endif
                endif
               
                set this = active_next
            endloop
        endmethod
       
        private static method hive_spider_onDamage takes nothing returns nothing
            local thistype this = get_group(Damage.source)
            local real mode = ModuloReal(mode, 3.)
           
            if mode == 0 then
                set mode = 3
            endif
           
            if this != 0 then
                if mode == 1 then
                    set Damage.amount = DATA(14, level)*GetHeroStr(unit, true)
                elseif mode == 2 then
                    set Damage.amount = DATA(14, level)*GetHeroAgi(unit, true)
                elseif mode == 3 then
                    set Damage.amount = DATA(14, level)*GetHeroInt(unit, true)
                endif
            endif
        endmethod
       
        //  Part one
        private static method hive_bufferAdd takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
           
            call UnitAddAbility(hive, 'Aloc')
            call ReleaseTimer(GetExpiredTimer())
        endmethod
       
        private method hive_create takes nothing returns nothing
            if hive == null then
                set hive = CreateUnit(GetOwningPlayer(unit), RAW_ID(0), tx, ty, 0)
               
                set mode = 1
               
                call SetUnitVertexColor(hive, 255, 255, 255, 0)
               
                if DATA(6, level) != 0 then
                    call TimerStart(NewTimerEx(this), 0., false, function thistype.hive_bufferAdd)
                else
                    call SetUnitInvulnerable(hive, true)
                endif
            else
                call SetUnitAnimation(hive, "stand")
                call QueueUnitAnimation(hive, "stand")
                call SetUnitInvulnerable(hive, false)
               
                call SetUnitOwner(hive, GetOwningPlayer(unit), true)
                call SetUnitPosition(hive, tx, ty)
               
                call PauseUnit(hive, false)
                call ShowUnit(hive, true)
               
                if DATA(6, level) != 0 then
                    call UnitRemoveAbility(hive, 'Aloc')
                    call UnitAddAbility(hive, 'Aloc')
                endif
               
                set mode = 1
           
                call SetUnitVertexColor(hive, 255, 255, 255, 0)
            endif
           
            if GetLocalPlayer() == GetOwningPlayer(unit) then
                call SelectUnit(hive, true)
                call SelectUnit(hive, false)
            endif
           
            call active_push()
            set active_head = 1
           
            if thistype(0).active_head == 0 then
                call TimerStart(ACTIVE_TIMER, DATA(10, 0), true, function thistype.hive_runList)
            endif
           
            set thistype(0).active_head = thistype(0).active_head + 1
        endmethod
       
        private static method prepare_hive_flag takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
           
            call hive_create()
        endmethod
       
        private method prepare_hive takes nothing returns nothing
            set timer = NewTimerEx(this)
            call TimerStart(timer, real_GetDist(GetUnitX(unit), GetUnitY(unit), GetSpellTargetX(), GetSpellTargetY())/DATA(9, 0), false, function thistype.prepare_hive_flag)
        endmethod
       
        static method create takes unit u returns thistype
            local thistype this = get(u)
            local thistype that
           
            if this == 0 then
                set this = allocate()
                set unit = u
               
                set level = GetUnitAbilityLevel(u, SPELL_ID())
                set head = 1
               
                call UnitAddAbility(u, RAW_ID(2))
                call UnitMakeAbilityPermanent(u, true, RAW_ID(2))
               
                call push()
                call local_insert(this)
               
                set tx = GetSpellTargetX()
                set ty = GetSpellTargetY()
               
                call prepare_hive()
                return this
            endif
            set that = allocate()
            set that.unit = unit
           
            set that.level = GetUnitAbilityLevel(unit, SPELL_ID())
            call that.local_insert(this)
           
            set that.tx = GetSpellTargetX()
            set that.ty = GetSpellTargetY()
           
            call UnitAddAbility(u, RAW_ID(2))
            call UnitMakeAbilityPermanent(u, true, RAW_ID(2))
               
            call that.prepare_hive()
            return that
        endmethod
   
        static method teleport takes unit u, real x, real y returns nothing
            local thistype this = get(u)
            local thistype head = this
            local thistype nearest = head
           
            if this == 0 then
                call echo("thistype.teleport: Instance of unit does not exist.")
                call echo("thistype.teleport: Returning")
                return
            endif
                       
            set this = local_next
            loop
                exitwhen this == head
               
                if (real_GetDist(x, y, GetUnitX(hive), GetUnitY(hive)) <= real_GetDist(x, y, GetUnitX(nearest.hive), GetUnitY(nearest.hive))) and mode == 2 then
                    set nearest = this
                endif
               
                set this = local_next
            endloop
           
            if nearest.mode != 2 then
                call DisplayTextToPlayer(GetOwningPlayer(u), 0, 0, "|cffffcc00The hives are not available.|r")
            else
                call nearest.overmind_onTeleport()
            endif
        endmethod
       
        //  Init method
        public static method init takes nothing returns nothing
            local trigger t = CreateTrigger()
           
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
            call TriggerAddCondition(t, function thistype.hive_onDeathEvent)
            call TriggerAddCondition(t, function thistype.target_onDeathEvent)
           
            set t = CreateTrigger()
           
            call Damage.registerModifierTrigger(t)
            call TriggerAddCondition(t, function thistype.hive_spider_onDamage)
            //  Located at part two
           
            set t = null
        endmethod
    endstruct
   
    private function OnSpellEvent takes nothing returns nothing
        if GetSpellAbilityId() == SPELL_ID() then
            call Data.create(GetTriggerUnit())
        elseif GetSpellAbilityId() == RAW_ID(2) then
            call Data.teleport(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())
        endif
    endfunction
   
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
       
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t, function OnSpellEvent)
       
        call ForForce(bj_FORCE_PLAYER[0], function Data.init)
        set t = null
    endfunction

endlibrary
 
Last edited:
Level 37
Joined
Jul 22, 2015
Messages
3,485
Our sticky yellow paint is done! I encountered so many WC3 bugs on this mechanic (note to self: never use raider ensnare). I was really hoping to make it a gradual slow, but I don't have that kind of time D: one more paint color to go!

WIP.gif


  • YPaint Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- --------
      • -------- CONFIG START --------
      • -------- --------
      • -------- --------
      • -------- --------
      • -------- imported object editor data --------
      • Set YPaint_ABILITY_SLOW = Slow (Yellow Paint)
      • Set YPaint_BUFF_SLOW = Slow (Yellow Paint)
      • -------- ^ note: make sure ABILITY_SLOW is giving the corresponding BUFF_SLOW in Object Editor --------
      • Set YPaint_ABILITY_SNARE = Snare (Yellow Paint)
      • Set YPaint_BUFF_SNARE = Ensnared (Yellow Paint)
      • -------- ^ note: make sure ABILITY_SNARE is giving the corresponding BUFF_SNARE in Object Editor --------
      • -------- --------
      • -------- imported triggers --------
      • Set YPaint_TRIGGER_LOOP = YPaint Loop <gen>
      • Set YPaint_TRIGGER_APPLY_SLOW = YPaint Slow Index <gen>
      • Set YPaint_TRIGGER_LOOP_SLOW = YPaint Slow Loop <gen>
      • -------- --------
      • -------- how long (in seconds) the puddle will last --------
      • Set YPaint_PUDDLE_DURATION = 5.00
      • Set YPaint_PUDDLE_DURATION_PER_LVL = 0.00
      • -------- --------
      • -------- how close a unit must be to the puddle to be slowed --------
      • Set YPaint_AOE = 150.00
      • Set YPaint_AOE_PER_LEVEL = 0.00
      • -------- --------
      • -------- duration of the slow --------
      • Set YPaint_SLOW_DURATION = 5.00
      • Set YPaint_SLOW_DURATION_PER_LVL = 0.00
      • -------- --------
      • -------- special effect for puddle --------
      • Set YPaint_SFX_PUDDLE = PaintBombPuddle_Yellow.mdl
      • Set YPaint_SFX_PUDDLE_AP = origin
      • Set YPaint_SFX_PUDDLE_SIZE = 1.75
      • Set YPaint_SFX_PUDDLE_DEATH_TIMER = 0.25
      • -------- ^ how much time (in seconds) is needed for death sfx to play --------
      • -------- --------
      • -------- special effect applied to the target when they are slowed --------
      • Set YPaint_SFX_SLOW = Abilities\Spells\Human\slow\slowtarget.mdl
      • Set YPaint_SFX_SLOW_AP = origin
      • -------- --------
      • -------- other --------
      • Set YPaint_PERIODIC_TIMER = 0.03
      • -------- --------
      • -------- --------
      • -------- CONFIG END --------
      • -------- --------
      • Trigger - Add to YPaint_TRIGGER_LOOP the event (Time - Every YPaint_PERIODIC_TIMER seconds of game time)
      • Trigger - Add to YPaint_TRIGGER_LOOP_SLOW the event (Time - Every YPaint_PERIODIC_TIMER seconds of game time)
      • Set YPaint_KEY_ABILITY_LVL = 4
      • Set YPaint_KEY_DURATION = 5
      • Set YPaint_KEY_SFX = 6
      • -------- preload --------
      • Custom script: set udg_YPaint_DummyCaster = GetRecycledDummyAnyAngle(GetRectMaxX(bj_mapInitialPlayableArea), GetRectMaxY(bj_mapInitialPlayableArea), 0.00)
      • Special Effect - Create a special effect attached to the YPaint_SFX_PUDDLE_AP of YPaint_DummyCaster using YPaint_SFX_PUDDLE
      • Special Effect - Destroy (Last created special effect)
      • -------- turning dummy unit into dummy caster --------
      • Unit - Unpause YPaint_DummyCaster
      • Unit - Add YPaint_ABILITY_SLOW to YPaint_DummyCaster
      • Unit - Add YPaint_ABILITY_SNARE to YPaint_DummyCaster
      • -------- unpausing because dummy units are paused by DummyRecycler --------
      • Custom script: call UnitRemoveAbility(udg_YPaint_DummyCaster, 'Amov')
      • -------- math calculations --------
      • Set YPaint_SFX_PUDDLE_SIZE = (YPaint_SFX_PUDDLE_SIZE x 100.00)
  • YPaint Index
    • Events
    • Conditions
    • Actions
      • -------- YPaint Index --------
      • -------- this trigger will create a new instance for the yellow paint mechanic --------
      • -------- --------
      • -------- members --------
      • -------- Caster[] = unit who casted PBomb_ABILITY --------
      • -------- Owner[] = player who owns Caster[] that threw the paint bucket --------
      • -------- AbilityLvl[] = level of PBomb_ABILITY when the caster initially casted the ability --------
      • -------- CurrentColor[] - the color the caster had selected when they casted PBomb_ABILITY --------
      • -------- Counter[] = duration of puddle --------
      • -------- PuddleX[] - x coordinate for the puddle --------
      • -------- PuddleY[] - y coordinate for the puddle --------
      • -------- --------
      • -------- --------
      • Set YPaint_SpellCount = (YPaint_SpellCount + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • YPaint_SpellCount Equal to 1
        • Then - Actions
          • Trigger - Turn on YPaint_TRIGGER_LOOP
        • Else - Actions
          • -------- do nothing --------
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • YPaint_RecycledSize Equal to 0
        • Then - Actions
          • Set YPaint_MaxIndex = (YPaint_MaxIndex + 1)
          • Set YPaint_SpellId = YPaint_MaxIndex
        • Else - Actions
          • Set YPaint_RecycledSize = (YPaint_RecycledSize - 1)
          • Set YPaint_SpellId = YPaint_RecycledStack[YPaint_RecycledSize]
      • Set YPaint_NodeNext[YPaint_SpellId] = 0
      • Set YPaint_NodePrev[YPaint_SpellId] = YPaint_NodePrev[0]
      • Set YPaint_NodeNext[YPaint_NodePrev[0]] = YPaint_SpellId
      • Set YPaint_NodePrev[0] = YPaint_SpellId
      • -------- --------
      • Set YPaint_Caster[YPaint_SpellId] = PBomb_Caster[PBomb_SpellId]
      • Set YPaint_Owner[YPaint_SpellId] = PBomb_Owner[PBomb_SpellId]
      • Set YPaint_AbilityLvl[YPaint_SpellId] = PBomb_AbilityLvl[PBomb_SpellId]
      • Set YPaint_CurrentColor[YPaint_SpellId] = PBomb_CurrentColor[PBomb_SpellId]
      • -------- --------
      • Set YPaint_TempReal = (Real(YPaint_AbilityLvl[YPaint_SpellId]))
      • Set YPaint_Counter[YPaint_SpellId] = (YPaint_PUDDLE_DURATION + (YPaint_PUDDLE_DURATION_PER_LVL x YPaint_TempReal))
      • Set YPaint_Radius[YPaint_SpellId] = (YPaint_AOE + (YPaint_AOE_PER_LEVEL x YPaint_TempReal))
      • -------- --------
      • Custom script: set udg_YPaint_PuddleX[udg_YPaint_SpellId] = GetUnitX(udg_PBomb_MissileUnit[udg_PBomb_SpellId])
      • Custom script: set udg_YPaint_PuddleY[udg_YPaint_SpellId] = GetUnitY(udg_PBomb_MissileUnit[udg_PBomb_SpellId])
      • Custom script: set udg_YPaint_PuddleUnit[udg_YPaint_SpellId] = GetRecycledDummyAnyAngle(udg_YPaint_PuddleX[udg_YPaint_SpellId], udg_YPaint_PuddleY[udg_YPaint_SpellId], 0.00)
      • Animation - Change YPaint_PuddleUnit[YPaint_SpellId]'s size to (YPaint_SFX_PUDDLE_SIZE%, 100.00%, 100.00%) of its original size
      • Special Effect - Create a special effect attached to the YPaint_SFX_PUDDLE_AP of YPaint_PuddleUnit[YPaint_SpellId] using YPaint_SFX_PUDDLE
      • Set YPaint_PuddleSfx[YPaint_SpellId] = (Last created special effect)
  • YPaint Loop
    • Events
    • Conditions
    • Actions
      • -------- YPaint Loop --------
      • -------- this trigger will periodically check if there are units within the radius of the puddle --------
      • -------- if there is an enemy unit within the puddle, the dummy caster will apply the slow effect on them --------
      • -------- if the enemy unit is already affected by the slow or snare, the dummy caster will do nothing --------
      • -------- --------
      • -------- members --------
      • -------- Caster[] = unit who casted PBomb_ABILITY --------
      • -------- Owner[] = player who owns Caster[] that threw the paint bucket --------
      • -------- AbilityLvl[] = level of PBomb_ABILITY when the caster initially casted the ability --------
      • -------- CurrentColor[] - the color the caster had selected when they casted PBomb_ABILITY --------
      • -------- Counter[] = duration of puddle --------
      • -------- PuddleX[] - x coordinate for the puddle --------
      • -------- PuddleY[] - y coordinate for the puddle --------
      • -------- --------
      • -------- --------
      • Set YPaint_SpellId = 0
      • For each (Integer YPaint_LoopInt) from 1 to YPaint_SpellCount, do (Actions)
        • Loop - Actions
          • Set YPaint_SpellId = YPaint_NodeNext[YPaint_SpellId]
          • -------- --------
          • -------- checking if the puddle reached the end of its life span --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • YPaint_Counter[YPaint_SpellId] Less than or equal to 0.00
            • Then - Actions
              • -------- puddle has reached the end of its life span; deallocate instance --------
              • -------- --------
              • -------- decreasing number of active puddles for this color --------
              • Custom script: set udg_SPaint_UnitId = GetHandleId(udg_YPaint_Caster[udg_YPaint_SpellId])
              • Hashtable - Save ((Load PBomb_KEY_ACTIVE_COLOR_COUNT[YPaint_CurrentColor[YPaint_SpellId]] of SPaint_UnitId from PBomb_Hash) - 1) as PBomb_KEY_ACTIVE_COLOR_COUNT[YPaint_CurrentColor[YPaint_SpellId]] of SPaint_UnitId in PBomb_Hash
              • -------- --------
              • Special Effect - Destroy YPaint_PuddleSfx[YPaint_SpellId]
              • Custom script: call DummyAddRecycleTimer(udg_YPaint_PuddleUnit[udg_YPaint_SpellId], udg_YPaint_SFX_PUDDLE_DEATH_TIMER)
              • Set YPaint_RecycledStack[YPaint_RecycledSize] = YPaint_SpellId
              • Set YPaint_RecycledSize = (YPaint_RecycledSize + 1)
              • Set YPaint_NodeNext[YPaint_NodePrev[YPaint_SpellId]] = YPaint_NodeNext[YPaint_SpellId]
              • Set YPaint_NodePrev[YPaint_NodeNext[YPaint_SpellId]] = YPaint_NodePrev[YPaint_SpellId]
              • -------- --------
              • Set YPaint_SpellCount = (YPaint_SpellCount - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • YPaint_SpellCount Equal to 0
                • Then - Actions
                  • Trigger - Turn off YPaint_TRIGGER_LOOP
                • Else - Actions
                  • -------- do nothing --------
            • Else - Actions
              • -------- puddle has not reached the end of its life span; continue slowing nearby enemy units --------
              • Set YPaint_Counter[YPaint_SpellId] = (YPaint_Counter[YPaint_SpellId] - YPaint_PERIODIC_TIMER)
              • -------- --------
              • Custom script: call SetUnitX(udg_YPaint_DummyCaster, udg_YPaint_PuddleX[udg_YPaint_SpellId])
              • Custom script: call SetUnitY(udg_YPaint_DummyCaster, udg_YPaint_PuddleY[udg_YPaint_SpellId])
              • -------- using GroupEnumUnitsInRange because GetUnitsInRangeOfLoc has a reference handle leak --------
              • Custom script: call GroupEnumUnitsInRange(udg_PBomb_InRangeGroup, udg_YPaint_PuddleX[udg_YPaint_SpellId], udg_YPaint_PuddleY[udg_YPaint_SpellId], udg_YPaint_Radius[udg_YPaint_SpellId], null)
              • Unit Group - Pick every unit in PBomb_InRangeGroup and do (Actions)
                • Loop - Actions
                  • Set YPaint_TempUnit = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (YPaint_TempUnit is A structure) Equal to False
                      • (YPaint_TempUnit is A flying unit) Equal to False
                      • (YPaint_TempUnit is Magic Immune) Equal to False
                      • (YPaint_TempUnit is alive) Equal to True
                      • (YPaint_TempUnit belongs to an enemy of YPaint_Owner[YPaint_SpellId]) Equal to True
                      • (YPaint_TempUnit has buff YPaint_BUFF_SLOW) Equal to False
                      • (YPaint_TempUnit has buff YPaint_BUFF_SNARE) Equal to False
                    • Then - Actions
                      • Trigger - Run YPaint_TRIGGER_APPLY_SLOW (ignoring conditions)
                    • Else - Actions
                      • -------- do nothing --------
                  • Unit Group - Remove YPaint_TempUnit from PBomb_InRangeGroup
  • YPaint Slow Index
    • Events
    • Conditions
    • Actions
      • -------- YPaint Slow Index --------
      • -------- this trigger will create an instance that slows the affected unit --------
      • -------- --------
      • -------- --------
      • Custom script: set udg_YPaint_UnitId = GetHandleId(udg_YPaint_TempUnit)
      • -------- --------
      • Unit Group - Add YPaint_TempUnit to YPaint_SlowedGroup
      • Set YPaint_GroupCount = (YPaint_GroupCount + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • YPaint_GroupCount Equal to 1
        • Then - Actions
          • Trigger - Turn on YPaint_TRIGGER_LOOP_SLOW
        • Else - Actions
          • -------- do nothing --------
      • -------- --------
      • Set YPaint_SlowCounter = (YPaint_SLOW_DURATION + (YPaint_SLOW_DURATION_PER_LVL x (Real(YPaint_AbilityLvl[YPaint_SpellId]))))
      • Unit - Order YPaint_DummyCaster to Human Sorceress - Slow YPaint_TempUnit
      • Special Effect - Create a special effect attached to the YPaint_SFX_SLOW_AP of YPaint_TempUnit using YPaint_SFX_SLOW
      • -------- --------
      • Hashtable - Save YPaint_AbilityLvl[YPaint_SpellId] as YPaint_KEY_ABILITY_LVL of YPaint_UnitId in PBomb_Hash
      • Hashtable - Save YPaint_SlowCounter as YPaint_KEY_DURATION of YPaint_UnitId in PBomb_Hash
      • Hashtable - Save Handle Of(Last created special effect) as YPaint_KEY_SFX of YPaint_UnitId in PBomb_Hash
  • YPaint Slow Loop
    • Events
    • Conditions
    • Actions
      • -------- YPaint Slow Loop --------
      • -------- this trigger will keep track of the duration of the slow on affected units --------
      • -------- if the unit still has the buff at the end of the duration, they will be snared --------
      • -------- --------
      • -------- --------
      • Unit Group - Pick every unit in YPaint_SlowedGroup and do (Actions)
        • Loop - Actions
          • Set YPaint_Target = (Picked unit)
          • Custom script: set udg_YPaint_UnitId = GetHandleId(udg_YPaint_Target)
          • -------- --------
          • Set YPaint_SlowCounter = ((Load YPaint_KEY_DURATION of YPaint_UnitId from PBomb_Hash) - YPaint_PERIODIC_TIMER)
          • -------- checking if the target loss the buff or if the duration is over --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (YPaint_Target is dead) Equal to True
                  • (YPaint_Target has buff YPaint_BUFF_SLOW) Equal to False
                  • YPaint_SlowCounter Less than or equal to 0.00
            • Then - Actions
              • -------- --------
              • -------- checking if target still has buff --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (YPaint_Target has buff YPaint_BUFF_SLOW) Equal to True
                • Then - Actions
                  • -------- target still had buff at the end of the duration; manually remove slow and snare the target --------
                  • Unit - Remove YPaint_BUFF_SLOW buff from YPaint_Target
                  • -------- --------
                  • Custom script: call SetUnitX(udg_YPaint_DummyCaster, GetUnitX(udg_YPaint_Target))
                  • Custom script: call SetUnitY(udg_YPaint_DummyCaster, GetUnitY(udg_YPaint_Target))
                  • Unit - Set level of YPaint_ABILITY_SNARE for YPaint_DummyCaster to (Load YPaint_KEY_ABILITY_LVL of YPaint_UnitId from PBomb_Hash)
                  • Unit - Order YPaint_DummyCaster to Night Elf Keeper Of The Grove - Entangling Roots YPaint_Target
                • Else - Actions
                  • -------- target loss the debuff; do nothing --------
              • -------- --------
              • Special Effect - Destroy (Load YPaint_KEY_SFX of YPaint_UnitId in PBomb_Hash)
              • -------- manually removing child keys because other child keys still might be in use --------
              • Custom script: call RemoveSavedInteger(udg_PBomb_Hash, udg_YPaint_UnitId, udg_YPaint_KEY_ABILITY_LVL)
              • Custom script: call RemoveSavedReal(udg_PBomb_Hash, udg_YPaint_UnitId, udg_YPaint_KEY_DURATION)
              • Custom script: call RemoveSavedHandle(udg_PBomb_Hash, udg_YPaint_UnitId, udg_YPaint_KEY_SFX)
              • -------- --------
              • Unit Group - Remove YPaint_Target from YPaint_SlowedGroup
              • Set YPaint_GroupCount = (YPaint_GroupCount - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • YPaint_GroupCount Equal to 0
                • Then - Actions
                  • Trigger - Turn off YPaint_TRIGGER_LOOP_SLOW
                • Else - Actions
                  • -------- do nothing --------
            • Else - Actions
              • -------- target still has the debuff with time left; save duration left --------
              • Hashtable - Save YPaint_SlowCounter as YPaint_KEY_DURATION of YPaint_UnitId in PBomb_Hash
Side note: @Cokemonkey11 is going to hate me after this contest. Give me a fair review and I promise to consider Wurst next year!

Capture.PNG
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,492
@IcemanBo @Murlocologist

I was talking with @KILLCIDE in the Discord, and it was brought to my attention that there is some small ambiguity in the Deadline Time as dictated by the first post in the Contest Thread.

Personally, as a Host, I have found it best to be absolutely, expressly specific, so as to avoid any frustrating confusion (for entrants yes, but also for the Host himself; having to deal with people misunderstanding. ;P)

I move to clarify the deadline as follows:

Saturday, December 30th, 2017, @ 11:59:59PM (GMT 0)
This way it is unequivocal which day, date, month & year are being talked about, and most importantly both the time frame & the time zone. (if we use/assume midnight (generally considered the 'end of the day' but technically the beginning of the next), people might assume the 31st is part of it. Or move back from 12 & be a minute late, etc).

~~~

Now, that being said, let me also put in my voice for a slight extension (lol); perhaps even if only a few days (say Tuesday, January 2nd, 2018 @ 11:59:59PM (GMT 0) or somesuch). While it's true it's the holidays and many people have work/school off, it's also true that many people are spending those holidays away/visiting said family, and modding time is not exactly at it's highest.
Just my $0.02
 
Level 37
Joined
Jul 22, 2015
Messages
3,485
say Tuesday, January 2nd, 2018 @ 11:59:59PM (GMT 0) or somesuch
For the record, I didn't start on my entry until the 16th of December because I had school, so I had a lot less time. With that in mind, I agree with the extension. I start school again on the 2nd, but the extra few days will allow me to debug and review my code more thoroughly.
 
Level 18
Joined
Feb 13, 2011
Messages
400
I am thankful of the the first deadline extension, however, due to family trips and commitments I will only be able to use 1 of the 8 days added to the deadline. Can we have a second extension that gives use one more weekend outside holidays?

EDIT: ps I am of those who only gets 1 week vacation off work.
 
Status
Not open for further replies.
Top