- Added TutorialMessage ability
-- Tutorial Messages are an ability like any other, except it can only be displayed once. Subsequent calls are ignored, the ability is removed from the game as soon as it is added -- This allows to add event triggered messages ingame. Messages are either text, or images (I don't have an image sample, but rules/classic.txt has a few examples that might help) -- only tested on Windows, although I made sure the PSP version compiles. Hopefully I also made the necessary for it to work in the touch version (touching the screen should be enough to close the tuto message) -- Room for improvement: possibility to choose a title in text mode, possibility to have some messages depending on others (e.g.: don't show message X until message Y has been shown), improve some of the abilities and triggers to give more flexibility, add events outside of game, to allow tuto messages in deck creator, etc...
This commit is contained in:
@@ -15,6 +15,7 @@ The Action Stack contains all information for Game Events that can be interrupte
|
||||
#include "Translate.h"
|
||||
#include "WResourceManager.h"
|
||||
#include "ModRules.h"
|
||||
#include "AllAbilities.h"
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
@@ -822,6 +823,12 @@ int ActionStack::receiveEventPlus(WEvent * event)
|
||||
|
||||
void ActionStack::Update(float dt)
|
||||
{
|
||||
|
||||
//This is a hack to avoid updating the stack while tuto messages are being shown
|
||||
//Ideally, the tuto messages should be moved to a layer above this one
|
||||
if (ATutorialMessage::Current)
|
||||
return;
|
||||
|
||||
askIfWishesToInterrupt = NULL;
|
||||
//modal = 0;
|
||||
GameObserver * game = GameObserver::GetInstance();
|
||||
@@ -1080,6 +1087,11 @@ void ActionStack::Fizzle(Interruptible * action)
|
||||
|
||||
void ActionStack::Render()
|
||||
{
|
||||
//This is a hack to avoid rendering the stack above the tuto messages
|
||||
//Ideally, the tuto messages should be moved to a layer above this one
|
||||
if (ATutorialMessage::Current)
|
||||
return;
|
||||
|
||||
static const float kSpacer = 8;
|
||||
static const float x0 = 250;
|
||||
static const float y0 = 0;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "AllAbilities.h"
|
||||
#include "Translate.h"
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
//Activated Abilities
|
||||
|
||||
@@ -3573,6 +3575,285 @@ ABlinkGeneric::~ABlinkGeneric()
|
||||
SAFE_DELETE(ability);
|
||||
}
|
||||
|
||||
|
||||
//Tutorial Messaging
|
||||
|
||||
ATutorialMessage * ATutorialMessage::Current = NULL;
|
||||
|
||||
ATutorialMessage::ATutorialMessage(MTGCardInstance * source, string message) : MTGAbility(0, source), IconButtonsController(0, 0)
|
||||
{
|
||||
mBgTex = NULL;
|
||||
|
||||
mElapsed = 0;
|
||||
mIsImage = false;
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
mBg[i] = NULL;
|
||||
|
||||
string gfx = WResourceManager::Instance()->graphicsFile(message);
|
||||
if (fileExists(gfx.c_str()))
|
||||
{
|
||||
mIsImage = true;
|
||||
mMessage = message;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMessage = _(message); //translate directly here, remove this and translate at rendering time if it bites us
|
||||
boost::replace_all(mMessage, "\\n", "\n");
|
||||
}
|
||||
|
||||
if (mIsImage)
|
||||
{
|
||||
mX = SCREEN_WIDTH_F / 2;
|
||||
mY = SCREEN_HEIGHT_F / 2;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mX = 0;
|
||||
mY = -SCREEN_HEIGHT_F - 0.1f; //Offscreen
|
||||
}
|
||||
mDontShow = mUserCloseRequest = alreadyShown();
|
||||
|
||||
if(mDontShow)
|
||||
forceDestroy = 1;
|
||||
}
|
||||
|
||||
|
||||
string ATutorialMessage::getOptionName()
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "tuto_";
|
||||
out << hash_djb2(mMessage.c_str());
|
||||
return out.str();
|
||||
}
|
||||
|
||||
bool ATutorialMessage::alreadyShown()
|
||||
{
|
||||
return options[getOptionName()].number ? true : false;
|
||||
}
|
||||
|
||||
bool ATutorialMessage::CheckUserInput(JButton key)
|
||||
{
|
||||
if (mUserCloseRequest) return false;
|
||||
|
||||
if(key == JGE_BTN_SEC || key == JGE_BTN_OK)
|
||||
{
|
||||
ButtonPressed(0, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
//Required for Mouse/touch input
|
||||
IconButtonsController::CheckUserInput(key);
|
||||
|
||||
return true; //this ability is modal, so it catches all key events until it gets closed
|
||||
}
|
||||
|
||||
void ATutorialMessage::Update(float dt)
|
||||
{
|
||||
if (!Current && !mDontShow)
|
||||
Current = this;
|
||||
|
||||
if (Current != this)
|
||||
return;
|
||||
|
||||
if (mUserCloseRequest && mY < -SCREEN_HEIGHT)
|
||||
mDontShow = true;
|
||||
|
||||
if (mDontShow)
|
||||
{
|
||||
Current = NULL;
|
||||
forceDestroy = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
mElapsed += dt;
|
||||
|
||||
IconButtonsController::Update(dt);
|
||||
|
||||
if (mIsImage)
|
||||
return;
|
||||
|
||||
//Below this only affects "text" mode
|
||||
if (!mUserCloseRequest && mY < 0)
|
||||
{
|
||||
mY = -SCREEN_HEIGHT + (SCREEN_HEIGHT * mElapsed / 0.75f); //Todo: more physical drop-in.
|
||||
if (mY >= 0)
|
||||
mY = 0;
|
||||
}
|
||||
else if (mUserCloseRequest && mY > -SCREEN_HEIGHT)
|
||||
{
|
||||
mY = -(SCREEN_HEIGHT * mElapsed / 0.75f);
|
||||
}
|
||||
}
|
||||
|
||||
void ATutorialMessage::ButtonPressed(int controllerId, int controlId)
|
||||
{
|
||||
//TODO : cancel ALL tips/tutorials for JGE_BTN_SEC?
|
||||
options[getOptionName()].number = 1;
|
||||
options.save(); //TODO: if we experience I/O slowness in tutorials, move this save at the end of a turn, or at the end of the game.
|
||||
mElapsed = 0;
|
||||
mUserCloseRequest = true;
|
||||
}
|
||||
|
||||
void ATutorialMessage::Render()
|
||||
{
|
||||
if (mDontShow)
|
||||
return;
|
||||
|
||||
if (mY < -SCREEN_HEIGHT)
|
||||
return;
|
||||
|
||||
if (!mBgTex)
|
||||
{
|
||||
if (mIsImage)
|
||||
{
|
||||
mBgTex = WResourceManager::Instance()->RetrieveTexture(mMessage, RETRIEVE_LOCK);
|
||||
if (mBgTex)
|
||||
{
|
||||
mBg[0] = NEW JQuad(mBgTex, 0, 0, (float) mBgTex->mWidth, (float) mBgTex->mHeight);
|
||||
mBg[0]->SetHotSpot(mBg[0]->mWidth / 2, mBg[0]->mHeight / 2);
|
||||
|
||||
//Continue Button
|
||||
JQuadPtr quad = WResourceManager::Instance()->RetrieveQuad("iconspsp.png", 4 * 32, 0, 32, 32, "iconpsp4", RETRIEVE_MANAGE);
|
||||
quad->SetHotSpot(16, 16);
|
||||
IconButton * iconButton = NEW IconButton(1, this, quad.get(), 0, mBg[0]->mHeight / 2, 0.7f, Fonts::MAGIC_FONT, _("continue"), 0, 16, true);
|
||||
Add(iconButton);
|
||||
}
|
||||
|
||||
if (options[Options::SFXVOLUME].number > 0)
|
||||
{
|
||||
JSample * sample = WResourceManager::Instance()->RetrieveSample("tutorial.wav");
|
||||
if (sample)
|
||||
JSoundSystem::GetInstance()->PlaySample(sample);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mBgTex = WResourceManager::Instance()->RetrieveTexture("taskboard.png", RETRIEVE_LOCK);
|
||||
|
||||
float unitH = static_cast<float> (mBgTex->mHeight / 4);
|
||||
float unitW = static_cast<float> (mBgTex->mWidth / 4);
|
||||
if (unitH == 0 || unitW == 0) return;
|
||||
|
||||
if (mBgTex)
|
||||
{
|
||||
mBg[0] = NEW JQuad(mBgTex, 0, 0, unitW, unitH);
|
||||
mBg[1] = NEW JQuad(mBgTex, unitW, 0, unitW * 2, unitH);
|
||||
mBg[2] = NEW JQuad(mBgTex, unitW * 3, 0, unitW, unitH);
|
||||
mBg[3] = NEW JQuad(mBgTex, 0, unitH, unitW, unitH * 2);
|
||||
mBg[4] = NEW JQuad(mBgTex, unitW, unitH, unitW * 2, unitH * 2);
|
||||
mBg[5] = NEW JQuad(mBgTex, unitW * 3, unitH, unitW, unitH * 2);
|
||||
mBg[6] = NEW JQuad(mBgTex, 0, unitH * 3, unitW, unitH);
|
||||
mBg[7] = NEW JQuad(mBgTex, unitW, unitH * 3, unitW * 2, unitH);
|
||||
mBg[8] = NEW JQuad(mBgTex, unitW * 3, unitH * 3, unitW, unitH);
|
||||
}
|
||||
|
||||
//Continue Button
|
||||
JQuadPtr quad = WResourceManager::Instance()->RetrieveQuad("iconspsp.png", 4 * 32, 0, 32, 32, "iconpsp4", RETRIEVE_MANAGE);
|
||||
quad->SetHotSpot(16, 16);
|
||||
IconButton * iconButton = NEW IconButton(1, this, quad.get(), SCREEN_WIDTH_F / 2, SCREEN_HEIGHT_F - 60, 0.7f, Fonts::MAGIC_FONT, _("continue"), 0, 16, true);
|
||||
Add(iconButton);
|
||||
|
||||
mSH = 64 / unitH;
|
||||
mSW = 64 / unitW;
|
||||
|
||||
if (options[Options::SFXVOLUME].number > 0)
|
||||
{
|
||||
JSample * sample = WResourceManager::Instance()->RetrieveSample("chain.wav");
|
||||
if (sample)
|
||||
JSoundSystem::GetInstance()->PlaySample(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JRenderer * r = JRenderer::GetInstance();
|
||||
|
||||
//Render background board
|
||||
if (mBgTex)
|
||||
{
|
||||
if (mIsImage)
|
||||
{
|
||||
int alpha = mUserCloseRequest ? MAX(0, 255 - (int)(mElapsed * 500)) : MIN(255, (int)(mElapsed * 500)) ;
|
||||
if (mUserCloseRequest && alpha == 0)
|
||||
mDontShow = true;
|
||||
|
||||
r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(alpha / 2,0,0,0));
|
||||
mBg[0]->SetColor(ARGB(alpha,255,255,255));
|
||||
r->RenderQuad(mBg[0], SCREEN_WIDTH_F /2 , SCREEN_HEIGHT_F / 2 , 0);
|
||||
IconButtonsController::SetColor(ARGB(alpha,255,255,255));
|
||||
}
|
||||
else
|
||||
{
|
||||
//Setup fonts.
|
||||
WFont * f2 = WResourceManager::Instance()->GetWFont(Fonts::MAGIC_FONT);
|
||||
f2->SetColor(ARGB(255, 205, 237, 240));
|
||||
|
||||
r->FillRect(0, mY, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(128,0,0,0));
|
||||
r->RenderQuad(mBg[0], 0, mY, 0, mSW, mSH); //TL
|
||||
r->RenderQuad(mBg[2], SCREEN_WIDTH - 64, mY, 0, mSW, mSH); //TR
|
||||
r->RenderQuad(mBg[6], 0, mY + SCREEN_HEIGHT - 64, 0, mSW, mSH); //BL
|
||||
r->RenderQuad(mBg[8], SCREEN_WIDTH - 64, mY + SCREEN_HEIGHT - 64, 0, mSW, mSH); //BR
|
||||
|
||||
//Stretch the sides
|
||||
float stretchV = (144.0f / 128.0f) * mSH;
|
||||
float stretchH = (176.0f / 128.0f) * mSW;
|
||||
r->RenderQuad(mBg[3], 0, mY + 64, 0, mSW, stretchV); //L
|
||||
r->RenderQuad(mBg[5], SCREEN_WIDTH - 64, mY + 64, 0, mSW, stretchV); //R
|
||||
r->RenderQuad(mBg[1], 64, mY, 0, stretchH, mSH); //T1
|
||||
r->RenderQuad(mBg[1], 240, mY, 0, stretchH, mSH); //T1
|
||||
r->RenderQuad(mBg[7], 64, mY + 208, 0, stretchH, mSH); //B1
|
||||
r->RenderQuad(mBg[7], 240, mY + 208, 0, stretchH, mSH); //B1
|
||||
r->RenderQuad(mBg[4], 64, mY + 64, 0, stretchH, stretchV); //Center1
|
||||
r->RenderQuad(mBg[4], 240, mY + 64, 0, stretchH, stretchV); //Center2
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(128,0,0,0));
|
||||
r->FillRect(10, 10 + mY, SCREEN_WIDTH - 10, SCREEN_HEIGHT - 10, ARGB(128,0,0,0));
|
||||
}
|
||||
|
||||
if (!mBgTex || !mIsImage)
|
||||
{
|
||||
float posX = 40, posY = mY + 20;
|
||||
string title = _("Help");
|
||||
|
||||
WFont * f = WResourceManager::Instance()->GetWFont(Fonts::MAGIC_FONT);
|
||||
WFont * f3 = WResourceManager::Instance()->GetWFont(Fonts::MENU_FONT); //OPTION_FONT
|
||||
f->SetColor(ARGB(255, 55, 46, 34));
|
||||
f3->SetColor(ARGB(255, 219, 206, 151));
|
||||
|
||||
f3->DrawString(title.c_str(), static_cast<float> ((SCREEN_WIDTH - 20) / 2 - title.length() * 4), posY);
|
||||
posY += 30;
|
||||
|
||||
f->DrawString(_(mMessage).c_str(), posX, posY);
|
||||
posY += 20;
|
||||
|
||||
f->SetScale(1);
|
||||
}
|
||||
|
||||
IconButtonsController::Render();
|
||||
|
||||
}
|
||||
|
||||
ATutorialMessage * ATutorialMessage::clone() const
|
||||
{
|
||||
ATutorialMessage * copy = NEW ATutorialMessage(*this);
|
||||
copy->mUserCloseRequest = copy->alreadyShown();
|
||||
return copy;
|
||||
}
|
||||
|
||||
ATutorialMessage::~ATutorialMessage()
|
||||
{
|
||||
if (mBgTex)
|
||||
{
|
||||
WResourceManager::Instance()->Release(mBgTex);
|
||||
for (int i = 0; i < 9; i++)
|
||||
SAFE_DELETE(mBg[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// utility functions
|
||||
|
||||
// Given a delimited string of abilities, add the ones to the list that are "Basic" MTG abilities
|
||||
|
||||
@@ -91,10 +91,9 @@ int Options::getID(string name)
|
||||
}
|
||||
|
||||
//Is it an unlocked set?
|
||||
size_t un = strlen("unlocked_");
|
||||
if (un < name.size())
|
||||
if (name.find("unlocked_") == 0)
|
||||
{
|
||||
string setname = name.substr(un);
|
||||
string setname = name.substr(strlen("unlocked_"));
|
||||
if (setlist.size())
|
||||
{
|
||||
int unlocked = setlist[setname];
|
||||
@@ -195,7 +194,7 @@ GameOption::GameOption(int value) :
|
||||
{
|
||||
}
|
||||
GameOption::GameOption(string value) :
|
||||
number(0), str(value)
|
||||
number(atoi(value.c_str())), str(value)
|
||||
{
|
||||
}
|
||||
GameOption::GameOption(int num, string str) :
|
||||
@@ -335,7 +334,7 @@ int GameOptions::load()
|
||||
int id = Options::getID(name);
|
||||
if (id == INVALID_OPTION)
|
||||
{
|
||||
unknown.push_back(s);
|
||||
if (!unknownMap[name]) unknownMap[name] = NEW GameOption(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -385,8 +384,16 @@ int GameOptions::save()
|
||||
opt->write(&file, name);
|
||||
}
|
||||
|
||||
for (vector<string>::size_type t = 0; t < unknown.size(); t++)
|
||||
file << unknown[t] << "\n";
|
||||
for (map<string, GameOption *>::iterator it = unknownMap.begin(); it != unknownMap.end(); it++)
|
||||
{
|
||||
if (it->second)
|
||||
{
|
||||
if (it->second->str.size())
|
||||
file << it->first << "=" << it->second->str << "\n";
|
||||
else if (it->second->number)
|
||||
file << it->first << "=" << it->second->number << "\n";
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
return 1;
|
||||
@@ -401,6 +408,26 @@ GameOption& GameOptions::operator[](int optionID)
|
||||
return *go;
|
||||
}
|
||||
|
||||
GameOption& GameOptions::operator[](string optionName)
|
||||
{
|
||||
int id = Options::getID(optionName);
|
||||
if (id != INVALID_OPTION)
|
||||
return operator[](id);
|
||||
|
||||
GameOption * go = get(optionName);
|
||||
|
||||
return * go;
|
||||
|
||||
}
|
||||
|
||||
GameOption * GameOptions::get(string optionName)
|
||||
{
|
||||
if (!unknownMap[optionName])
|
||||
unknownMap[optionName] = NEW GameOption(0);
|
||||
|
||||
return unknownMap[optionName];
|
||||
}
|
||||
|
||||
GameOption * GameOptions::get(int optionID)
|
||||
{
|
||||
//Invalid options!
|
||||
@@ -480,6 +507,10 @@ GameOptions::~GameOptions()
|
||||
for (vector<GameOption*>::iterator it = values.begin(); it != values.end(); it++)
|
||||
SAFE_DELETE(*it);
|
||||
values.clear();
|
||||
|
||||
for (map<string, GameOption*>::iterator it = unknownMap.begin(); it != unknownMap.end(); it++)
|
||||
SAFE_DELETE(it->second);
|
||||
unknownMap.clear();
|
||||
}
|
||||
|
||||
GameSettings options;
|
||||
@@ -570,6 +601,22 @@ GameOption& GameSettings::operator[](int optionID)
|
||||
return *go;
|
||||
}
|
||||
|
||||
GameOption& GameSettings::operator[](string optionName)
|
||||
{
|
||||
int id = Options::getID(optionName);
|
||||
if (id != INVALID_OPTION)
|
||||
return operator[](id);
|
||||
|
||||
if (!profileOptions)
|
||||
return invalid_option;
|
||||
|
||||
GameOption * go = profileOptions->get(optionName);
|
||||
|
||||
assert(go);
|
||||
|
||||
return *go;
|
||||
}
|
||||
|
||||
GameOption* GameSettings::get(int optionID)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -477,8 +477,7 @@ void GameStateShop::Update(float dt)
|
||||
lightAlpha = 0;
|
||||
if (lightAlpha > 50)
|
||||
lightAlpha = 50;
|
||||
// mParent->effect->UpdateSmall(dt);
|
||||
// mParent->effect->UpdateBig(dt);
|
||||
|
||||
if (mStage != STAGE_FADE_IN)
|
||||
mElapsed += dt;
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "IconButton.h"
|
||||
#include "WResourceManager.h"
|
||||
#include "WFont.h"
|
||||
|
||||
#define SCALE_SELECTED 1.2f
|
||||
#define SCALE_NORMAL 1.0f
|
||||
|
||||
IconButtonsController::IconButtonsController(float x, float y): JGuiController(0, NULL), mX(x), mY(y)
|
||||
{
|
||||
mListener = this;
|
||||
|
||||
}
|
||||
|
||||
void IconButtonsController::SetColor(PIXEL_TYPE color)
|
||||
{
|
||||
for (int i = 0; i < mCount; ++i)
|
||||
if (mObjects[i])
|
||||
((IconButton *)mObjects[i])->SetColor(color);
|
||||
}
|
||||
|
||||
IconButton::IconButton(int id, IconButtonsController * parent, string texture, float x, float y, float scale, int fontId, string text, float textRelativeX, float textRelativeY, bool hasFocus): JGuiObject(id)
|
||||
{
|
||||
mQuad = NULL;
|
||||
mTex = WResourceManager::Instance()->RetrieveTexture(texture, RETRIEVE_LOCK);
|
||||
if (mTex)
|
||||
{
|
||||
mQuad = NEW JQuad(mTex, 0, 0, (float) mTex->mWidth, (float) mTex->mHeight);
|
||||
}
|
||||
init(parent, mQuad, x, y, scale, fontId, text, textRelativeX, textRelativeY, hasFocus);
|
||||
}
|
||||
|
||||
IconButton::IconButton(int id, IconButtonsController * parent, JQuad * quad, float x, float y, float scale, int fontId, string text, float textRelativeX, float textRelativeY, bool hasFocus): JGuiObject(id)
|
||||
{
|
||||
mTex = NULL;
|
||||
init(parent, quad, x, y, scale, fontId, text, textRelativeX, textRelativeY, hasFocus);
|
||||
}
|
||||
|
||||
void IconButton::init(IconButtonsController * parent, JQuad * quad, float x, float y, float scale, int fontId, string text, float textRelativeX, float textRelativeY, bool hasFocus)
|
||||
{
|
||||
mParent = parent;
|
||||
mQuad = quad;
|
||||
mX = x;
|
||||
mY = y;
|
||||
mScale = scale;
|
||||
mFontId = fontId;
|
||||
mText = text;
|
||||
mTextRelativeX = textRelativeX;
|
||||
mTextRelativeY = textRelativeY;
|
||||
mHasFocus = hasFocus;
|
||||
|
||||
mCurrentScale = scale;
|
||||
mTargetScale = mHasFocus ? SCALE_SELECTED * mScale : SCALE_NORMAL * mScale;
|
||||
SetColor(ARGB(255,255,255,255));
|
||||
}
|
||||
|
||||
void IconButton::SetColor(PIXEL_TYPE color)
|
||||
{
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
bool IconButton::hasFocus()
|
||||
{
|
||||
return mHasFocus;
|
||||
}
|
||||
|
||||
void IconButton::Render()
|
||||
{
|
||||
JRenderer * r = JRenderer::GetInstance();
|
||||
|
||||
float relX = mX + mParent->mX;
|
||||
float relY = mY + mParent->mY;
|
||||
|
||||
if (mQuad)
|
||||
{
|
||||
mQuad->SetColor(mColor);
|
||||
r->RenderQuad(mQuad, relX, relY, 0, mCurrentScale, mCurrentScale);
|
||||
}
|
||||
if (mText.size())
|
||||
{
|
||||
WFont * mFont = WResourceManager::Instance()->GetWFont(mFontId);
|
||||
PIXEL_TYPE backup = mFont->GetColor();
|
||||
mFont->SetColor(ARGB(255,0,0,0));
|
||||
//TODO adapt if mTextRelativeX/Y/align are negative/positive
|
||||
mFont->DrawString(mText.c_str(), relX + mTextRelativeX , relY + mTextRelativeY , JGETEXT_CENTER);
|
||||
mFont->SetColor(backup);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void IconButton::Update(float dt)
|
||||
{
|
||||
if (mCurrentScale < mTargetScale)
|
||||
{
|
||||
mCurrentScale += 8.0f * dt;
|
||||
if (mCurrentScale > mTargetScale) mCurrentScale = mTargetScale;
|
||||
}
|
||||
else if (mCurrentScale > mTargetScale)
|
||||
{
|
||||
mCurrentScale -= 8.0f * dt;
|
||||
if (mCurrentScale < mTargetScale) mCurrentScale = mTargetScale;
|
||||
}
|
||||
}
|
||||
|
||||
void IconButton::Entering()
|
||||
{
|
||||
mHasFocus = true;
|
||||
mTargetScale = SCALE_SELECTED * mScale;
|
||||
}
|
||||
|
||||
bool IconButton::Leaving(JButton key)
|
||||
{
|
||||
mHasFocus = false;
|
||||
mTargetScale = SCALE_NORMAL * mScale;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IconButton::ButtonPressed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
IconButton::~IconButton()
|
||||
{
|
||||
if (mTex)
|
||||
{
|
||||
WResourceManager::Instance()->Release(mTex);
|
||||
SAFE_DELETE(mQuad);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ostream& IconButton::toString(ostream& out) const
|
||||
{
|
||||
return out << "IconButton ::: mHasFocus : " << mHasFocus;
|
||||
}
|
||||
@@ -743,6 +743,15 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
|
||||
}
|
||||
}
|
||||
|
||||
//This one is not a real ability, it displays a message on the screen. We use this for tutorials
|
||||
// Triggers need to be checked above this one, as events are usuallly what will trigger (...) these messages
|
||||
vector<string> splitMsg = parseBetween(s, "tutorial(", ")");
|
||||
if (splitMsg.size())
|
||||
{
|
||||
string msg = splitMsg[1];
|
||||
return NEW ATutorialMessage(card, msg);
|
||||
}
|
||||
|
||||
int restrictions = parseRestriction(s);
|
||||
|
||||
string newName = "";
|
||||
|
||||
@@ -588,7 +588,7 @@ int Rules::load(string _filename)
|
||||
if (_filename.size() < 5 || (_filename.find(".txt") == string::npos && _filename.find(".TXT") == string::npos))
|
||||
return 0;
|
||||
|
||||
if (!filename.size()) //this check is necessary because of the recursive calls (a fil loads other files)
|
||||
if (!filename.size()) //this check is necessary because of the recursive calls (a file loads other files)
|
||||
filename = _filename;
|
||||
char c_filename[4096];
|
||||
if (fileExists(_filename.c_str()))
|
||||
@@ -608,6 +608,7 @@ int Rules::load(string _filename)
|
||||
if (!file) return 0;
|
||||
|
||||
cleanup();
|
||||
|
||||
while (std::getline(file, s))
|
||||
{
|
||||
if (!s.size()) continue;
|
||||
@@ -618,6 +619,7 @@ int Rules::load(string _filename)
|
||||
if (s.find("include ") == 0)
|
||||
{
|
||||
load(s.substr(8));
|
||||
hidden = false; //To avoid transmitting the hidden param to children
|
||||
continue;
|
||||
}
|
||||
if (s.compare("[init]") == 0)
|
||||
|
||||
@@ -8,47 +8,10 @@
|
||||
#include "MTGDefinitions.h"
|
||||
#include <JRenderer.h>
|
||||
#include <math.h>
|
||||
#include "utils.h"
|
||||
|
||||
vector<string> Task::sAIDeckNames;
|
||||
|
||||
/*---------------- Utils -----------------*/
|
||||
// TODO: Move to dedicated file
|
||||
|
||||
//!! Copypaste from GameStateDeckViewer.cpp StringExplode. Move and #include here and there
|
||||
void ExplodeStr(string str, string separator, vector<string>* results)
|
||||
{
|
||||
int found;
|
||||
results->clear();
|
||||
found = str.find_first_of(separator);
|
||||
while (found != (int) string::npos)
|
||||
{
|
||||
if (found > 0)
|
||||
{
|
||||
results->push_back(str.substr(0, found));
|
||||
}
|
||||
else
|
||||
{
|
||||
results->push_back(" ");
|
||||
}
|
||||
str = str.substr(found + 1);
|
||||
found = str.find_first_of(separator);
|
||||
}
|
||||
if (str.length() > 0)
|
||||
{
|
||||
results->push_back(str);
|
||||
}
|
||||
}
|
||||
|
||||
string ImplodeStr(string separator, vector<string> strs)
|
||||
{
|
||||
string result = "";
|
||||
for (vector<string>::iterator it = strs.begin(); it != strs.end(); it++)
|
||||
{
|
||||
result += (it == strs.begin() ? "" : separator) + (*it);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*---------------- Task -----------------*/
|
||||
|
||||
Task::Task(char _type)
|
||||
@@ -80,7 +43,7 @@ string Task::toString()
|
||||
{
|
||||
storeCommonAttribs();
|
||||
storeCustomAttribs();
|
||||
return ImplodeStr(ITEM_SEPARATOR, persistentAttribs);
|
||||
return join(persistentAttribs, ITEM_SEPARATOR);
|
||||
}
|
||||
|
||||
// Store basic attributes to vector, for saving
|
||||
@@ -226,12 +189,12 @@ string Task::getAIDeckName(int id)
|
||||
// End of AI deck buffering code
|
||||
|
||||
// Each child class has to be added to the switch in this function (clumsy..)
|
||||
Task* Task::createFromStr(string params, bool rand)
|
||||
Task* Task::createFromStr(const string params, bool rand)
|
||||
{
|
||||
vector<string> exploded;
|
||||
Task *result;
|
||||
|
||||
ExplodeStr(params, ITEM_SEPARATOR, &exploded);
|
||||
split(params, ITEM_SEPARATOR[0], exploded);
|
||||
|
||||
switch (exploded[0][0])
|
||||
{
|
||||
|
||||
@@ -387,3 +387,13 @@ std::string wordWrap(const std::string& sentence, float width, int fontId)
|
||||
}
|
||||
|
||||
|
||||
unsigned long hash_djb2(const char *str)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
|
||||
while ((c = *str++))
|
||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
|
||||
return hash;
|
||||
}
|
||||
Reference in New Issue
Block a user