Impale script bug

Reaction score
91
Okay, as an idea from DotA and waaaks!, I wanted to make my own impale system for personal use due to the minor bugs the normal skill has. It worked perfectly when using it on a single unit but the problem comes when I impale more than 2-3 units from the "line" - as they return back to the ground a huge lag spike is created and my handle counter goes wild. The only things I run when the units get back to the ground are damaging, reseting height to 0 and applying a stun which duration is supposed to get refreshed if multiple impales are casted on the same unit while it's being stunned. I can't find a reason why this lag spike is created... Also, when it ends a random unit gets four-five times damaged instead of only once and then the system totally bugs and instead of tossing units it just makes random units get their height increased by 24 permanently.

JASS:
library ImpaleLib initializer Init uses TimerUtils, Table, xebasic, TimedEffects, GroupUtils

globals
    private constant integer AID_STUN = 'A00E' // Stun spell with 10 sec duration.
    private constant integer BID_STUN = 'B002' // Buff that comes with the spell
    private constant string  OID_STUN = "thunderbolt" // Order string
    private constant real RANGE = 150. // Range between sfx spikes creation
    private constant real TIME = 1.04 // Time in the air (including falling down).
    private constant real PERIOD = 0.03125 // Period for increasing height.
    private constant real PERIOD2 = 2 * PERIOD // Period for creating spikes.
    private constant real HEIGHT = 24. // Height increment per tick.
    // Some sfxs.
    private constant string SFX_IMPALE = "Abilities\\Spells\\Undead\\Impale\\ImpaleHitTarget.mdl"
    private constant string SFX_SPIKES = "Abilities\\Spells\\Undead\\Impale\\ImpaleMissTarget.mdl"
endglobals

globals
    private HandleTable ht
    private Table t
    private Table s
endglobals

private struct Data
    unit targ
    timer tim 
    integer ticks
    
    private static method Callback takes nothing returns nothing
        local Data d = Data(ht[GetExpiredTimer()])
        set d.ticks = d.ticks - 1 
        if d.ticks <= 0 or GetWidgetLife(d.targ) < 0.405 then
            call UnitRemoveAbility(d.targ, BID_STUN)
            call d.destroy() // End the stun.
        endif
    endmethod
    
    static method create takes unit targ, real dur returns Data
        local Data d = Data.allocate()
        local integer id = GetUnitId(targ)
        set d.targ = targ
        set d.ticks = R2I(dur / PERIOD)
        set d.tim = NewTimer()
        set ht[d.tim] = integer(d)
        set s[id] = integer(d)
        
        // Dummy stuff.
        //call UnitRemoveAbility(d.targ, 'Avul')
        call GetAvailableDummy(Player(13))
        call SetUnitX(dum, GetUnitX(d.targ))
        call SetUnitY(dum, GetUnitY(d.targ))
        call AddAndCastTarget(dum, d.targ, AID_STUN, 1, OID_STUN) 
        call ReleaseDummy(dum)
        
        call TimerStart(d.tim, PERIOD, true, function Data.Callback)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        // I think this stuff is never called...
        call ht.flush(.tim)
        call ReleaseTimer(.tim)
        call BJDebugMsg("STUN DATA DESTROYED!")
    endmethod
endstruct

function ImpaleStunTarget takes unit targ, real stun returns nothing
    call Data.create(targ, stun)
endfunction

