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

Burning Orbit v0.06

This spell creates a big orb. After servale seconds the orb splits up in smaller orbs which rotates around the middle. These smaller orbs casts from time to time chain lightnings uppon the enemies around. After some seconds the splits moves to the middle and change to the big orb. The orb last some seconds and then it disappears.

!Changes! Now you can decide if you want the 3d mode. Did some small changes. The missiles have yet the right facing on rotate. Effect change, name change.

Credits: Vexorian for BoundSentinel and TimerUtils. + Some others but can't remember them.

Please give credits when you use it.

@rmx hope this one is more creativ ;).

JASS:
scope BurningOrbit initializer init

//*************************************************************************************************************//
//                                                  Burning Orbit                                              //
//                                                        by                                                   //
//                                                      cedi                                                   //
//                                                                                                             //
//                                         needs: TimerUtils by Vexorian                                       //
//                                                Bound Sentinel by Vexorian                                   //
//                                                Dummy Model by                                               //
//                                                Vector lib by                                                //
//                                                Heights by cedi                                              //
//*************************************************************************************************************//

//For use, copy the trigger to your map, copy the dummy create a spell and adjust the values below.

globals
    //ID of the dummy spell
    private constant integer SPELL_ID            = 'A000'
    //ID of the spell which the splits should have. Beware, only unit target spells or passivs.
    private constant integer SPLIT_SPELL         = 'A001'
    //ID of the spell which they mmain orb should have. BEware, only passivs.
    private constant integer MAIN_SPELL          = '0000'
    //ID of the dummy
    private constant integer DUMMY_ID            = 'h000'
    //How many levels does your spell have?
    private constant integer SPELL_LEVEL_COUNT   = 4
    //How many splits do you want?
    private constant integer MAX_SPLITS          = 20
    //How many moves should the spreed out use?
    private constant integer MOVES               = 25
    //Red part of the color of the main orb ( 0 - 255 )
    private constant integer COLOR_RED           = 255
    //Green part of the color of the main orb ( 0 - 255 )
    private constant integer COLOR_GREEN         = 255
    //Blue part of the color of the main orb ( 0 - 255 )
    private constant integer COLOR_BLUE          = 255
    //Alpha part of the color of the main orb ( 0 - 255 )
    private constant integer COLOR_ALPHA         = 255
    //Red part of the color of the split orb ( 0 - 255 )
    private constant integer SPLIT_COLOR_RED     = 255
    //Green part of the color of the split orb ( 0 - 255 )
    private constant integer SPLIT_COLOR_GREEN   = 255
    //Blue part of the color of the split orb ( 0 - 255 )
    private constant integer SPLIT_COLOR_BLUE    = 255
    //Alpha part of the color of the split orb ( 0 - 255 )
    private constant integer SPLIT_COLOR_ALPHA   = 255
    //The move timer interval
    private constant real    TIMER_INTERVAL      = 0.02
    //Max distance of the splits to the main orb.
    private constant real    MAX_DISTANCE        = 300.00
    //Min distance of the splits to the main orb.
    private constant real    MIN_DISTANCE        = 100.00
    //Max rotation speed of the splits in grad.
    private constant real    MAX_SPEED           = 2.00
    //Min rotation speed of the splits in grad.
    private constant real    MIN_SPEED           = 0.50
    //Flyheight of the main orb.
    private constant real    MAIN_FLY_HEIGHT     = 500.00
    //Maximal cooldown add.
    private constant real    MAX_COOLDOWN_ADD    = 3.00
    //Delay between summon and split.
    private constant real    SPLIT_DELAY         = 3.00
    //Size of the main orb 1 == 100% size.
    private constant real    MAIN_SIZE           = 3.00
    //Size of the splits orb 1 == 100% size.
    private constant real    SPLIT_SIZE          = 1.00
    //Model of the splits.
    private constant string  SPLIT_MODEL         = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl" 
    //Model of the main orb.
    private constant string  MAIN_MODEL          = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
    //Effect when the main orb split up.
    private constant string  SPLIT_EFFECT        = "Abilities\\Spells\\Orc\\FeralSpirit\\feralspiritdone.mdl"
    //Effect when the main orb comes to gether.
    private constant string  SPLIT_END_EFFECT    = ""
    //Order string of the split spell.
    private constant string  ORDER_STRING        = "acidbomb"
    //Effect when the main orb appears.
    private constant string  CREATE_EFFECT       = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
    //Effect when the main orb disappears.
    private constant string  REMOVE_EFFECT       = "Abilities\\Spells\\Other\\Incinerate\\FireLordDeathExplode.mdl"
    //Should the main orb get invisible during splitting?
    private constant boolean HIDE_MAIN           = true
    //Is the split spell targeting enemies?
    private constant boolean TARGET_ENEMY        = true
    //Should the splits fly around on 3d?
    private constant boolean 3D                  = true
    
    private vector           AXISZ //System
    private vector           AXISX //System
    private vector           AXISY //System
    private vector           TEMPVECTOR2 //System
    private real     array   COOLDOWN //System
    private real     array   DURATION //System
    private real     array   AOE //System
    private group            TEMPGROUP           = CreateGroup() //System
