• 🏆 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!

[System] Missile

Level 19
Joined
Aug 8, 2007
Messages
2,765
cuz mods dont really care if you can go to the last page to post a bug report and see a fix.
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
Why is this still approved if it contains bugs?
Because it's still the only missile system with a good interface and no useless junk features.

EDIT: also ... doesn't require dozens of other libraries to import. Yes, I'm looking at you, Nes. ;)

If someone wants to write a lightweight missile system with about the same features, go for it!
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Results in System Error and double frees a dummy unit.
-->
JASS:
loop
     set u = FirstOfGroup(bj_lastCreatedGroup)
     exitwhen u==null
     if not(IsUnitInGroup(u,this.unitsHit)) and u!=this.target and thistype.onCollide(this,u) then
         call missileTerminate(this)
     endif
     call GroupAddUnit(this.unitsHit,u)
     call GroupRemoveUnit(bj_lastCreatedGroup,u)
endloop

Nonsense! Execute is never called nor run via execute(), evaluate() or ExecuteFunc() from anywhere.
Reading T32 doesn't solve the problem :p
-->
JASS:
    //***********************************************************************
    //  This function runs periodically. Can you see the trigger evaluation
    //  at the end? If you've read T32 then you know exactly what it does.
    //  The loop above is for cleaning up, the SIZE variable keeps track of
    //  how many instances have been deallocated by the user, if higher than
    //  0 then some of them need to be removed. STACK[SIZE] stores the value
    //  of the deallocated instances.
    private function Execute takes nothing returns nothing
        loop
            exitwhen SIZE==0
            set ACTIVE=ACTIVE-1
            set SIZE=SIZE-1
            set INSTANCES[STACK[SIZE]]=INSTANCES[STACK[SIZE]]-1
            if INSTANCES[STACK[SIZE]]==0 then
                call TIMER[STACK[SIZE]].stop()
                if ACTIVE==0 then
                    return
                endif
            endif
        endloop
        call TriggerEvaluate(FIRE)
    endfunction

Dirac failed to detect, when no missile is allocated
--> Constant Timer Loop32 is never stopped, once started.
--> TriggerEvaluations every 0.03215 for the whole game season.

FIRE does excacly what?
JASS:
        private trigger                     FIRE    =   CreateTrigger()

Missile is currently far from beeing good. I already re-wrote it for myself.
However I'm using a different LinkedList module and added some extra features.
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
Results in System Error and double frees a dummy unit.
-->
JASS:
loop
     set u = FirstOfGroup(bj_lastCreatedGroup)
     exitwhen u==null
     if not(IsUnitInGroup(u,this.unitsHit)) and u!=this.target and thistype.onCollide(this,u) then
         call missileTerminate(this)
     endif
     call GroupAddUnit(this.unitsHit,u)
     call GroupRemoveUnit(bj_lastCreatedGroup,u)
endloop

Nonsense! Execute is never called nor run via execute(), evaluate() or ExecuteFunc() from anywhere.
Reading T32 doesn't solve the problem :p
-->
JASS:
    //***********************************************************************
    //  This function runs periodically. Can you see the trigger evaluation
    //  at the end? If you've read T32 then you know exactly what it does.
    //  The loop above is for cleaning up, the SIZE variable keeps track of
    //  how many instances have been deallocated by the user, if higher than
    //  0 then some of them need to be removed. STACK[SIZE] stores the value
    //  of the deallocated instances.
    private function Execute takes nothing returns nothing
        loop
            exitwhen SIZE==0
            set ACTIVE=ACTIVE-1
            set SIZE=SIZE-1
            set INSTANCES[STACK[SIZE]]=INSTANCES[STACK[SIZE]]-1
            if INSTANCES[STACK[SIZE]]==0 then
                call TIMER[STACK[SIZE]].stop()
                if ACTIVE==0 then
                    return
                endif
            endif
        endloop
        call TriggerEvaluate(FIRE)
    endfunction

Dirac failed to detect, when no missile is allocated
--> Constant Timer Loop32 is never stopped, once started.
--> TriggerEvaluations every 0.03215 for the whole game season.

FIRE does excacly what?
JASS:
        private trigger                     FIRE    =   CreateTrigger()

Missile is currently far from beeing good. I already re-wrote it for myself.
However I'm using a different LinkedList module and added some extra features.
While you're at it, maybe give us one of your beta builds to test it out? I'd say you should stay as close to Dirac's API as possible in your own build, simply to allow full compatibility (you could also write a wrapper for that, but I hate it when people do that).

