• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Updates - June 29, 2009

Status
Not open for further replies.
Level 4
Joined
Apr 16, 2008
Messages
80
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.

attachment.php


And here is the code for the tower:

JASS:
//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.
 

Attachments

  • Generator.jpg
    Generator.jpg
    252.7 KB · Views: 521
Level 2
Joined
May 23, 2009
Messages
19
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.
 
Status
Not open for further replies.
Top