endglobals

//Cooldown of the split spell.
private function SET_COOLDOWN takes nothing returns nothing
    set COOLDOWN[1] = 3.00
    set COOLDOWN[2] = 3.00
    set COOLDOWN[3] = 3.00
    set COOLDOWN[4] = 3.00
endfunction

//Duration of the whole spell
private function SET_DURATION takes nothing returns nothing
    set DURATION[1] = 12.00
    set DURATION[2] = 12.00
    set DURATION[3] = 12.00
    set DURATION[4] = 12.00
endfunction

//Range of the dummy spell ( the value in the oe should be bigger then this )
private function SET_AOE takes nothing returns nothing
    set AOE[1] = 550.00
    set AOE[2] = 550.00
    set AOE[3] = 550.00
    set AOE[4] = 550.00
endfunction

//*************************************************************************************************************//
//                                                     !SYSTEM!                                                //
//*************************************************************************************************************//

private keyword SF_Split
private keyword SF_Main

private function IsAliveAndUnitAndNotMagicImmune takes nothing returns boolean
    return GetWidgetLife( GetFilterUnit() ) > 0.405 and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_MAGIC_IMMUNE) == false
endfunction

private struct SF_Split
    unit split
    integer movescounter = 0
    real angleZ
    real angleX
    real angleY
    real cd = 0.00
    real nextcast = 0.00
    
    boolean reachedLoc = false
    boolean goinInit = false
    
    effect sfx
    
    SF_Main root
    vector posi
    vector tmpposi
    vector move
    
    method onDestroy takes nothing returns nothing
        call DestroyEffect( .sfx )
        call KillUnit( .split )
        set .sfx = null
        set .split = null
        call .posi.destroy()
        call .move.destroy()
    endmethod
    
    private method GetRandomNextCast takes nothing returns nothing
        set .nextcast = COOLDOWN[.root.level] + GetRandomReal( 0.00, MAX_COOLDOWN_ADD )
    endmethod
    
    private method Cast takes nothing returns nothing
        local unit u
        call .GetRandomNextCast()
        set .cd = 0.00
        call GroupEnumUnitsInRange( TEMPGROUP, GetUnitX( .split ), GetUnitY( .split ), AOE[.root.level], Condition( function IsAliveAndUnitAndNotMagicImmune ) )
        loop
            set u = FirstOfGroup( TEMPGROUP )
            exitwhen u == null
            if IsUnitEnemy( u, .root.owner ) == TARGET_ENEMY then
                call IssueTargetOrder( .split, ORDER_STRING, u )
                set u = null
                call GroupClear( TEMPGROUP )
                exitwhen true
            endif
            call GroupRemoveUnit( TEMPGROUP, u )
        endloop
    endmethod
    
    private method Zangle takes real z returns nothing
        local integer i=R2I(z*bj_RADTODEG+90.5)
        if(i>=180) then
            set i=179
        elseif(i<0) then
            set i=0
        endif
            
        call SetUnitAnimationByIndex(.split, i  )
    endmethod
    
    private method Turn takes nothing returns nothing
        local real z = .posi.z
        local real x = .posi.x
        local real y = .posi.y
        call .posi.rotate( AXISZ, .angleZ )
        set x = ( .root.posi.x + .posi.x ) - ( .root.posi.x + x )
        set y = ( .root.posi.y + .posi.y ) - ( .root.posi.y + y )
        if 3D == true then
            call .posi.rotate( AXISX, .angleX )
            call .posi.rotate( AXISY, .angleY )
            set z = ( .root.posi.z + .posi.z ) - ( .root.posi.z + z )
            call .Zangle( Atan(( z  / (SquareRoot(x*x + y*y))) ) )
            call SetUnitZ( .split, .root.posi.z + .posi.z )
        endif
        call SetUnitX( .split, .root.posi.x + .posi.x )
        call SetUnitY( .split, .root.posi.y + .posi.y )
        call SetUnitFacing(.split,Atan2(y, x)*bj_RADTODEG)
    endmethod
    
     private method SetPositonReturn takes nothing returns nothing
        if .movescounter <= MOVES then
            call .tmpposi.add( .move )
            call SetUnitX( .split, .tmpposi.x )
            call SetUnitY( .split, .tmpposi.y )
            call SetUnitZ( .split, .tmpposi.z )
        else
            call .destroy()
        endif
        set .movescounter = .movescounter + 1
    endmethod
    
    private method SetPositon takes nothing returns nothing
        if .movescounter <= MOVES then
            call .tmpposi.add( .move )
            call SetUnitX( .split, .tmpposi.x )
            call SetUnitY( .split, .tmpposi.y )
            call SetUnitZ( .split, .tmpposi.z )
        else
            set .reachedLoc = true
        endif
        set .movescounter = .movescounter + 1
    endmethod
    
    method control takes nothing returns nothing
        if .root.splitlifetime <= 0.00 then
            call .destroy()
        endif
        if .root.goin == true then
            if .goinInit == false then
                set .movescounter = 0
                set .goinInit = true
                set .tmpposi.x = .root.posi.x + .posi.x
                set .tmpposi.y = .root.posi.y + .posi.y
                set .tmpposi.z = .root.posi.z + .posi.z
                set .move.x = ( .posi.x * -1.00 ) / I2R( MOVES )
                set .move.y = ( .posi.y * -1.00 ) / I2R( MOVES )
                set .move.z = ( .posi.z * -1.00 ) / I2R( MOVES )
                set .movescounter = 0
            endif
            call .SetPositonReturn()
        endif
        if .reachedLoc == false then
            call .SetPositon()
        elseif .root.goin == false then
            call .Turn()
            set .cd = .cd + TIMER_INTERVAL
            if .cd >= .nextcast then
                call .Cast()
            endif
        endif
    endmethod
    
    private method GetRamdomAngle takes nothing returns nothing
        local integer i = GetRandomInt( 0, 1 )
        local real r = GetRandomReal( MIN_SPEED, MAX_SPEED ) * bj_DEGTORAD
        if i == 0 then
            set .angleZ = r * -1
        else
            set .angleZ = r
        endif
        set i = GetRandomInt( 0, 1 )
        set r = GetRandomReal( MIN_SPEED, MAX_SPEED ) * bj_DEGTORAD
        if i == 0 then
            set .angleX = r * -1
        else
            set .angleX = r
        endif
        set i = GetRandomInt( 0, 1 )
        set r = GetRandomReal( MIN_SPEED, MAX_SPEED ) * bj_DEGTORAD
        if i == 0 then
            set .angleY = r * -1
        else
            set .angleY = r
        endif
    endmethod
    
    private method GetRandomPosi takes nothing returns nothing
        local real a = GetRandomReal( 0.00, 360.00 ) * bj_DEGTORAD
        local real b = GetRandomReal( 0.00, 180.00 ) * bj_DEGTORAD
        local real r = GetRandomReal( MIN_DISTANCE, MAX_DISTANCE )
        local real times = I2R( MOVES )
        set .posi = vector.create( r*Cos(a)*Cos(b), r*Cos(a)*Sin(b), r*Sin(a) )
        set .move = vector.create( .posi.x / times , .posi.y / times, .posi.z / times )
    endmethod
    
    static method create takes SF_Main root returns SF_Split
        local SF_Split data = SF_Split.allocate()
        set data.root = root
        call data.GetRandomPosi()
        call data.GetRamdomAngle()
        set data.split = CreateUnit( root.owner, DUMMY_ID, 0.00, 0.00, GetRandomReal( 0.00, 360.00 ) )
        set data.sfx = AddSpecialEffectTarget( SPLIT_MODEL, data.split, "origin" )
        call data.GetRandomNextCast()
        call UnitAddAbility( data.split, SPLIT_SPELL )
        call SetUnitAbilityLevel( data.split, SPLIT_SPELL, data.root.level )
        call data.SetPositon()
        call SetUnitVertexColor( data.split, SPLIT_COLOR_RED, SPLIT_COLOR_GREEN, SPLIT_COLOR_BLUE, SPLIT_COLOR_ALPHA )
        call SetUnitScale( data.split, SPLIT_SIZE, SPLIT_SIZE, SPLIT_SIZE )
        set data.tmpposi = vector.create( root.posi.x, root.posi.y, root.posi.z )
        return data
    endmethod
    
