HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Several Questions

01-31-2008, 03:11 AM#1
Joker
1. How do you keep several units from moving too far from each other? I can see how it would work with two, but with several, I don't see how I can do it. I want all the units to be free to move, not just focused on one point.

2.
Collapse JASS:
DistanceBetweenPoints

Thats the angle that this finds, right? So if you wanted Point B to face Point A, All you have to do is -180 from it right?

3. Units don't cause Desyncs with
Collapse JASS:
GetLocalPlayer()
right?
01-31-2008, 03:53 AM#2
Strilanc
DistanceBetweenPoints returns the distance between two points. Not the angle. AngleBetweenPoints is probably what you mean. 0 degrees is east (right), 90 degrees is north (up).

I don't see why the angle should matter if you're trying to restrict distance. You already have the important lengths. You need to be more specific how you want distance restrictions to work. Do you want moving units to drag sitting units, or sitting units to stop moving units, or some combination of both?

GetLocalPlayer will cause a desync if you use it to do anything non-superficial to a unit.
01-31-2008, 04:26 AM#3
aznricepuff
For question 1:

Find the 3 (or more) units' common center (i.e. average out x and y coordinates). Then find units' distances to that common center. Then you can restrict movement or w/e you want to do based on how far away a unit is from the common center.
01-31-2008, 12:12 PM#4
TaintedReality
Quote:
Thats the angle that this finds, right? So if you wanted Point B to face Point A, All you have to do is -180 from it right?

Just remember that if the angle is less than 180 to begin with, it will be less than 0, so you'll need to check for and fix that (by adding 360).

Quote:
3. Units don't cause Desyncs with

Collapse JASS:
GetLocalPlayer()

right?

Depends on what you're doing with units :).
01-31-2008, 10:48 PM#5
Joker
Quote:
Originally Posted by aznricepuff
For question 1:

Find the 3 (or more) units' common center (i.e. average out x and y coordinates). Then find units' distances to that common center. Then you can restrict movement or w/e you want to do based on how far away a unit is from the common center.
How would you average coordinates from several units?

Quote:
Originally Posted by TaintedReality
Depends on what you're doing with units :).
How about creating and destroying units for 1 player?
02-01-2008, 12:05 AM#6
TaintedReality
Quote:
How would you average coordinates from several units?

O.O. Just like you average anything else =P. ((x1 + x2 + x3) / 3) for 3 units.

Quote:
How about creating and destroying units for 1 player?

That would definitely desync.
02-01-2008, 12:55 AM#7
Joker
Quote:
Originally Posted by TaintedReality
O.O. Just like you average anything else =P. ((x1 + x2 + x3) / 3) for 3 units.
Meh...

Quote:
Originally Posted by TaintedReality
That would definitely desync.
Well, seeing as though I'm trying to keep several units together, I'm trying to create a spell for the units for the player to see how far they can move apart before being restricted.
02-01-2008, 04:20 AM#8
aznricepuff
Quote:
Originally Posted by Joker
Well, seeing as though I'm trying to keep several units together, I'm trying to create a spell for the units for the player to see how far they can move apart before being restricted.

And why do you need to remove units ONLY for a certain computer for that purpose?
02-01-2008, 07:09 AM#9
Pyrogasm
I would assume he's going to use units in a ring to represent the outer area. However, that's not the best solution. Instead, I would use units with no model file but still an attachment point (using no model will not work for this); try getting Vexorian/iNfraNe's dummy model.

Then, I'd attach the special effect you want to use to that model and change the model path locally, like so:
Collapse JASS:
local string EffectPath = ""
local unit U
local integer I = 0
//...
if GetLocalPlayer() == GetOwningPlayer(GetTriggerUnit()) then
    set EffectPath = "Abilities\\Whatever\\Whatever.mdx"
endif

loop
    set I = I+1
    exitwhen I > 25
    set U = CreateUnit(...)
    call AddSpecialEffectTarget(EffectPath, U, "origin")
endloop
02-04-2008, 02:18 AM#10
Joker
Ok i tried follow your model, Pyro, but it doesn't work...I'm not sure if I'm even doing this right.
Collapse JASS:
scope ViewArea

private function Boolexpr takes nothing returns boolean
    return IsUnitType( GetFilterUnit(), UNIT_TYPE_HERO ) == true
endfunction

