Spell Heat Cyclone

Sim

Forum Administrator
Staff member
Reaction score
534
I present thee Heat Cyclone:

heatcycloneimproved.jpg


It is a long time since I coded my last spell, especially in vJASS. So, the other day, I decided to make sure I remember how by coding a new spell. ^^

It is rather simple really, I just wanted to make an efficient spell with an efficient timer system.

Anyways.

Here's the code:

JASS:
scope HeatCyclone initializer Init

//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
//¤
//¤ ***************** 
//¤ - Heat Cyclone v2.0 - 
//¤ *****************
//¤ 
//¤ By: Daxtreme
//¤ 
//¤ --> How to implement in your map:
//¤                           
//¤     1. Copy the spell "Heat Cyclone" into your map.
//¤     2. Copy the spell named "Heat cyclone dummy" into your map.
//¤     3. (Optional, if you haven't a dummy unit already) Copy the unit "Dummy unit" into your map.
//¤     4. Copy this trigger into your map.
//¤     5. Import the FireTornado.mdx model into your map.
//¤     6. Import the Tornado2b.blp texture into your map.
//¤     7. Copy the trigger named "KT" into your map.
//¤     8. Copy the trigger named "GT" into your map.
//¤     9. Change the rawcodes in the configuration section so they fit with your map's.
//¤
//¤ --> How to customize it:
//¤
//¤     1. You can configure the spell using the few globals just below. Change their values.
//¤     2. The main editing happens in the object editor. The spell "Heat cyclone dummy" is the one that's
//¤        editable. Damage, Fireball speed, and distance are all examples of editable stuff.
//¤
//¤ CREDITS:
//¤
//¤     - JetFangInferno's Fire Tornado.
//¤     - Jesus4Lyf's KeyTimers2 and GTrigger Events sytems.
//¤     - Tinki3's spell map test template.
//¤
//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
//
// ***      Configuration Section      ***
//
//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

globals

private constant integer RawCode = 'A000' // The spell's rawcode in the editor
private constant integer dummyid = 'u001' // The dummy's id
private constant integer dummyspell = 'A002' // The dummy spell's id
private constant string effectpath = "war3mapImported\\FireTornado.mdx" // Path of the custom effect
private constant string orderstring = "carrionswarm" // Order string of the dummy spell
private constant real dummylife = 5. // If you want to increase the spell's duration, increasing the dummy's lifespan is
                                     // important.
private constant real angle = 18. // Angle increment between each fireball. The smaller the laggier.
private constant real period = 0.035 // Time between each instance of the dummy spell. Do not reduce this below 0.01
                                      // as the lag will increase
endglobals

//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
//
// ***       Spell Code       ***
//
// --> I highly recommend editing the following only if you know what you're doing.
//
//¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

private struct data
    unit c
    integer lvl
    integer i = 0
    integer id
    effect fireww
    unit dummy
    real x
    real y
endstruct

private function Timer takes nothing returns boolean
    local data d = KT_GetData()
    local real x2
    local real y2
    if ( GetUnitCurrentOrder(d.c) != d.id ) then
        call DestroyEffect(d.fireww)
        call data.destroy(d)
        set d.c = null
        set d.fireww = null
        set d.dummy = null
        return true
    endif 
    set d.i = d.i + 1
    set x2 = d.x + 50. * Cos((angle * I2R(d.i)) * bj_DEGTORAD) // The 50. is to ensure the dummy correctly turns.
    set y2 = d.y + 50. * Sin((angle * I2R(d.i)) * bj_DEGTORAD) // Else, the spell does not make a perfect cyclone.
    call SetUnitFacing(d.dummy, bj_RADTODEG * Atan2(y2 - d.y, x2 - d.x))
    call IssuePointOrder(d.dummy, orderstring, x2, y2)
    return false
endfunction


private function Actions takes nothing returns boolean
    local data d = data.create()
    
    set d.c = GetTriggerUnit()
    set d.lvl = GetUnitAbilityLevel(d.c, RawCode)
    set d.x = GetUnitX(d.c)
    set d.y = GetUnitY(d.c)
    set d.fireww = AddSpecialEffectTarget(effectpath, d.c, "origin")
    set d.id = GetUnitCurrentOrder(d.c)
    set d.dummy = CreateUnit(GetOwningPlayer(d.c), dummyid, d.x, d.y, 0.)
    call UnitAddAbility(d.dummy, dummyspell)
    call SetUnitAbilityLevel(d.dummy, dummyspell, d.lvl)
    call UnitApplyTimedLife(d.dummy, 'BTLF', dummylife)
    call KT_Add(function Timer, d, period)
    return false
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    call GT_AddActionToStartsEffectEvent(RawCode, function Actions)
endfunction

endscope


I'm a bit rusty with all this, and so I will gladly accept comments!

Thanks to JetFangInferno for the FireWhirlwind model, to Jesus4Lyf for his system KeyTimers2 and GTrigger, and to Tinki3 for the map template.

Enjoy!

EDIT: Small tweaks
EDIT2: Removed the order Id from configurable section. It now checks directly for the correct id.
EDIT3: struct is now private. Removed useless configuration. Made the effect path configurable.
EDIT4: MAJOR changes done to the spell. Removed lag almost entirely. Changed the missile effect and the base dummy spell.
EDIT5: Few tweaks updated.
EDIT6: Last update! Everything should be quite good now, and stable.
EDIT7: Version 2.0 (optional version) includes Jesus4Lyf's GTrigger system.
EDIT8: Update!
 

