Jump to content
Sign in to follow this  
tpw

TPW HOUSELIGHTS - automatic house light addon

Recommended Posts

Hmm, http://www.kylania.com/ex/?p=26 suggests otherwise, which is why I and many others use if (!isServer) exitWith {}; to make our scripts run on clients but not servers.

if (isDedicated) exitWith {};

and the script will run on clients only. No matter if it is a client playing on a dedicated server or a client in a hosted environment (including the host which is both, client and server, thus isServer is true for the host).

if (!isServer) exitWith is for scripts which should only run on a server (including a host in a hosted environment).

Xeno

Share this post


Link to post
Share on other sites

"[KH]Jman" tested it as the host of a non dedicated server and because that, "!isServer" wasn't true for him.

Share this post


Link to post
Share on other sites

I'm a bit confused!

Why does if (!isServer) exitWith {} work in SP and MP clients then? I remember being told long ago by someone to always include that code in the head of my scripts to keep them off servers.

Anyway, thanks for trying to enlighten me Rockhount and Xeno. I'll try if (isDedicated) exitWith {};

Share this post


Link to post
Share on other sites

I would recommend against starting the script from the init line of a playable (including player) unit for a MP mission. Pretty sure that that the init line is not run unless somebody actually choses (jip or not) the specific unit which has the init line.

There is no real need for the server to create the lights and manage it for all players. Just create all the lights locally for each player. If the algorithm does not depend on random elements then the result would be the same. Even if it does it probably doesn't matter. A lot of things isn't synced entirely in Arma. I think for instances that dead bodies may lie in different postures for each player in MP. I would do as Xeno suggests running the script on all client machines and create the lights locally for each player, starting the script for all in init.sqf or something like that.

Share this post


Link to post
Share on other sites

Ok, so I've been hard at work thinking and refining this thing. Here's v1.03:

  • Wrote my own flickering routine which hopefully achieves an approximation of Rydygier's, but with less calculation.
  • Wrote a flexible light-type system. You can add (or remove) as many light-types as you like, each with configurable colour, brightness and flickering.
  • Changed the code regarding (not) executing on dedi servers.

It should run on MP but each player will see different lights due to the randomisation. The CPU and network overhead to synchronise these visuals would be pretty high, and beyond my shit coding abilities.

I will put up an addon version shortly.

Thanks again for the input everyone!

if (isDedicated) exitWith {}; //This script won't run on dedicated servers (Thanks Xeno)

/*
TPW HOUSELIGHTS v 1.03
This script causes flickering lights to automatically come on in enterable buildings around the player. It will work on any map with ALICE2 compatible enterable buildings, and will simply ignore unenterable ALICE buildings.
Please feel free to modify and improve this script, on the proviso that you post your improvements for others to benefit from.
Thanks:
* CarlGustaffa for the azimuth code
* Rydygier for the inspiration for the flickering code
* RogueTrooper for the improved code for determining enterable buildings

TPW 20120519
*/  

///////////
//VARIABLES
///////////
//Distance player has to move for houses to be rescanned. Player must move greater than this distance to rescan houses.
_movedistance = 50;

//Distance around player to scan for houses to light. There's no point specifying a really large value since the engine won't reliably display lights past 100m or so. 
_housedistance = 100; 

//Percentage of houses to receive lights
_houseperc = 100; 

/*ARRAY OF LIGHT VALUES
You can add or remove lights to taste.
Each individual light array consists of:
[red,green,blue,maximum brightness,minimum brightness,%chance of flickering,%brightness to flicker]
red,green,blue,max and min are all in the range 0 - 255
Flickering %chance and %brightness are in the range 0-100
Flickering uses CPU, so if you want none, set all %chance of flickering values to 0. 
*/

_lightsarray = [
[255,127,24,40,20,100,10],//warm yellow/orange (candle or fire)
[255,200,100,40,20,80,5], //yellow/white (incandesecent)
[100,200,255,40,20,100,10]]; //Blue/white (television or fluorescent

//////////////////////////////////////////
//PROCESS LIGHT ARRAYS INTO USEABLE VALUES
//////////////////////////////////////////
_proclightsarray = [];
{
_red = _x select 0; _red = _red /255;
_green = _x select 1; _green = _green/255;
_blue = _x select 2; _blue = _blue/255;
_max = _x select 3;
_min = _x select 4;
_flperc = _x select 5;
_flvar = _x select 6; _flvar = _flvar/100;
_proclight = [_red,_green,_blue,_max,_min,_flperc,_flvar];
_proclightsarray = _proclightsarray + [_proclight];
} foreach _lightsarray;

//////////////////
//FLICKER FUNCTION
//////////////////
tpw_flicker = call compile format ["%1","{
_lt0 = _this select 0;
_br = _this select 1;
_fv = _this select 2;

_rng = _br * _fv;
_brmax = (_br + _rng);
_brmin = (_br - _rng);
_op = 1;
_inc = _rng/(random 10); 
_slp = random 0.1;
_br2 = _br;
while {not (isNull _lt0)} do
	{
_br2 = _br2 + (_op * _inc);	
_lt0 setLightBrightness _br2; 
if (_br2 > _brmax) then {_op = -1;_brmax = _br + (random _rng);_slp = random 0.2;_inc = _rng/((random 10) + 1);}; 
if (_br2 < _brmin) then {_op = 1;_brmin = _br - (random _rng);_slp = random 0.2;_inc = _rng/((random 10) + 1);};
sleep _slp;
	};
};"
];

////////////
//MAIN LOOP
////////////
// Initial dummy player position
_lastpos = [0,0,0];

while {true} do 
{

//Only recompute houses to light if player has moved > set distsance
if (player distance _lastpos > _movedistance) then 
{
//GET ANGLE OF SUN - ADAPTED FROM CARLGUSTAFFA
_lat = -1 * getNumber(configFile >> "CfgWorlds" >> worldName >> "latitude"); 
_day = 360 * (dateToNumber date); 
_hour = (daytime / 24) * 360; 
_sunangle = ((12 * cos(_day) - 78) * cos(_lat) * cos(_hour)) - (24 * sin(_lat) * cos(_day)); 	

//Recalculate player's position
_lastpos = (position player);

//Only bother if it's dark
if (_sunangle < 0) then 
	{
// Delete lights from previously lit houses		
{deletevehicle _x;} foreach tpw_lithouses; tpw_lithouses = []; 

//Find houses within set distance of player		
_houses = nearestObjects [getpos player, ["House"], _housedistance];
		{
//ONLY THE CHOSEN PERCENTAGE OF ENTERABLE HOUSES WITH MULTIPLE BUILDINGPOSITIONS  WILL ACTUALLY LIGHT UP
if ((((_x buildingpos 0) select 0) != 0) and ((random 100) < _houseperc)) then 
			{
_pos = getpos _x;
_lightnum = floor (random (count _proclightsarray));_light = _proclightsarray select _lightnum; //Select light type
_r = _light select 0;_g = _light select 1;_b = _light select 2;_col = [_r,_g,_b]; //Light colour values
_max = _light select 3;_min = _light select 4;//Light brightness range
_flperc = _light select 5;_flvar = _light select 6;//Light flickering parameters
_br = 0.1 * ((_min + (random (_max - _min)))/255); //Random brightness between specified range	
_lp = "#lightpoint" createVehicleLocal _pos; //Create light
_lp setLightBrightness _br; // Set its brightness
_lp setLightColor _col; // Set its colour
_lp lightAttachObject [_x, [random 2,random 2,1]]; // place it at a random position within house 
if ((random 100) < _flperc) then {[_lp,_br,_flvar] spawn tpw_flicker}; // Set appropriate flicker for light type
tpw_lithouses = tpw_lithouses + [_lp]; // Add it to the lit houses array so it can be removed later		
			};
		} foreach _houses;
	};
};
sleep 10;
};

Edited by tpw

Share this post


Link to post
Share on other sites

v1.03 is erroring out tpw.

Here is a snippet from my .RPT:

File C:\Users\******\Documents\ArmA 2 Other Profiles\*********\mpmissions\********\common\client\ambient_lights.sqf, line 40
Error in expression <20,5], 
_tv = [100,200,255,60,30,100,30]]; 
_ratio = [4,2,1]; 




_lightarray =>
 Error position: <]; 
_ratio = [4,2,1]; 




_lightarray =>
 Error Missing ; 

and here as well:

Error in expression <n player);

{deletevehicle _x;} foreach tpw_lithouses; tpw_lithouses = []; 

if >
 Error position: <tpw_lithouses; tpw_lithouses = []; 

if >
 Error Undefined variable in expression: tpw_lithouses
File C:\Users\*******\Documents\ArmA 2 Other Profiles\*******\mpmissions\*******\common\client\ambient_lights.sqf, line 97

EDIT: Error came from taking the code from the first post, the code given in the post above is error free.

Edited by bigshotking

Share this post


Link to post
Share on other sites

Thanks bigshotking. A rogue ] crept in when I was doing the final edit of the script version before uploading it. That's what you get for scripting late at night.

It should work as advertised for you now. The addon version is fine.

Cheers

tpw

v1.03 is erroring out tpw.

Here is a snippet from my .RPT:

File C:\Users\******\Documents\ArmA 2 Other Profiles\*********\mpmissions\********\common\client\ambient_lights.sqf, line 40
Error in expression <20,5], 
_tv = [100,200,255,60,30,100,30]]; 
_ratio = [4,2,1]; 




