library ObjectSystem initializer OnInit requires optional StunTarget
/**************************************************************
* Created by [email protected] *
**************************************************************
* User API: (note that @ refers to Object, and # refers to Object value that you recieve
* From creating.)
*
* ** Usefull ones **
*
* @create(owning player, startX, startY, facing angle)
* @createEX(owning player, startX, startY, endX, endY)
* #SetObject(NewUnit, DestroyEffect?)
* #Homing(to make the missle homing? requires to set your own target, or else it wont do nothing but lags!)
* #RegisterImpactAction(OnImpact.function name) // must be above the calling function.
*
* ** Editing specific values **
*
* #distance(new distance)
* #damage(new damage)
* #height(new height)
* #attackType(attacktype)
* #damageType(damagetype)
* #weapontype(weapontype)
* #toKill(kill object on impact?) #hitEnemies(to hit enemies only, or allies too?)
* #attack(attack boolean for damaging units) #ranged(ranged boolean for damaging units)
* #scale(the missle size (doesnt really change, just acts a colliseun size))
* #checkOffsetZ(check offset Z of the missle, or ignore it?)
* #arc(to use arc for the object?) $arcCurve(the curve of the arc.)
* #setEffect(the model path for the object model) #hitTerrain(hit terrain, or ignore it?)
* #heightDiffrence(the diffrence of the height that units can collide with each other,
* ** for example, object has 200 height, enemy has 100 height, diffrence is 100, they will collide.
* ** enemy has 0 height, diffrence height is 100, they will not collide.
* #duration(the duration of the missle untill it gets released)
* #maxdistance(the max distance of the missle untill it gets released)
* ** duration and maxdistance cancel each other. (the last one called, is the real usage of the missle)
*
* ** optional library **
* ** theres a optional library called StunTarget, it allows you to
* ** stun units on impact with object.
* ** this is how you register the impact event:
* ** important also: interval = 0.032 seconds.
* #StunOnImpact(real damageperinterval, real duration, boolean StunCheck)
* ** the check is used for disabling/enabling the stun event.
* ** so if you want it off, you just do
* #StunOnImpact(0, 0, false)
* ** if you want it on, you do:
* #StunOnImpact(damage per interval(interval = 0.032), duration (the duration that the stun lasts for) boolean true)
* **************** Last Words By Me **************************
* ** hope you find this sytem usefull! *
* ** Enjoy making your map =] *
* ***************** just a Example: **************************
* ** this is how i called the defaults for the objects.
* call this.distance(Missle_Distance_Traveled)
* call this.damage(Missle_Damage_On_Impact)
* call this.height(Missle_Height_On_Creation)
* call this.toKill(Missle_Destroy_On_Impact)
* call this.hitEnemies(Missle_Enemies_Only)
* call this.attackType(Missle_Damage_Attacktype)
* call this.damageType(Missle_Damage_Damagetype)
* call this.weaponType(Missle_Damage_Weapontype)
* call this.attack(Missle_Damage_Attack)
* call this.ranged(Missle_Damage_Ranged)
* call this.scale(Missle_Default_Scale)
* call this.checkOffsetZ(Missle_Check_OffsetZ)
* call this.arc(Missle_Use_Arc)
* call this.arcCurve(Missle_Default_Arc_Curve)
* call this.setEffect(Missle_Creation_Model_Path)
* call this.hitTerrain(Missle_Hit_Terrain)
* call this.heightDiffrence(Missle_Default_Height_Diffrence)
*
* if Missle_Run_On_Duration then
* call this.duration(Missle_Duration_Traveled)
* elseif not Missle_Run_On_Duration then
* call this.maxdistance(Missle_MaxDistance_Traveled)
* endif
* ***************** End Of Example ***************************
* Remember: this was made by dardas from hiveworkshop.com! *
**************************************************************/
function interface OnImpact takes Object id returns nothing
struct Object
//============================================
//============== Default Setup
//============================================
private static constant integer Missle_Dummy_Raw = 'e000'
private static constant real Missle_Damage_On_Impact = 150 // the damage the missle will deal to the target on impact
private static constant real Missle_Distance_Traveled = 25 // the distance the missle will travel in every 0.032 seconds.
private static constant real Missle_Duration_Traveled = 0.75 // the duration the missle will travel untill it will get destroyed
private static constant real Missle_MaxDistance_Traveled = 1500 // the max distance traveled by the missle untill it will get destroyed
private static constant real Missle_Height_On_Creation = 50 // the height of the missle when its created.
private static constant real Missle_Default_Scale = 3 // the size of the missle, used to hit enemies. (acts as collision)
private static constant real Missle_Default_Arc_Curve = 1.8 // the curve of the arc when shooting an arced missle.
private static constant real Missle_Default_Height_Diffrence = 50.5 // the diffrence between the 2 units height so they collide.(on impact)
private static constant boolean Missle_Destroy_On_Impact = true // if true it will destroy the missle automaticly on impact.
private static constant boolean Missle_Run_On_Duration = true // if false it will destroy the missle after max distance is done.
private static constant boolean Missle_Enemies_Only = true // if false, it will deal damage to enemies only, and will pass by allies.
private static constant boolean Missle_Return_Last = false // if true, you will be able to use the Object.last function.
private static constant boolean Missle_Check_OffsetZ = false // if true, the object will keep same height when going off cliffs, or etc.
private static constant boolean Missle_Use_Arc = true // if true, the missle will arc untill it reaches the target point.
private static constant boolean Missle_Hit_Terrain = true // if true, the missle will get automaticly released when terrain height is higher then the missle height.
private static constant string Missle_Creation_Model_Path = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilMissile.mdl" // the model automaticly created to the missle on creation.
private static constant attacktype Missle_Damage_Attacktype = ATTACK_TYPE_NORMAL // the attacktype used to damage enemies.
private static constant damagetype Missle_Damage_Damagetype = DAMAGE_TYPE_NORMAL // the damagetype used to damage enemies.
private static constant weapontype Missle_Damage_Weapontype = WEAPON_TYPE_WHOKNOWS // the weapontype used to damage enemies.
private static constant boolean Missle_Damage_Attack = false // not really sure what this 2 do,
private static constant boolean Missle_Damage_Ranged = false // but i think this 1 means if the attack is melle or ranged.
//============================================
//============== Dont touch below ~ For Your Own Good ~
//============================================
private static thistype Count = 0
private static thistype Count2 = 0
private static integer Count3 = 0
private static integer Count4 = 0
private static thistype dummy_id = 0
private static location MountainLoc = Location(0, 0)
private static group Group = CreateGroup()
private real Speed = 0
private real Duration = 0
private real MaxDist = 0
private real Damage = 0
private real Height = 0
private real StunDuration = 0
private real StunDps = 0
private real Size = 0
private real check = 0
private real curve = 0
private real HeightDiffrence = 0
private boolean DestroyOnImpact = false
private boolean RunOnDuration = false
private boolean EnemiesOnly = false
private boolean Stun = false
private boolean CheckOffsetZ = false
private boolean useArc = false
private boolean HitTerrain = false
private boolean executedImpact = false
private boolean homing = false
private string ModelPath = ""
private effect Effect = null
private attacktype Attacktype = null
private damagetype Damagetype = null
private weapontype Weapontype = null
private boolean Attack = false
private boolean Ranged = false
private OnImpact On_Impact = 0
readonly real x = 0
readonly real y = 0
readonly real startX = 0
readonly real startY = 0
readonly real angle = 0
readonly unit Object = null
readonly unit HomingTarget = null
readonly boolean isUsed = true
readonly static thistype last = 0
static method create takes player owner, real x, real y, real facing returns Object
set Count = Count + 1
set Count3 = Count3 + 1
set Count4 = Count4 + 1
set Count.startX = x
set Count.startY = y
set Count.Object = CreateUnit(owner, Missle_Dummy_Raw, x, y, facing)
set Count.angle = facing
set Count.isUsed = true
set Count.executedImpact = false
call Count.useDefaults()
if Missle_Return_Last then
set last = Count
endif
return Count
endmethod
static method createEX takes player owner, real startX, real startY, real endX, real endY returns Object
set Count = Count + 1
set Count3 = Count3 + 1
set Count4 = Count4 + 1
set Count.startX = startX
set Count.startY = startY
set Count.angle = bj_RADTODEG * Atan2(endY - startY, endX - startX)
set Count.Object = CreateUnit(owner, Missle_Dummy_Raw, startX, startY, Count.angle)
set Count.isUsed = true
call Count.useDefaults()
if Missle_Return_Last then
set last = Count
endif
// extra for EX function
call Count.maxdistance(SquareRoot((endX - startX) * (endX - startX) - (endY - startY) * (endY - startY)))
//======================
return Count
endmethod
method SetObject takes unit object, boolean removeeffect returns nothing
call RemoveUnit(this.Object)
set this.Object = object
if removeeffect then
call DestroyEffect(this.Effect)
set this.Effect = null
else
call this.setEffect(this.ModelPath)
endif
endmethod
method setHomingTarget takes unit target returns nothing
set this.HomingTarget = target
endmethod
//==============================================================
//======================= Making my life easier..
//==============================================================
private method CaculateArc takes nothing returns nothing
local real dx = 0
local real dy = 0
local real dx2 = 0
local real dy2 = 0
local real md = 0
if this.RunOnDuration then
set md = FindMaxDistance(this.Speed, this.Duration)
else
set md = this.MaxDist
endif
set dx = this.startX - this.x
set dy = this.startY - this.y
set dx2 = (this.startX + md * Cos (this.angle)) - this.startX
set dy2 = (this.startY + md * Sin (this.angle)) - this.startY
set this.Height = JumpParabola(SquareRoot(dx * dx + dy * dy), SquareRoot(dx2 * dx2 + dy2 * dy2), this.curve)
call SetUnitFlyHeight(this.Object, this.Height, 0)
endmethod
private method CrushCheck takes nothing returns nothing
local real x = GetUnitX(this.Object) + 25 * Cos (this.angle * bj_DEGTORAD)
local real y = GetUnitY(this.Object) + 25 * Sin (this.angle * bj_DEGTORAD)
if this.HitTerrain then
if GetCoordinateZ(x, y) >= GetUnitFlyHeight(this.Object) + GetUnitZ(this.Object) then
call this.Release()
endif
endif
endmethod
private method ChangeHomingAngle takes nothing returns nothing
local unit new = null
local player p = null
local real x = 0
local real y = 0
if this.homing then
set p = GetOwningPlayer(this.Object)
set x = GetUnitX(this.Object)
set y = GetUnitY(this.Object)
set this.angle = Atan2(GetUnitY(this.HomingTarget) - y, GetUnitX(this.HomingTarget) - x)
call SetUnitFacing(this.Object, this.angle)
endif
set new = null
endmethod
//===============================================================
//======================= Math methods
//===============================================================
private static method FindMaxDistance takes real Distance, real Duration returns real
// this function caculates max distance using distance and duration.
// this is by diehard@azeroth from hiveworkshop.
return (Distance/0.032) * Duration
endmethod
private static method FindDuration takes real Distance, real MaxDistance returns real
// this function caculates duration using max distance and distance.
// made by dardas
// made by kristian: Max distance * Interval / speed (just incase)
return MaxDistance / (Distance/0.032)
endmethod
private static method JumpParabola takes real dist, real maxdist,real curve returns real
// This function calculates the unit Z for a parabolic arc, by Shadow1500
// brought to me by diehard@azeroth from hiveworkshop.com
local real t = (dist*2)/maxdist-1
return (-t*t+1)*(maxdist/curve)
endmethod
private static method GetUnitZ takes unit u returns real
// finds a unit location Z, instead using another location.
return GetCoordinateZ(GetUnitX(u), GetUnitY(u))
endmethod
private static method GetCoordinateZ takes real x, real y returns real
// finds x/y location Z using a re-used dummy.
call MoveLocation(MountainLoc, x, y)
return GetLocationZ(MountainLoc)
endmethod
private static method GetZFactor takes real NewX, real NewY, real OldX, real OldY returns real
// this function caculates the Z offset of 2 locations.
// this function is by Inferior from hiveworkshop.com
local real z = 0
call MoveLocation(MountainLoc, NewX, NewY)
set z = GetLocationZ(MountainLoc)
call MoveLocation(MountainLoc, OldX, OldY)
return z - GetLocationZ(MountainLoc)
endmethod
//===============================================================
method allowFlight takes nothing returns nothing
call UnitAddAbility(this.Object, 'Amrf')
call UnitRemoveAbility(this.Object, 'Amrf')
endmethod
private method useDefaults takes nothing returns nothing
call this.distance(Missle_Distance_Traveled)
call this.damage(Missle_Damage_On_Impact)
call this.height(Missle_Height_On_Creation)
call this.toKill(Missle_Destroy_On_Impact)
call this.hitEnemies(Missle_Enemies_Only)
call this.attackType(Missle_Damage_Attacktype)
call this.damageType(Missle_Damage_Damagetype)
call this.weaponType(Missle_Damage_Weapontype)
call this.attack(Missle_Damage_Attack)
call this.ranged(Missle_Damage_Ranged)
call this.scale(Missle_Default_Scale)
call this.checkOffsetZ(Missle_Check_OffsetZ)
call this.arc(Missle_Use_Arc)
call this.arcCurve(Missle_Default_Arc_Curve)
call this.setEffect(Missle_Creation_Model_Path)
call this.hitTerrain(Missle_Hit_Terrain)
call this.heightDiffrence(Missle_Default_Height_Diffrence)
if Missle_Run_On_Duration then
call this.duration(Missle_Duration_Traveled)
elseif not Missle_Run_On_Duration then
call this.maxdistance(Missle_MaxDistance_Traveled)
endif
endmethod
method Release takes nothing returns nothing
if this.isUsed then
if this.executedImpact == false then
call this.On_Impact.execute(this)
set this.executedImpact = true
endif
set Count3 = Count3 - 1
call DestroyEffect(this.Effect)
set this.Effect = null
set this.isUsed = false
if this.DestroyOnImpact then
call RemoveUnit(this.Object)
endif
//if Count3 == 0 and Count4 == Count then
// set Count = 0
// set Count2 = 0
// set Count3 = 0
// set Count4 = 0
// call DisplayTimedTextToForce(GetPlayersAll(), 2, "|c00FF0000[DEBUG]|r |c0000FF00Restarted the count|r")
//endif
set this.Object = null
endif
endmethod
private method DamageFilter takes unit target returns nothing
call UnitDamageTarget(this.Object, target, this.Damage, this.Attack, this.Ranged, this.Attacktype, this.Damagetype, this.Weapontype)
endmethod
private static method UnitGroup takes nothing returns nothing
call dummy_id.On_Impact.execute(dummy_id)
set dummy_id.executedImpact = true
call dummy_id.DamageFilter(GetEnumUnit())
if dummy_id.DestroyOnImpact then
call dummy_id.Release()
endif
endmethod
private static method DamageBoolexpr takes nothing returns boolean
local real diffrence = dummy_id.Height - GetUnitFlyHeight(GetFilterUnit())
local boolean result = dummy_id.HeightDiffrence > diffrence and diffrence > -dummy_id.HeightDiffrence
if dummy_id.EnemiesOnly then
set result = IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(dummy_id.Object)) /*
*/and dummy_id.HeightDiffrence > diffrence and diffrence > -dummy_id.HeightDiffrence
endif
return GetWidgetLife(GetFilterUnit()) > 0.405 and result
endmethod
private method Actions takes nothing returns nothing
set dummy_id = this
call GroupEnumUnitsInRange(Group, this.x, this.y, this.Size * 10, Condition(function Object.DamageBoolexpr))
call ForGroup(Group, function Object.UnitGroup)
endmethod
//! textmacro loop takes Check, Increase, By
private method onLoop$By$ takes nothing returns nothing
if this.check < $Check$ then
set this.check = this.check + $Increase$
set this.x = GetUnitX(this.Object) + this.Speed * Cos (this.angle * bj_DEGTORAD)
set this.y = GetUnitY(this.Object) + this.Speed * Sin (this.angle * bj_DEGTORAD)
call SetUnitX(this.Object, this.x)
call SetUnitY(this.Object, this.y)
if this.useArc then
call this.CaculateArc()
elseif this.CheckOffsetZ then
call SetUnitFlyHeight(this.Object, GetZFactor(this.x, this.y, GetUnitX(this.Object), GetUnitY(this.Object)), 0)
endif
call this.ChangeHomingAngle()
call this.CrushCheck()
call this.Actions()
else
call this.Release()
endif
endmethod
//! endtextmacro
//! runtextmacro loop("this.Duration", "0.032", "Duration")
//! runtextmacro loop("this.MaxDist", "this.Speed", "Distance")
private static method LoopSplit takes nothing returns nothing
set Count2 = 0
if Count != 0 then
loop
set Count2 = Count2 + 1
if Count2.RunOnDuration then
call Count2.onLoopDuration()
else
call Count2.onLoopDistance()
endif
exitwhen Count2 >= Count
endloop
endif
endmethod
method setEffect takes string eff returns nothing
if this.Effect != null then
call DestroyEffect(this.Effect)
set this.Effect = null
endif
set this.ModelPath = eff
set this.Effect = AddSpecialEffectTarget(eff, this.Object, "origin")
endmethod
method TriggerAddImpactAction takes OnImpact executefunc returns nothing
set this.On_Impact = executefunc
endmethod
//! textmacro CAP takes head, name, takes, returns, body, body2, return
$head$ method $name$ takes $takes$ returns $returns$
$body$
$body2$
$return$
endmethod
//! endtextmacro
//! runtextmacro CAP("", "distance", "real distance", "nothing", "set this.Speed = distance", "", "")
//! runtextmacro CAP("", "duration", "real duration", "nothing", "set this.Duration = duration", "set this.RunOnDuration = true", "")
//! runtextmacro CAP("", "maxdistance", "real maxdistance", "nothing", "set this.MaxDist = maxdistance", "set this.RunOnDuration = false", "")
//! runtextmacro CAP("", "damage", "real damage", "nothing", "set this.Damage = damage", "", "")
//! runtextmacro CAP("", "height", "real height", "nothing", "set this.Height = height", "call SetUnitFlyHeight(this.Object, height, 0)", "")
//! runtextmacro CAP("", "scale", "real scale", "nothing", "set this.Size = scale", "", "")
//! runtextmacro CAP("", "arcCurve", "real curve", "nothing", "set this.curve = curve", "", "")
//! runtextmacro CAP("", "heightDiffrence", "real diffrence", "nothing", "set this.HeightDiffrence = diffrence", "", "")
//! runtextmacro CAP("", "toKill", "boolean kill", "nothing", "set this.DestroyOnImpact = kill", "", "")
//! runtextmacro CAP("", "hitEnemies", "boolean hitEnemies", "nothing", "set this.EnemiesOnly = hitEnemies", "", "")
//! runtextmacro CAP("", "checkOffsetZ", "boolean Check", "nothing", "set this.CheckOffsetZ = Check", "", "")
//! runtextmacro CAP("", "arc", "boolean useArc", "nothing", "set this.useArc = useArc", "", "")
//! runtextmacro CAP("", "hitTerrain", "boolean hit", "nothing", "set this.HitTerrain = hit", "", "")
//! runtextmacro CAP("", "Homing", "boolean homingmissle", "nothing", "set this.homing = homingmissle", "", "")
//! runtextmacro CAP("", "attackType", "attacktype data", "nothing", "set this.Attacktype = data", "", "")
//! runtextmacro CAP("", "damageType", "damagetype data", "nothing", "set this.Damagetype = data", "", "")
//! runtextmacro CAP("", "weaponType", "weapontype data", "nothing", "set this.Weapontype = data", "", "")
//! runtextmacro CAP("", "attack", "boolean attack", "nothing", "set this.Attack = attack", "", "")
//! runtextmacro CAP("", "ranged", "boolean ranged", "nothing", "set this.Ranged = ranged", "", "")
//==
//! runtextmacro CAP("", "getDistance", "nothing", "real", "", "", "return this.Speed")
//! runtextmacro CAP("", "getDuration", "nothing", "real", "", "", "return this.Duration")
//! runtextmacro CAP("", "getMaxDistance", "nothing", "real", "", "", "return this.MaxDist")
//! runtextmacro CAP("", "getDamage", "nothing", "real", "", "", "return this.Damage")
//! runtextmacro CAP("", "getHeight", "nothing", "real", "", "", "return this.Height")
//! runtextmacro CAP("", "getScale", "nothing", "real", "", "", "return this.Size")
//! runtextmacro CAP("", "getArcCurve", "nothing", "real", "", "", "return this.curve")
//! runtextmacro CAP("", "getHeightDiffrence", "nothing", "real", "", "", "return this.HeightDiffrence")
//! runtextmacro CAP("", "getToKill", "nothing", "boolean", "", "", "return this.DestroyOnImpact")
//! runtextmacro CAP("", "getHitEnemies", "nothing", "boolean", "", "", "return this.EnemiesOnly")
//! runtextmacro CAP("", "getCheckOffsetZ", "nothing", "boolean", "", "", "return this.CheckOffsetZ")
//! runtextmacro CAP("", "getArc", "nothing", "boolean", "", "", "return this.useArc")
//! runtextmacro CAP("", "getHitTerrain", "nothing", "boolean", "", "", "return this.HitTerrain")
//! runtextmacro CAP("", "getAttackType", "nothing", "attacktype", "", "", "return this.Attacktype")
//! runtextmacro CAP("", "getDamageType", "nothing", "damagetype", "", "", "return this.Damagetype")
//! runtextmacro CAP("", "getWeaponType", "nothing", "weapontype", "", "", "return this.Weapontype")
//! runtextmacro CAP("", "getAttack", "nothing", "boolean", "", "", "return this.Attack")
//! runtextmacro CAP("", "getRanged", "nothing", "boolean", "", "", "return this.Ranged")
endstruct
private function OnInit takes nothing returns nothing
call TimerStart(CreateTimer(), 0.032, true, function s__Object_LoopSplit)
endfunction
endlibrary