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

[vJass] (system) Missile

I have worked on this missle engine for 2 months now and start the first official beta today.

Please post feedback, critism, pros, cons, bugs, etc.
Thanks all for your patience!

And thanks for downloading.
Preview image by Furby. Thanks a lot!

Edit:
I've updated the testmap and added a second spell.
There is a lot of improvements in version 0.1.7 and I plan to make it even faster and even more modular. I also plan to create an easy to understand API.

Used librarys:


Changed all constants (TRUE, FALSE) to true/false
Changed interval to 0.03125
Fixed object leaks
Performance improvements on MissileMovement: Less object generation
Merged MissileLocHelpers to Missile<type>Target
Removed HomingMissile wrapper
Added second spell (Rain of Fire)
Removed Libraries from Modules



Changed name to Missile.
Completely remade in modules, supports now a lot of optional stuff.
Added SpellHelper, fixed a lot of problems, made the Miranas Arrow example WAY more powerful to show what this system is able to be capable of.


Keywords:
Missile, Projectile, xe, xemissile, xecollider, projectile, collider, awesome, anachron, collide, colliding, vJass
Contents

CustomMissile 0.1.7 (Map)

Reviews
BPower: 11:02, 25th Feb 2016 Reason for re-review: Nowadays the spell section is packed full of missile systems from different authors, therefore a more qualified moderator comment than "this is neat stuff" is required. There is keen...
Alright, here is the todo for next update.

[autofacing]
-allow xyAngle and zAngle autoface.
- autoface[xy/z] = true/false

[haze]
-enable it, get it to work.

[acceleration]
-add it
-timed
-min / max values

[offset]
-add it

[misc]
-rework engine, make it even faster
-overwork some code areas
-implement a new module system that allows dynamic features

while not all points may be in the next update, haze and autoface will be in there.
 
I already have a collision system in here.
The shield would not be a module.

#Update - 0.0.L


  • Remade a lot of the engine.
  • Very much code fixes.
  • Engine cares about minX/minY/maxX/maxY now.
  • Implemented offset.
  • Faster then ever.
  • Renamed a bunch of stuff.
  • You can decide whether to automatically update xy/z or not.
  • You can now decide for autoFacing of XY (zArc is still in progress)
  • Please check whether haze works.
  • Please check whether every else works correctly.
  • Please forgive me to not update this earlier and to have a lot of stuff renamed.
  • Decay has been overworked. Now decay counts the elapsed time (if its 0.)



[autofacing]
-allow zAngle autofacing.

[acceleration]
-add it
-timed
-min / max values

[misc]
-implement a new module system that allows dynamic features
-allow enumeration of missiles so you can do timefreeze spells
-add a timefreeze spell to the demo
 

Attachments

  • Reason.jpg
    Reason.jpg
    15.5 KB · Views: 75
Last edited:
Level 11
Joined
Sep 30, 2009
Messages
697
I am using a custom library named Event that allows to create your own event and to attach structs to these events.
So you can just create a event that you can fire whenever you want