private struct Data2
    unit cast
    unit targ
    real dmg
    real stun
    real facing
    integer ticks
    integer halfticks
    timer tim
    boolean flip = false
    
    private static method Callback takes nothing returns nothing
        local Data2 d = Data2(ht[GetExpiredTimer()])
        set d.ticks = d.ticks - 1
        if d.ticks == d.halfticks then
            set d.flip = true // Do a height deduction. 
        endif
        if d.ticks <= 0 then
            // Make it stop since the last order was hold position.
            call IssueImmediateOrder(d.targ, "stop")
            call UnitDamageTarget(d.cast, d.targ, d.dmg, true, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, null)
            call UnitAddAbility(d.targ, XE_HEIGHT_ENABLER)
            call UnitRemoveAbility(d.targ, XE_HEIGHT_ENABLER)
            call SetUnitFlyHeight(d.targ, 0., 0.)
            if d.stun != 0. then
                call ImpaleStunTarget(d.targ, d.stun)
            endif
            call d.destroy()
            return 
        endif
        call UnitAddAbility(d.targ, XE_HEIGHT_ENABLER)
        call UnitRemoveAbility(d.targ, XE_HEIGHT_ENABLER)
        if d.flip == true then // Height deduction? 
            call SetUnitFlyHeight(d.targ, GetUnitFlyHeight(d.targ) - HEIGHT, 0.)
        else // Then it should be increased.
            call SetUnitFlyHeight(d.targ, GetUnitFlyHeight(d.targ) + HEIGHT, 0.)
        endif
        // Simulate a "disabling" process instead of using pause. 
        call IssueImmediateOrder(d.targ, "holdposition")
        call SetUnitFacing(d.targ, d.facing)
    endmethod

    static method create takes unit cast, unit targ, real dmg, real stun returns Data2
        local Data2 d = Data2.allocate()
        local integer id = GetUnitId(targ) 
        set d.cast = cast
        set d.targ = targ
        set d.facing = GetUnitFacing(d.targ)
        set d.dmg = dmg
        set d.stun = stun
        set d.ticks = R2I(TIME / PERIOD)
        set d.halfticks = R2I(d.ticks * 0.5) // To check when the unit has to return back
                                             // to the ground.
        // Timed effect.
        call StartTimedEffect(AddSpecialEffect(SFX_IMPALE, GetUnitX(d.targ), GetUnitY(d.targ)), TIME)
        set d.tim = NewTimer()
        set ht[d.tim] = integer(d)
        set t[id] = integer(d)
        call TimerStart(d.tim, PERIOD, true, function Data2.Callback)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call ht.flush(.tim)
        call ReleaseTimer(.tim)
        call BJDebugMsg("TARGET DATA DESTROYED!")
    endmethod
endstruct

function ImpaleUnit takes unit cast, unit targ, real dmg, real stun returns nothing
    call Data2.create(cast, targ, dmg, stun)
endfunction

private struct Data3
    unit cast
    real dmg
    integer ticks
    real angle
    real x
    real y
    real cosp
    real sinp
    real aoe
    real stun
    timer tim
    group gr
    
    private static method GetEnemies takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(pass)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true
    endmethod
    
    private static method Callback takes nothing returns nothing
        local Data3 d = Data3(ht[GetExpiredTimer()])
        set d.x = d.x + d.cosp
        set d.y = d.y + d.sinp
        call StartTimedEffect(AddSpecialEffect(SFX_SPIKES, d.x, d.y), 1.)
        set pass = d.cast
        call GroupClear(ENUM_GROUP)
        call GroupEnumUnitsInRange(ENUM_GROUP, d.x, d.y, d.aoe, Condition(function Data3.GetEnemies))
        loop
            set fir = FirstOfGroup(ENUM_GROUP)
            exitwhen fir == null
            if IsUnitInGroup(fir, d.gr) == false then
                call GroupAddUnit(d.gr, fir)
                call ImpaleUnit(d.cast, fir, d.dmg, d.stun) // Do an impale...
            endif
            call GroupRemoveUnit(ENUM_GROUP, fir)
        endloop
        set d.ticks = d.ticks - 1
        if d.ticks <= 0 then
            call d.destroy()
        endif
    endmethod
    
    static method create takes unit cast, real dmg, real tx, real ty, real aoe, real distance, real stun returns Data3
        local Data3 d = Data3.allocate()
        set d.x = GetUnitX(cast)
        set d.y = GetUnitY(cast)
        set d.angle = Atan2(ty - d.y, tx - d.x)
        set d.cosp = RANGE * Cos(d.angle)
        set d.sinp = RANGE * Sin(d.angle)
        set d.cast = cast
        set d.dmg = dmg
        set d.aoe = aoe
        set d.stun = stun // Stun duration.
        set d.ticks = R2I(distance / RANGE)
        set d.gr = NewGroup() 
        set d.tim = NewTimer()
        set ht[d.tim] = integer(d)
        call TimerStart(d.tim, PERIOD2, true, function Data3.Callback)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call ht.flush(.tim)
        call ReleaseTimer(.tim)
        call ReleaseGroup(.gr)
        call BJDebugMsg("LINE DATA DESTROYED!")
    endmethod
endstruct

function ImpaleLine takes unit cast, real dmg, real tx, real ty, real aoe, real distance, real stun returns nothing
    call Data3.create(cast, dmg, tx, ty, aoe, distance, stun)
endfunction

private function Init takes nothing returns nothing
    set ht = HandleTable.create()
    set t = Table.create()
    set s = Table.create()