endstruct

private function Control takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local SF_Main data = GetTimerData( t )
    call data.control()
    set t = null
endfunction

private struct SF_Main
    unit main = null
    unit caster = null
    
    integer level = 1
    timer t = null
    
    player owner = null
    
    boolean goin = false
    boolean splitupdone = false
    boolean end = false
    boolean moving = false
    
    real splitlifetime
    real delay = SPLIT_DELAY
    
    effect sfx = null
    
    SF_Main data = 0
    SF_Split array splits[MAX_SPLITS]
    
    vector posi = 0
    vector move = 0
    
    method control takes nothing returns nothing
        local integer i = 0
        if .splitupdone == false then
            set .delay = .delay - TIMER_INTERVAL
            if .delay <= 0.00 then
                set .splitupdone = true
                call DestroyEffect( AddSpecialEffectTarget( SPLIT_EFFECT, .main, "origin" ) )
                if HIDE_MAIN then
                    call SetUnitVertexColor( .main, 255, 255, 255, 0 )
                endif
                loop
                    exitwhen i == MAX_SPLITS
                    set .splits[i] = SF_Split.create( .data )
                    set i = i + 1
                endloop
            endif
        endif
        if .splitlifetime <= 0.00 and .end == false then
            set .delay = SPLIT_DELAY
            set .end = true
            if HIDE_MAIN then
                call SetUnitVertexColor( .main, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_ALPHA )
                call DestroyEffect( AddSpecialEffectTarget( SPLIT_END_EFFECT, .main, "origin" ) )
                set i = 0
                loop
                    exitwhen i == MAX_SPLITS
                    if .splits[i] != 0 then
                        call .splits[i].control()
                    endif
                    set i = i + 1
                endloop
            endif
        endif
        if .end == true then
            set .delay = .delay - TIMER_INTERVAL
            if .delay <= 0.00 then
                call DestroyEffect( AddSpecialEffectTarget( REMOVE_EFFECT, .main, "origin" ) )
                call .destroy()
            endif
        endif
        if .moving then
            call .posi.add( .move )
            call SetUnitX( .main, .posi.x )
            call SetUnitY( .main, .posi.y )
        endif
        if .splitlifetime <= I2R( MOVES ) * TIMER_INTERVAL and .goin == false then
            set .goin = true
        endif
        set i = 0
        if .splitupdone and not .end then
            set .splitlifetime = .splitlifetime - TIMER_INTERVAL
            loop
                exitwhen i == MAX_SPLITS
                if .splits[i] != 0 then
                    call .splits[i].control()
                endif
                set i = i + 1
            endloop
        endif
    endmethod
    
    method onDestroy takes nothing returns nothing
        call ReleaseTimer( .t )
        call DestroyEffect( .sfx )
        call KillUnit( .main )
        call .posi.destroy()
        if .moving == true then
            call .move.destroy()
        endif
    endmethod
    
    static method create takes unit caster, real x, real y, vector move returns SF_Main
        local SF_Main data = SF_Main.allocate()
        set data.data = data
        set data.t = NewTimer()
        call SetTimerData( data.t, data )
        set data.caster = caster
        set data.owner = GetOwningPlayer( caster )
        set data.main = CreateUnit( data.owner, DUMMY_ID, x, y, GetRandomReal( 0.00, 360.00 ) )
        set data.sfx = AddSpecialEffectTarget( MAIN_MODEL, data.main, "origin" )
        set data.level = GetUnitAbilityLevel( caster, SPELL_ID )
        set data.splitlifetime = DURATION[data.level]
        call SetUnitFlyHeight( data.main, MAIN_FLY_HEIGHT, 0.00 )
        call DestroyEffect( AddSpecialEffectTarget( CREATE_EFFECT, data.main, "origin" ) )
        call UnitAddAbility( data.main, MAIN_SPELL )
        call SetUnitAbilityLevel( data.main, MAIN_SPELL, data.level )
        call SetUnitVertexColor( data.main, COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_ALPHA )
        call SetUnitScale( data.main, MAIN_SIZE, MAIN_SIZE, MAIN_SIZE )
        if move != 0 then
            set data.move = move
            set data.moving = true
        endif
        set data.posi = vector.create( x, y, GetUnitZ( data.main ) )
        call TimerStart( data.t, TIMER_INTERVAL, true, function Control )
        set caster = null
        return data
    endmethod
    
