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

Drone System

This is my MUI Drone System, requested by vercas.

Basicly it creates a unit and links it to another unit.

The "drone" will always be in the same distance and angle to the parent (relative to the parents facing) or even rotate around its parent.

Useful for auto-firing weapons (unit walks but weapons can still fire on enemies)
needed in for example space maps:
use this system to add weapons to ships. the weapons will fire even if the ship moves.

Try the testmap to see a bit of the power of this system!

ATTENTION:
To get this working you need:
- Jass knowledge
- JNGP
- LinkedListModule library (included)
- Table library (included)

v.2.0: Major code changes, use of hashtables, 5 new functions and a improved test map.
v.3.0: Updated the whole code to JESP vJass standart


JASS:
library DroneSystem requires Table, LinkedListModule /*
//============================================================================== 
//==========================   Drone System   ================================== 
//============================================================================== 
 This system allows you to add drones to a unit which follow/surround it.
 Examples: Space maps: Use this system to add weapons to ships. The weapons will fire even if the ship moves!
           Pokemon maps: Pikachu will always follow the trainer ;)                         

  ~~ Usage ~~

To create a new, static drone use
        call droneList[yourUnit].add( DroneRawcode, DistanceToTarget, AngleToTarget, IsDroneAttackable) returns drone
                                         integer          real             real             boolean
                                         
To create a new rotating drone use
        call droneList[yourUnit].addEx( DroneRawcode, DistanceToTarget, InitialAngleToTarget, AnglePerSecond, IsDroneAttackable) returns drone
                                          integer         real                  real              real            boolean
                                          
To clear all drones of a parent use
        call droneList[yourUnit].destroy()
                              
                              
To remove a specific drone use
        call drone[droneUnit].destroy()
        
You can modify the following values of a drone:
        set drone[droneUnit].angle = newAngle   <- the angle relative to the parents facing
        set drone[droneUnit].distance = newDistance   <- the distance to the parent
        set drone[droneUnit].anglePerSecond = new   <- the angle the rotating drone travels per second


*/        
// Setup Part:

    globals
        private constant real TIMER_INTERVAL = 0.01
    endglobals
    
