• 🏆 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!

[JASS] Chopping within range

Status
Not open for further replies.
Level 20
Joined
Nov 20, 2005
Messages
1,178
Hi all.
I need a trigger for a Peasant to make him chop the closest trees around a Region(this region will be pointed upon Town hall), so that when chops a tree, if the next tree is closer(but, for example, is on the other side of the Town hall) the peasant go there to chop it. Looks like easy to do, or to think? I'm in your hands! ^^ Need to explain better?
 
Level 9
Joined
Oct 15, 2006
Messages
339
It may be a waste of space, the whole of the trigger, and may increase lag depending on how it's done.

Ehh shizzle. I don't have sufficient knowledge. But i do have some suggestions. You could make the tree's life longer, or make it a permanant tree with infinite resources. You can also make the units able to return lumber without having to leave the tree.

ALSO, if you have a tree closer to the townhall on one side, but a tree is closer to the unit on the other side, the fact that the unit has to walk around the townhall makes this trigger not worth it - that is, unless, you simply want it. Otherwise a unit will waste more time getting lumber by walking around the townhall to get to closer trees to the townhall because the relationship is between the tree and unit, not tree and structure.

The trigger would have to be setup that the trees closer to the structure are harvested. I think you'd need a periodic event. Maybe not, though.
 
Last edited:
Level 13
Joined
Nov 22, 2006
Messages
1,260
Need to explain better?

Yes, that's why nobody answered you.

This thread is under JASS section, so I can use JASS then :). You need a function that will find the closest tree from a given point. Since I can't use groups (because it is only for units), I will use arrays.

Here's the brief code:

JASS:
scope ChopClosestTree

globals
    destructable array DestAr
    integer Int = 0
    destructable ClosestDest = null
endglobals

function SetDestArray takes nothing returns nothing
    set DestAr[Int] = GetEnumDestructable()
    set Int = Int + 1
endfunction

function GetClosestDest takes real x, real y, boolexpr e returns destructable
    local real md = 100000
    local real d
    local unit u
    local real dx
    local real dy
    local integer i = 0
    
    set ClosestDest = null
    set Int = 0
    
    call EnumDestructablesInRect(bj_mapInitialPlayableArea, e, function SetDestArray)
    
    loop
        exitwhen i == Int
        call GroupRemoveUnit(g, u)
        set dx = GetDestructableX(DestAr[i]) - x
        set dy = GetDestructableY(DestAr[i]) - y
        
        if (dx * dx + dy * dy) / 100000 < md then
            set ClosestDest = DestAr[i]
            set md = (dx * dx + dy * dy) / 100000
        endif
        
        set i = i + 1
    endloop
    
    call DestroyBoolExpr(e)
    
    return ClosestDest
endfunction

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

function PeasantChopClosestTree takes unit p returns destructable
    local real x = GetUnitX(p)
    local real y = GetUnitY(p)
    local boolexpr b = Condition(function TreeFilter)
    
    call IssueTargetOrder(p, "harvest", GetClosestDest(x, y, b))
    call DestroyBoolExpr(b)
    
    set b = null
endfunction

endscope


