• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

tripple shot

Status
Not open for further replies.
Level 20
Joined
Jul 14, 2011
Messages
3,213
Well, the problem seems pretty clear to me... We all made many mistakes :)



This allows saving with any problem, but I'm not sure if it works, didn't test.

This trigger has to be called "GetClosestWidget"
JASS:
/*****************************************************************************
*
*    Get Closest Widget (light version)
*        by Spinnaker v2.0.0.0
*
*      Special thanks to Troll-Brain
*
******************************************************************************
*
*    This snippet contains several functions which returns closest
*       widget to given coordinates and passed filter.
*
******************************************************************************
*
*    Important:
*       Performance drop depends on amount of units currently on the map
*       Snippet functions are designed to reduce the search time as much as
*       posible, although it's recommended to use non specific functions
*       wisely, especialy if your map contains large numbers of units.
*
******************************************************************************
*
*    Functions:
*       function GetClosestUnit takes real x, real y, boolexpr filter returns unit
*          - Returns closest unit matching specific filter
*       function GetClosestUnitInRange takes real x, real y, real radius, boolexpr filter returns unit
*          - Gets nearest unit in range matching specific filter
*       function GetClosestUnitInGroup takes real x, real y, group g returns unit
*          - Retrieves closest unit in given group
*
*       function GetClosestNUnitsInRange takes real x, real y, real radius, integer n, group g, boolexpr filter returns nothing
*          - Returns up to N nearest units in range of passed coordinates
*       function GetClosestNUnitsInGroup takes real x, real y, integer n, group sourceGroup, group destGroup returns nothing
*          - Retrieves up to N closest units in passed group
*
*****************************************************************************/
function InitTrig_GetClosestWidget takes nothing returns nothing
endfunction

library GetClosestWidget

    private keyword Init
    globals
        private unit array Q
        private real array V
        private integer C=0
    endglobals
    
    struct ClosestWidget extends array
        readonly static real distance=0
        readonly static real cX=0
        readonly static real cY=0
        readonly static unit cUnit=null
        static method resetData takes real x, real y returns nothing
            set distance=100000
            set cUnit=null
            set cX=x
            set cY=y
        endmethod
        static method enumUnits takes nothing returns nothing
            local unit u=GetEnumUnit()
            local real dx=GetUnitX(u)-cX
            local real dy=GetUnitY(u)-cY
            set dx=(dx*dx+dy*dy)/10000.
            if dx<distance then
                set cUnit=u
                set distance=dx
            endif
            set u=null
        endmethod
        static method sortUnits takes integer l, integer r returns nothing
            local integer i=l
            local integer j=r
            local real v=V[(l+r)/2]
            loop
                loop
                    exitwhen V[i]>=v
                    set i=i+1
                endloop
                loop
                    exitwhen V[j]<=v
                    set j=j-1
                endloop
                if i<=j then
                    set V[0]=V[i]
                    set V[i]=V[j]
                    set V[j]=V[0]
                    set Q[0]=Q[i]
                    set Q[i]=Q[j]
                    set Q[j]=Q[0]
                    set i=i+1
                    set j=j-1
                endif
                exitwhen i>j
            endloop
            if l<j then
                call sortUnits(l,j)
            endif
            if r>i then
                call sortUnits(i,r)
            endif
        endmethod
        static method saveGroup takes nothing returns nothing
            local real dx
            local real dy
            set C=C+1
            set Q[C]=GetEnumUnit()
            set dx=GetUnitX(Q[C])-cX
            set dy=GetUnitY(Q[C])-cY
            set V[C]=(dx*dx+dy*dy)/10000.
        endmethod
    endstruct
    
    function GetClosestUnit takes real x, real y, boolexpr filter returns unit
        local real r=800.
        call ClosestWidget.resetData(x,y)
        loop
            if r>3200. then
                call GroupEnumUnitsInRect(bj_lastCreatedGroup, bj_mapInitialPlayableArea, filter)
                exitwhen true
            else
                call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, r, filter)
                exitwhen FirstOfGroup(bj_lastCreatedGroup)!=null
            endif
            set r=2*r
        endloop
        call ForGroup(bj_lastCreatedGroup, function ClosestWidget.enumUnits)
        return ClosestWidget.cUnit
    endfunction
    
    function GetClosestUnitInRange takes real x, real y, real radius, boolexpr filter returns unit
        call ClosestWidget.resetData(x,y)
        if radius>=0 then
            call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, radius, filter)
            call ForGroup(bj_lastCreatedGroup, function ClosestWidget.enumUnits)
        endif
        return ClosestWidget.cUnit
    endfunction
    
    function GetClosestUnitInGroup takes real x, real y, group g returns unit
        call ClosestWidget.resetData(x,y)
        call ForGroup(g, function ClosestWidget.enumUnits)
        return ClosestWidget.cUnit
    endfunction
    
    function GetClosestNUnitsInRange takes real x, real y, real radius, integer n, group g, boolexpr filter returns nothing
        local integer q=n+1
        call ClosestWidget.resetData(x,y)
        if radius>=0 then
            call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, radius, filter)
            call ForGroup(bj_lastCreatedGroup, function ClosestWidget.saveGroup)
            call ClosestWidget.sortUnits(1,C)
            loop
            exitwhen n==0 or Q[-n+q]==null
                call GroupAddUnit(g, Q[-n+q])
                set n =n-1
            endloop
        endif
        set C=0
    endfunction
    
    function GetClosestNUnitsInGroup takes real x, real y, integer n, group sourceGroup, group destGroup returns nothing
        local integer q=n+1
        call ClosestWidget.resetData(x,y)
        call ForGroup(sourceGroup, function ClosestWidget.saveGroup)
        call ClosestWidget.sortUnits(1,C)
        loop
            exitwhen n==0 or Q[-n+q]==null
            call GroupAddUnit(destGroup, Q[-n+q])
            set n=n-1
        endloop
        set C=0
    endfunction
