#include "../plugin.h" #define DEFAULTHUDNAME "ftehud.hud" #define MAX_ELEMENTS 128 int testvar; int testvar2; int testvar3; int testvar4; int K_UPARROW; int K_DOWNARROW; int K_LEFTARROW; int K_RIGHTARROW; int K_ESCAPE; int K_MOUSE1; int K_MOUSE2; int K_HOME; int K_SHIFT; int K_SPACE; int K_F1; int K_F2; #define texture qhandle_t #define bool qboolean float realtime; #define Sound_Start(x) void vecNorm(float *in, float *out) { float new; new = in[0] * in[0] + in[1] * in[1] + in[2]*in[2]; new = (float)sqrt(new); if (new == 0) out[0] = out[1] = out[2] = 0; else { new = 1/new; out[0] = in[0] * new; out[1] = in[1] * new; out[2] = in[2] * new; } } #if 0 #define MAXCANNONS 4 #define MAXBULLETS 256 #define MAXMONSTERS 256 #define ENEMYTYPES 10 #define SHOTLEVELS 10 #else enum { M_CANNON1, M_CANNON2, M_CANNON3, M_CANNON4, M_CANNON5, M_CANNON6, M_CANNON7, M_CANNON8, M_CANNON9, M_CANNON10, M_CANNON11, M_CANNON12, M_ROCKETL1 = 50, M_ROCKETL2, M_ROCKETL3, M_ROCKETL4, M_ROCKETL5, M_ROCKETL6, M_ROCKETL7, M_ROCKETL8, M_ROCKETL9, M_ROCKETL10, M_ROCKETL11, M_ROCKETL12, M_FORWARD = 100, M_DIAG, M_DIAG2, M_SIDE, MAXADDONS }; #define FIRSTCANNON M_CANNON1 #define LASTCANNON M_ROCKETL1-1 #define FIRSTROCKET M_ROCKETL1 #define LASTROCKET M_FORWARD-1 #define FIRSTCENTRALMOD M_FORWARD #define LASTCENTRALMOD MAXADDONS-1 int MAXBULLETS = 255; int MAXMONSTERS = 256; int MAXSQUADS = 256; int MAXROUTES = 64; int MAXROUTEPOINTS=10; #define ENEMYTYPES monsterpics #define SHOTLEVELS weaponlevels #endif #define CONT_LEFTKEY 1 #define CONT_RIGHTKEY 2 #define CONT_FIREKEY 4 #define CONT_UPKEY 8 #define CONT_DOWNKEY 16 #define CONT_MOUSE 32 //right mouse button pressed #define PLAYERSHIPSPEEDX 2 #define PLAYERSHIPSPEEDY 2 #define ENEMYSHIPSPEEDX (random()-0.5) #define ENEMYSHIPSPEEDY (random()*2+(float)1) #define PUP_SHRUNKEN 1 //one round only void SIRestartGame (void); float random(void); int SIlevel; char SILevelName[128]; int weaponlevels; int monsterpics; //Textures in structures are pointers to the texture number. This means we don't have to cycle through each one when we reload the textures. typedef struct SIEnemyType_s { texture *picture; float width; float height; int health; float FireProb; int reward; int number; int AI; int healthregen; int shotdamage; texture *shotpicture; } SIEnemyType_t; typedef struct SIRoute_s { int numpoints; vec3_t pos[1]; } SIRoute_t; typedef struct SISquad_s { int route; int type; int number; float interval; float time; float speed; } SISquad_t; typedef struct SIaddon_s { float xoff; float yoff; int power; float refire; float reloadtime; texture *tex; } SIaddon_t; typedef struct SIp_s { float x; float y; float width; float height; int cash; int health; int contols; int powerups; SIaddon_t cannon[MAXADDONS]; } SIp_t; typedef struct SImonster_s { float xpos; float ypos; float width; float height; int routenum; int destnum; float xvel; float yvel; int health; int timetoregen; SIEnemyType_t *EnemyType; } SImonster_t; typedef struct SIbullet_s { int type; int charge; float xpos; float ypos; float width; float height; float xvel; float yvel; float yaccel; qboolean inuse; int damage; float alpha; float alphachange; texture *tex; } SIbullet_t; typedef struct ShopRegion_s { float x; float y; float width; float height; char *text; texture *tex; qboolean (*AppearCondition) (int ident); void (*CallFunc) (int ident); texture *(*Texture) (texture *def, int ident); int ident; } ShopRegion_t; int notenoughcash; SIRoute_t *SIRoute; SISquad_t *SISquad; SIEnemyType_t *SIEnemyType; SIp_t SIp; SImonster_t *SImonster; SIbullet_t *SIbullet; SIbullet_t *SIweapons; //prototypes qboolean SIShop; qboolean lastlevel; float deadtime; float leveltime; int livingmonsters; texture SIplayertexture; //both texture *SIbaddietexture; //game only texture *SIbullettexture; //game only texture SIexplosiontexture; //game only texture SIhealthtexture; //shop only texture SIleaveshoptexture; //shop only texture SIshrinktexture; //shop only texture SIcannontexture; //game+shop texture SIsideshottexture; //shop only texture SIrapidtexture; texture SIsavegametexture; texture SIloadgametexture; texture SIquittexture; /* sound SoundWin; sound SoundLoose; sound SoundFire; sound SoundExplosion; sound SoundHit; //when we don't kill */ void SISPHealth (int ident) { if (SIp.health >= 9) return; if (SIp.cash < 250) { notenoughcash = 250; return; } SIp.health++; SIp.cash -= 250; } qboolean SISPHealthThere (int ident) { if (SIp.health < 9) return true; return false; } void SISPUpgrade1 (int ident) { if (SIp.cannon[M_FORWARD].power >= weaponlevels-1) return; if (SIp.cash < 500) { notenoughcash = 250; return; } SIp.cannon[M_FORWARD].power++; SIp.cash -= 500; } texture *SISPUpgrade1Texture (texture *def, int ident) { return &SIbullettexture[SIp.cannon[M_FORWARD].power+1]; } qboolean SISPUpgrade1There (int ident) { if (SIp.cannon[M_FORWARD].power < weaponlevels-1) return true; return false; } void SISPShrink (int ident) { if (SIp.powerups & PUP_SHRUNKEN) //can't reshrink return; if (SIp.cash < 100) { notenoughcash = 250; return; } SIp.powerups |= PUP_SHRUNKEN; SIp.cash -= 100; } bool SISPShrinkThere (int ident) { if (SIp.powerups & PUP_SHRUNKEN) return false; return true; } void SISPCannon (int ident) { int a; if (SIp.cash < 1500) { notenoughcash = 250; return; } for (a = FIRSTCANNON; a <= LASTCANNON; a++) { if (SIp.cannon[a].power == 0) { SIp.cannon[a].tex = &SIcannontexture; SIp.cannon[a].power = 1; SIp.cash -= 1500; return; } } } bool SISPCannonThere (int ident) { int a; for (a = FIRSTCANNON; a <= LASTCANNON; a++) { if (SIp.cannon[a].power == 0) { return true; } } return false; } texture *SISPCannonUpgradeTexture (texture *def, int ident) { return &SIbullettexture[SIp.cannon[ident].power]; } void SISPCannonUpgrade(int ident) { if (SIp.cannon[ident].power >= weaponlevels) return; if (SIp.cash < 600) { notenoughcash = 250; return; } SIp.cannon[ident].power++; SIp.cash -= 600; } bool SISPCannonUpgradeThere(int ident) { if (SIp.cannon[ident].power >= weaponlevels || SIp.cannon[ident].power <= 0) return false; return true; } void SISPCannonBoost(int ident) { if (SIp.cannon[ident].reloadtime <= 0.1f) return; if (SIp.cash < 600) { notenoughcash = 250; return; } SIp.cannon[ident].reloadtime -= 0.1f; SIp.cash -= 600; } bool SISPCannonBoostThere(int ident) { if (SIp.cannon[ident].reloadtime <= 0.1f || SIp.cannon[ident].power <= 0) return false; return true; } void SISPRocket (int ident) { int a; if (SIp.cash < 1500) { notenoughcash = 250; return; } for (a = FIRSTROCKET; a <= LASTROCKET; a++) { if (SIp.cannon[a].power == 0) { SIp.cannon[a].tex = &SIcannontexture; SIp.cannon[a].power = 1; SIp.cash -= 1500; return; } } } bool SISPRocketThere (int ident) { int a; for (a = FIRSTROCKET; a <= LASTROCKET; a++) { if (SIp.cannon[a].power == 0) { return true; } } return false; } texture *SISPSideBurstTexture (texture *def, int ident) { return &SIbullettexture[SIp.cannon[M_SIDE].power]; } void SISPSideBurst (int ident) { if (SIp.cannon[M_SIDE].power >= weaponlevels) return; if (SIp.cash < 1000) { notenoughcash = 250; return; } SIp.cash -= 1000; SIp.cannon[M_SIDE].power+=1; } bool SISPSideBurstThere (int ident) { if (SIp.cannon[M_SIDE].power >= weaponlevels) return false; return true; } void SISPRapidFire (int ident) { if (SIp.cannon[M_FORWARD].reloadtime <= 0.1) return; if (SIp.cash < 250) { notenoughcash = 250; return; } SIp.cash -= 250; SIp.cannon[M_FORWARD].reloadtime -= 0.1f; } bool SISPRapidFireThere (int ident) { if (SIp.cannon[M_FORWARD].reloadtime <= 0.1) return false; return true; } void NextLevel (void); void LeaveShop (int ident) { NextLevel(); } bool gamesaved = 2; void SISaveGame(int ident) { int a; texture handle; FS_Open("spaceinv/spaceinv.sav", &handle, 2); FS_Write(handle, &SIp.cash, sizeof(SIp.cash)); FS_Write(handle, &SIp.powerups, sizeof(SIp.powerups)); FS_Write(handle, &SIp.health, sizeof(SIp.health)); FS_Write(handle, &SIlevel, sizeof(SIlevel)); for (a = 0; a < MAXADDONS; a++) { FS_Write(handle, &SIp.cannon[a].power, sizeof(SIp.cannon[a].power)); FS_Write(handle, &SIp.cannon[a].reloadtime, sizeof(SIp.cannon[a].reloadtime)); } FS_Close(handle); gamesaved = true; } void SILoadGame(int ident) { int a; int len; texture handle; len = FS_Open("spaceinv/spaceinv.sav", &handle, 1); if (len < 0) return; FS_Read(handle, &SIp.cash, sizeof(SIp.cash)); FS_Read(handle, &SIp.powerups, sizeof(SIp.powerups)); FS_Read(handle, &SIp.health, sizeof(SIp.health)); FS_Read(handle, &SIlevel, sizeof(SIlevel)); for (a = 0; a < MAXADDONS; a++) { FS_Read(handle, &SIp.cannon[a].power, sizeof(SIp.cannon[a].power)); FS_Read(handle, &SIp.cannon[a].reloadtime, sizeof(SIp.cannon[a].reloadtime)); if (SIp.cannon[a].power > weaponlevels) SIp.cannon[a].power = weaponlevels; } FS_Close(handle); } bool SILoadGameThere(int ident) { texture handle; if (gamesaved = 2) { if (FS_Open("spaceinv/spaceinv.sav", &handle, 1) >= 0) { FS_Close(handle); gamesaved = true; } else gamesaved = false; } return gamesaved; } bool SIFTRUE (int ident) {return true;} texture *SIShopTexture (texture *def, int ident) { return def; } ShopRegion_t ShopRegion[] = { {40, 40, 40, 40, "3Leave Shop", &SIleaveshoptexture, SIFTRUE, LeaveShop, SIShopTexture }, {40, 80, 40, 40, "3 Heal (250)", &SIhealthtexture, SISPHealthThere, SISPHealth, SIShopTexture }, {40, 120, 40, 40, "3 Rapid Fire (250)", &SIrapidtexture, SISPRapidFireThere, SISPRapidFire, SIShopTexture }, {80, 40, 40, 40, "3Upgrade Weapons (500)", NULL, SISPUpgrade1There, SISPUpgrade1, SISPUpgrade1Texture }, {80, 80, 40, 40, "3 Shrink (100)", &SIshrinktexture, SISPShrinkThere, SISPShrink, SIShopTexture }, // {80, 120, 40, 40, "4Quit Game", &SIquittexture, SIFTRUE, SIQuit, SIShopTexture }, {120, 40, 40, 40, "3 Side Cannon (1500)", &SIcannontexture, SISPCannonThere, SISPCannon, SIShopTexture, 1 }, {120, 80, 40, 40, "3 Spreader (1000)", &SIsideshottexture, SISPSideBurstThere, SISPSideBurst, SIShopTexture }, {120, 80, 20, 20, "3 Spreader (1000)", NULL, SISPSideBurstThere, SISPSideBurst, SISPSideBurstTexture}, {120, 120, 40, 40, "3Save Game", &SIsavegametexture, SIFTRUE, SISaveGame, SIShopTexture }, {120, 160, 40, 40, "3Load Game", &SIloadgametexture, SILoadGameThere, SILoadGame, SIShopTexture }, {80, 160, 40, 40, "3RocketLauncher (1500)", &SIcannontexture, SISPRocketThere, SISPRocket, SIShopTexture, 1 }, {160, 40, 40, 40, "3Upgrade Cannon1(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 0}, {200, 40, 40, 40, "3Upgrade Cannon2(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 1}, {240, 40, 40, 40, "3Upgrade Cannon3(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 2}, {280, 40, 40, 40, "3Upgrade Cannon4(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 3}, {320, 40, 40, 40, "3Upgrade Cannon5(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 4}, {360, 40, 40, 40, "3Upgrade Cannon6(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 5}, {400, 40, 40, 40, "3Upgrade Cannon7(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 6}, {440, 40, 40, 40, "3Upgrade Cannon8(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 7}, {480, 40, 40, 40, "3Upgrade Cannon9(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 8}, {520, 40, 40, 40, "3Upgrade Cannon10(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 9}, {560, 40, 40, 40, "3Upgrade Cannon11(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 10}, {600, 40, 40, 40, "3Upgrade Cannon12(600)", NULL, SISPCannonUpgradeThere, SISPCannonUpgrade, SISPCannonUpgradeTexture, 11}, {160, 80, 40, 40, "3 Boost Cannon1 (600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 0}, {200, 80, 40, 40, "3 Boost Cannon2 (600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 1}, {240, 80, 40, 40, "3 Boost Cannon3 (600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 2}, {280, 80, 40, 40, "3 Boost Cannon4 (600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 3}, {320, 80, 40, 40, "3 Boost Cannon5 (600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 4}, {360, 80, 40, 40, "3 Boost Cannon6 (600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 5}, {400, 80, 40, 40, "3 Boost Cannon7 (600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 6}, {440, 80, 40, 40, "3 Boost Cannon8 (600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 7}, {480, 80, 40, 40, "3 Boost Cannon9 (600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 8}, {520, 80, 40, 40, "3 Boost Cannon10(600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 9}, {560, 80, 40, 40, "3 Boost Cannon11(600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 10}, {600, 80, 40, 40, "3 Boost Cannon12(600)", &SIrapidtexture, SISPCannonBoostThere, SISPCannonBoost, SIShopTexture, 11}, }; ShopRegion_t *CurrentRegion = &ShopRegion[0]; SIbullet_t *SI_NewBullet (int bulletlevel) { int a; for (a = 0; a < MAXBULLETS; a++) { if (!SIbullet[a].inuse) { #if 0 memset(&SIbullet[a], 0, sizeof(SIbullet_t)); SIbullet[a].damage = bulletlevel+1; SIbullet[a].inuse = true; SIbullet[a].alpha = 1.0; SIbullet[a].tex = &SIbullettexture[bulletlevel]; #else if (bulletlevel < 0) { memcpy(&SIbullet[a], &SIweapons[0], sizeof(SIbullet_t)); SIbullet[a].type = bulletlevel; SIbullet[a].alphachange+=0.05f; } else memcpy(&SIbullet[a], &SIweapons[bulletlevel], sizeof(SIbullet_t)); SIbullet[a].inuse = true; #endif return &SIbullet[a]; } } return NULL; } SIbullet_t *SI_NewExplosion (float cx, float cy, float size) { int a; for (a = 0; a < MAXBULLETS; a++) { if (!SIbullet[a].inuse) { memset(&SIbullet[a], 0, sizeof(SIbullet_t)); SIbullet[a].inuse = true; SIbullet[a].alpha = (float)0.005; SIbullet[a].alphachange = (float)0.01; SIbullet[a].tex = &SIexplosiontexture; SIbullet[a].width = size; SIbullet[a].height = size; SIbullet[a].xpos = cx - size/2; SIbullet[a].ypos = cy - size/2; return &SIbullet[a]; } } return NULL; } float random(void) { return (float)(rand() & 0x7fff) / (float)0x7fff; } void Draw_String2C(int x, int y, char *string, int extraparam) { string++; x -= strlen(string)*4; while(*string) { Draw_Character(x+=8, y, *string++); } } void Draw_Picture(texture tex, float x, float y, float w, float h) { Draw_Image(x, y, w, h, 0, 0, 1, 1, tex); } int levelnametime = 0; int frame = 0; void SI_2D (void) { int a; int b; int i; float x; float y; frame++; if (SIShop) { if (lastlevel) { Draw_Colour4f(1, 1, 1, 1); Draw_String2C(vid.width / 2, vid.height / 3, "3You have compleated the game.", 2); Draw_String2C(vid.width / 2, vid.height / 2, "3Well done.", 2); Draw_String2C(vid.width / 2, (vid.height / 3)*2, "3Press any key to restart.", 2); Draw_String2C(vid.width / 2, vid.height-8, va("3Cash: %i", SIp.cash), 2); return; } if (SIp.powerups & PUP_SHRUNKEN) { SIp.width = 16; SIp.height = 16; } else { SIp.width = 32; SIp.height = 32; } for (a = 0; a < sizeof(ShopRegion)/sizeof(ShopRegion_t); a++) { if ((*ShopRegion[a].AppearCondition) (ShopRegion[a].ident)) Draw_Image(ShopRegion[a].x, ShopRegion[a].y, ShopRegion[a].width, ShopRegion[a].height, 0, 0, 1, 1, *(*ShopRegion[a].Texture) (ShopRegion[a].tex, ShopRegion[a].ident)); } if (SIp.health < 4) Draw_String2C(8, 8, va("4%i", SIp.health), 2); else Draw_String2C(8, 8, va("3%i", SIp.health), 2); Draw_Picture(SIplayertexture, SIp.x, SIp.y, SIp.width, SIp.height); for (a = 0; a < MAXADDONS; a++) { if (SIp.cannon[a].power) { if (SIp.cannon[a].tex) Draw_Picture(*SIp.cannon[a].tex, SIp.x + SIp.width*SIp.cannon[a].xoff, SIp.y + SIp.width*SIp.cannon[a].yoff, SIp.width, SIp.height); } } // if (SIp.powerups & PUP_CANNON) // Draw_Picture(SIcannontexture, SIp.x - SIp.width, SIp.y, SIp.width, SIp.height); // if (SIp.powerups & PUP_CANNON2) // Draw_Picture(SIcannontexture, SIp.x + SIp.width, SIp.y, SIp.width, SIp.height); if (notenoughcash) { notenoughcash--; Draw_Colour4f(1, 1, 1, (float)notenoughcash / 250); Draw_String2C(vid.width / 2, vid.height / 2, "4Not enough cash!", 2); } Draw_Colour4f(1, 1, 1, 1); if (CurrentRegion) Draw_String2C(vid.width / 2, 8, CurrentRegion->text, 2); Draw_String2C(vid.width / 2, vid.height-8, va("3Cash: %i", SIp.cash), 2); return; } if (SIp.health > 0) { Draw_Colour4f(1, 1, 1, 1); /* was a flame trail. :( grDisable(GL_TEXTURE_2D); grShadeModel(GL_SMOOTH); grBegin(GL_TRIANGLES); x = SIp.x+SIp.width/2; y = SIp.y+SIp.height; i = 12+rand()%8; grColor4f(0, 0, 1, 1); grVertex2f(x, y); grColor4f(1, 0, 1, 0); grVertex2f(x, y-i/2); grVertex2f(x+i, y); grColor4f(0, 0, 1, 1); grVertex2f(x, y); grColor4f(1, 0, 1, 0); grVertex2f(x+i, y); grVertex2f(x, y+i*2); grColor4f(0, 0, 1, 1); grVertex2f(x, y); grColor4f(1, 0, 1, 0); grVertex2f(x-i, y); grVertex2f(x, y+i*2); grColor4f(0, 0, 0, 1); grVertex2f(x, y); grColor4f(1, 0, 1, 0); grVertex2f(x, y-i/2); grVertex2f(x-i, y); /* grColor4f(1, 1, 1, 0); grVertex2f(x+8, y); grColor4f(1, 1, 1, 1); grVertex2f(x, y); grVertex2f(x, 0); grColor4f(1, 1, 1, 0); grVertex2f(x+8, 0); grColor4f(1, 1, 1, 1); grVertex2f(x, y); grColor4f(1, 1, 1, 0); grVertex2f(x-8, y); grVertex2f(x-8, 0); grColor4f(1, 1, 1, 1); grVertex2f(x, 0); grColor4f(1, 1, 1, 0); grVertex2f(x+8, y); grColor4f(1, 1, 1, 1); grVertex2f(x, y); grColor4f(1, 1, 1, 0); grVertex2f(x, y+8); grVertex2f(x+8, y+8); grVertex2f(x, y+8); grColor4f(1, 1, 1, 1); grVertex2f(x, y); grColor4f(1, 1, 1, 0); grVertex2f(x-8, y); grVertex2f(x-8, y+8); */ /* grEnd(); Draw_Colour4f(1, 1, 1, 1); */ Draw_Picture(SIplayertexture, SIp.x, SIp.y, SIp.width, SIp.height); for (a = 0; a < MAXADDONS; a++) { if (SIp.cannon[a].power) { if (SIp.cannon[a].tex) Draw_Picture(*SIp.cannon[a].tex, SIp.x + SIp.width*SIp.cannon[a].xoff, SIp.y + SIp.width*SIp.cannon[a].yoff, SIp.width, SIp.height); } } } for (a = 0; a < MAXMONSTERS; a++) { if (SImonster[a].health > 0) { Draw_Picture(*SImonster[a].EnemyType->picture, SImonster[a].xpos, SImonster[a].ypos, SImonster[a].width, SImonster[a].height); } } //grEnable(GL_BLEND); for (a = 0; a < MAXBULLETS; a++) { if (SIbullet[a].inuse) { switch (SIbullet[a].type) { case 1: for (b = 0; b < SIbullet[a].charge; b++) { Draw_Colour4f(random(), random(), random(), SIbullet[a].alpha); Draw_Line (SIbullet[a].xpos+SIbullet[a].width/2, SIbullet[a].ypos+SIbullet[a].height/2, SIbullet[a].xpos+SIbullet[a].width/2+(float)sin((frame+2)*(a+1)*(b+1))*SIbullet[a].width, SIbullet[a].ypos+SIbullet[a].height/2+(float)cos((frame+2)*(a+1)*(b+1))*SIbullet[a].height); } break; case 2: x=realtime*50; Draw_Colour4f(1, 1, 1, SIbullet[a].alpha); Draw_Picture(*SIbullet[a].tex, SIbullet[a].xpos, 0, SIbullet[a].width, SIbullet[a].ypos+SIbullet[a].height); break; /* case 3: x=realtime*50; grColor4f(1, 1, 1, SIbullet[a].alpha); grDisable(GL_TEXTURE_2D); grBegin(GL_LINE_STRIP); // grVertex2f(SIbullet[a].xpos, SIbullet[a].ypos); for (y = SIbullet[a].ypos; y>0; y-=SIbullet[a].yvel*5+0.2f,x+=1) grVertex2f((float)SIbullet[a].xpos+(float)SIbullet[a].charge*(float)sin(x), y); // for (y = SIbullet[a].ypos; y>0; y-=25,x+=1) // grVertex2f((float)SIbullet[a].xpos+(float)SIbullet[a].charge*(float)sin(x), y); // for (y = SIbullet[a].ypos; y>0; y-=25,x+=1) // grVertex2f((float)SIbullet[a].xpos+(float)SIbullet[a].charge*(float)sin(x), y); grEnd(); grEnable(GL_TEXTURE_2D); break; */ default: Draw_Colour4f(1, 1, 1, SIbullet[a].alpha); Draw_Picture(*SIbullet[a].tex, SIbullet[a].xpos, SIbullet[a].ypos, SIbullet[a].width, SIbullet[a].height); break; } } } Draw_Colour4f(1, 1, 1, 1); if (SIp.health <= 0) Draw_String2C(vid.width / 2, vid.height / 2, "4You LOOSE!", 2); else if (livingmonsters == 0) { Draw_String2C(vid.width / 2, vid.height / 2, "4You WIN!", 2); if (SIp.y + SIp.height < 0) Draw_String2C(vid.width / 2, (vid.height / 4) * 3, "3Press space!", 2); } else if (levelnametime) { Draw_Colour4f(1, 1, 1, (float)levelnametime/500); levelnametime--; Draw_String2C(vid.width/2, vid.height/2, SILevelName, 2); Draw_Colour4f(1, 1, 1, 1); } Draw_String2C(vid.width / 2, 4, va("3%i", SIp.cash), 1); if (SIp.health < 4) Draw_String2C(8, 8, va("4%i", SIp.health), 2); else Draw_String2C(8, 8, va("3%i", SIp.health), 2); } void SI_LoadTextures (void) { int a; for (a = 0; a < monsterpics; a++) SIbaddietexture[a] = Draw_LoadImage(va("spaceinv/enemy%i", a+1), false); for (a = 0; a < weaponlevels;a++) SIbullettexture[a] = Draw_LoadImage(va("spaceinv/gun%i", a+1), false); SIplayertexture = Draw_LoadImage("spaceinv/siplayer", false); SIexplosiontexture = Draw_LoadImage("spaceinv/bang", false); SIhealthtexture = Draw_LoadImage("spaceinv/health", false); SIleaveshoptexture = Draw_LoadImage("spaceinv/leaveshop", false); SIshrinktexture = Draw_LoadImage("spaceinv/shrink", false); SIcannontexture = Draw_LoadImage("spaceinv/cannon", false); SIquittexture = Draw_LoadImage("spaceinv/quit", false); SIsavegametexture = Draw_LoadImage("spaceinv/save", false); SIloadgametexture = Draw_LoadImage("spaceinv/load", false); SIsideshottexture = Draw_LoadImage("spaceinv/sideshot", false); SIrapidtexture = Draw_LoadImage("spaceinv/rapid", false); } //Add side cannons? bool SIHitPlayer(float x, float y, float width, float height) { if (x + width > SIp.x && x < SIp.x + SIp.width && y + height > SIp.y && y < SIp.y + SIp.height) return true; else return false; } SImonster_t *SIHitEnemy(float x, float y, float width, float height) { int a; for (a = 0; a < MAXMONSTERS; a++) { if (SImonster[a].health) { if (x + width > SImonster[a].xpos && x < SImonster[a].xpos + SImonster[a].width && y + height > SImonster[a].ypos && y < SImonster[a].ypos + SImonster[a].height) return &SImonster[a]; } } return NULL; } void SIKillEnemy(SImonster_t *en) { en->health = 0; livingmonsters--; SI_NewExplosion(en->xpos + en->width/2, en->ypos+ en->height/2, (en->width + en->height)/2); SIp.cash += en->EnemyType->reward; Sound_Start(SoundExplosion); if (livingmonsters <= 0) Sound_Start(SoundWin); } void SIHurtPlayer(int dam) { if (SIp.health <= 0) //already dead return; SIp.health -= dam; if (SIp.health < 0) SIp.health = 0; //no negative health if (SIp.health <= 0) //if final blow... { SI_NewExplosion(SIp.x + SIp.width/2, SIp.y + SIp.height/2, (SIp.width + SIp.height)); Sound_Start(SoundLoose); deadtime = realtime + 4.0f; } else Sound_Start(SoundHit); } float nextthink; void SI_MouseMove(int x, int y); void SI_Main(int mousex, int mousey) { int a; int i; int tm; float tmdist; SIbullet_t *bul; SImonster_t *en; vec3_t v; if (nextthink > realtime) { // Con_Printf("no time\n"); return; } // Con_Printf("time\n"); nextthink += 0.02f; if (nextthink < realtime-1) //don't run more than a second behind nextthink = realtime-1; if (SIShop) { if (lastlevel) { // Con_Printf("Lastlevel\n"); return; } // Con_Printf("%i (%f %f)\n", SIp.contols, SIp.x, SIp.y); if (!SIp.health) SIp.health=1; if (SIp.contols & CONT_LEFTKEY) SIp.x -= PLAYERSHIPSPEEDX; if (SIp.contols & CONT_RIGHTKEY) SIp.x += PLAYERSHIPSPEEDX; if (SIp.x < 0) SIp.x = 0; if (SIp.x + SIp.width >= vid.width) SIp.x = vid.width - SIp.width; if (SIp.contols & CONT_DOWNKEY) SIp.y += PLAYERSHIPSPEEDY; if (SIp.contols & CONT_UPKEY) SIp.y -= PLAYERSHIPSPEEDY; if (SIp.y < 0) SIp.y = 0; if (SIp.y + SIp.height >= vid.height) SIp.y = vid.height - SIp.height; CurrentRegion = NULL; for (a = 0; a < sizeof(ShopRegion) / sizeof(ShopRegion_t); a++) { if (SIp.x+SIp.width/2 < ShopRegion[a].x + ShopRegion[a].width && SIp.x+SIp.width/2 > ShopRegion[a].x && SIp.y+SIp.height/2 < ShopRegion[a].y + ShopRegion[a].height && SIp.y+SIp.height/2 > ShopRegion[a].y) { if ((*ShopRegion[a].AppearCondition) (ShopRegion[a].ident)) { CurrentRegion = &ShopRegion[a]; break; } } } if (SIp.contols & CONT_FIREKEY && CurrentRegion) { (*CurrentRegion->CallFunc) (CurrentRegion->ident); SIp.contols &= ~CONT_FIREKEY; } return; } leveltime += 0.02f; if (SIp.health > 0) { if (SIp.contols & CONT_LEFTKEY || (SIp.contols & CONT_MOUSE && SIp.x+SIp.width/2 > mousex)) SIp.x -= PLAYERSHIPSPEEDX; if (SIp.contols & CONT_RIGHTKEY || (SIp.contols & CONT_MOUSE && SIp.x+SIp.width/2 < mousex)) SIp.x += PLAYERSHIPSPEEDX; if (SIp.x < 0) SIp.x = 0; if (SIp.x + SIp.width >= vid.width) SIp.x = vid.width - SIp.width; if (livingmonsters > 0) { if (SIp.contols & CONT_DOWNKEY || (SIp.contols & CONT_MOUSE && SIp.y+SIp.height/2 < mousey)) SIp.y += PLAYERSHIPSPEEDY; if (SIp.contols & CONT_UPKEY || (SIp.contols & CONT_MOUSE && SIp.y+SIp.height/2 > mousey)) SIp.y -= PLAYERSHIPSPEEDY; if (SIp.y < (vid.height / 2)) SIp.y = (float)(vid.height / 2); if (SIp.y + SIp.height >= vid.height) SIp.y = vid.height - SIp.height; } else { SIp.y -= PLAYERSHIPSPEEDY; } if (SIp.contols & CONT_FIREKEY) { /* if (bul = SI_NewBullet(SIp.weaponpower)) { Sound_Start(SoundFire); bul->ypos = SIp.y - bul->height; bul->xpos = SIp.x + (SIp.width - bul->width) / 2; bul->xvel = 0; SIp.refire = SIp.reloadtime; */ #if 1 for (a = FIRSTCANNON; a <= LASTCANNON; a++) { if (SIp.cannon[a].power && SIp.cannon[a].refire < leveltime) { if (bul = SI_NewBullet(SIp.cannon[a].power - 1)) { bul->ypos = SIp.y - bul->height; bul->xpos = SIp.x + SIp.width*SIp.cannon[a].xoff + (SIp.width - bul->width) / 2; bul->xvel = 0; SIp.cannon[a].refire = leveltime + SIp.cannon[a].reloadtime; Sound_Start(SoundFire); } } } for (a = FIRSTCENTRALMOD; a <= LASTCENTRALMOD; a++) { if (SIp.cannon[a].power && SIp.cannon[a].refire < leveltime) { if (bul = SI_NewBullet(SIp.cannon[a].power - 1)) { bul->ypos = SIp.y - bul->height; bul->xpos = SIp.x + SIp.width*SIp.cannon[a].xoff + (SIp.width - bul->width) / 2; bul->xvel = 0; SIp.cannon[a].refire = leveltime + SIp.cannon[a].reloadtime; Sound_Start(SoundFire); } } } for (a = FIRSTROCKET; a <= LASTROCKET; a++) { if (SIp.cannon[a].power && SIp.cannon[a].refire < leveltime) { if (bul = SI_NewBullet(-1)) { bul->ypos = SIp.y - bul->height; bul->xpos = SIp.x + SIp.width*SIp.cannon[a].xoff + (SIp.width - bul->width) / 2; bul->xvel = 0; bul->yvel = -1; SIp.cannon[a].refire = leveltime + SIp.cannon[a].reloadtime; Sound_Start(SoundFire); } } } #else if (SIp.powerups & PUP_CANNON) { bul = SI_NewBullet(SIp.weaponpower); if (bul) { bul->width = 10; bul->height = 10; bul->damage = 1; bul->ypos = SIp.y - bul->height; bul->xpos = SIp.x - SIp.width + (SIp.width - bul->width) / 2; bul->xvel = 0; bul->yvel = (float)0.004; bul->yaccel = (float)0.002; } } if (SIp.powerups & PUP_CANNON2) { bul = SI_NewBullet(SIp.weaponpower); if (bul) { bul->width = 10; bul->height = 10; bul->damage = 1; bul->ypos = SIp.y - bul->height; bul->xpos = SIp.x + SIp.width + (SIp.width - bul->width) / 2; bul->xvel = 0; bul->yvel = (float)0.004; bul->yaccel = (float)0.002; } } #endif /* if (SIp.sidegun) { if (bul = SI_NewBullet(SIp.sidegun -1)) { bul->ypos = SIp.y - bul->height; bul->xpos = SIp.x + (SIp.width - bul->width) / 2; bul->xvel = (float)(random()-0.5)*2; } } } */ } } else { if (deadtime < realtime) SIRestartGame(); } for (a = 0; a < MAXSQUADS; a++) { if (SISquad[a].number && SISquad[a].time < leveltime) { SISquad[a].time += SISquad[a].interval; for (i = 0; i < MAXMONSTERS; i++) { if (SImonster[i].health <= 0) { SImonster[i].routenum = SISquad[a].route; SImonster[i].destnum = 1; SImonster[i].width = SIEnemyType[SISquad[a].type].width; SImonster[i].height = SIEnemyType[SISquad[a].type].height; SImonster[i].xpos = ((SIRoute[SImonster[i].routenum].pos[0])[0] - SImonster[i].width/2)/100.f*vid.height; SImonster[i].ypos = ((SIRoute[SImonster[i].routenum].pos[0])[1] - SImonster[i].height/2)/100.f*vid.height; SImonster[i].EnemyType = &SIEnemyType[SISquad[a].type]; SImonster[i].health = SIEnemyType[SISquad[a].type].health; SImonster[i].yvel = ENEMYSHIPSPEEDY; SImonster[i].xvel = (float)ENEMYSHIPSPEEDX; SISquad[a].number-=1; break; } } } } tm = -1; tmdist = 32767; for (a = 0; a < MAXMONSTERS; a++) { if (SImonster[a].health > 0) { if (tmdist > sqrt((SIp.x - SImonster[a].xpos)*(SIp.x - SImonster[a].xpos)+(SIp.y - SImonster[a].ypos)*(SIp.y - SImonster[a].ypos))) { tm = a; tmdist = (float)sqrt((SIp.x - SImonster[a].xpos)*(SIp.x - SImonster[a].xpos)+(SIp.y - SImonster[a].ypos)*(SIp.y - SImonster[a].ypos)); } if (SImonster[a].EnemyType->AI) { if (SImonster[a].xpos+SImonster[a].width/2 > SIp.x+SIp.width/2) { if (SImonster[a].xpos+SImonster[a].width/2 - 0.8 < SIp.x+SIp.width/2) SImonster[a].xvel = SIp.x+SIp.width/2-(SImonster[a].xpos+SImonster[a].width/2); else SImonster[a].xvel = (float)-0.8; } else if (SImonster[a].xpos < SIp.x) { if (SImonster[a].xpos+SImonster[a].width/2 + 0.8 > SIp.x+SIp.width/2) SImonster[a].xvel = SIp.x+SIp.width/2-(SImonster[a].xpos+SImonster[a].width/2); else SImonster[a].xvel = (float)0.8; } SImonster[a].ypos += SImonster[a].yvel; SImonster[a].xpos += SImonster[a].xvel; SImonster[a].yvel = 0; if (SImonster[a].xpos < 0) SImonster[a].xpos = 0; if (SImonster[a].xpos + SImonster[a].width >= vid.width) SImonster[a].xpos = vid.width - SImonster[a].width; if (SIHitPlayer(SImonster[a].xpos, SImonster[a].ypos, SImonster[a].width, SImonster[a].height) && SIp.health > 0) { SIHurtPlayer(SImonster[a].health); SIKillEnemy(&SImonster[a]); } else if (random() < SImonster[a].EnemyType->FireProb && SIp.health > 0 && SImonster[a].EnemyType->shotdamage >= 0) { if (bul = SI_NewBullet(SImonster[a].EnemyType->shotdamage)) { bul->yvel *= -1; bul->yvel -= SImonster[a].yvel; bul->yaccel *= -1; bul->xpos = SImonster[a].xpos + SImonster[a].width/2-bul->width/2; bul->ypos = SImonster[a].ypos + SImonster[a].height; // bul->width = 10; // bul->height = 10; } } } else { SImonster[a].ypos += SImonster[a].yvel; SImonster[a].xpos += SImonster[a].xvel; if (SImonster[a].xpos < 0) SImonster[a].xpos = 0; if (SImonster[a].xpos + SImonster[a].width >= vid.width) SImonster[a].xpos = vid.width - SImonster[a].width; if (SIHitPlayer(SImonster[a].xpos, SImonster[a].ypos, SImonster[a].width, SImonster[a].height) && SIp.health > 0) { SIHurtPlayer(SImonster[a].health); SIKillEnemy(&SImonster[a]); } else if (SImonster[a].ypos > vid.height) { SImonster[a].ypos = 0 - SImonster[a].height; SImonster[a].xpos = random() * vid.width; } else if (random() < SImonster[a].EnemyType->FireProb && SIp.health > 0 && SImonster[a].EnemyType->shotdamage >= 0) { if (bul = SI_NewBullet(SImonster[a].EnemyType->shotdamage)) { bul->yvel *= -1; bul->yvel -= SImonster[a].yvel; bul->yaccel *= -1; bul->xpos = SImonster[a].xpos + SImonster[a].width/2-bul->width/2; bul->ypos = SImonster[a].ypos + SImonster[a].height; // bul->width = 10; // bul->height = 10; } } else if (random() < 0.001) SImonster[a].xvel = (float)ENEMYSHIPSPEEDX; } if (SIEnemyType[a].healthregen) { if (SImonster[a].health < SImonster[a].health) { if (SIEnemyType[a].healthregen) SIEnemyType[a].healthregen--; else { SIEnemyType[a].healthregen = SImonster[a].timetoregen; SIEnemyType[a].health++; } } } } } for (a = 0; a < MAXBULLETS; a++) { if (SIbullet[a].inuse) { if (SIbullet[a].type == -2) { SIbullet[a].ypos += SIbullet[a].yvel; SIbullet[a].xpos += SIbullet[a].xvel; SIbullet[a].alpha += SIbullet[a].alphachange; if (SIbullet[a].alpha >= 1 && SIbullet[a].alphachange > 0) SIbullet[a].alphachange *= -1; else if (SIbullet[a].alphachange && SIbullet[a].alpha <= 0) SIbullet[a].inuse = false; } else if (SIbullet[a].type == -1) { if (tm >= 0) { v[0] = SImonster[tm].xpos+SImonster[tm].width/2 - SIbullet[a].xpos; v[1] = SImonster[tm].ypos+SImonster[tm].height/2 - SIbullet[a].ypos; v[2] = 0; vecNorm(v, v); if (bul = SI_NewBullet(-2)) { bul->xvel = -v[0]*3; bul->yvel = -v[1]*3; bul->alphachange = 0.05f; bul->xpos = SIbullet[a].xpos; bul->ypos = SIbullet[a].ypos; } v[0] += SIbullet[a].xvel; v[1] += SIbullet[a].yvel; vecNorm(v, v); SIbullet[a].xvel = v[0]*5; SIbullet[a].yvel = v[1]*5; } SIbullet[a].ypos += SIbullet[a].yvel; SIbullet[a].xpos += SIbullet[a].xvel; if (en = SIHitEnemy(SIbullet[a].xpos, SIbullet[a].ypos, SIbullet[a].width, SIbullet[a].height)) { en->health -= SIbullet[a].damage; if (en->health <= 0) { SIKillEnemy(en); } else { Sound_Start(SoundHit); } SIbullet[a].alpha = 0.5f; SIbullet[a].alphachange = 0.04f; SIbullet[a].tex = &SIexplosiontexture; SIbullet[a].xvel = 0; SIbullet[a].yvel = 0; SIbullet[a].damage = 0; SIbullet[a].yaccel = 0; SIbullet[a].charge = 0; SIbullet[a].type = 0; } if (SIbullet[a].ypos + SIbullet[a].height < 0 || SIbullet[a].ypos > vid.height) SIbullet[a].inuse = false; } else if (SIbullet[a].ypos + SIbullet[a].height < 0 || SIbullet[a].ypos > vid.height) { SIbullet[a].inuse = false; } else { SIbullet[a].yvel += SIbullet[a].yaccel; SIbullet[a].ypos -= SIbullet[a].yvel; SIbullet[a].xpos += SIbullet[a].xvel; if (SIbullet[a].type == 2) { if (en = SIHitEnemy(SIbullet[a].xpos, 0, SIbullet[a].width, SIbullet[a].ypos)) { en->health -= SIbullet[a].damage; if (en->health <= 0) { SIKillEnemy(en); } else { Sound_Start(SoundHit); } // SIbullet[a].alpha = 0.5f; // SIbullet[a].alphachange = 0.04f; // SIbullet[a].tex = &SIexplosiontexture; // SIbullet[a].xvel = 0; // SIbullet[a].yvel = 0; // SIbullet[a].damage = 0; // SIbullet[a].yaccel = 0; // SIbullet[a].charge = 0; // SIbullet[a].type = 0; } } else if (SIbullet[a].yvel > 0) { if (en = SIHitEnemy(SIbullet[a].xpos, SIbullet[a].ypos, SIbullet[a].width, SIbullet[a].height)) { en->health -= SIbullet[a].damage; if (en->health <= 0) { SIKillEnemy(en); } else { Sound_Start(SoundHit); } SIbullet[a].alpha = 0.5f; SIbullet[a].alphachange = 0.04f; SIbullet[a].tex = &SIexplosiontexture; SIbullet[a].xvel = 0; SIbullet[a].yvel = 0; SIbullet[a].damage = 0; SIbullet[a].yaccel = 0; SIbullet[a].charge = 0; SIbullet[a].type = 0; } } else if (SIbullet[a].yvel < 0) { if (SIHitPlayer(SIbullet[a].xpos, SIbullet[a].ypos, SIbullet[a].width, SIbullet[a].height)) { SIHurtPlayer(SIbullet[a].damage); SIbullet[a].alpha = 0.5f; SIbullet[a].alphachange = 0.04f; SIbullet[a].tex = &SIexplosiontexture; SIbullet[a].xvel = 0; SIbullet[a].yvel = 0; SIbullet[a].damage = 0; SIbullet[a].yaccel = 0; SIbullet[a].charge = 0; SIbullet[a].type = 0; } } SIbullet[a].alpha += SIbullet[a].alphachange; if (SIbullet[a].alpha >= 1 && SIbullet[a].alphachange > 0) SIbullet[a].alphachange *= -1; else if (SIbullet[a].alphachange && SIbullet[a].alpha <= 0) SIbullet[a].inuse = false; } } } } void SI_KeyUp(int k) { if (k == K_LEFTARROW) SIp.contols &= ~CONT_LEFTKEY; else if (k == K_RIGHTARROW) SIp.contols &= ~CONT_RIGHTKEY; else if (k == K_UPARROW) SIp.contols &= ~CONT_UPKEY; else if (k == K_DOWNARROW) SIp.contols &= ~CONT_DOWNKEY; else if (k == K_MOUSE1 || k == K_SPACE) SIp.contols &= ~CONT_FIREKEY; else if (k == K_MOUSE2) SIp.contols &= ~CONT_MOUSE; } void SI_KeyDown(int k) { if (SIShop && lastlevel) { SIlevel = 0; lastlevel = false; return; } else if (livingmonsters <= 0 && SIp.y + SIp.height < 0 && SIShop == false) { SIShop = true; SIlevel+=1; SIp.x = ShopRegion[0].x + ShopRegion[0].width/2; SIp.y = ShopRegion[0].y + ShopRegion[0].height/2; return; } else if (SIp.health <= 0) { if (k == K_SPACE && !(SIp.contols & CONT_FIREKEY)) deadtime += 1; return; } if (k == K_LEFTARROW) SIp.contols |= CONT_LEFTKEY; else if (k == K_RIGHTARROW) SIp.contols |= CONT_RIGHTKEY; else if (k == K_UPARROW) SIp.contols |= CONT_UPKEY; else if (k == K_DOWNARROW) SIp.contols |= CONT_DOWNKEY; else if (k == K_MOUSE1 || k == K_SPACE) SIp.contols |= CONT_FIREKEY; else if (k == K_MOUSE2) SIp.contols |= CONT_MOUSE; else if (k == '1') SIp.health = 9; else if (k == '2') SIp.cash += 100; else if (k == K_ESCAPE) Menu_Control(0); else Con_Printf("key %i not recognised\n", k); Con_Printf("%i (%i)\n", SIp.contols, k); } void SI_MouseMove(int x, int y) { static int ox; static int oy; if (SIShop && (ox != x || oy != y)) { SIp.x = (float)x - SIp.width/2; SIp.y = (float)y - SIp.height/2; ox = x; oy = y; } } qboolean FS_GetS(char *buffer, int buffersize, qhandle_t handle) { int i; buffersize--; for (i = 0; i < buffersize; i+=1) { if (FS_Read(handle, buffer+i, 1) <= 0) break; if (buffer[i] == '\n') break; } buffer[i] = '\0'; if (!i) return false; return true; } void SI_Initialize(void) { int a; /* SoundWin = Sound_LoadSound("spaceinv/sound/win.wav"); SoundLoose = Sound_LoadSound("spaceinv/sound/loose.wav"); SoundFire = Sound_LoadSound("spaceinv/sound/fire.wav"); SoundExplosion = Sound_LoadSound("spaceinv/sound/explode.wav"); SoundHit = Sound_LoadSound("spaceinv/sound/explode.wav"); */ if (SIEnemyType) //if one of these is defined, they must all be { free(SIEnemyType); free(SImonster); free(SIbullet); free(SIbaddietexture); free(SIbullettexture); SIbullettexture = NULL; free(SISquad); free(SIRoute); } if (SIweapons) free(SIweapons); { bool section = false; // FILE *F; char line[1024]; char *s; char *val; int len; qhandle_t f; len = FS_Open("spaceinv/weapons.txt", &f, 1); if (len>=0) { a = -1; while (1) { if (!FS_GetS(line, 1024, f)) break; // if (!fgets(line, 1024, F)) // break; //eof s = line; while(*s == ' ' || *s == '\t') //ignore indents s++; if (*s == '\n' || *s == '\r' || *s == '#') //ignore comments/blank lines continue; val = s + strlen(s)-1; while (*val == '\n' || *val == '\r' || *val == ' ' || *val == '\t') { *val = 0; val--; } val = strchr(s, '='); if (val) { *val = 0; val++; } if (section == 2 && *s != '[') { if (!strcasecmp(s, "monsterpics")) monsterpics = atoi(val); else if (!strcasecmp(s, "maxmonsters")) MAXMONSTERS = atoi(val); else if (!strcasecmp(s, "maxbullets")) MAXBULLETS = atoi(val); else if (!strcasecmp(s, "maxroutepoints")) MAXROUTEPOINTS = atoi(val); else if (!strcasecmp(s, "maxroutes")) MAXROUTES = atoi(val); else if (!strcasecmp(s, "maxsquads")) MAXSQUADS = atoi(val); else Con_Printf("Bad command \"%s\" in \"%s\"\n", s, "spaceinv\\weapons.txt"); } else if (section == 1 && *s != '[') { if (!strcasecmp(s, "width")) SIweapons[a].width = (float)atof(val); else if (!strcasecmp(s, "height")) SIweapons[a].height = (float)atof(val); else if (!strcasecmp(s, "yvel")) SIweapons[a].yvel = (float)atof(val); else if (!strcasecmp(s, "yaccel")) SIweapons[a].yaccel = (float)atof(val); else if (!strcasecmp(s, "damage")) SIweapons[a].damage = atoi(val); else if (!strcasecmp(s, "alpha")) SIweapons[a].alpha = (float)atof(val); else if (!strcasecmp(s, "alphachange")) SIweapons[a].alphachange = (float)atof(val); else if (!strcasecmp(s, "texturenum")) { if (!SIbullettexture) { SIbullettexture = malloc(sizeof(texture) * weaponlevels); memset(SIbullettexture, 0, sizeof(texture) * weaponlevels); } SIweapons[a].tex = &SIbullettexture[atoi(val)-1]; //allow different pictures } else if (!strcasecmp(s, "charge")) SIweapons[a].charge = atoi(val); //allow different pictures else if (!strcasecmp(s, "type")) SIweapons[a].type = atoi(val); else Con_Printf("Bad command \"%s\" in \"%s\"\n", s, "spaceinv\\weapons.txt"); } else if (!strcasecmp(s, "weapons")) { weaponlevels = atoi(val); // if (weaponlevels > SHOTLEVELS) // { // Log("Too many weapons set\n"); // weaponlevels = SHOTLEVELS; // } SIweapons = malloc(sizeof(SIbullet_t) * weaponlevels); memset(SIweapons, 0, sizeof(SIbullet_t) * weaponlevels); } else if (!strcasecmp(s, "[weapon")) { section = 1; if (weaponlevels == 0) Sys_Error("SILoadWeapons: number of weapons not set yet."); a = atoi(val); if (a > SHOTLEVELS) { a=0; Con_Printf("Bad type\n"); } else a-=1; } else if (!strcasecmp(s, "[info]")) { section = 2; } else Con_Printf("Bad command \"%s\" in \"%s\"\n", s, "spaceinv\\weapons.txt"); } FS_Close(f); } else { //GameCompleate = true; //NextLevel = 0; Sys_Error("Couldn't open file\n"); } } if (!SIbullettexture) { SIbullettexture = malloc(sizeof(texture) * weaponlevels); memset(SIbullettexture, 0, sizeof(texture) * weaponlevels); } SIEnemyType = malloc(sizeof(SIEnemyType_t) * ENEMYTYPES); memset(SIEnemyType, 0, sizeof(SIEnemyType_t) * ENEMYTYPES); SImonster = malloc(sizeof(SImonster_t) * MAXMONSTERS); memset(SImonster, 0, sizeof(SImonster_t) * MAXMONSTERS); SIbullet = malloc(sizeof(SIbullet_t) * MAXBULLETS); memset(SIbullet, 0, sizeof(SIbullet_t) * MAXBULLETS); SIbaddietexture = malloc(sizeof(texture) * ENEMYTYPES); memset(SIbaddietexture, 0, sizeof(texture) * ENEMYTYPES); SIRoute = malloc((sizeof(SIRoute_t)+(MAXROUTEPOINTS-1)*sizeof(vec3_t)) * MAXROUTES); memset(SIRoute, 0, (sizeof(SIRoute_t)+(MAXROUTEPOINTS-1)*sizeof(vec3_t)) * MAXROUTES); SISquad = malloc(sizeof(SISquad_t) * MAXSQUADS); memset(SISquad, 0, sizeof(SISquad_t) * MAXSQUADS); //loaded elsewhere // SIweapons = mmalloc(sizeof(SIbullet_t) * weaponlevels); SI_LoadTextures (); SIRestartGame (); } void NextLevel (void) { int a; // int numenemysoftype[ENEMYTYPES] = {5, 5, 50}; int etype = 0; SIEnemyType_t *et; if (SIp.powerups & PUP_SHRUNKEN) { SIp.height = 16; SIp.width = 16; SIp.powerups &= ~PUP_SHRUNKEN; } else { SIp.height = 32; SIp.width = 32; } SIp.y = vid.height - SIp.height; SIp.x = (vid.width - SIp.width) / 2; SIShop = false; deadtime = 0; nextthink = realtime; leveltime = 0; for (a = 0; a < MAXSQUADS; a++) SISquad[a].number = 0; #if 1 { int i; int usedtypes = false; int sectiontype=0; qhandle_t F; char line[1024]; char *s; char *val; int len; int rofs = 0; len = FS_Open(va("spaceinv/level%i.txt", SIlevel+1), &F, 1); if (len < 0) { SIlevel = 0; len = FS_Open(va("spaceinv/level%i.txt", SIlevel+1), &F, 1); //loop back to the start } // F = fopen(Sva("%sspaceinv\\level%i.txt", funcs->exe->gamepath, SIlevel+1), "rb"); if (len>=0) { a = -1; memset(SIEnemyType, 0, sizeof(SIEnemyType)); // memset(numenemysoftype, 0, sizeof(numenemysoftype)); while (1) { if (!FS_GetS(line, 1024, F)) break; //eof s = line; while(*s == ' ' || *s == '\t') //ignore indents s++; if (*s == '\n' || *s == '\r' || *s == '#') //ignore comments/blank lines continue; val = s + strlen(s)-1; while (*val == '\n' || *val == '\r' || *val == ' ' || *val == '\t') { *val = 0; val--; } val = strchr(s, '='); if (val) { *val = 0; val++; } if (*s == '[') { if (!strcasecmp(s+1, "info]")) { sectiontype = 1; } else if (!strcasecmp(s+1, "type")) { if (usedtypes == 0) Con_Printf("SINextLevel: Types not set yet"); a = atoi(val); if (a > ENEMYTYPES || a < 1) { a=0; Con_Printf("Bad type\n"); } else a-=1; memset(&SIEnemyType[a], 0, sizeof(SIEnemyType_t)); sectiontype = 2; } else if (!strcasecmp(s+1, "route")) { a = atoi(val); if (a > ENEMYTYPES || a < 1) { a=0; Con_Printf("Bad route\n"); } else a-=1; memset(&SIRoute[a], 0, sizeof(SIRoute_t)+(MAXROUTEPOINTS-1)*sizeof(vec3_t)); sectiontype = 3; } else if (!strcasecmp(s+1, "squad")) { a = atoi(val); if (a > MAXSQUADS || a < 1) { a=0; Con_Printf("Bad squad\n"); } else a-=1; memset(&SISquad[a], 0, sizeof(SISquad_t)); sectiontype = 4; } else Con_Printf("Bad block \"%s\" in \"%s\"\n", s, va("level%i.txt", SIlevel)); } else if (sectiontype == 0) { if (!strcasecmp(s, "types")) usedtypes = atoi(val); else Con_Printf("Bad command \"%s\" in \"%s\" (out of block)\n", s, va("level%i.txt", SIlevel)); } else if (sectiontype == 1) { if (!strcasecmp(s, "lastlevel")) lastlevel = atoi(val); else if (!strcasecmp(s, "levelname")) { strcpy(SILevelName, val); levelnametime = 500; } else Con_Printf("Bad command \"%s\" in \"%s\"\n", s, va("level%i.txt", SIlevel)); } else if (sectiontype == 2) { if (!strcasecmp(s, "width")) SIEnemyType[a].width = (float)atof(val); else if (!strcasecmp(s, "height")) SIEnemyType[a].height = (float)atof(val); else if (!strcasecmp(s, "power")) { SIEnemyType[a].shotdamage = atoi(val) - 1; if (SIEnemyType[a].shotdamage >= weaponlevels) { Con_Printf("Enemy %i has weapon number %i\n", a+1, SIEnemyType[a].shotdamage+1); SIEnemyType[a].shotdamage = weaponlevels-1; } } else if (!strcasecmp(s, "health")) SIEnemyType[a].health = atoi(val); else if (!strcasecmp(s, "reward")) SIEnemyType[a].reward = atoi(val); else if (!strcasecmp(s, "number")) SIEnemyType[a].number = atoi(val); else if (!strcasecmp(s, "ai")) SIEnemyType[a].AI = atoi(val); else if (!strcasecmp(s, "healthregen")) SIEnemyType[a].healthregen = atoi(val); else if (!strcasecmp(s, "picture")) { i = atoi(val) - 1; if (i < 0 || i >= monsterpics) { Sys_Errorf("Monster picture has the wrong value (%i)", i+1); } else SIEnemyType[a].picture = &SIbaddietexture[i]; //allow different pictures } else if (!strcasecmp(s, "fireprob")) SIEnemyType[a].FireProb = (float)atof(val); //allow different pictures else Con_Printf("Bad command \"%s\" in \"%s\"\n", s, va("level%i.txt", SIlevel)); } else if (sectiontype == 3) { if (!strcasecmp(s, "coords")) SIRoute[a].numpoints = atoi(val); else if (*s == 'x' || *s == 'X') (SIRoute[a].pos[atoi(s+1)-1])[0] = (float)atof(val); else if (*s == 'y' || *s == 'Y') (SIRoute[a].pos[atoi(s+1)-1])[1] = (float)atof(val); else if (*s == 'z' || *s == 'Z') (SIRoute[a].pos[atoi(s+1)-1])[2] = (float)atof(val); else Con_Printf("Bad route command \"%s\" in \"%s\"\n", s, va("level%i.txt", SIlevel)); } else if (sectiontype == 4) { if (!strcasecmp(s, "route")) SISquad[a].route = atoi(val)-1; else if (!strcasecmp(s, "type")) SISquad[a].type = atoi(val)-1; else if (!strcasecmp(s, "number")) SISquad[a].number = atoi(val); else if (!strcasecmp(s, "interval")) SISquad[a].interval = (float)atof(val); else if (!strcasecmp(s, "speed")) SISquad[a].speed = (float)atof(val); else if (!strcasecmp(s, "time")) SISquad[a].time = (float)atof(val); else Con_Printf("Bad squad command \"%s\" in \"%s\"\n", s, va("level%i.txt", SIlevel)); } else Con_Printf("Bad command \"%s\" in \"%s\"\n", s, va("level%i.txt", SIlevel)); } FS_Close(F); } else { //GameCompleate = true; //NextLevel = 0; Sys_Errorf("Couldn't open file\n", va("spaceinv/level%i.txt", SIlevel+1)); } } #else for (a = 0; a < ENEMYTYPES; a++) { SIEnemyType[a].health = a+1; SIEnemyType[a].height = (float)(16*(a+1)); SIEnemyType[a].width = (float)(16*(a+1)); SIEnemyType[a].picture = &SIbaddietexture; SIEnemyType[a].shotpicture = &SIbullettexture[0]; SIEnemyType[a].shotdamage = a-1; SIEnemyType[a].reward = (a+1) * 25; } #endif memset(SImonster, 0, sizeof(*SImonster)*MAXMONSTERS); livingmonsters = 0; while (SIEnemyType[etype].number <= 0) { etype++; if (etype >= ENEMYTYPES) break; } for (a = 0; a < MAXMONSTERS; a++) { if (etype < ENEMYTYPES) { et = &SIEnemyType[etype]; SImonster[a].EnemyType = et; SImonster[a].health = et->health; SImonster[a].xpos = random() * vid.width; SImonster[a].ypos = (random() * vid.height) / 2; SImonster[a].width = et->width; SImonster[a].height = et->height; SImonster[a].yvel = ENEMYSHIPSPEEDY; SImonster[a].xvel = (float)ENEMYSHIPSPEEDX; livingmonsters++; SIEnemyType[etype].number-=1; while (SIEnemyType[etype].number <= 0) { etype++; if (etype >= ENEMYTYPES) break; } if (SIEnemyType[etype].number <= 0) break; } else SImonster[a].health = 0; } for (a = 0; a < MAXSQUADS; a++) livingmonsters += SISquad[a].number; deadtime = 0; memset(SIbullet, 0, sizeof(SIbullet) * MAXBULLETS); for (a = 0; a < MAXADDONS; a++) SIp.cannon[a].refire = 0; } void SIRestartGame (void) { int a; SIp.health = 9; SIp.cash = 500; SIp.powerups = 0; SIp.height = 32; SIp.width = 32; SIp.y = (vid.height - SIp.height)/2; SIp.x = (vid.width - SIp.width) / 2; for (a = 0; a < MAXADDONS; a++) { SIp.cannon[a].xoff = 0; SIp.cannon[a].yoff = 0; SIp.cannon[a].power = 0; SIp.cannon[a].reloadtime = 0.8f; SIp.cannon[a].tex = NULL; } #if 1 for (a = FIRSTCANNON; a <= LASTCANNON; a++) { SIp.cannon[a].xoff = (int)((float)a-FIRSTCANNON+1.5f) / 2.0f; if (a%2) SIp.cannon[a].xoff *= -1; else SIp.cannon[a].xoff+=1; SIp.cannon[a].yoff = 0; SIp.cannon[a].tex = &SIcannontexture; } for (a = FIRSTROCKET; a <= LASTROCKET; a++) { SIp.cannon[a].xoff = (int)(a-FIRSTROCKET+1.5f) / 2.0f; SIp.cannon[a].xoff -= 0.5f; if (a%2) SIp.cannon[a].xoff *= -1.0f; else SIp.cannon[a].xoff += 1.0f; SIp.cannon[a].yoff = 0; SIp.cannon[a].tex = &SIcannontexture; } #else SIp.cannon[0].xoff = -1; SIp.cannon[1].xoff = 1; SIp.cannon[2].xoff = -2; SIp.cannon[3].xoff = 2; #endif SIp.cannon[M_FORWARD].power = 1; SIp.cannon[M_FORWARD].tex = &SIplayertexture; SIlevel = 0; lastlevel = false; SIShop = true; deadtime = 0; nextthink = 0; } int Plug_MenuEvent(int *args) { // args[2]=(int)(args[2]*640.0f/vid.width); // args[3]=(int)(args[3]*480.0f/vid.height); switch(args[0]) { case 0: //draw SI_Main(args[2], args[3]); SI_2D(); break; case 1: //keydown SI_KeyDown(args[1]); break; case 2: //keyup SI_KeyUp(args[1]); break; case 3: //menu closed (this is called even if we change it). break; case 4: //mousemove break; } return 0; } int Plug_Tick(int *args) { realtime = args[0]/1000.0f; return true; } int Plug_ExecuteCommand(int *args) { char cmd[256]; Cmd_Argv(0, cmd, sizeof(cmd)); if (!strcmp("spaceinv", cmd)) { Cvar_SetFloat("gl_blend2d", 1); SI_LoadTextures(); Menu_Control(1); return 1; } return 0; } int Plug_Init(int *args) { if (Plug_Export("Tick", Plug_Tick) && Plug_Export("ExecuteCommand", Plug_ExecuteCommand) && Plug_Export("MenuEvent", Plug_MenuEvent)) { K_UPARROW = Key_GetKeyCode("uparrow"); K_DOWNARROW = Key_GetKeyCode("downarrow"); K_LEFTARROW = Key_GetKeyCode("leftarrow"); K_RIGHTARROW = Key_GetKeyCode("rightarrow"); K_ESCAPE = Key_GetKeyCode("escape"); K_HOME = Key_GetKeyCode("home"); K_MOUSE1 = Key_GetKeyCode("mouse1"); K_MOUSE2 = Key_GetKeyCode("mouse2"); K_SHIFT = Key_GetKeyCode("shift"); K_SPACE = Key_GetKeyCode("space"); K_F1 = Key_GetKeyCode("f1"); K_F2 = Key_GetKeyCode("f2"); Cmd_AddCommand("spaceinv"); SI_Initialize(); SI_LoadTextures(); return 1; } return 0; }