Snippet SpeedMod

Dirac

22710180
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
 

Dirac

22710180
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
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
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.
 

Dirac

22710180
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
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
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?
 

Jesus4Lyf

Good Idea™
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
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
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)
 

KaerfNomekop

Swim, fishies. Swim through the veil of steel.
Do percentages always get a lower priority than specific increases? Or is it just Boots that add to a unit's base MS?
 

Dirac

22710180
@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
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
>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), 'Hpal', 0, 0, 0) // Movement - Speed Base = 200 in OE/Units/Human/Melee/Heroes/Paladin don't forget to set it
        local unit tc
        
        call BJDebugMsg(&quot;paly.move_speed = &quot; + R2S(GetUnitMoveSpeed(paly)))
        set tc = CreateUnit(Player(0), 'Otch', 0, 0, 0)
        call IssueImmediateOrderById(tc, 'AOae') // 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, 'bspd') // 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
 

Ayanami

칼리
@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.
 

Dirac

22710180
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.
 

Dirac

22710180
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.
 

Juggernaut

I don't know what to change it to
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
  • No one is chatting at the moment.
  • C Cherry.Grove:
    My boyfriend is super into Bethesda modding so I'm probably going to join him in that for a bit, then move on to making mobile/browser games.
  • C Cherry.Grove:
    I mostly just want to look at my old projects because I know I posted uploads on here somewhere.
  • C Cherry.Grove:
    My one game was basically Among Us but you sabotaged an entire medieval city simulated drastically inefficiently with dynamic NPCs :S
  • C Cherry.Grove:
    of course I never finished it x D
  • jonas jonas:
    xD
  • jonas jonas:
    I think you can still run the original game, just there's a chance your map won't work with the newer patches
  • jonas jonas:
    what development framework have you been looking at for mobile development?
  • jonas jonas:
    I'm currently creating (as a hobby) a space invaders like game for mobile using Xamarin, after starting a few larger projects that I also may not have finished :rolleyes::p
  • The Helper The Helper:
    Awesome! you should look at the Atari VCS platform it does not have a huge user base but the one it has is super active at around 11k and they have no games in there store
  • The Helper The Helper:
    basically it is linux
  • The Helper The Helper:
    OMG it is BanLord as Blackveiled on the forum
  • The Helper The Helper:
    what is up buddy
  • jonas jonas:
    thanks for the tip, that sounds cool. Never heard about the VCS before but seems like it should be a good match
  • tom_mai78101 tom_mai78101:
    The winter vacation left a toll on me. I missed staying up late and sleeping in late.
  • C Cherry.Grove:
    i haven't looked into it yet
  • C Cherry.Grove:
    If I could use something Python compatible it would save me some learning
  • C Cherry.Grove:
    But Unity might be easiest
  • C Cherry.Grove:
    looking at old posts here makes me happy. Makes me be all like "wow I was pretty smart in 2009"
  • C Cherry.Grove:
    mostly failing at life through adulthood really demotivated me for a while
  • C Cherry.Grove:
    ....what I don't get is why the fuck they would force us to permanently convert to a version of the game everyone fucking hated : \
  • C Cherry.Grove:
    Raid Shadow Legends texture pack smh
  • jonas jonas:
    Most people fail at life throughout their adulthood. Sometimes we get to learn from it. Usually it just feels like crap.
    +1
  • The Helper The Helper:
    What does not kill you makes you stronger is what they say
  • C Cherry.Grove:
    for real! :cool:

    Members online

    No members online now.

    Affiliates

    Hive Workshop NUON Dome
    Top