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: 926
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?
 
Demo map?
 
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.
 
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
 
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.
 
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.
 
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.
 
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.
 
Christ, Jesus. This is brilliant. Saves me the hassle of coding a past-522 movement speed spell myself. <3
 
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:
 
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 :|
 
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?
 
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.
 
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:
 
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 The Helper:
    News portal has been retired. Main page of site goes to Headline News forum now
  • The Helper The Helper:
    I am working on getting access to the old news portal under a different URL for those that would rather use that for news before we get a different news view.
  • Ghan Ghan:
    Easily done
    +1
  • The Helper The Helper:
    https://www.thehelper.net/pages/news/ is a link to the old news portal - i will integrate it into the interface somewhere when i figure it out
  • Ghan Ghan:
    Need to try something
  • Ghan Ghan:
    Hopefully this won't cause problems.
  • Ghan Ghan:
    Hmm
  • Ghan Ghan:
    I have converted the Headline News forum to an Article type forum. It will now show the top 20 threads with more detail of each thread.
  • Ghan Ghan:
    See how we like that.
  • The Helper The Helper:
    I do not see a way to go past the 1st page of posts on the forum though
  • The Helper The Helper:
    It is OK though for the main page to open up on the forum in the view it was before. As long as the portal has its own URL so it can be viewed that way I do want to try it as a regular forum view for a while
  • Ghan Ghan:
    Yeah I'm not sure what the deal is with the pagination.
  • Ghan Ghan:
    It SHOULD be there so I think it might just be an artifact of having an older style.
  • Ghan Ghan:
    I switched it to a "Standard" article forum. This will show the thread list like normal, but the threads themselves will have the first post set up above the rest of the "comments"
  • The Helper The Helper:
    I don't really get that article forum but I think it is because I have never really seen it used on a multi post thread
  • Ghan Ghan:
    RpNation makes more use of it right now as an example: https://www.rpnation.com/news/
  • The Helper The Helper:
  • The Helper The Helper:
    What do you think Tom?
  • tom_mai78101 tom_mai78101:
    I will have to get used to this.
  • tom_mai78101 tom_mai78101:
    The latest news feed looks good
  • The Helper The Helper:
    I would like to see it again like Ghan had it the first time with pagination though - without the pagination that view will not work but with pagination it just might...
  • The Helper The Helper:
    This drink recipe I have had more than a few times back in the day! Mind Eraser https://www.thehelper.net/threads/cocktail-mind-eraser.194720/

      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