| 1131 | } |
| 1132 | |
| 1133 | static void manageUnitAttackEvent(color_ostream& out) { |
| 1134 | if (!df::global::world) |
| 1135 | return; |
| 1136 | multimap<Plugin*,EventHandler> copy(handlers[EventType::UNIT_ATTACK].begin(), handlers[EventType::UNIT_ATTACK].end()); |
| 1137 | std::vector<df::report*>& reports = df::global::world->status.reports; |
| 1138 | size_t idx = df::report::binsearch_index(reports, lastReportUnitAttack, false); |
| 1139 | // returns the index to the key equal to or greater than the key provided |
| 1140 | idx = reports[idx]->id == lastReportUnitAttack ? idx + 1 : idx; // we need the index after (where the new stuff is) |
| 1141 | |
| 1142 | std::set<int32_t> strikeReports; |
| 1143 | for ( ; idx < reports.size(); idx++ ) { |
| 1144 | df::report* report = reports[idx]; |
| 1145 | lastReportUnitAttack = report->id; |
| 1146 | if ( report->flags.bits.continuation ) |
| 1147 | continue; |
| 1148 | df::announcement_type type = report->type; |
| 1149 | if ( type == df::announcement_type::COMBAT_STRIKE_DETAILS ) { |
| 1150 | strikeReports.insert(report->id); |
| 1151 | } |
| 1152 | } |
| 1153 | |
| 1154 | if ( strikeReports.empty() ) |
| 1155 | return; |
| 1156 | updateReportToRelevantUnits(); |
| 1157 | unordered_set<std::pair<int32_t, int32_t>, hash_pair> already_done; |
| 1158 | for (int reportId : strikeReports) { |
| 1159 | df::report* report = df::report::find(reportId); |
| 1160 | if ( !report ) |
| 1161 | continue; //TODO: error |
| 1162 | std::string reportStr = report->text; |
| 1163 | for ( int32_t b = reportId+1; ; b++ ) { |
| 1164 | df::report* report2 = df::report::find(b); |
| 1165 | if ( !report2 ) |
| 1166 | break; |
| 1167 | if ( report2->type != df::announcement_type::COMBAT_STRIKE_DETAILS ) |
| 1168 | break; |
| 1169 | if ( !report2->flags.bits.continuation ) |
| 1170 | break; |
| 1171 | reportStr += report2->text; |
| 1172 | } |
| 1173 | |
| 1174 | std::vector<int32_t>& relevantUnits = reportToRelevantUnits[report->id]; |
| 1175 | if ( relevantUnits.size() != 2 ) { |
| 1176 | continue; |
| 1177 | } |
| 1178 | |
| 1179 | df::unit* unit1 = df::unit::find(relevantUnits[0]); |
| 1180 | df::unit* unit2 = df::unit::find(relevantUnits[1]); |
| 1181 | |
| 1182 | df::unit_wound* wound1 = getWound(unit1,unit2); |
| 1183 | df::unit_wound* wound2 = getWound(unit2,unit1); |
| 1184 | |
| 1185 | UnitAttackData data{}; |
| 1186 | data.report_id = report->id; |
| 1187 | if ( wound1 && already_done.find(std::make_pair(unit1->id,unit2->id)) == already_done.end() ) { |
| 1188 | data.attacker = unit1->id; |
| 1189 | data.defender = unit2->id; |
| 1190 | data.wound = wound1->id; |
nothing calls this directly
no test coverage detected