void
Console::parse(std::string s)
{
+ for (std::list<ConsoleCommandReceiver*>::iterator i = commandReceivers.begin(); i != commandReceivers.end(); i++) {
+ ConsoleCommandReceiver* ccr = *i;
+ if (ccr->consoleCommand(s) == true) return;
+ }
addLine("unknown command: \"" + s + "\"");
}
}
}
+void
+Console::registerCommandReceiver(ConsoleCommandReceiver* ccr)
+{
+ commandReceivers.push_front(ccr);
+}
+
+void
+Console::unregisterCommandReceiver(ConsoleCommandReceiver* ccr)
+{
+ std::list<ConsoleCommandReceiver*>::iterator i = find(commandReceivers.begin(), commandReceivers.end(), ccr);
+ if (i != commandReceivers.end()) commandReceivers.erase(i);
+}
+
int Console::height = 0;
bool Console::focused = false;
std::list<std::string> Console::lines;
+std::list<ConsoleCommandReceiver*> Console::commandReceivers;
ConsoleStreamBuffer Console::inputBuffer;
ConsoleStreamBuffer Console::outputBuffer;
std::ostream Console::input(&Console::inputBuffer);
class Console;
class ConsoleStreamBuffer;
+class ConsoleCommandReceiver;
class DrawingContext;
class Surface;
static void show(); /**< display the console */
static void hide(); /**< hide the console */
static bool hasFocus(); /**< true if characters should be sent to the console instead of their normal target */
+ static void registerCommandReceiver(ConsoleCommandReceiver* ccr); /**< register instance to notify of commands entered in the console */
+ static void unregisterCommandReceiver(ConsoleCommandReceiver* ccr); /**< new commands should no longer be sent to this ccr */
protected:
static std::list<std::string> lines; /**< backbuffer of lines sent to the console */
+ static std::list<ConsoleCommandReceiver*> commandReceivers; /**< list of instances to notify of new console commands */
DrawingContext* context; /**< context to draw to */
Surface* background; /**< console background image */
static int height; /**< height of the console in px */
}
};
-#endif
-
+class ConsoleCommandReceiver
+{
+ public:
+ ConsoleCommandReceiver()
+ {
+ //Console::registerCommandReceiver(this);
+ }
+ virtual bool consoleCommand(std::string command) = 0; /**< callback from Console; return false if command was unknown, true otherwise */
+ virtual ~ConsoleCommandReceiver()
+ {
+ //Console::unregisterCommandReceiver(this);
+ }
+};
+#endif
: wait_for_key(-1), wait_for_joybutton(-1), key_options_menu(0),
joystick_options_menu(0)
{
- memset(last_keys, 0, sizeof(last_keys));
-
// initialize default keyboard map
keymap.insert(std::make_pair(SDLK_LEFT, LEFT));
keymap.insert(std::make_pair(SDLK_RIGHT, RIGHT));
JoystickKeyboardController::reset()
{
Controller::reset();
- for(size_t i = 0; i < sizeof(last_keys); ++i)
- last_keys[i] = 0;
}
void
switch(event.type) {
case SDL_KEYUP:
case SDL_KEYDOWN:
- // remember ascii keys for cheat codes...
- if(event.type == SDL_KEYDOWN &&
- (event.key.keysym.unicode & 0xFF80) == 0) {
- memmove(last_keys, last_keys+1, sizeof(last_keys)-1);
- last_keys[sizeof(last_keys)-1] = event.key.keysym.unicode;
-
+ if(event.type == SDL_KEYDOWN && (event.key.keysym.unicode & 0xFF80) == 0) {
if (Console::hasFocus()) {
// if the Console is open, send keys there
char c = event.key.keysym.unicode;
Console::show();
}
}
-
- if(GameSession::current() != NULL)
- GameSession::current()->try_cheats();
}
if(Console::hasFocus()) {
return joystick_options_menu;
}
-bool
-JoystickKeyboardController::check_cheatcode(const std::string& cheatcode)
-{
- if(cheatcode.size() > sizeof(last_keys)) {
- msg_debug("Cheat Code too long");
- return false;
- }
-
- for(size_t i = 0; i < cheatcode.size(); ++i) {
- if(last_keys[sizeof(last_keys)-1 - i] != cheatcode[cheatcode.size()-1-i])
- return false;
- }
- return true;
-}
-
//----------------------------------------------------------------------------
JoystickKeyboardController::KeyboardMenu::KeyboardMenu(
void write(lisp::Writer& writer);
void read(const lisp::Lisp& lisp);
- bool check_cheatcode(const std::string& cheatcode);
void reset();
Menu* get_key_options_menu();
JoystickMenu* joystick_options_menu;
friend class KeyboardMenu;
friend class JoystickMenu;
-
- char last_keys[20];
};
#endif
context = new DrawingContext();
console = new Console(context);
+ Console::registerCommandReceiver(this);
restart_level();
}
delete end_sequence_controller;
delete level;
delete context;
+ Console::unregisterCommandReceiver(this);
delete console;
current_ = NULL;
}
}
-void
-GameSession::try_cheats()
+bool
+GameSession::consoleCommand(std::string command)
{
- if(currentsector == 0)
- return;
+ if (command == "foo") {
+ msg_info("bar");
+ return true;
+ }
+
+ if (currentsector == 0) return false;
Player& tux = *currentsector->player;
// Cheating words (the goal of this is really for debugging,
// but could be used for some cheating, nothing wrong with that)
- if(main_controller->check_cheatcode("grow")) {
+ if (command == "grow") {
tux.set_bonus(GROWUP_BONUS, false);
+ return true;
}
- if(main_controller->check_cheatcode("fire")) {
+ if (command == "fire") {
tux.set_bonus(FIRE_BONUS, false);
+ return true;
}
- if(main_controller->check_cheatcode("ice")) {
+ if (command == "ice") {
tux.set_bonus(ICE_BONUS, false);
+ return true;
}
- if(main_controller->check_cheatcode("lifeup")) {
+ if (command == "lifeup") {
player_status->lives++;
+ return true;
}
- if(main_controller->check_cheatcode("lifedown")) {
+ if (command == "lifedown") {
player_status->lives--;
+ return true;
}
- if(main_controller->check_cheatcode("grease")) {
+ if (command == "grease") {
tux.physic.set_velocity_x(tux.physic.get_velocity_x()*3);
+ return true;
}
- if(main_controller->check_cheatcode("invincible")) {
+ if (command == "invincible") {
// be invincle for the rest of the level
tux.invincible_timer.start(10000);
+ return true;
}
- if(main_controller->check_cheatcode("mortal")) {
+ if (command == "mortal") {
// give up invincibility
tux.invincible_timer.stop();
+ return true;
}
- if(main_controller->check_cheatcode("shrink")) {
+ if (command == "shrink") {
// remove powerups
tux.kill(tux.SHRINK);
+ return true;
}
- if(main_controller->check_cheatcode("kill")) {
+ if (command == "kill") {
// kill Tux, but without losing a life
player_status->lives++;
tux.kill(tux.KILL);
+ return true;
}
- if(main_controller->check_cheatcode("whereami")) {
+ if (command == "whereami") {
msg_info("You are at x " << tux.get_pos().x << ", y " << tux.get_pos().y);
+ return true;
}
#if 0
- if(main_controller->check_cheatcode("grid")) {
+ if(command == "grid")) {
// toggle debug grid
debug_grid = !debug_grid;
+ return true;
}
#endif
- if(main_controller->check_cheatcode("gotoend")) {
+ if (command == "gotoend") {
// goes to the end of the level
tux.move(Vector(
(currentsector->solids->get_width()*32) - (SCREEN_WIDTH*2), 0));
currentsector->camera->reset(
Vector(tux.get_pos().x, tux.get_pos().y));
+ return true;
}
- if(main_controller->check_cheatcode("flip")) {
+ if (command == "flip") {
FlipLevelTransformer flip_transformer;
flip_transformer.transform(GameSession::current()->get_current_level());
+ return true;
}
- if(main_controller->check_cheatcode("finish")) {
+ if (command == "finish") {
// finish current sector
exit_status = ES_LEVEL_FINISHED;
// don't add points to stats though...
+ return true;
}
- if(main_controller->check_cheatcode("camera")) {
+ if (command == "camera") {
msg_info("Camera is at "
<< Sector::current()->camera->get_translation().x << ","
<< Sector::current()->camera->get_translation().y);
+ return true;
}
+
+ return false;
}
void
/** The GameSession class controlls the controll flow of a World, ie.
present the menu on specifc keypresses, render and update it while
keeping the speed and framerate sane, etc. */
-class GameSession
+class GameSession : public ConsoleCommandReceiver
{
public:
enum ExitStatus { ES_NONE, ES_LEVEL_FINISHED, ES_GAME_OVER, ES_LEVEL_ABORT };
{ return level; }
void start_sequence(const std::string& sequencename);
- /// called by JoystickKeyboardController after an ascii key has been pressed
- void try_cheats();
/** returns the "working directory" usually this is the directory where the
* currently played level resides. This is used when locating additional
* resources for the current level/world
*/
std::string get_working_directory();
-
+ bool consoleCommand(std::string command); /**< callback from Console; return false if command was unknown, true otherwise */
+
private:
void restart_level();