endstruct

private function IsSpell takes nothing returns boolean
    if GetSpellAbilityId() == SPELL_ID then
        call SF_Main.create( GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY(), 0 )
    endif
    return false
endfunction

private function init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function IsSpell ) )
    
    set AXISX = vector.create( 1.00, 0.00, 0.00 )
    set AXISY = vector.create( 0.00, 1.00, 0.00 )
    set AXISZ = vector.create( 0.00, 0.00, 1.00 )
    set TEMPVECTOR2 = vector.create( 0.00, 0.00, 0.00 )
    
    call SET_COOLDOWN()
    call SET_DURATION()
    call SET_AOE()
    
    set t = null
endfunction

endscope

Keywords:
orb, moving, rotating, generator, field, orbit, fire, burn, burning, heat, geometrie
Contents

Burning Orbit v0.06 (Map)

Reviews
19:27, 4th Oct 2009 TriggerHappy187: You fixed all of the leaks I mentioned. I also said I would approve this once you had done so.

Moderator

M

Moderator

19:27, 4th Oct 2009
TriggerHappy187:

You fixed all of the leaks I mentioned. I also said I would approve this once you had done so.
 

Rmx

Rmx

Level 19
Joined
Aug 27, 2007
Messages
1,164
Review



- Idea and creativity - # / 10

