struct Example
endstruct
function Hi takes nothing returns nothing
local Example this = Example.create()
local integer index
call SaveInteger(hash, 0, 0, this)
set this = LoadInteger(hash, 0, 0)
set index = this
endfunction
To put it simple, yes.So structs are integers?
private struct SpeedList
integer count = 0
real array speed
endstruct
real array speed [100]
. What does this actually mean?this.speed[3] = 5 // valid
this.speed[22] = 5 // valid
struct
(instance) will get an unique intger from 1 to 8191. (which is the limit for arrays)real[ID] = 3
this.real = 3
this
keyword is similar like the ID
above.struct list
real speed
endstruct
struct main
integer count
list data
endstruct
local integer i = 1
local main A = main.create()
loop
exitwhen i > 10
set A.count = A.count + 1
set A.data[A.count] = list.create()
set A.data[A.count] = 10.00*I2R(i)
set i = i + 1
endloop
private struct list
real speed = 0.00
endstruct
private struct SpeedList
integer count = 0
list data
method fill takes real speed returns list
local list A = list.create()
set A.speed = speed
return A
endmethod
endstruct
function test takes nothing returns nothing
local integer i = 1
local SpeedList A = SpeedList.create()
loop
exitwhen i > 10
set A.count = A.count + 1
set A.data = A.fill(10*I2R(i))
set i = i+1
endloop
endfunction
set A.data[A.count]
here no member of type [real
is references, so it can't be right.something.speed
at end, so it specifies the "speed" member of an instance. private struct list
real array speed [100]
endstruct
private struct SpeedList
integer count = 0
list data
endstruct
function test takes nothing returns nothing
local integer i = 1
local SpeedList A = SpeedList.create()
set A.data = list.create()
loop
exitwhen i > 10
set A.count = A.count + 1
set A.data.speed[A.count] = 10*I2R(i)
set i = i+1
endloop
endfunction
loop
exitwhen i <= 1
call BJDebugMsg(R2S(A.data.speed[A.count]))
set A.count = A.count - 1
set i = i - 1
endloop
private struct list extends array
real array speed [100]
endstruct
private struct SpeedList
integer count = 0
list /* not sure if I need to write "array" here */ data [8190]
endstruct
Sometimes, you'd like to have a global array of a struct type, just to be able to have that field syntax we all like so much, it can be more complicated than it is supposed to, for example you have to manually initialize all the indexes to create the unique indexes, etc. Another issue is when you do not really want to use .allocate() and .destroy() you would like to have your own ways for allocation. Array structs are a small syntax enhancement that is equivalent to an array of a struct type, you would be able to use the members for each index and you will not have to worry about .create().
JASS://Array structs are hard to explain, but should be simple to understand with an example struct playerdata extends array //syntax to declare an array struct integer a integer b integer c endstruct function init takes nothing returns nothing local playerdata pd set playerdata[3].a=12 //modifying player 3's fields. set playerdata[3].b=34 //notice it behaves as a global array set playerdata[3].c=500 set pd=playerdata[4] set pd.a=17 //modifying player 4's fields. set pd.b=111 //yep, this is also valid set pd.c=501 endfunction function updatePlayerStuff takes player p returns nothing local integer i=GetPlayerId(p) //some random function. set playerdata[i].a=playerdata[i].b endfunction
//! zinc
library ColorModifiers requires ARGB, Table
{
public constant integer COLOR_MODIFIER_OVERLAY = 1;
public constant integer COLOR_MODIFIER_MULTIPLY = 2;
public constant integer COLOR_MODIFIER_ADDITIVE = 3;
public struct ColorModifier
{
private unit target;
private ARGB color;
private integer order;
private integer mode = COLOR_MODIFIER_OVERLAY;
private real factor= 1.0;
private thistype next, prev; // Double linked circular list.
private static Table table; // For attaching modifier lists to units.
private integer tableId;
private static method onInit()
{ table = Table.create(); }
method updateUnit()
{
ARGB unitColor = 0xFFFFFFFF;
real a = unitColor.alpha/255.0;
real r = unitColor.red/255.0;
real g = unitColor.green/255.0;
real b = unitColor.blue/255.0;
thistype that = thistype(table[tableId]);
this = that.next;
while (this!=that) { // keep looping until we come around to the sentinel node again
if (mode==COLOR_MODIFIER_OVERLAY) {
a = a*(factor-1.0) + color.alpha/255.0*factor;
r = r*(factor-1.0) + color.red/255.0*factor;
g = g*(factor-1.0) + color.green/255.0*factor;
b = b*(factor-1.0) + color.blue/255.0*factor;
} else if (mode==COLOR_MODIFIER_MULTIPLY) {
a = a * color.alpha/255.0*factor;
r = r * color.red/255.0*factor;
g = g * color.green/255.0*factor;
b = b * color.blue/255.0*factor;
} else if (mode==COLOR_MODIFIER_ADDITIVE) {
a = a + color.alpha/255.0*factor;
r = r + color.red/255.0*factor;
g = g + color.green/255.0*factor;
b = b + color.blue/255.0*factor;
}
this = this.next;
}
unitColor.recolorUnit( target );
}
private method unitListAdd() // only called on an unlisted modifier
{
thistype that = thistype(table[tableId]); // get the modifier list for this unit
if (that==0) { // no existing list, create a sentinel node (the start of our list)
that = allocate();
table[tableId] = that; // link the sentinel node to the unit
that.tableId = tableId;
that.next = that;
that.prev = that;
} else { // other modifiers exist, find insertion point
while (that.prev.order>this.order&&that.prev.target!=null) that = that.prev;
}
this.prev = that.prev; // Insert the modifier into the list.
this.next = that;
that.prev.next = this;
that.prev = this;
updateUnit();
}
private method unitListRemove() // only called on a listed modifier
{
if (prev==next) { // if this is the last modifier in the list then destroy the list
table.flush(tableId); // unlink the list from the unit
prev.deallocate(); // also destroy the sentinel node
}
next.prev = prev; // Remove the modifier from the list.
prev.next = next;
next = 0; prev = 0;
}
static method create( unit u, ARGB c, integer priority ) -> thistype
{
thistype this = allocate();
target = u;
color = c;
order = priority;
tableId = GetHandleId( u );
unitListAdd();
return this;
}
method destroy()
{
unitListRemove();
target = null;
deallocate();
}
}
}
//! endzinc
Well, obviously, but like I said, this can be done by the code for those abilities. For example, you have a triggered spell that slows units in an area. How I would do it would be to apply a triggered buff to all units in the area when the spell is cast and in the code for that buff, create a speed modifier when the buff is applied and store it to the buff, then remove that modifier when the buff is removed. The speed modifier doesn't need to know which spell applied it because it's the spell code that's keeping track of the modifier, not the other way around.I link the speed to abilities, cuz for example:
A unit is slowed by ability '1' for 20%, and then it's slowed by ability '2' for 80%, when ability '1' is over, I don't want to give the unit 80% speed back, I want to give it 20%.
Well, obviously, but like I said, this can be done by the code for those abilities. For example, you have a triggered spell that slows units in an area. How I would do it would be to apply a triggered buff to all units in the area when the spell is cast and in the code for that buff, create a speed modifier when the buff is applied and store it to the buff, then remove that modifier when the buff is removed. The speed modifier doesn't need to know which spell applied it because it's the spell code that's keeping track of the modifier, not the other way around.
The idea is to write a system that does one specific thing: proper handling of the stacking of speed modifiers. You should focus on that, don't also put a buff/spell system on top of it. If users want their speed modifiers to be applied by a buff/spell, they can use another system for that part.
private struct SpeedList
integer count = 0
real speed1 = 0.00
real speed2 = 0.00
real speed3 = 0.00
real speed4 = 0.00
real speed5 = 0.00
real speed6 = 0.00
real speed7 = 0.00
real speed8 = 0.00
real speed9 = 0.00
real speed10 = 0.00
real speed11 = 0.00
real speed12 = 0.00
real speed13 = 0.00
real speed14 = 0.00
real speed15 = 0.00
real speed16 = 0.00
real speed17 = 0.00
real speed18 = 0.00
real speed19 = 0.00
real speed20 = 0.00
real speed21 = 0.00
real speed22 = 0.00
real speed23 = 0.00
real speed24 = 0.00
real speed25 = 0.00
real speed26 = 0.00
real speed27 = 0.00
real speed28 = 0.00
real speed29 = 0.00
real speed30 = 0.00
real speed31 = 0.00
real speed32 = 0.00
method fillSpeed takes real speed returns nothing
set this.count = this.count + 1
if this.count == 1 then
set this.speed1 = speed
elseif this.count == 2 then
set this.speed2 = speed
elseif this.count == 3 then
set this.speed3 = speed
elseif this.count == 4 then
set this.speed4 = speed
elseif this.count == 5 then
set this.speed5 = speed
elseif this.count == 6 then
set this.speed6 = speed
elseif this.count == 7 then
set this.speed7 = speed
elseif this.count == 8 then
set this.speed8 = speed
elseif this.count == 9 then
set this.speed9 = speed
elseif this.count == 10 then
set this.speed10 = speed
elseif this.count == 11 then
set this.speed11 = speed
elseif this.count == 12 then
set this.speed12 = speed
elseif this.count == 13 then
set this.speed13 = speed
elseif this.count == 14 then
set this.speed14 = speed
elseif this.count == 15 then
set this.speed15 = speed
elseif this.count == 16 then
set this.speed16 = speed
elseif this.count == 17 then
set this.speed17 = speed
elseif this.count == 18 then
set this.speed18 = speed
elseif this.count == 19 then
set this.speed19 = speed
elseif this.count == 20 then
set this.speed20 = speed
elseif this.count == 21 then
set this.speed21 = speed
elseif this.count == 22 then
set this.speed22 = speed
elseif this.count == 23 then
set this.speed23 = speed
elseif this.count == 24 then
set this.speed24 = speed
elseif this.count == 25 then
set this.speed25 = speed
elseif this.count == 26 then
set this.speed26 = speed
elseif this.count == 27 then
set this.speed27 = speed
elseif this.count == 28 then
set this.speed28 = speed
elseif this.count == 29 then
set this.speed29 = speed
elseif this.count == 30 then
set this.speed30 = speed
elseif this.count == 31 then
set this.speed31 = speed
elseif this.count == 32 then
set this.speed32 = speed
endif
endmethod
method getSpeed takes nothing returns real
set this.count = this.count - 1
if this.count == 0 then
return this.speed1
elseif this.count == 1 then
return this.speed2
elseif this.count == 2 then
return this.speed3
elseif this.count == 3 then
return this.speed4
elseif this.count == 4 then
return this.speed5
elseif this.count == 5 then
return this.speed6
elseif this.count == 6 then
return this.speed7
elseif this.count == 7 then
return this.speed8
elseif this.count == 8 then
return this.speed9
elseif this.count == 9 then
return this.speed10
elseif this.count == 10 then
return this.speed11
elseif this.count == 11 then
return this.speed12
elseif this.count == 12 then
return this.speed13
elseif this.count == 13 then
return this.speed14
elseif this.count == 14 then
return this.speed15
elseif this.count == 15 then
return this.speed16
elseif this.count == 16 then
return this.speed17
elseif this.count == 17 then
return this.speed18
elseif this.count == 18 then
return this.speed19
elseif this.count == 19 then
return this.speed20
elseif this.count == 20 then
return this.speed21
elseif this.count == 21 then
return this.speed22
elseif this.count == 22 then
return this.speed23
elseif this.count == 23 then
return this.speed24
elseif this.count == 24 then
return this.speed25
elseif this.count == 25 then
return this.speed26
elseif this.count == 26 then
return this.speed27
elseif this.count == 27 then
return this.speed28
elseif this.count == 28 then
return this.speed29
elseif this.count == 29 then
return this.speed30
elseif this.count == 30 then
return this.speed31
elseif this.count == 31 then
return this.speed32
endif
return 1.00
endmethod
endstruct
library MoveSpeed uses AutoIndex
private keyword mNext
private keyword mPrev
private struct UnitSpeed
private real mSpeed
private UnitSpeedChange mHead
private method onCreate takes nothing returns nothing
set mSpeed = GetUnitDefaultMoveSpeed(me)
endmethod
implement AutoCreate
private method recalculateSpeed takes nothing returns nothing
local real speed = mSpeed
local UnitSpeedChange change = mHead
loop
exitwhen change == 0
set speed = change.apply(speed)
set change = change.mNext
endloop
call SetUnitMoveSpeed(me, speed)
endmethod
public method push takes UnitSpeedChange change returns nothing
set change.mNext = mHead
set change.mPrev = 0
if mHead != 0 then
set mHead.mPrev = change
endif
set mHead = change
call recalculateSpeed()
endmethod
public method remove takes UnitSpeedChange change returns nothing
if change.mPrev != 0 then
set change.mPrev.mNext = change.mNext
endif
if change.mNext != 0 then
set change.mNext.mPrev = change.mPrev
endif
if change == mHead then
set mHead = change.mNext
endif
call recalculateSpeed()
endmethod
endstruct
struct UnitSpeedChange
private UnitSpeed mUnitSpeed
private real mChange
private boolean mIsRelative
thistype mNext
thistype mPrev
method apply takes real inputSpeed returns real
if mIsRelative then
return inputSpeed * mChange
endif
return inputSpeed + mChange
endmethod
public static method create takes unit which, real change, boolean isRelative returns thistype
local thistype this = thistype.allocate()
set this.mUnitSpeed = UnitSpeed[which]
set this.mChange = change
set this.mIsRelative = isRelative
call this.mUnitSpeed.push(this)
return this
endmethod
private method onDestroy takes nothing returns nothing
call this.mUnitSpeed.remove(this)
endmethod
endstruct
endlibrary
private struct CurrentSpeed
integer count = 0
real default = 0.00
real speed = 0.00
real hyperbolic = 10000.00
real linear = 1.00
static method create takes real d returns CurrentSpeed
local CurrentSpeed c = CurrentSpeed.allocate()
set c.default = d
set c.speed = d
return c
endmethod
method getActualSpeed takes nothing returns real
local real r = this.hyperbolic*this.linear
if r < MinMoveSpeed*100.00 then
return MinMoveSpeed
endif
return (r*this.default)/10000.00
endmethod
endstruct
private struct Data
unit u
timer t
integer buff_ab
real linear = 0.00
real hyperbolic = 1.00
static method create takes unit u, integer i returns Data
local Data d = Data.allocate()
set d.t = CreateTimer()
set d.u = u
set d.buff_ab = i
return d
endmethod
method onDestroy takes nothing returns nothing
call FlushChildHashtable( Table, GetHandleId(this.t) )
call DestroyTimer(this.t)
endmethod
method getEndSpeed takes real modif, CurrentSpeed c, boolean b returns real
local real result
if b then
set result = c.speed - c.default*(1-modif)
set this.linear = this.linear + (modif - 1)
set c.linear = c.linear + (modif - 1)
else
set result = c.speed * modif
set this.hyperbolic = this.hyperbolic * modif
set c.hyperbolic = c.hyperbolic * modif
endif
if result < MinMoveSpeed then
return MinMoveSpeed
endif
return result
endmethod
method getCurrentSpeed takes CurrentSpeed c returns real
set c.linear = c.linear - this.linear
set c.hyperbolic = c.hyperbolic / this.hyperbolic
return c.getActualSpeed()
endmethod
endstruct