Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F86291
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
385 KB
Referenced Files
None
Subscribers
None
View Options
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/src/BaseCreatureEntity.cpp b/src/BaseCreatureEntity.cpp
index 3b3c531..9e7e64d 100644
--- a/src/BaseCreatureEntity.cpp
+++ b/src/BaseCreatureEntity.cpp
@@ -1,852 +1,852 @@
#include "BaseCreatureEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "ExplosionEntity.h"
#include "TextMapper.h"
#include <iostream>
#include <sstream>
BaseCreatureEntity::BaseCreatureEntity(sf::Texture* image, float x = 0.0f, float y = 0.0f, int spriteWidth = -1, int spriteHeight = -1)
: CollidingSpriteEntity (image, x, y, spriteWidth, spriteHeight )
{
hurting = false;
displayDamage = true;
hurtingType = ShotTypeStandard;
shadowFrame = -1;
setMap(game().getCurrentMap(), TILE_WIDTH, TILE_HEIGHT, 0, 0);
hpDisplay = 0;
armor = 0.0f;
movingStyle = movWalking;
for (int i = 0; i < NB_SPECIAL_STATES; i++)
{
specialState[i].type = (enumSpecialState)i;
specialState[i].active = false;
specialState[i].timer = 0.0f;
specialState[i].param1 = 0.0f;
specialState[i].param2 = 0.0f;
specialState[i].param3 = 0.0f;
specialState[i].waitUnclear = false;
}
for (int i = 0; i < NB_RESISTANCES; i++)
{
resistance[i] = ResistanceStandard;
}
- recoil.active = false;
+ repulsion.active = false;
facingDirection = 2;
doesAccelerate = false;
}
int BaseCreatureEntity::getHp()
{
return hp;
}
int BaseCreatureEntity::getHpMax()
{
return hpMax;
}
void BaseCreatureEntity::setHp(int hp)
{
this->hp = hp;
}
void BaseCreatureEntity::setHpMax(int hpMax)
{
this->hpMax = hpMax;
}
int BaseCreatureEntity::getHpDisplay()
{
return hpDisplay;
}
float BaseCreatureEntity::getCreatureSpeed()
{
return creatureSpeed;
}
IntCoord BaseCreatureEntity::getCurrentTile()
{
int xMap = (x) / TILE_WIDTH;
int yMap = (y) / TILE_HEIGHT;
return (IntCoord(xMap, yMap));
}
BaseCreatureEntity::enumMovingStyle BaseCreatureEntity::getMovingStyle()
{
return movingStyle;
}
bool BaseCreatureEntity::isSpecialStateActive(enumSpecialState state)
{
return specialState[state].active;
}
specialStateStuct BaseCreatureEntity::getSpecialState(enumSpecialState state)
{
return specialState[state];
}
void BaseCreatureEntity::setSpecialState(enumSpecialState state, bool active, float timer, float param1, float param2,bool waitUnclear)
{
specialState[state].active = active;
specialState[state].timer = timer;
specialState[state].param1 = param1;
specialState[state].param2 = param2;
specialState[state].waitUnclear = waitUnclear;
}
float BaseCreatureEntity::animateStates(float delay)
{
for (int i = 0; i < NB_SPECIAL_STATES; i++)
{
if (specialState[i].active)
{
specialState[i].timer -= delay;
if (specialState[i].timer <= 0.0f)
{
setSpecialState((enumSpecialState)i, false, 0.0f, 0.0f, 0.0f);
game().getPlayer()->computePlayer();
if (i == SpecialStateTime) game().resumeMusic();
}
}
else if (specialState[i].waitUnclear && !game().getCurrentMap()->isCleared())
{
specialState[i].waitUnclear = false;
specialState[i].active = true;
game().getPlayer()->computePlayer();
}
}
// ice
if (specialState[SpecialStateIce].active) delay *= specialState[SpecialStateIce].param1;
// poison
if (specialState[SpecialStatePoison].active)
{
specialState[SpecialStatePoison].param3 -= delay;
if (specialState[SpecialStatePoison].param3 <= 0.0f)
{
specialState[SpecialStatePoison].param3 += specialState[SpecialStatePoison].param2;
// TODO
hurt(getHurtParams(specialState[SpecialStatePoison].param1, ShotTypeDeterministic, 0, false, SourceTypePoison, NB_ENEMY, false));
}
}
return delay;
}
void BaseCreatureEntity::animateColors(float delay)
{
// no color
sprite.setColor(sf::Color(255, 255, 255, 255 ));
if (hurting && hp > 0)
{
hurtingDelay -= delay;
if (hurtingDelay > 0.0f)
{
int fadeColor = (sf::Uint8)((HURTING_DELAY - hurtingDelay) * 255);
if (hurtingDelay > HURTING_DELAY) fadeColor = 0;
if (hurtingType == ShotTypeIce || hurtingType == ShotTypeCold)
sprite.setColor(sf::Color(fadeColor, fadeColor, 255, 255 )); // blue
else if (hurtingType == ShotTypePoison)
sprite.setColor(sf::Color(fadeColor, 255, fadeColor, 255 )); // green
else
sprite.setColor(sf::Color(255, fadeColor, fadeColor, 255 )); // red
}
else
{
hurting = false;
sprite.setColor(sf::Color(255, 255, 255, 255 ));
}
}
if (specialState[SpecialStateIce].active) sprite.setColor(sf::Color(100, 100, 255, 255 ));
else if (specialState[SpecialStatePoison].active)
{
int fade = 180 + 70 * cos(age * 5);
sprite.setColor(sf::Color(fade, 255, fade, 255 ));
}
}
void BaseCreatureEntity::animateRecoil(float delay)
{
- // recoil
- if (recoil.active)
+ // repulsion
+ if (repulsion.active)
{
- recoil.velocity.x *= 0.97f;
- recoil.velocity.y *= 0.97f;
+ repulsion.velocity.x *= 0.97f;
+ repulsion.velocity.y *= 0.97f;
- recoil.timer -= delay;
- if (recoil.timer <= 0.0f)
+ repulsion.timer -= delay;
+ if (repulsion.timer <= 0.0f)
{
- recoil.active = false;
+ repulsion.active = false;
computeFacingDirection();
// TODO ?
}
}
}
void BaseCreatureEntity::animatePhysics(float delay)
{
if (doesAccelerate)
{
velocity.x += acceleration.x;
velocity.y += acceleration.y;
if (velocity.x * velocity.x + velocity.y * velocity.y > creatureSpeed * creatureSpeed)
{
float l = sqrtf(velocity.x * velocity.x + velocity.y * velocity.y);
velocity.x = (velocity.x / l) * creatureSpeed;
velocity.y = (velocity.y / l) * creatureSpeed;
doesAccelerate = false;
}
}
velocity.x *= viscosity;
velocity.y *= viscosity;
float velx = velocity.x;
float vely = velocity.y;
if (specialState[SpecialStateSlow].active)
{
velx *= specialState[SpecialStateSlow].param1;
vely *= specialState[SpecialStateSlow].param1;
}
if (specialState[SpecialStateSpeed].active)
{
velx *= specialState[SpecialStateSpeed].param1;
vely *= specialState[SpecialStateSpeed].param1;
}
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun)
+ if (repulsion.stun)
{
velx = 0.0f;
vely = 0.0f;
}
- velx += recoil.velocity.x;
- vely += recoil.velocity.y;
+ velx += repulsion.velocity.x;
+ vely += repulsion.velocity.y;
}
spin *= viscosity;
angle += spin * delay;
if (isCollidingWithMap())
{
stuck();
}
else
{
if ((int)velx > 0)
{
x += velx * delay;
if (collideWithMap(DIRECTION_LEFT))
{
x = (float)((int)x);
while (collideWithMap(DIRECTION_LEFT))
x--;
collideMapRight();
}
else if (x > map->getWidth() * tileWidth + offsetX)
{
exitMap(DIRECTION_RIGHT);
}
}
else if ((int)velx < 0)
{
x += velx * delay;
if (collideWithMap(DIRECTION_RIGHT))
{
x = (float)((int)x);
while (collideWithMap(DIRECTION_RIGHT))
x++;
collideMapLeft();
}
else if (x < offsetX)
{
exitMap(DIRECTION_LEFT);
}
}
}
vely += weight * delay;
if ( vely > maxY) vely = maxY;
if ((int)vely > 0)
{
y += vely * delay;
if (collideWithMap(DIRECTION_BOTTOM))
{
y = (float)((int)y);
while (collideWithMap(DIRECTION_BOTTOM))
y--;
collideMapBottom();
}
}
else if ((int)vely < 0)
{
y += vely * delay;
if (collideWithMap(DIRECTION_TOP))
{
y = (float)((int)y);
while (collideWithMap(DIRECTION_TOP))
y++;
collideMapTop();
}
}
if (lifetime > 0)
{
if (age >= lifetime) dyingFromAge();
}
age += delay;
}
void BaseCreatureEntity::dyingFromAge()
{
dying();
}
void BaseCreatureEntity::animate(float delay)
{
if (hpDisplay > hp) hpDisplay--;
else if (hpDisplay < hp) hpDisplay++;
delay = animateStates(delay);
animateColors(delay);
animateRecoil(delay);
animatePhysics(delay);
z = y + height/2;
}
void BaseCreatureEntity::render(sf::RenderTarget* app)
{
if (!isDying && shadowFrame > -1)
{
// shadow
int nx = shadowFrame;
int ny = 0;
if (imagesProLine > 0 && shadowFrame >= imagesProLine)
{
nx = shadowFrame % imagesProLine;
ny = shadowFrame / imagesProLine;
}
sprite.setTextureRect(sf::IntRect(nx * width, ny * height, width, height));
app->draw(sprite);
}
CollidingSpriteEntity::render(app);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void BaseCreatureEntity::calculateBB()
{
}
bool BaseCreatureEntity::collideWithMap(int direction)
{
calculateBB();
int xTile0 = (boundingBox.left - offsetX) / tileWidth;
int xTilef = (boundingBox.left + boundingBox.width - offsetX) / tileWidth;
int yTile0 = (boundingBox.top - offsetY) / tileHeight;
int yTilef = (boundingBox.top + boundingBox.height - offsetY) / tileHeight;
if (boundingBox.top < 0) yTile0 = -1;
switch (direction)
{
case DIRECTION_RIGHT:
if (xTilef > xTile0) xTilef = xTile0;
break;
case DIRECTION_LEFT:
if (xTilef > xTile0) xTile0 = xTilef;
break;
case DIRECTION_TOP:
if (yTilef > yTile0) yTilef = yTile0;
break;
case DIRECTION_BOTTOM:
if (yTilef > yTile0) yTile0 = yTilef;
break;
}
for (int xTile = xTile0; xTile <= xTilef; xTile++)
for (int yTile = yTile0; yTile <= yTilef; yTile++)
{
if (movingStyle == movWalking)
{
if (isAttacking())
{
if ( dynamic_cast<DungeonMap*>(map)->isWalkable(xTile, yTile) == false
&& dynamic_cast<DungeonMap*>(map)->getLogicalTile(xTile, yTile) != LogicalDestroyable)
return true;
}
else
{
if ( dynamic_cast<DungeonMap*>(map)->isWalkable(xTile, yTile) == false )
return true;
}
}
else if (movingStyle == movFlying)
{
if ( dynamic_cast<DungeonMap*>(map)->isFlyable(xTile, yTile) == false ) return true;
}
}
return false;
}
bool BaseCreatureEntity::determineSatusChance(enumStateResistance resistance, int level)
{
bool hit = true;
switch (resistance)
{
case ResistanceVeryLow:
case ResistanceLow:
case ResistanceStandard: hit = true; break;
case ResistanceHigh: hit = rand() % 8 <= level * 2; break;
case ResistanceVeryHigh: hit = rand() % 10 <= level * 2; break;
case ResistanceImmune: hit = false; break;
}
return hit;
}
int BaseCreatureEntity::determineDamageBonus(enumStateResistance resistance, int level)
{
int bonus = 0;
switch (resistance)
{
case ResistanceVeryLow: bonus = 40 + 10 * level; break;
case ResistanceLow: bonus = 20 + 5 * level; break;
case ResistanceStandard: bonus = 0; break;
case ResistanceHigh: bonus = -25 + 5 * level; break;
case ResistanceVeryHigh: bonus = -50 + 5 * level; break;
case ResistanceImmune: bonus = -100 + 5 * level; break;
}
return bonus;
}
bool BaseCreatureEntity::textTooClose(TextEntity* textEntity, float xDistMin, float yDistMin)
{
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_FLYING_TEXT)
{
if (e != textEntity)
{
if (textEntity->getX() - e->getX() < xDistMin && textEntity->getX() - e->getX() > - xDistMin
&& textEntity->getY() - e->getY() < yDistMin && textEntity->getY() - e->getY() > - yDistMin)
return true;
}
}
}
return false;
}
void BaseCreatureEntity::makeExplode()
{
new ExplosionEntity(x, y, ExplosionTypeStandard, 16, EnemyTypeNone, false);
game().addCorpse(x, y, FRAME_CORPSE_SLIME_VIOLET);
SoundManager::getInstance().playSound(SOUND_BOOM_00);
}
int BaseCreatureEntity::hurt(StructHurt hurtParam)
{
int oldHp = hp;
int absorbedHp = 0;
bool poisoned = false;
hurtingType = hurtParam.hurtingType;
if (armor > 0.01f && hurtingType != ShotTypeDeterministic)
{
absorbedHp = hurtParam.damage * armor;
if (absorbedHp == 0) absorbedHp = 1;
hurtParam.damage -= absorbedHp;
}
if (hurtingType == ShotTypeIce
&& determineSatusChance(resistance[ResistanceFrozen], hurtParam.level))
{
// frozen ?
specialState[SpecialStateIce].active = true;
float frozenDelayMult = 1.0f;
float frozenMultAdd = 0.0f;
if (resistance[ResistanceFrozen] == ResistanceHigh)
{
if (hurtParam.level == 0)
{
frozenDelayMult = 0.8f;
frozenMultAdd = 0.2f;
}
else
{
frozenDelayMult = 0.85f;
frozenMultAdd = 0.15f;
}
}
else if (resistance[ResistanceFrozen] == ResistanceVeryHigh)
{
if (hurtParam.level < 2)
{
frozenDelayMult = 0.7f;
frozenMultAdd = 0.25f;
}
else
{
frozenDelayMult = 0.8f;
frozenMultAdd = 0.2f;
}
}
specialState[SpecialStateIce].timer = STATUS_FROZEN_DELAY[hurtParam.level] * frozenDelayMult;
specialState[SpecialStateIce].param1 = STATUS_FROZEN_MULT[hurtParam.level] + frozenMultAdd;
}
else if (hurtingType == ShotTypePoison && determineSatusChance(resistance[ResistancePoison], hurtParam.level))
{
specialState[SpecialStatePoison].active = true;
specialState[SpecialStatePoison].timer = POISON_TIMER[hurtParam.level];
specialState[SpecialStatePoison].param1 = POISON_DAMAGE[hurtParam.level];
specialState[SpecialStatePoison].param2 = POISON_DELAY[hurtParam.level];
specialState[SpecialStatePoison].param3 = POISON_DELAY[hurtParam.level];
poisoned = true;
}
// damage bonus
if (hurtingType == ShotTypeIce || hurtingType == ShotTypeCold)
hurtParam.damage += (hurtParam.damage * determineDamageBonus(resistance[ResistanceIce], hurtParam.level)) / 100;
else if (hurtingType == ShotTypeFire)
hurtParam.damage += (hurtParam.damage * determineDamageBonus(resistance[ResistanceFire], hurtParam.level)) / 100;
else if (hurtingType == ShotTypeLightning)
hurtParam.damage += (hurtParam.damage * determineDamageBonus(resistance[ResistanceLightning], hurtParam.level)) / 100;
else if (hurtingType == ShotTypeStone)
hurtParam.damage += (hurtParam.damage * determineDamageBonus(resistance[ResistanceStone], hurtParam.level)) / 100;
else if (hurtingType == ShotTypeIllusion)
hurtParam.damage += (hurtParam.damage * determineDamageBonus(resistance[ResistanceIllusion], hurtParam.level)) / 100;
//else if (hurtingType == ShotTypePoison)
// hurtParam.damage += (hurtParam.damage * determineDamageBonus(resistance[ResistancePoison], hurtParam.level)) / 100;
if (hurtParam.damage > 0)
{
hurting = true;
hurtingDelay = HURTING_DELAY;
this->hurtingType = hurtingType;
hp -= hurtParam.damage;
if (hp <= 0)
{
hp = 0;
prepareDying();
// exploding ?
if (game().getPlayer()->isEquiped(EQUIP_SULFUR) && canExplode)
{
int luck = hurtingType == ShotTypeFire ? 33 : 25;
if (rand() % 100 < luck) makeExplode();
}
}
// display damage
if (displayDamage && oldHp > 0)
{
int displayedDamage = hurtParam.damage;
if (hurtParam.goThrough && hp == 0)
{
hurtParam.damage = oldHp + absorbedHp;
displayedDamage = oldHp;
}
std::ostringstream oss;
oss << "-" << displayedDamage;
int textSize;
if (displayedDamage < 8) textSize = 17;
else textSize = 17 + (displayedDamage - 3) / 5;
TextEntity* text = new TextEntity(oss.str(), textSize, x, y - 20.0f);
text->setColor(TextEntity::COLOR_FADING_RED);
text->setAge(-0.6f);
text->setLifetime(0.3f);
text->setWeight(-60.0f);
text->setZ(2000);
text->setAlignment(ALIGN_CENTER);
text->setType(ENTITY_FLYING_TEXT);
while (textTooClose(text, 15, 15)) text->setY(text->getY() - 5);
if (hurtParam.critical)
{
std::ostringstream crss;
crss << tools::getLabel("critical");
if (game().getPlayer()->isEquiped(EQUIP_CRITICAL_ADVANCED))
crss << " X3";
else
crss << " X2";
displayFlyingText(x, text->getY() - 16.0f, 16, crss.str(), TextEntity::COLOR_FADING_RED);
}
if (poisoned)
{
displayFlyingText(x, text->getY() - 16.0f, 16, tools::getLabel("poison"), TextEntity::COLOR_FADING_RED);
}
if (hurtParam.critical) SoundManager::getInstance().playSound(SOUND_CRITICAL);
}
}
return hurtParam.damage;
}
void BaseCreatureEntity::displayFlyingText(float xText, float yText, int sizeText, std::string text, TextEntity::colorTypeEnum color)
{
TextEntity* textEntity = new TextEntity(text, sizeText, xText, yText);
textEntity->setColor(color);
textEntity->setAge(-0.6f);
textEntity->setLifetime(0.3f);
textEntity->setWeight(-60.0f);
textEntity->setZ(2000);
textEntity->setAlignment(ALIGN_CENTER);
textEntity->setType(ENTITY_FLYING_TEXT);
}
void BaseCreatureEntity::prepareDying()
{
dying();
}
void BaseCreatureEntity::dying()
{
isDying = true;
}
void BaseCreatureEntity::computeFacingDirection()
{
if (abs((int)velocity.x) > 0 || abs((int)velocity.y) > 0)
{
if (abs((int)velocity.x) > abs((int)velocity.y))
{
if (velocity.x > 0.0f) facingDirection = 6;
else facingDirection = 4;
}
else
{
if (velocity.y > 0.0f) facingDirection = 2;
else facingDirection = 8;
}
}
}
-void BaseCreatureEntity::giveRecoil(bool stun, Vector2D velocity, float timer)
+void BaseCreatureEntity::giveRepulsion(bool stun, Vector2D velocity, float timer)
{
- if (resistance[ResistanceRecoil] == ResistanceHigh)
+ if (resistance[ResistanceRepulsion] == ResistanceHigh)
{
velocity.x *= 0.75f;
velocity.y *= 0.75f;
timer *= 0.75f;
}
- else if (resistance[ResistanceRecoil] == ResistanceVeryHigh)
+ else if (resistance[ResistanceRepulsion] == ResistanceVeryHigh)
{
velocity.x *= 0.5f;
velocity.y *= 0.5f;
timer *= 0.5f;
}
- if (!(recoil.active && recoil.stun))
+ if (!(repulsion.active && repulsion.stun))
{
- recoil.active = true;
- recoil.stun = stun;
+ repulsion.active = true;
+ repulsion.stun = stun;
- if (this->velocity.x > 1.0f && velocity.x > 1.0f) recoil.velocity.x = velocity.x + this->velocity.x;
- else if (this->velocity.x < -1.0f && velocity.x < -1.0f) recoil.velocity.x = velocity.x + this->velocity.x;
- else recoil.velocity.x = velocity.x;
+ if (this->velocity.x > 1.0f && velocity.x > 1.0f) repulsion.velocity.x = velocity.x + this->velocity.x;
+ else if (this->velocity.x < -1.0f && velocity.x < -1.0f) repulsion.velocity.x = velocity.x + this->velocity.x;
+ else repulsion.velocity.x = velocity.x;
- if (this->velocity.y > 1.0f && velocity.y > 1.0f) recoil.velocity.y = velocity.y + this->velocity.y;
- else if (this->velocity.y < -1.0f && velocity.y < -1.0f) recoil.velocity.y = velocity.y + this->velocity.y;
- else recoil.velocity.y = velocity.y;
+ if (this->velocity.y > 1.0f && velocity.y > 1.0f) repulsion.velocity.y = velocity.y + this->velocity.y;
+ else if (this->velocity.y < -1.0f && velocity.y < -1.0f) repulsion.velocity.y = velocity.y + this->velocity.y;
+ else repulsion.velocity.y = velocity.y;
- recoil.timer = timer;
+ repulsion.timer = timer;
}
}
-void BaseCreatureEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
+void BaseCreatureEntity::inflictsRepulsionTo(BaseCreatureEntity* targetEntity)
{
}
bool BaseCreatureEntity::canCollide()
{
return true;
}
void BaseCreatureEntity::generateStar(sf::Color starColor)
{
game().generateStar(starColor, x, y);
}
bool BaseCreatureEntity::intersectsSegments(Vector2D a1, Vector2D a2, Vector2D b1, Vector2D b2)
{
Vector2D b(a2.x - a1.x, a2.y - a1.y);
Vector2D d(b2.x - b1.x, b2.y - b1.y);
float bDotDPerp = b.x * d.y - b.y * d.x;
// if b dot d == 0, it means the lines are parallel so have infinite intersection points
if (bDotDPerp == 0) return false;
Vector2D c(b1.x - a1.x, b1.y - a1.y);
float t = (c.x * d.y - c.y * d.x) / bDotDPerp;
if (t < 0 || t > 1) return false;
float u = (c.x * b.y - c.y * b.x) / bDotDPerp;
if (u < 0 || u > 1) return false;
return true;
}
bool BaseCreatureEntity::intersectsTile(Vector2D a1, Vector2D a2, int xTile, int yTile)
{
int posX = xTile * TILE_WIDTH;
int posY = yTile * TILE_HEIGHT;
if (intersectsSegments(a1, a2, Vector2D(posX, posY), Vector2D(posX + TILE_WIDTH, posY))) return true;
else if (intersectsSegments(a1, a2, Vector2D(posX, posY + TILE_HEIGHT), Vector2D(posX + TILE_WIDTH, posY + TILE_HEIGHT))) return true;
else if (intersectsSegments(a1, a2, Vector2D(posX + TILE_WIDTH, posY), Vector2D(posX + TILE_WIDTH, posY + TILE_HEIGHT))) return true;
else if (intersectsSegments(a1, a2, Vector2D(posX, posY), Vector2D(posX, posY + TILE_HEIGHT))) return true;
else
return false;
}
bool BaseCreatureEntity::canSee(float xf, float yf)
{
int tileX0 = x / TILE_WIDTH;
int tileXf = xf / TILE_WIDTH;
int tileY0 = y / TILE_HEIGHT;
int tileYf = yf / TILE_HEIGHT;
int xBegin, xEnd, yBegin, yEnd;
if (tileXf < tileX0)
{
xBegin = tileXf;
xEnd = tileX0;
}
else
{
xBegin = tileX0;
xEnd = tileXf;
}
if (tileYf < tileY0)
{
yBegin = tileYf;
yEnd = tileY0;
}
else
{
yBegin = tileY0;
yEnd = tileYf;
}
for (int i = xBegin; i <= xEnd; i++ )
for (int j = yBegin; j <= yEnd; j++ )
{
if (!game().getCurrentMap()->isShootable(i, j))
if (intersectsTile(Vector2D(x, y), game().getPlayerPosition(), i , j))
return false;
}
return true;
}
bool BaseCreatureEntity::canWalkTo(float xf, float yf)
{
int tileX0 = x / TILE_WIDTH;
int tileXf = xf / TILE_WIDTH;
int tileY0 = y / TILE_HEIGHT;
int tileYf = yf / TILE_HEIGHT;
int xBegin, xEnd, yBegin, yEnd;
if (tileXf < tileX0)
{
xBegin = tileXf;
xEnd = tileX0;
}
else
{
xBegin = tileX0;
xEnd = tileXf;
}
if (tileYf < tileY0)
{
yBegin = tileYf;
yEnd = tileY0;
}
else
{
yBegin = tileY0;
yEnd = tileYf;
}
for (int i = xBegin; i <= xEnd; i++ )
for (int j = yBegin; j <= yEnd; j++ )
{
if (!game().getCurrentMap()->isWalkable(i, j))
if (intersectsTile(Vector2D(x, y), game().getPlayerPosition(), i , j))
return false;
}
return true;
}
void BaseCreatureEntity::heal(int healPoints)
{
int savedHp = hp;
hp += healPoints;
if (hp > hpMax) hp = hpMax;
int healedHp = hp - savedHp;
if (savedHp > 0)
{
std::ostringstream oss;
oss << "+" << healedHp;
int textSize;
if (healedHp < 8) textSize = 17;
else textSize = 17 + (healedHp - 3) / 5;
TextEntity* text = new TextEntity(oss.str(), textSize, x, y - 20.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);
while (textTooClose(text, 15, 15)) text->setY(text->getY() - 5);
}
if (type == ENTITY_PLAYER) game().addHealingStat(healedHp);
}
bool BaseCreatureEntity::isAttacking()
{
return false;
}
diff --git a/src/BaseCreatureEntity.h b/src/BaseCreatureEntity.h
index 6f1e019..ab019a5 100644
--- a/src/BaseCreatureEntity.h
+++ b/src/BaseCreatureEntity.h
@@ -1,319 +1,320 @@
#ifndef BASECREATUREENTITY_H
#define BASECREATUREENTITY_H
#include "sfml_game/CollidingSpriteEntity.h"
#include "TextEntity.h"
#include "Constants.h"
enum enemyTypeEnum
{
// normal
EnemyTypeBat,
EnemyTypeBatSkeleton,
EnemyTypeRat,
EnemyTypeRatBlack,
EnemyTypeRatHelmet,
EnemyTypeRatBlackHelmet,
EnemyTypeEvilFlower,
EnemyTypeEvilFlowerIce,
EnemyTypeEvilFlowerFire,
EnemyTypeSnake,
EnemyTypeSnakeBlood,
EnemyTypeSlime,
EnemyTypeSlimeRed,
EnemyTypeSlimeBlue,
EnemyTypeSlimeViolet,
EnemyTypeImpBlue,
EnemyTypeImpRed,
EnemyTypePumpkin,
EnemyTypeWitch,
EnemyTypeWitchRed,
EnemyTypeCauldron,
EnemyTypeCauldronElemental,
EnemyTypeSpiderEgg,
EnemyTypeSpiderLittle,
EnemyTypeSpiderTarantula,
EnemyTypeGhost,
EnemyTypeZombie,
EnemyTypeZombieDark,
EnemyTypeBogeyman,
EnemyTypeSlimeLarge,
EnemyTypeSlimeRedLarge,
EnemyTypeSlimeBlueLarge,
EnemyTypeSlimeVioletLarge,
EnemyTypeSausage,
// mini boss
EnemyTypeBubble,
EnemyTypeBubbleIce,
EnemyTypeBubbleGreater,
// boss
EnemyTypeButcher,
EnemyTypeSlimeBoss,
EnemyTypeCyclops,
EnemyTypeRatKing,
EnemyTypeSpiderGiant,
EnemyTypeFrancky,
EnemyTypeVampire,
// invocated
EnemyTypeBat_invocated,
EnemyTypeBatSkeleton_invocated,
EnemyTypeRat_invocated,
EnemyTypeRatGreen,
EnemyTypeRatHelmet_invocated,
EnemyTypeSnake_invocated,
EnemyTypeSnakeBlood_invocated,
EnemyTypeSlime_invocated,
EnemyTypeSlimeRed_invocated,
EnemyTypeSlimeBlue_invocated,
EnemyTypeSlimeViolet_invocated,
EnemyTypePumpkin_invocated,
EnemyTypeSpiderEgg_invocated,
EnemyTypeSpiderLittle_invocated,
EnemyTypeSpiderTarantula_invocated,
EnemyTypeZombie_invocated,
EnemyTypeSausage_invocated,
EnemyTypeRockFalling,
EnemyTypeRockMissile,
EnemyTypeSpiderWeb,
EnemyTypeFranckyHead,
EnemyTypeFranckyHand,
EnemyTypeFranckyFoot,
EnemyTypeVampireDead,
EnemyTypeNone, // player of fairy
EnemyTypeDestroyable,
NB_ENEMY // = no enemy
};
enum sourceTypeEnum
{
SourceTypeMelee,
SourceTypeBolt,
SourceTypeExplosion,
SourceTypePoison
};
struct StructHurt
{
int damage;
enumShotType hurtingType;
int level;
bool critical;
sourceTypeEnum sourceType;
enemyTypeEnum enemyType;
bool goThrough;
};
enum enumSpecialState
{
SpecialStateIce, // = 0
SpecialStateSlow, // param 1 = multiplier
SpecialStateSpeed, // param 1 = multiplier
SpecialStatePoison,
SpecialStateWeakness,
SpecialStateStrength,
SpecialStateRage,
SpecialStateConfused,
SpecialStateTime,
DivineStateProtection,
DivineStateSpeed,
DivineStateFireRate,
DivineStateFireDamage,
NB_SPECIAL_STATES
};
enum enumStateResistance { ResistanceImmune, ResistanceVeryHigh, ResistanceHigh, ResistanceStandard, ResistanceLow, ResistanceVeryLow};
enum enumResistances
{
ResistanceIce, // = 0
ResistanceFire,
ResistanceStone,
ResistanceLightning,
ResistanceIllusion,
ResistancePoison,
- ResistanceRecoil,
+ ResistanceRepulsion,
ResistanceFrozen,
NB_RESISTANCES
};
struct specialStateStuct
{
enumSpecialState type;
bool active;
float timer;
float param1;
float param2;
float param3;
bool waitUnclear;
};
const std::string specialStateToLabel[NB_SPECIAL_STATES] =
{
"state_frozen",
"state_slow",
"state_speed",
"state_poison",
"state_weakness",
"state_strength",
"state_rage",
"state_confusion",
"state_time",
"state_div_protection",
"state_div_speed",
"state_div_firerate",
"state_div_damage"
};
const sf::Color specialStateToColor[NB_SPECIAL_STATES] =
{
sf::Color(100, 200, 255),
sf::Color::Red,
sf::Color::White,
sf::Color::Green,
sf::Color::Red,
sf::Color::White,
sf::Color::White,
sf::Color::White,
sf::Color::Red,
sf::Color::Yellow,
sf::Color::Yellow,
sf::Color::Yellow,
sf::Color::Yellow
};
class BaseCreatureEntity : public CollidingSpriteEntity
{
public:
BaseCreatureEntity(sf::Texture* image, float x, float y, int spriteWidth, int spriteHeight);
int getHp();
int getHpMax();
void setHp(int hp);
void setHpMax(int hpMax);
int getHpDisplay();
float getCreatureSpeed();
IntCoord getCurrentTile();
virtual void animate(float delay);
virtual float animateStates(float delay);
virtual void animateColors(float delay);
virtual void animateRecoil(float delay);
virtual void animatePhysics(float delay);
virtual void render(sf::RenderTarget* app);
virtual void calculateBB();
virtual bool collideWithMap(int direction);
void displayFlyingText(float xText, float yText, int sizeText, std::string text, TextEntity::colorTypeEnum color);
virtual int hurt(StructHurt hurtParam);
virtual void prepareDying();
virtual void dying();
enum enumMovingStyle { movWalking, movFlying};
virtual enumMovingStyle getMovingStyle();
enum enumBloodColor
{
BloodNone = -1,
BloodRed,
BloodGreen,
BloodRock,
BloodEgg,
BloodBubble,
BloodBubbleIce,
BloodBlack,
BloodBarrel,
BloodBarrelPowder,
BloodSkull
};
specialStateStuct specialState[NB_SPECIAL_STATES];
virtual void setSpecialState(enumSpecialState state, bool active, float timer, float param1, float param2, bool waitUnclear = false);
enumStateResistance resistance[NB_RESISTANCES];
bool isSpecialStateActive(enumSpecialState state);
specialStateStuct getSpecialState(enumSpecialState state);
- virtual void giveRecoil(bool stun, Vector2D velocity, float timer);
- virtual void inflictsRecoilTo(BaseCreatureEntity* targetEntity);
+ virtual void giveRepulsion(bool stun, Vector2D velocity, float timer);
+ virtual void inflictsRepulsionTo(BaseCreatureEntity* targetEntity);
virtual void computeFacingDirection();
virtual void dyingFromAge();
virtual bool canCollide();
bool canSee(float xf, float yf);
bool canWalkTo(float xf, float yf);
void heal(int healPoints);
static StructHurt getHurtParams(int damage,
enumShotType hurtingType,
int level,
bool critical,
sourceTypeEnum sourceType,
enemyTypeEnum enemyType,
bool goThrough)
{
StructHurt hurtParams;
hurtParams.damage = damage;
hurtParams.hurtingType = hurtingType;
hurtParams.level = level;
hurtParams.critical = critical;
hurtParams.sourceType = sourceType;
hurtParams.enemyType = enemyType;
hurtParams.goThrough = goThrough;
return hurtParams;
}
bool intersectsSegments(Vector2D a1, Vector2D a2, Vector2D b1, Vector2D b2);
bool intersectsTile(Vector2D a1, Vector2D a2, int xTile, int yTile);
virtual bool isAttacking(); // true when the monster is performing a melee attack
protected:
int hp;
int hpMax;
int hpDisplay;
float creatureSpeed;
bool doesAccelerate;
int shadowFrame;
int facingDirection;
float armor;
bool canExplode; // true if the monster can explode with a fire attack
bool displayDamage;
bool hurting;
float hurtingDelay;
enumShotType hurtingType;
enumBloodColor bloodColor;
enumMovingStyle movingStyle;
- struct recoilStruct
+ struct RepulseStruct
{
bool active;
Vector2D velocity;
bool stun;
+ bool propage;
float timer;
- } recoil;
+ } repulsion;
void generateStar(sf::Color starColor);
virtual void makeExplode();
private:
bool determineSatusChance(enumStateResistance resistance, int level);
int determineDamageBonus(enumStateResistance resistance, int level);
bool textTooClose(TextEntity* textEntity, float xDistMin, float yDistMin);
};
#endif // BASECREATUREENTITY_H
diff --git a/src/BatEntity.cpp b/src/BatEntity.cpp
index 05b5b7a..fc782d1 100644
--- a/src/BatEntity.cpp
+++ b/src/BatEntity.cpp
@@ -1,156 +1,156 @@
#include "BatEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
const int BAT_ACCELERATION = 10;
BatEntity::BatEntity(float x, float y, EnumBatType batType, bool invocated)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_BAT), x, y)
{
creatureSpeed = BAT_SPEED;
velocity = Vector2D(creatureSpeed);
imagesProLine = 10;
this->invocated = invocated;
this->batType = batType;
changingDelay = -0.5f;
shadowFrame = 9;
movingStyle = movFlying;
agonizingSound = SOUND_BAT_DYING;
sprite.setOrigin(32.0f, 26.0f);
if (batType == BatStandard)
{
enemyType = invocated ? EnemyTypeBat_invocated : EnemyTypeBat;
hp = BAT_HP;
meleeDamages = BAT_DAMAGES;
bloodColor = BloodRed;
dyingFrame = 8;
deathFrame = FRAME_CORPSE_BAT;
}
else // BatSkeleton
{
enemyType = invocated ? EnemyTypeBatSkeleton_invocated : EnemyTypeBatSkeleton;
hp = BAT_HP * 2;
meleeDamages = 8;
bloodColor = BloodNone;
dyingFrame = 18;
deathFrame = FRAME_CORPSE_BAT_SKELETON;
}
}
void BatEntity::animate(float delay)
{
if (!isAgonising)
{
changingDelay -= delay;
if (changingDelay < 0.0f)
{
if (batType != BatSkeleton || rand() % 3 == 0)
{
velocity = Vector2D(creatureSpeed);
acceleration.x = velocity.x / BAT_ACCELERATION;
acceleration.y = velocity.y / BAT_ACCELERATION;
computeFacingDirection();
velocity = Vector2D {0, 0};
doesAccelerate = true;
}
else
{
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), creatureSpeed ));
acceleration.x = velocity.x / BAT_ACCELERATION;
acceleration.y = velocity.y / BAT_ACCELERATION;
computeFacingDirection();
velocity = Vector2D {0, 0};
doesAccelerate = true;
}
changingDelay = 0.5f + (float)(rand() % 2500) / 1000.0f;
}
if (age < 0.0f)
frame = 1;
else
{
switch (facingDirection)
{
case 2: frame = 0; break;
case 4: frame = 2; break;
case 6: frame = 4; break;
case 8: frame = 6; break;
}
frame += ((int)(age * 7.0f)) % 2;
}
}
if (batType == BatSkeleton) frame += 10;
EnemyEntity::animate(delay);
}
void BatEntity::calculateBB()
{
boundingBox.left = (int)x - 16;
boundingBox.width = 32;
boundingBox.top = (int)y - 10;
boundingBox.height = 25;
}
void BatEntity::collideMapRight()
{
velocity.x = -velocity.x;
acceleration.x = -acceleration.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
else computeFacingDirection();
}
void BatEntity::collideMapLeft()
{
velocity.x = -velocity.x;
acceleration.x = -acceleration.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
else computeFacingDirection();
}
void BatEntity::collideMapTop()
{
velocity.y = -velocity.y;
acceleration.y = -acceleration.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
else computeFacingDirection();
}
void BatEntity::collideMapBottom()
{
velocity.y = -velocity.y;
acceleration.y = -acceleration.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
else computeFacingDirection();
}
void BatEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getEnemyType() != EnemyTypeSpiderWeb && entity->getMovingStyle() == movFlying)
{
setVelocity(Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), BAT_SPEED ));
computeFacingDirection();
}
}
void BatEntity::dying()
{
EnemyEntity::dying();
h = 25.0f;
}
void BatEntity::drop()
{
if (!invocated) EnemyEntity::drop();
}
diff --git a/src/BlackRatEntity.cpp b/src/BlackRatEntity.cpp
index e099988..d51d931 100644
--- a/src/BlackRatEntity.cpp
+++ b/src/BlackRatEntity.cpp
@@ -1,310 +1,310 @@
#include "BlackRatEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
BlackRatEntity::BlackRatEntity(float x, float y, ratBlackTypeEnum ratType)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_RAT), x, y),
currentTile(0, 0),
targetTile(0, 0)
{
this->ratType = ratType;
imagesProLine = 10;
if (ratType == RatBlackTypeNormal)
{
frame = 21;
dyingFrame = 29;
deathFrame = FRAME_CORPSE_BLACK_RAT;
enemyType = EnemyTypeRatBlack;
hp = BLACK_RAT_HP;
creatureSpeed = BLACK_RAT_SPEED;
}
else //(ratType == RatBlackTypeHelmet)
{
frame = 41;
dyingFrame = 49;
deathFrame = FRAME_CORPSE_BLACK_RAT_HELMET;
enemyType = EnemyTypeRatBlackHelmet;
hp = BLACK_RAT_HP_HELMET;
creatureSpeed = BLACK_RAT_SPEED_HELMET;
}
meleeDamages = BLACK_RAT_DAMAGES;
bloodColor = BloodRed;
shadowFrame = -1;
agonizingSound = SOUND_RAT_DYING;
currentDirection = 0;
sprite.setOrigin(32.0f, 38.0f);
findNextGoal();
}
void BlackRatEntity::animate(float delay)
{
if (age > 0.0f && !isAgonising)
{
// goal reached ?
if (currentDirection == 6 && x > (targetTile.x * TILE_WIDTH + TILE_WIDTH / 2) ) findNextGoal();
else if (currentDirection == 4 && x < (targetTile.x * TILE_WIDTH + TILE_WIDTH / 2) ) findNextGoal();
else if (currentDirection == 2 && y > (targetTile.y * TILE_HEIGHT + TILE_HEIGHT / 2 - 5) ) findNextGoal();
else if (currentDirection == 8 && y < (targetTile.y * TILE_HEIGHT + TILE_HEIGHT / 2 - 5) ) findNextGoal();
checkNextFacing(delay);
frame = ((int)(age * 5.0f)) % 4;
if (frame == 3) frame = 1;
if (facingDirection == 4 || facingDirection == 6) frame += 3;
isMirroring = (facingDirection == 6 );
if (facingDirection == 8) frame += 6;
if (ratType == RatBlackTypeHelmet) frame += 40;
else frame += 20;
}
EnemyEntity::animate(delay);
z = y + 17;
}
void BlackRatEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2 + RAT_BB_LEFT;
boundingBox.width = width - RAT_BB_WIDTH_DIFF;
boundingBox.top = (int)y - 13;
boundingBox.height = 31;
}
void BlackRatEntity::collideMapRight()
{
- if (recoil.active) recoil.active = false;
+ if (repulsion.active) repulsion.active = false;
findNextGoal();
}
void BlackRatEntity::collideMapLeft()
{
- if (recoil.active) recoil.active = false;
+ if (repulsion.active) repulsion.active = false;
findNextGoal();
}
void BlackRatEntity::collideMapTop()
{
- if (recoil.active) recoil.active = false;
+ if (repulsion.active) repulsion.active = false;
findNextGoal();
}
void BlackRatEntity::collideMapBottom()
{
- if (recoil.active) recoil.active = false;
+ if (repulsion.active) repulsion.active = false;
findNextGoal();
}
void BlackRatEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
{
int oldDirection = currentDirection;
if (currentDirection == 6 && entity->getX() > x)
{
currentDirection = 4;
targetTile = IntCoord(currentTile.x - 1, currentTile.y);
}
else if (currentDirection == 4 && entity->getX() < x)
{
currentDirection = 6;
targetTile = IntCoord(currentTile.x + 1, currentTile.y);
}
else if (currentDirection == 8 && entity->getY() < y)
{
currentDirection = 2;
targetTile = IntCoord(currentTile.x, currentTile.y + 1);
}
else if (currentDirection == 2 && entity->getY() > y)
{
currentDirection = 8;
targetTile = IntCoord(currentTile.x, currentTile.y - 1);
}
if (oldDirection != currentDirection)
{
switch (currentDirection)
{
case 4: velocity.x = - creatureSpeed; velocity.y = 0.0f; break;
case 6: velocity.x = + creatureSpeed; velocity.y = 0.0f; break;
case 2: velocity.y = + creatureSpeed; velocity.x = 0.0f; break;
case 8: velocity.y = - creatureSpeed; velocity.x = 0.0f; break;
default: break;
}
acceleration = { 0, 0 };
nextFacingDirection = currentDirection;
}
}
}
void BlackRatEntity::findNextGoal()
{
currentTile = getCurrentTile();
DungeonMap* dMap = game().getCurrentMap();
int backDirection = 0;
int oldDirection = currentDirection;
switch (currentDirection)
{
case 4: backDirection = 6; break;
case 6: backDirection = 4; break;
case 2: backDirection = 8; break;
case 8: backDirection = 2; break;
default: break;
}
bool ok = false;
{
int r = 0;
while (!ok)
{
r++;
if (r == 150) // watchdog
ok = true;
else if (r == 40)
{
backDirection = 5;
}
int newDir = rand() % 4;
if (newDir == 0)
{
if (backDirection != 4 && currentTile.x > 1 && (currentTile.y % 2 != 0) && dMap->isWalkable(currentTile.x - 1, currentTile.y))
{
currentDirection = 4;
targetTile = IntCoord(currentTile.x - 1, currentTile.y);
ok = true;
}
}
else if (newDir == 1)
{
if (backDirection != 6 && currentTile.x < MAP_WIDTH - 2 && (currentTile.y % 2 != 0) && dMap->isWalkable(currentTile.x + 1, currentTile.y))
{
currentDirection = 6;
targetTile = IntCoord(currentTile.x + 1, currentTile.y);
ok = true;
}
}
else if (newDir == 2)
{
if (backDirection != 8 && currentTile.y > 1 && (currentTile.x % 2 != 0) && dMap->isWalkable(currentTile.x, currentTile.y - 1))
{
currentDirection = 8;
targetTile = IntCoord(currentTile.x, currentTile.y - 1);
ok = true;
}
}
else
{
if (backDirection != 2 && currentTile.y < MAP_HEIGHT - 2 && (currentTile.x % 2 != 0) && dMap->isWalkable(currentTile.x, currentTile.y + 1))
{
currentDirection = 2;
targetTile = IntCoord(currentTile.x, currentTile.y + 1);
ok = true;
}
}
}
}
float accelerationAbs = (enemyType == EnemyTypeRatBlackHelmet) ? (creatureSpeed / 8) : (creatureSpeed / 16);
switch (currentDirection)
{
case 4:
velocity.x = -creatureSpeed;
velocity.y = 0.0f;
acceleration.x = -accelerationAbs;
acceleration.y = 0.0f;
break;
case 6:
velocity.x = creatureSpeed;
velocity.y = 0.0f;
acceleration.x = accelerationAbs;
acceleration.y = 0;
break;
case 2:
velocity.y = creatureSpeed;
velocity.x = 0.0f;
acceleration.y = accelerationAbs;
acceleration.x = 0.0f;
break;
case 8:
velocity.y = -creatureSpeed;
velocity.x = 0.0f;
acceleration.y = -accelerationAbs;
acceleration.x = 0.0f;
break;
default: break;
}
if (oldDirection != currentDirection)
{
velocity = Vector2D {0, 0};
doesAccelerate = true;
}
nextFacingDirection = currentDirection;
}
void BlackRatEntity::collideWithBolt(BoltEntity* boltEntity)
{
if (ratType == RatBlackTypeHelmet && boltEntity->getBoltType() != ShotTypeIllusion)
{
int collisionDir = getCollisionDirection(boltEntity);
bool boltCollide = true;
switch (facingDirection)
{
case 4:
if (collisionDir == 7 || collisionDir == 4 || collisionDir == 1) boltCollide = false;
break;
case 2:
if (collisionDir == 1 || collisionDir == 2 || collisionDir == 3) boltCollide = false;
break;
case 6:
if (collisionDir == 9 || collisionDir == 6 || collisionDir == 3) boltCollide = false;
break;
case 8:
if (collisionDir == 7 || collisionDir == 8 || collisionDir == 9) boltCollide = false;
break;
}
if (boltCollide) EnemyEntity::collideWithBolt(boltEntity);
else
{
float xs = (x + boltEntity->getX()) / 2;
float ys = (y + boltEntity->getY()) / 2;
boltEntity->collide();
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);
SoundManager::getInstance().playSound(SOUND_CLANG_00);
boltEntity->loseDamages(boltEntity->getDamages());
if (boltEntity->getBoltType() == ShotTypeStone)
{
float factor = (boltEntity->isFromPlayer() && game().getPlayer()->isEquiped(EQUIP_RAPID_SHOT)) ? 0.25f : 1.0f;
float recoilVelocity = factor * STONE_DECOIL_VELOCITY[boltEntity->getLevel()];
float recoilDelay = factor * STONE_DECOIL_DELAY[boltEntity->getLevel()];
Vector2D recoilVector = Vector2D(0, 0).vectorTo(boltEntity->getVelocity(),
recoilVelocity );
- giveRecoil(true, recoilVector, recoilDelay);
+ giveRepulsion(true, recoilVector, recoilDelay);
}
}
}
else EnemyEntity::collideWithBolt(boltEntity);
}
diff --git a/src/BogeymanEntity.cpp b/src/BogeymanEntity.cpp
index 1cb1e19..59de45f 100644
--- a/src/BogeymanEntity.cpp
+++ b/src/BogeymanEntity.cpp
@@ -1,310 +1,310 @@
#include "BogeymanEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "EnemyBoltEntity.h"
const float BOGEY_APPARITION_TIME = 1.0f;
const float BOGEY_DISAPPEARING_TIME = 1.0f;
const float BOGEY_ANIM_SPEED = 0.4f;
const float BOGEY_MOVING_DELAY = 1.0f;
const float BOGEY_INVISIBLE_DELAY = 1.0f;
const float BOGEY_VELOCITY = 155;
const float BOGEY_FIRE_VELOCITY = 320.0f;
const int BOGEY_HP = 100;
BogeymanEntity::BogeymanEntity(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_BOGEY), x, y)
{
// general
creatureSpeed = BOGEY_VELOCITY;
velocity = Vector2D(0.0f);
hp = BOGEY_HP;
meleeDamages = IMP_MELEE_DAMAGES;
bloodColor = BloodBlack;
changingDelay = BOGEY_APPARITION_TIME;
shadowFrame = -1;
movingStyle = movFlying;
imagesProLine = 8;
height = 88;
sprite.setOrigin(32,80);
state = 0;
resistance[ResistanceFrozen] = ResistanceImmune;
resistance[ResistancePoison] = ResistanceImmune;
resistance[ResistanceIce] = ResistanceHigh;
resistance[ResistanceIllusion] = ResistanceHigh;
resistance[ResistanceLightning] = ResistanceLow;
enemyType = EnemyTypeBogeyman;
hasFired = false;
isFireType1 = rand() % 2 == 0;
age = -0.001f * (rand()%4000);
}
void BogeymanEntity::animate(float delay)
{
if (!isDying && !isAgonising)
{
if (age < 0.0f)
frame = 1;
else
{
changingDelay -= delay;
if (changingDelay < 0.0f)
{
if (state == 0) // appear -> attack
{
state = 1;
changingDelay = 2 * BOGEY_ANIM_SPEED;
hasFired = false;
SoundManager::getInstance().playSound(SOUND_BOGEYMAN_ATTACK);
}
else if (state == 1) // attack -> move
{
changingDelay = BOGEY_MOVING_DELAY;
state = 2;
}
else if (state == 2) // move -> disappear
{
state = 3;
changingDelay = BOGEY_DISAPPEARING_TIME;
setVelocity(Vector2D(0.0f, 0.0f));
SoundManager::getInstance().playSound(SOUND_BOGEYMAN_VORTEX_01);
}
else if (state == 3)
{
state = 4;
changingDelay = BOGEY_INVISIBLE_DELAY;
}
else if (state == 4) // invisible -> apparition
{
state = 0;
changingDelay = BOGEY_APPARITION_TIME;
teleport();
SoundManager::getInstance().playSound(SOUND_BOGEYMAN_VORTEX_00);
}
else if (state == -1) // dying
{
isDying = true;
}
}
if (state == 1) // fira anim
{
frame = changingDelay / BOGEY_ANIM_SPEED * 8;
if (!hasFired && frame < 8)
{
hasFired = true;
fire();
}
frame = 32 - frame;
}
else if (state == 2) // normal
{
frame = (int)((BOGEY_MOVING_DELAY - changingDelay) / BOGEY_ANIM_SPEED * 8) % 16;
}
else if (state == -1)
{
frame = 64 - (8 * (changingDelay / BOGEY_ANIM_SPEED));
}
}
}
EnemyEntity::animate(delay);
if (age > 0 && delay >= age) SoundManager::getInstance().playSound(SOUND_BOGEYMAN_VORTEX_00);
z = y + 8;
}
void BogeymanEntity::calculateBB()
{
boundingBox.left = (int)x - 14;
boundingBox.width = 28;
boundingBox.top = (int)y - 55;
boundingBox.height = 58;
}
void BogeymanEntity::collideMapRight()
{
velocity.x = -velocity.x;
}
void BogeymanEntity::collideMapLeft()
{
velocity.x = -velocity.x;
}
void BogeymanEntity::collideMapTop()
{
velocity.y = -velocity.y;
}
void BogeymanEntity::collideMapBottom()
{
velocity.y = -velocity.y;
}
void BogeymanEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getEnemyType() != EnemyTypeSpiderWeb && entity->getMovingStyle() == movFlying)
{
Vector2D vel = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), 50.0f );
- giveRecoil(false, vel, 0.3f);
+ giveRepulsion(false, vel, 0.3f);
}
}
bool BogeymanEntity::canCollide()
{
return (state == 1 || state == 2);
}
int BogeymanEntity::hurt(StructHurt hurtParam)
{
int result = EnemyEntity::hurt(hurtParam);
return result;
}
void BogeymanEntity::dying()
{
EnemyEntity::dying();
for (int i = 0; i < 4; i++) game().generateBlood(x, y, BloodBlack);
h = 25.0f;
}
void BogeymanEntity::fire()
{
for (int i = 0; i < 4; i++)
{
EnemyBoltEntity* bolt;
bolt = new EnemyBoltEntity(x, y - 40, ShotTypeIllusion, 0, enemyType);
bolt->setDamages(8);
if (isFireType1)
{
switch (i)
{
case 0: bolt->setVelocity(Vector2D(BOGEY_FIRE_VELOCITY * 0.7f, BOGEY_FIRE_VELOCITY * 0.7f)); break;
case 1: bolt->setVelocity(Vector2D(BOGEY_FIRE_VELOCITY * -0.7f, BOGEY_FIRE_VELOCITY * 0.7f)); break;
case 2: bolt->setVelocity(Vector2D(BOGEY_FIRE_VELOCITY * -0.7f, BOGEY_FIRE_VELOCITY * -0.7f)); break;
case 3: bolt->setVelocity(Vector2D(BOGEY_FIRE_VELOCITY * 0.7f, BOGEY_FIRE_VELOCITY * -0.7f)); break;
}
}
else
{
switch (i)
{
case 0: bolt->setVelocity(Vector2D(BOGEY_FIRE_VELOCITY, 0)); break;
case 1: bolt->setVelocity(Vector2D(-BOGEY_FIRE_VELOCITY, 0)); break;
case 2: bolt->setVelocity(Vector2D(0, BOGEY_FIRE_VELOCITY)); break;
case 3: bolt->setVelocity(Vector2D(0, -BOGEY_FIRE_VELOCITY)); break;
}
}
}
SoundManager::getInstance().playSound(SOUND_BLAST_ILLUSION);
isFireType1 = !isFireType1;
}
void BogeymanEntity::render(sf::RenderTarget* app)
{
if (hurting && hp > 0)
{
if (hurtingDelay > 0.0f)
{
int fadeColor = (sf::Uint8)((HURTING_DELAY - hurtingDelay) * 127);
if (hurtingDelay > HURTING_DELAY) fadeColor = 0;
sprite.setColor(sf::Color(255, 255, 255, 128 + fadeColor )); // fade
}
}
if (state == 0)
{
if (changingDelay > BOGEY_APPARITION_TIME - 0.5f)
{
float scale = 2 * (BOGEY_APPARITION_TIME - changingDelay);
sprite.setScale(scale, scale);
}
else if (changingDelay < 0.5f)
{
float scale = changingDelay * 2;
sprite.setScale(scale, scale);
}
else
sprite.setScale(1.0f, 1.0f);
int holeFrame = ((int)(age * 20.0f)) % 8;
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(holeFrame * width, 5 * height, width, height));
app->draw(sprite);
sprite.setScale(1.0f, 1.0f);
if (changingDelay <= BOGEY_ANIM_SPEED)
{
frame = 32 + (8 * (changingDelay / BOGEY_ANIM_SPEED));
EnemyEntity::render(app);
}
}
else if (state == 3)
{
if (changingDelay > BOGEY_DISAPPEARING_TIME - 0.5f)
{
float scale = 2 * (BOGEY_DISAPPEARING_TIME - changingDelay);
sprite.setScale(scale, scale);
}
else if (changingDelay < 0.5f)
{
float scale = changingDelay * 2;
sprite.setScale(scale, scale);
}
else
sprite.setScale(1.0f, 1.0f);
int holeFrame = ((int)(age * 12.0f)) % 8;
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(holeFrame * width, 5 * height, width, height));
app->draw(sprite);
sprite.setScale(1.0f, 1.0f);
if (changingDelay >= (BOGEY_DISAPPEARING_TIME - BOGEY_ANIM_SPEED))
{
frame = 32 + (8 * ((BOGEY_DISAPPEARING_TIME - changingDelay) / BOGEY_ANIM_SPEED));
EnemyEntity::render(app);
}
}
else if (state != 4)
EnemyEntity::render(app);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void BogeymanEntity::teleport()
{
x = ((int)(game().getPlayer()->getX()) / TILE_WIDTH) * TILE_WIDTH + TILE_WIDTH * 0.5f;
y = ((int)(game().getPlayer()->getY()) / TILE_HEIGHT) * TILE_HEIGHT + TILE_HEIGHT * 0.5f;
}
void BogeymanEntity::prepareDying()
{
state = -1; // dying
changingDelay = BOGEY_ANIM_SPEED * 2;
velocity.x = 0.0f;
velocity.y = 0.0f;
SoundManager::getInstance().playSound(SOUND_BOGEYMAN_DIE);
type = ENTITY_ENEMY_NC;
}
diff --git a/src/BubbleEntity.cpp b/src/BubbleEntity.cpp
index d192066..7cdf8c5 100644
--- a/src/BubbleEntity.cpp
+++ b/src/BubbleEntity.cpp
@@ -1,206 +1,206 @@
#include "BubbleEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
BubbleEntity::BubbleEntity(float x, float y, EnumBubbleType bubbleType, int bubbleSize)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_BUBBLE), x, y)
{
this->bubbleSize = bubbleSize;
this->bubbleType = bubbleType;
imagesProLine = 2;
frame = 0;
enemyType = EnemyTypeBubble;
if (bubbleSize == 0)
{
hp = 20;
creatureSpeed = 150.0f;
}
else if (bubbleSize == 1)
{
hp = 18;
creatureSpeed = 180.0f;
sprite.setScale(0.7, 0.7);
age = 0.0f;
}
else if (bubbleSize == 2)
{
hp = 16;
creatureSpeed = 210.0f;
sprite.setScale(0.5, 0.5);
age = 0.0f;
}
else if (bubbleSize == 3)
{
hp = 12;
creatureSpeed = 225.0f;
sprite.setScale(0.35, 0.35);
age = 0.0f;
}
else if (bubbleSize == 4)
{
hp = 5;
creatureSpeed = 240.0f;
sprite.setScale(0.2, 0.2);
age = 0.0f;
}
velocity = Vector2D(creatureSpeed);
computeFacingDirection();
meleeDamages = 5;
bloodColor = BloodNone;
shadowFrame = 1;
if (bubbleType == BubbleIce)
{
frame = 2;
shadowFrame = 3;
meleeType = ShotTypeIce;
resistance[ResistanceFrozen] = ResistanceImmune;
resistance[ResistanceIce] = ResistanceVeryHigh;
resistance[ResistanceFire] = ResistanceVeryLow;
}
else
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_EYE));
imagesProLine = 12;
shadowFrame = 23;
spin = 20 + rand() % 20;
}
width = 128;
height = 128;
sprite.setOrigin(64, 64);
canExplode = false;
}
int BubbleEntity::getBubbleSize()
{
return bubbleSize;
}
void BubbleEntity::calculateBB()
{
boundingBox.left = (int)x - 50 * sprite.getScale().x;
boundingBox.width = 100 * sprite.getScale().x;
boundingBox.top = (int)y - 50 * sprite.getScale().x;
boundingBox.height = 100 * sprite.getScale().x;
}
void BubbleEntity::animate(float delay)
{
if (bubbleType != BubbleIce)
{
if (age > 0)
frame = ((int)(age * (28.0f + 5.0f * (float)bubbleSize))) % 18;
else
frame = 0;
}
EnemyEntity::animate(delay);
}
void BubbleEntity::render(sf::RenderTarget* app)
{
if (bubbleType != BubbleIce)
{
// shadow
sprite.setPosition(x, y + 5);
sprite.setTextureRect(sf::IntRect(11 * width, 1 * height, width, height));
app->draw(sprite);
// eye
sprite.setRotation(age * spin);
sprite.setPosition(x, y);
int nx = frame % imagesProLine;
int ny = frame / imagesProLine;
sprite.setTextureRect(sf::IntRect(nx * width, ny * height, width, height));
app->draw(sprite);
// lightning
sprite.setRotation(0);
sprite.setTextureRect(sf::IntRect(6 * width, height, width, height));
app->draw(sprite);
nx = 7 + (int)(age * 5) % 4;
sprite.setTextureRect(sf::IntRect(nx * width, height, width, height));
app->draw(sprite);
}
else
EnemyEntity::render(app);
}
void BubbleEntity::collideMapRight()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void BubbleEntity::collideMapLeft()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void BubbleEntity::collideMapTop()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void BubbleEntity::collideMapBottom()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void BubbleEntity::collideWithEnemy(EnemyEntity* entity)
{
BubbleEntity* bubbleEntity = dynamic_cast<BubbleEntity*>(entity);
if (bubbleEntity == NULL)
{
if (entity->getMovingStyle() == movWalking)
setVelocity(Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), creatureSpeed ));
}
else
{
if (bubbleEntity->getBubbleSize() <= bubbleSize)
setVelocity(Vector2D(bubbleEntity->getX(), bubbleEntity->getY()).vectorTo(Vector2D(x, y), creatureSpeed ));
}
}
void BubbleEntity::dying()
{
isDying = true;
if (bubbleSize == 0) game().addKilledEnemy(enemyType, hurtingType);
if (bubbleSize < 4)
{
int nbBubbles = 2;
if (bubbleType == BubbleTriple) nbBubbles = 3;
for (int i = 0; i < nbBubbles; i++)
{
BubbleEntity* b = new BubbleEntity(x - 5 + rand() % 10, y - 5 + rand() % 10, bubbleType, bubbleSize + 1);
b->setSpecialState(SpecialStateIce,
true,
specialState[SpecialStateIce].timer,
specialState[SpecialStateIce].param1,
specialState[SpecialStateIce].param2);
}
}
for (int i = 0; i < 5 - bubbleSize; i++)
game().generateBlood(x, y, bubbleType == BubbleIce ? BloodBubbleIce : BloodBubble);
if (bubbleType == BubbleIce)
SoundManager::getInstance().playSound(SOUND_ICE_BLOCK);
else
SoundManager::getInstance().playSound(SOUND_BUBBLE_00 + rand() % 2);
}
diff --git a/src/ButcherEntity.cpp b/src/ButcherEntity.cpp
index 7e58881..3ae8e38 100644
--- a/src/ButcherEntity.cpp
+++ b/src/ButcherEntity.cpp
@@ -1,168 +1,168 @@
#include "ButcherEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "SausageEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "TextMapper.h"
ButcherEntity::ButcherEntity(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_BUTCHER), x, y)
{
width = 80;
height = 160;
sprite.setOrigin(40, 115);
creatureSpeed = BUTCHER_VELOCITY;
velocity = Vector2D(creatureSpeed);
computeFacingDirection();
hp = BUTCHER_HP;
hpMax = BUTCHER_HP;
hpDisplay = BUTCHER_HP;
meleeDamages = BUTCHER_DAMAGES;
sausages = 0;
type = ENTITY_ENEMY_BOSS;
bloodColor = BloodRed;
shadowFrame = 4;
dyingFrame = 3;
deathFrame = FRAME_CORPSE_BUTCHER;
agonizingSound = SOUND_BUTCHER_DIE;
hurtingSound = SOUND_BUTCHER_HURT;
enemyType = EnemyTypeButcher;
timer = (rand() % 50) / 10.0f;
age = -1.5f;
frame = 1;
resistance[ResistanceFrozen] = ResistanceHigh;
- resistance[ResistanceRecoil] = ResistanceHigh;
+ resistance[ResistanceRepulsion] = ResistanceHigh;
canExplode = false;
}
void ButcherEntity::animate(float delay)
{
if (age > 0.0f && !isAgonising)
{
sprite.setColor(sf::Color(255,255,255,255));
timer = timer - delay;
if (timer <= 0.0f)
{
creatureSpeed = BUTCHER_VELOCITY + (hpMax - hp) * 0.8f;
timer = (rand() % 50) / 10.0f;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), creatureSpeed ));
if (rand()%2 == 0)
SoundManager::getInstance().playSound(SOUND_BUTCHER_00);
else
SoundManager::getInstance().playSound(SOUND_BUTCHER_01);
}
frame = ((int)(age * creatureSpeed / 25)) % 4;
if (frame == 3) frame = 1;
if (velocity.x > 1.0f) isMirroring = true;
else if (velocity.x < -1.0f) isMirroring = false;
}
EnemyEntity::animate(delay);
z = y + 30;
}
void ButcherEntity::calculateBB()
{
boundingBox.left = (int)x - 22;
boundingBox.width = 44;
boundingBox.top = (int)y - 18;
boundingBox.height = 48;
}
void ButcherEntity::collideMapRight()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void ButcherEntity::collideMapLeft()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void ButcherEntity::collideMapTop()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void ButcherEntity::collideMapBottom()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void ButcherEntity::collideWithEnemy(EnemyEntity* entity)
{
- if (recoil.active && recoil.stun) return;
+ if (repulsion.active && repulsion.stun) return;
if (entity->getMovingStyle() == movWalking && entity->getEnemyType() != EnemyTypeSausage_invocated)
{
Vector2D vel = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), 100.0f );
- giveRecoil(false, vel, 0.3f);
+ giveRepulsion(false, vel, 0.3f);
}
}
void ButcherEntity::drop()
{
dropItem(ItemScrollRevelation);
EntityManager::EntityList* entityList = EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
EnemyEntity* entity = dynamic_cast<EnemyEntity*>(e);
if (entity != NULL)
{
if (entity->getEnemyType()== EnemyTypeSausage_invocated)
{
entity->hurt(getHurtParams(entity->getHp(), ShotTypeStandard, 0, false, SourceTypeMelee, enemyType, false));
}
}
}
}
void ButcherEntity::render(sf::RenderTarget* app)
{
EnemyEntity::render(app);
renderLifeBar(app, tools::getLabel("enemy_butcher"));
}
int ButcherEntity::hurt(StructHurt hurtParam)
{
creatureSpeed = BUTCHER_VELOCITY + hpMax - hp;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), creatureSpeed ));
int result = EnemyEntity::hurt(hurtParam);
int totalDamages = hpMax - hp;
if (hp > 0 && totalDamages / 8 > sausages)
{
sausages++;
new SausageEntity(x, y, true);
}
return result;
}
bool ButcherEntity::isAttacking()
{
return true;
}
diff --git a/src/CauldronEntity.cpp b/src/CauldronEntity.cpp
index 29d9a99..98fa60e 100644
--- a/src/CauldronEntity.cpp
+++ b/src/CauldronEntity.cpp
@@ -1,250 +1,250 @@
#include "CauldronEntity.h"
#include "SlimeEntity.h"
#include "ExplosionEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
CauldronEntity::CauldronEntity(float x, float y, cauldronTypeEnum cauldronType)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_CAULDRON), x, y)
{
creatureSpeed = 0.0f;
velocity = Vector2D(0.0f, 0.0f);
hp = CAULDRON_HP;
hpMax = hp;
meleeDamages = 0;
this->cauldronType = cauldronType;
bloodColor = BloodNone;
invokeDelay = 2.5f;
bubbleDelay = 0.0f;
shadowFrame = 2;
sprite.setOrigin(32, 28);
imagesProLine = 2;
deathFrame = FRAME_CORPSE_CAULDRON;
dyingSound = SOUND_CAULDRON_DIE;
if (cauldronType == CauldronTypeElemental)
{
enemyType = EnemyTypeCauldronElemental;
colorChangeDelay = 4.0f + rand()% 40 * 0.1f;
colorState = rand() % 3;
}
else
{
enemyType = EnemyTypeCauldron;
}
enemyType = cauldronType == CauldronTypeStandard ? EnemyTypeCauldron : EnemyTypeCauldronElemental;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceImmune;
canExplode = false;
}
void CauldronEntity::animate(float delay)
{
if (isAgonising)
{
agonizingDelay -= delay;
if (agonizingDelay <= 0.0f)
{
isDying = true;
game().addCorpse(x, y, deathFrame);
}
}
else
{
SoundManager::getInstance().playSound(SOUND_CAULDRON, false);
invokeDelay -= delay;
if (invokeDelay < 0.0f)
{
if (cauldronType == CauldronTypeElemental)
{
if (game().getEnemyCount() < 9)
{
slimeTypeEnum slimeType = SlimeTypeStandard;
switch (colorState)
{
case 0: slimeType = SlimeTypeBlue; break;
case 1: slimeType = SlimeTypeRed; break;
case 2: slimeType = SlimeTypeStandard; break;
}
SlimeEntity* slime = new SlimeEntity(x, y, slimeType, true);
slime->disableCollidingTemporary();
invokeDelay = 3.75f + (float)(rand() % 3000) / 1000.0f;
}
}
else
{
SlimeEntity* slime = new SlimeEntity(x, y, SlimeTypeViolet, true);
slime->disableCollidingTemporary();
invokeDelay = 1.5f + (float)(rand() % 2500) / 1000.0f;
}
}
if (cauldronType == CauldronTypeElemental)
{
colorChangeDelay -= delay;
if (colorChangeDelay < 0.0f)
{
colorChangeDelay = 4.0f + rand()% 50 * 0.1f;
if (rand() % 2 == 0)
{
colorState++;
if (colorState > 2) colorState = 0;
}
else
{
colorState--;
if (colorState < 0) colorState = 2;
}
}
}
bubbleDelay -= delay;
if (bubbleDelay < 0.0f)
{
bubbleDelay = 0.3f;
int bubbleFrame = 32;
if (cauldronType == CauldronTypeElemental)
{
switch (colorState)
{
case 0: bubbleFrame = 33; break;
case 1: bubbleFrame = 34; break;
case 2: bubbleFrame = 35; break;
}
}
for (int i=0; i < 2; i++)
{
float xBub = x - 16 + rand() % 32;
SpriteEntity* bubble = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_CAULDRON), xBub, y - 20, 8, 8);
bubble->setZ(z);
bubble->setFrame(bubbleFrame);
bubble->setType(ENTITY_EFFECT);
bubble->setWeight(-20 - rand() % 40);
bubble->setLifetime(2.0f);
float bloodScale = 0.3f + (rand() % 20) * 0.1f;
bubble->setScale(bloodScale, bloodScale);
}
}
frame = hp > hpMax / 2 ? 0 : 1;
if (cauldronType == CauldronTypeElemental)
{
switch (colorState)
{
case 0: frame += 2; break;
case 1: frame += 4; break;
case 2: frame += 6; break;
}
}
EnemyEntity::animate(delay);
}
}
void CauldronEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (!isDying && !isAgonising && collideWithEntity(entity))
{
if (entity->getType() == ENTITY_PLAYER || entity->getType() == ENTITY_BOLT )
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(entity);
BoltEntity* boltEntity = dynamic_cast<BoltEntity*>(entity);
if (playerEntity != NULL && !playerEntity->isDead())
{
inflictsRecoilTo(playerEntity);
}
else if (boltEntity != NULL && !boltEntity->getDying() && boltEntity->getAge() > 0.05f)
{
collideWithBolt(boltEntity);
}
}
else // collision with other enemy ?
{
if (entity->getType() >= ENTITY_ENEMY && entity->getType() <= ENTITY_ENEMY_MAX)
{
if (this != entity)
{
EnemyEntity* enemyEntity = static_cast<EnemyEntity*>(entity);
if (enemyEntity->canCollide()) collideWithEnemy(enemyEntity);
}
}
}
}
}
void CauldronEntity::calculateBB()
{
boundingBox.left = (int)x - 25;
boundingBox.width = 50;
boundingBox.top = (int)y - 10;
boundingBox.height = 42;
}
void CauldronEntity::collideMapRight()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void CauldronEntity::collideMapLeft()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void CauldronEntity::collideMapTop()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void CauldronEntity::collideMapBottom()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void CauldronEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() != movFlying)
inflictsRecoilTo(entity);
}
void CauldronEntity::dying()
{
new ExplosionEntity(x, y, ExplosionTypeViolet, 0, EnemyTypeNone, true);
if (cauldronType == CauldronTypeElemental)
{
switch (colorState)
{
case 0: deathFrame = FRAME_CORPSE_CAULDRON_RED; break;
case 1: deathFrame = FRAME_CORPSE_CAULDRON_BLUE; break;
case 2: deathFrame = FRAME_CORPSE_CAULDRON_GREEN; break;
}
}
EnemyEntity::dying();
return;
}
void CauldronEntity::drop()
{
EnemyEntity::drop();
}
void CauldronEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
{
Vector2D recoilVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), 200.0f );
- targetEntity->giveRecoil(false, recoilVector, 0.1f);
+ targetEntity->giveRepulsion(false, recoilVector, 0.1f);
}
diff --git a/src/CyclopsEntity.cpp b/src/CyclopsEntity.cpp
index a3b2910..02aaf53 100644
--- a/src/CyclopsEntity.cpp
+++ b/src/CyclopsEntity.cpp
@@ -1,370 +1,370 @@
#include "CyclopsEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "RockMissileEntity.h"
#include "FallingRockEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "TextMapper.h"
#include <iostream>
CyclopsEntity::CyclopsEntity(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_CYCLOP), x, y)
{
width = 128;
height = 192;
creatureSpeed = CYCLOP_SPEED[0];
velocity = Vector2D(creatureSpeed);
hp = CYCLOP_HP;
hpDisplay = CYCLOP_HP;
hpMax = CYCLOP_HP;
meleeDamages = CYCLOP_DAMAGES;
type = ENTITY_ENEMY_BOSS;
bloodColor = BloodNone; // stones don't bleed
dyingFrame = 5;
deathFrame = FRAME_CORPSE_CYCLOP;
agonizingSound = SOUND_CYCLOP_DIE;
frame = 0;
if (game().getPlayerPosition().x > x) isMirroring = true;
sprite.setOrigin(64.0f, 143.0f);
nextRockMissile = 0;
destroyLevel = 0;
state = 0;
timer = 2.0f;
counter = 10;
age = -1.5f;
enemyType = EnemyTypeCyclops;
resistance[ResistanceFrozen] = ResistanceVeryHigh;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceImmune;
canExplode = false;
}
int CyclopsEntity::getHealthLevel()
{
int healthLevel = 0;
if (hp <= hpMax * 0.25) healthLevel = 3;
else if (hp <= hpMax * 0.5) healthLevel = 2;
else if (hp <= hpMax * 0.75) healthLevel = 1;
return healthLevel;
}
void CyclopsEntity::fire()
{
new RockMissileEntity(x, y - 27, nextRockMissile);
SoundManager::getInstance().playSound(SOUND_THROW);
}
void CyclopsEntity::initFallingGrid()
{
for (int i = 0; i < MAP_WIDTH; i++)
for (int j = 0; j < MAP_HEIGHT; j++)
fallingGrid[i][j] = false;
}
void CyclopsEntity::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,
false);
}
void CyclopsEntity::computeNextRockMissile()
{
if (getHealthLevel() == 0)
nextRockMissile = rand()%5 == 0 ? 1 : 0;
else if (getHealthLevel() == 1)
nextRockMissile = rand()%3 == 0 ? 1 : 0;
else if (getHealthLevel() == 2)
nextRockMissile = rand()%2 == 0 ? 0 : 1;
else
nextRockMissile = rand()%3 == 0 ? 0 : 1;
}
void CyclopsEntity::computeStates(float delay)
{
timer -= delay;
if (timer <= 0.0f)
{
if (state == 0) // walking
{
if (counter > 0)
{
counter--;
timer = 0.5f;
creatureSpeed = CYCLOP_SPEED[getHealthLevel()];
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), creatureSpeed ));
}
else
{
velocity.x = 0.0f;
velocity.y = 0.0f;
if (destroyLevel < getHealthLevel())
{
state = 3; // charge to destroy
destroyLevel++;
counter = destroyLevel + 1;
timer = 0.9f;
SoundManager::getInstance().playSound(SOUND_CYCLOP_00);
initFallingGrid();
}
else
{
state = 1; // charge to fire
timer = 0.9f;
counter = CYCLOP_NUMBER_ROCKS[getHealthLevel()];
SoundManager::getInstance().playSound(SOUND_CYCLOP_00);
computeNextRockMissile();
}
}
}
else if (state == 1) // fire
{
state = 2;
fire();
timer = CYCLOP_FIRE_DELAY[getHealthLevel()];
}
else if (state == 2) // fire end
{
if (counter <= 1)
{
state = 0;
timer = 0.2f;
counter = 10;
}
else
{
counter--;
state = 1;
timer = 0.2f;
computeNextRockMissile();
}
}
else if (state == 3)
{
state = 4; // destroy
timer = 0.2;
game().makeShake(0.4f);
SoundManager::getInstance().playSound(SOUND_CYCLOPS_IMPACT);
for (int i = 0; i < 10 ; i++) fallRock();
}
else if (state == 4)
{
if (counter <= 1)
{
state = 0;
timer = 0.2f;
counter = 10;
}
else
{
counter--;
state = 3;
timer = 0.3f;
}
}
}
}
void CyclopsEntity::animate(float delay)
{
if (age <= 0.0f)
{
age += delay;
return;
}
if (isAgonising)
{
if (h < -0.01f)
{
isDying = true;
game().addCorpse(x, y, deathFrame);
if (dyingSound != SOUND_NONE) SoundManager::getInstance().playSound(dyingSound);
}
else
{
frame = dyingFrame;
hVelocity -= 700.0f * delay;
h += hVelocity * delay;
}
return;
}
// special states
if (specialState[SpecialStateIce].active) delay *= specialState[SpecialStateIce].param1;
// IA
computeStates(delay);
// collisions
if (canCollide()) testSpriteCollisions();
BaseCreatureEntity::animate(delay);
// old frame (for sound)
int oldFrame = frame;
// current frame
if (state == 0)
{
int r = ((int)(age * 5.0f)) % 4;
if (r == 2) frame = 0;
else if (r == 3) frame = 2;
else frame = r;
if (oldFrame == 1 && frame == 0) SoundManager::getInstance().playSound(SOUND_HEAVY_STEP_00);
else if (oldFrame == 2 && frame == 0) SoundManager::getInstance().playSound(SOUND_HEAVY_STEP_01);
}
else if (state == 1)
{
isMirroring = game().getPlayer()->getX() > x;
frame = timer > 0.5f ? 4 : 3;
}
else if (state == 2)
{
frame = 4;
}
else if (state == 3)
{
frame = 6;
}
else if (state == 4)
{
frame = 7;
}
// frame's mirroring
if (velocity.x > 1.0f)
isMirroring = true;
else if (velocity.x < -1.0f)
isMirroring = false;
z = y + 36;
}
int CyclopsEntity::hurt(StructHurt hurtParam)
{
if (destroyLevel < getHealthLevel()) hurtParam.damage /= 3;
return EnemyEntity::hurt(hurtParam);
}
void CyclopsEntity::calculateBB()
{
boundingBox.left = (int)x - 32;
boundingBox.width = 58;
boundingBox.top = (int)y - 52;
boundingBox.height = 90;
}
void CyclopsEntity::afterWallCollide()
{
}
void CyclopsEntity::collideMapRight()
{
velocity.x = -velocity.x;
afterWallCollide();
}
void CyclopsEntity::collideMapLeft()
{
velocity.x = -velocity.x;
afterWallCollide();
}
void CyclopsEntity::collideMapTop()
{
velocity.y = -velocity.y;
afterWallCollide();
}
void CyclopsEntity::collideMapBottom()
{
velocity.y = -velocity.y;
afterWallCollide();
}
void CyclopsEntity::drop()
{
dropItem(ItemBossHeart);
}
void CyclopsEntity::render(sf::RenderTarget* app)
{
// shadow
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(8 * width, 0, width, height));
app->draw(sprite);
sprite.setPosition(x, y);
EnemyEntity::render(app);
// stones
if (state == 1 && timer < 0.5f)
{
if (nextRockMissile == 0) // small rock
{
sprite.setTextureRect(sf::IntRect(1152, 0, 64, 64));
if (isMirroring)
sprite.setPosition(x + 60, y + 45);
else
sprite.setPosition(x + 4, y + 45);
}
else // medium rock
{
sprite.setTextureRect(sf::IntRect(1152, 64, 64, 64));
if (isMirroring)
sprite.setPosition(x + 60, y + 33);
else
sprite.setPosition(x + 4, y + 33);
}
app->draw(sprite);
sprite.setPosition(x, y);
}
renderLifeBar(app, tools::getLabel("enemy_cyclops"));
}
void CyclopsEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
- inflictsRecoilTo(entity);
+ inflictsRepulsionTo(entity);
}
-void CyclopsEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
+void CyclopsEntity::inflictsRepulsionTo(BaseCreatureEntity* targetEntity)
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(targetEntity);
if (playerEntity != NULL && !playerEntity->isDead())
{
//Vector2D recoilVector = Vector2D(targetEntity->getX(), targetEntity->getY()).vectorTo(Vector2D(x, y), 450.0f);
Vector2D recoilVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), 450.0f);
- targetEntity->giveRecoil(true, recoilVector, 0.5f);
+ targetEntity->giveRepulsion(true, recoilVector, 0.5f);
}
}
diff --git a/src/CyclopsEntity.h b/src/CyclopsEntity.h
index 1872e0f..36ee65e 100644
--- a/src/CyclopsEntity.h
+++ b/src/CyclopsEntity.h
@@ -1,43 +1,43 @@
#ifndef CYCLOPENTITY_H
#define CYCLOPENTITY_H
#include "EnemyEntity.h"
#include "PlayerEntity.h"
class CyclopsEntity : public EnemyEntity
{
public:
CyclopsEntity(float x, float y);
virtual void animate(float delay);
virtual void render(sf::RenderTarget* app);
virtual void calculateBB();
- virtual void inflictsRecoilTo(BaseCreatureEntity* targetEntity);
+ virtual void inflictsRepulsionTo(BaseCreatureEntity* targetEntity) override;
protected:
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
void afterWallCollide();
virtual int hurt(StructHurt hurtParam) override;
virtual void collideWithEnemy(EnemyEntity* entity) override;
virtual void drop();
void computeStates(float delay);
int getHealthLevel();
private:
float timer;
int state;
int counter;
int destroyLevel;
int nextRockMissile;
void computeNextRockMissile();
void fire();
void fallRock();
void initFallingGrid();
bool fallingGrid[MAP_WIDTH][MAP_HEIGHT];
};
#endif // CYCLOPENTITY_H
diff --git a/src/EnemyEntity.cpp b/src/EnemyEntity.cpp
index 42525fb..76a613b 100644
--- a/src/EnemyEntity.cpp
+++ b/src/EnemyEntity.cpp
@@ -1,432 +1,432 @@
#include "EnemyEntity.h"
#include "PlayerEntity.h"
#include "ExplosionEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
const float FACING_DELAY = 0.17f;
EnemyEntity::EnemyEntity(sf::Texture* image, float x, float y)
: BaseCreatureEntity (image, x, y, 64, 64)
{
type = ENTITY_ENEMY;
bloodColor = BloodRed;
z = y;
h = 0;
age = -0.001f * (rand()%800) - 0.4f;
deathFrame = -1;
dyingFrame = -1;
dyingSound = SOUND_ENNEMY_DYING;
agonizingSound = SOUND_NONE;
hurtingSound = SOUND_NONE;
isAgonising = false;
enemyType = NB_ENEMY;
meleeLevel = 0;
meleeType = ShotTypeStandard;
canExplode = true;
label_dy = 0;
nextFacingDirection = 0;
facingTimer = -1.0f;
}
enemyTypeEnum EnemyEntity::getEnemyType()
{
return enemyType;
}
void EnemyEntity::checkNextFacing(float dt)
{
if (facingTimer > 0.0f) facingTimer -= dt;
if (facingDirection != nextFacingDirection && facingTimer <= 0.0f)
{
facingDirection = nextFacingDirection;
facingTimer = FACING_DELAY;
}
}
void EnemyEntity::setLabelDy(float label_dy)
{
this->label_dy = label_dy;
}
void EnemyEntity::animate(float delay)
{
if (isAgonising)
{
if (hpDisplay > hp) hpDisplay--;
if (h < -0.01f)
{
isAgonising = false;
isDying = true;
game().addCorpse(x, y, deathFrame);
if (dyingSound != SOUND_NONE) SoundManager::getInstance().playSound(dyingSound);
}
else
{
frame = dyingFrame;
hVelocity -= 700.0f * delay;
h += hVelocity * delay;
}
return;
}
if (canCollide()) testSpriteCollisions();
if (age > 0.0f)
BaseCreatureEntity::animate(delay);
else
age += delay;
// FIX enemy not on map
if (x < TILE_WIDTH / 2 || x > MAP_WIDTH * TILE_WIDTH || y < TILE_HEIGHT / 2 || y > MAP_HEIGHT * TILE_HEIGHT)
isDying = true;
}
void EnemyEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2;
boundingBox.width = width;
boundingBox.top = (int)y - height / 2;
boundingBox.height = height;
}
void EnemyEntity::collideMapRight()
{
velocity.x = 0.0f;
}
void EnemyEntity::collideMapLeft()
{
velocity.x = 0.0f;
}
void EnemyEntity::collideMapTop()
{
velocity.y = 0.0f;
}
void EnemyEntity::collideMapBottom()
{
velocity.y = 0.0f;
}
void EnemyEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (!isDying && !isAgonising && collideWithEntity(entity))
{
if (entity->getType() == ENTITY_PLAYER || entity->getType() == ENTITY_BOLT )
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(entity);
BoltEntity* boltEntity = dynamic_cast<BoltEntity*>(entity);
if (playerEntity != NULL && !playerEntity->isDead())
{
if (playerEntity->hurt(getHurtParams(meleeDamages, meleeType, meleeLevel, false, SourceTypeBolt, enemyType, false)) > 0)
{
float xs = (x + playerEntity->getX()) / 2;
float ys = (y + playerEntity->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);
if (playerEntity->isEquiped(EQUIP_ROBE_ADVANCED))
{
- giveRecoil(true, Vector2D(playerEntity->getX(), playerEntity->getY()).vectorTo(Vector2D(x, y), 800), 0.8f);
+ giveRepulsion(true, Vector2D(playerEntity->getX(), playerEntity->getY()).vectorTo(Vector2D(x, y), 800), 0.8f);
SoundManager::getInstance().playSound(SOUND_ELECTRIC_CHARGE);
star->setScale(1.5f, 1.5f);
star->setColor(sf::Color(220, 180, 255));
star->setLifetime(1.3f);
game().makeColorEffect(X_GAME_COLOR_VIOLET, 0.2f);
}
}
- inflictsRecoilTo(playerEntity);
+ inflictsRepulsionTo(playerEntity);
}
else if (boltEntity != NULL && !boltEntity->getDying() && boltEntity->getAge() > 0.05f)
{
collideWithBolt(boltEntity);
}
}
else // collision with other enemy ?
{
if (entity->getType() >= ENTITY_ENEMY && entity->getType() <= ENTITY_ENEMY_MAX)
{
if (this != entity)
{
EnemyEntity* enemyEntity = static_cast<EnemyEntity*>(entity);
if (enemyEntity->canCollide()) collideWithEnemy(enemyEntity);
}
}
}
}
}
void EnemyEntity::collideWithBolt(BoltEntity* boltEntity)
{
float xs = (x + boltEntity->getX()) / 2;
float ys = (y + boltEntity->getY()) / 2;
int maxDamages = hp;
int boltDamages = hurt(getHurtParams
(boltEntity->getDamages(),
boltEntity->getBoltType(),
boltEntity->getLevel(),
boltEntity->isCritical(),
SourceTypeBolt,
enemyType, boltEntity->getGoThrough()));
if (hp > 0)
{
boltEntity->loseDamages(boltEntity->getDamages());
}
else
{
boltEntity->loseDamages(maxDamages >= boltDamages ? boltDamages : maxDamages);
}
if (bloodColor > BloodNone) game().generateBlood(x, y, bloodColor);
SoundManager::getInstance().playSound(SOUND_IMPACT);
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);
if (boltEntity->getBoltType() == ShotTypeStone)
{
float factor = (boltEntity->isFromPlayer() && game().getPlayer()->isEquiped(EQUIP_RAPID_SHOT)) ? 0.25f : 1.0f;
float recoilVelocity = factor * STONE_DECOIL_VELOCITY[boltEntity->getLevel()];
float recoilDelay = factor * STONE_DECOIL_DELAY[boltEntity->getLevel()];
Vector2D recoilVector = Vector2D(0, 0).vectorTo(boltEntity->getVelocity(),
recoilVelocity );
- giveRecoil(true, recoilVector, recoilDelay);
+ giveRepulsion(true, recoilVector, recoilDelay);
}
boltEntity->collide();
}
int EnemyEntity::getCollisionDirection(BoltEntity* boltEntity)
{
int tol = 4;
float bx = boltEntity->getX();
float by = boltEntity->getY();
int alignX, alignY;
if (bx + tol < x) alignX = 4;
else if (bx - tol > x) alignX = 6;
else alignX = 5;
if (by + tol < y) alignY = 8;
else if (by - tol > y) alignY = 2;
else alignY = 5;
int collisionDir = 5;
if (alignX == 4)
{
if (alignY == 8) collisionDir = 7;
else if (alignY == 5) collisionDir = 4;
else if (alignY == 2) collisionDir = 1;
}
else if (alignX == 5)
{
if (alignY == 8) collisionDir = 8;
else if (alignY == 5) collisionDir = 5;
else if (alignY == 2) collisionDir = 2;
}
else if (alignX == 6)
{
if (alignY == 8) collisionDir = 9;
else if (alignY == 5) collisionDir = 6;
else if (alignY == 2) collisionDir = 3;
}
return collisionDir;
}
void EnemyEntity::collideWithEnemy(EnemyEntity* entity)
{
// To implement the behaviour when colliding with another ennemy
}
int EnemyEntity::hurt(StructHurt hurtParam)
{
int hurtedHp = BaseCreatureEntity::hurt(hurtParam);
if (hurtedHp > 0 && hurtingSound != SOUND_NONE && hp > 0)
SoundManager::getInstance().playSound(hurtingSound);
return hurtedHp;
}
void EnemyEntity::dying()
{
if (dyingFrame > -1)
{
isAgonising = true;
hVelocity = 200.0f;
if (agonizingSound != SOUND_NONE) SoundManager::getInstance().playSound(agonizingSound);
}
else // dyingFrame == -1
{
isDying = true;
game().addCorpse(x, y, deathFrame);
if (dyingSound != SOUND_NONE) SoundManager::getInstance().playSound(dyingSound);
}
if (bloodColor != BloodNone) for (int i = 0; i < 4; i++) game().generateBlood(x, y, bloodColor);
drop();
game().addKilledEnemy(enemyType, hurtingType);
}
void EnemyEntity::dropItem(enumItemType item)
{
ItemEntity* newItem = new ItemEntity(item, x, y);
newItem->setMap(map, TILE_WIDTH, TILE_HEIGHT, 0, 0);
newItem->setVelocity(Vector2D(50.0f + rand()% 140));
newItem->setViscosity(0.96f);
newItem->startsJumping();
}
void EnemyEntity::drop()
{
if (rand() % 40 == 0)
{
if (rand() % 2 == 0)
{
dropItem(ItemScrollRevelation);
}
else
{
dropItem((enumItemType)(ItemPotion01 + rand() % NUMBER_UNIDENTIFIED));
}
}
else
{
if (rand() % 5 == 0)
{
dropItem(ItemCopperCoin);
}
if (game().getPlayer()->isEquiped(EQUIP_LUCK) && rand() % 5 == 0)
{
dropItem(ItemCopperCoin);
}
if (rand() % 25 == 0)
{
dropItem(ItemHealthVerySmall);
}
}
}
bool EnemyEntity::canCollide()
{
return (!isAgonising);
}
void EnemyEntity::render(sf::RenderTarget* app)
{
if (isAgonising || (isDying && dyingFrame > -1))
{
if (shadowFrame > -1)
{
// shadow
int nx = shadowFrame;
int ny = 0;
if (imagesProLine > 0 && shadowFrame >= imagesProLine)
{
nx = shadowFrame % imagesProLine;
ny = shadowFrame / imagesProLine;
}
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(nx * width, ny * height, width, height));
app->draw(sprite);
}
int nx = dyingFrame;
int ny = 0;
if (imagesProLine > 0)
{
nx = dyingFrame % imagesProLine;
ny = dyingFrame / imagesProLine;
}
sprite.setPosition(x, y - h);
if (isMirroring)
sprite.setTextureRect(sf::IntRect(nx * width + width, ny * height, -width, height));
else
sprite.setTextureRect(sf::IntRect(nx * width, ny * height, width, height));
app->draw(sprite);
}
else
BaseCreatureEntity::render(app);
}
void EnemyEntity::renderLifeBar(sf::RenderTarget* app, std::string label)
{
game().addLifeBarToDisplay(label, hpDisplay, hpMax);
}
bool EnemyEntity::testEntityInMap()
{
int collideCounter = 6;
while (isCollidingWithMap() && collideCounter > 0)
{
int movCounter = 100;
if (collideWithMap(DIRECTION_LEFT) && !collideWithMap(DIRECTION_RIGHT))
{
x = (float)((int)x);
while (collideWithMap(DIRECTION_LEFT) && movCounter > 0)
{
x--;
movCounter--;
}
}
else if (collideWithMap(DIRECTION_RIGHT) && !collideWithMap(DIRECTION_LEFT))
{
x = (float)((int)x);
while (collideWithMap(DIRECTION_RIGHT) && movCounter > 0)
{
x++;
movCounter--;
}
}
else if (collideWithMap(DIRECTION_BOTTOM) && !collideWithMap(DIRECTION_TOP))
{
y = (float)((int)y);
while (collideWithMap(DIRECTION_BOTTOM) && movCounter > 0)
{
y--;
movCounter--;
}
}
else if (collideWithMap(DIRECTION_TOP) && !collideWithMap(DIRECTION_BOTTOM))
{
y = (float)((int)y);
while (collideWithMap(DIRECTION_TOP) && movCounter > 0)
{
y++;
movCounter--;
}
}
collideCounter--;
}
return (collideCounter > 0);
}
diff --git a/src/ExplosionEntity.cpp b/src/ExplosionEntity.cpp
index 9209cf2..7e29d3c 100644
--- a/src/ExplosionEntity.cpp
+++ b/src/ExplosionEntity.cpp
@@ -1,102 +1,102 @@
#include "ExplosionEntity.h"
#include "BaseCreatureEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "sfml_game/SpriteEntity.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include <iostream>
ExplosionEntity::ExplosionEntity(float x, float y, explosionTypeEnum explosionType, int damage, enemyTypeEnum enemyType, bool canHurtPlayer)
: SpriteEntity(ImageManager::getInstance().getImage(IMAGE_EXPLOSION), x, y, 100, 100)
{
type = ENTITY_EXPLOSION;
this->explosionType = explosionType;
imagesProLine = 6;
lifetime = 0.6f;
this->canHurtPlayer = canHurtPlayer;
this->damage = damage;
switch (explosionType)
{
case ExplosionTypeStandard: frame = 0; break;
case ExplosionTypeViolet: frame = 6; break;
}
sprite.setOrigin(50, 50);
testCollisions();
}
void ExplosionEntity::setCanHurtPlayer(bool can)
{
canHurtPlayer = can;
}
void ExplosionEntity::animate(float delay)
{
if (lifetime > 0)
{
if (age >= lifetime) isDying = true;
}
age += delay;
z = y + height / 2;
frame = age / lifetime * 6;
if (frame > 5) frame = 5;
switch (explosionType)
{
case ExplosionTypeStandard: break;
case ExplosionTypeViolet: frame += 6; break;
}
}
void ExplosionEntity::render(sf::RenderTarget* app)
{
SpriteEntity::render(app);
}
void ExplosionEntity::dying()
{
isDying = true;
}
void ExplosionEntity::testCollisions()
{
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
BaseCreatureEntity* entity = dynamic_cast<BaseCreatureEntity*>(e);
if (entity != NULL)
{
bool ok = true;
if (!canHurtPlayer && entity->getType() == ENTITY_PLAYER) ok = false;
if (ok && entity->getHp() > 0 && entity->canCollide())
{
entity->calculateBB();
sf::IntRect bb;
bb.left = x - 90;
bb.width = 180;
bb.top = y - 90;
bb.height = 180;
if (bb.intersects(entity->getBoundingBox()))
{
// TODO explosion type
if (damage > 0) entity->hurt(BaseCreatureEntity::getHurtParams(damage, ShotTypeFire, 0, false, SourceTypeExplosion, enemyType, false));
- Vector2D recoilVector = Vector2D(x, y).vectorTo(Vector2D(entity->getX(), entity->getY()), 800.0f );
- entity->giveRecoil(true, recoilVector, 1.0f);
+ Vector2D repulsionVector = Vector2D(x, y).vectorTo(Vector2D(entity->getX(), entity->getY()), 800.0f );
+ entity->giveRepulsion(true, repulsionVector, 1.0f);
}
}
}
}
}
diff --git a/src/FranckyEntity.cpp b/src/FranckyEntity.cpp
index a68989a..cb201e9 100644
--- a/src/FranckyEntity.cpp
+++ b/src/FranckyEntity.cpp
@@ -1,658 +1,658 @@
#include "FranckyEntity.h"
#include "BoltEntity.h"
#include "EnemyBoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "TextMapper.h"
#include <iostream>
FranckyEntity::FranckyEntity(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_FRANCKY), x, y)
{
width = 128;
height = 192;
creatureSpeed = 140;
velocity = Vector2D(creatureSpeed);
hp = 900;
hpDisplay = hp;
hpMax = hp;
meleeDamages = 16;
type = ENTITY_ENEMY_BOSS;
bloodColor = BloodRed;
deathFrame = FRAME_CORPSE_FRANCKY_TORSO;
shadowFrame = 5;
agonizingSound = SOUND_FRANCKY_DYING;
frame = 0;
if (game().getPlayerPosition().x > x) isMirroring = true;
sprite.setOrigin(64.0f, 143.0f);
state = 0;
timer = 3.0f;
followTimer = -1.0f;
counter = 10;
age = -1.5f;
enemyType = EnemyTypeFrancky;
resistance[ResistanceFrozen] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceImmune;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistanceLightning] = ResistanceVeryHigh;
canExplode = false;
}
void FranckyEntity::animate(float delay)
{
if (age <= 0.0f)
{
age += delay;
return;
}
// special states
if (specialState[SpecialStateIce].active) delay *= specialState[SpecialStateIce].param1;
// IA
timer -= delay;
if (timer < 0.0f)
{
state++;
if (state == 5)
{
state = 0;
followTimer = 0.25f;
}
int health;
switch (state)
{
case 0:
timer = 6.0f;
health = ((100 * hp) / hpMax);
if (health <= 33) timer = 4.5f;
else if (health <= 66) timer = 5.25f;
SoundManager::getInstance().playSound(SOUND_FRANCKY_00);
break;
case 1:
timer = 1.0f;
velocity.x = 0.0f;
velocity.y = 0.0f;
SoundManager::getInstance().playSound(SOUND_FRANCKY_01);
break;
case 3: timer = 0.2f; break;
case 2:
case 4: timer = 0.2f; fire(); break;
}
}
if (state == 0)
{
// walking
followTimer -= delay;
if (followTimer <= 0.0f)
{
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), creatureSpeed ));
followTimer = 0.25f;
}
}
else
{
SoundManager::getInstance().playSound(SOUND_ELECTRICITY, false);
}
// collisions
if (canCollide()) testSpriteCollisions();
BaseCreatureEntity::animate(delay);
// current frame
if (state == 0)
{
int r = ((int)(age * 5.0f)) % 4;
if (r == 2) frame = 0;
else if (r == 3) frame = 2;
else frame = r;
// frame's mirroring
if (velocity.x > 1.0f)
isMirroring = true;
else if (velocity.x < -1.0f)
isMirroring = false;
}
else
{
frame = 3 +((int)(age * 7.0f)) % 2;
isMirroring = game().getPlayer()->getX() > x;
}
z = y + 36;
}
void FranckyEntity::calculateBB()
{
boundingBox.left = (int)x - 32;
boundingBox.width = 58;
boundingBox.top = (int)y - 52;
boundingBox.height = 90;
}
void FranckyEntity::collideMapRight()
{
velocity.x = -velocity.x;
}
void FranckyEntity::collideMapLeft()
{
velocity.x = -velocity.x;
}
void FranckyEntity::collideMapTop()
{
velocity.y = -velocity.y;
}
void FranckyEntity::collideMapBottom()
{
velocity.y = -velocity.y;
}
void FranckyEntity::drop()
{
dropItem(ItemBossHeart);
}
void FranckyEntity::render(sf::RenderTarget* app)
{
EnemyEntity::render(app);
renderLifeBar(app, tools::getLabel("enemy_francky"));
}
void FranckyEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
- inflictsRecoilTo(entity);
+ inflictsRepulsionTo(entity);
}
-void FranckyEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
+void FranckyEntity::inflictsRepulsionTo(BaseCreatureEntity* targetEntity)
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(targetEntity);
if (playerEntity != NULL && !playerEntity->isDead())
{
- Vector2D recoilVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), 450.0f);
- targetEntity->giveRecoil(true, recoilVector, 0.5f);
+ Vector2D repulsionVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), 450.0f);
+ targetEntity->giveRepulsion(true, repulsionVector, 0.5f);
}
}
void FranckyEntity::dying()
{
// generates body parts
new FranckyEntityHand(x + 0.01f * (rand() % 100), y);
new FranckyEntityHand(x, y + 0.01f * (rand() % 100));
new FranckyEntityFoot(x + 0.01f * (rand() % 100), y);
new FranckyEntityFoot(x, y + 0.01f * (rand() % 100));
new FranckyEntityHead(x, y);
// FX
SpriteEntity* star = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_GIANT_SLIME), x, y, 128, 128, 8);
star->setFrame(4);
star->setColor(sf::Color(230, 255, 255));
star->setFading(true);
star->setZ(y+ 100);
star->setAge(-0.4f);
star->setLifetime(0.3f);
star->setType(ENTITY_EFFECT);
star->setSpin(400.0f);
SoundManager::getInstance().playSound(SOUND_SLIME_SMASH);
EnemyEntity::dying();
}
void FranckyEntity::fire()
{
SoundManager::getInstance().playSound(SOUND_ELECTRIC_BLAST);
int health = ((100 * hp) / hpMax);
float boltLifetime = 1.4f;
float boltSpeed = 370;
if (health <= 33)
{
boltLifetime = 1.8f;
boltSpeed = 430;
}
else if (health <= 66)
{
boltLifetime = 1.6f;
boltSpeed = 400;
}
for (float i = state == 2 ? 0.0f : PI / 8; i < 2 * PI; i += PI / 4)
{
EnemyBoltEntity* bolt = new EnemyBoltEntity(x, y, ShotTypeLightning, 0, enemyType);
bolt->setDamages(12);
float velx = boltSpeed * cos(i);
float vely = boltSpeed * sin(i);
bolt->setVelocity(Vector2D(velx, vely));
bolt->setLifetime(boltLifetime);
}
game().makeColorEffect(X_GAME_COLOR_BLUE, 0.3f);
}
///////////////////////////////////////////////////////////////////
//// HAND
///////////////////////////////////////////////////////////////////
FranckyEntityHand::FranckyEntityHand(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_FRANCKY), x, y)
{
creatureSpeed = 260;
velocity = Vector2D(creatureSpeed);
hp = 40;
meleeDamages = 8;
imagesProLine = 10;
bloodColor = BloodRed;
shadowFrame = 3 * imagesProLine + 5;
movingStyle = movWalking;
deathFrame = FRAME_CORPSE_FRANCKY_HAND;
sprite.setOrigin(32.0f, 46.0f);
enemyType = EnemyTypeFranckyHand;
frame = 3 * imagesProLine + 1;
age = 0.0f;
}
void FranckyEntityHand::animate(float delay)
{
if (!isAgonising)
{
if (age < 0.0f) frame = 3 * imagesProLine + 3;
else frame = 3 * imagesProLine + 3 + ((int)(age * 6.0f)) % 2;
isMirroring = velocity.x > 1.0f;
}
EnemyEntity::animate(delay);
}
void FranckyEntityHand::calculateBB()
{
boundingBox.left = (int)x - 20;
boundingBox.width = 40;
boundingBox.top = (int)y - 8;
boundingBox.height = 22;
}
void FranckyEntityHand::collideMapRight()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void FranckyEntityHand::collideMapLeft()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void FranckyEntityHand::collideMapTop()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void FranckyEntityHand::collideMapBottom()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void FranckyEntityHand::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getEnemyType() != EnemyTypeSpiderWeb && entity->getMovingStyle() == movWalking)
{
setVelocity(Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), creatureSpeed ));
}
}
void FranckyEntityHand::drop()
{
// Nothing
}
///////////////////////////////////////////////////////////////////
//// HEAD
///////////////////////////////////////////////////////////////////
FranckyEntityHead::FranckyEntityHead(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_FRANCKY), x, y)
{
creatureSpeed = 0.0f;
velocity = Vector2D(0.0f, 0.0f);
hp = 150;
hpMax = hp;
hpDisplay = hp;
meleeDamages = 5;
jumpingDelay = 0.0f;
enemyType = EnemyTypeFranckyHead;
bloodColor = BloodRed;
imagesProLine = 10;
frame = 3 * imagesProLine;
shadowFrame = 3 * imagesProLine + 2;
deathFrame = FRAME_CORPSE_FRANCKY_HEAD;
agonizingSound = SOUND_FRANCKY_DYING;
isJumping = false;
h = 0.0f;
viscosity = 0.98f;
sprite.setOrigin(32, 44);
resistance[ResistanceLightning] = ResistanceVeryHigh;
canExplode = false;
age = 0.0f;
}
void FranckyEntityHead::animate(float delay)
{
float slimeDelay = delay;
if (specialState[SpecialStateIce].active) slimeDelay = delay * specialState[SpecialStateIce].param1;
if (isJumping)
{
hVelocity -= 700.0f * slimeDelay;
h += hVelocity * slimeDelay;
bool firstTimeGround = false;
if (h <= 0.0f)
{
if (hp <= 0)
dying();
else
{
h = 0.0f;
if (isFirstJumping)
{
isFirstJumping = false;
firstTimeGround = true;
hVelocity = 120.0f;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT);
fire();
game().generateBlood(x, y, BloodRed);
}
else
{
jumpingDelay = 0.05f;
isJumping = false;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT_WEAK);
int r = rand() % 4;
if (r <= 1) SoundManager::getInstance().playSound(SOUND_FRANCKY_01 + r);
fire();
game().generateBlood(x, y, BloodRed);
}
}
}
if (firstTimeGround) frame = 2;
else if (hVelocity > -60.0f) frame = 1;
else frame = 0;
}
else
{
jumpingDelay -= slimeDelay;
if (jumpingDelay < 0.0f)
{
hVelocity = 180.0f;
isJumping = true;
isFirstJumping = true;
float randVel = 280.0f;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), randVel ));
}
}
frame = imagesProLine * 3 + (int)(age * 3) % 2;
isMirroring = velocity.x > 1.0f;
EnemyEntity::animate(delay);
z = y + 14;
}
void FranckyEntityHead::render(sf::RenderTarget* app)
{
if (!isDying && shadowFrame > -1)
{
// shadow
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect((shadowFrame % imagesProLine) * width, (shadowFrame / imagesProLine) * width, width, height));
app->draw(sprite);
}
sprite.setPosition(x, y - h);
if (isMirroring)
sprite.setTextureRect(sf::IntRect((frame % imagesProLine) * width + width, (frame / imagesProLine) * width, -width, height));
else
sprite.setTextureRect(sf::IntRect((frame % imagesProLine) * width, (frame / imagesProLine) * width, width, height));
app->draw(sprite);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
renderLifeBar(app, tools::getLabel("enemy_francky_head"));
}
void FranckyEntityHead::calculateBB()
{
boundingBox.left = (int)x - 16;
boundingBox.width = 32;
boundingBox.top = (int)y - 14;
boundingBox.height = 28;
}
void FranckyEntityHead::collideMapRight()
{
velocity.x = -velocity.x * 0.8f;
}
void FranckyEntityHead::collideMapLeft()
{
velocity.x = -velocity.x * 0.8f;
}
void FranckyEntityHead::collideMapTop()
{
velocity.y = -velocity.y * 0.8f;
}
void FranckyEntityHead::collideMapBottom()
{
velocity.y = -velocity.y * 0.8f;
}
void FranckyEntityHead::collideWithEnemy(EnemyEntity* entity)
{
- if (recoil.active && recoil.stun) return;
+ if (repulsion.active && repulsion.stun) return;
if (entity->getMovingStyle() == movWalking)
setVelocity(Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), velocity.norm() ));
}
void FranckyEntityHead::fire()
{
SoundManager::getInstance().playSound(SOUND_ELECTRIC_BLAST);
EnemyBoltEntity* bolt = new EnemyBoltEntity
(x, y + 10, ShotTypeLightning, 0, enemyType);
bolt->setDamages(8);
bolt->setLifetime(1.5f);
bolt->setMap(map, TILE_WIDTH, TILE_HEIGHT, 0, 0);
bolt->setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), 400 ));
}
///////////////////////////////////////////////////////////////////
//// FOOT
///////////////////////////////////////////////////////////////////
FranckyEntityFoot::FranckyEntityFoot(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_FRANCKY), x, y)
{
creatureSpeed = 0.0f;
velocity = Vector2D(0.0f, 0.0f);
hp = 40;
meleeDamages = 5;
jumpingDelay = 0.0f;
enemyType = EnemyTypeFranckyFoot;
bloodColor = BloodRed;
imagesProLine = 10;
frame = 3 * imagesProLine + 6;
shadowFrame = 3 * imagesProLine + 8;
deathFrame = FRAME_CORPSE_FRANCKY_FOOT;
isJumping = false;
h = 0.0f;
viscosity = 0.98f;
sprite.setOrigin(32, 44);
canExplode = false;
age = 0.0f;
}
void FranckyEntityFoot::animate(float delay)
{
float slimeDelay = delay;
if (specialState[SpecialStateIce].active) slimeDelay = delay * specialState[SpecialStateIce].param1;
if (isJumping)
{
hVelocity -= 700.0f * slimeDelay;
h += hVelocity * slimeDelay;
bool firstTimeGround = false;
if (h <= 0.0f)
{
if (hp <= 0)
dying();
else
{
h = 0.0f;
if (isFirstJumping)
{
isFirstJumping = false;
firstTimeGround = true;
hVelocity = 120.0f;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT);
game().generateBlood(x, y, BloodRed);
}
else
{
jumpingDelay = 0.05f;
isJumping = false;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT_WEAK);
game().generateBlood(x, y, BloodRed);
}
}
}
if (firstTimeGround) frame = 2;
else if (hVelocity > -60.0f) frame = 1;
else frame = 0;
}
else
{
jumpingDelay -= slimeDelay;
if (jumpingDelay < 0.0f)
{
hVelocity = 180.0f + rand() % 180;
isJumping = true;
isFirstJumping = true;
float randVel = 280.0f + rand() % 250;
setVelocity(Vector2D(randVel ));
}
}
frame = imagesProLine * 3 + 6 + (int)(age * 3) % 2;
isMirroring = velocity.x > 1.0f;
EnemyEntity::animate(delay);
z = y + 14;
}
void FranckyEntityFoot::render(sf::RenderTarget* app)
{
if (!isDying && shadowFrame > -1)
{
// shadow
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect((shadowFrame % imagesProLine) * width, (shadowFrame / imagesProLine) * width, width, height));
app->draw(sprite);
}
sprite.setPosition(x, y - h);
if (isMirroring)
sprite.setTextureRect(sf::IntRect((frame % imagesProLine) * width + width, (frame / imagesProLine) * width, -width, height));
else
sprite.setTextureRect(sf::IntRect((frame % imagesProLine) * width, (frame / imagesProLine) * width, width, height));
app->draw(sprite);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void FranckyEntityFoot::calculateBB()
{
boundingBox.left = (int)x - 16;
boundingBox.width = 32;
boundingBox.top = (int)y - 14;
boundingBox.height = 28;
}
void FranckyEntityFoot::collideMapRight()
{
velocity.x = -velocity.x * 0.8f;
}
void FranckyEntityFoot::collideMapLeft()
{
velocity.x = -velocity.x * 0.8f;
}
void FranckyEntityFoot::collideMapTop()
{
velocity.y = -velocity.y * 0.8f;
}
void FranckyEntityFoot::collideMapBottom()
{
velocity.y = -velocity.y * 0.8f;
}
void FranckyEntityFoot::collideWithEnemy(EnemyEntity* entity)
{
- if (recoil.active && recoil.stun) return;
+ if (repulsion.active && repulsion.stun) return;
if (entity->getMovingStyle() == movWalking)
setVelocity(Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), velocity.norm() ));
}
diff --git a/src/FranckyEntity.h b/src/FranckyEntity.h
index 393f9b9..57c8269 100644
--- a/src/FranckyEntity.h
+++ b/src/FranckyEntity.h
@@ -1,103 +1,103 @@
#ifndef FRANCKYENTITY_H
#define FRANCKYENTITY_H
#include "EnemyEntity.h"
#include "PlayerEntity.h"
class FranckyEntity : public EnemyEntity
{
public:
FranckyEntity(float x, float y);
virtual void animate(float delay);
virtual void render(sf::RenderTarget* app);
virtual void calculateBB();
- virtual void inflictsRecoilTo(BaseCreatureEntity* targetEntity);
+ virtual void inflictsRepulsionTo(BaseCreatureEntity* targetEntity) override;
protected:
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
virtual void collideWithEnemy(EnemyEntity* entity) override;
virtual void dying();
virtual void drop();
private:
float timer;
float followTimer;
int state;
int counter;
void fire();
};
///////////////////////////////////////////////////////////////////
class FranckyEntityHand : public EnemyEntity
{
public:
FranckyEntityHand(float x, float y);
virtual void animate(float delay);
virtual void calculateBB();
protected:
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
virtual void collideWithEnemy(EnemyEntity* entity) override;
virtual void drop();
};
///////////////////////////////////////////////////////////////////
class FranckyEntityHead : public EnemyEntity
{
public:
FranckyEntityHead(float x, float y);
virtual void animate(float delay);
virtual void render(sf::RenderTarget* app);
virtual void calculateBB();
protected:
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
virtual void collideWithEnemy(EnemyEntity* entity) override;
private:
float jumpingDelay;
bool isJumping;
bool isFirstJumping;
void fire();
};
///////////////////////////////////////////////////////////////////
class FranckyEntityFoot : public EnemyEntity
{
public:
FranckyEntityFoot(float x, float y);
virtual void animate(float delay);
virtual void render(sf::RenderTarget* app);
virtual void calculateBB();
protected:
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
virtual void collideWithEnemy(EnemyEntity* entity) override;
private:
float jumpingDelay;
bool isJumping;
bool isFirstJumping;
};
#endif // FRANCKYENTITY_H
diff --git a/src/GhostEntity.cpp b/src/GhostEntity.cpp
index 86a646d..32a54f4 100644
--- a/src/GhostEntity.cpp
+++ b/src/GhostEntity.cpp
@@ -1,160 +1,160 @@
#include "GhostEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
GhostEntity::GhostEntity(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_GHOST), x, y)
{
frame = 0;
dyingFrame = 4;
deathFrame = FRAME_CORPSE_GHOST;
enemyType = EnemyTypeGhost;
hp = GHOST_HP;
creatureSpeed = GHOST_SPEED;
meleeDamages = GHOST_DAMAGE;
movingStyle = movFlying;
velocity = Vector2D(creatureSpeed);
timer = 0.0f;
age -= 0.8f;
bloodColor = BloodNone;
agonizingSound = SOUND_GHOST_DYING;
resistance[ResistanceFrozen] = ResistanceHigh;
- resistance[ResistanceRecoil] = ResistanceHigh;
+ resistance[ResistanceRepulsion] = ResistanceHigh;
resistance[ResistancePoison] = ResistanceImmune;
}
void GhostEntity::animate(float delay)
{
if (age > 0.0f && !isAgonising)
{
timer = timer - delay;
if (timer <= 0.0f)
{
timer = 0.25f;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), creatureSpeed ));
}
frame = ((int)(age * 3.0f)) % 4;
if (frame == 3) frame = 1;
}
isMirroring = x > game().getPlayerPosition().x;
EnemyEntity::animate(delay);
z = y + 32;
}
void GhostEntity::calculateBB()
{
boundingBox.left = (int)x - 15;
boundingBox.width = 30;
boundingBox.top = (int)y - 15;
boundingBox.height = 30;
}
int GhostEntity::getGhostFade()
{
float dist1 = 24000.f;
float dist2 = 40000.f;
float dist = Vector2D(x, y).distance2(game().getPlayerPosition());
int fade;
if (dist < dist1) fade = 100;
else if (dist > dist2) fade = 0;
else
{
fade =((dist2 - dist) / (dist2 - dist1)) * 100;
if (fade < 0) fade = 0;
if (fade > 100) fade = 100;
}
if (age <= 0.0f)
{
int ageFade = 40;
if (age > -0.5f) ageFade = 0 - 80.0f * age;
return (fade > ageFade ? fade : ageFade);
}
return fade;
}
void GhostEntity::render(sf::RenderTarget* app)
{
int fade = getGhostFade();
if (fade == 100) SoundManager::getInstance().playSound(SOUND_GHOST);
if (fade == 100 || isAgonising)
{
sf::Color color = sprite.getColor();
color.a = 255;
sprite.setColor(color);
EnemyEntity::render(app);
}
else if (fade > 0)
{
sf::Color color = sprite.getColor();
color.a = fade * 255 / 100;
sprite.setColor(color);
EnemyEntity::render(app);
}
}
void GhostEntity::collideMapRight()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void GhostEntity::collideMapLeft()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void GhostEntity::collideMapTop()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void GhostEntity::collideMapBottom()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void GhostEntity::collideWithEnemy(EnemyEntity* entity)
{
- if (recoil.active && recoil.stun) return;
+ if (repulsion.active && repulsion.stun) return;
if (entity->getEnemyType() == EnemyTypeGhost)
{
Vector2D vel = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), 1.5f );
- giveRecoil(false, vel, 0.3f);
+ giveRepulsion(false, vel, 0.3f);
}
}
void GhostEntity::collideWithBolt(BoltEntity* boltEntity)
{
int fade = getGhostFade();
if (fade <= 0) return;
if (boltEntity->getBoltType() == ShotTypeIllusion) fade = 100;
boltEntity->setDamages(boltEntity->getDamages() * fade / 100);
EnemyEntity::collideWithBolt(boltEntity);
}
void GhostEntity::drop()
{
EnemyEntity::drop();
}
diff --git a/src/GiantSlimeEntity.cpp b/src/GiantSlimeEntity.cpp
index 3331b93..146988b 100644
--- a/src/GiantSlimeEntity.cpp
+++ b/src/GiantSlimeEntity.cpp
@@ -1,470 +1,470 @@
#include "GiantSlimeEntity.h"
#include "BoltEntity.h"
#include "EnemyBoltEntity.h"
#include "PlayerEntity.h"
#include "SlimeEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "TextMapper.h"
#include <iostream>
GiantSlimeEntity::GiantSlimeEntity(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_GIANT_SLIME), x, y)
{
width = 128;
height = 128;
creatureSpeed = GIANT_SLIME_SPEED;
velocity = Vector2D(creatureSpeed);
hp = GIANT_SLIME_HP;
hpDisplay = hp;
hpMax = GIANT_SLIME_HP;
meleeDamages = GIANT_SLIME_DAMAGES;
missileDelay = GIANT_SLIME_MISSILE_DELAY;
type = ENTITY_ENEMY_BOSS;
enemyType = EnemyTypeSlimeBoss;
bloodColor = BloodGreen;
shadowFrame = 3;
frame = 0;
sprite.setOrigin(64.0f, 64.0f);
h = 0.0f;
age = -2.0f;
changeToState(0);
slimeCounter = 0;
slimeTimer =5.0f;
resistance[ResistanceFrozen] = ResistanceVeryHigh;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceVeryHigh;
sprite.setOrigin(64, 84);
canExplode = false;
}
void GiantSlimeEntity::changeToState(int n)
{
if (n == 0) // walking
{
state = 0;
counter = 8 + rand() % 7;
timer = -1.0f;
viscosity = 1.0f;
}
else if (n == 1 || n == 3 || n == 5 || n == 8) // waiting
{
state = n;
timer = 1.2f;
setVelocity(Vector2D(0.0f, 0.0f));
}
else if (n == 2) // jumping
{
state = 2;
timer = 4.0f;
viscosity = 0.991f;
SoundManager::getInstance().playSound(SOUND_SLIME_JUMP);
hVelocity = 420.0f + rand() % 380;
isFirstJumping = true;
float randVel = 350.0f + rand() % 200;
if (rand() % 2 == 0)
{
float tan = (game().getPlayer()->getX() - x) / (game().getPlayer()->getY() - y);
float angle = atan(tan);
if (game().getPlayer()->getY() > y)
setVelocity(Vector2D(sin(angle) * randVel,
cos(angle) * randVel));
else
setVelocity(Vector2D(-sin(angle) * randVel,
-cos(angle) * randVel));
}
else
velocity = Vector2D(randVel);
}
else if (n == 4) // walking
{
state = 4;
if (hp <= hpMax / 4)
counter = 26;
if (hp <= hpMax / 2)
counter = 18;
else
counter = 12;
timer = GIANT_SLIME_MISSILE_DELAY;
}
else if (n == 6) // jumping
{
state = 6;
timer = 1.2f;
viscosity = 1.0f;
SoundManager::getInstance().playSound(SOUND_SLIME_JUMP);
hVelocity = GIANT_SLIME_ULTRA_JUMP_VELOCITY;
}
else if (n == 7) // falling
{
isFalling = false;
state = 7;
timer = GIANT_SLIME_ULTRA_JUMP_TIMER;
hVelocity = GIANT_SLIME_ULTRA_FALL_VELOCITY;
h = 1500;
}
}
void GiantSlimeEntity::animate(float delay)
{
slimeTimer -= delay;
if (slimeTimer <= 0.0f)
{
slimeTypeEnum slimeType = SlimeTypeStandard;
if (game().isAdvancedLevel())
{
slimeType = (slimeTypeEnum)(slimeType + rand() % 3);
}
switch (slimeCounter)
{
case 0:
new SlimeEntity(TILE_WIDTH * 1.5f, TILE_HEIGHT * 1.5f, slimeType, true);
break;
case 1:
new SlimeEntity(TILE_WIDTH * (MAP_WIDTH - 2) + TILE_WIDTH * 0.5f, TILE_HEIGHT * 1.5f, slimeType, true);
break;
case 2:
new SlimeEntity(TILE_WIDTH * (MAP_WIDTH - 2) + TILE_WIDTH * 0.5f, TILE_HEIGHT * (MAP_HEIGHT - 2) + TILE_HEIGHT * 0.5f, slimeType, true);
break;
case 3:
new SlimeEntity(TILE_WIDTH * 1.5f, TILE_HEIGHT * (MAP_HEIGHT - 2) + TILE_HEIGHT * 0.5f, slimeType, true);
break;
}
slimeTimer = 7.0f;
slimeCounter ++;
if (slimeCounter == 4) slimeCounter = 0;
}
if (age <= 0.0f)
{
age += delay;
return;
}
EnemyEntity::animate(delay);
if (specialState[SpecialStateIce].active) delay *= specialState[SpecialStateIce].param1;
timer -= delay;
if (timer <= 0.0f)
{
if (state == 0) // walking
{
counter--;
if (counter >= 0)
{
timer = 0.5f;
if (hp <= hpMax / 4)
creatureSpeed = GIANT_SLIME_SPEED * 1.4f;
if (hp <= hpMax / 2)
creatureSpeed = GIANT_SLIME_SPEED * 1.2f;
else
creatureSpeed = GIANT_SLIME_SPEED;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), GIANT_SLIME_SPEED ));
}
else
{
int r = rand() % 3;
if (r == 0) changeToState(1);
else if (r == 1) changeToState(3);
else changeToState(5);
}
}
else if (state == 1) // waiting for jumping
{
changeToState(2);
}
else if (state == 2) // jumping
{
changeToState(8);
}
else if (state == 3)
{
changeToState(4);
}
else if (state == 4) // walking
{
counter--;
if (counter >= 0)
{
if (hp <= hpMax / 4)
timer = missileDelay * 0.6f;
if (hp <= hpMax / 2)
timer = missileDelay * 0.8f;
else
timer = missileDelay;
fire();
}
else
{
changeToState(8);
}
}
else if (state == 5)
{
changeToState(6);
}
else if (state == 6) // jump
{
changeToState(7); // fall
}
else if (state == 7) // jump
{
}
else if (state == 8) // jump
{
changeToState(0); // fall
}
}
if (state == 0) // walking
{
frame = ((int)(age * 2.0f)) % 2;
}
else if (state == 1 || state == 5) // waiting to jump
{
if (timer < 0.25f)
frame = 1;
else
frame = 0;
}
else if (state == 2) // jumping
{
hVelocity -= 700.0f * delay;
h += hVelocity * delay;
if (h <= 0.0f)
{
if (hp <= 0)
dying();
else
{
h = 0.0f;
if (isFirstJumping)
{
isFirstJumping = false;
hVelocity = 160.0f;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT);
}
else
{
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT_WEAK);
viscosity = 0.96f;
changeToState(0);
}
}
}
if (hVelocity > 0.0f) frame = 2;
else frame = 0;
}
else if (state == 6) // ultra jump
{
if (h < 2000)
h += hVelocity * delay;
}
else if (state == 7) // ultra jump
{
if (!isFalling && timer <= 2.2f)
{
isFalling = true;
x = game().getPlayer()->getX();
y = game().getPlayer()->getY();
// to prevent collisions
float x0 = TILE_WIDTH + 1;
float xf = TILE_WIDTH * (MAP_WIDTH - 1) - 1;
float y0 = TILE_HEIGHT + 1;
float yf = TILE_HEIGHT * (MAP_HEIGHT - 1) - 1;
calculateBB();
if (boundingBox.left < x0) x += (x0 - boundingBox.left);
else if (boundingBox.left + boundingBox.width > xf) x -= (boundingBox.left + boundingBox.width - xf);
if (boundingBox.top < y0) y += (y0 - boundingBox.top);
else if (boundingBox.top + boundingBox.height > yf) y -= (boundingBox.top + boundingBox.height - yf);
}
if (timer < 2.3f)
{
h += hVelocity * delay;
if (h <= 0)
{
h = 0;
changeToState(8);
game().makeShake(0.8f);
SoundManager::getInstance().playSound(SOUND_CYCLOPS_IMPACT);
}
}
}
if (state == 6 && timer < 0.5f)
{
int fade = timer * 512;
if (fade < 0) fade = 0;
sprite.setColor(sf::Color(255, 255, 255, fade));
}
else if (state == 7 && timer < 1.5f)
sprite.setColor(sf::Color(255, 255, 255, 255));
else if (state == 7 && timer < 2.0f)
sprite.setColor(sf::Color(255, 255, 255, (2.0f - timer) * 512));
else if (state == 7)
sprite.setColor(sf::Color(255, 255, 255, 0));
isMirroring = (frame == 2) && (velocity.x < 0.0f);
z = y + 26;
}
void GiantSlimeEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2 + GIANT_SLIME_BB_LEFT;
boundingBox.width = width - GIANT_SLIME_BB_WIDTH_DIFF;
boundingBox.top = (int)y - height / 2 + 40;
boundingBox.height = height - 76;
}
void GiantSlimeEntity::collideMapRight()
{
velocity.x = -velocity.x;
}
void GiantSlimeEntity::collideMapLeft()
{
velocity.x = -velocity.x;
}
void GiantSlimeEntity::collideMapTop()
{
velocity.y = -velocity.y;
}
void GiantSlimeEntity::collideMapBottom()
{
velocity.y = -velocity.y;
}
void GiantSlimeEntity::dying()
{
isDying = true;
game().addKilledEnemy(enemyType, hurtingType);
game().addCorpse(x, y, FRAME_CORPSE_GIANT_SLIME);
float xSlime = x;
float ySlime = y;
if (x <= 1.5 * TILE_WIDTH) x = 1.5f * TILE_WIDTH + 2;
else if (x >= TILE_WIDTH * MAP_WIDTH - 1.5f * TILE_WIDTH) x = TILE_WIDTH * MAP_WIDTH - 1.5f * TILE_WIDTH -3;
if (y <= 1.5 * TILE_HEIGHT) y = 1.5 * TILE_HEIGHT + 2;
else if (y >= TILE_HEIGHT * MAP_HEIGHT - 1.5f * TILE_HEIGHT) y = TILE_HEIGHT * MAP_HEIGHT - 1.5f * TILE_HEIGHT -3;
for (int i = 0; i < 9; i++)
{
game().generateBlood(xSlime, ySlime, bloodColor);
SlimeEntity* slime = new SlimeEntity(x, y, SlimeTypeStandard, true);
slime->disableCollidingTemporary();
}
game().makeShake(1.0f);
SoundManager::getInstance().playSound(SOUND_SLIME_SMASH);
ItemEntity* newItem = new ItemEntity(ItemBossHeart, x, y);
newItem->setVelocity(Vector2D(100.0f + rand()% 250));
newItem->setViscosity(0.96f);
SpriteEntity* star = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_GIANT_SLIME), x, y, 128, 128, 8);
star->setFrame(4);
star->setFading(true);
star->setZ(y+ 100);
star->setAge(-0.4f);
star->setLifetime(0.3f);
star->setType(ENTITY_EFFECT);
star->setSpin(400.0f);
}
void GiantSlimeEntity::render(sf::RenderTarget* app)
{
if (!isDying)
{
// shadow
sprite.setPosition(x, y);
if (isMirroring)
sprite.setTextureRect(sf::IntRect(shadowFrame * width + width, 0, -width, height));
else
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
}
sprite.setPosition(x, y - h);
if (isMirroring)
sprite.setTextureRect(sf::IntRect(frame * width + width, 0, -width, height));
else
sprite.setTextureRect(sf::IntRect(frame * width, 0, width, height));
app->draw(sprite);
renderLifeBar(app, tools::getLabel("enemy_giant_slime"));
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void GiantSlimeEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
{
inflictsRecoilTo(entity);
}
}
void GiantSlimeEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
{
if (state == 7)
{
Vector2D recoilVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), KING_RAT_RUNNING_RECOIL );
- targetEntity->giveRecoil(true, recoilVector, 1.0f);
+ targetEntity->giveRepulsion(true, recoilVector, 1.0f);
}
}
bool GiantSlimeEntity::canCollide()
{
return h <= 70.0f;
}
BaseCreatureEntity::enumMovingStyle GiantSlimeEntity::getMovingStyle()
{
if (h <= 70.0f)
return movWalking;
else
return movFlying;
}
void GiantSlimeEntity::fire()
{
SoundManager::getInstance().playSound(SOUND_BLAST_FLOWER);
EnemyBoltEntity* bolt = new EnemyBoltEntity
(x, y + 10, ShotTypeStandard, 0, enemyType);
bolt->setFrame(1);
bolt->setMap(map, TILE_WIDTH, TILE_HEIGHT, 0, 0);
bolt->setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(),GIANT_SLIME_FIRE_VELOCITY ));
}
diff --git a/src/GiantSpiderEntity.cpp b/src/GiantSpiderEntity.cpp
index 42e45da..104800e 100644
--- a/src/GiantSpiderEntity.cpp
+++ b/src/GiantSpiderEntity.cpp
@@ -1,350 +1,350 @@
#include "GiantSpiderEntity.h"
#include "EnemyBoltEntity.h"
#include "PlayerEntity.h"
#include "SpiderEggEntity.h"
#include "SpiderWebEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "TextMapper.h"
#include <iostream>
GiantSpiderEntity::GiantSpiderEntity(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_GIANT_SPIDER), x, y)
{
width = 128;
height = 128;
creatureSpeed = GIANT_SPIDER_SPEED[0];
velocity = Vector2D(0.0f, 0.0f);
hp = GIANT_SPIDER_HP;
hpMax = hp;
hpDisplay = hp;
meleeDamages = GIANT_SPIDER_DAMAGE;
type = ENTITY_ENEMY;
enemyType = EnemyTypeSpiderGiant;
bloodColor = BloodGreen;
shadowFrame = 3;
dyingFrame = 4;
deathFrame = FRAME_CORPSE_GIANT_SPIDER;
agonizingSound = SOUND_SPIDER_DIE;
sprite.setOrigin(64.0f, 64.0f);
walkingSoundDelay = -1.0f;
h = 2000;
state = 0;
hurtLevel = 0;
labelHasChanged = false;
resistance[ResistanceFrozen] = ResistanceVeryHigh;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceImmune;
creatureName = "???";
canExplode = false;
}
void GiantSpiderEntity::animate(float delay)
{
if (age <= 0.0f)
{
age += delay;
return;
}
if (!isAgonising)
{
if (state == 0) // falling
{
h -= delay * 300.0f;
if (h <= 0.0f)
{
h = 0;
state = 1;
timer = 1.0f;
if (!labelHasChanged)
{
labelHasChanged = true;
creatureName = tools::getLabel("enemy_giant_spider");
game().testAndAddMessageToQueue(MsgInfoGiantSpiderAfter);
}
}
}
else if (state == 1) // wait after falling
{
timer -= delay;
if (timer <= 0.0f)
{
state = 2;
velocity = Vector2D(creatureSpeed);
timer = 10.0f;
fireDelay = 0.5f;
}
}
else if (state == 2) // moving
{
walkingSoundDelay -= delay;
if (walkingSoundDelay <= 0.0f)
{
walkingSoundDelay = 1.0f;
SoundManager::getInstance().playSound(SOUND_SPIDER_WALKING);
}
fireDelay -= delay;
if (fireDelay <= 0.0f)
{
if (rand() % 12 == 0)
{
SoundManager::getInstance().playSound(SOUND_SPIDER_WEB);
for (int i = 0; i < 3; i++) new SpiderWebEntity(x, y, false);
}
else
{
for (int i = 0; i < 4; i++) fire(i == 0 ? 1 : 0);
}
fireDelay = GIANT_SPIDER_FIRE_DELAY[hurtLevel];
}
timer -= delay;
if (getHealthLevel() > hurtLevel)
{
hurtLevel++;
state = 3;
velocity = Vector2D(0.0f, 0.0f);
timer = 1.0f;
creatureSpeed = GIANT_SPIDER_SPEED[hurtLevel];
SoundManager::getInstance().playSound(SOUND_SPIDER_HURT);
}
}
else if (state == 3) // wait after falling
{
timer -= delay;
if (timer <= 0.0f) state = 4;
}
else if (state == 4) // moving up
{
h += delay * 300.0f;
if (h >= 1500.0f)
{
state = 5;
timer = 6.0f;
for (int i = 0; i < GIANT_SPIDER_NUMBER_EGGS[hurtLevel]; i++)
{
new SpiderEggEntity(TILE_WIDTH * 1.5f + rand() % (TILE_WIDTH * 12),
TILE_HEIGHT * 1.5f + rand() % (TILE_HEIGHT * 6), true);
}
}
}
else if (state == 5) // waiting to fall
{
timer -= delay;
if (timer <= 0.0f)
state = 0;
}
// frame
frame = 0;
if (state == 2)
{
frame = ((int)(age * 6.0f)) % 4;
if (frame == 2) frame = 0;
else if (frame == 3) frame = 2;
}
}
EnemyEntity::animate(delay);
z = y + 40;
}
int GiantSpiderEntity::hurt(StructHurt hurtParam)
{
if (hurtLevel < getHealthLevel()) hurtParam.damage /= 5;
return EnemyEntity::hurt(hurtParam);
}
void GiantSpiderEntity::calculateBB()
{
boundingBox.left = (int)x - 45;
boundingBox.width = 90;
boundingBox.top = (int)y - 25;
boundingBox.height = 65;
}
void GiantSpiderEntity::collideMapRight()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void GiantSpiderEntity::collideMapLeft()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
}
void GiantSpiderEntity::collideMapTop()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void GiantSpiderEntity::collideMapBottom()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
}
void GiantSpiderEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
{
Vector2D v = Vector2D(x, y).vectorTo(Vector2D(entity->getX(), entity->getY()), 150.0f);
- entity->giveRecoil(false, v, 0.5f);
+ entity->giveRepulsion(false, v, 0.5f);
}
}
void GiantSpiderEntity::calculateRotation()
{
float h0 = 100;
float hf = 18;
if (state == 0)
{
if (h > h0) sprite.setRotation(180);
else if (h < hf) sprite.setRotation(0);
else
{
sprite.setRotation(180 + (h0 - h) * 180 / (h0 - hf));
}
}
if (state == 4)
{
if (h > h0) sprite.setRotation(180);
else if (h < hf) sprite.setRotation(0);
else
{
sprite.setRotation(180 - (h0 - h) * 180 / (h0 - hf));
}
}
else if (state == 2) sprite.setRotation(0);
}
void GiantSpiderEntity::render(sf::RenderTarget* app)
{
if (!isDying)
{
// shadow
sprite.setRotation(0.0f);
if (state == 0 || state == 4 || state == 5)
{
int h0 = 850;
int hf = 600;
int fade = 0;
if (h < h0)
{
if (h < hf) fade = 255;
else
{
fade = (h0 - h) * 255 / (h0 - hf);
if (fade < 0) fade = 0;
else if (fade > 255) fade = 255;
}
sprite.setColor(sf::Color(255, 255, 255, fade));
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
sprite.setColor(sf::Color(255, 255, 255, 255));
}
}
else
{
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
}
}
calculateRotation();
if (state == 0 || state == 1 || state == 3 || state == 4)
{
if (y - h > 0)
{
int fade = 255;
if (state == 1) fade = 255 * timer;
else if (state == 3) fade = 255 * (1.0f - timer);
sf::RectangleShape line(sf::Vector2f(2, y - h));
line.setPosition(x - 1, 0);
line.setFillColor(sf::Color(255, 255, 255, fade));
app->draw(line);
}
}
sprite.setPosition(x, y - h);
sprite.setTextureRect(sf::IntRect(frame * width, 0, width, height));
app->draw(sprite);
renderLifeBar(app, creatureName);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
bool GiantSpiderEntity::canCollide()
{
return h <= 70.0f;
}
void GiantSpiderEntity::fire(int fireType)
{
SoundManager::getInstance().playSound(SOUND_BLAST_POISON);
EnemyBoltEntity* bolt;
bolt = new EnemyBoltEntity(x, y, ShotTypePoison, 0, enemyType);
bolt->setDamages(5);
float fireVelocity = 180.0f;
if (specialState[SpecialStateIce].active) fireVelocity *= 0.5f;
bolt->setVelocity(Vector2D(fireVelocity));
}
int GiantSpiderEntity::getHealthLevel()
{
int healthLevel = 0;
if (hp <= hpMax * 0.25) healthLevel = 3;
else if (hp <= hpMax * 0.5) healthLevel = 2;
else if (hp <= hpMax * 0.75) healthLevel = 1;
return healthLevel;
}
void GiantSpiderEntity::drop()
{
dropItem(ItemBossHeart);
EntityManager::EntityList* entityList = EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
EnemyEntity* entity = dynamic_cast<EnemyEntity*>(e);
if (entity != NULL)
{
if (entity->getEnemyType()== EnemyTypeSpiderWeb)
{
entity->hurt(getHurtParams(entity->getHp(), ShotTypeStandard, 0, false, SourceTypeMelee, enemyType, false));
}
}
}
}
diff --git a/src/GreenRatEntity.cpp b/src/GreenRatEntity.cpp
index c94c93b..e41f69f 100644
--- a/src/GreenRatEntity.cpp
+++ b/src/GreenRatEntity.cpp
@@ -1,141 +1,141 @@
#include "GreenRatEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
GreenRatEntity::GreenRatEntity(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_RAT), x, y)
{
imagesProLine = 10;
creatureSpeed = GREEN_RAT_SPEED;
velocity = Vector2D(creatureSpeed);
computeFacingDirection();
hp = GREEN_RAT_HP;
meleeDamages = GREEN_RAT_DAMAGES;
type = ENTITY_ENEMY_INVOCATED;
enemyType = EnemyTypeRatGreen;
bloodColor = BloodRed;
shadowFrame = -1;
dyingFrame = 19;
deathFrame = FRAME_CORPSE_GREEN_RAT;
agonizingSound = SOUND_RAT_DYING;
timer = (rand() % 50) / 10.0f;
age = -GREEN_RAT_FADE;
frame = 11;
sprite.setOrigin(32.0f, 38.0f);
canExplode = false; // TO SEE
}
void GreenRatEntity::animate(float delay)
{
z = y + boundingBox.top + boundingBox.height;
if (age > 0.0f && !isAgonising)
{
sprite.setColor(sf::Color(255,255,255,255));
timer = timer - delay;
if (timer <= 0.0f)
{
timer = (rand() % 50) / 10.0f;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), GREEN_RAT_SPEED ));
computeFacingDirection();
}
frame = 8 + ((int)(age * 5.0f)) % 2;
if (facingDirection == 4 || facingDirection == 6) frame += 2;
isMirroring = (facingDirection == 4 );
if (facingDirection == 8) frame += 4;
frame = ((int)(age * 5.0f)) % 4;
if (frame == 3) frame = 1;
if (facingDirection == 4 || facingDirection == 6) frame += 3;
isMirroring = (facingDirection == 6 );
if (facingDirection == 8) frame += 6;
frame += 10;
}
else if (!isAgonising)
{
sprite.setColor(sf::Color(255,255,255,255 * (1.0 + age)));
}
else if (isAgonising)
{
if (hVelocity < -1.0f)
{
int fade = h * 200 / 25;
if (fade > 200) fade = 200;
else if (fade < 0) fade = 0;
sprite.setColor(sf::Color(255, 255, 255, fade));
}
}
EnemyEntity::animate(delay);
z = y + 17;
}
void GreenRatEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2 + RAT_BB_LEFT;
boundingBox.width = width - RAT_BB_WIDTH_DIFF;
boundingBox.top = (int)y - 13;
boundingBox.height = 31;
}
void GreenRatEntity::collideMapRight()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
computeFacingDirection();
}
void GreenRatEntity::collideMapLeft()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
computeFacingDirection();
}
void GreenRatEntity::collideMapTop()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
computeFacingDirection();
}
void GreenRatEntity::collideMapBottom()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
computeFacingDirection();
}
bool GreenRatEntity::canCollide()
{
return (age >= 0.0f);
}
void GreenRatEntity::collideWithEnemy(EnemyEntity* entity)
{
- if (recoil.active && recoil.stun) return;
+ if (repulsion.active && repulsion.stun) return;
if (entity->getMovingStyle() == movWalking )
{
Vector2D vel = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), 100.0f );
- giveRecoil(false, vel, 0.3f);
+ giveRepulsion(false, vel, 0.3f);
computeFacingDirection();
}
}
void GreenRatEntity::drop()
{
// no drop
}
diff --git a/src/KingRatEntity.cpp b/src/KingRatEntity.cpp
index 4021691..5b66c7c 100644
--- a/src/KingRatEntity.cpp
+++ b/src/KingRatEntity.cpp
@@ -1,373 +1,373 @@
#include "KingRatEntity.h"
#include "GreenRatEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "TextMapper.h"
#include <iostream>
KingRatEntity::KingRatEntity(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_KING_RAT), x, y)
{
width = 128;
height = 128;
creatureSpeed = KING_RAT_SPEED;
velocity = Vector2D(creatureSpeed);
hp = KING_RAT_HP;
hpDisplay = hp;
hpMax = KING_RAT_HP;
meleeDamages = KING_RAT_DAMAGES;
imagesProLine = 5;
type = ENTITY_ENEMY_BOSS;
enemyType = EnemyTypeRatKing;
bloodColor = BloodRed;
shadowFrame = 4;
dyingFrame = 5;
deathFrame = FRAME_CORPSE_KING_RAT;
dyingSound = SOUND_KING_RAT_DIE;
frame = 0;
if (game().getPlayerPosition().x > x) sprite.setScale(-1.0f, 1.0f);
sprite.setOrigin(64.0f, 70.0f);
state = 0;
timer = 2.0f + (rand() % 40) / 10.0f;
age = -2.0f;
berserkDelay = 1.0f + rand()%5 * 0.1f;
hasBeenBerserk = false;
resistance[ResistanceFrozen] = ResistanceVeryHigh;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceVeryHigh;
canExplode = false;
}
void KingRatEntity::animate(float delay)
{
if (age <= 0.0f)
{
age += delay;
return;
}
if (isAgonising)
{
if (h < -0.01f)
{
isDying = true;
game().addCorpse(x, y, deathFrame);
if (dyingSound != SOUND_NONE) SoundManager::getInstance().playSound(dyingSound);
}
else
{
frame = dyingFrame;
hVelocity -= 700.0f * delay;
h += hVelocity * delay;
}
return;
}
EnemyEntity::animate(delay);
if (specialState[SpecialStateIce].active) delay *= specialState[SpecialStateIce].param1;
float timerMult = 1.0f;
if (hp <= hpMax / 4)
{
creatureSpeed = KING_RAT_SPEED * 1.4f;
timerMult = 0.7f;
}
else if (hp <= hpMax / 2)
{
creatureSpeed = KING_RAT_SPEED * 1.2f;
timerMult = 0.85f;
}
else
{
creatureSpeed = KING_RAT_SPEED;
}
if (state == 5)
{
velocity.x *= 0.965f;
velocity.y *= 0.965f;
}
else
{
if (velocity.x > 0.1f) sprite.setScale(-1.0f, 1.0f);
else if (velocity.x < -0.1f) sprite.setScale(1.0f, 1.0f);
}
timer -= delay;
if (timer <= 0.0f)
{
if (state == 0)
{
state = 1;
// generate rats
generateGreenRats();
SoundManager::getInstance().playSound(SOUND_KING_RAT_1);
timer = 2.0f;
velocity.x = 0.0f;
velocity.y = 0.0f;
}
else if (state == 1) // generate rats
{
// to normal or berserk
if (hp < hpMax / 4 && !hasBeenBerserk)
{
hasBeenBerserk = true;
timer = 12.0f;
state = 6;
velocity = Vector2D(KING_RAT_BERSERK_SPEED);
SoundManager::getInstance().playSound(SOUND_KING_RAT_2);
}
else
{
timer = 7.0f * timerMult;
velocity = Vector2D(creatureSpeed);
state = 2;
}
}
else if (state == 2) // normal -> rush
{
state = 3;
// angry
timer = 1.0f;
velocity.x = 0.0f;
velocity.y = 0.0f;
SoundManager::getInstance().playSound(SOUND_KING_RAT_2);
}
else if (state == 3) // normal -> rush
{
state = 4;
// rush
timer = 12.0f;
float tan = (game().getPlayer()->getX() - x) / (game().getPlayer()->getY() - y);
float angle = atan(tan);
if (game().getPlayer()->getY() > y)
setVelocity(Vector2D(sin(angle) * KING_RAT_RUNNING_SPEED,
cos(angle) * KING_RAT_RUNNING_SPEED));
else
setVelocity(Vector2D(-sin(angle) * KING_RAT_RUNNING_SPEED,
-cos(angle) * KING_RAT_RUNNING_SPEED));
}
else if (state == 5) // wall impact
{
// to normal or berserk
if (hp < hpMax / 4 && !hasBeenBerserk)
{
hasBeenBerserk = true;
timer = 12.0f;
state = 6;
velocity = Vector2D(KING_RAT_BERSERK_SPEED);
SoundManager::getInstance().playSound(SOUND_KING_RAT_2);
}
else
{
timer = 7.0f * timerMult;
velocity = Vector2D(creatureSpeed);
state = 0;
}
}
else if (state == 6)
{
timer = 7.0f * timerMult;
velocity = Vector2D(creatureSpeed);
state = 0;
}
}
if (state == 6)
{
berserkDelay -= delay;
if (berserkDelay <= 0.0f)
{
berserkDelay = 0.6f + (rand()%10) / 20.0f;
SoundManager::getInstance().playSound(SOUND_KING_RAT_2);
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(),KING_RAT_BERSERK_SPEED ));
}
}
frame = 0;
if (state == 1)
frame = 3;
else if (state == 3 || state == 6)
{
frame = 3; //0;
int r = ((int)(age * 10.0f)) % 2;
if (r == 0)
sprite.setScale(-1.0f, 1.0f);
else
sprite.setScale(1.0f, 1.0f);
}
else if (state == 4)
{
int r = ((int)(age * 7.5f)) % 4;
if (r == 1) frame = 1;
else if (r == 3) frame = 2;
}
else if (state == 5)
{
frame = 0;
}
else
{
int r = ((int)(age * 5.0f)) % 4;
if (r == 1) frame = 1;
else if (r == 3) frame = 2;
}
z = y + 48;
}
int KingRatEntity::hurt(StructHurt hurtParam)
{
// berserk state protects
if (state == 6)
hurtParam.damage /= 4;
return EnemyEntity::hurt(hurtParam);
}
void KingRatEntity::calculateBB()
{
boundingBox.left = (int)x - 35;
boundingBox.width = 70;
boundingBox.top = (int)y - 15;
boundingBox.height = 63;
}
void KingRatEntity::afterWallCollide()
{
if (state == 4)
{
state = 5;
timer = 1.4f;
velocity.x *= 0.75f;
velocity.y *= 0.75f;
SoundManager::getInstance().playSound(SOUND_BIG_WALL_IMPACT);
game().makeShake(0.75f);
}
}
void KingRatEntity::collideMapRight()
{
velocity.x = -velocity.x;
afterWallCollide();
}
void KingRatEntity::collideMapLeft()
{
velocity.x = -velocity.x;
afterWallCollide();
}
void KingRatEntity::collideMapTop()
{
velocity.y = -velocity.y;
afterWallCollide();
}
void KingRatEntity::collideMapBottom()
{
velocity.y = -velocity.y;
afterWallCollide();
}
void KingRatEntity::drop()
{
dropItem(ItemBossHeart);
}
void KingRatEntity::generateGreenRats()
{
for (int i = 0; i < 5; i++)
{
float xr = x + -100 + rand() % 200;
float yr = y + -100 + rand() % 200;
if (xr > TILE_WIDTH * 1.5f && xr < TILE_WIDTH * (MAP_WIDTH - 2)
&& yr > TILE_HEIGHT * 1.5f && yr < TILE_HEIGHT * (MAP_HEIGHT - 2))
{
new GreenRatEntity(xr, yr);
}
else
i--;
}
}
void KingRatEntity::render(sf::RenderTarget* app)
{
EnemyEntity::render(app);
if (state == 6)
{
int r = ((int)(age *12.0f)) % 2;
if (r == 0)
sprite.setTextureRect(sf::IntRect(1 * width, 1 * height, width, height));
else
sprite.setTextureRect(sf::IntRect(2 * width, 1 * height, -width, height));
sprite.setPosition(x, y);
sprite.setColor(sf::Color(255, 255, 255, 190));
app->draw(sprite);
sprite.setColor(sf::Color(255, 255, 255, 255));
}
renderLifeBar(app, tools::getLabel("enemy_rat_king"));
}
void KingRatEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
{
- inflictsRecoilTo(entity);
+ inflictsrepulsionTo(entity);
}
}
-void KingRatEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
+void KingRatEntity::inflictsrepulsionTo(BaseCreatureEntity* targetEntity)
{
if (state == 4 || state == 6)
{
- Vector2D recoilVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), KING_RAT_RUNNING_RECOIL );
- targetEntity->giveRecoil(true, recoilVector, 1.0f);
+ Vector2D repulsionVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), KING_RAT_RUNNING_RECOIL );
+ targetEntity->giveRepulsion(true, repulsionVector, 1.0f);
}
if (state == 6)
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(targetEntity);
if (playerEntity != NULL && !playerEntity->isDead())
{
- Vector2D recoilVector = Vector2D(targetEntity->getX(), targetEntity->getY()).vectorTo(Vector2D(x, y), KING_RAT_RUNNING_RECOIL);
- giveRecoil(true, recoilVector, 1.0f);
+ Vector2D repulsionVector = Vector2D(targetEntity->getX(), targetEntity->getY()).vectorTo(Vector2D(x, y), KING_RAT_RUNNING_RECOIL);
+ giveRepulsion(true, repulsionVector, 1.0f);
}
}
}
diff --git a/src/KingRatEntity.h b/src/KingRatEntity.h
index 8c3d29c..ed7f2dd 100644
--- a/src/KingRatEntity.h
+++ b/src/KingRatEntity.h
@@ -1,34 +1,34 @@
#ifndef KINGRATSPRITE_H
#define KINGRATSPRITE_H
#include "EnemyEntity.h"
#include "PlayerEntity.h"
class KingRatEntity : public EnemyEntity
{
public:
KingRatEntity(float x, float y);
virtual void animate(float delay);
virtual void render(sf::RenderTarget* app);
virtual void calculateBB();
- virtual void inflictsRecoilTo(BaseCreatureEntity* targetEntity);
+ virtual void inflictsrepulsionTo(BaseCreatureEntity* targetEntity);
protected:
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
void afterWallCollide();
virtual int hurt(StructHurt hurtParam) override;
void generateGreenRats();
virtual void collideWithEnemy(EnemyEntity* entity) override;
virtual void drop();
private:
float timer;
float berserkDelay;
int state;
bool hasBeenBerserk;
};
#endif // KINGRATSPRITE_H
diff --git a/src/LargeSlimeEntity.cpp b/src/LargeSlimeEntity.cpp
index dcaa588..b41c017 100644
--- a/src/LargeSlimeEntity.cpp
+++ b/src/LargeSlimeEntity.cpp
@@ -1,415 +1,415 @@
#include "LargeSlimeEntity.h"
#include "BoltEntity.h"
#include "EnemyBoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "TextMapper.h"
#include <iostream>
LargeSlimeEntity::LargeSlimeEntity(float x, float y, slimeTypeEnum slimeType)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_GIANT_SLIME), x, y)
{
width = 128;
height = 128;
creatureSpeed = GIANT_SLIME_SPEED;
velocity = Vector2D(creatureSpeed);
hp = GIANT_SLIME_HP / 2;
hpDisplay = hp;
hpMax = hp;
meleeDamages = GIANT_SLIME_DAMAGES;
missileDelay = GIANT_SLIME_MISSILE_DELAY;
type = ENTITY_ENEMY;
bloodColor = BloodGreen;
shadowFrame = 3;
imagesProLine = 5;
h = 0.0f;
age = -1.0f;
this->slimeType = slimeType;
changeToState(0);
switch (slimeType)
{
case SlimeTypeBlue:
resistance[ResistanceFrozen] = ResistanceVeryHigh;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceHigh;
resistance[ResistanceIce] = ResistanceVeryHigh;
resistance[ResistanceFire] = ResistanceVeryLow;
enemyType = EnemyTypeSlimeBlueLarge;
meleeType = ShotTypeIce;
fireSound = SOUND_BLAST_ICE;
fireType = ShotTypeIce;
fireDamage = 8;
baseFrame = 10;
break;
case SlimeTypeRed:
resistance[ResistanceFrozen] = ResistanceHigh;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceHigh;
resistance[ResistanceIce] = ResistanceVeryLow;
resistance[ResistanceFire] = ResistanceVeryHigh;
enemyType = EnemyTypeSlimeRedLarge;
fireSound = SOUND_BLAST_FIRE;
fireType = ShotTypeFire;
fireDamage = 12;
baseFrame = 5;
break;
case SlimeTypeViolet:
resistance[ResistanceFrozen] = ResistanceHigh;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceHigh;
enemyType = EnemyTypeSlimeLarge;
fireSound = SOUND_BLAST_FLOWER;
fireType = ShotTypeStandard;
fireDamage = 8;
baseFrame = 15;
break;
case SlimeTypeStandard:
resistance[ResistanceFrozen] = ResistanceHigh;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceHigh;
enemyType = EnemyTypeSlimeLarge;
fireSound = SOUND_BLAST_FLOWER;
fireType = ShotTypeStandard;
fireDamage = 8;
baseFrame = 0;
break;
}
frame = baseFrame;
sprite.setOrigin(64, 84);
canExplode = false;
}
void LargeSlimeEntity::changeToState(int n)
{
if (n == 0) // walking
{
state = 0;
counter = 5 + rand() % 7;
timer = -1.0f;
viscosity = 1.0f;
}
else if (n == 1 || n == 3 || n == 5 || n == 8) // waiting
{
state = n;
timer = 1.2f;
setVelocity(Vector2D(0.0f, 0.0f));
}
else if (n == 2) // jumping
{
state = 2;
timer = 4.0f;
viscosity = 0.991f;
SoundManager::getInstance().playSound(SOUND_SLIME_JUMP);
hVelocity = 420.0f + rand() % 380;
isFirstJumping = true;
float randVel = 350.0f + rand() % 200;
if (rand() % 2 == 0)
{
float tan = (game().getPlayer()->getX() - x) / (game().getPlayer()->getY() - y);
float angle = atan(tan);
if (game().getPlayer()->getY() > y)
setVelocity(Vector2D(sin(angle) * randVel,
cos(angle) * randVel));
else
setVelocity(Vector2D(-sin(angle) * randVel,
-cos(angle) * randVel));
}
else
velocity = Vector2D(randVel);
}
else if (n == 4) // walking
{
state = 4;
if (hp <= hpMax / 4)
counter = 10;
if (hp <= hpMax / 2)
counter = 8;
else
counter = 6;
timer = GIANT_SLIME_MISSILE_DELAY;
}
}
void LargeSlimeEntity::animate(float delay)
{
if (age <= 0.0f)
{
age += delay;
return;
}
EnemyEntity::animate(delay);
if (specialState[SpecialStateIce].active) delay *= specialState[SpecialStateIce].param1;
timer -= delay;
frame = 0;
if (timer <= 0.0f)
{
if (state == 0) // walking
{
counter--;
if (counter >= 0)
{
timer = 0.5f;
if (hp <= hpMax / 4)
creatureSpeed = GIANT_SLIME_SPEED * 1.4f;
if (hp <= hpMax / 2)
creatureSpeed = GIANT_SLIME_SPEED * 1.2f;
else
creatureSpeed = GIANT_SLIME_SPEED;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), GIANT_SLIME_SPEED ));
}
else
{
int r = rand() % 2;
if (r == 0) changeToState(1);
else changeToState(3);
}
}
else if (state == 1) // waiting for jumping
{
changeToState(2);
}
else if (state == 2) // jumping
{
changeToState(8);
}
else if (state == 3)
{
changeToState(4);
}
else if (state == 4) // walking
{
counter--;
if (counter >= 0)
{
if (hp <= hpMax / 4)
timer = missileDelay * 0.6f;
if (hp <= hpMax / 2)
timer = missileDelay * 0.8f;
else
timer = missileDelay;
fire();
}
else
{
changeToState(8);
}
}
else if (state == 8) // jump
{
changeToState(0); // fall
}
}
if (state == 0) // walking
{
frame = ((int)(age * 2.0f)) % 2;
}
else if (state == 1 || state == 5) // waiting to jump
{
if (timer < 0.25f)
frame = 1;
else
frame = 0;
}
else if (state == 2) // jumping
{
hVelocity -= 700.0f * delay;
h += hVelocity * delay;
if (h <= 0.0f)
{
if (hp <= 0)
dying();
else
{
h = 0.0f;
if (isFirstJumping)
{
isFirstJumping = false;
hVelocity = 160.0f;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT);
}
else
{
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT_WEAK);
viscosity = 0.96f;
changeToState(0);
}
}
}
if (hVelocity > 0.0f) frame = 2;
else frame = 0;
}
isMirroring = (frame == 2) && (velocity.x < 0.0f);
frame += baseFrame;
z = y + 26;
}
void LargeSlimeEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2 + GIANT_SLIME_BB_LEFT;
boundingBox.width = width - GIANT_SLIME_BB_WIDTH_DIFF;
boundingBox.top = (int)y - height / 2 + 40;
boundingBox.height = height - 76;
}
void LargeSlimeEntity::collideMapRight()
{
velocity.x = -velocity.x;
}
void LargeSlimeEntity::collideMapLeft()
{
velocity.x = -velocity.x;
}
void LargeSlimeEntity::collideMapTop()
{
velocity.y = -velocity.y;
}
void LargeSlimeEntity::collideMapBottom()
{
velocity.y = -velocity.y;
}
void LargeSlimeEntity::dying()
{
isDying = true;
game().addKilledEnemy(enemyType, hurtingType);
if (slimeType == SlimeTypeBlue) game().addCorpse(x, y, FRAME_CORPSE_GIANT_SLIME_BLUE);
else if (slimeType == SlimeTypeRed) game().addCorpse(x, y, FRAME_CORPSE_GIANT_SLIME_RED);
else if (slimeType == SlimeTypeStandard) game().addCorpse(x, y, FRAME_CORPSE_GIANT_SLIME);
float xSlime = x;
float ySlime = y;
if (x <= 1.5 * TILE_WIDTH) x = 1.5f * TILE_WIDTH + 2;
else if (x >= TILE_WIDTH * MAP_WIDTH - 1.5f * TILE_WIDTH) x = TILE_WIDTH * MAP_WIDTH - 1.5f * TILE_WIDTH -3;
if (y <= 1.5 * TILE_HEIGHT) y = 1.5 * TILE_HEIGHT + 2;
else if (y >= TILE_HEIGHT * MAP_HEIGHT - 1.5f * TILE_HEIGHT) y = TILE_HEIGHT * MAP_HEIGHT - 1.5f * TILE_HEIGHT -3;
for (int i = 0; i < 9; i++)
{
game().generateBlood(xSlime, ySlime, bloodColor);
if (i % 2 == 0)
{
SlimeEntity* slime;
switch (slimeType)
{
case SlimeTypeBlue: slime = new SlimeEntity(x, y, SlimeTypeBlue, true); break;
case SlimeTypeRed: slime = new SlimeEntity(x, y, SlimeTypeRed, true); break;
case SlimeTypeViolet: slime = new SlimeEntity(x, y, SlimeTypeViolet, true); break;
default: slime = new SlimeEntity(x, y, SlimeTypeStandard, true); break;
}
slime->disableCollidingTemporary();
}
}
game().makeShake(1.0f);
SoundManager::getInstance().playSound(SOUND_SLIME_SMASH);
ItemEntity* newItem = new ItemEntity(ItemSilverCoin, x, y);
newItem->setVelocity(Vector2D(100.0f + rand()% 250));
newItem->setViscosity(0.96f);
SpriteEntity* star = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_GIANT_SLIME), x, y, 128, 128, 8);
star->setFrame(4);
star->setFading(true);
star->setZ(y+ 100);
star->setAge(-0.4f);
star->setLifetime(0.3f);
star->setType(ENTITY_EFFECT);
star->setSpin(400.0f);
}
void LargeSlimeEntity::render(sf::RenderTarget* app)
{
if (!isDying)
{
// shadow
sprite.setPosition(x, y);
if (isMirroring)
sprite.setTextureRect(sf::IntRect(shadowFrame * width + width, 0, -width, height));
else
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
}
sprite.setPosition(x, y - h);
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (frame % 5) * width + width, (frame / 5) * height, -width, height));
else
sprite.setTextureRect(sf::IntRect((frame % 5) * width, (frame / 5) * height, width, height));
app->draw(sprite);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void LargeSlimeEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
{
- inflictsRecoilTo(entity);
+ inflictsRepulsionTo(entity);
}
}
-void LargeSlimeEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
+void LargeSlimeEntity::inflictsRepulsionTo(BaseCreatureEntity* targetEntity)
{
if (state == 7)
{
Vector2D recoilVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), KING_RAT_RUNNING_RECOIL );
- targetEntity->giveRecoil(true, recoilVector, 1.0f);
+ targetEntity->giveRepulsion(true, recoilVector, 1.0f);
}
}
bool LargeSlimeEntity::canCollide()
{
return h <= 70.0f;
}
BaseCreatureEntity::enumMovingStyle LargeSlimeEntity::getMovingStyle()
{
if (h <= 70.0f)
return movWalking;
else
return movFlying;
}
void LargeSlimeEntity::fire()
{
SoundManager::getInstance().playSound(fireSound);
EnemyBoltEntity* bolt = new EnemyBoltEntity(x, y + 10, fireType, 0, enemyType);
bolt->setDamages(fireDamage);
bolt->setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(),GIANT_SLIME_FIRE_VELOCITY ));
}
diff --git a/src/LargeSlimeEntity.h b/src/LargeSlimeEntity.h
index fe96875..5cbb930 100644
--- a/src/LargeSlimeEntity.h
+++ b/src/LargeSlimeEntity.h
@@ -1,47 +1,47 @@
#ifndef LARGESLIMESPRITE_H
#define LARGESLIMESPRITE_H
#include "EnemyEntity.h"
#include "PlayerEntity.h"
#include "SlimeEntity.h"
class LargeSlimeEntity : public EnemyEntity
{
public:
LargeSlimeEntity(float x, float y, slimeTypeEnum slimeType);
virtual void animate(float delay);
virtual void render(sf::RenderTarget* app);
virtual void calculateBB();
- virtual void inflictsRecoilTo(BaseCreatureEntity* targetEntity);
+ virtual void inflictsRepulsionTo(BaseCreatureEntity* targetEntity) override;
virtual bool canCollide();
protected:
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
void afterWallCollide();
void changeToState(int n);
virtual void collideWithEnemy(EnemyEntity* entity) override;
virtual void dying();
virtual enumMovingStyle getMovingStyle();
private:
float timer;
int state, counter;
bool isFirstJumping;
bool isFalling;
float missileDelay;
slimeTypeEnum slimeType;
int fireSound;
int fireDamage;
enumShotType fireType;
int baseFrame;
void fire();
};
#endif // GIANTSLIMESPRITE_H
diff --git a/src/LittleSpiderEntity.cpp b/src/LittleSpiderEntity.cpp
index 53781ca..83e5fbb 100644
--- a/src/LittleSpiderEntity.cpp
+++ b/src/LittleSpiderEntity.cpp
@@ -1,142 +1,142 @@
#include "LittleSpiderEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "SpiderWebEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
LittleSpiderEntity::LittleSpiderEntity(float x, float y, EnumSpiderType spideType, bool invocated)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_LITTLE_SPIDER), x, y)
{
imagesProLine = 8;
creatureSpeed = 175.0f;
velocity = Vector2D(creatureSpeed * 0.25f);
meleeDamages = 5;
this->spideType = spideType;
if (spideType == SpiderTypeTarantula)
{
enemyType = invocated ? EnemyTypeSpiderTarantula_invocated : EnemyTypeSpiderTarantula;
frame = 8;
deathFrame = FRAME_CORPSE_LITTLE_SPIDER_TARANTULA;
dyingFrame = 11;
hp = 32;
webTimer = 3 + 0.1f * (float)(rand() % 50);
meleeType = ShotTypePoison;
meleeLevel = 1;
}
else
{
enemyType = invocated ? EnemyTypeSpiderLittle_invocated : EnemyTypeSpiderLittle;
frame = 0;
deathFrame = FRAME_CORPSE_LITTLE_SPIDER;
dyingFrame = 3;
hp = 16;
}
type = invocated ? ENTITY_ENEMY_INVOCATED : ENTITY_ENEMY;
bloodColor = BloodGreen;
shadowFrame = 4;
agonizingSound = SOUND_SPIDER_LITTLE_DIE;
timer = -1.0f; //(rand() % 50) / 10.0f;
if (invocated) age = 0.0f;
sprite.setOrigin(32.0f, 40.0f);
resistance[ResistancePoison] = ResistanceImmune;
roaming = true;
}
void LittleSpiderEntity::animate(float delay)
{
if (age > 0.0f && !isAgonising)
{
timer = timer - delay;
if (timer <= 0.0f)
{
timer = (rand() % 50) / 10.0f;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), creatureSpeed ));
roaming = false;
}
frame = ((int)(age * (roaming ? 1.5f : 5.0f))) % 3;
if (spideType == SpiderTypeTarantula)
frame += 8;
if (spideType == SpiderTypeTarantula)
{
webTimer = webTimer - delay;
if (webTimer <= 0.0f)
{
webTimer = 3 + 0.1f * (float)(rand() % 50);
new SpiderWebEntity(x, y, false);
}
}
}
EnemyEntity::animate(delay);
z = y + 21;
}
void LittleSpiderEntity::calculateBB()
{
boundingBox.left = (int)x - 18;
boundingBox.width = 36;
boundingBox.top = (int)y - 10;
boundingBox.height = 32;
}
void LittleSpiderEntity::collideMapRight()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
computeFacingDirection();
}
void LittleSpiderEntity::collideMapLeft()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
computeFacingDirection();
}
void LittleSpiderEntity::collideMapTop()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
computeFacingDirection();
}
void LittleSpiderEntity::collideMapBottom()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
computeFacingDirection();
}
void LittleSpiderEntity::collideWithEnemy(EnemyEntity* entity)
{
- if (recoil.active && recoil.stun) return;
+ if (repulsion.active && repulsion.stun) return;
if (entity->getMovingStyle() == movWalking )
{
Vector2D vel = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), 100.0f );
- giveRecoil(false, vel, 0.3f);
+ giveRepulsion(false, vel, 0.3f);
computeFacingDirection();
}
}
void LittleSpiderEntity::drop()
{
if (type == ENTITY_ENEMY)
EnemyEntity::drop();
}
diff --git a/src/ObstacleEntity.cpp b/src/ObstacleEntity.cpp
index ee0d846..6cc4941 100644
--- a/src/ObstacleEntity.cpp
+++ b/src/ObstacleEntity.cpp
@@ -1,205 +1,205 @@
#include "BoltEntity.h"
#include "EnemyBoltEntity.h"
#include "ExplosionEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "ObstacleEntity.h"
ObstacleEntity::ObstacleEntity(float x, float y, int objectFrame)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_DESTROYABLE), x, y)
{
imagesProLine = 3;
type = ENTITY_ENEMY_NC;
enemyType = EnemyTypeDestroyable;
movingStyle = movWalking;
explosive = false;
dyingSound = SOUND_BARREL_SMASH;
hurtingSound = SOUND_BARREL_HIT;
bloodColor = BloodNone;
obstacleBloodType = BloodBarrel;
deathFrame = FRAME_CORPSE_SLIME_VIOLET;
age = 0.0f;
frame = 0;
objectIndex = objectFrame;
xGrid = x / TILE_WIDTH;
yGrid = y / TILE_HEIGHT;
game().getCurrentMap()->setObjectTile(xGrid, yGrid, objectFrame);
game().getCurrentMap()->setLogicalTile(xGrid, yGrid, LogicalDestroyable);
// hp
if (objectIndex == MAPOBJ_BARREL || objectIndex == MAPOBJ_BARREL_NO_DROP
|| objectIndex == MAPOBJ_BARREL_EXPL || objectIndex == MAPOBJ_SKULL)
{
hp = 18;
hpMax = 18;
}
else if (objectIndex == MAPOBJ_BARREL + 1 || objectIndex == MAPOBJ_BARREL_NO_DROP + 1
|| objectIndex == MAPOBJ_BARREL_EXPL + 1 || objectIndex == MAPOBJ_SKULL + 1)
{
hp = 12;
hpMax = 12;
}
else if (objectIndex == MAPOBJ_BARREL + 2 || objectIndex == MAPOBJ_BARREL_NO_DROP + 2
|| objectIndex == MAPOBJ_BARREL_EXPL + 2 || objectIndex == MAPOBJ_SKULL + 2)
{
hp = 6;
hpMax = 6;
}
if (objectIndex >= MAPOBJ_BARREL_EXPL && objectIndex < MAPOBJ_BARREL_EXPL + 3)
{
obstacleBloodType = BloodBarrelPowder;
explosive = true;
initialFrame = 3;
initialObjectIndex = MAPOBJ_BARREL_EXPL;
frame = 3 + objectIndex - MAPOBJ_BARREL_EXPL;
}
else if (objectIndex >= MAPOBJ_BARREL && objectIndex < MAPOBJ_BARREL + 3)
{
initialFrame = 0;
initialObjectIndex = MAPOBJ_BARREL;
frame = objectIndex - MAPOBJ_BARREL;
}
else if (objectIndex >= MAPOBJ_BARREL_NO_DROP && objectIndex < MAPOBJ_BARREL_NO_DROP + 3)
{
initialFrame = 0;
initialObjectIndex = MAPOBJ_BARREL_NO_DROP;
frame = objectIndex - MAPOBJ_BARREL_NO_DROP;
}
else if (objectIndex >= MAPOBJ_SKULL && objectIndex < MAPOBJ_SKULL + 3)
{
obstacleBloodType = BloodSkull;
initialFrame = 6;
initialObjectIndex = MAPOBJ_SKULL;
frame = 6 + objectIndex - MAPOBJ_SKULL;
}
resistance[ResistanceFrozen] = ResistanceImmune;
- resistance[ResistanceRecoil] = ResistanceImmune;
+ resistance[ResistanceRepulsion] = ResistanceImmune;
resistance[ResistanceFire] = ResistanceVeryLow;
resistance[ResistancePoison] = ResistanceImmune;
canExplode = false;
}
int ObstacleEntity::getObjectIndex()
{
return objectIndex;
}
void ObstacleEntity::animate(float delay)
{
age += delay;
testSpriteCollisions();
}
void ObstacleEntity::render(sf::RenderTarget* app)
{
EnemyEntity::render(app);
}
void ObstacleEntity::dying()
{
EnemyEntity::dying();
game().getCurrentMap()->setObjectTile(xGrid, yGrid, 0);
game().getCurrentMap()->setLogicalTile(xGrid, yGrid, LogicalFloor);
for (int i = 0; i < 10; i++)
game().generateBlood(x, y, obstacleBloodType);
if (explosive && age > 2.0f)
{
new ExplosionEntity(x, y, ExplosionTypeStandard, 16, EnemyTypeNone, true);
SoundManager::getInstance().playSound(SOUND_BOOM_00);
game().addCorpse(x, y, deathFrame);
}
}
void ObstacleEntity::calculateBB()
{
boundingBox.left = (int)x - 30;
boundingBox.width = 60;
boundingBox.top = (int)y - 30;
boundingBox.height = 60;
}
void ObstacleEntity::drop()
{
if (initialObjectIndex == MAPOBJ_BARREL || initialObjectIndex == MAPOBJ_SKULL)
EnemyEntity::drop();
}
void ObstacleEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (entity == this) return;
if (!isDying && !isAgonising && collideWithEntity(entity))
{
if (entity->getType() == ENTITY_BOLT )
{
BoltEntity* boltEntity = dynamic_cast<BoltEntity*>(entity);
if (!boltEntity->getDying() && boltEntity->getAge() > 0.05f)
{
EnemyEntity::collideWithBolt(boltEntity);
correctFrame();
}
}
else if (entity->getType() == ENTITY_ENEMY_BOLT )
{
EnemyBoltEntity* boltEntity = dynamic_cast<EnemyBoltEntity*>(entity);
if (!boltEntity->getDying() && boltEntity->getAge() > 0.05f)
{
EnemyEntity::collideWithBolt(boltEntity);
correctFrame();
}
}
else if (entity->getType() >= ENTITY_ENEMY && entity->getType() <= ENTITY_ENEMY_MAX)
{
EnemyEntity* enemyEntity = dynamic_cast<EnemyEntity*>(entity);
if (!enemyEntity->getDying() && enemyEntity->canCollide()&& enemyEntity->getMovingStyle() != movFlying)
{
hurt(getHurtParams(hp, ShotTypeStandard, 0, false, SourceTypeMelee, enemyEntity->getEnemyType(), false));
}
}
}
}
void ObstacleEntity::correctFrame()
{
if (hp > 0)
{
if ( (hp - 1) / 6 == 1)
{
frame = initialFrame + 1;
objectIndex = initialObjectIndex + 1;
}
else if ( (hp - 1) / 6 == 0)
{
frame = initialFrame + 2;
objectIndex = initialObjectIndex + 2;
}
game().getCurrentMap()->setObjectTile(xGrid, yGrid, objectIndex);
}
}
int ObstacleEntity::hurt(StructHurt hurtParam)
{
int oldHp = hp;
int result = EnemyEntity::hurt(hurtParam);
int diff = oldHp - hp;
for (int i = 0; i < diff; i++)
game().generateBlood(x, y, obstacleBloodType);
return result;
}
diff --git a/src/PlayerEntity.cpp b/src/PlayerEntity.cpp
index 1e726ff..06f641a 100644
--- a/src/PlayerEntity.cpp
+++ b/src/PlayerEntity.cpp
@@ -1,3786 +1,3785 @@
#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;
rageFireDelay = 1.0f;
invincibleDelay = -1.0f;
divineInterventionDelay = -1.0f;
showCone = false;
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;
donation = 0;
endAge = 0.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 = 5;
// init the shots (to none)
for (int i = 0; i < SPECIAL_SHOT_SLOTS; i++)
{
specialShots[i] = ShotTypeStandard;
specialShotLevel[i] = 0;
}
// init the consumibles
for (int i = 0; i < MAX_SLOT_CONSUMABLES; i++)
consumable[i] = -1;
// init the lost HP
for (int i = 0; i < LAST_LEVEL; i++)
lostHp[i] = 0;
specialShotIndex = 0;
needInitShotType = false;
computePlayer();
firingDirection = 5;
facingDirection = 2;
keyDirection = 5;
canAnimateFire = true;
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;
shouldBeSavedFromDivinity = false;
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);
// Keep fairies on screen
if (fairies[i]->getX() < 0)
fairies[i]->setX(0);
else if (fairies[i]->getX() > MAP_WIDTH * TILE_WIDTH)
fairies[i]->setX(MAP_WIDTH * TILE_WIDTH);
if (fairies[i]->getY() < 0)
fairies[i]->setY(0);
else if (fairies[i]->getY() > MAP_HEIGHT * TILE_HEIGHT)
fairies[i]->setY(MAP_HEIGHT * TILE_HEIGHT);
}
}
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::getFadingDivinity(bool showCone)
{
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;
}
if (!this->showCone && showCone) return -1.0f;
if (divineInterventionDelay <= 0.0f) return -1.0f;
if (!this->showCone)
{
if (int(age * 12) % 2 == 0) return 1.0f;
else return 0.3f;
}
else 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
{
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;
}
}
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);
}
}
int PlayerEntity::getLostHp(int level)
{
if (level >= 1 && level <= LAST_LEVEL)
return (lostHp[level - 1]);
else
return 0;
}
void PlayerEntity::setLostHp(int level, int n)
{
if (level >= 1 && level <= LAST_LEVEL)
lostHp[level - 1] = n;
}
int PlayerEntity::getDamage()
{
return fireDamages;
}
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::getEndAge()
{
return endAge;
}
void PlayerEntity::setEndAge(float endAge)
{
this->endAge = endAge;
}
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;
if (game().getLevel() <= LAST_LEVEL)
{
if (getLostHp(game().getLevel()) == 0)
{
game().registerAchievement(AchievementNoDamage);
int counter = 0;
for (int i = 1; i <= game().getLevel(); i++) if (getLostHp(i) == 0) counter++;
if (counter >= 2) game().registerAchievement(AchievementNoDamage2);
if (counter >= 3) game().registerAchievement(AchievementNoDamage3);
}
}
}
float PlayerEntity::getFireRate()
{
return 1.0f / fireDelay;
}
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)
{
setEquipped(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();
}
// alchemy book
else if (acquiredItem == ItemBookAlchemy)
{
game().acquireAlchemyBook();
}
// 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;
+ repulsion.active = true;
+ repulsion.stun = true;
+ repulsion.velocity = Vector2D(350.0f);
+ repulsion.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 || playerStatus == playerStatusVictorious)
{
endAge += 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;
+ repulsion.active = true;
+ repulsion.stun = true;
+ repulsion.velocity = Vector2D(GAME_WIDTH / 2, GAME_HEIGHT /2).vectorTo(Vector2D(x, y), 650.0f);
+ repulsion.timer = 0.4f;
game().activateKeyRoomEffect(true);
}
}
//collidingDirection = 0;
BaseCreatureEntity::animate(delay);
if (firingDirection != 5)
facingDirection = firingDirection;
// find the frame
if (firingDirection != 5 && canAnimateFire)
{
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().getLevel() < LAST_LEVEL
&& game().getCurrentMap()->getRoomType() == roomTypeExit && y < TILE_HEIGHT * 0.6f)
{
playerStatus = playerStatusStairs;
velocity.y = creatureSpeed / 12;
velocity.x = -creatureSpeed / 3;
facingDirection = 4;
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(8);
exitDoorAroundEntity->setFrame(5 + 7 * 8);
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)
{
// effects
if (invincibleDelay >= 0.0f) invincibleDelay -= delay;
if (specialState[SpecialStateConfused].active)
SoundManager::getInstance().playSound(SOUND_VAMPIRE_HYPNOSIS, false);
// rage
if (specialState[SpecialStateRage].active)
{
specialState[SpecialStateRage].param3 -= delay;
if (specialState[SpecialStateRage].param3 <= 0.0f)
{
specialState[SpecialStateRage].param3 += specialState[SpecialStateRage].param2;
if (!equip[EQUIP_RAGE_AMULET]) rageFire(specialState[SpecialStateRage].param1, true, 1.5f);
}
}
if (equip[EQUIP_RAGE_AMULET])
{
rageFireDelay -= delay;
if (rageFireDelay <= 0.0f)
{
rageFireDelay += specialState[SpecialStateRage].active ? 1.5f : 8.0f;
rageFire(specialState[SpecialStateRage].param1, true, 1.5f);
}
}
}
z = y + 4;
}
bool PlayerEntity::canCollide()
{
return invincibleDelay <= 0.0f;
}
void PlayerEntity::setSpecialState(enumSpecialState state, bool active, float timer, float param1, float param2, bool waitUnclear)
{
BaseCreatureEntity::setSpecialState(state, active, timer, param1, param2, waitUnclear);
computePlayer();
}
void PlayerEntity::renderPlayer(sf::RenderTarget* app)
{
if (invincibleDelay > 0.0f)
{
if ((int)(age * 10.0f) % 2 == 0)return;
}
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);
}
else if (equip[EQUIP_AMULET_RETALIATION])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_2));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (3 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (3 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
if (equip[EQUIP_BELT_ADVANCED] && playerStatus != playerStatusDead)
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (27 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (27 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_LEATHER_BELT])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (15 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (15 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
// staff
int frameDx = equip[EQUIP_MAHOGANY_STAFF] ? 6 : 3;
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (frameDx + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (frameDx + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
if (equip[EQUIP_BLOOD_SNAKE])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (27 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (27 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
if (equip[EQUIP_REAR_SHOT_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_2));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_REAR_SHOT])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
// shot type
if (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)(endAge / 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, 6 * 72, 48, 72)); break;
case 4: fairySprite.setTextureRect(sf::IntRect( (4 + frame) * 48, 6 * 72, 48, 72)); break;
case 6: fairySprite.setTextureRect(sf::IntRect( (5 + frame) * 48, 6 * 72, - 48, 72)); break;
default: fairySprite.setTextureRect(sf::IntRect( frame * 48, 6 * 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)
{
collidingDirection = 5;
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 (touchLeft)
{
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));
if (firingDirection != 5)
facingDirection = firingDirection;
else
{
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::setEquipped(int item, bool toggleEquipped, bool isFairyPlayer)
{
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,
isFairyPlayer);
fairies.push_back(fairy);
int nbFamiliarFairies = 0;
for (auto fairy : fairies) if (!fairy->isPlayerControlled()) nbFamiliarFairies++;
if (nbFamiliarFairies == 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(float damage, bool full, float velMult)
{
float tempFireVelocity = fireVelocity * velMult;
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 = tempFireVelocity * i * 0.42f;
float vely = tempFireVelocity * j * 0.42f;
bolt->setVelocity(Vector2D(velx, vely));
if (full)
{
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 = -tempFireVelocity * i * 0.6f;
else if (i == -1 && j == 1) velx = tempFireVelocity * i * 0.6f;
else if (i == 1 && j == -1) vely= -tempFireVelocity * i * 0.6f;
else if (i == 1 && j == 1) vely = tempFireVelocity * i * 0.6f;
bolt->setVelocity(Vector2D(velx, vely));
}
}
SoundManager::getInstance().playSound(SOUND_BLAST_FIRE);
}
void PlayerEntity::resetFireDirection()
{
firingDirection = 5;
}
int PlayerEntity::getFireDirection()
{
return firingDirection;
}
void PlayerEntity::fire(int direction)
{
if (age < 0.7f) return;
firingDirection = direction;
if (playerStatus != playerStatusDead)
for(int unsigned i = 0; i < fairies.size(); i++)
fairies[i]->fire(direction);
if (canFirePlayer && playerStatus != playerStatusDead && playerStatus != playerStatusAcquire)
{
canAnimateFire = true;
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_ADVANCED])
{
float shootAngle = 0.165f;
float boltVelocity = fireVelocity * 0.75f;
BoltEntity* bolt1 = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypeStandard, 0);
bolt1->setDamages(fireDamages / 2);
bolt1->setFlying(isFairyTransmuted);
BoltEntity* bolt2 = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypeStandard, 0);
bolt2->setDamages(fireDamages / 2);
bolt2->setFlying(isFairyTransmuted);
switch (direction)
{
case 4:
bolt1->setVelocity(Vector2D(boltVelocity * cos(shootAngle), boltVelocity * sin(shootAngle)));
bolt2->setVelocity(Vector2D(boltVelocity * cos(shootAngle), -boltVelocity * sin(shootAngle)));
break;
case 6:
bolt1->setVelocity(Vector2D(-boltVelocity * cos(shootAngle), boltVelocity * sin(shootAngle)));
bolt2->setVelocity(Vector2D(-boltVelocity * cos(shootAngle), -boltVelocity * sin(shootAngle)));
break;
case 2:
bolt1->setVelocity(Vector2D(boltVelocity * sin(shootAngle), -boltVelocity * cos(shootAngle)));
bolt2->setVelocity(Vector2D(-boltVelocity * sin(shootAngle), -boltVelocity * cos(shootAngle)));
break;
case 8:
bolt1->setVelocity(Vector2D(boltVelocity * sin(shootAngle), boltVelocity * cos(shootAngle)));
bolt2->setVelocity(Vector2D(-boltVelocity * sin(shootAngle), boltVelocity * cos(shootAngle)));
break;
}
}
else 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_SIDE_SHOTS])
{
BoltEntity* bolt1 = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypeStandard, 0);
bolt1->setDamages(fireDamages / 2);
bolt1->setFlying(isFairyTransmuted);
BoltEntity* bolt2 = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypeStandard, 0);
bolt2->setDamages(fireDamages / 2);
bolt2->setFlying(isFairyTransmuted);
if (direction == 4 || direction == 6)
{
bolt1->setVelocity(Vector2D(0.0f, fireVelocity * 0.75f));
bolt2->setVelocity(Vector2D(0.0f, -fireVelocity * 0.75f));
}
else
{
bolt1->setVelocity(Vector2D(fireVelocity * 0.75f, 0.0f));
bolt2->setVelocity(Vector2D(-fireVelocity * 0.75f, 0.0f));
}
}
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();
}
else
{
canAnimateFire = false;
}
}
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;
}
shouldBeSavedFromDivinity = false;
bool divinityInvoked = false;
int thresholdDam = 5;
if (hp - hurtParam.damage <= thresholdDam && divinity.divinity >= 0 && game().getEnemyCount() > 2)
{
divinityInvoked = triggerDivinityBefore();
if (divinityInvoked)
{
game().testAndAddMessageToQueue((EnumMessages)(MsgInfoDivIntervention));
shouldBeSavedFromDivinity = true;
}
}
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_AMULET_RETALIATION] && !equip[EQUIP_RAGE_AMULET]) rageFire(10, hp <= hpMax / 5, 1.0f);
game().generateBlood(x, y, bloodColor);
}
hurtingDelay = HURTING_DELAY * 2.0f;
game().generateBlood(x, y, bloodColor);
game().proceedEvent(EventBeingHurted);
if (oldHp > hp && game().getLevel() <= LAST_LEVEL)
lostHp[game().getLevel() - 1] += (oldHp - hp);
lastHurtingEnemy = hurtParam.enemyType;
lastHurtingSource = hurtParam.sourceType;
// divinity
offerHealth(oldHp - hp);
if (!divinityInvoked && hp <= hpMax / 4 && divinity.divinity >= 0)
{
triggerDivinityAfter();
}
game().addHurtingStat(oldHp - hp);
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 (shouldBeSavedFromDivinity)
{
hp = 33 * hpMax / 100;
return;
}
else if (divinity.divinity > -1 && divinity.interventions < divinity.level - 1)
{
hp = 1;
return;
}
playerStatus = playerStatusDead;
endAge = 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());
if (game().getLevel() == 1) game().registerAchievement(AchievementNoob);
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 if (items[type].consumable)
{
acquireConsumable(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;
}
}
bool isUnidentified(enumItemType item)
{
return (item >= ItemPotion01 && item < ItemPotion01 + NUMBER_UNIDENTIFIED);
}
int PlayerEntity::getConsumable(int n)
{
if (n < 0 || n >= MAX_SLOT_CONSUMABLES) return -1;
else return consumable[n];
}
void PlayerEntity::setConsumable(int n, int type)
{
if (n < 0 || n >= MAX_SLOT_CONSUMABLES) return;
consumable[n] = type;
}
void PlayerEntity::dropConsumables(int n)
{
if (n < 0 || n >= MAX_SLOT_CONSUMABLES) return;
if (playerStatus != playerStatusPlaying) return;
if (consumable[n] < 0) return;
ItemEntity* newItem = new ItemEntity((enumItemType)(consumable[n]), x, y);
newItem->setVelocity(Vector2D(100.0f + rand()% 250));
newItem->setViscosity(0.96f);
newItem->setAge(-5.0f);
newItem->startsJumping();
consumable[n] = -1;
}
void PlayerEntity::tryToConsume(int n)
{
if (n < 0 || n >= MAX_SLOT_CONSUMABLES) return;
if (playerStatus != playerStatusPlaying) return;
if (consumable[n] > -1)
{
// unidentified
if (isUnidentified((enumItemType)consumable[n]))
{
enumItemType potion = (enumItemType)consumable[n];
enumItemType potionEffect = game().getPotion(potion);
game().setPotionToKnown(potion);
for (int i = 0; i < MAX_SLOT_CONSUMABLES; i++)
if (consumable[i] == potion) consumable[i] = potionEffect;
consume(potionEffect);
}
else if (items[consumable[n]].consumable)
// known
{
consume((enumItemType)consumable[n]);
}
else
{
std::cout << "[ERROR] Trying to consume item: " << items[consumable[n]].name << std::endl;
}
}
consumable[n] = -1;
}
void PlayerEntity::consume(enumItemType item)
{
switch(item)
{
case ItemScrollRevelation:
reveal();
spellAnimationDelay = spellAnimationDelayMax;
SoundManager::getInstance().playSound(SOUND_SCROLL);
break;
case ItemPotionHealth:
heal(equip[EQUIP_MANUAL_HEALTH] ? 28 : 18);
SoundManager::getInstance().playSound(SOUND_DRINK);
break;
case ItemPotionPoison:
specialState[SpecialStatePoison].active = true;
specialState[SpecialStatePoison].timer = POISON_TIMER[0];
specialState[SpecialStatePoison].param1 = POISON_DAMAGE[0];
specialState[SpecialStatePoison].param2 = POISON_DELAY[0];
specialState[SpecialStatePoison].param3 = POISON_DELAY[0];
displayFlyingText( x, y - 20.0f, 16, tools::getLabel("poison"), TextEntity::COLOR_FADING_RED);
SoundManager::getInstance().playSound(SOUND_DRINK);
break;
case ItemPotionSpeed:
specialState[SpecialStateSpeed].active = false;
specialState[SpecialStateSpeed].waitUnclear = true;
specialState[SpecialStateSpeed].timer = 30;
specialState[SpecialStateSpeed].param1 = 1.5f;
displayFlyingText( x, y - 20.0f, 16, tools::getLabel("effect_speed"), TextEntity::COLOR_FADING_BLUE);
SoundManager::getInstance().playSound(SOUND_DRINK);
break;
case ItemPotionSlow:
specialState[SpecialStateSlow].active = false;
specialState[SpecialStateSlow].waitUnclear = true;
specialState[SpecialStateSlow].timer = 30;
specialState[SpecialStateSlow].param1 = 0.35f;
displayFlyingText( x, y - 20.0f, 16, tools::getLabel("effect_slow"), TextEntity::COLOR_FADING_RED);
SoundManager::getInstance().playSound(SOUND_DRINK);
break;
case ItemPotionWeakness:
specialState[SpecialStateWeakness].active = false;
specialState[SpecialStateWeakness].waitUnclear = true;
specialState[SpecialStateWeakness].timer = 30;
specialState[SpecialStateWeakness].param1 = 0.5f;
displayFlyingText( x, y - 20.0f, 16, tools::getLabel("effect_weakness"), TextEntity::COLOR_FADING_RED);
SoundManager::getInstance().playSound(SOUND_DRINK);
break;
case ItemPotionStrength:
specialState[SpecialStateStrength].active = false;
specialState[SpecialStateStrength].waitUnclear = true;
specialState[SpecialStateStrength].timer = 30;
specialState[SpecialStateStrength].param1 = 1.5f;
displayFlyingText( x, y - 20.0f, 16, tools::getLabel("effect_strength"), TextEntity::COLOR_FADING_BLUE);
SoundManager::getInstance().playSound(SOUND_DRINK);
break;
case ItemPotionOblivion:
game().forget();
if (!equip[EQUIP_BOOK_ALCHEMY])
{
for (int i = 0; i < MAX_SLOT_CONSUMABLES; i++)
{
if (consumable[i] > -1)
{
if (consumable[i] >= ItemPotion01 + NUMBER_UNIDENTIFIED && consumable[i] < FirstEquipItem )
{
consumable[i] = game().getPotion((enumItemType)consumable[i]);
}
}
}
}
displayFlyingText( x, y - 20.0f, 16, tools::getLabel("effect_forget"), TextEntity::COLOR_FADING_RED);
SoundManager::getInstance().playSound(SOUND_DRINK);
break;
case ItemPotionConfusion:
specialState[SpecialStateConfused].active = false;
specialState[SpecialStateConfused].waitUnclear = true;
specialState[SpecialStateConfused].timer = 10;
displayFlyingText( x, y - 20.0f, 16, tools::getLabel("effect_confusion"), TextEntity::COLOR_FADING_RED);
SoundManager::getInstance().playSound(SOUND_DRINK);
break;
case ItemPotionCure:
for (int i = 0; i < DivineStateProtection; i++)
{
specialState[i].active = false;
specialState[i].waitUnclear = false;
}
displayFlyingText( x, y - 20.0f, 16, tools::getLabel("effect_cure"), TextEntity::COLOR_FADING_BLUE);
SoundManager::getInstance().playSound(SOUND_DRINK);
break;
case ItemPotionRage:
specialState[SpecialStateRage].active = false;
specialState[SpecialStateRage].waitUnclear = true;
specialState[SpecialStateRage].timer = 20.5f;
specialState[SpecialStateRage].param1 = 12;
specialState[SpecialStateRage].param2 = 2;
specialState[SpecialStateRage].param3 = 2;
displayFlyingText( x, y - 20.0f, 16, tools::getLabel("effect_rage"), TextEntity::COLOR_FADING_RED);
SoundManager::getInstance().playSound(SOUND_DRINK);
break;
default:
std::cout << "[ERROR] Trying to consume item: " << items[item].name << std::endl;
break;
}
SpriteEntity* usedItem = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_ITEMS), x, y, 32, 32);
usedItem->setImagesProLine(10);
if (item == ItemScrollRevelation)
usedItem->setFrame((int)item);
else
usedItem->setFrame(38);
usedItem->setFading(true);
usedItem->setZ(y - 100);
usedItem->setLifetime(0.7f);
usedItem->setAge(-0.7);
usedItem->setType(ENTITY_EFFECT);
usedItem->setSpin(rand() % 400 - 200);
usedItem->setVelocity(Vector2D(60));
}
void PlayerEntity::reveal()
{
for (int i = 0; i < MAX_SLOT_CONSUMABLES; i++)
{
if (consumable[i] > -1)
{
if (isUnidentified((enumItemType)consumable[i]))
{
game().setPotionToKnown((enumItemType)consumable[i]);
consumable[i] = game().getPotion((enumItemType)consumable[i]);
}
}
}
if (game().getCurrentMap()->callRevelation())
{
game().refreshMinimap();
SoundManager::getInstance().playSound(SOUND_SECRET);
}
}
bool PlayerEntity::canAquireConsumable(enumItemType type)
{
int nbConsumableSlot = equip[EQUIP_BAG] ? 4 : 2;
for (int i = 0; i < nbConsumableSlot; i++)
{
if (consumable[i] <= 0) return true;
}
return false;
}
void PlayerEntity::acquireConsumable(enumItemType type)
{
int nbConsumableSlot = equip[EQUIP_BAG] ? 4 : 2;
int emptySlot = -1;
for (int i = 0; emptySlot == -1 && i < nbConsumableSlot; i++)
{
if (consumable[i] <= 0) emptySlot = i;
}
if (emptySlot > -1)
{
consumable[emptySlot] = type;
if (type == ItemScrollRevelation)
SoundManager::getInstance().playSound(SOUND_SCROLL);
else
SoundManager::getInstance().playSound(SOUND_BOTTLE);
// events
game().proceedEvent(EventConsumable);
if (isUnidentified(type)) game().proceedEvent(EventPotion);
}
}
void PlayerEntity::onClearRoom()
{
if (divinity.divinity == DivinityHealer)
{
if (divinity.level > 1 && hp < hpMax)
{
divineInterventionDelay = WORSHIP_DELAY / 2;
isRegeneration = true;
showCone = 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;
// gloves
if (equip[EQUIP_GLOVES_ADVANCED]) fireDelayBonus -= 0.15f;
else if (equip[EQUIP_DISPLACEMENT_GLOVES]) fireDelayBonus -= 0.10f;
// hat
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;
// belt
if (equip[EQUIP_LEATHER_BELT]) fireDelayBonus -= 0.15f;
// boots
if (equip[EQUIP_BOOTS_ADVANCED]) creatureSpeedBonus += 0.25f;
else if (equip[EQUIP_LEATHER_BOOTS]) creatureSpeedBonus += 0.15f;
// multi-fire
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 >= 5) resistance[ResistanceRepulsion] = 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;
}
// potions
if (specialState[SpecialStateWeakness].active && !specialState[SpecialStateStrength].active)
fireDamages *= specialState[SpecialStateWeakness].param1;
if (specialState[SpecialStateStrength].active && !specialState[SpecialStateWeakness].active)
fireDamages *= specialState[SpecialStateStrength].param1;
}
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;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x * 0.7f;
}
void PlayerEntity::collideMapLeft()
{
collidingDirection = 4;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x * 0.7f;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x * 0.7f;
}
void PlayerEntity::collideMapTop()
{
collidingDirection = 8;
- if (recoil.active) recoil.velocity.y= -recoil.velocity.y * 0.7f;
+ if (repulsion.active) repulsion.velocity.y= -repulsion.velocity.y * 0.7f;
}
void PlayerEntity::collideMapBottom()
{
collidingDirection = 2;
- if (recoil.active) recoil.velocity.y= -recoil.velocity.y * 0.7f;
+ if (repulsion.active) repulsion.velocity.y= -repulsion.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::selectShotType(int n)
{
if (n == specialShotIndex) return;
if (n > 0 && getShotType(n) == ShotTypeStandard) return;
specialShotIndex = n;
initShotType();
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
computePlayer();
}
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;
donation += n;
if (donation >= 100) game().registerAchievement(AchievementFanatic);
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 >= 4 && game().getItemsCount() == 0 && donation >= 40)
{
if (divinity.divinity == DivinityIce && !equip[EQUIP_RING_ICE])
{
divineGift = true;
itemType = ItemRingIce;
}
else if (divinity.divinity == DivinityStone && !equip[EQUIP_RING_STONE])
{
divineGift = true;
itemType = ItemRingStone;
}
else if (divinity.divinity == DivinityAir && !equip[EQUIP_RING_LIGHTNING])
{
divineGift = true;
itemType = ItemRingLightning;
}
}
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;
showCone = true;
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(10.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->hurt(getHurtParams
(8,
ShotTypeStandard,
0,
false,
SourceTypeBolt,
EnemyTypeNone,
false));
- enemy->giveRecoil(true, Vector2D(x, y).vectorTo(Vector2D(enemy->getX(), enemy->getY()), 700.0f), 2.0f);
+ enemy->giveRepulsion(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, duration, armorBonus, 0.0f);
}
void PlayerEntity::divineHeal(int hpHealed)
{
int oldHp = hp;
hp += hpHealed;
if (hp > hpMax) hp = hpMax;
specialState[SpecialStatePoison].active = false;
divineInterventionDelay = WORSHIP_DELAY;
showCone = true;
isRegeneration = false;
game().addHealingStat(hp - oldHp);
}
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(8.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() % 2;
divineProtection(10.0f, 0.75f);
SoundManager::getInstance().playSound(SOUND_OM);
incrementDivInterventions();
divineHeal(hpMax / 3);
if (r == 0)
{
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 * 1.5f;
showCone = false;
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;
int oldLevel = divinity.level;
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)
{
if (oldLevel >= 4)
game().registerAchievement(AchievementApostate);
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 SpellTime:
activeSpell.delayMax = 70.0f;
activeSpell.frame = ItemSpellTime - FirstEquipItem;
break;
case SpellLightning:
activeSpell.delayMax = 70.0f;
activeSpell.frame = ItemSpellLightning - 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 SpellTime:
spellAnimationDelay = spellAnimationDelayMax;
castTimeStop();
break;
case SpellLightning:
spellAnimationDelay = spellAnimationDelayMax;
castLightning();
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] ? 6 : 4);
if (equip[EQUIP_BOOK_MAGIC_II] && boltDamage < 44) boltDamage = 44;
else if (!equip[EQUIP_BOOK_MAGIC_II] && boltDamage < 32) boltDamage = 32;
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));
}
}
}
void PlayerEntity::castTimeStop()
{
specialState[SpecialStateTime].active = true;
specialState[SpecialStateTime].timer = equip[EQUIP_BOOK_MAGIC_II] ? 7 : 5;
game().pauseMusic();
}
void PlayerEntity::castLightning()
{
game().makeColorEffect(X_GAME_COLOR_WHITE, 0.4f);
int nbBolts = equip[EQUIP_BOOK_MAGIC_II] ? 9 : 7;
for (int i = 0; i < nbBolts ; i++)
{
BoltEntity* bolt = new BoltEntity(x, getBolPositionY(), boltLifeTime, ShotTypeLightning, 0);
int boltDamage = game().getLevel() + 2;
if (i == 0) boltDamage += 10;
bolt->setDamages(boltDamage);
float shotAngle = rand() % 360;
bolt->setVelocity(Vector2D(400 * cos(shotAngle), 400 * sin(shotAngle)));
bolt->setViscosity(1.0f);
bolt->setLifetime(5 + 0.1f * (float)(rand() % 50));
}
SpriteEntity* lightningSprite = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_LIGHTNING), x, y - 300);
lightningSprite->setFading(true);
lightningSprite->setLifetime(0.2f);
lightningSprite->setAge(-0.4f);
lightningSprite->setRenderAdd();
lightningSprite->setZ(2000);
SoundManager::getInstance().playSound(SOUND_THUNDER);
}
diff --git a/src/PumpkinEntity.cpp b/src/PumpkinEntity.cpp
index 751535d..870684d 100644
--- a/src/PumpkinEntity.cpp
+++ b/src/PumpkinEntity.cpp
@@ -1,185 +1,185 @@
#include "PumpkinEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
PumpkinEntity::PumpkinEntity(float x, float y, bool invocated)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_PUMPKIN), x, y)
{
creatureSpeed = 0.0f;
velocity = Vector2D(0.0f, 0.0f);
hp = 40;
meleeDamages = 5;
this->invocated = invocated;
if (invocated)
{
type = ENTITY_ENEMY_INVOCATED;
jumpingDelay = 0.1f;
age = 0.0f;
}
else
{
jumpingDelay = 0.6f + 0.1f * (rand() % 20);
}
enemyType = invocated ? EnemyTypePumpkin_invocated : EnemyTypePumpkin;
bloodColor = BloodGreen;
frame = 2;
shadowFrame = 3;
dyingFrame = 4;
deathFrame = FRAME_CORPSE_PUMPKIN;
agonizingSound = SOUND_PUMPKIN_DIE;
isJumping = false;
h = 0.0f;
viscosity = 0.98f;
sprite.setOrigin(32, 44);
}
void PumpkinEntity::animate(float delay)
{
float slimeDelay = delay;
if (specialState[SpecialStateIce].active) slimeDelay = delay * specialState[SpecialStateIce].param1;
if (!isAgonising)
{
if (isJumping)
{
hVelocity -= 700.0f * slimeDelay;
h += hVelocity * slimeDelay;
bool firstTimeGround = false;
if (h <= 0.0f)
{
if (hp <= 0)
dying();
else
{
h = 0.0f;
if (isFirstJumping)
{
isFirstJumping = false;
firstTimeGround = true;
hVelocity = 120.0f;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT);
}
else
{
jumpingDelay = 0.05f;
isJumping = false;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT_WEAK);
}
}
}
if (firstTimeGround) frame = 2;
else if (hVelocity > -60.0f) frame = 1;
else frame = 0;
}
else
{
jumpingDelay -= slimeDelay;
if (jumpingDelay < 0.0f)
{
if (rand() % 2 == 0)
SoundManager::getInstance().playSound(SOUND_PUMPKIN_01, false);
else
SoundManager::getInstance().playSound(SOUND_PUMPKIN_00, false);
hVelocity = 200.0f;
isJumping = true;
isFirstJumping = true;
float randVel = 280.0f;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), randVel ));
}
else if (jumpingDelay < 0.05f)
frame = 1;
else frame = 2;
}
if (age > 0.0f && jumpingDelay < 0.05f)
{
frame = (int)(age * 6) % 4;
if (frame == 3) frame = 1;
}
else frame = 2;
}
EnemyEntity::animate(delay);
z = y + 14;
}
void PumpkinEntity::render(sf::RenderTarget* app)
{
if (!isDying && shadowFrame > -1)
{
// shadow
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
}
sprite.setPosition(x, y - h);
sprite.setTextureRect(sf::IntRect(frame * width, 0, width, height));
app->draw(sprite);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void PumpkinEntity::calculateBB()
{
boundingBox.left = (int)x - 16;
boundingBox.width = 32;
boundingBox.top = (int)y - 14;
boundingBox.height = 28;
}
void PumpkinEntity::collideMapRight()
{
velocity.x = -velocity.x * 0.8f;
}
void PumpkinEntity::collideMapLeft()
{
velocity.x = -velocity.x * 0.8f;
}
void PumpkinEntity::collideMapTop()
{
velocity.y = -velocity.y * 0.8f;
}
void PumpkinEntity::collideMapBottom()
{
velocity.y = -velocity.y * 0.8f;
}
void PumpkinEntity::collideWithEnemy(EnemyEntity* entity)
{
- if (recoil.active && recoil.stun) return;
+ if (repulsion.active && repulsion.stun) return;
if (entity->getMovingStyle() == movWalking)
setVelocity(Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), velocity.norm() ));
}
void PumpkinEntity::dying()
{
EnemyEntity::dying();
hVelocity = 320.0f;
}
void PumpkinEntity::prepareDying()
{
dying();
}
diff --git a/src/RatEntity.cpp b/src/RatEntity.cpp
index ee97c1b..8b18ef5 100644
--- a/src/RatEntity.cpp
+++ b/src/RatEntity.cpp
@@ -1,224 +1,224 @@
#include "RatEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
RatEntity::RatEntity(float x, float y, ratTypeEnum ratType, bool invocated)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_RAT), x, y)
{
this->ratType = ratType;
imagesProLine = 10;
this->invocated = invocated;
doesAccelerate = true;
if (ratType == RatTypeNormal)
{
frame = 1;
dyingFrame = 9;
deathFrame = FRAME_CORPSE_RAT;
if (invocated) enemyType = EnemyTypeRat_invocated;
else enemyType = EnemyTypeRat;
hp = RAT_HP;
creatureSpeed = RAT_SPEED;
}
else //(ratType == RatTypeHelmet)
{
frame = 31;
dyingFrame = 39;
deathFrame = FRAME_CORPSE_RAT_HELMET;
if (invocated) enemyType = EnemyTypeRatHelmet_invocated;
else enemyType = EnemyTypeRatHelmet;
hp = RAT_HP_HELMET;
creatureSpeed = RAT_SPEED_HELMET;
}
direction = rand() % 4;
clockTurn = rand() % 2 == 0;
compute(false);
timer = 6 + rand() % 6;
meleeDamages = RAT_DAMAGES;
bloodColor = BloodRed;
shadowFrame = -1;
agonizingSound = SOUND_RAT_DYING;
sprite.setOrigin(32.0f, 38.0f);
}
void RatEntity::animate(float delay)
{
if (age > 0.0f && !isAgonising)
{
timer -= delay;
if (timer < 0.0f)
{
timer = 6 + rand() % 6;
if (rand() % 3 == 0) clockTurn = !clockTurn;
compute(true);
}
checkNextFacing(delay);
frame = ((int)(age * 7.0f)) % 4;
if (frame == 3) frame = 1;
if (facingDirection == 4 || facingDirection == 6) frame += 3;
isMirroring = (facingDirection == 6 );
if (facingDirection == 8) frame += 6;
if (ratType == RatTypeHelmet) frame += 30;
}
EnemyEntity::animate(delay);
z = y + 17;
}
void RatEntity::compute(bool turn)
{
if (turn)
{
if (clockTurn)
{
direction++;
if (direction == 4) direction = 0;
}
else
{
direction--;
if (direction < 0) direction = 3;
}
}
velocity = Vector2D{0, 0};
float accelerationAbs = (enemyType == EnemyTypeRatHelmet || enemyType == EnemyTypeRatHelmet_invocated) ? (creatureSpeed / 10) : (creatureSpeed / 20);
doesAccelerate = true;
switch (direction)
{
case 0:
acceleration.x = 0;
acceleration.y = -accelerationAbs;
nextFacingDirection = 8;
break;
case 1:
acceleration.x = accelerationAbs;
acceleration.y = 0;
nextFacingDirection = 6;
break;
case 2:
acceleration.x = 0;
acceleration.y = accelerationAbs;
nextFacingDirection = 2;
break;
case 3:
acceleration.x = -accelerationAbs;
acceleration.y = 0;
nextFacingDirection = 4;
break;
}
}
void RatEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2 + RAT_BB_LEFT;
boundingBox.width = width - RAT_BB_WIDTH_DIFF;
boundingBox.top = (int)y - 13;
boundingBox.height = 31;
}
void RatEntity::collideMapRight()
{
- if (recoil.active) recoil.active = false;
+ if (repulsion.active) repulsion.active = false;
compute(true);
}
void RatEntity::collideMapLeft()
{
- if (recoil.active) recoil.active = false;
+ if (repulsion.active) repulsion.active = false;
compute(true);
}
void RatEntity::collideMapTop()
{
- if (recoil.active) recoil.active = false;
+ if (repulsion.active) repulsion.active = false;
compute(true);
}
void RatEntity::collideMapBottom()
{
- if (recoil.active) recoil.active = false;
+ if (repulsion.active) repulsion.active = false;
compute(true);
}
void RatEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
{
Vector2D recoilVector = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), 50.0f);
- giveRecoil(false, recoilVector, 0.2f);
+ giveRepulsion(false, recoilVector, 0.2f);
compute(true);
}
}
void RatEntity::collideWithBolt(BoltEntity* boltEntity)
{
if (ratType == RatTypeHelmet && boltEntity->getBoltType() != ShotTypeIllusion)
{
int collisionDir = getCollisionDirection(boltEntity);
bool boltCollide = true;
switch (facingDirection)
{
case 4:
if (collisionDir == 7 || collisionDir == 4 || collisionDir == 1) boltCollide = false;
break;
case 2:
if (collisionDir == 1 || collisionDir == 2 || collisionDir == 3) boltCollide = false;
break;
case 6:
if (collisionDir == 9 || collisionDir == 6 || collisionDir == 3) boltCollide = false;
break;
case 8:
if (collisionDir == 7 || collisionDir == 8 || collisionDir == 9) boltCollide = false;
break;
}
if (boltCollide) EnemyEntity::collideWithBolt(boltEntity);
else
{
float xs = (x + boltEntity->getX()) / 2;
float ys = (y + boltEntity->getY()) / 2;
boltEntity->collide();
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);
SoundManager::getInstance().playSound(SOUND_CLANG_00);
boltEntity->loseDamages(boltEntity->getDamages());
if (boltEntity->getBoltType() == ShotTypeStone)
{
float factor = (boltEntity->isFromPlayer() && game().getPlayer()->isEquiped(EQUIP_RAPID_SHOT)) ? 0.25f : 1.0f;
float recoilVelocity = factor * STONE_DECOIL_VELOCITY[boltEntity->getLevel()];
float recoilDelay = factor * STONE_DECOIL_DELAY[boltEntity->getLevel()];
Vector2D recoilVector = Vector2D(0, 0).vectorTo(boltEntity->getVelocity(),
recoilVelocity );
- giveRecoil(true, recoilVector, recoilDelay);
+ giveRepulsion(true, recoilVector, recoilDelay);
}
}
}
else EnemyEntity::collideWithBolt(boltEntity);
}
void RatEntity::drop()
{
if (!invocated) EnemyEntity::drop();
}
diff --git a/src/RockMissileEntity.cpp b/src/RockMissileEntity.cpp
index e613794..74985fb 100644
--- a/src/RockMissileEntity.cpp
+++ b/src/RockMissileEntity.cpp
@@ -1,139 +1,139 @@
#include "RockMissileEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
RockMissileEntity::RockMissileEntity(float x, float y, int rockType)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_CYCLOP), x, y)
{
Vector2D targetPos = game().getPlayerPosition();
imagesProLine = 20;
collisionDirection = -1;
enemyType = EnemyTypeRockMissile;
movingStyle = movFlying;
bloodColor = BloodNone; // stones don't bleed
hasCollided = false;
age = 0.0f;
this->rockType = rockType;
if (rockType == 0)
{
creatureSpeed = 500.0f;
hp = 12;
meleeDamages = 5;
frame = 18;
}
else
{
creatureSpeed = 450.0f;
hp = 24;
meleeDamages = 8;
frame = 38;
}
setVelocity(Vector2D(x, y).vectorNearlyTo(targetPos, creatureSpeed, 0.4f));
canExplode = false;
if (y < TILE_HEIGHT) this->y = TILE_HEIGHT;
if (!testEntityInMap()) isDying = true;
resistance[ResistancePoison] = ResistanceImmune;
}
void RockMissileEntity::animate(float delay)
{
EnemyEntity::animate(delay);
if (x < -60 || x > 1050 || y < - 50 || y > 800) isDying = true;
}
void RockMissileEntity::calculateBB()
{
int w;
if (rockType == 0) w = 20;
else w = 24;
boundingBox.left = (int)x - w / 2;
boundingBox.width = w;
boundingBox.top = (int)y - w / 2;
boundingBox.height = w;
}
void RockMissileEntity::collideWall()
{
if (rockType == 1 && !hasCollided)
{
hasCollided = true;
if (collisionDirection == DIRECTION_RIGHT || collisionDirection == DIRECTION_LEFT) velocity.x = -velocity.x;
else velocity.y = -velocity.y;
}
else
{
dying();
}
}
void RockMissileEntity::collideMapRight()
{
collisionDirection = DIRECTION_RIGHT;
collideWall();
}
void RockMissileEntity::collideMapLeft()
{
collisionDirection = DIRECTION_LEFT;
collideWall();
}
void RockMissileEntity::collideMapTop()
{
collisionDirection = DIRECTION_TOP;
collideWall();
}
void RockMissileEntity::collideMapBottom()
{
collisionDirection = DIRECTION_BOTTOM;
collideWall();
}
void RockMissileEntity::collideWithEnemy(EnemyEntity* entity)
{
}
void RockMissileEntity::dying()
{
isDying = true;
game().addKilledEnemy(enemyType, hurtingType);
SoundManager::getInstance().playSound(
rockType == 0 ? SOUND_ROCK_IMPACT_LIGHT : SOUND_ROCK_IMPACT_MEDIUM);
game().makeShake(0.1f);
for (int i = 0; i < 4; i++)
{
displayEntityStruct& de = game().getCurrentMapEntity()->generateBlood(x, y, BloodRock);
if ((collisionDirection == DIRECTION_LEFT) && (de.velocity.x < 0.0f))
de.velocity.x *= -0.25f;
else if ((collisionDirection == DIRECTION_RIGHT) && (de.velocity.x > 0.0f))
de.velocity.x *= -0.25f;
else if ((collisionDirection == DIRECTION_TOP) && (de.velocity.y < 0.0f))
de.velocity.y *= -0.25f;
else if ((collisionDirection == DIRECTION_BOTTOM) && (de.velocity.y > 0.0f))
de.velocity.y *= -0.25f;
}
}
-void RockMissileEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
+void RockMissileEntity::inflictsRepulsionTo(BaseCreatureEntity* targetEntity)
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(targetEntity);
if (playerEntity != NULL && !playerEntity->isDead())
{
- Vector2D recoilVector = Vector2D(0, 0).vectorTo(getVelocity(), 600.0f );
- targetEntity->giveRecoil(true, recoilVector, 0.5f);
+ Vector2D repulsionVector = Vector2D(0, 0).vectorTo(getVelocity(), 600.0f );
+ targetEntity->giveRepulsion(true, repulsionVector, 0.5f);
}
}
diff --git a/src/RockMissileEntity.h b/src/RockMissileEntity.h
index 993912f..2d2aa76 100644
--- a/src/RockMissileEntity.h
+++ b/src/RockMissileEntity.h
@@ -1,30 +1,30 @@
#ifndef ROCKMISSILENTITY_H
#define ROCKMISSILENTITY_H
#include "EnemyEntity.h"
class RockMissileEntity : public EnemyEntity
{
public:
RockMissileEntity(float x, float y, int rockType);
virtual void animate(float delay);
virtual void calculateBB();
protected:
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
virtual void collideWithEnemy(EnemyEntity* entity) override;
- virtual void inflictsRecoilTo(BaseCreatureEntity* targetEntity);
+ virtual void inflictsRepulsionTo(BaseCreatureEntity* targetEntity) override;
virtual void dying();
private:
int collisionDirection;
int rockType;
bool hasCollided;
void collideWall();
};
#endif // ROCKMISSILENTITY_H
diff --git a/src/SausageEntity.cpp b/src/SausageEntity.cpp
index b3777a6..3b3fb5f 100644
--- a/src/SausageEntity.cpp
+++ b/src/SausageEntity.cpp
@@ -1,190 +1,190 @@
#include "SausageEntity.h"
#include "ExplosionEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
SausageEntity::SausageEntity(float x, float y, bool invocated)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_SAUSAGE), x, y)
{
creatureSpeed = 0.0f;
hp = 8;
meleeDamages = 5;
this->invocated = invocated;
if (invocated) type = ENTITY_ENEMY_INVOCATED;
age = 0.0f;
enemyType = invocated ? EnemyTypeSausage_invocated : EnemyTypeSausage;
frame = 1;
shadowFrame = 3;
deathFrame = FRAME_CORPSE_SLIME_VIOLET;
agonizingSound = SOUND_NONE;
width = 48;
height = 48;
sprite.setOrigin(24, 24);
h = 0;
state = 0;
timer = 0.5f + 0.1f *( rand() % 12);
canExplode = false;
isNew = true;
}
void SausageEntity::render(sf::RenderTarget* app)
{
if (!isDying && shadowFrame > -1)
{
// shadow
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
}
sprite.setPosition(x, y - h);
sprite.setTextureRect(sf::IntRect(frame * width, 0, width, height));
app->draw(sprite);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void SausageEntity::animate(float delay)
{
isNew = false;
float sausDelay = delay;
if (specialState[SpecialStateIce].active) sausDelay = delay * specialState[SpecialStateIce].param1;
timer -= sausDelay;
if (timer <= 0.0f)
{
if (state == 0) // waiting
{
state++;
hVelocity = 450.0f;
}
else if (state == 2) // waiting in air
{
state++;
}
}
if (state == 1 || state == 3) // jumping / falling
{
hVelocity -= 750.0f * sausDelay;
if (state == 1 && /*hVelocity <= 0.0f*/ h > 35)
{
state = 2;
timer = 0.4f;
hVelocity = -100.0f;
}
else
h += hVelocity * sausDelay;
if (h <= 0.0f)
{
h = 0.0f;
state = 0;
timer = 1.0f;
}
}
if (h > 1.0f)
{
frame = ((int)(age * 20)) % 4;
if (frame == 3) frame = 1;
}
else
frame = 1;
EnemyEntity::animate(delay);
// frame
z = y + 14;
}
bool SausageEntity::canCollide()
{
return (!isNew);
}
void SausageEntity::calculateBB()
{
boundingBox.left = (int)x - 16;
boundingBox.width = 32;
boundingBox.top = (int)y - 14;
boundingBox.height = 28;
}
void SausageEntity::collideMapRight()
{
velocity.x = -velocity.x * 0.8f;
}
void SausageEntity::collideMapLeft()
{
velocity.x = -velocity.x * 0.8f;
}
void SausageEntity::collideMapTop()
{
velocity.y = -velocity.y * 0.8f;
}
void SausageEntity::collideMapBottom()
{
velocity.y = -velocity.y * 0.8f;
}
void SausageEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (!isDying && !isAgonising && collideWithEntity(entity))
{
if (entity->getType() == ENTITY_PLAYER || entity->getType() == ENTITY_BOLT )
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(entity);
BoltEntity* boltEntity = dynamic_cast<BoltEntity*>(entity);
if (playerEntity != NULL && !playerEntity->isDead()) dying();
else if (boltEntity != NULL && !boltEntity->getDying() && boltEntity->getAge() > 0.05f) collideWithBolt(boltEntity);
}
else // collision with other enemy ?
{
if (entity->getType() >= ENTITY_ENEMY && entity->getType() <= ENTITY_ENEMY_MAX)
{
if (this != entity)
{
EnemyEntity* enemyEntity = static_cast<EnemyEntity*>(entity);
if (enemyEntity->canCollide()) collideWithEnemy(enemyEntity);
}
}
}
}
}
void SausageEntity::collideWithEnemy(EnemyEntity* entity)
{
- if (recoil.active && recoil.stun) return;
+ if (repulsion.active && repulsion.stun) return;
Vector2D vel = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), 50.0f );
- giveRecoil(false, vel, 0.3f);
+ giveRepulsion(false, vel, 0.3f);
}
void SausageEntity::dying()
{
EnemyEntity::dying();
new ExplosionEntity(x, y, ExplosionTypeStandard, 18, EnemyTypeNone, true);
SoundManager::getInstance().playSound(SOUND_BOOM_00);
}
void SausageEntity::drop()
{
if (!invocated) EnemyEntity::drop();
}
diff --git a/src/SlimeEntity.cpp b/src/SlimeEntity.cpp
index 127ee17..bfaea90 100644
--- a/src/SlimeEntity.cpp
+++ b/src/SlimeEntity.cpp
@@ -1,416 +1,416 @@
#include "SlimeEntity.h"
#include "PlayerEntity.h"
#include "EnemyBoltEntity.h"
#include "ExplosionEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
SlimeEntity::SlimeEntity(float x, float y, slimeTypeEnum slimeType, bool invocated)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_SLIME), x, y)
{
creatureSpeed = 0.0f;
velocity = Vector2D(0.0f, 0.0f);
hp = SLIME_HP;
meleeDamages = SLIME_DAMAGES;
this->slimeType = slimeType;
this->invocated = invocated;
if (invocated)
{
type = ENTITY_ENEMY_INVOCATED;
jumpingDelay = 0.1f;
age = 0.0f;
}
else
{
jumpingDelay = 0.6f + 0.1f * (rand() % 20);
}
if (slimeType == SlimeTypeBlue)
{
resistance[ResistanceFrozen] = ResistanceImmune;
resistance[ResistanceIce] = ResistanceVeryHigh;
resistance[ResistanceFire] = ResistanceVeryLow;
enemyType = invocated ? EnemyTypeSlimeBlue_invocated : EnemyTypeSlimeBlue;
deathFrame = FRAME_CORPSE_SLIME_BLUE;
}
else if (slimeType == SlimeTypeRed)
{
resistance[ResistanceIce] = ResistanceVeryLow;
resistance[ResistanceFire] = ResistanceVeryHigh;
enemyType = invocated ? EnemyTypeSlimeRed_invocated : EnemyTypeSlimeRed;
deathFrame = FRAME_CORPSE_SLIME_RED;
}
else if (slimeType == SlimeTypeViolet)
{
enemyType = invocated ? EnemyTypeSlimeViolet_invocated : EnemyTypeSlimeViolet;
canExplode = false;
deathFrame = FRAME_CORPSE_SLIME_VIOLET;
}
else
{
enemyType = invocated ? EnemyTypeSlime_invocated : EnemyTypeSlime;
deathFrame = FRAME_CORPSE_SLIME;
}
bloodColor = BloodGreen;
frame = 0;
shadowFrame = 3;
imagesProLine = 4;
isJumping = false;
h = 0.0f;
viscosity = 0.98f;
sprite.setOrigin(32, 44);
isPet = false;
willExplode = false;
noCollisionTimer = -1.0f;
}
void SlimeEntity::setH(float h)
{
this->h = h;
}
void SlimeEntity::animate(float delay)
{
if (noCollisionTimer > 0.0f) noCollisionTimer -= delay;
float slimeDelay = delay;
if (specialState[SpecialStateIce].active) slimeDelay = delay * specialState[SpecialStateIce].param1;
if (isJumping)
{
hVelocity -= 700.0f * slimeDelay;
h += hVelocity * slimeDelay;
bool firstTimeGround = false;
if (h <= 0.0f)
{
if (hp <= 0)
dying();
else
{
h = 0.0f;
if (isFirstJumping)
{
isFirstJumping = false;
firstTimeGround = true;
hVelocity = 160.0f;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT);
if (slimeType == SlimeTypeBlue || slimeType == SlimeTypeRed)
fire();
else if (slimeType == SlimeTypeViolet)
{
hp = 0;
dying();
}
}
else
{
jumpingDelay = 0.4f + 0.1f * (rand() % 20);
isJumping = false;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT_WEAK);
}
}
}
if (firstTimeGround) frame = 0;
else if (hVelocity > -190.0f) frame = 2;
else frame = 1;
}
else
{
jumpingDelay -= slimeDelay;
if (jumpingDelay < 0.0f)
{
SoundManager::getInstance().playSound(SOUND_SLIME_JUMP);
hVelocity = 350.0f + rand() % 300;
isJumping = true;
isFirstJumping = true;
float randVel = 250.0f + rand() % 250;
if (!game().getPlayer()->isEquiped(EQUIP_MANUAL_SLIMES) && rand() % 2 == 0)
{
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), randVel ));
}
else
velocity = Vector2D(randVel);
}
else if (jumpingDelay < 0.1f)
frame = 1;
else frame = 0;
}
EnemyEntity::animate(delay);
z = y + 14;
}
void SlimeEntity::makeExplode()
{
if (isJumping)
willExplode = true;
else
BaseCreatureEntity::makeExplode();
}
void SlimeEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (!isDying && !isAgonising && collideWithEntity(entity))
{
if (!isPet && (entity->getType() == ENTITY_PLAYER || entity->getType() == ENTITY_BOLT ) )
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(entity);
BoltEntity* boltEntity = dynamic_cast<BoltEntity*>(entity);
if (playerEntity != NULL && !playerEntity->isDead())
{
if (playerEntity->hurt(getHurtParams(meleeDamages, meleeType, meleeDamages, false, SourceTypeMelee, enemyType, false)))
{
float xs = (x + playerEntity->getX()) / 2;
float ys = (y + playerEntity->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);
}
- inflictsRecoilTo(playerEntity);
+ inflictsRepulsionTo(playerEntity);
}
else if (boltEntity != NULL && !boltEntity->getDying() && boltEntity->getAge() > 0.05f)
{
collideWithBolt(boltEntity);
}
}
else // collision with other enemy ?
{
if (entity->getType() >= ENTITY_ENEMY && entity->getType() <= ENTITY_ENEMY_MAX_COUNT)
{
if (this != entity)
{
EnemyEntity* enemyEntity = static_cast<EnemyEntity*>(entity);
if (enemyEntity->canCollide()) collideWithEnemy(enemyEntity);
}
}
}
}
}
void SlimeEntity::render(sf::RenderTarget* app)
{
if (!isDying && shadowFrame > -1)
{
// shadow
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
}
sprite.setPosition(x, y - h);
sprite.setTextureRect(sf::IntRect(frame * width, slimeType * height, width, height));
app->draw(sprite);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void SlimeEntity::calculateBB()
{
if (isPet)
{
boundingBox.left = (int)x - 1;
boundingBox.width = 2;
boundingBox.top = (int)y - 1;
boundingBox.height = 2;
}
else
{
boundingBox.left = (int)x - width / 2 + SLIME_BB_LEFT;
boundingBox.width = width - SLIME_BB_WIDTH_DIFF;
boundingBox.top = (int)y - height / 2 + SLIME_BB_TOP - 15;
boundingBox.height = height - SLIME_BB_HEIGHT_DIFF;
}
}
void SlimeEntity::collideMapRight()
{
// if (x > OFFSET_X + MAP_WIDTH * TILE_WIDTH)
velocity.x = -velocity.x * 0.8f;
}
void SlimeEntity::collideMapLeft()
{
// if (x < OFFSET_X + MAP_WIDTH )
velocity.x = -velocity.x * 0.8f;
}
void SlimeEntity::collideMapTop()
{
// if (y > OFFSET_Y + MAP_HEIGHT * TILE_HEIGHT)
velocity.y = -velocity.y * 0.8f;
}
void SlimeEntity::collideMapBottom()
{
// if (y < OFFSET_Y + MAP_HEIGHT )
velocity.y = -velocity.y * 0.8f;
}
void SlimeEntity::collideWithEnemy(EnemyEntity* entity)
{
- if (recoil.active && recoil.stun) return;
+ if (repulsion.active && repulsion.stun) return;
if (entity->getMovingStyle() == movWalking)
{
Vector2D vel = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), 100.0f );
- giveRecoil(false, vel, 0.3f);
+ giveRepulsion(false, vel, 0.3f);
computeFacingDirection();
}
}
bool SlimeEntity::collideWithMap(int direction)
{
calculateBB();
int xTile0 = (boundingBox.left - offsetX) / tileWidth;
int xTilef = (boundingBox.left + boundingBox.width - offsetX) / tileWidth;
int yTile0 = (boundingBox.top - offsetY) / tileHeight;
int yTilef = (boundingBox.top + boundingBox.height - offsetY) / tileHeight;
if (boundingBox.top < 0) yTile0 = -1;
for (int xTile = xTile0; xTile <= xTilef; xTile++)
for (int yTile = yTile0; yTile <= yTilef; yTile++)
{
if (!game().getCurrentMap()->isFlyable(xTile, yTile))
{
switch (direction)
{
case DIRECTION_LEFT:
if (map->isLeftBlocking(xTile, yTile)) return true;
break;
case DIRECTION_RIGHT:
if (map->isRightBlocking(xTile, yTile)) return true;
break;
case DIRECTION_TOP:
if (map->isUpBlocking(xTile, yTile)) return true;
break;
case DIRECTION_BOTTOM:
if (map->isDownBlocking(xTile, yTile)) return true;
break;
}
}
}
return false;
}
void SlimeEntity::dying()
{
if (slimeType == SlimeTypeViolet) explode();
else if (willExplode) BaseCreatureEntity::makeExplode();
EnemyEntity::dying();
}
void SlimeEntity::prepareDying()
{
if (!isJumping)
dying();
}
bool SlimeEntity::canCollide()
{
if (noCollisionTimer > 0.0f) return false;
return h <= 70.0f && hp > 0;
}
void SlimeEntity::disableCollidingTemporary()
{
noCollisionTimer = 0.8f;
}
BaseCreatureEntity::enumMovingStyle SlimeEntity::getMovingStyle()
{
if (h <= 70.0f)
return movWalking;
else
return movFlying;
}
void SlimeEntity::fire()
{
for (int i = 0; i < 4; i++)
{
EnemyBoltEntity* bolt;
if (slimeType == SlimeTypeBlue)
{
bolt = new EnemyBoltEntity(x, y, ShotTypeIce, 0, enemyType);
bolt->setDamages(5);
}
else if (slimeType == SlimeTypeRed)
{
bolt = new EnemyBoltEntity(x, y, ShotTypeFire, 0, enemyType);
bolt->setDamages(8);
}
else
return;
switch (i)
{
case 0: bolt->setVelocity(Vector2D(SLIME_FIRE_VELOCITY, 0)); break;
case 1: bolt->setVelocity(Vector2D(-SLIME_FIRE_VELOCITY, 0)); break;
case 2: bolt->setVelocity(Vector2D(0, SLIME_FIRE_VELOCITY)); break;
case 3: bolt->setVelocity(Vector2D(0, -SLIME_FIRE_VELOCITY)); break;
}
}
if (slimeType == SlimeTypeBlue) SoundManager::getInstance().playSound(SOUND_BLAST_ICE);
else if (slimeType == SlimeTypeRed) SoundManager::getInstance().playSound(SOUND_BLAST_FIRE);
else SoundManager::getInstance().playSound(SOUND_BLAST_FLOWER);
}
void SlimeEntity::explode()
{
int damage = 12;
if (isPet) damage = game().getPlayer()->isEquiped(EQUIP_BOOK_MAGIC_II) ? 24 : 18;
new ExplosionEntity(x, y, ExplosionTypeStandard, damage, enemyType, true);
game().makeShake(1.0f);
SoundManager::getInstance().playSound(SOUND_BOOM_00);
}
void SlimeEntity::makePet(int direction)
{
isPet = true;
hVelocity = 450.0f;
SoundManager::getInstance().playSound(SOUND_SLIME_JUMP);
isJumping = true;
isFirstJumping = true;
switch (direction)
{
case 4: velocity.x = -350.0f; velocity.y = -0; break;
case 6: velocity.x = 350.0f; velocity.y = -0; break;
case 2: velocity.y = 350.0f; velocity.x = -0; break;
default: velocity.y = -350.0f; velocity.x = -0; break;
}
}
void SlimeEntity::drop()
{
if (!invocated) EnemyEntity::drop();
}
diff --git a/src/SlimePetEntity.cpp b/src/SlimePetEntity.cpp
index 0620166..c3d9bb2 100644
--- a/src/SlimePetEntity.cpp
+++ b/src/SlimePetEntity.cpp
@@ -1,307 +1,307 @@
#include "SlimePetEntity.h"
#include "PlayerEntity.h"
#include "EnemyBoltEntity.h"
#include "ExplosionEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
SlimePetEntity::SlimePetEntity()
: BaseCreatureEntity (ImageManager::getInstance().getImage(IMAGE_SLIME), 200, 200, 64, 64)
{
creatureSpeed = 0.0f;
velocity = Vector2D(0.0f, 0.0f);
hp = SLIME_HP;
jumpingDelay = 0.6f + 0.1f * (rand() % 20);
type = ENTITY_FAMILIAR_LOCAL;
frame = 0;
shadowFrame = 3;
imagesProLine = 4;
isJumping = false;
h = 0.0f;
attackDelay = -1.0f;
viscosity = 0.98f;
sprite.setOrigin(32, 44);
h = 1300;
hVelocity = 0.0f;
isJumping = true;
isFirstJumping = true;
age = 0.0f;
x = GAME_WIDTH * 0.5f;
y = GAME_HEIGHT * 0.5f;
if (game().getPlayer()->getX() < 2 * TILE_WIDTH) x = 2.5f * TILE_WIDTH;
else if (game().getPlayer()->getX() > GAME_WIDTH - 2 * TILE_WIDTH) x = GAME_WIDTH - 2.5f * TILE_WIDTH;
else if (game().getPlayer()->getY() < 2 * TILE_HEIGHT) y = 2.5f * TILE_HEIGHT;
else if (game().getPlayer()->getY() > GAME_HEIGHT - 2 * TILE_HEIGHT) y = GAME_HEIGHT - 2.5f * TILE_HEIGHT;
}
void SlimePetEntity::animate(float delay)
{
if (age < 0.0f)
{
age += delay;
}
else
{
attackDelay -= delay;
if (isJumping)
{
hVelocity -= 700.0f * delay;
h += hVelocity * delay;
bool firstTimeGround = false;
if (h <= 0.0f)
{
h = 0.0f;
if (isFalling())
{
fall();
}
else
{
if (isFirstJumping)
{
isFirstJumping = false;
firstTimeGround = true;
hVelocity = 160.0f;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT);
}
else
{
jumpingDelay = 0.3f + 0.1f * (rand() % 15);
isJumping = false;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT_WEAK);
}
}
}
if (firstTimeGround) frame = 0;
else if (hVelocity > -190.0f) frame = 2;
else frame = 1;
}
else if (isFalling())
{
fall();
}
else
{
jumpingDelay -= delay;
if (jumpingDelay < 0.0f)
{
SoundManager::getInstance().playSound(SOUND_SLIME_JUMP);
hVelocity = 300.0f + rand() % 250;
isJumping = true;
isFirstJumping = true;
float randVel = 250.0f + rand() % 250;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), randVel ));
}
else if (jumpingDelay < 0.1f)
frame = 1;
else frame = 0;
}
BaseCreatureEntity::animate(delay);
if (canCollide()) testSpriteCollisions();
}
z = y + 14;
}
void SlimePetEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (canCollide() && collideWithEntity(entity))
{
if (entity->getType() >= ENTITY_ENEMY && entity->getType() <= ENTITY_ENEMY_MAX_COUNT)
{
EnemyEntity* enemyEntity = static_cast<EnemyEntity*>(entity);
if (enemyEntity->canCollide())
{
if (attackDelay <= 0.0f)
{
enemyEntity->hurt(getHurtParams(12, ShotTypeStandard,0, false, SourceTypeMelee, EnemyTypeNone,false));
attackDelay = 0.65f;
float xs = (x + enemyEntity->getX()) / 2;
float ys = (y + enemyEntity->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);
}
if (enemyEntity->getMovingStyle() == movWalking)
{
Vector2D vel = Vector2D(enemyEntity->getX(), enemyEntity->getY()).vectorTo(Vector2D(x, y), 100.0f );
- giveRecoil(false, vel, 0.3f);
+ giveRepulsion(false, vel, 0.3f);
}
}
}
}
}
void SlimePetEntity::render(sf::RenderTarget* app)
{
// shadow
if (h < 1055)
{
int fade = 255;
if (h > 800)
fade = - (h - 1055);
sprite.setColor(sf::Color(255, 255, 255, fade));
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
sprite.setColor(sf::Color(255, 255, 255, 255));
}
// sprite
sprite.setPosition(x, y - h);
sprite.setTextureRect(sf::IntRect(frame * width, 4 * height, width, height));
app->draw(sprite);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void SlimePetEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2 + SLIME_BB_LEFT;
boundingBox.width = width - SLIME_BB_WIDTH_DIFF;
boundingBox.top = (int)y - height / 2 + SLIME_BB_TOP - 15;
boundingBox.height = height - SLIME_BB_HEIGHT_DIFF;
}
void SlimePetEntity::collideMapRight()
{
velocity.x = -velocity.x * 0.8f;
}
void SlimePetEntity::collideMapLeft()
{
velocity.x = -velocity.x * 0.8f;
}
void SlimePetEntity::collideMapTop()
{
velocity.y = -velocity.y * 0.8f;
}
void SlimePetEntity::collideMapBottom()
{
velocity.y = -velocity.y * 0.8f;
}
void SlimePetEntity::changeRoom()
{
h = 1500;
hVelocity = 0.0f;
isJumping = true;
isFirstJumping = true;
x = 300;
y = 250;
}
bool SlimePetEntity::collideWithMap(int direction)
{
calculateBB();
int xTile0 = (boundingBox.left - offsetX) / tileWidth;
int xTilef = (boundingBox.left + boundingBox.width - offsetX) / tileWidth;
int yTile0 = (boundingBox.top - offsetY) / tileHeight;
int yTilef = (boundingBox.top + boundingBox.height - offsetY) / tileHeight;
if (boundingBox.top < 0) yTile0 = -1;
for (int xTile = xTile0; xTile <= xTilef; xTile++)
for (int yTile = yTile0; yTile <= yTilef; yTile++)
{
if (!game().getCurrentMap()->isFlyable(xTile, yTile))
{
switch (direction)
{
case DIRECTION_LEFT:
if (map->isLeftBlocking(xTile, yTile)) return true;
break;
case DIRECTION_RIGHT:
if (map->isRightBlocking(xTile, yTile)) return true;
break;
case DIRECTION_TOP:
if (map->isUpBlocking(xTile, yTile)) return true;
break;
case DIRECTION_BOTTOM:
if (map->isDownBlocking(xTile, yTile)) return true;
break;
}
}
}
return false;
}
bool SlimePetEntity::canCollide()
{
return h <= 70.0f;
}
bool SlimePetEntity::isFalling()
{
int tilex0 = boundingBox.left / TILE_WIDTH;
int tiley0 = boundingBox.top / TILE_HEIGHT;
int tilexf = (boundingBox.left + boundingBox.width) / TILE_WIDTH;
int tileyf = (boundingBox.top + boundingBox.height) / TILE_HEIGHT;
return (game().getCurrentMap()->getLogicalTile(tilex0, tiley0) == LogicalHole
&& game().getCurrentMap()->getLogicalTile(tilex0, tileyf) == LogicalHole
&& game().getCurrentMap()->getLogicalTile(tilexf, tileyf) == LogicalHole
&& game().getCurrentMap()->getLogicalTile(tilexf, tiley0) == LogicalHole);
}
void SlimePetEntity::fall()
{
SpriteEntity* spriteEntity
= new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_SLIME),
x,
y + 6,
64, 64, 4);
spriteEntity->setAge(0.0f);
spriteEntity->setLifetime(3.0f);
spriteEntity->setShrinking(true);
spriteEntity->setFading(true);
spriteEntity->setFrame(16);
isDying = true;
SlimePetEntity* newSlime = new SlimePetEntity();
newSlime->setAge(-4.0f);
}
BaseCreatureEntity::enumMovingStyle SlimePetEntity::getMovingStyle()
{
if (h <= 70.0f)
return movWalking;
else
return movFlying;
}
diff --git a/src/SnakeEntity.cpp b/src/SnakeEntity.cpp
index 54fde7e..6d0b5c6 100644
--- a/src/SnakeEntity.cpp
+++ b/src/SnakeEntity.cpp
@@ -1,213 +1,213 @@
#include "SnakeEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
SnakeEntity::SnakeEntity(float x, float y, snakeTypeEnum snakeType, bool invocated)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_SNAKE), x, y)
{
this->snakeType = snakeType;
imagesProLine = 10;
this->invocated = invocated;
if (snakeType == SnakeTypeNormal)
{
frame = 0;
dyingFrame = 8;
deathFrame = FRAME_CORPSE_SNAKE;
if (invocated) enemyType = EnemyTypeSnake_invocated;
else enemyType = EnemyTypeSnake;
hp = SNAKE_HP;
creatureSpeed = SNAKE_SPEED;
meleeDamages = SNAKE_DAMAGE;
meleeType = ShotTypePoison;
}
else // snake blood
{
frame = 10;
dyingFrame = 18;
deathFrame = FRAME_CORPSE_SNAKE_BLOOD;
if (invocated) enemyType = EnemyTypeSnakeBlood_invocated;
else enemyType = EnemyTypeSnakeBlood;
hp = SNAKE_BLOOD_HP;
creatureSpeed = SNAKE_BLOOD_SPEED;
meleeDamages = SNAKE_BLOOD_DAMAGE;
}
velocity = Vector2D(creatureSpeed);
computeFacingDirection();
bloodColor = BloodRed;
shadowFrame = 9;
timer = -1.0f;
agonizingSound = SOUND_SNAKE_DIE;
resistance[ResistancePoison] = ResistanceImmune;
}
void SnakeEntity::animate(float delay)
{
if (age > 0.0f && !isAgonising)
{
sprite.setColor(sf::Color(255,255,255,255));
timer = timer - delay;
if (timer <= 0.0f)
{
timer = 0.8f;
if (canWalkTo(game().getPlayerPosition().x, game().getPlayerPosition().y))
{
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), creatureSpeed ));
computeFacingDirection();
}
}
switch (facingDirection)
{
case 2: frame = 0; break;
case 4: frame = 2; break;
case 6: frame = 4; break;
case 8: frame = 6; break;
}
frame += ((int)(age * 3.0f)) % 2;
if (snakeType == SnakeTypeBlood) frame += 10;
}
EnemyEntity::animate(delay);
z = y + 15;
}
void SnakeEntity::calculateBB()
{
boundingBox.left = (int)x - 15;
boundingBox.width = 30;
boundingBox.top = (int)y - 15;
boundingBox.height = 30;
}
void SnakeEntity::collideMapRight()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
else computeFacingDirection();
}
void SnakeEntity::collideMapLeft()
{
velocity.x = -velocity.x;
- if (recoil.active) recoil.velocity.x = -recoil.velocity.x;
+ if (repulsion.active) repulsion.velocity.x = -repulsion.velocity.x;
else computeFacingDirection();
}
void SnakeEntity::collideMapTop()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
else computeFacingDirection();
}
void SnakeEntity::collideMapBottom()
{
velocity.y = -velocity.y;
- if (recoil.active) recoil.velocity.y = -recoil.velocity.y;
+ if (repulsion.active) repulsion.velocity.y = -repulsion.velocity.y;
else computeFacingDirection();
}
void SnakeEntity::collideWithEnemy(EnemyEntity* entity)
{
- if (recoil.active && recoil.stun) return;
+ if (repulsion.active && repulsion.stun) return;
if (entity->getMovingStyle() == movWalking )
{
Vector2D vel = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), creatureSpeed );
if (velocity.x * vel.x < 0) velocity.x = vel.x;
if (velocity.y * vel.y < 0) velocity.y = vel.y;
timer = 0.05f;
}
}
void SnakeEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (!isDying && !isAgonising && collideWithEntity(entity))
{
if (entity->getType() == ENTITY_PLAYER || entity->getType() == ENTITY_BOLT )
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(entity);
BoltEntity* boltEntity = dynamic_cast<BoltEntity*>(entity);
if (playerEntity != NULL && !playerEntity->isDead())
{
int meleeLevel = 0;
if (snakeType == SnakeTypeBlood)
{
if (rand() % 3 == 0)
{
meleeType = ShotTypePoison;
meleeDamages = 4;
meleeLevel = 1;
}
else
{
meleeType = ShotTypeStandard;
meleeDamages = 8;
}
}
if (playerEntity->hurt(getHurtParams(meleeDamages, meleeType, meleeLevel, false, SourceTypeMelee, enemyType, false)))
{
float xs = (x + playerEntity->getX()) / 2;
float ys = (y + playerEntity->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);
}
- inflictsRecoilTo(playerEntity);
+ inflictsRepulsionTo(playerEntity);
}
else if (boltEntity != NULL && !boltEntity->getDying() && boltEntity->getAge() > 0.05f)
{
collideWithBolt(boltEntity);
}
}
else // collision with other enemy ?
{
if (entity->getType() >= ENTITY_ENEMY && entity->getType() <= ENTITY_ENEMY_MAX_COUNT)
{
if (this != entity)
{
EnemyEntity* enemyEntity = static_cast<EnemyEntity*>(entity);
if (enemyEntity->canCollide()) collideWithEnemy(enemyEntity);
}
}
}
}
}
void SnakeEntity::drop()
{
if (!invocated)
{
if (rand() % 5 == 0)
{
dropItem(ItemCopperCoin);
}
if (game().getPlayer()->isEquiped(EQUIP_LUCK) && rand() % 5 == 0)
{
dropItem(ItemCopperCoin);
}
if (rand() % 25 == 0)
{
dropItem(ItemHealthVerySmallPoison);
}
}
}
diff --git a/src/SpiderEggEntity.cpp b/src/SpiderEggEntity.cpp
index 078269b..287351f 100644
--- a/src/SpiderEggEntity.cpp
+++ b/src/SpiderEggEntity.cpp
@@ -1,163 +1,163 @@
#include "SpiderEggEntity.h"
#include "PlayerEntity.h"
#include "LittleSpiderEntity.h"
#include "BoltEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
SpiderEggEntity::SpiderEggEntity(float x, float y, bool invocated)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_SPIDER_EGG), x, y)
{
imagesProLine = 20;
type = invocated ? ENTITY_ENEMY_INVOCATED : ENTITY_ENEMY;
enemyType = invocated ? EnemyTypeSpiderEgg_invocated : EnemyTypeSpiderEgg;
this->invocated = invocated;
movingStyle = movFlying;
bloodColor = invocated ? BloodNone : BloodGreen;
deathFrame = FRAME_CORPSE_SPIDER_EGG;
dyingSound = rand() % 2 == 0 ? SOUND_EGG_SMASH_00 : SOUND_EGG_SMASH_01;
meleeDamages = 5;
age = 0.0f;
h = 1800 + rand() % 1000;
hp = 24;
jumping = false;
hVelocity = 0.0f;
lifetime = 12.0f + (rand() % 700) / 100;
}
void SpiderEggEntity::animate(float delay)
{
if (movingStyle == movFlying)
{
if (jumping)
{
hVelocity -= 300.0f * delay;
h += hVelocity * delay;
if (h <= 0.0f)
{
movingStyle = movWalking;
h = 0.0f;
}
}
else
{
h -= delay * 750.0f;
if (h < 0.0f)
{
h = 0.0f;
hVelocity = 100.0f;
jumping = true;
}
}
}
EnemyEntity::animate(delay);
z = y + 25;
frame = 0;
if (lifetime - age < 1.0f) frame = 3;
else if (lifetime - age < 2.5f) frame = 2;
else if (lifetime - age < 5.0f) frame = 1;
}
void SpiderEggEntity::dyingFromAge()
{
LittleSpiderEntity* ls = new LittleSpiderEntity(x, y, SpiderTypeStandard, invocated);
ls->setAge(-0.3f);
for (int i = 0; i < 4; i++)
{
SpriteEntity* blood = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_BLOOD), x, y, 16, 16, 6);
blood->setZ(-1);
blood->setFrame(18 + rand()%6);
blood->setType(ENTITY_BLOOD);
blood->setVelocity(Vector2D(rand()%250));
blood->setViscosity(0.95f);
float bloodScale = 1.0f + (rand() % 10) * 0.1f;
blood->setScale(bloodScale, bloodScale);
}
SoundManager::getInstance().playSound(SOUND_EGG_SMASH_00 + rand() % 2);
isDying = true;
}
void SpiderEggEntity::render(sf::RenderTarget* app)
{
int nx = frame % imagesProLine;
int ny = frame / imagesProLine;
// shadow
if (h <= 1600)
{
int f = 1600 - h;
if (f > 255) f = 255;
sprite.setColor(sf::Color(255, 255, 255, f));
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(4 * width, 0, width, height));
app->draw(sprite);
sprite.setColor(sf::Color(255, 255, 255, 255));
}
sprite.setPosition(x, y - h);
sprite.setTextureRect(sf::IntRect(nx * width, ny * height, width, height));
app->draw(sprite);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void SpiderEggEntity::calculateBB()
{
boundingBox.left = (int)x - 20;
boundingBox.width = 40;
boundingBox.top = (int)y - 5;
boundingBox.height = 30;
}
bool SpiderEggEntity::canCollide()
{
return h < 70;
}
void SpiderEggEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (!isDying && !isAgonising && collideWithEntity(entity))
{
if (entity->getType() == ENTITY_PLAYER || entity->getType() == ENTITY_BOLT )
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(entity);
BoltEntity* boltEntity = dynamic_cast<BoltEntity*>(entity);
if (movingStyle == movFlying && playerEntity != NULL && !playerEntity->isDead())
{
if (playerEntity->hurt(getHurtParams(meleeDamages, ShotTypeStandard, 0, false, SourceTypeMelee, enemyType, false)))
{
float xs = (x + playerEntity->getX()) / 2;
float ys = (y + playerEntity->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);
}
- inflictsRecoilTo(playerEntity);
+ inflictsRepulsionTo(playerEntity);
}
else if (boltEntity != NULL && !boltEntity->getDying() && boltEntity->getAge() > 0.05f)
{
EnemyEntity::collideWithBolt(boltEntity);
}
}
}
}
diff --git a/src/SpiderWebEntity.cpp b/src/SpiderWebEntity.cpp
index fbb6597..134f330 100644
--- a/src/SpiderWebEntity.cpp
+++ b/src/SpiderWebEntity.cpp
@@ -1,154 +1,154 @@
#include "SpiderWebEntity.h"
#include "PlayerEntity.h"
#include "BoltEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
SpiderWebEntity::SpiderWebEntity(float x, float y, bool isFromPlayer)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_SPIDER_WEB), x, y)
{
imagesProLine = 20;
type = ENTITY_ENEMY_NC;
enemyType = EnemyTypeSpiderWeb;
movingStyle = movFlying;
bloodColor = BloodNone; // web don't bleed
deathFrame = FRAME_CORPSE_SPIDER_WEB;
this->isFromPlayer = isFromPlayer;
age = 0.0f;
frame = 0;
setVelocity(Vector2D(80 + rand()% 500));
width = 128.0f;
height = 128.0f;
sprite.setOrigin(64.0f, 64.0f);
viscosity = 0.97f;
hp = 40;
hpMax = 40;
resistance[ResistanceFrozen] = ResistanceImmune;
- resistance[ResistanceRecoil] = ResistanceImmune;
+ resistance[ResistanceRepulsion] = ResistanceImmune;
resistance[ResistanceFire] = ResistanceVeryLow;
resistance[ResistanceStone] = ResistanceVeryLow;
resistance[ResistancePoison] = ResistanceImmune;
canExplode = false;
if (!testEntityInMap()) isDying = true;
}
void SpiderWebEntity::animate(float delay)
{
EnemyEntity::animate(delay);
if (age <= 0.5f)
{
float scale = age * 2.0f;
sprite.setScale(scale,scale);
}
else
sprite.setScale(1.0f, 1.0f);
int color = 177 + 78 * hp / hpMax;
sprite.setColor(sf::Color(color, color, color, 255));
}
void SpiderWebEntity::calculateBB()
{
boundingBox.left = (int)x - 45;
boundingBox.width = 90;
boundingBox.top = (int)y - 45;
boundingBox.height = 90;
}
void SpiderWebEntity::collideMapRight()
{
collideWall();
}
void SpiderWebEntity::collideMapLeft()
{
collideWall();
}
void SpiderWebEntity::collideMapTop()
{
collideWall();
}
void SpiderWebEntity::collideMapBottom()
{
collideWall();
}
void SpiderWebEntity::collideWall()
{
velocity.x = 0.0f;
velocity.y = 0.0f;
}
void SpiderWebEntity::collideWithEnemy(EnemyEntity* enemyEntity)
{
if (enemyEntity->getEnemyType() != EnemyTypeSpiderLittle_invocated
&& enemyEntity->getEnemyType() != EnemyTypeSpiderLittle
&& enemyEntity->getEnemyType() != EnemyTypeSpiderGiant
&& enemyEntity->getEnemyType() != EnemyTypeSpiderTarantula
&& enemyEntity->getEnemyType() != EnemyTypeSpiderTarantula_invocated
&& enemyEntity->getEnemyType() != EnemyTypeSpiderEgg
&& enemyEntity->getEnemyType() != EnemyTypeSpiderEgg_invocated
&& enemyEntity->getEnemyType() != EnemyTypeSpiderWeb)
{
if (!enemyEntity->isSpecialStateActive(SpecialStateSlow))
{
enemyEntity->setSpecialState(SpecialStateSlow, true, 0.15f, 0.25f, 0.0f);
hurt(getHurtParams(2, ShotTypeStandard, 0, false, SourceTypeMelee, enemyEntity->getEnemyType(), false));
}
}
}
void SpiderWebEntity::drop()
{
}
void SpiderWebEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (!isDying && !isAgonising && collideWithEntity(entity))
{
if (entity->getType() == ENTITY_PLAYER || entity->getType() == ENTITY_BOLT )
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(entity);
BoltEntity* boltEntity = dynamic_cast<BoltEntity*>(entity);
if (!isFromPlayer && playerEntity != NULL && !playerEntity->isDead())
{
if (!playerEntity->isSpecialStateActive(SpecialStateSlow))
{
playerEntity->setSpecialState(SpecialStateSlow, true, 0.1f, 0.33f, 0.0f);
// TODO
hurt(getHurtParams(2, ShotTypeStandard, 0, false, SourceTypeMelee, EnemyTypeNone, false));
}
}
else if (!isFromPlayer && boltEntity != NULL && !boltEntity->getDying() && boltEntity->getAge() > 0.05f)
{
EnemyEntity::collideWithBolt(boltEntity);
}
}
else // collision with other enemy ?
{
if (entity->getType() >= ENTITY_ENEMY && entity->getType() <= ENTITY_ENEMY_MAX)
{
if (this != entity)
{
EnemyEntity* enemyEntity = static_cast<EnemyEntity*>(entity);
if (enemyEntity->canCollide()) collideWithEnemy(enemyEntity);
}
}
}
}
}
diff --git a/src/VampireEntity.cpp b/src/VampireEntity.cpp
index 695dda2..1957cf1 100644
--- a/src/VampireEntity.cpp
+++ b/src/VampireEntity.cpp
@@ -1,806 +1,806 @@
#include "VampireEntity.h"
#include "BatEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "TextMapper.h"
#include <iostream>
#include <sstream>
const int VAMPIRE_HP = 1500;
const int VAMPIRE_DAMAGE = 12;
const float VAMPIRE_FLYING_DELAY = 1.2f;
const float VAMPIRE_BAT_DELAY = 0.225f;
const float VAMPIRE_CONFUSION_DELAY = 2.5f;
const float VAMPIRE_TRANSFORM_DELAY = 0.4f;
const float VAMPIRE_CRY_DELAY = 6.0f;
const float VAMPIRE_MOVE_COUNTER_MAX = 2;
const float VAMPIRE_DYING_TIME = 4.2f;
const int FORM_MAN = 0;
const int FORM_BAT = 1;
VampireEntity::VampireEntity(float myx, float myy)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_VAMPIRE), myx, myy)
{
width = 96;
height = 96;
creatureSpeed = 150;
hp = VAMPIRE_HP;
hpDisplay = VAMPIRE_HP;
hpMax = VAMPIRE_HP;
meleeDamages = VAMPIRE_DAMAGE;
shadowFrame = 30;
bodyFrame = 0;
type = ENTITY_ENEMY_BOSS;
//deathFrame = FRAME_CORPSE_CYCLOP;
batSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_VAMPIRE_BAT));
frame = 0;
if (game().getPlayerPosition().x > x) isMirroring = true;
sprite.setOrigin(48.0f, 74.0f);
imagesProLine = 6;
state = 0;
timer = 2.0f;
age = -1.0f;
enemyType = EnemyTypeVampire;
formState = FORM_MAN;
resistance[ResistanceFrozen] = ResistanceVeryHigh;
- resistance[ResistanceRecoil] = ResistanceVeryHigh;
+ resistance[ResistanceRepulsion] = ResistanceVeryHigh;
resistance[ResistancePoison] = ResistanceImmune;
canExplode = false;
x = GAME_WIDTH * 0.5f;
y = GAME_HEIGHT * 0.5f;
if (game().getPlayer()->getX() < 2 * TILE_WIDTH)
{
x = GAME_WIDTH - 2.5f * TILE_WIDTH;
targetPos = 4;
}
else if (game().getPlayer()->getX() > GAME_WIDTH - 2 * TILE_WIDTH)
{
x = 2.5f * TILE_WIDTH;
targetPos = 6;
}
else if (game().getPlayer()->getY() < 2 * TILE_HEIGHT)
{
y = GAME_HEIGHT - 2.5f * TILE_HEIGHT;
targetPos = 2;
}
else if (game().getPlayer()->getY() > GAME_HEIGHT - 2 * TILE_HEIGHT)
{
y = 2.5f * TILE_HEIGHT;
targetPos = 8;
}
moveCounter = 0;
}
int VampireEntity::getHealthLevel()
{
int healthLevel = 0;
if (hp <= hpMax * 0.25) healthLevel = 3;
else if (hp <= hpMax * 0.5) healthLevel = 2;
else if (hp <= hpMax * 0.75) healthLevel = 1;
return healthLevel;
}
void VampireEntity::computeStates(float delay)
{
timer -= delay;
if (timer <= 0.0f)
{
if (state == 0) // waiting bef hypnose
{
state = 1; // hypnose
timer = 1.6f;
game().getPlayer()->setSpecialState(SpecialStateConfused, true, VAMPIRE_CONFUSION_DELAY, VAMPIRE_CONFUSION_DELAY, 0.0f);
}
else if (state == 1) // hypnose
{
state = 2;
timer = 0.5f;
}
else if (state == 2) // waiting before laughing
{
state = 3; // laughing
timer = 1.3f; // 3.0f;
SoundManager::getInstance().playSound(SOUND_VAMPIRE_LAUGHING);
}
else if (state == 3) // laughing
{
state = 4;
timer = 0.1f;
}
else if (state == 4) // to bat cloud
{
if (getHealthLevel() > 1 && moveCounter <= 0)
{
state = 8;
timer = VAMPIRE_TRANSFORM_DELAY;
formState = FORM_BAT;
moveCounter = VAMPIRE_MOVE_COUNTER_MAX;
SoundManager::getInstance().playSound(SOUND_VAMPIRE_TRANSFORM_BOLT);
}
else
{
state = 5;
timer = VAMPIRE_TRANSFORM_DELAY;
moveCounter--;
SoundManager::getInstance().playSound(SOUND_VAMPIRE_TRANSFORM_BOLT);
}
}
else if (state == 5) // to bat cloud
{
state = 6;
frame = 10;
timer = VAMPIRE_FLYING_DELAY;
batTimer = VAMPIRE_BAT_DELAY;
xSource = x;
ySource = y;
if (targetPos == 4 || targetPos == 6)
{
targetPos = rand() % 2 == 0 ? 2 : 8;
}
else
{
targetPos = rand() % 2 == 0 ? 4 : 6;
}
}
else if (state == 6) // vampire flying in the cloud
{
state = 7;
timer = VAMPIRE_TRANSFORM_DELAY;
SoundManager::getInstance().playSound(SOUND_VAMPIRE_TRANSFORM_BOLT);
}
else if (state == 7) // cloud to vampire
{
state = 0;
timer = 0.5f;
}
else if (state == 8) // vampire to cloud < 50% HP
{
state = 9; // cloud to center
frame = 10;
timer = VAMPIRE_FLYING_DELAY;
batTimer = VAMPIRE_BAT_DELAY;
xSource = x;
ySource = y;
targetPos = 5;
if (hp <= hpMax * 0.1f)
{
numberOfRays = 6;
raySpeedFactor = 35.0f;
}
else if (hp <= hpMax * 0.2f)
{
numberOfRays = 5;
raySpeedFactor = 35.0f;
}
else if (hp <= hpMax * 0.3f)
{
numberOfRays = 5;
raySpeedFactor = 30.0f;
}
else if (hp <= hpMax * 0.4f)
{
numberOfRays = 4;
raySpeedFactor = 30.0f;
}
else
{
numberOfRays = 4;
raySpeedFactor = 20.0f;
}
}
else if (state == 9) // cloud to center
{
state = 10; // transform to giant bat
timer = VAMPIRE_TRANSFORM_DELAY;
}
else if (state == 10) // transform to giant bat
{
state = 11; // giant bat
for (int i = 0; i < 10; i++)
{
game().generateStar(sf::Color(200, 0, 200), x - 60 + rand() % 121, y - 60 + rand() % 121);
game().generateStar(sf::Color(0, 0, 0), x - 60 + rand() % 121, y - 60 + rand() % 121);
}
SoundManager::getInstance().playSound(SOUND_VAMPIRE_TRANSFORM_BAT);
timer = 1.0f;
}
else if (state == 11) // giant bat waiting
{
state = 12; // to cry
timer = VAMPIRE_CRY_DELAY;
}
else if (state == 12) // cry !
{
state = 13; // giant bat waiting
timer = VAMPIRE_TRANSFORM_DELAY;
for (int i = 0; i < 10; i++)
{
game().generateStar(sf::Color(200, 0, 200), x - 40 + rand() % 81, y - 40 + rand() % 81);
game().generateStar(sf::Color(0, 0, 0), x - 40 + rand() % 81, y - 40 + rand() % 81);
}
SoundManager::getInstance().playSound(SOUND_VAMPIRE_TRANSFORM_BAT);
}
else if (state == 13) // cry !
{
state = 6;
frame = 10;
timer = VAMPIRE_FLYING_DELAY;
batTimer = VAMPIRE_BAT_DELAY;
xSource = x;
ySource = y;
if (targetPos == 4 || targetPos == 6)
{
targetPos = rand() % 2 == 0 ? 2 : 8;
}
else
{
targetPos = rand() % 2 == 0 ? 4 : 6;
}
}
else
{
state = 0;
timer = 5.0f;
}
}
}
void VampireEntity::animate(float delay)
{
if (isAgonising)
{
timer += delay;
if (timer > VAMPIRE_DYING_TIME)
{
dying();
VampireDeadEntity* corpse = new VampireDeadEntity(x, y);
corpse->setMirroring(isMirroring);
}
return;
}
EnemyEntity::animate(delay);
if (isAgonising) return;
computeStates(delay);
if (state == 0)
{
if (timer < 0.2f) frame = 1;
else frame = 0;
}
else if (state == 1) // hypnose
{
frame = 2;
}
else if (state == 2 || state == 4) // waiting
{
frame = 0;
}
else if (state == 3) // laughing
{
frame = 3 + ((int)(age * 7.0f)) % 2;
}
else if (state == 5 || state == 8) // to bat cloud
{
sprite.setColor(sf::Color(255, 255, 255, 255));
if (timer > 0.2f)
{
frame = 0;
float fade = (VAMPIRE_TRANSFORM_DELAY - timer) / VAMPIRE_TRANSFORM_DELAY;
sprite.setColor(sf::Color(255 - fade * 250, 255 - fade * 250, 255 - fade * 250, 255));
isMirroring = game().getPlayer()->getX() > x;
}
else if (timer > 0.15f) frame = 6;
else if (timer > 0.1f) frame = 7;
else if (timer > 0.05f) frame = 8;
else frame = 9;
}
else if (state == 7 || state == 10) // to bat cloud
{
sprite.setColor(sf::Color(255, 255, 255, 255));
if (timer < 0.2f)
{
frame = 0;
float fade = timer * 4;
sprite.setColor(sf::Color(255 - fade * 250, 255 - fade * 250, 255 - fade * 250, 255));
isMirroring = game().getPlayer()->getX() > x;
}
else if (timer < VAMPIRE_TRANSFORM_DELAY - 0.15f) frame = 6;
else if (timer < VAMPIRE_TRANSFORM_DELAY - 0.1f) frame = 7;
else if (timer < VAMPIRE_TRANSFORM_DELAY - 0.05f) frame = 8;
else frame = 9;
}
else if (state == 6 || state == 9)
{
calculatePosition();
batTimer -= delay;
// bat generation
if (batTimer <= 0.0f)
{
batTimer += VAMPIRE_BAT_DELAY;
isMirroring = !isMirroring;
BatEntity* bat;
if (hp <= hpMax * 0.25f)
bat = new BatEntity(x, y, BatSkeleton, true);
else
bat = new BatEntity(x, y, BatStandard, true);
bat->setAge(0.0f);
}
// particules
for (int i = 0; i < 2; i++)
{
SpriteEntity* particle = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_VAMPIRE), x, y - 16, 96, 96);
particle->setFading(true);
particle->setImagesProLine(6);
particle->setZ(10);
particle->setLifetime(0.3f + 0.1f * (rand() % 10));
particle->setVelocity(Vector2D(12.0f));
particle->setType(ENTITY_EFFECT);
particle->setFrame(11 + 6 * i);
//particle->setFading(true);
particle->setShrinking(true);
particle->setX(x - 20 + rand()% 41);
particle->setY(y - 40 + rand()% 41);
}
for (int i = 0; i < 2; i++)
{
SpriteEntity* particle = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_VAMPIRE), x, y - 16, 96, 96);
particle->setFading(true);
particle->setImagesProLine(6);
particle->setZ(11);
//particle->setLifetime(0.9f);
particle->setLifetime(0.3f + 0.1f * (rand() % 10));
particle->setVelocity(Vector2D(12.0f));
particle->setType(ENTITY_EFFECT);
particle->setFrame(23 + 6 * i);
//particle->setFading(true);
particle->setShrinking(true);
particle->setRenderAdd();
particle->setX(x - 20 + rand()% 41);
particle->setY(y - 40 + rand()% 41);
}
}
else if (state == 12)
{
x = GAME_WIDTH / 2;
y = GAME_HEIGHT / 2;
testRaysCollision();
}
if (state != 5 && state != 7) isMirroring = game().getPlayer()->getX() > x;
z = y + 16;
}
void VampireEntity::calculatePosition()
{
float xTarget, yTarget;
if (targetPos == 4) xTarget = 2.5f * TILE_WIDTH;
else if (targetPos == 6) xTarget = GAME_WIDTH - 2.5f * TILE_WIDTH;
else xTarget = GAME_WIDTH * 0.5f;
if (targetPos == 8) yTarget = 2.5f * TILE_HEIGHT;
else if (targetPos == 2) yTarget = GAME_HEIGHT - 2.5f * TILE_HEIGHT;
else yTarget = GAME_HEIGHT * 0.5f;
x = xSource + (VAMPIRE_FLYING_DELAY - timer) / VAMPIRE_FLYING_DELAY * (xTarget - xSource);
y = ySource + (VAMPIRE_FLYING_DELAY - timer) / VAMPIRE_FLYING_DELAY * (yTarget - ySource);
}
int VampireEntity::hurt(StructHurt hurtParam)
{
if (state == 6 || state == 8 ||state == 9) armor = 1.0f;
else armor = 0.0f;
int result = EnemyEntity::hurt(hurtParam);
return result;
}
void VampireEntity::prepareDying()
{
// Giant bat ?
if (state == 11 || state ==12)
{
for (int i = 0; i < 10; i++)
{
game().generateStar(sf::Color(200, 0, 200), x - 40 + rand() % 81, y - 40 + rand() % 81);
game().generateStar(sf::Color(0, 0, 0), x - 40 + rand() % 81, y - 40 + rand() % 81);
}
SoundManager::getInstance().playSound(SOUND_VAMPIRE_TRANSFORM_BAT);
}
timer = 0.0f;
sprite.setOrigin(0.0f, 0.0f);
isAgonising = true;
SoundManager::getInstance().playSound(SOUND_VAMPIRE_DYING);
EntityManager::EntityList* entityList = EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
EnemyEntity* entity = dynamic_cast<EnemyEntity*>(e);
if (entity != NULL)
{
if (entity->getHp() > 0)
{
entity->hurt(getHurtParams(entity->getHp(), ShotTypeStandard, 0, false, SourceTypeMelee, enemyType, false));
}
}
}
type = ENTITY_ENEMY_NC;
}
void VampireEntity::calculateBB()
{
if (state >= 11)
{
boundingBox.left = (int)x - 50;
boundingBox.width = 100;
boundingBox.top = (int)y - 50;
boundingBox.height = 100;
}
else
{
boundingBox.left = (int)x - 16;
boundingBox.width = 32;
boundingBox.top = (int)y - 16;
boundingBox.height = 32;
}
}
void VampireEntity::drop()
{
dropItem(ItemBossHeart);
}
void VampireEntity::render(sf::RenderTarget* app)
{
if (isAgonising)
{
sprite.setPosition(x - 48, y - 74);
if (isMirroring) sprite.setTextureRect(sf::IntRect(1 * width, 2 * height, -width, height));
else sprite.setTextureRect(sf::IntRect(0 * width, 2 * height, width, height));
app->draw(sprite);
float burnHeight = timer < 4.0f ? height * timer / 4.0f : height;
if (isMirroring) sprite.setTextureRect(sf::IntRect(2 * width, 2 * height, -width, burnHeight));
else sprite.setTextureRect(sf::IntRect(width, 2 * height, width, burnHeight));
app->draw(sprite);
if (isMirroring) sprite.setTextureRect(sf::IntRect(2 * width, 2 * height, -width, height));
else sprite.setTextureRect(sf::IntRect(1 * width, 2 * height, width, height));
// fire
if (timer > 0.1f && timer < 3.8f)
{
sf::Sprite burn;
burn.setTexture(*ImageManager::getInstance().getImage(IMAGE_VAMPIRE));
if (isMirroring) burn.setTextureRect(sf::IntRect(5 * width, 2 * height + burnHeight - 4, -width, 6));
else burn.setTextureRect(sf::IntRect(4 * width, 2 * height + burnHeight - 4, width, 6));
burn.setPosition(x - 48, y - 74 - 4 + burnHeight);
app->draw(burn);
if (isMirroring) burn.setTextureRect(sf::IntRect(4 * width, 2 * height + burnHeight - 2, -width, 4));
else burn.setTextureRect(sf::IntRect(3 * width, 2 * height + burnHeight - 2, width, 4));
burn.setPosition(x - 48, y - 74 - 2 + burnHeight);
app->draw(burn);
float fade = (cos(12.0f * game().getAbsolutTime()) + 1.0f) * 0.5f;
burn.setColor(sf::Color(255, 255, 255, 100 * fade));
app->draw(burn, sf::BlendAdd);
}
// cone
sf::Sprite cone;
cone.setTexture(*ImageManager::getInstance().getImage(IMAGE_LIGHT_CONE));
cone.setPosition(x - 68, y - 600);
int fade = 200;
if (timer < 0.2f) fade = timer * 1000;
else if (timer > VAMPIRE_DYING_TIME - 0.5f) fade = (VAMPIRE_DYING_TIME - timer) * 400;
if (fade < 0) fade = 0;
cone.setColor(sf::Color(255, 255, 255, fade));
app->draw(cone, sf::BlendAdd);
}
else
{
if (state == 11 || state == 12) // giant bat
{
int oldBodyFrame = bodyFrame;
bodyFrame = (int)(age * 18) % 9;
if (oldBodyFrame == 6 && bodyFrame == 7)
SoundManager::getInstance().playSound(SOUND_VAMPIRE_FLAP);
batSprite.setTextureRect(sf::IntRect(418 * (bodyFrame % 3), 342 * (bodyFrame / 3), 418, 342));
batSprite.setPosition(x - 209, y - 200);
batSprite.setColor(sprite.getColor());
app->draw(batSprite);
if (state == 11)
{
frame = (int)(age * 4) % 9;
if (frame >= 5) frame = 8 - frame;
sprite.setTextureRect(sf::IntRect(width * frame, 3 * height, width, height));
if (timer < 1.0f && (int)(timer * 20) % 3 == 0) renderRays(app, false);
}
else if (state == 12)
{
// rays
renderRays(app, false);
// head
if (timer < 0.05f) frame = 1;
else if (timer < 0.1f) frame = 2;
else if (timer < 0.15f) frame = 3;
else if (timer < VAMPIRE_CRY_DELAY - 0.3f) frame = 4;
else if (timer < VAMPIRE_CRY_DELAY - 0.2f) frame = 3;
else if (timer < VAMPIRE_CRY_DELAY - 0.1f) frame = 2;
else frame = 1;
sprite.setTextureRect(sf::IntRect(width * frame, 4 * height, width, height));
}
sprite.setPosition(x + cosf(age * 2) * 2, y + sinf(age * 2) * 6);
app->draw(sprite);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
else
{
EnemyEntity::render(app);
if (state == 1) // hypnose
{
sf::Sprite eye;
eye.setOrigin(6, 6);
eye.setTexture(*ImageManager::getInstance().getImage(IMAGE_VAMPIRE));
eye.setTextureRect(sf::IntRect(5 * width, 0, 12, 12));
eye.setRotation(age * 500);
if (isMirroring) eye.setPosition(x + 10, y - 44);
else eye.setPosition(x - 10, y - 44);
app->draw(eye);
float fade = (cos(8.0f * game().getAbsolutTime()) + 1.0f) * 0.5f;
eye.setColor(sf::Color(255, 255, 255, 255 * fade));
app->draw(eye, sf::BlendAdd);
if (isMirroring) eye.setPosition(x - 4, y - 44);
else eye.setPosition(x + 4, y - 44);
eye.setColor(sf::Color(255, 255, 255, 255 ));
app->draw(eye);
eye.setColor(sf::Color(255, 255, 255, 255 * fade));
app->draw(eye, sf::BlendAdd);
}
}
renderLifeBar(app, tools::getLabel("enemy_vampire"));
}
}
void VampireEntity::renderRays(sf::RenderTarget* app, bool isGhost)
{
// rays
sf::RectangleShape ray(sf::Vector2f(500, 4));
ray.setOrigin(0, 2);
if (isGhost)
{
ray.setFillColor(sf::Color(128, 50, 50, 200));
ray.setOutlineColor(sf::Color(128, 50, 50, 100));
}
else
{
ray.setFillColor(sf::Color(255, 50, 50));
ray.setOutlineColor(sf::Color(255, 50, 50, 128));
}
ray.setOutlineThickness(1);
ray.setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2);
sf::RectangleShape rayLittle(sf::Vector2f(500, 2));
rayLittle.setOrigin(0, 1);
if (isGhost)
{
rayLittle.setFillColor(sf::Color(128, 50, 50, 100));
rayLittle.setOutlineColor(sf::Color(128, 50, 50, 50));
}
else
{
rayLittle.setFillColor(sf::Color(255, 50, 50, 150));
rayLittle.setOutlineColor(sf::Color(255, 50, 50, 75));
}
rayLittle.setOutlineThickness(1);
rayLittle.setPosition(GAME_WIDTH / 2, GAME_HEIGHT / 2);
float rayAngle = age * raySpeedFactor;
for (int i = 0; i < numberOfRays; i++)
{
ray.setRotation(rayAngle + i * 360 / numberOfRays);
app->draw(ray);
rayLittle.setRotation(ray.getRotation() + 3);
app->draw(rayLittle);
rayLittle.setRotation(ray.getRotation() - 3);
app->draw(rayLittle);
}
if (!isGhost)
SoundManager::getInstance().playSound(SOUND_VAMPIRE_SONIC_RAY, false);
}
void VampireEntity::testRaysCollision()
{
PlayerEntity* player = game().getPlayer();
if (player->canCollide() && player->getHp() > 0)
{
float rayAngle = age * raySpeedFactor;
Vector2D a1(GAME_WIDTH / 2, GAME_HEIGHT / 2);
Vector2D b1(player->getBoundingBox().left, player->getBoundingBox().top);
Vector2D b2(player->getBoundingBox().left + player->getBoundingBox().width, player->getBoundingBox().top);
Vector2D b3(player->getBoundingBox().left + player->getBoundingBox().width, player->getBoundingBox().top + player->getBoundingBox().height);
Vector2D b4(player->getBoundingBox().left, player->getBoundingBox().top + player->getBoundingBox().height);
for (int i = 0; i < numberOfRays; i++)
{
float currentAngle = rayAngle + i * 360 / numberOfRays;
Vector2D a2(GAME_WIDTH / 2 + 500 * cosf(currentAngle / 57.3f),
GAME_HEIGHT / 2 + 500 * sinf(currentAngle / 57.3f));
if (intersectsSegments(a1, a2, b1, b2)
|| intersectsSegments(a1, a2, b2, b3)
|| intersectsSegments(a1, a2, b3, b4)
|| intersectsSegments(a1, a2, b4, b1))
{
if (player->hurt(getHurtParams(8, ShotTypeStandard, 0, false, SourceTypeMelee, EnemyTypeVampire, false)) > 0)
{
SpriteEntity* star = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_VAMPIRE_PART), player->getX(), player->getY());
star->setFading(true);
star->setZ(y+ 100);
star->setLifetime(0.7f);
star->setType(ENTITY_EFFECT);
star->setSpin(400.0f);
}
}
}
}
}
void VampireEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(targetEntity);
if (playerEntity != NULL && !playerEntity->isDead())
{
Vector2D recoilVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), 450.0f);
- targetEntity->giveRecoil(true, recoilVector, 0.5f);
+ targetEntity->giveRepulsion(true, recoilVector, 0.5f);
}
}
void VampireEntity::generateBats(int batFrame)
{
SpriteEntity* spriteStar = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_VAMPIRE),
x - 50 + rand() % 101, y - 50 + rand() % 101, 96, 96, 6);
//spriteStar->setScale(0.8f, 0.8f);
spriteStar->setFrame(batFrame);
spriteStar->setZ(1000.0f);
//spriteStar->setSpin(-100 + rand()%200);
spriteStar->setVelocity(Vector2D(30 + rand()%60));
spriteStar->setWeight(-150);
spriteStar->setFading(true);
spriteStar->setAge(-0.8f);
spriteStar->setLifetime(0.1f + (rand() % 100) * 0.003f );
spriteStar->setType(ENTITY_EFFECT);
}
////////////////////// DEAD VAMPIRE /////////////////
VampireDeadEntity::VampireDeadEntity(float myx, float myy)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_VAMPIRE), myx, myy)
{
width = 96;
height = 96;
creatureSpeed = 0;
hp = 80;
hpMax = 80;
shadowFrame = 30;
type = ENTITY_ENEMY_NC;
deathFrame = FRAME_CORPSE_VAMPIRE;
dyingFrame = 14;
displayDamage = false;
frame = 13;
sprite.setOrigin(48.0f, 74.0f);
imagesProLine = 6;
bloodColor = BloodNone;
enemyType = EnemyTypeVampireDead;
resistance[ResistanceFrozen] = ResistanceImmune;
resistance[ResistancePoison] = ResistanceImmune;
canExplode = false;
}
void VampireDeadEntity::calculateBB()
{
boundingBox.left = (int)x - 16;
boundingBox.width = 32;
boundingBox.top = (int)y - 16;
boundingBox.height = 32;
}
void VampireDeadEntity::drop()
{
dropItem(ItemGoldCoin);
}
void VampireDeadEntity::animate(float delay)
{
EnemyEntity::animate(delay);
z = y + 16;
}
void VampireDeadEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(targetEntity);
if (playerEntity != NULL && !playerEntity->isDead())
{
Vector2D recoilVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), 100.0f);
- targetEntity->giveRecoil(false, recoilVector, 0.1f);
+ targetEntity->giveRepulsion(false, recoilVector, 0.1f);
}
}
void VampireDeadEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (!isDying && !isAgonising && collideWithEntity(entity))
{
if (entity->getType() == ENTITY_PLAYER || entity->getType() == ENTITY_BOLT )
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(entity);
BoltEntity* boltEntity = dynamic_cast<BoltEntity*>(entity);
if (playerEntity != NULL && !playerEntity->isDead()) inflictsRecoilTo(playerEntity);
else if (boltEntity != NULL && !boltEntity->getDying() && boltEntity->getAge() > 0.05f)
{
collideWithBolt(boltEntity);
}
}
}
}
diff --git a/src/WitchEntity.cpp b/src/WitchEntity.cpp
index a98954f..bfc530a 100644
--- a/src/WitchEntity.cpp
+++ b/src/WitchEntity.cpp
@@ -1,250 +1,250 @@
#include "WitchEntity.h"
#include "BoltEntity.h"
#include "EnemyBoltEntity.h"
#include "PlayerEntity.h"
#include "RatEntity.h"
#include "BatEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
WitchEntity::WitchEntity(float x, float y, witchTypeEnum witchType)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_WITCH), x, y)
{
this->witchType = witchType;
imagesProLine = 8;
if (witchType == WitchTypeNormal)
{
frame = 0;
dyingFrame = 5;
deathFrame = FRAME_CORPSE_WITCH;
enemyType = EnemyTypeWitch;
}
else
{
frame = 8;
dyingFrame = 13;
deathFrame = FRAME_CORPSE_WITCH_RED;
enemyType = EnemyTypeWitchRed;
}
hp = WITCH_HP;
hpMax = hp;
creatureSpeed = WITCH_VELOCITY;
velocity = Vector2D(creatureSpeed);
meleeDamages = WITCH_DAMAGE;
bloodColor = BloodRed;
shadowFrame = 4;
height = 96;
sprite.setOrigin(32, 71);
timer = 3.0f;
escapeTimer = -1.0f;
state = 0;
agonizingSound = (sound_resources)(SOUND_WITCH_DIE_00 + rand() % 2);
}
void WitchEntity::animate(float delay)
{
if (age > 0.0f && !isAgonising)
{
if (escapeTimer > 0.0f) escapeTimer -= delay;
timer -= delay;
if (timer <= 0.0f)
{
if (state == 0)
{
state = 1;
velocity = Vector2D(0.0f, 0.0f);
SoundManager::getInstance().playSound(SOUND_WITCH_00 + rand() % 3);
timer = 0.6f;
if (rand() % 7 == 0 || !canSee(game().getPlayerPosition().x, game().getPlayerPosition().y))
{
// invoke
int x0 = x / TILE_WIDTH;
if (x0 < 1) x0 = 1;
else if(x0 > MAP_WIDTH - 2) x0 = MAP_WIDTH - 2;
x0 = x0 * TILE_WIDTH + TILE_WIDTH / 2;
int y0 = y / TILE_HEIGHT;
if (y0 < 1) y0 = 1;
else if(y0 > MAP_HEIGHT - 2) y0 = MAP_HEIGHT - 2;
y0 = y0 * TILE_HEIGHT + TILE_HEIGHT / 2;
if (witchType == WitchTypeNormal) new RatEntity(x0, y0, RatEntity::RatTypeNormal, true);
else new BatEntity(x0, y0, BatStandard, true);
SoundManager::getInstance().playSound(SOUND_INVOKE);
for(int i=0; i < 6; i++)
{
generateStar(sf::Color(200, 50, 200, 255));
generateStar(sf::Color(255, 255, 255, 255));
}
}
else
{
// fire
fire();
if (witchType == WitchTypeNormal) fire();
}
}
else if (state == 1)
{
timer = 3.5f + (rand() % 25) * 0.1f;
if (!canSee(game().getPlayerPosition().x, game().getPlayerPosition().y)) timer += 1.2f;
velocity = Vector2D(creatureSpeed);
state = 0;
}
}
if (state == 0)
{
if (escapeTimer < 0.0f && Vector2D(x, y).distance2(game().getPlayerPosition()) <= 36000)
{
velocity = game().getPlayerPosition().vectorTo(Vector2D(x, y), creatureSpeed);
escapeTimer = 2.5f;
}
frame = ((int)(age * 5.0f)) % 4;
if (frame == 2) frame = 0;
else if (frame == 3) frame = 2;
if (velocity.x > 1.0f) isMirroring = true;
else if (velocity.x < -1.0f) isMirroring = false;
}
else if (state == 1)
{
frame = 3;
isMirroring = game().getPlayer()->getX() > x;
}
if (witchType == WitchTypeRed) frame += 8;
}
EnemyEntity::animate(delay);
z = y + 20;
}
void WitchEntity::calculateBB()
{
boundingBox.left = (int)x - 16;
boundingBox.width = 32;
boundingBox.top = (int)y - 25;
boundingBox.height = 45;
}
void WitchEntity::collideMapRight()
{
velocity.x = -velocity.x;
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.x = -recoil.velocity.x * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.x = -repulsion.velocity.x * 0.3f;
+ else (repulsion.active = false);
}
else computeFacingDirection();
}
void WitchEntity::collideMapLeft()
{
velocity.x = -velocity.x;
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.x = -recoil.velocity.x * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.x = -repulsion.velocity.x * 0.3f;
+ else (repulsion.active = false);
}
else computeFacingDirection();
}
void WitchEntity::collideMapTop()
{
velocity.y = -velocity.y;
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.y = -recoil.velocity.y * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.y = -repulsion.velocity.y * 0.3f;
+ else (repulsion.active = false);
}
else computeFacingDirection();
}
void WitchEntity::collideMapBottom()
{
velocity.y = -velocity.y;
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.y = -recoil.velocity.y * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.y = -repulsion.velocity.y * 0.3f;
+ else (repulsion.active = false);
}
else computeFacingDirection();
}
void WitchEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
{
setVelocity(Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), creatureSpeed ));
computeFacingDirection();
}
}
void WitchEntity::collideWithBolt(BoltEntity* boltEntity)
{
EnemyEntity::collideWithBolt(boltEntity);
}
void WitchEntity::fire()
{
if (witchType == WitchTypeNormal)
{
SoundManager::getInstance().playSound(SOUND_BLAST_FLOWER);
EnemyBoltEntity* bolt = new EnemyBoltEntity
(x, y + 10, ShotTypeStandard, 0, enemyType);
bolt->setMap(map, TILE_WIDTH, TILE_HEIGHT, 0, 0);
float flowerFireVelocity = EVIL_FLOWER_FIRE_VELOCITY;
if (specialState[SpecialStateIce].active) flowerFireVelocity *= 0.7f;
bolt->setVelocity(Vector2D(x, y).vectorNearlyTo(game().getPlayerPosition(), flowerFireVelocity, 1.0f ));
}
else
{
SoundManager::getInstance().playSound(SOUND_BLAST_FLOWER);
EnemyBoltEntity* bolt = new EnemyBoltEntity
(x, y + 10, ShotTypeBomb, 0, enemyType);
bolt->setMap(map, TILE_WIDTH, TILE_HEIGHT, 0, 0);
float flowerFireVelocity = EVIL_FLOWER_FIRE_VELOCITY * 0.9f;
if (specialState[SpecialStateIce].active) flowerFireVelocity *= 0.5f;
bolt->setVelocity(Vector2D(x, y).vectorNearlyTo(game().getPlayerPosition(), flowerFireVelocity, 1.0f ));
}
}
void WitchEntity::drop()
{
if (rand() % 12 == 0)
{
if (rand() % 5 == 0)
{
dropItem(ItemScrollRevelation);
}
else
{
dropItem((enumItemType)(ItemPotion01 + rand() % NUMBER_UNIDENTIFIED));
}
return;
}
else
{
if (rand() % 5 == 0)
{
dropItem(ItemCopperCoin);
}
if (game().getPlayer()->isEquiped(EQUIP_LUCK) && rand() % 5 == 0)
{
dropItem(ItemCopperCoin);
}
}
}
diff --git a/src/ZombieDarkEntity.cpp b/src/ZombieDarkEntity.cpp
index 5ebadf2..96e2e11 100644
--- a/src/ZombieDarkEntity.cpp
+++ b/src/ZombieDarkEntity.cpp
@@ -1,345 +1,345 @@
#include "ZombieDarkEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
ZombieDarkEntity::ZombieDarkEntity(float x, float y)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_ZOMBIE), x, y),
currentTile(0, 0),
targetTile(0, 0)
{
imagesProLine = 11;
frame = 11;
dyingFrame = 21;
bloodColor = BloodRed;
shadowFrame = 9;
deathFrame = FRAME_CORPSE_ZOMBIE_DARK;
enemyType = EnemyTypeZombieDark;
hp = ZOMBIE_HP;
creatureSpeed = ZOMBIE_SPEED;
meleeDamages = ZOMBIE_DAMAGE;
agonizingSound = SOUND_ZOMBIE_DYING;
currentDirection = 2 + 2 * rand()%4;
facingDirection = currentDirection;
nextFacingDirection = currentDirection;
height = 80;
sprite.setOrigin(32.0f, 60.0f);
attackTimer = 0.9f;
resistance[ResistanceFrozen] = ResistanceHigh;
- resistance[ResistanceRecoil] = ResistanceHigh;
+ resistance[ResistanceRepulsion] = ResistanceHigh;
resistance[ResistancePoison] = ResistanceImmune;
findNextGoal();
}
void ZombieDarkEntity::animate(float delay)
{
if (age > 0.0f && !isAgonising)
{
// goal reached ?
if (currentDirection == 6 && x > (targetTile.x * TILE_WIDTH + TILE_WIDTH / 2) ) findNextGoal();
else if (currentDirection == 4 && x < (targetTile.x * TILE_WIDTH + TILE_WIDTH / 2) ) findNextGoal();
else if (currentDirection == 2 && y > (targetTile.y * TILE_HEIGHT + TILE_HEIGHT / 2 - 5) ) findNextGoal();
else if (currentDirection == 8 && y < (targetTile.y * TILE_HEIGHT + TILE_HEIGHT / 2 - 5) ) findNextGoal();
checkNextFacing(delay);
frame = ((int)(age * 4.0f)) % 4;
if (frame == 3) frame = 1;
if (facingDirection == 4 || facingDirection == 6) frame += 3;
isMirroring = (facingDirection == 4 );
if (facingDirection == 8) frame += 6;
frame += 11;
attackTimer -= delay;
}
EnemyEntity::animate(delay);
z = y + 17;
}
void ZombieDarkEntity::calculateBB()
{
boundingBox.left = (int)x - 14;
boundingBox.width = 28;
boundingBox.top = (int)y - 18;
boundingBox.height = 36;
}
void ZombieDarkEntity::collideMapRight()
{
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.x = -recoil.velocity.x * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.x = -repulsion.velocity.x * 0.3f;
+ else (repulsion.active = false);
}
findNextRandomGoal();
}
void ZombieDarkEntity::collideMapLeft()
{
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.x = -recoil.velocity.x * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.x = -repulsion.velocity.x * 0.3f;
+ else (repulsion.active = false);
}
findNextRandomGoal();
}
void ZombieDarkEntity::collideMapTop()
{
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.y = -recoil.velocity.y * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.y = -repulsion.velocity.y * 0.3f;
+ else (repulsion.active = false);
}
findNextRandomGoal();
}
void ZombieDarkEntity::collideMapBottom()
{
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.y = -recoil.velocity.y * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.y = -repulsion.velocity.y * 0.3f;
+ else (repulsion.active = false);
}
findNextRandomGoal();
}
void ZombieDarkEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
{
if (currentDirection == 6 && entity->getX() > x)
{
currentDirection = 4;
targetTile = IntCoord(currentTile.x - 1, currentTile.y);
}
else if (currentDirection == 4 && entity->getX() < x)
{
currentDirection = 6;
targetTile = IntCoord(currentTile.x + 1, currentTile.y);
}
else if (currentDirection == 8 && entity->getY() < y)
{
currentDirection = 2;
targetTile = IntCoord(currentTile.x, currentTile.y + 1);
}
else if (currentDirection == 2 && entity->getY() > y)
{
currentDirection = 8;
targetTile = IntCoord(currentTile.x, currentTile.y - 1);
}
switch (currentDirection)
{
case 4: velocity.x = - creatureSpeed; velocity.y = 0.0f; break;
case 6: velocity.x = + creatureSpeed; velocity.y = 0.0f; break;
case 2: velocity.y = + creatureSpeed; velocity.x = 0.0f; break;
case 8: velocity.y = - creatureSpeed; velocity.x = 0.0f; break;
default: break;
}
nextFacingDirection = currentDirection;
}
}
void ZombieDarkEntity::findNextGoal()
{
currentTile = getCurrentTile();
float xPlayer = game().getPlayerPosition().x;
float yPlayer = game().getPlayerPosition().y;
float xDist = abs(x - xPlayer);
float yDist = abs(y - yPlayer);
int playerDirecion;
if (xDist >= yDist)
{
if (xPlayer > x) playerDirecion = 6;
else playerDirecion = 4;
}
else
{
if (yPlayer > y) playerDirecion = 2;
else playerDirecion = 8;
}
switch (currentDirection)
{
case 4:
if (playerDirecion != 6)
currentDirection = playerDirecion;
else
{
if (yPlayer > y) currentDirection = 2;
else currentDirection = 8;
}
break;
case 6:
if (playerDirecion != 4)
currentDirection = playerDirecion;
else
{
if (yPlayer > y) currentDirection = 2;
else currentDirection = 8;
}
break;
case 2:
if (playerDirecion != 8)
currentDirection = playerDirecion;
else
{
if (xPlayer > x) currentDirection = 6;
else currentDirection = 4;
}
break;
case 8:
if (playerDirecion != 2)
currentDirection = playerDirecion;
else
{
if (xPlayer > x) currentDirection = 6;
else currentDirection = 4;
}
break;
default: break;
}
switch (currentDirection)
{
case 4:
velocity.x = - creatureSpeed;
velocity.y = 0.0f;
targetTile = IntCoord(currentTile.x - 2, currentTile.y);
break;
case 6:
velocity.x = + creatureSpeed;
velocity.y = 0.0f;
targetTile = IntCoord(currentTile.x + 2, currentTile.y);
break;
case 2:
velocity.y = + creatureSpeed;
velocity.x = 0.0f;
targetTile = IntCoord(currentTile.x, currentTile.y + 2);
break;
case 8:
velocity.y = - creatureSpeed;
velocity.x = 0.0f;
targetTile = IntCoord(currentTile.x, currentTile.y - 2);
break;
default: break;
}
nextFacingDirection = currentDirection;
if (currentDirection == playerDirecion && attackTimer <= 0.0f)
{
- giveRecoil(false, Vector2D(velocity.x * 2.0f, velocity.y * 2.0f), 1.5f);
+ giveRepulsion(false, Vector2D(velocity.x * 2.0f, velocity.y * 2.0f), 1.5f);
attackTimer = 2.0f;
SoundManager::getInstance().playSound(SOUND_ZOMBIE_ATTACKING);
facingTimer = -1.0f;
}
else
SoundManager::getInstance().playSound(SOUND_ZOMBIE_00 + rand() % 2);
}
void ZombieDarkEntity::findNextRandomGoal()
{
currentTile = getCurrentTile();
DungeonMap* dMap = game().getCurrentMap();
int backDirection = 0;
switch (currentDirection)
{
case 4: backDirection = 6; break;
case 6: backDirection = 4; break;
case 2: backDirection = 8; break;
case 8: backDirection = 2; break;
default: break;
}
bool ok = false;
{
int r = 0;
while (!ok)
{
r++;
if (r == 150) // watchdog
ok = true;
else if (r == 40)
{
backDirection = 5;
}
int newDir = rand() % 4;
if (newDir == 0)
{
if (backDirection != 4 && currentTile.x > 1 && (currentTile.y % 2 != 0) && dMap->isWalkable(currentTile.x - 1, currentTile.y))
{
currentDirection = 4;
targetTile = IntCoord(currentTile.x - 1, currentTile.y);
ok = true;
}
}
else if (newDir == 1)
{
if (backDirection != 6 && currentTile.x < MAP_WIDTH - 2 && (currentTile.y % 2 != 0) && dMap->isWalkable(currentTile.x + 1, currentTile.y))
{
currentDirection = 6;
targetTile = IntCoord(currentTile.x + 1, currentTile.y);
ok = true;
}
}
else if (newDir == 2)
{
if (backDirection != 8 && currentTile.y > 1 && (currentTile.x % 2 != 0) && dMap->isWalkable(currentTile.x, currentTile.y - 1))
{
currentDirection = 8;
targetTile = IntCoord(currentTile.x, currentTile.y - 1);
ok = true;
}
}
else
{
if (backDirection != 2 && currentTile.y < MAP_HEIGHT - 2 && (currentTile.x % 2 != 0) && dMap->isWalkable(currentTile.x, currentTile.y + 1))
{
currentDirection = 2;
targetTile = IntCoord(currentTile.x, currentTile.y + 1);
ok = true;
}
}
}
}
switch (currentDirection)
{
case 4: velocity.x = - creatureSpeed; velocity.y = 0.0f; break;
case 6: velocity.x = + creatureSpeed; velocity.y = 0.0f; break;
case 2: velocity.y = + creatureSpeed; velocity.x = 0.0f; break;
case 8: velocity.y = - creatureSpeed; velocity.x = 0.0f; break;
default: break;
}
nextFacingDirection = currentDirection;
}
void ZombieDarkEntity::collideWithBolt(BoltEntity* boltEntity)
{
EnemyEntity::collideWithBolt(boltEntity);
}
bool ZombieDarkEntity::isAttacking()
{
return attackTimer > 1.0f;
}
diff --git a/src/ZombieEntity.cpp b/src/ZombieEntity.cpp
index 65f58dc..d283f8a 100644
--- a/src/ZombieEntity.cpp
+++ b/src/ZombieEntity.cpp
@@ -1,262 +1,262 @@
#include "ZombieEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
ZombieEntity::ZombieEntity(float x, float y, bool invocated)
: EnemyEntity (ImageManager::getInstance().getImage(IMAGE_ZOMBIE), x, y)
{
imagesProLine = 11;
this->invocated = invocated;
frame = 1;
dyingFrame = 10;
bloodColor = BloodRed;
shadowFrame = 9;
deathFrame = FRAME_CORPSE_ZOMBIE;
if (invocated) enemyType = EnemyTypeZombie_invocated;
else enemyType = EnemyTypeZombie;
hp = ZOMBIE_HP;
creatureSpeed = ZOMBIE_SPEED;
direction = rand() % 4;
facingDirection = direction;
nextFacingDirection = direction;
clockTurn = rand() % 2 == 0;
compute(false);
timer = 5 + rand() % 6;
attackTimer = 0.9f;
meleeDamages = ZOMBIE_DAMAGE;
agonizingSound = SOUND_ZOMBIE_DYING;
height = 80;
sprite.setOrigin(32.0f, 60.0f);
resistance[ResistanceFrozen] = ResistanceHigh;
- resistance[ResistanceRecoil] = ResistanceHigh;
+ resistance[ResistanceRepulsion] = ResistanceHigh;
resistance[ResistancePoison] = ResistanceImmune;
}
void ZombieEntity::animate(float delay)
{
if (isAgonising)
{
if (hpDisplay > hp) hpDisplay--;
if (h < -0.01f)
{
isAgonising = false;
isDying = true;
game().addCorpse(x, y, deathFrame);
if (dyingSound != SOUND_NONE) SoundManager::getInstance().playSound(dyingSound);
}
else
{
frame = dyingFrame;
hVelocity -= 700.0f * delay;
h += hVelocity * delay;
}
return;
}
else if (age > 0.0f)
{
if (attackTimer <= 0.0f && attack())
{
attackTimer = 2.0f;
- giveRecoil(false, Vector2D(velocity.x * 3.0f, velocity.y * 3.0f), 2.5f);
+ giveRepulsion(false, Vector2D(velocity.x * 3.0f, velocity.y * 3.0f), 2.5f);
}
else
{
timer -= delay;
attackTimer -= delay;
if (timer < 0.0f)
{
SoundManager::getInstance().playSound(SOUND_ZOMBIE_00 + rand() % 2);
timer = 5 + rand() % 6;
if (rand() % 3 == 0) clockTurn = !clockTurn;
compute(true);
}
}
checkNextFacing(delay);
frame = ((int)(age * 4.0f)) % 4;
if (frame == 3) frame = 1;
if (facingDirection == 4 || facingDirection == 6) frame += 3;
isMirroring = (facingDirection == 4 );
if (facingDirection == 8) frame += 6;
}
EnemyEntity::animate(delay);
z = y + 17;
}
bool ZombieEntity::attack()
{
Vector2D playerPos = game().getPlayerPosition();
bool attacking = false;
// left ?
if (playerPos.x < x && playerPos.y > y - 15 && playerPos.y < y + 15 && canSee(playerPos.x, playerPos.y))
{
direction = 3;
velocity.x = -creatureSpeed;
velocity.y = 0;
facingDirection = 4;
attacking = true;
}
// right ?
else if (playerPos.x > x && playerPos.y > y - 15 && playerPos.y < y + 15 && canSee(playerPos.x, playerPos.y))
{
direction = 1;
velocity.x = creatureSpeed;
velocity.y = 0;
facingDirection = 6;
attacking = true;
}
// down ?
else if (playerPos.y > y && playerPos.x > x - 15 && playerPos.x < x + 15 && canSee(playerPos.x, playerPos.y))
{
direction = 2;
velocity.x = 0;
velocity.y = creatureSpeed;
facingDirection = 2;
attacking = true;
}
// up ?
else if (playerPos.y < y && playerPos.x > x - 15 && playerPos.x < x + 15 && canSee(playerPos.x, playerPos.y))
{
direction = 0;
velocity.x = 0;
velocity.y = -creatureSpeed;
facingDirection = 8;
attacking = true;
}
if (attacking)
{
SoundManager::getInstance().playSound(SOUND_ZOMBIE_ATTACKING);
facingTimer = 0.2f;
nextFacingDirection = facingDirection;
}
return attacking;
}
void ZombieEntity::compute(bool turn)
{
if (turn)
{
if (clockTurn)
{
direction++;
if (direction == 4) direction = 0;
}
else
{
direction--;
if (direction < 0) direction = 3;
}
}
switch (direction)
{
case 0:
velocity.x = 0;
velocity.y = -creatureSpeed;
nextFacingDirection = 8;
break;
case 1:
velocity.x = creatureSpeed;
velocity.y = 0;
nextFacingDirection = 6;
break;
case 2:
velocity.x = 0;
velocity.y = creatureSpeed;
nextFacingDirection = 2;
break;
case 3:
velocity.x = -creatureSpeed;
velocity.y = 0;
nextFacingDirection = 4;
break;
}
}
void ZombieEntity::calculateBB()
{
boundingBox.left = (int)x - 14;
boundingBox.width = 28;
boundingBox.top = (int)y - 18;
boundingBox.height = 36;
}
void ZombieEntity::collideMapRight()
{
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.x = -recoil.velocity.x * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.x = -repulsion.velocity.x * 0.3f;
+ else (repulsion.active = false);
}
else compute(true);
}
void ZombieEntity::collideMapLeft()
{
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.x = -recoil.velocity.x * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.x = -repulsion.velocity.x * 0.3f;
+ else (repulsion.active = false);
}
else compute(true);
}
void ZombieEntity::collideMapTop()
{
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.y = -recoil.velocity.y * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.y = -repulsion.velocity.y * 0.3f;
+ else (repulsion.active = false);
}
else compute(true);
}
void ZombieEntity::collideMapBottom()
{
- if (recoil.active)
+ if (repulsion.active)
{
- if (recoil.stun) recoil.velocity.y = -recoil.velocity.y * 0.3f;
- else (recoil.active = false);
+ if (repulsion.stun) repulsion.velocity.y = -repulsion.velocity.y * 0.3f;
+ else (repulsion.active = false);
}
else compute(true);
}
void ZombieEntity::collideWithEnemy(EnemyEntity* entity)
{
if (entity->getMovingStyle() == movWalking)
{
Vector2D recoilVector = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), 50.0f);
- giveRecoil(false, recoilVector, 0.2f);
+ giveRepulsion(false, recoilVector, 0.2f);
compute(true);
}
}
void ZombieEntity::drop()
{
if (!invocated) EnemyEntity::drop();
}
bool ZombieEntity::isAttacking()
{
return attackTimer > 1.0f;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Sep 12, 5:33 AM (1 d, 3 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
42813
Default Alt Text
(385 KB)
Attached To
Mode
R78 witchblast
Attached
Detach File
Event Timeline
Log In to Comment