void Player::contact(Entity* e) { //not exactly elegant, but oh well. if(e->getType() == ET_ENTITY || e->getType() == ET_SPACESHIP_A || e->getType() == ET_SPACESHIP_B || e->getType() == ET_SPACESHIP_C || e->getType() == ET_SPACESHIP_D) { if(e->isDead()) { //if it's dead, we don't care about this collision return; } applyDamage(e->getCollisionDamage()); //apply collision damage to player e->setHealth(0); //kill entity _game->getGameplayScreen()->addScore(50); _game->getGameplayScreen()->addEnemyShot(); _game->getGameplayScreen()->getEntityManager()->deleteEntity(e->getId(), true); //schedule deletion } if(e->getType() == ET_POWERUP) { Powerup* powerup = static_cast <Powerup*> (e); std::string powerupType = powerup->getPowerupType(); if(powerupType == "hp") { _game->getGameplayScreen()->addHealth(100); } else if(powerupType == "score") { _game->getGameplayScreen()->addScore(50); } else if(powerupType == "dmg") { applyDamage(50); } powerup->setHealth(0); } }
void CollisionListener::PostSolve(b2Contact* theContact, const b2ContactImpulse* theImpulse) { auto anCollideEntityA = static_cast<GQE::IEntity*>(theContact->GetFixtureA()->GetBody()->GetUserData()); auto anCollideEntityB = static_cast<GQE::IEntity*>(theContact->GetFixtureB()->GetBody()->GetUserData()); float aImpactStrength = theImpulse->normalImpulses[0]; applyDamage(anCollideEntityA, aImpactStrength); applyDamage(anCollideEntityB, aImpactStrength); }
void Creep::takeDamage(int damage, Damage_Type damageType) { if (applyDamage(damage, damageType)) { displayHealthBar(); } if (m_health <= 0) { kill(damageType); } }
void Player::handleEvent(sf::Event e){ m_joystick = -1; for (int i = 0; i < 6 && m_joystick == -1; i++){ if (sf::Joystick::isConnected(i)) m_joystick = i; } if (e.type == sf::Event::JoystickButtonPressed){ int buttonId = e.joystickButton.button; if (buttonId < 4){ bool addCombo = false; if (!m_currentActions.empty() && m_actionToPlay == false){ if (m_animatedSprite.getFrame() > m_currentActions.front()->getMinFrame() && m_animatedSprite.getFrame() < m_currentActions.front()->getMaxFrame()){ m_currentActions.push(&m_actions[buttonId]); m_actionToPlay = true; addCombo = true; } } else if (m_actionToPlay == false){ m_currentActions.push(&m_actions[buttonId]); addCombo = true; currentAnim = &m_anims[m_currentActions.back()->getAnimName()]; m_animatedSprite.play(*currentAnim); m_animatedSprite.setLooped(false); applyDamage(); } if (addCombo){ switch (buttonId) { case 0: m_comboString += 'A'; break; case 1: m_comboString += 'B'; break; case 2: m_comboString += 'X'; break; case 3: m_comboString += 'Y'; break; } } } } }
void Player::behaviour(){ for (const Character* e : attackableEnemies){ if (e->getAlive() == false){ attackableEnemies.erase(std::find(attackableEnemies.begin(), attackableEnemies.end(), e)); break; } } if (m_actionToPlay && m_animatedSprite.getFrame() == m_currentActions.front()->getMaxFrame()){ m_currentActions.pop(); m_animatedSprite.play(m_anims[m_currentActions.front()->getAnimName()]); m_animatedSprite.setLooped(false); m_actionToPlay = false; applyDamage(); } //if all animations have stopped playing then reset if (m_animatedSprite.isPlaying() == false || (currentAnim == &m_anims["run"] && m_velocity == sf::Vector2f()) || (m_comboTriggered && m_currentActions.size() > 0 && m_animatedSprite.getFrame() == m_currentActions.front()->getMaxFrame())){ comboFinished(); } else if (currentAnim != &m_anims["run"]){ m_speed = 0; } float xPos = sf::Joystick::getAxisPosition(m_joystick, sf::Joystick::Axis::X); float yPos = sf::Joystick::getAxisPosition(m_joystick, sf::Joystick::Axis::Y); if ((xPos < 10 && xPos > -10) && (yPos < 10 && yPos > -10)){ m_velocity.x = 0; m_velocity.y = 0; sndMgr->stopSound("walking_grass"); return; } sndMgr->playSound("walking_grass", true); xPos = (xPos / 100) * m_speed; yPos = (yPos / 100) * m_speed; if (m_speed > 0 && currentAnim != &m_anims["run"]){ currentAnim = &m_anims["run"]; m_animatedSprite.play(*currentAnim); m_animatedSprite.setLooped(false); } m_velocity = sf::Vector2f(xPos, yPos); }
void Player::comboFinished(){ m_comboTriggered = true; if (m_comboString == "BX"){ std::cout << "BX combo triggered" << '\n'; m_currentActions.pop(); m_currentActions.push(&m_actions[4]); currentAnim = &m_anims[m_currentActions.back()->getAnimName()]; m_animatedSprite.play(*currentAnim); m_animatedSprite.setLooped(false); m_actionToPlay = false; applyDamage(2.f); } else{ m_comboTriggered = false; m_speed = max_speed; currentAnim = &m_anims["idle"]; m_animatedSprite.play(*currentAnim); m_animatedSprite.setLooped(false); m_actionToPlay = false; m_currentActions.swap(std::queue<Action*>()); //empty the queue } m_comboString = ""; }
void BattleHazard::applyEffect(GameState &state) { auto tile = tileObject->getOwningTile(); auto set = tile->ownedObjects; for (auto obj : set) { if (tile->ownedObjects.find(obj) == tile->ownedObjects.end()) { continue; } if (obj->getType() == TileObject::Type::Ground || obj->getType() == TileObject::Type::Feature || obj->getType() == TileObject::Type::LeftWall || obj->getType() == TileObject::Type::RightWall) { auto mp = std::static_pointer_cast<TileObjectBattleMapPart>(obj)->getOwner(); switch (damageType->effectType) { case DamageType::EffectType::Fire: LogWarning("Set map part on fire!"); break; default: mp->applyDamage(state, power, damageType); break; } } else if (obj->getType() == TileObject::Type::Unit) { StateRef<BattleUnit> u = { &state, std::static_pointer_cast<TileObjectBattleUnit>(obj)->getUnit()->id}; switch (damageType->effectType) { case DamageType::EffectType::Fire: LogWarning("Set unit on fire!"); break; default: { // Determine direction of hit Vec3<float> velocity = -position; velocity -= Vec3<float>{0.5f, 0.5f, 0.5f}; velocity += u->position; if (velocity.x == 0.0f && velocity.y == 0.0f) { velocity.z = 1.0f; } // Determine wether to hit head, legs or torso auto cposition = u->position; // Hit torso if (sqrtf(velocity.x * velocity.x + velocity.y * velocity.y) > std::abs(velocity.z)) { cposition.z += (float)u->getCurrentHeight() / 2.0f / 40.0f; } // Hit head else if (velocity.z < 0) { cposition.z += (float)u->getCurrentHeight() / 40.0f; } else { // Legs are defeault already } // Apply u->applyDamage(state, power, damageType, u->determineBodyPartHit(damageType, cposition, velocity)); } break; } } } }
void BattleHazard::applyEffect(GameState &state) { auto tile = tileObject->getOwningTile(); auto set = tile->ownedObjects; for (auto &obj : set) { if (tile->ownedObjects.find(obj) == tile->ownedObjects.end()) { continue; } if (obj->getType() == TileObject::Type::Ground || obj->getType() == TileObject::Type::Feature || obj->getType() == TileObject::Type::LeftWall || obj->getType() == TileObject::Type::RightWall) { auto mp = std::static_pointer_cast<TileObjectBattleMapPart>(obj)->getOwner(); switch (damageType->effectType) { case DamageType::EffectType::Fire: if (mp->applyBurning(state, age)) { // Map part burned and provided fuel for our fire, keep the fire raging if (power < 0 && age > 10) { power = -power; } } break; default: switch (damageType->blockType) { case DamageType::BlockType::Gas: case DamageType::BlockType::Psionic: break; default: mp->applyDamage(state, power, damageType); break; } break; } } else if (obj->getType() == TileObject::Type::Item) { if (damageType->effectType == DamageType::EffectType::Fire) { // It was observed that armor resists fire damage deal to it // It also appears that damage is applied gradually at a rate of around 1 damage per // second // In tests, marsec armor (20% modifier) was hurt by fire but X-Com armor (10% // modifier) was not // If we apply damage once per turn, we apply 4 at once. Since we round down, 4 * // 20% will be rounded to 0 // while it should be 1. So we add 1 here auto i = std::static_pointer_cast<TileObjectBattleItem>(obj)->getItem(); i->applyDamage(state, 2 * TICKS_PER_HAZARD_UPDATE / TICKS_PER_SECOND + 1, damageType); } } else if (obj->getType() == TileObject::Type::Unit) { StateRef<BattleUnit> u = { &state, std::static_pointer_cast<TileObjectBattleUnit>(obj)->getUnit()->id}; // Determine direction of hit Vec3<float> velocity = -position; velocity -= Vec3<float>{0.5f, 0.5f, 0.5f}; velocity += u->position; if (velocity.x == 0.0f && velocity.y == 0.0f) { velocity.z = 1.0f; } // Determine wether to hit head, legs or torso auto cposition = u->position; // Hit torso if (sqrtf(velocity.x * velocity.x + velocity.y * velocity.y) > std::abs(velocity.z)) { cposition.z += (float)u->getCurrentHeight() / 2.0f / 40.0f; } // Hit head else if (velocity.z < 0) { cposition.z += (float)u->getCurrentHeight() / 40.0f; } else { // Legs are defeault already } // Apply u->applyDamage(state, power, damageType, u->determineBodyPartHit(damageType, cposition, velocity), DamageSource::Hazard); } } }
void main_loop(Player &player1, Player &player2) { srand (time(NULL)); int random_num; std::string weather; player1.active = player1.pokemons[0]; player2.active = player2.pokemons[0]; player1.active_ability = player1.active->getAbility(); player2.active_ability = player2.active->getAbility(); field = {false, false, false, false, CLEAR}; switchin_abilities(player1.active_ability->name); switchin_abilitiies(player2.active_ability->name); Attack* attack1, attack2; int turn; bool bypass = false; while(!player1.forfeit || !player2.forfeit) //change this conditional to faints instead { //getPlayers actions here parseActions(player1); parseActions(player2); if(player1.action == SWITCH) { bypass = false; if(player2.action == FIGHT && player2.using_attack->name == "Pursuit") { applyDamage(player2.active, player1.active, player2.using_attack); bypass = true; } Switch(player1.active, player1.switchTo); active_ability1 = player1.active->getAbility(); switching_abilities(player1.active_ability->name); if(bypass) { //skip to next turn continue; } } if(player2.action == SWITCH) { bypass = false; if(player1.action == FIGHT && player1.using_attack->name == "Pursuit") { applyDamage(player1.active, player2.active, player1.using_attack); bypass = true; } Switch(player2.active, player2.switchTo); active_ability2 = player2.active->getAbility(); switching_abilities(player2.active_ability->name); // REMEMBER to apply spikes damages and shit if(bypass) { //skip to next turn continue; } } //apply damages turn = compareSpeed(player1.active, player2.active); switch(turn) { case -1: applyDamage(player2.active, player1.active, player2.using_attack); checkIsFaint(player1); applyDamage(player1.active, player2.active, player1.using_attack); checkIsFaint(player2); break; case 1: applyDamage(player1.active, player2.active, player1.using_attack); checkIsFaint(player2); applyDamage(player2.active, player1.active, player2.using_attack); checkIsFaint(player1); break; case 0: random_num = rand()%101; if(random_num < 50) { applyDamage(player1.active, player2.active, player1.using_attack); checkIsFaint(player2); applyDamage(player2.active, player1.active, player2.using_attack); checkIsFaint(player1); } else { applyDamage(player1.active, player2.active, player1.using_attack); checkIsFaint(player2); applyDamage(player2.active, player1.active, player2.using_attack); checkIsFaint(player1); } break; } afterBattleAbility(player1.active_ability->name); checkIsFaint(player1); checkIsFaint(player2); afterBattleAbility(player2.active_ability->name); checkIsFaint(player1); checkIsFaint(player2); } }
bool Npc::die() { return applyDamage(nullptr, _attribs.getCurrent(attrib::Types::HEALTH)) > 0.0; }
// Check collision void UFO::checkCollision(Handlers* handlers){ // Make sure UFO cannot leave level on left or right side LevelProperties* lp = (LevelProperties*)(handlers->levelProps); if (nextX - 50.0f < lp->getLevelLeft()) nextX = lp->getLevelLeft() + 50.0f; if (nextX + 50.0f > lp->getLevelRight()) nextX = lp->getLevelRight() - 50.0f; // Keep UFO from leaving top of level if (nextY < lp->getLevelTop()) nextY = lp->getLevelTop(); // ---------------------------------- // Check UFO collision with ground // Push UFO away from ground if too close // ---------------------------------- // Point used during collision detection Point p; Point* itr; // Setup vertical line segment vertA.setLocation(nextX, nextY); vertB.setLocation(nextX, nextY + minDistFromGround); // Normal ground check: itr = handlers->ground->getPoints(); if (itr != NULL){ while (itr->next != NULL){ // Check if player is close to point if ((*itr).getX() <= nextX && (*(itr->next)).getX() >= nextX){ if (checkSegSeg(vertA, vertB, *itr, *(itr->next), &p)){ nextX = p.getX(); nextY = p.getY() - minDistFromGround; break; } } itr = itr->next; } } // --------------------------------------------- // Check ufo collision with enemy projectiles // --------------------------------------------- // Fix collision rectangle for next step collisionArea.setLocation(locX - originX, locY - originY); collisionArea.setSize(width, height); Projectile** projs = ((ProjectileHandler*)handlers->projHandler)->getProjList(); Point projp; // Check all projectiles for collision for (int i = 0; i <= ((ProjectileHandler*)handlers->projHandler)->getLastActive(); i++){ // Null check if (projs[i] != NULL && projs[i]->getAlive() && projs[i]->getFiredBy() == PFB_ENEMY){ // Quick distance check if (dist(nextX, nextY,projs[i]->getCurrentX(), projs[i]->getCurrentY()) <100){ // Check for collision if (checkRecSeg(&collisionArea, projs[i]->getCurrentX(), projs[i]->getCurrentY(), projs[i]->getPrevX(), projs[i]->getPrevY(), &projp)){ // Tell projectile we had a player collision projs[i]->collide(&projp, handlers, P_PLAYER_COLL); // Apply projectile damage to player ((SoundHandler*)handlers->soundHandler)->playSoundEffect(SE_UFO_HIT); applyDamage(projs[i]->getDamage()); } } } } // --------------------------------------------- // Check ufo collision with enemy explosions // --------------------------------------------- Explosion* expls = ((ExplHandler*)handlers->explHander)->getExpls(); for (int i = 0; i <= ((ExplHandler*)handlers->explHander)->getLastActive(); i++){ if (expls[i].isValid()){ if (expls[i].firedByEnemy() && expls[i].inRadius(&collisionArea)){ applyDamage(expls[i].getDamage()); } } } }
void BattleExplosion::damage(GameState &state, const TileMap &map, Vec3<int> pos, int damage) { auto tile = map.getTile(pos); // Explosions with no hazard spawn smoke with half ttl if (!damageType->hazardType) { StateRef<DamageType> dtSmoke = {&state, "DAMAGETYPE_SMOKE"}; state.current_battle->placeHazard(state, ownerOrganisation, ownerUnit, dtSmoke, pos, dtSmoke->hazardType->getLifetime(state), damage, 2, false); } // Explosions with no custom explosion doodad spawn hazards when dealing damage else if (!damageType->explosionDoodad) { state.current_battle->placeHazard(state, ownerOrganisation, ownerUnit, damageType, pos, damageType->hazardType->getLifetime(state), damage, 1, false); } // Gas does no direct damage if (damageType->doesImpactDamage()) { auto set = tile->ownedObjects; for (auto &obj : set) { if (tile->ownedObjects.find(obj) == tile->ownedObjects.end()) { continue; } if (obj->getType() == TileObject::Type::Ground || obj->getType() == TileObject::Type::Feature || obj->getType() == TileObject::Type::LeftWall || obj->getType() == TileObject::Type::RightWall) { auto mp = std::static_pointer_cast<TileObjectBattleMapPart>(obj)->getOwner(); switch (damageType->effectType) { case DamageType::EffectType::Fire: // Nothing, map parts are not damaged by fire at explosion time break; default: mp->applyDamage(state, damage, damageType); break; } } else if (obj->getType() == TileObject::Type::Unit) { StateRef<BattleUnit> u = { &state, std::static_pointer_cast<TileObjectBattleUnit>(obj)->getUnit()->id}; if (affectedUnits.find(u) != affectedUnits.end()) { continue; } affectedUnits.insert(u); // Determine direction of hit Vec3<float> velocity = -position; velocity -= Vec3<float>{0.5f, 0.5f, 0.5f}; velocity += u->position; if (velocity.x == 0.0f && velocity.y == 0.0f) { velocity.z = 1.0f; } // Determine wether to hit head, legs or torso auto cposition = u->position; // Hit torso if coming from the side, not from above or below if (sqrtf(velocity.x * velocity.x + velocity.y * velocity.y) > std::abs(velocity.z)) { cposition.z += (float)u->getCurrentHeight() / 2.0f / 40.0f; } // Hit head if coming from above else if (velocity.z < 0) { cposition.z += (float)u->getCurrentHeight() / 40.0f; } // Hit legs if coming from below else { // Legs are defeault already } // Apply u->applyDamage(state, damage, damageType, u->determineBodyPartHit(damageType, cposition, velocity), DamageSource::Impact, ownerUnit); } else if (obj->getType() == TileObject::Type::Item) { // Special effects do not damage items, fire damages items differently and not on // explosion impact if (damageType->effectType == DamageType::EffectType::None) { auto i = std::static_pointer_cast<TileObjectBattleItem>(obj)->getItem(); i->applyDamage(state, damage, damageType); } } } } }
bool PlayerBullet::onImpact(Entity* hit) { auto impact = GameGlobals::get()->impact; auto position = getComponent<sz::Transform>()->getPosition(); auto color = getComponent<sz::Renderer>()->getColor(); impact->setColor(color); if(bulletStance == PlayerEntity::Stance::Offensive) impact->setScale(0.6f, 1.f + (thor::random(0, 10) >= 9 ? 1.5f : 0.f)); else impact->setScale(0.3f, 0.6f + (thor::random(0, 10) >= 9 ? 0.6f : 0.f)); impact->setPosition(position); impact->emit(1); auto bits = GameGlobals::get()->impactbits; bits->setColor(color); bits->setScale(0.02f, 0.1f); bits->setPosition(position); for(int i=0; i < 50; ++i) { float v = thor::random(0.f, 250.f); bits->setVelocityCone(v, m_angle + (thor::random(0, 2) == 0 ? -PI : 0.f), thor::random(0.f, 50.f)); bits->emit(1); } if(bulletStance == PlayerEntity::Stance::Offensive) { auto close = getComponent<sz::Physics>()->queryRadius(150.f); for(auto it = close.begin(); it != close.end(); ++it) { auto enemy = dynamic_cast<EnemyEntityBase*>(*it); if(!enemy || enemy == hit || enemy->isBoss()) continue; auto enemyPos = enemy->call(&sz::Transform::getPosition); float dist = sz::distance(position, enemyPos) / 22500.f; dist = std::min(1.f, dist); float falloff = (1.f - (dist * dist)) * 0.65f; float angle = sz::getAngle(position, enemyPos); enemy->applyDamage(DamageReport(m_shooter, m_damage * falloff, angle)); } } auto enemy = dynamic_cast<EnemyEntityBase*>(hit); if(enemy) { auto pos = enemy->getTransform->getPosition(); if(!enemy->isBoss()) { impact->setColor(sf::Color::White); impact->setScale(0.3f, 0.4f + (thor::random(0, 10) >= 9 ? 0.3f : 0.f)); } else { impact->setColor(color); impact->setScale(1.f, 1.4f + (thor::random(0, 10) >= 9 ? 0.4f : 0.f)); } impact->setPosition(pos + sf::Vector2f(thor::random(-30.f, 30.f), thor::random(-30.f, 30.f))); impact->emit(1); impact->setPosition(pos + sf::Vector2f(thor::random(-30.f, 30.f), thor::random(-30.f, 30.f))); impact->emit(1); } { auto boss = dynamic_cast<EnemyBossRed*>(hit); if(boss) { boss->increaseDmgMod(0.2f); } } return true; }