Based off of mathnerd314's patch to fix issue #327
authorRyan Flegel <rflegel@gmail.com>
Mon, 9 Jun 2008 00:34:21 +0000 (00:34 +0000)
committerRyan Flegel <rflegel@gmail.com>
Mon, 9 Jun 2008 00:34:21 +0000 (00:34 +0000)
- Dispensers can now support multiple badguys instead of just 'random'
- badguys can be dispensed randomly or in sequence
- dispenser type must now be specified as 'dropper', 'rocket-launcher' or 'cannon'. defaults to 'dropper' if not specified.

SVN-Revision: 5539

12 files changed:
data/levels/test/snowslope.stl
data/levels/test_old/direction.stl
data/levels/test_old/noloktest.stl
data/levels/world2/christoph9.stl
data/levels/world2/level2.stl
src/badguy/captainsnowball.cpp
src/badguy/dispenser.cpp
src/badguy/dispenser.hpp
src/direction.cpp [new file with mode: 0644]
src/direction.hpp
src/object_factory.cpp
src/object_factory.hpp

index 4f70c75..510c591 100644 (file)
@@ -31,7 +31,7 @@
       (y 709)
       (random #t)
       (type "cannon")
-      (badguy "kamikazesnowball")
+      (badguy "captainsnowball" "kamikazesnowball")
     )
     (fish
       (x 1954)
index f49da01..0f25b1b 100644 (file)
       (y 128)
     )
     (dispenser
+      (type "rocket-launcher")
       (badguy "mrrocket")
       (cycle 1)
       (direction "left")
       (y 996.4092)
     )
     (dispenser
+      (type "rocket-launcher")
       (badguy "mrrocket")
       (cycle 1)
       (direction "right")
index 4e41281..1f458b1 100644 (file)
@@ -49,7 +49,7 @@
                 (speed 0.5))
     (spawnpoint (name "main2") (x 100) (y 100))
     (secretarea (x 100) (y 100) (message "You found a secret area!"))
