HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

channeling spell trigger help

11-17-2009, 02:59 PM#1
deutschepharma
hi!

i'm trying to 'patch' wc3-tft by making a map-pack with some abilites/spells/units changes (mostly for personal use in lan parties).

for example, i tried to make every channeling ultimate to last at least 5 seconds, interrupted or not, in a following way:
1. hero cast fake spell. timer starts
2. dummy casts real spell
3. spell is interrupted.
a) if timer is expired (5 sec) nothing happens
b) if timer is not expired, spell is continually casted by dummy till 5 sec

this works well for all channeling spells, with two exceptions:

1. earthquake - despite code being identical to others, i've managed this one to either not work at all, exit to desktop or work for 5 seconds regardless of interruption

2. big bad voodoo - spell works correctly, except when interrupted during first 5 sec, shadow hunter gets under its influence for the remaining time (until 5 sec expires)

i would greatly appreciate suggestions or any other help. btw, my coding probably sucks to great extent, i'm aware of it

i've attached screenshot of defective earthquake trigger(s), as well as a test map

thanks in advance!
Attached Images
File type: jpgearthquake-trigger.jpg (175.2 KB)
Attached Files
File type: w3x(4)TwistedMeadows 0.98g tmp.w3x (267.4 KB)
11-17-2009, 03:49 PM#2
Anitarf
Could you also post one of the triggers that work for a side-by-side comparison?

Also, you don't need to post screenshots, you can just select the "copy as text" option on the trigger and then paste it into your post using the [trigger] tags, like this:

Trigger:
Untitled Trigger 001
Collapse Events
Time - Every 1.00 seconds of game time
Conditions
Collapse Actions
Game - Display to (All players) the text: Testing.
11-17-2009, 04:24 PM#3
deutschepharma
thanks for the quick reply!

here are (one after another) three parts of defective trigger, in comparison to working one. (thanks for the info about pasting, btw, looks really cool)

WORKING TRANQUILITY, part 1/3
Trigger:
tranq1
Collapse Events
Unit - A unit Begins casting an ability
Collapse Conditions
(Ability being cast) Equal to Tranquility (fake)
Collapse Actions
Set CreateNewTranqDummy = True
Set UltiUnit = (Triggering unit)
Set UltiPostion = (Position of UltiUnit)
Unit - Create 1 udcaster for (Owner of (Triggering unit)) at UltiPostion facing UltiPostion
Set ulticaster = (Last created unit)
Unit - Add a 5.00 second Generic expiration timer to ulticaster
Unit - Add Tranquility to ulticaster
Unit - Order ulticaster to Night Elf Keeper Of The Grove - Tranquility
Set TranqTimerStarted = True
Wait 5.00 seconds
Set TranqTimerExpired = True
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
CreateNewTranqDummy Equal to True
Collapse Then - Actions
Unit - Create 1 udcaster for (Owner of (Triggering unit)) at UltiPostion facing UltiPostion
Set ulticaster = (Last created unit)
Unit - Add Tranquility to ulticaster
Unit - Order ulticaster to Night Elf Keeper Of The Grove - Tranquility
Collapse Else - Actions
Do nothing

NOT-WORKING EARTHQUAKE, part 1/3
Trigger:
earth1
Collapse Events
Unit - A unit Begins casting an ability
Collapse Conditions
(Ability being cast) Equal to Earthquake (fake)
Collapse Actions
Set CreateNewEarthDummy = True
Set UltiUnit = (Triggering unit)
Set UltiPostion = (Position of UltiUnit)
Set UltiTarget = (Target point of ability being cast)
Unit - Create 1 udcaster for (Owner of (Triggering unit)) at UltiPostion facing UltiPostion
Set ulticaster = (Last created unit)
Unit - Add a 5.00 second Generic expiration timer to ulticaster
Unit - Add Earthquake to ulticaster
Unit - Order ulticaster to Orc Far Seer - Earthquake UltiTarget
Set EarthTimerStarted = True
Wait 5.00 seconds
Set EarthTimerExpired = True
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
CreateNewEarthDummy Equal to True
Collapse Then - Actions
Unit - Create 1 udcaster for (Owner of (Triggering unit)) at UltiPostion facing UltiPostion
Set ulticaster = (Last created unit)
Unit - Add Earthquake to ulticaster
Unit - Order ulticaster to Orc Far Seer - Earthquake UltiTarget
Collapse Else - Actions
Do nothing

WORKING TRANQUILITY, part 2/3
Trigger:
tranq2
Collapse Events
Unit - A unit Stops casting an ability
Collapse Conditions
(Ability being cast) Equal to Tranquility (fake)
TranqTimerStarted Equal to True
TranqTimerExpired Equal to True
Collapse Actions
Unit - Remove ulticaster from the game
Set UltiUnit = No unit
Set ulticaster = No unit
Set TranqTimerStarted = False
Set TranqTimerExpired = False

NOT-WORKING EARTHQUAKE, part 2/3
Trigger:
earth2
Collapse Events
Unit - A unit Stops casting an ability
Collapse Conditions
(Ability being cast) Equal to Earthquake (fake)
EarthTimerStarted Equal to True
EarthTimerExpired Equal to True
Collapse Actions
Unit - Remove ulticaster from the game
Set UltiUnit = No unit
Set ulticaster = No unit
Set EarthTimerStarted = False
Set EarthTimerExpired = False


WORKING TRANQUILITY, part 3/3
Trigger:
tranq3
Collapse Events
Unit - A unit Stops casting an ability
Collapse Conditions
(Ability being cast) Equal to Tranquility (fake)
TranqTimerStarted Equal to True
TranqTimerExpired Equal to False
Collapse Actions
Set CreateNewTranqDummy = False
Set TranqTimerStarted = False
Set TranqTimerExpired = False

