1 // Untahris (Common Playground) 2 // copyright (C) 2006 longuens@users.sourceforge.net 3 // Released under GNU General Public License (see the file COPYING) 4 // -------------------------------------------------------------- 5 // Bomber & Bomb. 6 7 struct OBomb : TPlayObject { 8 public: 9 int32 x; 10 int32 y; 11 int32 xtime; 12 int32 range; 13 OBombOBomb14 OBomb(int _owner, int _x, int _y, int _xtime, int _range) : x(_x), y(_y) { 15 owner = _owner; 16 range = _range; 17 time = g.time; 18 xtime = g.time + _xtime; 19 g.mapSet(x,y, cBomb1, owner); 20 g.objects.push_back(this); 21 } OBombOBomb22 OBomb(TBuffer &b) { 23 b.get(owner); 24 b.get(x); b.get(y); b.get(time); b.get(xtime); b.get(range); 25 } saveOBomb26 void save(TBuffer &b) { 27 b.putChar(11); 28 b.put(owner); b.put(x); b.put(y); b.put(time); b.put(xtime); b.put(range); 29 } goOBomb30 void go() { 31 if(time < xtime && g.map[y][x] != cExplosion) { 32 int phase = (2500 / (xtime-time)); 33 g.mapSet(x, y, phase&1 ? cBomb1 : cBomb2, owner); 34 time += 25; 35 if(time > xtime) time = xtime; 36 } 37 else if(time <= xtime) { 38 g.mapSet(x,y, cExplosion, owner); 39 d.playSoundAt(d.sndShoot, x, y); 40 for(int k=0; k<4; k++) 41 for(int r=1; r<=range; r++) { 42 int ax = x+kx[k]*r, ay = y+ky[k]*r; 43 CellType m = bigType(ax, ay); 44 if(isBonus(m)) { 45 clearBig(ax, ay, cFree, 0); 46 if(gc.regenerate(m) && gc.regenerateDestroyed) 47 placeBigRandomly(m, 0); 48 } 49 if(isCannon(m)) { 50 clearBig(ax, ay, cFree, 0); 51 g.mapSet(ax,ay, cExplosion, owner); 52 r=range; 53 } 54 switch(g.map[ay][ax]) { 55 case cExplosion: 56 // might be someone else's 57 break; 58 case cXunux: 59 destroyAt(ax, ay, owner, 0); 60 /* fallthrough */ 61 case cFree: 62 case cBomb1: 63 case cBomb2: 64 g.mapSet(ax,ay, cExplosion, owner); 65 break; 66 case cBreakWall: 67 case cSnakeTRON: 68 case cTetrisDown: 69 case cTetris: 70 case cCastleWall: 71 case cXunuxStable: 72 g.mapSet(ax,ay, cExplosion, owner); 73 r=range; 74 break; 75 case cSnakeHead: 76 g.mapSet(ax,ay, cSnakeDead, owner); 77 r=range; 78 break; 79 default: 80 r=range; 81 break; 82 } 83 } 84 xtime = time; // if it exploded due to another's explosion 85 time += 750; 86 ow()->ammo += ec().ammoPerShoot; 87 } 88 else if(time > xtime) { 89 g.mapSet(x,y, cFree, 0); 90 for(int k=0; k<4; k++) 91 for(int r=1; r<=range; r++) { 92 int ax = x+kx[k]*r, ay = y+ky[k]*r; 93 if(ax == 0 || ay == 0 || ax == g.sizeX-1 || ay == g.sizeY-1) continue; 94 if(g.map[ay][ax] == cExplosion) 95 g.mapSet(ax,ay, cFree, 0); 96 } 97 g.deleteObject(this); 98 } 99 } 100 }; 101 102 struct OBomber : TPlayObject { 103 public: 104 int x; 105 int y; OBomberOBomber106 OBomber(int _owner, int _x, int _y) : 107 x(_x), y(_y) { 108 owner = _owner; 109 time = g.time; 110 g.objects.push_back(this); 111 } 112 OBomberOBomber113 OBomber(TBuffer &b) { 114 b.get(owner); 115 b.get(x); b.get(y); 116 b.get(time); 117 } saveOBomber118 void save(TBuffer &b) { 119 b.putChar(10); 120 b.put(owner); 121 b.put(x); b.put(y); 122 b.put(time); 123 } 124 checkGoOBomber125 bool checkGo(int cx, int cy) { 126 cx = DeCtr(cx); 127 cy = DeCtr(cy); 128 // cannot block self with bomb 129 if(cx == DeCtr(x) && cy == DeCtr(y)) return true; 130 if(g.map[cy][cx] == cFree) return true; 131 if(g.map[cy][cx] == cExplosion) return true; 132 CellType m = bigType(cx, cy); 133 if(isBonus(m)) return true; 134 return false; 135 } 136 tryToGoOBomber137 void tryToGo(int k) { 138 int rx = x + kx[k] * (384 + 128); 139 int ry = y + ky[k] * (384 + 128); 140 bool u0 = checkGo(rx - ky[k] * 384, ry + kx[k] * 384); 141 bool u1 = checkGo(rx + ky[k] * 384, ry - kx[k] * 384); 142 if(u0 && u1) { 143 x += kx[k] * 128; 144 y += ky[k] * 128; 145 } 146 } 147 goOBomber148 void go() { 149 for(int k=0; k<4; k++) if(g.pl[owner]->key[k]) tryToGo(k); 150 time += spd()/2; 151 int nx = DeCtr(x); 152 int ny = DeCtr(y); 153 CellType m = bigType(nx, ny); 154 if(isBonus(m)) { 155 switch(m) { 156 case cBonusAmmo: 157 d.playSoundAt(d.sndRed, nx, ny); 158 ow()->score += scoreGain(); 159 ow()->gainAmmo(); 160 break; 161 case cBonusLevel: 162 d.playSoundAt(d.sndBlue, nx, ny); 163 ow()->score += scoreGain() * 10; 164 ow()->level++; 165 break; 166 case cBonusScore: 167 d.playSoundAt(d.sndGreen, nx, ny); 168 ow()->score += scoreGain(); 169 ow()->typeval += gc.bombBonusRange; 170 break; 171 } 172 if(gc.regenerate(m)) placeBigRandomly(m, 0); 173 clearBig(nx, ny, cFree, 0); 174 } 175 if(g.map[ny][nx] != cFree && g.map[ny][nx] != cBomb1 && g.map[ny][nx] != cBomb2) { 176 d.playSoundAt(d.sndDeath, nx, ny); 177 killedBy(g.owner[ny][nx]); 178 return; 179 } 180 } 181 drawOBomber182 void draw() { 183 DIc(icBomber).drawAtCentered(CTG(x), CTG(y)); 184 } reactToKeyOBomber185 void reactToKey(PlayerKey pk, bool pressed) { 186 if(!pressed) return; 187 int nx = DeCtr(x); 188 int ny = DeCtr(y); 189 if(pk == keyFire && g.map[ny][nx] == cFree && ow()->useAmmo()) { 190 d.playSoundAt(d.sndPlace, nx, ny); 191 new OBomb(owner, nx, ny, 50 * spd(), ow()->typeval); 192 } 193 } reactToBulletOBomber194 bool reactToBullet(OBullet *bullet) { 195 if(calcDistance(x-bullet->x, y-bullet->y) < 512) { 196 d.playSoundAt(d.sndDeath, x, y); 197 killedBy(bullet->owner); 198 return true; 199 } 200 return false; 201 } reactToCannonOBomber202 void reactToCannon(OCannonball *ball) { 203 if(calcDistance(x-ball->tx, y-ball->ty) < 512 + 512) { 204 d.playSoundAt(d.sndDeath, x, y); 205 killedBy(ball->owner); 206 } 207 } reactToThrusterOBomber208 bool reactToThruster(OThruster *enemy) { 209 if(calcDistance(x-enemy->x, y-enemy->y) < 512 + 1024) { 210 d.playSoundAt(d.sndDeath, x, y); 211 killedBy(enemy->owner); 212 // thruster is larger... it survives 213 } 214 return false; 215 } smashedByBallOBomber216 bool smashedByBall(OBall *enemy) { 217 if(calcDistance(x-enemy->x, y-enemy->y) < 512 + 512) { 218 d.playSoundAt(d.sndDeath, x, y); 219 killedBy(enemy->owner); 220 return true; 221 } 222 return false; 223 } catchesRopeOBomber224 bool catchesRope(int rx, int ry) { 225 if(calcDistance(x-rx, y-ry) < 512) { 226 return true; 227 } 228 return false; 229 } 230 void pullRope(OWorm *worm, int ddx, int ddy); 231 }; 232