dodgeball system

xAnaMorphine

Active Member
Reaction score
43
hello everyone,

i am working on a dodgeball system for my map based on the arrow ability of priestress of the moon a dota hero...
i want the "dodgeball" to be point target but still travel further and pierce
through units
i attached a map with what i have came up yet...
:banghead:
 

Attachments

  • my_first_attempt.w3x
    13 KB · Views: 127

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
What kind of problem are you having that you need help with?
 

Ashlebede

New Member
Reaction score
43
Being so bad with GUI, I wasn't really able to find anything wrong. >_<

Anyways, I made a nice JASS trigger that takes care of everything ; hits every unit only once, stops when it hits map border, trees or rocks or when terrain is not walkable.

JASS:
function Trig_Dodgeball_Conditions takes nothing returns boolean
    return GetSpellAbilityId()==udg_DS_Ability[0]
endfunction

function TreeFilter takes nothing returns boolean
    local integer d = GetDestructableTypeId(GetFilterDestructable())
    return d == &#039;ATtr&#039; or d == &#039;BTtw&#039; or d == &#039;KTtw&#039; or d == &#039;YTft&#039; or d == &#039;JTct&#039; or d == &#039;YTst&#039; or d == &#039;YTct&#039; or d == &#039;YTwt&#039; or d == &#039;JTwt&#039; or d == &#039;JTwt&#039; or d == &#039;FTtw&#039; or d == &#039;CTtr&#039; or d == &#039;ITtw&#039; or d == &#039;NTtw&#039; or d == &#039;OTtw&#039; or d == &#039;ZTtw&#039; or d == &#039;WTst&#039; or d == &#039;LTlt&#039; or d == &#039;GTsh&#039; or d == &#039;Xtlt&#039; or d == &#039;WTtw&#039; or d == &#039;Attc&#039; or d == &#039;BTtc&#039; or d == &#039;CTtc&#039; or d == &#039;ITtc&#039; or d == &#039;NTtc&#039; or d == &#039;ZTtc&#039;
endfunction

function Trig_Dodgeball_Destructable_Enum takes nothing returns nothing
    call RemoveUnit(udg_TEMP_Unit)
endfunction