-    (dispenser (x 700) (y 500) (badguy "mrrocket") (cycle 2))
+    (dispenser (x 700) (y 500) (type "rocket-launcher") (badguy "mrrocket") (cycle 2))
     (jumpy (x 500) (y 400))
     (tilemap
       (z-pos -100)
index 973162a..5add141 100644 (file)
       (cycle 3)
       (x 1824)
       (y 2348)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (dispenser
       (cycle 3)
       (x 4315.086)
       (y 588.6605)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (dispenser
       (cycle 3)
       (x 2844.737)
       (y 556.2125)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (dispenser
       (cycle 3)
       (x 5498.62)
       (y 1931.435)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (dispenser
       (cycle 4)
       (x 5499.327)
       (y 2347.921)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (dispenser
       (cycle 3)
       (x 1825.651)
       (y 1004.293)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (dispenser
       (cycle 4)
       (x 5499.327)
       (y 2571.367)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (dispenser
       (cycle 3)
       (x 5435.688)
       (y 1997.196)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (dispenser
       (cycle 3)
       (x 1849.266)
       (y 1932.47)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (dispenser
       (cycle 3)
       (x 1825.237)
       (y 1324.32)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (dispenser
       (cycle 3)
       (x 1825.944)
       (y 1164.807)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (firefly
index d114357..1975717 100644 (file)
@@ -22,6 +22,7 @@
       (x 10239)
       (y 165)
       (direction left)
+      (type "rocket-launcher")
       (badguy "mrrocket")
     )
     (door
index f1b433f..1c74ebb 100644 (file)
@@ -30,8 +30,9 @@ namespace{
 CaptainSnowball::CaptainSnowball(const lisp::Lisp& reader)
     : WalkingBadguy(reader, "images/creatures/snowball/cpt-snowball.sprite", "left", "right")
 {
-  walk_speed = WALK_SPEED; // peg leg
-  max_drop_height = -1;// eye patch
+  walk_speed = BOARDING_SPEED;
+  max_drop_height = -1;
+  physic.set_velocity_y(-400);
 }
 
 CaptainSnowball::CaptainSnowball(const Vector& pos, Direction d)
index 2a9d03e..d7c7b4e 100644 (file)
 
 #include "dispenser.hpp"
 #include "object/bullet.hpp"
-#include "badguy/bouncing_snowball.hpp"
-#include "badguy/snowball.hpp"
-#include "badguy/mrbomb.hpp"
-#include "badguy/mriceblock.hpp"
-#include "badguy/mrrocket.hpp"
-#include "badguy/poisonivy.hpp"
-#include "badguy/snail.hpp"
-#include "badguy/skullyhop.hpp"
-#include "badguy/captainsnowball.hpp"
-#include "badguy/kamikazesnowball.hpp"
 #include "random_generator.hpp"
 
 Dispenser::Dispenser(const lisp::Lisp& reader)
@@ -39,21 +29,32 @@ Dispenser::Dispenser(const lisp::Lisp& reader)
   set_colgroup_active(COLGROUP_MOVING_STATIC);
   sound_manager->preload("sounds/squish.wav");
   reader.get("cycle", cycle);
-  reader.get("badguy", badguy);
+  reader.get_vector("badguy", badguys);
+  random = false; // default
+  reader.get("random", random);
+  type = "dropper"; //default
+  reader.get("type", type);
+  next_badguy = 0;
   autotarget = false;
   swivel = false;
   broken = false;
-  if (badguy == "mrrocket") {
-     sprite->set_action(dir == LEFT ? "working-left" : "working-right");
-     set_colgroup_active(COLGROUP_MOVING); //if this were COLGROUP_MOVING_STATIC MrRocket would explode on launch.
-     if( start_dir == AUTO ){
+
+  if (badguys.size() <= 0)
+    throw std::runtime_error("No badguys in dispenser.");
+
+  if (type == "rocket-launcher") {
+    sprite->set_action(dir == LEFT ? "working-left" : "working-right");
+    set_colgroup_active(COLGROUP_MOVING); //if this were COLGROUP_MOVING_STATIC MrRocket would explode on launch.
+
+    if (start_dir == AUTO) {
       autotarget = true;
-     }
-  } else if ( badguy == "kamikazesnowball" ||  badguy == "captainsnowball" ) {
-     sprite->set_action("working");
+    }
+  } else if (type == "cannon") {
+    sprite->set_action("working");
   } else {
     sprite->set_action("dropper");
   }
+
   bbox.set_size(sprite->get_current_hitbox_width(), sprite->get_current_hitbox_height());
   countMe = false;
 }
@@ -66,7 +67,9 @@ Dispenser::write(lisp::Writer& writer)
   writer.write_float("x", start_position.x);
   writer.write_float("y", start_position.y);
   writer.write_float("cycle", cycle);
-  writer.write_string("badguy", badguy);
+  writer.write_bool("random", random);
+  writer.write_string("type", type);
+  writer.write_string_vector("badguy", badguys);
 
   writer.end_list("dispenser");
 }
@@ -100,9 +103,10 @@ Dispenser::collision_squished(GameObject& object)
 {
   //Cannon launching MrRocket can be broken by jumping on it
   //other dispencers are not that fragile.
-  if (broken || badguy != "mrrocket") {
+  if (broken || type != "rocket-launcher") {
     return false;
   }
+
   sprite->set_action(dir == LEFT ? "broken-left" : "broken-right");
   dispense_timer.start(0);
   set_colgroup_active(COLGROUP_MOVING_STATIC); // Tux can stand on broken cannon.
@@ -168,7 +172,6 @@ Dispenser::active_update(float )
   }
 }
 
-//      Add themed randomizer
 void
 Dispenser::launch_badguy()
 {
@@ -181,39 +184,31 @@ Dispenser::launch_badguy()
         launchdir = (player->get_pos().x > get_pos().x) ? RIGHT : LEFT;
       } 
     } 
-    if (badguy == "snowball")
-      Sector::current()->add_object(new SnowBall(Vector(get_pos().x, get_pos().y+32), launchdir));
-    else if (badguy == "bouncingsnowball")
-      Sector::current()->add_object(new BouncingSnowball(Vector(get_pos().x, get_pos().y+32), launchdir));
-    else if (badguy == "mrbomb")
-      Sector::current()->add_object(new MrBomb(Vector(get_pos().x, get_pos().y+32), launchdir));
-    else if (badguy == "mriceblock")
-      Sector::current()->add_object(new MrIceBlock(Vector(get_pos().x, get_pos().y+32), launchdir));
-    else if (badguy == "snail")
-      Sector::current()->add_object(new Snail(Vector(get_pos().x, get_pos().y+32), launchdir));
-    else if (badguy == "mrrocket") 
-      Sector::current()->add_object(new MrRocket(Vector(get_pos().x+(launchdir == LEFT ? -32 : 32), get_pos().y), launchdir));
-    else if (badguy == "captainsnowball")
-      Sector::current()->add_object(new CaptainSnowball(Vector(get_pos().x+(launchdir == LEFT ? -32 : 32), get_pos().y), launchdir));
-    else if (badguy == "kamikazesnowball")
-      Sector::current()->add_object(new KamikazeSnowball(Vector(get_pos().x+(launchdir == LEFT ? -32 : 32), get_pos().y), launchdir));
-    else if (badguy == "poisonivy")
-      Sector::current()->add_object(new PoisonIvy(Vector(get_pos().x, get_pos().y+32), launchdir));
-    else if (badguy == "skullyhop")
-      Sector::current()->add_object(new SkullyHop(Vector(get_pos().x, get_pos().y+44), launchdir));
-    else if (badguy == "random")
-    {
-      switch (systemRandom.rand(7))
-      {
-        case 0: Sector::current()->add_object(new SnowBall(Vector(get_pos().x, get_pos().y+32), launchdir)); break;
-        case 1: Sector::current()->add_object(new BouncingSnowball(Vector(get_pos().x, get_pos().y+32), launchdir)); break;
-        case 2: Sector::current()->add_object(new MrBomb(Vector(get_pos().x, get_pos().y+32), launchdir)); break;
-        case 3: Sector::current()->add_object(new MrIceBlock(Vector(get_pos().x, get_pos().y+32), launchdir)); break;
-        case 4: Sector::current()->add_object(new PoisonIvy(Vector(get_pos().x, get_pos().y+32), launchdir)); break;
-        case 5: Sector::current()->add_object(new Snail(Vector(get_pos().x, get_pos().y+32), launchdir)); break;
-        case 6: Sector::current()->add_object(new SkullyHop(Vector(get_pos().x, get_pos().y+44), launchdir)); break;
+
+    if (badguys.size() > 1) {
+      if (random) {
+        next_badguy = systemRandom.rand(badguys.size());
+      }
+      else {
+        next_badguy++;
+
+        if (next_badguy >= badguys.size())
+          next_badguy = 0;
       }
     }
+
+    std::string badguy = badguys[next_badguy];
+    GameObject* badguy_object = NULL;
+
+    if (type == "dropper")
+      badguy_object = create_badguy_object(badguy, Vector(get_pos().x, get_pos().y+32), launchdir);
+    else if (type == "cannon")
+      badguy_object = create_badguy_object(badguy, Vector(get_pos().x + (launchdir == LEFT ? -32 : 32), get_pos().y), launchdir);
+    else if (type == "rocket-launcher")
+      badguy_object = create_badguy_object(badguy, Vector(get_pos().x + (launchdir == LEFT ? -32 : 32), get_pos().y), launchdir);
+
+    if (badguy_object)
+      Sector::current()->add_object(badguy_object);
   }
 }
 
index 38a26fe..1066078 100644 (file)
@@ -44,11 +44,14 @@ protected:
   HitResponse collision(GameObject& other, const CollisionHit& hit);
   void launch_badguy();
   float cycle;
-  std::string badguy;
+  std::vector<std::string> badguys;
+  unsigned int next_badguy;
   Timer dispense_timer;
   bool autotarget;
   bool swivel;
   bool broken;
+  bool random;
+  std::string type;
 };
 
 #endif
diff --git a/src/direction.cpp b/src/direction.cpp
new file mode 100644 (file)
index 0000000..4ab1ccb
--- /dev/null
@@ -0,0 +1,45 @@
+//  $Id: direction.hpp 5006 2007-05-23 15:27:56Z tuxdev $
+//
+//  SuperTux
+//  Copyright (C) 2008 Ryan Flegel <rflegel@gmail.com>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  of the License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//  GNU General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+//  02111-1307, USA.
+
+#include "direction.hpp"
+
+std::ostream& operator<<(std::ostream& o, const Direction& dir)
+{
+    switch (dir)
+    {
+        case AUTO:
+            o << "auto";
+            break;
+        case LEFT:
+            o << "left";
+            break;
+        case RIGHT:
+            o << "right";
+            break;
+        case UP:
+            o << "up";
+            break;
+        case DOWN:
+            o << "down";
+            break;
+    }
+
+    return o;
+}
index e665d20..f4df937 100644 (file)
 #ifndef SUPERTUX_DIRECTION_H
 #define SUPERTUX_DIRECTION_H
 
+#include <iostream>
+
 enum Direction { AUTO, LEFT, RIGHT, UP, DOWN };
 
+std::ostream& operator<<(std::ostream& o, const Direction& dir);
+
 #endif
index fe89724..667a12f 100644 (file)
@@ -42,13 +42,27 @@ GameObject* create_object(const std::string& name, const lisp::Lisp& reader)
 GameObject* create_object(const std::string& name, const Vector& pos)
 {
   std::stringstream lisptext;
-  lisptext << "(" << name
-           << " (x " << pos.x << ")"
+  lisptext << "((x " << pos.x << ")"
            << " (y " << pos.y << "))";
 
   lisp::Parser parser;
   const lisp::Lisp* lisp = parser.parse(lisptext, "create_object");
-  GameObject* object = create_object(name, *lisp);
+  GameObject* object = create_object(name, *(lisp->get_car()));
 
   return object;
 }
+
+GameObject* create_badguy_object(const std::string& name, const Vector& pos, const Direction dir)
+{
+  std::stringstream lisptext;
+  lisptext << "((x " << pos.x << ")"
+           << " (y " << pos.y << ")"
+           << " (direction " << dir << "))";
+
+  lisp::Parser parser;
+  const lisp::Lisp* lisp = parser.parse(lisptext, "create_object");
+  GameObject* object = create_object(name, *(lisp->get_car()));
+
+  return object;
+}
+
index 0e0d0d3..40445d3 100644 (file)
@@ -23,6 +23,8 @@
 #include <string>
 #include <map>
 
+#include "direction.hpp"
+
 namespace lisp { class Lisp; }
 class Vector;
 class GameObject;
@@ -48,6 +50,7 @@ public:
 
 GameObject* create_object(const std::string& name, const lisp::Lisp& reader);
 GameObject* create_object(const std::string& name, const Vector& pos);
+GameObject* create_badguy_object(const std::string& name, const Vector& pos, Direction dir = LEFT);
 
 /** comment from Matze:
  * Yes I know macros are evil, but in this specific case they save