• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Missile Sys

Status
Not open for further replies.
Level 11
Joined
Aug 25, 2006
Messages
971
Only one annoyance, when you open up the function viewer its colors are the same as the rest of the theme, but the background is white! It makes all the colors look washed out lol... Where can I get Notepad++ ?

I'm getting a new bug, when its supposed to fire the missile, the missile just dissapears. I think its moving faster then its set to. Only a bit later the game crashes indicating it probably escaped the map.... It must be a problem with movement, check under FireWep Nor.AddX/Nor.AddY and check in Chess_Game_Forward to see how I use them

JASS:
globals 
    constant real TimerCycle = .025
    constant real UnitTimerCycle = .05
    constant real MAXDIST = 10000.0
    constant real EFFECTTIME = 10.0
    constant integer UNIT_TYPE = 'e001'
    constant real HEIGHT_THRESHOLD = 40
    constant real COLLISION_RADIUS = 32
    trigger Nar
    trigger Nxr
endglobals
struct Missile
    real CurDist
    real CurX
    real CurY
    real CurZ
    real AddX //This is the value from polar projection bj used to move the missile
    real AddY //Same as above!
    player Firer
    integer PrevStruct
    integer NextStruct
    real FExtinme
    boolean IsDead
    effect Mdlx
    unit Mis
    Weapon Wep
endstruct
struct Weapon
    integer PerBurst
    boolean UseBurst
    real CoolDown
    real XOffset
    real YOffset
    real ZOffset
    string Model
    real FireSpeed
    real Damage
endstruct
struct Unit
    real Prep
    player Owner
    unit Un
    integer PrevStruct
    integer NextStruct
    integer Wep
endstruct
globals
    integer LL_First_Missile = -1
    integer LL_Last_Missile = -1
    integer LL_First_Unit = -1
    integer LL_Last_Unit = -1
    //For collision info pasing
    group x_ColGroup = CreateGroup()
    player x_Attkr
    unit x_Violator
endglobals
library MissSys needs CasterSystem
    function EnemyContact_Enum takes nothing returns nothing
    local unit u = GetEnumUnit()
        if not(IsUnitAlly(u,x_Attkr) or IsPlayerAlly(x_Attkr,GetOwningPlayer(u))) then
            set x_Violator = u
        endif
    set u = null
    endfunction
    function EnemyContact takes real X, real Y, real ColRad, player Sm returns boolean
        call GroupClear(x_ColGroup)
        set x_Attkr = Sm
        set x_Violator = null
        call GroupEnumUnitsInRange(x_ColGroup,X,Y,ColRad,null)
        call ForGroup(x_ColGroup,function EnemyContact_Enum)
        if x_Violator == null then
            return false
        endif
    return true
    endfunction

    function UnRegUnit takes integer Struct returns nothing //This patches the linked list
    local Unit Nar = Struct
    local Unit Patched
        if not (Nar.PrevStruct == -1) then//These lines of code effectively patch the linked list
            set Patched = Nar.PrevStruct
            set Patched.NextStruct = Nar.NextStruct
        else
            set LL_First_Unit = Nar.NextStruct
        endif
        if not (Nar.NextStruct == -1) then
            set Patched = Nar.NextStruct
            set Patched.PrevStruct = Nar.PrevStruct
        else
            set LL_Last_Unit = Nar.PrevStruct
        endif
        call Nar.destroy() //Clean the struct!
    endfunction

    function FireWep takes integer k, unit l returns integer
    local Missile Nor = Missile.create()
    local Missile Prev
    local Unit x = k
    local Weapon y = x.Wep
    local location nm
    local real Speed = y.FireSpeed/TimerCycle
    local real FaxI = GetUnitFacing(x.Un) //Replace later for better accuracy
        if LL_First_Missile == -1 then
            set LL_First_Missile = Nor
            set LL_Last_Missile = Nor
            set Nor.PrevStruct = -1
        else
            set Prev = LL_Last_Missile
            set Prev.NextStruct = Nor
            set Nor.PrevStruct = Prev
            set LL_Last_Missile = Nor
        endif
        set Nor.CurDist = 0
        set Nor.CurX = GetUnitX(x.Un)
        set Nor.CurY = GetUnitY(x.Un)
        set nm = GetUnitLoc(x.Un)
        set Nor.CurZ = GetLocationZ(nm)
        call RemoveLocation(nm)
        set nm = null
        set Nor.NextStruct = -1
        set Nor.AddX = Speed * Cos(FaxI * bj_DEGTORAD) 
        set Nor.AddY = Speed * Sin(FaxI * bj_DEGTORAD)
        set Nor.Firer = GetOwningPlayer(x.Un)
        set Nor.FExtinme = EFFECTTIME
        set Nor.IsDead = false
                call DisplayTextToPlayer(Player(0),0,0,"L = " + I2S(GetPlayerId(Nor.Firer)) + "^" + R2S(Nor.CurX) + "^" + R2S(Nor.CurY) + "^" + R2S(FaxI))
        set Nor.Mis = CreateUnit(Nor.Firer,UNIT_TYPE,Nor.CurX,Nor.CurY,FaxI)
        set Nor.Mdlx = AddSpecialEffectTarget(y.Model,Nor.Mis,"origin")
        set Nor.Wep = y
