void ServantBerserkerFlail::subHP(int hp, DamageType dt) { bool noDamage = false; int r = getRandNum(); if (((ascension == 1 && r <= getLuk()) || (ascension == 2 && r <= getLuk() * 1.5)) && (dt == D_STR || dt == D_MAG)) { noDamage = true; log->addToEventLog(getFullName() + " deflected the attack and took no damage! Spin to Win!"); } if (!noDamage) { currHP -= hp; int mhp = getMaxHP(); if (currHP > mhp) currHP = mhp; else if (currHP <= 0) { currHP = 0; remAllDebuffs(false); } } }
vector<int> ServantAssassin::getEvade() { // Evasion = Speed * 2 + Luck // If presence concealment is active, add 25 to evade. int ev = getInitialEvade(); vector<int> evade; if (presenceConcealed()) evade.push_back(ev + 25); else evade.push_back(ev); // Clairvoyance: (LUK / 4) chance of taking no damage. evade.push_back(getLuk() / 4); return evade; }
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; }
void Player::save(){ char sql[10000]; sprintf_s(sql, 10000, "update keymap set "); for(int i=0; i<90; i++){ char temp[100]; if(i!=89) sprintf_s(temp, 100, "pos%d=%d, ", i, keys[i]); else sprintf_s(temp, 100, "pos%d=%d where charid=%d; ", i, keys[i], getPlayerid()); strcat_s(sql, 10000, temp); } MySQL::insert(sql); sprintf_s(sql, 10000, "update characters set level=%d, job=%d, str=%d, dex=%d, intt=%d, luk=%d, chp=%d, mhp=%d, cmp=%d, mmp=%d, ap=%d, sp=%d, exp=%d, fame=%d, map=%d, gender=%d, skin=%d, eyes=%d, hair=%d, mesos=%d where id=%d", getLevel(), getJob(), getStr(), getDex(), getInt(), getLuk(), getHP(), getRMHP(), getMP(), getRMMP(), getAp(), getSp(), getExp(), getFame(), getMap(), getGender(), getSkin(), getEyes(), getHair(), inv->getMesos() ,getPlayerid()); MySQL::insert(sql); char temp[1000]; sprintf_s(sql, 10000, "delete from equip where charid=%d;", getPlayerid()); MySQL::insert(sql); bool firstrun = true; for(int i=0; i<inv->getEquipNum(); i++){ if(firstrun == true){ sprintf_s(sql, 10000, "INSERT INTO equip VALUES (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", inv->getEquip(i)->id, Drops::equips[inv->getEquip(i)->id].type ,getPlayerid(), inv->getEquipPos(i), inv->getEquip(i)->slots, inv->getEquip(i)->scrolls, inv->getEquip(i)->istr, inv->getEquip(i)->idex, inv->getEquip(i)->iint, inv->getEquip(i)->iluk, inv->getEquip(i)->ihp, inv->getEquip(i)->imp, inv->getEquip(i)->iwatk, inv->getEquip(i)->imatk, inv->getEquip(i)->iwdef, inv->getEquip(i)->imdef, inv->getEquip(i)->iacc, inv->getEquip(i)->iavo, inv->getEquip(i)->ihand, inv->getEquip(i)->ijump, inv->getEquip(i)->ispeed); firstrun = false; } else{ sprintf_s(temp, 1000, ",(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", inv->getEquip(i)->id, Drops::equips[inv->getEquip(i)->id].type ,getPlayerid(), inv->getEquipPos(i), inv->getEquip(i)->slots, inv->getEquip(i)->scrolls, inv->getEquip(i)->istr, inv->getEquip(i)->idex, inv->getEquip(i)->iint, inv->getEquip(i)->iluk, inv->getEquip(i)->ihp, inv->getEquip(i)->imp, inv->getEquip(i)->iwatk, inv->getEquip(i)->imatk, inv->getEquip(i)->iwdef, inv->getEquip(i)->imdef, inv->getEquip(i)->iacc, inv->getEquip(i)->iavo, inv->getEquip(i)->ihand, inv->getEquip(i)->ijump, inv->getEquip(i)->ispeed); strcat_s(sql, 10000, temp); } } MySQL::insert(sql); sprintf_s(sql, 10000, "delete from skills where charid=%d;", getPlayerid()); MySQL::insert(sql); firstrun = true; for(int i=0; i<skills->getSkillsNum(); i++){ if(firstrun == true){ sprintf_s(sql, 10000, "INSERT INTO skills VALUES (%d, %d, %d)", getPlayerid(), skills->getSkillID(i), skills->getSkillLevel(skills->getSkillID(i))); firstrun = false; } else{ sprintf_s(temp, 1000, ",(%d, %d, %d)", getPlayerid(), skills->getSkillID(i), skills->getSkillLevel(skills->getSkillID(i))); strcat_s(sql, 10000, temp); } } MySQL::insert(sql); sprintf_s(sql, 10000, "DELETE FROM items WHERE charid=%d;", getPlayerid()); MySQL::insert(sql); firstrun = true; for(int i=0; i<inv->getItemNum(); i++){ if(firstrun == true){ sprintf_s(sql, 10000, "INSERT INTO items VALUES (%d, %d, %d, %d, %d)", inv->getItem(i)->id, getPlayerid() ,inv->getItem(i)->inv, inv->getItem(i)->pos, inv->getItem(i)->amount); firstrun = false; } else{ sprintf_s(temp, 1000, ",(%d, %d, %d, %d, %d)", inv->getItem(i)->id, getPlayerid() ,inv->getItem(i)->inv, inv->getItem(i)->pos, inv->getItem(i)->amount); strcat_s(sql, 10000, temp); } } MySQL::insert(sql); }
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; }