Attachments

  • Heat Cyclone v2.w3x
    88.9 KB · Views: 526

Tom Jones

N/A
Reaction score
437
Neat. Though you could probably get d.c's current order, and assign that to a variable and then check for that, instead of relying on a user defined orderid.
 

Sim

Forum Administrator
Staff member
Reaction score
534
Neat. Though you could probably get d.c's current order, and assign that to a variable and then check for that, instead of relying on a user defined orderid.

That's a nice idea. Working on that!
 

WolfieeifloW

WEHZ Helper
Reaction score
372
Just two things I saw:
  • Make "init" a private function.
  • And make "origin" customizable in the globals.
Otherwise, cool spell.
 

Sim

Forum Administrator
Staff member
Reaction score
534
Init is now private.

I actually made the effect path customizable, but its attachment point I didn't touch because it looks bad anyway if positioned otherwise.
 

Sim

Forum Administrator
Staff member
Reaction score
534
Thanks for the comments guys. :)
 

Sim

Forum Administrator
Staff member
Reaction score
534
Major update!

The spell's lag has been drastically decreased, and I think it looks wayyyy better now. Have a look at it!
 

Jesus4Lyf

Good Idea™
Reaction score
397
Hey, that's one brilliant looking spell. It really suits a bloodmage character, because the channel animation fits the cyclone model so well.

May I say though...

private constant real period = 0.0384

You should really change that to 0.035 or 0.04. The reason is Key Timers 2 doesn't support accuracy beyond 0.005. If it actually matters, I may be able to modify KT2 to allow more specific periods like 0.038. I just assumed people didn't need it. (See the "Cons" section of KT2.)

PS. Naturally I spammed the spell button and got about 10 instances going before it kinda lagged. XD
 

Sim

Forum Administrator
Staff member
Reaction score
534
> PS. Naturally I spammed the spell button and got about 10 instances going before it kinda lagged. XD

That's what's awesome with KT2 ;)

> You should really change that to 0.035 or 0.04

For sure. I chose randomly.

EDIT: updated! Period is set to 0.035. Nulled the handles within the struct. Fixed a boolexpr leak in the event.
 

BlackRose

Forum User
Reaction score
239
1. Hotkey don't work.
2. Map seems kinda small, I never liked the template anyway :(... it's too small.
3. Does inmporting the tornado.blp thingy affect the original spin?... or other Elemental Spins....

JASS:
        call DestroyEffect(d.fireww)
        call data.destroy(d)
        set d.c = null
        set d.p = null
        set d.fireww = null
        set d.dummy = null
        return true


I'm not that great at JASS, but you don't need to null them do you? I thought they were global arrays... and can't you put them into an onDestroy method?

---------------------------------------------

Otherwise, it's fancy :)
 

Jesus4Lyf

Good Idea™
Reaction score
397
BlackRose is indeed correct. Since stucts are stored in global arrays, they will be overwritten, so long as you destroy the struct. If the spell is only to be cast once in a map, then yes, null the struct data at the end. But if lets say if you don't null instance #3, then the next time you reach 3 instances, the old unnulled values will be overwritten anyway. :) (The condition for that is that you DO destroy the old structs, so the integer value can be re-used.)

So obviously they need not be in an onDestroy method either.
 

Sim

Forum Administrator
Staff member
Reaction score
534
Updated! In short, got rid of boolexpr leak and nulled globals handle. Why not. :)
 

Romek

Super Moderator
Reaction score
964
In the Init function, you set a boolexpr variable to null.
Then use it.
Then destroy null.
And null, null.

I think it'd be wise to just remove that local boolexpr. :p
 

Kenny

Back for now.
Reaction score
202
EDIT:

Haha, didn't realise you updated the spell without updating the script on your first post. :p (had crap about boolexpr in my original post)

Anywho, this spell is really cool, and looks really good. Had a lot of fun testing it out. +rep.

EDIT 2:

Your struct member for GetOwningPlayer() seems a little useless, you only really use it once. And im pretty sure player variables don't need to be nulled.
 

Romek

Super Moderator
Reaction score
964
> Some dude on HiveWorkshop told me this boolexpr usage method is the only way to get rid of the boolexpr expression leak.
I don't see how using a variable with the value of null is any better than using null itself.
(And then destroying the null, and nulling the null).

I heard that boolexprs in events don't leak anyway.
 

Sim

Forum Administrator
Staff member
Reaction score
534
Dude said:
well answer is all again blizzard's coding of it, boolexpr is like a table with condition you typed ~via Filter() or Condition() well since script does not know what pointer null is since it will not have table, the leak in memory is created because it will allocate something because you typed null and that something is some part of memory which can contain some data as well but will never again, until you leave the game.

Anyhow, I did it because I had nothing else to do. Right or wrong, it really does not matter as we can't be 100% sure it really leaks. Even if it does, it's 1 leak in the whole game, not 1 leak every time the spell is cast.

> Your struct member for GetOwningPlayer() seems a little useless, you only really use it once.

The struct member sure is useless.

> And im pretty sure player variables don't need to be nulled.

JASS:
type player             extends     handle  // a single player reference


It is an handle. Therefore, it must be nulled. (As a global variable in a struct, it leaks only once. But, why not remove it?)
I removed the player variable anyways.

EDIT: Updated the code above to fit the current version, and the player struct member removal. But that player removal is still not implemented in the map.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Howdy
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top