But yeah, I'd kill for an improved system. Dirac's system is still the best missile system in that is has exactly the right mixture of features and ease-of-use. Other missile systems on Hive are either not as powerful as this or unnecessarily convoluted.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
I kept the API completly, I only removed the LinkedList module and used List (Nestharus).
However List is within static if and is replaced by a a handwritten LinkedList if not in the map. (no debug only code)

I wrote onDestructable and something like onCliff
Missiles without acrs now keep fly height over canions and have improved the collision check.
Furthermore optional dummy unit usage in the following priority order MissileRecylcer>Dummy>CreateUnit

Performs worse on DEBUG_MODE than Dirac's, because I added a lot of debug checks here and there
to filter out wrong usage. Performs same (better, because of small improvements and proper TimerGroup stop.) without DEBUG_MODE = true.

I will check everything (after the weekend) and then post it.
I don't want to post unfinished code.

Here is just the requirements and configuration, rest comes next week (hopefully):

JASS:
library Missile /* (2.0)
*************************************************************************************
*
*   Missile is a custom projectile system written in vJass.
*   The main goal of Missile is to run as effective as possible 
*   without unessary external requirements. Instead those external resources
*   are implemented and used optionally.
*   I designed Missile 2.0 to replace Dirac's Missile library, which still has
*   a few serious bugs.
*   
*   The timer system is ConstantTimerLoop32 aka. CTL. - Credits to Nestharus
*   
*   Credits to Dirac, emjlr3, AceHart
*
*************************************************************************************
*
*   */ requires /* 
*
*       */ CTL                   /* - Link goes here -
*       */ AdvLoc                /* - Link goes here -
*
*   Optional requirements listed here can reduce overall code generation
*   and add safety features (BoundSentinel, WorldBounds, ..)
*   however they don't influence Missile's performace at all.
*   Thanks to Nestharus, they will add a lot DEBUG_ONLY code,
*   which may be useful to detect wrong usage. I totally 
*   recommend to import at least ErrorMessage to your map. 
*
*       */ optional WorldBounds   /* - Link goes here -
*       */ optional BoundSentinel /* - Link goes here -
*       */ optional GroupUtils    /* - Link goes here -
*       */ optional Alloc         /* - Link goes here -
*       */ optional Init          /* - Link goes here -
*       */ optional List          /* - Link goes here -
*       */ optional UnitIndexer   /* - Link goes here -
*       */ optional ErrorMessage  /* [url]https://github.com/nestharus/JASS/tree/master/jass/Systems/ErrorMessage[/url] 
*
************************************************************************************/
    globals 
        // Owner of all missiles.
        private constant player NEUTRAL_PASSIVE              = Player(15)
        
        // Set DUMMY_UNIT_ID to the correct raw code (object editor F6)
        private constant integer DUMMY_UNIT_ID               = 'h000'
        
        // The maximum collision size used in your map. If unsure leave it 196.
        // Precise values may improve the Missile's overall performance,
        // because a smaller value group enumerate less units per loop per missile.
        private constant integer MAXIMUM_COLLISION_SIZE      = 196

        // Set to true, if you want Missiles to collide with destructables.
        // Destructables need an occluder height above 0 to be considered as valid targets. 
        // Set to false, if you don't want Missiles to interact with your destruables.
        private constant boolean USE_ON_DESTRUCTABLE_FILTER  = false
        
        private constant boolean USE_CLIFF_COLLIDE_FILTER    = true
        
        // Allows to detect missile collisions in x/y and z axis. Normally it is only x and y.
        // Set only to true, if you wish to create missile which can fly over units or hit only flying units.
        private constant boolean USE_COLLISION_Z_FILTER      = false
    endglobals

For those who worry, UnitIndexer is just listed so it can be disabled when creating a new unit :)

UPDATE:

Uploaded it in the submissions forum. I wrote Missile very quickly and hope I didn't make any mistake.
 
Last edited:
Level 19
Joined
Mar 18, 2012
Messages
1,716
I wish to Graveyard Dirac's Missile in favor of the Missile library I submitted in the Jass Section.

Why graveyard Dirac's Missile?:
  • Does never stop CTL timer due to wrong implementation.
  • Has code, which is simply not working correctly or not used at all.
  • Malfunction within onCollide ( double free )
  • Missing features ( onDestructable, onTerrain, ... )
  • Badly optimized
  • Redundant dependencies ( New version requires nothing )
  • Chance for breaking a thread by dividing with 0 in AdvLoc ( distance == 0 )
  • For curved Missiles x/y stored values do not reflect a missiles current position.
  • No debug code to check wrong user usage.

I did maintain the API of Missile for backwards compatibility.
 
Last edited:
Top