- Eye Candy and Ingame Play - # / 10

- Coding - # / 20

- Description of spell - # / 5

- If Spell is MUI you get +3

-if spell is Recycled efficiently you get +2

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

-
The total amount is 50

If you get 10 = FAIL

If you get 20 = Lacking

If you get 30 = Acceptable

If you get 40 = Recommended

If you get 50 = Highly ! Recommended


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

Idea and Creativity - 9 / 10

Eye Candy & Ingame Play - 9 / 10

Coding - 16 / 20

Description of spell - 4 / 5


Total = 38

MUI [ yes ] then 38 + 3 = 41

Spell is Recycled Efficiently [ yes ] then 41 + 2 = 43

Status is [ Recommended ]


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



WOW i must say, the spell remind me of ATOM in chemistry but outstanding effect :D, creativity is very nice :D
rmx hope this one is more creativ ;).
I laughed my ass off .. when i SAW the Debug messages :p lol anyway ...
I didn't see you null the (unit main) just the caster ...
 
Level 10
Joined
May 19, 2008
Messages
176
Structs variables are only arrays with a special name. The struct is only an integer which stays for the index of the variable. Because of that you need to write in a constant array lenght for array variables in structs. Then this value representate the offset.

For example.

struct A
integer i
integer array i2[20]
endstruct

when you create a struct it has a number for example 0.
Yet there exist an integer array variable with the name A__i or something like that. When you set i == a value wc3 sets A__i[0] == the value.
On struct variable arrays they have reserved places. A__i2[0 - 20] is reserved for the struct.
The next struct has the places 21 - 41 and so on. Because of that you can have only 8191 / constant array size structs.

The result is, all struct members are globals. And globals can't leak.

So you see, caster is a local variable == Needs to be nulled. Main is a global variable == you don't have to null it. And where is there a debug msg?

Ahh btw, I done a second version of this spell, there the splits rotate around each axes. But the performance isn't so good like this one. But when you like to see it, I can send it.

cedi
 

Rmx

Rmx

Level 19
Joined
Aug 27, 2007
Messages
1,164
Damn this spell is of the HOOK !!!

I wish i could give you more rep, AWESOME and Amazing spell :D

5/5 for sure !

But one improvement .. the Starting Ball should be changed coz it looks bad .. but the ROTATING balls are AWESOME !! and i see how you made the rotation even more AMAZING !!

This link is going into my favourites !
 
Level 17
Joined
Sep 8, 2007
Messages
994
Wow the concept of this spell is great. The only problem I have with this - it is a little bit overpowered. :eek:
But whatever, since it is easy configurable it's not a big deal ^^
I will NEVER understand all these maths-formulas .... so I won't give it a try for now :p
Well, this spell is awesome, I can't say more than that. 5/5 +rep from me :)
 
Level 17
Joined
Mar 17, 2009
Messages
1,349
cedi said:
And globals can't leak.
Not true.