endfunction

endlibrary



EDIT:
Nvm, fixed, if someone wants the code to learn or just use:
JASS:
library ImpaleLib initializer Init uses TimerUtils, Table, DummyLib, xebasic, TimedEffects, GroupUtils, AbilityPreload

globals
    private constant integer AID_STUN = 'A00E' 
    private constant integer BID_STUN = 'B002' 
    private constant string  OID_STUN = "thunderbolt" 
    private constant real RANGE = 150.
    private constant real TIME = 1.04 
    private constant real PERIOD = 0.03125 
    private constant real PERIOD2 = 2 * PERIOD 
    private constant real HEIGHT = 24. 
    private constant string SFX_IMPALE = "Abilities\\Spells\\Undead\\Impale\\ImpaleHitTarget.mdl"
    private constant string SFX_SPIKES = "Abilities\\Spells\\Undead\\Impale\\ImpaleMissTarget.mdl"
endglobals

globals
    private HandleTable ht
    private Table t
    private unit dumi
endglobals

private struct Unit
    unit cast
    unit targ
    real dmg
    real stun
    real facing
    integer ticks
    integer halfticks
    timer tim
    boolean flip = false
    
    private static method Callback takes nothing returns nothing
        local Unit d = ht[GetExpiredTimer()]
        set d.ticks = d.ticks - 1
        if d.ticks == d.halfticks then
            set d.flip = true 
        endif
        if d.ticks <= 0 then
        //==============================================
            call UnitRemoveAbility(d.targ, 'Avul')    // You should remove this line.
        //==============================================
            call IssueImmediateOrder(d.targ, "stop")
            call UnitDamageTarget(d.cast, d.targ, d.dmg, true, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, null)
            call UnitAddAbility(d.targ, XE_HEIGHT_ENABLER)
            call UnitRemoveAbility(d.targ, XE_HEIGHT_ENABLER)
            call SetUnitFlyHeight(d.targ, 0., 0.)
            if d.stun != 0. then
                call SetUnitX(dumi, GetUnitX(d.targ))
                call SetUnitY(dumi, GetUnitY(d.targ))
                call AddAndCastTarget(dumi, d.targ, AID_STUN, R2I(d.stun), OID_STUN) 
            endif
            call UnitRemoveAbility(d.targ, XE_HEIGHT_ENABLER)
            call d.destroy()
        else
            call UnitAddAbility(d.targ, XE_HEIGHT_ENABLER)
            call UnitRemoveAbility(d.targ, XE_HEIGHT_ENABLER)
            if d.flip == true then 
                call SetUnitFlyHeight(d.targ, GetUnitFlyHeight(d.targ) - HEIGHT, 0.)
            else 
                call SetUnitFlyHeight(d.targ, GetUnitFlyHeight(d.targ) + HEIGHT, 0.)
            endif
            call IssueImmediateOrder(d.targ, "holdposition")
            call SetUnitFacing(d.targ, d.facing)
        endif
    endmethod

    static method create takes unit cast, unit targ, real dmg, real stun returns Unit
        local Unit d = Unit.allocate()
        local integer id = GetUnitId(targ) 
        set d.cast = cast
        set d.targ = targ
        set d.facing = GetUnitFacing(d.targ)
        set d.dmg = dmg
        set d.stun = stun
        set d.ticks = R2I(TIME / PERIOD)
        set d.halfticks = R2I(d.ticks * 0.5) 
        call StartTimedEffect(AddSpecialEffect(SFX_IMPALE, GetUnitX(d.targ), GetUnitY(d.targ)), TIME)
        set d.tim = NewTimer()
        set ht[d.tim] = d
        set t[id] = d
        call TimerStart(d.tim, PERIOD, true, function Unit.Callback)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call ht.flush(.tim)
        call ReleaseTimer(.tim)
    endmethod
endstruct

function ImpaleUnit takes unit cast, unit targ, real dmg, real stun returns nothing
    call Unit.create(cast, targ, dmg, stun)
endfunction