You would, of course, have to have Jass NewGen Pack (search it on wc3campaigns.net if you don't have it) to use this function.

I'm not sure if this works, I haven't tested it, I did it in a rush. I'm especially not sure about that GetClosestDest function.

One thing you have to add yourself, I don't know what's the string order for "harvest tree", so make it in GUI, convert it to JASS and find out (and replace that "harvest" part, I just guessed it's "harvest").

You just do call PeasantChopClosestTree(<peasant>).

EDIT: This probably doesn't work exactly as you wanted, but close. Peasant just starts to chop the nearest tree, no matter if the town hall is in the way. If you want trees in certain region, just add it in the TreeFilter function (IsDestructableInRect(GetFilterDestructable()) or something)
 
Level 11
Joined
Aug 25, 2006
Messages
971
The command is 'harvest' and what was the point of using scopes?!

Won't the scope make the function you want him to use private?

Screw the scope and use a library.. lol

Edit: I see you found the command
 
Level 11
Joined
Aug 25, 2006
Messages
971
Found about a dozen syntax errors. Cleaning them out... (There might be less, it just says 12+)

Error#1
JASS:
function PeasantChopClosestTree takes unit p returns destructable
    local real x = GetUnitX(p)
    local real y = GetUnitY(p)
    local boolexpr b = Condition(function TreeFilter)
    
    call IssueTargetOrder(p, "harvest", GetClosestDest(x, y, b))
    call DestroyBoolExpr(b)
    
    set b = null
endfunction
Wheres the return?

Lol for most of the errors it was complaining about a comment outside of the function.. rofl

Error #2
JASS:
function GetClosestDest takes real x, real y, boolexpr e returns destructable
    local real md = 100000
    local real d
    local unit u
    local real dx
    local real dy
    local integer i = 0
    
    set ClosestDest = null
    set Int = 0
    
    call EnumDestructablesInRect(bj_mapInitialPlayableArea, e, function SetDestArray)
    
    loop
        exitwhen i == Int
//        call GroupRemoveUnit(g, u)
        set dx = GetDestructableX(DestAr[i]) - x
        set dy = GetDestructableY(DestAr[i]) - y
        
        if (dx * dx + dy * dy) / 100000 < md then
            set ClosestDest = DestAr[i]
            set md = (dx * dx + dy * dy) / 100000
        endif
        
        set i = i + 1
    endloop
    
    call DestroyBoolExpr(e)
    
    return ClosestDest
endfunction
See the line of code I commented? What was that about??


Here it is, the new and slightly improved jass
JASS:
//! library TreeChopper

globals
    destructable array DestAr
    integer Int = 0
    destructable ClosestDest = null
endglobals

function SetDestArray takes nothing returns nothing
    set DestAr[Int] = GetEnumDestructable()
    set Int = Int + 1
endfunction

function GetClosestDest takes real x, real y, boolexpr e returns destructable
    local real md = 100000
    local real d
    local unit u
    local real dx
    local real dy
    local integer i = 0
    
    set ClosestDest = null
    set Int = 0
    
    call EnumDestructablesInRect(bj_mapInitialPlayableArea, e, function SetDestArray)
    
    loop
        exitwhen i == Int
//        call GroupRemoveUnit(g, u)
        set dx = GetDestructableX(DestAr[i]) - x
        set dy = GetDestructableY(DestAr[i]) - y
        
        if (dx * dx + dy * dy) / 100000 < md then
            set ClosestDest = DestAr[i]
            set md = (dx * dx + dy * dy) / 100000
        endif
        
        set i = i + 1
    endloop
    
    call DestroyBoolExpr(e)
    
    return ClosestDest
endfunction

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

function PeasantChopClosestTree takes unit p returns nothing
    local real x = GetUnitX(p)
    local real y = GetUnitY(p)
    local boolexpr b = Condition(function TreeFilter)
    
    call IssueTargetOrder(p, "harvest", GetClosestDest(x, y, b))
    call DestroyBoolExpr(b)
    
    set b = null
endfunction

//! endlibrary

I g2g but i'll come back in oh 8 or 9 hours
 
Level 20
Joined
Nov 20, 2005
Messages
1,178
WADDAFAAC is all of this stuffff???? O_______O

Never received so much answers in such short time(and before i have the time to reply) ^^

Well, let me explain better.
We HAVE to use Range, yes, or array, dunno what's name.

I've used the same kind of stuff in GUI to get a radius around the town hall so that when a structure is built outside that radius, it cannot be built(through other small functions).
we could make like this: set a range around the town hall(that covers the entire map -medium-) and find a way(that's all yours, i'm a noob with jass and i can't understand anything) to make AI peasant to chop the closest tree around the town hall(radius source). Of course the closest means the closest to the TH, not to the peasant. So if a peasant finishes to chop a tree next to other trees BUT those trees are further than a SINGLE tree(for example) to the other side of the TH, the guy has to get there and chop. Of course when a peasant dies and is retrained, he follows the same method, etc. etc. NEED TO EXPLAIN AGAIN? XD
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
The command is 'harvest' and what was the point of using scopes?!

Then my guess was correct. I don't know why I was using scopes.

Wheres the return?

Beats me :p

See the line of code I commented? What was that about??

I was converting from my GetClosestUnit function, I forgot to remove that.

Arghhh!!! Ok, I'm a lousy coder???? I suck!! My codes have thousand sintax errors!! I deserve to die!

But the reason I have all those errors is that I couldn't check the code, I was doing it in blind. I don't know if it even works, I was just guessing.

This guy is probably WTHing now, so we should probably help him on his level.

He's all yours guys, I don't feel like helping anymore.
 
Level 11
Joined
Aug 25, 2006
Messages
971
I've done much worse without a syntax checker. Thats why I carry one around in my pocket. (0_o)

Anyway lord LordPerenoldeII I will adjust the code to what you need, then post a screenshot of how to use it. I'll do this after I get home (So in about 8+ hours)


Ok I did the code, if someone helps LordPerenoldeII before I do, here it is:
JASS:
//! library TreeChopper

globals
    destructable array DestAr
    integer Int = 0
    destructable ClosestDest = null
    rect ToCheck
endglobals

function SetDestArray takes nothing returns nothing
    set DestAr[Int] = GetEnumDestructable()
    set Int = Int + 1
endfunction

function XYInRect takes rect whichRect, real x, real y returns boolean
    return ((GetRectMinX(whichRect) <= x) and (GetRectMaxX(whichRect) >= x) and (GetRectMinY(whichRect) <= y) and (GetRectMaxY(whichRect) >= y))
endfunction

function GetClosestDest takes real x, real y, boolexpr e returns destructable
    local real md = 100000
    local real d
    local unit u
    local real dx
    local real dy
    local integer i = 0
    
    set ClosestDest = null
    set Int = 0
    
    call EnumDestructablesInRect(bj_mapInitialPlayableArea, e, function SetDestArray)
    
    loop
        exitwhen i == Int
//        call GroupRemoveUnit(g, u)
        set dx = GetDestructableX(DestAr[i]) - x
        set dy = GetDestructableY(DestAr[i]) - y
        
        if (dx * dx + dy * dy) / 100000 < md and XYInRect(ToCheck,x,y) then
            set ClosestDest = DestAr[i]
            set md = (dx * dx + dy * dy) / 100000
        endif
        
        set i = i + 1
    endloop
    
    call DestroyBoolExpr(e)
    
    return ClosestDest
endfunction

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

function PeasantChopClosestTree takes unit TownHall, unit Harvester, rect HarvestArea returns nothing
    local real x = GetUnitX(TownHall)
    local real y = GetUnitY(TownHall)
    local boolexpr b = Condition(function TreeFilter)
    set ToCheck = HarvestArea
    call IssueTargetOrder(Harvester, "harvest", GetClosestDest(x, y, b))
    call DestroyBoolExpr(b)
    
    set b = null
endfunction

//! endlibrary
PS I'm in a rush!
 
Last edited:
Level 11
Joined
Aug 25, 2006
Messages
971
Yes the code above does what you want.
I won't be able to get on my computer (so I can't use my wc3 tools) for a few days. Me and my dad are reconstructing my computer.
First I bought a new graphics card, but it was too big and needed a new power supply. So now we're reassembling my computer in a bigger case with a bigger power supply. If you need help using the code above, just holler and someone should step in.

JASS:
function PeasantChopClosestTree takes unit TownHall, unit Harvester, rect HarvestArea returns nothing
  local real x = GetUnitX(TownHall)
  local real y = GetUnitY(TownHall)
  local boolexpr b = Condition(function TreeFilter) 
 set ToCheck = HarvestArea
 call IssueTargetOrder(Harvester, "harvest", GetClosestDest(x, y, b))
  call DestroyBoolExpr(b)
  set b = null
 endfunction
This is the important part (but you still need everything else)
 
Level 11
Joined
Aug 25, 2006
Messages
971
Sorry, without my comp. I can't get a screenshot at the moment. Would someone show him how to implement the code? All you have to do is: pick all units of type peasents owned by player blue and call the function with GetEnumUnit()!!!

For the "if a peasent dies, a new one takes over his job" I'd need to do a bit of GUI (or just amend my previous jass) but I can do neither without my comp (<_>)
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
DON'T destroy BoolExpr's. That will fuck everything up.

Well, it seems that blizzard doesn't know that.....

JASS:
function RandomItemInRectBJ takes rect r, boolexpr filter returns item
    set bj_itemRandomConsidered = 0
    set bj_itemRandomCurrentPick = null
    call EnumItemsInRect(r, filter, function RandomItemInRectBJEnum)
    call DestroyBoolExpr(filter)
    return bj_itemRandomCurrentPick
endfunction

JASS:
function RandomDestructableInRectBJ takes rect r, boolexpr filter returns destructable
    set bj_destRandomConsidered = 0
    set bj_destRandomCurrentPick = null
    call EnumDestructablesInRect(r, filter, function RandomDestructableInRectBJEnum)
    call DestroyBoolExpr(filter)
    return bj_destRandomCurrentPick
endfunction

JASS:
function EnumUnitsSelected takes player whichPlayer, boolexpr enumFilter, code enumAction returns nothing
    local group g = CreateGroup()
    call SyncSelections()
    call GroupEnumUnitsSelected(g, whichPlayer, enumFilter)
    call DestroyBoolExpr(enumFilter)
    call ForGroup(g, enumAction)
    call DestroyGroup(g)
endfunction

JASS:
function GetUnitsInRectMatching takes rect r, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRect(g, r, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

JASS:
function GetUnitsInRangeOfLocMatching takes real radius, location whichLocation, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

JASS:
function GetUnitsOfPlayerMatching takes player whichPlayer, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsOfPlayer(g, whichPlayer, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

JASS:
function GetPlayersMatching takes boolexpr filter returns force
    local force f = CreateForce()
    call ForceEnumPlayers(f, filter)
    call DestroyBoolExpr(filter)
    return f
endfunction

.........
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
Well, that is rarely the situation........this works for local boolexprs too, right?

JASS:
function ExecuteSomething takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local boolexpr b = GetHandleBoolExpr(t, "b") // this function doesn't exist in handle vars,
                                                 // but lets pretend that it does
                                                 // (you can add it easily)
    call DestroyBoolExpr(b)
    call SetHandleHandle(t, "b", null)
    call DestroyTimer(t)
    set t = null
    set b = null
endfunction

function DoSomethingWithBoolExpr takes nothing returns nothing
    local boolexpr b = Filter(function somfunc)
    local timer t = CreateTimer()
    call SetHandleHandle(t, "b", b)
    call TimerStart(t, 3, false, function ExecuteSomething)
    set b = null
    set t = null
endfunction


This would also destroy the boolexpr that was (in case of interfering) created before that first one was destroyed, right? I mean, the second boolexpr will be destroyed when the first one is, right? Well, that cleared everything up :)
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
Probably get Jass NewGen Pack from wc3campaigns, which is probably down. Then copy this code in a blank trigger converted to JASS (meaning convert it to JASS and erase all the code from there and put that code I linked).

Then use it like this in your code:

  • Events
  • Conditions
  • Actions
    • Set Peasant = ......
    • Custom script: call PeasantChopClosestTree(udg_Peasant)

The unit variable (Peasant) can, of course, be named differently, but then you also have to change that udg_Peasant (just leave udg_ and change Peasant into whatever you named the variable)
 
Status
Not open for further replies.
Top