Global variable COULD (and by could I mean that there's only a possibility) get recycled. Yet, that doesn't mean it can't leak.

Actually, indexed variables happen to leak if not nulled.

Why? The index would reach a max. value sometimes of - take 50 for example - and from thereon only reach 5. 45 leaks till the end of the game.

So in the end, I must tell you, null your globals (specially the indexed ones).


About the spell, nice orbiting you've got there. Yet about the idea, meh... must say not impressive.

Also, just as a nice funky idea (yeah I used the word funky :p) ummm... try giving each set of those missiles a vertex coloring :p

I tried green, seemed nice. Go for red, green & blue. :)


EDIT:
& oh, try not using lightning as it looks too, umm... flat :p use some missile which leaves a trail and move it quickly, or make something more creative :)
 
Level 10
Joined
May 19, 2008
Messages
176
It doesn't something impresive? Because it doesn't spam 100000000000000000 importet effects? When orbiting isn't impresive for you, I guess nothing is. That thingy required a lot of work, and I think it looks cool. May change the effects to something more like a missile, and then follow the way of one missile. Notic something? Yes every missile has an orbit.

@Deuterium you can change it by yourself, I made some new constants for the color of the missile also for the alpha value. So you can create ghost which flie around the middle and attacks with souls :D.

cedi
 
Some minor improvements.

  • GetWidgetLife is faster than GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE ).
  • In your Cast method if you stored GetOwningPlayer( .split ) somewhere, it would save many function calls depending on how much units are inside the group, and how many loops are ran.
  • You don't need to null timers created by TimerUtils.
  • I doubt you need to set caster = null in your create method.
  • Your IsSpell function leaks twice, and GetSpellTargetX/Y were introduced in 1.24, using those would prevent those location leaks.
 
Level 6
Joined
Jun 18, 2011
Messages
147
From looking at the code alone, I don't see anything obvious about it that would make it not work with Reforged. What is the issue you're encountering?

O, wow been so long since I last talked to you. Happy to see you're still here.

In the test map it does not load the game and when saving I get this as an error coming from the spell trigger:
capture1.130541
full

And in my map the first error comes up from the Vector trigger:
full
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
O, wow been so long since I last talked to you. Happy to see you're still here.

In the test map it does not load the game and when saving I get this as an error coming from the spell trigger:
capture1.130541
full

And in my map the first error comes up from the Vector trigger:
full
I am not able to see your pictures. Not sure how you uploaded them. Can you either paste them in plain text or use a different image host?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
In that case replace the Vector script with the below and it would fix those errors:

JASS:
library VectorLib

    globals
        private location loc = Location(0.0,0.0)
    endglobals

    struct vector
        real x
        real y
        real z
      
        static method create takes real x, real y, real z returns vector
            local vector v = vector.allocate()
            set v.x=x
            set v.y=y
            set v.z=z
            return v
        endmethod
      
        method getLength takes nothing returns real
          return SquareRoot(.x*.x + .y*.y + .z*.z)
        endmethod
      
        static method sum takes vector augend, vector addend returns vector
            local vector v = vector.allocate()
            set v.x = augend.x+addend.x
            set v.y = augend.y+addend.y
            set v.z = augend.z+addend.z
            return v
        endmethod
        method add takes vector addend returns nothing
            set this.x=this.x+addend.x
            set this.y=this.y+addend.y
            set this.z=this.z+addend.z
        endmethod
      
        static method difference takes vector minuend, vector subtrahend returns vector
            local vector v = vector.allocate()
            set v.x = minuend.x-subtrahend.x
            set v.y = minuend.y-subtrahend.y
            set v.z = minuend.z-subtrahend.z
            return v
        endmethod
        method subtract takes vector subtrahend returns nothing
            set this.x=this.x-subtrahend.x
            set this.y=this.y-subtrahend.y
            set this.z=this.z-subtrahend.z
        endmethod
      
        method scale takes real factor returns nothing
            set this.x=this.x*factor
            set this.y=this.y*factor
            set this.z=this.z*factor
        endmethod
      
        method setLength takes real length returns nothing
            local real l = SquareRoot(.x*.x + .y*.y + .z*.z)
            if l == 0.0 then
                debug call BJDebugMsg("Attempted to set the length of a vector with no length!")
                return
            endif
            set l = length/l
            set this.x = this.x*l
            set this.y = this.y*l
            set this.z = this.z*l
        endmethod
      
        static method dotProduct takes vector a, vector b returns real
            return (a.x*b.x+a.y*b.y+a.z*b.z)
        endmethod
      
        static method crossProduct takes vector a, vector b returns vector
            local vector v = vector.allocate()
            set v.x = a.y*b.z - a.z*b.y
            set v.y = a.z*b.x - a.x*b.z
            set v.z = a.x*b.y - a.y*b.x
            return v
        endmethod
      
        static method projectionVector takes vector projected, vector direction returns vector
            local vector v = vector.allocate()
            local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
            if l == 0.0 then
                call v.destroy()
                debug call BJDebugMsg("Attempted to project onto a vector with no length!")
                return 0
            endif
            set l = (projected.x*direction.x+projected.y*direction.y+projected.z*direction.z) / l
            set v.x = direction.x*l
            set v.y = direction.y*l
            set v.z = direction.z*l
            return v
        endmethod
        method projectVector takes vector direction returns nothing
            local real l = direction.x*direction.x+direction.y*direction.y+direction.z*direction.z
            if l == 0.0 then
                debug call BJDebugMsg("Attempted to project onto a vector with no length!")
                return
            endif
            set l = (this.x*direction.x+this.y*direction.y+this.z*direction.z) / l
            set this.x = direction.x*l
            set this.y = direction.y*l
            set this.z = direction.z*l
        endmethod

        static method projectionPlane takes vector projected, vector normal returns vector
            local vector v = vector.allocate()
            local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
            if l == 0.0 then
                call v.destroy()
                debug call BJDebugMsg("Attempted to project onto an undefined plane!")
                return 0
            endif
            set l = (projected.x*normal.x+projected.y*normal.y+projected.z*normal.z) / l
            set v.x = projected.x - normal.x*l
            set v.y = projected.y - normal.y*l
            set v.z = projected.z - normal.z*l
            return v
        endmethod
        method projectPlane takes vector normal returns nothing
            local real l = normal.x*normal.x+normal.y*normal.y+normal.z*normal.z
            if l == 0.0 then
                debug call BJDebugMsg("Attempted to project onto an undefined plane!")
                return
            endif
            set l = (this.x*normal.x+this.y*normal.y+this.z*normal.z) / l
            set this.x = this.x - normal.x*l
            set this.y = this.y - normal.y*l
            set this.z = this.z - normal.z*l
        endmethod

        static method getAngle takes vector a, vector b returns real
            local real l = SquareRoot(a.x*a.x + a.y*a.y + a.z*a.z)*SquareRoot(b.x*b.x + b.y*b.y + b.z*b.z)
            if l == 0 then
                debug call BJDebugMsg("Attempted to get angle between vectors with no length!")
                return 0.0
            endif
            return Acos((a.x*b.x+a.y*b.y+a.z*b.z)/l) //angle is returned in radians
        endmethod
      
        method rotate takes vector axis, real angle returns nothing //angle is taken in radians
            local real xx
            local real xy
            local real xz
            local real yx
            local real yy
            local real yz
            local real zx
            local real zy
            local real zz
            local real al = axis.x*axis.x+axis.y*axis.y+axis.z*axis.z //axis length^2
            local real f
            local real c = Cos(angle)
            local real s = Sin(angle)
            if al == 0.0 then
                debug call BJDebugMsg("Attempted to project onto a vector with no length!")
                return
            endif
            set f = (this.x*axis.x+this.y*axis.y+this.z*axis.z) / al
            set zx = axis.x*f
            set zy = axis.y*f
            set zz = axis.z*f //axis component of rotated vector
            set xx = this.x-zx
            set xy = this.y-zy
            set xz = this.z-zz //component of vector perpendicular to axis
            set al = SquareRoot(al)
            set yx = (axis.y*xz - axis.z*xy)/al
            set yy = (axis.z*xx - axis.x*xz)/al //y same length as x by using cross product and dividing with axis length
            set yz = (axis.x*xy - axis.y*xx)/al //x,y - coordinate system in which we rotate
            set this.x=xx*c+yx*s+zx
            set this.y=xy*c+yy*s+zy
            set this.z=xz*c+yz*s+zz
        endmethod
      
        static method createTerrainPoint takes real x, real y returns vector
            local vector v = vector.allocate()
            call MoveLocation(loc,x,y)
            set v.x=x
            set v.y=y
            set v.z=GetLocationZ(loc)
            return v
        endmethod
        method getTerrainPoint takes real x, real y returns nothing
            call MoveLocation(loc,x,y)
            set this.x=x
            set this.y=y
            set this.z=GetLocationZ(loc)
        endmethod

        static method createTerrainNormal takes real x, real y, real sampleRadius returns vector
            local vector v = vector.allocate()
            local real z1
            local real z2
            local real z3
            local real z4
            call MoveLocation(loc, x-sampleRadius, y)
            set z1=GetLocationZ(loc)
            call MoveLocation(loc, x+sampleRadius, y)
            set z2=GetLocationZ(loc)
            call MoveLocation(loc, x, y-sampleRadius)
            set z3=GetLocationZ(loc)
            call MoveLocation(loc, x, y+sampleRadius)
            set z4=GetLocationZ(loc)
            set sampleRadius=2*sampleRadius
            set v.x = (z1-z2)*sampleRadius
            set v.y = (z3-z4)*sampleRadius
            set v.z = sampleRadius*sampleRadius
            return v
        endmethod
        method getTerrainNormal takes real x, real y, real sampleRadius returns nothing
            local real z1
            local real z2
            local real z3
            local real z4
            call MoveLocation(loc, x-sampleRadius, y)
            set z1=GetLocationZ(loc)
            call MoveLocation(loc, x+sampleRadius, y)
            set z2=GetLocationZ(loc)
            call MoveLocation(loc, x, y-sampleRadius)
            set z3=GetLocationZ(loc)
            call MoveLocation(loc, x, y+sampleRadius)
            set z4=GetLocationZ(loc)
            set sampleRadius=2*sampleRadius
            set this.x = (z1-z2)*sampleRadius
            set this.y = (z3-z4)*sampleRadius
            set this.z = sampleRadius*sampleRadius
        endmethod

        method isInCylinder takes vector cylinderOrigin, vector cylinderHeight, real cylinderRadius returns boolean
            local real l

            local real x = this.x-cylinderOrigin.x
            local real y = this.y-cylinderOrigin.y
            local real z = this.z-cylinderOrigin.z
            if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z < 0.0 then //point below cylinder
                return false
            endif
          
            set x = x-cylinderHeight.x
            set y = y-cylinderHeight.y
            set z = z-cylinderHeight.z
            if x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z > 0.0 then //point above cylinder
                return false
            endif
          
            set l = cylinderHeight.x*cylinderHeight.x+cylinderHeight.y*cylinderHeight.y+cylinderHeight.z*cylinderHeight.z
            if l == 0.0 then
                debug call BJDebugMsg("Cylinder with no height!")
                return false
            endif
            set l = (x*cylinderHeight.x+y*cylinderHeight.y+z*cylinderHeight.z) / l
            set x = x - cylinderHeight.x*l
            set y = y - cylinderHeight.y*l
            set z = z - cylinderHeight.z*l
            if x*x+y*y+z*z > cylinderRadius*cylinderRadius then //point outside cylinder
                return false
            endif
          
            return true
        endmethod

        method isInCone takes vector coneOrigin, vector coneHeight, real coneRadius returns boolean
            local real l

            local real x = this.x-coneOrigin.x
            local real y = this.y-coneOrigin.y
            local real z = this.z-coneOrigin.z
            if x*coneHeight.x+y*coneHeight.y+z*coneHeight.z < 0.0 then //point below cone
                return false
            endif
          
            set l = coneHeight.x*coneHeight.x+coneHeight.y*coneHeight.y+coneHeight.z*coneHeight.z
            if l == 0.0 then
                debug call BJDebugMsg("cone with no height!")
                return false
            endif
            set l = (x*coneHeight.x+y*coneHeight.y+z*coneHeight.z) / l
            set x = x - coneHeight.x*l
            set y = y - coneHeight.y*l
            set z = z - coneHeight.z*l
            if SquareRoot(x*x+y*y+z*z) > coneRadius*(1.0-l) then //point outside cone
                return false
            endif
          
            return true
        endmethod

        method isInSphere takes vector sphereOrigin, real sphereRadius returns boolean
            if sphereRadius*sphereRadius < ((this.x-sphereOrigin.x)*(this.x-sphereOrigin.x)+(this.y-sphereOrigin.y)*(this.y-sphereOrigin.y)+(this.z-sphereOrigin.z)*(this.z-sphereOrigin.z)) then
                return false
            endif
            return true
        endmethod
    endstruct

endlibrary
 
Top