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!
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.
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.
However your above trigger will cause trees to be indestructible even for units which should destroy trees, like orcs and undead, not to mention catapults.
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?
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 =/
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?
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 ^^
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.
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 ?
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)
...
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.
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.
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.
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.
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
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.
"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.
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:
Unit - Ability list:
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.
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 ?
Hold Left Shift and press Enter. If it still doesn't work, then you need to enable such feature in the world editor. Go to File -> Preferences... -> General (tab) -> Check: "Allow negative real values in the Object Editor"
"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.
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:
Unit - Ability list:
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...
"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...
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
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.
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
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
^ 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.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.