//        call SetUnitUserData(l,Nor)
    return Nor
    endfunction
    function MissileDestroy takes integer Struct returns nothing //This patches the linked list
    local Missile Nar = Struct
    local Missile Patched
        if not (Nar.PrevStruct == -1) then//These lines of code effectively patch the linked list
            set Patched = Nar.PrevStruct
            set Patched.NextStruct = Nar.NextStruct
        else
            set LL_First_Missile = Nar.NextStruct
        endif
        if not (Nar.NextStruct == -1) then
            set Patched = Nar.NextStruct
            set Patched.PrevStruct = Nar.PrevStruct
        else
            set LL_Last_Missile = Nar.PrevStruct
        endif
        call Nar.destroy() //Clean the struct!
    endfunction
    function Chess_Game_Forward takes nothing returns nothing
    local Missile Star = LL_First_Missile
    local unit u
    local boolean DestroyS = false
    local integer Je
    local location Ne
    local Weapon Na
        call DisplayTextToPlayer(Player(0),0,0,"x = " + I2S(LL_First_Missile))
        loop
        exitwhen Star == -1
            call DisplayTextToPlayer(Player(0),0,0,"o = " + I2S(LL_First_Missile))
            if Star.IsDead == false then
                set Star.CurX = Star.CurX + Star.AddX
                set Star.CurY = Star.CurY + Star.AddY
                call SetUnitX(Star.Mis,Star.CurX)
                call SetUnitY(Star.Mis,Star.CurY)
             //   call Star.CurDist
            endif
            set Ne = GetUnitLoc(Star.Mis)
            if (GetLocationZ(Ne) + HEIGHT_THRESHOLD < Star.CurZ) or (GetLocationZ(Ne) - HEIGHT_THRESHOLD > Star.CurZ) then
                set DestroyS = true
            endif
            call RemoveLocation(Ne)
            set Ne = null
            if (Star.IsDead == false) and (DestroyS == false) then //If I use an and statement it will still evaluate the second function if the first is false! Thats a waste of comp power
                if EnemyContact(Star.CurX,Star.CurY,COLLISION_RADIUS,Star.Firer) then //x_Violator
                    set Na = Star.Wep
                    set DestroyS = true
                    call DamageUnitByTypes(Star.Mis,x_Violator,Na.Damage,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL)
                endif
            endif 
            if (Star.IsDead == false) and (DestroyS == true) then
                set Star.IsDead = true
            endif
            if Star.IsDead == true then
                set Star.FExtinme = Star.FExtinme - TimerCycle
                if Star.FExtinme <= 0 then
                    call DestroyEffect(Star.Mdlx)
                    call RemoveUnit(Star.Mis)
                    set Je = Star.NextStruct
                    call MissileDestroy(Star)
                    set Star = Je
                else
                    set Star = Star.NextStruct
                endif
            else
                set Star = Star.NextStruct
            endif
        endloop
        set u = null    
    endfunction

    
    function RegUnit takes unit u, integer y returns integer
    local Unit Nor = Unit.create()
    local Unit Prev
        if LL_First_Unit == -1 then
            set LL_First_Unit = Nor
            set LL_Last_Unit = Nor
            set Nor.PrevStruct = -1
        else
            set Prev = LL_Last_Unit
            set Prev.NextStruct = Nor
            set Nor.PrevStruct = Prev
            set LL_Last_Unit = Nor
        endif
        set Nor.Prep = 0
        set Nor.Owner = GetOwningPlayer(u)
        set Nor.Wep = y
        set Nor.NextStruct = -1
        set Nor.Un = u
        call SetUnitUserData(u,Nor)
    return Nor
    endfunction

    function InitWeapon takes integer PrBurst, boolean UsBurst, real ColDown, string Modle, real MissileSpeed, real Damag returns Weapon
    local Weapon m = Missile.create()
        set m.PerBurst = PrBurst
        set m.UseBurst = UsBurst
        set m.CoolDown = ColDown
        set m.Model = Modle
        set m.FireSpeed = MissileSpeed
        set m.Damage = Damag
    return m
    endfunction
    function RunCheckUnit takes nothing returns nothing
    local Unit Star = LL_First_Unit
    local unit u
    local boolean DestroyS = false
    local integer Je
        loop
        exitwhen Star == -1
            set DestroyS = false
            set u = Star.Un
            if Star.Prep > 0 then
                set Star.Prep = Star.Prep - UnitTimerCycle
                if Star.Prep < 0 then
                    set Star.Prep = 0
                endif
            endif
            if GetWidgetLife(u) <= 0 then
                set DestroyS = true
            endif
            if u == null then
                set DestroyS = true
            endif
            if DestroyS == true then
                set Je = Star.NextStruct
                call UnRegUnit(Star)
                set Star = Je
            else
                set Star = Star.NextStruct
            endif
        endloop
        set u = null
    endfunction
    function Hck takes nothing returns boolean
    local unit u = GetAttacker()
    local Unit Ar = GetUnitUserData(u)
    local boolean Ka
        if Ar.Un == u then
            set Ka = true
        else
            set Ka = false
        endif
        set u = null
    return Ka
    endfunction
    function MkUAttk takes nothing returns nothing
    local unit u = GetAttacker()
    local Unit x = GetUnitUserData(u)
    local Weapon y = x.Wep
        if x.Prep == 0 then
            call FireWep(x,u)
            set x.Prep = y.CoolDown
        endif
    set u = null
    endfunction
