]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/hook.qc
try predicting beam end
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hook.qc
1 .vector HookStart;
2 .vector HookEnd;
3 .float HookKillTime;
4 .vector LGBeamStart;
5 .vector LGBeamEnd;
6 .float LGBeamKillTime;
7 .float LGBeamSound;
8 .float LGBeamSilent;
9
10 void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float alpha, float drawflag)
11 {
12         // I want to draw a quad...
13         // from and to are MIDPOINTS.
14         
15         vector axis, thickdir, A, B, C, D;
16         float length_tex;
17
18         axis = normalize(to - from);
19         length_tex = aspect * vlen(to - from) / thickness;
20
21         // direction is perpendicular to the view normal, and perpendicular to the axis
22         thickdir = normalize(cross(axis, view_origin - from));
23
24 /*
25         print("from ", vtos(from), "\n");
26         print("to ", vtos(to), "\n");
27         print("org ", vtos(view_origin), "\n");
28         print("dir ", vtos(thickdir), "\n");
29 */
30
31         A = from - thickdir * (thickness / 2);
32         B = from + thickdir * (thickness / 2);
33         C = to + thickdir * (thickness / 2);
34         D = to - thickdir * (thickness / 2);
35
36         R_BeginPolygon(texture, drawflag);
37         R_PolygonVertex(A, '0 0 0' + shift * '1 0 0', rgb, alpha);
38         R_PolygonVertex(B, '0 1 0' + shift * '1 0 0', rgb, alpha);
39         R_PolygonVertex(C, '0 1 0' + (shift + length_tex) * '1 0 0', rgb, alpha);
40         R_PolygonVertex(D, '0 0 0' + (shift + length_tex) * '1 0 0', rgb, alpha);
41         R_EndPolygon();
42 }
43
44 string Draw_GrapplingHook_trace_callback_tex;
45 float Draw_GrapplingHook_trace_callback_rnd;
46 void Draw_GrapplingHook_trace_callback(vector start, vector hit, vector end)
47 {
48         Draw_CylindricLine(hit, start, 8, Draw_GrapplingHook_trace_callback_tex, 0.25, Draw_GrapplingHook_trace_callback_rnd, '1 1 1', 1, DRAWFLAG_NORMAL);
49         Draw_GrapplingHook_trace_callback_rnd += 0.25 * vlen(hit - start) / 8;
50 }
51
52 void Draw_GrapplingHook()
53 {
54         vector a, b;
55         string tex;
56         vector rgb;
57         float t;
58         float s;
59         vector vs;
60
61         if(time < self.HookKillTime)
62         {
63                 s = cvar("cl_gunalign");
64                 if(s != 1 && s != 2 && s != 4)
65                         s = 3; // default value
66                 --s;
67                 vs = hook_shotorigin[s];
68
69                 if(self.sv_entnum == player_localentnum - 1)
70                         a = view_origin + view_forward * vs_x + view_right * -vs_y + view_up * vs_z;
71                 else
72                         a = self.HookStart;
73                 b = self.HookEnd;
74
75                 t = GetPlayerColorForce(self.sv_entnum);
76
77                 if(t == COLOR_TEAM1)
78                 {
79                         tex = "particles/hook_red";
80                         rgb = '1 .3 .3';
81                 }
82                 else if(t == COLOR_TEAM2)
83                 {
84                         tex = "particles/hook_blue";
85                         rgb = '.3 .3 1';
86                 }
87                 else if(t == COLOR_TEAM3)
88                 {
89                         tex = "particles/hook_yellow";
90                         rgb = '1 1 .3';
91                 }
92                 else if(t == COLOR_TEAM4)
93                 {
94                         tex = "particles/hook_pink";
95                         rgb = '1 .3 1';
96                 }
97                 else
98                 {
99                         tex = "particles/hook_green";
100                         rgb = '.3 1 .3';
101                 }
102
103                 Draw_GrapplingHook_trace_callback_tex = tex;
104                 Draw_GrapplingHook_trace_callback_rnd = random();
105                 WarpZone_TraceBox_ThroughZone(a, '0 0 0', '0 0 0', b, MOVE_NOMONSTERS, world, world, Draw_GrapplingHook_trace_callback);
106                 Draw_GrapplingHook_trace_callback_tex = string_null;
107         }
108
109         if(time < self.LGBeamKillTime)
110         {
111                 s = cvar("cl_gunalign");
112                 if(s != 1 && s != 2 && s != 4)
113                         s = 3; // default value
114                 --s;
115                 vs = electro_shotorigin[s];
116
117                 if(self.sv_entnum == player_localentnum - 1)
118                 {
119                         a = view_origin + view_forward * vs_x + view_right * -vs_y + view_up * vs_z;
120                         b = a + view_forward * MAX_SHOT_DISTANCE;
121                 }
122                 else
123                 {
124                         a = self.LGBeamStart;
125                         b = self.LGBeamEnd;
126                 }
127
128                 tex = "particles/lgbeam";
129                 rgb = '1 1 1';
130
131                 Draw_GrapplingHook_trace_callback_tex = tex;
132                 Draw_GrapplingHook_trace_callback_rnd = random();
133                 WarpZone_TraceBox_ThroughZone(a, '0 0 0', '0 0 0', b, MOVE_NORMAL, world, world, Draw_GrapplingHook_trace_callback);
134                 Draw_GrapplingHook_trace_callback_tex = string_null;
135
136                 // helps the sound
137                 setorigin(self, a);
138         }
139
140         if(time < self.LGBeamKillTime && !self.LGBeamSilent)
141         {
142                 if(!self.LGBeamSound)
143                 {
144                         sound (self, CHAN_PROJECTILE, "weapons/lgbeam_fly.wav", VOL_BASE, ATTN_NORM);
145                         self.LGBeamSound = 1;
146                 }
147         }
148         else
149         {
150                 if(self.LGBeamSound)
151                 {
152                         sound (self, CHAN_PROJECTILE, "misc/null.wav", VOL_BASE, ATTN_NORM);
153                         self.LGBeamSound = 0;
154                 }
155         }
156 }
157
158 void Net_GrapplingHook()
159 {
160         float i, t;
161         vector start, end;
162         entity p;
163
164         i = ReadByte();
165         t = ReadByte();
166         end_x = ReadCoord();
167         end_y = ReadCoord();
168         end_z = ReadCoord();
169         start_x = ReadCoord();
170         start_y = ReadCoord();
171         start_z = ReadCoord();
172
173         if(i <= 0 || i >= 256) // not owned by a client
174                 return;
175         --i;
176
177         p = playerslots[i];
178         if(!p)
179                 return;
180
181         switch(t)
182         {
183                 case 0: // hook beam
184                         p.HookKillTime = time + 0.1;
185                         p.HookStart = start;
186                         p.HookEnd = end;
187                         p.draw = Draw_GrapplingHook;
188                         break;
189                 case 1: // electro lgbeam
190                         p.LGBeamKillTime = time + 0.1;
191                         p.LGBeamStart = start;
192                         p.LGBeamEnd = end;
193                         p.LGBeamSilent = 0;
194                         p.draw = Draw_GrapplingHook;
195                         break;
196                 case 2: // silent electro lgbeam
197                         p.LGBeamKillTime = time + 0.1;
198                         p.LGBeamStart = start;
199                         p.LGBeamEnd = end;
200                         p.LGBeamSilent = 1;
201                         p.draw = Draw_GrapplingHook;
202                         break;
203         }
204 }
205
206 void Hook_Precache()
207 {
208         precache_sound("weapons/lgbeam_fly.wav");
209 }