function Trig_Dodgeball_Timer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    
    local real dist = LoadReal(udg_Hashtable,GetHandleId(t),0)
    local real a = LoadReal(udg_Hashtable,GetHandleId(t),1)
    
    local group hitGroup = LoadGroupHandle(udg_Hashtable,GetHandleId(t),2)
    
    local unit u = LoadUnitHandle(udg_Hashtable,GetHandleId(t),3)
    local unit f = null
    local unit target = null
    
    local location loc = GetUnitLoc(u)

    local group g= GetUnitsInRangeOfLocAll(70.,loc)
    
    local real newX = GetUnitX(u)+Cos(a)*12.
    local real newY = GetUnitY(u)+Sin(a)*12.
    
    local rect rct = Rect(GetUnitX(u)-70.,GetUnitY(u)-70.,GetUnitX(u)+70.,GetUnitY(u)+70.)
    
    set udg_TEMP_Unit = u
    call EnumDestructablesInRect(rct,Condition(function TreeFilter),function Trig_Dodgeball_Destructable_Enum)
    
    call RemoveRect(rct)
    call RemoveLocation(loc)
    
    if dist&lt;3000. and not IsTerrainPathable(newX,newY,PATHING_TYPE_WALKABILITY) and RectContainsCoords(bj_mapInitialPlayableArea,newX,newY) then
            //enum loop. keeps only a units matching condition and sets a variable to that unit.
        loop
            set f = FirstOfGroup(g)
        exitwhen f==null
            if IsUnitEnemy(f,GetOwningPlayer(u)) and not IsUnitInGroup(f,hitGroup) then
                set target = f
                    exitwhen true
            endif
            call GroupRemoveUnit(g,f)
        endloop
        
        call DestroyGroup(g)
        
        call GroupAddUnit(hitGroup,target)
        
        call UnitDamageTarget(u,target,100.,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
        
        call SetUnitPosition(u,newX,newY)
        
        call SaveReal(udg_Hashtable,GetHandleId(t),0,dist+12.)
    else
        call DestroyGroup(g)
        call DestroyGroup(hitGroup)
        call RemoveUnit(u)
        call FlushChildHashtable(udg_Hashtable,GetHandleId(t))
        call DestroyTimer(t)
    endif
    
endfunction

function Trig_Dodgeball_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    
    local unit u = GetTriggerUnit()
    
    local location loc = GetSpellTargetLoc()
    
    local real a = Atan2(GetLocationY(loc)-GetUnitY(u),GetLocationX(loc)-GetUnitX(u)) //angle between casting unit &amp; target, as Radians
    
    local unit ball = CreateUnit(GetOwningPlayer(u),&#039;e000&#039;,GetUnitX(u)+128*Cos(a),GetUnitY(u)+128*Sin(a),a*bj_RADTODEG)
    
    local group g = CreateGroup()
    
    call SaveReal(udg_Hashtable,GetHandleId(t),0,0.)//dist
    call SaveReal(udg_Hashtable,GetHandleId(t),1,a)//angle in radians
    
    call SaveGroupHandle(udg_Hashtable,GetHandleId(t),2,g)//group with units already hit
    
    call SaveUnitHandle(udg_Hashtable,GetHandleId(t),3,ball)//ball
    
    call TimerStart(t,.03,true,function Trig_Dodgeball_Timer)
    
    call RemoveLocation(loc)
endfunction

//===========================================================================
function InitTrig_Dodgeball takes nothing returns nothing
    set gg_trg_Dodgeball = CreateTrigger(  )
    
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Dodgeball,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    
    call TriggerAddCondition(gg_trg_Dodgeball,Condition(function Trig_Dodgeball_Conditions))
    call TriggerAddAction( gg_trg_Dodgeball, function Trig_Dodgeball_Actions )
endfunction


Of course if you just use it without trying to analyze it, no one here will have learned anything. u_u

By the way, I tested it and it is 100% working. It does stop when it hits rocks or trees or the border and all. You might want to change its speed, though. Change that "12." in the following lines:

JASS:

local real newX = GetUnitX(u)+Cos(a)*12.
local real newY = GetUnitY(u)+Sin(a)*12.

call SaveReal(udg_Hashtable,GetHandleId(t),0,dist+12.)


Oh, and it deals a little less than 100 damage to those footmen, I figured it was because of attack & damage & armour types.
 

xAnaMorphine

Active Member
Reaction score
43
Being so bad with GUI, I wasn't really able to find anything wrong. >_<

Anyways, I made a nice JASS trigger that takes care of everything ; hits every unit only once, stops when it hits map border, trees or rocks or when terrain is not walkable.

JASS:
function Trig_Dodgeball_Conditions takes nothing returns boolean
    return GetSpellAbilityId()==udg_DS_Ability[0]
endfunction

function TreeFilter takes nothing returns boolean
    local integer d = GetDestructableTypeId(GetFilterDestructable())
    return d == &#039;ATtr&#039; or d == &#039;BTtw&#039; or d == &#039;KTtw&#039; or d == &#039;YTft&#039; or d == &#039;JTct&#039; or d == &#039;YTst&#039; or d == &#039;YTct&#039; or d == &#039;YTwt&#039; or d == &#039;JTwt&#039; or d == &#039;JTwt&#039; or d == &#039;FTtw&#039; or d == &#039;CTtr&#039; or d == &#039;ITtw&#039; or d == &#039;NTtw&#039; or d == &#039;OTtw&#039; or d == &#039;ZTtw&#039; or d == &#039;WTst&#039; or d == &#039;LTlt&#039; or d == &#039;GTsh&#039; or d == &#039;Xtlt&#039; or d == &#039;WTtw&#039; or d == &#039;Attc&#039; or d == &#039;BTtc&#039; or d == &#039;CTtc&#039; or d == &#039;ITtc&#039; or d == &#039;NTtc&#039; or d == &#039;ZTtc&#039;
endfunction

function Trig_Dodgeball_Destructable_Enum takes nothing returns nothing
    call RemoveUnit(udg_TEMP_Unit)
endfunction

function Trig_Dodgeball_Timer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    
    local real dist = LoadReal(udg_Hashtable,GetHandleId(t),0)
    local real a = LoadReal(udg_Hashtable,GetHandleId(t),1)
    
    local group hitGroup = LoadGroupHandle(udg_Hashtable,GetHandleId(t),2)
    
    local unit u = LoadUnitHandle(udg_Hashtable,GetHandleId(t),3)
    local unit f = null
    local unit target = null
    
    local location loc = GetUnitLoc(u)

    local group g= GetUnitsInRangeOfLocAll(70.,loc)
    
    local real newX = GetUnitX(u)+Cos(a)*12.
    local real newY = GetUnitY(u)+Sin(a)*12.
    
    local rect rct = Rect(GetUnitX(u)-70.,GetUnitY(u)-70.,GetUnitX(u)+70.,GetUnitY(u)+70.)
    
    set udg_TEMP_Unit = u
    call EnumDestructablesInRect(rct,Condition(function TreeFilter),function Trig_Dodgeball_Destructable_Enum)
    
    call RemoveRect(rct)
    call RemoveLocation(loc)
    
    if dist&lt;3000. and not IsTerrainPathable(newX,newY,PATHING_TYPE_WALKABILITY) and RectContainsCoords(bj_mapInitialPlayableArea,newX,newY) then
            //enum loop. keeps only a units matching condition and sets a variable to that unit.
        loop
            set f = FirstOfGroup(g)
        exitwhen f==null
            if IsUnitEnemy(f,GetOwningPlayer(u)) and not IsUnitInGroup(f,hitGroup) then
                set target = f
                    exitwhen true
            endif
            call GroupRemoveUnit(g,f)
        endloop
        
        call DestroyGroup(g)
        
        call GroupAddUnit(hitGroup,target)
        
        call UnitDamageTarget(u,target,100.,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
        
        call SetUnitPosition(u,newX,newY)
        
        call SaveReal(udg_Hashtable,GetHandleId(t),0,dist+12.)
    else
        call DestroyGroup(g)
        call DestroyGroup(hitGroup)
        call RemoveUnit(u)
        call FlushChildHashtable(udg_Hashtable,GetHandleId(t))
        call DestroyTimer(t)
    endif
    
endfunction

function Trig_Dodgeball_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    
    local unit u = GetTriggerUnit()
    
    local location loc = GetSpellTargetLoc()
    
    local real a = Atan2(GetLocationY(loc)-GetUnitY(u),GetLocationX(loc)-GetUnitX(u)) //angle between casting unit &amp; target, as Radians
    
    local unit ball = CreateUnit(GetOwningPlayer(u),&#039;e000&#039;,GetUnitX(u)+128*Cos(a),GetUnitY(u)+128*Sin(a),a*bj_RADTODEG)
    
    local group g = CreateGroup()
    
    call SaveReal(udg_Hashtable,GetHandleId(t),0,0.)//dist
    call SaveReal(udg_Hashtable,GetHandleId(t),1,a)//angle in radians
    
    call SaveGroupHandle(udg_Hashtable,GetHandleId(t),2,g)//group with units already hit
    
    call SaveUnitHandle(udg_Hashtable,GetHandleId(t),3,ball)//ball
    
    call TimerStart(t,.03,true,function Trig_Dodgeball_Timer)
    
    call RemoveLocation(loc)
endfunction

//===========================================================================
function InitTrig_Dodgeball takes nothing returns nothing
    set gg_trg_Dodgeball = CreateTrigger(  )
    
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Dodgeball,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    
    call TriggerAddCondition(gg_trg_Dodgeball,Condition(function Trig_Dodgeball_Conditions))
    call TriggerAddAction( gg_trg_Dodgeball, function Trig_Dodgeball_Actions )
endfunction


Of course if you just use it without trying to analyze it, no one here will have learned anything. u_u

By the way, I tested it and it is 100% working. It does stop when it hits rocks or trees or the border and all. You might want to change its speed, though. Change that "12." in the following lines:

JASS:
local real newX = GetUnitX(u)+Cos(a)*12.
local real newY = GetUnitY(u)+Sin(a)*12.

call SaveReal(udg_Hashtable,GetHandleId(t),0,dist+12.)


Oh, and it deals a little less than 100 damage to those footmen, I figured it was because of attack & damage & armour types.

Thanks, the damage does not matter for now.

JASS:
return d == &#039;ATtr&#039; or d == &#039;BTtw&#039; or d == &#039;KTtw&#039; or d == &#039;YTft&#039; or d == &#039;JTct&#039; or d == &#039;YTst&#039; or d == &#039;YTct&#039; or d == &#039;YTwt&#039; or d == &#039;JTwt&#039; or d == &#039;JTwt&#039; or d == &#039;FTtw&#039; or d == &#039;CTtr&#039; or d == &#039;ITtw&#039; or d == &#039;NTtw&#039; or d == &#039;OTtw&#039; or d == &#039;ZTtw&#039; or d == &#039;WTst&#039; or d == &#039;LTlt&#039; or d == &#039;GTsh&#039; or d == &#039;Xtlt&#039; or d == &#039;WTtw&#039; or d == &#039;Attc&#039; or d == &#039;BTtc&#039; or d == &#039;CTtc&#039; or d == &#039;ITtc&#039; or d == &#039;NTtc&#039; or d == &#039;ZTtc&#039;


Destructibles, so custom destructibles will also work?



okay, the 100 stands for the "damage" the rest is configurable

JASS:


You draw a circle :eek: and picked the shortest line from M to end
when you do sin or cos, that would change the curve right?


JASS:
        loop
            set f = FirstOfGroup(g)
        exitwhen f==null
        call CreateTextTagLocBJ( &quot;Miss!&quot;, udg_u, 0, 10, 100, 0.00, 0.00, 0 )
        call SetTextTagVelocityBJ( GetLastCreatedTextTag(), 64, 90 )
        call SetTextTagPermanentBJ( GetLastCreatedTextTag(), false )
        call SetTextTagFadepointBJ( GetLastCreatedTextTag(), 1.00 )
        call SetTextTagLifespanBJ( GetLastCreatedTextTag(), 1.50 )
            if IsUnitEnemy(f,GetOwningPlayer(u)) and not IsUnitInGroup(f,hitGroup) then
                set target = f
                    exitwhen true
            endif
            call GroupRemoveUnit(g,f)
        endloop


Will this display a "Miss!" when the unit hits a destructible etc.? (but not a unit)

thanks ashleblede, teach me more jass :D

--------------------

- When you stay close to another unit and use shoot, you will not hit it because it spawns behind
- how am i able to make the missle belong to a player so i can detect kill events
 

Ashlebede

New Member
Reaction score
43
Destructibles, so custom destructibles will also work?

This condition only checks for the default trees. If you want to add a custom destructible, you'll have to add your raw code amongst these ones.

JASS:


You draw a circle :eek: and picked the shortest line from M to end
when you do sin or cos, that would change the curve right?

Say, what? These are the 4 things I know about trigonometry and so far, it's been working right:

JASS:
local real angleInRadians = Atan2(y2-y1,x2-x1)
local real adjacentLength = Cos(AngleInRadians)*LenghtOfHypotenuse
local real oppositeLength = Sin(AngleInRadians)*LengthOfHypotenuse
local real LengthOfHypothenuse = SquareRoot(Xvariation*Xvariation+Yvariation*Yvariation)


Or just see this link. Now, I don't even understand these, I just use them and that's it. u_u

JASS:
loop
            set f = FirstOfGroup(g)
        exitwhen f==null
             // these functions would be called every time there is a unit within 70.00 range of the projectile
        call CreateTextTagLocBJ( &quot;Miss!&quot;, udg_u, 0, 10, 100, 0.00, 0.00, 0 )
        call SetTextTagVelocityBJ( GetLastCreatedTextTag(), 64, 90 )
        call SetTextTagPermanentBJ( GetLastCreatedTextTag(), false )
        call SetTextTagFadepointBJ( GetLastCreatedTextTag(), 1.00 )
        call SetTextTagLifespanBJ( GetLastCreatedTextTag(), 1.50 )
            if IsUnitEnemy(f,GetOwningPlayer(u)) and not IsUnitInGroup(f,hitGroup) then
                set target = f
                    exitwhen true
            endif
            call GroupRemoveUnit(g,f)
        endloop


Will this display a "Miss!" when the unit hits a destructible etc.? (but not a unit)

It will display a "Miss!", even if it doesn't hit an ally unit or hits the same unit for the second time. Now, if you wanted to make it display a miss, then it would be outside the loop, in the main "else", which normally only destroys the projectile :

JASS:
 else
                //this is called right before we destroy the projectile
            if IsTerrainPathable(newX,newY,PATHING_TYPE_WALKABILITY) or not RectContainsCoords(bj_mapInitialPlayableArea,newX,newY) then
                call CreateTextTagLocBJ( &quot;Miss!&quot;, udg_u, 0, 10, 100, 0.00, 0.00, 0 )
                call SetTextTagVelocityBJ( GetLastCreatedTextTag(), 64, 90 )
                call SetTextTagPermanentBJ( GetLastCreatedTextTag(), false )
                call SetTextTagFadepointBJ( GetLastCreatedTextTag(), 1.00 )
                call SetTextTagLifespanBJ( GetLastCreatedTextTag(), 1.50 )    
            endif
        call DestroyGroup(g)
        call DestroyGroup(hitGroup)
        call RemoveUnit(u)
        call FlushChildHashtable(udg_Hashtable,GetHandleId(t))
        call DestroyTimer(t)
endif


Note: [ljass]IsTerrainPathable()[/ljass] will return false if the terrain is pathable. I know it's weird.

And put the loop back as it was. For trees & other destructables, in that [ljass]function Trig_Dodgeball_Destructable_Enum[/ljass] :

JASS:
function Trig_Dodgeball_Destructable_Enum takes nothing returns nothing
        //this is called when there is a tree within 70.00 range of the projectile
    call RemoveUnit(udg_TEMP_Unit)
    call CreateTextTagLocBJ( &quot;Miss!&quot;, udg_u, 0, 10, 100, 0.00, 0.00, 0 )
    call SetTextTagVelocityBJ( GetLastCreatedTextTag(), 64, 90 )
    call SetTextTagPermanentBJ( GetLastCreatedTextTag(), false )
    call SetTextTagFadepointBJ( GetLastCreatedTextTag(), 1.00 )
    call SetTextTagLifespanBJ( GetLastCreatedTextTag(), 1.50 ) 
endfunction


Though if I were you I wouldn't use [ljass]GetLastCreatedTextag()[/ljass], but make a [ljass]local texttag[/ljass] variable. Then, once we store that in a variable, we can replace all those "BJ" functions with Natives ; native functions are usually more efficient.

For instance, we could replace [ljass]CreateTextTagLocBJ()[/ljass] with :

JASS:
call SetTextTagText(myTextTag, &quot;Miss!&quot;, 10 * 0.023 / 10)
call SetTextTagPos(myTextTag, GetLocationX(udg_u),GetLocationY(udg_u), 0.)
call SetTextTagColor(myTextTag, 255, 255, 255, 255)


That should create the same text tag, except, as I said, it is less computer hungry. When you call [ljass]CreateTextTagLocBJ()[/ljass], what this function does is call the same functions as these ones indirectly ; the computer has to search for the function in your script. If we use them directly, the process will be a little faster. It shouldn't make a big difference in this case, though.

Your function list should then become:

JASS:
//CreateTextTagLocBJ()
call SetTextTagText(myTextTag, &quot;Miss!&quot;, 10 * 0.023 / 10)
call SetTextTagPos(myTextTag, GetLocationX(udg_u),GetLocationY(udg_u), 0.)
call SetTextTagColor(myTextTag, 255, 255, 255, 255)
//SetTextTagVelocityBJ()
call SetTextTagVelocity(myTextTag,64,0)
//SetTextTagPermanentBJ()
call SetTextTagPermanent(myTextTag,false)
//SetTextTagFadepointBJ()
call SetTextTagFadepoint(myTextTag,1.)
//SetTextTagLifespanBJ()
call SetTextTagLifespan(myTextTag,1.5)


Note : You cannot use [ljass]GetLastCreatedTextTag()[/ljass] when you don't use BJ's.

I didn't test this, so it may or may not work. I'd say it may.

Edit:

When you stay close to another unit and use shoot, you will not hit it because it spawns behind

Try to change 128 to 32 or maybe even 16 on this line :

JASS:
local unit ball = CreateUnit(GetOwningPlayer(u),&#039;e000&#039;,GetUnitX(u)+128*Cos(a),GetUnitY(u)+128*Sin(a),a*bj_RADTODEG)


how am i able to make the missle belong to a player so i can detect kill events

It already belongs to the owner of the casting unit. You can always use :

JASS:
call SetUnitOwner(whichUnit,whichPlayer,changeColor)//changeColor being true or false
 

xAnaMorphine

Active Member
Reaction score
43
JASS:
call SetUnitOwner(whichUnit,whichPlayer,changeColor)//changeColor being true or false


=>

call SetUnitOwner(e000,GetOwningPlayer,changeColor)//changeColor being true or false

So I just edit this line into the system so this will work:

JASS:
function Trig_Player_Dies_Slayer_Conditions takes nothing returns boolean
    if ( not ( GetUnitTypeId(GetDyingUnit()) == &#039;H000&#039; ) ) then
        return false
    endif
    if ( not ( GetUnitTypeId(GetKillingUnitBJ()) == &#039;H000&#039; ) ) then
        return false
    endif
    return true
endfunction

function Trig_Player_Dies_Slayer_Func006001 takes nothing returns boolean
    return ( IsPlayerInForce(GetOwningPlayer(GetKillingUnitBJ()), udg_RedTeam) == true )
endfunction

function Trig_Player_Dies_Slayer_Func007001 takes nothing returns boolean
    return ( IsPlayerInForce(GetOwningPlayer(GetKillingUnitBJ()), udg_BlueTeam) == true )
endfunction

function Trig_Player_Dies_Slayer_Actions takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), ( GetPlayerName(GetOwningPlayer(GetDyingUnit())) + ( &quot; was killed by &quot; + GetPlayerName(GetOwningPlayer(GetKillingUnitBJ())) ) ) )
    call SetHeroLevelBJ( GetKillingUnitBJ(), ( GetHeroLevel(GetKillingUnitBJ()) + 1 ), true )
    set udg_PlayerScore[GetConvertedPlayerId(GetOwningPlayer(GetKillingUnitBJ()))] = ( udg_PlayerScore[GetConvertedPlayerId(GetOwningPlayer(GetKillingUnitBJ()))] + 1 )
    if ( Trig_Player_Dies_Slayer_Func006001() ) then
        set udg_RedTeamScore = ( udg_RedTeamScore + 1 )
    else
        call DoNothing(  )
    endif
    if ( Trig_Player_Dies_Slayer_Func007001() ) then
        set udg_BlueTeamScore = ( udg_BlueTeamScore + 1 )
    else
        call DoNothing(  )
    endif
    call ConditionalTriggerExecute( gg_trg_Leaderboard )
    call TriggerSleepAction( 5.00 )
    call RemoveUnit( GetDyingUnit() )
    call CreateNUnitsAtLoc( 1, &#039;H000&#039;, GetOwningPlayer(GetDyingUnit()), GetPlayerStartLocationLoc(GetOwningPlayer(GetDyingUnit())), bj_UNIT_FACING )
    call SelectUnitForPlayerSingle( GetLastCreatedUnit(), GetOwningPlayer(GetDyingUnit()) )
endfunction

//===========================================================================
function InitTrig_Player_Revive_TDM takes nothing returns nothing
    set gg_trg_Player_Revive_TDM = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Player_Revive_TDM, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_Player_Revive_TDM, Condition( function Trig_Player_Dies_Slayer_Conditions ) )
    call TriggerAddAction( gg_trg_Player_Revive_TDM, function Trig_Player_Dies_Slayer_Actions )
endfunction



JASS:
//CreateTextTagLocBJ()
call SetTextTagText(myTextTag, &quot;Miss!&quot;, 10 * 0.023 / 10)
call SetTextTagPos(myTextTag, GetLocationX(udg_u),GetLocationY(udg_u), 0.)
call SetTextTagColor(myTextTag, 255, 255, 255, 255)
//SetTextTagVelocityBJ()
call SetTextTagVelocity(myTextTag,64,0)
//SetTextTagPermanentBJ()
call SetTextTagPermanent(myTextTag,false)
//SetTextTagFadepointBJ()
call SetTextTagFadepoint(myTextTag,1.)
//SetTextTagLifespanBJ()
call SetTextTagLifespan(myTextTag,1.5)


Can you explain this a bit?

I came up with this:

JASS:
        if IsTerrainPathable(newX,newY,PATHING_TYPE_WALKABILITY) or not RectContainsCoords(bj_mapInitialPlayableArea,newX,newY) then
    set udg_TempPoint = GetUnitLoc(u)
    call CreateTextTag()
    set udg_myTextTag = 
//CreateTextTagLocBJ()
call SetTextTagText(myTextTag, &quot;Miss!&quot;, 10 * 0.023 / 10)
call SetTextTagPos(myTextTag, GetLocationX(udg_TempPoint),GetLocationY(udg_TempPoint), 0.)
call SetTextTagColor(myTextTag, 255, 255, 255, 255)
//SetTextTagVelocityBJ()
call SetTextTagVelocity(myTextTag,64,0)
//SetTextTagPermanentBJ()
call SetTextTagPermanent(myTextTag,false)
//SetTextTagFadepointBJ()
call SetTextTagFadepoint(myTextTag,1.)
//SetTextTagLifespanBJ()
call SetTextTagLifespan(myTextTag,1.5)

    call RemoveLocation(udg_TempPoint)


but what should i insert into
JASS:
set udg_myTextTag =


------------
i dont know if you noticed but the ball does not fly in a straight line
i will try to find out why
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
well, i'd say:
JASS:
set udg_myTextTag = CreateTextTag()

though for a local text tag you would need to cut the "udg_" since udg stands for: user-defined-global. and as we all know a global aint local for some obvious reasons.
 

xAnaMorphine

Active Member
Reaction score
43
well, i'd say:
JASS:
set udg_myTextTag = CreateTextTag()

though for a local text tag you would need to cut the "udg_" since udg stands for: user-defined-global. and as we all know a global aint local for some obvious reasons.

Thanks, everyone knows but me ;)
I am pretty new to Jass :eek:.
Btw, that won't work I guess o_o
 

Ashlebede

New Member
Reaction score
43
Local variables have to be declared before any function calls. so at the top of your function, you should declare one using the keyword [ljass]local[/ljass] :

JASS:
function Trig_Dodgeball_Timer takes nothing returns nothing
    local texttag myTextTag = CreateTextTag()


After that you can use it, since this created a blank texttag. As Accname stated, there is no need for an udg_ prefix which might cause naming issues. You might want to create it only later to avoid leaks, though :

JASS:
set myTextTag = CreateTextTag()


[ljass]myTextTag[/ljass] would then need to have [ljass]null[/ljass] as its value during declaration. ([ljass]local texttag myTextTag = null[/ljass])

The [ljass]SetUnitOwner()[/ljass] function doesn't need a unit-type, but a unit value([ljass]'e000'[/ljass] is not valid). We call it after the unit is created. For instance, in our function :

JASS:
function Trig_Dodgeball_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    
    local unit u = GetTriggerUnit()    

    local location loc = GetSpellTargetLoc()
    
    local real a = Atan2(GetLocationY(loc)-GetUnitY(u),GetLocationX(loc)-GetUnitX(u)) //angle between casting unit &amp; target, as Radians
    
    local unit ball = CreateUnit(GetOwningPlayer(u),&#039;e000&#039;,GetUnitX(u)+32*Cos(a),GetUnitY(u)+32*Sin(a),a*bj_RADTODEG)
    //we can&#039;t change its owner here, since there are more locals left to declare
    
    local group g = CreateGroup()

    call SetUnitOwner(ball,Player(0),false)//Player(0) returns Player 1.

    call SaveReal(udg_Hashtable,GetHandleId(t),0,0.)//dist
    call SaveReal(udg_Hashtable,GetHandleId(t),1,a)//angle in radians
    
    call SaveGroupHandle(udg_Hashtable,GetHandleId(t),2,g)//group with units already hit
    
    call SaveUnitHandle(udg_Hashtable,GetHandleId(t),3,ball)//ball
    
    call TimerStart(t,.03,true,function Trig_Dodgeball_Timer)
    
    call RemoveLocation(loc)
endfunction


JASS:
//CreateTextTagLocBJ()
call SetTextTagText(myTextTag, &quot;Miss!&quot;, 10 * 0.023 / 10)
call SetTextTagPos(myTextTag, GetLocationX(udg_u),GetLocationY(udg_u), 0.)
call SetTextTagColor(myTextTag, 255, 255, 255, 255)
//SetTextTagVelocityBJ()
call SetTextTagVelocity(myTextTag,64,0)
//SetTextTagPermanentBJ()
call SetTextTagPermanent(myTextTag,false)
//SetTextTagFadepointBJ()
call SetTextTagFadepoint(myTextTag,1.)
//SetTextTagLifespanBJ()
call SetTextTagLifespan(myTextTag,1.5)


Can you explain this a bit?

I commented the names of the functions each one replaces. If we look at [ljass]CreateTextTagLocBJ()[/ljass], we'll see this code:

JASS:
function CreateTextTagLocBJ takes string s, location loc, real zOffset, real size, real red, real green, real blue, real transparency returns texttag
    set bj_lastCreatedTextTag = CreateTextTag()
    call SetTextTagTextBJ(bj_lastCreatedTextTag, s, size)
    call SetTextTagPosBJ(bj_lastCreatedTextTag, loc, zOffset)
    call SetTextTagColorBJ(bj_lastCreatedTextTag, red, green, blue, transparency)

    return bj_lastCreatedTextTag
endfunction


This is a simplified function that calls even more simplified functions. If we look at each of them individually:

JASS:

//===========================================================================
function PercentTo255 takes real percentage returns integer
    return PercentToInt(percentage, 255)
endfunction

//***************************************************************************
//*
//*  Text Tag Utility Functions
//*
//***************************************************************************

//===========================================================================
// Scale the font size linearly such that size 10 equates to height 0.023.
// Screen-relative font heights are harder to grasp and than font sizes.
//
function TextTagSize2Height takes real size returns real
    return size * 0.023 / 10
endfunction

//===========================================================================
function SetTextTagColorBJ takes texttag tt, real red, real green, real blue, real transparency returns nothing
    call SetTextTagColor(tt, PercentTo255(red), PercentTo255(green), PercentTo255(blue), PercentTo255(100.0-transparency))
endfunction

//===========================================================================
function SetTextTagTextBJ takes texttag tt, string s, real size returns nothing
    local real textHeight = TextTagSize2Height(size)

    call SetTextTagText(tt, s, textHeight)
endfunction

//===========================================================================
function SetTextTagPosBJ takes texttag tt, location loc, real zOffset returns nothing
    call SetTextTagPos(tt, GetLocationX(loc), GetLocationY(loc), zOffset)
endfunction

//===========================================================================
function CreateTextTagLocBJ takes string s, location loc, real zOffset, real size, real red, real green, real blue, real transparency returns texttag
    set bj_lastCreatedTextTag = CreateTextTag()
    call SetTextTagTextBJ(bj_lastCreatedTextTag, s, size)
    call SetTextTagPosBJ(bj_lastCreatedTextTag, loc, zOffset)
    call SetTextTagColorBJ(bj_lastCreatedTextTag, red, green, blue, transparency)

    return bj_lastCreatedTextTag
endfunction


Now, you see, that's a lot of function calls, since every function [ljass]CreateTextTagLocBJ()[/ljass] calls will call even more functions. As you can see, there are also a few conversions which are made ([ljass]PercentTo255[/ljass] and [ljass]TextTagSize2Height[/ljass])

Anyways, I basically replaced those conversions with formulas and replaced every BJ function with the native they call. (natives are in purple and BJ's in red)

------------
i dont know if you noticed but the ball does not fly in a straight line
i will try to find out why

It was flying in a straight line when I tried. o_O
 

xAnaMorphine

Active Member
Reaction score
43
Good morning!

I just checked today and noticed it does fly in a line.
I guess I was really tired yesterday :(.
Since I am not really strong in Jass, you can guess what will happen next.

I placed this outside of the loop where the Projectiles are destroyed.
JASS:
            if IsTerrainPathable(newX,newY,PATHING_TYPE_WALKABILITY) or not RectContainsCoords(bj_mapInitialPlayableArea,newX,newY) then
                set udg_TempPoint = GetUnitLoc(u)
                //CreateTextTagLocBJ()
                call SetTextTagText(myTextTag, &quot;Miss!&quot;, 10 * 0.023 / 10)
                call SetTextTagPos(myTextTag, GetLocationX(udg_TempPoint),GetLocationY(udg_TempPoint), 0.)
                call SetTextTagColor(myTextTag, 255, 255, 255, 255)
                //SetTextTagVelocityBJ()
                call SetTextTagVelocity(myTextTag,64,0)
                //SetTextTagPermanentBJ()
                call SetTextTagPermanent(myTextTag,false)
                //SetTextTagFadepointBJ()
                call SetTextTagFadepoint(myTextTag,1.)
                //SetTextTagLifespanBJ()
                call SetTextTagLifespan(myTextTag,1.5) 
                set myTextTag = null
            endif


At the top I called:

JASS:
function Trig_Dodgeball_Timer takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local texttag myTextTag = CreateTextTag()
...


Yet again, It won't display for me. Am I even showing or creating a Text Tag? :rolleyes:


JASS:
call SetUnitOwner(whichUnit,whichPlayer,changeColor)


=> It works like a charm, thanks for that again.



JASS:
call SaveGroupHandle(udg_Hashtable,GetHandleId(t),2,g)


Not really sure about that one, but is it possible to check wether a Unit got hit by 2 Missile in the past 0.3 seconds for instance?

Remember that I am really grateful for what you have done already and really if you do not feel like helping out because I do not get things straight it is no problem. Also I do not want people to have more work then me because that is called leeching. :<
 

Ashlebede

New Member
Reaction score
43
First of all, that [ljass]GetUnitLoc()[/ljass] is unnecessary. You can use [ljass]GetUnitX(unit)[/ljass] and [ljass]GetUnitY(unit)[/ljass] instead of [ljass]GetLocationX()[/ljass] and [ljass]GetLocationY()[/ljass]. It will then be easier to avoid leaks if you take that habit. :D (I kind of like to specify insignificant details and forget about the important stuff... u_u )

And can you show me the whole timer function so I can see where exactly that texttag script was placed? D=

My guess would be that, forgetful as I am, there might be a [ljass]SetTextTagVisibility()[/ljass] missing.

JASS:
call SetTextTagVisibility(myTextTag,true)


Maybe, if you add that after that TextTag stuff... well, we can try! ^_^

is it possible to check wether a Unit got hit by 2 Missile in the past 0.3 seconds for instance?

Um... we'd have to use a timer for the unit we check and either Hashtables or UserData. (I'd say Hashtables) @_@

We'd still have to use hitGroup, since we don't want the same projectile to hit the unit twice, though. You'd have to declare another timer

It would be something like :

JASS:

//at the top of the map :
function Trig_Dodgeball_Timer2 takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit u = LoadUnitHandle(udg_Hashtable,GetHandleId(t),0)
    
    call FlushChildHashtable(udg_Hashtable,GetHandleId(u))

    call FlushChildHashtable(udg_Hashtable,GetHandleId(t))
    call DestroyTimer(t)
endfunction
...

//second timer declaration at the top of the function
        local timer tt = null
...
    //main loop
        loop
            set f = FirstOfGroup(g)
        exitwhen f==null
            if IsUnitEnemy(f,GetOwningPlayer(u)) and not IsUnitInGroup(f,hitGroup) and not HaveSavedHandle(udg_Hashtable,GetHandleId(f),1) then
                set target = f
                    exitwhen true
            endif
            call GroupRemoveUnit(g,f)
        endloop

   if target!=null then
        if HaveSavedHandle(udg_Hashtable,GetHandleId(target),0) then
            call SaveUnitHandle(udg_Hashtable,GetHandleId(target),1,u)
        else
            set tt = CreateTimer()
            call SaveUnitHandle(udg_Hashtable,GetHandleId(tt),0,target)
            call SaveUnitHandle(udg_Hashtable,GetHandleId(target),0,u)
            call TimerStart(tt,.3,false,function Trig_Dodgeball_Timer2)
        endif
    endif

        call DestroyGroup(g)
        
        call GroupAddUnit(hitGroup,target)
        
        call UnitDamageTarget(u,target,100.,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
        
        call SetUnitPosition(u,newX,newY)
...


Then again, that just may or may not work... and it's definitely not perfect. u_u

P.S.: Woot! My JASS tutorial was published! :D (But it's in French! Haha!)
 

xAnaMorphine

Active Member
Reaction score
43
First of all, that [ljass]GetUnitLoc()[/ljass] is unnecessary. You can use [ljass]GetUnitX(unit)[/ljass] and [ljass]GetUnitY(unit)[/ljass] instead of [ljass]GetLocationX()[/ljass] and [ljass]GetLocationY()[/ljass]. It will then be easier to avoid leaks if you take that habit. :D (I kind of like to specify insignificant details and forget about the important stuff... u_u )

And can you show me the whole timer function so I can see where exactly that texttag script was placed? D=

My guess would be that, forgetful as I am, there might be a [ljass]SetTextTagVisibility()[/ljass] missing.

JASS:
call SetTextTagVisibility(myTextTag,true)


Maybe, if you add that after that TextTag stuff... well, we can try! ^_^



Um... we'd have to use a timer for the unit we check and either Hashtables or UserData. (I'd say Hashtables) @_@

We'd still have to use hitGroup, since we don't want the same projectile to hit the unit twice, though. You'd have to declare another timer

It would be something like :

JASS:

//at the top of the map :
function Trig_Dodgeball_Timer2 takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit u = LoadUnitHandle(udg_Hashtable,GetHandleId(t),0)
    
    call FlushChildHashtable(udg_Hashtable,GetHandleId(u))

    call FlushChildHashtable(udg_Hashtable,GetHandleId(t))
    call DestroyTimer(t)
endfunction
...

//second timer declaration at the top of the function
        local timer tt = null
...
    //main loop
        loop
            set f = FirstOfGroup(g)
        exitwhen f==null
            if IsUnitEnemy(f,GetOwningPlayer(u)) and not IsUnitInGroup(f,hitGroup) and not HaveSavedHandle(udg_Hashtable,GetHandleId(f),1) then
                set target = f
                    exitwhen true
            endif
            call GroupRemoveUnit(g,f)
        endloop

   if target!=null then
        if HaveSavedHandle(udg_Hashtable,GetHandleId(target),0) then
            call SaveUnitHandle(udg_Hashtable,GetHandleId(target),1,u)
        else
            set tt = CreateTimer()
            call SaveUnitHandle(udg_Hashtable,GetHandleId(tt),0,target)
            call SaveUnitHandle(udg_Hashtable,GetHandleId(target),0,u)
            call TimerStart(tt,.3,false,function Trig_Dodgeball_Timer2)
        endif
    endif

        call DestroyGroup(g)
        
        call GroupAddUnit(hitGroup,target)
        
        call UnitDamageTarget(u,target,100.,false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
        
        call SetUnitPosition(u,newX,newY)
...


Then again, that just may or may not work... and it's definitely not perfect. u_u

P.S.: Woot! My JASS tutorial was published! :D (But it's in French! Haha!)

hm okay, I am already happy with what I got :D
thanks
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      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