(DP) Improved flashlight
Moderator: InsideQC Admins
7 posts
• Page 1 of 1
(DP) Improved flashlight
it's been 4 months since i began learning qc. however, it's been off/on learning and i am still a major noob.
i first started off with the flashlight tutorial by shockman so credits goes to him for this. i wanted to build on that, because frankly it gets boring after a while. my flashlight behaves a little more realistically. when the distance between you and the light increases, the light's size increases while it's brightness decreases, eventally not shining a light at all when it's too far away. it also has a glow effect when up close, and you can adjust it's color (be careful when doing that).
is it an absolutely remarkable and ingenious code? no, not really. it's a neat addition. im using darkplaces for this but i guess it will work with any engine that has tenebrae lighting. just be careful with any adjustments you make since the code's 'sensetive'.
ok here we go. this tutorial is massively commented for anyone who wants to learn about the code's workings.
1. In defs.qc
add this to the bottom:
2. In world.qc
find:
after this, add:
3. create a new file called flash.qc
4. add this to the file

5. in weapons.qc, place this in Impulsecommands:
6. add flash.qc above weapons.qc in progs.src
OPTIONAL. in your mod's dir, open config.cfg and bind a button to impulse 30. it would look something like this:
bind f "impulse 30"
There you go. it needs work, no doubt. especially the slight choppiness when the light's brightness is changing, but that shouldn't be too hard to change. i know i made some of this unnecessarily complicated, so anyone who wants to simplify is welcome. i think i did an okay job with the radius changing with distance.
if tenebrae lighting had a brightness factor (separate from color) this would be immensely easier and it would look a lot better. thinking about it now, this could be possible without tenebrae lighting, except that radius adjustment would be a problem.
ps. you can go ahead and use cubemap filters to make a better look for the light.
hope i helped some people. tell me what you guys think!
i first started off with the flashlight tutorial by shockman so credits goes to him for this. i wanted to build on that, because frankly it gets boring after a while. my flashlight behaves a little more realistically. when the distance between you and the light increases, the light's size increases while it's brightness decreases, eventally not shining a light at all when it's too far away. it also has a glow effect when up close, and you can adjust it's color (be careful when doing that).
is it an absolutely remarkable and ingenious code? no, not really. it's a neat addition. im using darkplaces for this but i guess it will work with any engine that has tenebrae lighting. just be careful with any adjustments you make since the code's 'sensetive'.
ok here we go. this tutorial is massively commented for anyone who wants to learn about the code's workings.
1. In defs.qc
add this to the bottom:
- Code: Select all
.float flash_flag; // On / off for the flashlight
.entity flash; // flashlight entity
.entity glare; // glare entity
2. In world.qc
find:
- Code: Select all
// 10 FLUORESCENT FLICKER
lightstyle(10, "mmamammmmammamamaaamammma");
// 11 SLOW PULSE NOT FADE TO BLACK
lightstyle(11, "abcdefghijklmnopqrrqponmlkjihgfedcba");
after this, add:
- Code: Select all
// 12 - 25 behind_you - FLASHLIGHT (these will control brightness levels later on)
lightstyle(12, "n");
lightstyle(13, "m");
lightstyle(14, "l");
lightstyle(15, "k");
lightstyle(16, "j");
lightstyle(17, "i");
lightstyle(18, "h");
lightstyle(19, "g");
lightstyle(20, "f");
lightstyle(21, "e");
lightstyle(22, "d");
lightstyle(23, "c");
lightstyle(24, "b");
lightstyle(25, "a");
// 12 - 25 behind_you - FLASHLIGHT
3. create a new file called flash.qc
4. add this to the file
- Code: Select all
void() light_update = // does the heavy calculations of the light
{
local float radi, dist, brit;
local vector v1, source;
if (self.owner.deadflag != DEAD_NO) // if the player is dead
self.effects = EF_NODRAW; // turn off the flashlight
makevectors (self.owner.v_angle); // Find out which direction player facing
source = self.owner.origin + '0 0 16'; // makes flashlight come out of center of screen
traceline (source, (source + v_forward * 1200), FALSE, self); // make the line for the flashlight (change FALSE to a TRUE to ignore enemies)
setorigin (self, trace_endpos + v_forward * -15); // flashlight sits on the end of this line. the -15 makes sure the light shines on an entity, not after it
v1 = trace_endpos - source;
radi = vlen(v1) / 1.5;
dist = radi;
brit = radi;
/*
calculates the vector distance between the source of the flashlight (player)
and the entity it collides with. the vector result is converted into a usable float via vlen.
the radius and brightness use this calculated results.
*/
if (dist < 65)
dist = 65; // adjust the 65's to your liking. they determine the light's lowest possible radius.
if (dist > 350)
dist = 350; // adjust the 350's to your liking. they determine the light's highest possible radius.
brit = brit / 52; // this deals with brightness.
/*
divides distance by a value. the 26 determines how much distance it takes
before light becomes invisible. it also divides that distance into 13 parts. here's an explanation:

- Code: Select all
there are 13 'segments' between you and the end of the light. each segment makes the light larger and
less bright than the previous one. if you are more than 13 segments away from an entity, you will have no light shining.
*/
brit = brit + 11; // this adds 12 to your lightstyle count in order to match the lightstyles found in world.qc
if (brit > 25)
brit = 25;
if (brit < 12)
brit = 12; // keeps them bound. stupid bound() function doesn't work
self.light_lev = dist; // radius of flashlight equal to local float 'dist' (increases when distance goes up)
self.color = ('2 2 2'); // flash color (rgb)
self.style = brit; // brightness of flashlight equal to local float 'brit' (decreases when distance goes up)
self.pflags = PFLAGS_FULLDYNAMIC; // this enables the light
self.angles = self.owner.v_angle; // this causes the light to point in the direction that you are facing
// self.skin = 201; // try adding cubemaps. they dont work 4 me.
self.nextthink = time + 0.01; // Repeat this in 0.01 seconds
};
void() glare_update = // glare calculations
{
local float dist;
local vector v1, source;
if (self.owner.deadflag != DEAD_NO) // if the player is dead
self.effects = EF_NODRAW; // turn off the glare
makevectors (self.owner.v_angle); // Find out which direction player facing
source = self.owner.origin + '0 0 16'; // makes glare come out of center of screen
traceline (source, (source + v_forward * 1000), FALSE, self); // make the line for the glare (change FALSE to a TRUE to ignore enemies)
setorigin (self, trace_endpos + v_forward * -30); // glare sits on the end of this line. the -15 makes sure the light shines on an entity, not after it
v1 = trace_endpos - source;
dist = vlen(v1);
if (dist <= 350)
self.light_lev = 175; // radius of glare (change 125 to ur liking)
self.color = ('1 1 1'); // glare color (rgb) best not to change
self.style = 0; // turns the glare on and off
self.pflags = PFLAGS_FULLDYNAMIC; // this enables the light
self.angles = self.owner.v_angle; // glare faces the same way as the player
self.nextthink = time + 0.01; // Repeat this in 0.01 seconds
};
void() flash_on = // when flashlight is on
{
local entity flashlight; // Make a new local entity to hold the flashlight
local entity glarelight; // new entity to hold glare effect
flashlight = spawn (); // Creates the flashlight
flashlight.movetype = MOVETYPE_NONE; // Flashlight doesn't wander on it's own
flashlight.solid = SOLID_NOT; // Flashlight cannot collide with anything
setmodel (flashlight, ""); // its a light, no model needed
setsize (flashlight, '0 0 0', '0 0 0'); // give the flashlight no size, so it can travel anywhere
setorigin (flashlight, self.origin); // sets the flashlight's origin data
flashlight.owner = self; // the flashlight belongs to its owner
self.flash = flashlight; // gives the flashlight the ability to turn off
glarelight = spawn (); // Creates the glare
glarelight.movetype = MOVETYPE_NONE; // glare doesn't wander on it's own
glarelight.solid = SOLID_NOT; // glare cannot collide with anything
setmodel (glarelight, ""); // its a glare, no model needed
setsize (glarelight, '0 0 0', '0 0 0'); // give the glare no size, so it can travel anywhere
setorigin (glarelight, self.origin); // sets the glare's origin data
glarelight.owner = self; // the glare belongs to its owner
self.glare = glarelight; // gives the glare the ability to turn off
flashlight.think = light_update; // make the flashlight do the function called light_update...
flashlight.nextthink = time + 0.01; // in 0.01 seconds
glarelight.think = glare_update; // make the glare do the function called glare_update...
glarelight.nextthink = time + 0.01; // in 0.01 seconds
};
void () flash_toggle = // when the flashlight has been triggered by the user
{
if (self.flash_flag == FALSE) // if the flashlight has been set to off
{
self.flash_flag = TRUE; // set the flashlight to on
flash_on(); // give the flashlight's characteristics
sound (self, CHAN_ITEM, "items/flash.wav", 1, ATTN_NORM); // play the sound when the flashlight turns on
}
else // if the flashlight has been set to on
{
self.flash_flag = FALSE; // set the flashlight to off
self.flash.think = SUB_Remove; // remove the flashlight....
self.flash.nextthink = time + 0.01; // in 0.01 seconds
self.glare.think = SUB_Remove; // remove the glare....
self.glare.nextthink = time + 0.01; // in 0.01 seconds
sound (self, CHAN_ITEM, "items/flash.wav", 1, ATTN_NORM); // play the sound when the flashlight turns off
}
};
5. in weapons.qc, place this in Impulsecommands:
- Code: Select all
if (self.impulse == 30)
flash_toggle ();
6. add flash.qc above weapons.qc in progs.src
OPTIONAL. in your mod's dir, open config.cfg and bind a button to impulse 30. it would look something like this:
bind f "impulse 30"
There you go. it needs work, no doubt. especially the slight choppiness when the light's brightness is changing, but that shouldn't be too hard to change. i know i made some of this unnecessarily complicated, so anyone who wants to simplify is welcome. i think i did an okay job with the radius changing with distance.
if tenebrae lighting had a brightness factor (separate from color) this would be immensely easier and it would look a lot better. thinking about it now, this could be possible without tenebrae lighting, except that radius adjustment would be a problem.
ps. you can go ahead and use cubemap filters to make a better look for the light.
hope i helped some people. tell me what you guys think!
Last edited by behind_you on Tue May 10, 2011 6:49 am, edited 2 times in total.
-

