Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F133868
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
130 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/media/doors.png b/media/doors.png
index 31496f2..d80ca43 100644
Binary files a/media/doors.png and b/media/doors.png differ
diff --git a/src/DoorEntity.h b/src/DoorEntity.h
index ac72f62..52a3c7a 100644
--- a/src/DoorEntity.h
+++ b/src/DoorEntity.h
@@ -1,36 +1,37 @@
#ifndef DOORENTITY_H
#define DOORENTITY_H
#include "sfml_game/SpriteEntity.h"
enum doorEnum
{
DoorStandard_0,
DoorStandard_1,
DoorStandard_2,
DoorStandard_3,
DoorStandard_4,
DoorBoss,
- DoorChallenge
+ DoorChallenge,
+ DoorExit
};
class DoorEntity : public SpriteEntity
{
public:
DoorEntity(int direction);
virtual void animate(float delay);
void render(sf::RenderTarget* app);
void renderDoors(sf::RenderTarget* app);
void setOpen(bool open);
void setDoorType(doorEnum doorType);
void closeDoor();
void openDoor();
private:
int direction;
bool isOpen;
float timer;
doorEnum doorType;
};
#endif // DOORENTITY_H
diff --git a/src/DungeonMap.cpp b/src/DungeonMap.cpp
index 6438083..6f9a7fa 100644
--- a/src/DungeonMap.cpp
+++ b/src/DungeonMap.cpp
@@ -1,1633 +1,1633 @@
#include "DungeonMap.h"
#include "GameFloor.h"
#include "ItemEntity.h"
#include "ChestEntity.h"
#include "sfml_game/ImageManager.h"
#include <cstdlib>
#include <stdio.h>
#include <iostream>
#include "WitchBlastGame.h"
DungeonMap::DungeonMap(int width, int height) : GameMap(width, height)
{
}
DungeonMap::DungeonMap(GameFloor* gameFloor, int x, int y) : GameMap(MAP_WIDTH, MAP_HEIGHT)
{
this->gameFloor = gameFloor;
this->x = x;
this->y = y;
cleared = false;
visited = false;
known = false;
for (int i = 0; i < NB_RANDOM_TILES_IN_ROOM; i++)
{
randomTileElements[i].type = -1;
randomTileElements[i].x = 0;
randomTileElements[i].y = 0;
randomTileElements[i].rotation = 0;
}
}
DungeonMap::~DungeonMap()
{
}
bool DungeonMap::isVisited()
{
return visited;
}
void DungeonMap::setVisited(bool b)
{
visited = b;
}
bool DungeonMap::isKnown()
{
return known;
}
void DungeonMap::setKnown(bool b)
{
known = b;
}
bool DungeonMap::isCleared()
{
return cleared;
}
void DungeonMap::setCleared(bool b)
{
cleared = b;
}
roomTypeEnum DungeonMap::getRoomType()
{
return roomType;
}
void DungeonMap::setRoomType(roomTypeEnum roomType)
{
this->roomType = roomType;
}
int DungeonMap::getObjectTile(int x, int y)
{
return objectsMap[x][y];
}
logicalMapStateEnum DungeonMap::getLogicalTile(int x, int y)
{
return logicalMap[x][y];
}
void DungeonMap::setObjectTile(int x, int y, int n)
{
objectsMap[x][y] = n;
}
void DungeonMap::setLogicalTile(int x, int y, logicalMapStateEnum state)
{
logicalMap[x][y] = state;
}
int DungeonMap::getFloorOffset()
{
return floorOffset;
}
int DungeonMap::getWallType()
{
return wallType;
}
void DungeonMap::setFloorOffset(int n)
{
floorOffset = n;
}
void DungeonMap::setWallType(int n)
{
wallType = n;
}
int DungeonMap::getDoorType(int direction)
{
if (roomType == roomTypeBoss) return DoorBoss;
if (roomType == roomTypeChallenge) return DoorChallenge;
int doorStypeStandard = DoorStandard_0 + (game().getLevel() - 1) % 5;
if (direction == 4)
{
if (hasNeighbourLeft())
{
if (getNeighbourLeft() == roomTypeBoss)
return DoorBoss;
else if (getNeighbourLeft() == roomTypeChallenge)
return DoorChallenge;
else
return doorStypeStandard;
}
else return -1;
}
if (direction == 6)
{
if (hasNeighbourRight())
{
if (getNeighbourRight() == roomTypeBoss)
return DoorBoss;
else if (getNeighbourRight() == roomTypeChallenge)
return DoorChallenge;
else
return doorStypeStandard;
}
else return -1;
}
if (direction == 8)
{
if (hasNeighbourUp())
{
if (getNeighbourUp() == roomTypeBoss)
return DoorBoss;
else if (getNeighbourUp() == roomTypeChallenge)
return DoorChallenge;
else
return doorStypeStandard;
}
else if (roomType == roomTypeExit)
- return doorStypeStandard;
+ return DoorExit;
else return -1;
}
if (direction == 2)
{
if (hasNeighbourDown())
{
if (getNeighbourDown() == roomTypeBoss)
return DoorBoss;
else if (getNeighbourDown() == roomTypeChallenge)
return DoorChallenge;
else
return doorStypeStandard;
}
else if (game().getLevel() > 1 && roomType == roomTypeStarting)
return doorStypeStandard;
else return -1;
}
return -1;
}
std::list<DungeonMap::itemListElement> DungeonMap::getItemList()
{
return (itemList);
}
std::list<DungeonMap::chestListElement> DungeonMap::getChestList()
{
return (chestList);
}
std::list<DungeonMap::spriteListElement> DungeonMap::getSpriteList()
{
return (spriteList);
}
DungeonMap::RandomTileElement DungeonMap::getRandomTileElement(int n)
{
if (n < 0 || n >= NB_RANDOM_TILES_IN_ROOM) return RandomTileElement { -1, 0, 0, 0};
return randomTileElements[n];
}
void DungeonMap::setRandomTileElement (int n, RandomTileElement rt)
{
if (n < 0 || n >= NB_RANDOM_TILES_IN_ROOM) return;
randomTileElements[n] = rt;
hasChanged = true;
}
void DungeonMap::displayToConsole()
{
for (int j=0; j < MAP_HEIGHT; j++)
{
for (int i=0; i < MAP_WIDTH; i++)
{
printf("%d", map[i][j]);
}
printf("\n");
}
printf("\n");
}
bool DungeonMap::isDownBlocking(int x, int y)
{
if (!inMap(x, y)) return false;
return (logicalMap[x][y] != LogicalFloor);
}
bool DungeonMap::isUpBlocking(int x, int y)
{
if (!inMap(x, y)) return false;
return (logicalMap[x][y] != LogicalFloor);
}
bool DungeonMap::isLeftBlocking(int x, int y)
{
if (!inMap(x, y)) return false;
return (logicalMap[x][y] != LogicalFloor);
}
bool DungeonMap::isRightBlocking(int x, int y)
{
if (!inMap(x, y)) return false;
return (logicalMap[x][y] != LogicalFloor);
}
bool DungeonMap::isWalkable(int x, int y)
{
if (!inMap(x, y)) return true;
if (roomType == roomTypeKey && !cleared)
{
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
if (x >= x0 - 1 && x <= x0 +1 && y >= y0 - 1 && y <= y0 + 1)
return false;
}
return (logicalMap[x][y] == LogicalFloor);
}
bool DungeonMap::isFlyable(int x, int y)
{
if (x < 0) return true;
if (x > MAP_WIDTH - 1) return true;
if (y < 0) return true;
if (y > MAP_HEIGHT - 1) return true;
return (logicalMap[x][y] != LogicalWall);
}
bool DungeonMap::isShootable(int x, int y)
{
if (!inMap(x, y)) return true;
return (logicalMap[x][y] != LogicalWall && logicalMap[x][y] != LogicalObstacle);
}
bool DungeonMap::containsHealth()
{
ItemList::iterator it;
for (it = itemList.begin (); it != itemList.end ();)
{
itemListElement ilm = *it;
it++;
if (ilm.type >= ItemHealthVerySmall && ilm.type <= ItemHealthVerySmallPoison)
return true;
}
return false;
}
void DungeonMap::randomize(int n)
{
int i, j;
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
initRoom();
// bonus
if (n == 5)
{
roomType = roomTypeBonus;
}
// others
else if (n > 0)
{
int r = rand() % 4;
if (r == 0) // corner blocks
{
map[1][1] = 4;
map[1][MAP_HEIGHT -2] = 4;
map[MAP_WIDTH - 2][1] = 4;
map[MAP_WIDTH - 2][MAP_HEIGHT -2] = 4;
}
else if (r == 1) // bloc in the middle
{
for (i = x0-1; i <= x0+1; i++)
for (j = y0-1; j <= y0+1; j++)
map[i][j] = 4;
}
else if (r == 2) // checker
{
for (i = 2; i < MAP_WIDTH - 2; i = i + 2)
for (j = 2; j < MAP_HEIGHT - 2; j = j + 2)
map[i][j] = 4;
}
cleared = false;
roomType = (roomTypeEnum)(rand() % 3);
}
else
{
cleared = true;
}
}
int DungeonMap::hasNeighbourLeft()
{
if (x > 0 && gameFloor->getRoom(x-1, y) > 0)
{
if (gameFloor->getRoom(x-1, y) == roomTypeBoss) return 2;
else return 1;
}
return 0;
}
int DungeonMap::hasNeighbourRight()
{
if (x < MAP_WIDTH -1 && gameFloor->getRoom(x+1, y) > 0)
{
if (gameFloor->getRoom(x+1, y) == roomTypeBoss) return 2;
else return 1;
}
return 0;
}
int DungeonMap::hasNeighbourUp()
{
if (y > 0 && gameFloor->getRoom(x, y-1) > 0)
{
if (gameFloor->getRoom(x, y-1) == roomTypeBoss) return 2;
else return 1;
}
return 0;
}
int DungeonMap::hasNeighbourDown()
{
if (y < MAP_HEIGHT -1 && gameFloor->getRoom(x, y+1) > 0)
{
if (gameFloor->getRoom(x, y+1) == roomTypeBoss) return 2;
else return 1;
}
return 0;
}
roomTypeEnum DungeonMap::getNeighbourLeft()
{
if (x > 0) return gameFloor->getRoom(x - 1, y);
else return roomTypeNULL;
}
roomTypeEnum DungeonMap::getNeighbourRight()
{
if (x < MAP_WIDTH - 1) return gameFloor->getRoom(x + 1, y);
else return roomTypeNULL;
}
roomTypeEnum DungeonMap::getNeighbourUp()
{
if (y > 0) return gameFloor->getRoom(x, y - 1);
else return roomTypeNULL;
}
roomTypeEnum DungeonMap::getNeighbourDown()
{
if (y < MAP_HEIGHT - 1) return gameFloor->getRoom(x, y + 1);
else return roomTypeNULL;
}
int DungeonMap::getDivinity(int x, int y)
{
if (x <= 0 || (x >= MAP_WIDTH - 1) || y <= 0 || (y >= MAP_HEIGHT - 1)) return -1;
if (map[x][y] >= MAP_TEMPLE && map[x][y] < MAP_TEMPLE + NB_DIVINITY)
return (map[x][y] - MAP_TEMPLE);
else
return -1;
}
void DungeonMap::initRoom()
{
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
int i, j;
// style
floorOffset = ((game().getLevel() - 1) % 8) * 24 ;
wallType = ((game().getLevel() - 1) % 2) ;
int wallOffset = wallType * 24;
// outer walls
map[0][0] = wallOffset + MAP_WALL_7 + rand() % 2;
for ( i = 1 ; i < width -1 ; i++)
{
if (i == width / 2)
{
map[i][0] = wallOffset + MAP_WALL_8 + rand() % 2;
map[i][height - 1] = wallOffset + MAP_WALL_8 + rand() % 2;
}
else if (i < width / 2)
{
map[i][0] = wallOffset + MAP_WALL_87 + rand() % 8;
map[i][height - 1] = wallOffset + MAP_WALL_87 + rand() % 8;
}
else
{
map[i][0] = wallOffset + MAP_WALL_87 + rand() % 8;
map[i][height - 1] = wallOffset + MAP_WALL_87 + rand() % 8;
}
}
map[width - 1][0] = wallOffset + MAP_WALL_7 + rand() % 2;
for ( int i = 1 ; i < height -1 ; i++)
{
if (i == height / 2)
{
map[0][i] = wallOffset + MAP_WALL_8 + rand() % 2;
map[width - 1][i] = wallOffset + MAP_WALL_8 + rand() % 2;
}
else if (i < height / 2)
{
map[0][i] = wallOffset + MAP_WALL_87 + rand() % 8;
map[width - 1][i] = wallOffset + MAP_WALL_87 + rand() % 8;
}
else
{
map[0][i] = wallOffset + MAP_WALL_87 + rand() % 8;
map[width - 1][i] = wallOffset + MAP_WALL_87 + rand() % 8;
}
}
map[0][height - 1] = wallOffset + MAP_WALL_7 + rand() % 2;
map[width - 1][height - 1] = wallOffset + MAP_WALL_7 + rand() % 2;
// floor
for ( j = 1 ; j < height - 1 ; j++)
{
for ( i = 1 ; i < width - 1 ; i++)
{
map[i][j] = floorOffset + rand()%(MAP_NORMAL_FLOOR);
while (map[i][j] == map[i - 1][j] || map[i][j] == map[i][j - 1] || map[i][j] == map[i - 1][j - 1] || map[i][j] == map[i + 1][j - 1])
map[i][j] = floorOffset + rand()%(MAP_NORMAL_FLOOR);
}
}
// objects
for ( j = 0 ; j < height; j++)
{
for ( i = 0 ; i < width; i++)
{
objectsMap[i][j] = 0;
if (i == 0 || j == 0 || i == width - 1 || j == height - 1)
logicalMap[i][j] = LogicalWall;
else
logicalMap[i][j] = LogicalFloor;
}
}
// alternative floor
for (i = 0; i < 8; i++)
{
if (rand() % 2 > 0)
{
map[1 + rand() % (MAP_WIDTH - 2)][1 + rand() % (MAP_HEIGHT - 2)] = floorOffset + 16 + i;
}
}
// alternative walls
for (i = 0; i < 8; i++)
{
if (rand() % 2 > 0)
{
int xTile = 0;
int yTile = 0;
int horizontal = rand() % 2;
if (horizontal == 0)
{
yTile = rand() % 2 == 0 ? 0 : MAP_HEIGHT - 1;
xTile = 1 + rand() % 12;
if (xTile > 6) xTile++;
}
else
{
xTile = rand() % 2 == 0 ? 0 : MAP_WIDTH - 1;
yTile = 1 + rand() % 6;
if (yTile > 3) yTile++;
}
map[xTile][yTile] = i + wallOffset + MAP_WALL_87 + 8;
}
}
/*if (hasNeighbourUp() && rand() % 3 == 0)
{
map[x0 - 2][0] = 9 + wallOffset + MAP_WALL_ALTERN;
map[x0 + 2][0] = 9 + wallOffset + MAP_WALL_ALTERN;
}
if (hasNeighbourDown() && rand() % 3 == 0)
{
map[x0 - 2][MAP_HEIGHT - 1] = 9 + wallOffset + MAP_WALL_ALTERN;
map[x0 + 2][MAP_HEIGHT - 1] = 9 + wallOffset + MAP_WALL_ALTERN;
}
if (hasNeighbourLeft() && rand() % 3 == 0)
{
map[0][y0 - 2] = 9 + wallOffset + MAP_WALL_ALTERN;
map[0][y0 + 2] = 9 + wallOffset + MAP_WALL_ALTERN;
}
if (hasNeighbourRight() && rand() % 3 == 0)
{
map[MAP_WIDTH - 1][y0 - 2] = 9 + wallOffset + MAP_WALL_ALTERN;
map[MAP_WIDTH - 1][y0 + 2] = 9 + wallOffset + MAP_WALL_ALTERN;
}*/
// doors ?
if (gameFloor != NULL)
{
if (x > 0 && gameFloor->getRoom(x - 1, y) > 0)
{
map[0][MAP_HEIGHT / 2] = floorOffset;
map[0][MAP_HEIGHT / 2 - 1] = floorOffset;
map[0][MAP_HEIGHT / 2 + 1] = floorOffset;
openDoor(0, y0);
}
if (x < MAP_WIDTH - 1 && gameFloor->getRoom(x + 1, y) > 0)
{
map[MAP_WIDTH - 1][MAP_HEIGHT / 2] = floorOffset;
map[MAP_WIDTH - 1][MAP_HEIGHT / 2 - 1] = floorOffset;
map[MAP_WIDTH - 1][MAP_HEIGHT / 2 + 1] = floorOffset;
openDoor(MAP_WIDTH - 1, y0);
}
if (y > 0 && gameFloor->getRoom(x, y - 1) > 0)
{
map[MAP_WIDTH / 2][0] = floorOffset;
map[MAP_WIDTH / 2 - 1][0] = floorOffset;
map[MAP_WIDTH / 2 + 1][0] = floorOffset;
openDoor(x0, 0);
}
if (y < MAP_HEIGHT -1 && gameFloor->getRoom(x, y + 1) > 0)
{
map[MAP_WIDTH / 2][MAP_HEIGHT - 1] = floorOffset;
map[MAP_WIDTH / 2 - 1][MAP_HEIGHT - 1] = floorOffset;
map[MAP_WIDTH / 2 + 1][MAP_HEIGHT - 1] = floorOffset;
openDoor(x0, MAP_HEIGHT -1);
}
}
}
void DungeonMap::openDoor(int x, int y)
{
objectsMap[x][y] = MAPOBJ_DOOR_OPEN;
logicalMap[x][y] = LogicalFloor;
}
void DungeonMap::closeDoor(int x, int y)
{
objectsMap[x][y] = MAPOBJ_DOOR_CLOSED;
logicalMap[x][y] = LogicalWall;
}
bool DungeonMap::isDoor(int x, int y)
{
return objectsMap[x][y] == MAPOBJ_DOOR_OPEN || objectsMap[x][y] == MAPOBJ_DOOR_CLOSED;
}
void DungeonMap::makePatternTile(int x, int y)
{
if (map[x][y] < 24 * 8 && (map[x][y] % 24) < 8) map[x][y] += 8;
else map[x][y] = (game().getLevel() - 1) * 24 + 8;
}
void DungeonMap::initPattern(patternEnum n)
{
int i, j;
if (n == PatternSmallChecker)
{
for ( i = 2 ; i < width - 2 ; i++)
for ( j = 2 ; j < height - 2 ; j++)
{
if ((i + j) % 2 == 1) makePatternTile(i, j);
}
}
if (n == PatternBigChecker)
{
for ( i = 1 ; i < width - 1 ; i++)
for ( j = 1 ; j < height - 1 ; j++)
{
if ((i + j) % 2 == 1) makePatternTile(i, j);
}
}
if (n == PatternBorder)
{
for ( i = 1 ; i < width - 1 ; i++)
for ( j = 1 ; j < height - 1 ; j++)
{
if (i == 1 || j == 1 || i == width - 2 || j == height - 2)
makePatternTile(i, j);
}
}
if (n == PatternBigCircle)
{
for ( i = 2 ; i < width - 2 ; i++)
for ( j = 2 ; j < height - 2 ; j++)
{
if (i == 2 || j == 2 || i == width - 3 || j == height - 3)
makePatternTile(i, j);
}
}
if (n == PatternSmallCircle || n == PatternSmallStar)
{
for ( i = 5 ; i < 10 ; i++)
for ( j = 2 ; j < height - 2 ; j++)
{
if (i == 5 || i == 9 || j == 2 || j == height - 3)
makePatternTile(i, j);
}
}
if (n == PatternSmallStar)
{
makePatternTile(7, 1);
makePatternTile(7, height - 2);
makePatternTile(4, 4);
makePatternTile(10, 4);
}
if (n == PatternSmallDisc)
{
for ( i = 5 ; i < 10 ; i++)
for ( j = 2 ; j < height - 2 ; j++)
{
makePatternTile(i, j);
}
}
}
void DungeonMap::generateInselRoom()
{
for (int i = 1; i < MAP_WIDTH - 1; i++)
for (int j = 1; j < MAP_HEIGHT - 1; j++)
{
if (i != MAP_WIDTH / 2 && j != MAP_HEIGHT / 2
&& !(i == MAP_WIDTH / 2 - 1 && j == MAP_HEIGHT / 2 - 1)
&& !(i == MAP_WIDTH / 2 - 1 && j == MAP_HEIGHT / 2 + 1)
&& !(i == MAP_WIDTH / 2 + 1 && j == MAP_HEIGHT / 2 - 1)
&& !(i == MAP_WIDTH / 2 + 1 && j == MAP_HEIGHT / 2 + 1)
)
addHole(i, j);
}
objectsMap[MAP_WIDTH / 2 - 2][MAP_HEIGHT / 2 - 1] = MAPOBJ_WALL_SPECIAL;
objectsMap[MAP_WIDTH / 2 - 1][MAP_HEIGHT / 2 - 2] = MAPOBJ_WALL_SPECIAL;
logicalMap[MAP_WIDTH / 2 - 2][MAP_HEIGHT / 2 - 1] = LogicalObstacle;
logicalMap[MAP_WIDTH / 2 - 1][MAP_HEIGHT / 2 - 2] = LogicalObstacle;
objectsMap[MAP_WIDTH / 2 + 2][MAP_HEIGHT / 2 - 1] = MAPOBJ_WALL_SPECIAL + 1;
objectsMap[MAP_WIDTH / 2 + 1][MAP_HEIGHT / 2 - 2] = MAPOBJ_WALL_SPECIAL + 1;
logicalMap[MAP_WIDTH / 2 + 2][MAP_HEIGHT / 2 - 1] = LogicalObstacle;
logicalMap[MAP_WIDTH / 2 + 1][MAP_HEIGHT / 2 - 2] = LogicalObstacle;
objectsMap[MAP_WIDTH / 2 - 2][MAP_HEIGHT / 2 + 1] = MAPOBJ_WALL_SPECIAL + 2;
objectsMap[MAP_WIDTH / 2 - 1][MAP_HEIGHT / 2 + 2] = MAPOBJ_WALL_SPECIAL + 2;
logicalMap[MAP_WIDTH / 2 - 2][MAP_HEIGHT / 2 + 1] = LogicalObstacle;
logicalMap[MAP_WIDTH / 2 - 1][MAP_HEIGHT / 2 + 2] = LogicalObstacle;
objectsMap[MAP_WIDTH / 2 + 2][MAP_HEIGHT / 2 + 1] = MAPOBJ_WALL_SPECIAL + 3;
objectsMap[MAP_WIDTH / 2 + 1][MAP_HEIGHT / 2 + 2] = MAPOBJ_WALL_SPECIAL + 3;
logicalMap[MAP_WIDTH / 2 + 2][MAP_HEIGHT / 2 + 1] = LogicalObstacle;
logicalMap[MAP_WIDTH / 2 + 1][MAP_HEIGHT / 2 + 2] = LogicalObstacle;
if (!hasNeighbourUp())
addHole(MAP_WIDTH / 2, 1);
if (!hasNeighbourDown())
addHole(MAP_WIDTH / 2, MAP_HEIGHT - 2);
if (!hasNeighbourLeft())
for (int i = 0; i < 4; i++)
{
addHole(1 + i, MAP_HEIGHT / 2);
addHole(1 + i, MAP_HEIGHT / 2 + 1);
}
if (!hasNeighbourRight())
for (int i = 0; i < 4; i++)
{
addHole(MAP_WIDTH - 2 - i, MAP_HEIGHT / 2);
addHole(MAP_WIDTH - 2 - i, MAP_HEIGHT / 2 + 1);
}
addHole(MAP_WIDTH / 2 - 1 , MAP_HEIGHT - 2);
addHole(MAP_WIDTH / 2 + 1 , MAP_HEIGHT - 2);
addHole(MAP_WIDTH / 2 - 2 , MAP_HEIGHT - 3);
addHole(MAP_WIDTH / 2 + 2 , MAP_HEIGHT - 3);
if (rand() % 2 == 0) makePatternTile(MAP_WIDTH / 2, MAP_HEIGHT / 2);
}
Vector2D DungeonMap::generateBonusRoom()
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
if (game().getLevel() == 1 || rand() % 3 > 0)
{
if (rand() % 3 == 0)
{
if (rand() % 2 == 0) initPattern(PatternSmallDisc);
else initPattern(PatternSmallStar);
}
objectsMap[x0 - 1][y0 - 1] = MAPOBJ_WALL_SPECIAL;
objectsMap[x0 - 1][y0 + 1] = MAPOBJ_WALL_SPECIAL + 2;
objectsMap[x0 + 1][y0 - 1] = MAPOBJ_WALL_SPECIAL + 1;
objectsMap[x0 + 1][y0 + 1] = MAPOBJ_WALL_SPECIAL + 3;
logicalMap[x0 - 1][y0 - 1] = LogicalObstacle;
logicalMap[x0 - 1][y0 + 1] = LogicalObstacle;
logicalMap[x0 + 1][y0 - 1] = LogicalObstacle;
logicalMap[x0 + 1][y0 + 1] = LogicalObstacle;
}
else
{
generateInselRoom();
}
generateRandomTiles();
return (Vector2D(x0 * TILE_WIDTH + TILE_WIDTH / 2, y0 * TILE_HEIGHT + TILE_HEIGHT / 2));
}
void DungeonMap::generateTemple(int x, int y, enumDivinityType type)
{
map[x][y] = MAP_TEMPLE + (int)type;
addHole(x - 1, y - 2);
addHole(x - 1, y - 1);
addHole(x - 1, y);
addHole(x + 1, y - 2);
addHole(x + 1, y - 1);
addHole(x + 1, y );
objectsMap[x][y - 2] = MAPOBJ_TEMPLE_WALL + (int)type;
objectsMap[x][y - 1] = MAPOBJ_TEMPLE_WALL + 10 + (int)type;
logicalMap[x][y - 2] = LogicalObstacle;
logicalMap[x][y - 1] = LogicalObstacle;
}
void DungeonMap::generateTempleRoom()
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = 1 + MAP_HEIGHT / 2;
if (rand() % 3 == 0)
{
if (rand() % 2 == 0) initPattern(PatternSmallDisc);
else initPattern(PatternSmallStar);
}
int d0, d1, d2;
d0 = rand() % NB_DIVINITY;
d1 = d0;
while (d0 == d1) d1 = rand() % NB_DIVINITY;
if (rand() % 2 == 0)
{
// three temple
d2 = d0;
while (d0 == d2 || d1 == d2) d2 = rand() % NB_DIVINITY;
generateTemple(x0 - 2, y0, (enumDivinityType)d0);
generateTemple(x0 + 2, y0, (enumDivinityType)d1);
generateTemple(x0, y0, (enumDivinityType)d2);
}
else
{
// two temples
generateTemple(x0 - 1, y0, (enumDivinityType)d0);
generateTemple(x0 + 1, y0, (enumDivinityType)d1);
}
generateRandomTiles();
}
void DungeonMap::generateCarpet(int x0, int y0, int w, int h, int n)
{
int xf = x0 + w - 1;
int yf = y0 + h - 1;
map[x0][y0] = n;
map[x0][yf] = n + 6;
map[xf][y0] = n + 2;
map[xf][yf] = n + 8;
int i, j;
for (i = x0 + 1; i <= xf - 1; i++)
{
map[i][y0] = n + 1;
map[i][yf] = n + 7;
for (j = y0 + 1; j <= yf - 1; j++)
map[i][j] = n + 4;
}
for (j = y0 + 1; j <= yf - 1; j++)
{
map[x0][j] = n + 3;
map[xf][j] = n + 5;
}
}
void DungeonMap::generateTable(int x0, int y0, int w, int h, int n)
{
int xf = x0 + w - 1;
int yf = y0 + h - 1;
objectsMap[x0][y0] = n;
objectsMap[x0][yf] = n + 6;
objectsMap[xf][y0] = n + 2;
objectsMap[xf][yf] = n + 8;
int i, j;
for (i = x0 + 1; i <= xf - 1; i++)
{
objectsMap[i][y0] = n + 1;
objectsMap[i][yf] = n + 7;
for (j = y0 + 1; j <= yf - 1; j++)
objectsMap[i][j] = n + 4;
}
for (j = y0 + 1; j <= yf - 1; j++)
{
objectsMap[x0][j] = n + 3;
objectsMap[xf][j] = n + 5;
}
for (i = x0; i <= xf; i++)
for (j = y0; j <= yf; j++)
logicalMap[i][j] = LogicalObstacle;
}
void DungeonMap::generateLongObject(int x0, int y0, int w, int n)
{
int xf = x0 + w - 1;
objectsMap[x0][y0] = n;
logicalMap[x0][y0] = LogicalObstacle;
for (int i = x0 + 1; i <= xf - 1; i++)
{
objectsMap[i][y0] = n + 1;
logicalMap[i][y0] = LogicalObstacle;
}
objectsMap[xf][y0] = n + 2;
logicalMap[xf][y0] = LogicalObstacle;
}
Vector2D DungeonMap::generateMerchantRoom()
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
for (int i = x0 - 3; i <= x0 + 3; i++)
{
if (i == x0 - 3) objectsMap[i][y0] = MAPOBJ_SHOP_LEFT;
else if (i == x0 + 3) objectsMap[i][y0] = MAPOBJ_SHOP_RIGHT;
else objectsMap[i][y0] = MAPOBJ_SHOP;
logicalMap[i][y0] = LogicalObstacle;
}
if (!hasNeighbourUp())
{
objectsMap[x0 - 1][0] = MAPOBJ_PNW;
objectsMap[x0][0] = MAPOBJ_PNW + 1;
objectsMap[x0 + 1][0] = MAPOBJ_PNW + 2;
}
else
{
objectsMap[x0 - 1][MAP_HEIGHT - 1] = MAPOBJ_PNW +3;
objectsMap[x0][MAP_HEIGHT - 1] = MAPOBJ_PNW + 4;
objectsMap[x0 + 1][MAP_HEIGHT - 1] = MAPOBJ_PNW + 5;
}
generateRandomTiles();
return (Vector2D(x0 * TILE_WIDTH + TILE_WIDTH / 2, y0 * TILE_HEIGHT + TILE_HEIGHT / 2));
}
Vector2D DungeonMap::generateKeyRoom()
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
objectsMap[x0 - 1][y0 - 1] = MAPOBJ_WALL_SPECIAL;
objectsMap[x0 - 1][y0 + 1] = MAPOBJ_WALL_SPECIAL + 2;
objectsMap[x0 + 1][y0 - 1] = MAPOBJ_WALL_SPECIAL + 1;
objectsMap[x0 + 1][y0 + 1] = MAPOBJ_WALL_SPECIAL + 3;
logicalMap[x0 - 1][y0 - 1] = LogicalObstacle;
logicalMap[x0 - 1][y0 + 1] = LogicalObstacle;
logicalMap[x0 + 1][y0 - 1] = LogicalObstacle;
logicalMap[x0 + 1][y0 + 1] = LogicalObstacle;
if (rand() % 3 == 0)
{
if (rand() % 2 == 0) initPattern(PatternSmallCircle);
else initPattern(PatternSmallStar);
}
map[x0][y0] = MAP_TILE_KEY;
map[x0 -1][y0] = MAP_TILE_KEY;
map[x0 + 1][y0] = MAP_TILE_KEY;
map[x0][y0 - 1] = MAP_TILE_KEY;
map[x0][y0 + 1] = MAP_TILE_KEY;
generateRandomTiles();
return (Vector2D(x0 * TILE_WIDTH + TILE_WIDTH / 2, y0 * TILE_HEIGHT + TILE_HEIGHT / 2));
}
void DungeonMap::generateExitRoom()
{
initRoom();
int x0 = MAP_WIDTH / 2;
map[x0][0] = floorOffset;
map[x0 - 1][0] = floorOffset;
map[x0 + 1][0] = floorOffset;
logicalMap[x0][0] = LogicalFloor;
if (rand() % 3 == 0) initPattern(PatternBorder);
generateRandomTiles();
}
void DungeonMap::generateRoomRandom(int type)
{
if (rand() % 3 == 0) generateRoomWithHoles(type);
else generateRoomWithoutHoles(type);
}
void DungeonMap::generateRoomWithoutHoles(int type)
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
int i, j, r;
if (type <= 0) // empty room
{
if (roomType == roomTypeStarting)
{
generateCarpet(5, 3, 5, 3, MAP_CARPET);
if (game().getLevel() > 1)
{
map[x0][MAP_HEIGHT - 1] = floorOffset;
}
}
else if (roomType == roomTypeBoss && (game().getLevel() == 2) ) // giant slime
{
// good ?
objectsMap[1][1] = MAPOBJ_GRID;
objectsMap[1][MAP_HEIGHT -2] = MAPOBJ_GRID;
objectsMap[MAP_WIDTH - 2][1] = MAPOBJ_GRID;
objectsMap[MAP_WIDTH - 2][MAP_HEIGHT -2] = MAPOBJ_GRID;
}
if (roomType == roomTypeStandard)
{
if (rand() % 3 > 0 && gameFloor->neighboorCount(x, y) > 1)
{
if (type == 0 && game().getLevel() < 6) generateCorridors();
}
else
{
if (rand() % 3 == 0) initPattern((patternEnum)(rand() % 4));
}
}
}
if (type == 1) // corner block
{
if (rand() % 3 == 0) initPattern(PatternSmallChecker);
int wallOffset = wallType * 24;
map[0][0] = MAP_WALL_X;
map[0][1] = wallOffset + MAP_WALL_7;
map[1][1] = wallOffset + MAP_WALL_77;
map[1][0] = wallOffset + MAP_WALL_7;
logicalMap[1][1] = LogicalWall;
map[0][MAP_HEIGHT - 1] = MAP_WALL_X;
map[0][MAP_HEIGHT - 2] = wallOffset + MAP_WALL_7;
map[1][MAP_HEIGHT - 2] = wallOffset + MAP_WALL_77;
map[1][MAP_HEIGHT - 1] = wallOffset + MAP_WALL_7;
logicalMap[1][MAP_HEIGHT -2] = LogicalWall;
map[MAP_WIDTH - 1][0] = MAP_WALL_X;
map[MAP_WIDTH - 1][1] = wallOffset + MAP_WALL_7;
map[MAP_WIDTH - 2][1] = wallOffset + MAP_WALL_77;
map[MAP_WIDTH - 2][0] = wallOffset + MAP_WALL_7;
logicalMap[MAP_WIDTH - 2][1] = LogicalWall;
map[MAP_WIDTH - 1][MAP_HEIGHT -1] = MAP_WALL_X;
map[MAP_WIDTH - 1][MAP_HEIGHT -2] = wallOffset + MAP_WALL_7;
map[MAP_WIDTH - 2][MAP_HEIGHT -2] = wallOffset + MAP_WALL_77;
map[MAP_WIDTH - 2][MAP_HEIGHT -1] = wallOffset + MAP_WALL_7;
logicalMap[MAP_WIDTH - 2][MAP_HEIGHT -2] = LogicalWall;
}
if (type == 2) // blocks in the middle
{
if (rand() % 3 == 0) initPattern(PatternBorder);
r = 1 + rand() % 3;
generateTable(x0 - r, y0 - 1, 1 + 2 * r, 3, MAPOBJ_BIG_OBSTACLE);
}
if (type == 3)
{
// big blocks in the corners
generateTable(2, 2, 2, 2, MAPOBJ_BIG_OBSTACLE);
generateTable(2, MAP_HEIGHT - 4, 2, 2, MAPOBJ_BIG_OBSTACLE);
generateTable(MAP_WIDTH - 4, MAP_HEIGHT - 4, 2, 2, MAPOBJ_BIG_OBSTACLE);
generateTable(MAP_WIDTH - 4, 2, 2, 2, MAPOBJ_BIG_OBSTACLE);
}
if (type == 4)
{
// objects
if (rand() % 2 == 0)
{
// type 1
if (rand() % 3 == 0) initPattern(PatternSmallChecker);
bool leftOriented = rand() % 2 == 0;
int bankType = rand() % 3;
if (bankType == 2)
{
int xPlayer = game().getPlayerPosition().x;
if (xPlayer > GAME_WIDTH - TILE_WIDTH && xPlayer < GAME_WIDTH + TILE_WIDTH)
bankType = rand() % 2;
}
int x0 = leftOriented ? 5 : 3;
if (leftOriented)
{
objectsMap[2][4] = MAPOBJ_CHURCH_FURN_L;
logicalMap[2][4] = LogicalObstacle;
}
else
{
objectsMap[12][4] = MAPOBJ_CHURCH_FURN_R;
logicalMap[12][4] = LogicalObstacle;
}
for (int i = 0; i < 3; i++)
{
int xPos = x0 + i * 3;
switch (bankType)
{
case 0:
objectsMap[xPos][2] = MAPOBJ_BANK_TOP;
objectsMap[xPos][3] = MAPOBJ_BANK_BOTTOM;
objectsMap[xPos][5] = MAPOBJ_BANK_TOP;
objectsMap[xPos][6] = MAPOBJ_BANK_BOTTOM;
for (int j = 2; j <= 6; j++) if (j != 4) logicalMap[xPos][j] = LogicalObstacle;
break;
case 1:
objectsMap[xPos][2] = MAPOBJ_BANK_TOP;
objectsMap[xPos][3] = MAPOBJ_BANK;
objectsMap[xPos][4] = MAPOBJ_BANK;
objectsMap[xPos][5] = MAPOBJ_BANK;
objectsMap[xPos][6] = MAPOBJ_BANK_BOTTOM;
for (int j = 2; j <= 6; j++) logicalMap[xPos][j] = LogicalObstacle;
break;
case 2:
objectsMap[xPos][1] = MAPOBJ_BANK_TOP;
objectsMap[xPos][2] = MAPOBJ_BANK;
objectsMap[xPos][3] = MAPOBJ_BANK_BOTTOM;
objectsMap[xPos][5] = MAPOBJ_BANK_TOP;
objectsMap[xPos][6] = MAPOBJ_BANK;
objectsMap[xPos][7] = MAPOBJ_BANK_BOTTOM;
for (int j = 1; j <= 7; j++) if (j != 4) logicalMap[xPos][j] = LogicalObstacle;
break;
}
}
}
else
{
initPattern(PatternSmallStar);
generateLongObject(2, 2, 3, MAPOBJ_LONG_LEFT);
generateLongObject(2, 6, 3, MAPOBJ_LONG_LEFT);
generateLongObject(10, 2, 3, MAPOBJ_LONG_LEFT);
generateLongObject(10, 6, 3, MAPOBJ_LONG_LEFT);
generateLongObject(6, 4, 3, MAPOBJ_LONG_LEFT);
}
}
if (type == ROOM_TYPE_CHECKER)
{
// "checker"
if (rand() % 3 == 0) initPattern(PatternSmallChecker);
for (i = 2; i < MAP_WIDTH - 2; i = i + 2)
for (j = 2; j < MAP_HEIGHT - 2; j = j + 2)
{
objectsMap[i][j] = game().getLevel() >= 6 ? MAPOBJ_TOMB : MAPOBJ_OBSTACLE;
logicalMap[i][j] = LogicalObstacle;
}
}
generateRandomTiles();
}
void DungeonMap::addHole(int x, int y)
{
int n = MAPOBJ_HOLE;
if (y > 0 && logicalMap[x][y - 1] == LogicalHole)
n = MAPOBJ_HOLE_BOTTOM;
else if (logicalMap[x - 1][y] == LogicalHole && logicalMap[x - 1][y - 1] == LogicalHole)
n = MAPOBJ_HOLE_LEFT;
else if (logicalMap[x + 1][y] == LogicalHole && logicalMap[x + 1][y - 1] == LogicalHole)
n = MAPOBJ_HOLE_RIGHT;
objectsMap[x][y] = n;
logicalMap[x][y] = LogicalHole;
if (logicalMap[x][y + 1] == LogicalHole && objectsMap[x - 1][y + 1] == MAPOBJ_HOLE_TOP)
objectsMap[x - 1][y + 1] = MAPOBJ_HOLE_LEFT;
if (logicalMap[x][y + 1] == LogicalHole && objectsMap[x + 1][y + 1] == MAPOBJ_HOLE_TOP)
objectsMap[x + 1][y + 1] = MAPOBJ_HOLE_RIGHT;
}
void DungeonMap::generateRoomWithHoles(int type)
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
int i, j, r;
if (type == 0)
{
if (roomType == roomTypeStarting)
{
generateCarpet(5, 3, 5, 3, MAP_CARPET);
if (game().getLevel() > 1)
{
map[x0 - 1][MAP_HEIGHT - 1] = 62;
map[x0][MAP_HEIGHT - 1] = 63;
map[x0 + 1][MAP_HEIGHT - 1] = 64;
}
}
/*else if (rand() % 2 == 0)
{
for (int i = 1; i <= MAP_WIDTH - 2; i++)
{
if (i != MAP_WIDTH / 2 || !hasNeighbourUp()) addHole(i, 1);
}
for (int i = 2; i <= MAP_HEIGHT - 3; i++)
{
if (i != MAP_HEIGHT / 2 || !hasNeighbourLeft()) addHole(1, i);
if (i != MAP_HEIGHT / 2 || !hasNeighbourRight()) addHole(MAP_WIDTH - 2, i);
}
addHole(MAP_WIDTH - 2, MAP_HEIGHT - 2);
for (int i = 1; i <= MAP_WIDTH - 3; i++)
{
if (i != MAP_WIDTH / 2 || !hasNeighbourDown()) addHole(i, MAP_HEIGHT - 2);
}
}*/
}
else if (type == 1)
{
// corner hole
if (rand() % 3 == 0) initPattern(PatternSmallChecker);
addHole(1, 1);
addHole(MAP_WIDTH - 2, MAP_HEIGHT -2);
addHole(1, MAP_HEIGHT -2);
addHole(MAP_WIDTH - 2, 1);
}
else if (type == 2)
{
// blocks in the middle
if (rand() % 3 == 0) initPattern(PatternBorder);
/*if (false) //irregular // TO CORRECT
{
r = 1; //rand() % 2;
for (i = x0 - r; i <= x0 + r; i++)
{
if (rand() % 3 == 0) addHole(i, y0 - 1);
addHole(i, y0);
if (rand() % 3 == 0) addHole(i, y0 + 1);
}
for (j = y0 - 1; j <= y0 + 1; j++)
{
if (rand() % 3 == 0) addHole(x0 - r - 1, j);
if (rand() % 3 == 0) addHole(x0 + r + 1, j);
}
}
else*/
{
r = 1 + rand() % 2;
for (i = x0 - r; i <= x0 + r; i++)
for (j = y0 - 1; j <= y0 + 1; j++)
{
addHole(i, j);
}
}
}
else if (type == 3)
{
// 4 holes
addHole(2, 2);
addHole(2, 3);
addHole(3, 2);
addHole(3, 3);
addHole(MAP_WIDTH - 4, 2);
addHole(MAP_WIDTH - 4, 3);
addHole(MAP_WIDTH - 3, 2);
addHole(MAP_WIDTH - 3, 3);
addHole(2, MAP_HEIGHT - 4);
addHole(2, MAP_HEIGHT - 3);
addHole(3, MAP_HEIGHT - 4);
addHole(3, MAP_HEIGHT - 3);
addHole(MAP_WIDTH - 4, MAP_HEIGHT - 4);
addHole(MAP_WIDTH - 4, MAP_HEIGHT - 3);
addHole(MAP_WIDTH - 3, MAP_HEIGHT - 4);
addHole(MAP_WIDTH - 3, MAP_HEIGHT - 3);
}
else if (type == 4)
{
if (rand() % 2 == 0)
{
// holes and (sometimes) obstacles randomly
if (rand() % 3 == 0) initPattern(PatternBigCircle);
int r = 6 + rand()% 5;
int obstacleType = rand() % 2;
for (int i = 0; i < r; i++)
{
int rx = 1 + rand() % (MAP_WIDTH - 3);
int ry = 1 + rand() % (MAP_HEIGHT - 3);
bool ok = true;
bool isObstacle = (obstacleType == 1) && rand() % 2 == 0;
if ( (rx == 1 && ry == MAP_HEIGHT / 2)
|| (rx == MAP_WIDTH - 2 && ry == MAP_HEIGHT / 2)
|| (rx == MAP_WIDTH /2 && ry == MAP_HEIGHT - 2)
|| (rx == MAP_WIDTH /2 && ry == 1) )
{
ok = false;
}
else
{
for (int ix = -1; ix <= 1; ix++)
for (int iy = -1; iy <= 1; iy++)
{
ok = ok && logicalMap[rx + ix][ry + iy] != LogicalHole;
ok = ok && logicalMap[rx + ix][ry + iy] != LogicalObstacle;
}
}
if (ok)
{
if (!isObstacle)
{
addHole(rx, ry);
}
else
{
objectsMap[rx][ry] = MAPOBJ_OBSTACLE;
logicalMap[rx][ry] = LogicalObstacle;
}
}
else
{
i--;
}
}
}
else
{
// big holes left and right
bool holesNW = rand() % 2 == 0;
for (int i = 0; i < 5; i++)
{
if (holesNW)
{
addHole(1 + i, 1);
addHole(1 + i, 2);
addHole(MAP_WIDTH - 2 - i, MAP_HEIGHT - 3);
addHole(MAP_WIDTH - 2 - i, MAP_HEIGHT - 2);
}
else
{
addHole(1 + i, MAP_HEIGHT - 3);
addHole(1 + i, MAP_HEIGHT - 2);
addHole(MAP_WIDTH - 2 - i, 1);
addHole(MAP_WIDTH - 2 - i, 2);
}
}
}
}
else //if (type == 5)
{
// "checker"
for (i = 2; i < MAP_WIDTH - 2; i = i + 2)
for (j = 2; j < MAP_HEIGHT - 2; j = j + 2)
{
addHole(i, j);
}
}
generateRandomTiles();
}
void DungeonMap::addItem(int itemType, float x, float y, bool merch)
{
itemListElement ilm;
ilm.type = itemType;
ilm.x = x;
ilm.y = y;
ilm.merch = merch;
itemList.push_back(ilm);
}
void DungeonMap::addSprite(int spriteType, int frame, float x, float y, float scale)
{
spriteListElement slm;
slm.type = spriteType;
slm.frame = frame;
slm.x = x;
slm.y = y;
slm.scale = scale;
spriteList.push_back(slm);
}
void DungeonMap::addChest(int chestType, bool state, float x, float y)
{
chestListElement clm;
clm.type = chestType;
clm.state = state;
clm.x = x;
clm.y = y;
chestList.push_back(clm);
}
void DungeonMap::restoreItems()
{
ItemList::iterator it;
for (it = itemList.begin (); it != itemList.end ();)
{
itemListElement ilm = *it;
it++;
ItemEntity* itemEntity = new ItemEntity((enumItemType)(ilm.type), ilm.x, ilm.y);
itemEntity->setMerchandise(ilm.merch);
}
}
void DungeonMap::restoreSprites()
{
SpriteList::iterator it;
for (it = spriteList.begin (); it != spriteList.end ();)
{
spriteListElement ilm = *it;
it++;
if (ilm.type == ENTITY_BLOOD)
game().getCurrentMapEntity()->addBlood(ilm.x, ilm.y, ilm.frame, ilm.scale);
else if (ilm.type == ENTITY_CORPSE)
game().getCurrentMapEntity()->addCorpse(ilm.x, ilm.y, ilm.frame);
}
}
void DungeonMap::restoreChests()
{
ChestList::iterator it;
for (it = chestList.begin (); it != chestList.end ();)
{
chestListElement clm = *it;
it++;
new ChestEntity(clm.x, clm.y, clm.type, clm.state);
}
}
void DungeonMap::restoreMapObjects()
{
restoreItems();
restoreSprites();
restoreChests();
cleanMapObjects();
}
void DungeonMap::cleanMapObjects()
{
itemList.clear();
spriteList.clear();
chestList.clear();
}
void DungeonMap::addRandomGrids(int n)
{
int counter = n;
while (counter > 0)
{
int rx = 1 + rand() % (MAP_WIDTH - 2);
int ry = 1 + rand() % (MAP_HEIGHT - 2);
if (logicalMap[rx][ry] == LogicalFloor
|| objectsMap[rx][ry] == 0)
{
objectsMap[rx][ry] = MAPOBJ_GRID;
counter--;
}
}
}
void DungeonMap::generateCorridors()
{
int xCor = 1 + rand()% 4;
int yCor = 1 + rand()% 1;
int wallOffset = wallType * 24;
if (!hasNeighbourLeft())
{
for (int i = 0; i < xCor; i++)
for (int j = 0; j < MAP_HEIGHT; j++)
{
map[i][j] = MAP_WALL_X;
logicalMap[i][j] = LogicalWall;
}
}
if (!hasNeighbourRight())
{
for (int i = MAP_WIDTH - 1; i > MAP_WIDTH - 1 - xCor; i--)
for (int j = 0; j < MAP_HEIGHT; j++)
{
map[i][j] = MAP_WALL_X;
logicalMap[i][j] = LogicalWall;
}
}
if (!hasNeighbourUp())
{
for (int i = 0; i < MAP_WIDTH; i++)
for (int j = 0; j < yCor; j++)
{
map[i][j] = MAP_WALL_X;
logicalMap[i][j] = LogicalWall;
}
}
if (!hasNeighbourDown())
{
for (int i = 0; i < MAP_WIDTH; i++)
for (int j = MAP_HEIGHT - 1; j > MAP_HEIGHT - 1 - yCor; j--)
{
map[i][j] = MAP_WALL_X;
logicalMap[i][j] = LogicalWall;
}
}
//
for (int i = 0; i < MAP_WIDTH; i++)
{
for (int j = 0; j < MAP_HEIGHT; j++)
{
if (map[i][j] != MAP_WALL_X)
{
if (getTile(i - 1, j) == MAP_WALL_X)
{
if (j == 0 || getTile(i, j - 1) == MAP_WALL_X)
{
map[i][j] = wallOffset + MAP_WALL_7;
}
else if (j == MAP_HEIGHT - 1 || getTile(i, j + 1) == MAP_WALL_X)
{
map[i][j] = wallOffset + MAP_WALL_7;
}
else
{
if (j < MAP_HEIGHT / 2) map[i][j] = wallOffset + MAP_WALL_87 + rand() % 8;
else if (j > MAP_HEIGHT / 2) map[i][j] = wallOffset + MAP_WALL_87 + rand() % 8;
else map[i][j] = wallOffset + MAP_WALL_8;
}
logicalMap[i][j] = LogicalWall;
}
else if (getTile(i + 1, j) == MAP_WALL_X)
{
if (j == 0 || getTile(i, j - 1) == MAP_WALL_X)
{
map[i][j] = wallOffset + MAP_WALL_7;
map[i][j] = wallOffset + MAP_WALL_7;
}
else if (j == MAP_HEIGHT - 1 || getTile(i, j + 1) == MAP_WALL_X) map[i][j] = wallOffset + MAP_WALL_7;
else
{
if (j < MAP_HEIGHT / 2) map[i][j] = wallOffset + MAP_WALL_87 + rand() % 8;
else if (j > MAP_HEIGHT / 2) map[i][j] = wallOffset + MAP_WALL_87 + rand() % 8;
else map[i][j] = wallOffset + MAP_WALL_8;
}
logicalMap[i][j] = LogicalWall;
}
else if (getTile(i, j - 1) == MAP_WALL_X)
{
if (i == 0) map[i][j] = wallOffset + MAP_WALL_7;
else if (i == MAP_WIDTH - 1) map[i][j] = wallOffset + MAP_WALL_7;
else
{
if (i < MAP_WIDTH / 2) map[i][j] = wallOffset + MAP_WALL_87 + rand() % 8;
else if (i > MAP_WIDTH / 2) map[i][j] = wallOffset + MAP_WALL_87 + rand() % 8;
else map[i][j] = wallOffset + MAP_WALL_8;
}
logicalMap[i][j] = LogicalWall;
}
else if (getTile(i, j + 1) == MAP_WALL_X)
{
if (i == 0) map[i][j] = wallOffset + MAP_WALL_7;
else if (i == MAP_WIDTH - 1) map[i][j] = wallOffset + MAP_WALL_7;
else
{
if (i < MAP_WIDTH / 2) map[i][j] = wallOffset + MAP_WALL_87 + rand() % 8;
else if (i > MAP_WIDTH / 2) map[i][j] = wallOffset + MAP_WALL_87 + rand() % 8;
else map[i][j] = wallOffset + MAP_WALL_8;
}
logicalMap[i][j] = LogicalWall;
}
}
}
}
}
void DungeonMap::generateRandomTiles()
{
for (int i = 0; i < NB_RANDOM_TILES_IN_ROOM; i++)
generateRandomTile(i);
}
void DungeonMap::generateRandomTile(int index)
{
bool ok = false;
for (int i = 0; !ok && i < NB_RANDOM_TILE_TRY; i++)
{
int n = rand() % NB_RANDOM_TILES;
int xTile, yTile;
if (randomDungeonTiles[n].canBeOnWall)
{
xTile = rand() % (GAME_WIDTH - randomDungeonTiles[n].width);
yTile = rand() % (GAME_HEIGHT - randomDungeonTiles[n].height);
}
else
{
xTile = TILE_WIDTH + rand() % (GAME_WIDTH - 2 * TILE_WIDTH - randomDungeonTiles[n].width);
yTile = TILE_HEIGHT + rand() % (GAME_HEIGHT - 2 * TILE_HEIGHT - randomDungeonTiles[n].height);
}
int x0 = xTile / TILE_WIDTH;
int xf = (xTile + randomDungeonTiles[n].width) / TILE_WIDTH;
int y0 = yTile / TILE_HEIGHT;
int yf = (yTile + randomDungeonTiles[n].height) / TILE_HEIGHT;
ok = true;
if (!randomDungeonTiles[n].randomPlace || roomType == roomTypeKey)
{
for (int ix = x0; ix <= xf; ix++)
for (int iy = y0; iy <= yf; iy++)
{
ok = ok && isWalkable(ix, iy);
}
}
if (ok && !randomDungeonTiles[n].canBeOnWall)
{
for (int ix = x0; ix <= xf; ix++)
for (int iy = y0; iy <= yf; iy++)
{
ok = ok && isFlyable(ix, iy);
}
}
if (ok)
{
randomTileElements[index].type = n;
randomTileElements[index].x = xTile;
randomTileElements[index].y = yTile;
if (randomDungeonTiles[n].canRotate)
randomTileElements[index].rotation = rand()% 360;
else
randomTileElements[index].rotation = 0;
}
}
}
diff --git a/src/PlayerEntity.cpp b/src/PlayerEntity.cpp
index 1065e85..ffe60d0 100644
--- a/src/PlayerEntity.cpp
+++ b/src/PlayerEntity.cpp
@@ -1,3198 +1,3196 @@
#include "PlayerEntity.h"
#include "SlimeEntity.h"
#include "SlimePetEntity.h"
#include "FallingRockEntity.h"
#include "BoltEntity.h"
#include "SpiderWebEntity.h"
#include "EvilFlowerEntity.h"
#include "EnemyBoltEntity.h"
#include "ItemEntity.h"
#include "FairyEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "TextEntity.h"
#include "TextMapper.h"
#include <iostream>
#include <sstream>
#define SPIRAL_STAIRCASE
const int xHalo[9][3] =
{
{ 13, 13, 18},
{ 47, 45, 37},
{ 48, 47, 44},
{ 15, 15, 16},
{ 45, 45, 45},
{ 46, 44, 42},
{ 13, 13, 13},
{ 13, 24, 36},
{ 13, 17, 13}
};
const int yHalo[9][3] =
{
{ 26, 25, 25},
{ 23, 23, 23},
{ 23, 24, 25},
{ 31, 32, 34},
{ 23, 23, 23},
{ 23, 22, 21},
{ 26, 26, 26},
{ 26, 15, 6},
{ 25, 27, 25}
};
const int KEYS_MOVE_TOLERANCE = 36;
PlayerEntity::PlayerEntity(float x, float y)
: BaseCreatureEntity (ImageManager::getInstance().getImage(IMAGE_PLAYER_0), x, y, 64, 96)
{
currentFireDelay = -1.0f;
randomFireDelay = -1.0f;
invincibleDelay = -1.0f;
divineInterventionDelay = -1.0f;
fireAnimationDelay = -1.0f;
fireAnimationDelayMax = 0.4f;
spellAnimationDelay = -1.0f;
spellAnimationDelayMax = 0.7f;
canFirePlayer = true;
type = ENTITY_PLAYER;
imagesProLine = 8;
playerStatus = playerStatusPlaying;
hp = INITIAL_PLAYER_HP;
#ifdef TEST_MODE
hp = INITIAL_PLAYER_HP * 100;
#endif // TEST_MODE
hpDisplay = hp;
hpMax = hp;
gold = 0;
deathAge = -1.0f;
hiccupDelay = HICCUP_DELAY;
idleAge = 0.0f;
boltLifeTime = INITIAL_BOLT_LIFE;
specialBoltTimer = -1.0f;
bloodColor = BloodRed;
canExplode = false;
// init the equipment (to empty)
for (int i = 0; i < NUMBER_EQUIP_ITEMS; i++) equip[i] = false;
collidingDirection = 0;
// init the shots (to none)
for (int i = 0; i < SPECIAL_SHOT_SLOTS; i++)
{
specialShots[i] = ShotTypeStandard;
specialShotLevel[i] = 0;
}
specialShotIndex = 0;
needInitShotType = false;
computePlayer();
firingDirection = 5;
facingDirection = 2;
keyDirection = 5;
sprite.setOrigin(32, 80);
protection.active = false;
armor = 0.0f;
activeSpell.delay = -1.0f;
activeSpell.spell = SpellNone;
divinity.divinity = -1;
divinity.piety = 0;
divinity.level = 0;
divinity.interventions = 0;
divinity.percentsToNextLevels = 0.0f;
isRegeneration = false;
isFairyTransmuted = false;
itemToBuy = NULL;
}
void PlayerEntity::moveTo(float newX, float newY)
{
float dx = newX - x;
float dy = newY - y;
x = newX;
y = newY;
for(int unsigned i = 0; i < fairies.size(); i++)
{
fairies[i]->setX(fairies[i]->getX() + dx);
fairies[i]->setY(fairies[i]->getY() + dy);
}
}
int PlayerEntity::getFacingDirection()
{
return facingDirection;
}
void PlayerEntity::setFacingDirection(int facingDirection)
{
if (facingDirection == 4 || facingDirection == 6 || facingDirection == 2 || facingDirection == 8)
this->facingDirection = facingDirection;
}
float PlayerEntity::getPercentFireDelay()
{
if (canFirePlayer) return 1.0f;
else return (1.0f - currentFireDelay / fireDelay);
}
float PlayerEntity::getLightCone()
{
if (playerStatus == playerStatusPraying)
{
float result = 1.0f;
if (statusTimer < 0.25f)
result = 4 * statusTimer;
else if (statusTimer > WORSHIP_DELAY - 0.25f)
result = (WORSHIP_DELAY - statusTimer) * 4;
return result;
}
else if (divineInterventionDelay > 0.0f)
{
float result = 1.0f;
if (divineInterventionDelay < 0.25f)
result = 4 * divineInterventionDelay;
else if (divineInterventionDelay > WORSHIP_DELAY - 0.25f)
result = (WORSHIP_DELAY - divineInterventionDelay) * 4;
if (isRegeneration) result *= 0.4f;
return result;
}
else return -1.0f;
}
float PlayerEntity::getPercentSpellDelay()
{
if (activeSpell.spell == SpellNone)
return getPercentFireDelay();
else
{
if (activeSpell.delay <= 0.0f) return 1.0f;
else return (1.0f - activeSpell.delay / activeSpell.delayMax);
}
}
bool PlayerEntity::isPoisoned()
{
return (specialState[SpecialStatePoison].active);
}
int PlayerEntity::getCollidingDirection()
{
return collidingDirection;
}
PlayerEntity::playerStatusEnum PlayerEntity::getPlayerStatus()
{
return playerStatus;
}
void PlayerEntity::setPlayerStatus(PlayerEntity::playerStatusEnum playerStatus)
{
this->playerStatus = playerStatus;
}
bool PlayerEntity::isDead()
{
return playerStatus == playerStatusDead;
}
enemyTypeEnum PlayerEntity::getLastHurtingEnemy()
{
return lastHurtingEnemy;
}
sourceTypeEnum PlayerEntity::getLastHurtingSource()
{
return lastHurtingSource;
}
float PlayerEntity::getDeathAge()
{
return deathAge;
}
void PlayerEntity::setDeathAge(float deathAge)
{
this->deathAge = deathAge;
}
bool PlayerEntity::getFairyTransmuted()
{
return isFairyTransmuted;
}
divinityStruct PlayerEntity::getDivinity()
{
return divinity;
}
int PlayerEntity::getPiety()
{
return divinity.piety;
}
void PlayerEntity::stuck()
{
if (playerStatus != playerStatusEntering)
castTeleport();
}
void PlayerEntity::setEntering()
{
playerStatus = playerStatusEntering;
}
void PlayerEntity::setLeavingLevel()
{
playerStatus = playerStatusGoingNext;
}
void PlayerEntity::pay(int price)
{
gold -= price;
displayAcquiredGold(-price);
if (gold < 0) gold = 0;
SoundManager::getInstance().playSound(SOUND_PAY);
}
void PlayerEntity::acquireItemAfterStance()
{
if (acquiredItem >= FirstEquipItem)
{
equip[acquiredItem - FirstEquipItem] = true;
if (acquiredItem != ItemBossKey) game().proceedEvent(EventGetItem);
// familiar
if (items[acquiredItem].familiar != FamiliarNone)
{
setEquiped(acquiredItem - FirstEquipItem, true);
game().proceedEvent(EventGetFamiliar);
}
// shot types
else if (items[acquiredItem].specialShot != (ShotTypeStandard))
{
registerSpecialShot(acquiredItem);
game().proceedEvent(EventGetSpecialShot);
}
// spells
else if (items[acquiredItem].spell != SpellNone)
{
setActiveSpell(items[acquiredItem].spell, false);
game().proceedEvent(EventGetSpell);
}
// pet slime
else if (acquiredItem == ItemPetSlime)
{
new SlimePetEntity();
}
// floor item
else if (acquiredItem == ItemFloorMap)
game().revealFloor();
else if (acquiredItem == ItemAlcohol)
hiccupDelay = HICCUP_DELAY;
// acquirement
if (equip[EQUIP_DISPLACEMENT_GLOVES] && equip[EQUIP_LEATHER_BOOTS] && equip[EQUIP_MAGICIAN_HAT] && equip[EQUIP_MAGICIAN_ROBE])
game().registerAchievement(AchievementCompleteSet);
computePlayer();
}
else
{
if (acquiredItem == ItemBossHeart)
{
int hpBonus = 2 + rand() % 4;
hpMax += hpBonus;
hp += hpBonus;
hpDisplay += hpBonus;
SoundManager::getInstance().playSound(SOUND_EAT);
std::ostringstream oss;
oss << "HP Max +" << hpBonus;
TextEntity* text = new TextEntity(oss.str(), 15, x, y - 50.0f);
text->setColor(TextEntity::COLOR_FADING_GREEN);
text->setAlignment(ALIGN_CENTER);
text->setAge(-1.0f);
text->setLifetime(1.2f);
text->setWeight(-60.0f);
text->setType(ENTITY_FLYING_TEXT);
text->setZ(2000);
}
else if (acquiredItem == ItemBonusHealth)
{
hpMax += 1;
hp = hpMax;
SoundManager::getInstance().playSound(SOUND_EAT);
TextEntity* text = new TextEntity("HP Max + 1", 15, x, y - 50.0f);
text->setColor(TextEntity::COLOR_FADING_GREEN);
text->setAlignment(ALIGN_CENTER);
text->setAge(-1.0f);
text->setLifetime(1.2f);
text->setWeight(-60.0f);
text->setType(ENTITY_FLYING_TEXT);
text->setZ(2000);
}
}
spriteItem->setDying(true);
spriteItemStar->setDying(true);
playerStatus = playerStatusPlaying;
}
void PlayerEntity::resetFloorItem()
{
equip[EQUIP_BOSS_KEY] = false;
equip[EQUIP_FLOOR_MAP] = false;
equip[EQUIP_ALCOHOL] = false;
equip[EQUIP_FAIRY_POWDER] = false;
equip[EQUIP_LUCK] = false;
computePlayer();
}
void PlayerEntity::setItemToBuy(ItemEntity* item)
{
itemToBuy = item;
}
ItemEntity* PlayerEntity::getItemToBuy()
{
return itemToBuy;
}
void PlayerEntity::animate(float delay)
{
// shot timer
if (specialBoltTimer >= 0.0f)
{
specialBoltTimer -= delay;
if (specialBoltTimer <= 0.0f)
{
if (getShotType() == ShotTypeIce) SoundManager::getInstance().playSound(SOUND_ICE_CHARGE);
}
}
if (playerStatus == playerStatusGoingNext)
{
return;
}
if (playerStatus == playerStatusStairs)
{
x += velocity.x * delay;
y += velocity.y * delay;
age += delay;
frame = ((int)(age * 7.0f)) % 4;
if (frame == 3) frame = 1;
if (x < (MAP_WIDTH / 2) * TILE_WIDTH - TILE_WIDTH / 2)
{
facingDirection = 8;
game().moveToOtherMap(8);
}
return;
}
// rate of fire
if (!canFirePlayer)
{
currentFireDelay -= delay;
canFirePlayer = (currentFireDelay <= 0.0f);
}
if (randomFireDelay >= 0.0f) randomFireDelay -= delay;
// spells
if (activeSpell.spell != SpellNone && activeSpell.delay > 0.0f)
{
if (game().getCurrentMap()->isCleared())
activeSpell.delay -= 40 * delay;
else
activeSpell.delay -= delay;
if (activeSpell.spell == SpellProtection && protection.active)
activeSpell.delay = activeSpell.delayMax;
if (activeSpell.delay <= 0.0f) SoundManager::getInstance().playSound(SOUND_SPELL_CHARGE);
}
// protection
if (protection.active)
{
protection.timer -= delay;
if (protection.timer <= 0.0f)
{
protection.active = false;
computePlayer();
}
}
// acquisition animation
if (playerStatus == playerStatusAcquire)
{
statusTimer -= delay;
if (statusTimer <= 0.0f)
{
acquireItemAfterStance();
}
}
else if (equip[EQUIP_ALCOHOL] && playerStatus == playerStatusPlaying)
{
hiccupDelay -= delay;
if (hiccupDelay <= 0.0f)
{
hiccupDelay = 4.0f;
// hiccup
recoil.active = true;
recoil.stun = true;
recoil.velocity = Vector2D(350.0f);
recoil.timer = 0.4f;
for (int i = 0; i < 4; i++)
{
BoltEntity* bolt = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypePoison, 0);
bolt->setDamages(4);
bolt->setFlying(isFairyTransmuted);
//bolt->setVelocity(recoil.velocity.vectorTo(Vector2D(0, 0), fireVelocity));
bolt->setVelocity(Vector2D(fireVelocity));
}
TextEntity* text = new TextEntity("*hic*", 16, x, y - 30.0f);
text->setColor(TextEntity::COLOR_FADING_GREEN);
text->setAge(-0.6f);
text->setLifetime(0.3f);
text->setWeight(-60.0f);
text->setZ(2000);
text->setAlignment(ALIGN_CENTER);
text->setType(ENTITY_FLYING_TEXT);
SoundManager::getInstance().playSound(SOUND_HICCUP);
SoundManager::getInstance().playSound(SOUND_BLAST_STANDARD);
}
}
if (divineInterventionDelay > 0.0f) divineInterventionDelay -= delay;
if (fireAnimationDelay > 0.0f)
{
fireAnimationDelay -= delay;
if (fireAnimationDelay <= 0.0f) fireAnimationDelay = -1.0f;
}
if (spellAnimationDelay > 0.0f)
{
spellAnimationDelay -= delay;
if (spellAnimationDelay <= 0.0f) spellAnimationDelay = -1.0f;
}
// unlocking animation
else if (playerStatus == playerStatusUnlocking || playerStatus == playerStatusPraying)
{
statusTimer -= delay;
if (statusTimer <= 0.0f)
{
playerStatus = playerStatusPlaying;
}
}
if (playerStatus == playerStatusDead)
{
deathAge += delay;
velocity = Vector2D(0.0f, 0.0f);
}
else
testSpriteCollisions();
// key room collision
if (game().getCurrentMap()->getRoomType() == roomTypeKey && !game().getCurrentMap()->isCleared())
{
sf::IntRect col1;
col1.width = 198;
col1.height = 68;
col1.top = 254;
col1.left = 380;
sf::IntRect col2;
col2.width = 68;
col2.height = 198;
col2.top = 189;
col2.left = 445;
if (boundingBox.intersects(col1) || boundingBox.intersects(col2))
{
recoil.active = true;
recoil.stun = true;
recoil.velocity = Vector2D(GAME_WIDTH / 2, GAME_HEIGHT /2).vectorTo(Vector2D(x, y), 650.0f);
recoil.timer = 0.4f;
game().activateKeyRoomEffect(true);
}
}
collidingDirection = 0;
BaseCreatureEntity::animate(delay);
if (firingDirection != 5)
facingDirection = firingDirection;
// find the frame
if (firingDirection != 5)
{
if (fireAnimationDelay < 0.0f)
fireAnimationDelay = fireAnimationDelayMax;
fireAnimationDirection = firingDirection;
}
else if (isMoving())
{
frame = ((int)(age * 7.0f)) % 4;
if (frame == 3) frame = 1;
}
else if (playerStatus == playerStatusAcquire || playerStatus == playerStatusUnlocking || playerStatus == playerStatusPraying)
frame = 3;
else if (playerStatus == playerStatusDead)
frame = 0;
else // standing
{
frame = 1;
}
if (playerStatus != playerStatusPlaying || isMoving() || firingDirection != 5)
idleAge = 0.0f;
else
idleAge += delay;
if (x < 0)
game().moveToOtherMap(4);
else if (x > MAP_WIDTH * TILE_WIDTH)
game().moveToOtherMap(6);
else if (y < 0)
game().moveToOtherMap(8);
else if (y > MAP_HEIGHT * TILE_HEIGHT)
game().moveToOtherMap(2);
#ifdef SPIRAL_STAIRCASE
else if (playerStatus == playerStatusPlaying
&& game().getCurrentMap()->getRoomType() == roomTypeExit && y < TILE_HEIGHT * 0.6f)
{
playerStatus = playerStatusStairs;
velocity.y = creatureSpeed / 12;
velocity.x = -creatureSpeed / 3;
facingDirection = 4;
- int doorStypeStandard = DoorStandard_0 + (game().getLevel() - 1) % 5;
-
SpriteEntity* exitDoorEntity = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_TILES),
(MAP_WIDTH / 2) * TILE_WIDTH - TILE_WIDTH / 2,
TILE_HEIGHT / 2, 64, 64, 1);
exitDoorEntity->setZ(TILE_HEIGHT);
exitDoorEntity->setImagesProLine(24);
exitDoorEntity->setFrame(MAP_WALL_BEGIN + 21 + 24 * game().getCurrentMap()->getWallType());
exitDoorEntity->setType(ENTITY_EFFECT);
SpriteEntity* exitDoorAroundEntity = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_DOORS),
(MAP_WIDTH / 2) * TILE_WIDTH - TILE_WIDTH / 2,
TILE_HEIGHT / 2, 64, 64, 1);
exitDoorAroundEntity->setZ(TILE_HEIGHT + 1);
exitDoorAroundEntity->setImagesProLine(2);
- exitDoorAroundEntity->setFrame(3 + 6 * doorStypeStandard);
+ exitDoorAroundEntity->setFrame(3 + 6 * DoorExit);
exitDoorAroundEntity->setType(ENTITY_EFFECT);
SpriteEntity* exitDoorEntityShadow = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_TILES_SHADOW),
(MAP_WIDTH / 2) * TILE_WIDTH - TILE_WIDTH / 2,
TILE_HEIGHT / 2, 64, 64, 1);
exitDoorEntityShadow->setZ(TILE_HEIGHT + 2);
exitDoorEntityShadow->setImagesProLine(10);
exitDoorEntityShadow->setFrame(4);
exitDoorEntityShadow->setType(ENTITY_EFFECT);
}
#endif
if (playerStatus == playerStatusEntering)
{
if (boundingBox.left > TILE_WIDTH
&& (boundingBox.left + boundingBox.width) < TILE_WIDTH * (MAP_WIDTH - 1)
&& boundingBox.top > TILE_HEIGHT
&& (boundingBox.top + boundingBox.height) < TILE_HEIGHT * (MAP_HEIGHT - 1))
{
playerStatus = playerStatusPlaying;
game().closeDoors();
}
else
{
if (x < 2 * TILE_WIDTH)
{
velocity.x = creatureSpeed;
velocity.y = 0.0f;
}
else if (x > (MAP_WIDTH - 3) * TILE_WIDTH)
{
velocity.x = -creatureSpeed;
velocity.y = 0.0f;
}
else if (y < 2 * TILE_HEIGHT)
{
velocity.y = creatureSpeed;
velocity.x = 0.0f;
}
else if (y > (MAP_HEIGHT - 3) * TILE_HEIGHT)
{
velocity.y = -creatureSpeed;
velocity.x = 0.0f;
}
}
}
if (playerStatus != playerStatusDead)
{
if (invincibleDelay >= 0.0f) invincibleDelay -= delay;
if (specialState[SpecialStateConfused].active)
SoundManager::getInstance().playSound(SOUND_VAMPIRE_HYPNOSIS, false);
}
z = y + 4;
}
bool PlayerEntity::canCollide()
{
return invincibleDelay <= 0.0f;
}
void PlayerEntity::setSpecialState(enumSpecialState state, bool active, float timer, float param1, float param2)
{
BaseCreatureEntity::setSpecialState(state, active, timer, param1, param2);
computePlayer();
}
void PlayerEntity::renderPlayer(sf::RenderTarget* app)
{
sf::Color savedColor = sprite.getColor();
if (isPoisoned()) sprite.setColor(sf::Color(180, 255, 180, 255));
// 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);
sprite.setColor(savedColor);
// boots
if (equip[EQUIP_BOOTS_ADVANCED] && playerStatus != playerStatusDead)
{
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] && playerStatus != playerStatusDead)
{
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] && playerStatus != playerStatusDead)
{
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);
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));
sprite.setColor(sf::Color(255, 255, 255, 100 + 100 * cosf(game().getAbsolutTime() * 3.5f)));
app->draw(sprite, sf::BlendAdd);
sprite.setColor(sf::Color(255, 255, 255, 255));
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] && playerStatus != playerStatusDead)
{
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);
}
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);
}
// 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])
{
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 (getShotType() != ShotTypeStandard)
{
switch (getShotType())
{
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;
case ShotTypePoison:
sprite.setColor(sf::Color(50, 255, 50, 255));
break;
default:
std::cout << "[WARNING] Can not render shot type: " << getShotType() << std::endl;
}
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.setColor(savedColor);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
// hat
if (equip[EQUIP_HAT_ADVANCED] && playerStatus != playerStatusDead)
{
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] && playerStatus != playerStatusDead)
{
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));
}
}
void PlayerEntity::renderHalo(sf::RenderTarget* app)
{
if (frame > 2 || spriteDy > 8) return;
// gems
if ((getShotType() == ShotTypeIce || getShotType() == ShotTypeLightning || getShotType() == ShotTypeFire || getShotType() == ShotTypePoison) && playerStatus != playerStatusDead)
{
int fade;
sf::Color savedColor = sprite.getColor();
if (getShotType() != ShotTypeIce || specialBoltTimer <= 0.0f) fade = 255;
else fade = ((STATUS_FROZEN_BOLT_DELAY[getShotLevel()] - specialBoltTimer) / STATUS_FROZEN_BOLT_DELAY[getShotLevel()]) * 128;
if (getShotType() == ShotTypeLightning)
fade = 150 + rand() % 105;
if (getShotType() == ShotTypeFire)
fade = 200 + rand() % 40;
if (getShotType() == ShotTypePoison)
fade = 150 + rand() % 40;
if (getShotType() == ShotTypeIce)
sprite.setTextureRect(sf::IntRect(448, 864, 20, 20));
else if (getShotType() == ShotTypeLightning)
sprite.setTextureRect(sf::IntRect(448 + 20, 864, 20, 20));
else if (getShotType() == ShotTypeFire)
sprite.setTextureRect(sf::IntRect(448 + 40, 864, 20, 20));
else if (getShotType() == ShotTypePoison)
sprite.setTextureRect(sf::IntRect(448, 864 + 20, 20, 20));
sprite.setColor(sf::Color(255, 255, 255, fade));
if (isMirroring)
sprite.setPosition(x - 10 + 64 - xHalo[spriteDy][frame], y - 10 + yHalo[spriteDy][frame]);
else
sprite.setPosition(x - 10 + xHalo[spriteDy][frame], y - 10 + yHalo[spriteDy][frame]);
sf::RenderStates r;
r.blendMode = sf::BlendAdd;
app->draw(sprite, r);
sprite.setPosition(x, y);
sprite.setColor(savedColor);
}
}
void PlayerEntity::render(sf::RenderTarget* app)
{
sprite.setPosition(x, y);
spriteDy = 0;
isMirroring = false;
if (idleAge > 8.5f)
{
idleAge -= 8.5f;
}
else if (idleAge >= 7.5)
{
spriteDy = 8;
frame = 2;
}
else if (idleAge >= 7.0)
{
spriteDy = 8;
frame = 1;
}
else if (idleAge >= 6.0)
{
spriteDy = 8;
frame = 0;
}
else if (idleAge >= 5.5f && facingDirection != 2)
{
facingDirection = 2;
idleAge -= 2.0f;
}
else if (fireAnimationDelay <= 0.0f && spellAnimationDelay <= 0.0f)
{
if (facingDirection == 6) spriteDy = 1;
else if (facingDirection == 8) spriteDy = 2;
else if (facingDirection == 4)
{
spriteDy = 1;
isMirroring = true;
}
}
else if (spellAnimationDelay >= 0.0f)
{
spriteDy = 7;
if (spellAnimationDelay < spellAnimationDelayMax * 0.1f) frame = 0;
else if (spellAnimationDelay < spellAnimationDelayMax * 0.2f) frame = 1;
else if (spellAnimationDelay < spellAnimationDelayMax * 0.7f) frame = 2;
else if (spellAnimationDelay < spellAnimationDelayMax * 0.85f) frame = 1;
else frame = 0;
}
else
{
if (fireAnimationDirection == 2) spriteDy = 3;
else if (fireAnimationDirection == 6) spriteDy = 4;
else if (fireAnimationDirection == 8) spriteDy = 5;
else if (fireAnimationDirection == 4)
{
spriteDy = 4;
isMirroring = true;
}
if (fireAnimationDelay < fireAnimationDelayMax * 0.2f) frame = 0;
else if (fireAnimationDelay < fireAnimationDelayMax * 0.4f) frame = 1;
else if (fireAnimationDelay < fireAnimationDelayMax * 0.6f) frame = 2;
else if (fireAnimationDelay < fireAnimationDelayMax * 0.8f) frame = 1;
else frame = 0;
}
if (playerStatus == playerStatusAcquire || playerStatus == playerStatusUnlocking)
{
spriteDy = 6;
frame = ((int)(age * 10.0f)) % 4;
if (frame == 3) frame = 1;
}
else if (playerStatus == playerStatusPraying)
{
spriteDy = 7;
frame = ((int)(age * 10.0f)) % 4;
if (frame == 3) frame = 1;
float delay = playerStatus == playerStatusPraying ? WORSHIP_DELAY : UNLOCK_DELAY;
if (statusTimer < delay * 0.1f) frame = 0;
else if (statusTimer < delay * 0.2f) frame = 1;
else if (statusTimer < delay * 0.7f) frame = 2;
else if (statusTimer < delay * 0.85f) frame = 1;
else frame = 0;
}
if (playerStatus == playerStatusDead)
{
frame = (int)(deathAge / 0.35f);
if (frame > 6) frame = 6;
spriteDy = 9;
sprite.setTextureRect(sf::IntRect( frame * width, spriteDy * height, width, height));
app->draw(sprite);
}
else
{
if (isFairyTransmuted)
{
frame = 0;
if (velocity.x * velocity.x + velocity.y * velocity.y > 400)
frame = ((int)(age * 24.0f)) % 2;
else
frame = ((int)(age * 18.0f)) % 2;
sf::Sprite fairySprite;
fairySprite.setColor(sprite.getColor());
fairySprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
fairySprite.setPosition(sprite.getPosition());
fairySprite.setOrigin(26, 62);
switch (facingDirection)
{
case 8: fairySprite.setTextureRect(sf::IntRect( (2 + frame) * 48, 5 * 72, 48, 72)); break;
case 4: fairySprite.setTextureRect(sf::IntRect( (4 + frame) * 48, 5 * 72, 48, 72)); break;
case 6: fairySprite.setTextureRect(sf::IntRect( (5 + frame) * 48, 5 * 72, - 48, 72)); break;
default: fairySprite.setTextureRect(sf::IntRect( frame * 48, 5 * 72, 48, 72)); break;
}
app->draw(fairySprite);
}
else
{
renderHalo(app);
renderPlayer(app);
}
// shield
if (playerStatus != playerStatusStairs && (specialState[DivineStateProtection].active || protection.active))
{
int firstFrame = 8;
if (specialState[DivineStateProtection].active && divinity.divinity == DivinityStone) firstFrame = 16;
float timer = specialState[DivineStateProtection].active ? specialState[DivineStateProtection].timer : protection.timer;
sprite.setTextureRect(sf::IntRect( firstFrame * width, 9 * height, width, height));
app->draw(sprite);
sf::Color savedColor = sprite.getColor();
sprite.setColor(sf::Color(255, 255, 255, 100 + cos(age * (timer < 2.0f ? 25 : 10)) * 30 ));
sprite.setTextureRect(sf::IntRect( (firstFrame + 1) * width, 9 * height, width, height));
app->draw(sprite);
sprite.setColor(savedColor);
}
// divine field
if (divinity.level > 1)
{
bool displayField = false;
int fieldFrame;
int fieldFade;
switch (divinity.divinity)
{
case DivinityHealer:
{
displayField = true;
fieldFrame = 10;
fieldFade = 40 * (divinity.level - 1);
break;
}
case DivinityFighter:
{
displayField = true;
fieldFrame = 12;
fieldFade = 40 * (divinity.level - 1);
break;
}
case DivinityIce:
{
if (divinity.level > 2)
{
displayField = true;
fieldFrame = 14;
fieldFade = 80 * (divinity.level - 3);
}
break;
}
case DivinityStone:
{
if (divinity.level > 2)
{
displayField = true;
fieldFrame = 16;
fieldFade = 80 * (divinity.level - 3);
}
break;
}
case DivinityAir:
{
if (divinity.level > 1)
{
displayField = true;
fieldFrame = 18;
fieldFade = 40 * (divinity.level - 1);
}
break;
}
}
if (displayField)
{
sf::Color savedColor = sprite.getColor();
sprite.setColor(sf::Color(255, 255, 255, fieldFade ));
sprite.setTextureRect(sf::IntRect( fieldFrame * width, 9 * height, width, height));
app->draw(sprite);
if (divinity.divinity != DivinityStone && divinity.divinity != DivinityHealer)
{
sprite.setColor(sf::Color(255, 255, 255, 2 + fieldFade / 2 + cos(age * 15) * fieldFade / 2 ));
sprite.setTextureRect(sf::IntRect( (fieldFrame + 1) * width, 9 * height, width, height));
app->draw(sprite);
sprite.setColor(savedColor);
}
if (divinity.divinity == DivinityHealer && divineInterventionDelay > 0.0f && isRegeneration)
{
sprite.setTextureRect(sf::IntRect( (fieldFrame + 1) * width, 9 * height, width, height));
app->draw(sprite);
}
sprite.setColor(savedColor);
}
}
}
if (game().getShowLogical() && playerStatus != playerStatusDead)
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void PlayerEntity::calculateBB()
{
if (isFairyTransmuted)
{
boundingBox.left = (int)x - 10;
boundingBox.width = 20;
boundingBox.top = (int)y - 29;
boundingBox.height = 20;
}
else
{
boundingBox.left = (int)x - 10;
boundingBox.width = 20;
boundingBox.top = (int)y - 29;
boundingBox.height = 33;
}
}
void PlayerEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (playerStatus == playerStatusDead || !canCollide()) return;
EnemyBoltEntity* boltEntity = dynamic_cast<EnemyBoltEntity*>(entity);
if (collideWithEntity(entity))
{
if (boltEntity != NULL && !boltEntity->getDying())
{
boltEntity->collide();
// TODO bolt source
hurt(getHurtParams(boltEntity->getDamages(),
boltEntity->getBoltType(),
boltEntity->getLevel(),
boltEntity->isCritical(),
SourceTypeBolt,
boltEntity->getEnemyType(),
false));
game().generateBlood(x, y, bloodColor);
float xs = (x + boltEntity->getX()) / 2;
float ys = (y + boltEntity->getY()) / 2;
SpriteEntity* star = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_HURT_IMPACT), xs, ys);
star->setFading(true);
star->setZ(y+ 100);
star->setLifetime(0.7f);
star->setType(ENTITY_EFFECT);
star->setSpin(400.0f);
}
}
}
bool PlayerEntity::willCollideWithMap(int dx, int dy, bool checkMiddle)
{
float oldX = x, oldY = y;
bool collide = true;
x = oldX + dx;
y = oldY + dy;
if (!isCollidingWithMap())
collide = false;
else if (checkMiddle)
{
x = oldX + dx / 2;
y = oldY + dy / 2;
if (!isCollidingWithMap())
collide = false;
}
x = oldX;
y = oldY;
return collide;
}
void PlayerEntity::move(int direction)
{
float oldX = x, oldY = y;
bool touchUp, touchDown, touchLeft, touchRight;
x = oldX + 1;
touchRight = isCollidingWithMap();
x = oldX - 1;
touchLeft = isCollidingWithMap();
x = oldX;
y = oldY + 1;
touchDown = isCollidingWithMap();
y = oldY - 1;
touchUp = isCollidingWithMap();
y = oldY;
if (specialState[SpecialStateConfused].active)
{
switch (direction)
{
case 4: direction = 6; break;
case 6: direction = 4; break;
case 2: direction = 8; break;
case 8: direction = 2; break;
case 1: direction = 9; break;
case 9: direction = 1; break;
case 7: direction = 3; break;
case 3: direction = 7; break;
}
}
keyDirection = direction;
if (playerStatus == playerStatusAcquire && statusTimer < ACQUIRE_DELAY / 2)
{
acquireItemAfterStance();
}
if (playerStatus == playerStatusPlaying)
{
switch (keyDirection)
{
case 1:
if (touchDown && touchLeft)
{
direction = 5;
collidingDirection = 1;
}
else if (touchDown)
{
direction = 4;
collidingDirection = 2;
}
else if (touchLeft)
{
direction = 2;
collidingDirection = 4;
}
break;
case 3:
if (touchDown && touchRight)
{
direction = 5;
collidingDirection = 3;
}
else if (touchDown)
{
direction = 6;
collidingDirection = 2;
}
else if (touchRight)
{
direction = 2;
collidingDirection = 6;
}
break;
case 7:
if (touchUp && touchLeft)
{
direction = 5;
collidingDirection = 7;
}
else if (touchUp)
{
direction = 4;
collidingDirection = 8;
}
else if (touchRight)
{
direction = 8;
collidingDirection = 1;
}
break;
case 9:
if (touchUp && touchRight)
{
direction = 5;
collidingDirection = 9;
}
else if (touchUp)
{
direction = 6;
collidingDirection = 8;
}
else if (touchRight)
{
direction = 8;
collidingDirection = 6;
}
break;
case 4:
if (touchLeft)
{
x = oldX - 2;
if (!willCollideWithMap(0, KEYS_MOVE_TOLERANCE, true))
direction = 2;
else if (!willCollideWithMap(0, -KEYS_MOVE_TOLERANCE, true))
direction = 8;
else
{
direction = 5;
collidingDirection = 4;
}
x = oldX;
}
break;
case 6:
if (touchRight)
{
x = oldX + 2;
if (!willCollideWithMap(0, KEYS_MOVE_TOLERANCE, true))
direction = 2;
else if (!willCollideWithMap(0, -KEYS_MOVE_TOLERANCE, true))
direction = 8;
else
{
direction = 5;
collidingDirection = 6;
}
x = oldX;
}
break;
case 8:
if (touchUp)
{
y = oldY - 2;
if (!willCollideWithMap(KEYS_MOVE_TOLERANCE, 0, true))
direction = 6;
else if (!willCollideWithMap(-KEYS_MOVE_TOLERANCE, 0, true))
direction = 4;
else
{
direction = 5;
collidingDirection = 8;
}
y = oldY;
}
break;
case 2:
if (touchDown)
{
y = oldY + 2;
if (!willCollideWithMap(KEYS_MOVE_TOLERANCE, 0, true))
direction = 6;
else if (!willCollideWithMap(-KEYS_MOVE_TOLERANCE, 0, true))
direction = 4;
else
{
direction = 5;
collidingDirection = 2;
}
y = oldY;
}
break;
}
float speedx = 0.0f, speedy = 0.0f;
if (direction == 4)
speedx = - creatureSpeed;
else if (direction == 1 || direction == 7)
speedx = - creatureSpeed * 0.7f;
else if (direction == 6)
speedx = creatureSpeed;
else if (direction == 3 || direction == 9)
speedx = creatureSpeed * 0.7f;
if (direction == 2)
speedy = creatureSpeed;
else if (direction == 1 || direction == 3)
speedy = creatureSpeed * 0.7f;
else if (direction == 8)
speedy = - creatureSpeed;
else if (direction == 7 || direction == 9)
speedy = - creatureSpeed * 0.7f;
setVelocity(Vector2D(speedx, speedy));
{
switch (keyDirection)
{
case 8:
facingDirection = 8;
break;
case 2:
facingDirection = 2;
break;
case 4:
facingDirection = 4;
break;
case 6:
facingDirection = 6;
break;
case 7:
if (facingDirection != 4 && facingDirection != 8) facingDirection = 4;
break;
case 1:
if (facingDirection != 4 && facingDirection != 2) facingDirection = 4;
break;
case 9:
if (facingDirection != 6 && facingDirection != 8) facingDirection = 6;
break;
case 3:
if (facingDirection != 6 && facingDirection != 2) facingDirection = 6;
break;
}
}
}
}
bool PlayerEntity::isMoving()
{
if (velocity.x < -1.0f || velocity.x > 1.0f) return true;
if (velocity.y < -1.0f || velocity.y > 1.0f) return true;
return false;
}
bool PlayerEntity::isEquiped(int eq)
{
return equip[eq];
}
bool* PlayerEntity::getEquipment()
{
return equip;
}
void PlayerEntity::setEquiped(int item, bool toggleEquipped)
{
equip[item] = toggleEquipped;
if (toggleEquipped && items[FirstEquipItem + item].familiar > FamiliarNone)
{
FairyEntity* fairy = new FairyEntity(x - 50.0f + rand() % 100,
y - 50.0f + rand() % 100,
items[FirstEquipItem + item].familiar);
fairies.push_back(fairy);
//if (fairies.size() == 3) game().registerAchievement(AchievementFairies);
}
computePlayer();
}
void PlayerEntity::generateBolt(float velx, float vely)
{
enumShotType boltType = ShotTypeStandard;
unsigned int shotLevel = 1;
switch (getShotType())
{
case ShotTypeIce:
if (getShotType() == ShotTypeIce)
{
if (specialBoltTimer <= 0.0f)
{
boltType = ShotTypeIce;
shotLevel = getShotLevel();
needInitShotType = true;
}
else boltType = ShotTypeCold;
}
break;
case ShotTypeStandard:
case ShotTypeIllusion:
case ShotTypeStone:
case ShotTypeLightning:
case ShotTypeFire:
case ShotTypePoison:
boltType = getShotType();
shotLevel = getShotLevel();
break;
default:
std::cout << "[WARNING] Can not generate shot type: " << getShotType() << std::endl;
}
BoltEntity* bolt = new BoltEntity(x, getBolPositionY(), boltLifeTime, boltType, shotLevel);
bolt->setFlying(isFairyTransmuted);
int boltDamage = fireDamages;
if (criticalChance > 0)
if (rand()% 100 < criticalChance)
{
boltDamage *= equip[EQUIP_CRITICAL_ADVANCED] ? 3 : 2;
bolt->setCritical(true);
}
bolt->setDamages(boltDamage);
if (equip[EQUIP_GLOVES_ADVANCED])
{
if (firingDirection == 2 || firingDirection == 8)
velx += velocity.x * 0.7f;
else if (firingDirection == 4 || firingDirection == 6)
vely += velocity.y * 0.7f;
}
bolt->setVelocity(Vector2D(velx, vely));
}
void PlayerEntity::rageFire()
{
for (int i = -1; i <= 1; i += 2)
for (int j = -1; j <= 1; j += 2)
{
BoltEntity* bolt = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypeFire, 0);
bolt->setDamages(10);
bolt->setFlying(isFairyTransmuted);
float velx = fireVelocity * i * 0.42f;
float vely = fireVelocity * j * 0.42f;
bolt->setVelocity(Vector2D(velx, vely));
if (hp <= hpMax / 5)
{
BoltEntity* bolt = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypeFire, 0);
bolt->setDamages(10);
bolt->setFlying(isFairyTransmuted);
float velx = 0.0f;
float vely = 0.0f;
if (i == -1 && j == -1) velx = -fireVelocity * i * 0.6f;
else if (i == -1 && j == 1) velx = fireVelocity * i * 0.6f;
else if (i == 1 && j == -1) vely= -fireVelocity * i * 0.6f;
else if (i == 1 && j == 1) vely = fireVelocity * i * 0.6f;
bolt->setVelocity(Vector2D(velx, vely));
}
}
SoundManager::getInstance().playSound(SOUND_BLAST_FIRE);
}
void PlayerEntity::resestFireDirection()
{
firingDirection = 5;
}
int PlayerEntity::getFireDirection()
{
return firingDirection;
}
void PlayerEntity::fire(int direction)
{
firingDirection = direction;
if (playerStatus != playerStatusDead)
for(int unsigned i = 0; i < fairies.size(); i++)
fairies[i]->fire(direction);
if (canFirePlayer && playerStatus != playerStatusDead && playerStatus != playerStatusAcquire)
{
switch (getShotType())
{
case ShotTypeCold:
case ShotTypeIce:
SoundManager::getInstance().playPitchModSound(SOUND_BLAST_ICE);
break;
case ShotTypeFire:
SoundManager::getInstance().playPitchModSound(SOUND_BLAST_FIRE);
break;
case ShotTypeIllusion:
SoundManager::getInstance().playPitchModSound(SOUND_BLAST_ILLUSION);
break;
case ShotTypeLightning:
SoundManager::getInstance().playPitchModSound(SOUND_BLAST_LIGHTNING);
break;
case ShotTypePoison:
SoundManager::getInstance().playPitchModSound(SOUND_BLAST_POISON);
break;
case ShotTypeStone:
SoundManager::getInstance().playPitchModSound(SOUND_BLAST_STONE);
break;
default:
SoundManager::getInstance().playPitchModSound(SOUND_BLAST_STANDARD);
break;
}
if (equip[EQUIP_BOOK_DUAL] || equip[EQUIP_BOOK_TRIPLE]
|| equip[EQUIP_BOOK_DUAL_QUICK] || equip[EQUIP_BOOK_TRIPLE_QUICK])
{
float shoot_angle = 0.2f;
if ((direction == 4 && velocity.x < -1.0f) || (direction == 6 && velocity.x > 1.0f)
|| (direction == 8 && velocity.y < -1.0f) || (direction == 2 && velocity.y > 1.0f))
shoot_angle = 0.1f;
else if ((direction == 6 && velocity.x < -1.0f) || (direction == 4 && velocity.x > 1.0f)
|| (direction == 2 && velocity.y < -1.0f) || (direction == 8 && velocity.y > 1.0f))
shoot_angle = (equip[EQUIP_BOOK_TRIPLE] || equip[EQUIP_BOOK_TRIPLE_QUICK]) ? 0.35f : 0.2f;
else if (!equip[EQUIP_BOOK_TRIPLE] && !equip[EQUIP_BOOK_TRIPLE_QUICK])
shoot_angle = 0.1f;
switch(direction)
{
case 4:
generateBolt(-fireVelocity * cos(shoot_angle), fireVelocity * sin(shoot_angle));
generateBolt(-fireVelocity * cos(shoot_angle), - fireVelocity * sin(shoot_angle));
break;
case 6:
generateBolt(fireVelocity * cos(shoot_angle), fireVelocity * sin(shoot_angle));
generateBolt(fireVelocity * cos(shoot_angle), - fireVelocity * sin(shoot_angle));
break;
case 8:
generateBolt(fireVelocity * sin(shoot_angle), -fireVelocity * cos(shoot_angle));
generateBolt(-fireVelocity * sin(shoot_angle), - fireVelocity * cos(shoot_angle));
break;
case 2:
generateBolt(fireVelocity * sin(shoot_angle), fireVelocity * cos(shoot_angle));
generateBolt(-fireVelocity * sin(shoot_angle), fireVelocity * cos(shoot_angle));
break;
}
}
if (equip[EQUIP_RAPID_SHOT])
{
Vector2D boltDirection;
switch(direction)
{
case 4:
boltDirection = Vector2D(0, 0).vectorNearlyTo(Vector2D(-1, 0), fireVelocity, 0.2f);
break;
case 6:
boltDirection = Vector2D(0, 0).vectorNearlyTo(Vector2D(1, 0), fireVelocity, 0.2f);
break;
case 8:
boltDirection = Vector2D(0, 0).vectorNearlyTo(Vector2D(0, -1), fireVelocity, 0.2f);
break;
case 2:
boltDirection = Vector2D(0, 0).vectorNearlyTo(Vector2D(0, 1), fireVelocity, 0.2f);
break;
}
generateBolt(boltDirection.x, boltDirection.y);
}
else if (!(equip[EQUIP_BOOK_DUAL] || equip[EQUIP_BOOK_DUAL_QUICK]) || (equip[EQUIP_BOOK_TRIPLE] || equip[EQUIP_BOOK_TRIPLE_QUICK]))
{
switch(direction)
{
case 4:
generateBolt(-fireVelocity, 0.0f);
break;
case 6:
generateBolt(fireVelocity, 0.0f);
break;
case 8:
generateBolt(0.0f, -fireVelocity);
break;
case 2:
generateBolt(0.0f, fireVelocity);
break;
}
}
if (equip[EQUIP_REAR_SHOT])
{
BoltEntity* bolt = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypeStandard, 0);
bolt->setDamages(fireDamages / 2);
bolt->setFlying(isFairyTransmuted);
float velx = 0.0f;
float vely = 0.0f;
switch (direction)
{
case 4:
velx = fireVelocity * 0.75f;
break;
case 6:
velx = -fireVelocity * 0.75f;
break;
case 2:
vely = -fireVelocity * 0.75f;
break;
case 8:
vely = fireVelocity * 0.75f;
break;
}
bolt->setVelocity(Vector2D(velx, vely));
}
if (equip[EQUIP_BOOK_RANDOM] && randomFireDelay <= 0.0f)
{
BoltEntity* bolt = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypeStandard, 0);
bolt->setDamages(fireDamages);
bolt->setFlying(isFairyTransmuted);
float shotAngle = rand() % 360;
bolt->setVelocity(Vector2D(fireVelocity * 0.75f * cos(shotAngle), fireVelocity * 0.75f * sin(shotAngle)));
randomFireDelay = fireDelay * 1.5f;
}
canFirePlayer = false;
currentFireDelay = fireDelay;
if (needInitShotType) initShotType();
}
}
bool PlayerEntity::canMove()
{
return (playerStatus == playerStatusPlaying
|| (playerStatus == playerStatusAcquire && statusTimer < ACQUIRE_DELAY / 2));
}
int PlayerEntity::hurt(StructHurt hurtParam)
{
if (playerStatus == playerStatusDead) return false;
if (isFairyTransmuted && hurtParam.hurtingType != ShotTypeDeterministic)
{
hurtParam.damage *= 2;
}
bool divinityInvoked = false;
if (hp - hurtParam.damage <= hpMax / 4 && divinity.divinity >= 0)
{
divinityInvoked = triggerDivinityBefore();
if (divinityInvoked)
game().testAndAddMessageToQueue((EnumMessages)(MsgInfoDivIntervention));
}
if (invincibleDelay <= 0.0f || hurtParam.hurtingType == ShotTypeDeterministic)
{
SoundManager::getInstance().playSound(SOUND_PLAYER_HIT);
int oldHp = hp;
if (BaseCreatureEntity::hurt(hurtParam) > 0)
{
if (hurtParam.hurtingType != ShotTypeDeterministic)
{
invincibleDelay = INVINCIBLE_DELAY;
if (equip[EQUIP_RAGE_AMULET]) rageFire();
game().generateBlood(x, y, bloodColor);
}
hurtingDelay = HURTING_DELAY * 2.0f;
game().generateBlood(x, y, bloodColor);
game().proceedEvent(EventBeingHurted);
lastHurtingEnemy = hurtParam.enemyType;
lastHurtingSource = hurtParam.sourceType;
// divinity
offerHealth(oldHp - hp);
if (!divinityInvoked && hp <= hpMax / 4 && divinity.divinity >= 0)
{
triggerDivinityAfter();
}
return true;
}
}
return false;
}
void PlayerEntity::setMap(GameMap* map, int tileWidth, int tileHeight, int offsetX, int offsetY)
{
CollidingSpriteEntity::setMap(map, tileWidth, tileHeight, offsetX, offsetY);
//if (slimePet != NULL) slimePet->setMap(map, tileWidth, tileHeight, offsetX, offsetY);
}
void PlayerEntity::loseItem(enumItemType itemType, bool isEquip)
{
CollidingSpriteEntity* itemSprite
= new CollidingSpriteEntity(ImageManager::getInstance().getImage(isEquip ? IMAGE_ITEMS_EQUIP : IMAGE_ITEMS), x, y, 32, 32);
itemSprite->setMap(map, TILE_WIDTH, TILE_HEIGHT, 0, 0);
itemSprite->setZ(-1);
itemSprite->setFrame(itemType);
itemSprite->setImagesProLine(10);
itemSprite->setType(ENTITY_BLOOD);
itemSprite->setVelocity(Vector2D(200 + rand()%450));
itemSprite->setViscosity(0.95f);
itemSprite->setSpin( (rand() % 700) - 350.0f);
}
void PlayerEntity::dying()
{
if (divinity.divinity > -1 && divinity.interventions < divinity.level - 1)
{
hp = 1;
return;
}
playerStatus = playerStatusDead;
deathAge = 0.0f;
hp = 0;
SoundManager::getInstance().playSound(SOUND_PLAYER_DIE);
setVelocity(Vector2D(0.0f, 0.0f));
int i;
for (i = 0; i < gold && i < 10; i++) loseItem(ItemCopperCoin, false);
for (i = 0; i < 5; i++) game().generateBlood(x, y, BloodRed);
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++)
{
if (equip[i])
{
if (items[i + FirstEquipItem].familiar == FamiliarNone)
loseItem(enumItemType(i), true);
}
}
remove(SAVE_FILE.c_str());
game().calculateScore();
}
void PlayerEntity::displayAcquiredGold(int n)
{
std::ostringstream oss;
if (n > 0) oss << "+";
oss << n;
TextEntity* text = new TextEntity(oss.str(), 16, x, y - 30.0f);
text->setColor(TextEntity::COLOR_FADING_YELLOW);
text->setAge(-0.6f);
text->setLifetime(0.3f);
text->setWeight(-60.0f);
text->setZ(2000);
text->setAlignment(ALIGN_CENTER);
text->setType(ENTITY_FLYING_TEXT);
}
void PlayerEntity::acquireItem(enumItemType type)
{
if (items[type].generatesStance) acquireStance(type);
else switch (type)
{
case ItemCopperCoin:
gold++;
displayAcquiredGold(1);
SoundManager::getInstance().playSound(SOUND_COIN_PICK_UP);
game().proceedEvent(EventGetCoin);
break;
case ItemSilverCoin:
gold = gold + 5;
displayAcquiredGold(5);
SoundManager::getInstance().playSound(SOUND_COIN_PICK_UP);
game().proceedEvent(EventGetCoin);
break;
case ItemGoldCoin:
gold = gold + 10;
displayAcquiredGold(10);
SoundManager::getInstance().playSound(SOUND_COIN_PICK_UP);
game().proceedEvent(EventGetCoin);
break;
case ItemHealthVerySmallPoison:
specialState[SpecialStatePoison].active = false;
case ItemHealthVerySmall:
heal(equip[EQUIP_MANUAL_HEALTH] ? 5 : 3);
SoundManager::getInstance().playSound(SOUND_EAT);
break;
case ItemHealthSmall:
heal(equip[EQUIP_MANUAL_HEALTH] ? 10 : 7);
SoundManager::getInstance().playSound(SOUND_EAT);
break;
case ItemHealth:
heal(equip[EQUIP_MANUAL_HEALTH] ? 22 : 15);
SoundManager::getInstance().playSound(SOUND_EAT);
break;
default:
break;
}
}
void PlayerEntity::onClearRoom()
{
if (divinity.divinity == DivinityHealer)
{
if (divinity.level > 1 && hp < hpMax)
{
divineInterventionDelay = WORSHIP_DELAY / 2;
isRegeneration = true;
if (divinity.level >= 5) heal(4);
else if (divinity.level >= 4) heal(3);
else if (divinity.level >= 3) heal(2);
else if (divinity.level >= 2) heal(1);
}
}
}
void PlayerEntity::computePlayer()
{
float boltLifeTimeBonus = 1.0f;
float fireDelayBonus = 1.0f;
float creatureSpeedBonus = 1.0f;
float fireVelocityBonus = 1.0f;
float fireDamagesBonus = 1.0f;
armor = 0.0f;
criticalChance = 0;
for (int i = 0; i < NB_RESISTANCES; i++) resistance[i] = ResistanceStandard;
if (equip[EQUIP_GLOVES_ADVANCED]) fireDelayBonus -= 0.15f;
else if (equip[EQUIP_DISPLACEMENT_GLOVES]) fireDelayBonus -= 0.10f;
if (equip[EQUIP_HAT_ADVANCED])
{
fireDelayBonus -= 0.3f;
resistance[ResistanceIce] = (enumStateResistance)(resistance[ResistanceIce] - 1);
resistance[ResistanceStone] = (enumStateResistance)(resistance[ResistanceStone] - 1);
resistance[ResistanceLightning] = (enumStateResistance)(resistance[ResistanceLightning] - 1);
resistance[ResistanceFire] = (enumStateResistance)(resistance[ResistanceFire] - 1);
}
else if (equip[EQUIP_MAGICIAN_HAT]) fireDelayBonus -= 0.2f;
if (equip[EQUIP_LEATHER_BELT]) fireDelayBonus -= 0.15f;
if (equip[EQUIP_BOOTS_ADVANCED]) creatureSpeedBonus += 0.25f;
else if (equip[EQUIP_LEATHER_BOOTS]) creatureSpeedBonus += 0.15f;
if (equip[EQUIP_BOOK_TRIPLE]) fireDelayBonus += 0.7f;
else if (equip[EQUIP_BOOK_DUAL]) fireDelayBonus += 0.5f;
if (equip[EQUIP_CRITICAL]) criticalChance += 5;
if (equip[EQUIP_MANUAL_STAFF]) boltLifeTimeBonus += 0.4f;
if (equip[EQUIP_MAHOGANY_STAFF])
{
fireVelocityBonus += 0.15f;
fireDamagesBonus += 0.5f;
}
if (equip[EQUIP_BLOOD_SNAKE]) fireDamagesBonus += 0.5f;
if (equip[EQUIP_ROBE_ADVANCED]) armor += 0.2f;
else if (equip[EQUIP_MAGICIAN_ROBE]) armor += 0.15f;
// divinity
switch (divinity.divinity)
{
case (DivinityHealer):
{
break;
}
case (DivinityFighter):
{
if (divinity.level >= 5)
fireDamagesBonus += 0.5f;
else if (divinity.level >= 4)
fireDamagesBonus += 0.375f;
else if (divinity.level >= 3)
fireDamagesBonus += 0.25f;
else if (divinity.level >= 2)
fireDamagesBonus += 0.125f;
break;
}
case (DivinityIce):
{
if (divinity.level >= 5) resistance[ResistanceFrozen] = ResistanceVeryHigh;
if (divinity.level >= 3) resistance[ResistanceIce] = (enumStateResistance)(resistance[ResistanceIce] - 1);
break;
}
case (DivinityStone):
{
if (divinity.level >= 5) resistance[ResistanceRecoil] = ResistanceVeryHigh;
if (divinity.level >= 3) resistance[ResistanceStone] = (enumStateResistance)(resistance[ResistanceStone] - 1);
break;
}
case (DivinityAir):
{
if (divinity.level > 1) creatureSpeedBonus += (divinity.level - 1) * 0.04f;
if (divinity.level >= 3) resistance[ResistanceLightning] = (enumStateResistance)(resistance[ResistanceLightning] - 1);
break;
}
}
fireDelay = INITIAL_PLAYER_FIRE_DELAY * fireDelayBonus;
creatureSpeed = INITIAL_PLAYER_SPEED * creatureSpeedBonus;
fireVelocity = INITIAL_BOLT_VELOCITY * fireVelocityBonus;
fireDamages = INITIAL_BOLT_DAMAGES * fireDamagesBonus;
boltLifeTime = INITIAL_BOLT_LIFE * boltLifeTimeBonus;
// gems
for (int i = 1; i < SPECIAL_SHOT_SLOTS; i++)
{
specialShotLevel[i] = 0;
switch (specialShots[i])
{
case ShotTypeIce:
if (equip[EQUIP_RING_ICE]) specialShotLevel[i]++;
if (divinity.divinity == DivinityIce && divinity.level >= 4) specialShotLevel[i]++;
break;
case ShotTypeStone:
if (equip[EQUIP_RING_STONE]) specialShotLevel[i]++;
if (divinity.divinity == DivinityStone && divinity.level >= 4) specialShotLevel[i]++;
break;
case ShotTypeLightning:
if (equip[EQUIP_RING_LIGHTNING]) specialShotLevel[i]++;
if (divinity.divinity == DivinityAir && divinity.level >= 4) specialShotLevel[i]++;
break;
case ShotTypeIllusion:
if (equip[EQUIP_RING_ILLUSION]) specialShotLevel[i]++;
break;
case ShotTypeFire:
if (equip[EQUIP_RING_FIRE]) specialShotLevel[i]++;
break;
case ShotTypePoison:
if (equip[EQUIP_RING_POISON]) specialShotLevel[i]++;
break;
default:
break;
}
}
if (getShotType() == ShotTypeIllusion) fireDamages *= ILLUSION_DAMAGE_DECREASE[getShotLevel()];
else if (getShotType() == ShotTypeFire) fireDamages *= FIRE_DAMAGE_INCREASE[getShotLevel()];
// divinity
if (specialState[DivineStateProtection].active)
armor += specialState[DivineStateProtection].param1;
// post-computation
if (equip[EQUIP_BOOK_TRIPLE_QUICK]) fireDamages *= 0.65f;
else if (equip[EQUIP_BOOK_DUAL_QUICK]) fireDamages *= 0.75f;
else if (equip[EQUIP_RAPID_SHOT])
{
fireDelay *= 0.20f;
fireDamages *= 0.25f;
}
if (equip[EQUIP_ALCOHOL]) fireDamages *= 1.25f;
// spells
if (protection.active) armor += protection.value;
if (armor > 1.0f) armor = 1.0f;
// fairy ?
if (isFairyTransmuted)
{
fireDamages *= 0.5f;
creatureSpeed *= 1.5f;
movingStyle = movFlying;
}
else
{
movingStyle = movWalking;
}
}
void PlayerEntity::acquireStance(enumItemType type)
{
velocity.x = 0.0f;
velocity.y = 0.0f;
playerStatus = playerStatusAcquire;
statusTimer = ACQUIRE_DELAY;
acquiredItem = (enumItemType)(type);
SoundManager::getInstance().playSound(SOUND_BONUS);
game().showArtefactDescription(type);
enumItemType itemFrame = type;
int itemImage = IMAGE_ITEMS;
if (itemFrame >= FirstEquipItem)
{
itemFrame = (enumItemType)(itemFrame - FirstEquipItem);
itemImage = IMAGE_ITEMS_EQUIP;
}
spriteItem = new SpriteEntity(
ImageManager::getInstance().getImage(itemImage),
x, y - 100.0f, ITEM_WIDTH, ITEM_HEIGHT);
spriteItem->setFrame((int)itemFrame);
spriteItem->setImagesProLine(10);
spriteItem->setZ(z);
spriteItem->setLifetime(ACQUIRE_DELAY);
spriteItemStar = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_STAR),
x, y - 100.0f);
spriteItemStar->setScale(4.0f, 4.0f);
spriteItemStar->setZ(z-1.0f);
spriteItemStar->setLifetime(ACQUIRE_DELAY);
spriteItemStar->setSpin(50.0f);
}
void PlayerEntity::collideMapRight()
{
collidingDirection = 6;
if (recoil.active) recoil.velocity.x = -recoil.velocity.x * 0.7f;
}
void PlayerEntity::collideMapLeft()
{
collidingDirection = 4;
if (recoil.active) recoil.velocity.x = -recoil.velocity.x * 0.7f;
}
void PlayerEntity::collideMapTop()
{
collidingDirection = 8;
if (recoil.active) recoil.velocity.y= -recoil.velocity.y * 0.7f;
}
void PlayerEntity::collideMapBottom()
{
collidingDirection = 2;
if (recoil.active) recoil.velocity.y= -recoil.velocity.y * 0.7f;
}
void PlayerEntity::useBossKey()
{
velocity.x = 0.0f;
velocity.y = 0.0f;
playerStatus = playerStatusUnlocking;
statusTimer = UNLOCK_DELAY;
acquiredItem = (enumItemType)(type - FirstEquipItem);
SoundManager::getInstance().playSound(SOUND_DOOR_OPENING_BOSS);
equip[EQUIP_BOSS_KEY] = false;
SpriteEntity* spriteItem = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP),
x, y - 80.0f, ITEM_WIDTH, ITEM_HEIGHT);
spriteItem->setFrame(EQUIP_BOSS_KEY);
spriteItem->setZ(z);
spriteItem->setAge(-UNLOCK_DELAY * 0.5f);
spriteItem->setLifetime(UNLOCK_DELAY * 0.5f);
spriteItem->setFading(true);
spriteItem->setSpin(300);
}
enumShotType PlayerEntity::getShotType()
{
return specialShots[specialShotIndex];
}
int PlayerEntity::getShotIndex()
{
return specialShotIndex;
}
void PlayerEntity::setShotIndex(int index)
{
specialShotIndex = index;
}
enumShotType PlayerEntity::getShotType(int slot)
{
return specialShots[slot];
}
void PlayerEntity::setShotType(int slot, enumShotType shotType)
{
specialShots[slot] = shotType;
}
void PlayerEntity::registerSpecialShot(int item)
{
bool found = false;
int index = 1;
while (index < SPECIAL_SHOT_SLOTS && !found)
{
found = specialShots[index] == ShotTypeStandard;
if (!found) index++;
}
if (found)
{
this->specialShots[index] = items[item].specialShot;
specialShotIndex = index;
initShotType();
}
}
void PlayerEntity::selectNextShotType()
{
int index = specialShotIndex + 1;
bool found = false;
while (index < SPECIAL_SHOT_SLOTS && !found)
{
if (specialShots[index] == ShotTypeStandard) index++;
else found = true;
}
if (found)
{
specialShotIndex = index;
initShotType();
}
else
specialShotIndex = 0;
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
computePlayer();
}
void PlayerEntity::initShotType()
{
specialBoltTimer = STATUS_FROZEN_BOLT_DELAY[getShotLevel()];
needInitShotType = false;
if (getShotType() == ShotTypeLightning)
SoundManager::getInstance().playSound(SOUND_ELECTRIC_CHARGE);
}
unsigned int PlayerEntity::getShotLevel()
{
return specialShotLevel[specialShotIndex];
}
unsigned int PlayerEntity::getShotLevel(int index)
{
return specialShotLevel[index];
}
int PlayerEntity::getFairieNumber()
{
return fairies.size();
}
FairyEntity* PlayerEntity::getFairy(unsigned int n)
{
if (n < fairies.size())
return fairies[n];
else
return NULL;
}
bool PlayerEntity::canGetNewShot(bool advancedShot)
{
int nbSpecial =0;
int nbAdvanced =0;
for (int i = 1; i < SPECIAL_SHOT_SLOTS; i++)
{
switch (specialShots[i])
{
case ShotTypeIce:
case ShotTypeStone:
case ShotTypeLightning:
nbSpecial++;
break;
case ShotTypeFire:
case ShotTypeIllusion:
case ShotTypePoison:
nbAdvanced++;
break;
case ShotTypeStandard:
break;
default:
std::cout << "[WARNING] Can not register shot type: " << getShotType() << std::endl;
}
}
if (advancedShot)
return (nbAdvanced >= SPECIAL_SHOT_SLOTS_ADVANCED);
else
return (nbSpecial >= SPECIAL_SHOT_SLOTS_STANDARD);
}
void PlayerEntity::interact(EnumInteractionType interaction, int id)
{
if (playerStatus == playerStatusPlaying)
{
// praying at the temple
if (interaction == InteractionTypeTemple)
{
if (divinity.divinity == id)
{
// donation
if (gold >= 10)
{
donate(10);
}
}
else
{
worship((enumDivinityType)id);
}
}
else if (interaction == InteractionTypeMerchandise)
{
if (itemToBuy != NULL) itemToBuy->buy();
}
}
}
float PlayerEntity::getBolPositionY()
{
if (isFairyTransmuted)
return y - 25;
else
return y - 20;
}
bool PlayerEntity::collideWithMap(int direction)
{
if (playerStatus == playerStatusEntering)
return false;
else
return BaseCreatureEntity::collideWithMap(direction);
}
// DIVINITY
void PlayerEntity::donate(int n)
{
if (gold >= n)
{
gold -= n;
displayAcquiredGold(-n);
SoundManager::getInstance().playSound(SOUND_PAY);
// standard : 1 gold = 3 piety
int pietyProGold = 3;
if (divinity.divinity == DivinityHealer)
pietyProGold = 5;
addPiety(pietyProGold * n);
// check item invoke
bool divineGift = false;
enumItemType itemType = ItemCopperCoin;
if (divinity.level >= 3 && game().getItemsCount() == 0)
{
if (divinity.divinity == DivinityHealer && !equip[EQUIP_MANUAL_HEALTH])
{
// Healer + level 3 = Health manual
divineGift = true;
itemType = ItemManualHealth;
}
else if (divinity.divinity == DivinityIce && !equip[EQUIP_GEM_ICE])
{
divineGift = true;
itemType = ItemGemIce;
}
else if (divinity.divinity == DivinityStone && !equip[EQUIP_GEM_STONE])
{
divineGift = true;
itemType = ItemGemStone;
}
else if (divinity.divinity == DivinityAir && !equip[EQUIP_GEM_LIGHTNING])
{
divineGift = true;
itemType = ItemGemLightning;
}
}
if (divineGift)
{
float xItem = GAME_WIDTH / 2;
float yItem = GAME_HEIGHT * 0.8f;
new ItemEntity(itemType, xItem, yItem);
SoundManager::getInstance().playSound(SOUND_OM);
divineInterventionDelay = WORSHIP_DELAY / 2;
isRegeneration = false;
for (int i = 0; i < 8; i++)
{
game().generateStar(sf::Color::White, xItem, yItem);
game().generateStar(sf::Color(255, 255, 210), xItem, yItem);
}
game().testAndAddMessageToQueue((EnumMessages)(MsgInfoDivGift));
}
}
}
void PlayerEntity::offerMonster(enemyTypeEnum monster, enumShotType hurtingType)
{
if (divinity.divinity > -1)
{
// standard : 1 monster = 2 piety - 1 boss = 20 piety
int pietyProMonster = 2;
int pietyProBoss = 20;
switch (divinity.divinity)
{
case DivinityHealer:
if (monster == EnemyTypeGhost
|| monster == EnemyTypeZombie
|| monster == EnemyTypeZombieDark
|| monster == EnemyTypeImpBlue
|| monster == EnemyTypeImpRed
|| monster == EnemyTypeWitch
|| monster == EnemyTypeWitchRed
|| monster == EnemyTypeBogeyman)
pietyProMonster = 4;
else
pietyProMonster = 0;
break;
case DivinityFighter:
pietyProMonster = 3;
pietyProBoss = 30;
break;
case DivinityIce:
if (monster == EnemyTypeSlimeRed
|| monster == EnemyTypeImpRed
|| monster == EnemyTypeEvilFlowerFire)
pietyProMonster = 4;
if (hurtingType == ShotTypeCold || hurtingType == ShotTypeIce)
{
pietyProMonster *= 1.5f;
pietyProBoss = 25;
}
break;
case DivinityStone:
if (hurtingType == ShotTypeCold || hurtingType == ShotTypeIce)
{
pietyProMonster = 3;
pietyProBoss = 30;
}
else
{
pietyProBoss = 25;
}
break;
}
if (monster < EnemyTypeButcher) // normal or mini-boss
{
addPiety(pietyProMonster);
}
else if (monster < EnemyTypeBat_invocated) // boss
{
addPiety(pietyProBoss);
}
}
}
void PlayerEntity::offerHealth(int lostHp)
{
if (divinity.divinity == DivinityHealer)
{
addPiety(lostHp * 2.5f);
}
}
void PlayerEntity::offerChallenge()
{
if (divinity.divinity >= 0)
addPiety(30);
}
void PlayerEntity::divineFury()
{
enumShotType shotType = ShotTypeStandard;
if (divinity.divinity == DivinityIce) shotType = ShotTypeIce;
else if (divinity.divinity == DivinityStone) shotType = ShotTypeStone;
else if (divinity.divinity == DivinityAir) shotType = ShotTypeLightning;
int multBonus = 6;
if (divinity.divinity == DivinityFighter) multBonus = 8;
for (int i = 0; i < (divinity.divinity == DivinityAir ? 16 : 32); i ++)
{
BoltEntity* bolt = new BoltEntity(TILE_WIDTH * 1.5f + rand() % (MAP_WIDTH - 3) * TILE_WIDTH ,
TILE_HEIGHT * 1.5f + rand() % (MAP_HEIGHT - 3) * TILE_HEIGHT,
boltLifeTime, shotType, 0);
bolt->setDamages(8 + divinity.level * multBonus);
float velx = 400 * cos(i);
float vely = 400 * sin(i);
bolt->setVelocity(Vector2D(velx, vely));
if (divinity.divinity == DivinityAir)
{
bolt->setFlying(true);
bolt->setLifetime(-1.0f);
}
else
{
bolt->setLifetime(8.0f);
}
bolt->setViscosity(1.0f);
bolt->setGoThrough(true);
bolt->setFromPlayer(false);
}
}
void PlayerEntity::divineDestroyUndead()
{
game().destroyUndead(40);
}
void PlayerEntity::divineIce()
{
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)
{
EnemyEntity* enemy = dynamic_cast<EnemyEntity*>(e);
enemy->setSpecialState(SpecialStateIce, true, 10.0f, 0.1f, 0.0f);
}
}
}
void PlayerEntity::divineRepulse()
{
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)
{
EnemyEntity* enemy = dynamic_cast<EnemyEntity*>(e);
enemy->giveRecoil(true, Vector2D(x, y).vectorTo(Vector2D(enemy->getX(), enemy->getY()), 700.0f), 2.0f);
}
}
// effect
for (int i = 0; i < 40; i++)
{
SpriteEntity* spriteRock = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_CYCLOP),
x, y, 64, 64);
spriteRock->setZ(1000.0f);
spriteRock->setImagesProLine(20);
spriteRock->setFrame(rand() % 2 == 0 ? 38 : 58);
spriteRock->setSpin(-100 + rand()%200);
spriteRock->setVelocity(Vector2D(400 + rand()%400));
spriteRock->setFading(true);
spriteRock->setAge(-0.8f);
spriteRock->setLifetime(2.0f);
spriteRock->setType(ENTITY_EFFECT);
}
game().makeShake(1.0f);
SoundManager::getInstance().playSound(SOUND_EARTHQUAKE);
}
void PlayerEntity::divineProtection(float duration, float armorBonus)
{
setSpecialState(DivineStateProtection, true, 4.0f, 0.8f, 0.0f);
}
void PlayerEntity::divineHeal(int hpHealed)
{
hp += hpHealed;
if (hp > hpMax) hp = hpMax;
specialState[SpecialStatePoison].active = false;
divineInterventionDelay = WORSHIP_DELAY;
isRegeneration = false;
}
bool PlayerEntity::triggerDivinityBefore()
{
if (divinity.divinity > -1 && divinity.interventions < divinity.level - 1)
{
switch (divinity.divinity)
{
case DivinityHealer:
{
if (game().getUndeadCount() > 0 && rand() % 2 == 0)
{
SoundManager::getInstance().playSound(SOUND_OM);
incrementDivInterventions();
divineHeal(hpMax / 2);
divineDestroyUndead();
game().makeColorEffect(X_GAME_COLOR_WHITE, 0.45f);
return true;
}
break;
}
case DivinityFighter:
{
int r = rand() % 3;
if (r == 0) return false;
SoundManager::getInstance().playSound(SOUND_OM);
incrementDivInterventions();
divineHeal(hpMax / 3);
if (r == 1) divineProtection(5.0f, 0.8f);
else divineFury();
game().makeColorEffect(X_GAME_COLOR_RED, 0.45f);
return true;
break;
}
case DivinityIce:
{
int r = rand() % 3;
if (r == 0) return false;
SoundManager::getInstance().playSound(SOUND_OM);
incrementDivInterventions();
divineHeal(hpMax / 3);
if (r == 1)
{
divineIce();
game().makeColorEffect(X_GAME_COLOR_BLUE, 7.5f);
}
else
{
divineFury();
game().makeColorEffect(X_GAME_COLOR_BLUE, 0.5f);
}
return true;
break;
}
case DivinityStone:
{
int r = rand() % 3;
r = 1;
divineProtection(10.0f, 0.5f);
if (r == 0) return false;
SoundManager::getInstance().playSound(SOUND_OM);
incrementDivInterventions();
divineHeal(hpMax / 3);
if (r == 1)
{
divineRepulse();
game().makeColorEffect(X_GAME_COLOR_BROWN, 3.0f);
}
else
{
divineFury();
game().makeColorEffect(X_GAME_COLOR_BROWN, 0.5f);
}
return true;
break;
}
case DivinityAir:
{
int r = rand() % 3;
if (r == 0) return false;
SoundManager::getInstance().playSound(SOUND_OM);
incrementDivInterventions();
divineHeal(hpMax / 3);
/*if (r == 1)
{
divineIce();
game().makeColorEffect(X_GAME_COLOR_BLUE, 7.5f);
}
else*/
{
divineFury();
game().makeColorEffect(X_GAME_COLOR_VIOLET, 0.5f);
}
return true;
break;
}
}
}
return false;
}
void PlayerEntity::triggerDivinityAfter()
{
if (divinity.divinity > -1 && divinity.interventions < divinity.level - 1)
{
switch (divinity.divinity)
{
case DivinityHealer:
{
SoundManager::getInstance().playSound(SOUND_OM);
incrementDivInterventions();
divineHeal(hpMax);
break;
}
//case DivinityFighter:
default:
{
SoundManager::getInstance().playSound(SOUND_OM);
incrementDivInterventions();
divineHeal(hpMax / 2);
break;
}
}
game().testAndAddMessageToQueue((EnumMessages)(MsgInfoDivIntervention));
}
}
void PlayerEntity::addPiety(int n)
{
if (n > 0 && equip[EQUIP_BOOK_PRAYER_I]) n *= 1.5f;
int oldLevel = divinity.level;
divinity.piety += n;
if (divinity.piety >= DIVINITY_LEVEL_TRESHOLD[MAX_DIVINITY_LEVEL - 1])
{
divinity.piety = DIVINITY_LEVEL_TRESHOLD[MAX_DIVINITY_LEVEL - 1];
divinity.percentsToNextLevels = 1.0f;
game().registerAchievement(AchievementPietyMax);
divinity.level = MAX_DIVINITY_LEVEL + 1;
}
else
{
int i = 0;
while (divinity.piety > DIVINITY_LEVEL_TRESHOLD[i] && i < (MAX_DIVINITY_LEVEL + 1)) i++;
divinity.level = i + 1;
if (divinity.level == 1)
divinity.percentsToNextLevels = (float)divinity.piety / (float)DIVINITY_LEVEL_TRESHOLD[0];
else
divinity.percentsToNextLevels
= (float)(divinity.piety - DIVINITY_LEVEL_TRESHOLD[divinity.level - 2])
/ (float)(DIVINITY_LEVEL_TRESHOLD[divinity.level - 1] - DIVINITY_LEVEL_TRESHOLD[divinity.level - 2]);
}
if (divinity.level > oldLevel)
{
SoundManager::getInstance().playSound(SOUND_OM);
divineInterventionDelay = WORSHIP_DELAY / 2;
isRegeneration = false;
pietyLevelUp();
computePlayer();
}
else if (divinity.level < oldLevel)
{
computePlayer();
}
}
void PlayerEntity::pietyLevelUp()
{
std::string label = "";
switch (divinity.divinity)
{
case DivinityFighter:
label = "div_fighter_lvl";
break;
case DivinityHealer:
if (divinity.level == 2) label = "div_healer_lvl_2";
else label = "div_healer_lvl_3";
break;
case DivinityIce:
if (divinity.level == 3) label = "div_ice_lvl_3";
else if (divinity.level == 4) label = "div_ice_lvl_4";
else if (divinity.level == 5) label = "div_ice_lvl_5";
break;
case DivinityStone:
if (divinity.level == 3) label = "div_stone_lvl_3";
else if (divinity.level == 4) label = "div_stone_lvl_4";
else if (divinity.level == 5) label = "div_stone_lvl_5";
break;
case DivinityAir:
if (divinity.level == 4) label = "div_air_lvl_4";
else label = "div_air_lvl";
break;
}
if (label.compare("") != 0) game().addDivLevelMessageToQueue(label);
}
void PlayerEntity::incrementDivInterventions()
{
divinity.interventions++;
addPiety(-divinity.piety * (equip[EQUIP_BOOK_PRAYER_II] ? 0.04f : 0.08f));
}
void PlayerEntity::worship(enumDivinityType id)
{
int oldPiety = divinity.piety;
bool isReconversion = divinity.divinity > -1;
playerStatus = playerStatusPraying;
statusTimer = WORSHIP_DELAY;
SoundManager::getInstance().playSound(SOUND_OM);
divinity.divinity = id;
divinity.piety = 0;
divinity.level = 1;
divinity.percentsToNextLevels = 0.0f;
facingDirection = 2;
// text
float x0 = MAP_WIDTH * 0.5f * TILE_WIDTH;
float y0 = MAP_HEIGHT * 0.5f * TILE_HEIGHT + 140.0f;
std::stringstream ss;
ss << tools::getLabel("worshipping") << " ";
ss << tools::getLabel(divinityLabel[divinity.divinity] + "_0");
TextEntity* text = new TextEntity(ss.str(), 24, x0, y0);
text->setAlignment(ALIGN_CENTER);
text->setLifetime(2.5f);
text->setWeight(-36.0f);
text->setZ(1200);
text->setColor(TextEntity::COLOR_FADING_WHITE);
// reconversion
if (isReconversion)
{
addPiety((equip[EQUIP_BOOK_PRAYER_I]) ? 0.66 * oldPiety : 0.5 * oldPiety);
if (divinity.interventions > divinity.level - 1)
divinity.interventions = divinity.level - 1;
}
else
divinity.interventions = 0;
// message
game().testAndAddMessageToQueue((EnumMessages)(MsgInfoDivHealer + (int)id));
}
void PlayerEntity::loadDivinity(int id, int piety, int level, int interventions)
{
divinity.divinity = id;
divinity.piety = piety;
divinity.level = level;
divinity.interventions = interventions;
if (id >= 0) addPiety(0);
}
// MAGIC
castSpellStruct PlayerEntity::getActiveSpell()
{
return activeSpell;
}
void PlayerEntity::setActiveSpell(enumCastSpell spell, bool fromSaveInFight)
{
if (activeSpell.spell != SpellNone)
{
// drop the old spell
equip[activeSpell.frame] = false;
ItemEntity* newItem = new ItemEntity((enumItemType)(ItemMagicianHat + activeSpell.frame), x, y);
newItem->setVelocity(Vector2D(100.0f + rand()% 250));
newItem->setViscosity(0.96f);
}
activeSpell.spell = spell;
switch (spell)
{
case SpellTeleport:
activeSpell.delayMax = 20.0f;
activeSpell.frame = ItemSpellTeleport - FirstEquipItem;
break;
case SpellSlimeExplode:
activeSpell.delayMax = 40.0f;
activeSpell.frame = ItemSpellSlimeExplode - FirstEquipItem;
break;
case SpellFireball:
activeSpell.delayMax = 20.0f;
activeSpell.frame = ItemSpellFireball - FirstEquipItem;
break;
case SpellFreeze:
activeSpell.delayMax = 40.0f;
activeSpell.frame = ItemSpellFreeze - FirstEquipItem;
break;
case SpellEarthquake:
activeSpell.delayMax = 40.0f;
activeSpell.frame = ItemSpellEarthquake - FirstEquipItem;
break;
case SpellProtection:
activeSpell.delayMax = 40.0f;
activeSpell.frame = ItemSpellProtection - FirstEquipItem;
break;
case SpellWeb:
activeSpell.delayMax = 35.0f;
activeSpell.frame = ItemSpellWeb - FirstEquipItem;
break;
case SpellFlower:
activeSpell.delayMax = 80.0f;
activeSpell.frame = ItemSpellFlower - FirstEquipItem;
break;
case SpellFairy:
activeSpell.delayMax = 10.0f;
activeSpell.frame = ItemSpellFairy - FirstEquipItem;
break;
case SpellNone:
break;
}
if (fromSaveInFight) activeSpell.delay = 1.0f;
else activeSpell.delay = activeSpell.delayMax;
}
void PlayerEntity::castSpell()
{
if (playerStatus != playerStatusPlaying) return;
if (canCastSpell())
{
activeSpell.delay = equip[EQUIP_BOOK_MAGIC_I] ? activeSpell.delayMax * 0.8f : activeSpell.delayMax;
switch (activeSpell.spell)
{
case SpellTeleport:
castTeleport();
break;
case SpellSlimeExplode:
castSummonsSlimeExplode();
break;
case SpellFireball:
castFireball();
break;
case SpellFreeze:
spellAnimationDelay = spellAnimationDelayMax;
castFreeze();
break;
case SpellEarthquake:
spellAnimationDelay = spellAnimationDelayMax;
castEarthquake();
break;
case SpellProtection:
spellAnimationDelay = spellAnimationDelayMax;
castProtection();
break;
case SpellWeb:
castWeb();
break;
case SpellFlower:
spellAnimationDelay = spellAnimationDelayMax;
castSummonsFlower();
break;
case SpellFairy:
castTransmuteFairy();
break;
case SpellNone:
break;
}
}
}
bool PlayerEntity::canCastSpell()
{
return activeSpell.spell != SpellNone && activeSpell.delay <= 0.0f;
}
void PlayerEntity::castTeleport()
{
bool ok = false;
int xm, ym;
float xNew = x, yNew = y;
invincibleDelay = equip[EQUIP_BOOK_MAGIC_II] ? 2.5f : 2.0f;
SoundManager::getInstance().playSound(SOUND_TELEPORT);
game().makeColorEffect(X_GAME_COLOR_VIOLET, 0.3f);
for(int i=0; i < 6; i++)
{
generateStar(sf::Color(50, 50, 255, 255));
generateStar(sf::Color(200, 200, 255, 255));
}
int counter = 150;
while (!ok && counter > 0)
{
counter--;
int distanceMin = 20000;
if (counter < 50) distanceMin = 30000;
else if (counter < 100) distanceMin = 25000;
xm = 1 +rand() % (MAP_WIDTH - 3);
ym = 1 +rand() % (MAP_HEIGHT - 3);
if (game().getCurrentMap()->isWalkable(xm, ym))
{
// enemy or bolt ?
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
bool isBad = false;
xNew = xm * TILE_WIDTH + TILE_WIDTH * 0.5f;
yNew = ym * TILE_HEIGHT+ TILE_HEIGHT * 0.5f;
for (it = entityList->begin (); !isBad && it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if ((e->getType() >= ENTITY_ENEMY && e->getType() <= ENTITY_ENEMY_MAX_COUNT) || e->getType() == ENTITY_ENEMY_BOLT)
isBad = Vector2D(xNew, yNew).distance2(Vector2D(e->getX(), e->getY())) < distanceMin;
}
if (!isBad)
{
x = xNew;
y = yNew;
}
}
}
for(int i=0; i < 6; i++)
{
generateStar(sf::Color(50, 50, 255, 255));
generateStar(sf::Color(200, 200, 255, 255));
}
}
void PlayerEntity::initFallingGrid()
{
for (int i = 0; i < MAP_WIDTH; i++)
for (int j = 0; j < MAP_HEIGHT; j++)
fallingGrid[i][j] = false;
}
void PlayerEntity::fallRock()
{
int rx, ry;
do
{
rx = 1 + rand() % (MAP_WIDTH - 2);
ry = 1 + rand() % (MAP_HEIGHT - 2);
}
while (fallingGrid[rx][ry]);
fallingGrid[rx][ry] = true;
new FallingRockEntity(rx * TILE_WIDTH + TILE_WIDTH / 2,
ry * TILE_HEIGHT + TILE_HEIGHT / 2,
rand() % 3,
true);
}
void PlayerEntity::castSummonsSlimeExplode()
{
SlimeEntity* slime = new SlimeEntity( ((int)(x) / TILE_WIDTH) * TILE_WIDTH + TILE_WIDTH * 0.5f,
y - 5, SlimeTypeViolet, true);
slime->makePet(facingDirection);
game().makeColorEffect(X_GAME_COLOR_VIOLET, 0.3f);
}
void PlayerEntity::castFireball()
{
SoundManager::getInstance().playSound(SOUND_FIREBALL);
game().makeColorEffect(X_GAME_COLOR_RED, 0.3f);
enumShotType boltType = ShotTypeFire;
unsigned int shotLevel = 2;
BoltEntity* bolt = new BoltEntity(x, getBolPositionY(), boltLifeTime + 0.5f, boltType, shotLevel);
int boltDamage = fireDamages * (equip[EQUIP_BOOK_MAGIC_II] ? 4 : 3);
if (equip[EQUIP_BOOK_MAGIC_II] && boltDamage < 16) boltDamage = 16;
else if (!equip[EQUIP_BOOK_MAGIC_II] && boltDamage < 12) boltDamage = 12;
bolt->setDamages(boltDamage);
bolt->setGoThrough(true);
float velx = 0.0f, vely = 0.0f;
if (facingDirection == 4) velx = -fireVelocity;
else if (facingDirection == 8) vely = -fireVelocity;
else if (facingDirection == 2) vely = fireVelocity;
else velx = fireVelocity;
bolt->setVelocity(Vector2D(velx, vely));
}
void PlayerEntity::castFreeze()
{
int iceLevel = equip[EQUIP_BOOK_MAGIC_II] ? 2 : 1;
for (float i = 0.0f; i < 2 * PI; i += PI / 8)
{
BoltEntity* bolt1 = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypeIce, iceLevel);
bolt1->setDamages(1);
float velx = fireVelocity * cos(i);
float vely = fireVelocity * sin(i);
bolt1->setVelocity(Vector2D(velx, vely));
}
game().makeColorEffect(X_GAME_COLOR_BLUE, 0.3f);
SoundManager::getInstance().playSound(SOUND_SPELL_FREEZE);
}
void PlayerEntity::castEarthquake()
{
initFallingGrid();
int nbIterations = equip[EQUIP_BOOK_MAGIC_II] ? 24 : 22;
for (int i = 0; i < nbIterations; i++) fallRock();
game().makeShake(0.25f);
game().makeColorEffect(X_GAME_COLOR_BROWN, 0.3f);
SoundManager::getInstance().playSound(SOUND_EARTHQUAKE);
}
void PlayerEntity::castProtection()
{
protection.active = true;
protection.value = equip[EQUIP_BOOK_MAGIC_II] ? 0.6f : 0.4f;
protection.timer = 10.0f;
computePlayer();
game().makeColorEffect(X_GAME_COLOR_BLUE, 0.3f);
SoundManager::getInstance().playSound(SOUND_SPELL_SHIELD);
}
void PlayerEntity::castWeb()
{
SoundManager::getInstance().playSound(SOUND_SPIDER_WEB);
int nbWeb = equip[EQUIP_BOOK_MAGIC_II] ? 4 : 3;
for (int i = 0; i < nbWeb; i++)
{
SpiderWebEntity* web = new SpiderWebEntity(x, y, true);
float webVel = 100 + rand()% 500;
float webAngle = -60 + rand() % 120;
webAngle = PI * webAngle / 180.0f;
if (facingDirection == 4) webAngle += PI;
else if (facingDirection == 8) webAngle -= PI * 0.5;
else if (facingDirection == 2) webAngle += PI * 0.5;
web->setVelocity(Vector2D(webVel * cos(webAngle), webVel * sin(webAngle)));
}
}
void PlayerEntity::castSummonsFlower()
{
SoundManager::getInstance().playSound(SOUND_INVOKE);
EvilFlowerEntity* flower = new EvilFlowerEntity(x, y, FlowerTypePet);
flower->setLifetime(equip[EQUIP_BOOK_MAGIC_II] ? 45 : 35);
if (equip[EQUIP_BOOK_MAGIC_II]) flower->setFireDelayMax(EVIL_FLOWER_FIRE_DELAY * 0.8f);
}
void PlayerEntity::castTransmuteFairy()
{
if (isFairyTransmuted)
{
movingStyle = movWalking;
if (isCollidingWithMap())
movingStyle = movFlying;
else
{
SoundManager::getInstance().playSound(SOUND_INVOKE);
isFairyTransmuted = false;
computePlayer();
for(int i=0; i < 6; i++)
{
generateStar(sf::Color(50, 50, 255, 255));
generateStar(sf::Color(200, 200, 255, 255));
}
}
}
else
{
SoundManager::getInstance().playSound(SOUND_INVOKE);
isFairyTransmuted = true;
computePlayer();
for(int i=0; i < 6; i++)
{
generateStar(sf::Color(50, 50, 255, 255));
generateStar(sf::Color(200, 200, 255, 255));
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Wed, Jun 17, 9:08 PM (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
69737
Default Alt Text
(130 KB)
Attached To
Mode
R78 witchblast
Attached
Detach File
Event Timeline