| 08-04-2009, 12:24 PM | #1 |
Hello guys! I've been developing a projectile system, which does a lot of things at the same time. Instead, of only moving a missile or making a jump individually, it does it all. However when I added the knockback feature to it, it started causing trouble. For example I have a unit which is spawning missiles and this missiles are moving upwards in a spiral movement. The missiles move perfectly without any problem until another unit starts knockbacking units, far away from the first unit. What happens now is that the missiles that are moving around the first unit will start to have their path changed. I realized the angle and the speed values get changed some how. Strange thing is that the knockbacks don't get messed up. I've already tested this 3D spiraling movement at the same time with jumps and missile arcs, and none have caused trouble. The knockback seems to be the root of the problem, but it's odd because I haven't changed anything on the system loop, only added a knockback method to make different calculations and to store them on the struct. Another thing that has been pissing me off as well: My system hads the possibility to attach an effect to the missile and in the end destroy it. But when I decided to put the knockback thing, I had to add another type of effect, an instant effect, which would be created and destroyed every time the unit moves. However I discovered it is the causer of the tremendous lag, when more than 60 missiles (instances) are being moved. When I remove the instant effect, everything goes back to normal, and my system become capable, once again, of moving more than 100 missiles. Now if someone has a solution for this, I'd really appreciate it, because I actually need that instant effect. here is the system code: (Sorry if it is too long and hard to read) Dummy Engine:library DummyEngine initializer Init private keyword Moving globals private integer FPS = 30 private timer TIMER private real DELAY = 1./FPS private group TEMP private group DEunits private integer MISSILEID = 'h000' private integer FLYABILITY = 'Amrf' private integer tot = 0 private Moving array store private boolexpr unitcheck integer count = 0 endglobals //======================================== //Terrain Pathability System by RisingDusk //======================================== globals constant integer TERRAIN_PATHING_DEEP = 1 constant integer TERRAIN_PATHING_SHALLOW = 2 constant integer TERRAIN_PATHING_LAND = 3 constant integer TERRAIN_PATHING_WALKABLE = 4 private unit Dummy = null private constant integer DUMMY_UNIT_ID = 'hfoo' private constant integer DUMMY_WINDWALK_ID = 'win&' private constant player OWNING_PLAYER = Player(15) private real WorldMinX = 0. private real WorldMinY = 0. endglobals function IsTerrainPathingType takes real x, real y, integer terrainPathingType returns boolean local boolean b = false if terrainPathingType == TERRAIN_PATHING_DEEP then return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) elseif terrainPathingType == TERRAIN_PATHING_SHALLOW then return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) elseif terrainPathingType == TERRAIN_PATHING_LAND then return IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) elseif terrainPathingType == TERRAIN_PATHING_WALKABLE then call SetUnitPosition(Dummy, x, y) set b = GetUnitX(Dummy) == x and GetUnitY(Dummy) == y and not (not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)) call SetUnitX(Dummy, WorldMinX) call SetUnitY(Dummy, WorldMinY) endif return b endfunction //======================================== //The rest of the Dummy Engine by Wizardum //======================================== private function unitfilter takes nothing returns boolean local unit u = GetFilterUnit( ) return not IsUnitType( u, UNIT_TYPE_MAGIC_IMMUNE ) and not IsUnitType( u, UNIT_TYPE_STRUCTURE ) and not IsUnitType( u, UNIT_TYPE_FLYING ) and GetWidgetLife( u ) > 0.405 endfunction private function ParabolicMovement takes real h, real d, real x returns real //By moyack local real a = -4*h/(d*d) local real b = 4*h/d return a*x*x + b*x endfunction private function Loop takes nothing returns nothing local Moving d local integer i = 0 local real x local real y local real z local real dx local real dy local group g = CreateGroup( ) loop exitwhen i >= tot set d = store[i] if d.rot then set d.cx = GetUnitX( d.c ) + d.d * Cos( d.a * bj_DEGTORAD ) set d.cy = GetUnitY( d.c ) + d.d * Sin( d.a * bj_DEGTORAD ) set d.d = d.d + d.s set d.a = d.a + d.da set d.da = d.da - d.dda else set d.cx = d.cx + d.s * Cos( d.a * bj_DEGTORAD ) set d.cy = d.cy + d.s * Sin( d.a * bj_DEGTORAD ) endif if d.up then if d.cz < d.mh then set d.cz = d.cz + d.ups call SetUnitFlyHeight( d.m, d.cz, 0. ) else call d.destroy( ) endif elseif d.pb then if d.cd < d.d then set d.cz = ParabolicMovement( d.mh, d.d, d.cd ) call SetUnitFlyHeight( d.m, d.cz, 0. ) set d.cd = d.cd + d.s else call d.destroy( ) endif endif set d.s = d.s - d.sd if IsTerrainPathingType( d.cx, d.cy, TERRAIN_PATHING_WALKABLE ) then call SetUnitX( d.m, d.cx ) call SetUnitY( d.m, d.cy ) if d.af then call SetUnitFacing( d.m, d.a ) endif call DestroyEffect( AddSpecialEffect( d.fi, d.cx, d.cy ) ) else call d.destroy( ) endif set d.ct = d.ct + DELAY if d.ct >= d.tim then call d.destroy( ) endif if d.rd > 0. then call d.Collision( d.cx, d.cy ) endif if d.mrd > 0. then call d.Damage( d.cx, d.cy, d.mrd, d.mdmg ) endif set i = i + 1 endloop if tot == 0 then call PauseTimer( TIMER ) endif endfunction private struct Moving unit c //source unit unit m //moved unit string fs //string attached effect model effect fx //actual attached model string fi //instant effect boolean koe //kill on the end real rd //collision radius string ceff //collision effect real erd //end radius real edmg //end damage real mrd //moving radius real mdmg //moving damage string deff //unit damage effect real mh //max height real ups //up speed real cz //current flying height boolean up //up movement check boolean pb //parabola check real cx //current x coordinate real cy //current y coordinate real d //maximum distance that will move real cd //current distance boolean rot //rotation check real s //speed real sd //speed decreaser real a //the angle real da //deviation angle real dda //decrease deviation angle boolean af //auto face current angle check real tim //the duration of the moving real ct //the current duration, once it reach the tim value it stoppes integer ID method Collision takes real x, real y returns nothing local group g = CreateGroup( ) local unit u call GroupEnumUnitsInRange( g, x, y, .rd, unitcheck ) set u = FirstOfGroup( g ) if u != null and not IsUnit( u, .c ) then call DestroyEffect( AddSpecialEffect( .ceff, x, y ) ) call .destroy( ) endif call DestroyGroup( g ) set u = null endmethod method Damage takes real x, real y, real radius, real dmg returns nothing local group g = CreateGroup( ) local unit u call GroupEnumUnitsInRange( g, x, y, radius, unitcheck ) loop set u = FirstOfGroup( g ) exitwhen u == null call GroupRemoveUnit( g, u ) if IsUnitEnemy( u, GetOwningPlayer( .c ) ) then call UnitDamageTarget( .c, u, dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null ) endif endloop call DestroyGroup( g ) endmethod static method create takes string fs, real x, real y returns Moving local Moving mis = Moving.allocate( ) set mis.fs = fs set mis.ct = 0. set mis.cz = 0. set mis.cd = 0. if count < tot then set count = tot call BJDebugMsg( I2S( count ) ) endif return mis endmethod private method Run takes nothing returns nothing set .cx = GetUnitX( .m ) set .cy = GetUnitY( .m ) if tot == 0 then call TimerStart( TIMER, DELAY, true, function Loop ) endif set store[tot] = this set .ID = tot set tot = tot + 1 endmethod //This method is for missiles that only deal damage in the end of the movement method missilemoveEND takes unit c, real time, real speed, real a, real radius, real dmg returns nothing set .a = a set .da = 0. set .c = c set .tim = time set .s = speed set .koe = true set .pb = false set .up = false set .rot = false set .af = false set .erd = radius set .edmg = dmg set .fx = AddSpecialEffectTarget( .fs, .m, "chest" ) call .Run( ) endmethod //This method is for missiles that continuously deal damage around. method missilemoveOT takes unit c, real time, real speed, real a, real radius, real dmg returns nothing set .a = a set .da = 0. set .c = c set .tim = time set .s = speed set .mrd = radius set .mdmg = dmg * DELAY set .koe = true set .rot = false set .pb = false set .up = false set .fx = AddSpecialEffectTarget( .fs, .m, "chest" ) call .Run( ) endmethod method missileupspiral takes unit c, real speed, real a, real maxheight, real maxdis, real disdecre, real ups returns nothing set .c = c set .tim = 1000. set .a = a set .da = speed set .mh = maxheight set .d = maxdis set .s = disdecre set .ups = ups set .rot = true set .up = true set .koe = false set .pb = false set .fx = AddSpecialEffectTarget( .fs, .m, "chest" ) call .Run( ) endmethod method missilearc takes unit c, real speed, real a, real maxheight, real maxdis returns nothing set .c = c set .tim = 1000. set .s = speed set .a = a set .mh = maxheight set .d = maxdis set .pb = true set .koe = false set .up = false set .rot = false set .fx = AddSpecialEffectTarget( .fs, .m, "chest" ) call .Run( ) endmethod method knockback takes unit c, real speed, real time, real a, real dmg returns nothing set .c = c set .tim = time set .s = speed set .sd = .s / .tim * DELAY set .a = a set .mdmg = dmg * DELAY set .pb = false set .koe = false set .up = false set .rot = false set .af = false call .Run( ) endmethod method unitjump takes unit c, real speed, real a, real maxheight, real maxdis returns nothing set .c = c set .tim = 1000. set .s = speed set .a = a set .mh = maxheight set .d = maxdis set .pb = true set .fx = AddSpecialEffectTarget( .fs, .m, "chest" ) call .Run( ) endmethod method onDestroy takes nothing returns nothing set tot = tot - 1 set store[.ID] = store[tot] set store[.ID].ID = .ID call PauseUnit( .m, false ) call .Damage( GetUnitX( .m ), GetUnitY( .m ), .erd, .edmg ) if .koe then call KillUnit( .m ) else endif call DestroyEffect( .fx ) call SetUnitFlyHeight( .m, GetUnitDefaultFlyHeight( .m ), 0. ) set .c = null set .m = null endmethod endstruct //================== //External Functions //================== function GetUpSpiral takes unit c, string fs, real speed, real angle, real maxheight, real maxdis, real disdecre, real ups returns nothing local real x = GetUnitX( c ) + maxdis * Cos( angle * bj_DEGTORAD ) local real y = GetUnitY( c ) + maxdis * Sin( angle * bj_DEGTORAD ) local Moving d = Moving.create( fs, x, y ) set d.m = CreateUnit( GetOwningPlayer( c ), MISSILEID, x, y, angle ) call d.missileupspiral( c, speed, angle, maxheight, maxdis, disdecre, ups ) endfunction function GetMissileArc takes unit c, string fs, real speed, real angle, real maxheight, real maxdis returns nothing local real x = GetUnitX( c ) local real y = GetUnitY( c ) local Moving d = Moving.create( fs, x, y ) set d.m = CreateUnit( GetOwningPlayer( c ), MISSILEID, x, y, angle ) call SetUnitX( d.m, x ) call SetUnitY( d.m, y ) call d.missilearc( c, speed, angle, maxheight, maxdis ) endfunction function GetJump takes unit c, string fs, real speed, real angle, real maxheight, real x, real y returns nothing local Moving d = Moving.create( fs, GetUnitX( c ), GetUnitX( c ) ) local real dx = x - GetUnitX( c ) local real dy = y - GetUnitY( c ) set d.m = c call UnitAddAbility( d.m, FLYABILITY ) call UnitRemoveAbility( d.m, FLYABILITY ) call d.unitjump( c, speed, angle, maxheight, SquareRoot( dx * dx + dy * dy ) ) endfunction function GetMissile takes unit c, string fs, real time, real speed, real angle, real radius, real dmg returns nothing local real x = GetUnitX( c ) local real y = GetUnitY( c ) local Moving d = Moving.create( fs, x, y ) set d.m = CreateUnit( GetOwningPlayer( c ), MISSILEID, x, y, angle ) call SetUnitX( d.m, x ) call SetUnitY( d.m, y ) call d.missilemoveEND( c, time, speed, angle, radius, dmg ) endfunction function GetKnockback takes unit c, unit t, string fi, real time, real speed, real angle, real dmg returns nothing local real x = GetUnitX( c ) local real y = GetUnitY( c ) local Moving d = Moving.create( "", x, y ) set d.fi = fi set d.m = t call d.knockback( c, speed, time, angle, dmg ) endfunction private function Init takes nothing returns nothing //============================ //Terrain Pathability settings //============================ set WorldMinX = GetRectMinX(bj_mapInitialPlayableArea) set WorldMinY = GetRectMinY(bj_mapInitialPlayableArea) set Dummy = CreateUnit(OWNING_PLAYER, DUMMY_UNIT_ID, 0., 0., 0.) call UnitAddAbility(Dummy, DUMMY_WINDWALK_ID) call UnitAddAbility(Dummy, 'Avul') call IssueImmediateOrderById(Dummy, 852129) //===================== //Dummy Engine Settings //===================== set TIMER = CreateTimer( ) set TEMP = CreateGroup( ) set DEunits = CreateGroup( ) set unitcheck = Condition( function unitfilter ) endfunction endlibrary Also if you want to see the horrible results, you can download the map at the bottom of this post. The blood mage is the one with spiraling effects, and the paladin is the one with the knockbacks. Try to run both at the same time, and you'll see what I mentioned above. By the way, suggestions to improve the overall efficiency of this system are welcome and appreciated. Thanks in advance!! Wizzy.. |
| 08-07-2009, 07:48 PM | #2 |
*bumping* |
| 08-07-2009, 08:24 PM | #3 |
Use a custom dust effect so that you wouldn't need to constantly create-destroy effects, you can use the ImpaleDustTarget.mdx as a base for the dust effect. |
| 08-07-2009, 08:42 PM | #4 |
now what's exactly a custom dust effect? |
| 08-07-2009, 08:47 PM | #5 |
Edited mdl model. |
| 08-08-2009, 11:33 AM | #6 |
and where exactly do I get it or do it? I've never heard something like that |
| 08-08-2009, 01:58 PM | #7 |
What I mean is make a dust model with a stand animation, instead of killing it every movement, you just keep on playing it's animation, which reduces the drag on the game engine. |
| 08-08-2009, 06:41 PM | #8 |
ah, I guess you're talking about a dummy effect right? nice idea. |
