| 09-16-2009, 11:02 AM | #1 |
i hope for your feedback to make the library better and to improve my skills :) JASS://* //* Library: Spawn Movement //* //* Version: 0.3a //* //* Description: library for the movement of spawning units. //* allows to create lanes and to set waypoints. //* also includes an automatically thing to disallow unit's flee. //* //* User functions: 1) function RegisterLane takes Lane WhichLane, integer Key returns nothing //* 2) function GetLane takes integer Key returns Lane //* 3) RegisterUnit takes unit WhichUnit, integer LaneKey returns nothing //* 4) GetUnitLane takes unit WhichUnit returns integer //* 5) GetUnitLaneKey takes unit WhichUnit returns integer //* 6) GetUnitWaypointIndex takes unit WhichUnit returns integer //* 7) SetUnitWaypointIndex takes unit WhichUnit, integer NewIndex returns nothing //* 8) GetUnitWaypointX takes unit WhichUnit returns real //* 9) GetUnitWaypointY takes unit WhichUnit returns real //* //* library SpawnMovement initializer init globals private constant integer MAXWAYPOINTS = 16 // max number of waypoints a lane contains private key INDEXLANE // index for the hashtable private key INDEXLANEKEY // index for the hashtable private key INDEXWAYPOINTX // index for the hashtable private key INDEXWAYPOINTY // index for the hashtable private key INDEXWAYPOINTID // index for the hashtable // MAP SPECIFIC VARIABLES public key TOPLANEWEST public key MIDDLELANEWEST public key BOTTOMLANEWEST public key TOPLANEEAST public key MIDDLELANEEAST public key BOTTOMLANEEAST private constant real REFRESHINTERVAL = 20 * 60 // every 20 minutes refresh the trigger // if u got problems with this, set the // interval to 0 to avoid refreshing private constant real EPSILON = 300 // tolerance for checking if unit is near waypoint private region REGION = null // region to store all waypointrects private boolexpr ENTERFILTER = null private trigger TRIG = null // trigger to catch "flee" orders of registered unit private trigger TRIG2 = null // trigger for region entering private timer TIM = null // timer to refresh the dynamic trigger private group REGISTEREDUNITS = null // group to add units after refreshing the trigger private hashtable TABLE = null // table to store all the data endglobals // struct for creating lanes struct Lane real array CoordX[MAXWAYPOINTS] real array CoordY[MAXWAYPOINTS] integer MaxCoords static method create takes real StartX, real StartY returns Lane local Lane data = Lane.allocate() set data.MaxCoords = 1 set data.CoordX[0] = StartX set data.CoordY[0] = StartY return data endmethod method AddCoord takes real X, real Y returns nothing if( this.MaxCoords > MAXWAYPOINTS ) then call BJDebugMsg( "SpawnMovement - Maximum Waypoints reached!" ) return endif set this.CoordX[ this.MaxCoords ] = X set this.CoordY[ this.MaxCoords ] = Y set this.MaxCoords = this.MaxCoords + 1 endmethod // returns the reversal of a lane // could be useful in aos maps method Reverse takes nothing returns Lane local integer i = this.MaxCoords-1 local Lane rev = Lane.create( 0, 0 ) set rev.MaxCoords = this.MaxCoords loop exitwhen i < 0 set rev.CoordX[this.MaxCoords-1-i] = this.CoordX[i] set rev.CoordY[this.MaxCoords-1-i] = this.CoordY[i] set i = i - 1 endloop return rev endmethod // returns the closest waypoint index to a given mapcoordinate method GetClosestWaypointID takes real X, real Y returns integer local integer i = this.MaxCoords-1 local integer id = i local real dx = GetRectMaxX( bj_mapInitialPlayableArea ) local real dy = 0 local real diff = 0 local real diff2 = dx * dx // store maximum possible maprange loop exitwhen i < 0 set dx = X - this.CoordX[i] set dy = Y - this.CoordY[i] set diff = dx * dx + dy * dy if( diff < diff2 ) then set diff2 = diff set id = i endif set i = i - 1 endloop return id endmethod endstruct // functions for the user // should be self explaning? :) public function RegisterLane takes Lane WhichLane, integer Key returns nothing local integer i = 0 local rect r = null debug local texttag t = null if( WhichLane == 0 ) then call BJDebugMsg( "SpawnMovement - Trying to register a null Lane!" ) return endif call SaveInteger( TABLE, Key, 0, WhichLane ) loop exitwhen i >= WhichLane.MaxCoords if( not IsPointInRegion( REGION, WhichLane.CoordX[i], WhichLane.CoordY[i] ) and i < WhichLane.MaxCoords - 1 ) then set r = Rect( WhichLane.CoordX[i]-EPSILON, WhichLane.CoordY[i]-EPSILON, WhichLane.CoordX[i]+EPSILON, WhichLane.CoordY[i]+EPSILON ) call RegionAddRect( REGION, r ) call RemoveRect( r ) set r = null endif debug set t = CreateTextTag() debug call SetTextTagText( t, "Lane:"+I2S(Key)+" --- X:"+I2S(R2I(WhichLane.CoordX[i]))+" --- Y:"+I2S(R2I(WhichLane.CoordY[i])), 0.03 ) debug call SetTextTagPos( t, WhichLane.CoordX[i], WhichLane.CoordY[i], 30.00 ) debug call SetTextTagPermanent( t, true ) debug call SetTextTagVisibility( t, true ) set i = i + 1 endloop endfunction public function GetLane takes integer Key returns Lane return LoadInteger( TABLE, Key, 0 ) endfunction public function RegisterUnit takes unit WhichUnit, integer LaneKey returns nothing local Lane l = 0 local integer uid = 0 if( WhichUnit == null ) then call BJDebugMsg( "SpawnMovement - Trying to register a null unit!" ) return endif if( IsUnitInGroup( WhichUnit, REGISTEREDUNITS ) ) then call BJDebugMsg( "SpawnMovement - Trying to register a unit which is already registered!" ) endif set l = GetLane( LaneKey ) if( l == 0 ) then call BJDebugMsg( "SpawnMovement - Trying to register a unit for a wrong lane!" ) return endif set uid = GetHandleId( WhichUnit ) call SaveInteger( TABLE, uid, INDEXLANE, l ) call SaveInteger( TABLE, uid, INDEXLANEKEY, LaneKey ) call SaveReal( TABLE, uid, INDEXWAYPOINTX, l.CoordX[0] ) call SaveReal( TABLE, uid, INDEXWAYPOINTY, l.CoordY[0] ) call SaveInteger( TABLE, uid, INDEXWAYPOINTID, 0 ) call GroupAddUnit( REGISTEREDUNITS, WhichUnit ) call TriggerRegisterUnitEvent( TRIG, WhichUnit, EVENT_UNIT_ISSUED_ORDER ) call TriggerRegisterUnitEvent( TRIG, WhichUnit, EVENT_UNIT_ISSUED_POINT_ORDER ) call IssuePointOrder( WhichUnit, "attack", l.CoordX[0], l.CoordY[0] ) endfunction public function DeregisterUnit takes unit WhichUnit returns nothing if( WhichUnit != null ) then call GroupRemoveUnit( REGISTEREDUNITS, WhichUnit ) endif endfunction public function GetUnitLane takes unit WhichUnit returns integer if( WhichUnit == null ) then call BJDebugMsg( "SpawnMovement - Trying to get the Lane of a null unit!" ) return 0 endif return LoadInteger( TABLE, GetHandleId( WhichUnit ), INDEXLANE ) endfunction public function GetUnitLaneKey takes unit WhichUnit returns integer if( WhichUnit == null ) then call BJDebugMsg( "SpawnMovement - Trying to get the LaneKey of a null unit!" ) return 0 endif return LoadInteger( TABLE, GetHandleId( WhichUnit ), INDEXLANEKEY ) endfunction public function GetUnitWaypointIndex takes unit WhichUnit returns integer if( WhichUnit == null ) then call BJDebugMsg( "SpawnMovement - Trying to get the Waypoint index of a null unit!" ) return 0 endif return LoadInteger( TABLE, GetHandleId( WhichUnit ), INDEXWAYPOINTID ) endfunction public function GetUnitWaypointX takes unit WhichUnit returns real if( WhichUnit == null ) then call BJDebugMsg( "SpawnMovement - Trying to get the X coordination of a null unit!" ) return 0 endif return LoadReal( TABLE, GetHandleId( WhichUnit ), INDEXWAYPOINTX ) endfunction public function GetUnitWaypointY takes unit WhichUnit returns real if( WhichUnit == null ) then call BJDebugMsg( "SpawnMovement - Trying to get the Y coordination of a null unit!" ) return 0 endif return LoadReal( TABLE, GetHandleId( WhichUnit ), INDEXWAYPOINTY ) endfunction public function SetUnitWaypointIndex takes unit WhichUnit, integer NewIndex returns nothing local Lane l = 0 local integer uid = 0 if( WhichUnit == null ) then call BJDebugMsg( "SpawnMovement - Trying to set the Waypoint index of a null unit!" ) return endif set l = GetUnitLane( WhichUnit ) if( NewIndex >= l.MaxCoords or NewIndex < 0 ) then call BJDebugMsg( "SpawnMovement - Setting Waypoint index out of bounds!" ) return endif set uid = GetHandleId( WhichUnit ) call SaveInteger( TABLE, uid, INDEXWAYPOINTID, NewIndex ) call SaveReal( TABLE, uid, INDEXWAYPOINTX, l.CoordX[NewIndex] ) call SaveReal( TABLE, uid, INDEXWAYPOINTY, l.CoordY[NewIndex] ) call IssuePointOrder( WhichUnit, "attack", l.CoordX[NewIndex], l.CoordY[NewIndex] ) endfunction // trigger fires, when registered units are given orders // if the order is a "flee" order, reorder the unit // to move to the last waypoint // // if the unit is already in range of the waypoint // set the next waypoint private function Trig_Conditions takes nothing returns boolean local integer OID = GetIssuedOrderId() local integer wid = 0 local integer uid = 0 local unit u = null local real x = 0 local real y = 0 local Lane l = 0 if( OID == 851976 or OID == 851973 or OID == 851974 or OID == 851972 or OID == 851993 or OID == 0 ) then set u = GetOrderedUnit() set x = GetUnitWaypointX( u ) set y = GetUnitWaypointY( u ) set l = GetUnitLane( u ) set wid = GetUnitWaypointIndex( u ) set uid = GetHandleId( u ) if( IsUnitInRangeXY( u, x, y, EPSILON ) and wid+1 < l.MaxCoords ) then set wid = wid + 1 call SaveReal( TABLE, uid, INDEXWAYPOINTX, l.CoordX[wid] ) call SaveReal( TABLE, uid, INDEXWAYPOINTY, l.CoordY[wid] ) call SaveInteger( TABLE, uid, INDEXWAYPOINTID, wid ) endif call IssuePointOrder( u, "attack", l.CoordX[wid], l.CoordY[wid] ) set u = null endif return false endfunction // trigger fires, when registered units come within range // of a waypoint dummy unit -> set next waypoint private function Trig2_Conditions takes nothing returns boolean local unit u = GetTriggerUnit() local integer wid = GetUnitWaypointIndex( u ) local integer uid = GetHandleId( u ) local real x = GetUnitWaypointX( u ) local real y = GetUnitWaypointY( u ) local Lane l = GetUnitLane( u ) if( IsUnitInRangeXY( u, x, y, EPSILON ) and wid+1 < l.MaxCoords ) then set wid = wid + 1 call SaveReal( TABLE, uid, INDEXWAYPOINTX, l.CoordX[wid] ) call SaveReal( TABLE, uid, INDEXWAYPOINTY, l.CoordY[wid] ) call SaveInteger( TABLE, uid, INDEXWAYPOINTID, wid ) endif call IssuePointOrder( u, "attack", l.CoordX[wid], l.CoordY[wid] ) set u = null return false endfunction // functions for refreshing the dynamic trigger private function group_callback takes nothing returns nothing call TriggerRegisterUnitEvent( TRIG, GetEnumUnit(), EVENT_UNIT_ISSUED_ORDER ) call TriggerRegisterUnitEvent( TRIG, GetEnumUnit(), EVENT_UNIT_ISSUED_POINT_ORDER ) endfunction private function RefreshTrigger takes nothing returns nothing call TriggerClearConditions( TRIG ) call DestroyTrigger( TRIG ) set TRIG = CreateTrigger() call TriggerAddCondition( TRIG, Condition( function Trig_Conditions ) ) call ForGroup( REGISTEREDUNITS, function group_callback ) endfunction // endfunctions private function EnterFilter takes nothing returns boolean return IsUnitInGroup( GetFilterUnit(), REGISTEREDUNITS ) endfunction // init function to initialize the globals // // also starts the refreshing of the dynamic trigger // if the refreshinterval is greater zero private function init takes nothing returns nothing local Lane l = 0 local Lane l2 = 0 set TABLE = InitHashtable() set TIM = CreateTimer() set REGISTEREDUNITS = CreateGroup() set REGION = CreateRegion() set TRIG = CreateTrigger() set TRIG2 = CreateTrigger() set ENTERFILTER = Condition( function EnterFilter ) call TriggerAddCondition( TRIG, Condition( function Trig_Conditions ) ) call TriggerAddCondition( TRIG2, Condition( function Trig2_Conditions ) ) if( REFRESHINTERVAL > 0 ) then call TimerStart( TIM, REFRESHINTERVAL, true, function RefreshTrigger ) endif // init toplane set l = l.create( -6400, 0 ) call l.AddCoord( -5000, 1100 ) call l.AddCoord( -2000, 4500 ) call l.AddCoord( 0, 4400 ) call l.AddCoord( 2300, 4300 ) call l.AddCoord( 3700, 3700 ) call l.AddCoord( 5200, 1700 ) call l.AddCoord( 6400, 0 ) set l2 = l.Reverse() call RegisterLane( l, TOPLANEWEST ) call RegisterLane( l2, TOPLANEEAST ) // init midlane set l = l.create( -6400, 0 ) call l.AddCoord( -4400, 0 ) call l.AddCoord( -3300, 0 ) call l.AddCoord( -2600, 1800 ) call l.AddCoord( -1800, 1800 ) call l.AddCoord( -1800, 0 ) call l.AddCoord( 1800, 0 ) call l.AddCoord( 2000, -1700 ) call l.AddCoord( 2700, -1700 ) call l.AddCoord( 3400, 0 ) call l.AddCoord( 4500, 0 ) call l.AddCoord( 6400, 0 ) set l2 = l.Reverse() call RegisterLane( l, MIDDLELANEWEST ) call RegisterLane( l2, MIDDLELANEEAST ) // init botlane set l = l.create( -6400, 0 ) call l.AddCoord( -5200, -1500 ) call l.AddCoord( -1700, -4900 ) call l.AddCoord( -700, -4800 ) call l.AddCoord( 2900, -4500 ) call l.AddCoord( 5400, -1400 ) call l.AddCoord( 6400, 0 ) set l2 = l.Reverse() call RegisterLane( l, BOTTOMLANEWEST ) call RegisterLane( l2, BOTTOMLANEEAST ) // register enter region event to TRIG2 call TriggerRegisterEnterRegion( TRIG2, REGION, ENTERFILTER ) endfunction endlibrary hoping for your feedback Quill example for usage Code:
local unit u = CreateUnit( Player(0), 'hfoo', 0, 0, 0 ) call RegisterUnit( u, SpawnMovement_TOPLANEWEST ) |
| 09-16-2009, 11:30 AM | #2 |
Funny, I had the same idea 2 weeks before: Anachrons AoS Move System. |
| 09-16-2009, 01:39 PM | #3 |
It's not the right forum. Script forum is for resource submissions, you should post in the "Triggers & Scripts" forum. I have moved it there. Furthermore, use [jass][/jass] tags for your code. |
| 09-16-2009, 01:52 PM | #4 |
Its funny, our both systems are quite the same somehow, however, I use repeating checks to check whether an unit is on the move, but you only check with commands, which is bugged and can be disabled with my system. |
| 09-16-2009, 07:51 PM | #5 |
JASS:set diff = dx*dx + dy*dy if diff < diff2 then set diff2 = diff endif Comparison of squares will yield the same result in the if condition. |
| 09-20-2009, 06:22 PM | #6 |
fixed a few things and added some stuff. i now use invisible permanent immolation dummies instead of rect entering or periodic checking (because the administration of regions was very ugly). the advantage of immo is, that it damages units when they come within range so you maybe can set the hero/unitduration in the ability to a higher value than 2 imo. i first thought of tornado slow aura, but this would add a buff to units and i think removing the buff per trigger will not disable the aura to add the buff a few seconds later when the unit is still in range? if so, i could remove immo and use tornado slow aura to avoid the 0.01 damage taken every immolation period. |
| 09-21-2009, 03:50 PM | #7 |
I still think my system is better, because its giving you more functionality and less rules to follow. Anachrons Move System. What I am missing at your system is the ability to remove the automatic reordering, your system is simply based of that function, which isn't well at all. |
| 09-23-2009, 06:13 PM | #8 | |
*update* i removed the thing with the perma immolation. dunno why i thought, this was a good way? :) however - included now an automatic rect generation at the given waypointcoordinate, if there isn't already a rect. so you now have both: order and entering trigger Quote:
2) if any1 wants to disabled the reordering (i don't know any reason why?) he can simple comment the triggeraddcondition thing in the init. shouldn't be a problem edit: fixed a stupid mistake of mine in version 0.3, where i added the enterregion event für each registering unit :/ also included an own filter to exclude non-registered entering units. also replaced the stop order in registerunit/setunitwaypointindex with an attack order. |
