| 05-20-2005, 06:45 AM | #1 |
After banging my head against this problem for a few days, I have to ask you assembled experts for help. I have a trigger which fires when a unit gets close to one of a number of other units. The event for this trigger is created dynamically, that is, during game play. This statement creates the event: Inside the trigger "TakeAMeeting", the "Entering Unit" gives me the unit that did the approaching, but there's no way to get the unit that was approached, the (Picked unit), in this case. My current solution is a complete kludge: I make a temporay region around the entering unit of a size larger than 132, then see if any units within that region are members of MyUnits. Since I conveniently place the members of MyUnits far enough away, this process results in exactly one unit, and that is my "approached" unit. Is there a better way? Here is the code in the TakeAMeeting trigger to get the "approached" unit: What I want is some way to get IQ_unit without all that rigamarole of points, regions, unit groups, et cetera. Seems to me Blizzard must have the approached unit somewhere, as it has to center a region around it. I suspect you're curious how the problem arose, the wider context, as it were: I'm writing a reusable package of triggers (GUI only, no jass) to encapsulate what I call an Item Quest - a quest where one must acquire a particular item (usually held by a powerful enemy hero), and deliver it to a neutral passive hero for a reward (another item). The package allows one to define many such quests simply by assigning to array elements the neutral passive hero (IQ_wanter), the item sought after (IQ_wanted_itemtype), and the reward (IQ_reward_itemtype). One of my objectives is a set of triggers with a minimum of code and variables, and this problem makes that objective hard to acheive. Thanks in advance for any help you can provide. Roy. |
| 05-20-2005, 09:37 AM | #2 |
There may be a better way to do this, but here goes my explanation. Right now you add new events to an existing trigger. My suggestion would be to dynamically create new triggers for each unit in your MyUnits group, then store info on the unit using the created trigger as a key. Your problem is that you cannot figure out which unit was approached. However, you easily know which trigger fired. If you have one trigger per unit, you take the trigger, and get your unit. To do this would will probably need to use a combination of the return bug, gamecache, and custom script. The return bug isn't really a bug, and is very helpful; don't be discouraged by the name. Gamecache is a hash table, so is pretty darn quick and allows storing of variables using string names. Custom script is basically putting lines of jass into the gui. Code:
Return bug functions in your custom script code area:
// this gives the integer value of any handle (unit, trigger, item, destructible, etc.)
function H2I takes handle value returns integer
return value
return 0
endfunction
// this simply converts that integer into a string ... so you don't have to go I2S(H2I( handle )) all the time
function H2S takes handle value returns string
return I2S(H2I(value))
endfunction
// this takes a stored integer value for a unit and returns the unit
function I2U takes integer value returns unit
return value
return null
endfunction
// needed variables which you need to use (i used your naming scheme)
temp_string
temp_integer
temp_trigger
IQ_unit
// this gives you an idea of how to setup what you need
setup
Events
Map initialization
Conditions
Actions
Game Cache - Create a game cache from YourMap // at map init you need to create a game cache, unless you already use one
Unit Group - Add SomeUnits <gen> to MyUnits // put your units in your group
Unit Group - Pick every unit in MyUnits and do (Actions)
Loop - Actions
Custom script: set udg_temp_trigger = CreateTrigger() // dynamically create a trigger
Trigger - Add to temp_trigger the event (Unit - A unit comes within 132.00 of (Picked unit)) // add the event to the trigger
Custom script: call TriggerAddAction( udg_temp_trigger, function Trig_fires_Actions ) // add the action to the trigger ... note that if you use a gui trigger, the actions for it are always function Trig_insert_your_trigger_name_here_Actions where _ represents a space
Custom script: set udg_temp_string = H2S( udg_temp_trigger ) // store the integer value of the trigger as a string
Custom script: set udg_temp_integer = H2I( GetEnumUnit() ) // get the integer value of the unit the trigger fires for
Game Cache - Store temp_integer as approached of temp_string in (Last created game cache) // store the unit in the gamecache using the trigger as a key ... gamecache stores things like this: cache > folder > key > value, in this case the cache refers to the last created one, the folder is the string for the trigger, and the key is the string approached
// the actions for your trigger when the event fires
fires
Events
Conditions
Actions
Custom script: set udg_temp_string = H2S( GetTriggeringTrigger() ) // triggeringtrigger is the trigger that is fired, store it as a string
Set temp_integer = (Load approached of temp_string from (Last created game cache)) // get the stored integer value of the unit you created the trigger for
Custom script: set udg_IQ_unit = I2U( udg_temp_integer ) // get the unit that integer value represents
Game - Display to (All players) the text: (String((Unit-type of (Triggering unit)))) // shows you the name of the approaching unit
Game - Display to (All players) the text: (String((Unit-type of IQ_unit))) // shows you the name of the approached unitHope that helps you out. Edit - Also, if you don't feel like diving into a few lines of jass with the return bugs, I guess you could setup two arrays, one for triggers, the other for units, and also maybe an integer variable to store the number of elements in the arrays. Basically you would need two lines of custom script: Code:
set udg_temp_trigger = CreateTrigger() call TriggerAddAction( udg_temp_trigger, function Trig_fires_Actions ) But then you just set trigger_array[i] = temp_trigger and unit_array[i] = Picked Unit. Then when the trigger fires, you do an if/then comparison in a loop, kind of like: Code:
For each (Integer A) from 1 to array_count, do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
trigger_array[Integer A] Equal to (This trigger)
Then - Actions
Set IQ_unit = unit_array[Integer A]
Custom script: exitwhen true /// maybe 3 lines of custom script :-\
Else - ActionsThis would work as well, but using the return bugs would be faster if you have a lot of units in your MyUnits group. |
| 05-24-2005, 03:06 PM | #3 |
umm, well since a unit is comming within ur picked unit, just repick the unit, lol, try this. Code:
unit comes wihtin range of unithere set theunituneedtopick = random unit wihtin samedistance of triggering unit matching - unit - matching unit not = triggering unit if u got alot of units bunched together, it wont work, but if u just got 1 unit touching another and u wanna select the unit that was being touched, u can do that. is that what u wanted? |
| 05-24-2005, 05:05 PM | #4 |
Well, that's the thing. Both methods I posted would work with any number of units present, and rather than radnomnly repicking a unit and hoping it is the right one, my methods get the exact unit every time. Also, if you implemented some checking process it would be like what mittu was doing originally, and the speed of such actions would be dependent on the number of units in his MyUnits group. My *first* method uses the trigger that fires to recall the unit that was approached, so there is a constant search time that is less that going through a list. |
| 05-24-2005, 05:11 PM | #5 |
SADISM's is the only way that would work all the time |
