System unitgroup

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
unitgroup is an attempt to replace the [ljass]native group[/ljass] type with a non native one (a struct type)
which is much easier to work with and is hopefully faster =).

Reasons that make the native group type "hard" to work with is that it doesn't know it's size (how many units there are),
requires enumeration callbacks (ForGroup) or FirstOfGroup enumerating for every operation performed on the group including
counting the number of units which are not really a good practice and doesn't have random access.

Requirements:
jasshelper compiler by Vexorian​
AutoIndex by grim001 or​
UnitIndexer by Nestharus​


The API is presented in C/C++ / C# / cJass / Galaxy Script function notation for brevity in pairs in which the
top one is the [ljass]group[/ljass] function name (if present) and the bottom is the [ljass]unitgroup[/ljass] alternative:

[ljass]group CreateGroup()[/ljass]
[ljass]static unitgroup new()[/ljass]

-- no native or bj available but possible --
[ljass]static unitgroup copy(unitgroup which_unitgroup)[/ljass]

[ljass]void GroupClear(group g)[/ljass]
[ljass]void clear()[/ljass]

[ljass]void DestroyGroup(group g)[/ljass]
[ljass]void delete()[/ljass]

[ljass]void GroupRemoveUnit(group g, unit u)[/ljass]
[ljass]void remove_unit(unit u)[/ljass]

[ljass]void GroupAddUnit(group g, unit u)[/ljass]
[ljass]void push_unit(unit u)[/ljass]

[ljass]bool IsUnitInGroup(unit u, group g)[/ljass]
[ljass]bool has_unit(unit u)[/ljass]

[ljass]unit GroupPickRandomUnit(group g)[/ljass]
[ljass]unit random_unit()[/ljass]

[ljass]void GroupEnumUnitsOfType(group g, string unitname, boolexpr filter)[/ljass]
[ljass]void enum_units_by_id(int id, int player, int max_count)[/ljass]

[ljass]void GroupEnumUnitsOfTypeCounted(group g, string unitname, boolexpr filter, int max_count)[/ljass]
[ljass]void enum_units_by_id(int id, int p, int max_count)[/ljass]

[ljass]void GroupEnumUnitsOfPlayer(group g, player p, boolexpr filter)[/ljass]
[ljass]void enum_units_of_player(int p, int max_count)[/ljass]

[ljass]void GroupEnumUnitsInRect(group g, rect r, boolexpr filter)[/ljass]
[ljass]void enum_units_in_rect(rect r, int p, int max_count)[/ljass]

[ljass]void GroupEnumUnitsInRectCounted(group g, rect r, boolexpr filter, int max_count)[/ljass]
[ljass]void enum_units_in_rect(rect r, int p, int max_count)[/ljass]

[ljass]void GroupEnumUnitsInRange(group g, real x, real y, real radius, boolexpr filter)[/ljass]
[ljass]void enum_units_in_range(real x, real y, real radius, int p, int max_count)[/ljass]

[ljass]void GroupEnumUnitsInRangeCounted(group g, real x, real y, real radius, boolexpr filter, int max_count)[/ljass]
[ljass]void enum_units_in_range(real x, real y, real radius, int p, int max_count)[/ljass]

[ljass]void GroupEnumUnitsSelected(group g, player p, boolexpr filter)[/ljass]
[ljass]void enum_units_selected_by_player(int p, int max_count)[/ljass]

[ljass]bool GroupImmediateOrderById(group g, int order)[/ljass]
[ljass]void immediate_order(int order)[/ljass]

[ljass]bool GroupPointOrderById(group g, int order, real x, real y)[/ljass]
[ljass]void point_order(int order, real x, real y)[/ljass]

[ljass]bool GroupTargetOrderById(group g, int order, widget target)[/ljass]
[ljass]void target_order(int order, widget target)[/ljass]

-- no native or bj available but possible --
[ljass]unit nearest_unit_from_point(real x, real y)[/ljass]

-- no native or bj available but possible --
[ljass]unit nearest_unit_from_unit(unit u)[/ljass]

