| 1120 | } |
| 1121 | |
| 1122 | void BattleUnit::applyPsiAttack(GameState &state, BattleUnit &attacker, PsiStatus status, |
| 1123 | StateRef<AEquipmentType> item, bool impact) |
| 1124 | { |
| 1125 | std::ignore = item; |
| 1126 | bool realTime = state.current_battle->mode == Battle::Mode::RealTime; |
| 1127 | if (impact) |
| 1128 | { |
| 1129 | sendAgentEvent(state, |
| 1130 | status == PsiStatus::Control ? GameEventType::AgentPsiControlled |
| 1131 | : GameEventType::AgentPsiAttacked, |
| 1132 | true); |
| 1133 | } |
| 1134 | bool finished = false; |
| 1135 | do |
| 1136 | { |
| 1137 | // In turn based, you attack over an over until you're done, and each attack costs extra |
| 1138 | if (!realTime && !impact && status != PsiStatus::Probe) |
| 1139 | { |
| 1140 | int cost = getPsiCost(status, true); |
| 1141 | if (attacker.agent->modified_stats.psi_energy < cost) |
| 1142 | { |
| 1143 | finished = true; |
| 1144 | continue; |
| 1145 | } |
| 1146 | attacker.agent->modified_stats.psi_energy -= cost; |
| 1147 | } |
| 1148 | // Actually apply attack |
| 1149 | switch (status) |
| 1150 | { |
| 1151 | case PsiStatus::Panic: |
| 1152 | if (!impact) |
| 1153 | { |
| 1154 | agent->modified_stats.loseMorale(realTime ? 8 : 4); |
| 1155 | if (agent->modified_stats.morale == 0) |
| 1156 | { |
| 1157 | std::set<UString> panickers; |
| 1158 | for (auto attacker : psiAttackers) |
| 1159 | { |
| 1160 | if (attacker.second == PsiStatus::Panic) |
| 1161 | { |
| 1162 | panickers.emplace(attacker.first); |
| 1163 | } |
| 1164 | } |
| 1165 | for (auto s : panickers) |
| 1166 | { |
| 1167 | StateRef<BattleUnit>(&state, s)->stopAttackPsi(state); |
| 1168 | } |
| 1169 | } |
| 1170 | } |
| 1171 | case PsiStatus::Stun: |
| 1172 | if (!impact) |
| 1173 | { |
| 1174 | applyDamageDirect(state, realTime ? 7 : 4, false, BodyPart::Body, 9001); |
| 1175 | } |
| 1176 | break; |
| 1177 | case PsiStatus::Control: |
| 1178 | if (impact) |
| 1179 | { |
no test coverage detected