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

Make three strike battle any other strike battle and add an option to steal tires #5307

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
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
10 changes: 10 additions & 0 deletions data/gui/screens/track_info.stkgui
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@
<label id="option-text" proportion="3" I18N="In the track info screen" text_align="left" align="center"/>
</div>

<div width="100%" height="fit" layout="horizontal-row" >
<div proportion="1" height="fit" layout="horizontal-row">
<div width="100%" height="fit" text-align="center" layout="vertical-row" >
<checkbox id="tire-stealing" align="center"/>
</div>
</div>
<spacer width="3%"/>
<label id="tire-stealing-text" proportion="3" I18N="In the track info screen" text_align="left" align="center"/>
</div>

<spacer width="1" height="1%"/>

<div width="100%" height="fit" layout="horizontal-row" >
Expand Down
3 changes: 3 additions & 0 deletions src/config/user_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,9 @@ namespace UserConfigParams
PARAM_PREFIX BoolUserConfigParam m_use_ffa_mode
PARAM_DEFAULT(BoolUserConfigParam(false, "use-ffa-mode",
&m_race_setup_group, "Use ffa mode instead of 3 strikes battle."));
PARAM_PREFIX BoolUserConfigParam m_tire_steal
PARAM_DEFAULT(BoolUserConfigParam(false, "tire-steal",
&m_race_setup_group, "Steal the tire when you hit a kart."));
PARAM_PREFIX IntUserConfigParam m_lap_trial_time_limit
PARAM_DEFAULT(IntUserConfigParam(3, "lap-trial-time-limit",
&m_race_setup_group, "Time limit in lap trial mode."));
Expand Down
7 changes: 4 additions & 3 deletions src/karts/controller/spare_tire_ai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "karts/controller/spare_tire_ai.hpp"

#include "config/user_config.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/kart_gfx.hpp"
#include "karts/max_speed.hpp"
Expand Down Expand Up @@ -142,12 +143,12 @@ void SpareTireAI::crashed(const AbstractKart *k)
// Nothing happen when two spare tire karts crash each other
if (dynamic_cast<const SpareTireAI*>(k->getController()) != NULL) return;

// Tell players that they can have at most 3 lives
// Add a life
RaceGUIBase* r = World::getWorld()->getRaceGUI();
if (m_tsb_world->getKartLife(k->getWorldKartId()) == 3)
if (m_tsb_world->getKartLife(k->getWorldKartId()) == UserConfigParams::m_ffa_time_limit && !UserConfigParams::m_tire_steal)
{
if (r)
r->addMessage(_("You can have at most 3 lives!"), k, 2.0f);
r->addMessage(_("You can have at most %d lives!"), k, 2.0f);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not an expert but I suppose this would need a pluralized form. Wait until someone else's feedback please.

}
// Otherwise add one life for that kart
else
Expand Down
106 changes: 68 additions & 38 deletions src/modes/three_strikes_battle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "karts/kart_properties_manager.hpp"
#include "physics/physics.hpp"
#include "states_screens/race_gui_base.hpp"
#include "states_screens/track_info_screen.hpp"
#include "tracks/arena_graph.hpp"
#include "tracks/arena_node.hpp"
#include "tracks/terrain_info.hpp"
Expand All @@ -55,16 +56,44 @@ ThreeStrikesBattle::ThreeStrikesBattle() : WorldWithRank()
m_insert_tire = 0;

m_tire = irr_driver->getMesh(file_manager->getAsset(FileManager::MODEL,
"tire.spm") );
"tire.spm") );
irr_driver->grabAllTextures(m_tire);

m_total_rescue = 0;
m_frame_count = 0;
m_start_time = irr_driver->getRealTime();
m_total_hit = 0;


} // ThreeStrikesBattle

