bool Player::meleeAttack(sf::Vector2i position) { for (int a = 0; a < (*npcs).size(); a++) { if ((*npcs)[a].getPosition() == position) { (*npcs)[a].takeDamage(calculateDamage(stats, (*npcs)[a].getStats())); return true; } } return false; }
//一列に並んだボールがあるかチェックする void GameLayer::checksLinedBalls() { //画面をタップ不可とする _touchable = false; if (existsLinedBalls()) { //3個以上並んだボールの存在する場合 //連鎖カウントアップ _chainNumber++; //ボールの削除と生成 removeAndGenerateBalls(); //アニメーション後に再チェック auto delay = DelayTime::create(ONE_ACTION_TIME * (_maxRemovedNo + 1)); auto func = CallFunc::create(CC_CALLBACK_0(GameLayer::checksLinedBalls, this)); auto seq = Sequence::create(delay, func, nullptr); runAction(seq); } else { int chainNum = 0; int damage = 0; int healing = 0; std::set<int> attackers; //ダメージ・回復量の計算 calculateDamage(chainNum, healing, damage, attackers); //敵にダメージを与える int afterHp = _enemyData->getHp() - damage; if (damage > 0) //アタック処理 attackToEnemy(damage, attackers); if (healing > 0) //回復処理 healMember(healing); //敵にダメージを与えた後の処理を設定 CallFunc* func; if (afterHp <= 0) func = CallFunc::create(CC_CALLBACK_0(GameLayer::winAnimation, this)); else func = CallFunc::create(CC_CALLBACK_0(GameLayer::attackFromEnemy, this)); runAction(Sequence::create(DelayTime::create(0.5), func, nullptr)); } }
//Initiates the attack action between the two Characters. //Pre: Both characters have been loaded. //Post: The initiator's attack is checked against the // receiver's defense. The attack that is leftover // after the defense is subtracted is then reduced // from the receiver's hitpoints. If the HP are reduced // to 0 or below, the Character will be dead. void ShieldBash::execute(){ if(initiator == NULL || receiver == NULL) return; //Determines the damage to the receiver. calculateDamage(); //Remove receiver's hitpoints. receiver->addToRemainingHP(-damageToReceiver); loadAnimations(); }
void BattleManager::applyDamage(Actor* caster, DamageAbility* damageAbility, Actor* target) { if (caster->getAbility(damageAbility->getName())->getCost() <= caster->getResource()) { int targetArmor; if (target->getAttribute(BONUS_ARMOR) == nullptr && target->getAttribute(BONUS_ARMOR) == nullptr) targetArmor = target->getAttribute(ARMOR)->getValue(); else{ targetArmor = target->getAttribute(ARMOR)->getValue(); } //full damage da ability tendo em conta as stats do player int abilityDamage = damageAbility->getFullDamage(caster); caster->changeResource(-(damageAbility->getCost())); target->takeDamage(calculateDamage(targetArmor, abilityDamage)); caster->update(); } }
void pkCU::evaluateMove_damage() { assert(getStackStage() == STAGE_MOVEBASE); assert(getTPKV().isAlive() && getPKV().isAlive()); // the floor of the stack: everything below this stack value has been evaluated size_t baseFloor = iBase, baseCeil = getStack().size(); const pokemon_nonvolatile& cPKNV = getPKNV(); const pokemon_nonvolatile& tPKNV = getTPKNV(); const move_nonvolatile& cMNV = cPKNV.getMove(getICAction()); const pokemon_base& cPKB = cPKNV.getBase(); const pokemon_base& tPKB = tPKNV.getBase(); const move& cMove = cMNV.getBase(); //Source: http://www.smogon.com/dp/articles/damage_formula /*BasePower = HH × BP × IT × CHG × (MS × WS) × UA × FA*/ // set basePower: //for (/*iBase = baseFloor, baseCeil = getStack().size()*/; iBase != baseCeil; ++iBase) { //if (getStackStage() != STAGE_MOVEBASE) { continue; } advanceStackStage(); uint32_t& basePower = getDamageComponent().damage; basePower = cMove.getPower(); int result = (basePower != UINT8_MAX)?1:0; CALLPLUGIN(result, PLUGIN_ON_SETBASEPOWER, onSetPower_rawType, *this, cMNV, cPKNV, tPKNV, getTMV(), getTTMV(), getPKV(), getTPKV(), basePower); assert(result > 0 && basePower > 0); } // calculate this move's type: for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_SETBASEPOWER) { continue; } advanceStackStage(); const type*& cType = getDamageComponent().mType; cType = &cMove.getType(); int result = 0; CALLPLUGIN(result, PLUGIN_ON_SETMOVETYPE, onModifyMoveType_rawType, *this, cMNV, cPKNV, tPKNV, getTMV(), getTTMV(), getPKV(), getTPKV(), cType); } // modify basePower: for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_SETMOVETYPE) { continue; } advanceStackStage(); uint32_t& basePower = getDamageComponent().damage; fpType baseModifier = 1.0; int result = 0; CALLPLUGIN(result, PLUGIN_ON_MODIFYBASEPOWER, onModifyPower_rawType, *this, cMNV, cPKNV, tPKNV, getTMV(), getTTMV(), getPKV(), getTPKV(), baseModifier); basePower = (uint32_t)(basePower * baseModifier); } // calculate attack and damage modifiers: uint32_t levelModifier = ((cPKNV.getLevel() * 2) / 5) + 2; for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_MODIFYBASEPOWER) { continue; } advanceStackStage(); damageComponents_t& cDamage = getDamageComponent(); size_t attackType; size_t defenseType; if (cMove.getDamageType() == ATK_PHYSICAL) { attackType = FV_ATTACK; defenseType = FV_DEFENSE; } else { attackType = FV_SPATTACK; defenseType = FV_SPDEFENSE; } uint32_t attackPower = getTMV().cGetFV_boosted(cPKNV, attackType); uint32_t attackPowerCrit = std::max(cPKNV.getFV_base(attackType), attackPower); uint32_t defensePower = getTTMV().cGetFV_boosted(tPKNV, defenseType); uint32_t defensePowerCrit = std::min(tPKNV.getFV_base(defenseType), defensePower); // calculate crit first: cDamage.damageCrit = ((levelModifier * cDamage.damage * attackPowerCrit) / 50) / defensePowerCrit; // and regular damage: cDamage.damage = ((levelModifier * cDamage.damage * attackPower) / 50) / defensePower; /* Mod1 = BRN × RL × TVT × SR × FF */ // modifier1: fpType attackPowerModifier = 1.0; int result = 0; CALLPLUGIN(result, PLUGIN_ON_MODIFYATTACKPOWER, onModifyPower_rawType, *this, cMNV, cPKNV, tPKNV, getTMV(), getTTMV(), getPKV(), getTPKV(), attackPowerModifier); // incorporate attack power modifier: cDamage.damage = (uint32_t)(cDamage.damage * attackPowerModifier) + 2; cDamage.damageCrit = (uint32_t)(cDamage.damageCrit * attackPowerModifier) + 2; } // calculate critical hit modifiers: for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_MODIFYATTACKPOWER) { continue; } advanceStackStage(); damageComponents_t& cDamage = getDamageComponent(); /* CH - Critical Hit modifier 3 if has sniper ability AND critical hit (mult 1.5) 2 if critical hit (mult 1.0) 1 else */ fpType criticalHitModifier = 2.0; int result = 0; CALLPLUGIN(result, PLUGIN_ON_MODIFYCRITICALPOWER, onModifyPower_rawType, *this, cMNV, cPKNV, tPKNV, getTMV(), getTTMV(), getPKV(), getTPKV(), criticalHitModifier); // incorporate critical power modifier: cDamage.damageCrit = (uint32_t)(cDamage.damageCrit * criticalHitModifier); } // calculate raw damage modifiers: for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_MODIFYCRITICALPOWER) { continue; } advanceStackStage(); damageComponents_t& cDamage = getDamageComponent(); /* Mod2 = Other modifier 1.3 if item = life orb 1+.1*n if item = metronome and used the same move n previous times, to a max of n=10 1.5 if attacking with Me First and attacks first (NOTE: SPECIAL BEHAVIOR with life orb / metronome!) 1 else */ fpType rawDamageMultiplier = 1.0; int result = 0; CALLPLUGIN(result, PLUGIN_ON_MODIFYRAWDAMAGE, onModifyPower_rawType, *this, cMNV, cPKNV, tPKNV, getTMV(), getTTMV(), getPKV(), getTPKV(), rawDamageMultiplier); // incorporate critical power modifier: cDamage.damage = (uint32_t)(cDamage.damage * rawDamageMultiplier); cDamage.damageCrit = (uint32_t)(cDamage.damageCrit * rawDamageMultiplier); } // calculate this move's STAB: for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_MODIFYRAWDAMAGE) { continue; } advanceStackStage(); damageComponents_t& cDamage = getDamageComponent(); bool hasStab = ((&cPKB.getType(0) == cDamage.mType) || (&cPKB.getType(1) == cDamage.mType)); fpType STABMultiplier = hasStab?1.5:1.0; int result = 0; CALLPLUGIN(result, PLUGIN_ON_MODIFYSTAB, onModifyPower_rawType, *this, cMNV, cPKNV, tPKNV, getTMV(), getTTMV(), getPKV(), getTPKV(), STABMultiplier); // incorporate STAB modifier: cDamage.damage = (uint32_t)(cDamage.damage * STABMultiplier); cDamage.damageCrit = (uint32_t)(cDamage.damageCrit * STABMultiplier); } // calculate the enemy pokemon's type resistance: for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_MODIFYSTAB) { continue; } advanceStackStage(); damageComponents_t& cDamage = getDamageComponent(); fpType typeModifier = 1.0; { // type1: typeModifier *= cDamage.mType->getModifier(tPKB.getType(0)); // type 2: typeModifier *= cDamage.mType->getModifier(tPKB.getType(1)); } int result = 0; CALLPLUGIN(result, PLUGIN_ON_SETDEFENSETYPE, onModifyTypePower_rawType, *this, cMNV, cPKNV, tPKNV, *cDamage.mType, getTMV(), getTTMV(), getPKV(), getTPKV(), typeModifier); // incorporate type modifier: cDamage.damage = (uint32_t)(cDamage.damage * typeModifier); cDamage.damageCrit = (uint32_t)(cDamage.damageCrit * typeModifier); } // calculate item resistance modifiers: for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_MODIFYTYPERESISTANCE) { continue; } advanceStackStage(); damageComponents_t& cDamage = getDamageComponent(); /* Mod3 = SRF × EB × TL × TRB */ fpType itemModifier = 1.0; int result = 0; CALLPLUGIN(result, PLUGIN_ON_MODIFYITEMPOWER, onModifyPower_rawType, *this, cMNV, cPKNV, tPKNV, getTMV(), getTTMV(), getPKV(), getTPKV(), itemModifier); // incorporate type modifier: cDamage.damage = (uint32_t)(cDamage.damage * itemModifier); cDamage.damageCrit = (uint32_t)(cDamage.damageCrit * itemModifier); } /* Damage Formula = (((((((Level × 2 ÷ 5) + 2) × BasePower × [Sp]Atk ÷ 50) ÷ [Sp]Def) × Mod1) + 2) × CH × Mod2 × R ÷ 100) × STAB × Type1 × Type2 × Mod3 */ // calculate probability to hit, miss: for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_MODIFYITEMPOWER) { continue; } advanceStackStage(); fpType& probabilityToHit = getDamageComponent().tProbability; /* probability to hit enemy pokemon */ probabilityToHit = getTMV().cGetAccuracy_boosted(FV_ACCURACY) // lowest is 33% or 1/3 * getTTMV().cGetAccuracy_boosted(FV_EVASION) // highest is 300% or 3 * cMove.getPrimaryAccuracy(); // lowest is 30% // to-hit modifying values: int result = 0; CALLPLUGIN(result, PLUGIN_ON_MODIFYHITPROBABILITY, onModifyPower_rawType, *this, cMNV, cPKNV, tPKNV, getTMV(), getTTMV(), getPKV(), getTPKV(), probabilityToHit); } // evaluate miss(1), hit(0): for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_MODIFYHITCHANCE) { continue; } advanceStackStage(); fpType& probabilityToHit = getDamageComponent().tProbability; // bound at MIN 0.033~ ... MAX 1.0 probabilityToHit = std::max(std::min(probabilityToHit, (fpType)1.0), (fpType)0.0); boost::array<size_t, 2> iHEnv = {{ getIBase(), SIZE_MAX }}; // did the move hit its target? Is it possible for the move to miss? if (mostlyGT(probabilityToHit, 0.0)) { // if there's a chance the primary effect will not occur: if (mostlyLT(probabilityToHit, 1.0)) { // duplicate the environment (duplicated environment is the miss environment): duplicateState(iHEnv, (1.0 - probabilityToHit)); } // modify bitmask as the hit effect occuring: getStack()[iHEnv[0]].setHit(getICTeam()); } // end of primary attack hits, and secondary attack is not assured else { // pass-through: no chance to hit or crit stackStage[iBase] = STAGE_POSTDAMAGE; } } // calculate probability to crit: for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_EVALUATEHITCHANCE) { continue; } advanceStackStage(); // don't continue to evaluate a stage that has not hit the enemy team: if (!getBase().hasHit(getICTeam())) { stackStage[iBase] = STAGE_POSTDAMAGE; continue; } fpType& probabilityToCrit = getDamageComponent().tProbability; /* Probability to critical hit, if the move has already hit */ probabilityToCrit = getTMV().cGetAccuracy_boosted(FV_CRITICALHIT); // to-crit modifying values: int result = 0; CALLPLUGIN(result, PLUGIN_ON_MODIFYCRITPROBABILITY, onModifyPower_rawType, *this, cMNV, cPKNV, tPKNV, getTMV(), getTTMV(), getPKV(), getTPKV(), probabilityToCrit); } // evaluate crit(2): for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_MODIFYCRITCHANCE) { continue; } advanceStackStage(); fpType& probabilityToCrit = getDamageComponent().tProbability; // determine the possibility that the move crit: boost::array<size_t, 2> iCEnv = {{ SIZE_MAX, getIBase() }}; if (mostlyGT(probabilityToCrit, 0.0) ) { if (mostlyLT(probabilityToCrit, 1.0)) { // duplicate the environment (duplicated environment is the crit environment): duplicateState(iCEnv, probabilityToCrit); } // modify bitmask as the crit effect occuring: getStack()[iCEnv[1]].setCrit(getICTeam()); } // even with no chance to crit there's still the possibility of damage } // perform actual damage calculation for (iBase = baseFloor, baseCeil = getStack().size(); iBase != baseCeil; ++iBase) { if (getStackStage() != STAGE_PREDAMAGE) { continue; } advanceStackStage(); if (!getBase().hasHit(getICTeam())) { continue; } calculateDamage(getBase().hasCrit(getICTeam())); } } // end of evaluateMove_damage