behind_you - Posts: 237
- Joined: Sat Feb 05, 2011 6:57 am
- Location: Tripoli, Libya
Re: (DP) Improved flashlight
it is a big example of the use of the qc!
great flashlight! I had to lower a little the potency!
Thanks Behind_you
great flashlight! I had to lower a little the potency!
Thanks Behind_you
hi, I am nahuel, I love quake and qc.
-

Nahuel - Posts: 492
- Joined: Wed Jan 12, 2011 8:42 pm
- Location: mar del plata
a = trace_endpos_x - source_x;
if (a < 0)
a = a * -1;
b = trace_endpos_y - source_y;
if (b < 0)
b = b * -1;
c = trace_endpos_z - source_z;
if (c < 0)
c = c * -1;
d = (a + b + c) / 3;
Averaging the three components? That seems wrong.
vec v1 = trace_endpos - source;
float distance = vlen(v1);
- Swift
- Posts: 60
- Joined: Tue Jan 26, 2010 11:02 am
You're better off giving your variables names that convey their meaning or function.
local float a, b, c, d, e, f, g, h;
conveys nothing.
On the other hand:
vector v1;
float distance, brightness, radius;
Is a lot easier to understand and debug.
Moreso your vector algebra is way off. Consider -
trace_endpos = '0 0 1'
source = '0 0 0'
Answer this: should distance be 1, or 1/3?
local float a, b, c, d, e, f, g, h;
conveys nothing.
On the other hand:
vector v1;
float distance, brightness, radius;
Is a lot easier to understand and debug.
Moreso your vector algebra is way off. Consider -
trace_endpos = '0 0 1'
source = '0 0 0'
Answer this: should distance be 1, or 1/3?
- Swift
- Posts: 60
- Joined: Tue Jan 26, 2010 11:02 am
7 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest