- Joined
- Jan 30, 2013
- Messages
- 12,758
Is there a way to revive non-hero units via trigger instead of duplicating the unit with CreateUnit?
It may be worth trying to pick all corpses nearby, hide them except for the corpse you are interested in, revive that single corpse and then unhide other corpses.Wouldn't it risk failure if two corpses are on top of each other?
Event:
- Unit - A unit dies
Conditions:
- (Unit-type of (Triggering unit)) is not a Hero
Actions:
- Set Temp_Loc = (Position of (Triggering unit))
- Set Temp_UnitType = (Unit-type of (Triggering unit))
- Set Temp_Owner = (Owner of (Triggering unit))
- Wait x seconds
- Unit - Replace (Triggering unit) with a Temp_UnitType using The new unit’s default life and mana
- Custom script: call RemoveLocation(udg_Temp_Loc)
Event:
- Unit - A unit dies
Conditions:
- (Unit-type of (Triggering unit)) is not a Hero
Actions:
- Set Temp_Unit = (Triggering unit)
- Set Temp_Loc = (Position of (Triggering unit))
- Set Temp_HP = (Life of (Triggering unit))
- Set Temp_MP = (Mana of (Triggering unit))
- Unit - Hide (Triggering unit)
- Unit - Pause (Triggering unit)
- Wait x seconds
step 2
Actions:
- Unit - Unpause (Temp_Unit)
- Unit - Move (Temp_Unit) instantly to Temp_Loc
- Unit - Set life of (Temp_Unit) to Temp_HP
- Unit - Set mana of (Temp_Unit) to Temp_MP
- Unit - Unhide (Temp_Unit)
(and optional we can add a Effect)
- Special Effect - Create resurrection effect at Temp_Loc
- Custom script: call RemoveLocation(udg_Temp_Loc)
Unfortunately, this does not revive the unit either. You could try to prevent the unit from dying (fake its death) but then again, it does not actually revive the unit.we can hide unit instead of killing and creating a new one
Code:Event: - Unit - A unit dies Conditions: - (Unit-type of (Triggering unit)) is not a Hero Actions: - Set Temp_Unit = (Triggering unit) - Set Temp_Loc = (Position of (Triggering unit)) - Set Temp_HP = (Life of (Triggering unit)) - Set Temp_MP = (Mana of (Triggering unit)) - Unit - Hide (Triggering unit) - Unit - Pause (Triggering unit) - Wait x seconds step 2 Actions: - Unit - Unpause (Temp_Unit) - Unit - Move (Temp_Unit) instantly to Temp_Loc - Unit - Set life of (Temp_Unit) to Temp_HP - Unit - Set mana of (Temp_Unit) to Temp_MP - Unit - Unhide (Temp_Unit) (and optional we can add a Effect) - Special Effect - Create resurrection effect at Temp_Loc - Custom script: call RemoveLocation(udg_Temp_Loc)
is it the same with Unit - Revive (x Unit) at x with x% life and x% mana then ? of so then iam out of idersI believe Reincarnation and Animate Dead work similarly. Resurrection is still your best option. I don't think there's any other way.
Unfortunately, this does not revive the unit either. You could try to prevent the unit from dying (fake its death) but then again, it does not actually revive the unit.
Event:
- Unit - A unit dies
Conditions:
- (Unit-type of (Triggering unit)) is not a Hero
Actions:
- Set Temp_Unit = (Triggering unit)
- Set Temp_Loc = (Position of (Triggering unit))
- Set Temp_HP = (Life of (Triggering unit))
- Set Temp_MP = (Mana of (Triggering unit))
- Unit - Remove (Triggering unit) from the game
- Wait x seconds
Step 2
Actions:
- Unit - Revive (Temp_Unit) at Temp_Loc with Temp_HP% life and Temp_MP% mana
- Special Effect - Create resurrection effect at Temp_Loc
- Custom script: call RemoveLocation(udg_Temp_Loc)
There's no Unit - Revive action in GUI, and no JASS nor LUA native for it either. Removing unit also permanently removes said unit and all of the relevant data of said unit from the game.is it the same with Unit - Revive (x Unit) at x with x% life and x% mana then ? of so then iam out of iders
because if it does work we can do,
Code:Event: - Unit - A unit dies Conditions: - (Unit-type of (Triggering unit)) is not a Hero Actions: - Set Temp_Unit = (Triggering unit) - Set Temp_Loc = (Position of (Triggering unit)) - Set Temp_HP = (Life of (Triggering unit)) - Set Temp_MP = (Mana of (Triggering unit)) - Unit - Remove (Triggering unit) from the game - Wait x seconds Step 2 Actions: - Unit - Revive (Temp_Unit) at Temp_Loc with Temp_HP% life and Temp_MP% mana - Special Effect - Create resurrection effect at Temp_Loc - Custom script: call RemoveLocation(udg_Temp_Loc)
but if also dont work then iam out of iders
Based on the responses here, I have to concur. There's no mean of mimicking resurrection directly via triggers. I also investigate Spell System, but apparently it uses the real resurrection ability for one of the spells which I thought might have a solution to my issue. I might need to check if it is possible to add an ability to a dead unit and then give it reincarnation to self-resurrect as an alternative.I believe Reincarnation and Animate Dead work similarly. Resurrection is still your best option. I don't think there's any other way.
To simplify, yes. The reason is that resurrection (and by extension animate dead) retains all unit data as shown in my example test map.so the goal is to simulate resurrection ability via triggers without removing or recreating the unit ?
Well, depending on the map, Suicidal classification comes first in mind since only sapper uses them. It's hard for a generic use-case to pick one classification that can be our valid target for Resurrection.Regarding the Resurrection solution, you could set it's Targets Allowed to require an unused Classification and Add/Remove that to the Corpses as needed. That might be better than Hiding a corpse since that would likely interrupt the Order of something like Cannibalize or Raise Dead.
Shadow here means the exact copy of the unit with all of their previous state intact. Revive is that exact shadow being revived again (I can work with the relocation, though now I have another question on that...)Target an area and raises the shadow of corpses within the area. Always succeed on level 1/2/3 units. Higher level units have 10/20/30% chance for success, with up to 3 attempts per corpse. Created shadows are permanent. When a shadow dies, drain mana equals to 30/20/10% of maximum health of killed shadow to revive them next to the caster, but permanently died if caster doesn't have mana to revive them. Cannot be used on workers and heroes.
Had to double post so notifications come your way.Regarding the Resurrection solution, you could set it's Targets Allowed to require an unused Classification and Add/Remove that to the Corpses as needed. That might be better than Hiding a corpse since that would likely interrupt the Order of something like Cannibalize or Raise Dead.
Edit, some other ideas:
1) Fake the entire Death system in your map. Detect lethal damage -> Hide "dead" unit -> Create a Special Effect that mimics the "dead" unit and it's death animation -> Create a corpse at it's position if necessary (you could even link the corpse to the "dead" unit).
2) Use a Unit Indexer that doesn't recycle unused Custom Values (or does so in a very controlled manner). Use that Custom Value as the key for all of your data tracking needs. Now whenever you want to transfer data from a Dead unit to a New unit you simply pass over the Custom Value.
Then for tracking the Abilities, you can use:
A Hashtable that stores each Unit-Type and all of their important "custom" information, like starting Abilities.
A set of custom "Add" and "Remove" Ability functions which track the unit's abilities in another Hashtable (one for individual units as opposed to unit-types).
That way when it comes time to Revive something you can instead create a new unit, transfer the reviving unit's custom value over to it, map the new unit to a central Unit Array (ie: UDexUnits in Bribe's unit indexer), and transfer the reviving unit's abilities over as well. Regarding issues, at the moment all I can think of would be Unit Groups. It's possible to avoid them entirely, if need be (arrays that use custom values come to mind).
Obviously these are more "design your entire map around it" solutions and not very practical.
I wanted to suggest this earlierWouldn't it risk failure if two corpses are on top of each other?
But I solved it thanks to this post: How To Stop Neutral Units From Returning To Spawn PointThe reason why is because of creeps. (arghh) When I move them to the dummy and then revive them, and then move them back, it works fine. But if I say attack them and then run, they will run back to the dummy. (After they are revived, that kind of "changes" their start position to wherever they were revived) So they run back and that is their new home.
Gamecache restoring the unit should, though. Try that on a dead unit.CreateUnit does not retain data from AddUnitAbility and MakeUnitAbilPermanent combo.
You probably want to comment out the highlighted section of the code, or at least wrap it in an ITE that checks that the unit is actually owned by a Neutral player:I am curious if the data for Game Cache does hold for multiplayer, because my memory recall they don't function in multiplayer hence the necessity of Save/Load Systems. It would be a great alternative, albeit there might be hidden drawbacks that needs to be tested in entirety, to the ReviveUnit that @Rheiko provided in the post prior.
For now, I'll go with the ReviveUnit that Rheiko has provided since it should solve the issue I have at the moment and this can be considered solved for my needs, though it might be worth exploring on the matter of reviving unit further if anyone wants to. Thanks everyone for the help!
function ReviveUnit takes unit u returns boolean
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local player p = GetOwningPlayer(u)
local boolean success
if IsUnitType(u, UNIT_TYPE_HERO) == true then
return ReviveHero(u, x, y, false)
else
call SetUnitX(u, rx)
call SetUnitY(u, ry)
set success = IssueImmediateOrderById(reviver, 852094)
call SetUnitX(u, x)
call SetUnitY(u, y)
// >>> ISSUES HERE <<<
// Prevent units to run back towards the resurrection spot
call SetUnitOwner(u, Player(0), false)
call SetUnitCreepGuard(u, false)
call RemoveGuardPosition(u)
call SetUnitOwner(u, p, true)
///////////////////////
endif
return success
endfunction
function ReviveUnit takes unit u returns boolean
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local boolean success
if IsUnitType(u, UNIT_TYPE_HERO) == true then
return ReviveHero(u, x, y, false)
else
call SetUnitX(u, rx)
call SetUnitY(u, ry)
set success = IssueImmediateOrderById(reviver, 852094)
call SetUnitX(u, x)
call SetUnitY(u, y)
call IssueImmediateOrder(u, "stop") // Replace with Integer id
endif
return success
endfunction
It does work for both neutral units and non-Neutral units. At least it does in the version I was testing it (1.27 and 1.31). However, I can't say for sure how it behaves in newer patches. Comment out that code and try to kill neutral units / non-Neutral units, wait for it to get resurrected, then attack it and run to the edge of the map, it will follow you but after a while, it will return to top right corner (location where it got resurrected) instead of to the center (location before it got resurrected). This will not happen with that code around.^ This does nothing on non-Neutral units and will likely cause unwanted side effects. In your map's case it may be entirely unwanted. Also, the function leaks a Player (p needs to be nulled).
Already tried it. Didn't help with the issue.Lastly, the Revived units stack on top of one another, I suggest Ordering them to Stop as well:
function ReviveUnit takes unit u returns boolean
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local boolean success
local player p
if IsUnitType(u, UNIT_TYPE_HERO) == true then
return ReviveHero(u, x, y, false)
else
set p = GetOwningPlayer(u)
call SetUnitX(u, rx)
call SetUnitY(u, ry)
set success = IssueImmediateOrderById(reviver, 852094)
call SetUnitX(u, x)
call SetUnitY(u, y)
call IssueImmediateOrder(u, "stop")
// Prevent units to run back towards the resurrection spot
call SetUnitOwner(u, Player(0), false)
call SetUnitCreepGuard(u, false)
call RemoveGuardPosition(u)
call SetUnitOwner(u, p, true)
set p = null
endif
return success
endfunction
call IssueImmediateOrder(u, "stop")
matters at all but we can try to be safe, I guess.local location loc = Location(0, 0)
// ^ That creates two things, a location variable (handle) and the actual location object which contains the coordinates
call RemoveLocation( loc )
// ^ That destroys the location object, but "loc" is still referencing it
set loc = null
// ^ That removes the final reference and helps it become garbage collected
Yeah, the player switch is necessary. I guess that's another downside to it. Surely, it can be optional but regardless what you choose, both have issues. If you want to reset guard of the resurrected unit, it can fire "A unit changes ownership" event but if you don't, the resurrected unit will go to the corner of the map.Anyway, is the Player switch necessary? That's the concerning function to me, since it can fire an Event like "A unit changes ownership". Also, it still seems like an optional thing to me, maybe create a global boolean to control the behavior -> If Reset_Guard_Pos == True then do that stuff.
function ReviveUnit takes unit u, boolean resetGuardPos returns boolean
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local boolean success
local player p
if IsUnitType(u, UNIT_TYPE_HERO) == true then
return ReviveHero(u, x, y, false)
else
set p = GetOwningPlayer(u)
call SetUnitX(u, rx)
call SetUnitY(u, ry)
set success = IssueImmediateOrderById(reviver, 852094)
call SetUnitX(u, x)
call SetUnitY(u, y)
call IssueImmediateOrder(u, "stop")
// Prevent units to run back towards the resurrection spot
if resetGuardPos == true then
call SetUnitOwner(u, Player(0), false)
call SetUnitCreepGuard(u, false)
call RemoveGuardPosition(u)
call SetUnitOwner(u, p, true)
endif
set p = null
endif
return success
endfunction
call ReviveUnit(unit whichUnit, boolean resetGuardPos)