string do_attack(monster_t& attacker, monster_t& defender) { int dmg = calc_damage(attacker, defender); int def_hp = attacker.max_hp * attacker.count; def_hp -= dmg; int killed = ceil(dmg / (float) defender.max_hp); defender.count = ceil(def_hp / (float) defender.max_hp); std::stringstream strm; strm << game_t::_get_monster_name(attacker.type) << "s do " << dmg << ". " << killed << " " << game_t::_get_monster_name(defender.type) << "s perish."; return strm.str(); }
void curr_attack() { // see if nv status allow for attack switch (CURR_POKEMON->nv.nvstatus) { case NON_S: case BRN_S: case PSN_S: case TXC_S: break; case FRZ_S: if (roll(.2)) { sprintf(msg, "%s thawed out!", CURR_PNAME); send(); CURR_POKEMON->nv.nvstatus = NON_S; break; } else { sprintf(msg, "%s is frozen solid!", CURR_PNAME); send(); return; } case PAR_S: if (roll(.25)) { sprintf(msg, "%s is fully paralyzed!", CURR_PNAME); send(); return; } else { break; } case SLP_S: if (CURR_POKEMON->nv.nv_arg > 0) { sprintf(msg, "%s is fast asleep!", CURR_PNAME); send(); CURR_POKEMON->nv.nv_arg--; return; } else { sprintf(msg, "%s woke up!", CURR_PNAME); send(); CURR_POKEMON->nv.nvstatus = NON_S; break; } case FNT_S: // should never happen default: return; } // see if v status allows for attack if (CURR_POKEMON->v.is_flinch) { sprintf(msg, "%s flinched!", CURR_PNAME); send(); CURR_POKEMON->v.is_flinch = false; return; } if (CURR_POKEMON->v.is_recharge) { sprintf(msg, "%s is recharging!", CURR_PNAME); send(); CURR_POKEMON->v.is_recharge = false; return; } if (CURR_POKEMON->v.is_confuse) { sprintf(msg, "%s is confused!", CURR_PNAME); send(); if (roll(.25)) { // this is not quite how it works in Pokemon sprintf(msg, "%s snapped out of confusion!", CURR_PNAME); send(); CURR_POKEMON->v.is_confuse = false; } else { if (roll(.5)) { sprintf(msg, "%s hurt itself in confusion!", CURR_PNAME); send(); int damage = calc_damage(CURR_POKEMON, CURR_POKEMON, 40, PHYSICAL_MT); // printf("[%s applied %i damage to himself]", CURR_PNAME, damage); apply_damage(CURR_POKEMON, damage); return; } } } move_s *move = curr_move(); sprintf(msg, "%s used %s!", CURR_PNAME, move->name); send(); // check if unique if (move->unique) { switch (move->unique) { default: // no unique moves at the moment return; } } // check accuracy if (is_aggressive(move)) { if (!roll(move->accuracy * calc_accuracy(CURR_POKEMON, OTHR_POKEMON))) { // swift support? sprintf(msg, "It missed!"); send(); return; } if (move->movetype != STATUS_MT) { int damage = calc_damage(CURR_POKEMON, OTHR_POKEMON, move->damage, move->movetype); double stab_bonus = (has_type(CURR_POKEMON, move->type) ? 1.5 : 1); // STAB bonus double effective_bonus = calc_effective(move->type, OTHR_POKEMON); // type bonus double crit_chance = (move->effect == HIGH_CRIT_E2 ? .125 : .0625); double crit_bonus = (roll(crit_chance) ? 1.5 : 1.0); // this is not quite how it works in Pokemon double rndm = (rand() % 16 + 85) / 100.0; // printf("%i, %lf, %lf, %lf, %lf", damage, stab_bonus, effective_bonus, crit_bonus, rndm); int total_damage = (int)(damage * stab_bonus * effective_bonus * crit_bonus * rndm); // if burnt, physical damage output is halfed if (CURR_POKEMON->nv.nvstatus == BRN_S && move->movetype == PHYSICAL_MT) { total_damage /= 2; } if (effective_bonus > 1) { sprintf(msg, "It's super effective!"); send(); } else if (effective_bonus == 0) { sprintf(msg, "It has no effect!"); send(); } else if (effective_bonus < 1) { sprintf(msg, "It's not very effective!"); send(); } if (crit_bonus > 1) { sprintf(msg, "Critical hit!"); send(); } // printf("[%s applies %i damage to %s]", CURR_PNAME, total_damage, OTHR_PNAME); apply_damage(OTHR_POKEMON, total_damage); } else { if (calc_effective(move->type, OTHR_POKEMON) == 0) { // thunder wave can't work on ground sprintf(msg, "It has no effect!"); send(); return; } } } int calculation; // can be used for some of the switch cases // check secondary effect if (move->effect != NON_E2) { if (roll(move->chance)) { switch (move->effect) { case APPLY_BRN_E2: apply_nvstatus(OTHR_POKEMON, BRN_S); break; case APPLY_FRZ_E2: apply_nvstatus(OTHR_POKEMON, FRZ_S); break; case APPLY_PAR_E2: apply_nvstatus(OTHR_POKEMON, PAR_S); break; case APPLY_PSN_E2: apply_nvstatus(OTHR_POKEMON, PSN_S); break; case APPLY_TXC_E2: apply_nvstatus(OTHR_POKEMON, TXC_S); break; case APPLY_SLP_E2: apply_nvstatus(OTHR_POKEMON, SLP_S); break; case APPLY_FLINCH_E2: OTHR_POKEMON->v.is_flinch = true; break; case APPLY_CONFUSE_E2: sprintf(msg, "%s became confused!", OTHR_PNAME); send(); OTHR_POKEMON->v.is_confuse = true; break; case HIGH_CRIT_E2: break; // this doesn't happen here case SELF_KILL_E2: apply_nvstatus(CURR_POKEMON, FNT_S); break; case SELF_ATTACK_E2: apply_attackstage(CURR_POKEMON, move->m_arg); break; case SELF_DEFENSE_E2: apply_defensestage(CURR_POKEMON, move->m_arg); break; case SELF_SATTACK_E2: apply_sattackstage(CURR_POKEMON, move->m_arg); break; case SELF_SDEFENSE_E2: apply_sdefensestage(CURR_POKEMON, move->m_arg); break; case SELF_SPEED_E2: apply_speedstage(CURR_POKEMON, move->m_arg); break; case SELF_ACCURACY_E2: apply_accuracystage(CURR_POKEMON, move->m_arg); break; case SELF_EVASION_E2: apply_evasionstage(CURR_POKEMON, move->m_arg); break; case OTHR_ATTACK_E2: apply_attackstage(OTHR_POKEMON, move->m_arg); break; case OTHR_DEFENSE_E2: apply_defensestage(OTHR_POKEMON, move->m_arg); break; case OTHR_SATTACK_E2: apply_sattackstage(OTHR_POKEMON, move->m_arg); break; case OTHR_SDEFENSE_E2: apply_sdefensestage(OTHR_POKEMON, move->m_arg); break; case OTHR_SPEED_E2: apply_speedstage(OTHR_POKEMON, move->m_arg); break; case OTHR_ACCURACY_E2: apply_accuracystage(OTHR_POKEMON, move->m_arg); break; case OTHR_EVASION_E2: apply_evasionstage(OTHR_POKEMON, move->m_arg); break; case SELF_ATTACK_SATTACK_E2: apply_attackstage(CURR_POKEMON, move->m_arg); apply_sattackstage(CURR_POKEMON, move->m_arg); break; case HAZE_E2: reset_stages(CURR_POKEMON); reset_stages(OTHR_POKEMON); break; case RECOIL_E2: calculation = battle.last_dmg / move->m_arg; // pos is recoil, neg is heal if (calculation > 0) { sprintf(msg, "%s was hit with recoil!", CURR_PNAME); send(); // printf("[%s took %i damage in recoil]", CURR_PNAME, calculation); } else if (calculation < 0) { sprintf(msg, "%s regained health!", CURR_PNAME); send(); // printf("[%s restored %i damage]", CURR_PNAME, calculation); } apply_damage(CURR_POKEMON, calculation); break; // this doesn't happen here case RECHARGE_E2: CURR_POKEMON->v.is_recharge = true; break; case NON_E2: // shouldn't happen break; } } } }