|
|
1.1 root 1: // cl_tent.c -- client side temporary entities
2:
3: #include "quakedef.h"
4:
5: int num_temp_entities;
6: entity_t cl_temp_entities[MAX_TEMP_ENTITIES];
7: beam_t cl_beams[MAX_BEAMS];
8:
9: sfx_t *cl_sfx_wizhit;
10: sfx_t *cl_sfx_knighthit;
11: sfx_t *cl_sfx_tink1;
12: sfx_t *cl_sfx_ric1;
13: sfx_t *cl_sfx_ric2;
14: sfx_t *cl_sfx_ric3;
15: sfx_t *cl_sfx_r_exp3;
16:
17: /*
18: =================
19: CL_ParseTEnt
20: =================
21: */
22: void CL_InitTEnts (void)
23: {
24: cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
25: cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
26: cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
27: cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
28: cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
29: cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
30: cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
31: }
32:
33: /*
34: =================
35: CL_ParseBeam
36: =================
37: */
38: void CL_ParseBeam (model_t *m)
39: {
40: int ent;
41: vec3_t start, end;
42: beam_t *b;
43: int i;
44:
45: ent = MSG_ReadShort ();
46:
47: start[0] = MSG_ReadCoord ();
48: start[1] = MSG_ReadCoord ();
49: start[2] = MSG_ReadCoord ();
50:
51: end[0] = MSG_ReadCoord ();
52: end[1] = MSG_ReadCoord ();
53: end[2] = MSG_ReadCoord ();
54:
55: // override any beam with the same entity
56: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
57: if (b->entity == ent)
58: {
59: b->entity = ent;
60: b->model = m;
61: b->endtime = cl.time + 0.2;
62: VectorCopy (start, b->start);
63: VectorCopy (end, b->end);
64: return;
65: }
66:
67: // find a free beam
68: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
69: {
70: if (!b->model || b->endtime < cl.time)
71: {
72: b->entity = ent;
73: b->model = m;
74: b->endtime = cl.time + 0.2;
75: VectorCopy (start, b->start);
76: VectorCopy (end, b->end);
77: return;
78: }
79: }
80: Con_Printf ("beam list overflow!\n");
81: }
82:
83: /*
84: =================
85: CL_ParseTEnt
86: =================
87: */
88: void CL_ParseTEnt (void)
89: {
90: int type;
91: vec3_t pos;
92: dlight_t *dl;
93: int rnd;
94:
95: type = MSG_ReadByte ();
96: switch (type)
97: {
98: case TE_WIZSPIKE: // spike hitting wall
99: pos[0] = MSG_ReadCoord ();
100: pos[1] = MSG_ReadCoord ();
101: pos[2] = MSG_ReadCoord ();
102: R_RunParticleEffect (pos, vec3_origin, 20, 30);
103: S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
104: break;
105:
106: case TE_KNIGHTSPIKE: // spike hitting wall
107: pos[0] = MSG_ReadCoord ();
108: pos[1] = MSG_ReadCoord ();
109: pos[2] = MSG_ReadCoord ();
110: R_RunParticleEffect (pos, vec3_origin, 226, 20);
111: S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
112: break;
113:
114: case TE_SPIKE: // spike hitting wall
115: pos[0] = MSG_ReadCoord ();
116: pos[1] = MSG_ReadCoord ();
117: pos[2] = MSG_ReadCoord ();
118: R_RunParticleEffect (pos, vec3_origin, 0, 10);
119:
120: if ( rand() % 5 )
121: S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
122: else
123: {
124: rnd = rand() & 3;
125: if (rnd == 1)
126: S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
127: else if (rnd == 2)
128: S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
129: else
130: S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
131: }
132: break;
133: case TE_SUPERSPIKE: // super spike hitting wall
134: pos[0] = MSG_ReadCoord ();
135: pos[1] = MSG_ReadCoord ();
136: pos[2] = MSG_ReadCoord ();
137: R_RunParticleEffect (pos, vec3_origin, 0, 20);
138:
139: if ( rand() % 5 )
140: S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
141: else
142: {
143: rnd = rand() & 3;
144: if (rnd == 1)
145: S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
146: else if (rnd == 2)
147: S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
148: else
149: S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
150: }
151: break;
152:
153: case TE_GUNSHOT: // bullet hitting wall
154: pos[0] = MSG_ReadCoord ();
155: pos[1] = MSG_ReadCoord ();
156: pos[2] = MSG_ReadCoord ();
157: R_RunParticleEffect (pos, vec3_origin, 0, 20);
158: break;
159:
160: case TE_EXPLOSION: // rocket explosion
161: pos[0] = MSG_ReadCoord ();
162: pos[1] = MSG_ReadCoord ();
163: pos[2] = MSG_ReadCoord ();
164: R_ParticleExplosion (pos);
165: dl = CL_AllocDlight ();
166: VectorCopy (pos, dl->origin);
167: dl->radius = 350;
168: dl->die = cl.time + 0.5;
169: dl->decay = 300;
170: S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
171: break;
172:
173: case TE_TAREXPLOSION: // tarbaby explosion
174: pos[0] = MSG_ReadCoord ();
175: pos[1] = MSG_ReadCoord ();
176: pos[2] = MSG_ReadCoord ();
177: R_BlobExplosion (pos);
178:
179: S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
180: break;
181:
182: case TE_LIGHTNING1: // lightning bolts
183: CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
184: break;
185:
186: case TE_LIGHTNING2: // lightning bolts
187: CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
188: break;
189:
190: case TE_LIGHTNING3: // lightning bolts
191: CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
192: break;
193:
194: case TE_LAVASPLASH:
195: pos[0] = MSG_ReadCoord ();
196: pos[1] = MSG_ReadCoord ();
197: pos[2] = MSG_ReadCoord ();
198: R_LavaSplash (pos);
199: break;
200:
201: case TE_TELEPORT:
202: pos[0] = MSG_ReadCoord ();
203: pos[1] = MSG_ReadCoord ();
204: pos[2] = MSG_ReadCoord ();
205: R_TeleportSplash (pos);
206: break;
207:
208: default:
209: Sys_Error ("CL_ParseTEnt: bad type");
210: }
211: }
212:
213:
214: /*
215: =================
216: CL_NewTempEntity
217: =================
218: */
219: entity_t *CL_NewTempEntity (void)
220: {
221: entity_t *ent;
222:
223: if (cl_numvisedicts == MAX_VISEDICTS)
224: return NULL;
225: if (num_temp_entities == MAX_TEMP_ENTITIES)
226: return NULL;
227: ent = &cl_temp_entities[num_temp_entities];
228: memset (ent, 0, sizeof(*ent));
229: num_temp_entities++;
230: cl_visedicts[cl_numvisedicts] = ent;
231: cl_numvisedicts++;
232:
233: ent->colormap = vid.colormap;
234: return ent;
235: }
236:
237:
238: /*
239: =================
240: CL_UpdateTEnts
241: =================
242: */
243: void CL_UpdateTEnts (void)
244: {
245: int i;
246: beam_t *b;
247: vec3_t dist, org;
248: float d;
249: entity_t *ent;
250: float yaw, pitch;
251: float forward;
252:
253: num_temp_entities = 0;
254:
255: // update lightning
256: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
257: {
258: if (!b->model || b->endtime < cl.time)
259: continue;
260:
261: // if coming from the player, update the start position
262: if (b->entity == cl.viewentity)
263: {
264: VectorCopy (cl_entities[cl.viewentity].origin, b->start);
265: }
266:
267: // calculate pitch and yaw
268: VectorSubtract (b->end, b->start, dist);
269:
270: if (dist[1] == 0 && dist[0] == 0)
271: {
272: yaw = 0;
273: if (dist[2] > 0)
274: pitch = 90;
275: else
276: pitch = 270;
277: }
278: else
279: {
280: yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
281: if (yaw < 0)
282: yaw += 360;
283:
284: forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
285: pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
286: if (pitch < 0)
287: pitch += 360;
288: }
289:
290: // add new entities for the lightning
291: VectorCopy (b->start, org);
292: d = VectorNormalize(dist);
293: while (d > 0)
294: {
295: ent = CL_NewTempEntity ();
296: if (!ent)
297: return;
298: VectorCopy (org, ent->origin);
299: ent->model = b->model;
300: ent->angles[0] = pitch;
301: ent->angles[1] = yaw;
302: ent->angles[2] = rand()%360;
303:
304: for (i=0 ; i<3 ; i++)
305: org[i] += dist[i]*30;
306: d -= 30;
307: }
308: }
309:
310: }
311:
312:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.