Unified Messaging Subsystem
[supertux.git] / src / player_status.cpp
1 //  $Id$
2 //
3 //  SuperTux -  A Jump'n Run
4 //  Copyright (C) 2003 Tobias Glaesser <tobi.web@gmx.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (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 #include <config.h>
20
21 #include "lisp/writer.hpp"
22 #include "lisp/lisp.hpp"
23 #include "player_status.hpp"
24 #include "resources.hpp"
25 #include "gettext.hpp"
26 #include "video/drawing_context.hpp"
27 #include "audio/sound_manager.hpp"
28 #include "sprite/sprite_manager.hpp"
29 #include "math/vector.hpp"
30 #include "main.hpp"
31 #include "msg.hpp"
32
33 static const int START_LIVES = 4;
34 static const int MAX_LIVES = 99;
35
36 PlayerStatus* player_status = 0;
37
38 PlayerStatus::PlayerStatus()
39   : coins(0),
40     lives(START_LIVES),
41     bonus(NO_BONUS),
42     score_multiplier(1),
43     max_score_multiplier(1)
44 {
45   reset();
46   key_brass = sprite_manager->create("images/objects/keys/key_brass.sprite");
47   key_iron = sprite_manager->create("images/objects/keys/key_iron.sprite");
48   key_bronze = sprite_manager->create("images/objects/keys/key_bronze.sprite");
49   key_silver = sprite_manager->create("images/objects/keys/key_silver.sprite");
50   key_gold = sprite_manager->create("images/objects/keys/key_gold.sprite");
51   key_brass->set_action("outline");
52   key_iron->set_action("outline");
53   key_bronze->set_action("outline");
54   key_silver->set_action("outline");
55   key_gold->set_action("outline");
56 }
57
58 PlayerStatus::~PlayerStatus()
59 {
60   delete key_brass;
61   delete key_iron;
62   delete key_bronze;
63   delete key_silver;
64   delete key_gold;
65 }
66
67 void PlayerStatus::reset()
68 {
69   coins = 0;
70   keys = 0;
71   lives = START_LIVES;
72   bonus = NO_BONUS;
73   score_multiplier = 1;
74   max_score_multiplier = 1;
75 }
76
77 void
78 PlayerStatus::incLives()
79 {
80   if(lives < MAX_LIVES)
81     ++lives;
82   sound_manager->play("sounds/lifeup.wav");
83 }
84
85 void
86 PlayerStatus::incCoins()
87 {
88   coins++;
89   if(coins >= 100) {
90     incLives();
91     coins = 0;
92   }
93   sound_manager->play("sounds/coin.wav");
94 }
95
96 void
97 PlayerStatus::set_keys(int new_key)
98 {
99   keys |= new_key;
100   key_brass->set_action(keys & KEY_BRASS ? "display" : "outline");
101   key_iron->set_action(keys & KEY_IRON ? "display" : "outline");
102   key_bronze->set_action(keys & KEY_BRONZE ? "display" : "outline");
103   key_silver->set_action(keys & KEY_SILVER ? "display" : "outline");
104   key_gold->set_action(keys & KEY_GOLD ? "display" : "outline");
105 }
106
107 void
108 PlayerStatus::write(lisp::Writer& writer)
109 {
110   switch(bonus) {
111     case NO_BONUS:
112       writer.write_string("bonus", "none");
113       break;
114     case GROWUP_BONUS:
115       writer.write_string("bonus", "growup");
116       break;
117     case FIRE_BONUS:
118       writer.write_string("bonus", "fireflower");
119       break;
120     case ICE_BONUS:
121       writer.write_string("bonus", "iceflower");
122       break;
123     default:
124       msg_warning("Unknown bonus type.");
125       writer.write_string("bonus", "none");
126   }
127   writer.write_bool("key-brass", keys & KEY_BRASS);
128   writer.write_bool("key-iron", keys & KEY_IRON);
129   writer.write_bool("key-bronze", keys & KEY_BRONZE);
130   writer.write_bool("key-silver", keys & KEY_SILVER);
131   writer.write_bool("key-gold", keys & KEY_GOLD);
132
133   writer.write_int("lives", lives);
134   writer.write_int("coins", coins);
135   writer.write_int("max-score-multiplier", max_score_multiplier);
136 }
137
138 void
139 PlayerStatus::read(const lisp::Lisp& lisp)
140 {
141   reset();
142   
143   std::string bonusname;
144   if(lisp.get("bonus", bonusname)) {
145     if(bonusname == "none") {
146       bonus = NO_BONUS;
147     } else if(bonusname == "growup") {
148       bonus = GROWUP_BONUS;
149     } else if(bonusname == "fireflower") {
150       bonus = FIRE_BONUS;
151     } else if(bonusname == "iceflower") {
152       bonus = ICE_BONUS;
153     } else {
154       msg_warning("Unknown bonus '" << bonusname << "' in savefile");
155       bonus = NO_BONUS;
156     }
157   }
158   bool val = false;
159   if(lisp.get("key-brass", val) && val == true)
160     set_keys(KEY_BRASS);
161   if(lisp.get("key-iron", val) && val == true)
162     set_keys(KEY_IRON);
163   if(lisp.get("key-bronze", val) && val == true)
164     set_keys(KEY_BRONZE);
165   if(lisp.get("key-silver", val) && val == true)
166     set_keys(KEY_SILVER);
167   if(lisp.get("key-gold", val) && val == true)
168     set_keys(KEY_GOLD);
169
170   lisp.get("lives", lives);
171   lisp.get("coins", coins);
172   lisp.get("max-score-multiplier", max_score_multiplier);
173 }
174
175 void
176 PlayerStatus::draw_keys(DrawingContext& context)
177 {
178   const float SPACING = 10;
179   float x,y; 
180   x = BORDER_X; y = BORDER_Y;
181   key_brass->draw(context, Vector(x, y), LAYER_FOREGROUND1);
182   x += key_brass->get_width() + SPACING;
183   key_iron->draw(context, Vector(x, y), LAYER_FOREGROUND1);
184   x += key_iron->get_width() + SPACING;
185   key_bronze->draw(context, Vector(x, y), LAYER_FOREGROUND1);
186   x += key_bronze->get_width() + SPACING;
187   key_silver->draw(context, Vector(x, y), LAYER_FOREGROUND1);
188   x += key_silver->get_width() + SPACING;
189   key_gold->draw(context, Vector(x, y), LAYER_FOREGROUND1);
190   x += key_gold->get_width() + SPACING;
191 }
192
193 void
194 PlayerStatus::draw(DrawingContext& context)
195 {
196   context.push_transform();
197   context.set_translation(Vector(0, 0));
198
199   char str[60];
200   
201   sprintf(str, " %d", player_status->coins);
202   const char* coinstext = _("COINS");
203   context.draw_text(white_text, coinstext,
204       Vector(SCREEN_WIDTH - white_text->get_text_width(coinstext) 
205               - white_text->get_text_width("   99") - BORDER_X, BORDER_Y),
206       LEFT_ALLIGN, LAYER_FOREGROUND1);
207   context.draw_text(gold_text, str,
208       Vector(SCREEN_WIDTH - gold_text->get_text_width(" 99") - BORDER_X, BORDER_Y),
209       LEFT_ALLIGN, LAYER_FOREGROUND1);
210
211   if (player_status->lives >= 5) {
212     sprintf(str, "%dx", player_status->lives);
213     float x = SCREEN_WIDTH - gold_text->get_text_width(str) - tux_life->get_width();
214     context.draw_text(gold_text, str, Vector(x - BORDER_X, BORDER_Y + 20), LEFT_ALLIGN,
215                       LAYER_FOREGROUND1);
216     context.draw_surface(tux_life, Vector(SCREEN_WIDTH - 16 - BORDER_X, BORDER_Y + 20),
217                          LAYER_FOREGROUND1);
218   } else {
219     for(int i= 0; i < player_status->lives; ++i)
220       context.draw_surface(tux_life, 
221           Vector(SCREEN_WIDTH - tux_life->get_width()*4 +(tux_life->get_width()*i) - BORDER_X,
222                  BORDER_Y + 20),
223           LAYER_FOREGROUND1);
224   }
225
226   const char* livestext = _("LIVES");
227   context.draw_text(white_text, livestext,
228       Vector(SCREEN_WIDTH - white_text->get_text_width(livestext) 
229                 - white_text->get_text_width("   99") - BORDER_X, BORDER_Y + 20),
230       LEFT_ALLIGN, LAYER_FOREGROUND1);
231   
232   draw_keys(context);  
233
234   context.pop_transform();
235 }
236
237 void
238 PlayerStatus::operator= (const PlayerStatus& other)
239 {
240   coins = other.coins;
241   lives = other.lives;
242   bonus = other.bonus;
243   score_multiplier = other.score_multiplier;
244   max_score_multiplier = other.max_score_multiplier;
245   keys = other.keys;
246 }
247