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: 139

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,464
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.
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/
  • The Helper The Helper:
    I think we need to add something to the bottom of the front page that shows the Headline News forum that has a link to go to the News Forum Index so people can see there is more news. Do you guys see what I am saying, lets say you read all the articles on the front page and you get to the end and it just ends, no kind of link for MOAR!
  • The Helper The Helper:
    Happy Wednesday!
    +1
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    Sticking with the desserts for now the latest recipe is Fried Apple Pies - https://www.thehelper.net/threads/recipe-fried-apple-pies.194297/
  • The Helper The Helper:
    Finally finding about some of the bots that are flooding the users online - bytespider apparently is a huge offender here - ignores robots.txt and comes in from a ton of different IPs
  • Monovertex Monovertex:
    @The Helper I'm really not seeing the "Signature" link in the sidebar on that page. Here's a screenshot:
  • The Helper The Helper:
    I have reported it - I was wondering why nobody I have given sigs to over the last few years have used them
  • The Helper The Helper:
    Ghan has said he has fixed this. Monovertex please confirm this fix. This was only a problem with people that had signatures in the upper levels like not the special members but the respected members.
  • The Helper The Helper:
    Here is a better place to manage this stuff https://www.thehelper.net/account/account-details which I think should be way more visible
  • The Helper The Helper:
    I am hoping that online user count drop is finally that TikTok bot banned
  • Ghan Ghan:
    I added the filter last night.

      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