endlibrary
//===========================================================================
function InitTrig_MissileSysAdd takes nothing returns nothing
    set gg_trg_MissileSysAdd = CreateTrigger(  )
    call TriggerAddAction( gg_trg_MissileSysAdd, function Chess_Game_Forward )
    call TriggerRegisterTimerEvent( gg_trg_MissileSysAdd, TimerCycle, true )
    set Nar = CreateTrigger(  )
    call TriggerAddAction( Nar, function RunCheckUnit )
    call TriggerRegisterTimerEvent( Nar, UnitTimerCycle, true )
    set Nxr = CreateTrigger()
    call TriggerAddCondition( Nxr,Filter(function Hck))
    call TriggerAddAction( Nxr, function MkUAttk )
    call TriggerRegisterAnyUnitEventBJ( Nxr, EVENT_PLAYER_UNIT_ATTACKED )
endfunction

Note: Updated (multiple times)
 
Last edited:
Level 20
Joined
Apr 22, 2007
Messages
1,960
UserData is definitely the fastest way to 'attach' structs on units.

For wall collision, are you talking about blizzard cliffs or models of walls? If blizzard cliffs, when the missile's fly height becomes <0. If models, well use GroupEnumUnitsInRange.

For the edges of the map, well get 4 globals and set them to the boundaries of bj_mapInitialPlayableArea. Then, every time you refresh the position of a missile, check if it's position is:
x>MinX and x<MaxX and y>MinY and y<MaxY
 
Level 11
Joined
Aug 25, 2006
Messages
971
Ok, but what do you mean <0? If its going up wont the value increase? And if its going down, won't the value decrease?

But yes I understand what your talking about. I'll try it when I get to that point in production. (Currently 20% complete)
 
Level 11
Joined
Aug 25, 2006
Messages
971
So how does checking its height help me at all in that case?
All my cliffs will be blizzard cliffs, and my terrain sucks so it wont be super variable.
 
Level 11
Joined
Aug 25, 2006
Messages
971
Yea, so I'll just set a threshold for variations, and when the fly height changes by more then the threshold over a short period of time, I'll say it collided.

Recently I ran into another problem, I'm dealing with multiple large structs, and remember all the names (var names/struct names/etc) is killing me. Does anyone have a better way of getting another editing window up then I used?(See screenshot)

Yes the first thing I did when TESH came out was make its theme match JassCraft.....
 

Attachments

  • sdf.jpg
    sdf.jpg
    50.3 KB · Views: 165
Level 20
Joined
Apr 22, 2007
Messages
1,960
Need_O2, this is a system, and systems generally (for use of the uses,requires,needs keywords) are libraries.

@wd40bomber7, I haven't really looked at the code (I probably will later, this looks interesting), since I have school crap to finish. But just by what you said, maybe when you initialize a missile, you don't multiply the x and y rates by the timer's timeout? Dunno. Also, some things you could do to debug it. Make the game periodically ping (minimap) the position of the missile, and be sure that debug mode is ON (for jasshelper).
 
Level 11
Joined
Aug 25, 2006
Messages
971
@Need_02 Its too easy...

@HINDYhat (and anyone else interested)
The ping idea is definitely good, but what happens if I set JassHelper to 'Debug'?

Ok: A quick description of my system: You register a weapon using one function. Then you register a unit to use that weapon. Whenever that unit attacks, it will use the weapon it was registered to use. This system isn't completely done, so the burst options as of yet do nothing.

When it uses the weapon, it'll fire a sort of collision missile which will hit enemies/walls and do their damage to the first enemy they hit.

Check out the following functions which may be the location of the glitch, I can't find it:
function FireWep - Nor.AddX and Nor.AddY
function Chess_Game_Forward (Look at the setting of Star.CurX and Star.CurY)
 
Status
Not open for further replies.
Top