1 /* modPill.cc
2    A "pill" which gives the player mods when taken
3 
4    Copyright (C) 2000  Mathias Broxvall
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20 
21 #include "modPill.h"
22 
23 #include "debris.h"
24 #include "game.h"
25 #include "mainMode.h"
26 #include "map.h"
27 #include "player.h"
28 #include "sign.h"
29 #include "sound.h"
30 
31 int isGoodPill[NUM_MODS] = {1, 1, 1, 0, 0, 0, 1, 1};
32 
ModPill(Game & g,Real x,Real y,int kind,int time,int resurrecting)33 ModPill::ModPill(Game &g, Real x, Real y, int kind, int time, int resurrecting)
34     : Ball(g, Role_OtherAnimated), kind(kind), resurrecting(resurrecting), time(time) {
35   no_physics = true;
36   realRadius = 0.2;
37   radius = realRadius;
38   is_on = true;
39 
40   /* Change our color to red */
41   primaryColor = Color(1., 0.2, 0.2, 1.0);
42 
43   /* set bogus velocity for the rendering of speed mods */
44   if (kind == MOD_SPEED) {
45     velocity[0] = 0.0;
46     velocity[1] = -1.2;
47   } else {
48     velocity = Coord3d();
49   }
50 
51   modTimeLeft[kind] = -1.0;
52   clock = 0.0;
53 
54   if (kind == MOD_EXTRA_LIFE) {
55     realRadius = 0.3;
56     radius = realRadius;
57     primaryColor = Color(1., 0.9, 0.2, 1.);
58     specularColor = Color(1., 0.9, 0.2, 1.);
59   }
60 
61   position[0] = x;
62   position[1] = y;
63   position[2] = game.map->getHeight(position[0], position[1]) + radius;
64 
65   timeLeft = 0.;
66 }
67 
~ModPill()68 ModPill::~ModPill() {}
69 
tick(Real t)70 void ModPill::tick(Real t) {
71   Animated::tick(t);
72 
73   Player *player = game.player1;
74   if (!is_on) {
75     timeLeft -= t;
76     if (resurrecting > 0.0 && timeLeft < 0) is_on = true;
77   }
78 
79   clock += t;
80   if (kind == MOD_LARGE) {
81     realRadius = 0.2 * (1.0 + std::fmod(clock, 2.0) / 2.0);
82     radius = realRadius;
83   } else if (kind == MOD_SMALL) {
84     realRadius = 0.2 / (1.0 + std::fmod(clock, 2.0) / 2.0);
85     radius = realRadius;
86   }
87 
88   if (is_on && kind == MOD_NITRO) Ball::generateNitroDebris(t);
89 
90   if (is_on) {
91     position[2] = game.map->getHeight(position[0], position[1]) + radius;
92     Coord3d v = player->position - position;
93     double dist = length(v);
94     if (dist < radius + player->radius) {
95       Coord3d signPos = position;
96       signPos[2] += 1.0;
97 
98       /* Explanations of modpills shown after taking them. Note that only bad
99          ones have an exclamation mark after them */
100       const char *modExplanations[NUM_MODS] = {
101           _("Speed ball"), _("Extra jump"), _("Spikes"),   _("Glass ball"),
102           _("Dizzy!"),     _("Freeze!"),    _("Floating"), _("Extra life"),
103           _("Small ball"), _("Large ball"), _("Nitro")};
104       game.add(new Sign(game, modExplanations[kind], 6.0, 1.0, 60.0, signPos));
105 
106       if (kind == MOD_EXTRA_LIFE) {
107         player->lives = std::min(4, player->lives + 1);
108       } else {
109         if (time >= 0.0)
110           player->modTimeLeft[kind] += time;
111         else
112           player->modTimeLeft[kind] = -1.0;
113       }
114 
115       if (kind == MOD_FROZEN) MainMode::mainMode->flash = 2.0;
116 
117       if (kind == MOD_EXTRA_LIFE)
118         playEffect(SFX_GOT_LIFE);
119       else if (isGoodPill[kind])
120         playEffect(SFX_GOT_GOODPILL);
121       else
122         playEffect(SFX_GOT_BADPILL);
123 
124       is_on = false;
125       if (!resurrecting) remove();
126       timeLeft = (Real)resurrecting;
127     }
128   }
129 }
130 
die(int)131 void ModPill::die(int /*how*/) {
132   is_on = false;
133   if (!resurrecting) remove();
134 }
135