JASS:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  ~~    Event     ~~    By Jesus4Lyf    ~~    Version 1.04    ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//  What is Event?
//         - Event simulates Warcraft III events. They can be created,
//           registered for, fired and also destroyed.
//         - Event, therefore, can also be used like a trigger "group".
//         - This was created when there was an influx of event style systems 
//           emerging that could really benefit from a standardised custom
//           events snippet. Many users were trying to achieve the same thing
//           and making the same kind of errors. This snippet aims to solve that.
//
//  Functions:
//         - Event.create()       --> Creates a new Event.
//         - .destroy()           --> Destroys an Event.
//         - .fire()              --> Fires all triggers which have been
//                                    registered on this Event.
//         - .register(trigger)   --> Registers another trigger on this Event.
//         - .unregister(trigger) --> Unregisters a trigger from this Event.
//
//  Details:
//         - Event is extremely efficient and lightweight.
//         - It is safe to use with dynamic triggers.
//         - Internally, it is just a linked list. Very simple.
//
//  How to import:
//         - Create a trigger named Event.
//         - Convert it to custom text and replace the whole trigger text with this.
//
//  Thanks:
//         - Builder Bob for the trigger destroy detection method.
//         - Azlier for inspiring this by ripping off my dodgier code.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library Event
    ///////////////
    // EventRegs //
    ////////////////////////////////////////////////////////////////////////////
    // For reading this far, you can learn one thing more.
    // Unlike normal Warcraft III events, you can attach to Event registries.
    // 
    // Event Registries are registrations of one trigger on one event.
    // These cannot be created or destroyed, just attached to.
    //
    // It is VERY efficient for loading and saving data.
    // 
    //  Functions:
    //         - set eventReg.data = someStruct --> Store data.
    //         - eventReg.data                  --> Retreive data.
    //         - Event.getTriggeringEventReg()  --> Get the triggering EventReg.
    //         - eventReg.destroy()             --> Undo this registration.
    // 
    private keyword destroyNode
    struct EventReg extends array
        integer data
        method clear takes nothing returns nothing
            set this.data=0
        endmethod
        method destroy takes nothing returns nothing
            call Event(this).destroyNode()
        endmethod
    endstruct
    
    private module Stack
        static thistype top=0
        static method increment takes nothing returns nothing
            set thistype.top=thistype(thistype.top+1)
        endmethod
        static method decrement takes nothing returns nothing
            set thistype.top=thistype(thistype.top-1)
        endmethod
    endmodule
    
    private struct EventStack extends array
        implement Stack
        Event current
    endstruct
    
    struct Event
        private trigger trig
        private thistype next
        private thistype prev
        
        static method getTriggeringEventReg takes nothing returns EventReg
            return EventStack.top.current
        endmethod
        
        static method create takes nothing returns Event
            local Event this=Event.allocate()
            set this.next=this
            set this.prev=this
            return this
        endmethod
        
        private static trigger currentTrigger
        method fire takes nothing returns nothing
            local thistype curr=this.next
            call EventStack.increment()
            loop
                exitwhen curr==this
                set thistype.currentTrigger=curr.trig
                if IsTriggerEnabled(thistype.currentTrigger) then
                    set EventStack.top.current=curr
                    if TriggerEvaluate(thistype.currentTrigger) then
                        call TriggerExecute(thistype.currentTrigger)
                    endif
                else
                    call EnableTrigger(thistype.currentTrigger) // Was trigger destroyed?
                    if IsTriggerEnabled(thistype.currentTrigger) then
                        call DisableTrigger(thistype.currentTrigger)
                    else // If trigger destroyed...
                        set curr.next.prev=curr.prev
                        set curr.prev.next=curr.next
                        call curr.deallocate()
                    endif
                endif
                set curr=curr.next
            endloop
            call EventStack.decrement()
        endmethod
        method register takes trigger t returns EventReg
            local Event new=Event.allocate()
            set new.prev=this.prev
            set this.prev.next=new
            set this.prev=new
            set new.next=this
            
            set new.trig=t
            
            call EventReg(new).clear()
            return new
        endmethod
        method destroyNode takes nothing returns nothing // called on EventReg
            set this.prev.next=this.next
            set this.next.prev=this.prev
            call this.deallocate()
        endmethod
        method unregister takes trigger t returns nothing
            local thistype curr=this.next
            loop
                exitwhen curr==this
                if curr.trig==t then
                    set curr.next.prev=curr.prev
                    set curr.prev.next=curr.next
                    call curr.deallocate()
                    return
                endif
                set curr=curr.next
            endloop
        endmethod
        
        method destroy takes nothing returns nothing
            local thistype curr=this.next
            loop
                call curr.deallocate()
                exitwhen curr==this
                set curr=curr.next
            endloop
        endmethod
        method chainDestroy takes nothing returns nothing
            call this.destroy() // backwards compatability.
        endmethod
    endstruct
    
    /////////////////////////////////////////////////////
    // Demonstration Functions & Alternative Interface //
    ////////////////////////////////////////////////////////////////////////////
    // What this would look like in normal WC3 style JASS (should all inline).
    // 
    function CreateEvent takes nothing returns Event
        return Event.create()
    endfunction
    function DestroyEvent takes Event whichEvent returns nothing
        call whichEvent.chainDestroy()
    endfunction
    function FireEvent takes Event whichEvent returns nothing
        call whichEvent.fire()
    endfunction
    function TriggerRegisterEvent takes trigger whichTrigger, Event whichEvent returns EventReg
        return whichEvent.register(whichTrigger)
    endfunction
    
    // And for EventRegs...
    function SetEventRegData takes EventReg whichEventReg, integer data returns nothing
        set whichEventReg.data=data
    endfunction
    function GetEventRegData takes EventReg whichEventReg returns integer
        return whichEventReg.data
    endfunction
    function GetTriggeringEventReg takes nothing returns integer
        return Event.getTriggeringEventReg()
    endfunction
