• 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.

Using an Ability as an Attached Timer

Status
Not open for further replies.
I want to create an ability that does nothing but casts itself at intervals every x seconds. Everything else in this post is irrelevant and is just here to show you what I'd be doing with said ability if I had it.

I'd be using it as a timer to make units check for potential mates every once in awhile & auto-mate if there's a female that is not pregnant in the vicinity. That would be scripted based on the event.

i.e.
  • Auto-mate
    • Events
      • Unit - Any Unit uses Action - Mate at Generic6 - Complete stage (Ignore shared abilities)
    • Local Variables
      • u = No Unit <Unit>
      • u 2 = No Unit <Unit>
      • cv = 0 <Integer>
      • cv 2 = 0 <Integer>
      • ug = (Empty unit group) <Unit Group>
      • ut = No Game Link <Game Link - Unit>
      • pt = No Point <Point>
      • r = No Region <Region>
      • gender = false <Boolean>
      • ------- Constants
      • radius = 15.0 <Real (Constant)>
      • uf = Required: Biological; Excluded: Missile, Dead, Hidden <Unit Filter>
    • Conditions
    • Actions
      • General - Custom Script: lv_u = EventUnit();...
JASS:
lv_u = EventUnit();
lv_cv = FixedToInt(UnitGetCustomValue(lv_u, gv_CVS));

if (!gv_mature[lv_cv]) {
    return true;
}

lv_ut = UnitGetType(lv_u);
lv_pt = UnitGetPosition(lv_u);
lv_r = RegionCircle(lv_pt, lv_radius);
lv_ug = UnitGroup(null, c_playerAny, lv_r, lv_uf, 0);

UnitGroupLoopBegin(lv_ug);
while (!UnitGroupLoopDone()) {
    lv_u2  = UnitGroupLoopCurrent();
    lv_cv2 = FixedToInt(UnitGetCustomValue(lv_u2, gv_CVS));
    
    if (UnitGetType(lv_u2) == lv_ut) {
        if (gv_mature[lv_cv2]) {
            if (gv_gender[lv_cv] != gv_gender[lv_cv2]) {
                if ((!gv_pregnant[lv_cv]) && (!gv_pregnant[lv_cv2])) { // The other 'pregnancy' check actually checks the males fertility.
                    UnitIssueOrder(lv_u, OrderTargetingUnit(AbilityCommand("Mate", 0), lv_u2), c_orderQueueAddToEnd);
                        if (!gv_gender[lv_cv]) {
                            UnitGroupLoopEnd();
                        }
                }
            }
        }
    }
    UnitGroupLoopStep();
}
UnitGroupLoopEnd();
UnitIssueOrder(lv_u, Order(AbilityCommand("stop", 0)), c_orderQueueAddToEnd);
Edit 2: I also need an ability that can be toggled on or off and does nothing at all, but for my stamina system.
 
Last edited:
Um done easily enough.

Event -> Every _ Seconds of Game Time
Condition -> <your conditions>
Action -> Make unit cast ability <mate>

As for the ability that is toggled on or off,
Make two button icons. One is the on icon (BTN) and one is the off icon (DSBTN)

