- Joined
- Nov 29, 2007
- Messages
- 371
Hello all, thanks for taking the time to read this post.
Myself and a friend are making a map but we have come up with three problems in the base stages of said map:
Here is a link to Exilus5's map: link
This is what we have so far for a missile system:
[EDIT] Missile system has been fixed and replaced
We don't have even a semi-functional shield system however.
A lot of the rest of the game is already planned out and *should* be easy to implement. These two things are, however, the two most important parts and without them the game is essentially unplayable.
Thank you in advance,
DrazharLn
P.S. Playing a few games of Exilus5' excellent Ship War will put what we are trying to do into perspective.
EDIT2: I've finally got round to fixing the code aznricepuff sent me so here it is:
EDIT3: You also need vJASS to run this code.
Myself and a friend are making a map but we have come up with three problems in the base stages of said map:
- How do we make a working shield [like in Ship War by Exilus5]
- How do we make a decent rocket system [FIXED, PM if you want details]
- And third, I'm awful at JASS, so [for the moment at least] am limited to UI
Here is a link to Exilus5's map: link
This is what we have so far for a missile system:
[EDIT] Missile system has been fixed and replaced
We don't have even a semi-functional shield system however.
A lot of the rest of the game is already planned out and *should* be easy to implement. These two things are, however, the two most important parts and without them the game is essentially unplayable.
Thank you in advance,
DrazharLn
P.S. Playing a few games of Exilus5' excellent Ship War will put what we are trying to do into perspective.
EDIT2: I've finally got round to fixing the code aznricepuff sent me so here it is:
JASS:
library lib
//Configuration - do NOT change the names of the variables, only the values
globals
real missiletimeout = 0.04 //how often the function that moves all missiles executes
real shieldtimeout = 0.04 //how often the function that updates all shields' life points executes
real missilearrivaldist = 20.00 //How far away a missile has to be from its target before it detonates
endglobals
//End Configuration
//Distance Functions - made public if for any reason you see fit to use them yourself
public function DistanceBetweenCoords takes real x1, real y1, real x2, real y2 returns real
return SquareRoot( ( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) )
endfunction
public function AngleBetweenCoords takes real x1, real y1, real x2, real y2 returns real
local real angle = ( bj_RADTODEG * Atan2( y2 - y1, x2 - x1 ) )
if ( angle < 0.00 ) then
set angle = angle + 360.00
endif
return angle
endfunction
public function PolarProjectionX takes real x, real distance, real angle returns real
return ( x + distance * Cos( angle * bj_DEGTORAD ) )
endfunction
public function PolarProjectionY takes real y, real distance, real angle returns real
return ( y + distance * Sin( angle * bj_DEGTORAD ) )
endfunction
//End Distance Functions
//Private Data
globals
private timer missiletimer = CreateTimer()
private missiledata array missilearray
private integer missiletotal = 0
private timer shieldtimer = CreateTimer()
private shielddata array shieldarray
private integer shieldtotal = 0
private group missilegroup = CreateGroup()
private group shieldgroup = CreateGroup()
private group array teamshieldgroup
private integer teamtotal = 0
private group tempgroup = CreateGroup()
private real tempdamage
private integer temptotal
endglobals
struct missiledata
unit missile
player owner
unit target
real targetx
real targety
real x
real y
real launchz = 0.00
real speed = 0.00
real arc = 0.00
real collision = 0.00
real damage = 0.00
real aoe = 0.00
real aoedamage = 0.00
real increment = 0.00
boolean destroyplease = false
method onDestroy takes nothing returns nothing
call GroupRemoveUnit( missilegroup, .missile )
endmethod
endstruct
struct shielddata
unit shield
real regen
real regendelay
real regencounter = 0.00
integer teamslot
boolean destroyable = false
boolean noncombat = false
boolean dead = false
boolean destroyplease = false
method onDestroy takes nothing returns nothing
call GroupRemoveUnit( shieldgroup, .shield )
call GroupRemoveUnit( teamshieldgroup[.teamslot], .shield )
endmethod
endstruct
private function Shield_DamageChild takes nothing returns nothing
local unit shield = GetEnumUnit()
local shielddata data = GetUnitUserData( shield )
local real damage = tempdamage
local real life = GetWidgetLife( shield )
if ( data.dead ) then
//shield has collapsed, so do not do damage
return
else
if ( life - damage < 0.405 ) then
//shield has taken too much damage
if ( data.destroyable ) then
//shield is destroyable, so kill the shield
call KillUnit( shield )
set data.destroyplease = true
else
//shield is not destroyable, so we collapse the shield and set it to dead
call SetWidgetLife( shield, 0.500 )
call SetUnitAnimation( shield, "death" )
set data.dead = true
set data.regencounter = data.regendelay
endif
else
//shield has not taken too much damage, so we simply subtract life
call SetWidgetLife( shield, life - damage )
if ( data.noncombat ) then
//shield cannot regen HP in combat, so we set up the regen counter
set data.regencounter = data.regendelay
endif
endif
endif
set shield = null
endfunction
private function Shield_Damage takes unit hurter, unit shield, real damage returns nothing
local integer counter
loop
exitwhen ( counter >= teamtotal )
if ( IsUnitInGroup( shield, teamshieldgroup[counter] ) ) then
set temptotal = CountUnitsInGroup( teamshieldgroup[counter] )
set tempdamage = damage / temptotal
call ForGroup( teamshieldgroup[counter], function Shield_DamageChild )
endif
set counter = counter + 1
endloop
endfunction
private function Shield_Update takes nothing returns nothing
local shielddata data
local real life
local real maxlife
local real regen
local real regencounter
local integer counter = 0
local unit shield
loop
exitwhen ( counter >= shieldtotal )
set data = shieldarray[counter]
if ( data.destroyplease ) then
//struct is slated for destruction, so we take care of that
set shieldarray[counter] = shieldarray[shieldtotal - 1]
set shieldtotal = shieldtotal - 1
call data.destroy()
set counter = counter - 1
else
set life = GetWidgetLife( data.shield )
set maxlife = GetUnitState( data.shield, UNIT_STATE_MAX_LIFE )
if ( regencounter <= 0.00 ) then
if ( data.dead ) then
//shield was previously collapsed, so we "uncollapse" it
set data.dead = false
call SetUnitAnimation( shield, "birth" )
endif
//update shield's HP
if ( ( life + regen * shieldtimeout ) >= maxlife ) then
call SetWidgetLife( data.shield, maxlife )
else
call SetWidgetLife( data.shield, life + regen * shieldtimeout )
endif
else
//shield is waiting to regenerate, countdown the counter
set regencounter = regencounter - shieldtimeout
endif
endif
set counter = counter + 1
endloop
if ( shieldtotal == 0 ) then
call PauseTimer( shieldtimer )
endif
endfunction
private function Missile_Increment takes nothing returns nothing
local missiledata data
local missiledata data2
local unit u
local real targetx
local real targety
local real angle
local real disttotarget
local real timeleft
local real z1
local real z2
local real arc
local integer counter = 0
local unit target
loop
exitwhen ( counter >= missiletotal )
set data = missilearray[counter]
if ( data.destroyplease ) then
//struct is slated for destruction, so we take care of that
set missilearray[counter] = missilearray[missiletotal - 1]
set missiletotal = missiletotal - 1
call data.destroy()
set counter = counter - 1
else
if ( GetWidgetLife( data.target ) < 0.405 ) then
//target is dead, set variable to null; now target coordinates will be locked onto the last coordinates of the target when it was still alive
set data.target = null
else
//target is alive, update target coordinates
set data.targetx = GetUnitX( target )
set data.targety = GetUnitY( target )
endif
set targetx = data.targetx
set targety = data.targety
set angle = AngleBetweenCoords( data.x, data.y, targetx, targety )
set disttotarget = DistanceBetweenCoords( data.x, data.y, targetx, targety )
set timeleft = disttotarget / data.speed
set z1 = GetUnitFlyHeight( data.missile )
set z2 = GetUnitFlyHeight( data.target )
if ( disttotarget <= missilearrivaldist ) then
//missile has reached target, detonate missile and deal damage
call KillUnit( data.missile )
set data.destroyplease = true
if ( IsUnitInGroup( data.target, shieldgroup ) ) then
//target is a shield, so we damage the shield
call Shield_Damage( data.missile, data.target, data.damage )
if ( data.aoe != 0.00 ) then
call UnitDamagePoint( data.missile, 0.00, data.aoe, targetx, targety, data.aoedamage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
endif
else
//target is a normal unit, we deal damage
if ( data.aoe == 0.00 ) then
call UnitDamageTarget( data.missile, data.target, data.damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
else
call UnitDamageTarget( data.missile, data.target, data.damage - data.aoedamage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
call UnitDamagePoint( data.missile, 0.00, data.aoe, targetx, targety, data.aoedamage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
endif
endif
else
if ( data.collision != 0.00 ) then
//missile has collision, check to see if missile has "collided"
call GroupEnumUnitsInRange( tempgroup, data.x, data.y, data.collision, null )
loop
set u = FirstOfGroup( tempgroup )
exitwhen ( u == null )
if ( IsUnitEnemy( u, data.owner ) ) then
if ( IsUnitInGroup( u, missilegroup ) and RAbsBJ( GetUnitFlyHeight( u ) - z1 ) <= data.collision ) then
//missile has collided, destroy two missiles
call KillUnit( data.missile )
set data.destroyplease = true
call KillUnit( u )
set data2 = GetUnitUserData( u )
set data2.destroyplease = true
endif
endif
endloop
call GroupClear( tempgroup )
else
if ( GetWidgetLife( data.missile ) >= 0.405 ) then
//missile is still alive, move missile toward target
call SetUnitFacing( data.missile, angle )
call SetUnitPosition( data.missile, PolarProjectionX( data.x, data.speed * missiletimeout, angle ), PolarProjectionY( data.y, data.speed * missiletimeout, angle ) )
//adjust missile flying height
call SetUnitFlyHeight( data.missile, z1 + ( ( z2 - z1 + 0.5 * arc * timeleft * timeleft ) / timeleft ) * missiletimeout, 0 )
endif
endif
endif
endif
set counter = counter + 1
endloop
if ( missiletotal == 0 ) then
call PauseTimer( missiletimer )
endif
endfunction
//End Private Data
//Control Functions
function Missile_LaunchTarget takes player owner, integer unitid, real launchx, real launchy, real launchz, real speed, real arc, real collision, unit target, real damage, real aoe, real aoedamage returns unit
local missiledata data = missiledata.create()
local real angle = AngleBetweenCoords( launchx, launchy, GetUnitX( target ), GetUnitY( target ) )
if ( IsUnitEnemy( target, owner ) ) then
set data = missiledata.create()
set data.missile = CreateUnit( owner, unitid, launchx, launchy, angle )
if ( launchz != 0.00 ) then
call SetUnitFlyHeight( data.missile, launchz, 0 )
endif
set data.owner = owner
set data.target = target
set data.x = launchx
set data.y = launchy
set data.launchz = launchz
set data.increment = speed
set data.arc = arc * 8000.0
set data.collision = collision
set data.damage = damage
set data.aoe = aoe
set data.aoedamage = aoedamage
call SetUnitUserData( data.missile, data )
if ( missiletotal == 0 ) then
call TimerStart( missiletimer, missiletimeout, true, function Missile_Increment )
endif
set missilearray[missiletotal] = data
set missiletotal = missiletotal + 1
return data.missile
endif
return null
endfunction
function Missile_Modify takes unit missile, real collision, real damage, real aoe, real aoedamage returns boolean
local missiledata data = GetUnitUserData( missile )
if ( IsUnitInGroup( missile, missilegroup ) == false ) then
return false
endif
set data.collision = collision
set data.damage = damage
set data.aoe = aoe
set data.aoedamage = aoedamage
return true
endfunction
function Missile_Destroy takes unit missile returns boolean
local missiledata data = GetUnitUserData( missile )
if ( IsUnitInGroup( missile, missilegroup ) == false ) then
return false
endif
call KillUnit( missile )
set data.destroyplease = true
return ( GetWidgetLife( missile ) < 0.405 )
endfunction
function Shield_Create takes player owner, integer unitid, integer teamslot, real x, real y, real facing, real regen, real regendelay, boolean noncombat, boolean destroyable returns unit
local shielddata data
if ( teamshieldgroup[teamslot] == null ) then
return null
endif
set data = shielddata.create()
set data.shield = CreateUnit( owner, unitid, x, y, facing )
set data.regen = regen
set data.regendelay = regendelay
set data.teamslot = teamslot
set data.noncombat = noncombat
set data.destroyable = destroyable
call SetUnitUserData( data.shield, data )
call GroupAddUnit( shieldgroup, data.shield )
call GroupAddUnit( teamshieldgroup[teamslot], data.shield )
if ( shieldtotal == 0 ) then
call TimerStart( shieldtimer, shieldtimeout, true, function Shield_Update )
endif
set shieldarray[shieldtotal] = data
set shieldtotal = shieldtotal + 1
return data.shield
endfunction
function Shield_Modify takes unit shield, real regen, real regendelay, boolean noncombat, boolean destroyable returns boolean
local shielddata data = GetUnitUserData( shield )
if ( IsUnitInGroup( shield, shieldgroup ) == false ) then
return false
endif
set data.regen = regen
set data.regendelay = regendelay
set data.noncombat = noncombat
set data.destroyable = destroyable
return true
endfunction
function Shield_ModifyState takes unit shield, boolean dead returns boolean
local shielddata data = GetUnitUserData( shield )
if ( IsUnitInGroup( shield, shieldgroup ) == false ) then
return false
endif
set data.dead = dead
return ( data.dead == dead )
endfunction
function Shield_TeamCreate takes nothing returns integer
set teamshieldgroup[teamtotal] = CreateGroup()
set teamtotal = teamtotal + 1
return ( teamtotal - 1 )
endfunction
function Shield_TeamDestroy takes integer teamslot returns boolean
if ( teamshieldgroup[teamslot] == null ) then
return false
endif
call DestroyGroup( teamshieldgroup[teamslot] )
set teamshieldgroup[teamslot] = teamshieldgroup[teamtotal - 1]
set teamshieldgroup[teamtotal - 1] = null
set teamtotal = teamtotal - 1
return true
endfunction
//End Control Functions
endlibrary
EDIT3: You also need vJASS to run this code.
Last edited: