Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update yeti behavior #2969

Merged
merged 19 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added data/images/creatures/ghosttree/hudlife.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion data/images/engine/editor/objects.stoi
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,10 @@
(icon "images/engine/editor/stalactite_ice_yeti.png"))
(object
(class "dart")
(icon "images/creatures/darttrap/granito/root_dart_left.png"))
(icon "images/creatures/darttrap/granito/root_dart_left.png"))
(object
(class "bigsnowball")
(icon "images/objects/big_snowball/big_snowball.png"))
)

(objectgroup
Expand Down
Binary file added data/images/objects/big_snowball/big_snowball.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions data/images/objects/big_snowball/big_snowball.sprite
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
(supertux-sprite
(action
(name "default")
(hitbox 6 6 87 84)
(images "big_snowball.png"))

(action
(name "particle")
(hitbox 2 2 29 28)
(images "big_snowball_particle.png"))
)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
93 changes: 93 additions & 0 deletions src/badguy/boss.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SuperTux
// Copyright (C) 2024 Daniel Ward <[email protected]>
//
// 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 3 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, see <http://www.gnu.org/licenses/>.

namespace
{
const int DEFAULT_LIVES = 5; // default lives
const int DEFAULT_PINCH_LIVES = 2; // default pinch lives
}

#include "badguy/boss.hpp"

#include "object/player.hpp"
#include "sprite/sprite.hpp"
#include "supertux/sector.hpp"
#include "util/reader_mapping.hpp"
#include "video/surface.hpp"

Boss::Boss(const ReaderMapping& reader, const std::string& sprite_name, int layer) :
BadGuy(reader, sprite_name, layer),
m_lives(),
m_pinch_lives(),
m_hud_head(),
m_hud_icon(),
m_pinch_mode(),
m_pinch_activation_script()
{
reader.get("lives", m_lives, DEFAULT_LIVES);
reader.get("pinch-lives", m_pinch_lives, DEFAULT_PINCH_LIVES);
m_countMe = true;

reader.get("pinch-activation-script", m_pinch_activation_script, "");
}

void
Boss::boss_update(float dt_sec)
{
if (!m_pinch_mode && (m_lives <= m_pinch_lives))
{
m_pinch_mode = true;
Sector::get().run_script(m_pinch_activation_script, "pinch-activation-script");
}
}

void
Boss::draw(DrawingContext& context)
{
draw_hit_points(context);
BadGuy::draw(context);
}

void
Boss::draw_hit_points(DrawingContext& context)
{
if (m_hud_head)
{
context.push_transform();
context.set_translation(Vector(0, 0));
context.transform().scale = 1.f;

for (int i = 0; i < m_lives; ++i)
{
context.color().draw_surface(m_hud_head, Vector(BORDER_X + (static_cast<float>(i * m_hud_head->get_width())), BORDER_Y + 1), LAYER_HUD);
}

context.pop_transform();
}
}

ObjectSettings
Boss::get_settings()
{
ObjectSettings result = BadGuy::get_settings();

result.add_text("hud-icon", &m_hud_icon, "hud-icon", "images/creatures/yeti/hudlife.png", OPTION_HIDDEN);
result.add_int(_("Lives"), &m_lives, "lives", DEFAULT_LIVES);
result.add_int(_("Lives to Pinch Mode"), &m_pinch_lives, "pinch-lives", DEFAULT_PINCH_LIVES);
result.add_script(_("Pinch Mode Activation Script"), &m_pinch_activation_script, "pinch-activation-script");

return result;
}
52 changes: 52 additions & 0 deletions src/badguy/boss.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SuperTux
// Copyright (C) 2024 Daniel Ward <[email protected]>
//
// 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 3 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, see <http://www.gnu.org/licenses/>.

#ifndef HEADER_SUPERTUX_BADGUY_BOSS_HPP
#define HEADER_SUPERTUX_BADGUY_BOSS_HPP

#include "badguy/badguy.hpp"

// This is a class for our (currently two) bosses, but can apply to future ones also.
// Includes information on lives, HUD, pinch mode activation, and death behavior.

class Boss : public BadGuy
{
public:
Boss(const ReaderMapping& mapping, const std::string& sprite_name, int layer = LAYER_OBJECTS);
virtual void boss_update(float dt_sec);
virtual void draw(DrawingContext& context) override;
void draw_hit_points(DrawingContext& context);
virtual ObjectSettings get_settings() override;

virtual bool is_flammable() const override { return false; }
virtual bool is_freezable() const override { return false; }

protected:
int m_lives;
int m_pinch_lives;
SurfacePtr m_hud_head;
std::string m_hud_icon;
bool m_pinch_mode;
std::string m_pinch_activation_script;

private:
Boss(const Boss&) = delete;
Boss& operator=(const Boss&) = delete;
};

#endif

/* EOF */
22 changes: 17 additions & 5 deletions src/badguy/bouncing_snowball.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,26 @@
static const float JUMPSPEED = -450;
static const float BSNOWBALL_WALKSPEED = 80;

BouncingSnowball::BouncingSnowball(const ReaderMapping& reader)
: BadGuy(reader, "images/creatures/bouncing_snowball/bouncing_snowball.sprite")
BouncingSnowball::BouncingSnowball(const ReaderMapping& reader) :
BadGuy(reader, "images/creatures/bouncing_snowball/bouncing_snowball.sprite"),
m_x_speed()
{
m_x_speed = BSNOWBALL_WALKSPEED;
parse_type(reader);
}

BouncingSnowball::BouncingSnowball(const Vector& pos, Direction d, float x_vel) :
BadGuy(pos, d, "images/creatures/bouncing_snowball/bouncing_snowball.sprite"),
m_x_speed()
{
m_countMe = false;
m_x_speed = x_vel;
}

void
BouncingSnowball::initialize()
{
m_physic.set_velocity_x(m_dir == Direction::LEFT ? -BSNOWBALL_WALKSPEED : BSNOWBALL_WALKSPEED);
m_physic.set_velocity_x(m_dir == Direction::LEFT ? -m_x_speed : m_x_speed);
set_action(m_dir);
}

Expand All @@ -49,8 +59,10 @@ BouncingSnowball::active_update(float dt_sec)
set_action(m_dir);
}
Rectf lookbelow = get_bbox();
lookbelow.set_bottom(lookbelow.get_bottom() + 48);
lookbelow.set_top(lookbelow.get_top() + 31);
lookbelow.set_bottom(get_bbox().get_bottom() + 48);
lookbelow.set_left(get_bbox().get_left() + 10);
lookbelow.set_right(get_bbox().get_right() - 10);
lookbelow.set_top(get_bbox().get_top() + 31);
bool groundBelow = !Sector::get().is_free_of_statics(lookbelow);
if (groundBelow && (m_physic.get_velocity_y() >= 64.0f))
{
Expand Down
3 changes: 3 additions & 0 deletions src/badguy/bouncing_snowball.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class BouncingSnowball final : public BadGuy
{
public:
BouncingSnowball(const ReaderMapping& reader);
BouncingSnowball(const Vector& pos, Direction d, float x_vel = 80);

virtual void initialize() override;

Expand Down Expand Up @@ -55,6 +56,8 @@ class BouncingSnowball final : public BadGuy
FATBAT
};

float m_x_speed;

private:
BouncingSnowball(const BouncingSnowball&) = delete;
BouncingSnowball& operator=(const BouncingSnowball&) = delete;
Expand Down
33 changes: 25 additions & 8 deletions src/badguy/ghosttree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@
#include "sprite/sprite_manager.hpp"
#include "supertux/flip_level_transformer.hpp"
#include "supertux/sector.hpp"
#include "util/reader_mapping.hpp"
#include "video/surface.hpp"

static const size_t WILLOWISP_COUNT = 10;
static const float WILLOWISP_TOP_OFFSET = -64;
static const Vector SUCK_TARGET_OFFSET = Vector(-16,-16);
static const float SUCK_TARGET_SPREAD = 8;

GhostTree::GhostTree(const ReaderMapping& mapping) :
BadGuy(mapping, "images/creatures/ghosttree/ghosttree.sprite", LAYER_OBJECTS - 10),
Boss(mapping, "images/creatures/ghosttree/ghosttree.sprite", LAYER_OBJECTS - 10),
mystate(STATE_IDLE),
willowisp_timer(),
willo_spawn_y(0),
Expand All @@ -49,9 +51,13 @@ GhostTree::GhostTree(const ReaderMapping& mapping) :
root_timer(),
treecolor(0),
suck_lantern_color(),
m_taking_life(),
suck_lantern(nullptr),
willowisps()
{
mapping.get("hud-icon", m_hud_icon, "images/creatures/ghosttree/hudlife.png");
m_hud_head = Surface::from_file(m_hud_icon);

set_colgroup_active(COLGROUP_TOUCHABLE);
SoundManager::current()->preload("sounds/tree_howling.ogg");
SoundManager::current()->preload("sounds/tree_suck.ogg");
Expand All @@ -60,14 +66,17 @@ GhostTree::GhostTree(const ReaderMapping& mapping) :
void
GhostTree::die()
{
mystate = STATE_DYING;
set_action("dying", 1);
glow_sprite->set_action("dying", 1);

for (const auto& willo : willowisps) {
willo->vanish();
}
run_dead_script();

if (m_lives <= 0) {
mystate = STATE_DYING;
set_action("dying", 1);
glow_sprite->set_action("dying", 1);
run_dead_script();
}
}

void
Expand All @@ -79,9 +88,12 @@ GhostTree::activate()
}

void
GhostTree::active_update(float /*dt_sec*/)
GhostTree::active_update(float dt_sec)
{
Boss::boss_update(dt_sec);

if (mystate == STATE_IDLE) {
m_taking_life = false;
if (colorchange_timer.check()) {
SoundManager::current()->play("sounds/tree_howling.ogg", get_pos());
suck_timer.start(3);
Expand Down Expand Up @@ -180,8 +192,13 @@ GhostTree::active_update(float /*dt_sec*/)
// Wait until the lantern is swallowed completely.
if (m_sprite->animation_done()) {
if (is_color_deadly(suck_lantern_color)) {
if (!m_taking_life) {
m_lives--;
m_taking_life = true;
}
die();
} else {
}
if (m_lives > 0) {
set_action("normal");
mystate = STATE_IDLE;
spawn_lantern();
Expand Down Expand Up @@ -215,7 +232,7 @@ GhostTree::willowisp_died(TreeWillOWisp* willowisp)
void
GhostTree::draw(DrawingContext& context)
{
BadGuy::draw(context);
Boss::draw(context);

context.push_transform();
if (mystate == STATE_SUCKING) {
Expand Down
8 changes: 4 additions & 4 deletions src/badguy/ghosttree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,16 @@
#ifndef HEADER_SUPERTUX_BADGUY_GHOSTTREE_HPP
#define HEADER_SUPERTUX_BADGUY_GHOSTTREE_HPP

#include "badguy/badguy.hpp"
#include "badguy/boss.hpp"

class TreeWillOWisp;
class Lantern;

class GhostTree final : public BadGuy
class GhostTree final : public Boss
{
public:
GhostTree(const ReaderMapping& mapping);

virtual bool is_flammable() const override { return false; }
virtual bool is_freezable() const override { return false; }
virtual void kill_fall() override { }

virtual void activate() override;
Expand Down Expand Up @@ -75,6 +73,8 @@ class GhostTree final : public BadGuy
int treecolor;
Color suck_lantern_color;

bool m_taking_life;

Lantern* suck_lantern; /**< Lantern that is currently being sucked in */

std::vector<TreeWillOWisp*> willowisps;
Expand Down
Loading
Loading