Event -> Unit uses <stamina> at Generic6 Complete
Condition -> Owner of (triggering unit) = 1
(Abs(P1StaminaCheck = true)
Action -> Set P1StaminaCheck = false
Enable Button (StaminaDSBTN) for owner of (triggering unit)
Disable Button (StaminaBTN) for owner of (triggering unit)

Event -> Unit uses <stamina> at Generic6 Complete
Condition -> Owner of (triggering unit) = 1
(Abs(P1StaminaCheck = falso)
Action -> Set P1StaminaCheck = true
Disable Button (StaminaDSBTN) for owner of (triggering unit)
Enable Button (StaminaBTN) for owner of (triggering unit)

P1StaminaCheck is a true/false variable.
You will need one for each player.
I can't remember if enable/disable button is a function.
If it isn't, just create two seperate abilities and have every trigger recognize both as an event.
Have one ability linked to BTN and one DSBTN.
I know for a fact "Enable Ability for (Player)" is a function.
Or you can take the easy way out and just not have a DSBTN or BTN and figure out some other way of letting the player know that stamina is on / off.
 
Um done easily enough.

Event -> Every _ Seconds of Game Time
Condition -> <your conditions>
Action -> Make unit cast ability <mate>

My question was purely pertaining to the data editor, I really don't need help with the scripts which I've actually already got done. The reason your first suggestion is not viable to me is because it would result in every single gender-assigned unit in my map trying to find a mate all at once. To do this I'd have to loop through a unit group, then set all those variables for each unit found in the unit group, and create a second unit group to find units it can mate with. All of that done at once would probably result in lag and I don't want synchronous mass-mating anyways. I just need an ability that does nothing but casts itself every x seconds.

This is how I have the script currently set up:


JASS:
//--------------------------------------------------------------------------------------------------
// Trigger: Auto-mate
//--------------------------------------------------------------------------------------------------
bool gt_Automate_Func (bool testConds, bool runActions) {
    // Variable Declarations
    unit lv_u;
    unit lv_u2;
    int lv_cv;
    int lv_cv2;
    unitgroup lv_ug;
    string lv_ut;
    point lv_pt;
    region lv_r;
    bool lv_gender;
    const fixed lv_radius = 15.0;
    unitfilter lv_uf;

    // Variable Initialization
    lv_u = null;
    lv_u2 = null;
    lv_cv = 0;
    lv_cv2 = 0;
    lv_ug = UnitGroupEmpty();
    lv_ut = null;
    lv_pt = null;
    lv_r = null;
    lv_gender = false;
    lv_uf = UnitFilter((1 << c_targetFilterBiological), 0, (1 << c_targetFilterMissile), (1 << (c_targetFilterDead - 32)) | (1 << (c_targetFilterHidden - 32)));

    // Actions
    if (!runActions) {
        return true;
    }

    lv_u = EventUnit();
    lv_cv = FixedToInt(UnitGetCustomValue(lv_u, gv_CVS));
    
    if (!gv_mature[lv_cv]) {
        return true;
    }
    
    lv_ut = UnitGetType(lv_u);
    lv_pt = UnitGetPosition(lv_u);
    lv_r = RegionCircle(lv_pt, lv_radius);
    lv_ug = UnitGroup(null, c_playerAny, lv_r, lv_uf, 0);
    
    UnitGroupLoopBegin(lv_ug);
    while (!UnitGroupLoopDone()) {
        lv_u2  = UnitGroupLoopCurrent();
        lv_cv2 = FixedToInt(UnitGetCustomValue(lv_u2, gv_CVS));
        
        if (UnitGetType(lv_u2) == lv_ut) {
            if (gv_mature[lv_cv2]) {
                if (gv_gender[lv_cv] != gv_gender[lv_cv2]) {
                    if ((!gv_pregnant[lv_cv]) && (!gv_pregnant[lv_cv2])) { // The other 'pregnancy' check actually checks the males fertility.
                        UnitIssueOrder(lv_u, OrderTargetingUnit(AbilityCommand("Mate", 0), lv_u2), c_orderQueueAddToEnd);
                            if (!gv_gender[lv_cv]) {
                                UnitGroupLoopEnd();
                            }
                    }
                }
            }
        }
        UnitGroupLoopStep();
    }
    UnitGroupLoopEnd();
    UnitIssueOrder(lv_u, Order(AbilityCommand("stop", 0)), c_orderQueueAddToEnd);
    return true;
}

//--------------------------------------------------------------------------------------------------
void gt_Automate_Init () {
    gt_Automate = TriggerCreate("gt_Automate_Func");
    TriggerAddEventUnitAbility(gt_Automate, null, AbilityCommand("Sprint", 0), c_unitAbilStageComplete, false);
}

I just need to make a new ability which auto-casts itself every x seconds.

As for the enable disable thing, I don't think you understood what I was asking there either. :sad: For that I just need to make my sprint ability toggle on/off like that one ability in Warcraft III that burns every unit within a certain radius around the unit while draining mana. Illidan has said ability in Footman Frenzy. I don't want my ability to drain mana or burn anything though, I just need it to toggle on/off and do nothing.
 
Apologies, I misunderstood what you wanted.
Take a look at the medivac heal ability to figure out auto-casting abilities (I for one have never had to make one, so I can offer little insight).

As for the enable disable thing, again I believe the best thing to do would be to have a variable tell you whether or not the ability is active. Maybe I just didn't word it for you to understand what I meant.

If the ability is on, the CheckAbility variable is set to true.
If the ability is off, the CheckAbility variable is set to false.
That's all that really means.
The trigger identifies when the ability is used, and if the ability is already on, turns it off. If it is off, turns it on.
To add cooldowns and what not, take a look at the data editor.
I imagine you're going to make your spell with triggers, so this would be the best bet.

However if you are going to make the ability in the data editor, the only thing I can think of that you can do is to create a behaviour that is given to units around the unit when the ability is on (again I can't really think of anything else to identify when the ability is on other than triggers. I always use triggers).

Oh and your scripting is alien to me.
I haven't taken the time to learn Galaxy or vJass / Jass yet.
 
Level 1
Joined
Feb 24, 2010
Messages
62
I'd say, use a Behavior with a periodic effect and add it to the units that need it.
From there on you can either use the data editor to check everything or use the 'Effect has been used blabla' event in the trigger editor to continue.
 
As for the enable disable thing, again I believe the best thing to do would be to have a variable tell you whether or not the ability is active. Maybe I just didn't word it for you to understand what I meant.

I don't need help with scripting and know full-well how to use booleans. The reason I want an ability you toggle on & off is for UI purposes. I could just have a regular ability that does nothing and then I set an attached boolean on/off like
JASS:
gv_isSprinting[lv_cv] = true;
however I'd like an ability that toggles on/off so you can see from looking at the button if they're sprinting or not. I don't need help with scripts, just the data editor. >.<

I imagine you're going to make your spell with triggers, so this would be the best bet.

I have no intentions to use that data editor for anything but dummy abilities that do nothing. The scripting language you see is .galaxy.


I'd say, use a Behavior with a periodic effect and add it to the units that need it.
From there on you can either use the data editor to check everything or use the 'Effect has been used blabla' event in the trigger editor to continue.

I have next to no understanding of how behaviours are used in the data editor.

I'm trying to trigger an event which I can reference the unit from every x seconds & run my auto-mate script off of.

I prefer to avoid that data editor but how is it even possible to check anything with it?
 
Last edited by a moderator:
As for the ability that is toggled on or off,
Make two button icons. One is the on icon (BTN) and one is the off icon (DSBTN)

This is how I would show whether or not the ability is active.
Basically all it is, is two abilities that have the same effect, but one ability has a darker button (meaning it is active).
The player would not know that it is two different abilities, instead would think that it means the button has already been clicked and is therefore active.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,259
BlueBerryWizard, why do you use custom script so inefficiently? Your conditional flow control structures could be optimized greatly for readability (and possibly speed).

Anyway...
Make a buff, set it up to run a perodic effect and give it to your units.
The perodic effect it runs is nothing more than a dummy (eg just a set type effect with no further processes).
You can then bind your trigger to the dummy effect with the appropiate event. (I still need to test this out, but it in theory should work).

The event I am refering to...
native void TriggerAddEventPlayerEffectUsed (trigger t, int player, string inEffect);
Hopefully it accepts anyplayer.

You could probably use a lot of data to simplify your system greatly. Triggers are meant to provide additional functionality which data does not.
 
This is how I would show whether or not the ability is active.
Basically all it is, is two abilities that have the same effect, but one ability has a darker button (meaning it is active).
The player would not know that it is two different abilities, instead would think that it means the button has already been clicked and is therefore active.

You have got to be trolling me. If so, 9/10 you've had me going for quite awhile.

BlueBerryWizard, why do you use custom script so inefficiently? Your conditional flow control structures could be optimized greatly for readability (and possibly speed).

Anyway...
Make a buff, set it up to run a perodic effect and give it to your units.
The perodic effect it runs is nothing more than a dummy (eg just a set type effect with no further processes).
You can then bind your trigger to the dummy effect with the appropiate event. (I still need to test this out, but it in theory should work).

The event I am refering to...
native void TriggerAddEventPlayerEffectUsed (trigger t, int player, string inEffect);
Hopefully it accepts anyplayer.

You could probably use a lot of data to simplify your system greatly. Triggers are meant to provide additional functionality which data does not.

It does accept any player. Can I get the unit that the effect was applied to though?

If I can't, I guess I'll have to make another integer array, attach said integers to the units, loop through em' all every interval, and subtract until they reach 0 in which case I have em' mate & I set that integer back to say 7 (so that if each interval is one second long, it takes them 7 seconds to try n' find a mate again).
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,259
Code:
// Effect amounts
const int c_effectAmountAbsorbed        = 0;
const int c_effectAmountDamaged         = 1;
const int c_effectAmountDodged          = 2;
const int c_effectAmountFound           = 3;
const int c_effectAmountHealed          = 4;
const int c_effectAmountKilled          = 5;
const int c_effectAmountSplashed        = 6;
const int c_effectAmountLifeChanged     = 7;
const int c_effectAmountShieldsChanged  = 8;
const int c_effectAmountEnergyChanged   = 9;

native string   EventPlayerEffectUsed ();
native point    EventPlayerEffectUsedPoint (int inLocation);
native unit     EventPlayerEffectUsedUnit (int inLocation);
native int      EventPlayerEffectUsedUnitOwner (int inLocation);
native string   EventPlayerEffectUsedUnitType (int inLocation);
native int      EventPlayerEffectUsedAmountInt (int inAmount, bool total);
native fixed    EventPlayerEffectUsedAmountFixed (int inAmount, bool total);

I can not find values for inLocation but I am guessing they are const\ant numbers representing the scope of the unit. Eg, is it the effect, the target, the outer etc.
 
Code:
// Effect amounts
const int c_effectAmountAbsorbed        = 0;
const int c_effectAmountDamaged         = 1;
const int c_effectAmountDodged          = 2;
const int c_effectAmountFound           = 3;
const int c_effectAmountHealed          = 4;
const int c_effectAmountKilled          = 5;
const int c_effectAmountSplashed        = 6;
const int c_effectAmountLifeChanged     = 7;
const int c_effectAmountShieldsChanged  = 8;
const int c_effectAmountEnergyChanged   = 9;

native string   EventPlayerEffectUsed ();
native point    EventPlayerEffectUsedPoint (int inLocation);
native unit     EventPlayerEffectUsedUnit (int inLocation);
native int      EventPlayerEffectUsedUnitOwner (int inLocation);
native string   EventPlayerEffectUsedUnitType (int inLocation);
native int      EventPlayerEffectUsedAmountInt (int inAmount, bool total);
native fixed    EventPlayerEffectUsedAmountFixed (int inAmount, bool total);

I can not find values for inLocation but I am guessing they are const\ant numbers representing the scope of the unit. Eg, is it the effect, the target, the outer etc.

I created a periodic buff but it doesn't even come up in the list for my event...

I'm just going to use a that integer array I was talking about until I'm ready to show you my map I guess.
 
You did attach an effect to the perodic buff right? Also what list? It is just a string field you put in and their script IDE does not give sujestions (cheapskates lol)....

>You did attach an effect to the perodic buff right?

That I did not.

Afterwards I did attached a (generic) effect and it still didn't work, but I tried a (set) effect instead and it worked.

My problem here is resolved.

I just need to change my script to make em' go for the nearest unit & not que orders and everything is done (in regards to auto-mating).
 
Status
Not open for further replies.
Top