_lightarray =>
 Error position: <]; 
_ratio = [4,2,1]; 




_lightarray =>
 Error Missing ; 

and here as well:

Error in expression <n player);

{deletevehicle _x;} foreach tpw_lithouses; tpw_lithouses = []; 

if >
 Error position: <tpw_lithouses; tpw_lithouses = []; 

if >
 Error Undefined variable in expression: tpw_lithouses
File C:\Users\*******\Documents\ArmA 2 Other Profiles\*******\mpmissions\*******\common\client\ambient_lights.sqf, line 97

EDIT: Error came from taking the code from the first post, the code given in the post above is error free.

Share this post


Link to post
Share on other sites

I haven't read the recent pages fully, so please excuse me if it should have been mentioned.

It seems as if the GLOBAL command createvehicle #lightpoint only works locally. The light only shows up where the command has been executed. Concerning randomness (colours and which houses are lit), the server should make globalvariable'd arrays that the clients have to use.

Btw, using totally randomized colours for many houses does NOT look that bad at all (_light setLightColor [random 1,random 1,random1]). This way, Zargabad at night for example with many total-randomized houselights looks nice (some kind of cosy and colourful Orient of auld lang syne).

Share this post


Link to post
Share on other sites

Hello tpw,

it is great to see, how a "little thing" is growing up! Now v 1.03

Well done mate and thx to all who help this smart guy! :pc:

That´s how com works! Fantastic!

Cheers

McLupo

Share this post


Link to post
Share on other sites

The link to v1.03 is broken on Armaholic.

Foxhound: could you please fix it?

Share this post


Link to post
Share on other sites

Hi everyone

I've spent the last few days trying out a few ideas to improve things so that you get more (flickering) lights, with less demands on your poor old CPU. I fully recognise that this houselight script is essentially eye candy, so making it take as few resources as possible is a priority.

Here's a development version which incorporates the following:

  • Distant lights are created with double the brightness, in an attempt to overcome some of the engine's shortcomings. You should see more distant lights now.
  • Lights will only flicker within a user definable distance from the player. This should cut CPU usage significantly.
  • Some code cleanups and optimisation courtesy of Demon Cleaner.

On my fairly substandard system I've been able to get a pretty good improvement in lighting, without any additional smoke coming out the back of my computer. Let me know how you go with this and I will make an addon version if it's all hunky dory.

In the mean time, I'm looking to try to get the light flickering functions to run via cba_fnc_addPerFrameHandle to further increase performance. However this is really moving into the realm of rocket surgery, so if anyone would care to offer a bit of advice it would be gratefully received!

// This script won't run on dedicated servers (Thanks Xeno)
if (isDedicated) exitWith {};

/*
 TPW HOUSELIGHTS v 1.04
 This script causes flickering lights to automatically come on in enterable
 buildings around the player. It will work on any map with ALICE2 compatible
 enterable buildings, and will simply ignore unenterable ALICE buildings.
 Please feel free to modify and improve this script, on the proviso that you
 post your improvements for others to benefit from.

 Thanks:
 * CarlGustaffa for the azimuth code
 * Rydygier for the inspiration for the flickering code
 * RogueTrooper for the improved code for determining enterable buildings
 * Xeno for config help
 * Demon Cleaner for code cleanup and optimisation

 TPW 20120525
*/  

////////////////
// VARIABLES //
//////////////

private ["_movedistance","_housedistance","_houseperc","_flickerdistance"];

// Distance player has to move for houses to be rescanned.
// Player must move greater than this distance to rescan houses.
_movedistance = 100;

// Distance around player to scan for houses to light.
_housedistance = 300;

// Percentage of houses to receive lights.
_houseperc = 100;

// How close player must be to a light to see it flickering - use a lower value if flickering lights are too CPU demanding
_flickerdistance = 40;


/* 
 LIGHT-TYPE VALUES
 Light-type will be picked at random.
 Each individual light array consists of: [red,green,blue,maximum brightness,
 minimum brightness,%chance of flickering,%brightness to flicker]
 Example: [255,127,24,60,30,80,10] = warm yellow, brightness between 20-60, 80%
 chance of flickering, 10% brightness variation when flickering 
 red, green and blue values are 0-255
 brightness values are 0-255
 flickering values are 0-100
 Light sources don't really stress the engine, but flickering lightsources can.
 If you want no flickering, set all %chance of flickering values to 0.
*/

private ["_candle","_incan","_tv","_ratio"];

_candle =[255,127,24,40,20,80,10]; // warm yellow/orange (candle or fire)
_incan = [255,200,100,40,20,20,5]; // yellow/white (incandesecent)
_tv = [100,200,255,40,20,100,30]; // blue/white (television or fluorescent)
_ratio = [4,2,1]; // ratio of candle:incan:tv

///////////////////////////////////////////////
// PROCESS LIGHT ARRAYS INTO USEABLE VALUES //
/////////////////////////////////////////////

private [
 "_lightarray",
 "_proclightarray",
 "_red",
 "_green",
 "_blue",
 "_max",
 "_min",
 "_flperc",
 "_flvar",
 "_proclight"
];

_lightarray = [];
for "_x" from 1 to (_ratio select 0) do {_lightarray = _lightarray + [_candle]};
for "_x" from 1 to (_ratio select 1) do {_lightarray = _lightarray + [_incan]};
for "_x" from 1 to (_ratio select 2) do {_lightarray = _lightarray + [_tv]};

_proclightarray = [];
{ _red = _x select 0;
 _red = _red / 255;
 _green = _x select 1;
 _green = _green / 255;
 _blue = _x select 2;
 _blue = _blue / 255;
 _max = _x select 3;
 _min = _x select 4;
 _flperc = _x select 5;
 _flvar = _x select 6;
 _flvar = _flvar / 100;
 _proclight = [_red,_green,_blue,_max,_min,_flperc,_flvar];
 _proclightarray = _proclightarray + [_proclight];
} foreach _lightarray;

///////////////////////
// FLICKER FUNCTION //
/////////////////////

tpw_flicker = call compile format ["%1","{
private ['_lt0','_br','_fv','_rng','_brmax','_brmin','_op','_inc','_br2','_fd','_ct'];
_lt0 = _this select 0;
_br = _this select 1;
_fv = _this select 2;
_fd = _this select 3;
_rng = _br * _fv;
_brmax = (_br + _rng);
_brmin = (_br - _rng);
_op = 1;
_inc = _rng / (random 10);
_br2 = _br;
_ldist = player distance _lt0;
_ct = 0;
while {not (isNull _lt0)} do {
_ct = _ct + 1;
if (_ldist < _fd) then {
_br2 = _br2 + (_op * _inc);
_lt0 setLightBrightness _br2;
if (_br2 > _brmax) then {
  _op = -1;
  _brmax = _br + (random _rng);
  _inc = _rng / ((random 10) + 1);
};
if (_br2 < _brmin) then {
  _op = 1;
  _brmin = _br - (random _rng);
  _inc = _rng / ((random 10) + 1);
};
};
sleep (random 0.2);
if (_ct > 100) then {_ldist = player distance _lt0; _ct = 0};
};
}"];

////////////////
// MAIN LOOP //
//////////////

private [
 "_lastpos",
 "_movedistance",
 "_lat",
 "_day",
 "_hour",
 "_sunangle",
 "_houses",
 "_pos",
 "_light",
 "_r",
 "_g",
 "_b",
 "_col",
 "_br",
 "_lp"
];

// Array of lit houses (public for debugging purposes)
tpw_lithouses = [];

// Initial dummy player position
_lastpos = [0,0,0];

while {true} do {
 // Only recompute houses to light if player has moved > set distsance
 if ((vehicle player) distance _lastpos > _movedistance) then {
   // GET ANGLE OF SUN - ADAPTED FROM CARLGUSTAFFA
   _lat = -1 * getNumber(configFile >> "CfgWorlds" >> worldName >> "latitude");
   _day = 360 * (dateToNumber date);
   _hour = (daytime / 24) * 360;
   _sunangle = ((12 * cos(_day) - 78) * cos(_lat) * cos(_hour)) - (24 * sin(_lat) * cos(_day));    

   // Recalculate player's position
   // Will report position of player even if player is in a vehicle
   _lastpos = (position (vehicle player));

   // Delete lights from previously lit houses  
   {deletevehicle _x} foreach tpw_lithouses;
   tpw_lithouses = [];

   // Only bother if it's dark
   if (_sunangle < 0) then {
     // Find houses within set distance of player        
     _houses = nearestObjects [getPosATL (vehicle player),["House"],_housedistance];  
     { // ONLY THE CHOSEN PERCENTAGE OF ENTERABLE HOUSES WITH MULTIPLE
       // BUILDINGPOSITIONS  WILL ACTUALLY LIGHT UP (THANKS ROGUE TROOPER)
       if ((((_x buildingpos 0) select 0) != 0) and ((random 100) < _houseperc)) then {
         _pos = getPosATL _x;

         // Select light type
         _light = _proclightarray select (floor (random (count _proclightarray)));

         _r = _light select 0;
         _g = _light select 1;
         _b = _light select 2;
         _col = [_r,_g,_b]; // Light colour values

         _max = _light select 3;
         _min = _light select 4;// Light brightness range
         _flperc = _light select 5;
         _flvar = _light select 6;// Light flickering parameters

         // Random brightness between specified range
         _br = 0.1 * ((_min + (random (_max - _min))) / 255);
	  // Distant lights are brighter to compensate for engine not obeying inverse square law
         if ((player distance _pos) > _movedistance) then {_br = _br * 2};  

	  _lp = "#lightpoint" createVehicleLocal _pos; // Create light
         _lp setLightBrightness _br; // Set its brightness
         _lp setLightColor _col; // Set its colour

	  // Place it at a random position within house
         _lp lightAttachObject [_x, [random 2,random 2,1]];

         if ((random 100) < _flperc)then {
	  [_lp,_br,_flvar,_flickerdistance] spawn tpw_flicker;
		}; // Set appropriate flicker for light type

         // Add it to the lit houses array so it can be removed later
         tpw_lithouses = tpw_lithouses + [_lp];
       };
     } foreach _houses;
   };
 };
 sleep 5;
};

Edited by tpw

Share this post


Link to post
Share on other sites

Thanks for the update, tpw. I'm already thinking how nicely this will spice up a mission I'm building :)

One question - can you turn lights on in tents (especially the larger types used as temporary barracks)?

Cheers

Orcinus

Share this post


Link to post
Share on other sites

Hi Orcinus

At the moment it will light up anything that is iskindof "house". Having a look through the Arma2 classes, I don't see many tents there under "house". If you can find out the more generic iskindof for tents, it can be added easily enough.

Sorry if this doesn't help much. I'll have a bit more of a play around and see what I can come up with for you.

Thanks for the update, tpw. I'm already thinking how nicely this will spice up a mission I'm building :)

One question - can you turn lights on in tents (especially the larger types used as temporary barracks)?

Cheers

Orcinus

Share this post


Link to post
Share on other sites

tpw fantastic job on this mate, works a treat.

Quick question, in a Dedi MP enviroment is

0 = [] execvm "tpw_houselights.sqf"

to be executed on each player?

Share this post


Link to post
Share on other sites

.... and on a dedi, if the player respawns does it need to be re-initialised? Is there a problem with multiple calls?

Share this post


Link to post
Share on other sites

tpw:

You actually don't need all of that call compile stuff in:

tpw_flicker = call compile format ["%1","{
private ['_lt0','_br','_fv','_rng','_brmax','_brmin','_op','_inc','_br2','_fd','_ct'];
_lt0 = _this select 0;
_br = _this select 1;
_fv = _this select 2;
_fd = _this select 3;
_rng = _br * _fv;
_brmax = (_br + _rng);
_brmin = (_br - _rng);
_op = 1;
_inc = _rng / (random 10);
_br2 = _br;
_ldist = player distance _lt0;
_ct = 0;
while {not (isNull _lt0)} do {
_ct = _ct + 1;
if (_ldist < _fd) then {
_br2 = _br2 + (_op * _inc);
_lt0 setLightBrightness _br2;
if (_br2 > _brmax) then {
  _op = -1;
  _brmax = _br + (random _rng);
  _inc = _rng / ((random 10) + 1);
   };
if (_br2 < _brmin) then {
  _op = 1;
  _brmin = _br - (random _rng);
  _inc = _rng / ((random 10) + 1);
   };
};
sleep (random 0.2);
if (_ct > 100) then {_ldist = player distance _lt0; _ct = 0};
};
}"]; 

You can just do this:

tpw_flicker = {
private ['_lt0','_br','_fv','_rng','_brmax','_brmin','_op','_inc','_br2','_fd','_ct'];
_lt0 = _this select 0;
_br = _this select 1;
_fv = _this select 2;
_fd = _this select 3;
_rng = _br * _fv;
_brmax = (_br + _rng);
_brmin = (_br - _rng);
_op = 1;
_inc = _rng / (random 10);
_br2 = _br;
_ldist = player distance _lt0;
_ct = 0;
while {not (isNull _lt0)} do {
	_ct = _ct + 1;
	if (_ldist < _fd) then {
		_br2 = _br2 + (_op * _inc);
		_lt0 setLightBrightness _br2;
		if (_br2 > _brmax) then {
			_op = -1;
			_brmax = _br + (random _rng);
			_inc = _rng / ((random 10) + 1);
		};
		if (_br2 < _brmin) then {
			_op = 1;
			_brmin = _br - (random _rng);
			_inc = _rng / ((random 10) + 1);
		};
	};
	sleep (random 0.2);
	if (_ct > 100) then {_ldist = player distance _lt0; _ct = 0};
};
};   

If you have

something = call compile format ["%1", "{code}"];

If you factor out the format you get

something = call compile "{code}";

If you then factor out the compile you get

something = call { {code} }

The result of calling that is '{code}' (that is a some code that returns some code. The last expression of any code is the result:

something = {code}

Share this post


Link to post
Share on other sites

@Shadow.D. ^BOB^ and Kremator. Sorry boys, I don't play MP, so my answers aren't going to be from a position of great wisdom: the script and addon versions don't run on the server, and have to be run on a per player basis. In an earlier post muzzleflash suggested against running the script version from the player's init line. So maybe init.sqf. I simply have no idea how it will go when a player respawns. Give it a go and let me know so I can add the info to the 1st post.

@muzzleflash, thanks a lot for the call compile stuff. It should be obvious to any decent arma scipter that I am a shit coder, and I am grateful for any pointers. My scripts are like a dancing bear: yes it can dance, no it's not going to join the Bolshoi any time soon :)

Share this post


Link to post
Share on other sites

So, exactly what steps need to be taken to make this work on Dedicated Servers?

Share this post


Link to post
Share on other sites
So, exactly what steps need to be taken to make this work on Dedicated Servers?

Short answer: If I knew I would have bloody done it.

Long answer: I've been working on a newer version which works quite differently than the previous versions, and which may go some way towards a system that others could tweak to work on a dedicated server. As I have stated N times in this thread, I don't play MP and have no real inkling of the concepts involved.

This newer development version works thusly:

  1. At startup it scans all houses within a 20km radius of the player into an _allhouses array
  2. All enterable houses in _allhouses are scanned into another array _houses
  3. Using setvariable, each house in _houses is then given its own set of lighting parameters, and a lit/unlit status
  4. Every 15 seconds _houses is scanned, and any unlit house within the player's specified radius has a light source created using the lighting parameters associated with that house. Any lit house outside the radius has its light removed.

This system has several benefits:

  • The computation regarding assigning lights to houses is gotten out of the way within a few seconds, and doesn't have to happen every time the player moves. And additionally, azimuth calculations are moved off to their own thread and only updated every 5 minutes, to save CPU.
  • While lights are assigned randomly according to user preferences, the settings remain with each house for the duration of play. If a user moves away from a given house, its light will be removed. If the user removes into range again, its light will resume with the same values (including flickering settings). This means there are no potentially jarring changes of lighting as a player moves around.
  • The array _houses, once established, could be made public and potentially shared between multiple players. All players might thus be able to see the same lights at a given position on a map.

Someone more MP savvy than me is welcome to look at the code (it's heavily commented and possible to work out what the hell I've done), and see if there's a way to make this happen on a dedi server.

As for me, I'm just happy that I have a more efficient and consistent house lighting system. Please test it out and see if it works for you. Code below:

// THIS SCRIPT WON'T RUN ON DEDICATED SERVERS
if (isDedicated) exitWith {};

/*
 TPW HOUSELIGHTS v 1.06
 This script causes flickering lights to automatically come on in enterable
 buildings around the player. It will work on any map with ALICE2 compatible
 enterable buildings, and will simply ignore unenterable ALICE buildings.
 Please feel free to modify and improve this script, on the proviso that you
 post your improvements for others to benefit from.

 Thanks:
 * CarlGustaffa for the azimuth code
 * Rydygier for the inspiration for the flickering code
 * RogueTrooper for the improved code for determining enterable buildings
 * Xeno for config and server help
 * Demon Cleaner for code cleanup and optimisation

 TPW 20120529
*/  

sleep 10; // Allow other scripts time to settle down

////////////////
// VARIABLES //
//////////////
private ["_housedistance","_houseperc","_flickerdistance"];

// Distance around player to scan for houses to light.
_housedistance = 200;

// Houses greater than this distance will be brighter, to compensate for engine.
_brightdistance = 100;

// Percentage of houses to receive lights.
_houseperc = 100;

// How close player must be to a light to see it flickering - use a lower value if flickering lights are too CPU demanding
_flickerdistance = 50;


/* 
 LIGHT-TYPE VALUES
 Light-type will be picked at random.
 Each individual light array consists of: [red,green,blue,maximum brightness,minimum brightness,%chance of flickering,%brightness to flicker]
 Example: [255,127,24,60,30,80,10] = warm yellow, brightness between 20-60, 80% chance of flickering, 10% brightness variation when flickering 
 Red, green and blue values are 0-255
 Brightness values are 0-255
 Flickering values are 0-100
 Light sources don't really stress the engine, but flickering lightsources can.
 If you want no flickering, set all %chance of flickering values to 0.
*/

private ["_candle","_incan","_tv","_ratio"];
_candle =[255,127,24,60,30,80,10]; // warm yellow/orange (candle or fire)
_incan = [255,200,100,80,40,20,5]; // yellow/white (incandesecent)
_tv = [100,200,255,60,30,100,30]; // blue/white (television or fluorescent)
_ratio = [4,2,1]; // ratio of candle:incan:tv

///////////////////////////////////////////////
// PROCESS LIGHT ARRAYS INTO USEABLE VALUES //
/////////////////////////////////////////////
private [
 "_lightarray",
 "_proclightarray",
 "_red",
 "_green",
 "_blue",
 "_max",
 "_min",
 "_flperc",
 "_flvar",
 "_proclight"
];

_lightarray = [];
for "_x" from 1 to (_ratio select 0) do {_lightarray = _lightarray + [_candle]};
for "_x" from 1 to (_ratio select 1) do {_lightarray = _lightarray + [_incan]};
for "_x" from 1 to (_ratio select 2) do {_lightarray = _lightarray + [_tv]};

_proclightarray = [];
{ _red = _x select 0;
 _red = _red / 255;
 _green = _x select 1;
 _green = _green / 255;
 _blue = _x select 2;
 _blue = _blue / 255;
 _max = _x select 3;
 _min = _x select 4;
 _flperc = _x select 5;
 _flvar = _x select 6;
 _flvar = _flvar / 100;
 _proclight = [_red,_green,_blue,_max,_min,_flperc,_flvar];
 _proclightarray = _proclightarray + [_proclight];
} foreach _lightarray;

///////////////////////
// FLICKER FUNCTION //
/////////////////////
tpw_flicker = {
private ['_lt0','_br','_fv','_rng','_brmax','_brmin','_op','_inc','_br2','_fd','_ct'];
_lt0 = _this select 0;
_br = _this select 1;
_fv = _this select 2;
_fd = _this select 3;
_rng = _br * _fv;
_brmax = (_br + _rng);
_brmin = (_br - _rng);
_op = 1;
_inc = _rng / (random 10);
_br2 = _br;
_ldist = player distance _lt0;
_ct = 0;
while {not (isNull _lt0)} do {
_ct = _ct + 1;
if (_ldist < _fd) then {
_br2 = _br2 + (_op * _inc);
_lt0 setLightBrightness _br2;
if (_br2 > _brmax) then {
  _op = -1;
  _brmax = _br + (random _rng);
  _inc = _rng / ((random 10) + 1);
};
if (_br2 < _brmin) then {
  _op = 1;
  _brmin = _br - (random _rng);
  _inc = _rng / ((random 10) + 1);
};
};
sleep (random 0.2);
if (_ct > 100) then {_ldist = player distance _lt0; _ct = 0};
};
};

///////////////
// SUN ANGLE//
/////////////
[] spawn {
while {true} do {
private ["_lat","_day","_hour","_sunangle"];
_lat = -1 * getNumber(configFile >> "CfgWorlds" >> worldName >> "latitude");
_day = 360 * (dateToNumber date);
_hour = (daytime / 24) * 360;
tpw_houselights_sunangle = ((12 * cos(_day) - 78) * cos(_lat) * cos(_hour)) - (24 * sin(_lat) * cos(_day));  
sleep 300; 
};
};

///////////////////////////
// INITIALISE ALL HOUSES//
/////////////////////////
private ["_allhouses","_houses"];
_allhouses = nearestObjects [getPosATL (vehicle player),["House"],20000]; // All houses within 20k radius of player
_houses = []; {if ((((_x buildingpos 0) select 0) != 0) and ((random 100) < _houseperc)) then {_houses = _houses + [_x]}} foreach _allhouses; // Pool of enterable houses that can be lit
tpw_housecount = count _houses; //public variable for debugging

///////////////////////////////////////////////
// LIGHT PARAMETERS FOR EACH LIGHTABLE HOUSE//
/////////////////////////////////////////////
private ["_light","_r","_g","_b","_col","_br","_lp"];
{_light = _proclightarray select (floor (random (count _proclightarray))); // Select light type
_r = _light select 0;_g = _light select 1;_b = _light select 2;_col = [_r,_g,_b]; // Light colour values
_max = _light select 3;_min = _light select 4;// Light brightness range
_flperc = _light select 5; _flvar = 0; if (random 100 < _flperc) then {_flvar = _light select 6};// Light flickering parameters
_br = 0.1 * ((_min + (random (_max - _min))) / 255);// Random brightness between specified range
_params = [_col,_br,_flvar]; // Bundle them up into a single variable
_x setvariable ["light_parameters",_params]; // Associate these parameters with this house
_x setvariable ["lit",0]; // Mark house as unlit
} foreach _houses;

[] spawn {
hintsilent format ["TPW Houselights v1.06 Inititalised\n%1 Lightable Houses",tpw_housecount];
sleep 5;
hintsilent "";
};

///////////////
// MAIN LOOP//
/////////////
tpw_lithouses = 0; // public variable for debugging
while {true} do 
{
// Only bother if it's dark
if (tpw_houselights_sunangle < 0) then {
{
private ["_lit","_light","_params","_dist"];
//Lighting variables associated with each house
_lit = _x getvariable "lit"; 
_light = _x getvariable "light_source"; 
_params = _x getvariable "light_parameters";
_dist = player distance _x;

//Light any unlit houses within specified distance
if ((_lit == 0) and (_dist < _housedistance)) then 
	{
_col = _params select 0; // Colour
_br = _params select 1; // Brightness
_flvar = _params select 2; // Flickering amount	
_lp = "#lightpoint" createVehicleLocal getposatl _x; // Create light
_lp setLightColor _col; // Set its colour
_lp setLightBrightness _br; // Set its brightness
_lp lightAttachObject [_x, [1,1,1]]; // Position it within house
if (_flvar > 0) then {[_lp,_br,_flvar,_flickerdistance] spawn tpw_flicker}; // Flicker if flickering value greater than 0
_x setvariable ["light_source",_lp]; // Assign this lightsource to this house
_x setvariable ["lit",1]; // Mark house as lit
tpw_lithouses= tpw_lithouses + 1; // Increment lit house counter
	};

//Remove lights from houses greater than specified distance		
if ((_lit == 1) and (_dist > _housedistance)) then 
	{
deletevehicle _light; // Remove the light
_x setvariable ["lit",0]; // Mark house as unlit
tpw_lithouses= tpw_lithouses - 1; // Decrement lit house counter
	};

//Increase the brightness of distant house lights		
if ((_lit == 1) and (_dist > _brightdistance)) then 
	{
_br = (_params select 1) * 1.5; // increase brightness
_light setlightbrightness _br;
	};	

//Normal brightness of close house lights		
if ((_lit == 1) and (_dist < _brightdistance)) then 
	{
_br = _params select 1; // normal brightness
_light setlightbrightness _br;
	};			

} foreach _houses;
};
sleep 15;
};

EDIT: Realised I'd posted a couple of bugs in the script on this page earlier. Fully functioning version now!

Edited by tpw

Share this post


Link to post
Share on other sites

Hi tpw,

How to add a specific light into a specific building ?

I'd like to add a candle-like light with flicker function into only one building.

Thanks :)