NOT-WORKING EARTHQUAKE, part 3/3
Trigger:
earth3
Collapse Events
Unit - A unit Stops casting an ability
Collapse Conditions
(Ability being cast) Equal to Earthquake (fake)
EarthTimerStarted Equal to True
EarthTimerExpired Equal to False
Collapse Actions
Set CreateNewEarthDummy = False
Set EarthTimerStarted = False
Set EarthTimerExpired = False


i suspect that trigger itself is correct (even if bad written), and that problem is related to "STATS - EFFECT" or "STATS - BUFFS" fields in "Earthquake (fake)" spell (changing fields makes spell not function in different manner), that's why i attached map
11-17-2009, 05:34 PM#4
Anitarf
Well, I don't see what the problem could be but I see other issues: for example, if multiple heroes cast an ultimate at about the same time, the code will get messed up because of shared variables. You are better off using a vJass system for this, I can write something quickly for you if you want.
11-17-2009, 07:27 PM#5
deutschepharma
yes, it would be most helpful, thank you!
11-17-2009, 08:40 PM#6
Anitarf
Here, completely untested, requires TimerUtils, Table and SpellEvent.

Collapse JASS:
scope SetupUltiChannel initializer Init
    private function Init takes nothing returns nothing
        // hero ability, caster ability, orderstring, min duration
        call NewUltiChannel('A000', 'A001', "starfall", 5.0)
        // repeat for each ultimate.
    endfunction
endscope

library UltiChannel initializer Init requires Table, TimerUtils, SpellEvent

    globals
        private constant integer CASTER_UNIT_ID = 'hfoo'
    endglobals

    private struct ultiData
        static Table spellTable
        static method get takes integer spellId returns ultiData
            return ultiData.spellTable[spellId]
        endmethod
        static method onInit takes nothing returns nothing
            set ultiData.spellTable=Table.create()
        endmethod

        integer heroSpellId
        integer casterSpellId
        string orderstring
        real minDuration
        static method create takes integer heroSpellId, integer casterSpellId, string spellOrderstring, real minSpellDuration returns ultiData
            local ultiData this=ultiData.allocate()
            set .heroSpellId=heroSpellId
            set .casterSpellId=casterSpellId
            set .minDuration=minSpellDuration
            set .orderstring=spellOrderstring
            set ultiData.spellTable[heroSpellId]=this
            return this
        endmethod
    endstruct

    private struct ultiSpell
        static HandleTable casterTable

        static method get takes unit caster returns ultiSpell
            return ultiSpell.casterTable[caster]
        endmethod
        static method onInit takes nothing returns nothing
            set ultiSpell.casterTable=HandleTable.create()
        endmethod
        
        private unit hero
        private unit caster
        private boolean stopped=false
        private boolean finished=false
        
        private static method expire takes nothing returns nothing
            local ultiSpell this=ultiSpell(GetTimerData(GetExpiredTimer()))
            call ReleaseTimer(GetExpiredTimer())
            set .finished=true
            if .stopped then
                call .destroy()
            endif
        endmethod
        static method create takes unit u, ultiData d returns ultiSpell
            local ultiSpell this=ultiSpell.allocate()
            local timer t=NewTimer()
            set .hero=u
            set .caster=CreateUnit(GetOwningPlayer(u), CASTER_UNIT_ID, GetUnitX(u), GetUnitY(u),GetUnitFacing(u))
            call UnitAddAbility(.caster, d.casterSpellId)
            call SetUnitAbilityLevel(.caster, d.casterSpellId, GetUnitAbilityLevel(u, d.heroSpellId))
            if SpellEvent.TargetUnit!=null then
                call IssueTargetOrder(.caster, d.orderstring, SpellEvent.TargetUnit)
            elseif SpellEvent.TargetX!=0.0 or SpellEvent.TargetY!=0.0 then
                call IssuePointOrder(.caster, d.orderstring, SpellEvent.TargetX, SpellEvent.TargetY)
            else
                call IssueImmediateOrder(.caster, d.orderstring)
            endif
            call SetTimerData(t, integer(this))
            call TimerStart(t, d.minDuration, false, function ultiSpell.expire)

            set ultiSpell.casterTable[u]=this
            return this
        endmethod
        method onDestroy takes nothing returns nothing
            call ultiSpell.casterTable.flush(.hero)
            call KillUnit(.caster)
        endmethod

        static method SpellStop takes nothing returns nothing
            local ultiSpell this=ultiSpell.get(SpellEvent.CastingUnit)
            if this!=0 then
                set .stopped=true
                if .finished then
                    call .destroy()
                endif
            endif
        endmethod
        static method SpellCast takes nothing returns nothing
            local ultiData d=ultiData.get(SpellEvent.AbilityId)
            if d!=0 then
                call ultiSpell.create(SpellEvent.CastingUnit, d)
            endif
        endmethod
    endstruct

    
    function NewUltiChannel takes integer heroSpellId, integer casterSpellId, string spellOrderstring, real minSpellDuration returns nothing
        local ultiData d=ultiData.create(heroSpellId, casterSpellId, spellOrderstring, minSpellDuration)
    endfunction

    private function Init takes nothing returns nothing
        call RegisterSpellEffectResponse(0, ultiSpell.SpellCast)
        call RegisterSpellEndCastResponse(0, ultiSpell.SpellStop)
    endfunction

endlibrary
11-17-2009, 09:24 PM#7
deutschepharma
wow. thanks!

it will probably take me some time to understand how this functions, but i believe it will be useful. thanks again