/***** Active Skills *****/ int ServantAssassin::poisonStrike(vector<Servant *> defenders) { if (actionMPCosts[ascension][1] > currMP) return 1; // Not enough MP to attack else { subMP(actionMPCosts[ascension][1]); for (unsigned int i = 0; i < defenders.size(); i++) { log->addToEventLog(getFullName() + " used Poison Strike against " + defenders[i]->getFullName() + "!"); // Check if you hit the targets vector<int> opEvade = defenders[i]->getEvade(); bool hit = false; // Calculate accuracy int accuracy = capZero(getHitRate() - opEvade[0]); int r = getRandNum(); if (accuracy >= r) hit = true; // Skill: Presence Detection skips all other evasion checks! // If you hit, apply the poison debuff if (hit) { vector<Stat> dStats; dStats.push_back(HP); vector<int> dAmount; dAmount.push_back(-1 * (defenders[i]->getMaxHP() / 20)); Debuff *poison = new Debuff("Poison", "Poison does damage over time.", defenders[i]->getTeam(), dStats, dAmount, 5); defenders[i]->addDebuff(poison); log->addToEventLog(getFullName() + " poisoned " + defenders[i]->getFullName() + "!"); } else { log->addToEventLog(getFullName() + " missed " + defenders[i]->getFullName() + "!"); } // Poison strike does no damage and thus there is no need to check // if the defender is dead. } } return 0; }
int ServantBerserkerClub::attack(vector<Servant *> defenders, bool counter) { if (actionMPCosts[ascension][0] > currMP) return 1; // Not enough MP to attack else { subMP(actionMPCosts[ascension][0]); for (unsigned int i = 0; i < defenders.size(); i++) { // Add the target to the list of previous targets (if they are not // already on it) if (!previouslyTargeted(defenders[i])) previousTargets.push_back(defenders[i]); int dam = 0; // Check if you hit the targets vector<int> opEvade = defenders[i]->getEvade(); bool hit = false; // Calculate accuracy int accuracy = capZero(getHitRate() - opEvade[0]); int r = getRandNum(); if (accuracy >= r) hit = true; if (opEvade.size() > 1 && hit) { for (unsigned int j = 1; j < opEvade.size() && hit; j++) { r = getRandNum(); if (opEvade[j] >= r) hit = false; } } // If you hit, calculate crit chance if (hit) { int attackMult = 1; int critChance = capZero(getCriticalRate() - defenders[i]->getCriticalEvade()); r = getRandNum(); if (critChance >= r) attackMult *= 3; // If you're at the Final Ascension and have already faced this // target, deal thrice as much damage and decrease DEF by 10 // (Barbarian's Wrath) if(ascension == 2 && previouslyTargeted(defenders[i])) { attackMult *= 3; vector<Stat> tS; tS.push_back(DEF); vector<int> tA; tA.push_back(-10); Debuff* bw = new Debuff("Barbarian's Wrath", "You tried to fight a Club Berserker twice, and paid the price.", defenders[i]->getTeam(), tS, tA, -1); defenders[i]->addDebuff(bw); log->addToEventLog(defenders[i]->getFullName() + " felt " + getFullName() + "'s Wrath!"); } // Deal the damage dam = capZero(getStr() - defenders[i]->getDef()) * attackMult; log->addToEventLog(getFullName() + " dealt " + to_string(dam) + " damage to " + defenders[i]->getFullName() + "."); defenders[i]->subHP(dam, D_STR); // Apply the Crushing Blow debuff vector<Stat> tStats; tStats.push_back(DEF); vector<int> tAmounts; tAmounts.push_back(-2); Debuff* bOut = new Debuff("Crushing Blow", "You took a blow from a Club Berserker, permanetly denting your armor.", defenders[i]->getTeam(), tStats, tAmounts, -1); defenders[i]->addDebuff(bOut); // Check to see if Barbarian's Might activates r = getRandNum(); if (r <= getLuk() * 2) { vector<Stat> tS; tS.push_back(DEF); vector<int> tA; tA.push_back(-5); Debuff* bm = new Debuff("Barbarian's Might", "You took an incredible blow from a Club Berserker, permanetly denting your armor.", defenders[i]->getTeam(), tS, tA, -1); defenders[i]->addDebuff(bm); log->addToEventLog(defenders[i]->getFullName() + " felt " + getFullName() + "'s Might!"); } } else { log->addToEventLog(getFullName() + " missed " + defenders[i]->getFullName() + "!"); } // Check to see if the defender is dead. If they are, do not call // the counterattack. Additionally, if they are an Avenger and they // die, activate Final Revenge. // If they are not dead but they are a Berserker, check to see if // Mad Counter activates. if(defenders[i]->getCurrHP() > 0) { // Check if the defender is a Berserker. If they are, and they // are adjacent to this unit, check to see if Mad Counter // activates. if (defenders[i]->getClass() == Berserker && isAdjacent(defenders[i])) { r = getRandNum(); if (defenders[i]->getLuk() >= r) { // Mad Counter activated! The attacking servant takes // damage equal to the damage they dealt. log->addToEventLog(defenders[i]->getFullName() + "'s Mad Counter activated, dealing " + to_string(dam) + " damage back to " + getFullName() + "."); subHP(dam, C_STR); } } // Call "attack" on the defending servant for their // counterattack, if you are in their range and you are the // initiating servant. if (defenders[i]->isInRange(this) && counter) { vector<Servant *> you; you.push_back(this); defenders[i]->attack(you, false); } } else { if (defenders[i]->getClass() == Avenger) { // Activate Final Revenge Debuff *finRev = defenders[i]->finalRevenge(); addDebuff(finRev); if (defenders[i]->getAscensionLvl() == 2) { subHP(.1 * getMaxHP(), OMNI); subMP(.1 * getMaxMP()); if (getCurrHP() == 0) { setHP(1); } } } } } } return 0; }
// Re-define attack to account for the Vengeance skill int ServantAvenger::attack(vector<Servant *> defenders, bool counter) { if (actionMPCosts[ascension][0] > currMP) return 1; // Not enough MP to attack else { subMP(actionMPCosts[ascension][0]); for (unsigned int i = 0; i < defenders.size(); i++) { int dam = 0; // Check if you hit the targets vector<int> opEvade = defenders[i]->getEvade(); bool hit = false; // Calculate accuracy int accuracy = capZero(getHitRate() - opEvade[0]); int r = getRandNum(); if (accuracy >= r) hit = true; if (opEvade.size() > 1 && hit) { for (unsigned int j = 1; j < opEvade.size() && hit; j++) { r = getRandNum(); if (opEvade[j] >= r) hit = false; } } // If you hit, calculate crit chance // Also check if Skill: Vengeance activates if (hit) { int attackMult = 1; int critChance = capZero(getCriticalRate() - defenders[i]->getCriticalEvade()); r = getRandNum(); if (critChance >= r) attackMult *= 3; // Check for Vengeance int addVengeance = 0; r = getRandNum(); if (getSkl() * 2 >= r) { addVengeance = (getMaxHP() - getCurrHP()) * 2; log->addToEventLog(getFullName() + " activated Vengeance!"); } // Deal the damage dam = (capZero(getStr() - defenders[i]->getDef()) + addVengeance) * attackMult; log->addToEventLog(getFullName() + " dealt " + to_string(dam) + " damage to " + defenders[i]->getFullName() + "."); defenders[i]->subHP(dam, D_STR); } else { log->addToEventLog(getFullName() + " missed " + defenders[i]->getFullName() + "!"); } // Check to see if the defender is dead. If they are, do not call // the counterattack. Additionally, if they are an Avenger and they // die, activate Final Revenge. // If they are not dead but they are a Berserker, check to see if // Mad Counter activates. if(defenders[i]->getCurrHP() > 0) { // Check if the defender is a Berserker. If they are, and they // are adjacent to this unit, check to see if Mad Counter // activates. if (defenders[i]->getClass() == Berserker && isAdjacent(defenders[i])) { r = getRandNum(); if (defenders[i]->getLuk() >= r) { // Mad Counter activated! The attacking servant takes // damage equal to the damage they dealt. log->addToEventLog(defenders[i]->getFullName() + "' Mad Counter activated, dealing " + to_string(dam) + " damage back to " + getFullName() + "."); subHP(dam, C_STR); } } // Call "attack" on the defending servant for their // counterattack, if you are in their range and you are the // initiating servant. if (defenders[i]->isInRange(this) && counter) { vector<Servant *> you; you.push_back(this); defenders[i]->attack(you, false); } } else { if (defenders[i]->getClass() == Avenger) { // Activate Final Revenge Debuff *finRev = defenders[i]->finalRevenge(); addDebuff(finRev); if (defenders[i]->getAscensionLvl() == 2) { subHP(.1 * getMaxHP(), OMNI); subMP(.1 * getMaxMP()); if (getCurrHP() == 0) { setHP(1); } } } } } } return 0; }
BlockInputStreams StorageSystemDictionaries::read( const Names & column_names, const ASTPtr & query, const Context & context, QueryProcessingStage::Enum & processed_stage, const size_t max_block_size, const unsigned) { check(column_names); processed_stage = QueryProcessingStage::FetchColumns; ColumnWithTypeAndName col_name{std::make_shared<ColumnString>(), std::make_shared<DataTypeString>(), "name"}; ColumnWithTypeAndName col_origin{std::make_shared<ColumnString>(), std::make_shared<DataTypeString>(), "origin"}; ColumnWithTypeAndName col_type{std::make_shared<ColumnString>(), std::make_shared<DataTypeString>(), "type"}; ColumnWithTypeAndName col_key{std::make_shared<ColumnString>(), std::make_shared<DataTypeString>(), "key"}; ColumnWithTypeAndName col_attribute_names{ std::make_shared<ColumnArray>(std::make_shared<ColumnString>()), std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>()), "attribute.names" }; ColumnWithTypeAndName col_attribute_types{ std::make_shared<ColumnArray>(std::make_shared<ColumnString>()), std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>()), "attribute.types" }; ColumnWithTypeAndName col_has_hierarchy{std::make_shared<ColumnUInt8>(), std::make_shared<DataTypeUInt8>(), "has_hierarchy"}; ColumnWithTypeAndName col_bytes_allocated{std::make_shared<ColumnUInt64>(), std::make_shared<DataTypeUInt64>(), "bytes_allocated"}; ColumnWithTypeAndName col_query_count{std::make_shared<ColumnUInt64>(), std::make_shared<DataTypeUInt64>(), "query_count"}; ColumnWithTypeAndName col_hit_rate{std::make_shared<ColumnFloat64>(), std::make_shared<DataTypeFloat64>(), "hit_rate"}; ColumnWithTypeAndName col_element_count{std::make_shared<ColumnUInt64>(), std::make_shared<DataTypeUInt64>(), "element_count"}; ColumnWithTypeAndName col_load_factor{std::make_shared<ColumnFloat64>(), std::make_shared<DataTypeFloat64>(), "load_factor"}; ColumnWithTypeAndName col_creation_time{std::make_shared<ColumnUInt32>(), std::make_shared<DataTypeDateTime>(), "creation_time"}; ColumnWithTypeAndName col_last_exception{std::make_shared<ColumnString>(), std::make_shared<DataTypeString>(), "last_exception"}; ColumnWithTypeAndName col_source{std::make_shared<ColumnString>(), std::make_shared<DataTypeString>(), "source"}; const auto & external_dictionaries = context.getExternalDictionaries(); const std::lock_guard<std::mutex> lock{external_dictionaries.dictionaries_mutex}; for (const auto & dict_info : external_dictionaries.dictionaries) { col_name.column->insert(dict_info.first); col_origin.column->insert(dict_info.second.origin); if (dict_info.second.dict) { const auto dict_ptr = dict_info.second.dict->get(); col_type.column->insert(dict_ptr->getTypeName()); const auto & dict_struct = dict_ptr->getStructure(); col_key.column->insert(dict_struct.getKeyDescription()); col_attribute_names.column->insert(ext::map<Array>(dict_struct.attributes, [] (auto & attr) -> decltype(auto) { return attr.name; })); col_attribute_types.column->insert(ext::map<Array>(dict_struct.attributes, [] (auto & attr) -> decltype(auto) { return attr.type->getName(); })); col_bytes_allocated.column->insert(dict_ptr->getBytesAllocated()); col_query_count.column->insert(dict_ptr->getQueryCount()); col_hit_rate.column->insert(dict_ptr->getHitRate()); col_element_count.column->insert(dict_ptr->getElementCount()); col_load_factor.column->insert(dict_ptr->getLoadFactor()); col_creation_time.column->insert(std::chrono::system_clock::to_time_t(dict_ptr->getCreationTime())); col_source.column->insert(dict_ptr->getSource()->toString()); } else { col_type.column->insertDefault(); col_key.column->insertDefault(); col_attribute_names.column->insertDefault(); col_attribute_types.column->insertDefault(); col_bytes_allocated.column->insertDefault(); col_query_count.column->insertDefault(); col_hit_rate.column->insertDefault(); col_element_count.column->insertDefault(); col_load_factor.column->insertDefault(); col_creation_time.column->insertDefault(); col_source.column->insertDefault(); } if (dict_info.second.exception) { try { std::rethrow_exception(dict_info.second.exception); } catch (...) { col_last_exception.column->insert(getCurrentExceptionMessage(false)); } } else col_last_exception.column->insertDefault(); } Block block{ col_name, col_origin, col_type, col_key, col_attribute_names, col_attribute_types, col_bytes_allocated, col_query_count, col_hit_rate, col_element_count, col_load_factor, col_creation_time, col_last_exception, col_source }; return BlockInputStreams{1, std::make_shared<OneBlockInputStream>(block)}; }
int ServantBerserkerFlail::attack(vector<Servant *> defenders, bool counter) { if (actionMPCosts[ascension][0] > currMP) return 1; // Not enough MP to attack else { subMP(actionMPCosts[ascension][0]); bool npActive = false; // Check if Lashing Out activates // "Hitting all adjacent opponents" only applies to the first two // ascension levels, as Maelstrom of Death trumps Lashing Out int r = getRandNum(); // Cratered Debuff vector<Stat> tS; tS.push_back(SPD); tS.push_back(DEF); vector<int> tA; tA.push_back(-5); tA.push_back(2); // Get the Team of the opposing team /*Team otherTeam = All; vector<vector<Servant*>> pField = field->getServantLocations(); for (unsigned int i = 0; i < pField.size(); i++) { for(unsigned int j = 0; j < pField[i].size(); j++) { if(pField[i][j] != NULL && pField[i][j]->getTeam() != getTeam()) { otherTeam = pField[i][j]->getTeam(); } } }*/ Debuff* br = new Debuff("Cratered", "The ground has been cratered.", All, tS, tA, -1); vector<Coordinate> crateredRange; if (ascension <= 1 && r < getLuk()) { // Add all adjacent servants to the defenders vector (as long as // they aren't already in it) vector<Servant*> adj = field->getAllInRange(this, getLowToHighRange(1,1)); for (unsigned int i = 0; i < adj.size(); i++) { bool isIn = false; for (unsigned int j = 0; j < defenders.size() && !isIn; j++) { if (adj[i] == defenders[j]) isIn = true; } if (!isIn) defenders.push_back(adj[i]); } crateredRange = getAbsoluteRange(1,1,this); } else if (ascension == 2 && r < getLuk() * 1.5) { crateredRange = getAbsoluteRange(1,2,this); } // Apply the cratered debuff to the appropriate spaces field->addDebuffToRange(br, crateredRange); for (unsigned int i = 0; i < defenders.size(); i++) { int dam = 0; // Check if you hit the targets vector<int> opEvade = defenders[i]->getEvade(); bool hit = false; // Calculate accuracy int accuracy = capZero(getHitRate() - opEvade[0]); r = getRandNum(); if (accuracy >= r) hit = true; // Maelstrom of Death doubles accuracy and prevents other evasion // skills from activating if (ascension == 2) accuracy *= 2; if (opEvade.size() > 1 && hit && ascension <= 1) { for (unsigned int j = 1; j < opEvade.size() && hit; j++) { r = getRandNum(); if (opEvade[j] >= r) hit = false; } } // If you hit, calculate crit chance if (hit) { int attackMult = 1; int critChance = capZero(getCriticalRate() - defenders[i]->getCriticalEvade()); // Spin To Win triples crit chance if (ascension >= 1) critChance *= 3; // Maelstrom of Death also doubles crit chance if (ascension == 2) critChance *= 2; r = getRandNum(); if (critChance >= r) attackMult *= 3; // Deal the damage dam = capZero(getStr() - defenders[i]->getDef()) * attackMult; log->addToEventLog(getFullName() + " dealt " + to_string(dam) + " damage to " + defenders[i]->getFullName() + "."); defenders[i]->subHP(dam, D_STR); } else { log->addToEventLog(getFullName() + " missed " + defenders[i]->getFullName() + "!"); } // Check to see if the defender is dead. If they are, do not call // the counterattack. Additionally, if they are an Avenger and they // die, activate Final Revenge. // If they are not dead but they are a Berserker, check to see if // Mad Counter activates. if(defenders[i]->getCurrHP() > 0) { // Check if the defender is a Berserker. If they are, and they // are adjacent to this unit, check to see if Mad Counter // activates. if (defenders[i]->getClass() == Berserker && isAdjacent(defenders[i])) { r = getRandNum(); if (defenders[i]->getLuk() >= r) { // Mad Counter activated! The attacking servant takes // damage equal to the damage they dealt. log->addToEventLog(defenders[i]->getFullName() + "'s Mad Counter activated, dealing " + to_string(dam) + " damage back to " + getFullName() + "."); subHP(dam, C_STR); } } // Call "attack" on the defending servant for their // counterattack, if you are in their range and you are the // initiating servant. // However if the servant is at their final ascension, or if // Lashing out activates, targets cannot counter if (!npActive && counter && defenders[i]->isInRange(this)) { vector<Servant *> you; you.push_back(this); defenders[i]->attack(you, false); } } else { if (defenders[i]->getClass() == Avenger) { // Activate Final Revenge Debuff *finRev = defenders[i]->finalRevenge(); addDebuff(finRev); if (defenders[i]->getAscensionLvl() == 2) { subHP(.1 * getMaxHP(), OMNI); subMP(.1 * getMaxMP()); if (getCurrHP() == 0) { setHP(1); } } } } } } return 0; }
/***** Function re-definitions *****/ int ServantAssassin::attack(vector<Servant *> defenders, bool counter) { if (actionMPCosts[ascension][0] > currMP) return 1; // Not enough MP to attack else { subMP(actionMPCosts[ascension][0]); for (unsigned int i = 0; i < defenders.size(); i++) { int dam = 0; // Check if you hit the targets vector<int> opEvade = defenders[i]->getEvade(); bool hit = false; // Calculate accuracy int accuracy = capZero(getHitRate() - opEvade[0]); int r = getRandNum(); if (accuracy >= r) hit = true; // Skill: Presence Detection skips all other evasion checks! // If you hit, calculate crit chance if (hit) { int attackMult = 1; int critChance = capZero(getCriticalRate() - defenders[i]->getCriticalEvade()); r = getRandNum(); if (critChance >= r) attackMult *= 3; // Calculate the chance of Lethality r = getRandNum(); if (getSkl() / 8 > r) { dam = defenders[i]->getMaxHP() * attackMult; log->addToEventLog(getFullName() + " activated Lethality against " + defenders[i]->getFullName() + "!" + to_string(dam) + " damage dealt!"); defenders[i]->subHP(dam, D_STR); } else { // Deal the damage dam = capZero(getStr() - defenders[i]->getDef()) * attackMult; log->addToEventLog(getFullName() + " dealt " + to_string(dam) + " damage to " + defenders[i]->getFullName() + "."); defenders[i]->subHP(dam, D_STR); } // Add the weapon-specific debuff to the target Debuff *deb = new Debuff(classDebuff->getDebuffName(), classDebuff->getDebuffDescrip(), defenders[i]->getTeam(), classDebuff->getDebuffStats(), classDebuff->getDebuffAmounts(), classDebuff->getTurnsRemaining()); defenders[i]->addDebuff(deb); } else { log->addToEventLog(getFullName() + " missed " + defenders[i]->getFullName() + "!"); } // Check to see if the defender is dead. If they are, do not call // the counterattack. Additionally, if they are an Avenger and they // die, activate Final Revenge. // If they are not dead but they are a Berserker, check to see if // Mad Counter activates. if(defenders[i]->getCurrHP() > 0) { // Check if the defender is a Berserker. If they are, and they // are adjacent to this unit, check to see if Mad Counter // activates. if (defenders[i]->getClass() == Berserker && isAdjacent(defenders[i])) { r = getRandNum(); if (defenders[i]->getLuk() >= r) { // Mad Counter activated! The attacking servant takes // damage equal to the damage they dealt. log->addToEventLog(defenders[i]->getFullName() + "' Mad Counter activated, dealing " + to_string(dam) + " damage back to " + getFullName() + "."); subHP(dam, C_STR); } } // Call "attack" on the defending servant for their // counterattack, if you are in their range and you are the // initiating servant. if (defenders[i]->isInRange(this) && counter) { vector<Servant *> you; you.push_back(this); defenders[i]->attack(you, false); } } else { if (defenders[i]->getClass() == Avenger) { // Activate Final Revenge Debuff *finRev = defenders[i]->finalRevenge(); addDebuff(finRev); if (defenders[i]->getAscensionLvl() == 2) { subHP(.1 * getMaxHP(), OMNI); subMP(.1 * getMaxMP()); if (getCurrHP() == 0) { setHP(1); } } } } } } return 0; }