- Joined
- Dec 31, 2006
- Messages
- 2,216
[SOLVED] Weird bug.
I never thought I had to ask for help on this, but I can't figure it out.
I submitted a spell yesterday and Dynasti found a bug which I thought I had fixed. The bug is really pissing me off because I can't find any reason for why it should happen. The bug is that the footmen suddenly stops in the air, but when I check their flying height it says 0. If someone can find out what's wrong I will give credits and +rep.
I'm not sure if it's any help, but the bug began to show up when I added my knockback system which shouldn't interfere in any way (I think).
Code:
Edit: Code added.
Edit: Solved!
I never thought I had to ask for help on this, but I can't figure it out.
I submitted a spell yesterday and Dynasti found a bug which I thought I had fixed. The bug is really pissing me off because I can't find any reason for why it should happen. The bug is that the footmen suddenly stops in the air, but when I check their flying height it says 0. If someone can find out what's wrong I will give credits and +rep.
I'm not sure if it's any help, but the bug began to show up when I added my knockback system which shouldn't interfere in any way (I think).
Code:
JASS:
library GC
globals
private constant gamecache gc = InitGameCache("GC.w3v")
endglobals
private function H2I takes handle h returns integer
return h
return 0
endfunction
function AttachStruct takes handle h, integer dat, string id returns nothing
call StoreInteger(gc, I2S(H2I(h)), id, dat)
endfunction
function GetAttachedStruct takes handle h, string id returns integer
return GetStoredInteger(gc, I2S(H2I(h)), id)
endfunction
endlibrary
JASS:
library Knockback initializer Init
globals
//==========================CONFIGURATION=============================
private constant real coll = 140. //The collision size of the unit which is knockbacked
private constant real interval = 0.04 //The interval of the timer
private constant real grav = 9.81 //The force of gravity
private constant boolean canfly = true //Can knockbacked units "fly"?
private constant string gsfx = "Dust.mdx" //The sliding effect on ground
private constant string wsfx = "Splash.mdx" //The sliding effect on water
//====================================================================
private real MAX_X
private real MAX_Y
private real MIN_X
private real MIN_Y
private integer Total = 0
private integer array Structs
private constant timer t = CreateTimer()
private boolean paused = false
endglobals
private function TreeFilter takes nothing returns boolean
local integer id = GetDestructableTypeId(GetFilterDestructable())
return id == 'LTlt' or id == 'ATtr' or id == 'BTtw' or id == 'KTtw' or id == 'YTft' or id == 'JTct' or id == 'YTst' or id == 'YTct' or id == 'YTwt' or id == 'JTtw' or id == 'DTsh' or id == 'FTtw' or id == 'CTtr' or id == 'ITtw' or id == 'NTtw' or id == 'OTtw' or id == 'ZTtw' or id == 'WTst' or id == 'GTsh' or id == 'VTlt' or id == 'WTtw' or id == 'ATtc' or id == 'BTtc' or id == 'CTtc' or id == 'ITtc' or id == 'NTtc' or id == 'ZTtc'
endfunction
struct knock
private unit u
private real xvel
private real yvel
private real xvelred
private real yvelred
private real zred
private real z
private boolean killtrees
private integer i
private integer sfx
private static method TreeKill takes nothing returns nothing
local destructable d = GetEnumDestructable()
if GetWidgetLife(d) > 0.405 then
call KillDestructable(d)
endif
set d = null
endmethod
static method Move takes nothing returns nothing
local knock k
local integer i = 1
local real x
local real y
local boolexpr b
local rect r
local location stupid
if Total == 0 then
debug call BJDebugMsg("Timer paused.")
call PauseTimer(t)
set paused = true
endif
loop
exitwhen i > Total
set k = Structs[i]
if k.i != null and k.i != 0 then
set x = GetUnitX(k.u) + k.xvel
set y = GetUnitY(k.u) + k.yvel
if canfly then
set stupid = Location(x, y)
set k.z = k.z - GetLocationZ(stupid)
call SetUnitFlyHeight(k.u, k.z, 0.)
set k.z = k.z - k.zred
if k.z > GetUnitDefaultFlyHeight(k.u) then
set k.zred = k.zred + (grav / (1./interval)) * 2.
else
set k.zred = 0.
call SetUnitFlyHeight(k.u, GetUnitDefaultFlyHeight(k.u), 500.)
endif
if k.z < 0. then
set k.z = 0.
set k.zred = 0.
endif
set k.z = k.z + GetLocationZ(stupid)
call RemoveLocation(stupid)
set stupid = null
endif
call SetUnitX(k.u, x)
call SetUnitY(k.u, y)
set k.sfx = k.sfx + 1
if k.sfx == 1 and GetUnitFlyHeight(k.u) < 5. then
if IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) then
call DestroyEffect(AddSpecialEffect(gsfx, x, y))
else
call DestroyEffect(AddSpecialEffect(wsfx, x, y))
endif
endif
if k.sfx == 5 then
set k.sfx = 0
endif
if k.xvel * k.xvel + k.yvel * k.yvel < 2. then
if (GetUnitFlyHeight(k.u) - GetUnitDefaultFlyHeight(k.u)) * (GetUnitFlyHeight(k.u) - GetUnitDefaultFlyHeight(k.u)) < 5. then
set Structs[i] = Structs[Total]
set Total = Total - 1
set i = i - 1
set k.i = 0
call k.destroy()
endif
else
set k.xvel = k.xvel - k.xvelred
set k.yvel = k.yvel - k.yvelred
endif
if k.killtrees then
set b = Condition(function TreeFilter)
set r = Rect(x - coll, y - coll, x + coll, y + coll)
call EnumDestructablesInRect(r, b, function knock.TreeKill)
call DestroyBoolExpr(b)
set b = null
call RemoveRect(r)
set r = null
endif
if x > MAX_X or x < MIN_X or y > MAX_Y or y < MIN_Y then
set Structs[i] = Structs[Total]
set Total = Total - 1
set i = i - 1
set k.i = 0
call SetUnitFlyHeight(k.u, GetUnitDefaultFlyHeight(k.u), 500.)
call k.destroy()
endif
set i = i + 1
endif
endloop
endmethod
static method Knockback takes unit u, real dist, real a, real tim, boolean killtrees returns nothing
local knock k = knock.allocate()
local location stupid = Location(GetUnitX(u), GetUnitY(u))
set k.u = u
set k.xvel = 2 * (dist * Cos(a)) / (tim/interval+1)
set k.yvel = 2 * (dist * Sin(a)) / (tim/interval+1)
set k.xvelred = k.xvel / (tim/interval)
set k.yvelred = k.yvel / (tim/interval)
set k.zred = 0.
set k.z = GetUnitFlyHeight(u) + GetLocationZ(stupid)
set k.killtrees = killtrees
set k.i = 1
set k.sfx = 0
set Total = Total + 1
set Structs[Total] = k
if paused then
debug call BJDebugMsg("Timer resumed.")
call TimerStart(t, interval, true, function knock.Move)
set paused = false
endif
call RemoveLocation(stupid)
set stupid = null
if canfly then
call UnitAddAbility(u, 'Amrf')
call UnitRemoveAbility(u, 'Amrf')
endif
debug call BJDebugMsg("Knockback started!")
endmethod
private method onDestroy takes nothing returns nothing
set .u = null
debug call BJDebugMsg("Knockback stopped!")
endmethod
endstruct
private function Init takes nothing returns nothing
local rect r = bj_mapInitialPlayableArea
call TimerStart(t, interval, true, function knock.Move)
set MAX_X = GetRectMaxX(r)
set MAX_Y = GetRectMaxY(r)
set MIN_X = GetRectMinX(r)
set MIN_Y = GetRectMinY(r)
set r = null
endfunction
endlibrary
JASS:
globals
constant integer abil = 'A000'//The raw code of the spell.
constant integer dummyid = '1234'//The raw code of the dummy.
constant real mass = 20.//The mass of the footmen.
constant real aoe = 600.//The radius of the spell.
constant real aoeinc = 100.//The increment of radius each level.
constant real dmg = 100.//The damage each footman will deal.
constant real dmginc = 100.//The increment of damage each level.
constant integer waves = 4//The number of waves.
constant integer waveinc = 1//The increment of waves each level.
constant real wavelenght = 1.5//The wait between each wave.
constant real height = 600.//The height the footmen will fall from.
constant boolean stun = true//Is stun enabled?
constant real stundur = 0.5//How many seconds should the units be stunned.
constant real stundurinc = 0.//The increment of stun duration each level.
constant boolean homing = true//Is homing enabled?
constant boolean channeling = true//Is the spell channeling?
constant boolean knock = true//Should knockback be enabled?
constant boolean killtrees = true//Should trees be destroyed if hit by knockbacked units?
constant real coll = 120.//The radius around the unit that may be knockbacked.
constant real knockd = 150.//The distance units will be knockbacked.
constant real time = 1.//How many seconds it will take to get knockbacked that distance.
//=====================================
constant real grav = 9.81//The force of gravity.
constant real interval = 0.04//The interval of the timer.
endglobals
//======================================================================================
//================DON'T TOUCH BELOW UNLESS YOU KNOW WHAT YOU'RE DOING!!!================
//======================================================================================
struct un
unit u
real i
real i2
endstruct
function RemoveUnitTimed_child takes nothing returns nothing
local timer t = GetExpiredTimer()
local un r = GetAttachedStruct(t, "rut")
call RemoveUnit(r.u)
set r.u = null
call r.destroy()
call DestroyTimer(t)
set t = null
endfunction
function RemoveUnitTimed takes unit u, real time returns nothing
local un r = un.create()
local timer t = CreateTimer()
set r.u = u
call AttachStruct(t, r, "rut")
call TimerStart(t, time, false, function RemoveUnitTimed_child)
set t = null
endfunction
function FadeInUnit_child takes nothing returns nothing
local timer t = GetExpiredTimer()
local un r = GetAttachedStruct(t, "fiu")
set r.i = r.i + r.i2
call SetUnitVertexColor(r.u, 255, 255, 255, R2I(r.i))
if r.i >= 255. then
call PauseTimer(t)
call DestroyTimer(t)
set t = null
set r.u = null
call r.destroy()
endif
set t = null
endfunction
function FadeInUnit takes unit u, real time returns nothing
local un r = un.create()
local timer t = CreateTimer()
set r.u = u
set r.i = 0.
set r.i2 = 255. / (time/0.04)
call AttachStruct(t, r, "fiu")
call SetUnitVertexColor(u, 255, 255, 255, 0)
call TimerStart(t, 0.04, true, function FadeInUnit_child)
set t = null
endfunction
globals
constant integer stunnerid = 'h002'
unit array uni
endglobals
function Stun_child takes nothing returns nothing
local timer t = GetExpiredTimer()
local un r = GetAttachedStruct(t, "s")
call AttachStruct(r.u, 0, "ss")
call UnitRemoveAbility(r.u, 'BPSE')
set r.u = null
call r.destroy()
call DestroyTimer(t)
set t = null
endfunction
function Stun takes unit u, real dur returns nothing
local un r = un.create()
local timer t = CreateTimer()
local integer i = GetAttachedStruct(u, "ss")
local integer n = 0
if i == 1 then
call DestroyTimer(t)
call r.destroy()
else
set r.u = u
loop
exitwhen OrderId2String(GetUnitCurrentOrder(uni[n])) != "thunderbolt"
exitwhen n == 91
set n = n + 1
endloop
if n == 91 then
call BJDebugMsg("\n\n\nERROR:\n Code: 375939\n Please send this error report to The_Reborn_Devil\n:)\n\n\n\n")//Hehehe
//==========I have an urge to screw with people ^^
call DestroyTimer(t)
set t = null
call r.destroy()
return
endif
call SetUnitX(uni[n], GetUnitX(u))
call SetUnitY(uni[n], GetUnitY(u))
call IssueTargetOrder(uni[n], "thunderbolt", u)
call AttachStruct(t, r, "s")
call AttachStruct(u, 1, "ss")
call TimerStart(t, dur, false, function Stun_child)
endif
set t = null
endfunction
globals
integer array structs
endglobals
struct man
unit u
unit u2
real xvel
real yvel
real zvel
real dmg
real stundur
integer i
static integer n
static timer t
method move takes nothing returns nothing
local real x1 = GetUnitX(.u)
local real y1 = GetUnitY(.u)
local real z1 = GetUnitFlyHeight(.u)
local real x2 = GetUnitX(.u2)
local real y2 = GetUnitY(.u2)
local real z2 = GetUnitFlyHeight(.u2)
local group g
local unit u
local player p = GetOwningPlayer(.u)
set .zvel = .zvel + (mass * grav) / ((.zvel+1) * 10.)
call SetUnitFlyHeight(.u, z1 - .zvel, 0.)
if homing then
set .xvel = .xvel + (x2 - x1) / ((z1 - z2) / .zvel)
set .yvel = .yvel + (y2 - y1) / ((z1 - z2) / .zvel)
call SetUnitPosition(.u, x1 + .xvel, y1 + .yvel)
set .xvel = .xvel / 1.5
set .yvel = .yvel / 1.5
endif
if z1 - z2 < 30. then
if .stundur > 0. then
call Stun(.u2, .stundur)
endif
call UnitDamageTarget(.u, .u2, .dmg, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null)
if knock then
set g = CreateGroup()
call GroupEnumUnitsInRange(g, x2, y2, coll, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, p) and u != .u2 then
call knock.Knockback(u, knockd, Atan2(GetUnitY(u) - y2, GetUnitX(u) - x2), time, killtrees)
endif
call GroupRemoveUnit(g, u)
set u = null
endloop
call DestroyGroup(g)
set g = null
endif
call .destroy()
endif
set p = null
endmethod
static method create takes player p, unit target, real z, real damg, real stundur returns man
local man m = man.allocate()
local real x = GetUnitX(target)
local real y = GetUnitY(target)
local location stupid = Location(x, y)
set m.u = CreateUnit(p, dummyid, x, y, 0.)
set m.u2 = target
set m.xvel = 0.
set m.yvel = 0.
set m.zvel = 0.
set m.dmg = damg
set m.stundur = stundur
set man.n = man.n + 1
set structs[man.n] = m
set m.i = man.n
call FadeInUnit(m.u, 0.6)
call UnitAddAbility(m.u, 'Amrf')
call UnitRemoveAbility(m.u, 'Amrf')
call SetUnitPathing(m.u, false)
call SetUnitFlyHeight(m.u, z - GetLocationZ(stupid), 0.)
call RemoveLocation(stupid)
set stupid = null
return m
endmethod
static method Loop takes nothing returns nothing
local man m
local integer i = 0
loop
exitwhen i > man.n
set m = structs[i]
if m.i != null then
call m.move()
endif
set i = i + 1
endloop
endmethod
method onDestroy takes nothing returns nothing
local man m
call KillUnit(.u)
call RemoveUnitTimed(.u, 3.)
set .u = null
set .u2 = null
set structs[.i] = structs[man.n]
set m = structs[.i]
set m.i = .i
set man.n = man.n - 1
endmethod
endstruct
struct fallofmen
unit u
real x
real y
real z
real aoe
real dmg
real stundur
integer waves
timer t
boolean first
trigger tr
static method wave takes nothing returns nothing
local timer t = GetExpiredTimer()
local fallofmen fom = GetAttachedStruct(t, "w")
local player p = GetOwningPlayer(fom.u)
local group g = CreateGroup()
local unit u
if fom.first then
call TimerStart(fom.t, wavelenght, true, function fallofmen.wave)
endif
call GroupEnumUnitsInRange(g, fom.x, fom.y, fom.aoe, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if GetWidgetLife(u) > 0.405 and IsUnitEnemy(u, p) then
call man.create(p, u, fom.z, fom.dmg, fom.stundur)
endif
call GroupRemoveUnit(g, u)
set u = null
endloop
call DestroyGroup(g)
set g = null
set fom.waves = fom.waves - 1
if fom.waves == 0 then
call fom.destroy()
endif
set t = null
set p = null
endmethod
static method stop takes nothing returns nothing
local trigger t = GetTriggeringTrigger()
local fallofmen fom = GetAttachedStruct(t, "stop")
call fom.destroy()
set t = null
endmethod
static method create takes unit u returns fallofmen
local fallofmen fom = fallofmen.allocate()
local player p = GetOwningPlayer(u)
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local location stupid = Location(x, y)
local real z = GetLocationZ(stupid)
local integer lvl = GetUnitAbilityLevel(u, abil)
call RemoveLocation(stupid)
set fom.u = u
set fom.x = x
set fom.y = y
set fom.z = z + height
set fom.aoe = aoe + (aoeinc * (lvl - 1))
set fom.dmg = dmg + (dmginc * (lvl - 1))
set fom.stundur = stundur + (stundurinc * (lvl - 1))
set fom.waves = waves + (waveinc * (lvl - 1))
set fom.t = CreateTimer()
set fom.first = true
if channeling then
set fom.tr = CreateTrigger()
call TriggerRegisterUnitEvent(fom.tr, u, EVENT_UNIT_ISSUED_ORDER)
call TriggerRegisterUnitEvent(fom.tr, u, EVENT_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterUnitEvent(fom.tr, u, EVENT_UNIT_ISSUED_POINT_ORDER)
call TriggerAddAction(fom.tr, function fallofmen.stop)
call AttachStruct(fom.tr, fom, "stop")
endif
call AttachStruct(fom.t, fom, "w")
call TimerStart(fom.t, 0., false, function fallofmen.wave)
return fom
endmethod
method onDestroy takes nothing returns nothing
call PauseTimer(.t)
call DestroyTimer(.t)
set .u = null
set .t = null
if channeling then
call DestroyTrigger(.tr)
set .tr = null
endif
endmethod
endstruct
function Conditions takes nothing returns boolean
return GetSpellAbilityId() == abil
endfunction
function Cast takes nothing returns nothing
local unit u = GetSpellAbilityUnit()
call fallofmen.create(u)
set u = null
endfunction
function InitTrig_Fall_of_Men takes nothing returns nothing
local trigger t = CreateTrigger()
local player p
local integer i = 0
set man.n = 0
set man.t = CreateTimer()
call TimerStart(man.t, interval, true, function man.Loop)
call RemoveUnit(CreateUnit(Player(12), dummyid, 0., 0., 0.))
loop
exitwhen i > 90
set uni[i] = CreateUnit(Player(12), stunnerid, 0., 0., 0.)
set i = i + 1
endloop
set i = 0
loop
exitwhen i == bj_MAX_PLAYER_SLOTS
set p = Player(i)
call TriggerRegisterPlayerUnitEvent(t, p, EVENT_PLAYER_UNIT_SPELL_CAST, null)
set p = null
set i = i + 1
endloop
call TriggerAddCondition(t, Condition(function Conditions))
call TriggerAddAction(t, function Cast)
set t = null
endfunction
Edit: Code added.
Edit: Solved!
Last edited: