Jump to content

Algorithm for determining light level.


Omega Haxors

Recommended Posts

I busted my nuts creating this, I figure someone here will appreciate it:
 

*PESUDOCODE*

SunVal = the current location's sunlight value (peaks at 22V)
BlockVal = the current location's block value (at the feet)
Time = the current time (10:30 for example, goes from 0:00 to 24:00)
LightLevel = The output variable (in Lux)

If you're holding a light source block in your main or offhand, set BlockVal to the greater: Current BlockVal, or the held item's light value

Divide both SunVal and BlockVal by 22 (this returns the % value of how much light is available)
Multiply SunVal and BlockVal by 10,000 (this is used to get the amount of energy in the light provided)

SunVal and BlockVal are now represented in Lux

Subtract 12:00 from the time (represent minutes as a fraction. For example 10:30 = 10.5)
If the time results in a negative number, multiply it by -1 (negates negative values)
Multiply Time by 0.1666 (returns a % value, from 0 to 200%)
Ceiling at 100% (If over 100%, then set the value to 100% Any time before 6 and after 18 is "midnight" and you can safely assume a value of 1)
Subtract Time by 1 (flips percentages, 0 becomes 1, 25% becomes 75% etc)

Multiply SunVal by Time (finally, now you know how much daylight there is)

If it's raining, divide SunVal by 10 (since the rainclouds block more light)
Always divide BlockVal by 10 (aritifical light carries less energy than sunlight does)

Compare SunVal and BlockVal. Set LightLevel to whichever one is higher.

Edited by Omega Haxors
Link to comment
Share on other sites

Time for the real code (as used in my mod)

 

        public float GetBlockLightAtEntity(Entity entity)
        {
            IBlockAccessor blocks = entity.World.BlockAccessor;
            float blocklight = 0//init the variable
            SyncedEntityPos pos = entity.Pos//init the location 
            BlockPos blockpos = pos.AsBlockPos//convert to block format
            blocklight = blocks.GetLightLevel(blockpos,EnumLightLevelType.OnlyBlockLight); //get the block light value at the location
            blocklight = blocklight / 22//to convert to % value
            return blocklight//Note: Non-sunlight sources are 1/3rd as strong, so be sure to divide them by 3 for apparant values
        }
        public float GetSunLightAtEntity(Entity entity, bool accountfordaytime = false//comes with an optional variable to account for daylight
        {
            IBlockAccessor blocks = entity.World.BlockAccessor;
            float sunlight = 0;
            SyncedEntityPos pos = entity.Pos;
            BlockPos blockpos = pos.AsBlockPos;
            sunlight = blocks.GetLightLevel(blockpos,EnumLightLevelType.OnlySunLight); //get the sun light value at the location
            sunlight = sunlight / 22;
            if(accountfordaytime//if true, calculations account for time as well
            {
                float hour = entity.World.Calendar.HourOfDay;
                hour = hour - 12//offset time (noon is center)
                if(hour < 0){hour = hour * -1;}//negative is now positive
                hour = hour * 0.1666f//convert to %
                if(hour > 1){hour = 1;} //any value over 100% is 100%
                hour = 1 - hour//flips % value (75% -> 25%)
                sunlight = sunlight * hour//reduce light level% by hour%
                
                bool israining = false//Vintagestory.GameContent.GameEffectsPacket.RainAndFogActive;
                //it's broken. For now, rain will not affect light level.
                if(israining)
                {
                    sunlight = sunlight * 0.9f//10% less
                }
            }
            return sunlight//as a % value, with 100% = a value of 22
        }
        public float GetEntityLightAtEntity(Entity entity) //gets the Entity Light produced by the entity, such as when a player holds a torch or a spider lights up
        {
            float entitylight = 0;
            if(entity.LightHsv != null)
            {
                entitylight = Convert.ToSingle(entity.LightHsv.GetValue(2)); //annoying workaround to convert object to float
            }
            entitylight = entitylight / 22;
            return entitylight
        }
        public float GetEntityLightAroundEntity(Entity centerentity) //gets the strongest Entity Light produced by nearby entities. This can include the center entity.
        {
            float strongestentitylight = 0;
 
            Entity[] entities = centerentity.World.GetEntitiesAround(centerentity.Pos.XYZ,9,9);
            foreach (Entity entity in entities)
            {
                float entitylight = 0;
                if(entity.LightHsv != null//crashes if you don't
                {
                entitylight = Convert.ToSingle(entity.LightHsv.GetValue(2)); //annoying workaround to convert object to float
                entitylight = entitylight - Convert.ToSingle(centerentity.Pos.DistanceTo(entity.Pos.XYZ)); //calculate light fall-off over distance
                strongestentitylight = Math.Max(strongestentitylight,entitylight); //pick the strongest light source
                }
            strongestentitylight = strongestentitylight / 22;
            }
            return strongestentitylight;
        }
Link to comment
Share on other sites

  • Omega Haxors changed the title to Algorithm for determining light level.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.