endlibrary
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Axerion said:
JASS:
    private module Stack
        static thistype top=0
        static method increment takes nothing returns nothing
            set thistype.top=thistype(thistype.top+1)
        endmethod
        static method decrement takes nothing returns nothing
            set thistype.top=thistype(thistype.top-1)
        endmethod
    endmodule
    
    private struct EventStack extends array
        implement Stack
        Event current
    endstruct

Why do you use an unnecessary module? Especially in private syntax.
 
Level 12
Joined
Sep 4, 2007
Messages
407
seems interesting, but i gotta restudy your system o_O (I was creating me stuff which now does not work xD)

Edit: fixed, you just changed a lot of words in it.

_______________________________________

JASS:
        //: == ---------------------------- ---------------------------- 
        //: #  Methods - Setting / Getting of members
        //: == ---------------------------- ---------------------------- 
        public method isUnitHit takes unit u returns boolean
            return IsUnitInGroup(u, .enumGroup)
        endmethod
        
        public method hitUnit takes unit u returns nothing
            call GroupAddUnit(.enumGroup, u)
        endmethod
        
        public method unhitUnit takes unit u returns nothing
            call GroupRemoveUnit(.enumGroup, u)
        endmethod

why this? isn't it better to manually pick a group from the grouputils stack and release it at onEnd?

you did this to avoid multiple hits in the same unit?

______________________________________

Important

Not Rated
12:32, 8th Apr 2010
TriggerHappy:


I have not yet tested the system.
You might as well comment out ParabolaZ2 as it serves the same purpose as the first one. The only reason is should even be in the library is to give a better explanation as to how the first one works. so yeah.. just comment it out (/* */).
Your globals are private, don't give them prefixes (CM_NAME).
You could store (2. * bj_PI * CM_PERIOD) in a constant instead of doing the operation each time.
Is there really a need for the local in enumDestsInRange?
You are using a group per instance, either A) recycle them or B) use a global group.
Is there a reason why you're creating the timer in onInit instead of just initializing it?
It would be more efficient if you placed the contents of all your update functions directly in the move method. Yes it's going to be harder to read but just make some comments explaining them. Because currently you are doing a bunch of unnecessary function calls.
The system name is horrible. Just by using a system not made by blizzard already indicates that it's custom. You might was well call it Missile.


I have tested the system and the demo map is really lacking.
If you want to show people the power of your system include some really awesome eyecandy examples.
Still need to recycle groups.
Your comments explaining the interface use the wrong grammar. It's ran, not runned.
You still need to remove the prefixes on your globals.
Why don't you just make locRect static? As of now you are creating and destroying rects when you could just be re-using the same one.
You realize you are destroying enumGroup twice, right?

wtf, this sytem NEEDS a better and (mostly a) more updated review from the moderators, this one is really old and does not match the current state of the system O.O. The way it is it just seems negative advertising (gives an untruthfull impression of the system), which is unfair. did you try to talk to some moderator? also the "not rated" stuff is unfair aswell.

