| 03-19-2009, 09:57 PM | #1 |
Hi guys, I am making a ward spell. Basically anytime a unit dies near the ward I want to raise 2 skelies from it (simple skely sumon). Thing is I could use a timer and make a periodic check to see if there are any nearby corpses, but I think that using an event "Unit_death" would be more efficient. Problem is that I can't find a solution for this problem without using dynamic triggers (which are evil). Then, I started having all kinds of ideas (what if my ward is activated when a building finished construction? or some other event happens?) but my brain is formated to think "timers and dynamic triggers only" and now they won't get out of my head. Does some one know a simple algorithm for this simple spell? |
| 03-19-2009, 10:02 PM | #2 |
Autocast Raise Dead? Or perhaps you want it scripted anyway? |
| 03-19-2009, 10:10 PM | #3 |
Use TriggerRegisterAnyUnitEventBJ with EVENT_PLAYER_UNIT_DEATH. Then use a global group to enum any wards in range of the dying units' X/Y coordinates. |
| 03-19-2009, 10:14 PM | #4 | ||
Quote:
Quote:
Also, this may be a silly question but, if a unit is within 300 range of a ward, then a ward is also withing 300 range of a unit, I mean the intersection area for both is exactly the same and mathematically equivalent right? |
| 03-19-2009, 10:17 PM | #5 |
you may not even need to enum units near the dying unit ... you could store all active wards in an unit-array or unit-group and then only check if your unit is in range of any of them... |
| 03-19-2009, 10:27 PM | #6 | |
Quote:
Also, if I use arrays, I will have the problem of "who gets the skelies" as well =S |
| 03-19-2009, 10:47 PM | #7 |
hmm ..yeah ..it would be applicable for a hero spell though (i thought it would be a hero spell..). Well then do the groupenum stuff on generic unitdeath event... but add a condition ...ammount of wards > 0 ... so you dont have to search for a ward when you dont have any wards at all... |
| 03-19-2009, 11:08 PM | #8 |
Everyone "wins" the skellies - I don't see why there needs to be any disctinction. But if you do want to limit the skellies, store a GetRandomReal from 1 to 100. Then divide the range of options up based on the number of wards in range. Say there are 10 wards. That means check if RandReal is between 1 and 10 for first. For the nth ward, check if the rand is between (n-1)*10 and n*10. This can be easily done with a FirstOfGroup loop and an integer incremented each time the group detects a ward. Or honestly, just check which ward is closest to the dying unit. SquareRoot heavy, but it gets the job done since the choice of ward is entirely arbitrary. |
| 03-20-2009, 12:45 AM | #9 | |
Quote:
|
| 03-20-2009, 01:03 AM | #10 |
No, I guess it isn't now that I think about it. |
| 03-20-2009, 01:35 AM | #11 |
You could also just let "everybody" win - create two units one at a time for each player so you can add timers to all of them, then remove the dead unit from the game (corpse is gone). |
| 03-20-2009, 04:26 PM | #12 |
MMm, if I have 5 wards, raising 5 skelies from a dead body is quite unbalanced for a melee spell xD I think I will follow the suggestion above. If a unit dies and I have 2 wards near it, the closest ward "claims" the body for the skely. If 2 wards have same distance, then I pick a random one =D I may post some code for people to see. ANyway, when I am done I will give +rep to all people for help and suggestions! EDIT EDIT EDIT Ok guys, here is the code for people who are interested. Suggestions on how to make the spell nice are also welcome: JASS://=========================================================================== //When a unit dies the ward summons a skely from it's body. If the ward has an //ability, that allows to summon stronger skelies. // //@author Flame_Phoenix // //@version 1.0 //=========================================================================== scope Ward initializer Init private keyword skelyIds //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer WARD_ID = 'h000' //the rw of the ward private constant real RANGE = 450. //Range of the ward private constant integer WARD_ABI = 'A001' //ability of the ward that allows strong skelies endglobals private function SkelySetup takes nothing returns nothing //here we type all types of units this spell can have //in this case I only use 2 types of units set skelyIds[1] = 'nlv1' //Skely level 1 set skelyIds[2] = 'nlv2' //Skely level 2 endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== globals private group wards private boolexpr targs private integer array skelyIds endglobals //=========================================================================== private function ChooseWards takes nothing returns boolean return GetUnitTypeId(GetFilterUnit()) == WARD_ID endfunction //=========================================================================== private function Actions takes nothing returns nothing local unit vic = GetTriggerUnit() local unit f local unit ward = null local unit skely //maths enters here local real vicX = GetUnitX(vic) local real vicY = GetUnitY(vic) local real x local real y local real dx local real minDist = RANGE //here I pick the closest ward to the victim call GroupEnumUnitsInRange(wards, vicX, vicY, RANGE, targs) loop set f = FirstOfGroup(wards) exitwhen(f == null) call GroupRemoveUnit(wards, f) //calculate distance set x = GetUnitX(f) set y = GetUnitY(f) set dx = SquareRoot((x - vicX) * (x - vicX) + (y - vicY) * (y - vicY)) if dx < minDist then set minDist = dx set ward = f endif endloop //now spawn the bastard! xD if ward != null then set skely = CreateUnit(GetOwningPlayer(ward), skelyIds[GetUnitAbilityLevel(ward, WARD_ABI)], vicX, vicY, 0.) call SetUnitAnimation(skely, "birth") //remove the body call ShowUnit(vic, false) endif //cleaning up the mess set ward = null set vic = null set skely = null endfunction //=========================================================================== private function Init takes nothing returns nothing local trigger WardTrg = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(WardTrg, EVENT_PLAYER_UNIT_DEATH ) call TriggerAddAction(WardTrg, function Actions) //Setting globals set wards = CreateGroup() set targs = Condition(function ChooseWards) call SkelySetup() endfunction endscope Btw, +rep to all as promised. |
| 03-20-2009, 05:25 PM | #13 |
JASS:
local real minDist = RANGE*RANGE + 1
... JASS:
set dx =(x - vicX) * (x - vicX) + (y - vicY) * (y - vicY)
|
| 03-20-2009, 10:08 PM | #14 |
@Bobo_The_Kodo Ahhh right ... I always forget to do that small optimization. Anyway, I did a few more modifications: JASS://=========================================================================== //When a unit dies the ward summons a skely from it's body. If the ward has an //ability, that allows to summon stronger skelies. // //@author Flame_Phoenix // //@version 1.1 //=========================================================================== scope Ward initializer Init private keyword skelyIds //=========================================================================== //=============================SETUP START=================================== //=========================================================================== globals private constant integer WARD_ID = 'h000' //the rw of the ward private constant real RANGE = 450. //Range of the ward private constant integer WARD_ABI = 'A001' //ability of the ward that allows strong skelies private constant real SKELY_DUR = 30. //duration of the skelies endglobals private function SkelySetup takes nothing returns nothing //here we type all types of units this spell can have //in this case I only use 2 types of units set skelyIds[1] = 'nlv1' //Skely level 1 set skelyIds[2] = 'nlv2' //Skely level 2 endfunction //=========================================================================== //=============================SETUP END===================================== //=========================================================================== globals private group wards private boolexpr targs private integer array skelyIds endglobals //=========================================================================== private function ChooseWards takes nothing returns boolean return GetUnitTypeId(GetFilterUnit()) == WARD_ID endfunction //=========================================================================== private function Actions takes nothing returns nothing local unit vic = GetTriggerUnit() local unit f local unit ward = null local unit skely //maths enters here local real vicX = GetUnitX(vic) local real vicY = GetUnitY(vic) local real x local real y local real dx local real minDist = RANGE * RANGE + 1 //here I pick the closest ward to the victim call GroupEnumUnitsInRange(wards, vicX, vicY, RANGE, targs) loop set f = FirstOfGroup(wards) exitwhen(f == null) call GroupRemoveUnit(wards, f) //calculate distance set x = GetUnitX(f) set y = GetUnitY(f) set dx = (x - vicX) * (x - vicX) + (y - vicY) * (y - vicY) if dx < minDist then set minDist = dx set ward = f endif endloop //now spawn the bastard! xD if ward != null then set skely = CreateUnit(GetOwningPlayer(ward), skelyIds[GetUnitAbilityLevel(ward, WARD_ABI)], vicX, vicY, 0.) call SetUnitAnimation(skely, "birth") call UnitApplyTimedLife(skely, 'BTLF', SKELY_DUR) //remove the body call ShowUnit(vic, false) endif //cleaning up the mess set ward = null set vic = null set skely = null endfunction //=========================================================================== private function Init takes nothing returns nothing local trigger WardTrg = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(WardTrg, EVENT_PLAYER_UNIT_DEATH ) call TriggerAddAction(WardTrg, function Actions) //Setting globals set wards = CreateGroup() set targs = Condition(function ChooseWards) call SkelySetup() endfunction endscope I think that now I start another thread, but about the spell, which I intend to improve using TimedLightning and fx_ reverse animation (I am going to give each skely a chance to get back to life, playing their death animation in reverse! xD ). Anyway thx for help, +rep! PS: It seems I have to wait 24 to give more reputation =( |
