![]() |
#1 | |
Obscurity, the Art
|
![]() Background: I made this system awhile ago and have had it lying around for awhile now. Someone posted something about needing one in the trigger forum, and then someone linked them to the one in the database. Well, I was going through that old system and noticed that it is so terrible! It needed cache, ran each unit on an individual timer, and so forth. So I decided in my infinite generosity (Haha, yeah right) to clean this thing up and submit it. Requirements:
System Code: ![]() Special Thanks: All credits to anything used in the spell are in the testmap, but I'll do it again here. Thanks to Vex for vJass, thanks to xombie for reporting a critical bug in the system, thanks to wc3c for being awesome, and thanks to whoever actually takes the time to read through this! Last edited by Rising_Dusk : 08-13-2009 at 04:15 PM. Reason: Updated |
|
![]() |
![]() |
Sponsored Links - Login to hide this ad! |
|
![]() |
#2 |
User
|
![]() I think it's faster to store cartesian velocity (vx,vy) than polar (speed, angle). You don't need to use trig functions at all when using cartesian.
__________________![]() //given vx, vy, subtract F from speed c = 1 - F/SquareRoot(vx*vx + vy*vy) vx *= c vy *= c Last edited by Strilanc : 03-31-2008 at 12:21 AM. |
![]() |
![]() |
![]() |
#3 |
Obscurity, the Art
|
![]() It could be, but squareroot is a really slow function for computation and I managed to avoid it entirely doing it this way. I'll see what some other people think before doing anything.
__________________EDIT: I just noticed I forgot to do something, damned! Stupid additional functions! |
![]() |
![]() |
![]() |
#4 | |
BuranX
|
![]() Quote:
|
|
![]() |
![]() |
![]() |
#5 |
Evil Overlord
Join Date: Jan 2006
Posts: 1,416
![]() ![]() ![]() |
![]() Neat system, works smoothly, easy to implement & use.
__________________Last edited by Fulla : 03-31-2008 at 12:53 AM. |
![]() |
![]() |
![]() |
#6 |
Lackadaisically Absent.
Respected User
|
![]() Most of your globals should be constant globals so they get inlined, like so (you should also move the TimerInterval constant to the top so that it can more easily be seen an changed):
__________________![]() globals //********************************************************* //* These are the configuration constants for the system //* //* EffectLocation: Where on the unit the effect attaches //* EffectPath_Water: What special effect to attach over water //* EffectPath_Ground: What special effect to attach over ground //* DestDestroy_Radius: Radius around which destructs die //* private constant string EffectLocation = "origin" private constant string EffectPath_Water = "MDX\\KnockbackWater.mdx" private constant string EffectPath_Ground = "MDX\\KnockbackDust.mdx" private constant real DestDestroy_Radius = 180. private constant real TimerInterval = 0.05 endglobals This line (and the other 5 lines in the script like it): set n.KBEffect = AddSpecialEffectTarget(EffectPath_Ground, n.Target, "origin") Should be changed to: set n.KBEffect = AddSpecialEffectTarget(EffectPath_Ground, n.Target, EffectLocation) You forgot a "debug" here (both places you wrote this): ![]() debug else debug call BJDebugMsg("System Error: Unknown Terrain Type") In fact, where you check this in the Update function can be re-written in a more optimized form: ![]() if (n.FXMode == 1) and (mode == 2) then call DestroyEffect(n.KBEffect) set n.KBEffect = AddSpecialEffectTarget(EffectPath_Ground, n.Target, "origin") elseif n.FXMode == 2) and (mode == 1) then call DestroyEffect(n.KBEffect) set n.KBEffect = AddSpecialEffectTarget(EffectPath_Water, n.Target, "origin") debug elseif n.FXMode == 0 then debug call BJDebugMsg("System Error: Unknown Terrain Type") endif You can remove the InitTrig function, as they are no longer forced by the editor. Any time you have local knocker n = 0, you don't need to initialize "n" at all. Another thing: why are you typecasting to integers in the global array? It would make more sense as a knocker array: private knocker array Knockers The order in which you used SetUnitPosition is wrong; since it takes into account pathing and sorts of things like that, it is conceivable that the unit does not end up where you think it will and it might be on a different type of terrain than the effect you are using. It should be in this order: ![]() set xf = xi + (n.Speed) * Cos(n.Angle*0.01745328) set yf = yi + (n.Speed) * Sin(n.Angle*0.01745328) call SetUnitPosition(n.Target, xf, yf) set n.FXMode = n.checkterrain(n) You don't need a local variable to reference n.Target; your usage of "u" is unnecessary. Instead of using a local rect, r, and creating a new handle every iteration of the loop, you should use a global rect and use SetRect on it: ![]() globals //... private rect R endglobals //... call SetRect(R, xf-DestDestroy_Radius, yf-DestDestroy_Radius, xf+DestDestroy_Radius, yf+DestDestroy_Radius) //... private function KnockbackSystemInit takes nothing returns nothing set Boolexpr = Condition(function KillDests_Check) set R = CreateRect() endfunction Why even bother to deal with degrees at all? Radians are more standard anyway, and you should just tell people that the functions take radians in the ReadMe. This will save you from some calculations Finally (on the subject of angles and cartesian velocity and all that crap), the way you've done it (as opposed to what Strilanc said) makes more sense because you're changing the velocity constantly. That being said, you should store the Cosine and Sine of the angle instead of just the angle in the struct: ![]() private struct knocker unit Target effect KBEffect integer FXMode boolean KillDest real Decrement real Speed real ASin real ACos method checkterrain takes knocker n returns integer local real x = GetUnitX(n.Target) local real y = GetUnitY(n.Target) if IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) then return 1 elseif not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) then return 2 endif return 0 endmethod static method create takes unit targ, real angle, real startspeed, real decrement, boolean killDestructables returns knocker local knocker n = knocker.allocate() set n.Target = targ set n.FXMode = n.checkterrain(n) if n.FXMode == 1 then set n.KBEffect = AddSpecialEffectTarget(EffectPath_Ground, n.Target, EffectLocation) elseif n.FXMode == 2 then set n.KBEffect = AddSpecialEffectTarget(EffectPath_Water, n.Target, EffectLocation) debug else debug call BJDebugMsg("System Error: Unknown Terrain Type") endif set n.KillDest = killDestructables set n.Decrement = decrement set n.Speed = startspeed set n.ASin = Sin(angle) set n.ACos = Cos(angle) return n endmethod private method onDestroy takes nothing returns nothing call DestroyEffect(this.KBEffect) endmethod endstruct //... set xf = xi + (n.Speed) * n.ACos set yf = yi + (n.Speed) * n.ASin Aside from that... |
![]() |
![]() |
![]() |
#7 | |||||||
Obscurity, the Art
|
![]() Now, that's impressive. Consider it all done. (Some things I disagree with, but the majority is good stuff)
__________________Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
EDIT: And you don't have to give me all of the examples. You should've saved yourself all of that time, I can figure stuff out strictly by words alone. :p |
|||||||
![]() |
![]() |
![]() |
#8 |
Alpha Male of Wc3c
Official Map Reviewer
|
![]() Yay, a decent knockback system. I would use it if I weren't forcing myself to code my own (using a tutorial) so I can both have a systm AND learn vJass.
__________________ |
![]() |
![]() |
![]() |
#9 | |
Lackadaisically Absent.
Respected User
|
![]() Yeah, well I like examples :)
__________________Quote:
![]() function Actions takes nothing returns nothing local unit U = GetTriggerUnit() local unit Target = GetSpellTargetUnit() call KnockbackUnit(Target, Atan2(GetUnitY(Target)-GetUnitY(U), GetUnitX(Target)-GetUnitX(U)), 500.00, 15.00, true) set U = null set Target = null endfunction Out of curiosity, what happens when you initiate a knockback on a unit that is already being knocked back? Does the system bug out at all (I think KnockbackStop would)? |
|
![]() |
![]() |
![]() |
#10 | |||
Obscurity, the Art
|
![]() Quote:
Quote:
Quote:
Updated, by the way. |
|||
![]() |
![]() |
![]() |
#11 |
Evil Emoticon
Respected User
Project Leader: PoC |
![]() ahHAAA!!! using my technique of calling random creeps to attack your hero!!! How dare you :P
One question: why you stop the timer when there's no units to move? to improve performance??? that's not necessary, and you save code. Even better, you can replace (optionally) the timer with a periodic trigger. But, in general, I see no other issue. |
![]() |
![]() |
![]() |
#12 | ||||
Lackadaisically Absent.
Respected User
|
![]() Quote:
Quote:
Quote:
Quote:
On that note, I shall approve this! One question though: how did you update your post without the "last edited by" message? Special Admin edits? |
||||
![]() |
![]() |
![]() |
#13 | |||
Obscurity, the Art
|
![]() Quote:
Quote:
Quote:
|
|||
![]() |
![]() |
![]() |
#14 |
Evil Overlord
Join Date: Jan 2006
Posts: 1,416
![]() ![]() ![]() |
![]() Would be neat if you added a little collision causes knockback, i.e. when a unit is sliding back and knocks into another unit, it causes it to get knockbacked aswell.
__________________Last edited by Fulla : 03-31-2008 at 09:44 AM. |
![]() |
![]() |
![]() |
#15 |
User
Join Date: Jan 2007
Posts: 542
![]() ![]() ![]() |
![]() hmm, i wonder what happens when units are pushed over the edge of a pathing type (eg: from floatability to walkability). The Effect shouldnt change, afaics. nvm, just noticed the if statement in the uptdate function.
Besides, from reading i would say, that units will move far too fast, youll have to replace (n.Speed) with (n.Speed*TimerInterval) to make it userfriendly, or you put into the readme, that users have to pass (desiredspeed * TimerInterval). Same applies to decrement. Last edited by Deaod : 03-31-2008 at 08:00 PM. |
![]() |
![]() |
![]() |
Thread Tools | Search this Thread |
|
|