Edited by Gemini

Share this post


Link to post
Share on other sites

Here's the easiest way I can think of. Save the script below as flicker.sqf, into your mission directory. In the editor, place a game logic near the building you want lit and in its init put 0 = [this] execvm "flicker.sqf";

This should cause the building nearest the logic to light up and start flickering. I'm not in front of my Arma computer so can't verify that it works.

//Variables
_house = nearestBuilding (_this select 0); // house nearest the logic
_housepos = getpos _house; // position of the house
_flickerdistance = 50; // If you move further than this, the light won't flicker

//Flicker
tpw_flicker = { 
private ['_lt0','_br','_fv','_rng','_brmax','_brmin','_op','_inc','_br2','_fd','_ct']; 
_lt0 = _this select 0; 
_br = _this select 1; 
_fv = _this select 2; 
_fd = _this select 3; 
_rng = _br * _fv; 
_brmax = (_br + _rng); 
_brmin = (_br - _rng); 
_op = 1; 
_inc = _rng / (random 10); 
_br2 = _br; 
_ldist = player distance _lt0; 
_ct = 0; 
while {not (isNull _lt0)} do { 
_ct = _ct + 1; 
if (_ldist < _fd) then { 
_br2 = _br2 + (_op * _inc); 
_lt0 setLightBrightness _br2; 
if (_br2 > _brmax) then { 
  _op = -1; 
  _brmax = _br + (random _rng); 
  _inc = _rng / ((random 10) + 1); 
   }; 
if (_br2 < _brmin) then { 
  _op = 1; 
  _brmin = _br - (random _rng); 
  _inc = _rng / ((random 10) + 1); 
   }; 
}; 
sleep (random 0.2); 
if (_ct > 100) then {_ldist = player distance _lt0; _ct = 0}; 
}; 
}; 

//Light
_lp = "#lightpoint" createVehicleLocal _housepos; 
_lp setLightColor [1,0.5,0.1]; // Set its colour 
_lp setLightBrightness 0.03; // Set its brightness 
_lp lightAttachObject [_house, [1,1,1]]; // Position it within house 
[_lp,0.03,0.1,_flickerdistance] spawn tpw_flicker;

Hi tpw,

How to add a specific light into a specific building ?

I'd like to add a candle-like light with flicker function into only obe building.

Thanks :)

Edited by tpw

Share this post


Link to post
Share on other sites

I have released v1.07 as an addon, incorporating all the stuff I've been testing and posting over the last week or so.

Share this post


Link to post
Share on other sites

Hi tpw,

thanks for the update today.

I'm thrilled about this addon, because it allows me with modest means to set an atmosphere that´s absolutely unique!

Thanks a lot!

For your pleasure, if you like...

Best regards

McLupo

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×