Snippet SpeedMod

Dirac

22710180
Reaction score
147
JASS:
library SpeedMod /* v2.1.0

*/uses/*
*/  LinkedListModule        /*  thehelper.net/forums/showthread.php/168775-LinkedListModule
*/  optional UnitIndexer    /*
*/  optional AIDS           /*

**********************************************************************
*
*   struct SpeedMod
*       -   Handles unit's movement speed modifications.
*
*       static method create takes unit whichUnit, real percent returns SpeedMod
*           -   Modifies the unit's speed in the given percent.
*           -   1.0 means 100% increase.
*       static method base takes unit whichUnit, real amount returns nothing
*           -   Modifies the unit's base speed by the given amount.
*           -   Giving it 20 adds 20 movement speed.
*       method destroy takes nothing returns nothing
*           -   Destroys the mod.
*       real amount
*           -   Is the percentage of speed this SpeedMod awards, if
*           -   set to another value it applies the effect.
*
*********************************************************************/
    
    private struct UnitBaseSpeed extends array
        implement LinkedList
        
        real add
        real total
        
        thistype node
        
        static if LIBRARY_UnitIndexer then
            method index takes nothing returns nothing
                set this.node = createNode()
            endmethod
            method deindex takes nothing returns nothing
                call this.node.flushNode()
            endmethod
        else
            method AIDS_onCreate takes nothing returns nothing
                set this.node = createNode()
            endmethod
            method AIDS_onDestroy takes nothing returns nothing
                call this.node.flushNode()
            endmethod
        endif
        
        implement optional UnitIndexStruct
        //! runtextmacro optional AIDS()
    endstruct
    
    struct SpeedMod extends array
        
        readonly unit target
        private real value
        private real input
        
        method operator amount= takes real v returns nothing
            local UnitBaseSpeed index=GetUnitUserData(target)
            local real speed=index.add+GetUnitDefaultMoveSpeed(target)
            set index.total=index.total-value
            set value=v*speed
            set input=v
            set index.total=index.total+value
            call SetUnitMoveSpeed(target,speed+index.total)
        endmethod
        
        static method base takes unit whichUnit, real value returns nothing
            local UnitBaseSpeed index=GetUnitUserData(whichUnit)
            local UnitBaseSpeed this = index.node.next
            set index.add=index.add+value
            call SetUnitMoveSpeed(whichUnit,GetUnitDefaultMoveSpeed(whichUnit)+index.add+index.total)
            loop
                exitwhen this.head
                set thistype(this).amount=thistype(this).input
                set this=this.next
            endloop
        endmethod
        
        method operator amount takes nothing returns real
            return input
        endmethod
        
        static method create takes unit whichUnit, real v returns thistype
            local thistype this=UnitBaseSpeed.allocate()
            local UnitBaseSpeed index=GetUnitUserData(whichUnit)
            local real speed=index.add+GetUnitDefaultMoveSpeed(whichUnit)
            set value=v*speed
            set input=v
            set target=whichUnit
            set index.total=index.total+value
            call SetUnitMoveSpeed(whichUnit,speed+index.total)
            call index.node.insertNode(this)
            return this
        endmethod
        
        method destroy takes nothing returns nothing
            local UnitBaseSpeed index=GetUnitUserData(target)
            set index.total=index.total-value
            call UnitBaseSpeed(this).removeNode()
            call UnitBaseSpeed(this).deallocate()
            call SetUnitMoveSpeed(target,GetUnitDefaultMoveSpeed(target)+index.add+index.total)
        endmethod
        
    endstruct
    
endlibrary
 
Thanks purge

Updated
-Multiple bugs occurred when dealing with MS above 522 or below 1, this is now fixed
-No longer requires a unit indexing system

Thoughts on v2.0.0
Percentage speed modificiation is a tricky thing to deal with, there are 2 ways to look at it:

