• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[vJASS] Making dummy unit face angle instantly

Status
Not open for further replies.
Level 2
Joined
Jun 5, 2014
Messages
11
How can you force a dummy unit to face a specific angle instantly?

I have a missile system which recycles dummy units. SetUnitFacing and all other functions don't work.

I've tried Vexorian's dummy model and trick, but its not working for me :O

An alternative is storing a dummy in a hashtable, then instantly restoring them with angle. Some people say hashtables are slow, so idk.

Any help?
 
They are not slow, they are only slow-er compared to other methods.

But I don't see why SetUnitFacing doesn't work for you. Have a check by replacing a Footman model with the missile and see if it has a forward facing, upon movement order. If not, maybe it is based off ribbons and it's not meant to have a solid facing.

Also make sure that the second parameter of SetUnitFacing is 0.
 
Level 2
Joined
Jun 5, 2014
Messages
11
nope not working :(

SetUnitFacing works, its just that its not "instant"

Im attaching special effects to the dummy and move them so they look like a missile. problem is when the unit is called, its not facing the direction instantly, making them look weird for the first 1-2 seconds upon casting because theyre still turning.
 
Level 2
Joined
Jun 5, 2014
Messages
11
Yep, tried that, though I'm not sure if I implemented it wrong since theres no test map or something.

The angle is inaccurate, and sometimes it looks weird.
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
Did you try to implement this from vexorian's dummy model or the model which grim001 added to topic?
 
Level 2
Joined
Jun 5, 2014
Messages
11
Both, however the one grim001 uploaded didn't even show the special effect at all.

I checked it and it had no bones / attachment points

I'm using vexorian's dummy model, replaced Bone_Root to Bone_Head just like his tutorial :(
 
Last edited:
Level 12
Joined
Feb 22, 2010
Messages
1,115
There is a map DummyTest at #12 post, did you check that?I will look also this dummy thing when I comeback.
 
Level 2
Joined
Jun 5, 2014
Messages
11
Yep I did, but WE says

"Main map file could not be opened."

I tried opening with regular WE and still the error appears :( Weird how no one mentions anything about the error :O
 
I made a really, really compact dummy recycler earlier to deal with this exact issue. It looks a bit crude, but it works like a charm and is propably faster than your hashtable approach:

JASS:
library dummyRecyclers initializer Init
    globals
        private constant integer NUM_ANGLES = 12 //THE AMMOUNT OF ANGLES STORED
        private constant integer DUMMY_ID = 'dumm' //UNIT ID OF YOUR DUMMY
        private constant real ANGLE = 360/NUM_ANGLES //DO NOT CHANGE
        private unit temp
        private group array dummyPools[NUM_ANGLES]
    endglobals
    
    function NewDummy takes real x, real y, real z, real a returns unit
        local integer i = ModuloInteger(R2I((a/ANGLE)+0.5), R2I(ANGLE))
        set temp = FirstOfGroup(dummyPools[i])
        if temp==null then
            set temp = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_ID,x,y,a)
            call UnitAddAbility(temp,'Amrf') //ALLOWS YOU TO ADJUST HEIGHT OF GROUND UNITS
            call UnitAddAbility(temp,'Aloc') //MAKE THE DUMMY UNSELECTABLE
            call UnitRemoveAbility(temp, 'Amrf')
            call SetUnitPathing(temp,false)
        else
            call GroupRemoveUnit(dummyPools[i],temp)
        endif
        call SetUnitFlyHeight(temp,z,0)
        call SetUnitFacing(temp, a)
        call SetUnitX(temp,x)
        call SetUnitY(temp,y)
        return temp
    endfunction
    
    function ReleaseDummy takes unit u returns nothing
        local integer i = R2I((GetUnitFacing(u)/ANGLE)+0.5)
        call GroupAddUnit(dummyPools[i],u)
    endfunction
    
    private function Init takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen i > NUM_ANGLES
            set dummyPools[i] = CreateGroup()
            set i = i + 1
        endloop
    endfunction
endlibrary

I also heard you mention the SetUnitLookAt method in the posts above. To make it work, you have to use SetUnitPosition immediately after you called SetUnitLookAt. You can make amazing things with this, and it is the basis for all kinds of motion in my "Age of Fighting Sail" map.

If you are making a missile system though, i would seriously advice you to base it off vectors. Then you could just use the vector scalars in the offset fields of SetUnitLookAt, rather than using trigonometry. There are also many different benefits, you will generally find that most problems that seemed complicated with polar coordinates suddenly become very simple. Vectors and quaternion/matrix rotation could ge hard to get into, but once you've learned it, you have learned one of the most important bases of game programming. If you want to learn more about vectors, i strongly suggest you to read Davids tutorial on linear algebra.

If you end up using vectors, i have some great libraries for quaternions and vectors which i could share:

JASS:
library vectors

	struct vector
    
		real xv
		real yv
		real zv
        
        implement optional vectorExtention_Quaternions

		static method create takes real xv, real yv, real zv returns thistype
        
			local thistype this = thistype.allocate()
            
			set .xv = xv
			set .yv = yv
			set .zv = zv
            
			return this
            
		endmethod
        
        method print takes nothing returns nothing
        
            call BJDebugMsg("( "+R2S(.xv)+" | "+R2S(.yv)+" | "+R2S(.zv)+" )")
            
        endmethod

		static method cross takes vector a, vector b returns vector
			//returns a vector perpendicular to the two input vectors. 
			local vector result = vector.allocate()
            
			set result.xv = (a.yv*b.zv)-(a.zv*b.yv)
			set result.yv = (a.zv*b.xv)-(a.xv*b.zv)
			set result.zv = (a.xv*b.yv)-(a.yv*b.xv)
            
			return result
            
		endmethod
        
		static method dot takes vector a, vector b returns real
        
			return (a.xv*b.xv)+(a.yv*b.yv)+(a.zv*b.zv)
            
		endmethod
        
        static method angleBetween takes vector v1, vector v2 returns real
            return Acos(vector.dot(v1, v2))*bj_RADTODEG
        endmethod
        
		method angle takes real theta, real phi returns vector
        
			set .xv = Cos(phi*bj_DEGTORAD)*Cos(theta*bj_DEGTORAD)
			set .yv = Cos(phi*bj_DEGTORAD)*Sin(theta*bj_DEGTORAD)
			set .zv = Sin(phi*bj_DEGTORAD)
            
            return this
            
		endmethod

		method add takes vector v returns vector
        
			set .xv = .xv+v.xv
			set .yv = .yv+v.yv
			set .zv = .zv+v.zv
            
            return this
            
		endmethod

		method sub takes vector v returns vector
        
			set .xv = .xv-v.xv
			set .yv = .yv-v.yv
			set .zv = .zv-v.zv
            
            return this
            
		endmethod
        
		method multiply takes vector v returns vector
        
            set .xv = .xv*v.xv
            set .yv = .yv*v.yv
            set .zv = .zv*v.zv
            
            return this
            
        endmethod

		method scale takes real mod returns vector
        
			set .xv = .xv*mod
			set .yv = .yv*mod
			set .zv = .zv*mod
            
            return this
            
		endmethod
        
        method setTo takes vector v returns vector
        
            set .xv = v.xv
            set .yv = v.yv
            set .zv = v.zv
            
            return this
            
        endmethod
        
        method setXYZ takes real x, real y, real z returns vector
        
            set .xv = x
            set .yv = y
            set .zv = z
            
            return this
    
        endmethod
        
        method zero takes nothing returns vector
        
            set .xv = 0
            set .yv = 0
            set .zv = 0
            
            return this
            
        endmethod

		method normalize takes nothing returns vector
        
			local real l = .length()
            if l!=0. and l != 1 then
                set .xv = .xv/l
                set .yv = .yv/l
                set .zv = .zv/l
            endif
            
            return this
            
		endmethod
        
		method invert takes nothing returns vector
        
			set .xv = -.xv
			set .yv = -.yv
			set .zv = -.zv
            
            return this
            
		endmethod
        
        method copy takes nothing returns vector
        
            return vector.create(.xv,.yv,.zv)
            
        endmethod

		method length takes nothing returns real
        
			return SquareRoot((.xv*.xv)+(.yv*.yv)+(.zv*.zv))
            
		endmethod
        
		method lengthSquared takes nothing returns real
        
			return (.xv*.xv)+(.yv*.yv)+(.zv*.zv)
            
		endmethod
        
		method lengthXY takes nothing returns real
        
			return SquareRoot((.xv*.xv)+(.yv*.yv))
            
		endmethod
        
        static method reflect takes vector direction, vector normal returns vector
        
            local vector result = vector.create(0, 0, 0)
            local real scale = -2 * vector.dot(normal, direction)

            set result.xv = direction.xv + (normal.xv * scale)
            set result.yv = direction.yv + (normal.yv * scale)
            set result.zv = direction.zv + (normal.zv * scale)

            return result
            
        endmethod
        
    endstruct
    
    module quaternionExtention_Vectors
    
        method rotateByVectorScaled takes vector v, real scale returns nothing
    
            local quaternion w = quaternion.createAxisAngleScaled(v,scale)
            
            call w.multiply(this)
            set .x = w.x
            set .y = w.y
            set .z = w.z
            set .w = w.w
            call w.destroy()
            
        endmethod
        
        static method createAxisAngleEx takes vector v returns quaternion
        
            local real a = v.length()
            local real sin = Sin(a*.5)
            local real cos = Cos(a*.5)
            
            if a==0. then
                set a=1.
            endif
            
            return quaternion.create(v.xv/a*sin,v.yv/a*sin,v.zv/a*sin,cos)
            
        endmethod
        
        static method createAxisAngle takes vector v, real a returns quaternion

            local real sin = Sin(a*.5)
            local real cos = Cos(a*.5)
            
            return quaternion.create(v.xv*sin, v.yv*sin, v.zv*sin, cos)
            
        endmethod
        
        static method createAxisAngleScaled takes vector v, real scale returns quaternion
        
            local real a = v.length()
            local real sin = Sin(a*scale*.5)
            local real cos = Cos(a*scale*.5)
            if a==0. then
                set a=1.
            endif
            
            return quaternion.create(v.xv/a*sin,v.yv/a*sin,v.zv/a*sin,cos)
            
        endmethod
        
        method getRoll takes nothing returns real
            local vector x = vector.create(1,0,0).rotateByQuaternion(this)
            local vector z = vector.create(0,0,1)
            local vector normal
            local vector zNoRoll
            local real r
            
            set normal = vector.cross(x,z)
            call z.rotateByQuaternion(this)
            set zNoRoll = vector.cross(x,normal).normalize()
            set r = vector.dot(z,zNoRoll)
            
            // Prevent rounding errors
            if r<=-1 then
                set r = bj_PI
            elseif r>=1 then
                set r = 0
            else
                set r = Acos(r)
            endif
            if vector.dot(z,normal)<0 then
                set r = -r
            endif
            set r = bj_PI-r
            
            call zNoRoll.destroy()
            call normal.destroy()
            call z.destroy()
            call x.destroy()
            
            return r
        endmethod
    endmodule
		
endlibrary

JASS:
library quaternions
    struct quaternion
        
        // q = ( x*i + y*j + z*k + w )
        
        real x
        real y
        real z
        real w
        
        implement optional quaternionExtention_Vectors
        
        method print takes nothing returns nothing
            call BJDebugMsg("( "+R2S(.x)+" | "+R2S(.y)+" | "+R2S(.z)+" | "+R2S(.w)+" )")
        endmethod
        
        method conjugate takes nothing returns quaternion
            set .x = -.x
            set .y = -.y
            set .z = -.z
            return this
        endmethod
        
        method scale takes real scalar returns quaternion
            set .x = .x*scalar
            set .y = .y*scalar
            set .z = .z*scalar
            set .w = .w*scalar
            return this
        endmethod
        
        method normalize takes nothing returns quaternion
            local real l = SquareRoot(.x*.x+.y*.y+.z*.z+.w*.w)
            if l!=0. then
                set .x = .x/l
                set .y = .y/l
                set .z = .z/l
                set .w = .w/l
            endif
            return this
        endmethod
        
        method setTo takes quaternion q2 returns quaternion
            set .x = q2.x
            set .y = q2.y
            set .z = q2.z
            set .w = q2.w
            return this
        endmethod
        
        method add takes quaternion q2 returns quaternion
            set .x = .x + q2.x
            set .y = .y + q2.y
            set .z = .z + q2.z
            set .w = .w + q2.w
            return this
        endmethod
        
        method multiply takes quaternion q2 returns quaternion
            local real x =  .x * q2.w + .y * q2.z - .z * q2.y + .w * q2.x
            local real y = -.x * q2.z + .y * q2.w + .z * q2.x + .w * q2.y
            local real z =  .x * q2.y - .y * q2.x + .z * q2.w + .w * q2.z
            local real w = -.x * q2.x - .y * q2.y - .z * q2.z + .w * q2.w
            set .x = x
            set .y = y
            set .z = z
            set .w = w
            return this
        endmethod
        
        method setXYZW takes real x, real y, real z, real w returns quaternion
            set .x = x
            set .y = y
            set .z = z
            set .w = w
            return this
        endmethod
        
        method copy takes nothing returns quaternion
            local quaternion q = quaternion.allocate()
            set q.x = .x
            set q.y = .y
            set q.z = .z
            set q.w = .w
            return q
        endmethod
        
        method setEuler takes real roll, real pitch, real yaw returns quaternion
            local real Sin0 
            local real Cos0
            local real Sin1 = Sin(pitch*.5)
            local real Cos1 = Cos(pitch*.5)
            local real Sin2
            local real Cos2
            
            if yaw == 0 then
                set Sin2 = 0
                set Cos2 = .5
            else
                set Sin2 = Sin(yaw*.5)
                set Cos2 = Cos(yaw*.5)
            endif
            
            if roll == 0 then
                set Sin0 = 0
                set Cos0 = .5
            else
                set Sin0 = Sin(roll*.5)
                set Cos0 = Cos(roll*.5)
            endif
            
            set .x = Sin0 * Cos1 * Cos2 - Cos0 * Sin1 * Sin2
            set .y = Cos0 * Sin1 * Cos2 + Sin0 * Cos1 * Sin2
            set .z = Cos0 * Cos1 * Sin2 - Sin0 * Sin1 * Cos2
            set .w = Cos0 * Cos1 * Cos2 + Sin0 * Sin1 * Sin2
            
            return this
        endmethod
        
        method getRollEx takes nothing returns real
            local real sqw = .w*.w
            local real sqx = .x*.x
            local real sqy = .y*.y
            local real sqz = .z*.z
            
            local real u = sqx + sqy + sqz +sqw
            local real test = .x*.y + .z*.w
            
            if test > 0.4999*u then
                //call BJDebugMsg("Case 1")
                return 0
                
            elseif test < -0.4999*u then
                //call BJDebugMsg("Case 2")
                return 0
                
            endif
            
            //call BJDebugMsg("Case 3")
            
            return Atan2(2*.x*.w -2*.y*.z, -sqx +sqy -sqz +sqw)*bj_RADTODEG
            
        endmethod
        
        static method createEuler takes real roll, real pitch, real yaw returns quaternion
            local real Sin0 
            local real Cos0
            local real Sin1 = Sin(pitch*.5)
            local real Cos1 = Cos(pitch*.5)
            local real Sin2
            local real Cos2
            
            if yaw == 0 then
                set Sin2 = 0
                set Cos2 = .5
            else
                set Sin2 = Sin(yaw*.5)
                set Cos2 = Cos(yaw*.5)
            endif
            
            if roll == 0 then
                set Sin0 = 0
                set Cos0 = .5
            else
                set Sin0 = Sin(roll*.5)
                set Cos0 = Cos(roll*.5)
            endif
            
            return quaternion.create(Sin0 * Cos1 * Cos2 - Cos0 * Sin1 * Sin2,Cos0 * Sin1 * Cos2 + Sin0 * Cos1 * Sin2,Cos0 * Cos1 * Sin2 - Sin0 * Sin1 * Cos2,Cos0 * Cos1 * Cos2 + Sin0 * Sin1 * Sin2)
        endmethod
        
        static method createMult takes quaternion q1, quaternion q2 returns quaternion
            local quaternion q = quaternion.allocate()
            set q.x =  q1.x * q2.w + q1.y * q2.z - q1.z * q2.y + q1.w * q2.x
            set q.y = -q1.x * q2.z + q1.y * q2.w + q1.z * q2.x + q1.w * q2.y
            set q.z =  q1.x * q2.y - q1.y * q2.x + q1.z * q2.w + q1.w * q2.z
            set q.w = -q1.x * q2.x - q1.y * q2.y - q1.z * q2.z + q1.w * q2.w
            return q
        endmethod
        
        static method create takes real x, real y, real z, real w returns quaternion
            local quaternion q = quaternion.allocate()
            set q.x = x
            set q.y = y
            set q.z = z
            set q.w = w
            return q
        endmethod
    endstruct
    
    module vectorExtention_Quaternions
        method rotateByQuaternion takes quaternion q returns vector
            // r = q*v
            local real x =  q.y * .zv - q.z * .yv + q.w * .xv
            local real y = -q.x * .zv + q.z * .xv + q.w * .yv
            local real z =  q.x * .yv - q.y * .xv + q.w * .zv
            local real w = -q.x * .xv - q.y * .yv - q.z * .zv
            
            // v = r*q'
            set .xv =  x * q.w - y * q.z + z * q.y - w * q.x
            set .yv =  x * q.z + y * q.w - z * q.x - w * q.y
            set .zv = -x * q.y + y * q.x + z * q.w - w * q.z
            return this
        endmethod
    
        method rotateByQuaternionInv takes quaternion q returns vector
            // r = q'*v
            local real x = -q.y * .zv + q.z * .yv + q.w * .xv
            local real y =  q.x * .zv - q.z * .xv + q.w * .yv
            local real z = -q.x * .yv + q.y * .xv + q.w * .zv
            local real w =  q.x * .xv + q.y * .yv + q.z * .zv
            
            // v = r*q
            set .xv =  x * q.w + y * q.z - z * q.y + w * q.x
            set .yv = -x * q.z + y * q.w + z * q.x + w * q.y
            set .zv =  x * q.y - y * q.x + z * q.w + w * q.z
            return this
        endmethod
    
        method addRotatedByQuaternion takes vector v, quaternion q returns vector
            // r = q*v
            local real x =  q.y * v.zv - q.z * v.yv + q.w * v.xv
            local real y = -q.x * v.zv + q.z * v.xv + q.w * v.yv
            local real z =  q.x * v.yv - q.y * v.xv + q.w * v.zv
            local real w = -q.x * v.xv - q.y * v.yv - q.z * v.zv
            
            // v = r*q'
            set .xv =  .xv + x * q.w - y * q.z + z * q.y - w * q.x
            set .yv =  .yv + x * q.z + y * q.w - z * q.x - w * q.y
            set .zv =  .zv - x * q.y + y * q.x + z * q.w - w * q.z
            return this
        endmethod
    endmodule

endlibrary
 
Level 2
Joined
Jun 5, 2014
Messages
11
Thanks for sharing, but I was thinking of a different approach from storing dummy units in regards to their angles.

Like just having an array of units, call them whenever a missile is fired, set their angle upon calling(instantly), then return them back to the array after the missile ends.

Is it possible? :O
 
Level 2
Joined
Jun 5, 2014
Messages
11
thanks so much, but everything is okay except the facing angle stuff which is not instant. nice map btw, reminds me of a game where you fight pirate ships with your own ship (i forgot the title) :)

I know its too much to ask but, can I please have an example where you used the SetUnitLookAt using Vexorian's dummy?
 
Alright, i wrote a piece of sample code. Ir requires this linked list module. I have not tested it yet, but like i said it was just to show how you could write a neat and readable projectile script with vectors in an OOP-stype manner. I have some really neat methods for making the missiles homing too, if you should ever be interrested.

JASS:
library Projectiles requires ListModule, vectors, quaternions 

    globals
        private constant real GRAVITY = 9.82 //ADJUST TO YOUR NEED
        private constant real INTERVAL = 0.03 //UPDATE RATE
        private constant real BOUNCE_FACTOR = 0.85 //VELOCITY LOST AT BOUNCE
        private constatn real AIR_RESISTANCE = 0.97
        
        private constant integer DUMMY_ID = 'dumm'

        private location LOC = Location(0,0)
    endglobals
    
    function GetTerrainZ takes real x, real y returns real
        call MoveLocation(LOC,x,y)
        return GetLocationZ(LOC)
    endfunction
    
    function GetTerrainNormal takes real x, real y returns vector
        local real z
        local real radius = 8.
        local vector v = vector.create(0,0,0)
        
        set z = GetTerrainZ(x-radius,y)
        set v.xv = z-GetTerrainZ(x+radius,y)
        set z = GetTerrainZ(x,y-radius)
        set v.yv = z-GetTerrainZ(x,y+radius)
        set v.zv = radius*2
        call v.normalize() //NORMALIZE METHOD MAKES SURE THE LENGTH OF THE VECTOR IS 1. 
        
        return v
    endfunction
    
    struct projclass
        boolean isHoming = false //THIS STRUCT CAN BE FILLED WITH ALL THE DATA YOU NEED. CREATE THE CLASSES AS GLOBALS ON STARTUP.
        boolean useGravity = false
        boolean doesBounce = false
        real damage = 10
    endstruct

    struct projectile
    
        implement List
        
        unit u
        effect e
        
        projclass class
        quaternion dir //WE DON'T USE QUATERNIONS MUCH IN THIS SAMPLE, BUT IF YOU WANT HOMING MISSILES YOU WILL NEED THEM.
        
        vector pos
        vector vel
        
        static method create takes string path, projclass c, real x, real y, real z, real pitch, real yaw, real vel returns thistype
            local thistype this = thistype.allocate()
            
            call .listAdd() //ADD THE PROJECTILE TO THE LINKED LIST
            
            set .u = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, x, y, yaw) 
            //....ALSO REMEMBER TO ADD LOCUST, RAVEN FORM ETC
            set .e = AddSpecialEffectTarget(path, .u, "origin")
            set .class = c
            
            set .dir = quaternion.createEuler(0, pitch*bj_DEGTORAD, yaw*bj_DEGTORAD) //REMEMBER THAT QUATERNIONS TAKE RADIANS
            set .pos = vector.create(x,y,z)
            set .vel = vector.create(vel, 0, 0).rotateByQuaternion(.dir) //THIS ROTATES THE VELOCITY VECTOR IN THE DIRECTION OF THE MISSILE
            
            return this
        endmethod
        
        method onDestroy takes nothing returns nothing
            call RemoveUnit(.u)
            call DestroyEffect(.e)
            call .pos.destroy()
            call .vel.destroy()
            call .dir.destroy()
            call .listRemove()
        endmethod
        
        method bounce takes nothing returns nothing
            local vector normal = GetTerrainNormal(.pos.xv, .pos.yv)
            local vector newvel = vector.reflect(.vel, normal) //THE REFLECT METHOD IS VERY EFFECTIVE AT MAKING BOUNCE EFFECTS.
            //REMEMBER THAT YOU CAN REFLECT A VECTOR AGAINST ANY NORMAL, LIKE THE NORMAL OF A WALL!!
            
            call .vel.setTo(newvel).scale(BOUNCE_FACTOR) //WE WANT TO LOSE SOME MOMENTUM FROM THE BOUNCE
            call normal.destroy()
            call newvel.destroy()
            //ALWAYS REMEMBER TO DESTROY ANY LOCAL VECTORS YOU USE, OR ELSE THEY WILL OVERFLOW
        endmethod
        
        method explode takes nothing returns nothing
            //ADD EFFECTS ETC
            call .destroy()
        endmethod
        
        static method update takes nothing returns nothing
            local thistype this = .first 
            local real tz = 0
            
            loop
                exitwhen this == 0
                
                set tz = GetTerrainZ(.pos.xv, .pos.yv)
                
                set .vel.zv = .vel.zv-GRAVITY //ADD GRAVITY TO MAKE IT FALL
                
                call .vel.scale(AIR_RESISTANCE) //YOU CAN ADD A CHECK TO THIS, IF YOU WANT YOUR PROJECTILE CLASS TO IGNORE AIR RESISTANCE
                call .pos.add(.vel) //ADD VELOCITY TO POSITION
                
                if .pos.zv < tz then
                    set .pos.zv = tz //MAKE SURE IT DOES NOT CLIP THROUGH THE GROUND
                    if .class.doesBounce then //IF IT HITS THE GROUND, BOUNCE OR EXPLODE
                        call .bounce()
                    else
                        call .explode()
                    endif
                endif
                
                //DO SOME COLLISION. THIS CAN BE APPROACHED IN MANY WAYS
                
                //UPDATE ORIENTATION
                call SetUnitLookAt(.u, "bone_head", .u, v.xv*100, v.yv*100, v.zv*100)
                call SetUnitPosition(.u, .pos.xv, .pos.yv)
                call SetUnitFlyHeight(.u, .pos.zv-tz, 0)
                
                set this = .next //THIS IS HOW YOU ITERATE THROUGH A LINKED LIST
            endloop

        endmethod
        
        static method onInit takes nothing returns nothing
            call TimerStart(CreateTimer(), INTERVAL, true, function thistype.update)
        endmethod
    endstruct

endlibrary
 
Last edited:
Level 2
Joined
Jun 5, 2014
Messages
11
well, turns out you just really cant change unit facing directly :/

ive searched everywhere and the closest you can achieve is the one they are using: angular dummy preloading and whatnot

i guess ill just have to use recycled dummies on circular projectiles that don't really matter where the dummy is facing (think of orbs), and just creating a new unit if it needs a to be straight line (like arrows)

thanks for the help anyways, gonna try to understand them sometime :D
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
I hope I am not misunderstanding what you want.

Can you test this map?
 

Attachments

  • DummyFace.w3x
    24.7 KB · Views: 75
Level 2
Joined
Jun 5, 2014
Messages
11
i used your dummy model and everything was okay now

turns out I wasn't using radians, didn't know that
but I don't think radians/angles don't affect turn rate, so I don't know what fixed that lol

anyways, Thanks so much :)

Edit: On a side note, is there any speed difference between calling UnitAddAbility on map init vs adding the ability manually in the Object Editor?
 
Last edited:
Level 12
Joined
Feb 22, 2010
Messages
1,115
Just add locust from object editor.

Btw can you add dummy to that wc3c topic I don't think I have an account there.
 
Status
Not open for further replies.
Top