private struct Line
    unit cast
    real dmg
    integer ticks
    real angle
    real x
    real y
    real cosp
    real sinp
    real aoe
    real stun
    timer tim
    group gr
    
    private static method GetEnemies takes nothing returns boolean
        return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(pass)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) == true
    endmethod
    
    private static method Callback takes nothing returns nothing
        local Line d = ht[GetExpiredTimer()]
        set d.x = d.x + d.cosp
        set d.y = d.y + d.sinp
        call StartTimedEffect(AddSpecialEffect(SFX_SPIKES, d.x, d.y), 1.)
        set pass = d.cast
        call GroupClear(ENUM_GROUP)
        call GroupEnumUnitsInRange(ENUM_GROUP, d.x, d.y, d.aoe, Condition(function Line.GetEnemies))
        loop
            set fir = FirstOfGroup(ENUM_GROUP)
            exitwhen fir == null
            if IsUnitInGroup(fir, d.gr) == false then
                call GroupAddUnit(d.gr, fir)
                call ImpaleUnit(d.cast, fir, d.dmg, d.stun) // Do an impale...
            endif
            call GroupRemoveUnit(ENUM_GROUP, fir)
        endloop
        set d.ticks = d.ticks - 1
        if d.ticks <= 0 then
            call d.destroy()
        endif
    endmethod
    
    static method create takes unit cast, real dmg, real tx, real ty, real aoe, real distance, real stun returns Line
        local Line d = Line.allocate()
        local unit gstu = GetSpellTargetUnit()
        if gstu != null then
            set tx = GetUnitX(gstu)
            set ty = GetUnitY(gstu)
            set gstu = null
        endif
        set d.x = GetUnitX(cast)
        set d.y = GetUnitY(cast)
        set d.angle = Atan2(ty - d.y, tx - d.x)
        set d.cosp = RANGE * Cos(d.angle)
        set d.sinp = RANGE * Sin(d.angle)
        set d.cast = cast
        set d.dmg = dmg
        set d.aoe = aoe
        set d.stun = stun
        set d.ticks = R2I(distance / RANGE)
        set d.gr = NewGroup() 
        set d.tim = NewTimer()
        set ht[d.tim] = d
        call TimerStart(d.tim, PERIOD2, true, function Line.Callback)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call ht.flush(.tim)
        call ReleaseTimer(.tim)
        call ReleaseGroup(.gr)
    endmethod
endstruct

function ImpaleLine takes unit cast, real dmg, real tx, real ty, real aoe, real distance, real stun returns nothing
    call Line.create(cast, dmg, tx, ty, aoe, distance, stun)
endfunction

private function Init takes nothing returns nothing
    set ht = HandleTable.create()
    set t = Table.create()
    
    call AbilityPreload(AID_STUN)
    
    set dumi = CreateUnit(Player(13), XE_DUMMY_UNITID, 0., 0., 0.)
    call UnitAddAbility(dumi, 'Aloc')
    call UnitAddAbility(dumi, AID_STUN)
endfunction

endlibrary
 

Viikuna

No Marlo no game.
Reaction score
265
I think wraithseeker posted some script I made that does things like that somewhere here. Wait I get you a link.

edit. link

You should just make this system to use AutoIndex and then use it ( Or at least make your own based on this ). But yea, I can try to find that error from your code, gonna take few minutes.
 
Reaction score
91
Well, I'm not searching for height stuff nor improvements on this one... I just want to know why do I get a massive 5-10 seconds spike and suddenly some odd stuff happen after it.
 

Viikuna

No Marlo no game.
Reaction score
265
Your code makes no sense to me at all, I think I either need some sleep or then I need to concentrate more. And Im starting to hate those Data1, Data2 names for structtype...

Anyways, I think its not fully MUI for somereason. Going to investigate further...
 
Reaction score
91
Okay, I found the reason for my epic spike...
It comes from my dummy unit library.

JASS:

private function CreateDummyUnits takes nothing returns nothing
    local integer a = 0
    local integer id 
    loop
        exitwhen a > DUMMY_UNITS_CREATED
        set DUMMY[a] = CreateUnit(Player(13), XE_DUMMY_UNITID, 9999., 9999., 0.)
        call UnitAddAbility(DUMMY[a], 'Aloc')
        set id = GetUnitId(DUMMY[a])
        set IS_SOME_DUMMY[id] = true
        set IS_IN_USE[id] = false
        set a = a + 1
    endloop
endfunction

This function is ran at map initialization. It should create a dummy unit and store a boolean for it (autoindex property) IS_IN_USE to false, which would refer if the unit is currently in use by some script.
Then I have a function that searches for a free dummy unit and if it finds one it assigns it to a global unit variable and makes its property to be in use.
JASS:

function GetAvailableDummy takes player p returns nothing
    local integer id  
    loop
        set dum = DUMMY[GetRandomInt(0, DUMMY_UNITS_CREATED)]
        set id = GetUnitId(dum)
        exitwhen (IS_IN_USE[id] == false)
    endloop
    call SetUnitOwner(dum, p, false)
    set IS_IN_USE[id] = true
endfunction


However, calling GetAvailableDummy seems to cause the massive spike and AutoIndex starts flooding my screen with some debug messages about indexing a unit that hasn't previously received an index. Could there be some reason that the first function that creates the units isn't working ?!

JASS:

library DummyLib initializer Init uses xebasic, Table, TimerUtils, AutoIndex, RegisterAnyUnitEvent

globals
    private constant real TIME = 5.
    private constant real WAIT = 0.28
endglobals

globals
    constant integer DUMMY_UNITS_CREATED = 100
endglobals

globals
    private HandleTable ht
endglobals

globals
    unit dum = null
endglobals

private function CreateDummyUnits takes nothing returns nothing
    local integer a = 0
    local integer id 
    loop
        exitwhen a > DUMMY_UNITS_CREATED
        set DUMMY[a] = CreateUnit(Player(13), XE_DUMMY_UNITID, 9999., 9999., 0.)
        call UnitAddAbility(DUMMY[a], 'Aloc')
        set id = GetUnitId(DUMMY[a])
        set IS_SOME_DUMMY[id] = true
        set IS_IN_USE[id] = false
        set a = a + 1
    endloop
endfunction

private struct Data
    unit dummy
    timer tim 
    
    private static method Callback takes nothing returns nothing
        call Data(ht[GetExpiredTimer()]).destroy()
    endmethod
    
    static method create takes unit dummy returns Data
        local Data d = Data.allocate()
        set d.dummy = dummy
        set d.tim = NewTimer()
        set ht[d.tim] = integer(d)
        call TimerStart(d.tim, TIME, false, function Data.Callback)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call ht.flush(.tim)
        call ReleaseTimer(.tim)
        call RemoveUnitEx(.dummy)
    endmethod
endstruct

private struct Release
    unit dum
    timer tim 
    
    private static method Callback takes nothing returns nothing
        call Release(ht[GetExpiredTimer()]).destroy()
    endmethod
    
    static method create takes unit dum returns Release
        local Release d = Release.allocate()
        set d.dum = dum
        set d.tim = NewTimer()
        set ht[d.tim] = integer(d)
        call TimerStart(d.tim, WAIT, false, function Release.Callback)
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call ReleaseTimer(.tim)
        call ht.flush(.tim)
        call SetUnitOwner(.dum, Player(13), false)
        set IS_IN_USE[GetUnitId(.dum)] = false
        call SetUnitX(.dum, 999.)
        call SetUnitY(.dum, 999.)
    endmethod
endstruct
    
private function Actions takes nothing returns nothing
    local unit dummy = GetTriggerUnit()
    local integer id = GetUnitId(dummy)
    if IS_SOME_DUMMY[id] == true then
        call Data.create(dummy)
    endif
    set dummy = null
endfunction

function GetAvailableDummy takes player p returns nothing
    local integer id  
    loop
        set dum = DUMMY[GetRandomInt(0, DUMMY_UNITS_CREATED)]
        set id = GetUnitId(dum)
        exitwhen (IS_IN_USE[id] == false)
    endloop
    call SetUnitOwner(dum, p, false)
    set IS_IN_USE[id] = true
endfunction

function ReleaseDummy takes unit dum returns nothing
    call Release.create(dum)
endfunction

function AddAndCastTarget takes unit dum, unit targ, integer aid, integer lvl, string oid returns nothing
    call UnitAddAbility(dum, aid)
    call SetUnitAbilityLevel(dum, aid, lvl)
    call IssueTargetOrder(dum, oid, targ)
endfunction

function AddAndCast takes unit dum, integer aid, integer lvl, string oid returns nothing
    call UnitAddAbility(dum, aid)
    call SetUnitAbilityLevel(dum, aid, lvl)
    call IssueImmediateOrder(dum, oid)
endfunction

private function Init takes nothing returns nothing
    call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_DEATH, null, function Actions)
    
    call CreateDummyUnits()
        
    set ht = HandleTable.create()
endfunction

endlibrary
 

Viikuna

No Marlo no game.
Reaction score
265
Why such a hassle? Cant you just use one global dummy to cast all stormbolts. ( Like in my AssAssTidies map ( link ) )
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top