System MoveSpeedX

Jesus4Lyf

Good Idea™
Reaction score
397
MoveSpeedX​
Version 1.0.1​

Requirements:
- Jass NewGen
- AIDS
- Key Timers 2

JASS:
//
//                             _____          _____
//        __  __  ___ _    ____\_   \        /    /
//       /  |/  |/ _ \ \  / /  __|    \    /    /
//      / / | / | (_) | \/ /|  __| \    \/    /
//     /_/|__/|_|\___/_\__/_|____|_  \      /
//          / __\  _ \  __|  __|   \ /      \         By Jesus4Lyf
//          \__ \  __/  __|  __| |) |   /\    \
//          \___/_|  |____|____|___/  /    \    \          v 1.0.1
//                             /____/        \____\
//      What is MoveSpeedX?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          MoveSpeedX allows you to modify a unit's movement speed, either by a
//          factor of its current speed or by a pure amount. It is possible to disobey
//          the 522 movement speed limit in Warcraft III in this way.
//
//          Please note that setting the speed too high will bug waypoints.
//          
//      How to implement?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Create a new trigger object called MoveSpeedX, go to 'Edit -> Convert to
//          Custom Text', and replace everything that's there with this script.
//
//      Functions:
//     ¯¯¯¯¯¯¯¯¯¯¯¯
//          function MSX_AddSpeedPure takes unit whichUnit, real speed returns nothing
//          function MSX_RemoveSpeedPure takes unit whichUnit, real speed returns nothing
//              - Adds or removes a pure amount of speed from the unit.
//
//          function MSX_AddSpeedFactor takes unit whichUnit, real factor returns nothing
//          function MSX_RemoveSpeedFactor takes unit whichUnit, real factor returns nothing
//              - Adds or removes a factor of speed from the unit.
//                For example, to add 10% movement speed to unit u, you would
//                call MS_AddSpeedFactor(u, 0.1).
//              - This stacks incrementally. So +10% +10% = +20%.
//              - This factor does not increase pure speed, only the unit's
//                speed outside of this system (so it does include buffs).
//
//          function MSX_GetMoveSpeed takes unit whichUnit returns real
//              - Returns the unit's move speed, inclusive of MoveSpeedX bonuses.
//          
//      Thanks:
//     ¯¯¯¯¯¯¯¯¯
//          - Frozenhelfir for the idea.
//
library MSX uses AIDS, KT
    globals
    //=================================================================
    //  This is the period on which all units will be run.
    // If you lower this value, movement bonuses will be smoother,
    // but will require more processing power (lag more).
    //  Also, the lower this is, the higher the move speed can be
    // before it starts bugging on waypoints. The lowest valid
    // period is 0.00125. A period of 0.00625 is very robust.
        private constant real PERIOD=0.03125
    //=================================================================
    endglobals
    //=================================================================
    //  This is a filter that determines whether or not a unit may have
    // its move speed modified. Units that pass this filter will be
    // indexed by AIDS if they have not already been.
    private function VALID_UNITS_FILTER takes unit u returns boolean
        return GetUnitAbilityLevel(u,'Aloc')==0 and not IsUnitType(u,UNIT_TYPE_STRUCTURE)
    endfunction
    //=================================================================
    
    globals//locals
        private unit Unit
        private real X
        private real Y
        private real Xinc
        private real Yinc
        private real Dist
    endglobals
    private struct SpeedData extends array
        real pureBonus
        real factorBonus
        private boolean remove
        private boolean onTimer
        private real x
        private real y
        private static method AIDS_filter takes unit u returns boolean
            return VALID_UNITS_FILTER(u)
        endmethod
        private method AIDS_onCreate takes nothing returns nothing
            set this.pureBonus=0.0
            set this.factorBonus=0.0
        endmethod
        private method AIDS_onDestroy takes nothing returns nothing
            set this.remove=true
        endmethod
        //! runtextmacro AIDS()
        private static method periodic takes nothing returns boolean
            local thistype this=thistype(KT_GetData())
            if this.remove then
                set this.onTimer=false
                return true
            endif
            set Unit=this.unit
            set X=GetUnitX(Unit)
            set Y=GetUnitY(Unit)
            if (not IsUnitPaused(Unit)) and GetUnitAbilityLevel(Unit,'BSTN')==0 and GetUnitAbilityLevel(Unit,'BPSE')==0 then
                if X!=this.x or Y!=this.y then
                    set Xinc=X-this.x
                    set Yinc=Y-this.y
                    if this.factorBonus!=0.0 then
                        set X=X+Xinc*this.factorBonus
                        set Y=Y+Yinc*this.factorBonus
                    endif
                    if this.pureBonus!=0.0 then
                        set Dist=SquareRoot(Xinc*Xinc+Yinc*Yinc)
                        set X=X+Xinc/Dist*this.pureBonus
                        set Y=Y+Yinc/Dist*this.pureBonus
                    endif
                    call SetUnitX(Unit,X)
                    call SetUnitY(Unit,Y)
                endif
            endif
            set this.x=X
            set this.y=Y
            return false
        endmethod
        method checkTimer takes nothing returns nothing
            if not this.onTimer then
                call KT_Add(function thistype.periodic,this,PERIOD)
                set this.onTimer=true
                set this.remove=false
                set this.x=GetUnitX(this.unit)
                set this.y=GetUnitY(this.unit)
            endif
            if this.pureBonus==0.0 and this.factorBonus==0.0 then
                set this.remove=true
            endif
        endmethod
    endstruct
    public function AddSpeedPure takes unit u, real speed returns nothing
        local SpeedData d=SpeedData<u>
        set d.pureBonus=d.pureBonus+speed*PERIOD
        call d.checkTimer()
    endfunction
    public function RemoveSpeedPure takes unit u, real speed returns nothing
        local SpeedData d=SpeedData<u>
        set d.pureBonus=d.pureBonus-speed*PERIOD
        call d.checkTimer()
    endfunction
    public function AddSpeedFactor takes unit u, real factor returns nothing
        local SpeedData d=SpeedData<u>
        set d.factorBonus=d.factorBonus+factor
        call d.checkTimer()
    endfunction
    public function RemoveSpeedFactor takes unit u, real factor returns nothing
        local SpeedData d=SpeedData<u>
        set d.factorBonus=d.factorBonus-factor
        call d.checkTimer()
    endfunction
    public function GetMoveSpeed takes unit u returns real
        local SpeedData d=SpeedData<u>
        return GetUnitMoveSpeed(u)*(1.0+d.factorBonus)+d.pureBonus
    endfunction
endlibrary
</u></u></u></u></u>
[/SPOILER]
This system is for modifying a unit's move speed, since the natives are fail and buffs are impractical, and the 522 sometimes just isn't what we want.

It's worth reading the comments about waypoints bugging and how to fix it. Refer to the "PERIOD" constant at the top of the code to see them (minor issue, easily solved). Basically, if you hack up a unit's movement speed too high it will miss its WC3 waypoints. You can reduce the PERIOD on the system to counter this.

Example use (20 times a second increases move speed for all units on map by 1):
JASS:
scope MoveSpeedXExample initializer OnInit
    globals
        private group GROUP=CreateGroup()
    endglobals
    private function ForAll takes nothing returns boolean
        call MSX_AddSpeedPure(GetFilterUnit(),1.0)
        return false
    endfunction
    private function Periodic takes nothing returns nothing
        call GroupEnumUnitsInRect(GROUP,bj_mapInitialPlayableArea,Filter(function ForAll))
    endfunction
    private function OnInit takes nothing returns nothing
        call TimerStart(CreateTimer(),0.05,true,function Periodic)
    endfunction
endscope

Updates:
- Version 1.0.1: Found a potential efficiency gain in moving the periodic function.
- Version 1.0.0: Release.
 

Attachments

  • MoveSpeedX.w3x
    41.1 KB · Views: 909

Igor_Z

You can change this now in User CP.
Reaction score
61
Since i don't know JASS i will ask you just 1 question...
When you increase movespeed by this system and while my unit has increased movespeed a unit to cast Bloodlust on my unit that will increase my unit's ms. After X time will I be able to return the ms of my unit to normal be4 the increasement has been placed?
 

Romek

Super Moderator
Reaction score
963
Demo map?
 

Jesus4Lyf

Good Idea™
Reaction score
397
When you increase movespeed by this system and while my unit has increased movespeed a unit to cast Bloodlust on my unit that will increase my unit's ms. After X time will I be able to return the ms of my unit to normal be4 the increasement has been placed?
Yes. It works like this:

Your unit's move speed
+/* buffs.
* MSX factor bonus.
+ MSX pure bonus.

So basically... this doesn't screw anything up. It doesn't directly modify move speed, it keeps itself independently. I know what you're saying, and this was basically made in part to solve that problem. :D

When both the MSX gain is revoked (pure or factor) and the bloodlust gain is removed, regardless the order of removal, the unit will return to the move speed it had before either was applied.

>Demo map?
Demo map up. It's just the example.
 

Igor_Z

You can change this now in User CP.
Reaction score
61
Well I won't use it because it requires NewGen which is very bugged. Thats why i don't use it. Just good job for that system. I haven't seen anything like it till now
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Because you use SetUnitX/Y instead of SetUnitPosition, the collision of the unit is ignored, the unit could be stucked beetween trees for example.
I don't think there is a good way to change the unit speed more than 512.
You can't be as good as war3 engine with simply jass2.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
It's a guess based on my knowledge but i didn't read the code so far, so maybe i'm wrong, i will try it tomorrow.
 

Viikuna

No Marlo no game.
Reaction score
265
If I remember correclty, the game indeed does some pathability checking when you use SetUnitX&Y for moving units that are currently walking.

My guess is that units walking triggers those pathability thingies, because sometimes when you move unit to some point where it should not be, it pops out when you give it a move order.
 

Renendaru

(Evol)ution is nothing without love.
Reaction score
309
Noticed that if you set the pheonix's move speed to something past 522, wait for it to die and revive, attempting to order it to move freezes wc3 for me.

Edit: Bleh, nevermind. I coded it wrong.
 

T.s.e

Wish I was old and a little sentimental
Reaction score
133
Christ, Jesus. This is brilliant. Saves me the hassle of coding a past-522 movement speed spell myself. <3
 

Exide

I am amazingly focused right now!
Reaction score
448
I think this is awesome.
I had great fun testing the demo map. :D

This system should be implemented on a larger map (perhaps one that is already completed), just to see how it works in a real situation.
-I reckon the footman would fly through any group of enemy units that would otherwise block him.

+rep
:thup:
 

Frozenhelfir

set Gwypaas = Guhveepaws
Reaction score
56
I noticed some snags around 1500ms with a .00125 period. Unhappy with this I decided to boost KT2 from 800 executions per second up to 80000 executions per second so I could use a .0000125 period. Not really sure how stable it is, or if timers can even go that low, but it was fun :). I tried using a movespeed of about 20,000-60,000 movespeed. However the unit just started doing the hokey pokey and it turned itself around. Went really fast when it wasn't doing that though.

Youtube links coming as soon as it uploads :)
EDIT: http://www.youtube.com/watch?v=g2wyVVeL8lM
:D I actually found I could fix it by making KT2 very unstable though :) :) :) /votes for J4L to ficks this so it doesn't have to require a hacked KT2 or let me try :D

JASS:
//      Thanks:
//     ¯¯¯¯¯¯¯¯¯
//          - Frozenhelfir stealing his system.

Fixed :|
 

Jesus4Lyf

Good Idea™
Reaction score
397
Unhappy with this I decided to boost KT2 from 800 executions per second up to 80000 executions per second so I could use a .0000125 period. Not really sure how stable it is, or if timers can even go that low, but it was fun :). I tried using a movespeed of about 20,000-60,000 movespeed. However the unit just started doing the hokey pokey and it turned itself around. Went really fast when it wasn't doing that though.
See, this is why we can't have nice things... :D

Sounds fun, but yea you did make KT2 unstable. Nice work all the same (now go back to using 800 execs/sec, or maybe 8,000 if you must as I originally instructed you :p). By the way, that value should be called the Resolution, not executions per second, but I suppose it's much the same thing.

Question, did it lag?
And question #2, do you need that high a move speed?
 

Frozenhelfir

set Gwypaas = Guhveepaws
Reaction score
56
See, this is why we can't have nice things... :D

Sounds fun, but yea you did make KT2 unstable. Nice work all the same (now go back to using 800 execs/sec, or maybe 8,000 if you must as I originally instructed you :p). By the way, that value should be called the Resolution, not executions per second, but I suppose it's much the same thing.

Question, did it lag?
And question #2, do you need that high a move speed?

Question 1: Nope, but it would probably lag other people
Question 2: Yes, my endgame items don't fuck around.
 

Kenny

Back for now.
Reaction score
202
Will this still attempt to move units when they are under the effect of a movement-type spell, such as a dash or blink or something? If so then that may be a little bit of a problem. If this were in a map I was making I would just add an "invisible" ability to a unit every time it uses a spell like that, and just check if it had that ability before adding the extra movement. However I'm not sure if that is the best possible way to do things for a public system.

But besides that, I see this as a way of completely replacing the wc3 movement speed system, which is awesome, and in high demand recently. So nice work. :thup:
 

Jesus4Lyf

Good Idea™
Reaction score
397
Darn. I didn't think about blink.

I can probably remove the speed bonus while a spell is casting. Currently, it doesn't apply while paused or stunned. :)

Edit: For Frozenhelfir...
JASS:
//
//                             _____          _____
//        __  __  ___ _    ____\_   \        /    /
//       /  |/  |/ _ \ \  / /  __|    \    /    /
//      / / | / | (_) | \/ /|  __| \    \/    /
//     /_/|__/|_|\___/_\__/_|____|_  \      /
//          / __\  _ \  __|  __|   \ /      \         By Jesus4Lyf
//          \__ \  __/  __|  __| |) |   /\    \
//          \___/_|  |____|____|___/  /    \    \          v 1.0.1 (UNOFFICIAL RELEASE)
//                             /____/        \____\
//      What is MoveSpeedX?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          MoveSpeedX allows you to modify a unit&#039;s movement speed, either by a
//          factor of its current speed or by a pure amount. It is possible to disobey
//          the 522 movement speed limit in Warcraft III in this way.
//
//          Please note that setting the speed too high will bug waypoints.
//          
//      How to implement?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Create a new trigger object called MoveSpeedX, go to &#039;Edit -&gt; Convert to
//          Custom Text&#039;, and replace everything that&#039;s there with this script.
//
//      Functions:
//     ¯¯¯¯¯¯¯¯¯¯¯¯
//          function MSX_AddSpeedPure takes unit whichUnit, real speed returns nothing
//          function MSX_RemoveSpeedPure takes unit whichUnit, real speed returns nothing
//              - Adds or removes a pure amount of speed from the unit.
//
//          function MSX_AddSpeedFactor takes unit whichUnit, real factor returns nothing
//          function MSX_RemoveSpeedFactor takes unit whichUnit, real factor returns nothing
//              - Adds or removes a factor of speed from the unit.
//                For example, to add 10% movement speed to unit u, you would
//                call MS_AddSpeedFactor(u, 0.1).
//              - This stacks incrementally. So +10% +10% = +20%.
//              - This factor does not increase pure speed, only the unit&#039;s
//                speed outside of this system (so it does include buffs).
//
//          function MSX_GetMoveSpeed takes unit whichUnit returns real
//              - Returns the unit&#039;s move speed, inclusive of MoveSpeedX bonuses.
//          
//      Thanks:
//     ¯¯¯¯¯¯¯¯¯
//          - Frozenhelfir for the idea.
//
library MSX uses AIDS, KT
    globals
    //=================================================================
    //  This is the period on which all units will be run.
    // If you lower this value, movement bonuses will be smoother,
    // but will require more processing power (lag more).
    //  Also, the lower this is, the higher the move speed can be
    // before it starts bugging on waypoints. There is no lowest period
    // in this version.
        private constant real PERIOD=0.001
    //=================================================================
    endglobals
    //=================================================================
    //  This is a filter that determines whether or not a unit may have
    // its move speed modified. Units that pass this filter will be
    // indexed by AIDS if they have not already been.
    private function VALID_UNITS_FILTER takes unit u returns boolean
        return GetUnitAbilityLevel(u,&#039;Aloc&#039;)==0 and not IsUnitType(u,UNIT_TYPE_STRUCTURE)
    endfunction
    //=================================================================
    
    globals//locals
        private unit Unit
        private real X
        private real Y
        private real Xinc
        private real Yinc
        private real Dist
    endglobals
    private struct SpeedData extends array
        real pureBonus
        real factorBonus
        private boolean remove
        private boolean onTimer
        private real x
        private real y
        private static method AIDS_filter takes unit u returns boolean
            return VALID_UNITS_FILTER(u)
        endmethod
        private method AIDS_onCreate takes nothing returns nothing
            set this.pureBonus=0.0
            set this.factorBonus=0.0
        endmethod
        private method AIDS_onDestroy takes nothing returns nothing
            set this.remove=true
        endmethod
        //! runtextmacro AIDS()
        private method periodic takes nothing returns boolean
            if this.remove then
                set this.onTimer=false
                return true
            endif
            set Unit=this.unit
            set X=GetUnitX(Unit)
            set Y=GetUnitY(Unit)
            if (not IsUnitPaused(Unit)) and GetUnitAbilityLevel(Unit,&#039;BSTN&#039;)==0 and GetUnitAbilityLevel(Unit,&#039;BPSE&#039;)==0 then
                if X!=this.x or Y!=this.y then
                    set Xinc=X-this.x
                    set Yinc=Y-this.y
                    if this.factorBonus!=0.0 then
                        set X=X+Xinc*this.factorBonus
                        set Y=Y+Yinc*this.factorBonus
                    endif
                    if this.pureBonus!=0.0 then
                        set Dist=SquareRoot(Xinc*Xinc+Yinc*Yinc)
                        set X=X+Xinc/Dist*this.pureBonus*PERIOD
                        set Y=Y+Yinc/Dist*this.pureBonus*PERIOD
                    endif
                    call SetUnitX(Unit,X)
                    call SetUnitY(Unit,Y)
                endif
            endif
            set this.x=X
            set this.y=Y
            return false
        endmethod
		// T32 implementation.
		private thistype next
        private thistype prev
        private static method PeriodicLoop takes nothing returns nothing
            local thistype this=thistype(0).next
            loop
                exitwhen this==0
                if this.periodic() then
                    // This is some real magic.
                    set this.prev.next=this.next
                    set this.next.prev=this.prev
                    // This will even work for the starting element.
                endif
                set this=this.next
            endloop
        endmethod
        method startPeriodic takes nothing returns nothing
            set thistype(0).next.prev=this
            set this.next=thistype(0).next
            set thistype(0).next=this
            set this.prev=thistype(0)
        endmethod
        private static method AIDS_onInit takes nothing returns nothing
            call TimerStart(CreateTimer(),PERIOD,true,function thistype.PeriodicLoop)
        endmethod
		// End T32 implementation.
        method checkTimer takes nothing returns nothing
            if not this.onTimer then
                call this.startPeriodic()
                set this.onTimer=true
                set this.remove=false
                set this.x=GetUnitX(this.unit)
                set this.y=GetUnitY(this.unit)
            endif
            if this.pureBonus==0.0 and this.factorBonus==0.0 then
                set this.remove=true
            endif
        endmethod
    endstruct
    public function AddSpeedPure takes unit u, real speed returns nothing
        local SpeedData d=SpeedData<u>
        set d.pureBonus=d.pureBonus+speed
        call d.checkTimer()
    endfunction
    public function RemoveSpeedPure takes unit u, real speed returns nothing
        local SpeedData d=SpeedData<u>
        set d.pureBonus=d.pureBonus-speed
        call d.checkTimer()
    endfunction
    public function AddSpeedFactor takes unit u, real factor returns nothing
        local SpeedData d=SpeedData<u>
        set d.factorBonus=d.factorBonus+factor
        call d.checkTimer()
    endfunction
    public function RemoveSpeedFactor takes unit u, real factor returns nothing
        local SpeedData d=SpeedData<u>
        set d.factorBonus=d.factorBonus-factor
        call d.checkTimer()
    endfunction
    public function GetMoveSpeed takes unit u returns real
        local SpeedData d=SpeedData<u>
        return GetUnitMoveSpeed(u)*(1.0+d.factorBonus)+d.pureBonus
    endfunction
endlibrary
</u></u></u></u></u>

Try this. Just wrote it, unsure if it compiles. :p
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      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