HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Scripting enabling unit abilities within range

05-23-2008, 08:57 AM#1
Archmage Owenalacaster
My attempts to imagine an efficient system toward my ends have yet to succeed. I welcome suggestions on how I might achieve my goal, outlined thusly:

- A unit (for example, Gendarme Private) is only able to use an ability when another unit (say, Gendarme Corporal) is nearby.
- Preferably, the ability would appear darkened as though disabled until the requirement is fulfilled.
- When the other unit is no longer in range, the ability becomes disabled or unusable again.

I'd prefer the disabled approach, since the alternative I think would necessitate acquiring the ability ID upon its use and then intercepting it and I just find that messy. I'd prefer not to detect the presence of a buff (as produced by an aura on the other unit) because that's not clean or efficient; the system involved ought to be applicable to units without auras.
05-24-2008, 03:07 AM#2
Anopob
I guess you can check when the unit is next to the unit (using the event), and then use a requirement (like an upgrade) to be upgraded or degraded whenever the person is or is not in range. Or you could always just remove/add the spell instead of the disabled form.
05-24-2008, 03:31 AM#3
Archmage Owenalacaster
Hm. I could achieve the disabled look by making two versions of the ability. The one with a disabled graphic would require an upgrade, and so the name of the upgrade could display as "Requires: Gendarme Corporal in vision range". The enabled graphic version would not need an upgrade, and so the trigger could toggle between the two abilities.

Perhaps I could code a something-second loop, which would constantly update who's who in unit groups based on range. Yeah, that might work. I'd prefer something cleaner that responds to specific events, but whatevah.

Thanks for the inspiration. I'll report back in a bit.
05-24-2008, 05:08 AM#4
Alevice
You could just set up a fake requirement, like an existance of a dummy unit. This affect on a player scale, so all units would be affected by the given requirement. A messier trick would be having all affected units changing its owner to a neutral computer that can be controlled by the player.
05-25-2008, 05:48 PM#5
Archmage Owenalacaster
Interesting suggestion, Levi. I think my fake upgrade requirement would be a cleaner approach, but if that falls through I'll try your ideas. I haven't begun coding it, though. I'm preoccupied with dissecting the ReplaceUnitBj function; I intend to create a function to replace a custom barricade unit with the barricade destructible when the former structure completes construction. When I either succeed or get bored, I'll get on scripting the subject of this thread.

UPDATE: My fake upgrade approach works perfectly. I'm still having trouble scripting for the unitgroups and ability toggles and such. Truly, I have a poor sense of how the design ought to flow, I'm barely started with a loop and a polledwait. I need to pick units and somehow send out the ones not in the vicinity of Gendarme Corporals to another group, which if they have the enabled version it disables it, else nothing, and for the Privates in the vicinity, if they have the disabled version of the ability it enables it, else nothing, clear the local unitgroups, lather, rinse, lather, rinse, OCD, repeat. I guess I have some sense of flow, but rather I lack a concise understanding of which functions I ought to call.

Eh, I need some JASS utilities. I'm sick of crashing worldedit.
05-25-2008, 06:14 PM#6
chobibo
download JassNewGen pack
05-29-2008, 03:16 AM#7
Archmage Owenalacaster
Still haven't thought of an efficient way of even selecting all of the Gendarme Privates within range (600) of Gendarme Corporals. I can't think of how to script it. Working on it, but suggestions are, of course, welcome.
05-29-2008, 05:12 AM#8
Alevice
I just got the grasp of your proposal on your second post, and yeah, it is way cleaner than what I had in mind.

This is roughly how I would implement it:

A periodic timer would keep checking which Privates are nearby the Corporal, using the following method: You basically create a rect (regions on everything oustide jass, even the terrain editor) with a width and height of 600 centered on your Corporal and pick all the units owned by the same player than the Corporal that are of type Private and are located on the given rect, remove Ability X and place Ability Y instead.

I know the periodic timer is somewhat of an undesired overhead, but alas, the only other solution is an event of unit within range of another unit that would get registered for every Private, and you would still have to add a periodic timer to check if it is not in range anymore to change it to the disabled version.
05-29-2008, 05:30 AM#9
chobibo
You can also use an aura to replace the rect, periodically check if the unit has the buff and replace skill x with skill y.
05-29-2008, 04:36 PM#10
Alevice
Quote:
Originally Posted by chobibo
You can also use an aura to replace the rect, periodically check if the unit has the buff and replace skill x with skill y.

