(10 ratings)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~ 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
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
//: == ---------------------------- ----------------------------
//: # 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
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?
I did this so users can manually add/remove hit units.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?
Yes, I talked to Ralle and The_Reborn_Devil, while Ralle is against me and says I should wait, TRD shares my opinion.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)
Shit, I forgot to remove that. Sorry, I'll change it on next update.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)
Why do you use an unnecessary module? Especially in private syntax.
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.
Yes it does.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)
Sure it will, but you can find the latest missile system version in there.I hope we will still be able to use projectile system separately.
What a shame.I'm currently using Kenny's projectiles system (from TH), where arcs don't work in situations like that.
Yes, me too. Thanks for the feedback.Hope you'll finish it soon.
All best. Furby.
Also, your projectiles appears to have no pitch? =/
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
Yes, I haven't added pitch yet, it will be there in the next release, sorry.
I am trying to make things optional but still useable and disableable at any time.
Fixed.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![]()
Later =)It would also be nice if you added some more examples ^^
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.