namespace
{
const int gradientLength = 9;

const int redGradient[gradientLength + 3] = {200, 255, 255, 255, 128, 0, 0, 0, 0, 0, 192, 200};
// ------------------------------------------------------------------------
const int greenGradient[gradientLength + 3] = {0, 100, 200, 255, 255, 255, 128, 255, 128, 0, 0, 0};
// ------------------------------------------------------------------------
const int blueGradient[gradientLength + 3] = {0, 0, 0, 0, 0, 0, 0, 255, 255, 192, 192, 0};
// ------------------------------------------------------------------------

video::SColor calculateColor(int current_lives, int starting_lives)
{
float lerp_time;
lerp_time = float(current_lives - 1)/float(starting_lives);
int lerp_index = floor(lerp_time*gradientLength);
lerp_time = lerp_time * gradientLength - lerp_index;
lerp_index = lerp_index % (gradientLength + 2);

auto channelBrightness = [lerp_time, lerp_index](const int* gradient)
{
return lerp(gradient[lerp_index], gradient[lerp_index + 1], lerp_time);
};

return video::SColor(255, channelBrightness(redGradient), channelBrightness(greenGradient), channelBrightness(blueGradient));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is called twice in two different ifs, those ifs seem identical and related only to the color logic, and not to the game mode itself. Pass the current and the maximum number of lives to this function, and let it do all the transformations with lerp_*** inside. Don't forget to put spaces around operators -*/.

lerp is still repeated three times. Please move it into a separate function or lambda, e.g. return video::SColor(255, f(redGradient), f(greenGradient), f(blueGradient)) with

auto f = [=](const int* a) -> int {
    return lerp(a[lerp_index], a[lerp_index + 1], new_lerp_time);
};

}
//-----------------------------------------------------------------------------
/** Initialises the three strikes battle. It sets up the data structure
* to keep track of points etc. for each kart.
Expand Down Expand Up @@ -98,11 +127,11 @@ ThreeStrikesBattle::~ThreeStrikesBattle()
void ThreeStrikesBattle::reset(bool restart)
{
WorldWithRank::reset(restart);

float next_spawn_time =
RaceManager::get()->getDifficulty() == RaceManager::DIFFICULTY_BEST ? 40.0f :
RaceManager::get()->getDifficulty() == RaceManager::DIFFICULTY_HARD ? 30.0f :
RaceManager::get()->getDifficulty() == RaceManager::DIFFICULTY_MEDIUM ?
RaceManager::get()->getDifficulty() == RaceManager::DIFFICULTY_BEST ? 40.0f :
RaceManager::get()->getDifficulty() == RaceManager::DIFFICULTY_HARD ? 30.0f :
RaceManager::get()->getDifficulty() == RaceManager::DIFFICULTY_MEDIUM ?
25.0f : 20.0f;
m_next_sta_spawn_ticks = stk_config->time2Ticks(next_spawn_time);

Expand All @@ -116,7 +145,8 @@ void ThreeStrikesBattle::reset(bool restart)
}
else
{
m_kart_info[n].m_lives = 3;
// Gets starting amount of lives straight from the config (please tell me if this is the best method)
m_kart_info[n].m_lives = UserConfigParams::m_ffa_time_limit;
}

// no positions in this mode
Expand All @@ -130,11 +160,11 @@ void ThreeStrikesBattle::reset(bool restart)

if (core::stringc(curr->getName()) == "tire1")
{
curr->setVisible(true);
curr->setVisible(UserConfigParams::m_ffa_time_limit >= 3);
}
else if (core::stringc(curr->getName()) == "tire2")
{
curr->setVisible(true);
curr->setVisible(UserConfigParams::m_ffa_time_limit >= 2);
}
}

Expand Down Expand Up @@ -229,10 +259,17 @@ bool ThreeStrikesBattle::kartHit(int kart_id, int hitter)
assert(kart_id < (int)m_karts.size());
// make kart lose a life, ignore if in profiling mode
if (!UserConfigParams::m_arena_ai_stats)
{
m_kart_info[kart_id].m_lives--;
// Don't return the tire if 1. the checkbox says so or if 2. the kart hit itself or 3. if there is no hitter. That causes a crash otherwise.
if (hitter != -1 && hitter != kart_id && UserConfigParams::m_tire_steal)
addKartLife(hitter);

}
else
{
m_total_hit++;

}
// record event
BattleEvent evt;
evt.m_time = getTime();
Expand Down Expand Up @@ -316,6 +353,11 @@ bool ThreeStrikesBattle::kartHit(int kart_id, int hitter)

// schedule a tire to be thrown away (but can't do it in this callback
// because the caller is currently iterating the list of track objects)
// don't do this if the tire is getting stolen

if (hitter != -1 && hitter != kart_id && UserConfigParams::m_tire_steal)
return true;

m_insert_tire++;
core::vector3df wheel_pos(m_karts[kart_id]->getKartWidth()*0.5f,
0.0f, 0.0f);
Expand Down Expand Up @@ -512,25 +554,18 @@ void ThreeStrikesBattle::getKartsDisplayInfo(
{
RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i];

// reset color
// Samples colours from a gradient at a regular interval. The colours get funky if it goes out of bound, i dont know why.

rank_info.lap = -1;

switch(m_kart_info[i].m_lives)
if (m_kart_info[i].m_lives == 0)
{
case 3:
rank_info.m_color = video::SColor(255, 0, 255, 0);
break;
case 2:
rank_info.m_color = video::SColor(255, 255, 229, 0);
break;
case 1:
rank_info.m_color = video::SColor(255, 255, 0, 0);
break;
case 0:
rank_info.m_color = video::SColor(128, 128, 128, 0);
break;
rank_info.m_color = video::SColor(255,128,128,128);
}
else
{
rank_info.m_color = calculateColor(m_kart_info[i].m_lives, UserConfigParams::m_ffa_time_limit);
}

std::ostringstream oss;
oss << m_kart_info[i].m_lives;

Expand All @@ -542,22 +577,17 @@ void ThreeStrikesBattle::getKartsDisplayInfo(
std::pair<int, video::SColor> ThreeStrikesBattle::getSpeedometerDigit(
const AbstractKart *kart) const
{
// Samples colours from a gradient at a regular interval. The colours get funky if it goes out of bound, i dont know why.

video::SColor color = video::SColor(255, 255, 255, 255);
int id = kart->getWorldKartId();
switch(m_kart_info[id].m_lives)
if (m_kart_info[id].m_lives == 0)
{
case 3:
color = video::SColor(255, 0, 255, 0);
break;
case 2:
color = video::SColor(255, 255, 229, 0);
break;
case 1:
color = video::SColor(255, 255, 0, 0);
break;
case 0:
color = video::SColor(255, 128, 128, 128);
break;
color = video::SColor(255,128,128,128);
}
else
{
color = calculateColor(m_kart_info[id].m_lives, UserConfigParams::m_ffa_time_limit);
}
return std::make_pair(m_kart_info[id].m_lives, color);
} // getSpeedometerDigit
Expand Down
1 change: 1 addition & 0 deletions src/modes/three_strikes_battle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ class ThreeStrikesBattle : public WorldWithRank
bool spareTireKartsSpawned() const;
// ------------------------------------------------------------------------
void spawnSpareTireKarts();
// ------------------------------------------------------------------------

}; // ThreeStrikesBattles

Expand Down
38 changes: 29 additions & 9 deletions src/states_screens/track_info_screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ void TrackInfoScreen::loadedFromFile()
m_ai_kart_spinner = getWidget<SpinnerWidget>("ai-spinner");
m_ai_kart_label = getWidget<LabelWidget>("ai-text");
m_option = getWidget<CheckBoxWidget>("option");
m_tire_stealing = getWidget<CheckBoxWidget>("tire-stealing");
m_record_race = getWidget<CheckBoxWidget>("record");
m_tire_stealing->setState(false);
m_option->setState(false);
m_record_race->setState(false);

Expand Down Expand Up @@ -251,14 +253,23 @@ void TrackInfoScreen::init()
m_target_type_label->setText(_("Game mode"), false);
m_target_type_spinner->clearLabels();
m_target_type_spinner->addLabel(_("3 Strikes Battle"));

m_target_type_spinner->addLabel(_("Free-For-All"));
m_target_type_spinner->setValue(UserConfigParams::m_use_ffa_mode ? 1 : 0);

m_target_value_label->setText(_("Maximum time (min.)"), false);
m_target_value_spinner->setValue(UserConfigParams::m_ffa_time_limit);
if (UserConfigParams::m_use_ffa_mode)
m_target_value_label->setText(_("Maximum time (min.)"), false);

else
m_target_value_label->setText(_("Starting tires"), false);

m_tire_stealing->setVisible(!UserConfigParams::m_use_ffa_mode);
getWidget<LabelWidget>("tire-stealing-text")->setVisible(!UserConfigParams::m_use_ffa_mode);
getWidget<LabelWidget>("tire-stealing-text")->setText(_("Steal tires"), false);
m_tire_stealing->setState(UserConfigParams::m_tire_steal);

m_target_value_label->setVisible(UserConfigParams::m_use_ffa_mode);
m_target_value_spinner->setVisible(UserConfigParams::m_use_ffa_mode);
m_target_value_label->setVisible(true);
m_target_value_spinner->setVisible(true);
}

// Lap count m_lap_spinner
Expand Down Expand Up @@ -286,12 +297,13 @@ void TrackInfoScreen::init()
m_target_value_label->setText(_("Maximum time (min.)"), false);
m_target_value_spinner->setValue(UserConfigParams::m_lap_trial_time_limit);
}
// Reverse track or random item in arena
// Reverse track and random item in arena
// -------------
const bool reverse_available = m_track->reverseAvailable()
&& !(RaceManager::get()->isEggHuntMode());
const bool random_item = m_track->hasNavMesh();


m_option->setVisible(reverse_available || random_item);
getWidget<LabelWidget>("option-text")->setVisible(reverse_available || random_item);
if (reverse_available)
Expand Down Expand Up @@ -663,9 +675,14 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name,
{
const bool enable_ffa = target_value != 0;
UserConfigParams::m_use_ffa_mode = enable_ffa;

m_tire_stealing->setVisible(!enable_ffa);
getWidget<LabelWidget>("tire-stealing-text")->setVisible(!enable_ffa);

m_target_value_label->setVisible(enable_ffa);
m_target_value_spinner->setVisible(enable_ffa);
if (enable_ffa)
m_target_value_label->setText(_("Maximum time (min.)"), false);
else
m_target_value_label->setText(_("Starting tires"), false);
}
}
else if (name == "target-value-spinner")
Expand All @@ -682,8 +699,7 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name,
{
const bool enable_ffa = m_target_type_spinner->getValue() != 0;

if (enable_ffa)
UserConfigParams::m_ffa_time_limit = m_target_value_spinner->getValue();
UserConfigParams::m_ffa_time_limit = m_target_value_spinner->getValue();
}
else if (m_is_lap_trial)
{
Expand Down Expand Up @@ -712,6 +728,10 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name,
// checkbox.
updateHighScores();
}
}
else if (name == "tire-stealing")
{
UserConfigParams::m_tire_steal = m_tire_stealing->getState();
}
else if (name == "record")
{
Expand Down
3 changes: 3 additions & 0 deletions src/states_screens/track_info_screen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ class TrackInfoScreen : public GUIEngine::Screen,
/** Check box for reverse mode or random item in arena. */
GUIEngine::CheckBoxWidget* m_option;

/** Check box for tire stealing. */
GUIEngine::CheckBoxWidget* m_tire_stealing;

/** Check box for record race. */
GUIEngine::CheckBoxWidget* m_record_race;

Expand Down
Loading