HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Help with limiting a unit in a spell

01-16-2009, 05:41 PM#1
Carolinemf
Hello,
I am creating this spell that creates a tower based on the item spell 'Build tiny scout tower'. I want to limit the total towers created this way, so that the lv. 1 spell has a max of one tower, and lv. 2, two towers max and so on. Just like the Web spell in DotA.
Can anyone please help me how to do this.

Sincerely Carolinemf
01-16-2009, 07:38 PM#2
Anitarf
In what way do you want to limit them? Once there are enough new ones can't be created anymore or once you create too many the oldest one is destroyed? Is the limit supposed to be on a per-player basis or per-caster basis?
01-17-2009, 11:13 AM#3
Carolinemf
When you create too many the oldest one is destroyed. And the per-player or per-caster is irrevelant since the only thing a player own in my map, is his hero.
Thanks for the reply.
01-17-2009, 11:41 AM#4
Archmage Owenalacaster
Do you want that in JASS, GUI, or using a simple if not quite perfect Object Editor trick?
01-18-2009, 12:03 AM#5
Carolinemf
I Don't know. Which one would you suggest? I haven't got that much experience with spells.
01-18-2009, 12:33 AM#6
Archmage Owenalacaster
I would suggest JASS. I'll write you up something, but in return you ought to learn some JASS.
01-18-2009, 12:34 AM#7
Kyrbi0
Ooh, may I see the Object Editor trick? (unless it involves Carrion Beetles...)
01-18-2009, 01:46 AM#8
Archmage Owenalacaster
Hah, yeah, Carrion Beetles. Ya got me.
I should have my solution in JASS when I take my lunchbreak in 4 hours.
EDIT: Debugging the script. It functions almost correctly; it isn't killing the oldest though. I think index sorting is a wonderful pain in the ass.
01-18-2009, 03:56 PM#9
Archmage Owenalacaster
Limited Summon: This version isn't MUI; I intend that the next version though. The sorting method isn't perfect, but it works almost as well.

To test, simply use the Blood Mage to cast Summon Guard Tower.

To use, copy and paste its trigger and the TimerUtils trigger from the map.

Collapse Limited Summon v0.1a:
library LimitedSummon initializer Init needs TimerUtils
    
    //===============================
    // These values are configurable.
    //===============================
    globals
        private constant integer SPELL_ID =     'A001'  // Enter the rawcode of your spell here.
        private constant integer SUMMON_ID =    'hgtw'  // Enter the rawcode of your summoned unit here.
        private constant integer SUMMON_LIMIT = 3       // Enter the maximum number of summon units
        private constant real TIMED_LIFE =      0       // If you want timed life, set to a positive value.

        private constant string SUMMON_FX =     "Abilities\\Spells\\Items\\TomeOfRetraining\\TomeOfRetrainingCaster.mdl"
    //===================================
    // The rest shouldn't need tampering.
    //===================================
        private constant integer BUFF_ID =      'BFig'  // Summoned unit buff for timed life.
        
        private integer summon_count =          0
        private group summon_group =            null
        private unit array summoned
    endglobals

//===========================================================================
    private function GetOccupiedIndex takes nothing returns integer
        local integer i = 0
        loop
            exitwhen summoned[i] != null or i == SUMMON_LIMIT
            set i = i+1
        endloop
        return i
    endfunction
    
    private function GetEmptyIndex takes nothing returns integer
        local integer i = 0
        loop
            exitwhen summoned[i] == null or i == SUMMON_LIMIT
            set i = i+1
        endloop
        return i
    endfunction
    
    private function actions takes nothing returns nothing
        local unit u = null
        local effect fx = null
        
        if summon_count >= SUMMON_LIMIT then
            call KillUnit(summoned[GetOccupiedIndex()])
        endif
        
        set u = CreateUnitAtLoc(GetTriggerPlayer(),SUMMON_ID,GetSpellTargetLoc(),GetUnitFacing(GetTriggerUnit()))
        set summoned[GetEmptyIndex()] = u
        set summon_count = summon_count+1
        call GroupAddUnit(summon_group,u)
        if TIMED_LIFE > 0 then
            call UnitAddType(u,UNIT_TYPE_SUMMONED)
            call UnitApplyTimedLife(u,BUFF_ID,TIMED_LIFE)
        endif
        
        set fx = AddSpecialEffect(SUMMON_FX,GetUnitX(u),GetUnitY(u))
        call DestroyEffect(fx)

        set u = null
        set fx = null
    endfunction

    private function conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELL_ID
    endfunction
