- Joined
- Nov 23, 2008
- Messages
- 512
hey may some of you have seen my missile system (Missile Sys) but as trigger hapy said the unit collision is very unefficient...
now i have reworked it and want to hear if it's now better.
now i have reworked it and want to hear if it's now better.
JASS:
library UnitCollision initializer Init
globals
private hashtable UC_Hash
private constant integer Sphere = 1
private constant integer Cylinder = 2
private real MaxCollSize = 0.
private constant integer DummyId = 'h000' // your private dummy unit
endglobals
function GetUnitCollSizeSphere takes unit u returns real
return LoadReal( UC_Hash, GetUnitTypeId(u), 1)
endfunction
function GetUnitRadCylinder takes unit u returns real
return LoadReal( UC_Hash, GetUnitTypeId(u), 1)
endfunction
function GetUnitHeightCylinder takes unit u returns real
return LoadReal( UC_Hash, GetUnitTypeId(u), 2)
endfunction
function GetUnitType takes unit u returns integer
return LoadInteger(UC_Hash,GetUnitTypeId(u),0)
endfunction
function AddUnitCollisionSphere takes integer uID, real rad returns nothing
call SaveInteger(UC_Hash, uID, 0, Sphere)
call SaveReal(UC_Hash, uID, 1, rad)
if rad >= MaxCollSize then
set MaxCollSize =rad+.5
endif
endfunction
function AddUnitCollisionCylinder takes integer uID, real rad, real height returns nothing
local real x = SquareRoot((rad*rad)+(height*height))
call SaveInteger(UC_Hash, uID, 0, Cylinder)
call SaveReal(UC_Hash, uID, 1, rad)
call SaveReal(UC_Hash, uID, 2, height)
if x >= MaxCollSize then
set MaxCollSize = x+.5
endif
endfunction
function CheckForCollision takes real x, real y, real z, real size, player p returns boolean
local group g = CreateGroup()
local unit u = null
local real array r
local boolean b = false
local location p1
local location p2
call GroupEnumUnitsInRange( g, x, y, MaxCollSize, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null or b == true
if GetUnitTypeId(u)!= DummyId and GetUnitState(u,UNIT_STATE_LIFE) > 0.405 then
if GetUnitType(u) == Sphere then
set r[0] = x - GetUnitX(u)
set r[1] = y - GetUnitY(u)
set r[2] = SquareRoot(r[0] * r[0] + r[1] * r[1])
set p1 = GetUnitLoc(u)
set p2 = Location(x,y)
set r[3] = (GetUnitFlyHeight(u)+GetLocationZ(p1))-(z+GetLocationZ(p2))
set r[4] = SquareRoot(r[2] * r[2] + r[3] * r[3])
set b = ((r[4] <= GetUnitCollSizeSphere(u)+size) and GetOwningPlayer(u) != p)
call RemoveLocation(p1)
call RemoveLocation(p2)
elseif GetUnitType(u) == Cylinder then
set r[0] = x - GetUnitX(u)
set r[1] = y - GetUnitY(u)
set r[2] = SquareRoot(r[0] * r[0] + r[1] * r[1])
set p1 = GetUnitLoc(u)
set p2 = Location(x,y)
set r[3] = GetUnitFlyHeight(u)
set b = (r[2] <= GetUnitRadCylinder(u)+size and z+GetLocationZ(p2) > r[3]-size+GetLocationZ(p1) and z+GetLocationZ(p2) < r[3]+GetUnitHeightCylinder(u)+size+GetLocationZ(p1) and GetOwningPlayer(u) != p)
call RemoveLocation(p1)
call RemoveLocation(p2)
endif
endif
call GroupRemoveUnit(g,u)
set u = null
endloop
call DestroyGroup(g)
set g = null
set u = null
return b
endfunction
// extra function to damage units in range with the unit collision system
// (simpel edit from the check for collision function)
function DamageUnitInRange takes real x, real y, real z, real damage, real rad, unit damagedealer returns nothing
local group g = CreateGroup()
local unit u = null
local real array r
local location p1
local location p2
call GroupEnumUnitsInRange( g, x, y, MaxCollSize, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if GetUnitTypeId(u)!= DummyId and GetUnitState(u,UNIT_STATE_LIFE) > 0.405 then
if GetUnitType(u) == Sphere then
set r[0] = x - GetUnitX(u)
set r[1] = y - GetUnitY(u)
set r[2] = SquareRoot(r[0] * r[0] + r[1] * r[1])
set p1 = GetUnitLoc(u)
set p2 = Location(x,y)
set r[3] = (GetUnitFlyHeight(u)+GetLocationZ(p1))-(z+GetLocationZ(p2))
set r[4] = SquareRoot(r[2] * r[2] + r[3] * r[3])
if (r[4] <= GetUnitCollSizeSphere(u)+rad) and GetOwningPlayer(u) != GetOwningPlayer(damagedealer) then
call UnitDamageTarget(damagedealer, u, damage, true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
endif
call RemoveLocation(p1)
call RemoveLocation(p2)
elseif GetUnitType(u) == Cylinder then
set r[0] = x - GetUnitX(u)
set r[1] = y - GetUnitY(u)
set r[2] = SquareRoot(r[0] * r[0] + r[1] * r[1])
set p1 = GetUnitLoc(u)
set p2 = Location(x,y)
set r[3] = GetUnitFlyHeight(u)
if r[2] <= GetUnitRadCylinder(u)+rad and z+GetLocationZ(p2) > r[3]-rad+GetLocationZ(p1) and z+GetLocationZ(p2) < r[3]+GetUnitHeightCylinder(u)+rad+GetLocationZ(p1) and GetOwningPlayer(u) != GetOwningPlayer(damagedealer) then
call UnitDamageTarget(damagedealer, u, damage, true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
endif
call RemoveLocation(p1)
call RemoveLocation(p2)
endif
endif
call GroupRemoveUnit(g,u)
set u = null
endloop
call DestroyGroup(g)
set g = null
set u = null
endfunction
private function Init takes nothing returns nothing
set UC_Hash = InitHashtable()
call AddUnitCollisionSphere('h004',100)
call AddUnitCollisionSphere('h001',30)
call AddUnitCollisionSphere('h005',50)
call AddUnitCollisionSphere('h007',90)
call AddUnitCollisionCylinder('h002',50,45)
call AddUnitCollisionCylinder('h008',45,100)
call AddUnitCollisionCylinder('h006',100,240)
call AddUnitCollisionCylinder('h003',60,280)
call AddUnitCollisionCylinder('h009',12.5,35)
call AddUnitCollisionCylinder('h00A',14,35)
endfunction
endlibrary
JASS:
library UnitCollision initializer Init
globals
//------------------ small Setup part ---------------------
private constant integer Sphere = 1
private constant integer Cylinder = 2
private constant integer Dummy_Id = 'h000' // your private dummy unit
//----------------- end of the settings -------------------
private location Point1 = Location(0,0)
private location Point2 = Location(0,0)
private hashtable UC_Hash
private real Max_CollSize = 0.
private group Picked_Group = CreateGroup()
private boolean Collision_Check = false
//---------------- stored things for the Unit Collision --------------
private real Stored_X = 0.
private real Stored_Y = 0.
private real Stored_Z = 0.
private real Stored_Size = 0.
private player Stored_Player = null
// ------------ stored things for the Damage Units in range function ---------
private real Stored_Damage = 0.
private unit Stored_Damagedealer = null
endglobals
function GetUnitCollSizeSphere takes unit u returns real
return LoadReal( UC_Hash, GetUnitTypeId(u), 1)
endfunction
function GetUnitRadCylinder takes unit u returns real
return LoadReal( UC_Hash, GetUnitTypeId(u), 1)
endfunction
function GetUnitHeightCylinder takes unit u returns real
return LoadReal( UC_Hash, GetUnitTypeId(u), 2)
endfunction
function GetUnitType takes unit u returns integer
return LoadInteger(UC_Hash,GetUnitTypeId(u),0)
endfunction
function AddUnitCollisionSphere takes integer uID, real rad returns nothing
call SaveInteger(UC_Hash, uID, 0, Sphere)
call SaveReal(UC_Hash, uID, 1, rad)
//-------------------------------------
if rad >= Max_CollSize then
set Max_CollSize =rad+.5
endif
endfunction
function AddUnitCollisionCylinder takes integer uID, real rad, real height returns nothing
local real x = SquareRoot((rad*rad)+(height*height))
//-------------------------------------
call SaveInteger(UC_Hash, uID, 0, Cylinder)
call SaveReal(UC_Hash, uID, 1, rad)
call SaveReal(UC_Hash, uID, 2, height)
//-------------------------------------
if x >= Max_CollSize then
set Max_CollSize = x+.5
endif
endfunction
function CheckForCollisionAction takes nothing returns boolean
local real array r
local unit u = GetFilterUnit()
call MoveLocation(Point2,Stored_X,Stored_Y)
call MoveLocation(Point1,GetUnitX(u),GetUnitY(u))
//-------------------------------------------------------------------
if Collision_Check == false then
if GetUnitTypeId(u)!= Dummy_Id and GetWidgetLife(u) > 0.405 then
if GetUnitType(u) == Sphere then
//--------------------------------------
set r[0] = Stored_X - GetUnitX(u)
set r[1] = Stored_Y - GetUnitY(u)
set r[2] = SquareRoot(r[0] * r[0] + r[1] * r[1])
//--------------------------------------
set r[3] = (GetUnitFlyHeight(u)+GetLocationZ(Point1))-(Stored_Z+GetLocationZ(Point2))
set r[4] = SquareRoot(r[2] * r[2] + r[3] * r[3])
//--------------------------------------
set Collision_Check = ((r[4] <= GetUnitCollSizeSphere(u)+Stored_Size) and GetOwningPlayer(u) != Stored_Player)
//--------------------------------------
elseif GetUnitType(u) == Cylinder then
//--------------------------------------
set r[0] = Stored_X - GetUnitX(u)
set r[1] = Stored_Y - GetUnitY(u)
set r[2] = SquareRoot(r[0] * r[0] + r[1] * r[1])
//--------------------------------------
set r[3] = GetUnitFlyHeight(u)
//--------------------------------------
set Collision_Check = (r[2] <= GetUnitRadCylinder(u)+Stored_Size and Stored_Z+GetLocationZ(Point2) > r[3]-Stored_Size+GetLocationZ(Point1) and Stored_Z+GetLocationZ(Point2) < r[3]+GetUnitHeightCylinder(u)+Stored_Size+GetLocationZ(Point1) and GetOwningPlayer(u) != Stored_Player)
//--------------------------------------
endif
endif
endif
//--------------------------------------
set u = null
return false
endfunction
function CheckForCollision takes real x, real y, real z, real size, player p returns boolean
set Stored_Player = p
set Stored_X = x
set Stored_Y = y
set Stored_Z = z
set Stored_Size = size
//-----------------------------------------------------------------
call GroupEnumUnitsInRange(Picked_Group, x, y, Max_CollSize, Filter(function CheckForCollisionAction))
//-----------------------------------------------------------------
set Picked_Group = null
//-----------------------------------------------------------------
return Collision_Check
endfunction
// |==========================================================================|
// |--------------------------------------------------------------------------|
// |==========================================================================|
function DamageUnitsInRangeAction takes nothing returns boolean
local unit u = GetFilterUnit()
local real array r
call MoveLocation(Point2,Stored_X,Stored_Y)
call MoveLocation(Point1,GetUnitX(u),GetUnitY(u))
//-------------------------------------------------------------------
if GetUnitTypeId(u)!= Dummy_Id and GetWidgetLife(u) > 0.405 then
if GetUnitType(u) == Sphere then
//------------------------------------------------
set r[0] = Stored_X - GetUnitX(u)
set r[1] = Stored_Y - GetUnitY(u)
set r[2] = SquareRoot(r[0] * r[0] + r[1] * r[1])
//------------------------------------------------
set r[3] = (GetUnitFlyHeight(u)+GetLocationZ(Point1))-(Stored_Z+GetLocationZ(Point2))
set r[4] = SquareRoot(r[2] * r[2] + r[3] * r[3])
//---------------------------------------------------------------------------------------------------------------------------
if (r[4] <= GetUnitCollSizeSphere(u)+Stored_Size) and GetOwningPlayer(u) != GetOwningPlayer(Stored_Damagedealer) then
call UnitDamageTarget(Stored_Damagedealer, u, Stored_Damage, true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
endif
//---------------------------------------------------------------------------------------------------------------------------
elseif GetUnitType(u) == Cylinder then
//----------------------------------------------------
set r[0] = Stored_X - GetUnitX(u)
set r[1] = Stored_Y - GetUnitY(u)
set r[2] = SquareRoot(r[0] * r[0] + r[1] * r[1])
//------------------------------------------------
set r[3] = GetUnitFlyHeight(u)
//----------------------------------------------------------------------------------------------------------------------------------------------------------------
if r[2] <= GetUnitRadCylinder(u)+Stored_Size and Stored_Z+GetLocationZ(Point2) > r[3]-Stored_Size+GetLocationZ(Point1) and Stored_Z+GetLocationZ(Point2) < r[3]+GetUnitHeightCylinder(u)+Stored_Size+GetLocationZ(Point1) and GetOwningPlayer(u) != GetOwningPlayer(Stored_Damagedealer) then
call UnitDamageTarget(Stored_Damagedealer, u, Stored_Damage, true, false, ATTACK_TYPE_MELEE, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
endif
//----------------------------------------------------------------------------------------------------------------------------------------------------------------
endif
endif
set u = null
return false
endfunction
function DamageUnitsInRange takes real x, real y, real z, real damage, real rad, unit damagedealer returns nothing
set Stored_Damagedealer = damagedealer
set Stored_Y = y
set Stored_Z = z
set Stored_Size = rad
set Stored_Damage = damage
//-------------------------------------------------------------------
call GroupEnumUnitsInRange(Picked_Group, x, y, Max_CollSize, Filter(function DamageUnitsInRangeAction))
//-------------------------------------------------------------------
set Picked_Group = null
set Stored_Damagedealer = null
endfunction
private function Init takes nothing returns nothing
set UC_Hash = InitHashtable()
//---------------------------------------------------------
// This is a good place to add a collision to a unit type
//---------------------------------------------------------
call AddUnitCollisionSphere('h004',100)
call AddUnitCollisionSphere('h001',30)
call AddUnitCollisionSphere('h005',50)
call AddUnitCollisionSphere('h007',90)
call AddUnitCollisionCylinder('h002',50,45)
call AddUnitCollisionCylinder('h008',45,100)
call AddUnitCollisionCylinder('h006',100,240)
call AddUnitCollisionCylinder('h003',60,280)
call AddUnitCollisionCylinder('h009',12.5,35)
call AddUnitCollisionCylinder('h00A',14,35)
endfunction
endlibrary
Last edited by a moderator: