FANDOM


Created by Cysis on the RealmCrafter: Community Edition forums.

Before starting this tut please backup all your work!

Right one of the classic features of RCS's stupidity is trying to Render everything at once. This causes low fps rates and limits the amount of detail you can have in your zones. LOD fixes this and tells your client only to render certain models depending on the players range to them, without affecting certain models for example terrain.

Scenery LOD First start by Opening your Client.bb file. Find the section that looks like this...

CameraProjMode(GY_Cam, 1)
   ; Render GUI
   CameraProjMode(Cam, 0)
   For S.Scenery = Each Scenery
      HideEntity(S\EN)
   Next
   For T.Terrain = Each Terrain
      HideEntity(T\EN)
   Next
   RenderWorld()
   CameraProjMode(Cam, 1)
   For S.Scenery = Each Scenery
      ShowEntity(S\EN)
   Next
   For T.Terrain = Each Terrain
      ShowEntity(T\EN)
   Next
   PostRenderWorld()   ; DebugBanner update
   UpdateFPS()

And replace it with....

 CameraProjMode(GY_Cam, 1)
   ; Render GUI
   CameraProjMode(Cam, 0)
   For S.Scenery = Each Scenery
      HideEntity(S\EN)
   Next
   For T.Terrain = Each Terrain
      HideEntity(T\EN)
   Next
   RenderWorld()
   CameraProjMode(Cam, 1)
   For S.Scenery = Each Scenery
   
      ;LOD scenery
      Select S\SceneryType$
         
         Case "T"
            ShowEntity(S\EN) 
         Case "B"
             If EntityDistance#(S\EN, Cam) < BuildingMaxViewDistance#
                ShowEntity(S\EN) 
            Else
                HideEntity(S\EN)
            EndIf
         Case "G"
            If EntityDistance#(S\EN, Cam) < GrassMaxViewDistance#
                ShowEntity(S\EN) 
            Else
                HideEntity(S\EN)
            EndIf
         Case "Z"
            If EntityDistance#(S\EN, Cam) < ObjectMaxViewDistance#
               ShowEntity(S\EN)
            Else
               HideEntity(S\EN)
            EndIf
         Default 
            ShowEntity(S\EN) 
            
      End Select 
   Next
   For T.Terrain = Each Terrain
      ShowEntity(T\EN)
   Next
   PostRenderWorld()   ; DebugBanner update
   UpdateFPS()

Next open ClientAreas.bb and find...

Type Scenery
   Field SceneryID ; Set by user, used for scenery ownerships
   Field EN, MeshID
   Field AnimationMode ; 0 = no animation, 1 = constant animation (loops), 2 = constant (ping-pongs), 3 = animate when selected
   Field ScaleX#, ScaleY#, ScaleZ#
   Field Lightmap$     ; Lightmap filename
   Field RCTE$         ; Used by toolbox editors only
   Field TextureID     ; To alter the texture loaded automatically with the model, if required (65535 to ignore)
   Field CatchRain
   Field Locked
End Type

And add this at the end...

Field SceneryType$ ;Variable declaration for view distance

Should now look like this...

Type Scenery
   Field SceneryID ; Set by user, used for scenery ownerships
   Field EN, MeshID
   Field AnimationMode ; 0 = no animation, 1 = constant animation (loops), 2 = constant (ping-pongs), 3 = animate when selected
   Field ScaleX#, ScaleY#, ScaleZ#
   Field Lightmap$     ; Lightmap filename
   Field RCTE$         ; Used by toolbox editors only
   Field TextureID     ; To alter the texture loaded automatically with the model, if required (65535 to ignore)
   Field CatchRain
   Field Locked
   Field SceneryType$ ;Variable declaration for view distance
End Type

Under this section add. these are your ranges for the Fade in and Fade out

;LOD (Set view distances here)
Const BuildingMinViewDistance# = 230.0 ; If distance < this value will be Visible, else will autofade slowly
Const BuildingMaxViewDistance# = 250.0 ; If distance > this value will be 100% invisible
Const GrassMinViewDistance# = 75.0
Const GrassMaxViewDistance# = 90.0
Const ObjectMinViewDistance# = 130.0
Const ObjectMaxViewDistance# = 150.0

Should now look like 

Type Scenery
   Field SceneryID ; Set by user, used for scenery ownerships
   Field EN, MeshID
   Field AnimationMode ; 0 = no animation, 1 = constant animation (loops), 2 = constant (ping-pongs), 3 = animate when selected
   Field ScaleX#, ScaleY#, ScaleZ#
   Field Lightmap$     ; Lightmap filename
   Field RCTE$         ; Used by toolbox editors only
   Field TextureID     ; To alter the texture loaded automatically with the model, if required (65535 to ignore)
   Field CatchRain
   Field Locked
   Field SceneryType$ ;Variable declaration for view distance Ramoida