(btw, just exercising freedom of speech, that's just my opinion, not trying to offend anyone)

________________________________

plz include documentation on how the haze values works. i cannot seem to make it work =( (i though the .hasHaze was never being set to true, even if i imput haze values different from 0)
 
Last edited:
why this? isn't it better to manually pick a group from the grouputils stack and release it at onEnd?

you did this to avoid multiple hits in the same unit?
I did this so users can manually add/remove hit units.
I don't want the user to be able to destroy the group.

wtf, this sytem NEEDS a better and (mostly a) more updated review from the moderators, this one is really old and does not match the current state of the system O.O. The way it is it just seems negative advertising (gives an untruthfull impression of the system), which is unfair. did you try to talk to some moderator? also the "not rated" stuff is unfair aswell.

(btw, just exercising freedom of speech, that's just my opinion, not trying to offend anyone)
Yes, I talked to Ralle and The_Reborn_Devil, while Ralle is against me and says I should wait, TRD shares my opinion.

plz include documentation on how the haze values works. i cannot seem to make it work =( (i though the .hasHaze was never being set to true, even if i imput haze values different from 0)
Shit, I forgot to remove that. Sorry, I'll change it on next update.
 
Level 1
Joined
May 5, 2010
Messages
6
errr,i am new here n im trying to make my own map with some for your model n spells but i cant seem 2 open the spell tat i download.so can some1 tell me how plsssss:cry::cool:
 
Level 1
Joined
May 5, 2010
Messages
6
errr,i am new here n im trying to make my own map with some for your model n spells but i cant seem 2 open the spell tat i download.so can some1 tell me how plsssss
 
Level 12
Joined
Sep 4, 2007
Messages
407
i agree with that. the review is absurd and is gives a bad image of you (or triggerhappy for those who use your system and notice he's just being REALLY unfair (not mentioning the adjectives he deserves but would just grant me reputation penalty)) (again, not offending, just exercising freedom of speech)
 
Level 12
Joined
Sep 4, 2007
Messages
407
have you talked to ralle? if you have you can delete this thread (which would hurt) and reupload, that would maki you r system just to be "pending" but would delete all the posts... You might aswell put a warning in your first post in this thread, saying that the review is completelly outdated and the moderator refuses to give you a new one (that's just a fact). I don't think he can punish you for that.
 
Level 12
Joined
Sep 4, 2007
Messages
407
I think that's all you can do =(

try asking when trigger happy are going to make it. or you can just make a poll (as protest) and ask users when trigger happy are going to review it. i think th will start moving when a lot of users start asking stuff.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Well considering he's been reviewing the spells from the contest for over 2 weeks (which is way too long) it's safe to say he's not fit to be a moderator, so there's not much you can do. If it is going to take TriggerHappy several weeks to sift through spell contest submissions and even longer just to change an outdated review then it's safe to say he's not fit to be a moderator, and he cannot tend to his responsibilities in due time.

Just because it's volunteer work doesn't mean that he should be able to take months to complete a simple review of a demo-map. If he cannot tend to the responsibilities that present themselves as expected then he is incapable of being a moderator. It's only going to hurt THW's reputation.
 
Level 12
Joined
Sep 4, 2007
Messages
407
In my opinion, he's could review it in due time. I just think he's lazy or trying to punish anachron for asking him to review it (like "pride-vegence"). either way, being lazy or childish, it's just not approppriate for a moderator.
 
Level 4
Joined
Feb 18, 2008
Messages
69
The next version is coming with a new system (So I'll have to delete this resource) because it's included in CustomAttack and its easier to handle it inside the other system.

It will feature a new dummy system and a hell easier and faster interface.

I hope we will still be able to use projectile system separately.

Also, your projectiles appears to have no pitch? =/ Which kinda sucks, cuz I wanted to use it as replacement of normal unit missiles. Maybe I just missed something? I like that your arcs works even when unit stands on higher position than target. (as far as I remember it does)

I'm currently using Kenny's projectiles system (from TH), where arcs don't work in situations like that.

Hope you'll finish it soon.

All best. Furby.
 
Also, your projectiles appears to have no pitch? =/ Which kinda sucks, cuz I wanted to use it as replacement of normal unit missiles. Maybe I just missed something? I like that your arcs works even when unit stands on higher position than target. (as far as I remember it does)
Yes it does.

I hope we will still be able to use projectile system separately.
Sure it will, but you can find the latest missile system version in there.

I'm currently using Kenny's projectiles system (from TH), where arcs don't work in situations like that.
What a shame.

Hope you'll finish it soon.

All best. Furby.
Yes, me too. Thanks for the feedback.
 
Level 4
Joined
Feb 18, 2008
Messages
69
Also, your projectiles appears to have no pitch? =/

1675aqg.jpg


This is just to show the problem, don't judge the code
JASS:
scope fail initializer init
globals
    private trigger DMG = CreateTrigger()
endglobals

    private struct projecMissile extends CustomMissile
        
        private unit source = null
        private unit aim = null
        
        public static method new takes unit caster, unit theTarget returns thistype
            local real x = GetUnitX(caster)
            local real y = GetUnitY(caster)
            local thistype this = thistype.create(x, y, GetLocZ(x, y) + 85., 0.)
            
            set .source = caster
            set .aim = theTarget
            
            call .setTargetUnit(theTarget)
            //call .setTargetUnitPos(theTarget)
            
            return this
        endmethod
        
        method onCreate takes nothing returns nothing
            set .sfx        = "Abilities\\Weapons\\Arrow\\ArrowMissile.mdl"
            set .scale      = 1.   //: 55% of the normal size
            set .colorA     = 255   //: Half transparent
            set .moveSpeed  = 900.  //: Moves with a rate of 512
            set .turnSpeed  = 0.15  //: Turns with a rate of 0.15
            set .hitRange   = 48.   //: Hits units and missles in range of 48.
            set .xyArc      = 0.0  //: Has an xyArc of 0.45
            set .zArc       = 0.15  //: Has an zArc of 0.45
            set .decay      = 6.    //: Decays after 6 seconds.
            set .h          = 50.   //: Has a height of 50.
            set .hitsUnits  = true  //: Hits units
        endmethod
        
        method onTargetReach takes nothing returns nothing
            call DisableTrigger(DMG)
            call UnitDamageTarget(.source, .aim, 10., false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
            call EnableTrigger(DMG)
            call .destroy()
        endmethod
    endstruct


    private function lol takes nothing returns nothing  
        local projecMissile missile = 0
        if GetUnitTypeId(GetEventDamageSource()) == 'earc' then
            set missile = projecMissile.new(GetEventDamageSource(),GetTriggerUnit())
        endif
    endfunction


    private function init takes nothing returns nothing
        call Damage_RegisterEvent(DMG)
        call TriggerAddAction(DMG, function lol)
    endfunction
endscope

What am I doing wrong? There's no pitch, looks unnaturally. :(
 
Update - 0.0.N


  • Remade a lot of the engine.
  • Added a dummy engine. Missiles now have to be actived with .use.
  • You can now clone missiles. That is why I made the dummy engine.
  • You can now enumerate missiles.
  • Fixed the math functions The_Reborn_Devil told me to fix. Thanks.
  • The effect unit isn't an hero any longer.
  • A lot of fixes have been added to the whole system.
  • You can now load/save missiles easily with CustomMissile.load(HandleIdOfMissile) and Instance.save()
  • Very much new updates, I don't remember everything.


Update - 0.1.0


  • Fixed a few small stuff.


In the Library Loc:
In your method DistBetweenUnits you don't require the two first reals because in that method you don't take into account the difference in height.
Fixed.

In the main library CustomMissile:
I seem to have missed the function ParabolaZ2 at the top.
Make it return this ((2*(y0+y1)-4*h)/(d*d))*x*x + ((y1-y0-((2*(y0+y1)-4*h)/(d*d))*d*d)/d)*x + y0 too :D
Fixed.


It would also be nice if you added some more examples ^^
Later =)

Also thanks to Furby for the new preview image.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Okay, well I gave this thing a look and I still have to say I like mine better.

When your projectiles are shot over cliff edges (and down slopes in terrain) the pitch-angle that they rest at is off, and they seem to be faced more "downwards" than they should be.

There's another thing. If you set the projectile speed to something low (like 100) and give it a unit target, the projectile will be destroyed long before it actually is supposed to reach it's target. The slower the missile is going, the more inaccurate the timing will be.

Okay, this is based on hitRange I see. This is not a very wise way of doing this, and it can display a lot of bugs in plausible situations. I'll give you a screen-shot below with this showing extremely bad cases where the projectile misses it's target and screws up the result. Also, when your targets are moving there seem to be a lot of problems with the projectiles arcing properly; lots of twitching and stuff.



Okay, in this picture you can see how the projectiles are all tilted at an improper angle. The decay-time also tripped me out because the projectiles were all destroyed long before they should, but after further examination it seems that this is handled by your decay timer.



This is what I was talking about before. The three projectiles that seem to be moving strangely are both cases where they've missed their target because it is moving. The other two projectiles are not good examples, but they were twitching as the target moved, facing slightly up to down then back up again. There was also a case where the projectile was stuck on the ground and slowly moved towards the edge of the map. I don't get how you missed these problems, as they are frequent and can be even more frequent when the user doesn't know exactly how to use your system.
 
Top