Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Updates - June 29, 2009

Discussion in 'Cowardice TD' started by Zaraf, Jun 29, 2009.

  1. Zaraf

    Zaraf

    Joined:
    Apr 16, 2008
    Messages:
    80
    Resources:
    0
    Resources:
    0
    Well, progress on the map has been going good, but hasn't moved forward as far as I had expected by this time. The main reason for that is that I started learning vJASS so that I could become fairly independent as far as requiring someone to code for me. Thankfully I've been able to learn at a reasonably good pace, and I've started discovering how horrible most of the code in my map really is. That's what happens when you get 3 or 4 different people coding the core of your map over a year -_-

    Anyway, so I've been spending time cleaning up, reorganizing, optimizing and in some cases, just plain remaking a lot of the stuff in my map that was originally already "finished".

    Here is an example of something I did. I had a semi-working Generator tower before, but it wasn't exactly to my liking. At the time, however, I was lacking the skills to be able to do it myself, but now I can!

    So this is the first tower in my map that I coded entirely myself. And I must say, I'm quite pleased with the results.

    Generator Screenshot
    [​IMG]


    And here is the code for the tower:

    Generator vJASS Code
    Code (vJASS):
    //Generator Tower by Zaraf
    scope GeneratorTower initializer Init

            globals
                private constant string  CIRCLE_SFX    = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"  //Special effect that the range circle is made up of
                private constant string  UNIT_SFX_HIT  = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
                private constant integer PASSIVE_ID    = 'A00Q' //raw code of the passive dummy ability that just is meant to keep track of the ability level.
                private constant integer LINK_ABILITY  = 'A03O' //raw code of the link ability.
                private constant integer DESTROY_LINK  = 'A046' //raw code of the destroy ability that destroys the links.
                private constant integer DUMMY_SPELL   = 'A016' //still need to see if I really need this ability or not.
                private constant integer DAZE_DUMMY_ID = 'h03V' //still need to see if I really need this ability or not.
                private constant attacktype   A_TYPE   = ATTACK_TYPE_CHAOS     // Attack type of damage dealt by electricity to creeps.
                private constant damagetype   D_TYPE   = DAMAGE_TYPE_UNIVERSAL // Damage type of damage dealt by electricity to creeps.
                private constant weapontype   W_TYPE   = WEAPON_TYPE_WHOKNOWS  // Weapon type of damage dealt by electricity to creeps.
                private constant real    EFFECT_HEIGHT = 100.00 //The height above ground that the lightning effect appears.
                private constant string  EFFECT_TYPE   = "FORK" //The code of the type of lightning effect that appears.
                private constant real    TIMER_PERIOD  = 2.00   //The speed at which the color of the lightning changes.
                private constant real    DAMAGE_PERIOD = 0.10   //The speed at which the lightning is checked to see if units are nearby and to damage them.
                private constant string  MESSAGE1      = "\nCannot build the Link Tower outside of range."               //error message that appears
                private constant string  MESSAGE2      = "\nCannot build Link Tower too close to the Generator Tower."   //error message that appears
                private constant real    MIN_DISTANCE  = 128.00 //Minimum distance at which you cannot build a link tower
                private constant real ANGLE_INCREMENT  = 10.0  //Make sure this is divisible into 360 WITHOUT a remainder
            endglobals
           
    //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~                    
           
        private struct Generator
       
            unit      u               //the generator tower
            unit      c               //the link tower
            unit      d               //daze casting dummy unit
            player    p               //owner of generator
            integer  id               //player id of owner
            integer lvl               //level of the base generator ability
            integer  cc = 1           //color counter, keeps track of the color array slot to use
            real     xu               //x position of generator
            real     yu               //y position of generator
            real     xc               //x position of link tower
            real     yc               //y position of link tower
            effect array circ [100]   //Array used to create and destroy the range circle
            lightning e               //lightning effect that is created
            boolean  bh = false       //Builder Hit - checks if the builder has been dazed
            boolean  cool = false     //DestroyLinkCoolDown - checks if the cooldown is happening or not
            boolean  link = false     //LinkActive - checks if the link is established or not
           
        endstruct
       
            globals
                private Generator array GeneratorStruct
                private          integer FilterPlayerId          //The variable used to feed the player id to the filter function
                private          boolexpr DamageFilter
       
                private string   array LightningSFX
            endglobals

    //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~            
           
        private function Range takes integer lvl returns real
            return 300.0 + (150.0 * lvl)
        endfunction
       
        private function Damage takes integer lvl returns real
            return 0.0 + (1.0 * lvl)
        endfunction
       
    //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~    
       
        private function Cond takes nothing returns boolean
            local boolean a = GetOwningPlayer(GetTriggerUnit()) == GetTriggerPlayer()
            local boolean b = (GetUnitTypeId(GetTriggerUnit()) == GENERATOR_TOWER_ID)
            local boolean c = (GetUnitTypeId(GetTriggerUnit()) == GENERATOR_2_TOWER_ID)
            local boolean d = (GetUnitTypeId(GetTriggerUnit()) == GENERATOR_3_TOWER_ID)
           
            return a and (b or c or d)
        endfunction
       
        private function UpgradeCondition takes nothing returns boolean
            return (GetUnitLevel(BuilderChosen[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))+1]) >= 30)
        endfunction
       
        private function LinkTowerCond takes nothing returns boolean
            return GetSpellAbilityId() == LINK_ABILITY
        endfunction
       
        private function LinkTowerCheck takes nothing returns boolean
            return GetUnitTypeId(GetConstructedStructure()) == GENERATOR_LINK_TOWER_ID
        endfunction
       
        private function DestroyLinkCheck takes nothing returns boolean
            return (GetSpellAbilityId() == DESTROY_LINK) or (GetSpellAbilityId() == SELL_ID) or (GetSpellAbilityId() == DEMOLISH_ID)
        endfunction
           
        private function FilterTargets takes unit filter returns boolean
            return IsUnitType(filter,UNIT_TYPE_STRUCTURE) == false and (GetWidgetLife(filter) > 0.406) and IsUnitType(filter,UNIT_TYPE_FLYING) == false
        endfunction
       
    //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~

        private function DamageFilterActions takes nothing returns boolean
            local Generator g = GeneratorStruct[FilterPlayerId]
            local integer n = GetRandomInt(0,100)
           
            if FilterTargets(GetFilterUnit()) then
                if IsUnitInRangeOfSegment(GetFilterUnit(), g.xu, g.yu, g.xc, g.yc, 40.0) == true then
                    if GetFilterUnit() == BuilderChosen[g.id+1] then  //If your builder touches the electricity, he gets dazed.
                        if g.bh == false then
                            set g.bh = true
                            set g.d = CreateUnit(Player(11), DAZE_DUMMY_ID, g.xu, g.yu, 0)
                            call UnitApplyTimedLife(g.d, 'BTLF', 1.)
                            call UnitAddAbility(g.d, DUMMY_SPELL)
                            call SetUnitAbilityLevel(g.d, DUMMY_SPELL, g.lvl)
                            call IssueTargetOrder(g.d, "slow", GetFilterUnit())
                            call DestroyEffect(AddSpecialEffectTarget(UNIT_SFX_HIT, GetFilterUnit(), "chest"))
                        endif
                    else
                        call UnitDamageTarget(g.u, GetFilterUnit(), Damage(g.lvl), false, false, A_TYPE, D_TYPE, W_TYPE)
                        if n > 90 then
                            call DestroyEffect(AddSpecialEffectTarget(UNIT_SFX_HIT, GetFilterUnit(), "chest"))
                        endif
                    endif
                endif
            endif
            return false
        endfunction

        private function GeneratorDamage takes nothing returns nothing
            local Generator g = Generator(GetTimerData(GetExpiredTimer()))
           
            set FilterPlayerId = g.id
            call GroupEnumUnitsInRangeOfSegment(ENUM_GROUP, g.xu, g.yu, g.xc, g.yc, 1.0, DamageFilter)
            if g.link == false then
                call ReleaseTimer(GetExpiredTimer())
            //    call BJDebugMsg("Timer is being released")
            endif
        endfunction

    //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~        
        private function ChangeLightningColor takes nothing returns nothing
            local Generator g = Generator(GetTimerData(GetExpiredTimer()))
            local integer i = g.cc
            local integer n = GetRandomInt(1,100)
            if g.link == false then
                call ReleaseTimer(GetExpiredTimer())
            //    call BJDebugMsg("Timer is being released")
            else
                if n > 95 then
                    set n = GetRandomInt(0,2)
                    call DestroyEffect(AddSpecialEffect(LightningSFX[n], GetUnitX(g.u), GetUnitY(g.u)))
                    call DestroyEffect(AddSpecialEffect(LightningSFX[n], GetUnitX(g.c), GetUnitY(g.c)))
                endif
                call SetLightningColor(g.e, RedColor[g.cc], GreenColor[g.cc], BlueColor[g.cc], 1.0)
                if g.cc == 51 then
                    set g.cc = 1
                else
                    set g.cc = g.cc + 1
                endif
                set g.bh = false
            endif
        endfunction
           
        private function CreateLink takes Generator g returns nothing
            local timer t = NewTimer()
            local timer damagetimer = NewTimer()
            local integer n = GetRandomInt(0,2)
            local real zu
            local real zc
           
            set g.xu = GetUnitX(g.u)
            set g.yu = GetUnitY(g.u)
            set g.xc = GetUnitX(g.c)
            set g.yc = GetUnitY(g.c)
           
            set zu = GetPointZ(g.xu, g.yu) + EFFECT_HEIGHT
            set zc = GetPointZ(g.xc, g.yc) + EFFECT_HEIGHT
           
            call DestroyEffect(AddSpecialEffect(LightningSFX[n], g.xu, g.yu))
            call DestroyEffect(AddSpecialEffect(LightningSFX[n], g.xc, g.yc))
            set g.e = AddLightningEx(EFFECT_TYPE, false, g.xu, g.yu, zu, g.xc, g.yc, zc)
            call SetLightningColor(g.e, 1.0, 0.0, 0.0, 1.0)
            set g.link = true
            call SetTimerData(t, g)
            call TimerStart(t, TIMER_PERIOD, true, function ChangeLightningColor)
            call SetTimerData(damagetimer, g)
            call TimerStart(damagetimer, DAMAGE_PERIOD, true, function GeneratorDamage)
            set t = null
            set damagetimer = null
        endfunction
       
        private function BreakLink takes Generator g returns nothing
            set g.link = false
            call DestroyLightning(g.e)
            call KillUnit(g.c)
        endfunction
           
    //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~        
           
        private function SelectActions takes Generator g returns nothing  //These actions happen when you select the tower.  It creates the range ring around the tower.
            local integer n   = 0
            local rect    r   = PlayerArea[POS[g.id+1]]

            local real x
            local real y
            local real offset = 50.0
            local real angle = 0.0
           
            loop
                exitwhen n > (360.0/ANGLE_INCREMENT)
                if g.circ[n] != null then
                    call DestroyEffect(g.circ[n])
                    set g.circ[n] = null
                endif
                set x = g.xu + Range(g.lvl) * Cos( (angle + ANGLE_INCREMENT * n) * bj_DEGTORAD)
                set y = g.yu + Range(g.lvl) * Sin( (angle + ANGLE_INCREMENT * n) * bj_DEGTORAD)
                if x <= GetRectMinX(r) then
                    set x = GetRectMinX(r) + offset
                endif
                if x >= GetRectMaxX(r) then
                    set x = GetRectMaxX(r) - offset
                endif
                if y <= GetRectMinY(r) then
                    set y = GetRectMinY(r) + offset
                endif
                if y >= GetRectMaxY(r) then
                    set y = GetRectMaxY(r) - offset
                endif
                set g.circ[n] = AddSpecialEffect(CIRCLE_SFX, x, y)
                set n = n + 1
            endloop
        endfunction
       
        private function SelectEvent takes nothing returns nothing
            local Generator g = GeneratorStruct[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]
            call SelectActions(g)
        endfunction
       
        private function DeselectActions takes Generator g returns nothing  //These actions happen when you deselect the tower.  It destroys the range ring around the tower.
            local integer n   = 0
           
            loop
                exitwhen n > (360.0/ANGLE_INCREMENT)
                call DestroyEffect(g.circ[n])
                set g.circ[n] = null
                set n = n + 1
            endloop
        endfunction
       
        private function DeselectEvent takes nothing returns nothing
            local Generator g = GeneratorStruct[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]
            call DeselectActions(g)
        endfunction

    //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~    
       
        private function LinkTowerBuild takes nothing returns nothing  //This is the ability to build the link tower
            local Generator g = GeneratorStruct[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]
            local location trgt = GetSpellTargetLoc()
            local real     tx   = GetLocationX(trgt)
            local real     ty   = GetLocationY(trgt)
            local real     dx   = tx - g.xu
            local real     dy   = ty - g.yu
            local real     Dist = SquareRoot(dx * dx + dy * dy)
            local rect     r    = PlayerArea[POS[g.id+1]]

            if     tx <= GetRectMinX(r) or tx >= GetRectMaxX(r) or ty <= GetRectMinY(r) or ty >= GetRectMaxY(r) then
                call SetUnitPosition(g.u, g.xu, g.yu)   //This is meant to stop the tower's ability from working...cancelling the link tower creation ability.
                call SimError(g.p, MESSAGE1)
            elseif Dist > Range(g.lvl) then
                call SetUnitPosition(g.u, g.xu, g.yu)   //This is meant to stop the tower's ability from working...cancelling the link tower creation ability.
                call SimError(g.p, MESSAGE1)
            elseif Dist < MIN_DISTANCE then
                call SetUnitPosition(g.u, g.xu, g.yu)   //This is meant to stop the tower's ability from working...cancelling the link tower creation ability.
                call SimError(g.p, MESSAGE2)
            endif
            call RemoveLocation(trgt)
            set trgt = null
        endfunction
           
        private function LinkTowerConstruction takes nothing returns nothing  //This is the detection of the actual finished construction of the link tower
            local Generator g = GeneratorStruct[GetPlayerId(GetOwningPlayer(GetConstructedStructure()))]
           
            set g.c = GetConstructedStructure()
            set g.xu = GetUnitX(g.c)
            set g.yu = GetUnitY(g.c)
            set g.cool = true      //This is set to true so that the first time the generator uses the destroy link ability, that it does nothing.
            call UnitAddAbility(g.u, DESTROY_LINK)
            call SetUnitAbilityLevel(g.u, DESTROY_LINK, g.lvl)
            call UnitRemoveAbility(g.u, LINK_ABILITY)
            call IssueImmediateOrder(g.u, "tranquility") //This orders the Generator to use the Destroy Link ability so that it starts the cooldown.
            call CreateLink(g)
        endfunction
       
        private function DestroyLinkCast takes nothing returns nothing
            local Generator g = GeneratorStruct[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))]
           
            if ( (GetSpellAbilityId() == SELL_ID) or (GetSpellAbilityId() == DEMOLISH_ID) ) and (g.lvl > 0) then
                call DeselectActions(g)
                call BreakLink(g)
                call SellActions()
                call g.destroy()
            //    call BJDebugMsg("Struct destroyed")
            elseif g.cool == false then
                call BreakLink(g)
                call UnitAddAbility(g.u, LINK_ABILITY)
                call SetUnitAbilityLevel(g.u, LINK_ABILITY, g.lvl)
                call UnitRemoveAbility(g.u, DESTROY_LINK)
            else
                set g.cool = false
            endif
        endfunction
       
        private function GeneratorUpgrade takes nothing returns nothing
            local integer id = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
            local integer i  = GetUnitTypeId(GetTriggerUnit())
            local Generator g

            if (i == GENERATOR_TOWER_ID) then
                    set GeneratorStruct[id] = Generator.create()
                    set g = GeneratorStruct[id]
                    set g.u = GetTriggerUnit()
                    set g.p = GetOwningPlayer(g.u)
                    set g.id = GetPlayerId(g.p)
                    set g.lvl = GetUnitAbilityLevel(g.u, PASSIVE_ID)
                    set g.xu  = GetUnitX(g.u)
                    set g.yu  = GetUnitY(g.u)
                    call SelectActions(g)
            elseif (i == GENERATOR_2_TOWER_ID) or (i == GENERATOR_3_TOWER_ID) then
                    set g = GeneratorStruct[id]
                    call IncUnitAbilityLevel(GetTriggerUnit(), PASSIVE_ID)
                    set g.lvl = GetUnitAbilityLevel(GetTriggerUnit(), PASSIVE_ID)
                    call SelectActions(g)
                    call DestroyLinkCast()
            endif
        endfunction
       
    //*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~

        private function Init takes nothing returns nothing
            local integer n  = 0
            local trigger t1 = CreateTrigger()
            local trigger t2 = CreateTrigger()
            local trigger t3 = CreateTrigger()
            local trigger t4 = CreateTrigger()
            local trigger t5 = CreateTrigger()
            local trigger t6 = CreateTrigger()
           
            loop
                exitwhen n > 7
                call TriggerRegisterPlayerUnitEvent(t1, Player(n), EVENT_PLAYER_UNIT_SELECTED, null)
                call TriggerRegisterPlayerUnitEvent(t2, Player(n), EVENT_PLAYER_UNIT_DESELECTED, null)
                call TriggerRegisterPlayerUnitEvent(t3, Player(n), EVENT_PLAYER_UNIT_SPELL_CAST, null)
                call TriggerRegisterPlayerUnitEvent(t4, Player(n), EVENT_PLAYER_UNIT_UPGRADE_FINISH, null)
                call TriggerRegisterPlayerUnitEvent(t5, Player(n), EVENT_PLAYER_UNIT_CONSTRUCT_FINISH, null)
                call TriggerRegisterPlayerUnitEvent(t6, Player(n), EVENT_PLAYER_UNIT_SPELL_CAST, null)
                set n = n + 1
            endloop
           
            call TriggerAddCondition(t1, Condition(function Cond))
            call TriggerAddCondition(t2, Condition(function Cond))
            call TriggerAddCondition(t3, Condition(function LinkTowerCond))
            call TriggerAddCondition(t4, Condition(function UpgradeCondition))
            call TriggerAddCondition(t5, Condition(function LinkTowerCheck))
            call TriggerAddCondition(t6, Condition(function DestroyLinkCheck))
           
            call TriggerAddAction(t1, function SelectEvent)
            call TriggerAddAction(t2, function DeselectEvent)
            call TriggerAddAction(t3, function LinkTowerBuild)
            call TriggerAddAction(t4, function GeneratorUpgrade)
            call TriggerAddAction(t5, function LinkTowerConstruction)
            call TriggerAddAction(t6, function DestroyLinkCast)
           
            set DamageFilter = Condition(function DamageFilterActions)
           
            set LightningSFX[0] = "Abilities\\Spells\\Demon\\DemonBoltImpact\\DemonBoltImpact.mdl"
            set LightningSFX[1] = "Abilities\\Spells\\Items\\AIlb\\AIlbSpecialArt.mdl"
            set LightningSFX[2] = "Abilities\\Weapons\\Bolt\\BoltImpact.mdl"
        endfunction

    endscope


    It ended up becoming quite long. I took the screenshot a little zoomed out so you could easily see everything. The blue circle thingy you see around the Generator is created whenever you have the generator selected, and destroyed when you deselect the generator. It is meant to easily let you determine visually the limits of how far away you can place your link tower.

    You can't really appriciate the coolness of the Generator tower until you see it in action. If anyone would like to try it out, let me know and I'll hook you up :)

    I'm currently rewriting the Vacuum tower. It ended up breaking due to the retarded coder who used GetUserUnitData and SetUserUnitData. Some other systems in my map ended up breaking that, and thus the tower no longer worked. As of right now, I got the tower working correctly, and I just need to add in its upgrades and such.
     

    Attached Files:

  2. MR. FJ

    MR. FJ

    Joined:
    Oct 16, 2005
    Messages:
    105
    Resources:
    4
    Maps:
    4
    Resources:
    4
    Looks nice, I hope you wont stop working on this map :) Please do send me the latest copy of your map, if you like and I'll give some response ;)

    mr.fj@hotmail.com
     
  3. MR. FJ

    MR. FJ

    Joined:
    Oct 16, 2005
    Messages:
    105
    Resources:
    4
    Maps:
    4
    Resources:
    4
    You should consider adding an attack, with no targets, to all the trigger based towers. That way we can see how much damage and how fast it shoots, just as with non trigger based towers :)
     
  4. Zaraf

    Zaraf

    Joined:
    Apr 16, 2008
    Messages:
    80
    Resources:
    0
    Resources:
    0
  5. Ayeso

    Ayeso

    Joined:
    Nov 8, 2008
    Messages:
    1
    Resources:
    0
    Resources:
    0
    Wow, U of A?

    Im from Edmonton as well ;)
     
  6. Gorman

    Gorman

    Joined:
    May 23, 2009
    Messages:
    19
    Resources:
    0
    Resources:
    0
    Grats on getting hosted man :)
    Looks pretty good so far n_n

    Havn't talked to you in a while ey, if your on US.East some time /w me, my nick is Pointy.