#
# SuperTux -coop patch
-# Copyright (C) 2007 Christoph Sommer <christoph.sommer@2007.expires.deltadevelopment.de>
+# Copyright (C) 2007,2008 Christoph Sommer <christoph.sommer@2007.expires.deltadevelopment.de>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# Installing the patch should be pretty straightforward. Simply run the
# following command prior to running jam:
#
-# patch -p0 < contrib/supertux-coop.diff
+# patch -p1 < contrib/supertux-coop.diff
#
-# This patch works for revision 4866. It may break for later revisions.
+# This patch works for revision 5236. It may break for later revisions.
#
# -----------------------------------------------------------------------------
-Index: src/control/joystickkeyboardcontroller.cpp
-===================================================================
---- src/control/joystickkeyboardcontroller.cpp (revision 4856)
-+++ src/control/joystickkeyboardcontroller.cpp (working copy)
-@@ -29,6 +29,7 @@
+diff --git a/src/control/joystickkeyboardcontroller.cpp b/src/control/joystickkeyboardcontroller.cpp
+index c0ca307..93cbb7c 100644
+--- a/src/control/joystickkeyboardcontroller.cpp
++++ b/src/control/joystickkeyboardcontroller.cpp
+@@ -30,6 +30,7 @@
#include "game_session.hpp"
#include "console.hpp"
#include "gameconfig.hpp"
+#include "main.hpp"
- class JoystickKeyboardController::JoystickMenu : public Menu
- {
-@@ -339,7 +340,7 @@
-
- ButtonMap::iterator i = joy_button_map.find(event.jbutton.button);
- if(i == joy_button_map.end()) {
-- log_debug << "Unmapped joybutton " << (int)event.jbutton.button << " pressed" << std::endl;
-+ //log_debug << "Unmapped joybutton " << (int)event.jbutton.button << " pressed" << std::endl;
- return;
- }
+ namespace{
+ const int SCAN_JOYSTICKS = Controller::CONTROLCOUNT + 1;
+@@ -502,11 +503,11 @@ JoystickKeyboardController::process_key_event(const SDL_Event& event)
+ KeyMap::iterator key_mapping = keymap.find(event.key.keysym.sym);
-@@ -360,13 +361,13 @@
// if console key was pressed: toggle console
- if ((key_mapping != keymap.end()) && (key_mapping->second == CONSOLE)) {
- if (event.type != SDL_KEYDOWN) return;
-- Console::instance->toggle();
-+ if (this == main_controller) Console::instance->toggle();
- return;
- }
-
- // if console is open: send key there
- if (Console::instance->hasFocus()) {
-- process_console_key_event(event);
-+ if (this == main_controller) process_console_key_event(event);
- return;
- }
-
-@@ -378,7 +379,7 @@
-
- // default action: update controls
- if(key_mapping == keymap.end()) {
-- log_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl;
-+ //log_debug << "Key " << event.key.keysym.sym << " is unbound" << std::endl;
- return;
- }
- Control control = key_mapping->second;
-Index: src/options_menu.cpp
-===================================================================
---- src/options_menu.cpp (revision 4856)
-+++ src/options_menu.cpp (working copy)
-@@ -58,6 +58,8 @@
- }
- add_submenu(_("Setup Keyboard"), main_controller->get_key_options_menu());
- add_submenu(_("Setup Joystick"),main_controller->get_joystick_options_menu());
-+ add_submenu(std::string(_("Setup Keyboard"))+" (P2)", secondary_controller->get_key_options_menu());
-+ add_submenu(std::string(_("Setup Joystick"))+" (P2)", secondary_controller->get_joystick_options_menu());
- add_hl();
- add_back(_("Back"));
- }
-Index: src/main.hpp
-===================================================================
---- src/main.hpp (revision 4856)
-+++ src/main.hpp (working copy)
-@@ -31,5 +31,6 @@
- // global variables
- class JoystickKeyboardController;
- extern JoystickKeyboardController* main_controller;
-+extern JoystickKeyboardController* secondary_controller;
-
- #endif
-Index: src/game_session.cpp
-===================================================================
---- src/game_session.cpp (revision 4856)
-+++ src/game_session.cpp (working copy)
-@@ -117,6 +117,7 @@
+- if ((key_mapping != keymap.end()) && (key_mapping->second == CONSOLE)) {
++ if ((key_mapping != keymap.end()) && (key_mapping->second == CONSOLE) && (this == main_controller)) {
+ if (event.type == SDL_KEYDOWN)
+ Console::instance->toggle();
+ } else {
+- if (Console::instance->hasFocus()) {
++ if (Console::instance->hasFocus() && (this == main_controller)) {
+ // if console is open: send key there
+ process_console_key_event(event);
+ } else if (Menu::current()) {
+diff --git a/src/game_session.cpp b/src/game_session.cpp
+index f6cf505..93f85da 100644
+--- a/src/game_session.cpp
++++ b/src/game_session.cpp
+@@ -126,6 +126,7 @@ GameSession::restart_level()
end_sequence = 0;
main_controller->reset();
currentsector = 0;
-@@ -542,9 +543,11 @@
-
- // TODO make a screen out of this, another mainloop is ugly
- main_controller->update();
-+ secondary_controller->update();
- SDL_Event event;
- while (SDL_PollEvent(&event)) {
- main_controller->process_event(event);
-+ secondary_controller->process_event(event);
- if(event.type == SDL_QUIT)
- main_loop->quit();
- }
-Index: src/mainloop.cpp
-===================================================================
---- src/mainloop.cpp (revision 4856)
-+++ src/mainloop.cpp (working copy)
-@@ -166,9 +166,11 @@
- MainLoop::process_events()
- {
- main_controller->update();
-+ secondary_controller->update();
- SDL_Event event;
- while(SDL_PollEvent(&event)) {
- main_controller->process_event(event);
-+ secondary_controller->process_event(event);
- if(Menu::current() != NULL)
- Menu::current()->event(event);
- if(event.type == SDL_QUIT)
-Index: src/object/player.cpp
-===================================================================
---- src/object/player.cpp (revision 4856)
-+++ src/object/player.cpp (working copy)
-@@ -116,6 +116,7 @@
- {
- this->name = name;
- controller = main_controller;
-+ if (name == "Penny") controller = secondary_controller;
- smalltux_gameover = sprite_manager->create("images/creatures/tux_small/smalltux-gameover.sprite");
- smalltux_star = sprite_manager->create("images/creatures/tux_small/smalltux-star.sprite");
- bigtux_star = sprite_manager->create("images/creatures/tux_big/bigtux-star.sprite");
-@@ -875,6 +876,9 @@
-
- int layer = LAYER_OBJECTS + 1;
-
-+ // draw second player behind main player
-+ if (name == "Penny") layer -= 20;
-+
- /* Set Tux sprite action */
- if (climbing)
- {
-@@ -1049,6 +1053,12 @@
- return FORCE_MOVE;
+@@ -506,6 +507,22 @@ GameSession::update(float elapsed_time)
+ game_pause = false;
}
-+ // Multiple Players pass through one another
-+ Player* player = dynamic_cast<Player*> (&other);
-+ if(player) {
-+ return FORCE_MOVE;
++ // two-player hack: resurrect Penny when she dies
++ Player* tux = currentsector->player;
++ for(std::vector<GameObject*>::iterator i = currentsector->gameobjects.begin(); i != currentsector->gameobjects.end(); ++i) {
++ Player* p = dynamic_cast<Player*>(*i);
++ if (!p) continue;
++ if (p == tux) continue;
++ if (p->is_dead()) {
++ p->remove_me();
++ static PlayerStatus* ps = new PlayerStatus();
++ p = new Player(ps, "Penny");
++ currentsector->add_object(p);
++ p->move(tux->get_pos());
++ p->safe_timer.start(TUX_SAFE_TIME);
++ }
+ }
+
- if(hit.left || hit.right) {
- try_grab(); //grab objects right now, in update it will be too late
- }
-@@ -1141,6 +1151,8 @@
- dying_timer.start(3.0);
- set_group(COLGROUP_DISABLED);
+ check_end_conditions();
-+ if (name == "Penny") return;
-+
- DisplayEffect* effect = new DisplayEffect();
- effect->fade_out(3.0);
- Sector::current()->add_object(effect);
-Index: src/gameconfig.cpp
-===================================================================
---- src/gameconfig.cpp (revision 4856)
-+++ src/gameconfig.cpp (working copy)
-@@ -86,6 +86,10 @@
+ // respawning in new sector?
+diff --git a/src/gameconfig.cpp b/src/gameconfig.cpp
+index 289b6a2..65e8ce2 100644
+--- a/src/gameconfig.cpp
++++ b/src/gameconfig.cpp
+@@ -108,6 +108,10 @@ Config::load()
if(config_control_lisp && main_controller) {
main_controller->read(*config_control_lisp);
}
+ if(config_control_lisp2 && secondary_controller) {
+ secondary_controller->read(*config_control_lisp2);
+ }
- }
- void
-@@ -116,6 +120,11 @@
+ const lisp::Lisp* config_addons_lisp = config_lisp->get_lisp("addons");
+ if(config_addons_lisp) {
+@@ -152,6 +156,11 @@ Config::save()
main_controller->write(writer);
writer.end_list("control");
}
+ writer.end_list("control-p2");
+ }
- writer.end_list("supertux-config");
- }
-Index: src/main.cpp
-===================================================================
---- src/main.cpp (revision 4856)
-+++ src/main.cpp (working copy)
-@@ -58,6 +58,7 @@
-
- SDL_Surface* screen = 0;
+ writer.start_list("addons");
+ AddonManager::get_instance().write_config(writer);
+diff --git a/src/main.cpp b/src/main.cpp
+index fedbe0c..af6dfb6 100644
+--- a/src/main.cpp
++++ b/src/main.cpp
+@@ -65,6 +65,7 @@ namespace supertux_apple {
+ namespace { DrawingContext *context_pointer; }
+ SDL_Surface *screen;
JoystickKeyboardController* main_controller = 0;
+JoystickKeyboardController* secondary_controller = 0;
TinyGetText::DictionaryManager dictionary_manager;
int SCREEN_WIDTH;
-@@ -514,6 +515,7 @@
+@@ -541,6 +542,7 @@ int main(int argc, char** argv)
timelog("controller");
main_controller = new JoystickKeyboardController();
+ secondary_controller = new JoystickKeyboardController();
+
timelog("config");
init_config();
- timelog("tinygettext");
-@@ -587,7 +589,9 @@
+@@ -629,7 +631,9 @@ int main(int argc, char** argv)
delete config;
config = NULL;
delete main_controller;
delete Console::instance;
Console::instance = NULL;
Scripting::exit_squirrel();
-Index: src/sector.cpp
-===================================================================
---- src/sector.cpp (revision 4856)
-+++ src/sector.cpp (working copy)
-@@ -74,11 +74,21 @@
+diff --git a/src/main.hpp b/src/main.hpp
+index 92c1752..917c7f2 100644
+--- a/src/main.hpp
++++ b/src/main.hpp
+@@ -36,5 +36,6 @@ extern int SCREEN_HEIGHT;
+ // global variables
+ class JoystickKeyboardController;
+ extern JoystickKeyboardController* main_controller;
++extern JoystickKeyboardController* secondary_controller;
+
+ #endif
+diff --git a/src/mainloop.cpp b/src/mainloop.cpp
+index ca6ba5e..402737f 100644
+--- a/src/mainloop.cpp
++++ b/src/mainloop.cpp
+@@ -180,11 +180,13 @@ void
+ MainLoop::process_events()
+ {
+ main_controller->update();
++ secondary_controller->update();
+ Uint8* keystate = SDL_GetKeyState(NULL);
+ SDL_Event event;
+ while(SDL_PollEvent(&event))
+ {
+ main_controller->process_event(event);
++ secondary_controller->process_event(event);
+
+ if(Menu::current() != NULL)
+ Menu::current()->event(event);
+diff --git a/src/object/player.cpp b/src/object/player.cpp
+index 709aebd..5c4b96d 100644
+--- a/src/object/player.cpp
++++ b/src/object/player.cpp
+@@ -117,6 +117,7 @@ Player::Player(PlayerStatus* _player_status, const std::string& name)
+ {
+ this->name = name;
+ controller = main_controller;
++ if (name == "Penny") controller = secondary_controller;
+ scripting_controller = new CodeController();
+ sprite = sprite_manager->create("images/creatures/tux/tux.sprite");
+ airarrow.reset(new Surface("images/engine/hud/airarrow.png"));
+@@ -958,6 +959,13 @@ Player::draw(DrawingContext& context)
+ else
+ sa_prefix = "small";
+
++ // two-player hack: draw Penny in a different color
++ if (name == "Penny") {
++ sprite->set_color(Color(1.0f, 1.0f, 0.5f, 1.0f));
++ } else {
++ sprite->set_color(Color(1.0f, 1.0f, 1.0f, 1.0f));
++ }
++
+ /* Set Tux sprite action */
+ if(dying) {
+ sprite->set_action("gameover");
+@@ -1116,6 +1124,12 @@ Player::collision(GameObject& other, const CollisionHit& hit)
+ return FORCE_MOVE;
+ }
+
++ // Multiple Players pass through one another
++ Player* player = dynamic_cast<Player*> (&other);
++ if(player) {
++ return FORCE_MOVE;
++ }
++
+ if(hit.left || hit.right) {
+ try_grab(); //grab objects right now, in update it will be too late
+ }
+@@ -1217,6 +1231,8 @@ Player::kill(bool completely)
+ dying_timer.start(3.0);
+ set_group(COLGROUP_DISABLED);
+
++ if (name == "Penny") return;
++
+ DisplayEffect* effect = new DisplayEffect();
+ effect->fade_out(3.0);
+ Sector::current()->add_object(effect);
+diff --git a/src/options_menu.cpp b/src/options_menu.cpp
+index ad1eff7..dbd7a49 100644
+--- a/src/options_menu.cpp
++++ b/src/options_menu.cpp
+@@ -223,6 +223,13 @@ OptionsMenu::OptionsMenu()
+
+ add_submenu(_("Setup Joystick"),main_controller->get_joystick_options_menu())
+ ->set_help(_("Configure joystick control-action mappings"));
++
++ add_submenu(_("Setup Keyboard (P2)"), secondary_controller->get_key_options_menu())
++ ->set_help(_("Configure key-action mappings"));
++
++ add_submenu(_("Setup Joystick (P2)"),secondary_controller->get_joystick_options_menu())
++ ->set_help(_("Configure joystick control-action mappings"));
++
+ add_hl();
+ add_back(_("Back"));
+ }
+diff --git a/src/sector.cpp b/src/sector.cpp
+index 1ff1692..c62f632 100644
+--- a/src/sector.cpp
++++ b/src/sector.cpp
+@@ -77,11 +77,21 @@ Sector* Sector::_current = 0;
bool Sector::show_collrects = false;
bool Sector::draw_solids_only = false;
add_object(new DisplayEffect("Effect"));
add_object(new TextObject("Text"));
-@@ -591,6 +601,16 @@
+@@ -610,6 +620,16 @@ Sector::activate(const Vector& player_pos)
player->move(npos);
}
camera->reset(player->get_pos());
update_game_objects();
-@@ -639,6 +659,15 @@
+@@ -670,6 +690,15 @@ Sector::update(float elapsed_time)
{
player->check_bounds(camera);
/* update objects */
for(GameObjects::iterator i = gameobjects.begin();
i != gameobjects.end(); ++i) {
-@@ -721,7 +750,7 @@
+@@ -764,7 +793,7 @@ Sector::before_object_add(GameObject* object)
Player* player = dynamic_cast<Player*> (object);
if(player != NULL) {
if(this->player != 0) {