(The way this snippet does)
if the unit has 400 movement speed and receives 50% slow, it would have it's movement speed reduced down to 200, but if it's reduced by 50% again it would reduce it's speed down to 100, when the first effect wears out the unit would have 300 speed. But hey, shouldn't it be 200? The unit has a 50% ms reduction effect applied and it had originally 400 movement speed!
Yes, turns out that this would be quite hard to do
In order to properly apply movement speed to units a priority queue must be created (using linked lists and such).

(The proper way)
X unit receives a 20% ms reduction, after that a 35% reduction and then a 60% increase.
If the unit's X movement speed was 400 when it first received the first reduction it's new speed would be

400-20%=320
320-35%=208
208+60%=332.8

Ok now imagine that the second effect (35%) wears off, because this effect reduced a total of 112 movement speed (from 320 down to 208) the unit would gain the speed lost, ending up with 332.8+112 = 444.8
Lets redo the math to see what happened

400-20%=320
320+60%=512

Well that's not right, why does it have 444.8 and not 512?
The system needs this fix, but it's going to be heavy, i'll add it in the next update
 
Dirac:
1. (The proper way)
X unit receives a 20% ms reduction, after that a 35% reduction and then a 60% increase.
If the X'x movement speed was 400 when it first received the reduction it's new speed would be

400-20%=320
320-35%=208
208+60%=332.8

1. That's not the way the warcraft 3 game does it.
The percentage is always based on the default movement speed, so your example becomes:

400 - 20% = 400 - 80 // current mv speed 400 - 80 = 320
400 - 35% = 400 - 140 // current mv speed 320 - 140 = 180
400 + 60% = 400 + 240 // current mv speed 180 + 240 = 420 = 400 + 5%

You don't need "priority queue", just basic arithmetic.
 
Well too bad because i don't agree with w3's way of doing things.
If your unit has boots that increase movement speed by 100 that would mean that the "base" movement speed should include the boot's bonus, this is why the system takes into account the current movement speed rather than the default one
 
Well the 100 movement speed would just be added to the base/default of the unit, i.e not the current movement speed. So that new percentage bonuses will be calculated from the new default/base?
 
Don't we... have this?
JASS:
//              - MoveSpeed (modMoveSpeedBonus, getMoveSpeedBonus)
//              - MoveSpeedPercent (modMoveSpeedPercentBonus, getMoveSpeedPercentBonus) // percent of current move speed (after normal bonuses).

Except your one still obeys the 522 cap and breaks if anything slows units by normal means, I think?

Kind of funny, Status applies % bonus last, your system applies % bonus first. Wonder which is more correct? lol, not so relevant.. :p
 
Works but not quite.

Ex:

A hero with 200 default movement speed set in the OE/Units tab

Dirac.SpeedMod:

SpeedMod.create(<hero>, 0.1 /* +10% */) // now the hero has 220 movement speed.
SpeedMod.base(<hero>, +50) // now the hero has 250 movement speed?! =)

wc3:

the hero becomes under the effect of endurance aura +10% level 1 Tauren Chieftain // now the hero has 220 movement speed
the hero gets a boots of speed +50 // now the hero has 275 movement speed

Why 275 and not 270 or even 250? What happened in the wc3's case is that when the base movement speed changed (when the hero equipped the boots of speed)
all the speed percent bonuses attached to the unit got recalculated. In this case only the endurance aura effect was recalculated. (200 + 50 = 250 + 10% = 275)

So if you do intend to replicate the wc3's "style/way" I think you'll need a list of SpeedMods attached to the unit and which have to be recalculated each time the base movement speed changes with the SpeedMod.base(...)



*default movement speed = Movement Speed Base in OE/Units
*base movement speed = default movement speed + boots of speed like bonus (not a percent bonus but a flat bonus)
 
Do percentages always get a lower priority than specific increases? Or is it just Boots that add to a unit's base MS?
 
@Sgqvur
That's not the way the warcraft 3 game does it.
The percentage is always based on the default movement speed
What happened in the wc3's case is that when the base movement speed changed (when the hero equipped the boots of speed)
Make up your mind, you can't change the unit's default movement speed inside the game, you just can't.
Therefore your example won't be 275 but 270

Also, v2.0.1
-Fixed a bug that caused unit's with active speed mods to be deleted when the unit had it's base speed changed
 
>Therefore your example won't be 275 but 270

JASS:
struct test

    static method it takes nothing returns nothing
        local unit paly = CreateUnit(Player(0), &#039;Hpal&#039;, 0, 0, 0) // Movement - Speed Base = 200 in OE/Units/Human/Melee/Heroes/Paladin don&#039;t forget to set it
        local unit tc
        
        call BJDebugMsg(&quot;paly.move_speed = &quot; + R2S(GetUnitMoveSpeed(paly)))
        set tc = CreateUnit(Player(0), &#039;Otch&#039;, 0, 0, 0)
        call IssueImmediateOrderById(tc, &#039;AOae&#039;) // learn endurance aura
        call TriggerSleepAction(4) // wait for the aura to kick in
        call BJDebugMsg(&quot;paly.move_speed = &quot; + R2S(GetUnitMoveSpeed(paly)))
        call UnitAddItemById(paly, &#039;bspd&#039;) // boots of speed +50 (default is +60 so change this as well) Units/Abilities/Special/Items/Item Move Speed Bonus
        call BJDebugMsg(&quot;paly.move_speed = &quot; + R2S(GetUnitMoveSpeed(paly)))
    endmethod
    
    static method onInit takes nothing returns nothing
        call it.execute()
    endmethod
    
endstruct
 
@Sgqvur

Make up your mind, you can't change the unit's default movement speed inside the game, you just can't.
Therefore your example won't be 275 but 270

It actually does become 275. The MS percentage factor is applied to any permanent MS bonus as well.
 
Like i quoted Sgqvur in the post before, he said otherwise in a previous post.
Glad to see you tested it out, do realize that you said
"The percentage is always based on the default movement speed"
and that's not true.
For justice i'll update this system (soon) using linked lists to loop through speed mods and update their values when units get a base movement speed gain.
 
v2.1.0
-Added AIDS or UnitIndexer as a requirement
-Removed Alloc as a requirement, the system now uses LinkedList for smart allocation.
-Changing the unit's "base" speed now affects all speed mods on the unit.
 
Sorry for necro but for a jass newbie how can I use this ?
Can you post a sample trigger where the units' speed is modified using this tool?
----
no one ?
 
General chit-chat
Help Users
  • The Helper The Helper:
    alternatively if you not making at least 23 an hour you could work in an Aldi warehouse
  • Varine Varine:
    Yeah I've been thinking about using AI for shit. I'm on vacation next week so I'm going to spend some time reorganizing everything and getting all my shit back in order
  • Varine Varine:
    lol I technically make less than 23 right now because I'm on salary and am there all the time, but it's a lot more than a normal wage still. I also have a meeting soon to renegotiate my pay because I want about a 25% increase to account for what I'm actually doing or a re-evaluation of our duties so that that my responsibilities are more in line with my pay. Depending on how that goes I'm prepared to give notice and move on, I don't mind taking less money so I'd have time for the rest of my life, but I'd rather they just fucking pay me enough to justify the commitment on my end. Plus right now I hold pretty much all the cards since I'm the only one actually qualified for my position.
    +1
  • Varine Varine:
    The other chef was there before me and got his position by virtue of being the only adult when the old general manager got married and didn't want to deal with the kitchen all the time, and happened to be in the position when the GM quit. New GM is fine with front of house but doesn't know enough about the kitchen side to really do anything or notice that I'm the one primarily maintaining it. Last time I left they hired like 3 people to replace me and there was still a noticeable drop in quality, so I got offered like 6 dollars an hour more and a pretty significant summer bonus to come back
  • Varine Varine:
    So honestly even if I leave I think it would last a couple of months until it's obvious that I am not exactly replaceable and then I would be in an even better position.
  • Varine Varine:
    But as of right now I have two other job offers that are reasonably close to what my hourly equivalency would be, and I would probably have more time for my other projects. The gap would be pretty easy to fill up if I had time to do my side jobs. I use to do some catering and private events, personal lessons, consultations, ect, and I charge like 120 an hour for those. But they aren't consistent enough for a full time job, too small of a town. And I'm not allowed to move for another year until my probation is over
  • Varine Varine:
    I guess I could get it transferred, but that seems like a hassle.
  • Varine Varine:
    Plus I have a storage room full of broken consoles I need to fix. I need to build a little reflow oven so I can manufacture some mod chips still, but it'll get there.
    +1
  • Varine Varine:
    I would like to get out of cooking in general at some point in the next ten years, but for the time being I can make decent money and pump that into savings. I've been taking some engineering classes online, but those aren't exactly career oriented at the moment, but I think getting into electronic or computer engineering of some sort would be ideal. I'm just going to keep taking some classes here and there until there's one that I am really into.
    +2
  • The Helper The Helper:
    There is money in fixing and reselling consoles. Problem is people know that so they are doing it
  • The Helper The Helper:
    If you can find a source of broken consoles though you can make money fixing them - sometimes some big money
  • Varine Varine:
    I was buying them on Ebay, but it's pretty competitive, so more recently I've just been telling the thrift stores to call me and I will come take all their electronics they can't sell. I've volunteered there before and people use them like a dump sometimes, and so they just have a massive amount of broken shit they throw away
  • Varine Varine:
    The local GoodWill was pretty into it, surprisingly the animal shelter store was not. The lady I talked to there seemed to think I was trying to steal stuff or something, she wasn't very nice about it. Like I'm just trying to stop you having to throw a bunch of electronics away, if you can sell it great. I'd probably pay you for the broken shit too if you wanted
  • Varine Varine:
    Then I make posts on Facebook yard sale pages sometimes saying I want your old electronics, but Facebook being Facebook people on there are also wary about why I want it, then want a bunch of money like it's going to be very worth it
  • Varine Varine:
    Sooner than later I'm going to get my archives business going a little more. I need some office space that is kind of hard to get at the moment, but without it, I have to be like "Yeah so go ahead and just leave your family heirlooms and hundred year old photographs here at my shitty apartment and give me a thousand dollars, and next month I'll give you a thumb drive. I promise I'll take care of them!"
    +1
  • Varine Varine:
    I can do some things with them at their home, but when people have thousands of slides and very delicate newspaper clippings and things, not really practical. I
  • Varine Varine:
    I would be there for days, even with my camera set up slides can take a long time, and if they want perfect captures I really need to use my scanners that are professionally made for that. My camera rig works well for what it is, but for enlargements and things it's not as good.
  • Varine Varine:
    I've only had a couple clients with that so far, though. I don't have a website or anything yet though.
  • Varine Varine:
    Console repair can be worthwhile, but it's also not a thing I can do at scale in my house. I just don't have room for the equipment. I need an office that I can segregate out for archival and then electronic restoration.
  • Varine Varine:
    But in order for that to be real, I need more time, and for more time I need to work less, and to work less I need a different job, and for a different job I need more money to fall back on so that I can make enough to just pay like, rent and utilities and use my savings to find these projects
    +1
  • Varine Varine:
    Another couple years. I just need to take it slow and it'll get there.
  • jonas jonas:
    any chance to get that stolen money back?
  • jonas jonas:
    Maybe you can do console repair just as a side thing, especially if there's so much competition business might be slow. Or do you need a lot of special equipment for that?
  • jonas jonas:
    I recently bought a used sauna and the preowner told me some component is broken, I took a look and it was just a burnt fuse, really cheap to fix. I was real proud of my self since I usually have two left hands for this kinda stuff :p
  • tom_mai78101 tom_mai78101:
    I am still playing Shapez 2. What an awful thing to happen, Varine, and hopefully everything has been sorted out soon. Always use multi-factor authentication whenever you have the opportunity to do so.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top