endlibrary

This is the GUI Trigger, obviously, now in JASS. I Improved it a bit removing Bj's and else.
This Trigger has to be called "Triple Shot"
JASS:
ffunction TripleShot_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00K' // Your TripleShot Ability Raw ID
endfunction

function TripleShot_GroupActions takes nothing returns nothing
    local unit u = CreateUnit(GetTriggerPlayer(), 'h00C', GetUnitX(udg_Unit), GetUnitY(udg_Unit), 0) // The Dummy
    call IssueTargetOrder(u, "firebolt", GetEnumUnit()) // Dummy order Firebolt Picked Unit
    call UnitApplyTimedLife(u, 'BTLF', 1.00) // Generic Expiration Timer
    call GroupRemoveUnit(udg_NearUnits, GetEnumUnit()) // Removing the target from the group
    set u = null
endfunction

function TripleShot_Filter takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit(), GetTriggerPlayer()) and GetWidgetLife(GetFilterUnit()) > 0.405 // The Condition for units to pick
endfunction

function TripleShot_Actions takes nothing returns nothing
    set udg_Unit = GetTriggerUnit() // The triggering unit
    call GetClosestNUnitsInRange(GetUnitX(udg_Unit), GetUnitY(udg_Unit), 400, 3, udg_NearUnits, Condition(function TripleShot_Filter)) // Getting Closest Units
    call ForGroup( udg_NearUnits, function TripleShot_GroupActions ) // Calling the Group Actions
    endfunction


//===========================================================================
function InitTrig_Triple_shot takes nothing returns nothing
    set gg_trg_Triple_shot = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Triple_shot, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Triple_shot, Condition( function TripleShot_Conditions ) )
    call TriggerAddAction( gg_trg_Triple_shot, function TripleShot_Actions )
