• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Wood

Status
Not open for further replies.
Level 5
Joined
Jul 12, 2013
Messages
118
Hello. I am trying to create a map of the High Elves. I would like peasants I create cutting wood in the manner of human peasants, but do not destroy the trees. Can not find how I can do.
Someone he already found the solution? In advance, thank you.
PS. I'm french, sorry for the English.
 
Level 12
Joined
Sep 11, 2011
Messages
1,176
I hope I understand you clearly.

1. Go to Object Editor
2. Search for the "Harvest (Gold and Lumber)" in Abilities > Special > Units > Harvest (Gold and Lumber)
3. Search for a field called "Data - Damage to Tree"
4. Change the value of the field to 0

When you don't do damage to trees, you won't destroy them.
 
Level 5
Joined
Jul 12, 2013
Messages
118
Thank you but I've already tried. It is impossible to deal 0 dmg to the tree.
Another idea ?
 
Level 12
Joined
Sep 11, 2011
Messages
1,176
Thank you but I've already tried. It is impossible to deal 0 dmg to the tree.
Another idea ?

Try this..

  • Untitled Trigger 001
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • Destructible - Pick every destructible in (Playable map area) and do (Actions)
        • Loop - Actions
          • Destructible - Set life of (Picked destructible) to (Max life of (Picked destructible))
Now, everytime the tree is being damaged, it will recover..
 
Level 5
Joined
Jul 12, 2013
Messages
118
Thank you TwoVenomous.
But in fact - Nichilus, again thank you - I want the orcs, humans and the undead can still trees. I want only my peasants do not destroy the trees.
I thought of a trigger that makes pushing the trees when they are destroyed by a high elf peasant.
Is it possible?
 
Level 5
Joined
Jul 12, 2013
Messages
118
"What's that supposed to mean ?"
When a tree dead, the destructible resurect.
Sorry for the english. I'm french.
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
"What's that supposed to mean ?"
When a tree dead, the destructible resurect.
Sorry for the english. I'm french.

http://www.hiveworkshop.com/forums/submissions-414/snippet-treerevival-233090/

^ Use this if you will. However, it only enables revival for a specific type of tree.

  • Untitled Trigger 001
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • Destructible - Pick every destructible in (Playable map area) and do (Actions)
        • Loop - Actions
          • Destructible - Set life of (Picked destructible) to (Max life of (Picked destructible))
This
  • Makes every type of destructible basically indestructible (pun not intended), not just trees since it doesn't have a filter. -> http://www.hiveworkshop.com/forums/spells-569/isdestree-v1-2-a-224623/
  • Uses a 0.01 loop, which means 100 actions per second. I believe 0.03 is more than sufficient already. I don't think any tree can be damaged more than 33 times per second.

I will try to think of an alternative tomorrow. It is really late now and I am tired also =/
 
Last edited:
Level 16
Joined
Dec 15, 2011
Messages
1,423
I have finished writing a library for you to handle exactly what you need. You will need JNGP to run this.

JASS:
library InfiniteTreeHarvest uses IsDestructableTree
    // Credit to PitzerMike Destructable lib and Bribe for the improved IsDestructableTree

    globals
        // CONFIGURABLES
        
        // Your peon unit type raw code
        private constant integer UNIT_ID = 'hpea'
        
        // END CONFIGURABLES
    endglobals
    
    private module ITHInit
        private static method onInit takes nothing returns nothing
            call init()
        endmethod
    endmodule
    
    private struct InfiniteTreeHarvest extends array
    
        private static method check takes nothing returns boolean
            local destructable dest = GetOrderTargetDestructable()

            if GetUnitTypeId(GetTriggerUnit()) == UNIT_ID and (GetIssuedOrderId() == 852018 or GetIssuedOrderId() ==  851971) and IsDestructableTree(dest) then
                call SetDestructableLife(dest, GetDestructableMaxLife(dest))
            endif
            
            set dest = null
            
            return false
        endmethod
        
        private static method init takes nothing returns nothing
            local trigger trig = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
            call TriggerAddCondition(trig, Condition(function thistype.check))
            set trig = null
        endmethod
        
        implement ITHInit
        
    endstruct
endlibrary

I have also attached a test map. The peasants can harvest the trees indefinitely but Catapult attacks or w/e can still destroy the trees.

Just a note, if you set the "Damage to tree" field too high, there may be a case that the tree is destroyed. Thus I advise that you leave it at 1.
 

Attachments

  • InfiniteTreeHarvest.w3x
    20.3 KB · Views: 51
Level 16
Joined
Dec 15, 2011
Messages
1,423
Does this will not bug if another peon start harvest trees and after the high elves come harvest to set it's life to 100% ?
P.S : I'm french too so my english can be bad ^^

Well that is indeed a valid point. I originally intend to go with a different approach; however, Warcraft doesn't support a method to get the destructable killer and thus it would be cumbersome to write a library that do exactly just that ̣̣̣since a lot of factors have to be taken into consideration to decide the correct killer.

I will be waiting for OP's answer regarding this particular matter. If you are cunning a bit with the map, the proposed issue can be avoided.

Btw, your english is fine, don't worry :D
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
But if the high elves workers got all the same attack damage on tree why not make a constant damage that the use can setup and heal the destructible to the attack damage + 1 ?

There is a problem with that. The system cannot detect when the peon hits the tree again aka proceeding with the harvest order until he gets enough lumber to carry back.

I will outline your method and how it can go wrong.

Peon A is ordered to harvest the tree with tree damage of 1.
Presuming the tree's HP is now 49, we heal it to 50 (max tree HP).
Peon A deals 10 damage to get 10 lumber and carry back.
The tree's HP is now 40.
Peon A is ordered again to harvest.
Blah blah, tree health is now 32 (40 + 2 - 10)
...

So after only a few times, the tree is cut down.
 
Level 8
Joined
Jan 28, 2016
Messages
486
Setting the value to zero leaves the worker in an infinite loop apparently (doesn't gather lumber but deals no damage to the tree; therefore never dies). Setting the value to a negative number achieves the same results with the added bonus of the worker playing its "stand lumber work" animation. Classic Blizzard.

I have an old (incomplete) system which uses the Sentinel ability to 'override' whenever the worker is ordered to gather lumber and then 'override' the Sentinel ability with a hidden Channel ability to simulate the channel-like state of a worker when harvesting resources. The rest (gaining lumber, tracking it, etc.) is handled with triggers. It gets even more complicated though once you factor in the movement triggers for when a worker drops off the lumber, returns automatically to the same tree after the drop off, finishes on a tree and automatically switches to another one nearby, and so on.

I'd upload the map but I'm not on my computer.
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
There are two ways I would recommend.

1, the choppy way.
When any destructable dies, you check if any of the units near it is a high elf peasant.
If so, you revive the destructable. (Or remove and create a new one, whichever looks better.)
Be aware that it doesnt check the actual source of the damage (maybe it is possible, but cant remember).
Also, a tree of 1 hp, harvested by orcs or humans where a high elf pops in (just has to be near the tree) and the tree is cut down, it would be revived, or if the high elf did it, he simply reset the health to the maximum.
And you can continue making situations like that where it would not work properly.

2, The proper way.
When a high elf is ordered to attack a tree (or harvest, cant remember which it was) you order it to cast a hidden ability instead.
The ability will simulate the harvest, looping the attack animation for an infinite amount of time, having a periodic timer at the chop interval to increase a value that counts the carried wood, checks whenever that wood reaches the maximum amount of wood that you want any high elf peasant to have and cast another ability that returns the wood to the nearest "lumber mill".
This way, everything works fine, but basic features such as upgrades/abilities that increase wood capacity of a peasant, or the gathering speed would not work without being accounted for by the system.

I didnt look at the script being posted here before (including its approach) and it might be a very good solution as well, but if you dont care about those "odd" situations of the choppy way, then you can take that as a solution as well.
 
Level 5
Joined
Jul 12, 2013
Messages
118
I did not understand everything
Can you join it on a map
Then I would understand better
Thank you
 
Level 24
Joined
Aug 1, 2013
Messages
4,658
I am most certain that it wont help you understand.
I can say that out of experience ;)
If my explaination doesnt do, then my code doesnt either.

In essence, the two methods come down to this:
1, revive the tree if there is a high elf peasant nearby.
2, recreate a gathering system using abilities.
 
Level 11
Joined
Jun 2, 2004
Messages
849
My way, which I think is easier though not technically foolproof and may not be applicable to your situation:

1: Give trees ridiculous hitpoints.
2: Scale anything that normally damages trees (attacks, harvesting) to make it so they die in the same amount of time.
3: Make another harvest ability that does 1 damage, give this to your elves.

Making trees die normally to things like siege units and flamestrike may be impossible/impractical, if you're wanting to make a melee map (which I think you are) with a custom race. Also the trees may theoretically eventually die to your elf harvesters, though with sufficient tree health this shouldn't ever practically happen.
 
Level 3
Joined
Oct 27, 2016
Messages
34
I did several tests but it does not work

I've tried several methods, but I think we're going to have to chock this one up to "broken-ass-world editor"

Apparently "killing unit" doesn't count a unit that kills a doodad, and "harvest" doesn't activate "A unit begins using an ability"-style triggers or any variation of those. You may want to simply rethink the elf harvest gimmick a little :(
 
Level 8
Joined
Jan 28, 2016
Messages
486
I've tried several methods, but I think we're going to have to chock this one up to "broken-ass-world editor"

Apparently "killing unit" doesn't count a unit that kills a doodad, and "harvest" doesn't activate "A unit begins using an ability"-style triggers or any variation of those. You may want to simply rethink the elf harvest gimmick a little :(

You can use the following event to detect when a worker is gathering/harvesting. Unfortunately this triggers the moment you send the worker to gather, not when he reaches the tree, so you still have to detect when that happens. Note that I've added the attack order in the conditions because all workers have their second attacks enabled but you can't see them in the UI. Why? Ask Blizzard. Apparently they decided to hide any attack that has its Targets Allowed set to trees only (if you add any other target type, it will show) which is understandable.

  • Gather Order
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
      • ((Target destructible of issued order) is alive) Equal to True
      • Or - Any (Conditions) are true
        • Conditions
          • (Issued order) Equal to (Order(smart))
          • (Issued order) Equal to (Order(attack))
          • (Issued order) Equal to (Order(harvest))
    • Actions
      • Game - Display to (All players) the text: (String((Issued order)))

The only other alternative I could come up with is to make the tree invulnerable. I discovered that as long as the Gather ability can target invulnerable trees, it will not deal damage (which is based on the worker's hidden second attack and therefore won't deal damage) yet still earn lumber on each attack. In essence, an infinite supply of lumber! The obvious issue with this however is that the tree is invulnerable, so siege units and spells which would normally destroy the tree won't.

To add to this idea of creating invincible trees, you could develop some sort of racial trait with your High Elves where your lumber mills turn all trees within a certain range invulnerable, similar to how the Undead and Night Elves need to convert gold mines before being able to mine. It doesn't have to be a lumber mill; it could be Farms that provide this effect or a special type of building. You could even have it as part of a spell that is cast by the workers or possibly by a secondary worker unit which can only harvest lumber (i.e.: how the Undead have their gatherers split between Acolytes and Ghouls).

Once again, there's no easy way to make this happen. Until someone discovers a reliable solution, triggering the whole process would be the most accurate method but would require a fair bit of effort to make it work properly.
 
Last edited:
Level 11
Joined
Jun 2, 2004
Messages
849
"Enchanting" nearby trees to make them both invulnerable and harvestable by your elves actually sounds kinda cool. I like that idea.

One problem I thought of though is for cooperative bases, you could screw over your allies' lumber harvesting. Maybe to fix that all harvesters could harvest from invulnerable trees, but that does reduce the flavor of the race somewhat, imo.
 
Last edited:
Level 13
Joined
May 10, 2009
Messages
868
Here's a possible (attempt of a) solution for you:

1 - Create another harvest ability and make it cause negative damage (I suggest that you put 2x the damage of the first harvest ability).
2 - Add that ability to the unit, but place it after/below the first one.
3 - The second ability will only heal the tree while the other actually collects lumber from it.

NOTE: If you leave the "healing" ability in front/on top of the one that collects wood, the workers won't return to the unit that receives lumber.

CONS:
-The unit will have a glitched/bugged animation. Sometimes you might see the unit delivering the lumber, but will come back towards the tree with that "carrying lumber" animation.
-The tree might play the "being hit" animation even when the worker is walking away from it / delivering the lumber.
-The worker will display both Harvest (Collect and Heal) abilities on his Command UI (unless you manage to hide it in a spell book).
-You probably have to adjust the amount of life the tree has, depending on how much damage the first harvest ability causes.
-Sometimes, if a worker tries to collect lumber from a tree that is already surrounded by many workers. That worker might just stop or return to the unit that receives lumber. I believe he stops, because both abilities are trying to give orders to a worker at the same time.

So this is what I did:

Abilities:
zBUC1uG.png


Unit - Ability list:
AHM4Ihs.png


In my example, I didn't have to edit the tree hit points (Default: 50 HP). If the tree still "dies" in your game, increase its HP a little bit.

As you can see, there are many cons that you should consider. If your map doesn't have hundreds of workers collecting wood, nor do you care about the second ability being displayed on the worker's UI. Then, you should try it out.

I hope this helps you. Otherwise, I would try what Wietlol said.
 
Level 5
Joined
Jul 12, 2013
Messages
118
I tried different solutions
The first I have not managed to implement
Blood Sool: I managed the beginning but impossible to "-10" in wood cost
How are you doing ?
 
Level 8
Joined
Jan 28, 2016
Messages
486
"Enchanting" nearby trees to make them both invulnerable and harvestable by your elves actually sounds kinda cool. I like that idea.

One problem I thought of though is for cooperative bases, you could screw over your allies' lumber harvesting. Maybe to fix that all harvesters could harvest from invulnerable trees, but that does reduce the flavor of the race somewhat, imo.

"Enchanting" sounds much better than my description! Yeah, didn't consider co-op bases; would definitely be an issue in that regard.


Here's a possible (attempt of a) solution for you:

1 - Create another harvest ability and make it cause negative damage (I suggest that you put 2x the damage of the first harvest ability).
2 - Add that ability to the unit, but place it after/below the first one.
3 - The second ability will only heal the tree while the other actually collects lumber from it.

NOTE: If you leave the "healing" ability in front/on top of the one that collects wood, the workers won't return to the unit that receives lumber.

CONS:
-The unit will have a glitched/bugged animation. Sometimes you might see the unit delivering the lumber, but will come back towards the tree with that "carrying lumber" animation.
-The tree might play the "being hit" animation even when the worker is walking away from it / delivering the lumber.
-The worker will display both Harvest (Collect and Heal) abilities on his Command UI (unless you manage to hide it in a spell book).
-You probably have to adjust the amount of life the tree has, depending on how much damage the first harvest ability causes.
-Sometimes, if a worker tries to collect lumber from a tree that is already surrounded by many workers. That worker might just stop or return to the unit that receives lumber. I believe he stops, because both abilities are trying to give orders to a worker at the same time.

So this is what I did:

Abilities:
zBUC1uG.png


Unit - Ability list:
AHM4Ihs.png


In my example, I didn't have to edit the tree hit points (Default: 50 HP). If the tree still "dies" in your game, increase its HP a little bit.

As you can see, there are many cons that you should consider. If your map doesn't have hundreds of workers collecting wood, nor do you care about the second ability being displayed on the worker's UI. Then, you should try it out.

I hope this helps you. Otherwise, I would try what Wietlol said.

Nice find! It's a shame the animations on both the worker and the tree bug out, and that you can't hide the second Gather ability in a spellbook (I might be wrong about this), but it does manage to allow harvesting lumber without damaging the tree so I guess...

its-something.jpg
 
Level 13
Joined
May 10, 2009
Messages
868
"Enchanting" sounds much better than my description! Yeah, didn't consider co-op bases; would definitely be an issue in that regard.




Nice find! It's a shame the animations on both the worker and the tree bug out, and that you can't hide the second Gather ability in a spellbook (I might be wrong about this), but it does manage to allow harvesting lumber without damaging the tree so I guess...

its-something.jpg

Yeah, that's more of a disappointment than a real fix.

The author of this post could also give the wisp's gather ability to the worker in order to collect wood, and then add later the normal peasant's harvest ability - but it only collects gold now. So, you wouldn't need to worry about any animation, nor workers getting stuck. However, the worker will be in a tree and won't need to go back to a Lumber Mill. hehehe
 
Level 5
Joined
Jul 12, 2013
Messages
118
I tried to hide the skill in a spell book but by doing this the skill no longer works.
How can I do to hide the added skill?
Thanks in advance.
 
Level 8
Joined
Jan 28, 2016
Messages
486
I tried to hide the skill in a spell book but by doing this the skill no longer works.
How can I do to hide the added skill?
Thanks in advance.

The only other option I can think of is to set the icon's X and Y positions to 0 and -11 respectively. You can find more information about it in this thread: How to stack standard buttons.

leandrotp discover way to hide any button completely. But it lead to crashes on MAC versions.

And his discovery a lot easier. You just need to set the button X position to 0 and Y to -11.

Or for standart command card buttons (example for Move):
Code:
[CmdMove]
Art=CommandMove
Buttonpos=0,-11
 
Level 13
Joined
May 10, 2009
Messages
868
I decided to make a snippet to fix all the previous problems mentioned. My previous suggestion contains a lot of glitches, and workers might not collect lumber sometimes.

Required variables (notice that udg_Harvest_Group is an array variable):
  • Needed variables
    • Events
    • Conditions
    • Actions
      • -------- This is just here in order to help you create these variables without needing to create them manually. --------
      • -------- But first you need to enable copying/pasting variables automatically in your editor preferences. --------
      • -------- File -> Preferences... -> General (tab) -> Mark: Automatically create unknown variables while pasting trigger data. --------
      • Set Harvest_Group[0] = (Last created unit group)
      • Set Harvest_Hashtable = (Last created hashtable)
      • Set Harvest_TreeChecker = (Last created unit)
      • Set Harvest_Distance = 0.00
      • Set Harvest_Heal = 0.00
      • Set Harvest_Interval = 0.00
      • Set Harvest_Worker = 0
Don't forget to choose your worker raw id in the end of this code, and also edit other values so that everything runs fine.

JASS:
function HarvestLoop takes nothing returns nothing
    local unit fog = null
    local destructable d = null
 
    if FirstOfGroup(udg_Harvest_Group[0]) == null then
        call PauseTimer(LoadTimerHandle(udg_Harvest_Hashtable, 0, 0))
        return
    endif
 
    loop
        set fog = FirstOfGroup(udg_Harvest_Group[0])
        exitwhen fog == null
        call GroupRemoveUnit(udg_Harvest_Group[0], fog)
        if GetWidgetLife(fog) > .405 then
            call GroupAddUnit(udg_Harvest_Group[1], fog)
        
            set d = LoadDestructableHandle(udg_Harvest_Hashtable, GetHandleId(fog), 0)
            if d != null and IsUnitInRangeXY(fog, GetDestructableX(d), GetDestructableY(d), udg_Harvest_Distance) then
                call SetWidgetLife(d, GetWidgetLife(d) + udg_Harvest_Heal)
            endif
            set d = null
        else
            call GroupRemoveUnit(udg_Harvest_Group[0], fog)
            call FlushChildHashtable(udg_Harvest_Hashtable, GetHandleId(fog))
        endif
    endloop
 
    // Swap
 
    set udg_Harvest_Group[2] = udg_Harvest_Group[0]
    set udg_Harvest_Group[0] = udg_Harvest_Group[1]
    set udg_Harvest_Group[1] = udg_Harvest_Group[2]
endfunction

function HarvestOrder takes nothing returns nothing
    local destructable d = GetOrderTargetDestructable()
    local unit u = GetTriggerUnit()
 
    if GetUnitTypeId(u) == udg_Harvest_Worker and udg_Harvest_TreeChecker != u then
        if IssueTargetOrderById(udg_Harvest_TreeChecker, 852018, d) and (GetUnitCurrentOrder(u) == 851971 or GetUnitCurrentOrder(u) == 852018 or GetUnitCurrentOrder(u) == 851970) then
            if FirstOfGroup(udg_Harvest_Group[0]) == null then
                call TimerStart(LoadTimerHandle(udg_Harvest_Hashtable, 0, 0), udg_Harvest_Interval, true, function HarvestLoop)
            endif
            call GroupAddUnit(udg_Harvest_Group[0], u)
            call SaveDestructableHandle(udg_Harvest_Hashtable, GetHandleId(u), 0, d)
        else
            call GroupRemoveUnit(udg_Harvest_Group[0], u)
            call FlushChildHashtable(udg_Harvest_Hashtable, GetHandleId(u))
        endif
        call IssueImmediateOrderById(udg_Harvest_TreeChecker, 851972)
    endif
 
    set d = null
    set u = null
endfunction

//===========================================================================
function InitTrig_Harvest takes nothing returns nothing
    local trigger harvest = CreateTrigger()
 
    //=============CONFIG==============//
 
    set udg_Harvest_Worker      = 'hpea'        // The raw code of your worker.
    set udg_Harvest_Interval    = 1.            // This is the interval that it takes to heal a tree.
    set udg_Harvest_Heal        = 2.            // How much life should a tree receive for every Harvest_Interval. (Default: 2 HP/sec)
    set udg_Harvest_Distance    = 150.          // The maximum distance your worker must be from the tree in order to start healing it.
 
    //=============CONFIG==============//
 
    // Harvest order
    call TriggerRegisterAnyUnitEventBJ(harvest, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
    call TriggerRegisterAnyUnitEventBJ(harvest, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
    call TriggerRegisterAnyUnitEventBJ(harvest, EVENT_PLAYER_UNIT_ISSUED_ORDER)
    call TriggerAddAction(harvest, function HarvestOrder)
 
    // Tree Checker
    set udg_Harvest_TreeChecker = CreateUnit(Player(15), udg_Harvest_Worker, 0, 0, 270)
    call UnitAddAbility(udg_Harvest_TreeChecker, 'Aloc')
    call SetUnitUseFood(udg_Harvest_TreeChecker, false)
    call ShowUnit(udg_Harvest_TreeChecker, false)
 
    set udg_Harvest_Hashtable = InitHashtable()
    call SaveTimerHandle(udg_Harvest_Hashtable, 0, 0, CreateTimer())
 
    set harvest = null
endfunction

Used order IDs:
Code:
851971 - Smart
852018 - Harvest
851970 - Rally
851972 - Stop

I know that it could've been better, but I made this thinking about everyone who uses vanilla world editor.

EDIT: Fixed the mistake that WereElf mentioned.
 
Last edited:
Level 13
Joined
Jan 2, 2016
Messages
978
You have a mistake there. call SaveDestructableHandle(udg_Harvest_Hashtable, 0, GetHandleId(u), d) should be call SaveDestructableHandle(udg_Harvest_Hashtable, GetHandleId(u), 0, d)
and set d = LoadDestructableHandle(udg_Harvest_Hashtable, 0, GetHandleId(fog)) should be set d = LoadDestructableHandle(udg_Harvest_Hashtable, GetHandleId(fog), 0)
Cuz now call FlushChildHashtable(udg_Harvest_Hashtable, GetHandleId(u)) doesn't do anything :p
 
Level 13
Joined
May 10, 2009
Messages
868
^ Thanks for that! I've also added a condition to only heal a tree if it's alive, because workers could occasionally revive trees if a flame strike or anything else destroyed it.

I attached a map; anyone can copy and paste those triggers to their map easily now.
 

Attachments

  • harvest.w3x
    22.5 KB · Views: 50
Status
Not open for further replies.
Top