#include "BattleState.h"
#include "PartyLayout.h"
+#include "states/DefeatState.h"
#include "states/SelectMoveAction.h"
#include "states/PerformAttacks.h"
#include "states/VictoryState.h"
return;
}
if (battle.Defeat()) {
- Ctrl().PopState();
+ if (alreadyPushed) {
+ Ctrl().PopState();
+ } else {
+ Ctrl().PushState(new DefeatState(&battle, this));
+ alreadyPushed = true;
+ }
return;
}
// TODO: this should not push a state while quitting
, noEquipmentText("MISSING TRANSLATION")
, escapeText("MISSING TRANSLATION")
+, defeatText("MISSING TRANSLATION")
, numberAnimationPrototype(0)
, bigNumberSprite(0)
td.AddField("noEquipmentText", FieldDescription(((char *)&r.noEquipmentText) - ((char *)&r), Interpreter::STRING_ID).SetReferenced().SetDescription("text to show for missing equipment"));
td.AddField("escapeText", FieldDescription(((char *)&r.escapeText) - ((char *)&r), Interpreter::STRING_ID).SetReferenced().SetDescription("displayed when the party escapes"));
+ td.AddField("defeatText", FieldDescription(((char *)&r.defeatText) - ((char *)&r), Interpreter::STRING_ID).SetReferenced().SetDescription("displayed when the party was defeated"));
td.AddField("numberAnimationPrototype", FieldDescription(((char *)&r.numberAnimationPrototype) - ((char *)&r), Animation::TYPE_ID).SetReferenced().SetDescription("animation of an attack's result digit"));
const char *noEquipmentText;
const char *escapeText;
+ const char *defeatText;
const graphics::Animation *numberAnimationPrototype;
--- /dev/null
+#include "DefeatState.h"
+
+#include "../Battle.h"
+#include "../BattleState.h"
+#include "../Resources.h"
+#include "../../app/Application.h"
+#include "../../app/Input.h"
+#include "../../math/Vector.h"
+#include "../../graphics/ColorFade.h"
+#include "../../graphics/Font.h"
+#include "../../graphics/Frame.h"
+#include "../../sdl/Desaturate.h"
+
+using app::Application;
+using app::Input;
+using graphics::ColorFade;
+using graphics::Font;
+using graphics::Frame;
+using math::Vector;
+using std::vector;
+
+namespace battle {
+
+DefeatState::DefeatState(
+ Battle *battle,
+ BattleState *parent)
+: battle(battle)
+, parent(parent)
+, cache(0)
+, format(0) {
+
+}
+
+
+void DefeatState::OnEnterState(SDL_Surface *screen) {
+ timer = GraphicsTimers().StartCountdown(1500);
+ format = screen->format;
+ OnResize(screen->w, screen->h);
+}
+
+void DefeatState::OnExitState(SDL_Surface *screen) {
+ if (cache) {
+ SDL_FreeSurface(cache);
+ cache = 0;
+ }
+}
+
+void DefeatState::OnResumeState(SDL_Surface *screen) {
+
+}
+
+void DefeatState::OnPauseState(SDL_Surface *screen) {
+
+}
+
+
+void DefeatState::OnResize(int width, int height) {
+ const Resources &res = parent->Res();
+ const Frame &frame = *res.titleFrame;
+ const Font &font = *res.titleFont;
+
+ framePosition = parent->ScreenOffset();
+ frameSize = Vector<int> (
+ parent->Width(),
+ frame.BorderHeight() * 2 + font.CharHeight());
+
+ textPosition = Vector<int>(
+ (parent->Width() - strlen(res.defeatText) * font.CharWidth()) / 2,
+ frame.BorderHeight());
+
+ parent->Resize(width, height);
+ if (cache) {
+ SDL_FreeSurface(cache);
+ }
+ cache = SDL_CreateRGBSurface(0, width, height, format->BitsPerPixel,
+ format->Rmask, format->Gmask, format->Bmask, format->Amask);
+ parent->Render(cache);
+ parent->RenderHeroes(cache);
+ RenderTitleBar(cache);
+}
+
+
+void DefeatState::HandleEvents(const Input &input) {
+ if (timer.Finished()) {
+ Ctrl().PopState();
+ }
+}
+
+
+void DefeatState::UpdateWorld(Uint32 deltaT) {
+
+}
+
+void DefeatState::Render(SDL_Surface *screen) {
+ if (screen->format->palette
+ || cache->format->palette) {
+ // I refuse to desaturate an indexed color urface
+ SDL_BlitSurface(cache, 0, screen, 0);
+ return;
+ }
+
+ sdl::Desaturate(cache, screen, timer.Remaining() * 255 / 1500);
+}
+
+void DefeatState::RenderTitleBar(SDL_Surface *screen) {
+ const Resources &res = parent->Res();
+ res.titleFrame->Draw(screen, framePosition, frameSize.X(), frameSize.Y());
+ res.titleFont->DrawString(res.defeatText, screen, textPosition);
+}
+
+}
--- /dev/null
+#ifndef BATTLE_DEFEATSTATE_H_
+#define BATTLE_DEFEATSTATE_H_
+
+namespace battle {
+ class Battle;
+ class BattleState;
+}
+
+#include "../../app/State.h"
+#include "../../math/Vector.h"
+
+#include <SDL.h>
+
+namespace battle {
+
+class DefeatState
+: public app::State {
+
+public:
+ DefeatState(
+ Battle *battle,
+ BattleState *parent);
+
+public:
+ virtual void HandleEvents(const app::Input &);
+ virtual void UpdateWorld(Uint32 deltaT);
+ virtual void Render(SDL_Surface *);
+
+private:
+ virtual void OnEnterState(SDL_Surface *screen);
+ virtual void OnExitState(SDL_Surface *screen);
+ virtual void OnResumeState(SDL_Surface *screen);
+ virtual void OnPauseState(SDL_Surface *screen);
+
+ virtual void OnResize(int width, int height);
+
+private:
+ void RenderTitleBar(SDL_Surface *screen);
+
+private:
+ Battle *battle;
+ BattleState *parent;
+ SDL_Surface *cache;
+ SDL_PixelFormat *format;
+ app::Timer<Uint32> timer;
+ math::Vector<int> framePosition;
+ math::Vector<int> frameSize;
+ math::Vector<int> textPosition;
+
+};
+
+}
+
+#endif
--- /dev/null
+#include "Desaturate.h"
+
+#include <stdexcept>
+
+using std::runtime_error;
+
+
+namespace sdl {
+
+template<typename SrcType, typename DestType>
+void DesaturatePixel(
+ SrcType *src, SDL_PixelFormat *srcFmt,
+ DestType *dest, SDL_PixelFormat *destFmt,
+ Uint8 amount) {
+
+ Uint8 srcRed = (((*src) & srcFmt->Rmask)
+ >> srcFmt->Rshift) << srcFmt->Rloss;
+ Uint8 srcGreen = (((*src) & srcFmt->Gmask)
+ >> srcFmt->Gshift) << srcFmt->Gloss;
+ Uint8 srcBlue = (((*src) & srcFmt->Bmask)
+ >> srcFmt->Bshift) << srcFmt->Bloss;
+
+ Uint8 srcGrey = (srcRed * 76 + srcGreen * 150 + srcBlue * 29) / 255;
+
+ Uint8 destRed = (srcRed * amount + srcGrey * (255 - amount)) / 255;
+ Uint8 destGreen = (srcGreen * amount + srcGrey * (255 - amount)) / 255;
+ Uint8 destBlue = (srcBlue * amount + srcGrey * (255 - amount)) / 255;
+
+ *dest
+ = ((destRed >> destFmt->Rloss) << destFmt->Rshift)
+ | ((destGreen >> destFmt->Gloss) << destFmt->Gshift)
+ | ((destBlue >> destFmt->Bloss) << destFmt->Bshift)
+ | (*dest & destFmt->Amask);
+}
+
+void Desaturate(
+ SDL_Surface *src,
+ SDL_Surface *dest,
+ Uint8 amount) {
+ Uint32 size = src->w * src->h;
+ SDL_LockSurface(src);
+ SDL_LockSurface(dest);
+ SDL_PixelFormat *srcFmt = src->format;
+ SDL_PixelFormat *destFmt = dest->format;
+ Uint8 srcBPP = srcFmt->BytesPerPixel;
+ Uint8 destBPP = destFmt->BytesPerPixel;
+ switch (srcBPP) {
+ default:
+ SDL_UnlockSurface(dest);
+ SDL_UnlockSurface(src);
+ throw runtime_error("unable to read src format");
+ case 2: {
+ Uint16 *srcIter = reinterpret_cast<Uint16 *>(
+ src->pixels);
+ Uint16 *srcEnd = srcIter + size;
+ switch (destBPP) {
+ default:
+ SDL_UnlockSurface(dest);
+ SDL_UnlockSurface(src);
+ throw runtime_error("unable to read src format");
+ case 2: {
+ Uint16 *destIter = reinterpret_cast<Uint16 *>(
+ dest->pixels);
+ Uint16 *destEnd = destIter + size;
+ for (;srcIter < srcEnd && destIter < destEnd;
+ ++srcIter, ++destIter) {
+ DesaturatePixel(
+ srcIter, srcFmt,
+ destIter, destFmt,
+ amount);
+ }
+ break; }
+ case 4: {
+ Uint32 *destIter = reinterpret_cast<Uint32 *>(
+ dest->pixels);
+ Uint32 *destEnd = destIter + size;
+ for (;srcIter < srcEnd && destIter < destEnd;
+ ++srcIter, ++destIter) {
+ DesaturatePixel(
+ srcIter, srcFmt,
+ destIter, destFmt,
+ amount);
+ }
+ break; }
+ }
+ break; }
+ case 4: {
+ Uint32 *srcIter = reinterpret_cast<Uint32 *>(
+ src->pixels);
+ Uint32 *srcEnd = srcIter + size;
+ switch (destBPP) {
+ default:
+ SDL_UnlockSurface(dest);
+ SDL_UnlockSurface(src);
+ throw runtime_error("unable to read src format");
+ case 2: {
+ Uint16 *destIter = reinterpret_cast<Uint16 *>(
+ dest->pixels);
+ Uint16 *destEnd = destIter + size;
+ for (;srcIter < srcEnd && destIter < destEnd;
+ ++srcIter, ++destIter) {
+ DesaturatePixel(
+ srcIter, srcFmt,
+ destIter, destFmt,
+ amount);
+ }
+ break; }
+ case 4: {
+ Uint32 *destIter = reinterpret_cast<Uint32 *>(
+ dest->pixels);
+ Uint32 *destEnd = destIter + size;
+ for (;srcIter < srcEnd && destIter < destEnd;
+ ++srcIter, ++destIter) {
+ DesaturatePixel(
+ srcIter, srcFmt,
+ destIter, destFmt,
+ amount);
+ }
+ break; }
+ }
+ break; }
+ }
+ SDL_UnlockSurface(dest);
+ SDL_UnlockSurface(src);
+}
+
+}
--- /dev/null
+#ifndef SDL_DESATURATE_H_
+#define SDL_DESATURATE_H_
+
+#include <SDL.h>
+
+namespace sdl {
+
+/// Copy src to dest, desaturated by amount/255.
+void Desaturate(
+ SDL_Surface *src,
+ SDL_Surface *dest,
+ Uint8 amount);
+
+}
+
+#endif
noEquipmentText: "No equip",
escapeText: "Escapes.",
+ defeatText: "Total Defeat.",
victoryGetsText: "Gets",
victoryExpText: "EXP",