endfunction
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
It's impossible, because it saved ok in mine :) Be aware that you have to delete the other ones you had, I mean, replace these two with this two.

Be sure that the name of the triggers Match as indicated
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
It has to, because of the "function InitTrig_GetClosestWidget takes nothing returns nothing"

<< EDIT >>

I made some mistakes on the JASS script. I don't know how's that it allowed me to save with those there...

Replace the script in the "Triple Shot" trigger with this
JASS:
function TripleShot_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00K' // Your TripleShot Ability Raw ID
endfunction

function TripleShot_GroupActions takes nothing returns nothing
    local unit u = CreateUnit(GetTriggerPlayer(), 'h00C', GetUnitX(udg_Unit), GetUnitY(udg_Unit), 0) // The Dummy
    call IssueTargetOrder(u, "firebolt", GetEnumUnit()) // Dummy order Firebolt Picked Unit
    call UnitApplyTimedLife(u, 'BTLF', 1.00) // Generic Expiration Timer
    call GroupRemoveUnit(udg_NearUnits, GetEnumUnit()) // Removing the target from the group
    set u = null
endfunction

function TripleShot_Filter takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit(), GetTriggerPlayer()) and GetWidgetLife(GetFilterUnit()) > 0.405 // The Condition for units to pick
endfunction

function TripleShot_Actions takes nothing returns nothing
    set udg_Unit = GetTriggerUnit() // The triggering unit
    call GetClosestNUnitsInRange(GetUnitX(udg_Unit), GetUnitY(udg_Unit), 400, 3, udg_NearUnits, Condition(function TripleShot_Filter)) // Getting Closest Units
    call ForGroup( udg_NearUnits, function TripleShot_GroupActions ) // Calling the Group Actions
    endfunction


//===========================================================================
function InitTrig_Triple_Shot takes nothing returns nothing
    set gg_trg_Triple_Shot = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Triple_Shot, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Triple_Shot, Condition( function TripleShot_Conditions ) )
    call TriggerAddAction( gg_trg_Triple_Shot, function TripleShot_Actions )
endfunction

It showed me several problems within it untill I saved without any warning advice. Should work now.
 
Last edited:
Level 9
Joined
May 31, 2010
Messages
366
Does not work anyway's same save errors....

thex are all "undeclared variable XXX"
XXX is for units, Yc, Xc, distance etc.

maybe i should create variables for this types?
then i need to know all variables you are using in the code and wich type they are
 
Level 9
Joined
May 31, 2010
Messages
366
i dont understand what your talking about jass cuz i don't know anything about jass

the question i have is: should i create the variables wich are showed to me in the error messages or not and when yes do i use the normal variables from gui or do i have to do something else?
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
NO. You Should not create anything. The Variables are all created within the Library. There's no need to create anything. As I've said, I fixed the "Triple Shot" trigger, and copied the library as it's, and it all works perfectly.

If you installed JNPG as you should have, and you are using it, it has to work.

JASS is naked GUI. GUI is the pretty dumb girl. JASS is the ugly smart girl.

JASS is much easier, it's better, it's more efficient, it's faster to work, it allows things that GUI doesn't allow, it gives you more control over everything. It's faster for you to work with, and it's faster for WC3 to work with it after you optimize your scripts. Yuu just have to be more carefull, because GUI doesn't everything for you, but it's crap. In JASS you work a bit more, but it's a lot better.
 
Level 9
Joined
May 31, 2010
Messages
366
i have JNPG and i use it (i need to use it cuz of the doodad limit) and it stoll don't work
i copied everything from your trigger and replaced the old one in my map with that -> same error's

it shows me that the variables are not declared, so i think i need to create them, but i don't know anything about jass and how it works so that i will not do anything you don't tell me to do

finally it still does not work
 
Level 9
Joined
May 31, 2010
Messages
366
...here are the screenshots
 

Attachments

  • error 1.jpg
    error 1.jpg
    412.7 KB · Views: 66
  • error 2.jpg
    error 2.jpg
    414.9 KB · Views: 115
Level 5
Joined
Sep 28, 2010
Messages
75
All right, i tested your map until i saved successfully.
First, change this code if you have not done so:
JASS:
ffunction TripleShot_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00K' // Your TripleShot Ability Raw ID
endfunction

TO:
JASS:
function TripleShot_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A00K' // Your TripleShot Ability Raw ID
endfunction

Next, change the name of your trigger
  • Triple Shot
TO:
  • Triple shot
'S' should be 's'
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Flash, he already did that. I posted the fix with those indications. The Trigger that's giving problems is the GetClosestWidget library. Somehow his JNPG doesn't detect it as a library and requires all the variables and stuff.

'A00K' is the Raw ID of your TripleShot ability.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Your map should be playable, since these 2 triggers doesn't modify at all the rest of your map.

You don't have to create them. They are created within the GetClosestWidget library, the problem relies on your JNPG not doing it. Flashbone has tested, and I've tested, and it works for both of us. I just downloaded your map, pressed "save" and it worked. So, triggers are just fine, but your JNPG isnt.
 
Level 9
Joined
May 31, 2010
Messages
366
http://www.wc3c.net/showthread.php?t=90999

there i downloaded it

my we also have other problems, normally water creates tile pathability unwalkable in my we units can still walk under water if i dont change the pathability of a tile and set this tile in my map on the deep water positions

maybe could you just save my map and post it here when the libary is created once it maybe could work
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
There. That should work for testing.

It does work, getting the nearest targets.
 

Attachments

  • Triple Shot Distance Test.w3x
    21.1 KB · Views: 62
And how's that works for the three nearest targets?

sry for imba delay. I didn't log untill now.
Finding the most near, the next most near, and the final most near units indeed harder.

Action:
if (unit group 1 contains more than 3 units){
set point1= position of unit.
set Aunit(player number of caster unit) = random unit from unit group1
set point 2 = position of aunit
set distancereal1 = distance between p1 and p2
call remove point2
pick every unit in unitgroup and do actions: {
set point2= unit-position of unit.
if(distance between p1 and p2 greater than real1){
set real1 = distance between p1 and p2.
set Aunit = picked unit
}
COMMENT/ MOST NEAR UNIT WAS FOUND

set Bunit(player number of caster unit) = random unit from unit group1
set point 2 = position of Bunit
set distancereal2 = distance between p1 and p2
call remove point2
pick every unit in unitgroup and do actions: {
set point2= unit-position of picked unit.
if( 1) distance between p1 and p2 greater than real2
2) distance between p1 and p2 not equal to real1){
set real2 = distance between p1 and p2.
set Bunit = picked unit
}

COMMENT/ 2nd MOST NEAR UNIT WAS FOUND

set Cunit(player number of caster unit) = random unit from unit group1
set point 2 = position of Cunit
set distancereal3 = distance between p1 and p2
call remove point2
pick every unit in unitgroup and do actions: {
set point2= unit-position of picked unit.
if( 1) distance between p1 and p2 greater than real3
2) distance between p1 and p2 not equal to real1
3) distance between p1 and p2 not equal to real1){
set real3 = distance between p1 and p2.
set Cunit = picked unit
}

COMMENT/ 3rd MOST NEAR UNIT WAS FOUND
Cause casting unit to damage Aunit(player number of of casting) dealing most high damage
Cause casting unit to damage Bunit(player number of of casting) dealing medium damage
Cause casting unit to damage Cunit(player number of of casting) dealing most low damage

Set player group = owner of casting unit
text to player group ("{A unit name} took most high damage")
text to player group ("{B unit name} took medium damage")
text to player group ("{C unit name} took most high damage")
remove player group


// Comment: I made it so the spell reach its full potential, the units name can be told even after the cast finish , as long as the units alive, and it can make most high or most low damage based on who was most close.
 
Status
Not open for further replies.
Top