[ljass]void ForGroup(group g, code callback)[/ljass]
JASS:
// equivalent in Zinc notation:

integer i = 0;
unit u;
for (0 <= i < |unitgroup_instance|.size)
{
    u = |unitgroup_instance|<i>;
    // do stuff with u
}
</i>


[ljass]unit FirstOfGroup(group g)[/ljass]
[ljass]|unitgroup_instance|[0][/ljass]

[ljass]int CountUnitsInGroup(group g)[/ljass]
[ljass]|unitgroup_instance|.size[/ljass]


JASS:
library unitgroup uses optional AutoIndex, optional UnitIndexer

    globals
    
    private constant boolean USE_ARRAYS_FOR_STORAGE = true
   
    // if the above constant is true then only 
    // UNITGROUP_MAX_INSTANCES unitgroups are allowed
    // each with maximum size of UNITGROUP_MAX_SIZE units
    private constant integer UNITGROUP_MAX_INSTANCES = 320
    private constant integer UNITGROUP_MAX_SIZE      = 1024
    private unit array UGC[UNITGROUP_MAX_INSTANCES][UNITGROUP_MAX_SIZE]
    // Note: UNITGROUP_MAX_INSTANCES * UNITGROUP_MAX_SIZE &lt;= 409 550 must be true
    //       else a compile time error will pop

    // else if the above constant is false then
    // 8190 unitgroups are allowed each with
    // an &quot;unlimited&quot; (limited by ram only) amount of units
    private hashtable HT

    // in terms of speed the 2d array (UGC) should be faster
    // so set the constant to true if you prefer speed
    // else set it to false if you want to be safe than sorry =)

    endglobals




    globals

    // used in some enum&lt;*&gt; methods
    constant integer ANY_PLAYER   = -1

    // could be used in all enum&lt;*&gt; methods
    constant integer NO_MAX_COUNT = 0

    private unit    array Units
    private integer       Units_count = 0

    endglobals

    private struct indexer extends array

    static if LIBRARY_AutoIndex then

        static method index takes unit u returns nothing
            set Units[Units_count] = u
            set Units_count = Units_count + 1
        endmethod

        static method deindex takes unit u returns nothing
            local integer i          = 0
            local integer unit_index = 0

            loop
                exitwhen  i &gt;= Units_count
                if Units<i> == u then
                    set unit_index = i
                    exitwhen true
                endif

                set i = i + 1
            endloop

            set Units[unit_index] = Units[Units_count - 1]
            set Units_count = Units_count - 1
        endmethod

        static method onInit takes nothing returns nothing
            call OnUnitIndexed(indexer.index)
            call OnUnitDeindexed(indexer.deindex)
        endmethod

    elseif LIBRARY_UnitIndexer then

        method index takes nothing returns nothing
            set Units[Units_count] = unit
            set Units_count = Units_count + 1
        endmethod

        method deindex takes nothing returns nothing
            local integer i          = 0
            local integer unit_index = 0

            loop
                exitwhen  i &gt;= Units_count
                if Units<i> == unit then
                    set unit_index = i
                    exitwhen true
                endif

                set i = i + 1
            endloop

            set Units[unit_index] = Units[Units_count - 1]
            set Units_count = Units_count - 1

        endmethod
        
        implement optional UnitIndexStruct

    else
        compiletimeexeption e = &quot;You need a unit indexing library =)&quot;
        throw e
    endif

    endstruct


           
    struct unitgroup

        // the number of units in the unitgroup
        readonly integer size


        //! textmacro unitgroup_assert_size takes METHOD_NAME, RETURN_VALUE
                debug if size &lt;= 0 then
                debug     call BJDebugMsg(&quot;unitgroup error: method $METHOD_NAME$: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: unitgroup is empty&quot;)
                debug     return $RETURN_VALUE$
                debug endif
        //! endtextmacro

        method operator[] takes integer i returns unit
            debug if  i &lt; 0 or i &gt;= size  then
            debug     call BJDebugMsg(&quot;unitgroup error: method operator[]: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: array index out of bounds&quot;)
            debug     return null
            debug endif

            static if USE_ARRAYS_FOR_STORAGE then
                return UGC[this]<i>
            else
                return LoadUnitHandle(HT, this, i)
            endif
        endmethod

        method operator[]= takes integer i, unit u returns nothing
            debug if  i &lt; 0 or i &gt;= size  then
            debug     call BJDebugMsg(&quot;unitgroup error: method operator[]=: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: array index out of bounds&quot;)
            debug     return
            debug endif

            static if USE_ARRAYS_FOR_STORAGE then
                set UGC[this]<i> = u
            else
                call SaveUnitHandle(HT, this, i, u)
            endif
        endmethod

        method has_unit takes unit which_unit returns boolean
            local integer i     = 0
            local unit    u     = null
            local boolean found = false

            //! runtextmacro unitgroup_assert_size(&quot;has_unit&quot;, &quot;false&quot;)

            loop
                exitwhen i &gt;= size

                static if USE_ARRAYS_FOR_STORAGE then
                    set u = UGC[this]<i>
                else
                    set u = LoadUnitHandle(HT, this, i)
                endif

                if u == which_unit then
                    set found = true
                    exitwhen true
                endif

                set i = i + 1
            endloop
        
            set u = null
            return found
        endmethod

        method remove_unit takes unit u returns nothing
            local integer i          = 0
            local integer unit_index = -1

            //! runtextmacro unitgroup_assert_size(&quot;remove_unit&quot;, &quot;&quot;)

            if u == null then
                debug call BJDebugMsg(&quot;unitgroup error: method remove_unit: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: attempt to remove null unit&quot;)
                return
            endif
            
            loop
                exitwhen i &gt;= size
                static if USE_ARRAYS_FOR_STORAGE then
                    if u == UGC[this]<i> then
                        set unit_index = i
                        exitwhen true
                    endif
                else
                    if u == LoadUnitHandle(HT, this, i) then
                        set unit_index = i
                        exitwhen true
                    endif
                endif
    
                set i = i + 1
            endloop
                        
            // if the unit was found
            if unit_index != -1 then
                static if USE_ARRAYS_FOR_STORAGE then
                    set UGC[this][unit_index] = UGC[this][size -1]
                    set size = size - 1
                else                        
                    call SaveUnitHandle(HT, this, unit_index, LoadUnitHandle(HT, this, size - 1))
                    set size = size -1
                endif
            endif
        endmethod

        method push_unit takes unit u returns nothing
            static if USE_ARRAYS_FOR_STORAGE then
                set UGC[this][size] = u
            else
                call SaveUnitHandle(HT, this, size, u)
            endif
            set size = size + 1
        endmethod

        method random_unit takes nothing returns unit

            //! runtextmacro unitgroup_assert_size(&quot;random_unit&quot;, &quot;null&quot;)

            static if USE_ARRAYS_FOR_STORAGE then
                return UGC[this][GetRandomInt(0, size -1)]
            else
                return LoadUnitHandle(HT, this, GetRandomInt(0, size - 1))
            endif
        endmethod


        method enum_units_of_player takes integer p, integer max_count returns nothing
            local integer i = 0
            local integer n = 0
            local player  P = null
            local unit    u = null                       

            if p == ANY_PLAYER then
                debug call BJDebugMsg(&quot;unitgroup error: method enum_units_of_player: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: expected a specific player not ANY_PLAYER&quot;)
                return
            endif

            set P = Player(p)
    
            loop
                exitwhen i &gt;= Units_count or (n &gt;= max_count and max_count != NO_MAX_COUNT)
                               
                set u = Units<i>
                if P == GetOwningPlayer(u) then

                    // push the unit
                    static if USE_ARRAYS_FOR_STORAGE then
                        set UGC[this][size] = u
                    else
                        call SaveUnitHandle(HT, this, size, u)
                    endif
                    set size = size + 1 
                endif

                set i = i + 1
                set n = n + 1
            endloop

            set u = null
        endmethod

        method enum_units_by_id takes integer id, integer p, integer max_count returns nothing
            local integer i = 0
            local integer n = 0
            local player  P = null
            local unit    u = null

            if id == 0 then
                debug call BJDebugMsg(&quot;unitgroup error: method enum_units_by_id: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: invalid unit id&quot;)
                return
            endif

            if p != ANY_PLAYER then
                set P = Player(p)
            endif
            
            loop
                exitwhen i &gt;= Units_count or (n &gt;= max_count and max_count != NO_MAX_COUNT)
                               
                set u = Units<i>
                if (p == ANY_PLAYER or P == GetOwningPlayer(u)) and id == GetUnitTypeId(u) then

                    static if USE_ARRAYS_FOR_STORAGE then
                        set UGC[this][size] = u
                    else
                        call SaveUnitHandle(HT, this, size, u)
                    endif
                    set size = size + 1 
                endif

                set i = i + 1
                set n = n + 1
            endloop

            set u = null
        endmethod

        method enum_units_in_rect takes rect r, integer p, integer max_count returns nothing
            local integer i    = 0
            local integer n    = 0
            local player  P    = null
            local unit    u    = null
            local real    ux   = 0
            local real    uy   = 0
            local real    minx = 0
            local real    maxx = 0
            local real    miny = 0
            local real    maxy = 0

            if r == null then
                debug call BJDebugMsg(&quot;unitgroup error: method enum_units_in_rect: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: expected a non null rect&quot;)
                return
            endif

            if p != ANY_PLAYER then
                set P = Player(p)
            endif

            set minx = GetRectMinX(r)
            set maxx = GetRectMaxX(r)
            set miny = GetRectMinY(r)
            set maxy = GetRectMaxY(r)
            
            loop
                exitwhen i &gt;= Units_count or (n &gt;= max_count and max_count != NO_MAX_COUNT)
                               
                set u = Units<i>
                set ux = GetUnitX(u)
                set uy = GetUnitY(u)
                if (p == ANY_PLAYER or P == GetOwningPlayer(u)) and minx &lt; ux and ux &lt; maxx and miny &lt; uy and uy &lt; maxy then

                    static if USE_ARRAYS_FOR_STORAGE then
                        set UGC[this][size] = u
                    else
                        call SaveUnitHandle(HT, this, size, u)
                    endif
                    set size = size + 1 
                endif

                set i = i + 1
                set n = n + 1
            endloop

            set u = null
        endmethod

        method enum_units_in_range takes real x, real y, real radius, integer p, integer max_count returns nothing
            local integer i = 0
            local integer n = 0
            local player  P = null
            local unit    u = null

            if radius &lt;= 0 then
                debug call BJDebugMsg(&quot;unitgroup error: method enum_units_in_range: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: invalid radius&quot;)
                return
            endif

            if p != ANY_PLAYER then
                set P = Player(p)
            endif

            loop
                exitwhen i &gt;= Units_count or (n &gt;= max_count and max_count != NO_MAX_COUNT)
                               
                set u = Units<i>
                if (p == ANY_PLAYER or P == GetOwningPlayer(u)) and IsUnitInRangeXY(u, x, y, radius) then

                    static if USE_ARRAYS_FOR_STORAGE then
                        set UGC[this][size] = u
                    else
                        call SaveUnitHandle(HT, this, size, u)
                    endif
                    set size = size + 1 
                endif

                set i = i + 1
                set n = n + 1
            endloop

            set u = null
        endmethod

        method enum_units_selected_by_player takes integer p, integer max_count returns nothing
            local integer i = 0
            local integer n = 0
            local player  P = null
            local unit    u = null

            if p == ANY_PLAYER then
                debug call BJDebugMsg(&quot;unitgroup error: method enum_units_selected_by_player: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: expected a specific player not ANY_PLAYER&quot;)
                return
            endif

            set P = Player(p)

            loop
                exitwhen i &gt;= Units_count or (n &gt;= max_count and max_count != NO_MAX_COUNT)
                               
                set u = Units<i>
                if IsUnitSelected(u, P) then

                    static if USE_ARRAYS_FOR_STORAGE then
                        set UGC[this][size] = u
                    else
                        call SaveUnitHandle(HT, this, size, u)
                    endif
                    set size = size + 1 
                endif

                set i = i + 1
                set n = n + 1
            endloop

            set u = null
        endmethod


        method immediate_order takes integer order returns nothing
            local integer i = 0
            local unit    u = null

            //! runtextmacro unitgroup_assert_size(&quot;immediate_order&quot;, &quot;&quot;)

            if order == 0 then
                debug call BJDebugMsg(&quot;unitgroup error: method immediate_order: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: ivalid order&quot;)
                return
            endif

            loop
                exitwhen i &gt;= size

                static if USE_ARRAYS_FOR_STORAGE then
                    set u = UGC[this]<i>
                else
                    set u = LoadUnitHandle(HT, this, i)
                endif

                call IssueImmediateOrderById(u, order)

                set i = i + 1
            endloop

            set u = null
        endmethod

        method point_order takes integer order, real x, real y returns nothing
            local integer i = 0
            local unit    u = null

            //! runtextmacro unitgroup_assert_size(&quot;point_order&quot;, &quot;&quot;)

            if order == 0 then
                debug call BJDebugMsg(&quot;unitgroup error: method point_order: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: ivalid order&quot;)
                return
            endif

            loop
                exitwhen i &gt;= size

                static if USE_ARRAYS_FOR_STORAGE then
                    set u = UGC[this]<i>
                else
                    set u = LoadUnitHandle(HT, this, i)
                endif

                call IssuePointOrderById(u, order, x, y)

                set i = i + 1
            endloop

            set u = null
        endmethod

        method target_order takes integer order, widget target returns nothing
            local integer i = 0
            local unit    u = null

            //! runtextmacro unitgroup_assert_size(&quot;target_order&quot;, &quot;&quot;)

            if order == 0 then
                debug call BJDebugMsg(&quot;unitgroup error: method target_order: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: ivalid order&quot;)
                return
            elseif target == null then
                debug call BJDebugMsg(&quot;unitgroup error: method target_order: &quot; + &quot;instance id = &quot; + I2S(this) + &quot;: expected a non null target&quot;)
                return
            endif

            loop
                exitwhen i &gt;= size

                static if USE_ARRAYS_FOR_STORAGE then
                    set u = UGC[this]<i>
                else
                    set u = LoadUnitHandle(HT, this, i)
                endif

                call IssueTargetOrderById(u, order, target)

                set i = i + 1
            endloop

            set u = null
        endmethod


        method nearest_unit_from_point takes real x, real y returns unit
            local integer i                 = 0
            local unit    u                 = null
            local real    ux                = 0
            local real    uy                = 0
            local real    curr_min_distance = 9999999
            local unit    nearest_unit      = null
            local real    dx                = 0
            local real    dy                = 0
            local real    distance          = 0

            //! runtextmacro unitgroup_assert_size(&quot;nearest_unit_from_point&quot;, &quot;null&quot;)

            loop
                exitwhen i &gt;= size

                static if USE_ARRAYS_FOR_STORAGE then
                    set u = UGC[this]<i>
                else
                    set u = LoadUnitHandle(HT, this, i)
                endif
                
                set ux = GetUnitX(u)
                set uy = GetUnitY(u)
                set dx = ux - x
                set dy = uy - y
                set distance = SquareRoot(dx * dx + dy * dy)

                if curr_min_distance &gt; distance then
                    set curr_min_distance = distance
                    set nearest_unit = u
                endif

                set i = i + 1
            endloop
                    
            set u = null

            return nearest_unit
        endmethod

        method nearest_unit_from_unit takes unit which_unit returns unit
            local integer i                 = 0
            local unit    u                 = null
            local real    ux                = 0
            local real    uy                = 0
            local real    curr_min_distance = 9999999
            local unit    nearest_unit      = null
            local real    dx                = 0
            local real    dy                = 0
            local real    distance          = 0
            local real    x                 = GetUnitX(which_unit)
            local real    y                 = GetUnitY(which_unit)

            //! runtextmacro unitgroup_assert_size(&quot;nearest_unit_from_unit&quot;, &quot;null&quot;)

            loop
                exitwhen i &gt;= size

                static if USE_ARRAYS_FOR_STORAGE then
                    set u = UGC[this]<i>
                else
                    set u = LoadUnitHandle(HT, this, i)
                endif

                if u != which_unit then
                
                    set ux = GetUnitX(u)
                    set uy = GetUnitY(u)
                    set dx = ux - x
                    set dy = uy - y
                    set distance = SquareRoot(dx * dx + dy * dy)

                    if curr_min_distance &gt; distance then
                        set curr_min_distance = distance
                        set nearest_unit = u
                    endif

                endif

                set i = i + 1
            endloop
                    
            set u = null

            return nearest_unit
        endmethod


        static method new takes nothing returns unitgroup
            local unitgroup ug = allocate()

            debug static if USE_ARRAYS_FOR_STORAGE then
            debug    if integer(ug) &gt; UNITGROUP_MAX_INSTANCES then
            debug        call BJDebugMsg(&quot;unitgroup error: constructor: out of unitgroups&quot;)
            debug        return unitgroup(0)
            debug    endif
            debug  endif

            set ug.size = 0

            return ug
        endmethod

        static method copy takes unitgroup which_unitgroup returns unitgroup
            local unitgroup ug = allocate()
            local integer   i  = 0

            debug static if USE_ARRAYS_FOR_STORAGE then
            debug    if integer(ug) &gt; UNITGROUP_MAX_INSTANCES then
            debug        call BJDebugMsg(&quot;unitgroup error: copy constructor: out of unitgroups&quot;)
            debug        return unitgroup(0)
            debug    endif
            debug  endif

            loop
                exitwhen i &gt;= which_unitgroup.size

                static if USE_ARRAYS_FOR_STORAGE then
                    set UGC[ug]<i> = UGC[which_unitgroup]<i>
                else
                    call SaveUnitHandle(HT, ug, i, LoadUnitHandle(HT, which_unitgroup, i))
                endif

                set i = i + 1
            endloop

            set ug.size = which_unitgroup.size

            return ug
        endmethod

        method clear takes nothing returns nothing
            set size = 0
        endmethod

        method delete takes nothing returns nothing
            call deallocate()
        endmethod

        private static method onInit takes nothing returns nothing
            static if USE_ARRAYS_FOR_STORAGE then
            else
                set HT = InitHashtable()
            endif
        endmethod

    endstruct
    
endlibrary
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
A good idea, but a linked list group will be much faster.
And someone already benchmarked custom group, it is still slower than native group.

So, there is no point to reinvent the wheel.
 

Laiev

Hey Listen!!
Reaction score
188
[ljass]library unitgroup uses optional AutoIndex, optional UnitIndexer[/ljass]

AutoIndex? Serious? You should support AIDS instead of AutoIndex.

Not everyone code in [ljass]zinc[/ljass], so you should change this:

[ljass]unit random_unit()[/ljass]

Sorry but is just bad.

[ljass].unitRandom() -> unit[/ljass]

And so for the others.
 

Laiev

Hey Listen!!
Reaction score
188
JASS:
/*~*/
        private static method onInit takes nothing returns nothing
            static if USE_ARRAYS_FOR_STORAGE then
            else
                set HT = InitHashtable()
            endif
        endmethod


Why not:

JASS:
/*~*/
        private static method onInit takes nothing returns nothing
            static if not USE_ARRAYS_FOR_STORAGE then
                set HT = InitHashtable()
            endif
        endmethod


Or better:

JASS:
/*~*/
        private module M
            private static method onInit takes nothing returns nothing
                static if not USE_ARRAYS_FOR_STORAGE then
                    set HT = InitHashtable()
                endif
            endmethod
        endmodule
        private struct S extends array
            implement M
        endstruct


?

Also you leak your function of nearest unit :)
 

tooltiperror

Super Moderator
Reaction score
231
Idea has been revisited many times. Speed gains are negligible (or nonexistent) and this has been debated ad nauseam.

Graveyarded unless a very strong rebuttal is provided to the points in the GroupTools thread.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Howdy
  • 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 Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top