Skip to content

Commit ed80778

Browse files
committed
Optimize of radsite
1 parent 4f27ca0 commit ed80778

File tree

2 files changed

+78
-23
lines changed

2 files changed

+78
-23
lines changed

src/Ext/Bullet/Body.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ void BulletExt::ExtData::ApplyRadiationToCell(CellStruct cell, int spread, int r
113113
{
114114
const auto pRadExt = RadSiteExt::ExtMap.Find(pSite);
115115

116-
if (pRadExt->Type != pRadType || pWeapon != pRadExt->Weapon)
116+
if (pRadExt->Type != pRadType || spread != pSite->Spread)
117117
return false;
118118

119119
if (pRadExt->RadInvoker && pThis->Owner)

src/Ext/RadSite/Hooks.cpp

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,12 @@ DEFINE_HOOK(0x43FB23, BuildingClass_AI_Radiation, 0x5)
121121
if (pBuilding->Type->ImmuneToRadiation || pBuilding->InLimbo || pBuilding->BeingWarpedOut || pBuilding->TemporalTargetingMe)
122122
return 0;
123123

124-
int radDelay = RulesExt::Global()->RadApplicationDelay_Building;
125-
126-
if (RulesExt::Global()->UseGlobalRadApplicationDelay &&
127-
(radDelay == 0 || Unsorted::CurrentFrame % radDelay != 0))
124+
if (RulesExt::Global()->UseGlobalRadApplicationDelay)
128125
{
129-
return 0;
126+
const int delay = RulesExt::Global()->RadApplicationDelay_Building;
127+
128+
if (delay == 0 || Unsorted::CurrentFrame % delay)
129+
return 0;
130130
}
131131

132132
const auto buildingCoords = pBuilding->GetMapCoords();
@@ -141,39 +141,65 @@ DEFINE_HOOK(0x43FB23, BuildingClass_AI_Radiation, 0x5)
141141
continue;
142142

143143
const auto pCellExt = CellExt::ExtMap.Find(pCell);
144+
std::vector<std::pair<RadTypeClass*, std::vector<std::pair<RadSiteClass*, int>>>> typeMap;
145+
typeMap.reserve(RadTypeClass::Array.size());
144146

145147
for (const auto& [pRadSite, radLevel] : pCellExt->RadLevels)
146148
{
147149
if (radLevel <= 0)
148150
continue;
149151

150152
const auto pRadExt = RadSiteExt::ExtMap.Find(pRadSite);
151-
RadTypeClass* pType = pRadExt->Type;
152-
int maxDamageCount = pType->GetBuildingDamageMaxCount();
153+
const auto pRadType = pRadExt->Type;
154+
int maxDamageCount = pRadType->GetBuildingDamageMaxCount();
153155

154156
if (maxDamageCount > 0 && damageCounts[pRadSite] >= maxDamageCount)
155157
continue;
156158

157-
if (!pType->GetWarhead())
159+
if (!pRadType->GetWarhead())
158160
continue;
159161

160162
if (!RulesExt::Global()->UseGlobalRadApplicationDelay)
161163
{
162-
int delay = pType->GetBuildingApplicationDelay();
164+
const int delay = pRadType->GetBuildingApplicationDelay();
163165

164-
if ((delay == 0) || (Unsorted::CurrentFrame % delay != 0))
166+
if (delay == 0 || Unsorted::CurrentFrame % delay)
165167
continue;
166168
}
167169

168-
if (pBuilding->IsAlive) // simple fix for previous issues
170+
const auto it = std::ranges::find_if(typeMap, [pRadType](std::pair<RadTypeClass*, std::vector<std::pair<RadSiteClass*, int>>> const& item) { return item.first == pRadType; });
171+
172+
if (it != typeMap.cend())
173+
{
174+
it->second.emplace_back(pRadSite, radLevel);
175+
}
176+
else
177+
{
178+
std::vector<std::pair<RadSiteClass*, int>> sites { std::make_pair(pRadSite, radLevel) };
179+
typeMap.emplace_back(pRadType, std::move(sites));
180+
}
181+
}
182+
183+
for (auto& [_, sites] : typeMap)
184+
std::ranges::stable_sort(sites, [](std::pair<RadSiteClass*, int> const& left, std::pair<RadSiteClass*, int> const& right) { return left.second > right.second; });
185+
186+
for (const auto& [pRadType, sites] : typeMap)
187+
{
188+
const int radLevelMax = pRadType->GetLevelMax();
189+
int radLevelSum = 0;
190+
191+
for (const auto& [pRadSite, radLevel] : sites)
169192
{
170-
int damage = Game::F2I(radLevel * pType->GetLevelFactor());
193+
const int remain = radLevelMax - radLevelSum;
194+
int damage = static_cast<int>(std::min(radLevel, remain) * pRadType->GetLevelFactor());
171195

172-
if (maxDamageCount > 0)
173-
damageCounts[pRadSite]++;
196+
if (pBuilding->IsAlive && !RadSiteExt::ExtMap.Find(pRadSite)->ApplyRadiationDamage(pBuilding, damage))
197+
return 0;
174198

175-
if (!pRadExt->ApplyRadiationDamage(pBuilding, damage))
199+
if (radLevel >= remain)
176200
break;
201+
202+
radLevelSum += radLevel;
177203
}
178204
}
179205
}
@@ -196,32 +222,61 @@ DEFINE_HOOK(0x4DA59F, FootClass_AI_Radiation, 0x5)
196222
{
197223
const auto pCell = pFoot->GetCell();
198224
const auto pCellExt = CellExt::ExtMap.Find(pCell);
225+
std::vector<std::pair<RadTypeClass*, std::vector<std::pair<RadSiteClass*, int>>>> typeMap;
226+
typeMap.reserve(RadTypeClass::Array.size());
199227

200228
for (const auto& [pRadSite, radLevel] : pCellExt->RadLevels)
201229
{
202230
if (radLevel <= 0)
203231
continue;
204232

205233
const auto pRadExt = RadSiteExt::ExtMap.Find(pRadSite);
206-
RadTypeClass* pType = pRadExt->Type;
234+
const auto pRadType = pRadExt->Type;
207235

208-
if (!pType->GetWarhead())
236+
if (!pRadType->GetWarhead())
209237
continue;
210238

211239
if (!RulesExt::Global()->UseGlobalRadApplicationDelay)
212240
{
213-
int delay = pType->GetApplicationDelay();
241+
const int delay = pRadType->GetApplicationDelay();
214242

215-
if ((delay == 0) || (Unsorted::CurrentFrame % delay != 0))
243+
if (delay == 0 || Unsorted::CurrentFrame % delay)
216244
continue;
217245
}
218246

219-
if (pFoot->IsAlive || !pFoot->IsSinking)
247+
const auto it = std::ranges::find_if(typeMap, [pRadType](std::pair<RadTypeClass*, std::vector<std::pair<RadSiteClass*, int>>> const& item) { return item.first == pRadType; });
248+
249+
if (it != typeMap.cend())
250+
{
251+
it->second.emplace_back(pRadSite, radLevel);
252+
}
253+
else
254+
{
255+
std::vector<std::pair<RadSiteClass*, int>> sites { std::make_pair(pRadSite, radLevel) };
256+
typeMap.emplace_back(pRadType, std::move(sites));
257+
}
258+
}
259+
260+
for (auto& [_, sites] : typeMap)
261+
std::ranges::stable_sort(sites, [](std::pair<RadSiteClass*, int> const& left, std::pair<RadSiteClass*, int> const& right) { return left.second > right.second; });
262+
263+
for (const auto& [pRadType, sites] : typeMap)
264+
{
265+
const int radLevelMax = pRadType->GetLevelMax();
266+
int radLevelSum = 0;
267+
268+
for (const auto& [pRadSite, radLevel] : sites)
220269
{
221-
int damage = Game::F2I(radLevel * pType->GetLevelFactor());
270+
const int remain = radLevelMax - radLevelSum;
271+
int damage = static_cast<int>(std::min(radLevel, remain) * pRadType->GetLevelFactor());
272+
273+
if ((pFoot->IsAlive || !pFoot->IsSinking) && !RadSiteExt::ExtMap.Find(pRadSite)->ApplyRadiationDamage(pFoot, damage))
274+
return ReturnFromFunction;
222275

223-
if (!pRadExt->ApplyRadiationDamage(pFoot, damage))
276+
if (radLevel >= remain)
224277
break;
278+
279+
radLevelSum += radLevel;
225280
}
226281
}
227282
}

0 commit comments

Comments
 (0)