//===========================================================================

    private function ResortArray takes integer startIndex returns nothing
        local integer i = startIndex
        loop
            set summoned[i] = summoned[i+1]
            set i = i+1
            exitwhen i == SUMMON_LIMIT
        endloop
    endfunction

    private function Clean_actions takes nothing returns nothing
        local unit u = GetTriggerUnit()
        local integer i = 0
        set summon_count = summon_count-1
        call GroupRemoveUnit(summon_group,u)
        loop
            exitwhen summoned[i] == u
            set i = i+1
        endloop
        set summoned[i] = null
        call ResortArray(i)
        set u = null
    endfunction
    
    private function Clean_conditions takes nothing returns boolean
        return IsUnitInGroup(GetTriggerUnit(),summon_group)
    endfunction
//===========================================================================
    globals
        public trigger trig = null
        public trigger clean = null
    endglobals

    private function Init takes nothing returns nothing
        set summon_group = CreateGroup()
        set trig = CreateTrigger()
        set clean = CreateTrigger()
        
        call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( trig, Condition( function conditions ) )
        call TriggerAddAction( trig, function actions )

        call TriggerRegisterAnyUnitEventBJ( clean, EVENT_PLAYER_UNIT_DEATH )
        call TriggerAddCondition( clean, Condition( function Clean_conditions ) )
        call TriggerAddAction( clean, function Clean_actions )
    endfunction

endlibrary
Attached Files
File type: w3xLimitedSummon_TestMap.w3x (30.9 KB)
01-18-2009, 04:09 PM#10
Anitarf
You really shouldn't be using integer to handle typecasting...
You don't even need anything of the sorts in this case, you ma destroy the effect as soon as you create it and it will play it's animation to the end before disappearing anyway.

Edit: I had some time on my hands so I coded this, fully MUI (well, unless the summoned units can summon themselves, and even then it's an easy fix); however, since I don't have a wc3 computer right now this was written in notepad and likely has typos so someone who knows vJass might need to test it first and fix any syntax errors:

Edit2: Old code removed, new code with fixed syntax errors and bugs can be found here.
01-19-2009, 12:46 AM#11
Archmage Owenalacaster
By god, how envious I am. Thanks though.
01-19-2009, 08:11 AM#12
Carolinemf
Thank you very much for your help and replies. I think its a bit difficult for me, as I've never worked with Jass or scripting before. But I'll try to read some tutorials first.

By the way. How do i configure the trigger so that my 'Guard Tower' spell in lv. 1 - allows one tower, and in lv. 2 - two towers, up to lv. 5. Or is that a nasty kind of work and takes a long long time?
01-19-2009, 10:12 AM#13
Archmage Owenalacaster
Anitarf's version has a function called SummonLimit near the beginning. Where it says return 1+GetUnitAbilityLevel(u, SUMMON_ABILITY_ID), remove 1+.

EDIT: By the way, Anitarf, you ought to submit your version to the database.
01-28-2009, 10:17 PM#14
Anitarf
Quote:
Originally Posted by Archmage Owenalacaster
EDIT: By the way, Anitarf, you ought to submit your version to the database.
Well, now that I've got my WC3 computer back and was able to fix the syntax errors and a silly bug, here it is.