Quote:
I'd prefer the disabled approach, since the alternative I think would necessitate acquiring the ability ID upon its use and then intercepting it and I just find that messy. I'd prefer not to detect the presence of a buff (as produced by an aura on the other unit) because that's not clean or efficient; the system involved ought to be applicable to units without auras.
05-30-2008, 06:15 AM#11
Archmage Owenalacaster
I've got a model in GUI that seems like it would work, so I have a fair idea of how things are flowing. However, my work on making a clean script without those forsaken bj functions is troubling. I get lost sometimes while dissecting code. Eh, I'll post my (hopefully) working script soon and see how I might improve on it.
05-31-2008, 06:39 AM#12
Archmage Owenalacaster
I get many syntax errors when I check it, but, eh, nothing seems wrong with it.
Using JassNewGen, current version, all standard features initially on.
Collapse JASS:
// Script for the ability Surge of Aggression
scope Surge
// Declaring private variables
    globals
        private group disabled = CreateGroup()
        private group enabled = CreateGroup()
    endglobals
// Declaring private functions
    private function Add_Disabled takes nothing returns nothing
        call GroupAddUnitSimple( GetEnumUnit(), disabled)
    endfunction

    private function Filt_Privates takes nothing returns boolean
        if ( not (GetUnitTypeId(GetEnumUnit()) == 'h001' ) ) then
            return false
        endif
        return true
    endfunction

    private function Shuffle_Enabled takes nothing returns nothing
        if ( Filt_Privates() ) then
            call GroupRemoveUnitSimple( GetEnumUnit(), disabled )
            call GroupAddUnitSimple( GetEnumUnit(), enabled )
        else
        endif
    endfunction

    private function Add_Enabled takes nothing returns nothing
        call ForGroupBJ( GetUnitsInRangeOfLocAll(600.00, GetUnitLoc(GetEnumUnit())), function Shuffle_Enabled )
    endfunction

    private function Swap_Disabled takes nothing returns nothing
        call UnitRemoveAbilityBJ( 'A005', GetEnumUnit() )
        call UnitAddAbilityBJ( 'A004', GetEnumUnit() )
    endfunction

    private function Swap_Enabled takes nothing returns nothing
        call UnitRemoveAbilityBJ( 'A004', GetEnumUnit() )
        call UnitAddAbilityBJ( 'A005', GetEnumUnit() )
    endfunction
// The Actual Trigger Stuff
    function Trig_Ability_Surge_Actions takes nothing returns nothing
        loop
            call GroupClear(disabled)
            call GroupClear(enabled)
            call ForGroupBJ( GetUnitsOfPlayerAndTypeId(Player(0), 'h001'), function Add_Disabled )
            call ForGroupBJ( GetUnitsOfPlayerAndTypeId(Player(0), 'h002'), function Add_Enabled )
            call ForGroupBJ( disabled , function Swap_Disabled )
            call ForGroupBJ( enabled , function Swap_Enabled )
            call PolledWait(2.000)
        endloop
    endfunction
// The Initialization Stuff Follows...
. . .
endscope


UPDATE:
Test ran smoothly, with but a few minor bugs.
- Counts dead Corporals ('h002') when getting Privates ('h001') within 600.00 range. I may have a solution.
- Groups split between in- and out-of-range will not display a button at all, since they are different abilities.
- The ability is based on Roar, and so will only activate singularly instead of in unison. I shall need a new base.
05-31-2008, 08:46 AM#13
Themerion
I think you should perhaps clean up that code a little bit, so that we can get a better overview...

Quote:
Using JassNewGen, current version, all standard features initially on.

Good. If you hold down Ctrl and click on a function name, you can see how the function is made. For instance, you'll see:

Collapse JASS:
// This function is just an unneccesary wrapper around GroupAddUnit...

function GroupAddUnitSimple takes unit toAdd, group target returns nothing
    call GroupAddUnit(target, toAdd)
endfunction

This:
Collapse JASS:
    private function Filt_Privates takes nothing returns boolean
        if ( not (GetUnitTypeId(GetEnumUnit()) == 'h001' ) ) then
            return false
        endif
        return true
    endfunction

    private function Shuffle_Enabled takes nothing returns nothing
        if ( Filt_Privates() ) then
            call GroupRemoveUnitSimple( GetEnumUnit(), disabled )
            call GroupAddUnitSimple( GetEnumUnit(), enabled )
        else
        endif
    endfunction

Can be turned into this:

Collapse JASS:
    private function Shuffle_Enabled takes nothing returns nothing
// We can just take the contition from Filter_Privates() and put it directly into here:
        if GetUnitTypeId(GetEnumUnit()) == 'h001') then

// Replacing GroupAddUnitSimple with GroupAddUnit
            call GroupRemoveUnit( disabled, GetEnumUnit() )
            call GroupAddUnit( enabled , GetEnumUnit())

// No need for the else
//        else
        endif
    endfunction