/*  How to implement this system in your map??
       just copy and paste this trigger into your map
*/
//============================================================================== 
//==========================   System Code  ==================================== 
//============================================================================== 

    globals
        private Table table
    endglobals

    struct drone extends array
        readonly unit unit
        real distance
        private real a
        private real s
        implement LinkedList
        
        static method operator [] takes unit u returns drone
            return table[GetHandleId(u)]
        endmethod
        
        method operator angle= takes real v returns nothing
            set .a = angle * bj_DEGTORAD
        endmethod
        method operator angle takes nothing returns real
            return .a
        endmethod
        
        method operator anglePerSecond= takes real v returns nothing
            set .s = v * TIMER_INTERVAL * bj_DEGTORAD
        endmethod
        method operator anglePerSecond takes nothing returns real
            return .s * bj_RADTODEG / TIMER_INTERVAL
        endmethod
        
        method destroy takes nothing returns nothing
            call table.remove(GetHandleId(.unit))
            call .removeNode()
            call .deallocate()
        endmethod
        
        method update takes unit parent returns nothing
            if IsUnitType(.unit, UNIT_TYPE_DEAD) or GetUnitTypeId(.unit) == 0 then
                call .destroy()
            else
                set .a = .a + .s
                call SetUnitX(.unit, GetUnitX(parent) + .distance * Cos(GetUnitFacing(parent) * bj_DEGTORAD + .a))
                call SetUnitY(.unit, GetUnitY(parent) + .distance * Sin(GetUnitFacing(parent) * bj_DEGTORAD + .a))
                if GetUnitCurrentOrder(.unit) == OrderId("move") then
                    call IssueImmediateOrder(.unit, "stop")
                endif
            endif
        endmethod
        
        method add takes unit u, real d, real a, real s returns drone
            local thistype new = .allocate()
            set new.unit = u
            set new.distance = d
            set new.a = a
            set new.s = s
            call SetUnitPathing(u, false)
            set table[GetHandleId(u)] = new
            call .insertNode(new)
            return new
        endmethod
    endstruct
    
    struct droneList extends array
        private static timer tim
        
        private drone list
        readonly unit parent
        
        implement LinkedList
        
        static method operator [] takes unit u returns droneList
            local droneList this
            if table.has(GetHandleId(u)) then
                set this = table[GetHandleId(u)]
            else
                set this = droneList.allocate()
                set .list = drone.createNode()
                set .parent = u
                set table[GetHandleId(u)] = this
                if .base.next.head then
                    call TimerStart(.tim, TIMER_INTERVAL, true, function thistype.periodic)
                endif
                call .base.insertNode(this)
            endif
            return this
        endmethod
        
        method destroy takes nothing returns nothing
            local drone node = .list.next
            loop
                exitwhen node.head
                call RemoveUnit(node.unit)
                call node.destroy()
                set node = node.next
            endloop
            call table.remove(GetHandleId(.parent))
            call .list.removeNode()
            call .list.deallocate()
            call .removeNode()
            call .deallocate()
        endmethod
        
        private static method periodic takes nothing returns nothing
            local droneList this = .base.next
            local drone node
            local real x
            local real y
            local real f
            local boolean dead
            loop
                exitwhen .head
                set dead = IsUnitType(.parent, UNIT_TYPE_DEAD) or GetUnitTypeId(.parent) == 0
                if not dead then
                    set node = .list.next
                    loop
                        exitwhen node.head
                        call node.update(.parent)
                        set node = node.next
                    endloop
                endif
                if dead or .list.next.head then
                    call .destroy()
                endif
                set this = .next
            endloop
            if .base.next.head then
                call PauseTimer(.tim)
            endif
        endmethod

        method addEx takes integer droneId, real distance, real angle, real anglePerSecond, boolean attackable returns drone
            local real x = GetUnitX(parent) + distance * Cos((GetUnitFacing(parent) + angle) * bj_DEGTORAD)
            local real y = GetUnitY(parent) + distance * Sin((GetUnitFacing(parent) + angle) * bj_DEGTORAD)
            local drone new = .list.add(CreateUnit(GetOwningPlayer(parent), droneId, x, y, GetUnitFacing(parent)), distance, angle * bj_DEGTORAD, anglePerSecond * TIMER_INTERVAL * bj_DEGTORAD)
            call SetUnitInvulnerable(new.unit, not attackable)
            return new
        endmethod

        method add takes integer droneId, real distance, real angle, boolean attackable returns drone
            return .addEx(droneId, distance, angle, 0, attackable)
        endmethod

        private static method onInit takes nothing returns nothing
            set table = Table.create()
            set .tim = CreateTimer()
        endmethod

    endstruct
endlibrary


//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com

Keywords:
vJass, unit, ward, tower, MUI, MPI, jesp, the, witcher, drone, circle, surround, follow
Contents

Drone System (Map)

Reviews
19:37, 26th Oct 2009 TriggerHappy187: I see no uses for this system, though obviously there are some if this was requested.

Moderator

M

Moderator

19:37, 26th Oct 2009
TriggerHappy187:

I see no uses for this system, though obviously there are some if this was requested.
 
Level 10
Joined
Feb 7, 2005
Messages
409
Hey is there a way to remove all drones attached to the unit? and if not, can you add one? I was also wondering if you could add the option to allow the drones to "orbit" the unit they're attached to, as well as the option to modify the speed of said orbit.

-Teld

4/5 great system yet again Witcher
 
Last edited:
Level 10
Joined
Feb 7, 2005
Messages
409
Very nice witcher, splendid work as always I'd be happy to update my rating to a 5/5 now.

And for those of you who said this system has little use (the moderator) I'll add two examples that I have already used it for:

1. Floating Orb Attachments (the orb floats behind the caster and is a hero dummy unit, this orb gets buffed attack damage dependent on the intelligence of the caster and will hit up to 5 enemies at a time.)

2. Pestering Poison (once cast the poison manifests itself as a shadow imp above the targeted unit, this mischievous imp will attack the target as long as it lingers, but may occasionally switch it's target as it sees fit.)

This system has many uses and potential as long as you think outside the box a little bit, again, great work Witcher.

-Teld
 
Top