Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F102423
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
225 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/WitchBlastGame.cpp b/src/WitchBlastGame.cpp
index e6f5955..cac6623 100644
--- a/src/WitchBlastGame.cpp
+++ b/src/WitchBlastGame.cpp
@@ -1,7390 +1,7398 @@
/** This file is part of Witch Blast.
*
* Witch Blast 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.
*
* Witch Blast 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 Witch Blast. If not, see <http://www.gnu.org/licenses/>.
*/
#include "WitchBlastGame.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/TileMapEntity.h"
#include "DungeonMap.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "sfml_game/EntityManager.h"
#include "Constants.h"
#include "RatEntity.h"
#include "BlackRatEntity.h"
#include "GreenRatEntity.h"
#include "KingRatEntity.h"
#include "CyclopsEntity.h"
#include "GiantSpiderEntity.h"
#include "GiantSlimeEntity.h"
#include "ButcherEntity.h"
#include "BatEntity.h"
#include "ImpEntity.h"
#include "SlimeEntity.h"
#include "LargeSlimeEntity.h"
#include "PumpkinEntity.h"
#include "ChestEntity.h"
#include "EvilFlowerEntity.h"
#include "BubbleEntity.h"
#include "ItemEntity.h"
#include "WitchEntity.h"
#include "CauldronEntity.h"
#include "SnakeEntity.h"
#include "GhostEntity.h"
#include "ZombieEntity.h"
#include "ZombieDarkEntity.h"
#include "BogeymanEntity.h"
#include "LittleSpiderEntity.h"
#include "SpiderEggEntity.h"
#include "FranckyEntity.h"
#include "VampireEntity.h"
#include "ObstacleEntity.h"
#include "ArtefactDescriptionEntity.h"
#include "PnjEntity.h"
#include "TextEntity.h"
#include "StandardRoomGenerator.h"
#include "Scoring.h"
#include "MessageGenerator.h"
#include "TextMapper.h"
#include "SlimePetEntity.h"
#include "SausageEntity.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <ctime>
#include <algorithm>
//#define LEVEL_TEST_MODE
#ifdef ONLINE_MODE
#include "OnlineScoring.h"
#endif // ONLINE_MODE
const float PORTRAIT_DIAPLAY_TIME = 5.0f;
const float ENDING_TIMER = 8.0f;
const unsigned int ACHIEV_LINES = 3;
const int VolumeModifier = 55;
static std::string intToString(int n)
{
std::ostringstream oss;
oss << n;
return oss.str();
}
static std::string keyToString(sf::Keyboard::Key key)
{
std::string s = "Unknown";
if (key >= sf::Keyboard::A && key <= sf::Keyboard::Z)
{
char c = 'A' + key - sf::Keyboard::A;
std::ostringstream oss;
oss << c;
s = oss.str();
}
else if (key >= sf::Keyboard::Num0 && key <= sf::Keyboard::Num9)
{
char c = '0' + key - sf::Keyboard::Num0;
std::ostringstream oss;
oss << c;
s = oss.str();
}
else if (key >= sf::Keyboard::Numpad0 && key <= sf::Keyboard::Numpad9)
{
char c = '0' + key - sf::Keyboard::Num0;
std::ostringstream oss;
oss << c << " (numpad)";
s = oss.str();
}
else if (key >= sf::Keyboard::F1 && key <= sf::Keyboard::F15)
{
std::ostringstream oss;
oss << "F" << (int)key - (int)sf::Keyboard::F1;
s = oss.str();
}
else if (key == sf::Keyboard::Escape) s = "Escape";
else if (key == sf::Keyboard::LControl) s = "Left Control";
else if (key == sf::Keyboard::LShift) s = "Left Shift";
else if (key == sf::Keyboard::LAlt) s = "Left Alt";
else if (key == sf::Keyboard::LSystem) s = "Left System";
else if (key == sf::Keyboard::RControl) s = "Right Control";
else if (key == sf::Keyboard::RShift) s = "Right Shift";
else if (key == sf::Keyboard::RAlt) s = "Right Alt";
else if (key == sf::Keyboard::RSystem) s = "Right System";
else if (key == sf::Keyboard::Space) s = "Space";
else if (key == sf::Keyboard::Tab) s = "Tab";
else if (key == sf::Keyboard::Left) s = "Left arrow";
else if (key == sf::Keyboard::Right) s = "Right arrow";
else if (key == sf::Keyboard::Up) s = "Up arrow";
else if (key == sf::Keyboard::Down) s = "Down arrow";
else if (key == sf::Keyboard::LBracket) s = "[";
else if (key == sf::Keyboard::RBracket) s = "]";
else if (key == sf::Keyboard::SemiColon) s = ";";
else if (key == sf::Keyboard::Comma) s = ",";
else if (key == sf::Keyboard::Period) s = ".";
else if (key == sf::Keyboard::Quote) s = "Quote";
else if (key == sf::Keyboard::Slash) s = "/";
else if (key == sf::Keyboard::BackSlash) s = "\\";
else if (key == sf::Keyboard::Tilde) s = "~";
else if (key == sf::Keyboard::Equal) s = "=";
else if (key == sf::Keyboard::Dash) s = "_";
else if (key == sf::Keyboard::Return) s = "Return";
else if (key == sf::Keyboard::BackSpace) s = "BackSpace";
else if (key == sf::Keyboard::PageUp) s = "Page Up";
else if (key == sf::Keyboard::PageDown) s = "Page Down";
else if (key == sf::Keyboard::End) s = "End";
else if (key == sf::Keyboard::Home) s = "Home";
else if (key == sf::Keyboard::Insert) s = "Insert";
else if (key == sf::Keyboard::Delete) s = "Delete";
else if (key == sf::Keyboard::Add) s = "+";
else if (key == sf::Keyboard::Subtract) s = "-";
else if (key == sf::Keyboard::Multiply) s = "*";
else if (key == sf::Keyboard::Divide) s = "/";
else if (key == sf::Keyboard::Pause) s = "Pause";
else if (key == sf::Keyboard::KeyCount) s = "Key Count";
return s;
}
std::map<EnumWorldEvents, EnumMessages> eventToMessage =
{
{ EventMeetRatsOrBats, MsgInfoRatsBats },
{ EventMeetSnakes, MsgInfoSnakes },
{ EventMeetWitches, MsgInfoWitches },
{ EventGetCoin, MsgInfoGold },
{ EventGetFamiliar, MsgInfoFamiliar },
{ EventBeingHurted, MsgTutoHeal },
{ EventFindShop, MsgTutoShops },
{ EventFindBossDoor, MsgTutoBossDoor },
{ EventFindChallengeDoor, MsgTutoChallengeDoor },
{ EventFindTemple, MsgTutoTemple },
{ EventGetItem, MsgTutoItems },
{ EventGetSpecialShot, MsgTutoShots },
{ EventGetSpell, MsgTutoSpell },
{ EventAchievement, MsgTutoAchievements },
{ EventConsumable, MsgTutoConsumables },
{ EventPotion, MsgTutoPotions },
};
// author: AFS
// source: https://github.com/LaurentGomila/SFML/wiki/Source:-Letterbox-effect-using-a-view
static sf::View getLetterboxView(sf::View view, int windowWidth, int windowHeight)
{
// Compares the aspect ratio of the window to the aspect ratio of the view,
// and sets the view's viewport accordingly in order to archieve a letterbox effect.
// A new view (with a new viewport set) is returned.
float windowRatio = windowWidth / (float) windowHeight;
float viewRatio = view.getSize().x / (float) view.getSize().y;
float sizeX = 1;
float sizeY = 1;
float posX = 0;
float posY = 0;
bool horizontalSpacing = true;
if (windowRatio < viewRatio)
horizontalSpacing = false;
// If horizontalSpacing is true, the black bars will appear on the left and right side.
// Otherwise, the black bars will appear on the top and bottom.
if (horizontalSpacing)
{
sizeX = viewRatio / windowRatio;
posX = (1 - sizeX) / 2.0;
}
else
{
sizeY = windowRatio / viewRatio;
posY = (1 - sizeY) / 2.0;
}
view.setViewport( sf::FloatRect(posX, posY, sizeX, sizeY) );
return view;
}
static sf::View getFullScreenLetterboxView(sf::View view, int clientWidth, int clientHeight)
{
sf::View returnView(sf::FloatRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
float clientRatio = clientWidth / (float) clientHeight;
float viewRatio = view.getSize().x / (float) view.getSize().y;
float sizeX = 1;
float sizeY = 1;
float posX = 0;
float posY = 0;
bool horizontalSpacing = true;
if (clientRatio > viewRatio)
horizontalSpacing = false;
// If horizontalSpacing is true, the black bars will appear on the left and right side.
// Otherwise, the black bars will appear on the top and bottom.
if (horizontalSpacing)
{
sizeX = clientRatio / viewRatio;
posX = (1 - sizeX) / 2.0;
}
else
{
sizeY = viewRatio / clientRatio;
posY = (1 - sizeY) / 2.0;
}
returnView.setViewport( sf::FloatRect(posX, posY, sizeX, sizeY) );
return returnView;
}
namespace
{
WitchBlastGame* gameptr;
}
WitchBlastGame::WitchBlastGame()
{
gameptr = this;
gameFromSaveFile = false;
configureFromFile();
if (parameters.vsync == false)
{
//app->setVerticalSyncEnabled(false);
app->setFramerateLimit(60);
}
// Fullscreen ?
if (parameters.fullscreen)
{
create(SCREEN_WIDTH, SCREEN_HEIGHT, APP_NAME + " V" + APP_VERSION, true, parameters.vsync);
sf::View view = app->getDefaultView();
view = getFullScreenLetterboxView( view, SCREEN_WIDTH, SCREEN_HEIGHT );
app->setView(view);
}
else
{
create(SCREEN_WIDTH, SCREEN_HEIGHT, APP_NAME + " V" + APP_VERSION, false, parameters.vsync);
}
// init current music
currentStandardMusic = 0;
// loading resources
const char *const images[] =
{
"media/player_0.png", "media/player_1.png",
"media/player_2.png",
"media/bolt.png", "media/tiles.png",
"media/rat.png", "media/minimap.png",
"media/map_background.png",
"media/items.png", "media/items_equip.png",
"media/items.png", "media/items_equip.png",
"media/chest.png", "media/bat.png",
"media/evil_flower.png", "media/slime.png",
"media/imp.png", "media/spider_egg.png",
"media/spider_web.png", "media/little_spider.png",
"media/bubble.png", "media/eyeball.png",
"media/witch.png",
"media/cauldron.png", "media/snake.png",
"media/pumpkin.png", "media/ghost.png",
"media/zombie.png", "media/bogeyman.png",
"media/sausage.png",
"media/butcher.png", "media/giant_slime.png",
"media/king_rat.png", "media/cyclops.png",
"media/giant_spider.png", "media/francky.png",
"media/vampire.png", "media/vampire_bat.png",
"media/vampire_part.png",
"media/blood.png",
"media/corpses.png", "media/corpses_big.png",
"media/star.png", "media/star2.png",
"media/hurt_impact.png",
"media/interface.png", "media/hud_shots.png",
"media/explosion.png", "media/keys_qwer.png",
"media/keys_azer.png", "media/message_icons.png",
"media/night.png", "media/title.png",
"media/overlay_00.png", "media/light_cone.png",
"media/divinity.png",
"media/pnj.png", "media/fairy.png",
"media/key_area.png",
"media/ui_life.png", "media/ui_mana.png",
"media/ui_spells.png", "media/ui_message.png",
"media/ui_top_layer.png", "media/ui_achiev.png",
"media/fog.png", "media/title_animation.png",
"media/splatter.png", "media/witch_intro.png",
"media/item_description.png", "media/death_certificate.png",
"media/achievements.png", "media/boss_pictures.png",
"media/portrait_part.png", "media/dungeon_random.png",
"media/dungeon_objects.png", "media/shadows_standard.png",
"media/shadows_corners.png", "media/shadows_medium.png",
"media/shadows_small.png", "media/doors.png",
"media/destroyable_objects.png", "media/hall_of_fame.png",
"media/lightning.png",
};
for (const char *const filename : images)
ImageManager::getInstance().addImage(filename);
const char *const sounds[] =
{
"media/sound/blast00.ogg", "media/sound/blast01.ogg",
"media/sound/blast_elec.ogg", "media/sound/blast_fire.ogg",
"media/sound/blast_ice.ogg", "media/sound/blast_illusion.ogg",
"media/sound/blast_poison.ogg", "media/sound/blast_stone.ogg",
"media/sound/door_closing.ogg", "media/sound/door_opening.ogg",
"media/sound/chest_opening.ogg", "media/sound/impact.ogg",
"media/sound/bonus.ogg", "media/sound/drink.ogg",
"media/sound/eat.ogg", "media/sound/player_hit.ogg",
"media/sound/player_die.ogg", "media/sound/ennemy_dying.ogg",
"media/sound/coin.ogg", "media/sound/pay.ogg",
"media/sound/wall_impact.ogg", "media/sound/big_wall_impact.ogg",
"media/sound/king_rat_cry_1.ogg", "media/sound/king_rat_cry_2.ogg",
"media/sound/king_rat_die.ogg", "media/sound/slime_jump.ogg",
"media/sound/slime_impact.ogg", "media/sound/slime_impact_weak.ogg",
"media/sound/slime_impact_boss.ogg",
"media/sound/slime_smash.ogg", "media/sound/ice_charge.ogg",
"media/sound/electric.ogg", "media/sound/select.ogg",
"media/sound/heart.ogg", "media/sound/rat_die.ogg",
"media/sound/bat_die.ogg", "media/sound/imp_hurt.ogg",
"media/sound/imp_die.ogg", "media/sound/rock_impact.ogg",
"media/sound/rock_impact_medium.ogg", "media/sound/rock_impact_heavy.ogg",
"media/sound/throw.ogg", "media/sound/cyclop00.ogg",
"media/sound/cyclop_die.ogg", "media/sound/cyclops_impact.ogg",
"media/sound/butcher_00.ogg", "media/sound/butcher_01.ogg",
"media/sound/butcher_hurt.ogg", "media/sound/butcher_die.ogg",
"media/sound/vib.ogg",
"media/sound/boom_00.ogg", "media/sound/clang_00.ogg",
"media/sound/bubble_00.ogg", "media/sound/bubble_01.ogg",
"media/sound/trap.ogg", "media/sound/egg_smash_00.ogg",
"media/sound/egg_smash_01.ogg", "media/sound/spider_walking.ogg",
"media/sound/spider_web.ogg", "media/sound/spider_hurt.ogg",
"media/sound/spider_die.ogg", "media/sound/little_spider_die.ogg",
"media/sound/witch_00.ogg", "media/sound/witch_01.ogg",
"media/sound/witch_die_00.ogg", "media/sound/witch_die_01.ogg",
"media/sound/witch_02.ogg", "media/sound/invoke.ogg",
"media/sound/cauldron.ogg", "media/sound/cauldron_die.ogg",
"media/sound/snake_die.ogg", "media/sound/pumpkin_00.ogg",
"media/sound/pumpkin_01.ogg", "media/sound/pumpkin_die.ogg",
"media/sound/critical.ogg",
"media/sound/gong.ogg", "media/sound/teleport.ogg",
"media/sound/spell_charge.ogg", "media/sound/fireball.ogg",
"media/sound/message.ogg", "media/sound/earthquake.ogg",
"media/sound/spell_freeze.ogg", "media/sound/spell_shield.ogg",
"media/sound/heavy_step_00.ogg", "media/sound/heavy_step_01.ogg",
"media/sound/night.ogg", "media/sound/grumble.ogg",
"media/sound/zombie_00.ogg", "media/sound/zombie_01.ogg",
"media/sound/zombie_attack.ogg", "media/sound/zombie_die.ogg",
"media/sound/ghost.ogg", "media/sound/ghost_die.ogg",
"media/sound/electricity.ogg",
"media/sound/electric_blast.ogg", "media/sound/francky_00.ogg",
"media/sound/francky_01.ogg", "media/sound/francky_02.ogg",
"media/sound/francky_die.ogg", "media/sound/om.ogg",
"media/sound/glass.ogg", "media/sound/hiccup.ogg",
"media/sound/splatch.ogg", "media/sound/intro_witch.ogg",
"media/sound/force_field.ogg", "media/sound/door_opening_boss.ogg",
"media/sound/achievement.ogg",
"media/sound/vampire_flying.ogg", "media/sound/vampire_flap.ogg",
"media/sound/vampire_sonic.ogg", "media/sound/vampire_laughing.ogg",
"media/sound/vampire_transform_bolt.ogg", "media/sound/vampire_transform_bat.ogg",
"media/sound/vampire_hypnosis.ogg", "media/sound/vampire_cry.ogg",
"media/sound/vampire_dying.ogg", "media/sound/ice_block.ogg",
"media/sound/bogeyman_die.ogg", "media/sound/bogeyman_attack.ogg",
"media/sound/bogeyman_vortex_00.ogg", "media/sound/bogeyman_vortex_01.ogg",
"media/sound/barrel_hit.ogg", "media/sound/barrel_smash.ogg",
"media/sound/secret.ogg", "media/sound/scroll.ogg",
"media/sound/tic_tac.ogg", "media/sound/bottle.ogg",
"media/sound/thunder.ogg",
};
// AA in fullscreen
if (parameters.fullscreen) enableAA(true);
// game main client position in the UI
xOffset = OFFSET_X;
yOffset = OFFSET_Y;
SoundManager::getInstance().setVolume(parameters.soundVolume);
for (const char *const filename : sounds)
{
SoundManager::getInstance().addSound(filename);
}
if (font.loadFromFile("media/DejaVuSans-Bold.ttf"))
{
myText.setFont(font);
}
miniMap = NULL;
currentMap = NULL;
currentFloor = NULL;
lastScore.score = 0;
lastScore.name = "";
lastScore.level = 0;
int i;
for (i = 0; i < NB_X_GAME; i++) xGame[i].active = false;
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++) equipNudeToDisplay[i] = false;
for (i = 0; i < NB_MESSAGES; i++) gameMessagesToSkip[i] = false;
for (i = 0; i < NB_ACHIEVEMENTS; i++) achievementState[i] = AchievementUndone;
for (i = 0; i < NB_ENEMY; i++) globalData.killedMonster[i] = 0;
saveInFight.monsters.clear();
showLogical = false;
showGameTime = false;
uiSprites.shotsSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_HUD_SHOTS));
uiSprites.topLayer.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_TOP_LAYER));
uiSprites.topLayer.setPosition(0, 602);
uiSprites.msgBoxSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_MESSAGE));
uiSprites.iconSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_MESSAGE_ICONS));
uiSprites.iconSprite.setPosition(12, 614);
uiSprites.mapBgSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_MAP_BACKGROUND));
uiSprites.mapBgSprite.setPosition(342, 23);
introScreenSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_INTRO));
titleSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_TITLE));
titleSprite.setOrigin(titleSprite.getTextureRect().width / 2, titleSprite.getTextureRect().height / 2);
scoreState = ScoreOK;
loopCounter = 0;
loadGameData();
loadHiScores();
receiveScoreFromServer();
srand(time(NULL));
fairySpriteOffsetY = 0;
if (isAdvanced()) fairySpriteOffsetY = 72 + 72 * (rand() % 4);
}
void WitchBlastGame::enableAA(bool enable)
{
for (int i = 0; i < NB_IMAGES; i++)
{
if (i != IMAGE_TILES && i != IMAGE_DUNGEON_OBJECTS
&& i != IMAGE_TILES_SHADOW && i != IMAGE_TILES_SHADOW_CORNER && i != IMAGE_TILES_SHADOW_MEDIUM
&& i != IMAGE_MINIMAP
&& i != IMAGE_DOORS
&& i != IMAGE_FOG
&& i != IMAGE_ITEMS_PRES && i != IMAGE_ITEMS_EQUIP_PRES && i != IMAGE_CORPSES
&& i != IMAGE_CORPSES_BIG)
ImageManager::getInstance().getImage(i)->setSmooth(enable);
}
}
WitchBlastGame::~WitchBlastGame()
{
// cleaning all entities
EntityManager::getInstance().clean();
// cleaning data
if (miniMap != NULL) delete (miniMap);
if (currentFloor != NULL) delete (currentFloor);
if (sendScoreThread.joinable()) sendScoreThread.join();
if (receiveScoreThread.joinable()) receiveScoreThread.join();
}
DungeonMap* WitchBlastGame::getCurrentMap()
{
return currentMap;
}
GameFloor* WitchBlastGame::getCurrentFloor()
{
return currentFloor;
}
int WitchBlastGame::getFloorX()
{
return floorX;
}
int WitchBlastGame::getFloorY()
{
return floorY;
}
DungeonMapEntity* WitchBlastGame::getCurrentMapEntity()
{
return dungeonEntity;
}
PlayerEntity* WitchBlastGame::getPlayer()
{
return player;
}
Vector2D WitchBlastGame::getPlayerPosition()
{
return Vector2D(player->getX(), player->getY());
}
int WitchBlastGame::getLevel()
{
return level;
}
int WitchBlastGame::getChallengeLevel()
{
return challengeLevel;
}
int WitchBlastGame::getSecretsFound()
{
return secretsFound;
}
bool WitchBlastGame::getShowLogical()
{
return showLogical;
}
float WitchBlastGame::getDeltaTime()
{
return deltaTime;
}
float WitchBlastGame::getGameTime()
{
return gameTime;
}
void WitchBlastGame::onUpdate()
{
if (gameState == gameStatePlaying)
{
if (isPlayerAlive) player->setItemToBuy(NULL);
loopCounter++;
if (loopCounter > 3) loopCounter = 0;
// time stop
if (player->isSpecialStateActive(SpecialStateTime))
{
if (loopCounter == 0)
EntityManager::getInstance().animate(deltaTime);
else
player->animate(deltaTime);
SoundManager::getInstance().playSound(SOUND_CLOCK, false);
}
else
{
EntityManager::getInstance().animate(deltaTime);
if (isPressing(KeyTimeControl, false))
{
EntityManager::getInstance().animate(deltaTime);
SoundManager::getInstance().playSound(SOUND_VIB, false);
}
}
if (isPlayerAlive) gameTime += deltaTime;
for (int i = 0; i < NB_X_GAME; i++)
{
if (xGame[i].active)
{
xGame[i].timer -= deltaTime;
if (xGame[i].timer <= 0.0f)
{
xGame[i].active = false;
if (i == (int)xGameTypeFade && xGame[i].param == X_GAME_FADE_OUT)
{
if (player->getPlayerStatus() == PlayerEntity::playerStatusGoingNext)
{
level++;
startNewLevel();
}
else
startNewGame(false, 1);
}
}
}
}
if (isPlayerAlive)
{
if (player->getHp() <= 0)
{
isPlayerAlive = false;
playMusic(MusicEnding);
}
}
}
else if (gameState == gameStatePlayingDisplayBoss)
{
bossDisplayTimer += deltaTime;
if (bossDisplayTimer >= PORTRAIT_DIAPLAY_TIME) gameState = gameStatePlaying;
}
}
void WitchBlastGame::startNewGame(bool fromSaveFile, int startingLevel)
{
gameState = gameStateInit;
level = 1;
challengeLevel = 1;
secretsFound = 0;
gameTime = 0.0f;
initEvents();
scoreSaveFile = "";
interaction.active = false;
endingTimer = -1.0f;
// cleaning all entities
EntityManager::getInstance().clean();
SoundManager::getInstance().stopSound(SOUND_NIGHT);
// cleaning the message queue
std::queue<messageStruct> empty;
std::swap( messagesQueue, empty );
// cleaning the achievements queue
std::queue<achievementStruct> empty2;
std::swap( achievementsQueue, empty2 );
// cleaning data
if (miniMap != NULL) delete (miniMap);
if (currentFloor != NULL) delete (currentFloor);
miniMap = NULL;
currentFloor = NULL;
// init in game menu
buildInGameMenu();
dungeonEntity = new DungeonMapEntity();
// the interface
uiSprites.gui.setTexture(*ImageManager::getInstance().getImage(IMAGE_INTERFACE));
// key symbol on the interface
uiSprites.keySprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
uiSprites.keySprite.setTextureRect(sf::IntRect(ITEM_WIDTH * EQUIP_BOSS_KEY, 0, ITEM_WIDTH, ITEM_HEIGHT));
uiSprites.keySprite.setPosition(737, 612);
miniMap = new GameMap(FLOOR_WIDTH, FLOOR_HEIGHT);
// minimap on the interface
miniMapEntity = new TileMapEntity(ImageManager::getInstance().getImage(IMAGE_MINIMAP), miniMap, 19, 15, 10);
miniMapEntity->setTileBox(20, 16);
miniMapEntity->setX(800);
miniMapEntity->setY(645);
miniMapEntity->setZ(10001.0f);
// doors
doorEntity[0] = new DoorEntity(8);
doorEntity[1] = new DoorEntity(4);
doorEntity[2] = new DoorEntity(2);
doorEntity[3] = new DoorEntity(6);
saveInFight.isFight = false;
if (fromSaveFile)
{
if (!loadGame())
{
fromSaveFile = false;
}
else
{
gameFromSaveFile = true;
playLevel(saveInFight.isFight);
}
}
if (!fromSaveFile)
{
gameFromSaveFile = false;
// the player
player = new PlayerEntity((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f));
resetKilledEnemies();
randomizePotionMap();
if (startingLevel > 1)
{
for (int i = 1; i < startingLevel; i++)
{
level = i;
if (level == 3)
{
player->acquireItem(getItemSpell());
player->acquireItemAfterStance();
}
player->setHpMax(player->getHpMax() + 2 + rand() % 4);
item_equip_enum item = getRandomEquipItem(false, false);
player->acquireItem((enumItemType)(item + FirstEquipItem));
player->acquireItemAfterStance();
item = getRandomEquipItem(true, true);
player->acquireItem((enumItemType)(item + FirstEquipItem));
player->acquireItemAfterStance();
if (i % 2 == 0)
{
item = getRandomEquipItem(false, false);
player->acquireItem((enumItemType)(item + FirstEquipItem));
player->acquireItemAfterStance();
}
}
level++;
player->setHp(player->getHpMax());
player->setGold(8 + rand() % 45);
if (startingLevel > 2)
{
player->loadDivinity(rand() % NB_DIVINITY, (startingLevel - 2) * 200, 1, 0);
}
}
startNewLevel();
}
}
void WitchBlastGame::startNewLevel()
{
// reset floor items
player->resetFloorItem();
// reset present items
resetPresentItems();
bool needShop = false;
// create the new level
if (currentFloor != NULL)
{
if (level > 1)
{
if (!currentFloor->hasRoomOfType(roomTypeMerchant)) needShop = true;
}
delete currentFloor;
}
currentFloor = new GameFloor(level);
if (needShop) currentFloor->setForceShop();
currentFloor->createFloor();
// center it
floorX = FLOOR_WIDTH / 2;
floorY = FLOOR_HEIGHT / 2;
// move the player
if (level == 1)
player->moveTo((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f));
else
player->moveTo((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT - 2 * TILE_HEIGHT));
// the boss room is closed
bossRoomOpened = false;
if (level <= 7) testAndAddMessageToQueue((EnumMessages)(MsgInfoLevel1 + level - 1));
if (level == 1)
{
testAndAddMessageToQueue(MsgTutoBasics);
testAndAddMessageToQueue(MsgTutoTips);
}
playLevel(false);
}
void WitchBlastGame::playLevel(bool isFight)
{
isPlayerAlive = true;
if (!isFight)
{
player->setVelocity(Vector2D(0.0f, 0.0f));
player->setPlayerStatus(PlayerEntity::playerStatusPlaying);
}
// first map is open
roomClosed = false;
// generate the map
refreshMap();
// items from save
currentMap->restoreMapObjects();
if (isFight)
{
checkEntering();
saveMapItems();
}
// populate with monsters
if (isFight)
{
auto monsters_save = saveInFight.monsters;
saveInFight.monsters.clear();
for (auto monster: monsters_save)
addMonster(monster.id, monster.x, monster.y);
if (currentMap->getRoomType() == roomTypeBoss) playMusic(MusicBoss);
else if (currentMap->getRoomType() == roomTypeChallenge) playMusic(MusicChallenge);
else playMusic(MusicDungeon);
}
else
playMusic(MusicDungeon);
// game time counter an state
lastTime = getAbsolutTime();
gameState = gameStatePlaying;
// fade in
xGame[xGameTypeFade].active = true;
xGame[xGameTypeFade].param = X_GAME_FADE_IN;
xGame[xGameTypeFade].timer = FADE_IN_DELAY;
float x0 = MAP_WIDTH * 0.5f * TILE_WIDTH;
float y0 = MAP_HEIGHT * 0.5f * TILE_HEIGHT + 40.0f;
std::ostringstream oss;
oss << tools::getLabel("level") << " " << level;
TextEntity* text = new TextEntity(oss.str(), 30, x0, y0);
text->setAlignment(ALIGN_CENTER);
text->setLifetime(2.5f);
text->setWeight(-36.0f);
text->setZ(1000);
text->setColor(TextEntity::COLOR_FADING_WHITE);
}
void WitchBlastGame::prepareIntro()
{
EntityManager::getInstance().clean();
introSprites[0] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_FOG));
introSprites[0]->setX(SCREEN_WIDTH / 2);
introSprites[0]->setY(SCREEN_HEIGHT - 202);
introSprites[1] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_FOG));
introSprites[1]->setX(SCREEN_WIDTH / 2 + 970);
introSprites[1]->setY(SCREEN_HEIGHT - 202);
gameState = gameStateIntro;
gameTime = 0.0f;
introState = 0;
introSoundState = 0;
SoundManager::getInstance().playSound(SOUND_NIGHT);
}
void WitchBlastGame::updateIntro()
{
gameTime += deltaTime;
bool toMenu = false;
for (int i = 0; i < 2; i++)
{
introSprites[i]->setX(introSprites[i]->getX() - deltaTime * 35);
if (introSprites[i]->getX() < - SCREEN_WIDTH / 2) introSprites[i]->setX(introSprites[i]->getX() + 2 * SCREEN_WIDTH);
}
if (gameTime > 2.0f && introSoundState == 0)
{
SoundManager::getInstance().playSound(SOUND_INTRO_WITCH);
introSoundState++;
}
else if (gameTime > 7.0f && introSoundState == 1)
{
playMusic(MusicIntro);
introSoundState++;
}
if (introState == 0 && gameTime > 2.5f)
{
introState = 1;
introSprites[2] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_TITLE_ANIM),
SCREEN_WIDTH / 2,
SCREEN_HEIGHT / 2,
310, 278, 3);
introSprites[2]->setZ(50);
}
else if (introState == 1)
{
int frame = (gameTime - 2.5f) * 8.0f;
if (frame > 16)
{
frame = 16;
introState = 2;
introSprites[3] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_WITCH_INTRO));
introSprites[3]->setX(368 + 1000);
introSprites[3]->setY(424 - 480);
introSprites[3]->setZ(40);
EntityManager::getInstance().sortByZ();
}
introSprites[2]->setFrame(frame);
}
else if (introState == 2)
{
float xSprite = introSprites[3]->getX() - deltaTime * 800;
float ySprite = introSprites[3]->getY() + deltaTime * 400;
if (xSprite < 368)
{
introState = 3;
introSprites[3]->setDying(true);
EntityManager::getInstance().animate(deltaTime);
xSprite = 368;
ySprite = 424;
introSprites[4] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_SPLATTER));
introSprites[4]->setX(368);
introSprites[4]->setY(424);
introSprites[4]->setZ(45);
introSprites[4]->setScale(0.5f, 0.5f);
EntityManager::getInstance().sortByZ();
SoundManager::getInstance().stopSound(SOUND_INTRO_WITCH);
SoundManager::getInstance().playSound(SOUND_SPLATCH);
}
else
{
introSprites[3]->setX(xSprite);
introSprites[3]->setY(ySprite);
introSprites[3]->setAngle(gameTime * 500);
}
}
else if (introState == 3)
{
float scale = introSprites[4]->getScaleX();
scale += deltaTime * 5.0f;
if (scale > 1.0f) scale = 1.0f;
introSprites[4]->setScale(scale, scale);
if (gameTime > 8.0f)
{
introState = 4;
introSprites[2]->setDying(true);
introSprites[4]->setDying(true);
EntityManager::getInstance().animate(deltaTime);
toMenu = true;
}
}
sf::Event event;
bool stopDemo = false;
while (app->pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
{
//saveGameData();
app->close();
}
if (event.type == sf::Event::Resized)
{
enableAA(true);
sf::View view = app->getDefaultView();
view = getLetterboxView( view, event.size.width, event.size.height );
app->setView(view);
}
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Escape) stopDemo = true;
}
}
if (isPressing(KeyFireDown, true)) stopDemo = true;
if (stopDemo)
{
if (introState < 4)
{
if (introState > 0) introSprites[2]->setDying(true);
if (introState == 2) introSprites[3]->setDying(true);
if (introState > 2) introSprites[4]->setDying(true);
EntityManager::getInstance().animate(deltaTime);
if (introState < 3)
{
SoundManager::getInstance().stopSound(SOUND_INTRO_WITCH);
SoundManager::getInstance().playSound(SOUND_SPLATCH);
}
}
toMenu = true;
}
if (toMenu)
{
if (introSoundState <= 1) playMusic(MusicIntro);
switchToMenu();
}
}
void WitchBlastGame::renderIntro()
{
app->draw(introScreenSprite);
titleSprite.setPosition(SCREEN_WIDTH / 2 - 15, 371);
if (introState == 4) app->draw(titleSprite);
EntityManager::getInstance().render(app);
}
void WitchBlastGame::updateRunningGame()
{
bool backToMenu = false;
bool escape = false;
// Process events
sf::Event event;
while (app->pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
{
if (gameState == gameStatePlaying && !player->isDead()) saveGame();
saveGameData();
app->close();
}
if (event.type == sf::Event::Resized)
{
enableAA(true);
sf::View view = app->getDefaultView();
view = getLetterboxView( view, event.size.width, event.size.height );
app->setView(view);
}
if (event.type == sf::Event::MouseWheelMoved)
{
if (gameState == gameStatePlaying) player->selectNextShotType();
}
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Escape)
{
escape = true;
}
if (event.key.code == sf::Keyboard::Return && gameState == gameStatePlaying)
{
if (!achievementsQueue.empty())
{
if (achievementsQueue.front().timer > 1.0f)
achievementsQueue.front().timer = 1.0f;
}
else if (!messagesQueue.empty())
{
if (messagesQueue.front().timer > 0.5f)
messagesQueue.front().timer = 0.5f;
}
}
if (event.key.code == sf::Keyboard::X)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)) startNewGame(false, 1);
}
if (event.key.code >= sf::Keyboard::Num1 && event.key.code <= sf::Keyboard::Num8)
{
#ifdef LEVEL_TEST_MODE
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt) && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl))
{
startNewGame(false, event.key.code - sf::Keyboard::Num1 + 1);
}
else
#endif
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift))
{
player->dropConsumables(event.key.code - sf::Keyboard::Num1);
}
else
{
player->tryToConsume(event.key.code - sf::Keyboard::Num1);
}
}
if (event.key.code == sf::Keyboard::F1)
{
if (!isPlayerAlive && player->getEndAge() > 3.5f)
{
if (scoreSaveFile.compare("") == 0) saveDeathScreen();
}
else
{
saveScreen();
}
}
if (event.key.code == sf::Keyboard::F2)
{
showLogical = !showLogical;
}
if (event.key.code == sf::Keyboard::F3)
{
showGameTime = !showGameTime;
}
// DEBUG
#ifdef TEST_MODE
/*if (event.key.code == sf::Keyboard::Delete)
{
StructHurt hurt;
hurt.critical = false;
hurt.damage = 1;
hurt.enemyType = EnemyTypeGhost; //EnemyTypeNone;
hurt.goThrough = false;
hurt.hurtingType = ShotTypeStandard;
hurt.level = 0;
hurt.sourceType = SourceTypeMelee;
player->hurt(hurt);
}*/
if (event.key.code == sf::Keyboard::F5)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new BubbleEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 + 70,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2, BubbleTriple, 0);
new BubbleEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 - 70,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2, BubbleIce, 0);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeRat, 1);
findPlaceMonsters(EnemyTypeRatBlack, 1);
findPlaceMonsters(EnemyTypeRatGreen, 1);
findPlaceMonsters(EnemyTypeRatHelmet, 1);
findPlaceMonsters(EnemyTypeRatBlackHelmet, 1);
}
}
if (event.key.code == sf::Keyboard::F6)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new ButcherEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeBat, 1);
findPlaceMonsters(EnemyTypeBatSkeleton, 2);
findPlaceMonsters(EnemyTypeImpBlue, 1);
findPlaceMonsters(EnemyTypeImpRed, 1);
}
}
if (event.key.code == sf::Keyboard::F7)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new GiantSlimeEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeEvilFlower, 1);
findPlaceMonsters(EnemyTypeEvilFlowerIce, 1);
findPlaceMonsters(EnemyTypeEvilFlowerFire, 1);
findPlaceMonsters(EnemyTypePumpkin, 1);
}
}
if (event.key.code == sf::Keyboard::F8)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new CyclopsEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeSlime, 1);
findPlaceMonsters(EnemyTypeSlimeBlue, 1);
findPlaceMonsters(EnemyTypeSlimeRed, 1);
findPlaceMonsters(EnemyTypeSlimeViolet, 1);
}
}
if (event.key.code == sf::Keyboard::F9)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new KingRatEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeSnake, 2);
findPlaceMonsters(EnemyTypeSnakeBlood, 2);
}
}
if (event.key.code == sf::Keyboard::F10)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new GiantSpiderEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeWitch, 1);
findPlaceMonsters(EnemyTypeWitchRed, 1);
findPlaceMonsters(EnemyTypeCauldron, 1);
findPlaceMonsters(EnemyTypeCauldronElemental, 1);
}
}
if (event.key.code == sf::Keyboard::F11)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new FranckyEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeSpiderEgg_invocated, 2);
findPlaceMonsters(EnemyTypeSpiderLittle, 2);
findPlaceMonsters(EnemyTypeSpiderTarantula, 2);
}
}
if (event.key.code == sf::Keyboard::F12)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new VampireEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeZombie, 2);
findPlaceMonsters(EnemyTypeZombieDark, 2);
findPlaceMonsters(EnemyTypeGhost, 2);
findPlaceMonsters(EnemyTypeBogeyman, 2);
}
}
if (event.key.code == sf::Keyboard::F4)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift))
for (int i = 0; i < NUMBER_ITEMS - NUMBER_EQUIP_ITEMS; i++)
new ItemEntity((enumItemType)i, 100 + (i % 14) * 58, 100 + (i / 14) * 60);
else
for (int i = NUMBER_ITEMS - NUMBER_EQUIP_ITEMS; i < NUMBER_ITEMS; i++)
new ItemEntity((enumItemType)i, 100 + ( (i - NUMBER_ITEMS + NUMBER_EQUIP_ITEMS) % 14) * 58, 100 + ((i - NUMBER_ITEMS + NUMBER_EQUIP_ITEMS) / 14) * 60);
}
#endif // TEST_MODE
}
}
// POST EVENT
if (escape)
{
if (player->isDead() || player->getPlayerStatus() == PlayerEntity::playerStatusVictorious) backToMenu = true;
else if (gameState == gameStatePlaying) gameState = gameStatePlayingPause;
else if (gameState == gameStatePlayingPause) gameState = gameStatePlaying;
else if (gameState == gameStatePlayingDisplayBoss) gameState = gameStatePlaying;
}
if ( (player->isDead() || player->getPlayerStatus() == PlayerEntity::playerStatusVictorious) && !xGame[xGameTypeFade].active && isPressing(KeyFireDown, true))
{
if (player->getEndAge() < DEATH_CERTIFICATE_DELAY) player->setEndAge(DEATH_CERTIFICATE_DELAY);
else backToMenu = true;
}
else if (gameState == gameStatePlayingPause)
{
if (isPressing(KeyDown, true))
{
menuInGame.index++;
if (menuInGame.index == menuInGame.items.size()) menuInGame.index = 0;
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
else if (isPressing(KeyUp, true))
{
if (menuInGame.index == 0) menuInGame.index = menuInGame.items.size() - 1;
else menuInGame.index--;
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
else if (isPressing(KeyFireDown, true))
{
switch (menuInGame.items[menuInGame.index].id)
{
case MenuStartNew:
case MenuStartOld:
case MenuKeys:
case MenuJoystick:
case MenuConfig:
case MenuTutoReset:
case MenuConfigBack:
case MenuLanguage:
case MenuCredits:
case MenuHiScores:
case MenuPlayerName:
case MenuVolumeMusic:
case MenuVolumeSound:
case MenuAchievements:
std::cout << "[ERROR] Bad Menu ID\n";
break;
case MenuExit:
backToMenu = true;
remove(SAVE_FILE.c_str());
break;
case MenuContinue:
gameState = gameStatePlaying;
break;
case MenuSaveAndQuit:
saveGame();
backToMenu = true;
break;
}
}
}
else if (gameState == gameStatePlaying)
{
if (player->canMove()) player->setVelocity(Vector2D(0.0f, 0.0f));
if (isPressing(KeyLeft, false))
{
if (isPressing(KeyUp, false))
player->move(7);
else if (isPressing(KeyDown, false))
player->move(1);
else
player->move(4);
}
else if (isPressing(KeyRight, false))
{
if (isPressing(KeyUp, false))
player->move(9);
else if (isPressing(KeyDown, false))
player->move(3);
else
player->move(6);
}
else if (isPressing(KeyUp, false))
{
player->move(8);
}
else if (isPressing(KeyDown, false))
{
player->move(2);
}
if (isPressing(KeyInteract, true))
{
if (!player->isDead() && interaction.active) player->interact(interaction.type, interaction.id);
}
if (isPressing(KeyFireSelect, true))
{
if (gameState == gameStatePlaying) player->selectNextShotType();
}
if (isPressing(KeySpell, true))
{
if (gameState == gameStatePlaying) player->castSpell();
}
player->resetFireDirection();
if (isPressing(KeyFireLeft, false))
player->fire(4);
else if (isPressing(KeyFireRight, false))
player->fire(6);
else if (isPressing(KeyFireUp, false))
player->fire(8);
else if (isPressing(KeyFireDown, false))
player->fire(2);
// alternative "one button" gameplay
else if (isPressing(KeyFire, false))
{
if (gameState == gameStatePlaying && isPressing(KeyFire, true))
firingDirection = player->getFacingDirection();
player->fire(firingDirection);
}
// alternative "firing with the mouse" gameplay
else if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
sf::Vector2i mousePosition = sf::Mouse::getPosition(*app);
int xm = mousePosition.x - player->getX();
int ym = mousePosition.y - player->getY();
if (abs(xm) >= abs(ym))
{
if (xm > 0) player->fire(6);
else player->fire(4);
}
else
{
if (ym > 0) player->fire(2);
else player->fire(8);
}
}
// spell (right click)
if (sf::Mouse::isButtonPressed(sf::Mouse::Right) && (gameState == gameStatePlaying))
{
sf::Vector2i mousePosition = sf::Mouse::getPosition(*app);
int xm = mousePosition.x - player->getX();
int ym = mousePosition.y - player->getY();
if (abs(xm) >= abs(ym))
{
if (xm > 0) player->setFacingDirection(6);
else player->setFacingDirection(4);
}
else
{
if (ym > 0) player->setFacingDirection(2);
else player->setFacingDirection(8);
}
player->castSpell();
}
// message queue
if (!messagesQueue.empty())
{
messagesQueue.front().timer -= deltaTime;
if (messagesQueue.front().timer < 0.0f)
{
messagesQueue.pop();
if (!messagesQueue.empty()) SoundManager::getInstance().playSound(SOUND_MESSAGE);
}
}
// achievement queue
if (!achievementsQueue.empty() && achievementsQueue.front().hasStarted)
{
achievementsQueue.front().timer -= deltaTime;
if (achievementsQueue.front().timer < 0.0f)
{
achievementsQueue.pop();
}
}
// victorious end of game ?
if (endingTimer > 0.0f)
{
endingTimer -= deltaTime;
if (endingTimer <= 0.0f)
{
calculateScore();
player->setPlayerStatus(PlayerEntity::playerStatusVictorious);
player->setVelocity(Vector2D(0, 0));
}
}
}
else if (gameState == gameStatePlayingDisplayBoss)
{
if (isPressing(KeyFireDown, true)) gameState = gameStatePlaying;
}
onUpdate();
verifyDoorUnlocking();
checkInteraction();
if (roomClosed)
{
if (getEnemyCount() == 0)
{
currentMap->setCleared(true);
if (currentMap->getRoomType() == roomTypeKey)
new ItemEntity( (enumItemType)(ItemBossKey),
MAP_WIDTH / 2 * TILE_WIDTH + TILE_WIDTH / 2,
MAP_HEIGHT / 2 * TILE_HEIGHT + TILE_HEIGHT / 2);
player->onClearRoom();
openDoors();
remove(SAVE_FILE.c_str());
if (currentMap->getRoomType() == roomTypeBoss)
{
playMusic(MusicDungeon);
}
else if (currentMap->getRoomType() == roomTypeChallenge && !player->isDead())
{
ChestEntity* chest = new ChestEntity((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f),
ChestChallenge, false);
chest->makeAppear();
// sound
SoundManager::getInstance().playSound(SOUND_GONG);
playMusic(MusicDungeon);
// text
float x0 = MAP_WIDTH * 0.5f * TILE_WIDTH;
float y0 = MAP_HEIGHT * 0.5f * TILE_HEIGHT + 40.0f;
TextEntity* text = new TextEntity("COMPLETE !", 30, x0, y0);
text->setAlignment(ALIGN_CENTER);
text->setLifetime(2.5f);
text->setWeight(-36.0f);
text->setZ(1200);
text->setColor(TextEntity::COLOR_FADING_WHITE);
challengeLevel++;
if (challengeLevel == 5) registerAchievement(AchievementChallenges);
player->offerChallenge();
}
}
}
if (backToMenu)
{
if (player->isDead() || player->getPlayerStatus() == PlayerEntity::playerStatusVictorious)
{
EntityManager::getInstance().clean();
introSprites[0] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_FOG));
introSprites[0]->setX(SCREEN_WIDTH / 2);
introSprites[0]->setY(SCREEN_HEIGHT - 202);
introSprites[1] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_FOG));
introSprites[1]->setX(SCREEN_WIDTH / 2 + 970);
introSprites[1]->setY(SCREEN_HEIGHT - 202);
switchToMenu();
menuState = MenuStateHiScores;
#ifdef ONLINE_MODE
menuScoreIndex = 0;
#else
menuScoreIndex = 2;
#endif
}
else
{
prepareIntro();
switchToMenu();
menuState = MenuStateMain;
}
}
}
void WitchBlastGame::addLifeBarToDisplay(std::string label, int hp, int hpMax)
{
lifeBar.toDisplay = true;
lifeBar.label = label;
lifeBar.hp = hp;
lifeBar.hpMax = hpMax;
}
void WitchBlastGame::renderBossPortrait()
{
if (gameState == gameStatePlayingDisplayBoss)
{
float transitionTime = 2.5f;
float endTime = PORTRAIT_DIAPLAY_TIME;
int xBoss = GAME_WIDTH / 2 - 267;
int fade = 255;
if (bossDisplayTimer < 0.25f)
{
xBoss += (0.25f - bossDisplayTimer) * 3000;
//fade = 255 - (0.25f - bossDisplayTimer) * 1000;
}
else if (bossDisplayTimer > endTime - 0.75f)
{
fade = (endTime - bossDisplayTimer) * 333;
if (fade < 0) fade = 0;
}
// background
sf::RectangleShape rectangle;
rectangle.setFillColor(sf::Color(0, 0, 0, fade));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH, MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
// boss
if (bossDisplayTimer > transitionTime) // + 1.0f)
{
EnemyEntity* boss = getBoss();
if (boss)
{
sf::View view = app->getView();
view.move(-5, -5);
app->setView(view);
boss->render(app);
view.move(5, 5);
app->setView(view);
}
/*if (bossDisplayTimer < transitionTime + 1.5f)
{
rectangle.setFillColor(sf::Color(0, 0, 0, (1.5 - (bossDisplayTimer - transitionTime)) * 510));
app->draw(rectangle);
std::cout << 1.5 - (bossDisplayTimer - transitionTime) << " ";
}*/
//if (bossDisplayTimer < transitionTime + 2.0f)
{
//rectangle.setFillColor(sf::Color(0, 0, 0, (2.0 - (bossDisplayTimer - transitionTime)) * 255));
//app->draw(rectangle);
//std::cout << 1.5 - (bossDisplayTimer - transitionTime) << " ";
}
}
// boss portrait
if (bossDisplayTimer < transitionTime)
{
sf::Sprite bossSprite;
bossSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_BOSS_PICTURES));
bossSprite.setPosition(xBoss, 0);
app->draw(bossSprite);
}
else
{
if (bossDisplayState == 0)
{
SoundManager::getInstance().playSound(SOUND_BOOM_00);
for (int i = 0; i < 250; i++)
{
SpriteEntity* spriteStar = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_PORTRAIT_PART),
GAME_WIDTH / 2 - 150 + rand() % 300, GAME_HEIGHT / 2 - 150 + rand() % 300);
spriteStar->setScale(5.0f, 5.0f);
spriteStar->setZ(7000.0f);
spriteStar->setSpin(-100 + rand()%200);
spriteStar->setVelocity(Vector2D(400 + rand()%800));
spriteStar->setFading(true);
spriteStar->setLifetime(4.1f + (rand() % 100) * 0.003f );
spriteStar->setColor(sf::Color(rand() % 255, rand() % 255, 255, 128));
spriteStar->setColor(sf::Color(40, 4, 40, 128));
spriteStar->setType(ENTITY_EFFECT);
if (rand()% 2 == 0) spriteStar->setRenderAdd();
}
bossDisplayState = 1;
}
else if (bossDisplayState == 1 && bossDisplayTimer > transitionTime + 0.2f)
{
bossDisplayState = 2;
for (int i = 0; i < 50; i++)
{
SpriteEntity* spriteStar = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_PORTRAIT_PART),
GAME_WIDTH / 2 - 150 + rand() % 300, GAME_HEIGHT / 2 - 150 + rand() % 300);
spriteStar->setScale(4.0f, 4.0f);
spriteStar->setZ(7000.0f);
spriteStar->setSpin(-100 + rand()%200);
spriteStar->setVelocity(Vector2D(400 + rand()%800));
spriteStar->setFading(true);
spriteStar->setLifetime(4.1f + (rand() % 100) * 0.003f );
spriteStar->setColor(sf::Color(rand() % 255, rand() % 255, 255, 128));
spriteStar->setColor(sf::Color(20, 2, 20, 128));
spriteStar->setType(ENTITY_EFFECT);
spriteStar->setRenderAdd();
}
}
else if (bossDisplayState == 2 && bossDisplayTimer > transitionTime + 0.4f)
{
bossDisplayState = 3;
for (int i = 0; i < 50; i++)
{
SpriteEntity* spriteStar = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_PORTRAIT_PART),
GAME_WIDTH / 2 - 150 + rand() % 300, GAME_HEIGHT / 2 - 150 + rand() % 300);
spriteStar->setScale(3.0f, 3.0f);
spriteStar->setZ(7000.0f);
spriteStar->setSpin(-100 + rand()%200);
spriteStar->setVelocity(Vector2D(400 + rand()%800));
spriteStar->setFading(true);
spriteStar->setLifetime(4.1f + (rand() % 100) * 0.003f );
spriteStar->setColor(sf::Color(rand() % 255, rand() % 255, 255, 128));
spriteStar->setColor(sf::Color(20, 2, 20, 128));
spriteStar->setType(ENTITY_EFFECT);
spriteStar->setRenderAdd();
}
}
animateEffects();
}
}
}
void WitchBlastGame::renderGame()
{
lifeBar.toDisplay = false;
EntityManager::getInstance().renderUnder(app, 5000);
EntityManager::getInstance().renderUnder(app, 5000);
}
void WitchBlastGame::generateUiParticle(float x, float y)
{
SpriteEntity* particle = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_BOLT),
x, y, BOLT_WIDTH, BOLT_HEIGHT);
particle->setFading(true);
particle->setImagesProLine(BOLT_PRO_LINE);
particle->setZ(10000);
particle->setLifetime(0.5f);
particle->setVelocity(Vector2D(30 + rand() % 50));
particle->setWeight(200);
particle->setType(ENTITY_EFFECT);
//particle->setFrame(BOLT_PRO_LINE + 2);
particle->setFrame(BOLT_PRO_LINE * 2 + 6);
particle->setRenderAdd();
particle->setScale(0.35f, 0.35f);
particle->setFading(true);
}
void WitchBlastGame::renderHud()
{
// boss life bar ?
if (lifeBar.toDisplay && gameState != gameStatePlayingDisplayBoss) renderLifeBar();
//renderBossPortrait();
// interaction text ?
if (interaction.active)
{
if (interaction.type == InteractionTypeTemple)
write(interaction.label, 20, GAME_WIDTH / 2, 480, ALIGN_CENTER,sf::Color::White, app, 2, 2, 0);
else if (interaction.type == InteractionTypeMerchandise)
write(interaction.label, 20, GAME_WIDTH / 2, 480, ALIGN_CENTER,sf::Color::White, app, 2, 2, 0);
}
// light cone ?
float fade = player->getLightCone();
if (fade > 0.0f)
{
sf::Sprite cone;
cone.setTexture(*ImageManager::getInstance().getImage(IMAGE_LIGHT_CONE));
cone.setPosition(player->getX() - 64, player->getY() - 580);
cone.setColor(sf::Color(255, 255, 255, 255 * fade));
app->draw(cone, sf::BlendAdd);
}
app->draw(uiSprites.gui);
EntityManager::getInstance().renderAfter(app, 5000);
if (gameState == gameStatePlayingDisplayBoss)
{
// boss name
int fade = 255;
if (bossDisplayTimer < 0.25f)
{
fade = 255 - (0.25f - bossDisplayTimer) * 1000;
}
else if (bossDisplayTimer > PORTRAIT_DIAPLAY_TIME - 0.25f)
{
fade = (PORTRAIT_DIAPLAY_TIME - bossDisplayTimer) * 1000;
if (fade < 0) fade = 0;
}
write("THE COOK", 27, GAME_WIDTH / 2, 540, ALIGN_CENTER, sf::Color(255, 255, 255, fade), app, 0, 0, 0);
}
}
void WitchBlastGame::renderLifeBar()
{
if (lifeBar.toDisplay)
{
float l = lifeBar.hp * ((MAP_WIDTH - 1) * TILE_WIDTH) / lifeBar.hpMax;
int label_dy = 0;
sf::RectangleShape rectangle(sf::Vector2f((MAP_WIDTH - 1) * TILE_WIDTH, 25));
rectangle.setFillColor(sf::Color(0, 0, 0,128));
rectangle.setPosition(sf::Vector2f(TILE_WIDTH / 2, label_dy + 22));
rectangle.setOutlineThickness(1);
rectangle.setOutlineColor(sf::Color(200, 200, 200, 200));
app->draw(rectangle);
rectangle.setSize(sf::Vector2f(l, 25));
rectangle.setFillColor(sf::Color(190, 20, 20));
rectangle.setOutlineThickness(0);
rectangle.setPosition(sf::Vector2f(TILE_WIDTH / 2, label_dy + 22));
app->draw(rectangle);
game().write( lifeBar.label,
18,
TILE_WIDTH / 2 + 10.0f,
label_dy + 23,
ALIGN_LEFT,
sf::Color(255, 255, 255),
app, 0 , 0, 0);
}
}
void WitchBlastGame::renderRunningGame()
{
EntityManager::getInstance().sortByZ();
getCurrentMapEntity()->computeBoltParticulesVertices();
if (!isPlayerAlive)
{
sf::View view = app->getView();
sf::View viewSave = app->getView();
float endAge = player->getEndAge();
if (!parameters.zoom || endAge > 4.0f)
{
// do nothing
}
else if (endAge > 3.0f)
{
view.zoom(1.0f - 0.75f * (4.0f - endAge));
float xDiff = view.getCenter().x - player->getX();
float yDiff = view.getCenter().y - player->getY();
view.setCenter(view.getCenter().x - xDiff * (4.0f - endAge),
view.getCenter().y - yDiff * (4.0f - endAge));
}
else if (endAge > 1.0f)
{
view.zoom(0.25f);
view.setCenter(player->getX(), player->getY());
}
else
{
view.zoom(1.0f - 0.75f * endAge);
float xDiff = view.getCenter().x - player->getX();
float yDiff = view.getCenter().y - player->getY();
view.setCenter(view.getCenter().x - xDiff * endAge,
view.getCenter().y - yDiff * endAge);
}
view.move(-5, -5);
app->setView(view);
renderGame();
app->setView(viewSave);
renderHud();
}
else if (parameters.zoom && gameTime < 1.0f)
{
sf::View view = app->getView();
sf::View viewSave = app->getView();
view.zoom(0.25f + 0.75f * (gameTime));
view.move(-5, -5);
app->setView(view);
renderGame();
app->setView(viewSave);
renderHud();
}
else if (xGame[xGameTypeShake].active)
{
sf::View view = app->getView();
sf::View viewSave = app->getView();
view.move(-4 + rand() % 9, -4 + rand() % 9);
app->setView(view);
renderGame();
app->setView(viewSave);
renderHud();
}
else
{
sf::View view = app->getView();
sf::View viewSave = app->getView();
view.move(-OFFSET_X, -OFFSET_Y);
app->setView(view);
renderGame();
app->setView(viewSave);
renderHud();
}
sf::RectangleShape rectangle(sf::Vector2f(200, 25));
// effects
if (player->isSpecialStateActive(SpecialStateTime))
{
sf::RectangleShape whiteLine = sf::RectangleShape(sf::Vector2f(GAME_WIDTH, 2));
whiteLine.setFillColor(sf::Color(255, 255, 255, 32));
for (int i = 0; i < 8; i++)
{
whiteLine.setPosition(xOffset, yOffset + rand() % GAME_HEIGHT);
app->draw(whiteLine);
}
}
if (isPressing(KeyTimeControl, false) && gameState == gameStatePlaying)
{
// effect
int effectFade = 10 + 20 * (1.0f + cos(12.0f * getAbsolutTime())) * 0.5f;
rectangle.setFillColor(sf::Color(0, 255, 255, effectFade));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
sf::RenderStates r;
r.blendMode = sf::BlendAlpha ;
app->draw(rectangle, r);
}
if (xGame[xGameTypeFade].active && xGame[xGameTypeFade].param == X_GAME_FADE_IN)
{
// fade in
rectangle.setFillColor(sf::Color(0, 0, 0, 255 - ((FADE_IN_DELAY - xGame[xGameTypeFade].timer) / FADE_IN_DELAY) * 255));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
}
else if (xGame[xGameTypeFade].active && xGame[xGameTypeFade].param == X_GAME_FADE_OUT)
{
// fade out
rectangle.setFillColor(sf::Color(0, 0, 0, ((FADE_IN_DELAY - xGame[xGameTypeFade].timer) / FADE_IN_DELAY) * 255));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
}
if (player->isSpecialStateActive(SpecialStateConfused))
{
specialStateStuct specialState = player->getSpecialState(SpecialStateConfused);
// effect
int effectFade = 150 + cos(3.0f * getAbsolutTime()) * 100;
// fade
int fade = 55;
if (specialState.timer < 0.4f)
fade = 55 - (0.4f - specialState.timer) / 0.4f * 55;
else if (specialState.timer > specialState.param1 - 0.4f)
fade = (specialState.param1 - specialState.timer) / 0.4f * 55;
if (fade < 0) fade = 0;
else if (fade > 55) fade = 55;
fade *= 1.5f;
rectangle.setFillColor(sf::Color(255 - effectFade, 0, effectFade, fade));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
sf::RenderStates r;
r.blendMode = sf::BlendAlpha ;
app->draw(rectangle, r);
}
else if (xGame[xGameTypeFadeColor].active)
{
// color fade
unsigned int r = 0, g = 0, b = 0;
switch (xGame[xGameTypeFadeColor].param)
{
case X_GAME_COLOR_RED:
r = 255;
g = 100;
break;
case X_GAME_COLOR_GREEN:
g = 255;
break;
case X_GAME_COLOR_BLUE:
b = 255;
break;
case X_GAME_COLOR_VIOLET:
r = 255;
b = 200;
break;
case X_GAME_COLOR_BROWN:
r = 200;
b = 100;
g = 150;
break;
case X_GAME_COLOR_WHITE:
r = 255;
b = 255;
g = 255;
break;
}
int alpha = xGame[xGameTypeFadeColor].timer * 200.0f / xGame[xGameTypeFadeColor].duration;
rectangle.setFillColor(sf::Color(r, g, b, alpha));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle, sf::BlendAdd);
}
if (gameState != gameStatePlayingDisplayBoss) renderMessages();
app->draw(uiSprites.topLayer);
std::ostringstream oss;
oss << player->getGold();
write(oss.str(), 18, 518, 619, ALIGN_CENTER, sf::Color::White, app, 0, 0, 0);
myText.setColor(sf::Color(0, 0, 0, 255));
myText.setCharacterSize(16);
oss.str("");
oss << tools::getLabel("level") << " " << level;
write(oss.str(), 16, 880, 610, ALIGN_CENTER, sf::Color::Black, app, 0, 0, 0);
//if (gameState == gameStatePlaying)
{
sf::Sprite hpSprite;
hpSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_LIFE));
int hpFade = 88.0f * (float)player->getHpDisplay() / (float)player->getHpMax();
if (hpFade < 0) hpFade = 0;
else if (hpFade > 88) hpFade = 88;
hpSprite.setPosition(170, 619 + 88 - hpFade);
hpSprite.setTextureRect(sf::IntRect(0, 88 - hpFade, 88, hpFade));
app->draw(hpSprite);
oss.str("");
oss << player->getHp() << "/" << player->getHpMax();
write(oss.str(), 16, 210, 654, ALIGN_CENTER, sf::Color::White, app, 0, 0, 0);
// mana
sf::Sprite manaSprite;
manaSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_MANA));
int manaFade = player->getPercentFireDelay() * 98;
manaSprite.setPosition(558, 614 + 98 - manaFade);
manaSprite.setTextureRect(sf::IntRect(0, 98 - manaFade, 98, manaFade));
app->draw(manaSprite);
if (player->getActiveSpell().spell != SpellNone)
{
sf::Sprite spellSprite;
spellSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_SPELLS));
spellSprite.setPosition(568, 624);
int frame = player->getActiveSpell().spell;
spellSprite.setTextureRect(sf::IntRect(frame * 78, 78, 78, 78));
app->draw(spellSprite);
int spellFade = player->getPercentSpellDelay() * 78;
spellSprite.setPosition(568, 624 + 78 - spellFade);
spellSprite.setTextureRect(sf::IntRect(frame * 78, 78 - spellFade, 78, spellFade));
app->draw(spellSprite);
if (player->canCastSpell())
{
float fade = (cos(8.0f * getAbsolutTime()) + 1.0f) * 0.5f;
spellSprite .setColor(sf::Color(255, 255, 255, 255 * fade));
app->draw(spellSprite, sf::BlendAdd);
}
}
// drawing the key on the interface
if (player->isEquiped(EQUIP_BOSS_KEY)) app->draw(uiSprites.keySprite);
// drawing the level items
if (player->isEquiped(EQUIP_FLOOR_MAP))
{
sf::Sprite mapSprite;
mapSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
mapSprite.setTextureRect(sf::IntRect(ITEM_WIDTH * 3, ITEM_HEIGHT * 4, ITEM_WIDTH, ITEM_HEIGHT));
mapSprite.setPosition(737, 648);
app->draw(mapSprite);
}
if (player->isEquiped(EQUIP_ALCOHOL))
{
sf::Sprite alcSprite;
alcSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
alcSprite.setTextureRect(sf::IntRect(ITEM_WIDTH * 4, ITEM_HEIGHT * 4, ITEM_WIDTH, ITEM_HEIGHT));
alcSprite.setPosition(737, 681);
app->draw(alcSprite);
}
if (player->isEquiped(EQUIP_LUCK))
{
sf::Sprite alcSprite;
alcSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
alcSprite.setTextureRect(sf::IntRect(ITEM_WIDTH * 5, ITEM_HEIGHT * 4, ITEM_WIDTH, ITEM_HEIGHT));
alcSprite.setPosition(704, 681);
app->draw(alcSprite);
}
if (player->isEquiped(EQUIP_FAIRY_POWDER))
{
sf::Sprite alcSprite;
alcSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
alcSprite.setTextureRect(sf::IntRect(ITEM_WIDTH * 6, ITEM_HEIGHT * 4, ITEM_WIDTH, ITEM_HEIGHT));
alcSprite.setPosition(671, 681);
app->draw(alcSprite);
}
// drawing the consumable
if (!player->isEquiped(EQUIP_BAG))
{
sf::RectangleShape shadow(sf::Vector2f(70, 33));
shadow.setFillColor(sf::Color(0, 0, 0, 128));
shadow.setPosition(sf::Vector2f(386, 614));
app->draw(shadow);
}
for (int i = 0; i < MAX_SLOT_CONSUMABLES; i++)
{
int item = player->getConsumable(i);
if (item > -1)
{
sf::Sprite consSprite;
consSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS));
consSprite.setPosition(315 + 37 * i, 615);
if (item < FirstEquipItem && item >= ItemPotion01 + NUMBER_UNIDENTIFIED)
{
int bottle = (int)(getPotion((enumItemType)item));
consSprite.setTextureRect(sf::IntRect(ITEM_WIDTH * (bottle % 10), ITEM_HEIGHT * (bottle / 10), ITEM_WIDTH, ITEM_HEIGHT));
app->draw(consSprite);
}
consSprite.setTextureRect(sf::IntRect(ITEM_WIDTH * (item % 10), ITEM_HEIGHT * (item / 10), ITEM_WIDTH, ITEM_HEIGHT));
app->draw(consSprite);
}
}
// drawing message icon
if (!messagesQueue.empty())
{
int fade = 255;
if (messagesQueue.front().timer < 0.5f)
{
fade = (2 * messagesQueue.front().timer) * 255;
}
else if (messagesQueue.front().timerMax - messagesQueue.front().timer < 0.5f)
{
fade = (2 * (messagesQueue.front().timerMax - messagesQueue.front().timer)) * 255;
}
uiSprites.iconSprite.setColor(sf::Color(255, 255, 255, fade));
uiSprites.iconSprite.setTextureRect(sf::IntRect((messagesQueue.front().icon % 10) * 72, (messagesQueue.front().icon / 10) * 96, 72, 96));
app->draw(uiSprites.iconSprite);
}
// drawing the divinity
if (player->getDivinity().divinity >= 0)
{
sf::Sprite divSprite;
divSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_DIVINITY));
divSprite.setPosition(100, 614);
divSprite.setTextureRect(sf::IntRect(player->getDivinity().divinity * 48, 0, 48, 85));
app->draw(divSprite);
float fade = player->getLightCone();
if (fade > 0.0f && player->getPlayerStatus() != PlayerEntity::playerStatusPraying)
{
divSprite.setTextureRect(sf::IntRect(player->getDivinity().divinity * 48, 85, 48, 85));
divSprite.setColor(sf::Color(255, 255, 255, 255 * fade));
app->draw(divSprite);
}
rectangle.setOutlineThickness(0);
if (player->getDivinity().interventions + 1 < player->getDivinity().level)
{
int fade = 50 + 50 * cosf(game().getAbsolutTime() * 8);
rectangle.setFillColor(sf::Color(100 + fade, 100 + fade, 200 + fade / 2, 255));
}
else
rectangle.setFillColor(sf::Color(100, 100, 200, 255));
rectangle.setPosition(sf::Vector2f(101, 689));
rectangle.setSize(sf::Vector2f(46 * player->getDivinity().percentsToNextLevels, 9));
app->draw(rectangle);
std::ostringstream oss;
if (player->getDivinity().level == MAX_DIVINITY_LEVEL + 1) oss << "MAX";
else oss << "lvl " << player->getDivinity().level;
write(oss.str(), 11, 122, 702, ALIGN_CENTER, sf::Color::White, app, 0, 0, 0);
}
// render the shots
renderHudShots(app);
if (gameState == gameStatePlayingPause)
{
// background
rectangle.setFillColor(sf::Color(0, 0, 0, 200));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH, MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
// minimap
int mapx = 350;
int mapy = 30;
// background
app->draw(rectangle);
app->draw(uiSprites.mapBgSprite);
// map
float miniX = miniMapEntity->getX();
float miniY = miniMapEntity->getY();
miniMapEntity->setX(mapx);
miniMapEntity->setY(mapy);
miniMapEntity->computeVertices();
miniMapEntity->render(app);
miniMapEntity->setX(miniX);
miniMapEntity->setY(miniY);
miniMapEntity->computeVertices();
float x = 200;
float y = 480;
// items
write(tools::getLabel("inventory"), 16, x, y, ALIGN_LEFT, sf::Color::White, app, 0, 0, 0);
int n = 0;
for (auto i: sortedEquipement)
{
if (i != EQUIP_BOSS_KEY && player->isEquiped(i))
{
sf::Sprite itemSprite;
itemSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
itemSprite.setPosition(x + n * 32, y + 20);
itemSprite.setTextureRect(sf::IntRect((i % 10) * 32, (i / 10) * 32, 32, 32));
app->draw(itemSprite);
n++;
}
}
renderInGameMenu();
}
if (player->isDead())
{
float deathAge = player->getEndAge();
if (deathAge > DEATH_CERTIFICATE_DELAY)
{
rectangle.setFillColor(sf::Color(0, 0, 0, 180));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
renderDeathScreen(80, 110);
if (scoreSaveFile.compare("") == 0)
{
write(tools::getLabel("certificate_capture"), 16, 80, 430, ALIGN_LEFT, sf::Color::White, app, 0, 0, 0);
}
else
{
std::stringstream ss;
ss << tools::getLabel("certificate_saved") << " " << scoreSaveFile;
write(ss.str(), 16, 80, 430, ALIGN_LEFT, sf::Color::White, app, 0, 0, 0);
}
}
else if (deathAge > DEATH_CERTIFICATE_DELAY - 1.0f)
{
rectangle.setFillColor(sf::Color(0, 0, 0, 180 * (deathAge - 2.5f)));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
renderDeathScreen(80 + (DEATH_CERTIFICATE_DELAY - deathAge) * 1000, 110);
}
}
else if (player->getPlayerStatus() == PlayerEntity::playerStatusVictorious)
{
if (player->getEndAge() > 2.0f)
{
rectangle.setFillColor(sf::Color(0, 0, 0, 180));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
renderDeathScreen(80, 110);
if (scoreSaveFile.compare("") == 0)
{
write(tools::getLabel("certificate_capture"), 16, 80, 430, ALIGN_LEFT, sf::Color::White, app, 0, 0, 0);
}
else
{
std::stringstream ss;
ss << tools::getLabel("certificate_saved") << " " << scoreSaveFile;
write(ss.str(), 16, 80, 430, ALIGN_LEFT, sf::Color::White, app, 0, 0, 0);
}
}
else
{
rectangle.setFillColor(sf::Color(0, 0, 0, 90 * (player->getEndAge())));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
renderDeathScreen(80 + (2.0f - player->getEndAge() ) * 1000, 110);
}
}
else if (player->getPlayerStatus() != PlayerEntity::playerStatusVictorious && currentMap->getRoomType() == roomTypeExit && level >= LAST_LEVEL)
{
float x0 = (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2;
write(tools::getLabel("congratulations_1"), 25, x0, 220, ALIGN_CENTER, sf::Color::White, app, 2, 2, 0);
write(tools::getLabel("congratulations_2"), 23, x0, 250, ALIGN_CENTER, sf::Color::White, app, 2, 2, 0);
write(tools::getLabel("congratulations_3"), 23, x0, 280, ALIGN_CENTER, sf::Color::White, app, 2, 2, 0);
registerAchievement(AchievementWin);
if (endingTimer < 0.0f)
endingTimer = ENDING_TIMER;
}
}
// show game time
if (showGameTime)
{
int minutes = (int)gameTime / 60;
int secondes = (int)gameTime % 60;
std::stringstream ss;
if (minutes < 10) ss << "0";
ss << minutes;
ss << ":";
if (secondes < 10) ss << "0";
ss << secondes;
write(ss.str(), 14, 4, 4, ALIGN_LEFT, sf::Color::Green, app, 0, 0, 0);
}
// achievements ?
if (!achievementsQueue.empty()) // && (currentMap->isCleared() || achievementsQueue.front().hasStarted) )
{
if (!achievementsQueue.front().hasStarted)
{
SoundManager::getInstance().playSound(SOUND_ACHIEVEMENT);
achievementsQueue.front().hasStarted = true;
achievementState[achievementsQueue.front().type] = AchievementDone;
saveGameData();
proceedEvent(EventAchievement);
// text
float x0 = MAP_WIDTH * 0.5f * TILE_WIDTH;
float y0 = MAP_HEIGHT * 0.5f * TILE_HEIGHT + 40.0f;
TextEntity* text = new TextEntity(tools::getLabel("achievement_complete"), 30, x0, y0);
text->setAlignment(ALIGN_CENTER);
text->setLifetime(2.5f);
text->setWeight(-36.0f);
text->setZ(1200);
text->setColor(TextEntity::COLOR_FADING_WHITE);
}
int xPos = 560;
int yPos = 4;
int opening = 384;
float achievAge = ACHIEVEMENT_DELAY_MAX - achievementsQueue.front().timer;
sf::Sprite spriteScroll;
if (achievAge < 1.0f)
opening = 32;
else if (achievAge < 2.0f)
opening = 32 + (achievAge - 1.0f) * (384 - 32);
else if (achievAge > ACHIEVEMENT_DELAY_MAX - 1.0f)
opening = 32 + (ACHIEVEMENT_DELAY_MAX - achievAge) * (384 - 32);
if (achievAge < 0.5f)
spriteScroll.setColor(sf::Color(255, 255, 255, 500 * achievAge));
else if (achievAge > ACHIEVEMENT_DELAY_MAX - 0.5f)
spriteScroll.setColor(sf::Color(255, 255, 255, 500 * (ACHIEVEMENT_DELAY_MAX - achievAge)));
spriteScroll.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_ACHIEV));
spriteScroll.setTextureRect(sf::IntRect(128 + 384 - opening, 0, opening, 64));
spriteScroll.setPosition(xPos + 384 - opening, yPos);
app->draw(spriteScroll);
if ((achievAge > 1.0f && achievAge < 2.0f) || achievAge > ACHIEVEMENT_DELAY_MAX - 1.0f)
spriteScroll.setTextureRect(sf::IntRect(32 * ((int)(achievAge * 8) % 4), 0, 32, 64));
else
spriteScroll.setTextureRect(sf::IntRect(0, 0, 32, 64));
spriteScroll.setPosition(xPos + 394 - opening - 16, yPos);
app->draw(spriteScroll);
if (achievAge > 2.0f && achievAge < ACHIEVEMENT_DELAY_MAX - 1.0f)
{
sf::Sprite icon;
icon.setTexture(*ImageManager::getInstance().getImage(IMAGE_ACHIEVEMENTS));
icon.setTextureRect(sf::IntRect( ((achievementsQueue.front().type + 1) % 10) * 64,
((achievementsQueue.front().type + 1) / 10) * 64, 64, 64));
icon.setPosition(xPos + 308, yPos + 9);
icon.setScale(0.7f, 0.7f);
app->draw(icon);
icon.setColor(sf::Color(255, 255, 255, 50 + 50 * cosf(getAbsolutTime() * 4)));
app->draw(icon, sf::BlendAdd);
game().write(achievementsQueue.front().message, 13, xPos + 34, yPos + 10, ALIGN_LEFT, sf::Color::Black, app, 0, 0, 0);
if (achievements[achievementsQueue.front().type].unlockType == UnlockItem)
{
game().write(tools::getLabel(items[achievements[achievementsQueue.front().type].unlock].name),
13, xPos + 70, yPos + 34, ALIGN_LEFT, sf::Color::Black, app, 0, 0, 0);
}
else if (achievements[achievementsQueue.front().type].unlockType == UnlockFunctionality)
{
game().write(tools::getLabel(functionalityLabel[achievements[achievementsQueue.front().type].unlock]),
13, xPos + 70, yPos + 34, ALIGN_LEFT, sf::Color::Black, app, 0, 0, 0);
}
}
//if (achievAge < 1.0f)
{
int i = achievementsQueue.front().counter;
if (i < 64)
{
for (int j = 0; j < 2; j++)
{
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40, yPos - i + 64);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40, yPos - i + 64 + 1);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40, yPos - i + 64 + 2);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40, yPos - i + 64 + 3);
}
}
else if (i < 40 + 64)
{
for (int j = 0; j < 2; j++)
{
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40 + i - 64, yPos);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40 + i - 63, yPos);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40 + i - 62, yPos);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40 + i - 61, yPos);
}
}
else if (i < 40 + 64 + 64)
{
for (int j = 0; j < 2; j++)
{
generateUiParticle(xPos + 394 + 16 + 4 - opening, yPos + i - 40 - 64);
generateUiParticle(xPos + 394 + 16 + 4 - opening, yPos + i - 40 - 64 + 1);
generateUiParticle(xPos + 394 + 16 + 4 - opening, yPos + i - 40 - 64 + 2);
generateUiParticle(xPos + 394 + 16 + 4 - opening, yPos + i - 40 - 64 + 3);
}
}
else if (i < 40 + 64 + 40 + 64)
{
for (int j = 0; j < 2; j++)
{
generateUiParticle(xPos + 394 + 16 + 4 - 32 - i + 144, yPos + 64);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - i + 144 + 1, yPos + 64);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - i + 144 + 2, yPos + 64);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - i + 144 + 3, yPos + 64);
}
}
achievementsQueue.front().counter += 4;
}
}
// show player effects
if (isPlayerAlive)
{
float x0 = 20, y0 = 540, yStep = -20;
for (int i = 0; i < NB_SPECIAL_STATES; i++)
{
if ( (player->isSpecialStateActive((enumSpecialState)i) && player->getSpecialState((enumSpecialState)i).timer > 0.35f)
|| player->getSpecialState((enumSpecialState)i).waitUnclear)
{
std::stringstream oss;
oss << tools::getLabel(specialStateToLabel[i]) << " : ";
if (player->getSpecialState((enumSpecialState)i).waitUnclear)
{
oss << "waiting";
int n = (int)(getAbsolutTime() * 3) % 3;
if (n == 0) oss << ".";
else if (n == 1) oss << "..";
else oss << "...";
}
else
oss << (int)(player->getSpecialState((enumSpecialState)i).timer);
write(oss.str(), 12, x0, y0, ALIGN_LEFT, specialStateToColor[i], app, 0, 0, 0);
y0 += yStep;
}
}
}
}
void WitchBlastGame::renderMessages()
{
// message queue
if (!messagesQueue.empty())
{
int dy = 30;
if (messagesQueue.front().timer < 0.5f)
{
dy *= (2 * messagesQueue.front().timer);
}
else if (messagesQueue.front().timerMax - messagesQueue.front().timer < 0.5f)
{
dy *= (2 * (messagesQueue.front().timerMax - messagesQueue.front().timer));
}
uiSprites.msgBoxSprite.setPosition(0, 590 - dy);
app->draw(uiSprites.msgBoxSprite);
std::stringstream ss;
ss << messagesQueue.front().message[0];
ss << ": ";
ss << messagesQueue.front().message[1];
ss << std::endl;
ss << messagesQueue.front().message[2];
write(ss.str(), 16, 10, 592 - dy, ALIGN_LEFT, sf::Color::White, app, 0, 0, 0);
}
}
void WitchBlastGame::saveDeathScreen()
{
std::stringstream ss;
ss << "rip_";
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
ss << (now->tm_year + 1900);
if (now->tm_mon < 9) ss << "0";
ss << (now->tm_mon + 1);
if (now->tm_mday < 9) ss << "0";
ss << now->tm_mday;
if (now->tm_hour <= 9) ss << "0";
ss << (now->tm_hour);
if (now->tm_min <= 9) ss << "0";
ss << (now->tm_min);
if (now->tm_sec <= 9) ss << "0";
ss << (now->tm_sec);
ss << ".png";
int width = 810, height = 300, border = 4;
int x = 80, y = 110;
sf::Image screenShot(app->capture());
sf::Image savedImage;
savedImage.create(width + border * 2, height + border * 2);
savedImage.copy(screenShot,0 , 0, sf::IntRect( x - border, y - border, width + border * 2, height + border * 2));
savedImage.saveToFile(ss.str());
}
void WitchBlastGame::saveScreen()
{
std::stringstream ss;
ss << "screenshot_";
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
ss << (now->tm_year + 1900);
if (now->tm_mon < 9) ss << "0";
ss << (now->tm_mon + 1);
if (now->tm_mday < 9) ss << "0";
ss << now->tm_mday;
if (now->tm_hour <= 9) ss << "0";
ss << (now->tm_hour);
if (now->tm_min <= 9) ss << "0";
ss << (now->tm_min);
if (now->tm_sec <= 9) ss << "0";
ss << (now->tm_sec);
ss << ".png";
sf::Image screenShot(app->capture());
screenShot.saveToFile(ss.str());
}
void WitchBlastGame::renderDeathScreen(float x, float y)
{
int xRect = 810;
sf::Sprite rectangle;
rectangle.setTexture(*ImageManager::getInstance().getImage(IMAGE_DEATH_CERTIFICATE));
rectangle.setPosition(x - 4, y - 4);
app->draw(rectangle);
std::stringstream ss;
if (player->isDead())
ss << parameters.playerName << " - " << tools::getLabel("dc_certificate");
else
ss << parameters.playerName << " - " << tools::getLabel("dc_victory");
write(ss.str(), 18, x + xRect / 2, y + 5, ALIGN_CENTER, sf::Color::Black, app, 0, 0, 0);
ss.str(std::string());
ss.clear();
int minutes = (int)gameTime / 60;
if (minutes < 1) minutes = 1;
if (player->isDead())
{
ss << tools::getLabel("dc_killed_by") << " " << sourceToString(player->getLastHurtingSource(), player->getLastHurtingEnemy()) << "." << std::endl;
ss << tools::getLabel("dc_died_level") << " " << level << " " << tools::getLabel("dc_after") << " " << minutes << " " << tools::getLabel("dc_minutes") << "." << std::endl;
}
else
{
ss << tools::getLabel("dc_after_victory") << " " << minutes << " " << tools::getLabel("dc_minutes") << "." << std::endl;
}
ss << tools::getLabel("dc_killed_monsters") << ": " << bodyCount << std::endl;
ss << tools::getLabel("dc_gold") << ": " << player->getGold() << std::endl;
ss << tools::getLabel("dc_challenges") << ": " << challengeLevel - 1 << std::endl;
write(ss.str(), 16, x + 112, y + 50, ALIGN_LEFT, sf::Color::Black, app, 0, 0, 0);
// player
renderPlayer(x + 40, y + 48, player->getEquipment(), player->getShotType(), 1, 0);
// items
write(tools::getLabel("inventory"), 16, x + 14, y + 165, ALIGN_LEFT, sf::Color::Black, app, 0, 0, 0);
int n = 0;
for (auto i: sortedEquipement)
{
if (i != EQUIP_BOSS_KEY && player->isEquiped(i))
{
sf::Sprite itemSprite;
itemSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
itemSprite.setPosition(x + 14 + n * 32, y + 183);
itemSprite.setTextureRect(sf::IntRect((i % 10) * 32, (i / 10) * 32, 32, 32));
app->draw(itemSprite);
n++;
}
}
ss.str("");
ss.clear();
ss << "Score: " << score;
write(ss.str(), 24, x + xRect / 2, y + 240, ALIGN_CENTER, sf::Color::Black, app, 0, 0, 0);
}
bool compareScores(WitchBlastGame::StructScore s1, WitchBlastGame::StructScore s2)
{
return s1.score > s2.score;
}
void WitchBlastGame::calculateScore()
{
score = 0;
bodyCount = 0;
for (int enemyType = EnemyTypeBat; enemyType < EnemyTypeRockFalling; enemyType++)
{
bodyCount += killedEnemies[enemyType];
score += killedEnemies[enemyType] * getMonsterScore((enemyTypeEnum)enemyType);
}
score += getChallengeScore(challengeLevel);
score += getSecretScore(secretsFound);
score += getGoldScore(player->getGold());
for (int i = 0; i < NUMBER_EQUIP_ITEMS; i++)
{
if (player->isEquiped(i)) score += getItemScore((item_equip_enum)i);
lastScore.equip[i] = player->isEquiped(i);
}
// perfects
for (int i = 1; i < level; i++)
{
if (player->getLostHp(i) == 0) score += getPerfectScore();
}
// time
if (!player->isDead())
{
score += getTimeScore((int)(gameTime / 60.0f));
lastScore.level = -1;
}
else
lastScore.level = level;
// to save
lastScore.name = parameters.playerName;
lastScore.score = score;
lastScore.shotType = player->getShotType();
lastScore.divinity = player->getDivinity().divinity;
lastScore.killedBy = player->getLastHurtingEnemy();
lastScore.time = (int)gameTime;
scores.push_back(lastScore);
std::sort (scores.begin(), scores.end(), compareScores);
saveHiScores();
// Online
#ifdef ONLINE_MODE
if (!gameFromSaveFile)
{
sendScoreToServer();
}
else
{
receiveScoreFromServer();
}
#endif // ONLINE_MODE
}
void WitchBlastGame::switchToMenu()
{
gameState = gameStateMenu;
buildMenu(false);
if (!config.configFileExists())
{
menuState = MenuStateFirst;
menuFirst.index = 0;
menuKeyIndex = 0;
}
}
void WitchBlastGame::updateMenu()
{
SoundManager::getInstance().playSound(SOUND_NIGHT, false);
menuStuct* menu = NULL;
bool noMenu = false;
if (menuState == MenuStateMain)
menu = &menuMain;
else if (menuState == MenuStateConfig)
menu = &menuConfig;
else if (menuState == MenuStateFirst)
menu = &menuFirst;
else
noMenu = true;
bool escape = false;
EntityManager::getInstance().animate(deltaTime);
for (int i = 0; i < 2; i++)
{
introSprites[i]->setX(introSprites[i]->getX() - deltaTime * 35);
if (introSprites[i]->getX() < - SCREEN_WIDTH / 2) introSprites[i]->setX(introSprites[i]->getX() + 2 * SCREEN_WIDTH);
}
// Process events
sf::Event event;
while (app->pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
{
saveGameData();
app->close();
}
if (event.type == sf::Event::Resized)
{
enableAA(true);
sf::View view = app->getDefaultView();
view = getLetterboxView( view, event.size.width, event.size.height );
app->setView(view);
}
if (event.type == sf::Event::TextEntered)
{
if (menuState == MenuStateChangeName)
{
if (event.text.unicode < 128)
{
char c = static_cast<char>(event.text.unicode);
if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_')
parameters.playerName += static_cast<char>(event.text.unicode);
}
}
}
if (event.type == sf::Event::KeyPressed && menuState == MenuStateKeys)
{
bool alreadyUsed = false;
if (event.key.code == sf::Keyboard::Escape) alreadyUsed = true;
for (unsigned int i = 0; i < menuKeyIndex; i++)
if (input[i] == event.key.code) alreadyUsed = true;
// TODO more tests
if (!alreadyUsed)
{
input[menuKeyIndex] = event.key.code;
menuKeyIndex++;
if (menuKeyIndex == NumberKeys)
{
menuState = MenuStateConfig;
saveConfigurationToFile();
}
}
}
else if (menuState == MenuStateJoystick)
{
bool alreadyUsed = false;
int nbButtons = sf::Joystick::getButtonCount(0);
bool found = false;
JoystickInputStruct jInput;
// Escape = out
if (event.key.code == sf::Keyboard::Escape)
{
menuState = MenuStateConfig;
saveConfigurationToFile();
return;
}
// button pressed ?
for (int i = 0; !found && i < nbButtons; i++)
{
if (sf::Joystick::isButtonPressed(0, i))
{
jInput.isButton = true;
jInput.value = i;
jInput.axis = sf::Joystick::X;
found = true;
}
}
if (!found)
{
// axis ?
for (int i = sf::Joystick::X; i <= sf::Joystick::PovY; i++)
{
if (sf::Joystick::hasAxis(0, (sf::Joystick::Axis)i))
{
if (sf::Joystick::getAxisPosition(0, (sf::Joystick::Axis)i) < -50)
{
jInput.isButton = false;
jInput.value = -1;
jInput.axis = (sf::Joystick::Axis)i;
found = true;
}
else if (sf::Joystick::getAxisPosition(0, (sf::Joystick::Axis)i) > 50)
{
jInput.isButton = false;
jInput.value = 1;
jInput.axis = (sf::Joystick::Axis)i;
found = true;
}
}
}
}
if (found)
{
// already exist ?
for (unsigned int i = 0; i < menuKeyIndex; i++)
{
if (jInput.isButton && joystickInput[i].isButton
&& joystickInput[i].value == jInput.value)
alreadyUsed = true;
if (!jInput.isButton && !joystickInput[i].isButton
&& joystickInput[i].axis == jInput.axis
&& joystickInput[i].value == jInput.value)
alreadyUsed = true;
}
if (!alreadyUsed)
{
joystickInput[menuKeyIndex] = jInput;
menuKeyIndex++;
if (menuKeyIndex == NumberKeys)
{
menuState = MenuStateConfig;
saveConfigurationToFile();
}
}
}
}
else
{
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::F1)
{
saveScreen();
}
if (menuState == MenuStateChangeName)
{
if (event.key.code == sf::Keyboard::Escape || event.key.code == sf::Keyboard::Return)
{
saveConfigurationToFile();
menuState = MenuStateMain;
}
else if (event.key.code == sf::Keyboard::BackSpace)
{
if (parameters.playerName.size() > 0)
parameters.playerName.erase(parameters.playerName.size() - 1);
}
}
else if (event.key.code == sf::Keyboard::Escape)
{
escape = true;
}
}
}
}
// END EVENT PROCESSING
if (menuState == MenuStateAchievements)
{
if (isPressing(KeyRight, true))
{
if (menuAchIndex % 8 < 7) menuAchIndex++;
}
else if (isPressing(KeyLeft, true))
{
if (menuAchIndex % 8 > 0) menuAchIndex--;
}
else if (isPressing(KeyDown, true))
{
if (menuAchIndex / 8 < ACHIEV_LINES) menuAchIndex += 8;
}
else if (isPressing(KeyUp, true))
{
if (menuAchIndex / 8 > 0) menuAchIndex -= 8;
}
else if (isPressing(KeyFireDown, true))
{
if (menuAchIndex / 8 >= ACHIEV_LINES) menuState = MenuStateMain;
}
if (escape) menuState = MenuStateMain;
}
else if (menuState == MenuStateCredits)
{
if (escape || isPressing(KeyFireDown, true)) menuState = MenuStateMain;
}
else if (menuState == MenuStateHiScores)
{
if (escape || isPressing(KeyFireDown, true))
{
menuScoreIndex++;
if (menuScoreIndex > 2)
{
menuState = MenuStateMain;
if (lastScore.level > 0)
{
lastScore.level = 0;
lastScore.score = 0;
playMusic(MusicIntro);
}
}
}
}
if (!noMenu)
{
if (escape)
{
saveGameData();
app->close();
}
else if (isPressing(KeyDown, true))
{
menu->index++;
if (menu->index == menu->items.size()) menu->index = 0;
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
else if (isPressing(KeyUp, true))
{
if (menu->index == 0) menu->index = menu->items.size() - 1;
else menu->index--;
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
else if (isPressing(KeyRight, true))
{
if (menu->items[menu->index].id == MenuLanguage)
{
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
parameters.language++;
if (parameters.language >= NB_LANGUAGES) parameters.language = 0;
if (menuState == MenuStateConfig) saveConfigurationToFile();
tools::setLanguage(languageString[parameters.language]);
buildMenu(true);
}
else if (menu->items[menu->index].id == MenuVolumeSound)
{
parameters.soundVolume = (parameters.soundVolume / 10) * 10 + 10;
if (parameters.soundVolume > 100) parameters.soundVolume = 100;
saveConfigurationToFile();
SoundManager::getInstance().setVolume(parameters.soundVolume);
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
else if (menu->items[menu->index].id == MenuVolumeMusic)
{
parameters.musicVolume = (parameters.musicVolume / 10) * 10 + 10;
if (parameters.musicVolume > 100) parameters.musicVolume = 100;
saveConfigurationToFile();
updateMusicVolume();
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
}
else if (isPressing(KeyLeft, true))
{
if (menu->items[menu->index].id == MenuLanguage)
{
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
parameters.language--;
if (parameters.language < 0) parameters.language = NB_LANGUAGES - 1;
if (menuState == MenuStateConfig) saveConfigurationToFile();
tools::setLanguage(languageString[parameters.language]);
buildMenu(true);
}
else if (menu->items[menu->index].id == MenuVolumeSound)
{
parameters.soundVolume = (parameters.soundVolume / 10) * 10 - 10;
if (parameters.soundVolume < 0) parameters.soundVolume = 0;
saveConfigurationToFile();
SoundManager::getInstance().setVolume(parameters.soundVolume);
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
else if (menu->items[menu->index].id == MenuVolumeMusic)
{
parameters.musicVolume = (parameters.musicVolume / 10) * 10 - 10;
if (parameters.musicVolume < 0) parameters.musicVolume = 0;
saveConfigurationToFile();
updateMusicVolume();
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
}
else if (isPressing(KeyFireDown, true))
{
switch (menu->items[menu->index].id)
{
case MenuStartNew:
startNewGame(false, 1);
remove(SAVE_FILE.c_str());
break;
case MenuStartOld:
startNewGame(true, 1);
break;
case MenuKeys:
menuState = MenuStateKeys;
menuKeyIndex = 0;
break;
case MenuJoystick:
if (sf::Joystick::isConnected(0))
{
buildMenu(true);
menuState = MenuStateJoystick;
menuKeyIndex = 0;
}
else
buildMenu(true);
break;
case MenuCredits:
menuState = MenuStateCredits;
break;
case MenuHiScores:
menuState = MenuStateHiScores;
#ifdef ONLINE_MODE
menuScoreIndex = 0;
#else
menuScoreIndex = 2;
#endif
receiveScoreFromServer();
//loadHiScoresOnline(false);
//loadHiScoresOnline(true);
break;
case MenuAchievements:
menuState = MenuStateAchievements;
menuAchIndex = 0;
break;
case MenuPlayerName:
menuState = MenuStateChangeName;
break;
case MenuConfig:
menuState = MenuStateConfig;
break;
case MenuTutoReset:
for (int i = 0; i < NB_MESSAGES; i++) gameMessagesToSkip[i] = false;
SoundManager::getInstance().playSound(SOUND_SPELL_FREEZE);
saveGameData();
break;
case MenuConfigBack:
menuState = MenuStateMain;
break;
case MenuLanguage:
if (menuState == MenuStateFirst)
{
registerLanguage();
if (parameters.playerName.compare("") == 0 )
{
menuMain.index = 0;
menuState = MenuStateChangeName;
}
else
menuState = MenuStateMain;
}
break;
case MenuExit:
saveGameData();
app->close();
break;
case MenuVolumeSound:
case MenuVolumeMusic:
break;
case MenuContinue:
case MenuSaveAndQuit:
std::cout << "[ERROR] Bad Menu ID\n";
break;
}
}
}
}
void WitchBlastGame::renderMenu()
{
if (menuState == MenuStateCredits)
{
renderCredits();
return;
}
else if (menuState == MenuStateHiScores)
{
//renderHiScores();
if (menuScoreIndex == 0)
renderScores(scoresOnline, "Best Players (ON-LINE)");
else if (menuScoreIndex == 1)
renderScores(scoresOnlineDay, "Best TODAY Scores (ON-LINE)");
else
renderScores(scores, "Best Scores (local)");
return;
}
else if (menuState == MenuStateAchievements)
{
renderAchievements();
return;
}
app->draw(introScreenSprite);
if (titleSprite.getPosition().y > 160) titleSprite.move(0, -8);
else if (titleSprite.getPosition().y < 160) titleSprite.setPosition(SCREEN_WIDTH / 2 - 15, 160);
app->draw(titleSprite);
EntityManager::getInstance().render(app);
menuStuct* menu = nullptr;
if (menuState == MenuStateMain || menuState == MenuStateChangeName)
menu = &menuMain;
else if (menuState == MenuStateConfig)
menu = &menuConfig;
else if (menuState == MenuStateFirst)
menu = &menuFirst;
int xAlign = 290;
int yTop = 320;
int yStep = 40;
if (menuState == MenuStateKeys)
{
// menu keys
if (config.configFileExists())
write(tools::getLabel("key_configuration"), 18, xAlign, 295, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
else
write(tools::getLabel("key_configuration_desc"), 18, xAlign, 295, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
for (unsigned int i = 0; i < NumberKeys; i++)
{
sf::Color itemColor;
if (menuKeyIndex == i) itemColor = sf::Color(255, 255, 255, 255);
else itemColor = sf::Color(180, 180, 180, 255);
std::ostringstream oss;
oss << tools::getLabel(inputKeyString[i]) << ": ";
if (menuKeyIndex == i) oss << tools::getLabel("key_configuration_insert");
else if (menuKeyIndex > i) oss << keyToString(input[i]);
write(oss.str(), 16, xAlign, 330 + i * 25, ALIGN_LEFT, itemColor, app, 1, 1, 0);
}
}
else if (menuState == MenuStateJoystick)
{
// menu keys
if (config.configFileExists())
write(tools::getLabel("joystick_configuration"), 18, xAlign, 295, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
else
write(tools::getLabel("joystick_configuration_desc"), 18, xAlign, 295, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
for (unsigned int i = 0; i < NumberKeys; i++)
{
sf::Color itemColor;
if (menuKeyIndex == i) itemColor = sf::Color(255, 255, 255, 255);
else itemColor = sf::Color(180, 180, 180, 255);
std::ostringstream oss;
oss << tools::getLabel(inputKeyString[i]) << ": ";
if (menuKeyIndex == i) oss << tools::getLabel("joystick_configuration_insert");
else if (menuKeyIndex > i) oss << "OK";
write(oss.str(), 16, xAlign, 330 + i * 25, ALIGN_LEFT, itemColor, app, 1, 1, 0);
}
}
else
{
// menu
for (unsigned int i = 0; i < menu->items.size(); i++)
{
sf::Color itemColor;
if (menu->index == i)
{
itemColor = sf::Color(255, 255, 255, 255);
sf::Sprite fairySprite;
fairySprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
fairySprite.setTextureRect(sf::IntRect( 48 * ((int)(20 *getAbsolutTime()) % 2), fairySpriteOffsetY, 48, 48));
fairySprite.setPosition(xAlign - 60, yTop - 10 + i * yStep + 5 * cos( 6 * getAbsolutTime()));
app->draw(fairySprite);
}
else itemColor = sf::Color(120, 120, 120, 255);
std::string label = menu->items[i].label;
if (menu->items[i].id == MenuLanguage)
{
std::ostringstream oss;
oss << label << " : " << tools::getLabel(languageString[parameters.language]);
label = oss.str();
}
else if (menu->items[i].id == MenuPlayerName)
{
std::ostringstream oss;
oss << label << " : " << parameters.playerName;
if (menuState == MenuStateChangeName && (int)(getAbsolutTime() * 3) % 2 == 0) oss << "_";
label = oss.str();
}
else if (menu->items[i].id == MenuVolumeSound)
{
std::ostringstream oss;
oss << label << " : ";
if (parameters.soundVolume == 0) oss << "OFF";
else oss << parameters.soundVolume;
label = oss.str();
}
else if (menu->items[i].id == MenuVolumeMusic)
{
std::ostringstream oss;
oss << label << " : ";
if (parameters.musicVolume == 0) oss << "OFF";
else oss << parameters.musicVolume;
label = oss.str();
}
write(label, 21, xAlign, yTop + i * yStep, ALIGN_LEFT, itemColor, app, 1, 1, 0);
}
write(menu->items[menu->index].description, 18, xAlign,
yTop + menu->items.size() * yStep + 8, ALIGN_LEFT, sf::Color(60, 80, 220), app, 0, 0, 0);
// Keys
if (menuState == MenuStateFirst)
{
// displaying the standard key configuration
int xKeys = 270;
int yKeys = 380;
sf::Sprite keysSprite;
if (parameters.language == 1) // french
keysSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_KEYS_AZER));
else
keysSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_KEYS_QWER));
keysSprite.setPosition(xKeys, yKeys);
app->draw(keysSprite);
// legend
write(tools::getLabel("keys_move"), 16, xKeys + 190, yKeys + 10, ALIGN_LEFT, sf::Color::White, app, 1, 1, 0);
write(tools::getLabel("keys_time"), 16, xKeys + 295, yKeys + 14, ALIGN_LEFT, sf::Color::White, app, 1, 1, 0);
write(tools::getLabel("keys_fire"), 16, xKeys + 360, yKeys + 54, ALIGN_LEFT, sf::Color::White, app, 1, 1, 0);
write(tools::getLabel("key_spell"), 16, xKeys + 148, yKeys + 184, ALIGN_CENTER, sf::Color::White, app, 1, 1, 0);
// TODO key interact
std::ostringstream oss;
oss << tools::getLabel("keys_select_1") << std::endl << tools::getLabel("keys_select_2");
write(oss.str(), 16, xKeys + 4, yKeys + 100, ALIGN_LEFT, sf::Color::White, app, 1, 1, 0);
}
}
std::ostringstream oss;
oss << APP_NAME << " v" << APP_VERSION << " - 2014-2015 - " << " Seby (code), Pierre \"dejam0rt\" Baron (2D art)";
write(oss.str(), 17, 5, 680, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
}
void WitchBlastGame::renderAchievements()
{
app->draw(introScreenSprite);
if (titleSprite.getPosition().y > 160) titleSprite.move(0, -8);
else if (titleSprite.getPosition().y < 160) titleSprite.setPosition(SCREEN_WIDTH / 2 - 15, 180);
app->draw(titleSprite);
// achievements
write(tools::getLabel("menu_achievements"), 30, 485, 280, ALIGN_CENTER, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
int achWidth = 64, achHeight = 64, x0 = 180, y0 = 380, xStep = 16, yStep = 16, nbProLine = 8;
if (menuAchIndex / 8 < ACHIEV_LINES)
{
sf::RectangleShape rectangle(sf::Vector2f(achWidth, achHeight));
rectangle.setPosition(x0 + (menuAchIndex % nbProLine) * (achWidth + xStep), y0 + (menuAchIndex / nbProLine) * (achHeight + yStep));
rectangle.setOutlineThickness(3);
rectangle.setOutlineColor(sf::Color(50, 255, 50));
app->draw(rectangle);
}
sf::Sprite sprite;
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ACHIEVEMENTS));
for (int k : sortedAchievements)
{
int i = sortedAchievements[k];
sprite.setPosition(x0 + (k % nbProLine) * (achWidth + xStep), y0 + (k / nbProLine) * (achHeight + yStep));
if (achievementState[i] == AchievementDone)
{
sprite.setTextureRect(sf::IntRect( ((i + 1) % 10) * achWidth, ((i + 1) / 10) * achHeight, achWidth, achHeight));
}
else
{
sprite.setTextureRect(sf::IntRect(0, 0, achWidth, achHeight));
}
app->draw(sprite);
}
if (menuAchIndex / 8 >= ACHIEV_LINES)
{
write(tools::getLabel("config_back"), 17, 485, 620, ALIGN_CENTER, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
}
else
{
write(tools::getLabel("config_back"), 17, 485, 620, ALIGN_CENTER, sf::Color(180, 180, 180, 255), app, 1, 1, 0);
sf::Color fontColor = sf::Color::White;
std::stringstream oss;
int achIndex = sortedAchievements[menuAchIndex];
if (!achievementState[achIndex] == AchievementDone && (
achIndex == AchievementGiantSlime
|| achIndex == AchievementCyclops
|| achIndex == AchievementRatKing
|| achIndex == AchievementGiantSpider
|| achIndex == AchievementFrancky
|| achIndex == AchievementVampire)
)
oss << "???";
else
oss << tools::getLabel(achievements[achIndex].label);
oss << ": ";
if (achievementState[achIndex] == AchievementDone)
{
oss << tools::getLabel(achievements[achIndex].label + "_desc");
if (achievements[achIndex].unlockType == UnlockItem && achievements[achIndex].unlock > -1)
oss << "\nUNLOCK: " << tools::getLabel(items[achievements[achIndex].unlock].name);
else if (achievements[achIndex].unlockType == UnlockFunctionality && achievements[achIndex].unlock > -1)
oss << "\nUNLOCK: " << tools::getLabel(functionalityLabel[achievements[achIndex].unlock]);
}
else
{
if (isFunctionalityLocked(FunctionalityAllAchievements))
oss << "???";
else
oss << tools::getLabel(achievements[achIndex].label + "_desc");
fontColor = sf::Color(150, 150, 150);
}
write(oss.str(), 19, 100, 650, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
}
}
void WitchBlastGame::renderCredits()
{
app->draw(introScreenSprite);
if (titleSprite.getPosition().y > 160) titleSprite.move(0, -8);
else if (titleSprite.getPosition().y < 160) titleSprite.setPosition(SCREEN_WIDTH / 2 - 15, 180);
app->draw(titleSprite);
// credits
write(tools::getLabel("credits"), 30, 485, 275, ALIGN_CENTER, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
int yCursorInit = 365;
int yStep = 30;
int xLeft = 30;
int xRight = 470;
int xMarging = 20;
int yCursor = yCursorInit;
write("Code", 22, xLeft, yCursor, ALIGN_LEFT, sf::Color(210, 210, 255, 255), app, 0, 0, 0);
yCursor += yStep;
int i = 0;
while (creditsCode[i] != "END")
{
write(creditsCode[i], 19, xLeft + xMarging, yCursor, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0, 0, 0);
yCursor += yStep;
i++;
}
yCursor += yStep;
write("2D Art", 22, xLeft, yCursor, ALIGN_LEFT, sf::Color(210, 210, 255, 255), app, 0, 0, 0);
yCursor += yStep;
i = 0;
while (credits2D[i] != "END")
{
write(credits2D[i], 19, xLeft + xMarging, yCursor, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0, 0, 0);
yCursor += yStep;
i++;
}
yCursor += yStep;
write("Sound", 22, xLeft, yCursor, ALIGN_LEFT, sf::Color(210, 210, 255, 255), app, 0, 0, 0);
yCursor += yStep;
i = 0;
while (creditsSound[i] != "END")
{
write(creditsSound[i], 19, xLeft + xMarging, yCursor, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0, 0, 0);
yCursor += yStep;
i++;
}
yCursor += yStep;
////// RIGHT
yCursor = yCursorInit + yStep;
write("Music", 22, xRight, yCursor, ALIGN_LEFT, sf::Color(210, 210, 255, 255), app, 0, 0, 0);
yCursor += yStep;
i = 0;
while (creditsMusic[i] != "END")
{
write(creditsMusic[i], 19, xRight + xMarging, yCursor, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0, 0, 0);
yCursor += yStep;
i++;
}
yCursor += yStep;
write("Translation", 22, xRight, yCursor, ALIGN_LEFT, sf::Color(210, 210, 255, 255), app, 0, 0, 0);
yCursor += yStep;
i = 0;
while (creditsTranslate[i] != "END")
{
write(creditsTranslate[i], 19, xRight + xMarging, yCursor, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0, 0, 0);
yCursor += yStep;
i++;
}
yCursor += yStep;
}
void WitchBlastGame::renderScores(std::vector <StructScore> scoresToRender, std::string title)
{
sf::Sprite bgSprite;
bgSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_HALL_OF_FAME));
app->draw(bgSprite);
// hi-scores-title
write(title, 30, 485, 60, ALIGN_CENTER, sf::Color(0, 0, 0, 255), app, 0, 0, 0);
int xEquip = 540;
//int yEquip = 360;
int xPlayerLeft = 60;
int xPlayerRight = 850;
int xName = 260;
int xTime = 420;
int xLevel = 480;
int xScore = 180;
int y0 = 130;
int yStep = 50;
for (unsigned int i = 0; i < scoresToRender.size() && i < SCORES_MAX; i++)
{
sf::Color color = sf::Color( 15, 15, 15);
- if (scoresToRender[i].score == lastScore.score && scoresToRender[i].level == lastScore.level && scoresToRender[i].name == lastScore.name)
+ if (scoresToRender[i].score == lastScore.score
+ && scoresToRender[i].level == lastScore.level
+ && scoresToRender[i].name == lastScore.name
+ && scoresToRender[i].time == lastScore.time)
{
int fade = 1 + cosf(getAbsolutTime() * 8) * 63;
color = sf::Color(255 - fade, 128, 255 - fade);
}
+ else if (scoresToRender[i].name == parameters.playerName)
+ {
+ int fade = 70 + sinf(getAbsolutTime() * 4) * 70;
+ color = sf::Color(fade * 1.5, fade, 0);
+ }
// equipment
int n = 0;
for (auto ii: scoreEquipement)
if (ii != EQUIP_BOSS_KEY && scoresToRender[i].equip[ii]) n++;
int dx = 30;
if (n > 14) dx = 16;
else if (n > 8) dx = 20;
n = 0;
for (auto ii: scoreEquipement)
{
if (ii != EQUIP_BOSS_KEY && scoresToRender[i].equip[ii])
{
sf::Sprite itemSprite;
itemSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
itemSprite.setPosition(xEquip + n * dx, y0 + 22 + yStep * i);
itemSprite.setTextureRect(sf::IntRect((ii % 10) * 32, (ii / 10) * 32, 32, 32));
app->draw(itemSprite);
n++;
}
}
if (i < 2)
renderPlayer((i % 2 == 0) ? xPlayerLeft : xPlayerRight, y0 - 14 + yStep * i, scoresToRender[i].equip, scoresToRender[i].shotType, 2, 7);
else if (i >= 8)
renderPlayer((i % 2 == 0) ? xPlayerLeft : xPlayerRight, y0 - 14 + yStep * i, scoresToRender[i].equip, scoresToRender[i].shotType, 0, 8);
else
renderPlayer((i % 2 == 0) ? xPlayerLeft : xPlayerRight, y0 - 14 + yStep * i, scoresToRender[i].equip, scoresToRender[i].shotType, 1, 0);
write(scoresToRender[i].name, 16, xName, y0 + 28 + yStep * i, ALIGN_LEFT, color, app, 0, 0, 0);
std::stringstream levelSS;
if (scoresToRender[i].level == -1) levelSS << "Win";
else levelSS << "lvl " << scoresToRender[i].level;
write(levelSS.str(), 16, xLevel, y0 + 28 + yStep * i, ALIGN_LEFT, color, app, 0, 0, 0);
write(intToString(scoresToRender[i].score), 17, xScore, y0 + 28 + yStep * i, ALIGN_LEFT, color, app, 0, 0, 0);
std::stringstream timeSS;
if (scoresToRender[i].time < 100)
{
timeSS << scoresToRender[i].time << " s";
}
else
{
int minutes = scoresToRender[i].time / 60;
if (minutes < 1) minutes = 1;
timeSS << minutes << " m";
}
write(timeSS.str(), 16, xTime, y0 + 28 + yStep * i, ALIGN_LEFT, color, app, 0, 0, 0);
write(intToString(scoresToRender[i].score), 17, xScore, y0 + 28 + yStep * i, ALIGN_LEFT, color, app, 0, 0, 0);
}
// retrieving from DB ?
if ( (menuScoreIndex == 0 && scoreState == ScoreLoading)
|| (menuScoreIndex == 1 && ((scoreState == ScoreLoading) || (scoreState == ScoreLoadingDay))))
{
std::stringstream oss;
oss << "Loading";
int n = (int)(getAbsolutTime() * 3) % 3;
if (n == 0) oss << ".";
else if (n == 1) oss << "..";
else oss << "...";
write(oss.str(), 15, 20, 20, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
}
}
void WitchBlastGame::renderHiScores()
{
sf::Sprite bgSprite;
bgSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_INTRO));
app->draw(bgSprite);
// hi-scores-title
write(tools::getLabel("hi_scores"), 30, 485, 20, ALIGN_CENTER, sf::Color(255, 255, 255, 255), app, 1, 1, 0);
int x0 = 25;
int x1 = 70;
int x2 = 125;
int x3 = 430;
int y0 = 130;
int yStep = 100;
int xRight = SCREEN_WIDTH / 2;
sf::RectangleShape line(sf::Vector2f(2, 600));
line.setPosition(SCREEN_WIDTH / 2, 80);
app->draw(line);
for (unsigned int i = 0; i < scores.size() && i < SCORES_MAX; i++)
{
int index = i < SCORES_MAX / 2 ? i : i - SCORES_MAX / 2;
sf::Color color = sf::Color( 220, 220, 220);
if (scores[i].score == lastScore.score && scores[i].level == lastScore.level && scores[i].name == lastScore.name)
{
int fade = 1 + cosf(getAbsolutTime() * 8) * 63;
color = sf::Color(255, 128 + fade, 255);
}
renderPlayer(x1 + (i / 5) * xRight, y0 + yStep * index, scores[i].equip, scores[i].shotType, 1, 0);
write(intToString(i + 1), 24, x0 + (i / 5) * xRight, y0 + 30 + yStep * index, ALIGN_CENTER, color, app, 1, 1, 0);
std::stringstream ss;
ss << scores[i].name << " (" << scores[i].level << ")";
write(ss.str(), 17, x2 + (i / 5) * xRight, y0 + 30 + yStep * index, ALIGN_LEFT, color, app, 1, 1, 0);
write(intToString(scores[i].score), 17, x3 + (i / 5) * xRight, y0 + 30 + yStep * index, ALIGN_RIGHT, color, app, 1, 1, 0);
}
}
void WitchBlastGame::renderInGameMenu()
{
menuStuct* menu = &menuInGame;
int xAlign = 290;
int yAlign = 200;
{
// menu
for (unsigned int i = 0; i < menu->items.size(); i++)
{
sf::Color itemColor;
if (menu->index == i)
{
itemColor = sf::Color(255, 255, 255, 255);
sf::Sprite fairySprite;
fairySprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
fairySprite.setTextureRect(sf::IntRect( 48 * ((int)(8 *getAbsolutTime()) % 2), fairySpriteOffsetY, 48, 48));
fairySprite.setPosition(xAlign - 60, yAlign + i * 90 + 5 * cos( 6 * getAbsolutTime()));
app->draw(fairySprite);
}
else itemColor = sf::Color(120, 120, 120, 255);
std::string label = menu->items[i].label;
write(label, 23, xAlign, yAlign + 10 + i * 90, ALIGN_LEFT, itemColor, app, 1, 1, 0);
write(menu->items[i].description, 15, xAlign, yAlign + i * 90 + 50, ALIGN_LEFT, itemColor, app, 0, 0, 0);
}
}
}
void WitchBlastGame::startGame()
{
lastTime = getAbsolutTime();
prepareIntro();
// Start game loop
while (app->isOpen())
{
deltaTime = getAbsolutTime() - lastTime;
if (deltaTime < 0.008f)
{
float sleepTime = 1.0f / 60.0f - deltaTime;
sf::sleep(sf::seconds(sleepTime));
deltaTime = getAbsolutTime() - lastTime;
}
lastTime = getAbsolutTime();
if (deltaTime > 0.05f) deltaTime = 0.05f;
if (app->hasFocus())
{
updateActionKeys();
switch (gameState)
{
case gameStateInit:
case gameStateKeyConfig:
case gameStateJoystickConfig:
case gameStateMenu:
updateMenu();
break;
case gameStateIntro:
updateIntro();
break;
case gameStatePlaying:
case gameStatePlayingPause:
case gameStatePlayingDisplayBoss:
updateRunningGame();
break;
}
}
else
{
// Process events
sf::Event event;
while (app->pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
{
saveGameData();
app->close();
}
if (event.type == sf::Event::LostFocus)
{
if (parameters.pauseOnFocusLost && gameState == gameStatePlaying && !player->isDead())
gameState = gameStatePlayingPause;
}
}
}
onRender();
}
quitGame();
}
void WitchBlastGame::createFloor()
{
// TODO : extracts from createNewGame
}
void WitchBlastGame::closeDoors()
{
if (!currentMap->isCleared())
{
int i;
for(i = 0; i < MAP_WIDTH; i++)
{
if (currentMap->isDoor(i, 0)) currentMap->closeDoor(i, 0);
if (currentMap->isDoor(i, MAP_HEIGHT - 1)) currentMap->closeDoor(i, MAP_HEIGHT - 1);
}
for(i = 0; i < MAP_HEIGHT; i++)
{
if (currentMap->isDoor(0, i)) currentMap->closeDoor(0, i);
if (currentMap->isDoor(MAP_WIDTH - 1, i)) currentMap->closeDoor(MAP_WIDTH - 1, i);
}
roomClosed = true;
}
}
void WitchBlastGame::openDoors()
{
int i;
for(i = 0; i < MAP_WIDTH; i++)
{
if (currentMap->isDoor(i, 0)) currentMap->openDoor(i, 0);
if (currentMap->isDoor(i, MAP_HEIGHT - 1)) currentMap->openDoor(i, MAP_HEIGHT - 1);
}
for(i = 0; i < MAP_HEIGHT; i++)
{
if (currentMap->isDoor(0, i)) currentMap->openDoor(0, i);
if (currentMap->isDoor(MAP_WIDTH - 1, i)) currentMap->openDoor(MAP_WIDTH - 1, i);
}
roomClosed = false;
SoundManager::getInstance().playSound(SOUND_DOOR_OPENING);
if (currentMap->hasNeighbourUp() == 2 && !bossRoomOpened)
currentMap->closeDoor(MAP_WIDTH/2, 0);
else if (currentMap->hasNeighbourUp() == 1)
doorEntity[0]->openDoor();
if (currentMap->hasNeighbourLeft() == 2 && !bossRoomOpened)
currentMap->closeDoor(0, MAP_HEIGHT / 2);
else if (currentMap->hasNeighbourLeft() == 1)
doorEntity[1]->openDoor();
if (currentMap->hasNeighbourDown() == 2 && !bossRoomOpened)
currentMap->closeDoor(MAP_WIDTH / 2, MAP_HEIGHT - 1);
else if (currentMap->hasNeighbourDown() == 1)
doorEntity[2]->openDoor();
if (currentMap->hasNeighbourRight() == 2 && !bossRoomOpened)
currentMap->closeDoor(MAP_WIDTH - 1, MAP_HEIGHT / 2);
else if (currentMap->hasNeighbourRight() == 1)
doorEntity[3]->openDoor();
}
EnemyEntity* WitchBlastGame::getBoss()
{
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() == ENTITY_ENEMY_BOSS) return static_cast<EnemyEntity*> (e);
}
return NULL;
}
int WitchBlastGame::getEnemyCount()
{
int n=0;
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() >= ENTITY_ENEMY && e->getType() <= ENTITY_ENEMY_MAX_COUNT) n++;
}
return n;
}
int WitchBlastGame::getUndeadCount()
{
int n=0;
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() >= ENTITY_ENEMY && e->getType() <= ENTITY_ENEMY_MAX_COUNT)
{
EnemyEntity* enemy = dynamic_cast<EnemyEntity*>(e);
if (enemy->canCollide() && (enemy->getEnemyType() == EnemyTypeZombie || enemy->getEnemyType() == EnemyTypeZombieDark
|| enemy->getEnemyType() == EnemyTypeGhost || enemy->getEnemyType() == EnemyTypeVampire || enemy->getEnemyType() == EnemyTypeBat_invocated) )
n++;
}
}
return n;
}
void WitchBlastGame::killArtefactDescription()
{
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() == ENTITY_ARTIFACT_DESCRIPTION)
{
e->setDying(true);
}
}
}
void WitchBlastGame::animateEffects()
{
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() == ENTITY_EFFECT)
e->animate(deltaTime);
}
}
void WitchBlastGame::destroyUndead(int damage)
{
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() >= ENTITY_ENEMY && e->getType() <= ENTITY_ENEMY_MAX_COUNT)
{
EnemyEntity* enemy = dynamic_cast<EnemyEntity*>(e);
if (enemy->canCollide() && (enemy->getEnemyType() == EnemyTypeZombie || enemy->getEnemyType() == EnemyTypeZombieDark
|| enemy->getEnemyType() == EnemyTypeGhost || enemy->getEnemyType() == EnemyTypeVampire || enemy->getEnemyType() == EnemyTypeBat_invocated) )
{
enemy->hurt(BaseCreatureEntity::getHurtParams(damage, ShotTypeStandard, 0, false, SourceTypeMelee, EnemyTypeNone, false));
SpriteEntity* spriteCone = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_LIGHT_CONE),
enemy->getX(), enemy->getZ() - 290);
spriteCone->setZ(1000.0f);
spriteCone->setFading(true);
spriteCone->setAge(-1.2f);
spriteCone->setLifetime(2.4f);
spriteCone->setRenderAdd();
}
}
}
}
int WitchBlastGame::getItemsCount()
{
int n=0;
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() == ENTITY_ITEM) n++;
}
return n;
}
Vector2D WitchBlastGame::getNearestEnemy(float x, float y)
{
Vector2D target(-100.0f, -100.0f);
float distanceMin = -1.0f;
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() >= ENTITY_ENEMY && e->getType() <= ENTITY_ENEMY_MAX_COUNT)
{
// enemy
EnemyEntity* enemy = dynamic_cast<EnemyEntity*>(e);
if (enemy->canCollide())
{
float d2 = (x - enemy->getX()) * (x - enemy->getX()) + (y - enemy->getY()) * (y - enemy->getY());
if (target.x < -1.0f || d2 < distanceMin)
{
distanceMin = d2;
target.x = enemy->getX();
target.y = enemy->getY();
}
}
}
}
return target;
}
void WitchBlastGame::setDoorVisible(int n)
{
if (n >= 0 && n < 4)
doorEntity[n]->setVisible(true);
}
void WitchBlastGame::checkDoor(int doorId, roomTypeEnum roomCurrent, roomTypeEnum roomNeighbour, bool isNeighbourKnown)
{
if (roomNeighbour == roomTypeNULL)
{
doorEntity[doorId]->setVisible(false);
return;
}
doorEntity[doorId]->setVisible(isNeighbourKnown);
doorEntity[doorId]->setDoorType(currentMap->getDoorType(doorId));
if (roomNeighbour == roomTypeBoss && !bossRoomOpened)
{
doorEntity[doorId]->setOpen(false);
switch (doorId)
{
case 0:
currentMap->closeDoor(MAP_WIDTH/2, 0);
break;
case 1:
currentMap->closeDoor(0, MAP_HEIGHT / 2);
break;
case 2:
currentMap->closeDoor(MAP_WIDTH/2, MAP_HEIGHT - 1);
break;
case 3:
currentMap->closeDoor(MAP_WIDTH - 1, MAP_HEIGHT / 2);
break;
}
}
else
doorEntity[doorId]->setOpen(true);
}
void WitchBlastGame::refreshMap()
{
// clean the sprites from old map
EntityManager::getInstance().partialClean(10);
// if new map, it has to be randomized
bool generateMap = !(currentFloor->getMap(floorX, floorY)->isVisited());
currentMap = currentFloor->getAndVisitMap(floorX, floorY);
// load the map
dungeonEntity->refreshMap();
player->setMap(currentMap, TILE_WIDTH, TILE_HEIGHT, 0, 0);
refreshMinimap();
if(generateMap)
this->generateMap();
else
{
if (currentMap->getRoomType() == roomTypeMerchant)
{
new PnjEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2 - 1) * TILE_HEIGHT,
0);
}
}
// check doors
checkDoor(0, currentMap->getRoomType(), currentMap->getNeighbourUp(), currentMap->hasKnownNeighbour(North, true));
checkDoor(1, currentMap->getRoomType(), currentMap->getNeighbourLeft(), currentMap->hasKnownNeighbour(West, true));
checkDoor(2, currentMap->getRoomType(), currentMap->getNeighbourDown(), currentMap->hasKnownNeighbour(South, true));
checkDoor(3, currentMap->getRoomType(), currentMap->getNeighbourRight(), currentMap->hasKnownNeighbour(East, true));
// pet slime
if (player->isEquiped(EQUIP_PET_SLIME) && currentMap->getRoomType() != roomTypeTemple) new SlimePetEntity();
// barrels
checkDestroyableObjects();
}
void WitchBlastGame::refreshMinimap()
{
for (int j=0; j < FLOOR_HEIGHT; j++)
for (int i=0; i < FLOOR_WIDTH; i++)
{
int roomType = currentFloor->getRoom(i, j);
if (roomType > roomTypeNULL && currentFloor->getMap(i, j)->isVisited()&& currentFloor->getMap(i, j)->isKnown())
{
if (roomType == roomTypeStarting
|| roomType == roomTypeChallenge
|| roomType == roomTypeBonus
|| roomType == roomTypeKey
|| roomType == roomTypeBoss
|| roomType == roomTypeStandard
|| roomType == roomTypeSecret)
{
if ( currentFloor->getMap(i, j)->containsHealth())
miniMap->setTile(i, j, 5);
else
miniMap->setTile(i, j, roomTypeStandard);
}
else
{
if (roomType == roomTypeMerchant)
miniMap->setTile(i, j, 3);
else if (roomType == roomTypeTemple)
miniMap->setTile(i, j, 7);
else if (roomType == roomTypeSecret)
miniMap->setTile(i, j, 8);
else
miniMap->setTile(i, j, currentFloor->getRoom(i, j));
}
}
else if (roomType > roomTypeNULL && currentFloor->getMap(i, j)->isKnown())
{
switch (roomType)
{
case roomTypeBoss:
miniMap->setTile(i, j, 12);
proceedEvent(EventFindBossDoor);
break;
case roomTypeChallenge:
miniMap->setTile(i, j, 15);
proceedEvent(EventFindBossDoor);
break;
case roomTypeMerchant:
miniMap->setTile(i, j,
game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP) ? 13 : 11 );
break;
case roomTypeKey:
miniMap->setTile(i, j,
game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP) ? 14 : 11 );
break;
case roomTypeExit:
miniMap->setTile(i, j,
game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP) ? 16 : 11 );
break;
case roomTypeTemple:
miniMap->setTile(i, j,
game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP) ? 17 : 11 );
break;
case roomTypeBonus:
miniMap->setTile(i, j,
game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP) ? 2 : 11 );
break;
case roomTypeSecret:
miniMap->setTile(i, j, 18 );
break;
case roomTypeStandard:
case roomTypeStarting:
miniMap->setTile(i, j, 11);
break;
case roomTypeNULL:
miniMap->setTile(i, j, 0);
break;
}
}
else
miniMap->setTile(i, j, 0);
}
miniMap->setTile(floorX, floorY, 10);
int xMap = 760 + (6 - floorX) * 19;
if (xMap < 710) xMap = 710;
else if (xMap > 795) xMap = 795;
int yMap = 620 + (3 - floorY) * 15;
if (yMap < 596) yMap = 596;
else if (yMap > 640) yMap = 640;
miniMapEntity->setX(xMap);
miniMapEntity->setY(yMap);
}
void WitchBlastGame::checkEntering()
{
if (!currentMap->isCleared())
{
player->setEntering();
SoundManager::getInstance().playSound(SOUND_DOOR_CLOSING);
for (int i=0; i<4; i++)
doorEntity[i]->closeDoor();
}
}
void WitchBlastGame::saveMapItems()
{
currentMap->cleanMapObjects();
// blood
std::vector <displayEntityStruct> blood = dungeonEntity->getBlood();
for (auto particle: blood)
currentMap->addSprite(ENTITY_BLOOD, particle.frame, particle.x, particle.y, particle.scale);
// corpses
std::vector <displayEntityStruct> corpses = dungeonEntity->getCorpses();
for (auto particle: corpses)
currentMap->addSprite(ENTITY_CORPSE, particle.frame, particle.x, particle.y, particle.scale);
EntityManager::EntityList* entityList = EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity* e = *it;
it++;
ItemEntity* itemEntity = dynamic_cast<ItemEntity*>(e);
ChestEntity* chestEntity = dynamic_cast<ChestEntity*>(e);
if (itemEntity != NULL && !itemEntity->getDying())
{
currentMap->addItem(itemEntity->getItemType(), itemEntity->getX(), itemEntity->getY(), itemEntity->getMerchandise());
} // endif
else if (chestEntity != NULL && !chestEntity->getDying())
{
currentMap->addChest(chestEntity->getChestType(), chestEntity->getOpened(), chestEntity->getX(), chestEntity->getY());
} // endif
} // end for
}
void WitchBlastGame::moveToOtherMap(int direction)
{
// stairs to next level
if (direction == 8 && currentMap->getRoomType() == roomTypeExit)
{
if (player->getPlayerStatus() != PlayerEntity::playerStatusGoingNext)
{
player->setLeavingLevel();
xGame[xGameTypeFade].active = true;
xGame[xGameTypeFade].param = X_GAME_FADE_OUT;
xGame[xGameTypeFade].timer = FADE_OUT_DELAY;
player->setVelocity(Vector2D(0.0f, - INITIAL_PLAYER_SPEED / 2));
}
}
// go to another room
else
{
saveMapItems();
switch (direction)
{
case (4):
floorX--;
player->moveTo((MAP_WIDTH * TILE_WIDTH), player->getY());
player->move(4);
break;
case (6):
floorX++;
player->moveTo(0, player->getY());
player->move(6);
break;
case (8):
floorY--;
player->moveTo(player->getX(), MAP_HEIGHT * TILE_HEIGHT);
player->move(8);
break;
case (2):
floorY++;
player->moveTo(player->getX(), 0);
break;
}
refreshMap();
checkEntering();
currentMap->restoreMapObjects();
saveInFight.x = player->getX();
saveInFight.y = player->getY();
saveInFight.direction = direction;
saveMapItems();
if (!currentMap->isCleared())
{
saveGame();
}
}
}
void WitchBlastGame::onRender()
{
// clear the view
app->clear(sf::Color::Black);
switch (gameState)
{
case gameStateInit:
case gameStateKeyConfig:
case gameStateJoystickConfig:
case gameStateMenu:
renderMenu();
break;
case gameStatePlaying:
case gameStatePlayingPause:
case gameStatePlayingDisplayBoss:
renderRunningGame();
break;
case gameStateIntro:
renderIntro();
break;
}
app->display();
}
void WitchBlastGame::renderHudShots(sf::RenderTarget* app)
{
int xHud = 277;
int yHud = 655;
int index = 0;
for (int i = 0; i < SPECIAL_SHOT_SLOTS; i++)
{
if (i == 0 || player->getShotType(i) != ShotTypeStandard)
{
int type_shot = player->getShotType(i);
uiSprites.shotsSprite.setPosition(xHud + 55 * index, yHud);
if (index == player->getShotIndex())
{
uiSprites.shotsSprite.setTextureRect(sf::IntRect(0, 0, 48, 48));
app->draw(uiSprites.shotsSprite);
}
uiSprites.shotsSprite.setTextureRect(sf::IntRect(48 * ( 1 + type_shot), 0, 48, 48));
app->draw(uiSprites.shotsSprite);
// level
if (i > 0)
{
std::ostringstream oss;
oss << "lvl " << player->getShotLevel(i) + 1;
write(oss.str(), 10, xHud + 55 * index + 10, yHud + 48, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0, 0, 0);
}
index++;
}
}
}
void WitchBlastGame::generateBlood(float x, float y, BaseCreatureEntity::enumBloodColor bloodColor)
{
dungeonEntity->generateBlood(x, y, bloodColor);
// double blood if the "Blood Snake" object is equipped
if (player->isEquiped(EQUIP_BLOOD_SNAKE)) dungeonEntity->generateBlood(x, y, bloodColor);
}
void WitchBlastGame::addCorpse(float x, float y, int frame)
{
dungeonEntity->addCorpse(x, y, frame);
}
void WitchBlastGame::showArtefactDescription(enumItemType itemType)
{
killArtefactDescription();
new ArtefactDescriptionEntity(itemType);
}
void WitchBlastGame::generateMap()
{
saveInFight.monsters.clear();
if (currentMap->getRoomType() == roomTypeStandard)
generateStandardMap();
else if (currentMap->getRoomType() == roomTypeBonus)
{
currentMap->setCleared(true);
Vector2D v = currentMap->generateBonusRoom();
int bonusType = getRandomEquipItem(false, false);
if (items[FirstEquipItem + bonusType].familiar > FamiliarNone)
{
new ChestEntity(v.x, v.y, ChestFairy + items[FirstEquipItem + bonusType].familiar, false);
}
else
{
new ItemEntity( (enumItemType)(FirstEquipItem + bonusType), v.x ,v.y);
}
}
else if (currentMap->getRoomType() == roomTypeKey)
{
currentMap->generateKeyRoom();
initMonsterArray();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
monsterArray[x0][y0] = true;
if (level == 1)
{
findPlaceMonsters(EnemyTypeRat, 2);
findPlaceMonsters(EnemyTypeBat, 2);
}
else if (level < 6)
{
findPlaceMonsters(EnemyTypeRat, 5);
findPlaceMonsters(EnemyTypeBat, 5);
for (int i = 2; i < level; i++)
{
if (rand()%2 == 0)findPlaceMonsters(EnemyTypeImpBlue, 1);
else findPlaceMonsters(EnemyTypeImpRed, 1);
}
}
else
{
findPlaceMonsters(EnemyTypeZombie, 5);
findPlaceMonsters(EnemyTypeBat, 5);
for (int i = 5; i < level; i++)
{
if (rand()%2 == 0)findPlaceMonsters(EnemyTypeImpBlue, 1);
else findPlaceMonsters(EnemyTypeImpRed, 1);
}
}
}
else if (currentMap->getRoomType() == roomTypeMerchant)
{
currentMap->generateMerchantRoom();
ItemEntity* item1 = new ItemEntity(
ItemHealth,
(MAP_WIDTH / 2 - 1) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + 5);
item1->setMerchandise(true);
ItemEntity* item3 = new ItemEntity(
ItemHealthSmall,
(MAP_WIDTH / 2 + 1) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + 5);
item3->setMerchandise(true);
int bonusType = getRandomEquipItem(true, true);
ItemEntity* item2 = new ItemEntity(
(enumItemType)(FirstEquipItem + bonusType),
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + 5);
item2->setMerchandise(true);
// level item ?
if (rand() % 3 == 0)
{
int r = rand() % 4;
int item4Type = -1;
switch (r)
{
case 0:
if (!game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP)) item4Type = ItemFloorMap;
break;
case 1:
if (!game().getPlayer()->isEquiped(EQUIP_ALCOHOL)) item4Type = ItemAlcohol;
break;
case 2:
if (!game().getPlayer()->isEquiped(EQUIP_LUCK)) item4Type = ItemLuck;
break;
default:
if (!game().getPlayer()->isEquiped(EQUIP_FAIRY_POWDER) && player->getFairieNumber() > 0) item4Type = ItemFairyPowder;
break;
}
if (item4Type > -1)
{
ItemEntity* item4 = new ItemEntity(
(enumItemType)(item4Type),
(MAP_WIDTH / 2 + 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + 5);
item4->setMerchandise(true);
}
}
// consumable item
if (rand() % 3 == 0) // potion
{
ItemEntity* item5 = new ItemEntity(
(enumItemType)(ItemPotion01 + rand() % NUMBER_UNIDENTIFIED),
(MAP_WIDTH / 2 - 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + 5);
item5->setMerchandise(true);
}
else // scroll
{
ItemEntity* item5 = new ItemEntity(
(enumItemType)ItemScrollRevelation,
(MAP_WIDTH / 2 - 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + 5);
item5->setMerchandise(true);
}
new PnjEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2 - 1) * TILE_HEIGHT,
0);
currentMap->setCleared(true);
proceedEvent(EventFindShop);
}
else if (currentMap->getRoomType() == roomTypeChallenge)
{
currentMap->generateRoomWithoutHoles(0);
if (challengeLevel == 1)
{
addMonster(EnemyTypeBubble,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
addMonster(challengeLevel >= 3 ? EnemyTypeBubbleIce : EnemyTypeBubble,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 - 80,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
addMonster(challengeLevel >= 4 ? EnemyTypeBubbleGreater : EnemyTypeBubble,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 + 80,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
playMusic(MusicChallenge);
}
else if (currentMap->getRoomType() == roomTypeBoss)
{
currentMap->generateRoomWithoutHoles(0);
if (level == 1)
{
findPlaceMonsters(EnemyTypeRat, 2);
addMonster(EnemyTypeButcher,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoButcher);
}
else if (level == 2)
{
addMonster(EnemyTypeSlimeBoss,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoGiantSlime);
}
else if (level == 3)
{
addMonster(EnemyTypeCyclops,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoCyclops);
}
else if (level == 4)
{
addMonster(EnemyTypeRatKing,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoWererat);
}
else if (level == 5)
{
addMonster(EnemyTypeSpiderGiant,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoGiantSpiderBefore);
}
else if (level == 6)
{
addMonster(EnemyTypeFrancky,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoFranky);
}
else if (level == 7)
{
addMonster(EnemyTypeVampire,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoVampire);
}
else if (level == 8)
{
// TODO
FranckyEntity* b2 = new FranckyEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b2->setLabelDy(-530);
KingRatEntity* b3 = new KingRatEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 + 100,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b3->setLabelDy(-20);
new CyclopsEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 + 120,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else // level > 6
{
GiantSpiderEntity* b1 = new GiantSpiderEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 - 100,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b1->setLabelDy(10);
GiantSlimeEntity* b2 = new GiantSlimeEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b2->setLabelDy(-510);
KingRatEntity* b3 = new KingRatEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 + 100,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b3->setLabelDy(-20);
CyclopsEntity* b4 = new CyclopsEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b4->setLabelDy(-540);
findPlaceMonsters(EnemyTypeCauldron, 2);
findPlaceMonsters(EnemyTypeImpBlue, 4);
}
playMusic(MusicBoss);
// boss screen
if (parameters.displayBossPortrait)
{
gameState = gameStatePlayingDisplayBoss;
bossDisplayTimer = 0.0f;
bossDisplayState = 0;
dungeonEntity->animate(0.0f);
}
}
else if (currentMap->getRoomType() == roomTypeStarting)
{
currentMap->generateRoomWithoutHoles(0);
currentMap->setCleared(true);
}
else if (currentMap->getRoomType() == roomTypeExit)
{
currentMap->generateExitRoom();
currentMap->setCleared(true);
new ChestEntity((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f),
ChestExit, false);
}
else if (currentMap->getRoomType() == roomTypeTemple)
{
currentMap->generateTempleRoom();
currentMap->setCleared(true);
proceedEvent(EventFindTemple);
}
else if (currentMap->getRoomType() == roomTypeSecret)
{
currentMap->generateSecretRoom();
if (rand() % 7 > 0)
{
new ChestEntity((TILE_WIDTH * MAP_WIDTH * 0.5f + TILE_WIDTH),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f),
ChestBasic, false);
new ChestEntity((TILE_WIDTH * MAP_WIDTH * 0.5f - TILE_WIDTH),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f),
ChestBasic, false);
}
else
{
int bonusType = getRandomEquipItem(false, false);
if (items[FirstEquipItem + bonusType].familiar > FamiliarNone)
{
new ChestEntity(TILE_WIDTH * MAP_WIDTH * 0.5f,
TILE_HEIGHT * MAP_HEIGHT * 0.5f,
ChestFairy + items[FirstEquipItem + bonusType].familiar, false);
}
else
{
new ItemEntity( (enumItemType)(FirstEquipItem + bonusType),
TILE_WIDTH * MAP_WIDTH * 0.5f,
TILE_HEIGHT * MAP_HEIGHT * 0.5f);
}
}
currentMap->setCleared(true);
// secret found text
TextEntity* text = new TextEntity(tools::getLabel("secret_found"),
25,
MAP_WIDTH * 0.5f * TILE_WIDTH,
MAP_HEIGHT * 0.5f * TILE_HEIGHT + 10.0f);
text->setAlignment(ALIGN_CENTER);
text->setLifetime(2.5f);
text->setWeight(-36.0f);
text->setZ(1200);
text->setColor(TextEntity::COLOR_FADING_WHITE);
SoundManager::getInstance().playSound(SOUND_SECRET);
secretsFound++;
}
else // "normal" room
currentMap->randomize(currentMap->getRoomType());
}
void WitchBlastGame::write(std::string str, int size, float x, float y, int align, sf::Color color, sf::RenderTarget* app, int xShadow = 0, int yShadow = 0, int maxWidth = 0)
{
myText.setString(str);
myText.setString(sf::String::fromUtf8(str.begin(), str.end()));
myText.setCharacterSize(size);
if (maxWidth > 0)
{
while (myText.getLocalBounds().width > maxWidth && size > 5)
{
size--;
myText.setCharacterSize(size);
}
}
float xFont = x;
if (align == ALIGN_CENTER)
xFont = x - myText.getLocalBounds().width / 2;
else if (align == ALIGN_RIGHT)
xFont = x - myText.getLocalBounds().width;
if (xShadow != 0 && yShadow != 0)
{
myText.setPosition(xFont + xShadow, y + yShadow);
myText.setColor(sf::Color(0, 0, 0, 255));
app->draw(myText);
}
myText.setPosition(xFont, y);
myText.setColor(color);
app->draw(myText);
}
void WitchBlastGame::initMonsterArray()
{
for (int i = 0; i < MAP_WIDTH; i++)
for (int j = 0; j < MAP_HEIGHT; j++)
monsterArray[i][j] = false;
}
void WitchBlastGame::addMonster(enemyTypeEnum monsterType, float xm, float ym)
{
StructMonster monster;
monster.id = monsterType;
monster.x = xm;
monster.y = ym;
saveInFight.monsters.push_back(monster);
switch (monsterType)
{
case EnemyTypeRat:
new RatEntity(xm, ym - 2, RatEntity::RatTypeNormal, false);
proceedEvent(EventMeetRatsOrBats);
break;
case EnemyTypeRatGreen:
new GreenRatEntity(xm, ym - 2);
proceedEvent(EventMeetRatsOrBats);
break;
case EnemyTypeRatBlack:
new BlackRatEntity(xm, ym - 5, BlackRatEntity::RatBlackTypeNormal);
break;
case EnemyTypeRatHelmet:
new RatEntity(xm, ym - 2, RatEntity::RatTypeHelmet, false);
break;
case EnemyTypeRatBlackHelmet:
new BlackRatEntity(xm, ym - 5, BlackRatEntity::RatBlackTypeHelmet);
break;
case EnemyTypeBat:
new BatEntity(xm, ym, BatStandard, false);
proceedEvent(EventMeetRatsOrBats);
break;
case EnemyTypeBatSkeleton:
new BatEntity(xm, ym, BatSkeleton, false);
break;
case EnemyTypeSnake:
new SnakeEntity(xm, ym, SnakeEntity::SnakeTypeNormal, false);
proceedEvent(EventMeetSnakes);
break;
case EnemyTypeSnakeBlood:
new SnakeEntity(xm, ym, SnakeEntity::SnakeTypeBlood, false);
proceedEvent(EventMeetSnakes);
break;
case EnemyTypeEvilFlower:
new EvilFlowerEntity(xm, ym - 2, FlowerTypeStandard);
break;
case EnemyTypeEvilFlowerIce:
new EvilFlowerEntity(xm, ym - 2, FlowerTypeIce);
break;
case EnemyTypeEvilFlowerFire:
new EvilFlowerEntity(xm, ym - 2, FlowerTypeFire);
break;
case EnemyTypeSlime:
new SlimeEntity(xm, ym, SlimeTypeStandard, false);
break;
case EnemyTypeImpRed:
new ImpEntity(xm, ym, ImpEntity::ImpTypeRed);
break;
case EnemyTypeImpBlue:
new ImpEntity(xm, ym, ImpEntity::ImpTypeBlue);
break;
case EnemyTypeSlimeRed:
new SlimeEntity(xm, ym, SlimeTypeRed, false);
break;
case EnemyTypeSlimeBlue:
new SlimeEntity(xm, ym, SlimeTypeBlue, false);
break;
case EnemyTypeSlimeViolet:
new SlimeEntity(xm, ym, SlimeTypeViolet, false);
break;
case EnemyTypePumpkin:
new PumpkinEntity(xm, ym, false);
break;
case EnemyTypeWitch:
new WitchEntity(xm, ym, WitchEntity::WitchTypeNormal);
proceedEvent(EventMeetWitches);
break;
case EnemyTypeWitchRed:
new WitchEntity(xm, ym, WitchEntity::WitchTypeRed);
proceedEvent(EventMeetWitches);
break;
case EnemyTypeCauldron:
new CauldronEntity(xm, ym, CauldronTypeStandard);
break;
case EnemyTypeCauldronElemental:
new CauldronEntity(xm, ym, CauldronTypeElemental);
break;
case EnemyTypeSpiderEgg:
new SpiderEggEntity(xm, ym, false);
break;
case EnemyTypeSpiderEgg_invocated:
new SpiderEggEntity(xm, ym, true);
break;
case EnemyTypeSpiderLittle:
new LittleSpiderEntity(xm, ym, SpiderTypeStandard, false);
break;
case EnemyTypeSpiderTarantula:
new LittleSpiderEntity(xm, ym, SpiderTypeTarantula, false);
break;
case EnemyTypeGhost:
new GhostEntity(xm, ym);
break;
case EnemyTypeZombie:
new ZombieEntity(xm, ym, false);
break;
case EnemyTypeZombieDark:
new ZombieDarkEntity(xm, ym);
break;
case EnemyTypeBogeyman:
new BogeymanEntity(xm, ym);
break;
case EnemyTypeSausage:
new SausageEntity(xm, ym, false);
break;
case EnemyTypeSpiderLittle_invocated:
new LittleSpiderEntity(xm, ym, SpiderTypeStandard, true);
break;
case EnemyTypeSpiderTarantula_invocated:
new LittleSpiderEntity(xm, ym, SpiderTypeTarantula, true);
break;
case EnemyTypeBubble:
new BubbleEntity(xm, ym, BubbleStandard, 0);
break;
case EnemyTypeBubbleIce:
new BubbleEntity(xm, ym, BubbleIce, 0);
break;
case EnemyTypeBubbleGreater:
new BubbleEntity(xm, ym, BubbleTriple, 0);
break;
case EnemyTypeSlimeLarge:
new LargeSlimeEntity(xm, ym, SlimeTypeStandard);
break;
case EnemyTypeSlimeBlueLarge:
new LargeSlimeEntity(xm, ym, SlimeTypeBlue);
break;
case EnemyTypeSlimeRedLarge:
new LargeSlimeEntity(xm, ym, SlimeTypeRed);
break;
case EnemyTypeSlimeVioletLarge:
new LargeSlimeEntity(xm, ym, SlimeTypeViolet);
break;
case EnemyTypeButcher:
new ButcherEntity(xm, ym);
break;
case EnemyTypeSlimeBoss:
new GiantSlimeEntity(xm, ym);
break;
case EnemyTypeCyclops:
new CyclopsEntity(xm, ym);
break;
case EnemyTypeRatKing:
new KingRatEntity(xm, ym);
break;
case EnemyTypeSpiderGiant:
new GiantSpiderEntity(xm, ym);
break;
case EnemyTypeFrancky:
new FranckyEntity(xm, ym);
break;
case EnemyTypeVampire:
new VampireEntity(xm, ym);
break;
default:
std::cout << "[WARNING] Enemy (" << monsterType << ") not handled in switch.\n";
}
}
void WitchBlastGame::findPlaceMonsters(enemyTypeEnum monsterType, int amount)
{
// find a suitable place
bool isMonsterFlying = monsterType == EnemyTypeBat
|| monsterType == EnemyTypeImpBlue
|| monsterType == EnemyTypeImpRed;
bool isMonsterLarge = monsterType == EnemyTypeSlimeLarge
|| monsterType == EnemyTypeSlimeBlueLarge
|| monsterType == EnemyTypeSlimeRedLarge
|| monsterType == EnemyTypeSlimeVioletLarge;
bool bOk;
int xm, ym;
float xMonster, yMonster;
for (int index = 0; index < amount; index++)
{
bOk = false;
int watchdog = 200;
while (!bOk && watchdog > 0)
{
bOk = true;
watchdog--;
if (isMonsterLarge)
{
xm = 2 +rand() % (MAP_WIDTH - 5);
ym = 2 +rand() % (MAP_HEIGHT - 5);
}
else
{
xm = 1 +rand() % (MAP_WIDTH - 3);
ym = 1 +rand() % (MAP_HEIGHT - 3);
}
if (monsterArray[xm][ym])
{
bOk = false;
}
if (bOk && !isMonsterFlying && !currentMap->isWalkable(xm, ym))
{
bOk = false;
}
if (bOk && isMonsterFlying && !currentMap->isFlyable(xm, ym))
{
bOk = false;
}
if (bOk)
{
xMonster = xm * TILE_WIDTH + TILE_WIDTH * 0.5f;
yMonster = ym * TILE_HEIGHT+ TILE_HEIGHT * 0.5f;
float dist2 = (xMonster - player->getX())*(xMonster - player->getX()) + (yMonster - player->getY())*(yMonster - player->getY());
if ( dist2 < 75000.0f)
{
bOk = false;
}
else
{
addMonster(monsterType, xMonster, yMonster);
monsterArray[xm][ym] = true;
}
}
}
}
}
bool WitchBlastGame::isAdvanced()
{
return (achievementState[AchievementVampire] == AchievementDone);
}
bool WitchBlastGame::isAdvancedLevel()
{
if (isAdvanced())
{
return (rand() % 150 < getAchievementsPercents());
}
else
return false;
}
void WitchBlastGame::generateStandardMap()
{
initMonsterArray();
saveInFight.monsters.clear();
generateStandardRoom(level, isAdvancedLevel());
}
item_equip_enum WitchBlastGame::getRandomEquipItem(bool toSale = false, bool noFairy = false)
{
std::vector<int> bonusSet;
int setSize = 0;
for (int i = 0; i < NUMBER_EQUIP_ITEMS; i++)
{
bool itemOk = true;
int eq = i + FirstEquipItem;
if (player->isEquiped(i)) itemOk = false;
if (itemOk && presentItems[i]) itemOk = false;
// TODO item already in floor
if (itemOk && toSale && !items[eq].canBeSold) itemOk = false;
if (itemOk && !toSale && !items[eq].canBeFound) itemOk = false;
if (itemOk && items[eq].level > level) itemOk = false;
if (itemOk && isItemLocked((enumItemType)eq)) itemOk = false;
if (itemOk && items[eq].requirement >= FirstEquipItem
&& !player->isEquiped(items[eq].requirement - FirstEquipItem)) itemOk = false;
if (itemOk && toSale && level == 1 && items[eq].price > 25) itemOk = false;
if (itemOk && toSale && level == 2 && items[eq].price > 35) itemOk = false;
if (itemOk && (items[eq].specialShot != ShotTypeStandard && items[eq].level < 3) && player->canGetNewShot(false))
itemOk = false;
if (itemOk && (items[eq].specialShot != ShotTypeStandard && items[eq].level >= 3) && player->canGetNewShot(true))
itemOk = false;
if (itemOk && i == EQUIP_BOOK_DUAL && (player->isEquiped(EQUIP_BOOK_DUAL_QUICK) || player->isEquiped(EQUIP_RAPID_SHOT)))
itemOk = false;
if (itemOk && i == EQUIP_BOOK_DUAL_QUICK && (player->isEquiped(EQUIP_BOOK_DUAL) || player->isEquiped(EQUIP_RAPID_SHOT)))
itemOk = false;
if (itemOk && i == EQUIP_RAPID_SHOT && (player->isEquiped(EQUIP_BOOK_DUAL_QUICK) || player->isEquiped(EQUIP_BOOK_DUAL)))
itemOk = false;
if (itemOk && noFairy && items[eq].familiar != FamiliarNone) itemOk = false;
if (itemOk)
{
int n = 0;
switch (items[eq].rarity)
{
case RarityCommon:
n = 8;
break;
case RarityUncommon:
n = 4;
break;
case RarityRare:
n = 2;
break;
case RarityVeryRare:
n = 1;
break;
}
//if (itemOk && eq == ItemPetSlime) n = 15000;
for (int j = 0; j < n; j++)
{
bonusSet.push_back(i);
setSize++;
}
}
}
int bonusType = 0;
if (setSize > 0) bonusType = bonusSet[rand() % setSize];
//addPresentItem(bonusType);
return (item_equip_enum) bonusType;
}
enumItemType WitchBlastGame::getItemSpell()
{
bool ok = false;
enumItemType item = ItemMagicianHat;
while (!ok)
{
enumCastSpell n = (enumCastSpell)(rand() % SPELL_MAX);
if (player->getActiveSpell().spell != n) ok = true;
if (ok)
{
switch (n)
{
case SpellNone:
case SpellTeleport:
item = ItemSpellTeleport;
break;
case SpellSlimeExplode:
item = ItemSpellSlimeExplode;
break;
case SpellFireball:
item = ItemSpellFireball;
break;
case SpellFreeze:
item = ItemSpellFreeze;
break;
case SpellEarthquake:
item = ItemSpellEarthquake;
break;
case SpellProtection:
item = ItemSpellProtection;
break;
case SpellWeb:
item = ItemSpellWeb;
break;
case SpellFlower:
item = ItemSpellFlower;
break;
case SpellFairy:
item = ItemSpellFairy;
break;
case SpellTime:
item = ItemSpellTime;
break;
case SpellLightning:
item = ItemSpellLightning;
break;
}
ok = !isItemLocked(item);
}
}
return item;
}
void WitchBlastGame::generateChallengeBonus(float x, float y)
{
// TODO (jumping)
// loot
if (player->getActiveSpell().spell == SpellNone || rand() % 2 == 0)
{
enumItemType spell1 = getItemSpell();
ItemEntity* spellItem = new ItemEntity(spell1, x, y);
spellItem->setVelocity(Vector2D(100.0f + rand()% 250));
if (spellItem->getVelocity().y < 0.0f) spellItem->setVelocity(Vector2D(spellItem->getVelocity().x, -spellItem->getVelocity().y));
spellItem->setViscosity(0.96f);
spellItem->startsJumping();
if (!isFunctionalityLocked(FunctionalityDoubleSpellDrop))
{
enumItemType spell2 = spell1;
while (spell2 == spell1) spell2 = getItemSpell();
ItemEntity* spellItem2 = new ItemEntity(spell2, x, y);
spellItem2->setVelocity(Vector2D(100.0f + rand()% 250));
if (spellItem2->getVelocity().y < 0.0f) spellItem2->setVelocity(Vector2D(spellItem2->getVelocity().x, -spellItem2->getVelocity().y));
spellItem2->setViscosity(0.96f);
spellItem2->startsJumping();
}
ItemEntity* healthItem1 = new ItemEntity(ItemHealthVerySmall, x, y);
healthItem1->setVelocity(Vector2D(100.0f + rand()% 250));
healthItem1->setViscosity(0.96f);
healthItem1->startsJumping();
ItemEntity* healthItem2 = new ItemEntity(ItemHealthVerySmallPoison, x, y);
healthItem2->setVelocity(Vector2D(100.0f + rand()% 250));
healthItem2->setViscosity(0.96f);
healthItem2->startsJumping();
}
else
{
ItemEntity* newItem;
if (challengeLevel < 4 || rand() % (player->isEquiped(EQUIP_LUCK) ? 5 : 8) > 0)
newItem = new ItemEntity(ItemBonusHealth, x, y);
else
newItem = new ItemEntity((enumItemType)(FirstEquipItem + getRandomEquipItem()), x, y);
if (newItem->getVelocity().y < 0.0f) newItem->setVelocity(Vector2D(newItem->getVelocity().x, -newItem->getVelocity().y));
newItem->setVelocity(Vector2D(100.0f + rand()% 250));
newItem->setViscosity(0.96f);
newItem->startsJumping();
int gold = 2 + rand() % (player->isEquiped(EQUIP_LUCK) ? 9 : 14);
for (int i = 0; i < gold; i++)
{
ItemEntity* newItem = new ItemEntity(ItemCopperCoin, x, y);
newItem->setVelocity(Vector2D(90.0f + rand()% 150));
newItem->setViscosity(0.96f);
newItem->startsJumping();
}
}
}
void WitchBlastGame::checkInteraction()
{
interaction.active = false;
if (player->getPlayerStatus() != PlayerEntity::playerStatusPlaying) return;
if (currentMap->getRoomType() == roomTypeTemple)
{
int divinity = currentMap->getDivinity(player->getX() / TILE_WIDTH, player->getZ() / TILE_HEIGHT);
if (divinity > -1)
{
interaction.active = true;
interaction.type = InteractionTypeTemple;
interaction.id = divinity;
std::stringstream ss;
ss << "[" << keyToString(input[KeyInteract]) << "] - ";
if (player->getDivinity().divinity == divinity)
{
ss << tools::getLabel("interact_donate");
if (player->getGold() < 10)
{
ss << " ";
ss << tools::getLabel("interact_donate_fail");
}
}
else
{
ss << tools::getLabel("interact_worship");
ss << " ";
ss << tools::getLabel(divinityLabel[divinity] + "_0");
}
interaction.label = ss.str();
}
}
else if (player->getItemToBuy() != NULL)
{
interaction.active = true;
interaction.type = InteractionTypeMerchandise;
interaction.id = player->getItemToBuy()->getItemType();
std::stringstream ss;
ss << tools::getLabel(items[interaction.id].name);
ss << ": ";
ss << tools::getLabel(items[interaction.id].description);
if (player->getItemToBuy()->canBePickedUp())
{
ss << std::endl;
ss << "[" << keyToString(input[KeyInteract]) << "] - ";
ss << tools::getLabel("interact_shop");
}
interaction.label = ss.str();
}
}
void WitchBlastGame::verifyDoorUnlocking()
{
int collidingDirection = (player->getCollidingDirection());
if (collidingDirection != 5 && currentMap->isCleared() && !bossRoomOpened && player->isEquiped(EQUIP_BOSS_KEY))
{
int xt = (player->getX()) / TILE_WIDTH;
int yt = (player->getY()) / TILE_HEIGHT;
if (yt <= 1 && xt >= MAP_WIDTH / 2 - 1 && xt <= MAP_WIDTH / 2 + 1 && currentMap->hasNeighbourUp() == 2)
{
doorEntity[0]->openDoor();
currentMap->openDoor(MAP_WIDTH / 2, 0);
SoundManager::getInstance().playSound(SOUND_DOOR_OPENING);
player->useBossKey();
bossRoomOpened = true;
}
if (yt >= MAP_HEIGHT - 2 && xt >= MAP_WIDTH / 2 - 1 &&xt <= MAP_WIDTH / 2 + 1 && currentMap->hasNeighbourDown() == 2)
{
doorEntity[2]->openDoor();
currentMap->openDoor(MAP_WIDTH / 2, MAP_HEIGHT - 1);
SoundManager::getInstance().playSound(SOUND_DOOR_OPENING);
player->useBossKey();
bossRoomOpened = true;
}
if (xt <= 1 && yt >= MAP_HEIGHT / 2 - 1 && yt <= MAP_HEIGHT / 2 + 1 && currentMap->hasNeighbourLeft() == 2)
{
doorEntity[1]->openDoor();
currentMap->openDoor(0, MAP_HEIGHT / 2);
SoundManager::getInstance().playSound(SOUND_DOOR_OPENING);
player->useBossKey();
bossRoomOpened = true;
}
if (xt >= MAP_WIDTH - 2 && yt >= MAP_HEIGHT / 2 - 1 && yt <= MAP_HEIGHT / 2 + 1 && currentMap->hasNeighbourRight() == 2)
{
doorEntity[3]->openDoor();
currentMap->openDoor(MAP_WIDTH - 1, MAP_HEIGHT / 2);
SoundManager::getInstance().playSound(SOUND_DOOR_OPENING);
player->useBossKey();
bossRoomOpened = true;
}
}
}
void WitchBlastGame::playMusic(musicEnum musicChoice)
{
music.stop();
if (parameters.musicVolume <= 0) return;
music.setLoop(true);
music.setVolume(parameters.musicVolume * VolumeModifier / 100);
bool ok = false;
switch (musicChoice)
{
case MusicDungeon:
{
int r = currentStandardMusic;
while (r == currentStandardMusic) r = rand() % 3;
switch (r)
{
case 0: ok = music.openFromFile("media/sound/WitchBlastTheme.ogg"); break;
case 1: ok = music.openFromFile("media/sound/SavageLife.ogg"); break;
case 2: ok = music.openFromFile("media/sound/HauntedLighthouse.ogg"); break;
}
currentStandardMusic = r;
}
break;
case MusicEnding:
ok = music.openFromFile("media/sound/AmbiantMedieval.ogg");
break;
case MusicBoss:
ok = music.openFromFile("media/sound/ShowMeThePower.ogg");
break;
case MusicChallenge:
ok = music.openFromFile("media/sound/HellsFire.ogg");
break;
case MusicIntro:
ok = music.openFromFile("media/sound/WitchBlastTheme.ogg");
break;
}
if (ok)
music.play();
}
void WitchBlastGame::pauseMusic()
{
music.pause();
}
void WitchBlastGame::resumeMusic()
{
music.play();
}
void WitchBlastGame::updateMusicVolume()
{
if (music.getStatus() == sf::Music::Playing)
{
if (parameters.musicVolume == 0)
music.stop();
else
music.setVolume(parameters.musicVolume * VolumeModifier / 100);
}
else
{
if (parameters.musicVolume > 0)
{
bool ok = music.openFromFile("media/sound/wb.ogg");
music.setVolume(parameters.musicVolume * VolumeModifier / 100);
if (ok) music.play();
}
}
}
void WitchBlastGame::makeShake(float duration)
{
xGame[xGameTypeShake].active = true;
xGame[xGameTypeShake].timer = duration;
}
void WitchBlastGame::makeColorEffect(int color, float duration)
{
xGame[xGameTypeFadeColor].active = true;
xGame[xGameTypeFadeColor].param = color;
xGame[xGameTypeFadeColor].timer = duration;
xGame[xGameTypeFadeColor].duration = duration;
}
void WitchBlastGame::saveGame()
{
if (player->getPlayerStatus() == PlayerEntity::playerStatusAcquire)
player->acquireItemAfterStance();
std::ofstream file(SAVE_FILE.c_str(), std::ios::out | std::ios::trunc);
int i, j, k, l;
if (file)
{
// version (for compatibility check)
file << SAVE_VERSION << std::endl;
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
file << (now->tm_year + 1900) << '-';
if (now->tm_mon < 9) file << "0";
file << (now->tm_mon + 1) << '-';
if (now->tm_mday < 9) file << "0";
file << now->tm_mday
<< std::endl;
if (now->tm_hour <= 9) file << "0";
file << (now->tm_hour) << ':';
if (now->tm_min <= 9) file << "0";
file << (now->tm_min) << std::endl;
// floor
file << level << " " << challengeLevel << " " << secretsFound << std::endl;
// game age
file << (int)gameTime << std::endl;
// player equip
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++) file << player->isEquiped(i) << " ";
file << std::endl;
file << player->getShotType() << std::endl;
int nbRooms = 0;
for (j = 0; j < FLOOR_HEIGHT; j++)
{
for (i = 0; i < FLOOR_WIDTH; i++)
{
file << currentFloor->getRoom(i,j) << " ";
if (currentFloor->getRoom(i,j) > 0) nbRooms++;
}
file << std::endl;
}
// kill stats
for (i = 0; i < NB_ENEMY; i++) file << killedEnemies[i] << " ";
file << std::endl;
// potions
for(auto it = potionMap.begin(); it != potionMap.end(); ++it)
{
file << it->first << " " << it->second.effect << " " << it->second.known << std::endl;
}
// maps
if (currentMap->isCleared())
saveMapItems();
file << nbRooms << std::endl;
for (j = 0; j < FLOOR_HEIGHT; j++)
{
for (i = 0; i < FLOOR_WIDTH; i++)
{
if (currentFloor->getRoom(i,j) > 0)
{
file << i << " " << j << " "
<< currentFloor->getMap(i, j)->getRoomType() << " "
<< currentFloor->getMap(i, j)->isKnown() << " "
<< currentFloor->getMap(i, j)->isVisited() << " "
<< currentFloor->getMap(i, j)->isRevealed() << " "
<< currentFloor->getMap(i, j)->isCleared() << std::endl;
if (currentFloor->getMap(i, j)->isVisited())
{
for (l = 0; l < MAP_HEIGHT; l++)
{
for (k = 0; k < MAP_WIDTH; k++)
{
int tile = currentFloor->getMap(i, j)->getTile(k, l);
file << tile << " ";
tile = currentFloor->getMap(i, j)->getObjectTile(k, l);
if (tile == MAPOBJ_DOOR_CLOSED) tile = MAPOBJ_DOOR_OPEN;
file << tile << " ";
file << currentFloor->getMap(i, j)->getLogicalTile(k, l) << " ";
}
file << std::endl;
}
// style
file << currentFloor->getMap(i, j)->getFloorOffset() << " "
<< currentFloor->getMap(i, j)->getWallType() << std::endl;
// items, etc...
std::list<DungeonMap::itemListElement> itemList = currentFloor->getMap(i, j)->getItemList();
file << itemList.size() << std::endl;
std::list<DungeonMap::itemListElement>::iterator it;
for (it = itemList.begin (); it != itemList.end ();)
{
DungeonMap::itemListElement ilm = *it;
it++;
file << ilm.type << " " << ilm.x << " " << ilm.y << " " << ilm.merch << std::endl;
}
// chests
std::list<DungeonMap::chestListElement> chestList = currentFloor->getMap(i, j)->getChestList();
file << chestList.size() << std::endl;
std::list<DungeonMap::chestListElement>::iterator itc;
for (itc = chestList.begin (); itc != chestList.end ();)
{
DungeonMap::chestListElement ilm = *itc;
itc++;
file << ilm.type << " " << ilm.x << " " << ilm.y << " " << ilm.state << std::endl;
}
// sprites
std::list<DungeonMap::spriteListElement> spriteList = currentFloor->getMap(i, j)->getSpriteList();
file << spriteList.size() << std::endl;
std::list<DungeonMap::spriteListElement>::iterator its;
for (its = spriteList.begin (); its != spriteList.end ();)
{
DungeonMap::spriteListElement ilm = *its;
its++;
file << ilm.type << " " << ilm.frame << " " << ilm.x << " " << ilm.y << " " << ilm.scale << std::endl;
}
// doors
for (int k = 0; k < 4; k++)
file << currentFloor->getMap(i, j)->getDoorType(k) << " ";
file << std::endl;
// random sprite
for (int k = 0; k < NB_RANDOM_TILES_IN_ROOM; k++)
{
file << currentFloor->getMap(i, j)->getRandomTileElement(k).type
<< " " <<currentFloor->getMap(i, j)->getRandomTileElement(k).x
<< " " << currentFloor->getMap(i, j)->getRandomTileElement(k).y
<< " " << currentFloor->getMap(i, j)->getRandomTileElement(k).rotation << std::endl;
}
}
}
}
file << std::endl;
}
// game
file << floorX << " " << floorY << std::endl;
file << bossRoomOpened << std::endl;
// boss door !
// fight ?
if (currentMap->isCleared())
{
file << false << std::endl;
}
else
{
file << true << std::endl;
file << saveInFight.x << " " << saveInFight.y << " " << saveInFight.direction << std::endl;
file << saveInFight.monsters.size();
for (auto monster : saveInFight.monsters)
file << " " << monster.id << " " << monster.x << " " << monster.y;
file << std::endl;
}
// player
file << player->getHp() << " " << player->getHpMax() << " " << player->getGold() << " " << player->getDonation() << std::endl;
// lost hp
for (i = 1; i <= LAST_LEVEL; i++) file << player->getLostHp(i) << " ";
file << std::endl;
// equip
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++) file << player->isEquiped(i) << " ";
file << std::endl;
file << player->getX() << " " << player->getY() << std::endl;
file << player->getShotIndex();
for (i = 0; i < SPECIAL_SHOT_SLOTS; i++) file << " " << player->getShotType(i) << std::endl;
file << player->getActiveSpell().spell << std::endl;
for (i = 0; i < MAX_SLOT_CONSUMABLES; i++)
{
file << player->getConsumable(i) << " ";
}
file << std::endl;
// divinity
file << player->getDivinity().divinity << " " << player->getDivinity().piety << " "
<< player->getDivinity().level << " " << player->getDivinity().interventions << std::endl;
// events
for (i = 0; i < NB_EVENTS; i++) file << worldEvent[i] << " ";
file.close();
}
else
{
std::cerr << "[ERROR] Saving the game..." << std::endl;
}
}
bool WitchBlastGame::loadGame()
{
resetPresentItems();
saveInFight.monsters.clear();
std::ifstream file(SAVE_FILE.c_str(), std::ios::in);
if (file)
{
int i, j, k, n;
// version
std::string v;
file >> v;
if (v != SAVE_VERSION)
{
file.close();
remove(SAVE_FILE.c_str());
return false;
}
// date an time
file >> v;
file >> v;
// floor
file >> level;
file >> challengeLevel;
file >> secretsFound;
file >> gameTime;
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++)
{
bool eq;
file >> eq;
}
file >> n;
currentFloor = new GameFloor(level);
for (j = 0; j < FLOOR_HEIGHT; j++)
{
for (i = 0; i < FLOOR_WIDTH; i++)
{
int n;
file >> n;
currentFloor->setRoom(i, j, (roomTypeEnum)n);
}
}
// kill stats
for (int i = 0; i < NB_ENEMY; i++) file >> killedEnemies[i];
// potions
for (i = 0; i < NUMBER_UNIDENTIFIED * 2; i++)
{
int source, effect;
bool known;
file >> source >> effect >> known;
addPotionToMap((enumItemType)source, (enumItemType)effect, known);
}
// maps
int nbRooms;
file >> nbRooms;
for (k = 0; k < nbRooms; k++)
{
file >> i;
file >> j;
file >> n;
DungeonMap* iMap = new DungeonMap(currentFloor, i, j);
currentFloor->setMap(i, j, iMap);
iMap->setRoomType((roomTypeEnum)n);
bool flag;
file >> flag;
iMap->setKnown(flag);
file >> flag;
iMap->setVisited(flag);
file >> flag;
if (!flag) iMap->setRevealed(flag);
file >> flag;
iMap->setCleared(flag);
if (iMap->isVisited())
{
for (j = 0; j < MAP_HEIGHT; j++)
{
for (i = 0; i < MAP_WIDTH; i++)
{
file >> n;
iMap->setTile(i, j, n);
file >> n;
iMap->setObjectTile(i, j, n);
file >> n;
iMap->setLogicalTile(i, j, (logicalMapStateEnum)n);
}
}
// style
file >> n;
iMap->setFloorOffset(n);
file >> n;
iMap->setWallType(n);
// items int the map
file >> n;
for (i = 0; i < n; i++)
{
int t;
float x, y;
bool merc;
file >> t >> x >> y >> merc;
iMap->addItem(t, x, y, merc);
}
// chests in the map
file >> n;
for (i = 0; i < n; i++)
{
int t;
float x, y;
bool state;
file >> t >> x >> y >> state;
iMap->addChest(t, state, x, y);
}
// sprites in the map
file >> n;
for (i = 0; i < n; i++)
{
int t, f;
float x, y, scale;
file >> t >> f >> x >> y >> scale;
iMap->addSprite(t, f, x, y, scale);
}
// doors
for (int index = 0; index < 4; index++)
{
file >> n;
iMap->setDoorType(index, (doorEnum)n);
}
// random sprite
for (int index = 0; index < NB_RANDOM_TILES_IN_ROOM; index++)
{
DungeonMap::RandomTileElement rd;
file >> rd.type;
file >> rd.x;
file >> rd.y;
file >> rd.rotation;
iMap->setRandomTileElement(index, rd);
}
// random sprite
}
}
// game
file >> floorX >> floorY;
currentMap = currentFloor->getMap(floorX, floorY);
file >> bossRoomOpened;
// fight ?
file >> saveInFight.isFight;
if (saveInFight.isFight)
{
currentMap->setCleared(false);
file >> saveInFight.x;
file >> saveInFight.y;
file >> saveInFight.direction;
file >> n;
for (i = 0; i < n; i++)
{
StructMonster monster;
file >> j;
monster.id = (enemyTypeEnum)j;
file >> monster.x;
file >> monster.y;
saveInFight.monsters.push_back(monster);
}
}
// player
int hp, hpMax, gold, donation;
file >> hp >> hpMax >> gold >> donation;
player = new PlayerEntity((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f));
player->setHp(hp);
player->setHpMax(hpMax);
player->setGold(gold);
player->setDonation(donation);
// lost hp
for (i = 1; i <= LAST_LEVEL; i++)
{
file >> n;
player->setLostHp(i, n);
}
// equip
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++)
{
bool eq;
file >> eq;
player->setEquiped(i, eq);
}
float x, y;
file >> x >> y;
if (saveInFight.isFight)
{
x = saveInFight.x;
y = saveInFight.y;
player->move(saveInFight.direction);
player->setEntering();
}
player->moveTo(x, y);
file >> n;
player->setShotIndex(n);
for (i = 0; i < SPECIAL_SHOT_SLOTS; i++)
{
file >> n;
player->setShotType(i, (enumShotType)n);
}
file >> n;
player->setActiveSpell((enumCastSpell)n, saveInFight.isFight);
for (i = 0; i < MAX_SLOT_CONSUMABLES; i++)
{
file >> n;
player->setConsumable(i, n);
}
// divinity
{
int divinityId, piety, divLevel, interventions;
file >> divinityId;
file >> piety;
file >> divLevel;
file >> interventions;
player->loadDivinity(divinityId, piety, divLevel, interventions);
}
// events
for (i = 0; i < NB_EVENTS; i++)
{
bool event;
file >> event;
worldEvent[i] = event;
}
player->computePlayer();
file.close();
remove(SAVE_FILE.c_str());
}
else
{
return false;
}
return true;
}
WitchBlastGame::saveHeaderStruct WitchBlastGame::loadGameHeader()
{
saveHeaderStruct saveHeader;
saveHeader.ok = true;
std::ifstream file(SAVE_FILE.c_str(), std::ios::in);
if (file)
{
// version
std::string v;
file >> v;
if (v != SAVE_VERSION)
{
file.close();
remove(SAVE_FILE.c_str());
saveHeader.ok = false;
}
else
{
// date an time
file >> saveHeader.date;
file >> saveHeader.time;
// floor
file >> saveHeader.level;
int challengeLevel;
file >> challengeLevel;
file >> saveHeader.gameTime;
for (int i = 0; i < NUMBER_EQUIP_ITEMS; i++)
file >> equipToDisplay[i];
file >> saveHeader.shotType;
}
}
else
{
saveHeader.ok = false;
}
return saveHeader;
}
void WitchBlastGame::saveGameData()
{
// TODO
std::ofstream file(SAVE_DATA_FILE.c_str(), std::ios::out | std::ios::trunc);
if (file)
{
// version (for compatibility check)
file << SAVE_VERSION << std::endl;
int i;
// tuto
for (i = 0; i < NB_MESSAGES; i++)
{
messageStruct msg = getMessage((EnumMessages)i);
if (msg.messageType == MessageTypeTutorial)
{
file << gameMessagesToSkip[i] << " ";
}
else file << "0 ";
}
file << std::endl;
// achievements
for (i = 0; i < NB_ACHIEVEMENTS; i++)
{
if (achievementState[i] == AchievementDone) file << "1 ";
else file << "0 ";
}
file << std::endl;
// monsters
for (i = 0; i < NB_ENEMY; i++)
{
file << globalData.killedMonster[i] << " ";
}
file << std::endl;
file.close();
}
else
{
std::cout << "[ERROR] Impossible to open save data file.\n";
}
}
void WitchBlastGame::loadGameData()
{
std::ifstream file(SAVE_DATA_FILE.c_str(), std::ios::in);
int i;
if (file)
{
// version
std::string v;
file >> v;
if (v != SAVE_VERSION)
{
file.close();
remove(SAVE_DATA_FILE.c_str());
return;
}
// tuto
for (i = 0; i < NB_MESSAGES; i++)
{
file >> gameMessagesToSkip[i];
}
}
// Achievements
for (i = 0; i < NB_ACHIEVEMENTS; i++)
{
int n;
file >> n;
if (n == 1) achievementState[i] = AchievementDone;
else achievementState[i] = AchievementUndone;
}
// Monsters
for (i = 0; i < NB_ENEMY; i++)
file >> globalData.killedMonster[i];
}
void WitchBlastGame::addKey(int logicInput, std::string key)
{
int iKey = config.findInt(key);
if (iKey >= 0)
{
sf::Keyboard::Key k = (sf::Keyboard::Key)iKey;
input[logicInput] = k;
}
}
void WitchBlastGame::saveConfigurationToFile()
{
std::map<std::string, std::string> newMap;
// parameters
newMap["language"] = intToString(parameters.language);
newMap["player_name"] = parameters.playerName;
// audio volume
newMap["volume_sound"] = intToString(parameters.soundVolume);
newMap["volume_music"] = intToString(parameters.musicVolume);
newMap["zoom_enabled"] = parameters.zoom ? "1" : "0";
newMap["vsync_enabled"] = parameters.vsync ? "1" : "0";
newMap["blood_spreading"] = parameters.bloodSpread ? "1" : "0";
newMap["fullscreen"] = parameters.fullscreen ? "1" : "0";
newMap["pause_on_focus_lost"] = parameters.pauseOnFocusLost ? "1" : "0";
newMap["display_boss_portrait"] = parameters.displayBossPortrait ? "1" : "0";
// Keys
newMap["keyboard_move_up"] = intToString(input[KeyUp]);
newMap["keyboard_move_down"] = intToString(input[KeyDown]);
newMap["keyboard_move_left"] = intToString(input[KeyLeft]);
newMap["keyboard_move_right"] = intToString(input[KeyRight]);
newMap["keyboard_fire_up"] = intToString(input[KeyFireUp]);
newMap["keyboard_fire_down"] = intToString(input[KeyFireDown]);
newMap["keyboard_fire_left"] = intToString(input[KeyFireLeft]);
newMap["keyboard_fire_right"] = intToString(input[KeyFireRight]);
newMap["keyboard_spell"] = intToString(input[KeySpell]);
newMap["keyboard_interact"] = intToString(input[KeyInteract]);
newMap["keyboard_fire"] = intToString(input[KeyFire]);
newMap["keyboard_time_control"] = intToString(input[KeyTimeControl]);
newMap["keyboard_fire_select"] = intToString(input[KeyFireSelect]);
// Joystick
for (unsigned int i = 0; i < NumberKeys; i++)
{
std::stringstream oss_button;
oss_button << "joy_" << inputKeyStr[i] << "_button";
std::stringstream oss_value;
oss_value << "joy_" << inputKeyStr[i] << "_value";
std::stringstream oss_axis;
oss_axis << "joy_" << inputKeyStr[i] << "_axis";
newMap[oss_button.str()] = joystickInput[i].isButton ? "1" : "0";
newMap[oss_value.str()] = intToString(joystickInput[i].value);
newMap[oss_axis.str()] = intToString(joystickInput[i].axis);
}
config.saveToFile(CONFIG_FILE, newMap);
}
void WitchBlastGame::configureFromFile()
{
// default
parameters.language = 0; // english
parameters.zoom = true;
parameters.vsync = true;
parameters.bloodSpread = true;
parameters.fullscreen = false;
parameters.pauseOnFocusLost = true;
parameters.musicVolume = 80;
parameters.soundVolume = 80;
parameters.playerName = "";
parameters.displayBossPortrait = false;
input[KeyUp] = sf::Keyboard::W;
input[KeyDown] = sf::Keyboard::S;
input[KeyLeft] = sf::Keyboard::A;
input[KeyRight] = sf::Keyboard::D;
input[KeyFireUp] = sf::Keyboard::Up;
input[KeyFireDown] = sf::Keyboard::Down;
input[KeyFireLeft] = sf::Keyboard::Left;
input[KeyFireRight] = sf::Keyboard::Right;
input[KeyFire] = sf::Keyboard::RControl;
input[KeySpell] = sf::Keyboard::Space;
input[KeyInteract] = sf::Keyboard::E;
input[KeyFireSelect] = sf::Keyboard::Tab;
input[KeyTimeControl] = sf::Keyboard::RShift;
// Joystick
joystickInput[KeyUp].isButton = false;
joystickInput[KeyUp].axis = sf::Joystick::Y;
joystickInput[KeyUp].value = -1;
joystickInput[KeyDown].isButton = false;
joystickInput[KeyDown].axis = sf::Joystick::Y;
joystickInput[KeyDown].value = 1;
joystickInput[KeyLeft].isButton = false;
joystickInput[KeyLeft].axis = sf::Joystick::X;
joystickInput[KeyLeft].value = -1;
joystickInput[KeyRight].isButton = false;
joystickInput[KeyRight].axis = sf::Joystick::X;
joystickInput[KeyRight].value = 1;
for (unsigned int i = KeyFireUp; i < NumberKeys; i++)
{
joystickInput[i].isButton = true;
joystickInput[i].axis = sf::Joystick::X;
joystickInput[i].value = i - 4;
}
// from file
addKey(KeyUp, "keyboard_move_up");
addKey(KeyDown, "keyboard_move_down");
addKey(KeyLeft, "keyboard_move_left");
addKey(KeyRight, "keyboard_move_right");
addKey(KeyFireUp, "keyboard_fire_up");
addKey(KeyFireDown, "keyboard_fire_down");
addKey(KeyFireLeft, "keyboard_fire_left");
addKey(KeyFireRight, "keyboard_fire_right");
addKey(KeyFire, "keyboard_fire");
addKey(KeySpell, "keyboard_spell");
addKey(KeyInteract, "keyboard_interact");
addKey(KeyTimeControl, "keyboard_time_control");
addKey(KeyFireSelect, "keyboard_fire_select");
// Joystick
for (unsigned int i = 0; i < NumberKeys; i++)
{
std::stringstream oss_button;
oss_button << "joy_" << inputKeyStr[i] << "_button";
std::stringstream oss_value;
oss_value << "joy_" << inputKeyStr[i] << "_value";
std::stringstream oss_axis;
oss_axis << "joy_" << inputKeyStr[i] << "_axis";
int isButton = config.findInt(oss_button.str());
if (isButton > -1000)
joystickInput[i].isButton = isButton;
int n = config.findInt(oss_value.str());
if (n > -1000)
joystickInput[i].value = n;
n = config.findInt(oss_axis.str());
if (n >= sf::Joystick::Axis::X && n <= sf::Joystick::Axis::PovY)
joystickInput[i].axis = (sf::Joystick::Axis)n;
}
int i = config.findInt("language");
if (i >= 0 && i < NB_LANGUAGES) parameters.language = i;
i = config.findInt("volume_sound");
if (i >= 0) parameters.soundVolume = i;
i = config.findInt("volume_music");
if (i >= 0) parameters.musicVolume = i;
i = config.findInt("vsync_enabled");
if (i >= 0) parameters.vsync = i;
i = config.findInt("zoom_enabled");
if (i >= 0) parameters.zoom = i;
i = config.findInt("blood_spreading");
if (i >= 0) parameters.bloodSpread = i;
i = config.findInt("fullscreen");
if (i >= 0) parameters.fullscreen = i;
i = config.findInt("pause_on_focus_lost");
if (i >= 0) parameters.pauseOnFocusLost = i;
i = config.findInt("display_boss_portrait");
if (i >= 0) parameters.displayBossPortrait = i;
std::string playerName = config.findString("player_name");
if (playerName.size() > 0) parameters.playerName = playerName;
tools::setLanguage(languageString[parameters.language]);
}
parameterStruct WitchBlastGame::getParameters()
{
return parameters;
}
void WitchBlastGame::buildMenu(bool rebuild)
{
menuMain.items.clear();
menuConfig.items.clear();
menuFirst.items.clear();
if (!rebuild)
{
menuState = MenuStateMain;
menuMain.age = 0.0f;
menuConfig.age = 0.0f;
menuConfig.index = 0;
}
saveHeader = loadGameHeader();
menuItemStuct itemName;
itemName.label = tools::getLabel("player_name");
itemName.description = tools::getLabel("player_name_desc");
itemName.id = MenuPlayerName;
menuMain.items.push_back(itemName);
if (saveHeader.ok)
{
menuItemStuct itemStart;
itemStart.label = tools::getLabel("start_new_game");
itemStart.description = tools::getLabel("start_desc");
itemStart.id = MenuStartNew;
menuMain.items.push_back(itemStart);
menuItemStuct itemLoad;
itemStart.label = tools::getLabel("restore");
std::ostringstream oss;
oss << saveHeader.date << " " << tools::getLabel("at") << " " << saveHeader.time << " - " << tools::getLabel("level") << " " << saveHeader.level;
itemStart.description = oss.str();
itemStart.id = MenuStartOld;
menuMain.items.push_back(itemStart);
if (!rebuild) menuMain.index = 2;
}
else
{
menuItemStuct itemStart;
itemStart.label = tools::getLabel("start_new_game");
itemStart.description = tools::getLabel("begin_journey");
itemStart.id = MenuStartNew;
menuMain.items.push_back(itemStart);
if (!rebuild) menuMain.index = 1;
}
if (parameters.playerName.compare("") == 0 && menuState == MenuStateMain)
{
menuMain.index = 0;
menuState = MenuStateChangeName;
}
menuItemStuct itemConfig;
itemConfig.label = tools::getLabel("configure_game");
itemConfig.description = tools::getLabel("configure_game_desc");
itemConfig.id = MenuConfig;
menuMain.items.push_back(itemConfig);
if (!isFunctionalityLocked(FunctionalityAchievementsScreen))
{
menuItemStuct itemAchiev;
std::ostringstream oss;
oss << tools::getLabel("menu_achievements");
oss << " (" << getAchievementsPercents() << "%)";
itemAchiev.label = oss.str();
itemAchiev.description = tools::getLabel("menu_achievements_desc");
itemAchiev.id = MenuAchievements;
menuMain.items.push_back(itemAchiev);
}
//if (scores.size() > 0)
{
menuItemStuct itemHiScores;
itemHiScores.label = tools::getLabel("hi_scores");
itemHiScores.description = tools::getLabel("hi_scores_desc");
itemHiScores.id = MenuHiScores;
menuMain.items.push_back(itemHiScores);
}
menuItemStuct itemCredits;
itemCredits.label = tools::getLabel("credits");
itemCredits.description = tools::getLabel("credits_desc");
itemCredits.id = MenuCredits;
menuMain.items.push_back(itemCredits);
menuItemStuct itemExit;
itemExit.label = tools::getLabel("exit_game");
itemExit.description = tools::getLabel("return_to_desktop");
itemExit.id = MenuExit;
menuMain.items.push_back(itemExit);
// configuration
menuItemStuct itemKeys;
itemKeys.label = tools::getLabel("config_keys");
itemKeys.description = tools::getLabel("redef_input");
itemKeys.id = MenuKeys;
menuConfig.items.push_back(itemKeys);
menuItemStuct itemJoystick;
itemJoystick.label = tools::getLabel("config_joystick");
if (sf::Joystick::isConnected(0))
itemJoystick.description = tools::getLabel("redef_joystick");
else
itemJoystick.description = tools::getLabel("joystick_not_found");
itemJoystick.id = MenuJoystick;
menuConfig.items.push_back(itemJoystick);
menuItemStuct itemLanguage;
itemLanguage.label = tools::getLabel("config_lang");
itemLanguage.description = tools::getLabel("config_lang_desc");
itemLanguage.id = MenuLanguage;
menuConfig.items.push_back(itemLanguage);
menuItemStuct itemVolumeSound;
itemVolumeSound.label = tools::getLabel("volume_sound");
itemVolumeSound.description = tools::getLabel("volume_sound_desc");
itemVolumeSound.id = MenuVolumeSound;
menuConfig.items.push_back(itemVolumeSound);
menuItemStuct itemVolumeMusic;
itemVolumeMusic.label = tools::getLabel("volume_music");
itemVolumeMusic.description = tools::getLabel("volume_sound_desc");
itemVolumeMusic.id = MenuVolumeMusic;
menuConfig.items.push_back(itemVolumeMusic);
menuItemStuct itemTutoReset;
itemTutoReset.label = tools::getLabel("tuto_reset");
itemTutoReset.description = tools::getLabel("tuto_reset_desc");
itemTutoReset.id = MenuTutoReset;
menuConfig.items.push_back(itemTutoReset);
menuItemStuct itemConfigBack;
itemConfigBack.label = tools::getLabel("config_back");
itemConfigBack.description = tools::getLabel("config_back_desc");
itemConfigBack.id = MenuConfigBack;
menuConfig.items.push_back(itemConfigBack);
//first time screen
menuFirst.items.push_back(itemLanguage);
}
void WitchBlastGame::buildInGameMenu()
{
menuInGame.items.clear();
menuItemStuct itemContinue;
itemContinue.label = tools::getLabel("menu_continue");
itemContinue.description = tools::getLabel("menu_continue_desc");
itemContinue.id = MenuContinue;
menuInGame.items.push_back(itemContinue);
menuItemStuct itemSaveQuit;
itemSaveQuit.label = tools::getLabel("menu_save_quit");
itemSaveQuit.description = tools::getLabel("menu_save_quit_desc");
itemSaveQuit.id = MenuSaveAndQuit;
menuInGame.items.push_back(itemSaveQuit);
menuItemStuct itemQuit;
itemQuit.label = tools::getLabel("menu_quit");
itemQuit.description = tools::getLabel("menu_quit_desc");
itemQuit.id = MenuExit;
menuInGame.items.push_back(itemQuit);
menuInGame.index = 0;
}
void WitchBlastGame::resetKilledEnemies()
{
for (int i = 0; i < NB_ENEMY; i++) killedEnemies[i] = 0;
}
void WitchBlastGame::addKilledEnemy(enemyTypeEnum enemyType, enumShotType hurtingType)
{
if(!player->isDead())
{
if (enemyType == NB_ENEMY)
std::cout << "[ERROR] No enemy type";
else
{
killedEnemies[enemyType]++;
globalData.killedMonster[enemyType]++;
player->offerMonster(enemyType, hurtingType);
// achievements
if (enemyType == EnemyTypeButcher) registerAchievement(AchievementButcher);
else if (enemyType == EnemyTypeSlimeBoss) registerAchievement(AchievementGiantSlime);
else if (enemyType == EnemyTypeCyclops) registerAchievement(AchievementCyclops);
else if (enemyType == EnemyTypeRatKing) registerAchievement(AchievementRatKing);
else if (enemyType == EnemyTypeSpiderGiant) registerAchievement(AchievementGiantSpider);
else if (enemyType == EnemyTypeFranckyHead) registerAchievement(AchievementFrancky);
else if (enemyType == EnemyTypeVampire) registerAchievement(AchievementVampire);
else if ((enemyType == EnemyTypeRat || enemyType == EnemyTypeRatHelmet || enemyType == EnemyTypeRat_invocated
|| enemyType == EnemyTypeRatBlack || enemyType == EnemyTypeRatBlackHelmet))
{
if (globalData.killedMonster[EnemyTypeRat] + globalData.killedMonster[EnemyTypeRatHelmet] + globalData.killedMonster[EnemyTypeRat_invocated]
+ globalData.killedMonster[EnemyTypeRatBlack] + globalData.killedMonster[EnemyTypeRatBlackHelmet] >= 250)
registerAchievement(AchievementRats);
}
else if (enemyType == EnemyTypeWitch || enemyType == EnemyTypeWitchRed)
{
if (globalData.killedMonster[EnemyTypeWitch] + globalData.killedMonster[EnemyTypeWitchRed] >= 50)
registerAchievement(AchievementWitches);
}
else if (enemyType == EnemyTypeGhost)
{
if (globalData.killedMonster[EnemyTypeGhost] >= 50)
registerAchievement(AchievementGhostbuster);
}
else if (enemyType == EnemyTypeSpiderEgg || enemyType == EnemyTypeSpiderEgg_invocated)
{
if (globalData.killedMonster[EnemyTypeSpiderEgg] + globalData.killedMonster[EnemyTypeSpiderEgg_invocated] >= 100)
registerAchievement(AchievementEggs);
}
}
}
}
void WitchBlastGame::registerLanguage()
{
// default keys
if (parameters.language == 1)
{
// french keyboard
input[KeyUp] = sf::Keyboard::Z;
input[KeyLeft] = sf::Keyboard::Q;
}
else
{
// QWERT / QWERTZ keyboard
input[KeyUp] = sf::Keyboard::W;
input[KeyLeft] = sf::Keyboard::A;
}
input[KeyDown] = sf::Keyboard::S;
input[KeyRight] = sf::Keyboard::D;
input[KeyFireUp] = sf::Keyboard::Up;
input[KeyFireDown] = sf::Keyboard::Down;
input[KeyFireLeft] = sf::Keyboard::Left;
input[KeyFireRight] = sf::Keyboard::Right;
input[KeyFire] = sf::Keyboard::RControl;
input[KeyFireSelect] = sf::Keyboard::Tab;
input[KeyTimeControl] = sf::Keyboard::RShift;
input[KeySpell] = sf::Keyboard::Space;
saveConfigurationToFile();
}
int WitchBlastGame::getAchievementsPercents()
{
int n = 0;
for (int i = 0; i < NB_ACHIEVEMENTS; i++)
if (achievementState[i] == AchievementDone) n++;
return (n * 100) / NB_ACHIEVEMENTS;
}
void WitchBlastGame::testAndAddMessageToQueue(EnumMessages type)
{
if (gameMessagesToSkip[type] == false)
{
if (messagesQueue.empty()) SoundManager::getInstance().playSound(SOUND_MESSAGE);
messageStruct msg = getMessage(type);
if (type == MsgInfoDivGift || type == MsgInfoDivIntervention)
{
std::stringstream ss;
ss << tools::getLabel(divinityLabel[player->getDivinity().divinity] + "_0");
ss << " ";
if (type == MsgInfoDivGift)
ss << tools::getLabel("divinity_gift_1");
else // (type == MsgInfoDivIntervention)
ss << tools::getLabel("divinity_intervention_1");
msg.message[1] = ss.str();
msg.icon = 2 + player->getDivinity().divinity;
}
messagesQueue.push(msg);
if (msg.messageType == MessageTypeTutorial)
{
gameMessagesToSkip[type] = true;
saveGameData();
}
}
}
void WitchBlastGame::addDivLevelMessageToQueue(std::string label)
{
if (label.compare("") == 0) return;
if (messagesQueue.empty()) SoundManager::getInstance().playSound(SOUND_MESSAGE);
messageStruct msg = getMessage(MsgInfoDivLevel);
std::stringstream ss;
ss << tools::getLabel(divinityLabel[player->getDivinity().divinity] + "_0");
ss << " ";
ss << tools::getLabel(label);
msg.message[1] = ss.str();
msg.icon = 2 + player->getDivinity().divinity;
messagesQueue.push(msg);
}
void WitchBlastGame::initEvents()
{
for (int i = 0; i < NB_EVENTS; i++)
worldEvent[i] = false;
}
void WitchBlastGame::proceedEvent(EnumWorldEvents event)
{
// achievements
if (event == EventGetCoin)
{
if (achievementState[Achievement100] == AchievementUndone && player->getGold() > 100)
registerAchievement(Achievement100);
}
else if (event == EventPietyMax)
{
if (achievementState[AchievementPietyMax] == AchievementUndone) registerAchievement(AchievementPietyMax);
}
else if (event == Event4Hits)
{
if (achievementState[Achievement4Hits] == AchievementUndone) registerAchievement(Achievement4Hits);
}
// message ?
if (worldEvent[event]) return;
worldEvent[event] = true;
testAndAddMessageToQueue(eventToMessage[event]);
}
void WitchBlastGame::renderPlayer(float x, float y,
bool equip[NUMBER_EQUIP_ITEMS], int shotType,
int frame, int spriteDy)
{
bool isMirroring = false;
sf::Sprite sprite;
if (equip[EQUIP_FAIRY_FIRE])
{
sprite.setPosition(x - 35, y - 25);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 144, 48, 60));
app->draw(sprite);
}
if (equip[EQUIP_FAIRY_ICE])
{
sprite.setPosition(x - 5, y - 25);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 216, 48, 60));
app->draw(sprite);
}
if (equip[EQUIP_FAIRY])
{
sprite.setPosition(x - 40, y);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 0, 48, 60));
app->draw(sprite);
}
if (equip[EQUIP_FAIRY_TARGET])
{
sprite.setPosition(x - 10, y);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 72, 48, 60));
app->draw(sprite);
}
if (equip[EQUIP_FAIRY_POISON])
{
sprite.setPosition(x + 20, y);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 288, 48, 60));
app->draw(sprite);
}
if (equip[EQUIP_FAIRY_STONE])
{
sprite.setPosition(x - 5, y + 15);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 360, 48, 60));
app->draw(sprite);
}
// slime
if (equip[EQUIP_PET_SLIME])
{
sprite.setPosition(x - 20, y + 24);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_SLIME));
sprite.setTextureRect(sf::IntRect( 64, 256, 64, 64));
app->draw(sprite);
}
sprite.setPosition(x, y);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
int width = 64;
int height = 96;
// body
if (isMirroring)
sprite.setTextureRect(sf::IntRect( frame * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( frame * width, spriteDy * height, width, height));
app->draw(sprite);
// boots
if (equip[EQUIP_BOOTS_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (21 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (21 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_LEATHER_BOOTS])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (9 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (9 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
if (equip[EQUIP_ROBE_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (12 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (12 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_MAGICIAN_ROBE])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (12 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (12 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
if (equip[EQUIP_GLOVES_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (24 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (24 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_DISPLACEMENT_GLOVES])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (21 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (21 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
if (equip[EQUIP_CRITICAL_ADVANCED])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (24 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (24 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
else if (equip[EQUIP_CRITICAL])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (18 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (18 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
if (equip[EQUIP_RAGE_AMULET])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (18 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (18 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
else if (equip[EQUIP_AMULET_RETALIATION])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_2));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (3 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (3 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
if (equip[EQUIP_BELT_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (27 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (27 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_LEATHER_BELT])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (15 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (15 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
// hat
if (equip[EQUIP_HAT_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (9 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (9 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_MAGICIAN_HAT])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (6 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (6 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
// staff
int frameDx = equip[EQUIP_MAHOGANY_STAFF] ? 6 : 3;
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (frameDx + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (frameDx + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
if (equip[EQUIP_BLOOD_SNAKE])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (27 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (27 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
if (equip[EQUIP_REAR_SHOT_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_2));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_REAR_SHOT])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
// shot type
if (shotType != ShotTypeStandard)
{
switch (shotType)
{
case ShotTypeIce:
sprite.setColor(sf::Color(100, 220, 255, 255));
break;
case ShotTypeStone:
sprite.setColor(sf::Color(120, 120, 150, 255));
break;
case ShotTypeLightning:
sprite.setColor(sf::Color(255, 255, 0, 255));
break;
case ShotTypeIllusion:
sprite.setColor(sf::Color(240, 180, 250, 255));
break;
case ShotTypeStandard:
sprite.setColor(sf::Color(255, 255, 255, 0));
break;
case ShotTypeFire:
sprite.setColor(sf::Color(255, 180, 0, 255));
break;
default:
break;
}
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (3 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (3 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
}
std::string WitchBlastGame::enemyToString(enemyTypeEnum enemyType)
{
std::string value = "unknown";
switch (enemyType)
{
case EnemyTypeBat_invocated:
case EnemyTypeBat:
value = "enemy_type_bat";
break;
case EnemyTypeBatSkeleton_invocated:
case EnemyTypeBatSkeleton:
value = "enemy_type_bat_skeleton";
break;
case EnemyTypeRat_invocated:
case EnemyTypeRat:
value = "enemy_type_rat";
break;
case EnemyTypeRatBlack:
value = "enemy_type_rat_black";
break;
case EnemyTypeRatHelmet_invocated:
case EnemyTypeRatHelmet:
value = "enemy_type_rat_helmet";
break;
case EnemyTypeRatBlackHelmet:
value = "enemy_type_rat_black_helmet";
break;
case EnemyTypeEvilFlower:
value = "enemy_type_evil_flower";
break;
case EnemyTypeEvilFlowerIce:
value = "enemy_type_evil_flower_ice";
break;
case EnemyTypeEvilFlowerFire:
value = "enemy_type_evil_flower_fire";
break;
case EnemyTypeSnake_invocated:
case EnemyTypeSnake:
value = "enemy_type_snake";
break;
case EnemyTypeSnakeBlood_invocated:
case EnemyTypeSnakeBlood:
value = "enemy_type_snake_blood";
break;
case EnemyTypeSlime_invocated:
case EnemyTypeSlime:
value = "enemy_type_slime";
break;
case EnemyTypeSlimeRed_invocated:
case EnemyTypeSlimeRed:
value = "enemy_type_slime_red";
break;
case EnemyTypeSlimeBlue_invocated:
case EnemyTypeSlimeBlue:
value = "enemy_type_slime_blue";
break;
case EnemyTypeSlimeViolet_invocated:
case EnemyTypeSlimeViolet:
value = "enemy_type_slime_violet";
break;
case EnemyTypeImpBlue:
value = "enemy_type_imp_blue";
break;
case EnemyTypeImpRed:
value = "enemy_type_imp_red";
break;
case EnemyTypePumpkin_invocated:
case EnemyTypePumpkin:
value = "enemy_type_pumpkin";
break;
case EnemyTypeWitch:
value = "enemy_type_witch";
break;
case EnemyTypeWitchRed:
value = "enemy_type_witch_red";
break;
case EnemyTypeCauldron:
value = "enemy_type_cauldron";
break;
case EnemyTypeCauldronElemental:
value = "enemy_type_cauldron_elemental";
break;
case EnemyTypeGhost:
value = "enemy_type_ghost";
break;
case EnemyTypeZombie_invocated:
case EnemyTypeZombie:
value = "enemy_type_zombie";
break;
case EnemyTypeZombieDark:
value = "enemy_type_zombie_dark";
break;
case EnemyTypeBogeyman:
value = "enemy_type_bogeyman";
break;
case EnemyTypeSausage_invocated:
case EnemyTypeSausage:
value = "enemy_type_sausage";
break;
// mini boss
case EnemyTypeBubble:
value = "enemy_type_bubble";
break;
case EnemyTypeBubbleIce:
value = "enemy_type_bubble_ice";
break;
case EnemyTypeBubbleGreater:
value = "enemy_type_bubble_greater";
break;
case EnemyTypeSlimeLarge:
value = "enemy_type_slime_large";
break;
case EnemyTypeSlimeBlueLarge:
value = "enemy_type_slime_blue_large";
break;
case EnemyTypeSlimeRedLarge:
value = "enemy_type_slime_red_large";
break;
case EnemyTypeSlimeVioletLarge:
value = "enemy_type_slime_violet_large";
break;
// boss
case EnemyTypeButcher:
value = "enemy_type_boss_butcher";
break;
case EnemyTypeSlimeBoss:
value = "enemy_type_boss_slime_giant";
break;
case EnemyTypeCyclops:
value = "enemy_type_boss_cyclops";
break;
case EnemyTypeRatKing:
value = "enemy_type_boss_rat_king";
break;
case EnemyTypeSpiderGiant:
value = "enemy_type_boss_spider_giant";
break;
case EnemyTypeFranckyHand:
case EnemyTypeFranckyHead:
case EnemyTypeFranckyFoot:
case EnemyTypeFrancky:
value = "enemy_type_francky";
break;
case EnemyTypeVampire:
case EnemyTypeVampireDead:
value = "enemy_type_vampire";
break;
// invocated
case EnemyTypeRatGreen:
value = "enemy_type_green_rat";
break;
case EnemyTypeRockFalling:
value = "enemy_type_rock_falling";
break;
case EnemyTypeRockMissile:
value = "enemy_type_rock_missile";
break;
case EnemyTypeSpiderEgg:
case EnemyTypeSpiderEgg_invocated:
value = "enemy_type_spider_egg";
break;
case EnemyTypeSpiderLittle:
case EnemyTypeSpiderLittle_invocated:
value = "enemy_type_spider_little";
break;
case EnemyTypeSpiderTarantula:
case EnemyTypeSpiderTarantula_invocated:
value = "enemy_type_spider_tarantula";
break;
case EnemyTypeSpiderWeb:
value = "enemy_type_spider_web";
break;
case EnemyTypeNone:
value = "enemy_type_himself";
break;
case EnemyTypeDestroyable:
value = "";
break;
case NB_ENEMY:
break;
}
return value;
}
std::string WitchBlastGame::sourceToString(sourceTypeEnum sourceType, enemyTypeEnum enemyType)
{
std::string value = "unknown";
switch (sourceType)
{
case SourceTypeBolt:
case SourceTypeMelee:
value = tools::getLabel(enemyToString(enemyType));
break;
case SourceTypeExplosion:
value = tools::getLabel("source_explosion");
break;
case SourceTypePoison:
value = tools::getLabel("source_poison");
}
return value;
}
std::string WitchBlastGame::equipToString(bool equip[NUMBER_EQUIP_ITEMS])
{
std::stringstream oss;
for (int i = 0; i < NUMBER_EQUIP_ITEMS; i++)
oss << (equip[i] ? 1 : 0);
return oss.str();
}
void WitchBlastGame::saveHiScores()
{
std::ofstream file(HISCORES_FILE.c_str(), std::ios::out | std::ios::trunc);
if (file)
{
// version (for compatibility check)
file << SAVE_VERSION << std::endl;
file << scores.size() << std::endl;
// tuto
for (unsigned int i = 0; i < scores.size() && i < SCORES_MAX; i++)
{
file << scores[i].name << " ";
file << scores[i].level << " ";
file << scores[i].score << " ";
file << scores[i].shotType << " ";
file << scores[i].divinity << " ";
file << scores[i].killedBy << " ";
file << scores[i].time << " ";
// player equip
for (int j = 0; j < NUMBER_EQUIP_ITEMS; j++)
file << scores[i].equip[j] << " ";
file << std::endl;
}
file << std::endl;
file.close();
}
else
{
std::cout << "[ERROR] Impossible to open hi-scores file.\n";
}
}
void WitchBlastGame::loadHiScores()
{
scores.clear();
std::ifstream file(HISCORES_FILE.c_str(), std::ios::in);
if (file)
{
// version
std::string v;
file >> v;
if (v != SAVE_VERSION)
{
file.close();
remove(SAVE_DATA_FILE.c_str());
return;
}
int nbScores;
file >> nbScores;
for (int i = 0; i < nbScores; i++)
{
StructScore score;
file >> score.name;
file >> score.level;
file >> score.score;
file >> score.shotType;
file >> score.divinity;
file >> score.killedBy;
file >> score.time;
for (int j = 0; j < NUMBER_EQUIP_ITEMS; j++)
file >> score.equip[j];
scores.push_back(score);
}
}
}
void WitchBlastGame::revealFloor()
{
currentFloor->reveal();
refreshMinimap();
}
void WitchBlastGame::activateKeyRoomEffect(bool withColorEffect)
{
dungeonEntity->activateKeyRoomEffect();
if (withColorEffect) makeColorEffect(X_GAME_COLOR_VIOLET, 0.35f);
SoundManager::getInstance().playSound(SOUND_FORCE_FIELD);
}
void WitchBlastGame::generateStar(sf::Color starColor, float xStar, float yStar)
{
SpriteEntity* spriteStar = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_STAR_2),
xStar, yStar);
spriteStar->setScale(0.8f, 0.8f);
spriteStar->setZ(1000.0f);
spriteStar->setSpin(-100 + rand()%200);
spriteStar->setVelocity(Vector2D(10 + rand()%40));
spriteStar->setWeight(-150);
spriteStar->setFading(true);
spriteStar->setAge(-0.8f);
spriteStar->setLifetime(0.1f + (rand() % 100) * 0.003f );
spriteStar->setColor(starColor);
spriteStar->setType(ENTITY_EFFECT);
}
void WitchBlastGame::registerAchievement(enumAchievementType achievement)
{
if (achievementState[achievement] == AchievementUndone)
{
achievementState[achievement] = AchievementPending;
achievementStruct ach;
ach.type = achievement;
ach.message = tools::getLabel(achievements[achievement].label);
ach.timer = ACHIEVEMENT_DELAY_MAX;
ach.counter = 0;
ach.hasStarted = false;
achievementsQueue.push(ach);
}
}
bool WitchBlastGame::isItemLocked(enumItemType item)
{
for (int i = 0; i < NB_ACHIEVEMENTS; i++)
{
if (achievementState[i] == AchievementUndone)
{
if (achievements[i].unlockType == UnlockItem)
if (achievements[i].unlock == (int)item) return true;
}
}
return false;
}
bool WitchBlastGame::isFunctionalityLocked(enumFunctionalityType func)
{
for (int i = 0; i < NB_ACHIEVEMENTS; i++)
{
if (achievementState[i] == AchievementUndone)
{
if (achievements[i].unlockType == UnlockFunctionality)
if (achievements[i].unlock == (int)func) return true;
}
}
return false;
}
void WitchBlastGame::renderDoors()
{
for (int i = 0; i < 4; i++) doorEntity[i]->renderDoors(app);
}
void WitchBlastGame::resetPresentItems()
{
for (int i = 0; i < NUMBER_EQUIP_ITEMS; i++) presentItems[i] = false;
}
bool WitchBlastGame::isPresentItem(int n)
{
if (n >= 0 && n < NUMBER_EQUIP_ITEMS) return presentItems[n];
else return false;
}
void WitchBlastGame::addPresentItem(int n)
{
if (n >= 0 && n < NUMBER_EQUIP_ITEMS) presentItems[n] = true;
}
bool WitchBlastGame::isPressing(inputKeyEnum k, bool oneShot)
{
return (actionKey[k].isPressed && (!oneShot || actionKey[k].isTriggered));
}
bool WitchBlastGame::getPressingState(inputKeyEnum k)
{
// arrows in menu
if (gameState != gameStatePlaying
|| player->isDead()
|| player->getPlayerStatus() == PlayerEntity::playerStatusVictorious)
{
if (k == KeyLeft && sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) return true;
if (k == KeyRight && sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) return true;
if (k == KeyUp && sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) return true;
if (k == KeyDown && sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) return true;
if (k == KeyFireDown && sf::Keyboard::isKeyPressed(sf::Keyboard::Return)) return true;
}
// keyboard
if (sf::Keyboard::isKeyPressed(input[k])) return true;
if (!sf::Joystick::isConnected(0)) return false;
// joystick
if (joystickInput[k].isButton)
{
// button
if (joystickInput[k].value >= 0)
if (sf::Joystick::isButtonPressed(0, joystickInput[k].value)) return true;
}
else
{
// axis
if (joystickInput[k].value < 0 && sf::Joystick::getAxisPosition(0, joystickInput[k].axis) < -40) return true;
else if (joystickInput[k].value > 0 && sf::Joystick::getAxisPosition(0, joystickInput[k].axis) > 40) return true;
}
return false;
}
void WitchBlastGame::updateActionKeys()
{
for (unsigned int i = 0; i < NumberKeys; i++)
{
bool oldState = actionKey[i].isPressed;
actionKey[i].isPressed = getPressingState((inputKeyEnum)i);
actionKey[i].isTriggered = actionKey[i].isPressed && !oldState;
}
}
void WitchBlastGame::sendScoreToServer()
{
if (sendScoreThread.joinable()) sendScoreThread.join();
sendScoreThread = std::thread(&WitchBlastGame::sendScoreToServerThread, this);
receiveScoreFromServer();
}
void WitchBlastGame::sendScoreToServerThread()
{
#ifdef ONLINE_MODE
sendScore(lastScore.score,
lastScore.level,
lastScore.name,
equipToString(lastScore.equip),
lastScore.shotType,
lastScore.divinity,
lastScore.killedBy,
lastScore.time,
SCORE_VERSION);
#endif
}
void WitchBlastGame::receiveScoreFromServer()
{
#ifdef ONLINE_MODE
scoreState = ScoreLoading;
if (receiveScoreThread.joinable()) receiveScoreThread.join();
receiveScoreThread = std::thread(&WitchBlastGame::receiveScoreFromServerThread, this);
#endif
}
void WitchBlastGame::receiveScoreFromServerThread()
{
if (sendScoreThread.joinable()) sendScoreThread.join();
loadHiScoresOnline(false);
scoreState = ScoreLoadingDay;
loadHiScoresOnline(true);
scoreState = ScoreOK;
}
void WitchBlastGame::loadHiScoresOnline(bool fromDayOnly)
{
#ifdef ONLINE_MODE
std::vector <StructScore> scoresTemp;
std::vector<std::string> receivedScores = receiveScores(fromDayOnly);
int nbParameters = 8;
if (receivedScores.size() > 0
&& receivedScores.size() % nbParameters == 0
&& receivedScores.size() / nbParameters <= 10)
{
int nbScores = receivedScores.size() / nbParameters;
for (int i = 0; i < nbScores; i++)
{
StructScore score;
std::istringstream scoreStr(receivedScores[i * nbParameters]);
scoreStr >> score.score;
score.name = receivedScores[i * nbParameters + 1];
std::istringstream levelStr(receivedScores[i * nbParameters + 2]);
levelStr >> score.level;
for (int j = 0; j < NUMBER_EQUIP_ITEMS; j++)
{
score.equip[j] = (receivedScores[i * nbParameters + 3])[j] == '1';
}
std::istringstream shotStr(receivedScores[i * nbParameters + 4]);
shotStr >> score.shotType;
std::istringstream divStr(receivedScores[i * nbParameters + 5]);
divStr >> score.divinity;
std::istringstream killStr(receivedScores[i * nbParameters + 6]);
killStr >> score.killedBy;
std::istringstream timeStr(receivedScores[i * nbParameters + 7]);
timeStr >> score.time;
scoresTemp.push_back(score);
}
if (fromDayOnly)
{
scoresOnlineDay.clear();
scoresOnlineDay = scoresTemp;
}
else
{
scoresOnline.clear();
scoresOnline = scoresTemp;
}
}
#endif
}
void WitchBlastGame::checkDestroyableObjects()
{
for (int i = 0; i < MAP_WIDTH; i++)
for (int j = 0; j < MAP_HEIGHT; j++)
{
if (currentMap->getObjectTile(i, j) >= MAPOBJ_BARREL/* && currentMap->getObjectTile(i, j) < MAPOBJ_BARREL_EXPL + 3*/)
{
new ObstacleEntity(i * TILE_WIDTH + TILE_WIDTH / 2, j * TILE_HEIGHT + TILE_HEIGHT / 2, currentMap->getObjectTile(i, j));
}
}
}
void WitchBlastGame::randomizePotionMap()
{
potionMap.clear();
std::vector<int> potionEffect;
for (int i = 0; i < NUMBER_UNIDENTIFIED; i++) potionEffect.push_back(i);
for (int i = 0; i < NUMBER_UNIDENTIFIED; i++)
{
int r = rand() % potionEffect.size();
addPotionToMap((enumItemType)(ItemPotion01 + i), (enumItemType)(ItemPotionHealth + potionEffect[r]), false);
potionEffect.erase(potionEffect.begin() + r);
}
}
void WitchBlastGame::acquireAlchemyBook()
{
for (int i = 0; i < NUMBER_UNIDENTIFIED; i++)
{
if (rand() % 2 > 0)
{
enumItemType potion = (enumItemType)(ItemPotion01 + i);
if (!potionEffectKnown(potion)) setPotionToKnown(potion);
}
}
// drop potion
ItemEntity* potionItem = new ItemEntity( (enumItemType)(ItemPotion01 + rand() % NUMBER_UNIDENTIFIED), player->getX(), player->getY());
potionItem->setVelocity(Vector2D(100.0f + rand()% 250));
potionItem->setViscosity(0.96f);
potionItem->startsJumping();
}
void WitchBlastGame::addPotionToMap(enumItemType source, enumItemType effect, bool known)
{
potionMap[source] = structPotionMap { effect, known};
potionMap[effect] = structPotionMap { source, known};
}
enumItemType WitchBlastGame::getPotion(enumItemType source)
{
return potionMap[source].effect;
}
bool WitchBlastGame::potionEffectKnown(enumItemType source)
{
return potionMap[source].known;
}
void WitchBlastGame::setPotionToKnown(enumItemType source)
{
potionMap[source].known = true;
potionMap[potionMap[source].effect].known = true;
// message
if (messagesQueue.empty()) SoundManager::getInstance().playSound(SOUND_MESSAGE);
messageStruct msg = getMessage(MsgInfoPotionId);
std::stringstream ss;
ss << msg.message[1];
ss << " ";
ss << tools::getLabel(items[getPotion(source)].name);
msg.message[1] = ss.str();
messagesQueue.push(msg);
}
void WitchBlastGame::forgetPotions()
{
for (int i = ItemPotion01; i < FirstEquipItem; i++)
{
potionMap[(enumItemType)i].known = false;
potionMap[potionMap[(enumItemType)i].effect].known = false;
}
}
void WitchBlastGame::forget()
{
// forget map
if (!player->isEquiped(EQUIP_FLOOR_MAP))
{
currentFloor->forget(floorX, floorY);
refreshMinimap();
}
// forget potions
if (!player->isEquiped(EQUIP_BOOK_ALCHEMY))
{
forgetPotions();
}
}
WitchBlastGame &game()
{
return *gameptr;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Jan 30, 4:24 PM (5 d, 11 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55435
Default Alt Text
(225 KB)
Attached To
Mode
R78 witchblast
Attached
Detach File
Event Timeline
Log In to Comment