1 /*
2  * Shotgun Debugger
3  * Copyright 2005 Game Creation Society
4  *
5  * Programmed by Matt Sarnoff
6  * http://www.contrib.andrew.cmu.edu/~msarnoff
7  * http://www.gamecreation.org
8  *
9  * objects.h - header file for object routines
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  * MD2 model loader by DigiBen, www.gametutorials.com. Adapted from his code.
26  * The MD2 model format is copyright id software, inc.
27  */
28 
29 #ifndef _OBJECTS_H_
30 #define _OBJECTS_H_
31 
32 #include "sdb.h"
33 
34 // Types of all objects
35 enum OBJECT_TYPES {
36 
37 ENT_PLAYER, ENT_BOX, ENT_BARREL, ENT_STEEL_CRATE, ENT_MISC1, ENT_MISC2, ENT_MISC3, ENT_MISC4, ENT_MISC5,
38 ENT_UNARMED_GUARD, ENT_MIB, ENT_ARMED_DRONE, ENT_HUNTER, ENT_GLADIATOR,
39 ENT_TURRET1, ENT_SLAVE_TURRET, ENT_EMISC1,
40 ENT_EMISC2, ENT_EMISC3, ENT_EMISC4, ENT_EMISC5,
41 
42 POWERUP_HEALTH, POWERUP_SHOTGUN_AMMO, POWERUP_ENERGY_CLIP,
43 POWERUP_HEPA_CLIP, POWERUP_LASER_CELL, POWERUP_GRENADE, POWERUP_ESG_BATTERY,
44 POWERUP_KEY1, POWERUP_KEY2, POWERUP_KEY3, WEAPON_RIFLE,
45 WEAPON_SHOTGUN, WEAPON_HEPA, WEAPON_RED_LASER, WEAPON_ESG,
46 
47 EXPLODER, BLT_LASER,
48 
49 PART_PARTICLE, PART_PARTICLE_BLOOD, PART_PARTICLE_SLIME, PART_PARTICLE_SPARK, PART_PARTICLE_ENERGY,
50 PART_PARTICLE_WOOD, PART_PARTICLE_METAL, PART_PARTICLE_GLOW, PART_HEPA_TRAIL, PART_HEPA_EXPLOSION, PART_HEPA_SPARK, PART_GRENADE_TRAIL,
51 PART_LASER_SPARK1, PART_LASER_SPARK2, PART_ESG_SHOCKWAVE,
52 PART_BIT,
53 PART_MF_RIFLE, PART_MF_SHOTGUN,
54 PART_RIFLE_SHELL, PART_SHOTGUN_SHELL,
55 PART_EXPLOSION, PART_EXPLOSIONPART,
56 PART_SMOKE,
57 
58 
59 BLT_RIFLE, BLT_SHOTGUN, BLT_HEPA, BLT_GRENADE, BLT_SHRAPNEL, BLT_BLASTER,
60 
61 ESG_EXPLODER,
62 NUM_OBJ_TYPES};
63 #define MAX_ENT     38
64 //#define MAX_POWERUP 24
65 #define MAX_PART    7
66 
67 #define IS_ENEMY(x)   (x >= ENT_UNARMED_GUARD && x <= ENT_SLAVE_TURRET)
68 #define IS_POWERUP(x) (x >= POWERUP_HEALTH   && x <= WEAPON_ESG)
69 #define IS_WEAPON(x)  (x >= WEAPON_RIFLE && x <= WEAPON_ESG)
70 #define IS_BULLET(x)  (x >= BLT_RIFLE        && x <= BLT_BLASTER)
71 #define POWERUP_HEALTH_AMOUNT   25
72 
73 // Extra type definitions for particles
74 enum PARTICLE_TYPES {
75 P_PART_PARTICLE, P_PART_PARTICLE_BLOOD, P_PART_PARTICLE_SLIME, P_PART_PARTICLE_SPARK, P_PART_PARTICLE_ENERGY,
76 P_PART_PARTICLE_WOOD, P_PART_PARTICLE_METAL, P_PART_PARTICLE_GLOW, P_PART_HEPA_TRAIL,P_PART_HEPA_EXPLOSION,P_PART_HEPA_SPARK,P_PART_GRENADE_TRAIL,
77 P_PART_LASER_SPARK1, P_PART_LASER_SPARK2, P_PART_ESG_SHOCKWAVE,
78 P_PART_BIT,
79 P_PART_MF_RIFLE, P_PART_MF_SHOTGUN,
80 P_PART_RIFLE_SHELL, P_PART_SHOTGUN_SHELL,
81 P_PART_EXPLOSION, P_PART_EXPLOSIONPART,
82 P_PART_SMOKE,
83 
84 P_BLT_RIFLE, P_BLT_SHOTGUN, P_BLT_HEPA, P_BLT_GRENADE, P_BLT_SHRAPNEL, P_BLT_BLASTER,
85 P_ESG_EXPLODER,
86 NUM_PART_TYPES};
87 
88 // Extra type definitions for bullets
89 enum BULLET_TYPES {
90 B_BLT_RIFLE, B_BLT_SHOTGUN, B_BLT_HEPA, B_BLT_GRENADE, B_BLT_SHRAPNEL, B_BLT_BLASTER,
91 NUM_BLT_TYPES};
92 
93 // Laser types
94 enum LASER_TYPES {
95 L_STANDARD, L_CHARGED,
96 NUM_LASER_TYPES};
97 
98 // Death types
99 enum DEATH_TYPES { DEATH_NONE, DEATH_PLAYER, DEATH_SMALL_EXPLOSION, DEATH_EXPLOSION,
100 DEATH_HEPA_EXPLOSION, DEATH_GRENADE_EXPLOSION, DEATH_WOOD, DEATH_ROBOT, DEATH_GLADIATOR, DEATH_POWERUP, DEATH_ESG, NUM_DEATH_TYPES };
101 
102 enum ALERT_TYPES { ALERT_NONE, ALERT_TOUCH, ALERT_SHOT, ALERT_SHOCKWAVE };
103 
104 #define MAX_OBJ_SPRITES  32
105 #define NO_SPRITE        -1
106 #define NO_MODEL         -1
107 #define NO_ALERT         -1000
108 #define INF              -1
109 #define ANIM_FWD         1
110 #define ANIM_REV         -1
111 #define FORCE_RECT       true
112 #define FORCE_POLAR      false
113 #define HIT_NOTHING      0
114 #define HIT_DIE          1
115 #define HIT_STOP         2
116 #define HIT_BOUNCE       3
117 #define ANIM_BASE        false
118 #define ANIM_TRANSIENT   true
119 #define DAMAGE_SHOCKWAVE true
120 #define DAMAGE_BULLET    false
121 #define SHOCK_ESG        -10000.0
122 
123 #define NUM_KEYS         5
124 
125 #define JUMP_PAUSE_TIME          0.5
126 #define FALL_KILL_DELAY          2.0
127 #define PUSH_STRENGTH            0.5
128 #define TERMINAL_VELOCITY        100.0
129 #define WALL_COLLISION_THRESHOLD 20.0
130 #define WALL_DAMAGE_THRESHOLD    35.0
131 #define IMPACT_DAMAGE_FACTOR     10.0
132 #define IMPACT_STUN_FACTOR       33.0
133 #define GIB_THRESHOLD            -30.0
134 #define AUG_DAMAGE_SUPPRESSION   0.25
135 #define AUG_SPEED_INCREASE       1.4
136 
137 
138 
139 #define texQuad(texnum) glBindTexture(GL_TEXTURE_2D, textures[texnum]); \
140     glBegin(GL_QUADS); \
141     glTexCoord2f(0.0, 0.0); \
142     glVertex2f(-objType[type].spriteSize.c[X]/2, objType[type].spriteSize.c[Y]/2); \
143     glTexCoord2f(1.0, 0.0); \
144     glVertex2f(objType[type].spriteSize.c[X]/2, objType[type].spriteSize.c[Y]/2); \
145     glTexCoord2f(1.0, 1.0); \
146     glVertex2f(objType[type].spriteSize.c[X]/2, -objType[type].spriteSize.c[Y]/2); \
147     glTexCoord2f(0.0, 1.0); \
148     glVertex2f(-objType[type].spriteSize.c[X]/2, -objType[type].spriteSize.c[Y]/2); \
149     glEnd(); \
150 
151 #define texQuadSize(texnum,w,h) glBindTexture(GL_TEXTURE_2D, textures[texnum]); \
152     glBegin(GL_QUADS); \
153     glTexCoord2f(0.0, 0.0); \
154     glVertex2f(-w/2, h/2); \
155     glTexCoord2f(1.0, 0.0); \
156     glVertex2f(w/2, h/2); \
157     glTexCoord2f(1.0, 1.0); \
158     glVertex2f(w/2, -h/2); \
159     glTexCoord2f(0.0, 1.0); \
160     glVertex2f(-w/2, -h/2); \
161     glEnd(); \
162 
163 #define texQuadClip(texnum,width,offset) glBindTexture(GL_TEXTURE_2D, textures[texnum]); \
164     glBegin(GL_QUADS); \
165     glTexCoord2f(width*offset, 0.0); \
166     glVertex2f(-objType[type].spriteSize.c[X]/2, objType[type].spriteSize.c[Y]/2); \
167     glTexCoord2f(width*offset+offset, 0.0); \
168     glVertex2f(objType[type].spriteSize.c[X]/2, objType[type].spriteSize.c[Y]/2); \
169     glTexCoord2f(width*offset+offset, 1.0); \
170     glVertex2f(objType[type].spriteSize.c[X]/2, -objType[type].spriteSize.c[Y]/2); \
171     glTexCoord2f(width*offset, 1.0); \
172     glVertex2f(-objType[type].spriteSize.c[X]/2, -objType[type].spriteSize.c[Y]/2); \
173     glEnd(); \
174 
175 #define addWeapon(wepn,name,full) \
176     if (augmented) \
177       pickedUp = false; \
178     else if (wpn[wepn].addClipAmt() > 0 || !(weapons & (1 << wepn))) \
179       setMessage(name); \
180     else \
181     { \
182       setMessage(full); \
183       pickedUp = false; \
184     } \
185     weapons |= 1 << wepn; \
186 
187 #define addWeaponSwitch(wepn,name,full) \
188     if (augmented) \
189       pickedUp = false; \
190     else if (wpn[wepn].addClipAmt() > 0 || !(weapons & (1 << wepn))) \
191     { \
192       setMessage(name); \
193       currWeapon = wepn; \
194     } \
195     else \
196     { \
197       setMessage(full); \
198       pickedUp = false; \
199     } \
200     weapons |= 1 << wepn; \
201 
202 #define addAmmoPowerup(wepn,str,full) \
203     if (augmented) \
204       pickedUp = false; \
205     else if ((iAmt = wpn[wepn].addClipAmt()) > 0) \
206       setMessage(str, iAmt); \
207     else \
208     { \
209       setMessage(full); \
210       pickedUp = false; \
211     } \
212 
213 extern int oID;
214 
215 // Data for animation control
216 class Animation
217 {
218   public:
Animation()219     Animation() { reset(); }
Animation(int nf,float dl,int lp)220     Animation(int nf, float dl, int lp) { set(nf, dl, lp); }
define(int nf,float dl,int lp)221     void define(int nf, float dl, int lp) { numFrames = nf; delay = dl; loop = lp; }
set(int nf,float dl,int lp)222     void set(int nf, float dl, int lp) { define(nf, dl, lp); reset(); }
reset()223     void reset() { done = false; run = true; animTime = frame = numLoops = 0; stopAtFrame = -1; direction = ANIM_FWD; }
224     void update();
225 
NumFrames()226     int NumFrames() { return numFrames; }
Loops()227     int Loops() { return loop; }
isDone()228     bool isDone() { return done; }
Frame()229     int Frame() { return frame; }
Delay()230     float Delay() { return delay; }
Time()231     float Time() { return animTime; }
232 
setDelay(float dl)233     void setDelay(float dl) { delay = dl; }
setDirection(int dir)234     void setDirection(int dir) { direction = dir; }
freezeAtFrame(int f)235     void freezeAtFrame(int f) { stopAtFrame = f; }
236 
237   private:
238     int numFrames;
239     float delay;
240     int loop;
241     bool run;
242     bool done;
243 
244     float animTime;
245     int frame;
246     int numLoops;
247     int direction;
248     int stopAtFrame;
249 };
250 
251 class ModelAnimation
252 {
253   public:
ModelAnimation()254     ModelAnimation() { reset(); }
ModelAnimation(int mdl)255     ModelAnimation(int mdl) { set(mdl); }
reset()256     void reset() { model = baseAnim = transientAnim = 0; currAnim = false; currFrame = 0; nextFrame = 1; animTime = 0.0; speed = ANIMATION_SPEED; }
set(int mdl)257     void set(int mdl) { reset(); model = mdl; }
setSpeed(float s)258     void setSpeed(float s) { speed = s; }
259     void update();
260     void setAnimation(int val, bool loop);
inc()261     void inc() { currFrame++; nextFrame++; }
262     void draw();
263   //private:
264     int model;
265     int currFrame, nextFrame;
266     int baseAnim, transientAnim;
267     bool currAnim;
268     float animTime;
269     float speed;
270 };
271 
272 // A force vector, applied to the specified object for the specified
273 // length of time. Measured in my force units (essentially the newton
274 // in US units, because the game uses US units)
275 class Force
276 {
277   public:
Force()278     Force() { reset(); }
Force(int obj,float dur,float a,float b,bool mode)279     Force(int obj, float dur, float a, float b, bool mode) { set(obj,dur,a,b,mode); }
280     void set(int obj, float dur, float a, float b, bool mode);
reset()281     void reset() { forceTime = 0; active = false; destroyMe = false; }
282     void apply();
setActive(bool val)283     void setActive(bool val) {active = val;}
toBeDestroyed()284     bool toBeDestroyed() { return destroyMe; }
285   private:
286     int target;
287     float duration;
288     Vector2D force;
289     float forceTime;
290     bool active;
291     bool destroyMe;
292 };
293 
294 // An explosion shockwave.
295 class Shockwave
296 {
297   public:
Shockwave()298     Shockwave() { reset(); }
299 
300     // So much for Kate's syntax highlighting. I originally named "float otr" "float or"
301     // (for "outer radius") and was getting the weirdest syntax errors ("parse error before "||").
302     // I nearly screwed myself until I finally remembered that "or" is a C++ reserved word.
303     // That's why I changed it to "otr".
Shockwave(float x,float y,float ir,float irs,float otr,float ors,float dur,float frc,float hlth,bool ag)304     Shockwave(float x, float y, float ir, float irs, float otr, float ors, float dur, float frc, float hlth, bool ag)
305     { set(x, y, ir, irs, otr, ors, dur, frc, hlth, ag); }
306     void set(float x, float y, float ir, float irs, float otr, float ors, float dur, float frc, float hlth, bool ag);
307     void reset();
308     void update();
309     void draw();
310     bool detect(Vector2D p, float *resultForce, float *resultHealth);
PosX()311     float PosX() { return pos.c[X]; }
PosY()312     float PosY() { return pos.c[Y]; }
setActive(bool val)313     void setActive(bool val) { active = val; }
isActive()314     bool isActive() { return active; }
toBeDestroyed()315     bool toBeDestroyed() { return destroyMe; }
AffectGladiators()316     bool AffectGladiators() { return affectGladiators; }
317   private:
318     Vector2D pos;
319     float innerRad, outerRad;
320     float innerRadSpeed, outerRadSpeed;
321     float duration;
322     float force;
323     float health;
324     bool affectGladiators;
325     float shockTime;
326     bool active;
327     bool destroyMe;
328 };
329 
330 // A set of event-trigger flags.
331 // Value is 0 (do not take the action), 1 or -1 (take the action),
332 // or anywhere in between (analog input is allowed by some functions)
333 class ObjectEventTriggers
334 {
335   public:
ObjectEventTriggers()336     ObjectEventTriggers() { reset(); }
reset()337     void reset() { LR = FB = strafe = 0.0; jump = fire = grenade = reload = switchWpn = 0; }
setLR(float val)338     void setLR(float val) { LR = val; }
setFB(float val)339     void setFB(float val) { FB = val; }
setStrafe(float val)340     void setStrafe(float val) { strafe = val; }
setJump(int val)341     void setJump(int val) { jump = val; }
setFire(int val)342     void setFire(int val) { fire = val; }
setGrenade(int val)343     void setGrenade(int val) { grenade = val; }
setReload(int val)344     void setReload(int val) { reload = val; }
setSwitchWpn(int val)345     void setSwitchWpn(int val) { switchWpn = val; }
getLR()346     float getLR() { return LR; }
getFB()347     float getFB() { return FB; }
getStrafe()348     float getStrafe() { return strafe; }
getJump()349     int getJump() { return jump; }
getFire()350     int getFire() { return fire; }
getGrenade()351     int getGrenade() { return grenade; }
getReload()352     int getReload() { return reload; }
getSwitchWpn()353     int getSwitchWpn() { return switchWpn; }
354 
355   private:
356     float LR;      // turn left (-1) or right (+1)
357     float FB;      // move forward (+1) or backward (-1)
358     float strafe;  // strafe left (-1) or right (+1)
359     int jump;      // jump
360     int fire;      // fire current weapon
361     int grenade;   // throw grenade
362     int reload;    // reload current weapon
363     int switchWpn; // switch weapon
364 };
365 
366 // Specifications for an object. Different types of object
367 // (particle, etc.) may have an additional, more specific specification.
368 // ObjectType specifies basic information about movement, life, appearance, etc.
369 class ObjectType
370 {
371   public:
ObjectType()372     ObjectType() {}
ObjectType(float im,float iw,float ih,float ir,float imv,float ijv,float imtv,float ia,float ita,float hlth,int dth,bool cd,bool grav,bool shad)373     ObjectType(float im,float iw,float ih,float ir,float imv,float ijv,float imtv,float ia,float ita,float hlth,int dth,bool cd,bool grav,bool shad)
374     { set(im, iw, ih, ir, imv, ijv, imtv, ia, ita, hlth, dth, grav, shad, cd); }
375     void set(float im,float iw,float ih,float ir,float imv,float ijv,float imtv,float ia,float ita,float hlth,int dth,bool cd,bool grav,bool shad);
clearSprites()376     void clearSprites() { for (int i=0;i<MAX_OBJ_SPRITES;i++) sprites[i]=NO_SPRITE; }
377     void setSprites(int num, ...);
setModels(int mod1,int mod2)378     void setModels(int mod1, int mod2) { model1 = mod1; numModels = 1; if (mod2 != NO_MODEL) { model2 = mod2; numModels++; } }
379 
380     float mass;         // object mass (pounds)
381     Vector2D spriteSize;// sprite height and width (note that this may, and probably
382                         // will, exceed the dimensions of the actual object. An object's
383                         // real size is determined by the bounding-box parameter.
384     float boundRadius;  // bounding circle radius
385 
386     float maxVel;       // maximum velocity (feet per second)
387     float jumpVel;      // jump velocity (feet per second)
388     float maxTurnvel;   // maximum turn speed (radians per second)
389 
390     float accel;        // lateral acceleration rate (feet per second squared)
391     float turnAccel;    // turning acceleration rate (radians per second squared)
392 
393     bool collide;       // collision detection on/off?
394     bool gravAffect;    // is the object affected by gravity?
395     bool hasShadow;     // does the object have a shadow?
396 
397     float maxHealth;    // maximum health (-1 == indestructible)
398 
399     int deathType;      // death type
400 
401     // Possible appearances of this object.
402     // Each object type uses and controls these sprites in its own way.
403     int sprites[MAX_OBJ_SPRITES];
404 
405     int model1, model2;
406     int numModels;
407 };
408 
409 class ParticleType
410 {
411   public:
ParticleType()412     ParticleType() {}
ParticleType(float mrl,float mrs,float mrjs,float rv,float mrrv,float fs,float mrfs,float sf,float ss,float sst,int hb,bool gl,float acc,int anf,float ad,float mrad,int al)413     ParticleType(float mrl, float mrs, float mrjs, float rv, float mrrv, float fs, float mrfs, float sf, float ss, float sst, int hb, bool gl,
414              float acc, int anf, float ad, float mrad, int al)
415              { set(mrl, mrs, mrjs, rv, mrrv, fs, mrfs, sf, ss, sst, hb, gl, acc, anf, ad, mrad, al); }
416     void set(float mrl, float mrs, float mrjs, float rv, float mrrv, float fs, float mrfs, float sf, float ss, float sst, int hb, bool gl,
417              float acc, int anf, float ad, float mrad, int al);
418 
419     float maxRandAddedToLife;   // life, speed, and jump speed are both defined in
420     float maxRandAddedToSpeed;  // the ObjectType.
421     float maxRandAddedToJumpSpeed;
422     float minRotVel;            // minimum rotational velocity
423     float maxRandAddedToRotVel;
424     float minFadeSpeed;
425     float maxRandAddedToFadeSpeed;
426     float startFade;
427     float scaleSpeed;
428     float scaleStop;
429     int hitBehavior;
430     bool glow;
431     float accel;
432 
433     int animNumFrames;
434     float animDelay;
435     float maxRandAddedToAnimDelay;
436     int animLoop;
437 };
438 
439 class BulletType
440 {
441   public:
BulletType()442     BulletType() {}
BulletType(float dmg,float f)443     BulletType(float dmg, float f) { set(dmg, f); }
set(float dmg,float f)444     void set(float dmg, float f) { damage = dmg; impactForce = f; }
445 
446     float damage;
447     float impactForce;
448 };
449 
450 class LaserType
451 {
452   public:
LaserType()453     LaserType() {}
LaserType(int spr,float w,float mr,int mb,float dmg,float fs)454     LaserType(int spr, float w, float mr, int mb, float dmg, float fs) { set(spr, w, mr, mb, dmg, fs); }
set(int spr,float w,float mr,int mb,float dmg,float fs)455     void set(int spr, float w, float mr, int mb, float dmg, float fs)
456     { sprite = spr; width = w; maxRange = mr; maxBounces = mb; damage = dmg; fadeSpeed = fs; }
457 
458     int sprite;
459     float width;
460     float maxRange;
461     int maxBounces;
462     float damage;
463     float fadeSpeed;
464 };
465 
466 // Base class for objects.
467 class Object : public LevelObject
468 {
469   public:
Object()470     Object() { type = 0; pos.set(0,0); vel.set(0,0); reset(); respondTo1 = respondTo2 = 0; setID(); }
Object(int typ)471     Object(int typ) { type = typ; reset(); setID(); }
Object(int typ,float x,float y,float head,int rt1,int rt2,int tr,int tt)472     Object(int typ, float x, float y, float head, int rt1, int rt2, int tr, int tt) { setID(); set(typ, x, y, head, rt1, rt2, tr, tt); }
Object(int typ,float x,float y,float height,float head,int rt1,int rt2,int tr,int tt)473     Object(int typ, float x, float y, float height, float head, int rt1, int rt2, int tr, int tt) { setID(); set(typ, x, y, height, head, rt1, rt2, tr, tt); }
set(int typ,float x,float y,float head,int rt1,int rt2,int tr,int tt)474     void set(int typ, float x, float y, float head, int rt1, int rt2, int tr, int tt)
475     { type = typ; reset(); setStartPos(x,y); heading = origHeading = head; trigInit(tr, tt); respondTo1 = rt1; respondTo2 = rt2; fixed = false; augmented = false;  spr1 = spr2 = NO_SPRITE; }
set(int typ,float x,float y,float height,float head,int rt1,int rt2,int tr,int tt)476     void set(int typ, float x, float y, float height, float head, int rt1, int rt2, int tr, int tt)
477     { type = typ; reset(); setStartPos(x,y); h = height; heading = origHeading = head; trigInit(tr, tt); respondTo1 = rt1; respondTo2 = rt2; fixed = false; augmented = false; spr1 = spr2 = NO_SPRITE; }
478 
479     virtual void reset();
480     virtual void draw();
481     virtual void drawShadow();
482     virtual void update();
483 
484     static void resetIDCounter();
485     void setID();
setPos(float x,float y)486     void setPos(float x, float y) { pos.set(x, y); }
setStartPos(float x,float y)487     void setStartPos(float x, float y) { setPos(x, y); origPos.set(x,y); }
addPos(Vector2D v)488     void addPos(Vector2D v) { pos += v; }
setVel(float x,float y)489     void setVel(float x, float y) { vel.set(x, y); }
setHeight(float nh)490     void setHeight(float nh) { h = nh; }
setHeading(float nhead)491     void setHeading(float nhead) { heading = nhead; }
setLookAngle(float nangle)492     void setLookAngle(float nangle) { lookAngle = nangle; }
493     void turn(float amt);
setSpeed(float nspeed)494     void setSpeed(float nspeed) { speed = nspeed; }
setHVel(float nhvel)495     void setHVel(float nhvel) { hvel = nhvel; }
setTurnVel(float ntvel)496     void setTurnVel(float ntvel) { turnvel = ntvel; }
setActive(bool val)497     void setActive(bool val) { active = val; }
setHealth(int val)498     void setHealth(int val) { health = val; }
499     void setAnimation(int val, bool anim);
500     void changeVel(Vector2D v);
501     void changeForceVel(Vector2D v);
502     void changeForceVelNoMass(Vector2D v);
503 
setDirectionAlert(float ang,int typ)504     void setDirectionAlert(float ang, int typ) { dirAlert = ang; dirAlertType = typ; }
505     void changeHealth(float amt);
506     float changeHealthAmt(float amt);
507     void damage(float amt, bool by);
508     void stun(float amt);
509     void dyingCheck();
510 
511     void kill(bool death);
die(float delay)512     void die(float delay) { dying = true; dyingTimer = delay; }
513     void doDeath();
514 
Type()515     int Type() { return type; }
Pos()516     Vector2D Pos() { return pos; }
Vel()517     Vector2D Vel() { return vel; }
518 
ID()519     int ID() { return id; }
PosX()520     float PosX() { return pos.c[X]; }
PosY()521     float PosY() { return pos.c[Y]; }
Heading()522     float Heading() { return heading; }
LookAngle()523     float LookAngle() { return lookAngle; }
VelX()524     float VelX() { return vel.c[X]; }
VelY()525     float VelY() { return vel.c[Y]; }
Speed()526     float Speed() { return vel.mag(); }
Height()527     float Height() { return h; }
HVel()528     float HVel() { return hvel; }
Turnvel()529     float Turnvel() { return turnvel; }
Health()530     float Health() { return health; }
StunTimer()531     float StunTimer() { return stunTimer; }
Stunned()532     bool Stunned() { return stunTimer > 0; }
Dying()533     bool Dying() { return dying; }
Fixed()534     bool Fixed() { return fixed; }
Keys()535     int Keys() { return keys; }
isActive()536     bool isActive() { return active; }
toBeDestroyed()537     bool toBeDestroyed() { return destroyMe; }
Falling()538     bool Falling() { return fall; }
RespondTo1()539     int RespondTo1() { return respondTo1; }
RespondTo2()540     int RespondTo2() { return respondTo2; }
DirectionAlert()541     float DirectionAlert() { return dirAlert; }
DirectionAlertType()542     float DirectionAlertType() { return dirAlertType; }
State()543     int State() { return state; }
LastDamageAmount()544     float LastDamageAmount() { return lastDamageAmount; }
Augmented()545     bool Augmented() { return augmented; }
Augment()546     void Augment() { model[1].set(MDL_PLAYER_TORSO2); augmented = true; }
547 
Wpn()548     virtual Weapon* Wpn() {}
CurrWeapon()549     virtual int CurrWeapon() {}
selectWeapon(int wp)550     virtual void selectWeapon(int wp) {}
weaponState(int wp)551     virtual char weaponState(int wp) {}
keyState(int wp)552     virtual char keyState(int wp) {}
WeaponPoint()553     virtual Vector2D* WeaponPoint() {}
554 
giveKey(int key)555     void giveKey(int key) { keys |= 1 << key-1; }
givePowerup(int idx)556     virtual void givePowerup(int idx) {}
557 
resetCollided()558     void resetCollided() { collided = -1; }
setCollided(int with)559     void setCollided(int with) { collided = with; }
Collided()560     int Collided() { return collided; }
561 
resetShockCollisions()562     void resetShockCollisions() { shockCollisions = 0; }
ShockCollisions()563     long long int ShockCollisions() { return shockCollisions; }
564 
565     ObjectEventTriggers ev;
566 
nextAnimFrame()567     void nextAnimFrame() { model[0].inc(); model[1].inc(); }
CurrFrame()568     void CurrFrame() { printf("m1=(%d->%d) m2=(%d->%d)\n", model[0].currFrame+1, model[0].nextFrame+1, model[1].currFrame+1, model[1].nextFrame+1); }
setObjectCollisionDetectOnOff(bool s)569     void setObjectCollisionDetectOnOff(bool s) { collideWithObjects = s; }
570   protected:
571     void drawStart();
572     void drawEnd();
573 
574     void shockwaveCollisionDetect();
575     void laserCollisionDetect();
576     Wall* wallCollisionDetect(int cell, Vector2D *inter);
577     bool floorCollisionDetect(int cell, float *fric);
578     void surfaceCollisionDetect(int cell, float *fric, float *hlth);
579     void objectCollisionDetect(int cell);
CollideWithObjects()580     bool CollideWithObjects() { return collideWithObjects; }
581 
582     void levelCollisionDetection();
583 
584     int id;
585 
586     int type;         // object type (for lookup in the global objType table)
587     bool augmented;
588     bool collideWithObjects;
589 
590     Vector2D pos;     // position
591     float h;          // height
592 
593     Vector2D vel;     // x and y velocity components
594     Vector2D moveVel;
595     Vector2D forceVel;
596     float speed;      // lateral (x-y) speed (feet per second)
597     float jumpSpeed, jumpHeading, jumpStrafe, jumpPause;
598 
599     float hvel;       // height velocity
600 
601     float heading;    // heading
602     float lookAngle;  // direction the player is looking in (can be different from movement heading)
603     float turnvel;    // turning speed (radians per second)
604 
605     Vector2D origPos;
606     float origHeading;
607 
608     // The object can be comprised of two independently-controlled sprites
609     // displayed on top of each other. spr1 is the lower sprite, spr2 is the upper
610     // sprite.
611     int spr1, spr2;
612     Animation spr1Anim, spr2Anim;
613 
614     ModelAnimation model[2];
615     bool useModel;
616 
617     float health;       // health (dead at 0)
618     int keys;           // bitfield of keys this object owns
619 
620     // Whether an entity is fully alive or not
621     bool active;
622     bool dying;
623     bool damagedBy;
624     float lastDamageAmount;
625     float dyingTimer;
626 
627     bool fixed;
628 
629     // Set this flag to tell the "higher powers" to deallocate this object.
630     bool destroyMe;
631 
632     // Whether an object has just hit the ground
633     bool hitGround;
634 
635     bool surfaceHealthSound;
636 
637     // Whether we should let this object fall to its DEATH
638     bool fall;
639     float fallTimer;
640 
641     float stunTimer;
642 
643     int collided;
644     Uint64 shockCollisions; // bit-flags
645 
646     float dirAlert;
647     int dirAlertType;
648 
649     int respondTo1;
650     int respondTo2;
651 
652     float currSurfaceFriction;
653     float currSurfaceHealth;
654 
655     int state;
656 };
657 
658 // A static or moving entity (player, enemy, other object)
659 class Entity: public Object
660 {
661   public:
Entity()662     Entity() : Object() {}
Entity(int typ)663     Entity(int typ) : Object(typ) {}
Entity(int typ,float x,float y,float head,int st,bool fix,int rt1,int rt2,int tr,int tt,bool aug)664     Entity(int typ, float x, float y, float head, int st, bool fix, int rt1, int rt2, int tr, int tt, bool aug) : Object(typ, x, y, head, rt1, rt2, tr, tt) { fixed = fix; state = st; if (aug) Augment(); }
665     void reset();
666     void draw();
667     void update();
drawShadow()668     void drawShadow() { Object::drawShadow(); }
669 
670     void setPlayerAnimations();
671 
selectWeapon(int wp)672     void selectWeapon(int wp)
673     { if (HAS_WEAPON(weapons, wp)) currWeapon = wp; }
674     void selectNextWeapon();
675 
676     void givePowerup(int idx);
677 
CurrWeapon()678     int CurrWeapon() { return currWeapon; }
Wpn()679     Weapon* Wpn() { return &wpn[currWeapon]; }
WeaponPoint()680     Vector2D* WeaponPoint() { return &wpnPos[currWeapon]; }
681     char weaponState(int wp);
682     char keyState(int k);
683   private:
684     int weapons;
685     float grenadeThrowTimer;
686     bool throwGrenade;
687 
688     bool jumping;
689     bool jumpReady;
690 
691     bool walkSound;
692 
693     Weapon wpn[NUM_PLAYER_WEAPONS];
694     Vector2D wpnPos[NUM_PLAYER_WEAPONS];
695     int currWeapon;
696     bool switchReady;
697 };
698 
699 // A particle
700 class Particle: public Object
701 {
702   public:
Particle()703     Particle() : Object() { color.white(); }
Particle(int typ)704     Particle(int typ) : Object(typ) { initType(); }
Particle(int typ,float x,float y,float head)705     Particle(int typ, float x, float y, float head) : Object(typ, x, y, head, 0, 0, 0, 0) { initType(); }
Particle(int typ,float x,float y,float height,float head)706     Particle(int typ, float x, float y, float height, float head) : Object(typ, x, y, height, head, 0, 0, 0, 0) { initType(); }
initType()707     void initType() { pType = type - PART_PARTICLE; color.white(); }
708     void launch(int typ, float x, float y, float height, float head, float alph, int sprite);
709     void launch(int typ, float x, float y, float height, float head, float alph, int sprite, float r, float g, float b);
setSpeed(float s)710     void setSpeed(float s) { speed = s; }
711     void reset();
712     void draw();
713     void drawShadow();
714     void update();
715     void levelCollisionDetection();
716   protected:
717     int pType;
718     int bounceCount;
719     float rotation;
720     float rotVel;
721     float alpha;
722     float fadeSpeed;
723     float scale;
724 
725     float additionalSpeed;
726 
727     RGBAColor color;
728 
729     Animation anim;
730 
731 };
732 
733 // A bullet/projectile
734 class Bullet: public Particle
735 {
736   public:
Bullet()737     Bullet() : Particle() {}
Bullet(int own,int typ)738     Bullet(int own, int typ) : Particle(typ) { owner = own; bType = type - BLT_RIFLE; }
Bullet(int own,int typ,float x,float y,float head)739     Bullet(int own, int typ, float x, float y, float head) : Particle(typ, x, y, head) { owner = own; bType = type - BLT_RIFLE; }
Bullet(int own,int typ,float x,float y,float height,float head)740     Bullet(int own, int typ, float x, float y, float height, float head) : Particle(typ, x, y, height, head) { owner = own; bType = type - BLT_RIFLE; }
launch(int own,int typ,float x,float y,float height,float head)741     void launch(int own, int typ, float x, float y, float height, float head)
742     { frameDelay = 2; owner = own; bType = typ - BLT_RIFLE; Particle::launch(typ, x, y, height, head, 1.0, 0); }
743 
kill(bool death)744     void kill(bool death) { Object::kill(death); }
745 
BType()746     int BType() { return bType; }
747 
748     void update();
749 
Live()750     bool Live() { return frameDelay == 0; }
Owner()751     int Owner() { return owner; }
752   private:
753     int bType;
754     int owner;
755 
756     int frameDelay;
757 };
758 
759 class LaserBeam
760 {
761   public:
LaserBeam()762     LaserBeam() {}
763     LaserBeam(Vector2D np1, Vector2D np2);
764 
765     Vector2D p1, p2;
766     float angle;
767     float length;
768 };
769 
770 // LASER!
771 class Laser
772 {
773   public:
Laser()774     Laser() { active = destroyMe = false; live = 0; beams.clear(); }
775     void launch(int typ, float x, float y, float height, float head);
776     void draw();
777     void update();
Live()778     int Live() { return live; }
toBeDestroyed()779     bool toBeDestroyed() { return destroyMe; }
Type()780     int Type() { return type; }
781     vector<LaserBeam> beams;
782   private:
783     Wall* wallCollisionDetect(Vector2D pos, float head, float distLeft, Vector2D *inter);
784 
785     bool active;
786     int live;
787     bool destroyMe;
788 
789     int type;
790     float h;
791     float alpha;
792 };
793 
794 // Array of specification structures for all different types of objects.
795 extern ObjectType objType[NUM_OBJ_TYPES];
796 extern ParticleType partType[NUM_PART_TYPES];
797 extern BulletType bltType[NUM_BLT_TYPES];
798 extern LaserType lasType[NUM_LASER_TYPES];
799 void initObjectTypes();
800 
801 #endif
802