library Objects requires UnitZ, InstanceIterator, Vector, Boundary, UnitCollision, ObjectInit, LinkedList
struct Object //Treated as cylinders
static thistype dis
real radius
real height
real mass
Vector velocity
real lastX
real lastY
real lastZ
real movementX
real movementY
boolean moving
/*static method EnumObjectsInRange takes real x, real y, real radius, code c returns nothing
endmethod*/
implement ObjectList
static method createFilter takes unit u returns boolean
return IsUnitType(u, UNIT_TYPE_OBJECT)
endmethod
method onCreate takes nothing returns nothing
set radius = GetUnitCollisionSize(me)
set height = GetUnitHeight(me)
set mass = GetUnitMass(me)
set velocity = Vector.create(0.00, 0.00, 0.00)
call listAdd()
endmethod
method onDestroy takes nothing returns nothing
call stop32()
call velocity.destroy()
call listRemove()
endmethod
implement AutoCreate
implement AutoDestroy
static method collision takes nothing returns boolean
local thistype this = dis
local thistype that
local unit f = GetFilterUnit()
local Vector d
local Vector v1
local Vector v2
local Vector v3
local Vector v4
local real l1
local real l2
if f != .me and IsUnitType(f, UNIT_TYPE_OBJECT) and RAbsBJ(GetUnitZ(.me) - GetUnitZ(f)) <= 100.0 then
set d = Vector.create(GetUnitX(f) - GetUnitX(.me), GetUnitY(f) - GetUnitY(.me), GetUnitZ(f) - GetUnitZ(.me))
set that = thistype[f]
if Vector.dotProduct(this.velocity, that.velocity) <= 0.00 then
if Vector.dotProduct(this.velocity, d) <= 0.00 then
set f = null
call d.destroy()
return false
endif
else
if Vector.dotProduct(this.velocity, d) <= 0.00 then
set l1 = this.velocity.getLength()
set l2 = that.velocity.getLength()
else
set l1 = that.velocity.getLength()
set l2 = this.velocity.getLength()
endif
if l1 >= l2 then
set f = null
call d.destroy()
return false
endif
endif
set v1 = Vector.projectionVector(that.velocity, d)
set v2 = Vector.projectionVector(this.velocity, d)
if RAbsBJ(v2.getLength() - sgn(Vector.dotProduct(v1, v2))*v1.getLength()) > PLAYER_BUMP_SFX_THRESHOLD then
call d.setLength(d.getLength()/2)
call Sfx(PLAYER_BUMP_SFX_PATH, GetUnitX(.me) + d.x, GetUnitY(.me) + d.y, GetUnitZ(.me), Atan2(d.y, d.x)*bj_RADTODEG + 180.0, 0.00, 0.7)
endif
set l1 = d.x
set d.x = -d.y
set d.y = l1
set v3 = Vector.projectionVector(this.velocity, d)
set v4 = Vector.projectionVector(that.velocity, d)
call this.velocity.destroy()
call that.velocity.destroy()
set this.velocity = v1
call this.applyVector(v3)
set that.velocity = v2
call that.applyVector(v4)
call d.destroy()
call v3.destroy()
call v4.destroy()
set f = null
endif
return false
endmethod
method iterate32 takes nothing returns nothing
local real z
local Vector v
if ((selection == 3 or selection == 4) and .moving and IsUnitType(.me, UNIT_TYPE_PLAYER)) then
if (.velocity.getLength() < PLAYER_MAX_SLIDE_SPEED) then
set v = Vector.create(PLAYER_SLIDE_SPEED_ICE * Cos(GetUnitFacing(.me) * bj_DEGTORAD), PLAYER_SLIDE_SPEED_ICE * Sin(GetUnitFacing(.me) * bj_DEGTORAD), 0.00)
call .applyVector(v)
call v.destroy()
call GroupEnumUnitsInRange(enumGroup, .movementX, .movementY, POSITION_RADIUS, Filter(function thistype.checkEnd))
endif
endif
if radius > 0.00 then
if GetUnitFlyHeight(me) < 1.00 then
call EnableUnitCollision(me)
if velocity.getLength() > PLAYER_FRICTION_GROUND then
call .velocity.setLength(.velocity.getLength() - PLAYER_FRICTION_GROUND)
else
call SetUnitFlyHeight(.me, 0.00, 0.00)
call .velocity.setLength(0.00)
call .stop32()
return
endif
else
set .velocity.z = .velocity.z - GRAVITY_ACCELERATION
if .velocity.getLength() > PLAYER_FRICTION_AIR then
call .velocity.setLength(.velocity.getLength() - PLAYER_FRICTION_AIR)
else
call .velocity.setLength(0.00)
endif
endif
endif
if RectContainsCoords(bj_mapInitialPlayableArea , GetUnitX(.me) + .velocity.x, GetUnitY(.me) + .velocity.y) then
if GetUnitFlyHeight(.me) < 1.00 then
call SetUnitX(.me, GetUnitX(.me) + .velocity.x)
call SetUnitY(.me, GetUnitY(.me) + .velocity.y)
else
call SetUnitX(.me, .lastX + .velocity.x)
call SetUnitY(.me, .lastY + .velocity.y)
endif
endif
if (not IsPointInRegion(playable, GetUnitX(.me), GetUnitY(.me))) or (not IsTerrainWalkable(GetUnitX(.me), GetUnitY(.me))) then
call SetUnitPosition(.me, GetUnitX(.me), GetUnitY(.me))
endif
set .lastX = GetUnitX(.me)
set .lastY = GetUnitY(.me)
set z = GetUnitZ(.me) + .velocity.z
if z < GetTerrainZ(GetUnitX(.me), GetUnitY(.me)) and .velocity.z < 0.00 then
call SetUnitFlyHeight(.me, 0.00, 0.00)
if IsUnitType(me, UNIT_TYPE_PLAYER) and .velocity.z < -PLAYER_BUMP_SFX_THRESHOLD then
call Sfx(PLAYER_BUMP_SFX_PATH, GetUnitX(.me), GetUnitY(.me), 0.00, 0.00, 90, 0.7)
endif
set .velocity.z = -.velocity.z
if radius > 0.00 then
set .velocity.z = .velocity.z - PLAYER_BUMP_SPEED_LOSS
if .velocity.z < 0.00 then
set .velocity.z = 0.00
endif
endif
else
call SetUnitZ(.me, z)
if radius > 0.00 and z >= 1.00 then
call DisableUnitCollision(me)
endif
endif
if .velocity.getLength() != 0.00 and radius > 0.00 then
set .dis = this
call GroupEnumUnitsInRange(enumGroup, GetUnitX(.me), GetUnitY(.me), 80.0, Filter(function thistype.collision))
endif
endmethod
implement II32
method setX takes real x returns nothing
call SetUnitX(me, x)
set lastX = x
endmethod
method setY takes real y returns nothing
call SetUnitY(me, y)
set lastY = y
endmethod
method setZ takes real z returns nothing
call SetUnitZ(me, z)
set lastZ = z
endmethod
method applyVector takes Vector v returns nothing
local real loss = 0.00
if IsUnitType(me, UNIT_TYPE_PLAYER) then
set loss = PLAYER_BUMP_SPEED_LOSS
endif
call velocity.add(v)
call BoundaryCheck(me, velocity, loss)
if start32() then
set lastX = GetUnitX(me)
set lastY = GetUnitY(me)
set lastZ = GetUnitZ(me)
endif
endmethod
method setVector takes Vector v returns nothing
set velocity.x = v.x
set velocity.y = v.y
set velocity.z = v.z
endmethod
method getVector takes nothing returns Vector
return velocity
endmethod
/*method exertForce takes Vector f returns nothing
local real l = f.getLength()
call f.setLength(f.getLength()/mass)
call applyVector(f)
call f.setLength(l)
endmethod*/
private static method checkEnd takes nothing returns boolean
local unit f = GetFilterUnit()
local real x = GetUnitX(f)
local real y = GetUnitY(f)
if (IsUnitType(f, UNIT_TYPE_PLAYER)) then
set x = Pow(thistype[f].movementX - x, 2)
set y = Pow(thistype[f].movementY - y, 2)
if (SquareRoot(x + y) <= POSITION_RADIUS) then
set thistype[f].moving = false
endif
endif
set f = null
return false
endmethod
static method isMoving takes nothing returns nothing
local unit u = GetTriggerUnit()
local string s = OrderId2String(GetIssuedOrderId())
local Ball ball = Ball.balls[0]
if IsUnitType(u, UNIT_TYPE_PLAYER) and unitActive[GetPlayerId(GetOwningPlayer(u))] then
if s == "smart" then
set thistype[u].moving = true
set thistype[u].movementX = GetOrderPointX()
set thistype[u].movementY = GetOrderPointY()
call thistype[u].start32()
else
set thistype[u].moving = false
endif
endif
set u = null
endmethod
static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, function thistype.isMoving)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, function thistype.isMoving)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, function thistype.isMoving)
endmethod
endstruct
endlibrary