1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 Copyright (C) 2000-2006 Tim Angus
5 
6 This file is part of Tremulous.
7 
8 Tremulous is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
12 
13 Tremulous is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Tremulous; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 ===========================================================================
22 */
23 
24 // bg_misc.c -- both games misc functions, all completely stateless
25 
26 #include "../qcommon/q_shared.h"
27 #include "bg_public.h"
28 
29 int  trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode );
30 void trap_FS_Read( void *buffer, int len, fileHandle_t f );
31 void trap_FS_Write( const void *buffer, int len, fileHandle_t f );
32 void trap_FS_FCloseFile( fileHandle_t f );
33 void trap_FS_Seek( fileHandle_t f, long offset, fsOrigin_t origin ); // fsOrigin_t
34 
35 buildableAttributes_t bg_buildableList[ ] =
36 {
37   {
38     BA_A_SPAWN,            //int       buildNum;
39     "eggpod",              //char      *buildName;
40     "Egg",                 //char      *humanName;
41     "team_alien_spawn",    //char      *entityName;
42     { "models/buildables/eggpod/eggpod.md3", 0, 0, 0 },
43     1.0f,                  //float     modelScale;
44     { -15, -15, -15 },     //vec3_t    mins;
45     { 15, 15, 15 },        //vec3_t    maxs;
46     0.0f,                  //float     zOffset;
47     TR_GRAVITY,            //trType_t  traj;
48     0.0,                   //float     bounce;
49     ASPAWN_BP,             //int       buildPoints;
50     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
51     ASPAWN_HEALTH,         //int       health;
52     ASPAWN_REGEN,          //int       regenRate;
53     ASPAWN_SPLASHDAMAGE,   //int       splashDamage;
54     ASPAWN_SPLASHRADIUS,   //int       splashRadius;
55     MOD_ASPAWN,            //int       meansOfDeath;
56     BIT_ALIENS,            //int       team;
57     ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ),    //weapon_t  buildWeapon;
58     BANIM_IDLE1,           //int       idleAnim;
59     100,                   //int       nextthink;
60     ASPAWN_BT,             //int       buildTime;
61     qfalse,                //qboolean  usable;
62     0,                     //int       turretRange;
63     0,                     //int       turretFireSpeed;
64     WP_NONE,               //weapon_t  turretProjType;
65     0.5f,                  //float     minNormal;
66     qtrue,                 //qboolean  invertNormal;
67     qfalse,                //qboolean  creepTest;
68     ASPAWN_CREEPSIZE,      //int       creepSize;
69     qfalse,                //qboolean  dccTest;
70     qfalse                 //qboolean  reactorTest;
71   },
72   {
73     BA_A_BARRICADE,        //int       buildNum;
74     "barricade",           //char      *buildName;
75     "Barricade",           //char      *humanName;
76     "team_alien_barricade",//char      *entityName;
77     { "models/buildables/barricade/barricade.md3", 0, 0, 0 },
78     1.0f,                  //float     modelScale;
79     { -35, -35, -15 },     //vec3_t    mins;
80     { 35, 35, 60 },        //vec3_t    maxs;
81     0.0f,                  //float     zOffset;
82     TR_GRAVITY,            //trType_t  traj;
83     0.0,                   //float     bounce;
84     BARRICADE_BP,          //int       buildPoints;
85     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
86     BARRICADE_HEALTH,      //int       health;
87     BARRICADE_REGEN,       //int       regenRate;
88     BARRICADE_SPLASHDAMAGE,//int       splashDamage;
89     BARRICADE_SPLASHRADIUS,//int       splashRadius;
90     MOD_ASPAWN,            //int       meansOfDeath;
91     BIT_ALIENS,            //int       team;
92     ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ),    //weapon_t  buildWeapon;
93     BANIM_IDLE1,           //int       idleAnim;
94     100,                   //int       nextthink;
95     BARRICADE_BT,          //int       buildTime;
96     qfalse,                //qboolean  usable;
97     0,                     //int       turretRange;
98     0,                     //int       turretFireSpeed;
99     WP_NONE,               //weapon_t  turretProjType;
100     0.707f,                //float     minNormal;
101     qfalse,                //qboolean  invertNormal;
102     qtrue,                 //qboolean  creepTest;
103     BARRICADE_CREEPSIZE,   //int       creepSize;
104     qfalse,                //qboolean  dccTest;
105     qfalse                 //qboolean  reactorTest;
106   },
107   {
108     BA_A_BOOSTER,          //int       buildNum;
109     "booster",             //char      *buildName;
110     "Booster",             //char      *humanName;
111     "team_alien_booster",  //char      *entityName;
112     { "models/buildables/booster/booster.md3", 0, 0, 0 },
113     1.0f,                  //float     modelScale;
114     { -26, -26, -9 },     //vec3_t     mins;
115     { 26, 26, 9 },        //vec3_t     maxs;
116     0.0f,                  //float     zOffset;
117     TR_GRAVITY,            //trType_t  traj;
118     0.0,                   //float     bounce;
119     BOOSTER_BP,            //int       buildPoints;
120     ( 1 << S2 )|( 1 << S3 ), //int  stages
121     BOOSTER_HEALTH,        //int       health;
122     BOOSTER_REGEN,         //int       regenRate;
123     BOOSTER_SPLASHDAMAGE,  //int       splashDamage;
124     BOOSTER_SPLASHRADIUS,  //int       splashRadius;
125     MOD_ASPAWN,            //int       meansOfDeath;
126     BIT_ALIENS,            //int       team;
127     ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ),    //weapon_t  buildWeapon;
128     BANIM_IDLE1,           //int       idleAnim;
129     100,                   //int       nextthink;
130     BOOSTER_BT,            //int       buildTime;
131     qfalse,                //qboolean  usable;
132     0,                     //int       turretRange;
133     0,                     //int       turretFireSpeed;
134     WP_NONE,               //weapon_t  turretProjType;
135     0.707f,                //float     minNormal;
136     qfalse,                //qboolean  invertNormal;
137     qtrue,                 //qboolean  creepTest;
138     BOOSTER_CREEPSIZE,     //int       creepSize;
139     qfalse,                //qboolean  dccTest;
140     qfalse                 //qboolean  reactorTest;
141   },
142   {
143     BA_A_ACIDTUBE,         //int       buildNum;
144     "acid_tube",           //char      *buildName;
145     "Acid Tube",           //char      *humanName;
146     "team_alien_acid_tube",//char      *entityName;
147     { "models/buildables/acid_tube/acid_tube.md3", 0, 0, 0 },
148     1.0f,                  //float     modelScale;
149     { -25, -25, -25 },     //vec3_t    mins;
150     { 25, 25, 25 },        //vec3_t    maxs;
151     -15.0f,                //float     zOffset;
152     TR_GRAVITY,            //trType_t  traj;
153     0.0,                   //float     bounce;
154     ACIDTUBE_BP,           //int       buildPoints;
155     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
156     ACIDTUBE_HEALTH,       //int       health;
157     ACIDTUBE_REGEN,        //int       regenRate;
158     ACIDTUBE_SPLASHDAMAGE, //int       splashDamage;
159     ACIDTUBE_SPLASHRADIUS, //int       splashRadius;
160     MOD_ATUBE,             //int       meansOfDeath;
161     BIT_ALIENS,            //int       team;
162     ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ),    //weapon_t  buildWeapon;
163     BANIM_IDLE1,           //int       idleAnim;
164     200,                   //int       nextthink;
165     ACIDTUBE_BT,           //int       buildTime;
166     qfalse,                //qboolean  usable;
167     0,                     //int       turretRange;
168     0,                     //int       turretFireSpeed;
169     WP_NONE,               //weapon_t  turretProjType;
170     0.0f,                  //float     minNormal;
171     qtrue,                 //qboolean  invertNormal;
172     qtrue,                 //qboolean  creepTest;
173     ACIDTUBE_CREEPSIZE,    //int       creepSize;
174     qfalse,                //qboolean  dccTest;
175     qfalse                 //qboolean  reactorTest;
176   },
177   {
178     BA_A_HIVE,             //int       buildNum;
179     "hive",                //char      *buildName;
180     "Hive",                //char      *humanName;
181     "team_alien_hive",     //char      *entityName;
182     { "models/buildables/acid_tube/acid_tube.md3", 0, 0, 0 },
183     1.0f,                  //float     modelScale;
184     { -35, -35, -25 },     //vec3_t    mins;
185     { 35, 35, 25 },        //vec3_t    maxs;
186     -15.0f,                //float     zOffset;
187     TR_GRAVITY,            //trType_t  traj;
188     0.0,                   //float     bounce;
189     HIVE_BP,               //int       buildPoints;
190     ( 1 << S3 ),           //int  stages
191     HIVE_HEALTH,           //int       health;
192     HIVE_REGEN,            //int       regenRate;
193     HIVE_SPLASHDAMAGE,     //int       splashDamage;
194     HIVE_SPLASHRADIUS,     //int       splashRadius;
195     MOD_ASPAWN,            //int       meansOfDeath;
196     BIT_ALIENS,            //int       team;
197     ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ),    //weapon_t  buildWeapon;
198     BANIM_IDLE1,           //int       idleAnim;
199     500,                   //int       nextthink;
200     HIVE_BT,               //int       buildTime;
201     qfalse,                //qboolean  usable;
202     0,                     //int       turretRange;
203     0,                     //int       turretFireSpeed;
204     WP_HIVE,               //weapon_t  turretProjType;
205     0.0f,                  //float     minNormal;
206     qtrue,                 //qboolean  invertNormal;
207     qtrue,                 //qboolean  creepTest;
208     HIVE_CREEPSIZE,        //int       creepSize;
209     qfalse,                //qboolean  dccTest;
210     qfalse                 //qboolean  reactorTest;
211   },
212   {
213     BA_A_TRAPPER,          //int       buildNum;
214     "trapper",             //char      *buildName;
215     "Trapper",             //char      *humanName;
216     "team_alien_trapper",  //char      *entityName;
217     { "models/buildables/trapper/trapper.md3", 0, 0, 0 },
218     1.0f,                  //float     modelScale;
219     { -15, -15, -15 },     //vec3_t    mins;
220     { 15, 15, 15 },        //vec3_t    maxs;
221     0.0f,                  //float     zOffset;
222     TR_GRAVITY,            //trType_t  traj;
223     0.0,                   //float     bounce;
224     TRAPPER_BP,            //int       buildPoints;
225     ( 1 << S2 )|( 1 << S3 ), //int  stages //NEEDS ADV BUILDER SO S2 AND UP
226     TRAPPER_HEALTH,        //int       health;
227     TRAPPER_REGEN,         //int       regenRate;
228     TRAPPER_SPLASHDAMAGE,  //int       splashDamage;
229     TRAPPER_SPLASHRADIUS,  //int       splashRadius;
230     MOD_ASPAWN,            //int       meansOfDeath;
231     BIT_ALIENS,            //int       team;
232     ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ),    //weapon_t  buildWeapon;
233     BANIM_IDLE1,           //int       idleAnim;
234     100,                   //int       nextthink;
235     TRAPPER_BT,            //int       buildTime;
236     qfalse,                //qboolean  usable;
237     TRAPPER_RANGE,         //int       turretRange;
238     TRAPPER_REPEAT,        //int       turretFireSpeed;
239     WP_LOCKBLOB_LAUNCHER,  //weapon_t  turretProjType;
240     0.0f,                  //float     minNormal;
241     qtrue,                 //qboolean  invertNormal;
242     qtrue,                 //qboolean  creepTest;
243     TRAPPER_CREEPSIZE,     //int       creepSize;
244     qfalse,                //qboolean  dccTest;
245     qfalse                 //qboolean  reactorTest;
246   },
247   {
248     BA_A_OVERMIND,         //int       buildNum;
249     "overmind",            //char      *buildName;
250     "Overmind",            //char      *humanName;
251     "team_alien_overmind", //char      *entityName;
252     { "models/buildables/overmind/overmind.md3", 0, 0, 0 },
253     1.0f,                  //float     modelScale;
254     { -45, -45, -15 },     //vec3_t    mins;
255     { 45, 45, 95 },        //vec3_t    maxs;
256     0.0f,                  //float     zOffset;
257     TR_GRAVITY,            //trType_t  traj;
258     0.0,                   //float     bounce;
259     OVERMIND_BP,           //int       buildPoints;
260     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
261     OVERMIND_HEALTH,       //int       health;
262     OVERMIND_REGEN,        //int       regenRate;
263     OVERMIND_SPLASHDAMAGE, //int       splashDamage;
264     OVERMIND_SPLASHRADIUS, //int       splashRadius;
265     MOD_ASPAWN,            //int       meansOfDeath;
266     BIT_ALIENS,            //int       team;
267     ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ),    //weapon_t  buildWeapon;
268     BANIM_IDLE1,           //int       idleAnim;
269     OVERMIND_ATTACK_REPEAT,//int       nextthink;
270     OVERMIND_BT,           //int       buildTime;
271     qfalse,                //qboolean  usable;
272     0,                     //int       turretRange;
273     0,                     //int       turretFireSpeed;
274     WP_NONE,               //weapon_t  turretProjType;
275     0.95f,                 //float     minNormal;
276     qfalse,                //qboolean  invertNormal;
277     qfalse,                //qboolean  creepTest;
278     OVERMIND_CREEPSIZE,    //int       creepSize;
279     qfalse,                //qboolean  dccTest;
280     qtrue                  //qboolean  reactorTest;
281   },
282   {
283     BA_A_HOVEL,            //int       buildNum;
284     "hovel",               //char      *buildName;
285     "Hovel",               //char      *humanName;
286     "team_alien_hovel",    //char      *entityName;
287     { "models/buildables/hovel/hovel.md3", 0, 0, 0 },
288     1.0f,                  //float     modelScale;
289     { -50, -50, -20 },     //vec3_t    mins;
290     { 50, 50, 20 },        //vec3_t    maxs;
291     0.0f,                  //float     zOffset;
292     TR_GRAVITY,            //trType_t  traj;
293     0.0,                   //float     bounce;
294     HOVEL_BP,              //int       buildPoints;
295     ( 1 << S3 ),           //int  stages
296     HOVEL_HEALTH,          //int       health;
297     HOVEL_REGEN,           //int       regenRate;
298     HOVEL_SPLASHDAMAGE,    //int       splashDamage;
299     HOVEL_SPLASHRADIUS,    //int       splashRadius;
300     MOD_ASPAWN,            //int       meansOfDeath;
301     BIT_ALIENS,            //int       team;
302     ( 1 << WP_ABUILD )|( 1 << WP_ABUILD2 ),    //weapon_t  buildWeapon;
303     BANIM_IDLE1,           //int       idleAnim;
304     150,                   //int       nextthink;
305     HOVEL_BT,              //int       buildTime;
306     qtrue,                 //qboolean  usable;
307     0,                     //int       turretRange;
308     0,                     //int       turretFireSpeed;
309     WP_NONE,               //weapon_t  turretProjType;
310     0.95f,                 //float     minNormal;
311     qfalse,                //qboolean  invertNormal;
312     qtrue,                 //qboolean  creepTest;
313     HOVEL_CREEPSIZE,       //int       creepSize;
314     qfalse,                //qboolean  dccTest;
315     qtrue                  //qboolean  reactorTest;
316   },
317   {
318     BA_H_SPAWN,            //int       buildNum;
319     "telenode",            //char      *buildName;
320     "Telenode",            //char      *humanName;
321     "team_human_spawn",    //char      *entityName;
322     { "models/buildables/telenode/telenode.md3", 0, 0, 0 },
323     1.0f,                  //float     modelScale;
324     { -40, -40, -4 },      //vec3_t    mins;
325     { 40, 40, 4 },         //vec3_t    maxs;
326     0.0f,                  //float     zOffset;
327     TR_GRAVITY,            //trType_t  traj;
328     0.0,                   //float     bounce;
329     HSPAWN_BP,             //int       buildPoints;
330     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
331     HSPAWN_HEALTH,         //int       health;
332     0,                     //int       regenRate;
333     HSPAWN_SPLASHDAMAGE,   //int       splashDamage;
334     HSPAWN_SPLASHRADIUS,   //int       splashRadius;
335     MOD_HSPAWN,            //int       meansOfDeath;
336     BIT_HUMANS,            //int       team;
337     ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ),    //weapon_t  buildWeapon;
338     BANIM_IDLE1,           //int       idleAnim;
339     100,                   //int       nextthink;
340     HSPAWN_BT,             //int       buildTime;
341     qfalse,                //qboolean  usable;
342     0,                     //int       turretRange;
343     0,                     //int       turretFireSpeed;
344     WP_NONE,               //weapon_t  turretProjType;
345     0.95f,                 //float     minNormal;
346     qfalse,                //qboolean  invertNormal;
347     qfalse,                //qboolean  creepTest;
348     0,                     //int       creepSize;
349     qfalse,                //qboolean  dccTest;
350     qfalse                 //qboolean  reactorTest;
351   },
352   {
353     BA_H_MEDISTAT,         //int       buildNum;
354     "medistat",            //char      *buildName;
355     "Medistation",         //char      *humanName;
356     "team_human_medistat", //char      *entityName;
357     { "models/buildables/medistat/medistat.md3", 0, 0, 0 },
358     1.0f,                  //float     modelScale;
359     { -35, -35, -7 },      //vec3_t    mins;
360     { 35, 35, 7 },         //vec3_t    maxs;
361     0.0f,                  //float     zOffset;
362     TR_GRAVITY,            //trType_t  traj;
363     0.0,                   //float     bounce;
364     MEDISTAT_BP,           //int       buildPoints;
365     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
366     MEDISTAT_HEALTH,       //int       health;
367     0,                     //int       regenRate;
368     MEDISTAT_SPLASHDAMAGE, //int       splashDamage;
369     MEDISTAT_SPLASHRADIUS, //int       splashRadius;
370     MOD_HSPAWN,            //int       meansOfDeath;
371     BIT_HUMANS,            //int       team;
372     ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ),    //weapon_t  buildWeapon;
373     BANIM_IDLE1,           //int       idleAnim;
374     100,                   //int       nextthink;
375     MEDISTAT_BT,           //int       buildTime;
376     qfalse,                //qboolean  usable;
377     0,                     //int       turretRange;
378     0,                     //int       turretFireSpeed;
379     WP_NONE,               //weapon_t  turretProjType;
380     0.95f,                 //float     minNormal;
381     qfalse,                //qboolean  invertNormal;
382     qfalse,                //qboolean  creepTest;
383     0,                     //int       creepSize;
384     qfalse,                //qboolean  dccTest;
385     qfalse                 //qboolean  reactorTest;
386   },
387   {
388     BA_H_MGTURRET,         //int       buildNum;
389     "mgturret",            //char      *buildName;
390     "Machinegun Turret",   //char      *humanName;
391     "team_human_mgturret", //char      *entityName;
392     { "models/buildables/mgturret/turret_base.md3",
393       "models/buildables/mgturret/turret_barrel.md3",
394       "models/buildables/mgturret/turret_top.md3", 0 },
395     1.0f,                  //float     modelScale;
396     { -25, -25, -20 },     //vec3_t    mins;
397     { 25, 25, 20 },        //vec3_t    maxs;
398     0.0f,                  //float     zOffset;
399     TR_GRAVITY,            //trType_t  traj;
400     0.0,                   //float     bounce;
401     MGTURRET_BP,           //int       buildPoints;
402     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
403     MGTURRET_HEALTH,       //int       health;
404     0,                     //int       regenRate;
405     MGTURRET_SPLASHDAMAGE, //int       splashDamage;
406     MGTURRET_SPLASHRADIUS, //int       splashRadius;
407     MOD_HSPAWN,            //int       meansOfDeath;
408     BIT_HUMANS,            //int       team;
409     ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ),   //weapon_t  buildWeapon;
410     BANIM_IDLE1,           //int       idleAnim;
411     50,                    //int       nextthink;
412     MGTURRET_BT,           //int       buildTime;
413     qfalse,                //qboolean  usable;
414     MGTURRET_RANGE,        //int       turretRange;
415     MGTURRET_REPEAT,       //int       turretFireSpeed;
416     WP_MGTURRET,           //weapon_t  turretProjType;
417     0.95f,                 //float     minNormal;
418     qfalse,                //qboolean  invertNormal;
419     qfalse,                //qboolean  creepTest;
420     0,                     //int       creepSize;
421     qfalse,                //qboolean  dccTest;
422     qfalse                 //qboolean  reactorTest;
423   },
424   {
425     BA_H_TESLAGEN,         //int       buildNum;
426     "tesla",               //char      *buildName;
427     "Tesla Generator",     //char      *humanName;
428     "team_human_tesla",    //char      *entityName;
429     { "models/buildables/tesla/tesla.md3", 0, 0, 0 },
430     1.0f,                  //float     modelScale;
431     { -22, -22, -40 },     //vec3_t    mins;
432     { 22, 22, 40 },        //vec3_t    maxs;
433     0.0f,                  //float     zOffset;
434     TR_GRAVITY,            //trType_t  traj;
435     0.0,                   //float     bounce;
436     TESLAGEN_BP,           //int       buildPoints;
437     ( 1 << S3 ),           //int       stages
438     TESLAGEN_HEALTH,       //int       health;
439     0,                     //int       regenRate;
440     TESLAGEN_SPLASHDAMAGE, //int       splashDamage;
441     TESLAGEN_SPLASHRADIUS, //int       splashRadius;
442     MOD_HSPAWN,            //int       meansOfDeath;
443     BIT_HUMANS,            //int       team;
444     ( 1 << WP_HBUILD2 ),   //weapon_t  buildWeapon;
445     BANIM_IDLE1,           //int       idleAnim;
446     150,                   //int       nextthink;
447     TESLAGEN_BT,           //int       buildTime;
448     qfalse,                //qboolean  usable;
449     TESLAGEN_RANGE,        //int       turretRange;
450     TESLAGEN_REPEAT,       //int       turretFireSpeed;
451     WP_TESLAGEN,           //weapon_t  turretProjType;
452     0.95f,                 //float     minNormal;
453     qfalse,                //qboolean  invertNormal;
454     qfalse,                //qboolean  creepTest;
455     0,                     //int       creepSize;
456     qtrue,                 //qboolean  dccTest;
457     qfalse                 //qboolean  reactorTest;
458   },
459   {
460     BA_H_DCC,              //int       buildNum;
461     "dcc",                 //char      *buildName;
462     "Defence Computer",    //char      *humanName;
463     "team_human_dcc",      //char      *entityName;
464     { "models/buildables/dcc/dcc.md3", 0, 0, 0 },
465     1.0f,                  //float     modelScale;
466     { -35, -35, -13 },     //vec3_t    mins;
467     { 35, 35, 47 },        //vec3_t    maxs;
468     0.0f,                  //float     zOffset;
469     TR_GRAVITY,            //trType_t  traj;
470     0.0,                   //float     bounce;
471     DC_BP,                 //int       buildPoints;
472     ( 1 << S2 )|( 1 << S3 ), //int       stages
473     DC_HEALTH,             //int       health;
474     0,                     //int       regenRate;
475     DC_SPLASHDAMAGE,       //int       splashDamage;
476     DC_SPLASHRADIUS,       //int       splashRadius;
477     MOD_HSPAWN,            //int       meansOfDeath;
478     BIT_HUMANS,            //int       team;
479     ( 1 << WP_HBUILD2 ),   //weapon_t  buildWeapon;
480     BANIM_IDLE1,           //int       idleAnim;
481     100,                   //int       nextthink;
482     DC_BT,                 //int       buildTime;
483     qfalse,                //qboolean  usable;
484     0,                     //int       turretRange;
485     0,                     //int       turretFireSpeed;
486     WP_NONE,               //weapon_t  turretProjType;
487     0.95f,                 //float     minNormal;
488     qfalse,                //qboolean  invertNormal;
489     qfalse,                //qboolean  creepTest;
490     0,                     //int       creepSize;
491     qfalse,                //qboolean  dccTest;
492     qfalse                 //qboolean  reactorTest;
493   },
494   {
495     BA_H_ARMOURY,          //int       buildNum;
496     "arm",                 //char      *buildName;
497     "Armoury",             //char      *humanName;
498     "team_human_armoury",  //char      *entityName;
499     { "models/buildables/arm/arm.md3", 0, 0, 0 },
500     1.0f,                  //float     modelScale;
501     { -40, -40, -13 },     //vec3_t    mins;
502     { 40, 40, 50 },        //vec3_t    maxs;
503     0.0f,                  //float     zOffset;
504     TR_GRAVITY,            //trType_t  traj;
505     0.0,                   //float     bounce;
506     ARMOURY_BP,            //int       buildPoints;
507     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
508     ARMOURY_HEALTH,        //int       health;
509     0,                     //int       regenRate;
510     ARMOURY_SPLASHDAMAGE,  //int       splashDamage;
511     ARMOURY_SPLASHRADIUS,  //int       splashRadius;
512     MOD_HSPAWN,            //int       meansOfDeath;
513     BIT_HUMANS,            //int       team;
514     ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ),    //weapon_t  buildWeapon;
515     BANIM_IDLE1,           //int       idleAnim;
516     100,                   //int       nextthink;
517     ARMOURY_BT,            //int       buildTime;
518     qtrue,                 //qboolean  usable;
519     0,                     //int       turretRange;
520     0,                     //int       turretFireSpeed;
521     WP_NONE,               //weapon_t  turretProjType;
522     0.95f,                 //float     minNormal;
523     qfalse,                //qboolean  invertNormal;
524     qfalse,                //qboolean  creepTest;
525     0,                     //int       creepSize;
526     qfalse,                //qboolean  dccTest;
527     qfalse                 //qboolean  reactorTest;
528   },
529   {
530     BA_H_REACTOR,          //int       buildNum;
531     "reactor",             //char      *buildName;
532     "Reactor",             //char      *humanName;
533     "team_human_reactor",  //char      *entityName;
534     { "models/buildables/reactor/reactor.md3", 0, 0, 0 },
535     1.0f,                  //float     modelScale;
536     { -50, -50, -15 },     //vec3_t    mins;
537     { 50, 50, 95 },        //vec3_t    maxs;
538     0.0f,                  //float     zOffset;
539     TR_GRAVITY,            //trType_t  traj;
540     0.0,                   //float     bounce;
541     REACTOR_BP,            //int       buildPoints;
542     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
543     REACTOR_HEALTH,        //int       health;
544     0,                     //int       regenRate;
545     REACTOR_SPLASHDAMAGE,  //int       splashDamage;
546     REACTOR_SPLASHRADIUS,  //int       splashRadius;
547     MOD_HSPAWN,            //int       meansOfDeath;
548     BIT_HUMANS,            //int       team;
549     ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ),    //weapon_t  buildWeapon;
550     BANIM_IDLE1,           //int       idleAnim;
551     REACTOR_ATTACK_REPEAT, //int       nextthink;
552     REACTOR_BT,            //int       buildTime;
553     qtrue,                 //qboolean  usable;
554     0,                     //int       turretRange;
555     0,                     //int       turretFireSpeed;
556     WP_NONE,               //weapon_t  turretProjType;
557     0.95f,                 //float     minNormal;
558     qfalse,                //qboolean  invertNormal;
559     qfalse,                //qboolean  creepTest;
560     0,                     //int       creepSize;
561     qfalse,                //qboolean  dccTest;
562     qtrue                  //qboolean  reactorTest;
563   },
564   {
565     BA_H_REPEATER,         //int       buildNum;
566     "repeater",            //char      *buildName;
567     "Repeater",            //char      *humanName;
568     "team_human_repeater", //char      *entityName;
569     { "models/buildables/repeater/repeater.md3", 0, 0, 0 },
570     1.0f,                  //float     modelScale;
571     { -15, -15, -15 },     //vec3_t    mins;
572     { 15, 15, 25 },        //vec3_t    maxs;
573     0.0f,                  //float     zOffset;
574     TR_GRAVITY,            //trType_t  traj;
575     0.0,                   //float     bounce;
576     REPEATER_BP,           //int       buildPoints;
577     ( 1 << S2 )|( 1 << S3 ), //int  stages
578     REPEATER_HEALTH,       //int       health;
579     0,                     //int       regenRate;
580     REPEATER_SPLASHDAMAGE, //int       splashDamage;
581     REPEATER_SPLASHRADIUS, //int       splashRadius;
582     MOD_HSPAWN,            //int       meansOfDeath;
583     BIT_HUMANS,            //int       team;
584     ( 1 << WP_HBUILD )|( 1 << WP_HBUILD2 ),    //weapon_t  buildWeapon;
585     BANIM_IDLE1,           //int       idleAnim;
586     100,                   //int       nextthink;
587     REPEATER_BT,           //int       buildTime;
588     qtrue,                 //qboolean  usable;
589     0,                     //int       turretRange;
590     0,                     //int       turretFireSpeed;
591     WP_NONE,               //weapon_t  turretProjType;
592     0.95f,                 //float     minNormal;
593     qfalse,                //qboolean  invertNormal;
594     qfalse,                //qboolean  creepTest;
595     0,                     //int       creepSize;
596     qfalse,                //qboolean  dccTest;
597     qfalse                 //qboolean  reactorTest;
598   }
599 };
600 
601 int   bg_numBuildables = sizeof( bg_buildableList ) / sizeof( bg_buildableList[ 0 ] );
602 
603 //separate from bg_buildableList to work around char struct init bug
604 buildableAttributeOverrides_t bg_buildableOverrideList[ BA_NUM_BUILDABLES ];
605 
606 /*
607 ==============
608 BG_FindBuildNumForName
609 ==============
610 */
BG_FindBuildNumForName(char * name)611 int BG_FindBuildNumForName( char *name )
612 {
613   int i;
614 
615   for( i = 0; i < bg_numBuildables; i++ )
616   {
617     if( !Q_stricmp( bg_buildableList[ i ].buildName, name ) )
618       return bg_buildableList[ i ].buildNum;
619   }
620 
621   //wimp out
622   return BA_NONE;
623 }
624 
625 /*
626 ==============
627 BG_FindBuildNumForEntityName
628 ==============
629 */
BG_FindBuildNumForEntityName(char * name)630 int BG_FindBuildNumForEntityName( char *name )
631 {
632   int i;
633 
634   for( i = 0; i < bg_numBuildables; i++ )
635   {
636     if( !Q_stricmp( bg_buildableList[ i ].entityName, name ) )
637       return bg_buildableList[ i ].buildNum;
638   }
639 
640   //wimp out
641   return BA_NONE;
642 }
643 
644 /*
645 ==============
646 BG_FindNameForBuildNum
647 ==============
648 */
BG_FindNameForBuildable(int bclass)649 char *BG_FindNameForBuildable( int bclass )
650 {
651   int i;
652 
653   for( i = 0; i < bg_numBuildables; i++ )
654   {
655     if( bg_buildableList[ i ].buildNum == bclass )
656       return bg_buildableList[ i ].buildName;
657   }
658 
659   //wimp out
660   return 0;
661 }
662 
663 /*
664 ==============
665 BG_FindHumanNameForBuildNum
666 ==============
667 */
BG_FindHumanNameForBuildable(int bclass)668 char *BG_FindHumanNameForBuildable( int bclass )
669 {
670   int i;
671 
672   for( i = 0; i < bg_numBuildables; i++ )
673   {
674     if( bg_buildableList[ i ].buildNum == bclass )
675       return bg_buildableList[ i ].humanName;
676   }
677 
678   //wimp out
679   return 0;
680 }
681 
682 /*
683 ==============
684 BG_FindEntityNameForBuildNum
685 ==============
686 */
BG_FindEntityNameForBuildable(int bclass)687 char *BG_FindEntityNameForBuildable( int bclass )
688 {
689   int i;
690 
691   for( i = 0; i < bg_numBuildables; i++ )
692   {
693     if( bg_buildableList[ i ].buildNum == bclass )
694       return bg_buildableList[ i ].entityName;
695   }
696 
697   //wimp out
698   return 0;
699 }
700 
701 /*
702 ==============
703 BG_FindModelsForBuildNum
704 ==============
705 */
BG_FindModelsForBuildable(int bclass,int modelNum)706 char *BG_FindModelsForBuildable( int bclass, int modelNum )
707 {
708   int i;
709 
710   if( bg_buildableOverrideList[ bclass ].models[ modelNum ][ 0 ] != 0 )
711     return bg_buildableOverrideList[ bclass ].models[ modelNum ];
712 
713   for( i = 0; i < bg_numBuildables; i++ )
714   {
715     if( bg_buildableList[ i ].buildNum == bclass )
716       return bg_buildableList[ i ].models[ modelNum ];
717   }
718 
719   //wimp out
720   return 0;
721 }
722 
723 /*
724 ==============
725 BG_FindModelScaleForBuildable
726 ==============
727 */
BG_FindModelScaleForBuildable(int bclass)728 float BG_FindModelScaleForBuildable( int bclass )
729 {
730   int i;
731 
732   if( bg_buildableOverrideList[ bclass ].modelScale != 0.0f )
733     return bg_buildableOverrideList[ bclass ].modelScale;
734 
735   for( i = 0; i < bg_numBuildables; i++ )
736   {
737     if( bg_buildableList[ i ].buildNum == bclass )
738       return bg_buildableList[ i ].modelScale;
739   }
740 
741   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindModelScaleForBuildable( %d )\n", bclass );
742   return 1.0f;
743 }
744 
745 /*
746 ==============
747 BG_FindBBoxForBuildable
748 ==============
749 */
BG_FindBBoxForBuildable(int bclass,vec3_t mins,vec3_t maxs)750 void BG_FindBBoxForBuildable( int bclass, vec3_t mins, vec3_t maxs )
751 {
752   int i;
753 
754   for( i = 0; i < bg_numBuildables; i++ )
755   {
756     if( bg_buildableList[ i ].buildNum == bclass )
757     {
758       if( mins != NULL )
759       {
760         VectorCopy( bg_buildableList[ i ].mins, mins );
761 
762         if( VectorLength( bg_buildableOverrideList[ bclass ].mins ) )
763           VectorCopy( bg_buildableOverrideList[ bclass ].mins, mins );
764       }
765 
766       if( maxs != NULL )
767       {
768         VectorCopy( bg_buildableList[ i ].maxs, maxs );
769 
770         if( VectorLength( bg_buildableOverrideList[ bclass ].maxs ) )
771           VectorCopy( bg_buildableOverrideList[ bclass ].maxs, maxs );
772       }
773 
774       return;
775     }
776   }
777 
778   if( mins != NULL )
779     VectorCopy( bg_buildableList[ 0 ].mins, mins );
780 
781   if( maxs != NULL )
782     VectorCopy( bg_buildableList[ 0 ].maxs, maxs );
783 }
784 
785 /*
786 ==============
787 BG_FindZOffsetForBuildable
788 ==============
789 */
BG_FindZOffsetForBuildable(int bclass)790 float BG_FindZOffsetForBuildable( int bclass )
791 {
792   int i;
793 
794   if( bg_buildableOverrideList[ bclass ].zOffset != 0.0f )
795     return bg_buildableOverrideList[ bclass ].zOffset;
796 
797   for( i = 0; i < bg_numBuildables; i++ )
798   {
799     if( bg_buildableList[ i ].buildNum == bclass )
800     {
801       return bg_buildableList[ i ].zOffset;
802     }
803   }
804 
805   return 0.0f;
806 }
807 
808 /*
809 ==============
810 BG_FindTrajectoryForBuildable
811 ==============
812 */
BG_FindTrajectoryForBuildable(int bclass)813 trType_t BG_FindTrajectoryForBuildable( int bclass )
814 {
815   int i;
816 
817   for( i = 0; i < bg_numBuildables; i++ )
818   {
819     if( bg_buildableList[ i ].buildNum == bclass )
820     {
821       return bg_buildableList[ i ].traj;
822     }
823   }
824 
825   return TR_GRAVITY;
826 }
827 
828 /*
829 ==============
830 BG_FindBounceForBuildable
831 ==============
832 */
BG_FindBounceForBuildable(int bclass)833 float BG_FindBounceForBuildable( int bclass )
834 {
835   int i;
836 
837   for( i = 0; i < bg_numBuildables; i++ )
838   {
839     if( bg_buildableList[ i ].buildNum == bclass )
840     {
841       return bg_buildableList[ i ].bounce;
842     }
843   }
844 
845   return 0.0;
846 }
847 
848 /*
849 ==============
850 BG_FindBuildPointsForBuildable
851 ==============
852 */
BG_FindBuildPointsForBuildable(int bclass)853 int BG_FindBuildPointsForBuildable( int bclass )
854 {
855   int i;
856 
857   for( i = 0; i < bg_numBuildables; i++ )
858   {
859     if( bg_buildableList[ i ].buildNum == bclass )
860     {
861       return bg_buildableList[ i ].buildPoints;
862     }
863   }
864 
865   return 1000;
866 }
867 
868 /*
869 ==============
870 BG_FindStagesForBuildable
871 ==============
872 */
BG_FindStagesForBuildable(int bclass,stage_t stage)873 qboolean BG_FindStagesForBuildable( int bclass, stage_t stage )
874 {
875   int i;
876 
877   for( i = 0; i < bg_numBuildables; i++ )
878   {
879     if( bg_buildableList[ i ].buildNum == bclass )
880     {
881       if( bg_buildableList[ i ].stages & ( 1 << stage ) )
882         return qtrue;
883       else
884         return qfalse;
885     }
886   }
887 
888   return qfalse;
889 }
890 
891 /*
892 ==============
893 BG_FindHealthForBuildable
894 ==============
895 */
BG_FindHealthForBuildable(int bclass)896 int BG_FindHealthForBuildable( int bclass )
897 {
898   int i;
899 
900   for( i = 0; i < bg_numBuildables; i++ )
901   {
902     if( bg_buildableList[ i ].buildNum == bclass )
903     {
904       return bg_buildableList[ i ].health;
905     }
906   }
907 
908   return 1000;
909 }
910 
911 /*
912 ==============
913 BG_FindRegenRateForBuildable
914 ==============
915 */
BG_FindRegenRateForBuildable(int bclass)916 int BG_FindRegenRateForBuildable( int bclass )
917 {
918   int i;
919 
920   for( i = 0; i < bg_numBuildables; i++ )
921   {
922     if( bg_buildableList[ i ].buildNum == bclass )
923     {
924       return bg_buildableList[ i ].regenRate;
925     }
926   }
927 
928   return 0;
929 }
930 
931 /*
932 ==============
933 BG_FindSplashDamageForBuildable
934 ==============
935 */
BG_FindSplashDamageForBuildable(int bclass)936 int BG_FindSplashDamageForBuildable( int bclass )
937 {
938   int i;
939 
940   for( i = 0; i < bg_numBuildables; i++ )
941   {
942     if( bg_buildableList[ i ].buildNum == bclass )
943     {
944       return bg_buildableList[ i ].splashDamage;
945     }
946   }
947 
948   return 50;
949 }
950 
951 /*
952 ==============
953 BG_FindSplashRadiusForBuildable
954 ==============
955 */
BG_FindSplashRadiusForBuildable(int bclass)956 int BG_FindSplashRadiusForBuildable( int bclass )
957 {
958   int i;
959 
960   for( i = 0; i < bg_numBuildables; i++ )
961   {
962     if( bg_buildableList[ i ].buildNum == bclass )
963     {
964       return bg_buildableList[ i ].splashRadius;
965     }
966   }
967 
968   return 200;
969 }
970 
971 /*
972 ==============
973 BG_FindMODForBuildable
974 ==============
975 */
BG_FindMODForBuildable(int bclass)976 int BG_FindMODForBuildable( int bclass )
977 {
978   int i;
979 
980   for( i = 0; i < bg_numBuildables; i++ )
981   {
982     if( bg_buildableList[ i ].buildNum == bclass )
983     {
984       return bg_buildableList[ i ].meansOfDeath;
985     }
986   }
987 
988   return MOD_UNKNOWN;
989 }
990 
991 /*
992 ==============
993 BG_FindTeamForBuildable
994 ==============
995 */
BG_FindTeamForBuildable(int bclass)996 int BG_FindTeamForBuildable( int bclass )
997 {
998   int i;
999 
1000   for( i = 0; i < bg_numBuildables; i++ )
1001   {
1002     if( bg_buildableList[ i ].buildNum == bclass )
1003     {
1004       return bg_buildableList[ i ].team;
1005     }
1006   }
1007 
1008   return BIT_NONE;
1009 }
1010 
1011 /*
1012 ==============
1013 BG_FindBuildWeaponForBuildable
1014 ==============
1015 */
BG_FindBuildWeaponForBuildable(int bclass)1016 weapon_t BG_FindBuildWeaponForBuildable( int bclass )
1017 {
1018   int i;
1019 
1020   for( i = 0; i < bg_numBuildables; i++ )
1021   {
1022     if( bg_buildableList[ i ].buildNum == bclass )
1023     {
1024       return bg_buildableList[ i ].buildWeapon;
1025     }
1026   }
1027 
1028   return BA_NONE;
1029 }
1030 
1031 /*
1032 ==============
1033 BG_FindAnimForBuildable
1034 ==============
1035 */
BG_FindAnimForBuildable(int bclass)1036 int BG_FindAnimForBuildable( int bclass )
1037 {
1038   int i;
1039 
1040   for( i = 0; i < bg_numBuildables; i++ )
1041   {
1042     if( bg_buildableList[ i ].buildNum == bclass )
1043     {
1044       return bg_buildableList[ i ].idleAnim;
1045     }
1046   }
1047 
1048   return BANIM_IDLE1;
1049 }
1050 
1051 /*
1052 ==============
1053 BG_FindNextThinkForBuildable
1054 ==============
1055 */
BG_FindNextThinkForBuildable(int bclass)1056 int BG_FindNextThinkForBuildable( int bclass )
1057 {
1058   int i;
1059 
1060   for( i = 0; i < bg_numBuildables; i++ )
1061   {
1062     if( bg_buildableList[ i ].buildNum == bclass )
1063     {
1064       return bg_buildableList[ i ].nextthink;
1065     }
1066   }
1067 
1068   return 100;
1069 }
1070 
1071 /*
1072 ==============
1073 BG_FindBuildTimeForBuildable
1074 ==============
1075 */
BG_FindBuildTimeForBuildable(int bclass)1076 int BG_FindBuildTimeForBuildable( int bclass )
1077 {
1078   int i;
1079 
1080   for( i = 0; i < bg_numBuildables; i++ )
1081   {
1082     if( bg_buildableList[ i ].buildNum == bclass )
1083     {
1084       return bg_buildableList[ i ].buildTime;
1085     }
1086   }
1087 
1088   return 10000;
1089 }
1090 
1091 /*
1092 ==============
1093 BG_FindUsableForBuildable
1094 ==============
1095 */
BG_FindUsableForBuildable(int bclass)1096 qboolean BG_FindUsableForBuildable( int bclass )
1097 {
1098   int i;
1099 
1100   for( i = 0; i < bg_numBuildables; i++ )
1101   {
1102     if( bg_buildableList[ i ].buildNum == bclass )
1103     {
1104       return bg_buildableList[ i ].usable;
1105     }
1106   }
1107 
1108   return qfalse;
1109 }
1110 
1111 /*
1112 ==============
1113 BG_FindFireSpeedForBuildable
1114 ==============
1115 */
BG_FindFireSpeedForBuildable(int bclass)1116 int BG_FindFireSpeedForBuildable( int bclass )
1117 {
1118   int i;
1119 
1120   for( i = 0; i < bg_numBuildables; i++ )
1121   {
1122     if( bg_buildableList[ i ].buildNum == bclass )
1123     {
1124       return bg_buildableList[ i ].turretFireSpeed;
1125     }
1126   }
1127 
1128   return 1000;
1129 }
1130 
1131 /*
1132 ==============
1133 BG_FindRangeForBuildable
1134 ==============
1135 */
BG_FindRangeForBuildable(int bclass)1136 int BG_FindRangeForBuildable( int bclass )
1137 {
1138   int i;
1139 
1140   for( i = 0; i < bg_numBuildables; i++ )
1141   {
1142     if( bg_buildableList[ i ].buildNum == bclass )
1143     {
1144       return bg_buildableList[ i ].turretRange;
1145     }
1146   }
1147 
1148   return 1000;
1149 }
1150 
1151 /*
1152 ==============
1153 BG_FindProjTypeForBuildable
1154 ==============
1155 */
BG_FindProjTypeForBuildable(int bclass)1156 weapon_t BG_FindProjTypeForBuildable( int bclass )
1157 {
1158   int i;
1159 
1160   for( i = 0; i < bg_numBuildables; i++ )
1161   {
1162     if( bg_buildableList[ i ].buildNum == bclass )
1163     {
1164       return bg_buildableList[ i ].turretProjType;
1165     }
1166   }
1167 
1168   return WP_NONE;
1169 }
1170 
1171 /*
1172 ==============
1173 BG_FindMinNormalForBuildable
1174 ==============
1175 */
BG_FindMinNormalForBuildable(int bclass)1176 float BG_FindMinNormalForBuildable( int bclass )
1177 {
1178   int i;
1179 
1180   for( i = 0; i < bg_numBuildables; i++ )
1181   {
1182     if( bg_buildableList[ i ].buildNum == bclass )
1183     {
1184       return bg_buildableList[ i ].minNormal;
1185     }
1186   }
1187 
1188   return 0.707f;
1189 }
1190 
1191 /*
1192 ==============
1193 BG_FindInvertNormalForBuildable
1194 ==============
1195 */
BG_FindInvertNormalForBuildable(int bclass)1196 qboolean BG_FindInvertNormalForBuildable( int bclass )
1197 {
1198   int i;
1199 
1200   for( i = 0; i < bg_numBuildables; i++ )
1201   {
1202     if( bg_buildableList[ i ].buildNum == bclass )
1203     {
1204       return bg_buildableList[ i ].invertNormal;
1205     }
1206   }
1207 
1208   return qfalse;
1209 }
1210 
1211 /*
1212 ==============
1213 BG_FindCreepTestForBuildable
1214 ==============
1215 */
BG_FindCreepTestForBuildable(int bclass)1216 int BG_FindCreepTestForBuildable( int bclass )
1217 {
1218   int i;
1219 
1220   for( i = 0; i < bg_numBuildables; i++ )
1221   {
1222     if( bg_buildableList[ i ].buildNum == bclass )
1223     {
1224       return bg_buildableList[ i ].creepTest;
1225     }
1226   }
1227 
1228   return qfalse;
1229 }
1230 
1231 /*
1232 ==============
1233 BG_FindCreepSizeForBuildable
1234 ==============
1235 */
BG_FindCreepSizeForBuildable(int bclass)1236 int BG_FindCreepSizeForBuildable( int bclass )
1237 {
1238   int i;
1239 
1240   for( i = 0; i < bg_numBuildables; i++ )
1241   {
1242     if( bg_buildableList[ i ].buildNum == bclass )
1243     {
1244       return bg_buildableList[ i ].creepSize;
1245     }
1246   }
1247 
1248   return CREEP_BASESIZE;
1249 }
1250 
1251 /*
1252 ==============
1253 BG_FindDCCTestForBuildable
1254 ==============
1255 */
BG_FindDCCTestForBuildable(int bclass)1256 int BG_FindDCCTestForBuildable( int bclass )
1257 {
1258   int i;
1259 
1260   for( i = 0; i < bg_numBuildables; i++ )
1261   {
1262     if( bg_buildableList[ i ].buildNum == bclass )
1263     {
1264       return bg_buildableList[ i ].dccTest;
1265     }
1266   }
1267 
1268   return qfalse;
1269 }
1270 
1271 /*
1272 ==============
1273 BG_FindUniqueTestForBuildable
1274 ==============
1275 */
BG_FindUniqueTestForBuildable(int bclass)1276 int BG_FindUniqueTestForBuildable( int bclass )
1277 {
1278   int i;
1279 
1280   for( i = 0; i < bg_numBuildables; i++ )
1281   {
1282     if( bg_buildableList[ i ].buildNum == bclass )
1283     {
1284       return bg_buildableList[ i ].reactorTest;
1285     }
1286   }
1287 
1288   return qfalse;
1289 }
1290 
1291 /*
1292 ==============
1293 BG_FindOverrideForBuildable
1294 ==============
1295 */
BG_FindOverrideForBuildable(int bclass)1296 static buildableAttributeOverrides_t *BG_FindOverrideForBuildable( int bclass )
1297 {
1298   return &bg_buildableOverrideList[ bclass ];
1299 }
1300 
1301 /*
1302 ======================
1303 BG_ParseBuildableFile
1304 
1305 Parses a configuration file describing a builable
1306 ======================
1307 */
BG_ParseBuildableFile(const char * filename,buildableAttributeOverrides_t * bao)1308 static qboolean BG_ParseBuildableFile( const char *filename, buildableAttributeOverrides_t *bao )
1309 {
1310   char          *text_p;
1311   int           i;
1312   int           len;
1313   char          *token;
1314   char          text[ 20000 ];
1315   fileHandle_t  f;
1316   float         scale;
1317 
1318 
1319   // load the file
1320   len = trap_FS_FOpenFile( filename, &f, FS_READ );
1321   if( len <= 0 )
1322     return qfalse;
1323 
1324   if( len >= sizeof( text ) - 1 )
1325   {
1326     Com_Printf( S_COLOR_RED "ERROR: Buildable file %s too long\n", filename );
1327     return qfalse;
1328   }
1329 
1330   trap_FS_Read( text, len, f );
1331   text[ len ] = 0;
1332   trap_FS_FCloseFile( f );
1333 
1334   // parse the text
1335   text_p = text;
1336 
1337   // read optional parameters
1338   while( 1 )
1339   {
1340     token = COM_Parse( &text_p );
1341 
1342     if( !token )
1343       break;
1344 
1345     if( !Q_stricmp( token, "" ) )
1346       break;
1347 
1348     if( !Q_stricmp( token, "model" ) )
1349     {
1350       int index = 0;
1351 
1352       token = COM_Parse( &text_p );
1353       if( !token )
1354         break;
1355 
1356       index = atoi( token );
1357 
1358       if( index < 0 )
1359         index = 0;
1360       else if( index > 3 )
1361         index = 3;
1362 
1363       token = COM_Parse( &text_p );
1364       if( !token )
1365         break;
1366 
1367       Q_strncpyz( bao->models[ index ], token, sizeof( bao->models[ 0 ] ) );
1368 
1369       continue;
1370     }
1371     else if( !Q_stricmp( token, "modelScale" ) )
1372     {
1373       token = COM_Parse( &text_p );
1374       if( !token )
1375         break;
1376 
1377       scale = atof( token );
1378 
1379       if( scale < 0.0f )
1380         scale = 0.0f;
1381 
1382       bao->modelScale = scale;
1383 
1384       continue;
1385     }
1386     else if( !Q_stricmp( token, "mins" ) )
1387     {
1388       for( i = 0; i <= 2; i++ )
1389       {
1390         token = COM_Parse( &text_p );
1391         if( !token )
1392           break;
1393 
1394         bao->mins[ i ] = atof( token );
1395       }
1396 
1397       continue;
1398     }
1399     else if( !Q_stricmp( token, "maxs" ) )
1400     {
1401       for( i = 0; i <= 2; i++ )
1402       {
1403         token = COM_Parse( &text_p );
1404         if( !token )
1405           break;
1406 
1407         bao->maxs[ i ] = atof( token );
1408       }
1409 
1410       continue;
1411     }
1412     else if( !Q_stricmp( token, "zOffset" ) )
1413     {
1414       float offset;
1415 
1416       token = COM_Parse( &text_p );
1417       if( !token )
1418         break;
1419 
1420       offset = atof( token );
1421 
1422       bao->zOffset = offset;
1423 
1424       continue;
1425     }
1426 
1427 
1428     Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token );
1429     return qfalse;
1430   }
1431 
1432   return qtrue;
1433 }
1434 
1435 /*
1436 ===============
1437 BG_InitBuildableOverrides
1438 
1439 Set any overrides specfied by file
1440 ===============
1441 */
BG_InitBuildableOverrides(void)1442 void BG_InitBuildableOverrides( void )
1443 {
1444   int                           i;
1445   buildableAttributeOverrides_t *bao;
1446 
1447   for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ )
1448   {
1449     bao = BG_FindOverrideForBuildable( i );
1450 
1451     BG_ParseBuildableFile( va( "overrides/buildables/%s.cfg", BG_FindNameForBuildable( i ) ), bao );
1452   }
1453 }
1454 
1455 ////////////////////////////////////////////////////////////////////////////////
1456 
1457 classAttributes_t bg_classList[ ] =
1458 {
1459   {
1460     PCL_NONE,                                       //int     classnum;
1461     "spectator",                                    //char    *className;
1462     "Spectator",                                    //char    *humanName;
1463     "",                                             //char    *modelname;
1464     1.0f,                                           //float   modelScale;
1465     "",                                             //char    *skinname;
1466     1.0f,                                           //float   shadowScale;
1467     "",                                             //char    *hudname;
1468     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ),            //int  stages
1469     { -15, -15, -15 },                              //vec3_t  mins;
1470     { 15, 15, 15 },                                 //vec3_t  maxs;
1471     { 15, 15, 15 },                                 //vec3_t  crouchmaxs;
1472     { -15, -15, -15 },                              //vec3_t  deadmins;
1473     { 15, 15, 15 },                                 //vec3_t  deadmaxs;
1474     0.0f,                                           //float   zOffset
1475     0, 0,                                           //int     viewheight, crouchviewheight;
1476     0,                                              //int     health;
1477     0.0f,                                           //float   fallDamage;
1478     0,                                              //int     regenRate;
1479     0,                                              //int     abilities;
1480     WP_NONE,                                        //weapon_t  startWeapon
1481     0.0f,                                           //float   buildDist;
1482     90,                                             //int     fov;
1483     0.000f,                                         //float   bob;
1484     1.0f,                                           //float   bobCycle;
1485     0,                                              //int     steptime;
1486     600,                                            //float   speed;
1487     10.0f,                                          //float   acceleration;
1488     1.0f,                                           //float   airAcceleration;
1489     6.0f,                                           //float   friction;
1490     100.0f,                                         //float   stopSpeed;
1491     270.0f,                                         //float   jumpMagnitude;
1492     1.0f,                                           //float   knockbackScale;
1493     { PCL_NONE, PCL_NONE, PCL_NONE },               //int     children[ 3 ];
1494     0,                                              //int     cost;
1495     0                                               //int     value;
1496   },
1497   {
1498     PCL_ALIEN_BUILDER0,                             //int     classnum;
1499     "builder",                                      //char    *className;
1500     "Builder",                                      //char    *humanName;
1501     "builder",                                      //char    *modelname;
1502     1.0f,                                           //float   modelScale;
1503     "default",                                      //char    *skinname;
1504     1.0f,                                           //float   shadowScale;
1505     "alien_builder_hud",                            //char    *hudname;
1506     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ),            //int  stages
1507     { -15, -15, -20 },                              //vec3_t  mins;
1508     { 15, 15, 20 },                                 //vec3_t  maxs;
1509     { 15, 15, 20 },                                 //vec3_t  crouchmaxs;
1510     { -15, -15, -4 },                               //vec3_t  deadmins;
1511     { 15, 15, 4 },                                  //vec3_t  deadmaxs;
1512     0.0f,                                           //float   zOffset
1513     0, 0,                                           //int     viewheight, crouchviewheight;
1514     ABUILDER_HEALTH,                                //int     health;
1515     0.2f,                                           //float   fallDamage;
1516     ABUILDER_REGEN,                                 //int     regenRate;
1517     SCA_TAKESFALLDAMAGE|SCA_FOVWARPS|SCA_ALIENSENSE,//int     abilities;
1518     WP_ABUILD,                                      //weapon_t  startWeapon
1519     95.0f,                                          //float   buildDist;
1520     80,                                             //int     fov;
1521     0.001f,                                         //float   bob;
1522     2.0f,                                           //float   bobCycle;
1523     150,                                            //int     steptime;
1524     ABUILDER_SPEED,                                 //float   speed;
1525     10.0f,                                          //float   acceleration;
1526     1.0f,                                           //float   airAcceleration;
1527     6.0f,                                           //float   friction;
1528     100.0f,                                         //float   stopSpeed;
1529     195.0f,                                         //float   jumpMagnitude;
1530     1.0f,                                           //float   knockbackScale;
1531     { PCL_ALIEN_BUILDER0_UPG, PCL_ALIEN_LEVEL0, PCL_NONE },       //int     children[ 3 ];
1532     ABUILDER_COST,                                  //int     cost;
1533     ABUILDER_VALUE                                  //int     value;
1534   },
1535   {
1536     PCL_ALIEN_BUILDER0_UPG,                         //int     classnum;
1537     "builderupg",                                   //char    *classname;
1538     "Advanced Builder",                             //char    *humanname;
1539     "builder",                                      //char    *modelname;
1540     1.0f,                                           //float   modelScale;
1541     "advanced",                                     //char    *skinname;
1542     1.0f,                                           //float   shadowScale;
1543     "alien_builder_hud",                            //char    *hudname;
1544     ( 1 << S2 )|( 1 << S3 ),                        //int  stages
1545     { -20, -20, -20 },                              //vec3_t  mins;
1546     { 20, 20, 20 },                                 //vec3_t  maxs;
1547     { 20, 20, 20 },                                 //vec3_t  crouchmaxs;
1548     { -20, -20, -4 },                               //vec3_t  deadmins;
1549     { 20, 20, 4 },                                  //vec3_t  deadmaxs;
1550     0.0f,                                           //float   zOffset
1551     0, 0,                                           //int     viewheight, crouchviewheight;
1552     ABUILDER_UPG_HEALTH,                            //int     health;
1553     0.0f,                                           //float   fallDamage;
1554     ABUILDER_UPG_REGEN,                             //int     regenRate;
1555     SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE,    //int     abilities;
1556     WP_ABUILD2,                                     //weapon_t  startWeapon
1557     105.0f,                                         //float   buildDist;
1558     110,                                            //int     fov;
1559     0.001f,                                         //float   bob;
1560     2.0f,                                           //float   bobCycle;
1561     100,                                            //int     steptime;
1562     ABUILDER_UPG_SPEED,                             //float   speed;
1563     10.0f,                                          //float   acceleration;
1564     1.0f,                                           //float   airAcceleration;
1565     6.0f,                                           //float   friction;
1566     100.0f,                                         //float   stopSpeed;
1567     270.0f,                                         //float   jumpMagnitude;
1568     1.0f,                                           //float   knockbackScale;
1569     { PCL_ALIEN_LEVEL0, PCL_NONE, PCL_NONE },       //int     children[ 3 ];
1570     ABUILDER_UPG_COST,                              //int     cost;
1571     ABUILDER_UPG_VALUE                              //int     value;
1572   },
1573   {
1574     PCL_ALIEN_LEVEL0,                               //int     classnum;
1575     "level0",                                       //char    *classname;
1576     "Soldier",                                      //char    *humanname;
1577     "jumper",                                       //char    *modelname;
1578     0.2f,                                           //float   modelScale;
1579     "default",                                      //char    *skinname;
1580     0.3f,                                           //float   shadowScale;
1581     "alien_general_hud",                            //char    *hudname;
1582     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ),            //int  stages
1583     { -15, -15, -15 },                              //vec3_t  mins;
1584     { 15, 15, 15 },                                 //vec3_t  maxs;
1585     { 15, 15, 15 },                                 //vec3_t  crouchmaxs;
1586     { -15, -15, -4 },                               //vec3_t  deadmins;
1587     { 15, 15, 4 },                                  //vec3_t  deadmaxs;
1588     -8.0f,                                          //float   zOffset
1589     0, 0,                                           //int     viewheight, crouchviewheight;
1590     LEVEL0_HEALTH,                                  //int     health;
1591     0.0f,                                           //float   fallDamage;
1592     LEVEL0_REGEN,                                   //int     regenRate;
1593     SCA_WALLCLIMBER|SCA_NOWEAPONDRIFT|
1594       SCA_FOVWARPS|SCA_ALIENSENSE,                  //int     abilities;
1595     WP_ALEVEL0,                                     //weapon_t  startWeapon
1596     0.0f,                                           //float   buildDist;
1597     140,                                            //int     fov;
1598     0.0f,                                           //float   bob;
1599     2.5f,                                           //float   bobCycle;
1600     25,                                             //int     steptime;
1601     LEVEL0_SPEED,                                   //float   speed;
1602     10.0f,                                          //float   acceleration;
1603     1.0f,                                           //float   airAcceleration;
1604     6.0f,                                           //float   friction;
1605     400.0f,                                         //float   stopSpeed;
1606     250.0f,                                         //float   jumpMagnitude;
1607     2.0f,                                           //float   knockbackScale;
1608     { PCL_ALIEN_LEVEL1, PCL_NONE, PCL_NONE },       //int     children[ 3 ];
1609     LEVEL0_COST,                                    //int     cost;
1610     LEVEL0_VALUE                                    //int     value;
1611   },
1612   {
1613     PCL_ALIEN_LEVEL1,                               //int     classnum;
1614     "level1",                                       //char    *classname;
1615     "Hydra",                                        //char    *humanname;
1616     "spitter",                                      //char    *modelname;
1617     0.6f,                                           //float   modelScale;
1618     "default",                                      //char    *skinname;
1619     1.0f,                                           //float   shadowScale;
1620     "alien_general_hud",                            //char    *hudname;
1621     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ),            //int  stages
1622     { -18, -18, -18 },                              //vec3_t  mins;
1623     { 18, 18, 18 },                                 //vec3_t  maxs;
1624     { 18, 18, 18 },                                 //vec3_t  crouchmaxs;
1625     { -18, -18, -4 },                               //vec3_t  deadmins;
1626     { 18, 18, 4 },                                  //vec3_t  deadmaxs;
1627     0.0f,                                           //float   zOffset
1628     0, 0,                                           //int     viewheight, crouchviewheight;
1629     LEVEL1_HEALTH,                                  //int     health;
1630     0.0f,                                           //float   fallDamage;
1631     LEVEL1_REGEN,                                   //int     regenRate;
1632     SCA_NOWEAPONDRIFT|
1633       SCA_FOVWARPS|SCA_WALLCLIMBER|SCA_ALIENSENSE,  //int     abilities;
1634     WP_ALEVEL1,                                     //weapon_t  startWeapon
1635     0.0f,                                           //float   buildDist;
1636     120,                                            //int     fov;
1637     0.001f,                                         //float   bob;
1638     1.8f,                                           //float   bobCycle;
1639     60,                                             //int     steptime;
1640     LEVEL1_SPEED,                                   //float   speed;
1641     10.0f,                                          //float   acceleration;
1642     1.0f,                                           //float   airAcceleration;
1643     6.0f,                                           //float   friction;
1644     300.0f,                                         //float   stopSpeed;
1645     270.0f,                                         //float   jumpMagnitude;
1646     1.2f,                                           //float   knockbackScale;
1647     { PCL_ALIEN_LEVEL2, PCL_ALIEN_LEVEL1_UPG, PCL_NONE },   //int     children[ 3 ];
1648     LEVEL1_COST,                                     //int     cost;
1649     LEVEL1_VALUE                                     //int     value;
1650   },
1651   {
1652     PCL_ALIEN_LEVEL1_UPG,                           //int     classnum;
1653     "level1upg",                                    //char    *classname;
1654     "Hydra Upgrade",                                //char    *humanname;
1655     "spitter",                                      //char    *modelname;
1656     0.7f,                                           //float   modelScale;
1657     "blue",                                         //char    *skinname;
1658     1.0f,                                           //float   shadowScale;
1659     "alien_general_hud",                            //char    *hudname;
1660     ( 1 << S2 )|( 1 << S3 ),                        //int  stages
1661     { -20, -20, -20 },                              //vec3_t  mins;
1662     { 20, 20, 20 },                                 //vec3_t  maxs;
1663     { 20, 20, 20 },                                 //vec3_t  crouchmaxs;
1664     { -20, -20, -4 },                               //vec3_t  deadmins;
1665     { 20, 20, 4 },                                  //vec3_t  deadmaxs;
1666     0.0f,                                           //float   zOffset
1667     0, 0,                                           //int     viewheight, crouchviewheight;
1668     LEVEL1_UPG_HEALTH,                              //int     health;
1669     0.0f,                                           //float   fallDamage;
1670     LEVEL1_UPG_REGEN,                               //int     regenRate;
1671     SCA_NOWEAPONDRIFT|SCA_FOVWARPS|
1672       SCA_WALLCLIMBER|SCA_ALIENSENSE,               //int     abilities;
1673     WP_ALEVEL1_UPG,                                 //weapon_t  startWeapon
1674     0.0f,                                           //float   buildDist;
1675     120,                                            //int     fov;
1676     0.001f,                                         //float   bob;
1677     1.8f,                                           //float   bobCycle;
1678     60,                                             //int     steptime;
1679     LEVEL1_UPG_SPEED,                               //float   speed;
1680     10.0f,                                          //float   acceleration;
1681     1.0f,                                           //float   airAcceleration;
1682     6.0f,                                           //float   friction;
1683     300.0f,                                         //float   stopSpeed;
1684     270.0f,                                         //float   jumpMagnitude;
1685     1.1f,                                           //float   knockbackScale;
1686     { PCL_ALIEN_LEVEL2, PCL_NONE, PCL_NONE },       //int     children[ 3 ];
1687     LEVEL1_UPG_COST,                                //int     cost;
1688     LEVEL1_UPG_VALUE                                //int     value;
1689   },
1690   {
1691     PCL_ALIEN_LEVEL2,                               //int     classnum;
1692     "level2",                                       //char    *classname;
1693     "Chimera",                                      //char    *humanname;
1694     "tarantula",                                    //char    *modelname;
1695     0.75f,                                          //float   modelScale;
1696     "default",                                      //char    *skinname;
1697     1.0f,                                           //float   shadowScale;
1698     "alien_general_hud",                            //char    *hudname;
1699     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ),            //int  stages
1700     { -22, -22, -22 },                              //vec3_t  mins;
1701     { 22, 22, 22 },                                 //vec3_t  maxs;
1702     { 22, 22, 22 },                                 //vec3_t  crouchmaxs;
1703     { -22, -22, -4 },                               //vec3_t  deadmins;
1704     { 22, 22, 4 },                                  //vec3_t  deadmaxs;
1705     0.0f,                                           //float   zOffset
1706     10, 10,                                         //int     viewheight, crouchviewheight;
1707     LEVEL2_HEALTH,                                  //int     health;
1708     0.0f,                                           //float   fallDamage;
1709     LEVEL2_REGEN,                                   //int     regenRate;
1710     SCA_NOWEAPONDRIFT|SCA_WALLJUMPER|
1711       SCA_FOVWARPS|SCA_ALIENSENSE,                  //int     abilities;
1712     WP_ALEVEL2,                                     //weapon_t  startWeapon
1713     0.0f,                                           //float   buildDist;
1714     90,                                             //int     fov;
1715     0.001f,                                         //float   bob;
1716     1.5f,                                           //float   bobCycle;
1717     80,                                             //int     steptime;
1718     LEVEL2_SPEED,                                   //float   speed;
1719     10.0f,                                          //float   acceleration;
1720     2.0f,                                           //float   airAcceleration;
1721     6.0f,                                           //float   friction;
1722     100.0f,                                         //float   stopSpeed;
1723     400.0f,                                         //float   jumpMagnitude;
1724     0.8f,                                           //float   knockbackScale;
1725     { PCL_ALIEN_LEVEL3, PCL_ALIEN_LEVEL2_UPG, PCL_NONE },   //int     children[ 3 ];
1726     LEVEL2_COST,                                    //int     cost;
1727     LEVEL2_VALUE                                    //int     value;
1728   },
1729   {
1730     PCL_ALIEN_LEVEL2_UPG,                           //int     classnum;
1731     "level2upg",                                    //char    *classname;
1732     "Chimera Upgrade",                              //char    *humanname;
1733     "tarantula",                                    //char    *modelname;
1734     0.9f,                                           //float   modelScale;
1735     "red",                                          //char    *skinname;
1736     1.0f,                                           //float   shadowScale;
1737     "alien_general_hud",                            //char    *hudname;
1738     ( 1 << S2 )|( 1 << S3 ),                        //int  stages
1739     { -24, -24, -24 },                              //vec3_t  mins;
1740     { 24, 24, 24 },                                 //vec3_t  maxs;
1741     { 24, 24, 24 },                                 //vec3_t  crouchmaxs;
1742     { -24, -24, -4 },                               //vec3_t  deadmins;
1743     { 24, 24, 4 },                                  //vec3_t  deadmaxs;
1744     0.0f,                                           //float   zOffset
1745     12, 12,                                         //int     viewheight, crouchviewheight;
1746     LEVEL2_UPG_HEALTH,                              //int     health;
1747     0.0f,                                           //float   fallDamage;
1748     LEVEL2_UPG_REGEN,                               //int     regenRate;
1749     SCA_NOWEAPONDRIFT|SCA_WALLJUMPER|
1750       SCA_FOVWARPS|SCA_ALIENSENSE,                  //int     abilities;
1751     WP_ALEVEL2_UPG,                                 //weapon_t  startWeapon
1752     0.0f,                                           //float   buildDist;
1753     90,                                             //int     fov;
1754     0.001f,                                         //float   bob;
1755     1.5f,                                           //float   bobCycle;
1756     80,                                             //int     steptime;
1757     LEVEL2_UPG_SPEED,                               //float   speed;
1758     10.0f,                                          //float   acceleration;
1759     2.0f,                                           //float   airAcceleration;
1760     6.0f,                                           //float   friction;
1761     100.0f,                                         //float   stopSpeed;
1762     400.0f,                                         //float   jumpMagnitude;
1763     0.7f,                                           //float   knockbackScale;
1764     { PCL_ALIEN_LEVEL3, PCL_NONE, PCL_NONE },       //int     children[ 3 ];
1765     LEVEL2_UPG_COST,                                //int     cost;
1766     LEVEL2_UPG_VALUE                                //int     value;
1767   },
1768   {
1769     PCL_ALIEN_LEVEL3,                               //int     classnum;
1770     "level3",                                       //char    *classname;
1771     "Dragoon",                                      //char    *humanname;
1772     "prowl",                                        //char    *modelname;
1773     1.0f,                                           //float   modelScale;
1774     "default",                                      //char    *skinname;
1775     1.0f,                                           //float   shadowScale;
1776     "alien_general_hud",                            //char    *hudname;
1777     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ),            //int  stages
1778     { -32, -32, -21 },                              //vec3_t  mins;
1779     { 32, 32, 21 },                                 //vec3_t  maxs;
1780     { 32, 32, 21 },                                 //vec3_t  crouchmaxs;
1781     { -32, -32, -4 },                               //vec3_t  deadmins;
1782     { 32, 32, 4 },                                  //vec3_t  deadmaxs;
1783     0.0f,                                           //float   zOffset
1784     24, 24,                                         //int     viewheight, crouchviewheight;
1785     LEVEL3_HEALTH,                                  //int     health;
1786     0.0f,                                           //float   fallDamage;
1787     LEVEL3_REGEN,                                   //int     regenRate;
1788     SCA_NOWEAPONDRIFT|
1789       SCA_FOVWARPS|SCA_ALIENSENSE,                  //int     abilities;
1790     WP_ALEVEL3,                                     //weapon_t  startWeapon
1791     0.0f,                                           //float   buildDist;
1792     110,                                            //int     fov;
1793     0.0005f,                                        //float   bob;
1794     1.3f,                                           //float   bobCycle;
1795     90,                                             //int     steptime;
1796     LEVEL3_SPEED,                                   //float   speed;
1797     10.0f,                                          //float   acceleration;
1798     1.0f,                                           //float   airAcceleration;
1799     6.0f,                                           //float   friction;
1800     200.0f,                                         //float   stopSpeed;
1801     270.0f,                                         //float   jumpMagnitude;
1802     0.5f,                                           //float   knockbackScale;
1803     { PCL_ALIEN_LEVEL4, PCL_ALIEN_LEVEL3_UPG, PCL_NONE },   //int     children[ 3 ];
1804     LEVEL3_COST,                                    //int     cost;
1805     LEVEL3_VALUE                                    //int     value;
1806   },
1807   {
1808     PCL_ALIEN_LEVEL3_UPG,                           //int     classnum;
1809     "level3upg",                                    //char    *classname;
1810     "Dragoon Upgrade",                              //char    *humanname;
1811     "prowl",                                        //char    *modelname;
1812     1.0f,                                           //float   modelScale;
1813     "default",                                      //char    *skinname;
1814     1.0f,                                           //float   shadowScale;
1815     "alien_general_hud",                            //char    *hudname;
1816     ( 1 << S3 ),                                    //int  stages
1817     { -32, -32, -21 },                              //vec3_t  mins;
1818     { 32, 32, 21 },                                 //vec3_t  maxs;
1819     { 32, 32, 21 },                                 //vec3_t  crouchmaxs;
1820     { -32, -32, -4 },                               //vec3_t  deadmins;
1821     { 32, 32, 4 },                                  //vec3_t  deadmaxs;
1822     0.0f,                                           //float   zOffset
1823     27, 27,                                         //int     viewheight, crouchviewheight;
1824     LEVEL3_UPG_HEALTH,                              //int     health;
1825     0.0f,                                           //float   fallDamage;
1826     LEVEL3_UPG_REGEN,                               //int     regenRate;
1827     SCA_NOWEAPONDRIFT|
1828       SCA_FOVWARPS|SCA_ALIENSENSE,                  //int     abilities;
1829     WP_ALEVEL3_UPG,                                 //weapon_t  startWeapon
1830     0.0f,                                           //float   buildDist;
1831     110,                                            //int     fov;
1832     0.0005f,                                        //float   bob;
1833     1.3f,                                           //float   bobCycle;
1834     90,                                             //int     steptime;
1835     LEVEL3_UPG_SPEED,                               //float   speed;
1836     10.0f,                                          //float   acceleration;
1837     1.0f,                                           //float   airAcceleration;
1838     6.0f,                                           //float   friction;
1839     200.0f,                                         //float   stopSpeed;
1840     270.0f,                                         //float   jumpMagnitude;
1841     0.4f,                                           //float   knockbackScale;
1842     { PCL_ALIEN_LEVEL4, PCL_NONE, PCL_NONE },       //int     children[ 3 ];
1843     LEVEL3_UPG_COST,                                //int     cost;
1844     LEVEL3_UPG_VALUE                                //int     value;
1845   },
1846   {
1847     PCL_ALIEN_LEVEL4,                               //int     classnum;
1848     "level4",                                       //char    *classname;
1849     "Big Mofo",                                     //char    *humanname;
1850     "mofo",                                         //char    *modelname;
1851     1.0f,                                           //float   modelScale;
1852     "default",                                      //char    *skinname;
1853     2.0f,                                           //float   shadowScale;
1854     "alien_general_hud",                            //char    *hudname;
1855     ( 1 << S3 ),                                    //int  stages
1856     { -30, -30, -20 },                              //vec3_t  mins;
1857     { 30, 30, 20 },                                 //vec3_t  maxs;
1858     { 30, 30, 20 },                                 //vec3_t  crouchmaxs;
1859     { -15, -15, -4 },                               //vec3_t  deadmins;
1860     { 15, 15, 4 },                                  //vec3_t  deadmaxs;
1861     0.0f,                                           //float   zOffset
1862     35, 35,                                         //int     viewheight, crouchviewheight;
1863     LEVEL4_HEALTH,                                  //int     health;
1864     0.0f,                                           //float   fallDamage;
1865     LEVEL4_REGEN,                                   //int     regenRate;
1866     SCA_NOWEAPONDRIFT|
1867       SCA_FOVWARPS|SCA_ALIENSENSE,                  //int     abilities;
1868     WP_ALEVEL4,                                     //weapon_t  startWeapon
1869     0.0f,                                           //float   buildDist;
1870     90,                                             //int     fov;
1871     0.001f,                                         //float   bob;
1872     1.1f,                                           //float   bobCycle;
1873     100,                                            //int     steptime;
1874     LEVEL4_SPEED,                                   //float   speed;
1875     10.0f,                                          //float   acceleration;
1876     1.0f,                                           //float   airAcceleration;
1877     6.0f,                                           //float   friction;
1878     100.0f,                                         //float   stopSpeed;
1879     170.0f,                                         //float   jumpMagnitude;
1880     0.1f,                                           //float   knockbackScale;
1881     { PCL_NONE, PCL_NONE, PCL_NONE },               //int     children[ 3 ];
1882     LEVEL4_COST,                                    //int     cost;
1883     LEVEL4_VALUE                                    //int     value;
1884   },
1885   {
1886     PCL_HUMAN,                                      //int     classnum;
1887     "human_base",                                   //char    *classname;
1888     "Human",                                        //char    *humanname;
1889     "sarge",                                        //char    *modelname;
1890     1.0f,                                           //float   modelScale;
1891     "default",                                      //char    *skinname;
1892     1.0f,                                           //float   shadowScale;
1893     "human_hud",                                    //char    *hudname;
1894     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ),            //int  stages
1895     { -15, -15, -24 },                              //vec3_t  mins;
1896     { 15, 15, 32 },                                 //vec3_t  maxs;
1897     { 15, 15, 16 },                                 //vec3_t  crouchmaxs;
1898     { -15, -15, -4 },                               //vec3_t  deadmins;
1899     { 15, 15, 4 },                                  //vec3_t  deadmaxs;
1900     0.0f,                                           //float   zOffset
1901     26, 12,                                         //int     viewheight, crouchviewheight;
1902     100,                                            //int     health;
1903     1.0f,                                           //float   fallDamage;
1904     0,                                              //int     regenRate;
1905     SCA_TAKESFALLDAMAGE|
1906       SCA_CANUSELADDERS,                            //int     abilities;
1907     WP_NONE, //special-cased in g_client.c          //weapon_t  startWeapon
1908     110.0f,                                         //float   buildDist;
1909     90,                                             //int     fov;
1910     0.002f,                                         //float   bob;
1911     1.0f,                                           //float   bobCycle;
1912     100,                                            //int     steptime;
1913     1.0f,                                           //float   speed;
1914     10.0f,                                          //float   acceleration;
1915     1.0f,                                           //float   airAcceleration;
1916     6.0f,                                           //float   friction;
1917     100.0f,                                         //float   stopSpeed;
1918     220.0f,                                         //float   jumpMagnitude;
1919     1.0f,                                           //float   knockbackScale;
1920     { PCL_NONE, PCL_NONE, PCL_NONE },               //int     children[ 3 ];
1921     0,                                              //int     cost;
1922     0                                               //int     value;
1923   },
1924   {
1925     //this isn't a real class, but a dummy to force the client to precache the model
1926     //FIXME: one day do this in a less hacky fashion
1927     PCL_HUMAN_BSUIT, "human_bsuit", "bsuit",
1928 
1929     "keel",
1930     1.0f,
1931     "default",
1932     1.0f,
1933 
1934     "bsuit", ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), { 0, 0, 0 }, { 0, 0, 0, },
1935     { 0, 0, 0, }, { 0, 0, 0, }, { 0, 0, 0, }, 0.0f, 0, 0, 0, 0.0f, 0, 0, WP_NONE, 0.0f, 0,
1936     0.0f, 1.0f, 0, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 270.0f, 1.0f, { PCL_NONE, PCL_NONE, PCL_NONE }, 0, 0
1937   }
1938 };
1939 
1940 int   bg_numPclasses = sizeof( bg_classList ) / sizeof( bg_classList[ 0 ] );
1941 
1942 //separate from bg_classList to work around char struct init bug
1943 classAttributeOverrides_t bg_classOverrideList[ PCL_NUM_CLASSES ];
1944 
1945 /*
1946 ==============
1947 BG_FindClassNumForName
1948 ==============
1949 */
BG_FindClassNumForName(char * name)1950 int BG_FindClassNumForName( char *name )
1951 {
1952   int i;
1953 
1954   for( i = 0; i < bg_numPclasses; i++ )
1955   {
1956     if( !Q_stricmp( bg_classList[ i ].className, name ) )
1957       return bg_classList[ i ].classNum;
1958   }
1959 
1960   //wimp out
1961   return PCL_NONE;
1962 }
1963 
1964 /*
1965 ==============
1966 BG_FindNameForClassNum
1967 ==============
1968 */
BG_FindNameForClassNum(int pclass)1969 char *BG_FindNameForClassNum( int pclass )
1970 {
1971   int i;
1972 
1973   for( i = 0; i < bg_numPclasses; i++ )
1974   {
1975     if( bg_classList[ i ].classNum == pclass )
1976       return bg_classList[ i ].className;
1977   }
1978 
1979   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindNameForClassNum\n" );
1980   //wimp out
1981   return 0;
1982 }
1983 
1984 /*
1985 ==============
1986 BG_FindHumanNameForClassNum
1987 ==============
1988 */
BG_FindHumanNameForClassNum(int pclass)1989 char *BG_FindHumanNameForClassNum( int pclass )
1990 {
1991   int i;
1992 
1993   if( bg_classOverrideList[ pclass ].humanName[ 0 ] != 0 )
1994     return bg_classOverrideList[ pclass ].humanName;
1995 
1996   for( i = 0; i < bg_numPclasses; i++ )
1997   {
1998     if( bg_classList[ i ].classNum == pclass )
1999       return bg_classList[ i ].humanName;
2000   }
2001 
2002   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindHumanNameForClassNum\n" );
2003   //wimp out
2004   return 0;
2005 }
2006 
2007 /*
2008 ==============
2009 BG_FindModelNameForClass
2010 ==============
2011 */
BG_FindModelNameForClass(int pclass)2012 char *BG_FindModelNameForClass( int pclass )
2013 {
2014   int i;
2015 
2016   if( bg_classOverrideList[ pclass ].modelName[ 0 ] != 0 )
2017     return bg_classOverrideList[ pclass ].modelName;
2018 
2019   for( i = 0; i < bg_numPclasses; i++ )
2020   {
2021     if( bg_classList[ i ].classNum == pclass )
2022       return bg_classList[ i ].modelName;
2023   }
2024 
2025   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindModelNameForClass\n" );
2026   //note: must return a valid modelName!
2027   return bg_classList[ 0 ].modelName;
2028 }
2029 
2030 /*
2031 ==============
2032 BG_FindModelScaleForClass
2033 ==============
2034 */
BG_FindModelScaleForClass(int pclass)2035 float BG_FindModelScaleForClass( int pclass )
2036 {
2037   int i;
2038 
2039   if( bg_classOverrideList[ pclass ].modelScale != 0.0f )
2040     return bg_classOverrideList[ pclass ].modelScale;
2041 
2042   for( i = 0; i < bg_numPclasses; i++ )
2043   {
2044     if( bg_classList[ i ].classNum == pclass )
2045     {
2046       return bg_classList[ i ].modelScale;
2047     }
2048   }
2049 
2050   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindModelScaleForClass( %d )\n", pclass );
2051   return 1.0f;
2052 }
2053 
2054 /*
2055 ==============
2056 BG_FindSkinNameForClass
2057 ==============
2058 */
BG_FindSkinNameForClass(int pclass)2059 char *BG_FindSkinNameForClass( int pclass )
2060 {
2061   int i;
2062 
2063   if( bg_classOverrideList[ pclass ].skinName[ 0 ] != 0 )
2064     return bg_classOverrideList[ pclass ].skinName;
2065 
2066   for( i = 0; i < bg_numPclasses; i++ )
2067   {
2068     if( bg_classList[ i ].classNum == pclass )
2069       return bg_classList[ i ].skinName;
2070   }
2071 
2072   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindSkinNameForClass\n" );
2073   //note: must return a valid modelName!
2074   return bg_classList[ 0 ].skinName;
2075 }
2076 
2077 /*
2078 ==============
2079 BG_FindShadowScaleForClass
2080 ==============
2081 */
BG_FindShadowScaleForClass(int pclass)2082 float BG_FindShadowScaleForClass( int pclass )
2083 {
2084   int i;
2085 
2086   if( bg_classOverrideList[ pclass ].shadowScale != 0.0f )
2087     return bg_classOverrideList[ pclass ].shadowScale;
2088 
2089   for( i = 0; i < bg_numPclasses; i++ )
2090   {
2091     if( bg_classList[ i ].classNum == pclass )
2092     {
2093       return bg_classList[ i ].shadowScale;
2094     }
2095   }
2096 
2097   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindShadowScaleForClass( %d )\n", pclass );
2098   return 1.0f;
2099 }
2100 
2101 /*
2102 ==============
2103 BG_FindHudNameForClass
2104 ==============
2105 */
BG_FindHudNameForClass(int pclass)2106 char *BG_FindHudNameForClass( int pclass )
2107 {
2108   int i;
2109 
2110   if( bg_classOverrideList[ pclass ].hudName[ 0 ] != 0 )
2111     return bg_classOverrideList[ pclass ].hudName;
2112 
2113   for( i = 0; i < bg_numPclasses; i++ )
2114   {
2115     if( bg_classList[ i ].classNum == pclass )
2116       return bg_classList[ i ].hudName;
2117   }
2118 
2119   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindHudNameForClass\n" );
2120   //note: must return a valid hudName!
2121   return bg_classList[ 0 ].hudName;
2122 }
2123 
2124 /*
2125 ==============
2126 BG_FindStagesForClass
2127 ==============
2128 */
BG_FindStagesForClass(int pclass,stage_t stage)2129 qboolean BG_FindStagesForClass( int pclass, stage_t stage )
2130 {
2131   int i;
2132 
2133   for( i = 0; i < bg_numPclasses; i++ )
2134   {
2135     if( bg_classList[ i ].classNum == pclass )
2136     {
2137       if( bg_classList[ i ].stages & ( 1 << stage ) )
2138         return qtrue;
2139       else
2140         return qfalse;
2141     }
2142   }
2143 
2144   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindStagesForClass\n" );
2145   return qfalse;
2146 }
2147 
2148 /*
2149 ==============
2150 BG_FindBBoxForClass
2151 ==============
2152 */
BG_FindBBoxForClass(int pclass,vec3_t mins,vec3_t maxs,vec3_t cmaxs,vec3_t dmins,vec3_t dmaxs)2153 void BG_FindBBoxForClass( int pclass, vec3_t mins, vec3_t maxs, vec3_t cmaxs, vec3_t dmins, vec3_t dmaxs )
2154 {
2155   int i;
2156 
2157   for( i = 0; i < bg_numPclasses; i++ )
2158   {
2159     if( bg_classList[ i ].classNum == pclass )
2160     {
2161       if( mins != NULL )
2162       {
2163         VectorCopy( bg_classList[ i ].mins, mins );
2164 
2165         if( VectorLength( bg_classOverrideList[ pclass ].mins ) )
2166           VectorCopy( bg_classOverrideList[ pclass ].mins, mins );
2167       }
2168 
2169       if( maxs != NULL )
2170       {
2171         VectorCopy( bg_classList[ i ].maxs, maxs );
2172 
2173         if( VectorLength( bg_classOverrideList[ pclass ].maxs ) )
2174           VectorCopy( bg_classOverrideList[ pclass ].maxs, maxs );
2175       }
2176 
2177       if( cmaxs != NULL )
2178       {
2179         VectorCopy( bg_classList[ i ].crouchMaxs, cmaxs );
2180 
2181         if( VectorLength( bg_classOverrideList[ pclass ].crouchMaxs ) )
2182           VectorCopy( bg_classOverrideList[ pclass ].crouchMaxs, cmaxs );
2183       }
2184 
2185       if( dmins != NULL )
2186       {
2187         VectorCopy( bg_classList[ i ].deadMins, dmins );
2188 
2189         if( VectorLength( bg_classOverrideList[ pclass ].deadMins ) )
2190           VectorCopy( bg_classOverrideList[ pclass ].deadMins, dmins );
2191       }
2192 
2193       if( dmaxs != NULL )
2194       {
2195         VectorCopy( bg_classList[ i ].deadMaxs, dmaxs );
2196 
2197         if( VectorLength( bg_classOverrideList[ pclass ].deadMaxs ) )
2198           VectorCopy( bg_classOverrideList[ pclass ].deadMaxs, dmaxs );
2199       }
2200 
2201       return;
2202     }
2203   }
2204 
2205   if( mins != NULL )
2206     VectorCopy( bg_classList[ 0 ].mins,        mins );
2207 
2208   if( maxs != NULL )
2209     VectorCopy( bg_classList[ 0 ].maxs,        maxs );
2210 
2211   if( cmaxs != NULL )
2212     VectorCopy( bg_classList[ 0 ].crouchMaxs,  cmaxs );
2213 
2214   if( dmins != NULL )
2215     VectorCopy( bg_classList[ 0 ].deadMins,    dmins );
2216 
2217   if( dmaxs != NULL )
2218     VectorCopy( bg_classList[ 0 ].deadMaxs,    dmaxs );
2219 }
2220 
2221 /*
2222 ==============
2223 BG_FindZOffsetForClass
2224 ==============
2225 */
BG_FindZOffsetForClass(int pclass)2226 float BG_FindZOffsetForClass( int pclass )
2227 {
2228   int i;
2229 
2230   if( bg_classOverrideList[ pclass ].zOffset != 0.0f )
2231     return bg_classOverrideList[ pclass ].zOffset;
2232 
2233   for( i = 0; i < bg_numPclasses; i++ )
2234   {
2235     if( bg_classList[ i ].classNum == pclass )
2236     {
2237       return bg_classList[ i ].zOffset;
2238     }
2239   }
2240 
2241   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindZOffsetForClass\n" );
2242   return 0.0f;
2243 }
2244 
2245 /*
2246 ==============
2247 BG_FindViewheightForClass
2248 ==============
2249 */
BG_FindViewheightForClass(int pclass,int * viewheight,int * cViewheight)2250 void BG_FindViewheightForClass( int pclass, int *viewheight, int *cViewheight )
2251 {
2252   int i;
2253 
2254   for( i = 0; i < bg_numPclasses; i++ )
2255   {
2256     if( bg_classList[ i ].classNum == pclass )
2257     {
2258       if( viewheight != NULL )
2259         *viewheight = bg_classList[ i ].viewheight;
2260 
2261       if( cViewheight != NULL )
2262         *cViewheight = bg_classList[ i ].crouchViewheight;
2263 
2264       return;
2265     }
2266   }
2267 
2268   if( viewheight != NULL )
2269     *viewheight = bg_classList[ 0 ].viewheight;
2270 
2271   if( cViewheight != NULL )
2272     *cViewheight = bg_classList[ 0 ].crouchViewheight;
2273 }
2274 
2275 /*
2276 ==============
2277 BG_FindHealthForClass
2278 ==============
2279 */
BG_FindHealthForClass(int pclass)2280 int BG_FindHealthForClass( int pclass )
2281 {
2282   int i;
2283 
2284   for( i = 0; i < bg_numPclasses; i++ )
2285   {
2286     if( bg_classList[ i ].classNum == pclass )
2287     {
2288       return bg_classList[ i ].health;
2289     }
2290   }
2291 
2292   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindHealthForClass\n" );
2293   return 100;
2294 }
2295 
2296 /*
2297 ==============
2298 BG_FindFallDamageForClass
2299 ==============
2300 */
BG_FindFallDamageForClass(int pclass)2301 float BG_FindFallDamageForClass( int pclass )
2302 {
2303   int i;
2304 
2305   for( i = 0; i < bg_numPclasses; i++ )
2306   {
2307     if( bg_classList[ i ].classNum == pclass )
2308     {
2309       return bg_classList[ i ].fallDamage;
2310     }
2311   }
2312 
2313   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindFallDamageForClass\n" );
2314   return 100;
2315 }
2316 
2317 /*
2318 ==============
2319 BG_FindRegenRateForClass
2320 ==============
2321 */
BG_FindRegenRateForClass(int pclass)2322 int BG_FindRegenRateForClass( int pclass )
2323 {
2324   int i;
2325 
2326   for( i = 0; i < bg_numPclasses; i++ )
2327   {
2328     if( bg_classList[ i ].classNum == pclass )
2329     {
2330       return bg_classList[ i ].regenRate;
2331     }
2332   }
2333 
2334   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindRegenRateForClass\n" );
2335   return 0;
2336 }
2337 
2338 /*
2339 ==============
2340 BG_FindFovForClass
2341 ==============
2342 */
BG_FindFovForClass(int pclass)2343 int BG_FindFovForClass( int pclass )
2344 {
2345   int i;
2346 
2347   for( i = 0; i < bg_numPclasses; i++ )
2348   {
2349     if( bg_classList[ i ].classNum == pclass )
2350     {
2351       return bg_classList[ i ].fov;
2352     }
2353   }
2354 
2355   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindFovForClass\n" );
2356   return 90;
2357 }
2358 
2359 /*
2360 ==============
2361 BG_FindBobForClass
2362 ==============
2363 */
BG_FindBobForClass(int pclass)2364 float BG_FindBobForClass( int pclass )
2365 {
2366   int i;
2367 
2368   for( i = 0; i < bg_numPclasses; i++ )
2369   {
2370     if( bg_classList[ i ].classNum == pclass )
2371     {
2372       return bg_classList[ i ].bob;
2373     }
2374   }
2375 
2376   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindBobForClass\n" );
2377   return 0.002;
2378 }
2379 
2380 /*
2381 ==============
2382 BG_FindBobCycleForClass
2383 ==============
2384 */
BG_FindBobCycleForClass(int pclass)2385 float BG_FindBobCycleForClass( int pclass )
2386 {
2387   int i;
2388 
2389   for( i = 0; i < bg_numPclasses; i++ )
2390   {
2391     if( bg_classList[ i ].classNum == pclass )
2392     {
2393       return bg_classList[ i ].bobCycle;
2394     }
2395   }
2396 
2397   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindBobCycleForClass\n" );
2398   return 1.0f;
2399 }
2400 
2401 /*
2402 ==============
2403 BG_FindSpeedForClass
2404 ==============
2405 */
BG_FindSpeedForClass(int pclass)2406 float BG_FindSpeedForClass( int pclass )
2407 {
2408   int i;
2409 
2410   for( i = 0; i < bg_numPclasses; i++ )
2411   {
2412     if( bg_classList[ i ].classNum == pclass )
2413     {
2414       return bg_classList[ i ].speed;
2415     }
2416   }
2417 
2418   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindSpeedForClass\n" );
2419   return 1.0f;
2420 }
2421 
2422 /*
2423 ==============
2424 BG_FindAccelerationForClass
2425 ==============
2426 */
BG_FindAccelerationForClass(int pclass)2427 float BG_FindAccelerationForClass( int pclass )
2428 {
2429   int i;
2430 
2431   for( i = 0; i < bg_numPclasses; i++ )
2432   {
2433     if( bg_classList[ i ].classNum == pclass )
2434     {
2435       return bg_classList[ i ].acceleration;
2436     }
2437   }
2438 
2439   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindAccelerationForClass\n" );
2440   return 10.0f;
2441 }
2442 
2443 /*
2444 ==============
2445 BG_FindAirAccelerationForClass
2446 ==============
2447 */
BG_FindAirAccelerationForClass(int pclass)2448 float BG_FindAirAccelerationForClass( int pclass )
2449 {
2450   int i;
2451 
2452   for( i = 0; i < bg_numPclasses; i++ )
2453   {
2454     if( bg_classList[ i ].classNum == pclass )
2455     {
2456       return bg_classList[ i ].airAcceleration;
2457     }
2458   }
2459 
2460   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindAirAccelerationForClass\n" );
2461   return 1.0f;
2462 }
2463 
2464 /*
2465 ==============
2466 BG_FindFrictionForClass
2467 ==============
2468 */
BG_FindFrictionForClass(int pclass)2469 float BG_FindFrictionForClass( int pclass )
2470 {
2471   int i;
2472 
2473   for( i = 0; i < bg_numPclasses; i++ )
2474   {
2475     if( bg_classList[ i ].classNum == pclass )
2476     {
2477       return bg_classList[ i ].friction;
2478     }
2479   }
2480 
2481   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindFrictionForClass\n" );
2482   return 6.0f;
2483 }
2484 
2485 /*
2486 ==============
2487 BG_FindStopSpeedForClass
2488 ==============
2489 */
BG_FindStopSpeedForClass(int pclass)2490 float BG_FindStopSpeedForClass( int pclass )
2491 {
2492   int i;
2493 
2494   for( i = 0; i < bg_numPclasses; i++ )
2495   {
2496     if( bg_classList[ i ].classNum == pclass )
2497     {
2498       return bg_classList[ i ].stopSpeed;
2499     }
2500   }
2501 
2502   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindStopSpeedForClass\n" );
2503   return 100.0f;
2504 }
2505 
2506 /*
2507 ==============
2508 BG_FindJumpMagnitudeForClass
2509 ==============
2510 */
BG_FindJumpMagnitudeForClass(int pclass)2511 float BG_FindJumpMagnitudeForClass( int pclass )
2512 {
2513   int i;
2514 
2515   for( i = 0; i < bg_numPclasses; i++ )
2516   {
2517     if( bg_classList[ i ].classNum == pclass )
2518     {
2519       return bg_classList[ i ].jumpMagnitude;
2520     }
2521   }
2522 
2523   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindJumpMagnitudeForClass\n" );
2524   return 270.0f;
2525 }
2526 
2527 /*
2528 ==============
2529 BG_FindKnockbackScaleForClass
2530 ==============
2531 */
BG_FindKnockbackScaleForClass(int pclass)2532 float BG_FindKnockbackScaleForClass( int pclass )
2533 {
2534   int i;
2535 
2536   for( i = 0; i < bg_numPclasses; i++ )
2537   {
2538     if( bg_classList[ i ].classNum == pclass )
2539     {
2540       return bg_classList[ i ].knockbackScale;
2541     }
2542   }
2543 
2544   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindKnockbackScaleForClass\n" );
2545   return 1.0f;
2546 }
2547 
2548 /*
2549 ==============
2550 BG_FindSteptimeForClass
2551 ==============
2552 */
BG_FindSteptimeForClass(int pclass)2553 int BG_FindSteptimeForClass( int pclass )
2554 {
2555   int i;
2556 
2557   for( i = 0; i < bg_numPclasses; i++ )
2558   {
2559     if( bg_classList[ i ].classNum == pclass )
2560     {
2561       return bg_classList[ i ].steptime;
2562     }
2563   }
2564 
2565   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindSteptimeForClass\n" );
2566   return 200;
2567 }
2568 
2569 /*
2570 ==============
2571 BG_ClassHasAbility
2572 ==============
2573 */
BG_ClassHasAbility(int pclass,int ability)2574 qboolean BG_ClassHasAbility( int pclass, int ability )
2575 {
2576   int i;
2577 
2578   for( i = 0; i < bg_numPclasses; i++ )
2579   {
2580     if( bg_classList[ i ].classNum == pclass )
2581     {
2582       return ( bg_classList[ i ].abilities & ability );
2583     }
2584   }
2585 
2586   return qfalse;
2587 }
2588 
2589 /*
2590 ==============
2591 BG_FindStartWeaponForClass
2592 ==============
2593 */
BG_FindStartWeaponForClass(int pclass)2594 weapon_t BG_FindStartWeaponForClass( int pclass )
2595 {
2596   int i;
2597 
2598   for( i = 0; i < bg_numPclasses; i++ )
2599   {
2600     if( bg_classList[ i ].classNum == pclass )
2601     {
2602       return bg_classList[ i ].startWeapon;
2603     }
2604   }
2605 
2606   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindStartWeaponForClass\n" );
2607   return WP_NONE;
2608 }
2609 
2610 /*
2611 ==============
2612 BG_FindBuildDistForClass
2613 ==============
2614 */
BG_FindBuildDistForClass(int pclass)2615 float BG_FindBuildDistForClass( int pclass )
2616 {
2617   int i;
2618 
2619   for( i = 0; i < bg_numPclasses; i++ )
2620   {
2621     if( bg_classList[ i ].classNum == pclass )
2622     {
2623       return bg_classList[ i ].buildDist;
2624     }
2625   }
2626 
2627   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindBuildDistForClass\n" );
2628   return 0.0f;
2629 }
2630 
2631 /*
2632 ==============
2633 BG_ClassCanEvolveFromTo
2634 ==============
2635 */
BG_ClassCanEvolveFromTo(int fclass,int tclass,int credits,int num)2636 int BG_ClassCanEvolveFromTo( int fclass, int tclass, int credits, int num )
2637 {
2638   int i, j, cost;
2639 
2640   cost = BG_FindCostOfClass( tclass );
2641 
2642   //base case
2643   if( credits < cost )
2644     return -1;
2645 
2646   if( fclass == PCL_NONE || tclass == PCL_NONE )
2647     return -1;
2648 
2649   for( i = 0; i < bg_numPclasses; i++ )
2650   {
2651     if( bg_classList[ i ].classNum == fclass )
2652     {
2653       for( j = 0; j < 3; j++ )
2654         if( bg_classList[ i ].children[ j ] == tclass )
2655           return num + cost;
2656 
2657       for( j = 0; j < 3; j++ )
2658       {
2659         int sub;
2660 
2661         cost = BG_FindCostOfClass( bg_classList[ i ].children[ j ] );
2662         sub = BG_ClassCanEvolveFromTo( bg_classList[ i ].children[ j ],
2663                                        tclass, credits - cost, num + cost );
2664         if( sub >= 0 )
2665           return sub;
2666       }
2667 
2668       return -1; //may as well return by this point
2669     }
2670   }
2671 
2672   return -1;
2673 }
2674 
2675 /*
2676 ==============
2677 BG_FindValueOfClass
2678 ==============
2679 */
BG_FindValueOfClass(int pclass)2680 int BG_FindValueOfClass( int pclass )
2681 {
2682   int i;
2683 
2684   for( i = 0; i < bg_numPclasses; i++ )
2685   {
2686     if( bg_classList[ i ].classNum == pclass )
2687     {
2688       return bg_classList[ i ].value;
2689     }
2690   }
2691 
2692   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindValueOfClass\n" );
2693   return 0;
2694 }
2695 
2696 /*
2697 ==============
2698 BG_FindCostOfClass
2699 ==============
2700 */
BG_FindCostOfClass(int pclass)2701 int BG_FindCostOfClass( int pclass )
2702 {
2703   int i;
2704 
2705   for( i = 0; i < bg_numPclasses; i++ )
2706   {
2707     if( bg_classList[ i ].classNum == pclass )
2708     {
2709       return bg_classList[ i ].cost;
2710     }
2711   }
2712 
2713   Com_Printf( S_COLOR_YELLOW "WARNING: fallthrough in BG_FindCostOfClass\n" );
2714   return 0;
2715 }
2716 
2717 /*
2718 ==============
2719 BG_FindOverrideForClass
2720 ==============
2721 */
BG_FindOverrideForClass(int pclass)2722 static classAttributeOverrides_t *BG_FindOverrideForClass( int pclass )
2723 {
2724   return &bg_classOverrideList[ pclass ];
2725 }
2726 
2727 /*
2728 ======================
2729 BG_ParseClassFile
2730 
2731 Parses a configuration file describing a class
2732 ======================
2733 */
BG_ParseClassFile(const char * filename,classAttributeOverrides_t * cao)2734 static qboolean BG_ParseClassFile( const char *filename, classAttributeOverrides_t *cao )
2735 {
2736   char          *text_p;
2737   int           i;
2738   int           len;
2739   char          *token;
2740   char          text[ 20000 ];
2741   fileHandle_t  f;
2742   float         scale = 0.0f;
2743 
2744 
2745   // load the file
2746   len = trap_FS_FOpenFile( filename, &f, FS_READ );
2747   if( len <= 0 )
2748     return qfalse;
2749 
2750   if( len >= sizeof( text ) - 1 )
2751   {
2752     Com_Printf( S_COLOR_RED "ERROR: Class file %s too long\n", filename );
2753     return qfalse;
2754   }
2755 
2756   trap_FS_Read( text, len, f );
2757   text[ len ] = 0;
2758   trap_FS_FCloseFile( f );
2759 
2760   // parse the text
2761   text_p = text;
2762 
2763   // read optional parameters
2764   while( 1 )
2765   {
2766     token = COM_Parse( &text_p );
2767 
2768     if( !token )
2769       break;
2770 
2771     if( !Q_stricmp( token, "" ) )
2772       break;
2773 
2774     if( !Q_stricmp( token, "model" ) )
2775     {
2776       token = COM_Parse( &text_p );
2777       if( !token )
2778         break;
2779 
2780       Q_strncpyz( cao->modelName, token, sizeof( cao->modelName ) );
2781 
2782       continue;
2783     }
2784     else if( !Q_stricmp( token, "skin" ) )
2785     {
2786       token = COM_Parse( &text_p );
2787       if( !token )
2788         break;
2789 
2790       Q_strncpyz( cao->skinName, token, sizeof( cao->skinName ) );
2791 
2792       continue;
2793     }
2794     else if( !Q_stricmp( token, "hud" ) )
2795     {
2796       token = COM_Parse( &text_p );
2797       if( !token )
2798         break;
2799 
2800       Q_strncpyz( cao->hudName, token, sizeof( cao->hudName ) );
2801 
2802       continue;
2803     }
2804     else if( !Q_stricmp( token, "modelScale" ) )
2805     {
2806       token = COM_Parse( &text_p );
2807       if( !token )
2808         break;
2809 
2810       scale = atof( token );
2811 
2812       if( scale < 0.0f )
2813         scale = 0.0f;
2814 
2815       cao->modelScale = scale;
2816 
2817       continue;
2818     }
2819     else if( !Q_stricmp( token, "shadowScale" ) )
2820     {
2821       token = COM_Parse( &text_p );
2822       if( !token )
2823         break;
2824 
2825       scale = atof( token );
2826 
2827       if( scale < 0.0f )
2828         scale = 0.0f;
2829 
2830       cao->shadowScale = scale;
2831 
2832       continue;
2833     }
2834     else if( !Q_stricmp( token, "mins" ) )
2835     {
2836       for( i = 0; i <= 2; i++ )
2837       {
2838         token = COM_Parse( &text_p );
2839         if( !token )
2840           break;
2841 
2842         cao->mins[ i ] = atof( token );
2843       }
2844 
2845       continue;
2846     }
2847     else if( !Q_stricmp( token, "maxs" ) )
2848     {
2849       for( i = 0; i <= 2; i++ )
2850       {
2851         token = COM_Parse( &text_p );
2852         if( !token )
2853           break;
2854 
2855         cao->maxs[ i ] = atof( token );
2856       }
2857 
2858       continue;
2859     }
2860     else if( !Q_stricmp( token, "deadMins" ) )
2861     {
2862       for( i = 0; i <= 2; i++ )
2863       {
2864         token = COM_Parse( &text_p );
2865         if( !token )
2866           break;
2867 
2868         cao->deadMins[ i ] = atof( token );
2869       }
2870 
2871       continue;
2872     }
2873     else if( !Q_stricmp( token, "deadMaxs" ) )
2874     {
2875       for( i = 0; i <= 2; i++ )
2876       {
2877         token = COM_Parse( &text_p );
2878         if( !token )
2879           break;
2880 
2881         cao->deadMaxs[ i ] = atof( token );
2882       }
2883 
2884       continue;
2885     }
2886     else if( !Q_stricmp( token, "crouchMaxs" ) )
2887     {
2888       for( i = 0; i <= 2; i++ )
2889       {
2890         token = COM_Parse( &text_p );
2891         if( !token )
2892           break;
2893 
2894         cao->crouchMaxs[ i ] = atof( token );
2895       }
2896 
2897       continue;
2898     }
2899     else if( !Q_stricmp( token, "zOffset" ) )
2900     {
2901       float offset;
2902 
2903       token = COM_Parse( &text_p );
2904       if( !token )
2905         break;
2906 
2907       offset = atof( token );
2908 
2909       cao->zOffset = offset;
2910 
2911       continue;
2912     }
2913     else if( !Q_stricmp( token, "name" ) )
2914     {
2915       token = COM_Parse( &text_p );
2916       if( !token )
2917         break;
2918 
2919       Q_strncpyz( cao->humanName, token, sizeof( cao->humanName ) );
2920 
2921       continue;
2922     }
2923 
2924 
2925     Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token );
2926     return qfalse;
2927   }
2928 
2929   return qtrue;
2930 }
2931 
2932 /*
2933 ===============
2934 BG_InitClassOverrides
2935 
2936 Set any overrides specfied by file
2937 ===============
2938 */
BG_InitClassOverrides(void)2939 void BG_InitClassOverrides( void )
2940 {
2941   int                       i;
2942   classAttributeOverrides_t *cao;
2943 
2944   for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ )
2945   {
2946     cao = BG_FindOverrideForClass( i );
2947 
2948     BG_ParseClassFile( va( "overrides/classes/%s.cfg", BG_FindNameForClassNum( i ) ), cao );
2949   }
2950 }
2951 
2952 ////////////////////////////////////////////////////////////////////////////////
2953 
2954 weaponAttributes_t bg_weapons[ ] =
2955 {
2956   {
2957     WP_BLASTER,           //int       weaponNum;
2958     0,                    //int       price;
2959     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
2960     0,                    //int       slots;
2961     "blaster",            //char      *weaponName;
2962     "Blaster",            //char      *weaponHumanName;
2963     0,                    //int       maxAmmo;
2964     0,                    //int       maxClips;
2965     qtrue,                //int       infiniteAmmo;
2966     qfalse,               //int       usesEnergy;
2967     BLASTER_REPEAT,       //int       repeatRate1;
2968     0,                    //int       repeatRate2;
2969     0,                    //int       repeatRate3;
2970     0,                    //int       reloadTime;
2971     qfalse,               //qboolean  hasAltMode;
2972     qfalse,               //qboolean  hasThirdMode;
2973     qfalse,               //qboolean  canZoom;
2974     90.0f,                //float     zoomFov;
2975     qfalse,               //qboolean  purchasable;
2976     0,                    //int       buildDelay;
2977     WUT_HUMANS            //WUTeam_t  team;
2978   },
2979   {
2980     WP_MACHINEGUN,        //int       weaponNum;
2981     RIFLE_PRICE,          //int       price;
2982     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
2983     SLOT_WEAPON,          //int       slots;
2984     "rifle",              //char      *weaponName;
2985     "Rifle",              //char      *weaponHumanName;
2986     RIFLE_CLIPSIZE,       //int       maxAmmo;
2987     RIFLE_MAXCLIPS,       //int       maxClips;
2988     qfalse,               //int       infiniteAmmo;
2989     qfalse,               //int       usesEnergy;
2990     RIFLE_REPEAT,         //int       repeatRate1;
2991     0,                    //int       repeatRate2;
2992     0,                    //int       repeatRate3;
2993     RIFLE_RELOAD,         //int       reloadTime;
2994     qfalse,               //qboolean  hasAltMode;
2995     qfalse,               //qboolean  hasThirdMode;
2996     qfalse,               //qboolean  canZoom;
2997     90.0f,                //float     zoomFov;
2998     qtrue,                //qboolean  purchasable;
2999     0,                    //int       buildDelay;
3000     WUT_HUMANS            //WUTeam_t  team;
3001   },
3002   {
3003     WP_SHOTGUN,           //int       weaponNum;
3004     SHOTGUN_PRICE,        //int       price;
3005     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3006     SLOT_WEAPON,          //int       slots;
3007     "shotgun",            //char      *weaponName;
3008     "Shotgun",            //char      *weaponHumanName;
3009     SHOTGUN_SHELLS,       //int       maxAmmo;
3010     SHOTGUN_MAXCLIPS,     //int       maxClips;
3011     qfalse,               //int       infiniteAmmo;
3012     qfalse,               //int       usesEnergy;
3013     SHOTGUN_REPEAT,       //int       repeatRate1;
3014     0,                    //int       repeatRate2;
3015     0,                    //int       repeatRate3;
3016     SHOTGUN_RELOAD,       //int       reloadTime;
3017     qfalse,               //qboolean  hasAltMode;
3018     qfalse,               //qboolean  hasThirdMode;
3019     qfalse,               //qboolean  canZoom;
3020     90.0f,                //float     zoomFov;
3021     qtrue,                //qboolean  purchasable;
3022     0,                    //int       buildDelay;
3023     WUT_HUMANS            //WUTeam_t  team;
3024   },
3025   {
3026     WP_FLAMER,            //int       weaponNum;
3027     FLAMER_PRICE,         //int       price;
3028     ( 1 << S2 )|( 1 << S3 ), //int  stages
3029     SLOT_WEAPON,          //int       slots;
3030     "flamer",             //char      *weaponName;
3031     "Flame Thrower",      //char      *weaponHumanName;
3032     FLAMER_GAS,           //int       maxAmmo;
3033     0,                    //int       maxClips;
3034     qfalse,               //int       infiniteAmmo;
3035     qfalse,               //int       usesEnergy;
3036     FLAMER_REPEAT,        //int       repeatRate1;
3037     0,                    //int       repeatRate2;
3038     0,                    //int       repeatRate3;
3039     0,                    //int       reloadTime;
3040     qfalse,               //qboolean  hasAltMode;
3041     qfalse,               //qboolean  hasThirdMode;
3042     qfalse,               //qboolean  canZoom;
3043     90.0f,                //float     zoomFov;
3044     qtrue,                //qboolean  purchasable;
3045     0,                    //int       buildDelay;
3046     WUT_HUMANS            //WUTeam_t  team;
3047   },
3048   {
3049     WP_CHAINGUN,          //int       weaponNum;
3050     CHAINGUN_PRICE,       //int       price;
3051     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3052     SLOT_WEAPON,          //int       slots;
3053     "chaingun",           //char      *weaponName;
3054     "Chaingun",           //char      *weaponHumanName;
3055     CHAINGUN_BULLETS,     //int       maxAmmo;
3056     0,                    //int       maxClips;
3057     qfalse,               //int       infiniteAmmo;
3058     qfalse,               //int       usesEnergy;
3059     CHAINGUN_REPEAT,      //int       repeatRate1;
3060     0,                    //int       repeatRate2;
3061     0,                    //int       repeatRate3;
3062     0,                    //int       reloadTime;
3063     qfalse,               //qboolean  hasAltMode;
3064     qfalse,               //qboolean  hasThirdMode;
3065     qfalse,               //qboolean  canZoom;
3066     90.0f,                //float     zoomFov;
3067     qtrue,                //qboolean  purchasable;
3068     0,                    //int       buildDelay;
3069     WUT_HUMANS            //WUTeam_t  team;
3070   },
3071   {
3072     WP_MASS_DRIVER,       //int       weaponNum;
3073     MDRIVER_PRICE,        //int       price;
3074     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3075     SLOT_WEAPON,          //int       slots;
3076     "mdriver",            //char      *weaponName;
3077     "Mass Driver",        //char      *weaponHumanName;
3078     MDRIVER_CLIPSIZE,     //int       maxAmmo;
3079     MDRIVER_MAXCLIPS,     //int       maxClips;
3080     qfalse,               //int       infiniteAmmo;
3081     qtrue,                //int       usesEnergy;
3082     MDRIVER_REPEAT,       //int       repeatRate1;
3083     0,                    //int       repeatRate2;
3084     0,                    //int       repeatRate3;
3085     MDRIVER_RELOAD,       //int       reloadTime;
3086     qfalse,               //qboolean  hasAltMode;
3087     qfalse,               //qboolean  hasThirdMode;
3088     qtrue,                //qboolean  canZoom;
3089     20.0f,                //float     zoomFov;
3090     qtrue,                //qboolean  purchasable;
3091     0,                    //int       buildDelay;
3092     WUT_HUMANS            //WUTeam_t  team;
3093   },
3094   {
3095     WP_PULSE_RIFLE,       //int       weaponNum;
3096     PRIFLE_PRICE,         //int       price;
3097     ( 1 << S2 )|( 1 << S3 ), //int  stages
3098     SLOT_WEAPON,          //int       slots;
3099     "prifle",             //char      *weaponName;
3100     "Pulse Rifle",        //char      *weaponHumanName;
3101     PRIFLE_CLIPS,         //int       maxAmmo;
3102     PRIFLE_MAXCLIPS,      //int       maxClips;
3103     qfalse,               //int       infiniteAmmo;
3104     qtrue,                //int       usesEnergy;
3105     PRIFLE_REPEAT,        //int       repeatRate1;
3106     0,                    //int       repeatRate2;
3107     0,                    //int       repeatRate3;
3108     PRIFLE_RELOAD,        //int       reloadTime;
3109     qfalse,               //qboolean  hasAltMode;
3110     qfalse,               //qboolean  hasThirdMode;
3111     qfalse,               //qboolean  canZoom;
3112     90.0f,                //float     zoomFov;
3113     qtrue,                //qboolean  purchasable;
3114     0,                    //int       buildDelay;
3115     WUT_HUMANS            //WUTeam_t  team;
3116   },
3117   {
3118     WP_LUCIFER_CANNON,    //int       weaponNum;
3119     LCANNON_PRICE,        //int       price;
3120     ( 1 << S3 ),          //int  stages
3121     SLOT_WEAPON,          //int       slots;
3122     "lcannon",            //char      *weaponName;
3123     "Lucifer Cannon",     //char      *weaponHumanName;
3124     LCANNON_AMMO,         //int       maxAmmo;
3125     0,                    //int       maxClips;
3126     qfalse,               //int       infiniteAmmo;
3127     qtrue,                //int       usesEnergy;
3128     LCANNON_REPEAT,       //int       repeatRate1;
3129     LCANNON_CHARGEREPEAT, //int       repeatRate2;
3130     0,                    //int       repeatRate3;
3131     LCANNON_RELOAD,       //int       reloadTime;
3132     qtrue,                //qboolean  hasAltMode;
3133     qfalse,               //qboolean  hasThirdMode;
3134     qfalse,               //qboolean  canZoom;
3135     90.0f,                //float     zoomFov;
3136     qtrue,                //qboolean  purchasable;
3137     0,                    //int       buildDelay;
3138     WUT_HUMANS            //WUTeam_t  team;
3139   },
3140   {
3141     WP_LAS_GUN,           //int       weaponNum;
3142     LASGUN_PRICE,         //int       price;
3143     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3144     SLOT_WEAPON,          //int       slots;
3145     "lgun",               //char      *weaponName;
3146     "Las Gun",            //char      *weaponHumanName;
3147     LASGUN_AMMO,          //int       maxAmmo;
3148     0,                    //int       maxClips;
3149     qfalse,               //int       infiniteAmmo;
3150     qtrue,                //int       usesEnergy;
3151     LASGUN_REPEAT,        //int       repeatRate1;
3152     0,                    //int       repeatRate2;
3153     0,                    //int       repeatRate3;
3154     LASGUN_RELOAD,        //int       reloadTime;
3155     qfalse,               //qboolean  hasAltMode;
3156     qfalse,               //qboolean  hasThirdMode;
3157     qfalse,               //qboolean  canZoom;
3158     90.0f,                //float     zoomFov;
3159     qtrue,                //qboolean  purchasable;
3160     0,                    //int       buildDelay;
3161     WUT_HUMANS            //WUTeam_t  team;
3162   },
3163   {
3164     WP_PAIN_SAW,          //int       weaponNum;
3165     PAINSAW_PRICE,        //int       price;
3166     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3167     SLOT_WEAPON,          //int       slots;
3168     "psaw",               //char      *weaponName;
3169     "Pain Saw",           //char      *weaponHumanName;
3170     0,                    //int       maxAmmo;
3171     0,                    //int       maxClips;
3172     qtrue,                //int       infiniteAmmo;
3173     qfalse,               //int       usesEnergy;
3174     PAINSAW_REPEAT,       //int       repeatRate1;
3175     0,                    //int       repeatRate2;
3176     0,                    //int       repeatRate3;
3177     0,                    //int       reloadTime;
3178     qfalse,               //qboolean  hasAltMode;
3179     qfalse,               //qboolean  hasThirdMode;
3180     qfalse,               //qboolean  canZoom;
3181     90.0f,                //float     zoomFov;
3182     qtrue,                //qboolean  purchasable;
3183     0,                    //int       buildDelay;
3184     WUT_HUMANS            //WUTeam_t  team;
3185   },
3186   {
3187     WP_GRENADE,           //int       weaponNum;
3188     GRENADE_PRICE,        //int       price;
3189     ( 1 << S2 )|( 1 << S3 ), //int  stages
3190     SLOT_NONE,            //int       slots;
3191     "grenade",            //char      *weaponName;
3192     "Grenade",            //char      *weaponHumanName;
3193     1,                    //int       maxAmmo;
3194     0,                    //int       maxClips;
3195     qfalse,               //int       infiniteAmmo;
3196     qfalse,               //int       usesEnergy;
3197     GRENADE_REPEAT,       //int       repeatRate1;
3198     0,                    //int       repeatRate2;
3199     0,                    //int       repeatRate3;
3200     0,                    //int       reloadTime;
3201     qfalse,               //qboolean  hasAltMode;
3202     qfalse,               //qboolean  hasThirdMode;
3203     qfalse,               //qboolean  canZoom;
3204     90.0f,                //float     zoomFov;
3205     qfalse,               //qboolean  purchasable;
3206     0,                    //int       buildDelay;
3207     WUT_HUMANS            //WUTeam_t  team;
3208   },
3209   {
3210     WP_HBUILD,            //int       weaponNum;
3211     HBUILD_PRICE,         //int       price;
3212     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3213     SLOT_WEAPON,          //int       slots;
3214     "ckit",               //char      *weaponName;
3215     "Construction Kit",   //char      *weaponHumanName;
3216     0,                    //int       maxAmmo;
3217     0,                    //int       maxClips;
3218     qtrue,                //int       infiniteAmmo;
3219     qfalse,               //int       usesEnergy;
3220     HBUILD_REPEAT,        //int       repeatRate1;
3221     HBUILD_REPEAT,        //int       repeatRate2;
3222     0,                    //int       repeatRate3;
3223     0,                    //int       reloadTime;
3224     qtrue,                //qboolean  hasAltMode;
3225     qfalse,               //qboolean  hasThirdMode;
3226     qfalse,               //qboolean  canZoom;
3227     90.0f,                //float     zoomFov;
3228     qtrue,                //qboolean  purchasable;
3229     HBUILD_DELAY,         //int       buildDelay;
3230     WUT_HUMANS            //WUTeam_t  team;
3231   },
3232   {
3233     WP_HBUILD2,           //int       weaponNum;
3234     HBUILD2_PRICE,        //int       price;
3235     ( 1 << S2 )|( 1 << S3 ), //int  stages
3236     SLOT_WEAPON,          //int       slots;
3237     "ackit",              //char      *weaponName;
3238     "Adv Construction Kit",//char      *weaponHumanName;
3239     0,                    //int       maxAmmo;
3240     0,                    //int       maxClips;
3241     qtrue,                //int       infiniteAmmo;
3242     qfalse,               //int       usesEnergy;
3243     HBUILD2_REPEAT,       //int       repeatRate1;
3244     HBUILD2_REPEAT,       //int       repeatRate2;
3245     0,                    //int       repeatRate3;
3246     0,                    //int       reloadTime;
3247     qtrue,                //qboolean  hasAltMode;
3248     qfalse,               //qboolean  hasThirdMode;
3249     qfalse,               //qboolean  canZoom;
3250     90.0f,                //float     zoomFov;
3251     qtrue,                //qboolean  purchasable;
3252     HBUILD2_DELAY,        //int       buildDelay;
3253     WUT_HUMANS            //WUTeam_t  team;
3254   },
3255   {
3256     WP_ABUILD,            //int       weaponNum;
3257     0,                    //int       price;
3258     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3259     SLOT_WEAPON,          //int       slots;
3260     "abuild",             //char      *weaponName;
3261     "Alien build weapon", //char      *weaponHumanName;
3262     0,                    //int       maxAmmo;
3263     0,                    //int       maxClips;
3264     qtrue,                //int       infiniteAmmo;
3265     qfalse,               //int       usesEnergy;
3266     ABUILDER_BUILD_REPEAT,//int       repeatRate1;
3267     ABUILDER_BUILD_REPEAT,//int       repeatRate2;
3268     0,                    //int       repeatRate3;
3269     0,                    //int       reloadTime;
3270     qtrue,                //qboolean  hasAltMode;
3271     qfalse,               //qboolean  hasThirdMode;
3272     qfalse,               //qboolean  canZoom;
3273     90.0f,                //float     zoomFov;
3274     qtrue,                //qboolean  purchasable;
3275     ABUILDER_BASE_DELAY,  //int       buildDelay;
3276     WUT_ALIENS            //WUTeam_t  team;
3277   },
3278   {
3279     WP_ABUILD2,           //int       weaponNum;
3280     0,                    //int       price;
3281     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3282     SLOT_WEAPON,          //int       slots;
3283     "abuildupg",          //char      *weaponName;
3284     "Alien build weapon2",//char      *weaponHumanName;
3285     0,                    //int       maxAmmo;
3286     0,                    //int       maxClips;
3287     qtrue,                //int       infiniteAmmo;
3288     qfalse,               //int       usesEnergy;
3289     ABUILDER_BUILD_REPEAT,//int       repeatRate1;
3290     ABUILDER_CLAW_REPEAT, //int       repeatRate2;
3291     ABUILDER_BLOB_REPEAT, //int       repeatRate3;
3292     0,                    //int       reloadTime;
3293     qtrue,                //qboolean  hasAltMode;
3294     qtrue,                //qboolean  hasThirdMode;
3295     qfalse,               //qboolean  canZoom;
3296     90.0f,                //float     zoomFov;
3297     qtrue,                //qboolean  purchasable;
3298     ABUILDER_ADV_DELAY,   //int       buildDelay;
3299     WUT_ALIENS            //WUTeam_t  team;
3300   },
3301   {
3302     WP_ALEVEL0,           //int       weaponNum;
3303     0,                    //int       price;
3304     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3305     SLOT_WEAPON,          //int       slots;
3306     "level0",             //char      *weaponName;
3307     "Bite",               //char      *weaponHumanName;
3308     0,                    //int       maxAmmo;
3309     0,                    //int       maxClips;
3310     qtrue,                //int       infiniteAmmo;
3311     qfalse,               //int       usesEnergy;
3312     LEVEL0_BITE_REPEAT,  //int       repeatRate1;
3313     0,                    //int       repeatRate2;
3314     0,                    //int       repeatRate3;
3315     0,                    //int       reloadTime;
3316     qfalse,               //qboolean  hasAltMode;
3317     qfalse,               //qboolean  hasThirdMode;
3318     qfalse,               //qboolean  canZoom;
3319     90.0f,                //float     zoomFov;
3320     qfalse,               //qboolean  purchasable;
3321     0,                    //int       buildDelay;
3322     WUT_ALIENS            //WUTeam_t  team;
3323   },
3324   {
3325     WP_ALEVEL1,           //int       weaponNum;
3326     0,                    //int       price;
3327     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3328     SLOT_WEAPON,          //int       slots;
3329     "level1",             //char      *weaponName;
3330     "Claws",              //char      *weaponHumanName;
3331     0,                    //int       maxAmmo;
3332     0,                    //int       maxClips;
3333     qtrue,                //int       infiniteAmmo;
3334     qfalse,               //int       usesEnergy;
3335     LEVEL1_CLAW_REPEAT,   //int       repeatRate1;
3336     0,                    //int       repeatRate2;
3337     0,                    //int       repeatRate3;
3338     0,                    //int       reloadTime;
3339     qfalse,               //qboolean  hasAltMode;
3340     qfalse,               //qboolean  hasThirdMode;
3341     qfalse,               //qboolean  canZoom;
3342     90.0f,                //float     zoomFov;
3343     qfalse,               //qboolean  purchasable;
3344     0,                    //int       buildDelay;
3345     WUT_ALIENS            //WUTeam_t  team;
3346   },
3347   {
3348     WP_ALEVEL1_UPG,       //int       weaponNum;
3349     0,                    //int       price;
3350     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3351     SLOT_WEAPON,          //int       slots;
3352     "level1upg",          //char      *weaponName;
3353     "Claws Upgrade",      //char      *weaponHumanName;
3354     0,                    //int       maxAmmo;
3355     0,                    //int       maxClips;
3356     qtrue,                //int       infiniteAmmo;
3357     qfalse,               //int       usesEnergy;
3358     LEVEL1_CLAW_U_REPEAT, //int       repeatRate1;
3359     LEVEL1_PCLOUD_REPEAT, //int       repeatRate2;
3360     0,                    //int       repeatRate3;
3361     0,                    //int       reloadTime;
3362     qtrue,                //qboolean  hasAltMode;
3363     qfalse,               //qboolean  hasThirdMode;
3364     qfalse,               //qboolean  canZoom;
3365     90.0f,                //float     zoomFov;
3366     qfalse,               //qboolean  purchasable;
3367     0,                    //int       buildDelay;
3368     WUT_ALIENS            //WUTeam_t  team;
3369   },
3370   {
3371     WP_ALEVEL2,           //int       weaponNum;
3372     0,                    //int       price;
3373     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3374     SLOT_WEAPON,          //int       slots;
3375     "level2",             //char      *weaponName;
3376     "Bite",               //char      *weaponHumanName;
3377     0,                    //int       maxAmmo;
3378     0,                    //int       maxClips;
3379     qtrue,                //int       infiniteAmmo;
3380     qfalse,               //int       usesEnergy;
3381     LEVEL2_CLAW_REPEAT,   //int       repeatRate1;
3382     0,                    //int       repeatRate2;
3383     0,                    //int       repeatRate3;
3384     0,                    //int       reloadTime;
3385     qfalse,               //qboolean  hasAltMode;
3386     qfalse,               //qboolean  hasThirdMode;
3387     qfalse,               //qboolean  canZoom;
3388     90.0f,                //float     zoomFov;
3389     qfalse,               //qboolean  purchasable;
3390     0,                    //int       buildDelay;
3391     WUT_ALIENS            //WUTeam_t  team;
3392   },
3393   {
3394     WP_ALEVEL2_UPG,       //int       weaponNum;
3395     0,                    //int       price;
3396     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3397     SLOT_WEAPON,          //int       slots;
3398     "level2upg",          //char      *weaponName;
3399     "Zap",                //char      *weaponHumanName;
3400     0,                    //int       maxAmmo;
3401     0,                    //int       maxClips;
3402     qtrue,                //int       infiniteAmmo;
3403     qfalse,               //int       usesEnergy;
3404     LEVEL2_CLAW_U_REPEAT, //int       repeatRate1;
3405     LEVEL2_AREAZAP_REPEAT,//int       repeatRate2;
3406     0,                    //int       repeatRate3;
3407     0,                    //int       reloadTime;
3408     qtrue,                //qboolean  hasAltMode;
3409     qfalse,               //qboolean  hasThirdMode;
3410     qfalse,               //qboolean  canZoom;
3411     90.0f,                //float     zoomFov;
3412     qfalse,               //qboolean  purchasable;
3413     0,                    //int       buildDelay;
3414     WUT_ALIENS            //WUTeam_t  team;
3415   },
3416   {
3417     WP_ALEVEL3,           //int       weaponNum;
3418     0,                    //int       price;
3419     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3420     SLOT_WEAPON,          //int       slots;
3421     "level3",             //char      *weaponName;
3422     "Pounce",             //char      *weaponHumanName;
3423     0,                    //int       maxAmmo;
3424     0,                    //int       maxClips;
3425     qtrue,                //int       infiniteAmmo;
3426     qfalse,               //int       usesEnergy;
3427     LEVEL3_CLAW_REPEAT,   //int       repeatRate1;
3428     0,                    //int       repeatRate2;
3429     0,                    //int       repeatRate3;
3430     0,                    //int       reloadTime;
3431     qfalse,               //qboolean  hasAltMode;
3432     qfalse,               //qboolean  hasThirdMode;
3433     qfalse,               //qboolean  canZoom;
3434     90.0f,                //float     zoomFov;
3435     qfalse,               //qboolean  purchasable;
3436     0,                    //int       buildDelay;
3437     WUT_ALIENS            //WUTeam_t  team;
3438   },
3439   {
3440     WP_ALEVEL3_UPG,       //int       weaponNum;
3441     0,                    //int       price;
3442     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3443     SLOT_WEAPON,          //int       slots;
3444     "level3upg",          //char      *weaponName;
3445     "Pounce (upgrade)",   //char      *weaponHumanName;
3446     3,                    //int       maxAmmo;
3447     0,                    //int       maxClips;
3448     qtrue,                //int       infiniteAmmo;
3449     qfalse,               //int       usesEnergy;
3450     LEVEL3_CLAW_U_REPEAT, //int       repeatRate1;
3451     0,                    //int       repeatRate2;
3452     LEVEL3_BOUNCEBALL_REPEAT,//int       repeatRate3;
3453     0,                    //int       reloadTime;
3454     qfalse,               //qboolean  hasAltMode;
3455     qtrue,                //qboolean  hasThirdMode;
3456     qfalse,               //qboolean  canZoom;
3457     90.0f,                //float     zoomFov;
3458     qfalse,               //qboolean  purchasable;
3459     0,                    //int       buildDelay;
3460     WUT_ALIENS            //WUTeam_t  team;
3461   },
3462   {
3463     WP_ALEVEL4,           //int       weaponNum;
3464     0,                    //int       price;
3465     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3466     SLOT_WEAPON,          //int       slots;
3467     "level4",             //char      *weaponName;
3468     "Charge",             //char      *weaponHumanName;
3469     0,                    //int       maxAmmo;
3470     0,                    //int       maxClips;
3471     qtrue,                //int       infiniteAmmo;
3472     qfalse,               //int       usesEnergy;
3473     LEVEL4_CLAW_REPEAT,    //int       repeatRate1;
3474     0,                    //int       repeatRate2;
3475     0,                    //int       repeatRate3;
3476     0,                    //int       reloadTime;
3477     qfalse,               //qboolean  hasAltMode;
3478     qfalse,               //qboolean  hasThirdMode;
3479     qfalse,               //qboolean  canZoom;
3480     90.0f,                //float     zoomFov;
3481     qfalse,               //qboolean  purchasable;
3482     0,                    //int       buildDelay;
3483     WUT_ALIENS            //WUTeam_t  team;
3484   },
3485   {
3486     WP_LOCKBLOB_LAUNCHER, //int       weaponNum;
3487     0,                    //int       price;
3488     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3489     SLOT_WEAPON,          //int       slots;
3490     "lockblob",           //char      *weaponName;
3491     "Lock Blob",          //char      *weaponHumanName;
3492     0,                    //int       maxAmmo;
3493     0,                    //int       maxClips;
3494     qtrue,                //int       infiniteAmmo;
3495     qfalse,               //int       usesEnergy;
3496     500,                  //int       repeatRate1;
3497     500,                  //int       repeatRate2;
3498     500,                  //int       repeatRate3;
3499     0,                    //int       reloadTime;
3500     qfalse,               //qboolean  hasAltMode;
3501     qfalse,               //qboolean  hasThirdMode;
3502     qfalse,               //qboolean  canZoom;
3503     90.0f,                //float     zoomFov;
3504     qfalse,               //qboolean  purchasable;
3505     0,                    //int       buildDelay;
3506     WUT_ALIENS            //WUTeam_t  team;
3507   },
3508   {
3509     WP_HIVE,              //int       weaponNum;
3510     0,                    //int       price;
3511     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3512     SLOT_WEAPON,          //int       slots;
3513     "hive",               //char      *weaponName;
3514     "Hive",               //char      *weaponHumanName;
3515     0,                    //int       maxAmmo;
3516     0,                    //int       maxClips;
3517     qtrue,                //int       infiniteAmmo;
3518     qfalse,               //int       usesEnergy;
3519     500,                  //int       repeatRate1;
3520     500,                  //int       repeatRate2;
3521     500,                  //int       repeatRate3;
3522     0,                    //int       reloadTime;
3523     qfalse,               //qboolean  hasAltMode;
3524     qfalse,               //qboolean  hasThirdMode;
3525     qfalse,               //qboolean  canZoom;
3526     90.0f,                //float     zoomFov;
3527     qfalse,               //qboolean  purchasable;
3528     0,                    //int       buildDelay;
3529     WUT_ALIENS            //WUTeam_t  team;
3530   },
3531   {
3532     WP_MGTURRET,          //int       weaponNum;
3533     0,                    //int       price;
3534     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3535     SLOT_WEAPON,          //int       slots;
3536     "mgturret",           //char      *weaponName;
3537     "Machinegun Turret",  //char      *weaponHumanName;
3538     0,                    //int       maxAmmo;
3539     0,                    //int       maxClips;
3540     qtrue,                //int       infiniteAmmo;
3541     qfalse,               //int       usesEnergy;
3542     0,                    //int       repeatRate1;
3543     0,                    //int       repeatRate2;
3544     0,                    //int       repeatRate3;
3545     0,                    //int       reloadTime;
3546     qfalse,               //qboolean  hasAltMode;
3547     qfalse,               //qboolean  hasThirdMode;
3548     qfalse,               //qboolean  canZoom;
3549     90.0f,                //float     zoomFov;
3550     qfalse,               //qboolean  purchasable;
3551     0,                    //int       buildDelay;
3552     WUT_HUMANS            //WUTeam_t  team;
3553   },
3554   {
3555     WP_TESLAGEN,          //int       weaponNum;
3556     0,                    //int       price;
3557     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3558     SLOT_WEAPON,          //int       slots;
3559     "teslagen",           //char      *weaponName;
3560     "Tesla Generator",    //char      *weaponHumanName;
3561     0,                    //int       maxAmmo;
3562     0,                    //int       maxClips;
3563     qtrue,                //int       infiniteAmmo;
3564     qtrue,                //int       usesEnergy;
3565     500,                  //int       repeatRate1;
3566     500,                  //int       repeatRate2;
3567     500,                  //int       repeatRate3;
3568     0,                    //int       reloadTime;
3569     qfalse,               //qboolean  hasAltMode;
3570     qfalse,               //qboolean  hasThirdMode;
3571     qfalse,               //qboolean  canZoom;
3572     90.0f,                //float     zoomFov;
3573     qfalse,               //qboolean  purchasable;
3574     0,                    //int       buildDelay;
3575     WUT_HUMANS            //WUTeam_t  team;
3576   }
3577 };
3578 
3579 int   bg_numWeapons = sizeof( bg_weapons ) / sizeof( bg_weapons[ 0 ] );
3580 
3581 /*
3582 ==============
3583 BG_FindPriceForWeapon
3584 ==============
3585 */
BG_FindPriceForWeapon(int weapon)3586 int BG_FindPriceForWeapon( int weapon )
3587 {
3588   int i;
3589 
3590   for( i = 0; i < bg_numWeapons; i++ )
3591   {
3592     if( bg_weapons[ i ].weaponNum == weapon )
3593     {
3594       return bg_weapons[ i ].price;
3595     }
3596   }
3597 
3598   return 100;
3599 }
3600 
3601 /*
3602 ==============
3603 BG_FindStagesForWeapon
3604 ==============
3605 */
BG_FindStagesForWeapon(int weapon,stage_t stage)3606 qboolean BG_FindStagesForWeapon( int weapon, stage_t stage )
3607 {
3608   int i;
3609 
3610   for( i = 0; i < bg_numWeapons; i++ )
3611   {
3612     if( bg_weapons[ i ].weaponNum == weapon )
3613     {
3614       if( bg_weapons[ i ].stages & ( 1 << stage ) )
3615         return qtrue;
3616       else
3617         return qfalse;
3618     }
3619   }
3620 
3621   return qfalse;
3622 }
3623 
3624 /*
3625 ==============
3626 BG_FindSlotsForWeapon
3627 ==============
3628 */
BG_FindSlotsForWeapon(int weapon)3629 int BG_FindSlotsForWeapon( int weapon )
3630 {
3631   int i;
3632 
3633   for( i = 0; i < bg_numWeapons; i++ )
3634   {
3635     if( bg_weapons[ i ].weaponNum == weapon )
3636     {
3637       return bg_weapons[ i ].slots;
3638     }
3639   }
3640 
3641   return SLOT_WEAPON;
3642 }
3643 
3644 /*
3645 ==============
3646 BG_FindNameForWeapon
3647 ==============
3648 */
BG_FindNameForWeapon(int weapon)3649 char *BG_FindNameForWeapon( int weapon )
3650 {
3651   int i;
3652 
3653   for( i = 0; i < bg_numWeapons; i++ )
3654   {
3655     if( bg_weapons[ i ].weaponNum == weapon )
3656       return bg_weapons[ i ].weaponName;
3657   }
3658 
3659   //wimp out
3660   return 0;
3661 }
3662 
3663 /*
3664 ==============
3665 BG_FindWeaponNumForName
3666 ==============
3667 */
BG_FindWeaponNumForName(char * name)3668 int BG_FindWeaponNumForName( char *name )
3669 {
3670   int i;
3671 
3672   for( i = 0; i < bg_numWeapons; i++ )
3673   {
3674     if( !Q_stricmp( bg_weapons[ i ].weaponName, name ) )
3675       return bg_weapons[ i ].weaponNum;
3676   }
3677 
3678   //wimp out
3679   return WP_NONE;
3680 }
3681 
3682 /*
3683 ==============
3684 BG_FindHumanNameForWeapon
3685 ==============
3686 */
BG_FindHumanNameForWeapon(int weapon)3687 char *BG_FindHumanNameForWeapon( int weapon )
3688 {
3689   int i;
3690 
3691   for( i = 0; i < bg_numWeapons; i++ )
3692   {
3693     if( bg_weapons[ i ].weaponNum == weapon )
3694       return bg_weapons[ i ].weaponHumanName;
3695   }
3696 
3697   //wimp out
3698   return 0;
3699 }
3700 
3701 /*
3702 ==============
3703 BG_FindAmmoForWeapon
3704 ==============
3705 */
BG_FindAmmoForWeapon(int weapon,int * maxAmmo,int * maxClips)3706 void BG_FindAmmoForWeapon( int weapon, int *maxAmmo, int *maxClips )
3707 {
3708   int i;
3709 
3710   for( i = 0; i < bg_numWeapons; i++ )
3711   {
3712     if( bg_weapons[ i ].weaponNum == weapon )
3713     {
3714       if( maxAmmo != NULL )
3715         *maxAmmo = bg_weapons[ i ].maxAmmo;
3716       if( maxClips != NULL )
3717         *maxClips = bg_weapons[ i ].maxClips;
3718 
3719       //no need to keep going
3720       break;
3721     }
3722   }
3723 }
3724 
3725 /*
3726 ==============
3727 BG_FindInfinteAmmoForWeapon
3728 ==============
3729 */
BG_FindInfinteAmmoForWeapon(int weapon)3730 qboolean BG_FindInfinteAmmoForWeapon( int weapon )
3731 {
3732   int i;
3733 
3734   for( i = 0; i < bg_numWeapons; i++ )
3735   {
3736     if( bg_weapons[ i ].weaponNum == weapon )
3737     {
3738       return bg_weapons[ i ].infiniteAmmo;
3739     }
3740   }
3741 
3742   return qfalse;
3743 }
3744 
3745 /*
3746 ==============
3747 BG_FindUsesEnergyForWeapon
3748 ==============
3749 */
BG_FindUsesEnergyForWeapon(int weapon)3750 qboolean BG_FindUsesEnergyForWeapon( int weapon )
3751 {
3752   int i;
3753 
3754   for( i = 0; i < bg_numWeapons; i++ )
3755   {
3756     if( bg_weapons[ i ].weaponNum == weapon )
3757     {
3758       return bg_weapons[ i ].usesEnergy;
3759     }
3760   }
3761 
3762   return qfalse;
3763 }
3764 
3765 /*
3766 ==============
3767 BG_FindRepeatRate1ForWeapon
3768 ==============
3769 */
BG_FindRepeatRate1ForWeapon(int weapon)3770 int BG_FindRepeatRate1ForWeapon( int weapon )
3771 {
3772   int i;
3773 
3774   for( i = 0; i < bg_numWeapons; i++ )
3775   {
3776     if( bg_weapons[ i ].weaponNum == weapon )
3777       return bg_weapons[ i ].repeatRate1;
3778   }
3779 
3780   return 1000;
3781 }
3782 
3783 /*
3784 ==============
3785 BG_FindRepeatRate2ForWeapon
3786 ==============
3787 */
BG_FindRepeatRate2ForWeapon(int weapon)3788 int BG_FindRepeatRate2ForWeapon( int weapon )
3789 {
3790   int i;
3791 
3792   for( i = 0; i < bg_numWeapons; i++ )
3793   {
3794     if( bg_weapons[ i ].weaponNum == weapon )
3795       return bg_weapons[ i ].repeatRate2;
3796   }
3797 
3798   return 1000;
3799 }
3800 
3801 /*
3802 ==============
3803 BG_FindRepeatRate3ForWeapon
3804 ==============
3805 */
BG_FindRepeatRate3ForWeapon(int weapon)3806 int BG_FindRepeatRate3ForWeapon( int weapon )
3807 {
3808   int i;
3809 
3810   for( i = 0; i < bg_numWeapons; i++ )
3811   {
3812     if( bg_weapons[ i ].weaponNum == weapon )
3813       return bg_weapons[ i ].repeatRate3;
3814   }
3815 
3816   return 1000;
3817 }
3818 
3819 /*
3820 ==============
3821 BG_FindReloadTimeForWeapon
3822 ==============
3823 */
BG_FindReloadTimeForWeapon(int weapon)3824 int BG_FindReloadTimeForWeapon( int weapon )
3825 {
3826   int i;
3827 
3828   for( i = 0; i < bg_numWeapons; i++ )
3829   {
3830     if( bg_weapons[ i ].weaponNum == weapon )
3831     {
3832       return bg_weapons[ i ].reloadTime;
3833     }
3834   }
3835 
3836   return 1000;
3837 }
3838 
3839 /*
3840 ==============
3841 BG_WeaponHasAltMode
3842 ==============
3843 */
BG_WeaponHasAltMode(int weapon)3844 qboolean BG_WeaponHasAltMode( int weapon )
3845 {
3846   int i;
3847 
3848   for( i = 0; i < bg_numWeapons; i++ )
3849   {
3850     if( bg_weapons[ i ].weaponNum == weapon )
3851     {
3852       return bg_weapons[ i ].hasAltMode;
3853     }
3854   }
3855 
3856   return qfalse;
3857 }
3858 
3859 /*
3860 ==============
3861 BG_WeaponHasThirdMode
3862 ==============
3863 */
BG_WeaponHasThirdMode(int weapon)3864 qboolean BG_WeaponHasThirdMode( int weapon )
3865 {
3866   int i;
3867 
3868   for( i = 0; i < bg_numWeapons; i++ )
3869   {
3870     if( bg_weapons[ i ].weaponNum == weapon )
3871     {
3872       return bg_weapons[ i ].hasThirdMode;
3873     }
3874   }
3875 
3876   return qfalse;
3877 }
3878 
3879 /*
3880 ==============
3881 BG_WeaponCanZoom
3882 ==============
3883 */
BG_WeaponCanZoom(int weapon)3884 qboolean BG_WeaponCanZoom( int weapon )
3885 {
3886   int i;
3887 
3888   for( i = 0; i < bg_numWeapons; i++ )
3889   {
3890     if( bg_weapons[ i ].weaponNum == weapon )
3891     {
3892       return bg_weapons[ i ].canZoom;
3893     }
3894   }
3895 
3896   return qfalse;
3897 }
3898 
3899 /*
3900 ==============
3901 BG_FindZoomFovForWeapon
3902 ==============
3903 */
BG_FindZoomFovForWeapon(int weapon)3904 float BG_FindZoomFovForWeapon( int weapon )
3905 {
3906   int i;
3907 
3908   for( i = 0; i < bg_numWeapons; i++ )
3909   {
3910     if( bg_weapons[ i ].weaponNum == weapon )
3911     {
3912       return bg_weapons[ i ].zoomFov;
3913     }
3914   }
3915 
3916   return qfalse;
3917 }
3918 
3919 /*
3920 ==============
3921 BG_FindPurchasableForWeapon
3922 ==============
3923 */
BG_FindPurchasableForWeapon(int weapon)3924 qboolean BG_FindPurchasableForWeapon( int weapon )
3925 {
3926   int i;
3927 
3928   for( i = 0; i < bg_numWeapons; i++ )
3929   {
3930     if( bg_weapons[ i ].weaponNum == weapon )
3931     {
3932       return bg_weapons[ i ].purchasable;
3933     }
3934   }
3935 
3936   return qfalse;
3937 }
3938 
3939 /*
3940 ==============
3941 BG_FindBuildDelayForWeapon
3942 ==============
3943 */
BG_FindBuildDelayForWeapon(int weapon)3944 int BG_FindBuildDelayForWeapon( int weapon )
3945 {
3946   int i;
3947 
3948   for( i = 0; i < bg_numWeapons; i++ )
3949   {
3950     if( bg_weapons[ i ].weaponNum == weapon )
3951     {
3952       return bg_weapons[ i ].buildDelay;
3953     }
3954   }
3955 
3956   return 0;
3957 }
3958 
3959 /*
3960 ==============
3961 BG_FindTeamForWeapon
3962 ==============
3963 */
BG_FindTeamForWeapon(int weapon)3964 WUTeam_t BG_FindTeamForWeapon( int weapon )
3965 {
3966   int i;
3967 
3968   for( i = 0; i < bg_numWeapons; i++ )
3969   {
3970     if( bg_weapons[ i ].weaponNum == weapon )
3971     {
3972       return bg_weapons[ i ].team;
3973     }
3974   }
3975 
3976   return WUT_NONE;
3977 }
3978 
3979 ////////////////////////////////////////////////////////////////////////////////
3980 
3981 upgradeAttributes_t bg_upgrades[ ] =
3982 {
3983   {
3984     UP_LIGHTARMOUR,         //int   upgradeNum;
3985     LIGHTARMOUR_PRICE,      //int   price;
3986     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
3987     SLOT_TORSO|SLOT_ARMS|SLOT_LEGS, //int   slots;
3988     "larmour",              //char  *upgradeName;
3989     "Light Armour",         //char  *upgradeHumanName;
3990     "icons/iconu_larmour",
3991     qtrue,                  //qboolean purchasable
3992     qfalse,                 //qboolean usable
3993     WUT_HUMANS              //WUTeam_t  team;
3994   },
3995   {
3996     UP_HELMET,              //int   upgradeNum;
3997     HELMET_PRICE,           //int   price;
3998     ( 1 << S2 )|( 1 << S3 ), //int  stages
3999     SLOT_HEAD,              //int   slots;
4000     "helmet",               //char  *upgradeName;
4001     "Helmet",               //char  *upgradeHumanName;
4002     "icons/iconu_helmet",
4003     qtrue,                  //qboolean purchasable
4004     qfalse,                 //qboolean usable
4005     WUT_HUMANS              //WUTeam_t  team;
4006   },
4007   {
4008     UP_MEDKIT,              //int   upgradeNum;
4009     MEDKIT_PRICE,           //int   price;
4010     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
4011     SLOT_NONE,              //int   slots;
4012     "medkit",               //char  *upgradeName;
4013     "Medkit",               //char  *upgradeHumanName;
4014     "icons/iconu_atoxin",
4015     qfalse,                 //qboolean purchasable
4016     qtrue,                  //qboolean usable
4017     WUT_HUMANS              //WUTeam_t  team;
4018   },
4019   {
4020     UP_BATTPACK,            //int   upgradeNum;
4021     BATTPACK_PRICE,         //int   price;
4022     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
4023     SLOT_BACKPACK,          //int   slots;
4024     "battpack",             //char  *upgradeName;
4025     "Battery Pack",         //char  *upgradeHumanName;
4026     "icons/iconu_battpack",
4027     qtrue,                  //qboolean purchasable
4028     qfalse,                 //qboolean usable
4029     WUT_HUMANS              //WUTeam_t  team;
4030   },
4031   {
4032     UP_JETPACK,             //int   upgradeNum;
4033     JETPACK_PRICE,          //int   price;
4034     ( 1 << S2 )|( 1 << S3 ), //int  stages
4035     SLOT_BACKPACK,          //int   slots;
4036     "jetpack",              //char  *upgradeName;
4037     "Jet Pack",             //char  *upgradeHumanName;
4038     "icons/iconu_jetpack",
4039     qtrue,                  //qboolean purchasable
4040     qtrue,                  //qboolean usable
4041     WUT_HUMANS              //WUTeam_t  team;
4042   },
4043   {
4044     UP_BATTLESUIT,          //int   upgradeNum;
4045     BSUIT_PRICE,            //int   price;
4046     ( 1 << S3 ),            //int  stages
4047     SLOT_HEAD|SLOT_TORSO|SLOT_ARMS|SLOT_LEGS|SLOT_BACKPACK, //int   slots;
4048     "bsuit",                //char  *upgradeName;
4049     "Battlesuit",           //char  *upgradeHumanName;
4050     "icons/iconu_bsuit",
4051     qtrue,                  //qboolean purchasable
4052     qfalse,                 //qboolean usable
4053     WUT_HUMANS              //WUTeam_t  team;
4054   },
4055   {
4056     UP_GRENADE,             //int   upgradeNum;
4057     GRENADE_PRICE,          //int   price;
4058     ( 1 << S2 )|( 1 << S3 ),//int  stages
4059     SLOT_NONE,              //int   slots;
4060     "gren",                 //char  *upgradeName;
4061     "Grenade",              //char  *upgradeHumanName;
4062     0,
4063     qtrue,                  //qboolean purchasable
4064     qtrue,                  //qboolean usable
4065     WUT_HUMANS              //WUTeam_t  team;
4066   },
4067   {
4068     UP_AMMO,                //int   upgradeNum;
4069     0,                      //int   price;
4070     ( 1 << S1 )|( 1 << S2 )|( 1 << S3 ), //int  stages
4071     SLOT_NONE,              //int   slots;
4072     "ammo",                 //char  *upgradeName;
4073     "Ammunition",           //char  *upgradeHumanName;
4074     0,
4075     qtrue,                  //qboolean purchasable
4076     qfalse,                 //qboolean usable
4077     WUT_HUMANS              //WUTeam_t  team;
4078   }
4079 };
4080 
4081 int   bg_numUpgrades = sizeof( bg_upgrades ) / sizeof( bg_upgrades[ 0 ] );
4082 
4083 /*
4084 ==============
4085 BG_FindPriceForUpgrade
4086 ==============
4087 */
BG_FindPriceForUpgrade(int upgrade)4088 int BG_FindPriceForUpgrade( int upgrade )
4089 {
4090   int i;
4091 
4092   for( i = 0; i < bg_numUpgrades; i++ )
4093   {
4094     if( bg_upgrades[ i ].upgradeNum == upgrade )
4095     {
4096       return bg_upgrades[ i ].price;
4097     }
4098   }
4099 
4100   return 100;
4101 }
4102 
4103 /*
4104 ==============
4105 BG_FindStagesForUpgrade
4106 ==============
4107 */
BG_FindStagesForUpgrade(int upgrade,stage_t stage)4108 qboolean BG_FindStagesForUpgrade( int upgrade, stage_t stage )
4109 {
4110   int i;
4111 
4112   for( i = 0; i < bg_numUpgrades; i++ )
4113   {
4114     if( bg_upgrades[ i ].upgradeNum == upgrade )
4115     {
4116       if( bg_upgrades[ i ].stages & ( 1 << stage ) )
4117         return qtrue;
4118       else
4119         return qfalse;
4120     }
4121   }
4122 
4123   return qfalse;
4124 }
4125 
4126 /*
4127 ==============
4128 BG_FindSlotsForUpgrade
4129 ==============
4130 */
BG_FindSlotsForUpgrade(int upgrade)4131 int BG_FindSlotsForUpgrade( int upgrade )
4132 {
4133   int i;
4134 
4135   for( i = 0; i < bg_numUpgrades; i++ )
4136   {
4137     if( bg_upgrades[ i ].upgradeNum == upgrade )
4138     {
4139       return bg_upgrades[ i ].slots;
4140     }
4141   }
4142 
4143   return SLOT_NONE;
4144 }
4145 
4146 /*
4147 ==============
4148 BG_FindNameForUpgrade
4149 ==============
4150 */
BG_FindNameForUpgrade(int upgrade)4151 char *BG_FindNameForUpgrade( int upgrade )
4152 {
4153   int i;
4154 
4155   for( i = 0; i < bg_numUpgrades; i++ )
4156   {
4157     if( bg_upgrades[ i ].upgradeNum == upgrade )
4158       return bg_upgrades[ i ].upgradeName;
4159   }
4160 
4161   //wimp out
4162   return 0;
4163 }
4164 
4165 /*
4166 ==============
4167 BG_FindUpgradeNumForName
4168 ==============
4169 */
BG_FindUpgradeNumForName(char * name)4170 int BG_FindUpgradeNumForName( char *name )
4171 {
4172   int i;
4173 
4174   for( i = 0; i < bg_numUpgrades; i++ )
4175   {
4176     if( !Q_stricmp( bg_upgrades[ i ].upgradeName, name ) )
4177       return bg_upgrades[ i ].upgradeNum;
4178   }
4179 
4180   //wimp out
4181   return UP_NONE;
4182 }
4183 
4184 /*
4185 ==============
4186 BG_FindHumanNameForUpgrade
4187 ==============
4188 */
BG_FindHumanNameForUpgrade(int upgrade)4189 char *BG_FindHumanNameForUpgrade( int upgrade )
4190 {
4191   int i;
4192 
4193   for( i = 0; i < bg_numUpgrades; i++ )
4194   {
4195     if( bg_upgrades[ i ].upgradeNum == upgrade )
4196       return bg_upgrades[ i ].upgradeHumanName;
4197   }
4198 
4199   //wimp out
4200   return 0;
4201 }
4202 
4203 /*
4204 ==============
4205 BG_FindIconForUpgrade
4206 ==============
4207 */
BG_FindIconForUpgrade(int upgrade)4208 char *BG_FindIconForUpgrade( int upgrade )
4209 {
4210   int i;
4211 
4212   for( i = 0; i < bg_numUpgrades; i++ )
4213   {
4214     if( bg_upgrades[ i ].upgradeNum == upgrade )
4215       return bg_upgrades[ i ].icon;
4216   }
4217 
4218   //wimp out
4219   return 0;
4220 }
4221 
4222 /*
4223 ==============
4224 BG_FindPurchasableForUpgrade
4225 ==============
4226 */
BG_FindPurchasableForUpgrade(int upgrade)4227 qboolean BG_FindPurchasableForUpgrade( int upgrade )
4228 {
4229   int i;
4230 
4231   for( i = 0; i < bg_numUpgrades; i++ )
4232   {
4233     if( bg_upgrades[ i ].upgradeNum == upgrade )
4234       return bg_upgrades[ i ].purchasable;
4235   }
4236 
4237   return qfalse;
4238 }
4239 
4240 /*
4241 ==============
4242 BG_FindUsableForUpgrade
4243 ==============
4244 */
BG_FindUsableForUpgrade(int upgrade)4245 qboolean BG_FindUsableForUpgrade( int upgrade )
4246 {
4247   int i;
4248 
4249   for( i = 0; i < bg_numUpgrades; i++ )
4250   {
4251     if( bg_upgrades[ i ].upgradeNum == upgrade )
4252       return bg_upgrades[ i ].usable;
4253   }
4254 
4255   return qfalse;
4256 }
4257 
4258 /*
4259 ==============
4260 BG_FindTeamForUpgrade
4261 ==============
4262 */
BG_FindTeamForUpgrade(int upgrade)4263 WUTeam_t BG_FindTeamForUpgrade( int upgrade )
4264 {
4265   int i;
4266 
4267   for( i = 0; i < bg_numUpgrades; i++ )
4268   {
4269     if( bg_upgrades[ i ].upgradeNum == upgrade )
4270     {
4271       return bg_upgrades[ i ].team;
4272     }
4273   }
4274 
4275   return WUT_NONE;
4276 }
4277 
4278 ////////////////////////////////////////////////////////////////////////////////
4279 
4280 /*
4281 ================
4282 BG_EvaluateTrajectory
4283 
4284 ================
4285 */
BG_EvaluateTrajectory(const trajectory_t * tr,int atTime,vec3_t result)4286 void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result )
4287 {
4288   float   deltaTime;
4289   float   phase;
4290 
4291   switch( tr->trType )
4292   {
4293     case TR_STATIONARY:
4294     case TR_INTERPOLATE:
4295       VectorCopy( tr->trBase, result );
4296       break;
4297 
4298     case TR_LINEAR:
4299       deltaTime = ( atTime - tr->trTime ) * 0.001;  // milliseconds to seconds
4300       VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
4301       break;
4302 
4303     case TR_SINE:
4304       deltaTime = ( atTime - tr->trTime ) / (float)tr->trDuration;
4305       phase = sin( deltaTime * M_PI * 2 );
4306       VectorMA( tr->trBase, phase, tr->trDelta, result );
4307       break;
4308 
4309     case TR_LINEAR_STOP:
4310       if( atTime > tr->trTime + tr->trDuration )
4311         atTime = tr->trTime + tr->trDuration;
4312 
4313       deltaTime = ( atTime - tr->trTime ) * 0.001;  // milliseconds to seconds
4314       if( deltaTime < 0 )
4315         deltaTime = 0;
4316 
4317       VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
4318       break;
4319 
4320     case TR_GRAVITY:
4321       deltaTime = ( atTime - tr->trTime ) * 0.001;  // milliseconds to seconds
4322       VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
4323       result[ 2 ] -= 0.5 * DEFAULT_GRAVITY * deltaTime * deltaTime;   // FIXME: local gravity...
4324       break;
4325 
4326     case TR_BUOYANCY:
4327       deltaTime = ( atTime - tr->trTime ) * 0.001;  // milliseconds to seconds
4328       VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
4329       result[ 2 ] += 0.5 * DEFAULT_GRAVITY * deltaTime * deltaTime;   // FIXME: local gravity...
4330       break;
4331 
4332     default:
4333       Com_Error( ERR_DROP, "BG_EvaluateTrajectory: unknown trType: %i", tr->trTime );
4334       break;
4335   }
4336 }
4337 
4338 /*
4339 ================
4340 BG_EvaluateTrajectoryDelta
4341 
4342 For determining velocity at a given time
4343 ================
4344 */
BG_EvaluateTrajectoryDelta(const trajectory_t * tr,int atTime,vec3_t result)4345 void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result )
4346 {
4347   float deltaTime;
4348   float phase;
4349 
4350   switch( tr->trType )
4351   {
4352     case TR_STATIONARY:
4353     case TR_INTERPOLATE:
4354       VectorClear( result );
4355       break;
4356 
4357     case TR_LINEAR:
4358       VectorCopy( tr->trDelta, result );
4359       break;
4360 
4361     case TR_SINE:
4362       deltaTime = ( atTime - tr->trTime ) / (float)tr->trDuration;
4363       phase = cos( deltaTime * M_PI * 2 );  // derivative of sin = cos
4364       phase *= 0.5;
4365       VectorScale( tr->trDelta, phase, result );
4366       break;
4367 
4368     case TR_LINEAR_STOP:
4369       if( atTime > tr->trTime + tr->trDuration )
4370       {
4371         VectorClear( result );
4372         return;
4373       }
4374       VectorCopy( tr->trDelta, result );
4375       break;
4376 
4377     case TR_GRAVITY:
4378       deltaTime = ( atTime - tr->trTime ) * 0.001;  // milliseconds to seconds
4379       VectorCopy( tr->trDelta, result );
4380       result[ 2 ] -= DEFAULT_GRAVITY * deltaTime;   // FIXME: local gravity...
4381       break;
4382 
4383     case TR_BUOYANCY:
4384       deltaTime = ( atTime - tr->trTime ) * 0.001;  // milliseconds to seconds
4385       VectorCopy( tr->trDelta, result );
4386       result[ 2 ] += DEFAULT_GRAVITY * deltaTime;   // FIXME: local gravity...
4387       break;
4388 
4389     default:
4390       Com_Error( ERR_DROP, "BG_EvaluateTrajectoryDelta: unknown trType: %i", tr->trTime );
4391       break;
4392   }
4393 }
4394 
4395 char *eventnames[ ] =
4396 {
4397   "EV_NONE",
4398 
4399   "EV_FOOTSTEP",
4400   "EV_FOOTSTEP_METAL",
4401   "EV_FOOTSTEP_SQUELCH",
4402   "EV_FOOTSPLASH",
4403   "EV_FOOTWADE",
4404   "EV_SWIM",
4405 
4406   "EV_STEP_4",
4407   "EV_STEP_8",
4408   "EV_STEP_12",
4409   "EV_STEP_16",
4410 
4411   "EV_STEPDN_4",
4412   "EV_STEPDN_8",
4413   "EV_STEPDN_12",
4414   "EV_STEPDN_16",
4415 
4416   "EV_FALL_SHORT",
4417   "EV_FALL_MEDIUM",
4418   "EV_FALL_FAR",
4419   "EV_FALLING",
4420 
4421   "EV_JUMP",
4422   "EV_WATER_TOUCH", // foot touches
4423   "EV_WATER_LEAVE", // foot leaves
4424   "EV_WATER_UNDER", // head touches
4425   "EV_WATER_CLEAR", // head leaves
4426 
4427   "EV_NOAMMO",
4428   "EV_CHANGE_WEAPON",
4429   "EV_FIRE_WEAPON",
4430   "EV_FIRE_WEAPON2",
4431   "EV_FIRE_WEAPON3",
4432 
4433   "EV_PLAYER_RESPAWN", //TA: for fovwarp effects
4434   "EV_PLAYER_TELEPORT_IN",
4435   "EV_PLAYER_TELEPORT_OUT",
4436 
4437   "EV_GRENADE_BOUNCE",    // eventParm will be the soundindex
4438 
4439   "EV_GENERAL_SOUND",
4440   "EV_GLOBAL_SOUND",    // no attenuation
4441 
4442   "EV_BULLET_HIT_FLESH",
4443   "EV_BULLET_HIT_WALL",
4444 
4445   "EV_SHOTGUN",
4446 
4447   "EV_MISSILE_HIT",
4448   "EV_MISSILE_MISS",
4449   "EV_MISSILE_MISS_METAL",
4450   "EV_TESLATRAIL",
4451   "EV_BULLET",        // otherEntity is the shooter
4452 
4453   "EV_LEV1_GRAB",
4454   "EV_LEV4_CHARGE_PREPARE",
4455   "EV_LEV4_CHARGE_START",
4456 
4457   "EV_PAIN",
4458   "EV_DEATH1",
4459   "EV_DEATH2",
4460   "EV_DEATH3",
4461   "EV_OBITUARY",
4462 
4463   "EV_GIB_PLAYER",      // gib a previously living player
4464 
4465   "EV_BUILD_CONSTRUCT", //TA
4466   "EV_BUILD_DESTROY",   //TA
4467   "EV_BUILD_DELAY",     //TA: can't build yet
4468   "EV_BUILD_REPAIR",    //TA: repairing buildable
4469   "EV_BUILD_REPAIRED",  //TA: buildable has full health
4470   "EV_HUMAN_BUILDABLE_EXPLOSION",
4471   "EV_ALIEN_BUILDABLE_EXPLOSION",
4472   "EV_ALIEN_ACIDTUBE",
4473 
4474   "EV_MEDKIT_USED",
4475 
4476   "EV_ALIEN_EVOLVE",
4477   "EV_ALIEN_EVOLVE_FAILED",
4478 
4479   "EV_DEBUG_LINE",
4480   "EV_STOPLOOPINGSOUND",
4481   "EV_TAUNT",
4482 
4483   "EV_OVERMIND_ATTACK", //TA: overmind under attack
4484   "EV_OVERMIND_DYING",  //TA: overmind close to death
4485   "EV_OVERMIND_SPAWNS", //TA: overmind needs spawns
4486 
4487   "EV_DCC_ATTACK",      //TA: dcc under attack
4488 
4489   "EV_RPTUSE_SOUND"     //TA: trigger a sound
4490 };
4491 
4492 /*
4493 ===============
4494 BG_AddPredictableEventToPlayerstate
4495 
4496 Handles the sequence numbers
4497 ===============
4498 */
4499 
4500 void  trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
4501 
BG_AddPredictableEventToPlayerstate(int newEvent,int eventParm,playerState_t * ps)4502 void BG_AddPredictableEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps )
4503 {
4504 #ifdef _DEBUG
4505   {
4506     char buf[ 256 ];
4507     trap_Cvar_VariableStringBuffer( "showevents", buf, sizeof( buf ) );
4508 
4509     if( atof( buf ) != 0 )
4510     {
4511 #ifdef QAGAME
4512       Com_Printf( " game event svt %5d -> %5d: num = %20s parm %d\n",
4513                   ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, eventnames[ newEvent ], eventParm);
4514 #else
4515       Com_Printf( "Cgame event svt %5d -> %5d: num = %20s parm %d\n",
4516                   ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, eventnames[ newEvent ], eventParm);
4517 #endif
4518     }
4519   }
4520 #endif
4521   ps->events[ ps->eventSequence & ( MAX_PS_EVENTS - 1 ) ] = newEvent;
4522   ps->eventParms[ ps->eventSequence & ( MAX_PS_EVENTS - 1 ) ] = eventParm;
4523   ps->eventSequence++;
4524 }
4525 
4526 
4527 /*
4528 ========================
4529 BG_PlayerStateToEntityState
4530 
4531 This is done after each set of usercmd_t on the server,
4532 and after local prediction on the client
4533 ========================
4534 */
BG_PlayerStateToEntityState(playerState_t * ps,entityState_t * s,qboolean snap)4535 void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap )
4536 {
4537   int     i;
4538 
4539   if( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR || ps->pm_type == PM_FREEZE )
4540     s->eType = ET_INVISIBLE;
4541   else if( ps->persistant[ PERS_TEAM ] == TEAM_SPECTATOR )
4542     s->eType = ET_INVISIBLE;
4543   else
4544     s->eType = ET_PLAYER;
4545 
4546   s->number = ps->clientNum;
4547 
4548   s->pos.trType = TR_INTERPOLATE;
4549   VectorCopy( ps->origin, s->pos.trBase );
4550 
4551   if( snap )
4552     SnapVector( s->pos.trBase );
4553 
4554   //set the trDelta for flag direction
4555   VectorCopy( ps->velocity, s->pos.trDelta );
4556 
4557   s->apos.trType = TR_INTERPOLATE;
4558   VectorCopy( ps->viewangles, s->apos.trBase );
4559 
4560   if( snap )
4561     SnapVector( s->apos.trBase );
4562 
4563   //TA: i need for other things :)
4564   //s->angles2[YAW] = ps->movementDir;
4565   s->time2 = ps->movementDir;
4566   s->legsAnim = ps->legsAnim;
4567   s->torsoAnim = ps->torsoAnim;
4568   s->clientNum = ps->clientNum;   // ET_PLAYER looks here instead of at number
4569                     // so corpses can also reference the proper config
4570   s->eFlags = ps->eFlags;
4571   if( ps->stats[STAT_HEALTH] <= 0 )
4572     s->eFlags |= EF_DEAD;
4573   else
4574     s->eFlags &= ~EF_DEAD;
4575 
4576   if( ps->stats[ STAT_STATE ] & SS_BLOBLOCKED )
4577     s->eFlags |= EF_BLOBLOCKED;
4578   else
4579     s->eFlags &= ~EF_BLOBLOCKED;
4580 
4581   if( ps->externalEvent )
4582   {
4583     s->event = ps->externalEvent;
4584     s->eventParm = ps->externalEventParm;
4585   }
4586   else if( ps->entityEventSequence < ps->eventSequence )
4587   {
4588     int   seq;
4589 
4590     if( ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS )
4591       ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS;
4592 
4593     seq = ps->entityEventSequence & ( MAX_PS_EVENTS - 1 );
4594     s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 );
4595     s->eventParm = ps->eventParms[ seq ];
4596     ps->entityEventSequence++;
4597   }
4598 
4599   s->weapon = ps->weapon;
4600   s->groundEntityNum = ps->groundEntityNum;
4601 
4602   //store items held and active items in otherEntityNum
4603   s->modelindex = 0;
4604   s->modelindex2 = 0;
4605   for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
4606   {
4607     if( BG_InventoryContainsUpgrade( i, ps->stats ) )
4608     {
4609       s->modelindex |= 1 << i;
4610 
4611       if( BG_UpgradeIsActive( i, ps->stats ) )
4612         s->modelindex2 |= 1 << i;
4613     }
4614   }
4615 
4616   //TA: use powerups field to store team/class info:
4617   s->powerups = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 );
4618 
4619   //TA: have to get the surfNormal thru somehow...
4620   VectorCopy( ps->grapplePoint, s->angles2 );
4621   if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
4622     s->eFlags |= EF_WALLCLIMBCEILING;
4623 
4624   s->loopSound = ps->loopSound;
4625   s->generic1 = ps->generic1;
4626 
4627   if( s->generic1 <= WPM_NONE || s->generic1 >= WPM_NUM_WEAPONMODES )
4628     s->generic1 = WPM_PRIMARY;
4629 }
4630 
4631 
4632 /*
4633 ========================
4634 BG_PlayerStateToEntityStateExtraPolate
4635 
4636 This is done after each set of usercmd_t on the server,
4637 and after local prediction on the client
4638 ========================
4639 */
BG_PlayerStateToEntityStateExtraPolate(playerState_t * ps,entityState_t * s,int time,qboolean snap)4640 void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap )
4641 {
4642   int     i;
4643 
4644   if( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR || ps->pm_type == PM_FREEZE )
4645     s->eType = ET_INVISIBLE;
4646   else if( ps->persistant[ PERS_TEAM ] == TEAM_SPECTATOR )
4647     s->eType = ET_INVISIBLE;
4648   else
4649     s->eType = ET_PLAYER;
4650 
4651   s->number = ps->clientNum;
4652 
4653   s->pos.trType = TR_LINEAR_STOP;
4654   VectorCopy( ps->origin, s->pos.trBase );
4655 
4656   if( snap )
4657     SnapVector( s->pos.trBase );
4658 
4659   // set the trDelta for flag direction and linear prediction
4660   VectorCopy( ps->velocity, s->pos.trDelta );
4661   // set the time for linear prediction
4662   s->pos.trTime = time;
4663   // set maximum extra polation time
4664   s->pos.trDuration = 50; // 1000 / sv_fps (default = 20)
4665 
4666   s->apos.trType = TR_INTERPOLATE;
4667   VectorCopy( ps->viewangles, s->apos.trBase );
4668   if( snap )
4669     SnapVector( s->apos.trBase );
4670 
4671   //TA: i need for other things :)
4672   //s->angles2[YAW] = ps->movementDir;
4673   s->time2 = ps->movementDir;
4674   s->legsAnim = ps->legsAnim;
4675   s->torsoAnim = ps->torsoAnim;
4676   s->clientNum = ps->clientNum;   // ET_PLAYER looks here instead of at number
4677                     // so corpses can also reference the proper config
4678   s->eFlags = ps->eFlags;
4679 
4680   if( ps->stats[STAT_HEALTH] <= 0 )
4681     s->eFlags |= EF_DEAD;
4682   else
4683     s->eFlags &= ~EF_DEAD;
4684 
4685   if( ps->stats[ STAT_STATE ] & SS_BLOBLOCKED )
4686     s->eFlags |= EF_BLOBLOCKED;
4687   else
4688     s->eFlags &= ~EF_BLOBLOCKED;
4689 
4690   if( ps->externalEvent )
4691   {
4692     s->event = ps->externalEvent;
4693     s->eventParm = ps->externalEventParm;
4694   }
4695   else if( ps->entityEventSequence < ps->eventSequence )
4696   {
4697     int   seq;
4698 
4699     if( ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS )
4700       ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS;
4701 
4702     seq = ps->entityEventSequence & ( MAX_PS_EVENTS - 1 );
4703     s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 );
4704     s->eventParm = ps->eventParms[ seq ];
4705     ps->entityEventSequence++;
4706   }
4707 
4708   s->weapon = ps->weapon;
4709   s->groundEntityNum = ps->groundEntityNum;
4710 
4711   //store items held and active items in otherEntityNum
4712   s->modelindex = 0;
4713   s->modelindex2 = 0;
4714 
4715   for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
4716   {
4717     if( BG_InventoryContainsUpgrade( i, ps->stats ) )
4718     {
4719       s->modelindex |= 1 << i;
4720 
4721       if( BG_UpgradeIsActive( i, ps->stats ) )
4722         s->modelindex2 |= 1 << i;
4723     }
4724   }
4725 
4726   //TA: use powerups field to store team/class info:
4727   s->powerups = ps->stats[ STAT_PTEAM ] | ( ps->stats[ STAT_PCLASS ] << 8 );
4728 
4729   //TA: have to get the surfNormal thru somehow...
4730   VectorCopy( ps->grapplePoint, s->angles2 );
4731   if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
4732     s->eFlags |= EF_WALLCLIMBCEILING;
4733 
4734   s->loopSound = ps->loopSound;
4735   s->generic1 = ps->generic1;
4736 
4737   if( s->generic1 <= WPM_NONE || s->generic1 >= WPM_NUM_WEAPONMODES )
4738     s->generic1 = WPM_PRIMARY;
4739 }
4740 
4741 /*
4742 ========================
4743 BG_UnpackAmmoArray
4744 
4745 Extract the ammo quantity from the array
4746 ========================
4747 */
BG_UnpackAmmoArray(int weapon,int psAmmo[],int psAmmo2[],int * ammo,int * clips)4748 void BG_UnpackAmmoArray( int weapon, int psAmmo[ ], int psAmmo2[ ], int *ammo, int *clips )
4749 {
4750   int   ammoarray[ 32 ];
4751   int   i;
4752 
4753   for( i = 0; i <= 15; i++ )
4754     ammoarray[ i ] = psAmmo[ i ];
4755 
4756   for( i = 16; i <= 31; i++ )
4757     ammoarray[ i ] = psAmmo2[ i - 16 ];
4758 
4759   if( ammo != NULL )
4760     *ammo = ammoarray[ weapon ] & 0x0FFF;
4761 
4762   if( clips != NULL )
4763     *clips = ( ammoarray[ weapon ] >> 12 ) & 0x0F;
4764 }
4765 
4766 /*
4767 ========================
4768 BG_PackAmmoArray
4769 
4770 Pack the ammo quantity into the array
4771 ========================
4772 */
BG_PackAmmoArray(int weapon,int psAmmo[],int psAmmo2[],int ammo,int clips)4773 void BG_PackAmmoArray( int weapon, int psAmmo[ ], int psAmmo2[ ], int ammo, int clips )
4774 {
4775   int   weaponvalue;
4776 
4777   weaponvalue = ammo | ( clips << 12 );
4778 
4779   if( weapon <= 15 )
4780     psAmmo[ weapon ] = weaponvalue;
4781   else if( weapon >= 16 )
4782     psAmmo2[ weapon - 16 ] = weaponvalue;
4783 }
4784 
4785 /*
4786 ========================
4787 BG_WeaponIsFull
4788 
4789 Check if a weapon has full ammo
4790 ========================
4791 */
BG_WeaponIsFull(weapon_t weapon,int stats[],int psAmmo[],int psAmmo2[])4792 qboolean BG_WeaponIsFull( weapon_t weapon, int stats[ ], int psAmmo[ ], int psAmmo2[ ] )
4793 {
4794   int maxAmmo, maxClips;
4795   int ammo, clips;
4796 
4797   BG_FindAmmoForWeapon( weapon, &maxAmmo, &maxClips );
4798   BG_UnpackAmmoArray( weapon, psAmmo, psAmmo2, &ammo, &clips );
4799 
4800   if( BG_InventoryContainsUpgrade( UP_BATTPACK, stats ) )
4801     maxAmmo = (int)( (float)maxAmmo * BATTPACK_MODIFIER );
4802 
4803   return ( maxAmmo == ammo ) && ( maxClips == clips );
4804 }
4805 
4806 /*
4807 ========================
4808 BG_AddWeaponToInventory
4809 
4810 Give a player a weapon
4811 ========================
4812 */
BG_AddWeaponToInventory(int weapon,int stats[])4813 void BG_AddWeaponToInventory( int weapon, int stats[ ] )
4814 {
4815   int  weaponList;
4816 
4817   weaponList = ( stats[ STAT_WEAPONS ] & 0x0000FFFF ) | ( ( stats[ STAT_WEAPONS2 ] << 16 ) & 0xFFFF0000 );
4818 
4819   weaponList |= ( 1 << weapon );
4820 
4821   stats[ STAT_WEAPONS ] = weaponList & 0x0000FFFF;
4822   stats[ STAT_WEAPONS2 ] = ( weaponList & 0xFFFF0000 ) >> 16;
4823 
4824   if( stats[ STAT_SLOTS ] & BG_FindSlotsForWeapon( weapon ) )
4825     Com_Printf( S_COLOR_YELLOW "WARNING: Held items conflict with weapon %d\n", weapon );
4826 
4827   stats[ STAT_SLOTS ] |= BG_FindSlotsForWeapon( weapon );
4828 }
4829 
4830 /*
4831 ========================
4832 BG_RemoveWeaponToInventory
4833 
4834 Take a weapon from a player
4835 ========================
4836 */
BG_RemoveWeaponFromInventory(int weapon,int stats[])4837 void BG_RemoveWeaponFromInventory( int weapon, int stats[ ] )
4838 {
4839   int  weaponList;
4840 
4841   weaponList = ( stats[ STAT_WEAPONS ] & 0x0000FFFF ) | ( ( stats[ STAT_WEAPONS2 ] << 16 ) & 0xFFFF0000 );
4842 
4843   weaponList &= ~( 1 << weapon );
4844 
4845   stats[ STAT_WEAPONS ] = weaponList & 0x0000FFFF;
4846   stats[ STAT_WEAPONS2 ] = ( weaponList & 0xFFFF0000 ) >> 16;
4847 
4848   stats[ STAT_SLOTS ] &= ~BG_FindSlotsForWeapon( weapon );
4849 }
4850 
4851 /*
4852 ========================
4853 BG_InventoryContainsWeapon
4854 
4855 Does the player hold a weapon?
4856 ========================
4857 */
BG_InventoryContainsWeapon(int weapon,int stats[])4858 qboolean BG_InventoryContainsWeapon( int weapon, int stats[ ] )
4859 {
4860   int  weaponList;
4861 
4862   weaponList = ( stats[ STAT_WEAPONS ] & 0x0000FFFF ) | ( ( stats[ STAT_WEAPONS2 ] << 16 ) & 0xFFFF0000 );
4863 
4864   return( weaponList & ( 1 << weapon ) );
4865 }
4866 
4867 /*
4868 ========================
4869 BG_AddUpgradeToInventory
4870 
4871 Give the player an upgrade
4872 ========================
4873 */
BG_AddUpgradeToInventory(int item,int stats[])4874 void BG_AddUpgradeToInventory( int item, int stats[ ] )
4875 {
4876   stats[ STAT_ITEMS ] |= ( 1 << item );
4877 
4878   if( stats[ STAT_SLOTS ] & BG_FindSlotsForUpgrade( item ) )
4879     Com_Printf( S_COLOR_YELLOW "WARNING: Held items conflict with upgrade %d\n", item );
4880 
4881   stats[ STAT_SLOTS ] |= BG_FindSlotsForUpgrade( item );
4882 }
4883 
4884 /*
4885 ========================
4886 BG_RemoveUpgradeFromInventory
4887 
4888 Take an upgrade from the player
4889 ========================
4890 */
BG_RemoveUpgradeFromInventory(int item,int stats[])4891 void BG_RemoveUpgradeFromInventory( int item, int stats[ ] )
4892 {
4893   stats[ STAT_ITEMS ] &= ~( 1 << item );
4894 
4895   stats[ STAT_SLOTS ] &= ~BG_FindSlotsForUpgrade( item );
4896 }
4897 
4898 /*
4899 ========================
4900 BG_InventoryContainsUpgrade
4901 
4902 Does the player hold an upgrade?
4903 ========================
4904 */
BG_InventoryContainsUpgrade(int item,int stats[])4905 qboolean BG_InventoryContainsUpgrade( int item, int stats[ ] )
4906 {
4907   return( stats[ STAT_ITEMS ] & ( 1 << item ) );
4908 }
4909 
4910 /*
4911 ========================
4912 BG_ActivateUpgrade
4913 
4914 Activates an upgrade
4915 ========================
4916 */
BG_ActivateUpgrade(int item,int stats[])4917 void BG_ActivateUpgrade( int item, int stats[ ] )
4918 {
4919   stats[ STAT_ACTIVEITEMS ] |= ( 1 << item );
4920 }
4921 
4922 /*
4923 ========================
4924 BG_DeactivateUpgrade
4925 
4926 Deactivates an upgrade
4927 ========================
4928 */
BG_DeactivateUpgrade(int item,int stats[])4929 void BG_DeactivateUpgrade( int item, int stats[ ] )
4930 {
4931   stats[ STAT_ACTIVEITEMS ] &= ~( 1 << item );
4932 }
4933 
4934 /*
4935 ========================
4936 BG_UpgradeIsActive
4937 
4938 Is this upgrade active?
4939 ========================
4940 */
BG_UpgradeIsActive(int item,int stats[])4941 qboolean BG_UpgradeIsActive( int item, int stats[ ] )
4942 {
4943   return( stats[ STAT_ACTIVEITEMS ] & ( 1 << item ) );
4944 }
4945 
4946 /*
4947 ===============
4948 BG_RotateAxis
4949 
4950 Shared axis rotation function
4951 ===============
4952 */
BG_RotateAxis(vec3_t surfNormal,vec3_t inAxis[3],vec3_t outAxis[3],qboolean inverse,qboolean ceiling)4953 qboolean BG_RotateAxis( vec3_t surfNormal, vec3_t inAxis[ 3 ],
4954                         vec3_t outAxis[ 3 ], qboolean inverse, qboolean ceiling )
4955 {
4956   vec3_t  refNormal = { 0.0f, 0.0f, 1.0f };
4957   vec3_t  ceilingNormal = { 0.0f, 0.0f, -1.0f };
4958   vec3_t  localNormal, xNormal;
4959   float   rotAngle;
4960 
4961   //the grapplePoint being a surfNormal rotation Normal hack... see above :)
4962   if( ceiling )
4963   {
4964     VectorCopy( ceilingNormal, localNormal );
4965     VectorCopy( surfNormal, xNormal );
4966   }
4967   else
4968   {
4969     //cross the reference normal and the surface normal to get the rotation axis
4970     VectorCopy( surfNormal, localNormal );
4971     CrossProduct( localNormal, refNormal, xNormal );
4972     VectorNormalize( xNormal );
4973   }
4974 
4975   //can't rotate with no rotation vector
4976   if( VectorLength( xNormal ) != 0.0f )
4977   {
4978     rotAngle = RAD2DEG( acos( DotProduct( localNormal, refNormal ) ) );
4979 
4980     if( inverse )
4981       rotAngle = -rotAngle;
4982 
4983     AngleNormalize180( rotAngle );
4984 
4985     //hmmm could get away with only one rotation and some clever stuff later... but i'm lazy
4986     RotatePointAroundVector( outAxis[ 0 ], xNormal, inAxis[ 0 ], -rotAngle );
4987     RotatePointAroundVector( outAxis[ 1 ], xNormal, inAxis[ 1 ], -rotAngle );
4988     RotatePointAroundVector( outAxis[ 2 ], xNormal, inAxis[ 2 ], -rotAngle );
4989   }
4990   else
4991     return qfalse;
4992 
4993   return qtrue;
4994 }
4995 
4996 /*
4997 ===============
4998 BG_PositionBuildableRelativeToPlayer
4999 
5000 Find a place to build a buildable
5001 ===============
5002 */
BG_PositionBuildableRelativeToPlayer(const playerState_t * ps,const vec3_t mins,const vec3_t maxs,void (* trace)(trace_t *,const vec3_t,const vec3_t,const vec3_t,const vec3_t,int,int),vec3_t outOrigin,vec3_t outAngles,trace_t * tr)5003 void BG_PositionBuildableRelativeToPlayer( const playerState_t *ps,
5004                                            const vec3_t mins, const vec3_t maxs,
5005                                            void (*trace)( trace_t *, const vec3_t, const vec3_t,
5006                                                           const vec3_t, const vec3_t, int, int ),
5007                                            vec3_t outOrigin, vec3_t outAngles, trace_t *tr )
5008 {
5009   vec3_t  forward, entityOrigin, targetOrigin;
5010   vec3_t  angles, playerOrigin, playerNormal;
5011   float   buildDist;
5012 
5013   if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBING )
5014   {
5015     if( ps->stats[ STAT_STATE ] & SS_WALLCLIMBINGCEILING )
5016       VectorSet( playerNormal, 0.0f, 0.0f, -1.0f );
5017     else
5018       VectorCopy( ps->grapplePoint, playerNormal );
5019   }
5020   else
5021     VectorSet( playerNormal, 0.0f, 0.0f, 1.0f );
5022 
5023   VectorCopy( ps->viewangles, angles );
5024   VectorCopy( ps->origin, playerOrigin );
5025   buildDist = BG_FindBuildDistForClass( ps->stats[ STAT_PCLASS ] );
5026 
5027   AngleVectors( angles, forward, NULL, NULL );
5028   ProjectPointOnPlane( forward, forward, playerNormal );
5029   VectorNormalize( forward );
5030 
5031   VectorMA( playerOrigin, buildDist, forward, entityOrigin );
5032 
5033   VectorCopy( entityOrigin, targetOrigin );
5034 
5035   //so buildings can be placed facing slopes
5036   VectorMA( entityOrigin, 32, playerNormal, entityOrigin );
5037 
5038   //so buildings drop to floor
5039   VectorMA( targetOrigin, -128, playerNormal, targetOrigin );
5040 
5041   (*trace)( tr, entityOrigin, mins, maxs, targetOrigin, ps->clientNum, MASK_PLAYERSOLID );
5042   VectorCopy( tr->endpos, entityOrigin );
5043   VectorMA( entityOrigin, 0.1f, playerNormal, outOrigin );
5044   vectoangles( forward, outAngles );
5045 }
5046 
5047 /*
5048 ===============
5049 BG_GetValueOfHuman
5050 
5051 Returns the kills value of some human player
5052 ===============
5053 */
BG_GetValueOfHuman(playerState_t * ps)5054 int BG_GetValueOfHuman( playerState_t *ps )
5055 {
5056   int     i, worth = 0;
5057   float   portion;
5058 
5059   for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
5060   {
5061     if( BG_InventoryContainsUpgrade( i, ps->stats ) )
5062       worth += BG_FindPriceForUpgrade( i );
5063   }
5064 
5065   for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )
5066   {
5067     if( BG_InventoryContainsWeapon( i, ps->stats ) )
5068       worth += BG_FindPriceForWeapon( i );
5069   }
5070 
5071   portion = worth / (float)HUMAN_MAXED;
5072 
5073   if( portion < 0.01f )
5074     portion = 0.01f;
5075   else if( portion > 1.0f )
5076     portion = 1.0f;
5077 
5078   return ceil( ALIEN_MAX_SINGLE_KILLS * portion );
5079 }
5080 
5081 /*
5082 ===============
5083 atof_neg
5084 
5085 atof with an allowance for negative values
5086 ===============
5087 */
atof_neg(char * token,qboolean allowNegative)5088 float atof_neg( char *token, qboolean allowNegative )
5089 {
5090   float value;
5091 
5092   value = atof( token );
5093 
5094   if( !allowNegative && value < 0.0f )
5095     value = 1.0f;
5096 
5097   return value;
5098 }
5099 
5100 /*
5101 ===============
5102 atoi_neg
5103 
5104 atoi with an allowance for negative values
5105 ===============
5106 */
atoi_neg(char * token,qboolean allowNegative)5107 int atoi_neg( char *token, qboolean allowNegative )
5108 {
5109   int value;
5110 
5111   value = atoi( token );
5112 
5113   if( !allowNegative && value < 0 )
5114     value = 1;
5115 
5116   return value;
5117 }
5118 
5119 /*
5120 ===============
5121 BG_ParseCSVEquipmentList
5122 ===============
5123 */
BG_ParseCSVEquipmentList(const char * string,weapon_t * weapons,int weaponsSize,upgrade_t * upgrades,int upgradesSize)5124 void BG_ParseCSVEquipmentList( const char *string, weapon_t *weapons, int weaponsSize,
5125     upgrade_t *upgrades, int upgradesSize )
5126 {
5127   char      buffer[ MAX_STRING_CHARS ];
5128   int       i = 0, j = 0;
5129   char      *p, *q;
5130   qboolean  EOS = qfalse;
5131 
5132   Q_strncpyz( buffer, string, MAX_STRING_CHARS );
5133 
5134   p = q = buffer;
5135 
5136   while( *p != '\0' )
5137   {
5138     //skip to first , or EOS
5139     while( *p != ',' && *p != '\0' )
5140       p++;
5141 
5142     if( *p == '\0' )
5143       EOS = qtrue;
5144 
5145     *p = '\0';
5146 
5147     //strip leading whitespace
5148     while( *q == ' ' )
5149       q++;
5150 
5151     if( weaponsSize )
5152       weapons[ i ] = BG_FindWeaponNumForName( q );
5153 
5154     if( upgradesSize )
5155       upgrades[ j ] = BG_FindUpgradeNumForName( q );
5156 
5157     if( weaponsSize && weapons[ i ] == WP_NONE &&
5158         upgradesSize && upgrades[ j ] == UP_NONE )
5159       Com_Printf( S_COLOR_YELLOW "WARNING: unknown equipment %s\n", q );
5160     else if( weaponsSize && weapons[ i ] != WP_NONE )
5161       i++;
5162     else if( upgradesSize && upgrades[ j ] != UP_NONE )
5163       j++;
5164 
5165     if( !EOS )
5166     {
5167       p++;
5168       q = p;
5169     }
5170     else
5171       break;
5172 
5173     if( i == ( weaponsSize - 1 ) || j == ( upgradesSize - 1 ) )
5174       break;
5175   }
5176 
5177   if( weaponsSize )
5178     weapons[ i ] = WP_NONE;
5179 
5180   if( upgradesSize )
5181     upgrades[ j ] = UP_NONE;
5182 }
5183 
5184 /*
5185 ===============
5186 BG_ParseCSVClassList
5187 ===============
5188 */
BG_ParseCSVClassList(const char * string,pClass_t * classes,int classesSize)5189 void BG_ParseCSVClassList( const char *string, pClass_t *classes, int classesSize )
5190 {
5191   char      buffer[ MAX_STRING_CHARS ];
5192   int       i = 0;
5193   char      *p, *q;
5194   qboolean  EOS = qfalse;
5195 
5196   Q_strncpyz( buffer, string, MAX_STRING_CHARS );
5197 
5198   p = q = buffer;
5199 
5200   while( *p != '\0' )
5201   {
5202     //skip to first , or EOS
5203     while( *p != ',' && *p != '\0' )
5204       p++;
5205 
5206     if( *p == '\0' )
5207       EOS = qtrue;
5208 
5209     *p = '\0';
5210 
5211     //strip leading whitespace
5212     while( *q == ' ' )
5213       q++;
5214 
5215     classes[ i ] = BG_FindClassNumForName( q );
5216 
5217     if( classes[ i ] == PCL_NONE )
5218       Com_Printf( S_COLOR_YELLOW "WARNING: unknown class %s\n", q );
5219     else
5220       i++;
5221 
5222     if( !EOS )
5223     {
5224       p++;
5225       q = p;
5226     }
5227     else
5228       break;
5229   }
5230 
5231   classes[ i ] = PCL_NONE;
5232 }
5233 
5234 /*
5235 ===============
5236 BG_ParseCSVBuildableList
5237 ===============
5238 */
BG_ParseCSVBuildableList(const char * string,buildable_t * buildables,int buildablesSize)5239 void BG_ParseCSVBuildableList( const char *string, buildable_t *buildables, int buildablesSize )
5240 {
5241   char      buffer[ MAX_STRING_CHARS ];
5242   int       i = 0;
5243   char      *p, *q;
5244   qboolean  EOS = qfalse;
5245 
5246   Q_strncpyz( buffer, string, MAX_STRING_CHARS );
5247 
5248   p = q = buffer;
5249 
5250   while( *p != '\0' )
5251   {
5252     //skip to first , or EOS
5253     while( *p != ',' && *p != '\0' )
5254       p++;
5255 
5256     if( *p == '\0' )
5257       EOS = qtrue;
5258 
5259     *p = '\0';
5260 
5261     //strip leading whitespace
5262     while( *q == ' ' )
5263       q++;
5264 
5265     buildables[ i ] = BG_FindClassNumForName( q );
5266 
5267     if( buildables[ i ] == BA_NONE )
5268       Com_Printf( S_COLOR_YELLOW "WARNING: unknown buildable %s\n", q );
5269     else
5270       i++;
5271 
5272     if( !EOS )
5273     {
5274       p++;
5275       q = p;
5276     }
5277     else
5278       break;
5279   }
5280 
5281   buildables[ i ] = BA_NONE;
5282 }
5283 
5284 /*
5285 ============
5286 BG_UpgradeClassAvailable
5287 ============
5288 */
BG_UpgradeClassAvailable(playerState_t * ps)5289 qboolean BG_UpgradeClassAvailable( playerState_t *ps )
5290 {
5291   int     i;
5292   char    buffer[ MAX_STRING_CHARS ];
5293   stage_t currentStage;
5294 
5295   trap_Cvar_VariableStringBuffer( "g_alienStage", buffer, MAX_STRING_CHARS );
5296   currentStage = atoi( buffer );
5297 
5298   for( i = PCL_NONE + 1; i < PCL_NUM_CLASSES; i++ )
5299   {
5300     if( BG_ClassCanEvolveFromTo( ps->stats[ STAT_PCLASS ], i,
5301             ps->persistant[ PERS_CREDIT ], 0 ) >= 0 &&
5302         BG_FindStagesForClass( i, currentStage ) &&
5303         BG_ClassIsAllowed( i ) )
5304     {
5305       return qtrue;
5306     }
5307   }
5308 
5309   return qfalse;
5310 }
5311 
5312 typedef struct gameElements_s
5313 {
5314   buildable_t       buildables[ BA_NUM_BUILDABLES ];
5315   pClass_t          classes[ PCL_NUM_CLASSES ];
5316   weapon_t          weapons[ WP_NUM_WEAPONS ];
5317   upgrade_t         upgrades[ UP_NUM_UPGRADES ];
5318 } gameElements_t;
5319 
5320 static gameElements_t bg_disabledGameElements;
5321 
5322 /*
5323 ============
5324 BG_InitAllowedGameElements
5325 ============
5326 */
BG_InitAllowedGameElements(void)5327 void BG_InitAllowedGameElements( void )
5328 {
5329   char cvar[ MAX_CVAR_VALUE_STRING ];
5330 
5331   trap_Cvar_VariableStringBuffer( "g_disabledEquipment",
5332       cvar, MAX_CVAR_VALUE_STRING );
5333 
5334   BG_ParseCSVEquipmentList( cvar,
5335       bg_disabledGameElements.weapons, WP_NUM_WEAPONS,
5336       bg_disabledGameElements.upgrades, UP_NUM_UPGRADES );
5337 
5338   trap_Cvar_VariableStringBuffer( "g_disabledClasses",
5339       cvar, MAX_CVAR_VALUE_STRING );
5340 
5341   BG_ParseCSVClassList( cvar,
5342       bg_disabledGameElements.classes, PCL_NUM_CLASSES );
5343 
5344   trap_Cvar_VariableStringBuffer( "g_disabledBuildables",
5345       cvar, MAX_CVAR_VALUE_STRING );
5346 
5347   BG_ParseCSVBuildableList( cvar,
5348       bg_disabledGameElements.buildables, BA_NUM_BUILDABLES );
5349 }
5350 
5351 /*
5352 ============
5353 BG_WeaponIsAllowed
5354 ============
5355 */
BG_WeaponIsAllowed(weapon_t weapon)5356 qboolean BG_WeaponIsAllowed( weapon_t weapon )
5357 {
5358   int i;
5359 
5360   for( i = 0; i < WP_NUM_WEAPONS &&
5361       bg_disabledGameElements.weapons[ i ] != WP_NONE; i++ )
5362   {
5363     if( bg_disabledGameElements.weapons[ i ] == weapon )
5364       return qfalse;
5365   }
5366 
5367   return qtrue;
5368 }
5369 
5370 /*
5371 ============
5372 BG_UpgradeIsAllowed
5373 ============
5374 */
BG_UpgradeIsAllowed(upgrade_t upgrade)5375 qboolean BG_UpgradeIsAllowed( upgrade_t upgrade )
5376 {
5377   int i;
5378 
5379   for( i = 0; i < UP_NUM_UPGRADES &&
5380       bg_disabledGameElements.upgrades[ i ] != UP_NONE; i++ )
5381   {
5382     if( bg_disabledGameElements.upgrades[ i ] == upgrade )
5383       return qfalse;
5384   }
5385 
5386   return qtrue;
5387 }
5388 
5389 /*
5390 ============
5391 BG_ClassIsAllowed
5392 ============
5393 */
BG_ClassIsAllowed(pClass_t class)5394 qboolean BG_ClassIsAllowed( pClass_t class )
5395 {
5396   int i;
5397 
5398   for( i = 0; i < PCL_NUM_CLASSES &&
5399       bg_disabledGameElements.classes[ i ] != PCL_NONE; i++ )
5400   {
5401     if( bg_disabledGameElements.classes[ i ] == class )
5402       return qfalse;
5403   }
5404 
5405   return qtrue;
5406 }
5407 
5408 /*
5409 ============
5410 BG_BuildableIsAllowed
5411 ============
5412 */
BG_BuildableIsAllowed(buildable_t buildable)5413 qboolean BG_BuildableIsAllowed( buildable_t buildable )
5414 {
5415   int i;
5416 
5417   for( i = 0; i < BA_NUM_BUILDABLES &&
5418       bg_disabledGameElements.buildables[ i ] != BA_NONE; i++ )
5419   {
5420     if( bg_disabledGameElements.buildables[ i ] == buildable )
5421       return qfalse;
5422   }
5423 
5424   return qtrue;
5425 }
5426