more laser madness (now: dark lasers, pulsating laser, laser beam interpolation)
[divverent/nexuiz.git] / data / qcsrc / client / laser.qc
1 // FIXME make this generic code, to be used for other entities too?
2 .vector iorigin1, iorigin2;
3 .vector ivelocity1, ivelocity2;
4 .vector iangles1, iangles2;
5 .float itime1, itime2;
6 void InterpolateOrigin_Note()
7 {
8         float dt;
9
10         self.iorigin1 = self.iorigin2;
11         self.iangles1 = self.iangles2;
12         self.ivelocity1 = self.ivelocity2;
13
14         self.iorigin2 = self.origin;
15         self.iangles2 = self.angles;
16         self.ivelocity2 = self.velocity;
17
18         dt = time - self.itime1;
19
20         if(vlen(self.iorigin2 - self.iorigin1) > 1000)
21         {
22                 self.iorigin1 = self.iorigin2;
23                 self.iangles1 = self.iangles2;
24                 self.ivelocity1 = self.ivelocity2;
25         }
26         else if(vlen(self.ivelocity2 - self.ivelocity1) > 1000)
27         {
28                 self.iangles1 = self.iangles2;
29                 self.ivelocity1 = self.ivelocity2;
30         }
31
32         if(dt < 0.2)
33         {
34                 self.itime1 = time;
35                 self.itime2 = time + getstatf(STAT_SYS_TICRATE);
36         }
37         else
38         {
39                 // don't lerp
40                 self.itime1 = self.itime2 = time;
41         }
42 }
43 void InterpolateOrigin_Do()
44 {
45         if(self.itime1 && self.itime2 && self.itime1 != self.itime2)
46         {
47                 float f;
48                 f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1);
49                 self.origin = (1 - f) * self.iorigin1 + f * self.iorigin2;
50                 self.angles = (1 - f) * self.iangles1 + f * self.iangles2;
51                 self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2;
52         }
53 }
54 void InterpolateOrigin_Undo()
55 {
56         self.origin = self.iorigin2;
57         self.angles = self.iangles2;
58         self.velocity = self.ivelocity2;
59 }
60
61 // a laser goes from origin in direction angles
62 // it has color 'colormod'
63 // and stops when something is in the way
64 .float cnt; // end effect
65 .vector colormod;
66 .float state; // on-off
67 .float count; // flags for the laser
68 .vector velocity;
69 .float alpha;
70
71 void Draw_Laser()
72 {
73         if(!self.state)
74                 return;
75         InterpolateOrigin_Do();
76         if(self.count & 0x80)
77         {
78                 traceline(self.origin, self.velocity, 0, self);
79         }
80         else
81         {
82                 makevectors(self.angles);
83                 traceline(self.origin, self.origin + v_forward * 32768, 0, self);
84         }
85         if(self.alpha)
86         {
87                 Draw_CylindricLine(self.origin, trace_endpos, 2, "particles/laserbeam", 0, time * 3, self.colormod, self.alpha, DRAWFLAG_NORMAL); // TODO make a texture to make the laser look smoother
88         }
89         else
90         {
91                 Draw_CylindricLine(self.origin, trace_endpos, 2, "particles/laserbeam", 0, time * 3, self.colormod, 1, DRAWFLAG_ADDITIVE); // TODO make a texture to make the laser look smoother
92         }
93         pointparticles(self.cnt, trace_endpos, trace_plane_normal, 256 * drawframetime);
94 }
95
96 void Ent_Laser()
97 {
98         float f;
99         // 30 bytes, or 13 bytes for just moving
100         f = ReadByte();
101         self.count = (f & 0xC0);
102         InterpolateOrigin_Undo();
103         if(f & 1)
104         {
105                 self.origin_x = ReadCoord();
106                 self.origin_y = ReadCoord();
107                 self.origin_z = ReadCoord();
108         }
109         if(f & 8)
110         {
111                 self.colormod_x = ReadByte() / 255.0;
112                 self.colormod_y = ReadByte() / 255.0;
113                 self.colormod_z = ReadByte() / 255.0;
114                 if(f & 0x40)
115                         self.alpha = ReadByte() / 255.0;
116                 else
117                         self.alpha = 0;
118                 self.cnt = ReadShort(); // effect number
119         }
120         if(f & 2)
121         {
122                 if(f & 0x80)
123                 {
124                         self.velocity_x = ReadCoord();
125                         self.velocity_y = ReadCoord();
126                         self.velocity_z = ReadCoord();
127                 }
128                 else
129                 {
130                         self.angles_x = ReadCoord();
131                         self.angles_y = ReadCoord();
132                 }
133         }
134         if(f & 4)
135                 self.state = ReadByte();
136         InterpolateOrigin_Note();
137         self.draw = Draw_Laser;
138 }