[WIP] Unit Physics

Hektor

New Member
Reaction score
3
Hmm, this is just a project I'm working on. So far, all I've accomplished is Gravity.

Yes, I know it's not very optimized.

I'm just putting it together, at the moment. I'm planning on heavily optimizing it, so any tips and criticism are welcome.

(Yes, I know GetUnitDatas is used multiple times while unnecessary. I'm getting to addressing optimization still.)

Warning: Currently, all is in cJASS. A vJASS version will be up shortly after the cJASS edition is complete.

Also, one thing I was wondering, is using a key faster than StringHash?

JASS:
library Uphc initializer Ini
    globals
        private hashtable Hash = new hashtable;                 // Data storage
        private timer Timer = new timer;
    endglobals
    
    define {
        GetUnitDatas( Gud_unit ) = {                            // Automated data gathering!
            unit u = Gud_unit;
            int Id = GetHandleId( u );
            bool G = LoadBoolean( Hash, Id, Gravity );
            real S = LoadReal( Hash, Id, Speed );
            real M = LoadReal( Hash, Id, Mass );
            real T = LoadReal( Hash, Id, Time );
            real D = 0;
            bool F = LoadBoolean( Hash, Id, Friction );
        }
        
        Gravity = StringHash( "Gravity" );                      // Hash for Gravity
        Group = StringHash( "Group" );                          // Hash for Group
        Speed = StringHash( "Speed" );                          // Hash for Speed
        Mass = StringHash( "Mass" );                            // Hash for Mass
        Time = StringHash( "Time" );                            // Hash for Time
        Friction = StringHash( "Friction" );                    // Hash for Friction
        
        GInactive = 0;                                          // Index for Inactive
        GActive = 1;                                            // Index for Active
        FInactive = 2;                                          // Index for Inactive
        FActive = 3;                                            // Index for Inactive
        
        DefaultGravity = 16;                                    // Default Gravity
        DefaultSpeed = DefaultMass * DefaultGravity;            // Default Speed
        DefaultMass = 100.00;                                   // Default Mass
        DefaultDamage = 150.00;                                 // Default Damage
        MaxNoDamageFall = 0.25;                                 // Max fall height for no damage
        MASSPERCENTAGE = 0.05;                                  // Percentage of mass to decrease fall damage
        DefaultFriction = 0.1;                                  // Default Friction
    }
    
    private void GroupGravity( ) {                              // Group gravity
        GetUnitDatas( GetEnumUnit() );
        if Uchc_GetUnitZ( u ) <= 1 {
            if T > MaxNoDamageFall {
                D = T * DefaultDamage;
                SetUnitState( u, UNIT_STATE_LIFE, GetUnitState(u, UNIT_STATE_LIFE) - D + MASSPERCENTAGE * M );
            }
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, GActive), u );
            GroupAddUnit( LoadGroupHandle(Hash, Group, GInactive), u );
            T = 0;
            SaveReal( Hash, Id, Time, T );
            return
        }
        T = T + TimerGetTimeout(Timer);
        SaveReal( Hash, Id, Time, T );
        S = Pow( DefaultMass, T )
        SaveReal( Hash, Id, Speed, S);
        Uchc_SetUnitZ( u, Uchc_GetUnitZ(u) - S);
    }
    
    private void GravityValidation( ) {                         // Gravity validation
        GetUnitDatas( GetEnumUnit() );
        if G == true {
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, GInactive), u );
            GroupAddUnit( LoadGroupHandle(Hash, Group, GActive), u );
            
            return
        }
        GroupRemoveUnit( LoadGroupHandle(Hash, Group, GActive), u );
        GroupAddUnit( LoadGroupHandle(Hash, Group, GInactive), u );
    }
    
    private void GroupFriction( ) {                             // Group friction
    }
    
    private void FrictionValidation( ) {                        // Friction validation
        GetUnitDatas( GetEnumUnit() );
        if F == true {
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, FInactive), u );
            GroupAddUnit( LoadGroupHandle(Hash, Group, FActive), u );
            
            return
        }
        GroupRemoveUnit( LoadGroupHandle(Hash, Group, FActive), u );
        GroupAddUnit( LoadGroupHandle(Hash, Group, FInactive), u );
    }
    
    private void Periodic( ) {                                  // Main periodic
        group GI = LoadGroupHandle( Hash, Group, GInactive );
        group GA = LoadGroupHandle( Hash, Group, GActive );
        group FI = LoadGroupHandle( Hash, Group, FInactive );
        group FA = LoadGroupHandle( Hash, Group, FActive );
        
        ForGroup( GI, function GravityValidation );
        ForGroup( GA, function GravityValidation );
        
        ForGroup( GA, function GroupGravity );
        
        ForGroup( FI, function GravityValidation );
        ForGroup( FA, function GravityValidation );
        
        ForGroup( FA, function GroupFriction );
    }
    
    public void SetUnitFriction( unit whichUnit, bool flag ) {  // Friction toggle
        GetUnitDatas( whichUnit );
        if flag != F {
            SaveBoolean( Hash, Id, Friction, flag );
        }
        
        if flag == false {
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, FActive), whichUnit );
            GroupAddUnit( LoadGroupHandle(Hash, Group, FInactive), whichUnit );
        } else {
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, FInactive), whichUnit );
            GroupAddUnit( LoadGroupHandle(Hash, Group, FActive), whichUnit );
        }
    }
    
    public void SetUnitGravity( unit whichUnit, bool flag ) {   // Gravity toggle
        GetUnitDatas( whichUnit );
        if flag != G {
            SaveBoolean( Hash, Id, Gravity, flag );
        }
        
        if flag == false {
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, GActive), whichUnit );
            GroupAddUnit( LoadGroupHandle(Hash, Group, GInactive), whichUnit );
        } else {
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, GInactive), whichUnit );
            GroupAddUnit( LoadGroupHandle(Hash, Group, GActive), whichUnit );
        }
    }
    
    public void SetUnitMass( unit whichUnit, real mass ) {      // Mass config
        GetUnitDatas( whichUnit );
        SaveReal( Hash, Id, Mass, mass );
    }
    
    public real GetUnitMass( unit whichUnit ) {                 // mass config
        GetUnitDatas( whichUnit );
        return M;
    }
    
    private bool Leave( ) {                                     // Leave Flush
        GetUnitDatas( GetTriggerUnit() )
        if IsUnitType( u, UNIT_TYPE_DEAD ) {
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, GInactive), u );
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, GActive), u );
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, FInactive), u );
            GroupRemoveUnit( LoadGroupHandle(Hash, Group, FActive), u );
            FlushChildHashtable( Hash, Id );
        }
        
        return false;
    }
    
    private bool Enter( ) {                                     // Enter Add
        GetUnitDatas( GetFilterUnit() );
        if G == null {
            SaveBoolean( Hash, Id, Gravity, true );
            SaveReal( Hash, Id, Speed, DefaultSpeed );
            SaveReal( Hash, Id, Mass, DefaultMass );
            SaveReal( Hash, Id, Time, 0.00 );
            SaveBoolean( Hash, Id, Friction, true );
        }
        
        if UnitAddAbility( u, 'Amrf' ) {                        // AutoFly -Azlier
            UnitRemoveAbility( u, 'Amrf' );
        }
        
        GroupAddUnit( LoadGroupHandle(Hash, Group, GActive), u );
        GroupAddUnit( LoadGroupHandle(Hash, Group, FActive), u );
        
        return false;
    }
    
    private void Ini( ) {
        region r = new region;
        RegionAddRect( r, GetWorldBounds() );
        TriggerRegisterEnterRegion( new trigger, r, Filter(function Enter) );
        TriggerRegisterLeaveRegion( new trigger, r, Filter(function Leave) );
        SaveGroupHandle( Hash, Group, GInactive, new group );
        SaveGroupHandle( Hash, Group, GActive, new group );
        SaveGroupHandle( Hash, Group, FInactive, new group );
        SaveGroupHandle( Hash, Group, FActive, new group );
        TimerStart(Timer, Uchc_defaultTimer, true, function Periodic)
    }
endlibrary


JASS:
include "cj_types.j"
include "cj_typesEx.j"
include "cj_types_priv.j"
include "cj_typesEx_priv.j"

library Uchc initializer Ini
    globals
        public constant real defaultTimer = 0.0325;
        public constant real defaultFast  = 0.01;
        private location heightFixer = Location(0,0);
    endglobals
    
    define {
        msg(string) = DisplayTextToPlayer(GetLocalPlayer(), 0, 0, string);
    }
    
    public void SetUnitZ( unit whichUnit, real height ) {
        call MoveLocation( heightFixer, GetUnitX(whichUnit), GetUnitY(whichUnit) );
        call SetUnitFlyHeight( whichUnit, height-GetLocationZ(heightFixer), 0 );
    }
    
    public real GetUnitZ( unit whichUnit ) {
        call MoveLocation( heightFixer, GetUnitX(whichUnit), GetUnitY(whichUnit) );
        return GetUnitFlyHeight(whichUnit)-GetLocationZ(heightFixer);
    }
    
    void Ini( ) {
    }
endlibrary


Note: Hurrah, spoilers don't work (for people with low rep, I presume to decrease the amount of spoiler spam).
 

Jesus4Lyf

Good Idea™
Reaction score
397
Mm. Can't read your code, because it's cJass. Maybe others can. Chances are Nestharus will tell you things.

Hm. You seem to be attaching using hashtables instead of unituserdata and arrays.

AIDS/T32 will provide you with a powerful timer system handling everything and unit attachment which kicks the crap out of hashtables. :)

No more unit groups. ;)
 

Hektor

New Member
Reaction score
3
Hmm. To be honest, I don't think cJASS is all that different to read than vJASS :p The only differences are the missing "call" and "[end]function" keywords and the public/private ReturnType then function name, to name a few.

Anyways, Nes will, then I'll talk to him on MSN and he'll just say "Oh. It's you." Yeah.

As for AIDS/T32, I've (We've) used T32 for a projectile system and it was quite nice.

I just liked to use hashtables because in all honesty, I was lazy to setup a bunch of arrays.

Perhaps when I finish this, I'll convert it to AIDS or T32 and kick the crap out of this version.

And my question wasn't answered, which is better: keys (vJASS) or StringHash?
 

Jesus4Lyf

Good Idea™
Reaction score
397
Keys. (Sorry for missing the question.)

>I've (We've) used T32 for a projectile system and it was quite nice.
Cool. It is written for such things. :)

Thing with cJass is you have {;}s. I hate them.
JASS:
    define {
        GetUnitDatas( Gud_unit ) = {                            // Automated data gathering!
            unit u = Gud_unit;
            int Id = GetHandleId( u );
            bool G = LoadBoolean( Hash, Id, Gravity );
            real S = LoadReal( Hash, Id, Speed );
            real M = LoadReal( Hash, Id, Mass );
            real T = LoadReal( Hash, Id, Time );
            real D = 0;
            bool F = LoadBoolean( Hash, Id, Friction );
        }

I have no idea what that means. (I intend to continue to not know, as well.)
 

Hektor

New Member
Reaction score
3
Tis, alright. I learned something. So, other than converting it from hashtables, (if you can read it) what else is there?
 

Jesus4Lyf

Good Idea™
Reaction score
397
Not using unit groups...
JASS:
library Uchc initializer Ini
    globals
        public constant real defaultTimer = 0.0325;
        public constant real defaultFast  = 0.01;

Following standards... -->
JASS:
library PhysicsX initializer Ini
    globals
        public constant real DEFAULT_TIMER = 0.0325;
        public constant real DEFAULT_FAST  = 0.01;

At the end of the day it doesn't matter, keep updating your code and posting or whatever. I find it difficult to read at the moment, regardless of that I don't know cJass. I think you'd find it easier to write and maintain an AIDS/T32 struct.
JASS:
struct MyMagic extends array
    //! runtextmacro AIDS()
    real xVelocity
    real yVelocity
    private method periodic takes nothing returns boolean
        // Do some periodic stuff using .members
        return false
    endmethod
    implement T32
    private method AIDS_onCreate takes nothing returns nothing
        set .xVelocity=0
        set .yVelocity=0
    endmethod
    // call .startPeriodic somewhere...
endstruct

I dunno. Neat and easy kinda... I still need to make T32x. <_<
 

Hektor

New Member
Reaction score
3
Well, I'll keep updating, and some time will convert it to AIDS/T32.

And I'll do something about those groups, I suppose.

Currently, I'm working on a way to make friction. And friction that only affects coded movement. For example, knockback. Which then users won't have to have an acceleration an a deceleration. Just a straight speed and friction will take care of the rest.
 

Jesus4Lyf

Good Idea™
Reaction score
397
>Well, I'll keep updating, and some time will convert it to AIDS/T32.
>And I'll do something about those groups, I suppose.
Same thing.

>Currently, I'm working on a way to make friction. And friction that only affects coded movement. For example, knockback. Which then users won't have to have an acceleration an a deceleration. Just a straight speed and friction will take care of the rest.

>_< Is Nestharus your mentor?
You should forget what leaks are and write a map in GUI. :)
 

Hektor

New Member
Reaction score
3
Actually, I'm making a map right now, but not in GUI, though :p. Won't reveal what it is yet, though. This is part of it. Though, I should really work on other aspects of the map. However, this has to get done. Might as well do something. So, I decided to work, ultimately, on the Physics Engine.

>>_< Is Nestharus your mentor?

Why do you say that?
 

Hektor

New Member
Reaction score
3
Hmm.

Code:
Crappy
    Events
        Map initialization
    Conditions
    Actions
        Custom script:   call Nut.evaluate()
        Custom script:   endfunction
        Custom script:   function Doh takes nothing returns nothing
        Custom script:   call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Ha, ha! Does this count as crappy GUI?")
        Custom script:   endfunction
        Custom script:   function Nut takes nothing returns nothing
        For each (Integer A) from 1 to 12, do (Actions)
            Loop - Actions
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        True Equal to True
                    Then - Actions
                        Custom script:   call TimerStart(CreateTimer(), 0.0325, true, function Doh)
                    Else - Actions

Yes?

This is what it looks like in JASS:

JASS:
function Trig_Crappy_Func007Func001C takes nothing returns boolean
    if ( not ( true == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_Crappy_Actions takes nothing returns nothing
    call Nut.evaluate()
    endfunction
    function Doh takes nothing returns nothing
    call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;Ha, ha! Does this count as crappy GUI?&quot;)
    endfunction
    function Nut takes nothing returns nothing
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 12
    loop
        exitwhen bj_forLoopAIndex &gt; bj_forLoopAIndexEnd
        if ( Trig_Crappy_Func007Func001C() ) then
            call TimerStart(CreateTimer(), 0.0325, true, function Doh)
        else
        endif
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
endfunction

//===========================================================================
function InitTrig_Crappy takes nothing returns nothing
    set gg_trg_Crappy = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Crappy, function Trig_Crappy_Actions )
endfunction


So awkward looking.
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
My eyes burn of unefficienty when I see this, please remove that code! :mad:

And you're declaring functions inside of other functions. ?&?&?HJV
 

Jesus4Lyf

Good Idea™
Reaction score
397
>My eyes burn of unefficienty when I see this, please remove that code!
*Facepalms*
Your eyes burn because you stuck a lit matchstick in them. :p

Nice GUI. :thup:
(Actually I might do that in my maps. It seems like a practical way to code timer system stuff in GUI. o_O :p)

>Why do you say that?
Because well, it seems he's great at coming up with concepts where the practical implementation is irrelevant or unhelpful.

Like for friction: Did you know there is no point? Even if each thing processes friction by itself, it will be more efficient, and if you use T32 it will merge the SetUnitPosition/X/Ys in effect anyway (no chop from having two "slides" acting on one unit).
 

Lyerae

I keep popping up on this site from time to time.
Reaction score
105
> Your eyes burn because you stuck a lit matchstick in them.
Lolwut?

> And you're declaring functions inside of other functions.
Look at it, closely.

---

Code looks good, but I barely understand cJASS, so it could be completely wrong and I couldn't tell.
 

Hektor

New Member
Reaction score
3
Well, I just wanted to do friction because... Damn. I can't come up with a good response unless I tell you I'm working on Physics Wars :-/

Lol, let's use that method for all our timer system stuff then. I was actually surprised I didn't make a dumb mistake and it worked XD I was like "Cool."
 

Nestharus

o-o
Reaction score
84
Ok... there are so many issues with your code that o-o...

JASS:

    define {
        msg(string) = DisplayTextToPlayer(GetLocalPlayer(), 0, 0, string);
    }


prinft()...

I have no idea what that means. (I intend to continue to not know, as well.)

Jesus4Lyf, don't worry. When I first saw his little GetUnitDatas thing, I scratched my head for a second wondering wth it was ; P.

JASS:

define {
        GetUnitDatas( Gud_unit ) = {                            // Automated data gathering!
            unit u = Gud_unit;
            int Id = GetHandleId( u );
            bool G = LoadBoolean( Hash, Id, Gravity );
            real S = LoadReal( Hash, Id, Speed );
            real M = LoadReal( Hash, Id, Mass );
            real T = LoadReal( Hash, Id, Time );
            real D = 0;
            bool F = LoadBoolean( Hash, Id, Friction );
        }


zamg at that awful interface unless you planning to keep them private : |.

J4L, that's a function that you call within another function. That define creates that whole list of local vars in the function calling it, but here's the thing.. it bugs if it's used more than once? Why? You can't have 2 vars with the same given name. He's made quite a few mistakes here ><. He either needs to use the var name as part of the local, meaning that he'll even have more issues, or he needs to make it a private define that he uses within his own functions or something ><. How he has it right now is going to make it very difficult to use and "loads" of code. I don't believe the speed gain to the code ratio is worth it at all here.

JASS:

        Gravity = StringHash( &quot;Gravity&quot; );                      // Hash for Gravity
        Group = StringHash( &quot;Group&quot; );                          // Hash for Group
        Speed = StringHash( &quot;Speed&quot; );                          // Hash for Speed
        Mass = StringHash( &quot;Mass&quot; );                            // Hash for Mass
        Time = StringHash( &quot;Time&quot; );                            // Hash for Time
        Friction = StringHash( &quot;Friction&quot; );                    // Hash for Friction


This was said before, but these should all be keys

Next, you have a mass of groups and timers and it appears that you add all units to the gravity unit group or w/e... Uh... I seriously suggest you use a list because all of these group enumerations are going to literally rape you when you start actually using this in a map, especially if you plan to do them every .03125 seconds.

JASS:

    void Ini( ) {
    }


Should be private unless you like conflicting with other functions.

Finally
JASS:

define {
        GetUnitDatas( Gud_unit ) = {                            // Automated data gathering!
            unit u = Gud_unit;
            int Id = GetHandleId( u );
            bool G = LoadBoolean( Hash, Id, Gravity );
            real S = LoadReal( Hash, Id, Speed );
            real M = LoadReal( Hash, Id, Mass );
            real T = LoadReal( Hash, Id, Time );
            real D = 0;
            bool F = LoadBoolean( Hash, Id, Friction );
        }
        
        Gravity = StringHash( &quot;Gravity&quot; );                      // Hash for Gravity
        Group = StringHash( &quot;Group&quot; );                          // Hash for Group
        Speed = StringHash( &quot;Speed&quot; );                          // Hash for Speed
        Mass = StringHash( &quot;Mass&quot; );                            // Hash for Mass
        Time = StringHash( &quot;Time&quot; );                            // Hash for Time
        Friction = StringHash( &quot;Friction&quot; );                    // Hash for Friction
        
        GInactive = 0;                                          // Index for Inactive
        GActive = 1;                                            // Index for Active
        FInactive = 2;                                          // Index for Inactive
        FActive = 3;                                            // Index for Inactive
        
        DefaultGravity = 16;                                    // Default Gravity
        DefaultSpeed = DefaultMass * DefaultGravity;            // Default Speed
        DefaultMass = 100.00;                                   // Default Mass
        DefaultDamage = 150.00;                                 // Default Damage
        MaxNoDamageFall = 0.25;                                 // Max fall height for no damage
        MASSPERCENTAGE = 0.05;                                  // Percentage of mass to decrease fall damage
        DefaultFriction = 0.1;                                  // Default Friction
    }


This whole mess needs to either all be private or all needs to be named as so-
<Library.Definition>

or

Library_Definition

Don't care what you do, but atm none of that stuff is at all encapsulated, which is like asking for naming conflicts.


There is a whole other mess of things wrong... but I'd have to start picking away at everything. I'm sure there are a few other glaring things that'd hit me in the face from glancing at code, but those were the biggest ones : ). I'll glance again and even examine it for you if you like : P.
 

Gtam

Lerning how to write and read!! Yeah.
Reaction score
164
Well, I just wanted to do friction because... Damn. I can't come up with a good response unless I tell you I'm working on Physics Wars :-/

Lol, let's use that method for all our timer system stuff then. I was actually surprised I didn't make a dumb mistake and it worked XD I was like "Cool."


Im sorry but you working on Physics Wars was pretty obvious :D:D:D:D:D:D:D.
 

Hektor

New Member
Reaction score
3
zamg at that awful interface unless you planning to keep them private : |.

'Course I do.

Should be private unless you like conflicting with other functions.

Whoops. I thought I made it private.

There is a whole other mess of things wrong... but I'd have to start picking away at everything. I'm sure there are a few other glaring things that'd hit me in the face from glancing at code, but those were the biggest ones : ). I'll glance again and even examine it for you if you like : P.

Yes, do that please.

And about that encapsulation, I plan on converting it to vJASS, then, when it's converted, all of those defines will have been processed and I'll go through and optimize that way.

As for the list, Linked Lists?
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Varine Varine:
    How can you tell the difference between real traffic and indexing or AI generation bots?
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/

      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