End Type

;LOD (Set view distances here)
Const BuildingMinViewDistance# = 230.0 ; If distance < this value will be Visible, else will autofade slowly
Const BuildingMaxViewDistance# = 250.0 ; If distance > this value will be 100% invisible
Const GrassMinViewDistance# = 75.0
Const GrassMaxViewDistance# = 90.0
Const ObjectMinViewDistance# = 130.0
Const ObjectMaxViewDistance# = 150.0

Next Scroll down and find 

 If S\EN <> 0
            ; Toolbox extras
            If Len(S\RCTE$) > 5
               Select Left$(S\RCTE$, 5)
                  Case "_TREE"
                     If DisplayItems = False
                        swingsty = Int(Mid$(S\RCTE$, 6, 1))
                        evergrn = Int(Mid$(S\RCTE$, 7, 1))
                        S\EN = LoadTree("", evergrn, S\EN, swingsty)
                     EndIf
                  Case "_GRSS"
                     swingsty = Int(Mid$(S\RCTE$, 6, 1))
                     evergrn = Int(Mid$(S\RCTE$, 7, 1))
                     S\EN = LoadGrass("", evergrn, S\EN, swingsty)
                  Case "_RCDN"
                     If DisplayItems = False
                        RotateMesh(S\EN, Pitch#, Yaw#, Roll#)
                        ScaleEntity(S\EN, S\ScaleX#, S\ScaleY#, S\ScaleZ#)
                        ChunkTerrain(S\EN, 3, 3, 3, X#, Y#, Z#)
                        Delete S
                        Goto CancelScenery
                     EndIf
               End Select
            EndIf

            ; Set position/rotation
            PositionEntity S\EN, X#, Y#, Z# : RotateEntity S\EN, Pitch#, Yaw#, Roll#
            ScaleEntity S\EN, S\ScaleX#, S\ScaleY#, S\ScaleZ#

Underneath it add

;LOD 
            S\SceneryType$ = "" ;initiate the variable just in case
            If Instr(Name$, "RCTE\") ;these folders wont be affected by LOD, this is so that models that have actors on it wont disappear causing the actors to fall 
S\SceneryType$ = "T" ;If it is Terrain, mark it as "T" ;This will be used at Client.bb
            ;;BUILDINGS
             ElseIf Instr(Name$, "BUILDINGS\")
S\SceneryType$ = "B" 
               EntityAutoFade S\EN,BuildingMinViewDistance#,BuildingMaxViewDistance#;If it is an object set autofade
            ;GRASS
            ElseIf Instr(Name$, "GRASS\")
S\SceneryType$ = "G"
               EntityAutoFade S\EN, GrassMinViewDistance#, GrassMaxViewDistance#
               
            ElseIf Instr(Name$, "OBJECTS\")
               S\SceneryType$ = "Z"
               EntityAutoFade S\EN, ObjectMinViewDistance#, ObjectMaxViewDistance#
               
            EndIf

That section is your file Directories for the different ranges. It has been Set up to already look into your \Data\Meshes folder so you need to add the folders of your models yourself. The way you do this is using

Instr(Name$, "FOLDERNAME\")

But if you want more than one folder of models affected by that LOD range then simply add.

Or Instr(Name$, "FOLDERNAME2\")

Next to it on the same line so it looks a bit like

Instr(Name$, "FOLDERNAME\") Or Instr(Name$, "FOLDERNAME2\")

etc. YOU MUST WRITE FOLDER NAMES IN CAPITALS EVEN IF THEY ARE NOT NAMED WITH CAPITALS also you must have \ at the end of the name or it wont work. Any folder that isn't listed in these three sections simply wont be affected by LOD and will continue to render as usual.

I believe thats it for scenery LOD give it a try and please post if it's not working i may have missed something.

Actor LOD This one is much simpler to set up. Open your Client.bb and find under Function UpdateActorInstances()

SetPickModes()

   ; Updates for every actor
   For AI.ActorInstance = Each ActorInstance

      ; If it's not dead
      If AI\Attributes\Value[HealthStat] > 0
         ; Fade in (uses \AIMode field which is a server field, to save adding an extra field and using server memory)
         ; DISABLE - uses entityautofade instead
;         If AI\AIMode < 501
;            If AI = Me Or AI = Me\Mount Then AI\AIMode = 499 ; The player and the player's mount do not fade in
;            AI\AIMode = AI\AIMode + 2
;            Alpha# = Float#(AI\AIMode) / 501.0
;            EntityAlpha AI\EN, Alpha#
;            EntityAlpha AI\ShadowEN, Alpha#
;            If AI\WeaponEN <> 0 Then EntityAlpha AI\WeaponEN, Alpha#
;            If AI\ShieldEN <> 0 Then EntityAlpha AI\ShieldEN, Alpha#
;            If AI\HatEN <> 0 Then EntityAlpha AI\HatEN, Alpha#
;         EndIf
            
               
         ; Check if this actor is underwater
         AI\Underwater = 0
         If AI\Actor\Environment = Environment_Amphibious
            For W.Water = Each Water
               If EntityY#(AI\CollisionEN) < EntityY#(W\EN) - 0.5
                  If Abs(EntityX#(AI\CollisionEN) - EntityX#(W\EN)) < (W\ScaleX# / 2.0)
                     If Abs(EntityZ#(AI\CollisionEN) - EntityZ#(W\EN)) < (W\ScaleZ# / 2.0)
                        AI\Underwater = Handle(W)
                        PositionEntity(AI\EN, 0, 0, 0)
                        Exit
                     EndIf
                  EndIf
               EndIf
            Next
         EndIf
         If AI\Underwater = 0 Then PositionEntity(AI\EN, 0, MeshHeight#(AI\EN) / -2.0, 0)

Under this add

EntityAutoFade(AI\EN),55,65 ; adjust these for range values Min,Max
               If EntityDistance(AI\EN,cam) > (50) 
                 HideEntity(AI\EN) 
             ElseIf EntityDistance(AI\EN,cam) <(45)  
                 ShowEntity(AI\EN) 
               EndIf

Should now look like 

Function UpdateActorInstances()

   SetPickModes()

   ; Updates for every actor
   For AI.ActorInstance = Each ActorInstance

      ; If it's not dead
      If AI\Attributes\Value[HealthStat] > 0
         ; Fade in (uses \AIMode field which is a server field, to save adding an extra field and using server memory)
         ; DISABLE - uses entityautofade instead
;         If AI\AIMode < 501
;            If AI = Me Or AI = Me\Mount Then AI\AIMode = 499 ; The player and the player's mount do not fade in
;            AI\AIMode = AI\AIMode + 2
;            Alpha# = Float#(AI\AIMode) / 501.0
;            EntityAlpha AI\EN, Alpha#
;            EntityAlpha AI\ShadowEN, Alpha#
;            If AI\WeaponEN <> 0 Then EntityAlpha AI\WeaponEN, Alpha#
;            If AI\ShieldEN <> 0 Then EntityAlpha AI\ShieldEN, Alpha#
;            If AI\HatEN <> 0 Then EntityAlpha AI\HatEN, Alpha#
;         EndIf
            
               
         ; Check if this actor is underwater
         AI\Underwater = 0
         If AI\Actor\Environment = Environment_Amphibious
            For W.Water = Each Water
               If EntityY#(AI\CollisionEN) < EntityY#(W\EN) - 0.5
                  If Abs(EntityX#(AI\CollisionEN) - EntityX#(W\EN)) < (W\ScaleX# / 2.0)
                     If Abs(EntityZ#(AI\CollisionEN) - EntityZ#(W\EN)) < (W\ScaleZ# / 2.0)
                        AI\Underwater = Handle(W)
                        PositionEntity(AI\EN, 0, 0, 0)
                        Exit
                     EndIf
                  EndIf
               EndIf
            Next
         EndIf
         If AI\Underwater = 0 Then PositionEntity(AI\EN, 0, MeshHeight#(AI\EN) / -2.0, 0)
         
   EntityAutoFade(AI\EN),55,65
               If EntityDistance(AI\EN,cam) > (50) 
                 HideEntity(AI\EN) 
             ElseIf EntityDistance(AI\EN,cam) <(45)  
                 ShowEntity(AI\EN) 
               EndIf

         ; Show/hide nametags in HideNametags mode 2 (selected only)
         If HideNametags = 2
            If AI\NametagEN <> 0
               If Handle(AI) = PlayerTarget
                  ShowEntity(AI\NametagEN)
               Else
                  HideEntity(AI\NametagEN)
               EndIf
            EndIf
         EndIf

And thats it. Again post if you get a MAV so that it can be fixed for everyone! Save everything and compile an .Exe and try it out!