diff --git a/data/images/objects/bonus_block/malus-badegg.png b/data/images/objects/bonus_block/malus-badegg.png new file mode 100644 index 00000000000..29bec808a29 Binary files /dev/null and b/data/images/objects/bonus_block/malus-badegg.png differ diff --git a/data/images/powerups/badegg/badegg-shade.png b/data/images/powerups/badegg/badegg-shade.png new file mode 100644 index 00000000000..ac279c81aaf Binary files /dev/null and b/data/images/powerups/badegg/badegg-shade.png differ diff --git a/data/images/powerups/badegg/badegg.png b/data/images/powerups/badegg/badegg.png new file mode 100644 index 00000000000..1f59832a8da Binary files /dev/null and b/data/images/powerups/badegg/badegg.png differ diff --git a/data/images/powerups/badegg/badegg.sprite b/data/images/powerups/badegg/badegg.sprite new file mode 100644 index 00000000000..912c24f2aaa --- /dev/null +++ b/data/images/powerups/badegg/badegg.sprite @@ -0,0 +1,10 @@ +(supertux-sprite + (action + (name "default") + (images "badegg.png") + ) + (action + (name "shadow") + (images "badegg-shade.png") + ) +) diff --git a/data/images/tiles.strf b/data/images/tiles.strf index 2c92e3fe5a2..9d021252df9 100644 --- a/data/images/tiles.strf +++ b/data/images/tiles.strf @@ -21,7 +21,7 @@ ;; next-id: 7949 ;; free/skipped ids (please use before any other): - ;; 4639-4660, 5061-5089, 5268-5283, 5453-5527 + ;; 4641-4660, 5061-5089, 5268-5283, 5453-5527 ;; No group ids are currently skipped! Delete this line if any are and replace it with said ids... (tilegroup @@ -1429,8 +1429,9 @@ 102 140 3161 3162 104 105 3160 7026 3037 2943 2944 2945 - 2946 112 1311 7394 - 7396 7397 7398 7395 + 2946 4640 112 1311 + 7394 7396 7397 7398 + 7395 0 0 0 57 58 2841 2842 59 60 2843 2844 @@ -2143,6 +2144,29 @@ (fps 15) ) + (tile + (id 4640) + (images + "objects/bonus_block/full-0.png" + "objects/bonus_block/full-1.png" + "objects/bonus_block/full-2.png" + "objects/bonus_block/full-3.png" + "objects/bonus_block/full-4.png" + "objects/bonus_block/full-3.png" + "objects/bonus_block/full-2.png" + "objects/bonus_block/full-1.png" + "objects/bonus_block/full-0.png" + "objects/bonus_block/full-0.png" + "objects/bonus_block/full-0.png" + ) + (solid #t) + (object-name "bonusblock") + (object-data "(sprite \"images/objects/bonus_block/bonusblock.sprite\") (data 18)") + (editor-images "objects/bonus_block/malus-badegg.png") + (data 18) + (fps 15) + ) + (tile (id 1) (images diff --git a/src/object/bonus_block.cpp b/src/object/bonus_block.cpp index 273a6f594e9..a5aede019d9 100644 --- a/src/object/bonus_block.cpp +++ b/src/object/bonus_block.cpp @@ -250,6 +250,7 @@ BonusBlock::get_content_by_data(int tile_data) const case 15: return Content::LIGHT_ON; case 16: return Content::RETROGROW; case 17: return Content::RETROSTAR; + case 18: return Content::BADEGG; default: log_warning << "Invalid box contents" << std::endl; return Content::COIN; @@ -265,9 +266,9 @@ BonusBlock::get_settings() result.add_int(_("Count"), &m_hit_counter, "count", get_default_hit_counter()); result.add_enum(_("Content"), reinterpret_cast(&m_contents), { _("Coin"), _("Growth (fire flower)"), _("Growth (ice flower)"), _("Growth (air flower)"), - _("Growth (earth flower)"), _("Growth (retro)"), _("Star"), _("Star (retro)"), _("Tux doll"), _("Custom"), _("Script"), _("Light"), _("Light (On)"), + _("Growth (earth flower)"), _("Growth (retro)"), _("Star"), _("Star (retro)"), _("Tux doll"), _("Rotten egg"), _("Custom"), _("Script"), _("Light"), _("Light (On)"), _("Trampoline"), _("Portable trampoline"), _("Coin rain"), _("Coin explosion"), _("Rock"), _("Potion") }, - { "coin", "firegrow", "icegrow", "airgrow", "earthgrow", "retrogrow", "star", "retrostar", "1up", "custom", "script", "light", "light-on", + { "coin", "firegrow", "icegrow", "airgrow", "earthgrow", "retrogrow", "star", "retrostar", "1up", "badegg", "custom", "script", "light", "light-on", "trampoline", "portabletrampoline", "rain", "explode", "rock", "potion" }, static_cast(Content::COIN), "contents"); @@ -414,6 +415,12 @@ BonusBlock::try_open(Player* player) break; } + case Content::BADEGG: + { + raise_growup_bonus(player, MALUS_BADEGG, direction); + break; + } + case Content::CUSTOM: { auto moving_obj_copy = to_moving_object(GameObjectFactory::instance().create(m_object->get_class_name(), get_pos() + Vector(0, -32), @@ -582,6 +589,12 @@ BonusBlock::try_drop(Player *player) break; } + case Content::BADEGG: + { + drop_growup_bonus(player, PowerUp::BADEGG, direction, countdown); + break; + } + case Content::CUSTOM: { // NOTE: Non-portable trampolines could be moved to Content::CUSTOM, but they should not drop. @@ -656,9 +669,13 @@ BonusBlock::raise_growup_bonus(Player* player, const BonusType& bonus, const Dir const std::string& growup_sprite, const std::string& flower_sprite) { std::unique_ptr obj; - if (player->get_status().bonus[player->get_id()] == BONUS_NONE) + if (bonus == MALUS_BADEGG) + { + obj = std::make_unique(MALUS_BADEGG, get_pos(), dir, growup_sprite); + } + else if (player->get_status().bonus[player->get_id()] == BONUS_NONE) { - obj = std::make_unique(get_pos(), dir, growup_sprite); + obj = std::make_unique(BONUS_GROWUP, get_pos(), dir, growup_sprite); } else { @@ -673,9 +690,13 @@ void BonusBlock::drop_growup_bonus(Player* player, int type, const Direction& dir, bool& countdown, const std::string& growup_sprite) { - if (player->get_status().bonus[player->get_id()] == BONUS_NONE) + if (type == PowerUp::BADEGG) + { + Sector::get().add(MALUS_BADEGG, get_pos() + Vector(0, 32), dir, growup_sprite); + } + else if (player->get_status().bonus[player->get_id()] == BONUS_NONE) { - Sector::get().add(get_pos() + Vector(0, 32), dir, growup_sprite); + Sector::get().add(BONUS_GROWUP, get_pos() + Vector(0, 32), dir, growup_sprite); } else { @@ -720,6 +741,8 @@ BonusBlock::get_content_from_string(const std::string& contentstring) const return Content::RETROSTAR; else if (contentstring == "1up") return Content::ONEUP; + else if (contentstring == "badegg") + return Content::BADEGG; else if (contentstring == "custom") return Content::CUSTOM; else if (contentstring == "script") // Use this when the bonus block is intended to contain ONLY a script. diff --git a/src/object/bonus_block.hpp b/src/object/bonus_block.hpp index f0c9160b5b1..e8aa36d8123 100644 --- a/src/object/bonus_block.hpp +++ b/src/object/bonus_block.hpp @@ -36,6 +36,7 @@ class BonusBlock final : public Block STAR, RETROSTAR, ONEUP, + BADEGG, CUSTOM, SCRIPT, LIGHT, diff --git a/src/object/growup.cpp b/src/object/growup.cpp index e5e1dc6ed40..e35aaada07c 100644 --- a/src/object/growup.cpp +++ b/src/object/growup.cpp @@ -24,21 +24,33 @@ #include "sprite/sprite.hpp" #include "sprite/sprite_manager.hpp" -GrowUp::GrowUp(const Vector& pos, Direction direction, const std::string& custom_sprite) : - MovingSprite(pos, custom_sprite.empty() ? "images/powerups/egg/egg.sprite" : custom_sprite, LAYER_OBJECTS, COLGROUP_MOVING), +GrowUp::GrowUp(BonusType type, const Vector& pos, Direction direction, const std::string& custom_sprite) : + MovingSprite(pos, + !custom_sprite.empty() ? custom_sprite : + (type == BONUS_GROWUP) ? "images/powerups/egg/egg.sprite" : + "images/powerups/badegg/badegg.sprite", + LAYER_OBJECTS, COLGROUP_MOVING + ), + m_growup_type(type), + m_growup_default_sprite((m_growup_type == BONUS_GROWUP) ? "images/powerups/egg/egg.sprite" : "images/powerups/badegg/badegg.sprite"), m_physic(), m_custom_sprite(!custom_sprite.empty()), - m_shadesprite(SpriteManager::current()->create("images/powerups/egg/egg.sprite")), + m_shadesprite(SpriteManager::current()->create(m_growup_default_sprite)), m_lightsprite(SpriteManager::current()->create("images/objects/lightmap_light/lightmap_light-small.sprite")) { m_physic.enable_gravity(true); m_physic.set_velocity_x((direction == Direction::LEFT) ? -100.0f : 100.0f); - SoundManager::current()->preload("sounds/grow.ogg"); // Set the shadow action for the egg sprite, so it remains in place as the egg rolls. m_shadesprite->set_action("shadow"); // Configure the light sprite for the glow effect. m_lightsprite->set_blend(Blend::ADD); - m_lightsprite->set_color(Color(0.2f, 0.2f, 0.0f)); + if (m_growup_type == BONUS_GROWUP) { + m_lightsprite->set_color(Color(0.2f, 0.2f, 0.0f)); + SoundManager::current()->preload("sounds/grow.ogg"); + } else { + m_lightsprite->set_color(Color(0.2f, 0.0f, 0.2f)); + SoundManager::current()->preload("sounds/hurt.wav"); + } } void @@ -84,13 +96,18 @@ GrowUp::collision(MovingObject& other, const CollisionHit& hit ) { auto player = dynamic_cast(&other); if (player != nullptr) { - if (!player->add_bonus(BONUS_GROWUP, true)) { - // Tux can't grow right now. - collision_solid( hit ); - return ABORT_MOVE; + if (m_growup_type == BONUS_GROWUP) { + if (!player->add_bonus(BONUS_GROWUP, true)) { + // Tux can't grow right now. + collision_solid( hit ); + return ABORT_MOVE; + } + + SoundManager::current()->play("sounds/grow.ogg", get_pos()); + } else { + player->kill(false); + SoundManager::current()->play("sounds/hurt.wav", get_pos()); } - - SoundManager::current()->play("sounds/grow.ogg", get_pos()); remove_me(); return ABORT_MOVE; diff --git a/src/object/growup.hpp b/src/object/growup.hpp index ec10fe8fb7d..7ddf5c4a2cf 100644 --- a/src/object/growup.hpp +++ b/src/object/growup.hpp @@ -19,11 +19,12 @@ #include "object/moving_sprite.hpp" #include "supertux/direction.hpp" #include "supertux/physic.hpp" +#include "supertux/player_status.hpp" class GrowUp final : public MovingSprite { public: - GrowUp(const Vector& pos, Direction direction = Direction::RIGHT, const std::string& custom_sprite = ""); + GrowUp(BonusType type, const Vector& pos, Direction direction = Direction::RIGHT, const std::string& custom_sprite = ""); virtual GameObjectClasses get_class_types() const override { return MovingSprite::get_class_types().add(typeid(GrowUp)); } virtual bool is_saveable() const override { return false; } @@ -39,6 +40,8 @@ class GrowUp final : public MovingSprite private: Physic m_physic; + BonusType m_growup_type; + std::string m_growup_default_sprite; const bool m_custom_sprite; SpritePtr m_shadesprite; SpritePtr m_lightsprite; diff --git a/src/object/powerup.cpp b/src/object/powerup.cpp index 54480880a57..2814d382911 100644 --- a/src/object/powerup.cpp +++ b/src/object/powerup.cpp @@ -59,6 +59,7 @@ PowerUp::get_types() const { return { { "egg", _("Egg") }, + { "badegg", _("Rotten Egg") }, { "fire", _("Fire Flower") }, { "ice", _("Ice Flower") }, { "air", _("Air Flower") }, @@ -77,6 +78,8 @@ PowerUp::get_default_sprite_name() const { switch (m_type) { + case BADEGG: + return "images/powerups/badegg/badegg.sprite"; case FIRE: return "images/powerups/fireflower/fireflower.sprite"; case ICE: @@ -107,6 +110,7 @@ PowerUp::initialize() { physic.enable_gravity(true); SoundManager::current()->preload("sounds/grow.ogg"); + SoundManager::current()->preload("sounds/hurt.wav"); SoundManager::current()->preload("sounds/fire-flower.wav"); SoundManager::current()->preload("sounds/gulp.wav"); @@ -115,6 +119,8 @@ PowerUp::initialize() { if (matches_sprite("images/powerups/egg/egg.sprite")) m_type = EGG; + else if (matches_sprite("images/powerups/badegg/badegg.sprite")) + m_type = BADEGG; else if (matches_sprite("images/powerups/fireflower/fireflower.sprite")) m_type = FIRE; else if (matches_sprite("images/powerups/iceflower/iceflower.sprite")) @@ -147,6 +153,9 @@ PowerUp::setup_lightsprite() case EGG: lightsprite->set_color(Color(0.2f, 0.2f, 0.0f)); break; + case BADEGG: + lightsprite->set_color(Color(0.2f, 0.f, 0.2f)); + break; case FIRE: lightsprite->set_color(Color(0.3f, 0.0f, 0.0f)); break; @@ -209,6 +218,10 @@ PowerUp::collision(MovingObject& other, const CollisionHit&) return FORCE_MOVE; SoundManager::current()->play("sounds/grow.ogg", get_pos()); break; + case BADEGG: + player->kill(false); + SoundManager::current()->play("sounds/hurt.wav", get_pos()); + break; case FIRE: case COFFEE: if (!player->add_bonus(BONUS_FIRE, true)) @@ -255,6 +268,9 @@ PowerUp::get_type_from_bonustype(int type) case BONUS_GROWUP: return EGG; + case MALUS_BADEGG: + return BADEGG; + case BONUS_FIRE: return FIRE; diff --git a/src/object/powerup.hpp b/src/object/powerup.hpp index 5f1d3605b48..2241b6e93d3 100644 --- a/src/object/powerup.hpp +++ b/src/object/powerup.hpp @@ -24,6 +24,7 @@ class PowerUp : public MovingSprite public: enum Type { EGG, + BADEGG, FIRE, ICE, AIR, diff --git a/src/supertux/player_status.cpp b/src/supertux/player_status.cpp index f5d8c69bd51..16b1501c5b8 100644 --- a/src/supertux/player_status.cpp +++ b/src/supertux/player_status.cpp @@ -109,6 +109,8 @@ PlayerStatus::get_bonus_name(BonusType bonustype) return "earthflower"; case BONUS_GROWUP: return "egg"; + case MALUS_BADEGG: + return "badegg"; case BONUS_NONE: return "none"; default: @@ -124,6 +126,8 @@ PlayerStatus::get_bonus_from_name(const std::string& name) return BONUS_NONE; } else if (name == "growup" || name == "egg") { return BONUS_GROWUP; + } else if (name == "badegg") { + return MALUS_BADEGG; } else if (name == "fireflower") { return BONUS_FIRE; } else if (name == "iceflower") { @@ -152,6 +156,8 @@ PlayerStatus::get_bonus_sprite(BonusType bonustype) return "images/powerups/earthflower/earthflower.sprite"; case BONUS_GROWUP: return "images/powerups/egg/egg.sprite"; + case MALUS_BADEGG: + return "images/powerups/badegg/badegg.sprite"; default: return ""; } @@ -358,6 +364,8 @@ PlayerStatus::get_bonus_prefix(int player_id) const return "small"; case BONUS_GROWUP: return "big"; + case MALUS_BADEGG: + return "corrupt"; case BONUS_FIRE: return "fire"; case BONUS_ICE: diff --git a/src/supertux/player_status.hpp b/src/supertux/player_status.hpp index 78481991391..3bc7c531684 100644 --- a/src/supertux/player_status.hpp +++ b/src/supertux/player_status.hpp @@ -43,7 +43,8 @@ enum BonusType { BONUS_FIRE, /*!< @description Fire bonus. */ BONUS_ICE, /*!< @description Ice bonus. */ BONUS_AIR, /*!< @description Air bonus. */ - BONUS_EARTH /*!< @description Earth bonus. */ + BONUS_EARTH, /*!< @description Earth bonus. */ + MALUS_BADEGG /*!< @description Rotten Egg fake bonus. */ }; /** This class keeps player status between different game sessions (for