//===========================================================================
private function Actions takes nothing returns nothing
    local unit a = GetSpellAbilityUnit()
    local real ax = GetUnitX(a)
    local real ay = GetUnitY(a)
    local real angle
    local player p = GetOwningPlayer(a)
    local group g = CreateGroup()
    local unit f
    local real array x
    local real array y
    local real tx
    local real ty
    local integer i = 0
    local string path = ""
    local unit U
    local integer I = 0
    
    call GroupEnumUnitsOfPlayer( g, p, Condition( function Boolexpr ) )
    
    loop
        set f = FirstOfGroup(g)
        exitwhen f == null
        set x[i] = GetUnitX(f)
        set y[i] = GetUnitY(f)
        set i = i + 1
        call GroupRemoveUnit( g, f )
    endloop
    
    if i == 2 then
        set tx = (x[0] + x[1])/2
        set ty = (y[0] + y[1])/2
    elseif i == 3 then
        set tx = (x[0] + x[1] + x[2])/3
        set ty = (y[0] + y[1] + y[2])/3
    elseif i == 4 then
        set tx = (x[0] + x[1] + x[2] + x[3])/4
        set ty = (y[0] + y[1] + y[2] + y[3])/4
    endif
    
    if GetLocalPlayer() == p then
        set path = "Abilities\\Weapons\\DruidoftheTalonMissile\\DruidoftheTalonMissile.mdl"
    endif
    
    set angle = bj_RADTODEG * Atan2(ty - ay, tx - ax)
    loop
        exitwhen I > 359
        set U = CreateUnit( p, 'h002', tx + angle, ty + angle, I )
        call UnitApplyTimedLife( U, 'BTLF', 5 )
        call AddSpecialEffectTarget( path, U, "origin")
        set I = I + 12
        set angle = angle + I*angle
    endloop
    
    call DestroyGroup(g)
    set g = null
    set U = null
    set f = null
    set a = null
endfunction

//===========================================================================
private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A006'
endfunction

//===========================================================================
public function InitTrig takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Conditions ) )
    call TriggerAddAction( t, function Actions )
endfunction

endscope
One unit does get created though. Also, when the unit dies, the attachment stays in game...
02-04-2008, 04:10 AM#11
Pyrogasm
Well, you set up your if block wrong. It should be this:
Collapse JASS:
    if i == 1 then
        set tx = (x[0] + x[1])/2
        set ty = (y[0] + y[1])/2
    elseif i == 2 then
        set tx = (x[0] + x[1] + x[2])/3
        set ty = (y[0] + y[1] + y[2])/3
    elseif i == 3 then
        set tx = (x[0] + x[1] + x[2] + x[3])/4
        set ty = (y[0] + y[1] + y[2] + y[3])/4
    endif
And your loop is set up all wrong. All the units are created in the same place. You are also going to need to store the effects and destroy them later. It should look like this:
Collapse JASS:
private struct Effects
    effect array E[30]
endstruct

private function Callback takes nothing returns nothing
    local timer T = GetExpiredTimer()
    local integer i = -1
    local Effects data = Effects(GetHandleInt(T, "RingData"))

    loop
        set i = i+1
        exitwhen i>29
        call DestroyEffect(data.E[i])
    endloop

    call data.destroy()
    call DestroyTimer(T)
    set T = null
endfunction

private function Actions takes nothing returns nothing
    //...
    //No need for the "angle" or "I" variables
    local Effects data = Effects.create()
    local real Radius = 250.00 //Whatever you want the radius of the ring to be
    local timer T = CreateTimer()
    //...
    set i = -1
    loop
        set i = i+1
        exitwhen i > 29
        set U = CreateUnit(p, 'h002', tx+Radius*Cos(0.20944*i), ty+Radius*Sin(0.20944*i), (i*12)-180.00) //0.20944 = 2∏/30
        call UnitApplyTimedLife(U, 'BTLF', 5.00)
        set data.E[i] = AddSpecialEffectTarget(path, U, "origin")
    endloop

    call SetHandleInt(T, "RingData", data)
    call TimerStart(T, 5.00, false, function Callback)
    //...
    set T = null
endfunction
02-04-2008, 11:13 PM#12
Joker
You make me look so stupid. :P Thanks for the help. I'm gonna start repping you any chance I get since I never seem to be able to.
02-04-2008, 11:55 PM#13
Pyrogasm
Bah. You just need experience.
02-06-2008, 09:21 PM#14
Joker
For some odd reason, this gives wrong coordinates
Collapse JASS:
    loop
        set f = FirstOfGroup(g)
        exitwhen f == null
        set x[i] = GetUnitX(f)
        set y[i] = GetUnitY(f)
        set i = i + 1
        call GroupRemoveUnit( g, f )
    endloop

    if i == 1 then
        set tx = (x[0] + x[1])/2
        set ty = (y[0] + y[1])/2
    elseif i == 2 then
        set tx = (x[0] + x[1] + x[2])/3
        set ty = (y[0] + y[1] + y[2])/3
    elseif i == 3 then
        set tx = (x[0] + x[1] + x[2] + x[3])/4
        set ty = (y[0] + y[1] + y[2] + y[3])/4
    endif
its offset. I tested it with using the casters (x,y) and it worked fine.
02-06-2008, 10:13 PM#15
Themerion
That's strange, since the code looks like it ought to work.

Are you certain you have got the right units?

Collapse JASS:
private function Boolexpr takes nothing returns boolean
    return IsUnitType( GetFilterUnit(), UNIT_TYPE_HERO ) == true
endfunction
// ....
call GroupEnumUnitsOfPlayer( g, GetOwningPlayer(a), Condition( function Boolexpr ) )

Is it your intention to pick all heroes from owner of SpellAbilityUnit(), regardless of CastingPoint and distance?

Just to be sure that the Group contains the right units, you can try a simple GetUnitName-check on all units in the group.