1 #include "Debug.h"
2 #include "LoadSaveData.h"
3 #include "LoadSaveObjectType.h"
4 #include "LoadSaveSoldierType.h"
5 #include "Overhead.h"
6 #include "Tactical_Save.h"
7 #include "Types.h"
8 
9 #include <string_theory/string>
10 
11 #include <algorithm>
12 #include <stdexcept>
13 
MercChecksum(SOLDIERTYPE const & s)14 static UINT32 MercChecksum(SOLDIERTYPE const& s)
15 {
16 	UINT32 sum = 1;
17 
18 	sum += 1 + s.bLife;
19 	sum *= 1 + s.bLifeMax;
20 	sum += 1 + s.bAgility;
21 	sum *= 1 + s.bDexterity;
22 	sum += 1 + s.bStrength;
23 	sum *= 1 + s.bMarksmanship;
24 	sum += 1 + s.bMedical;
25 	sum *= 1 + s.bMechanical;
26 	sum += 1 + s.bExplosive;
27 	sum *= 1 + s.bExpLevel;
28 	sum += 1 + s.ubProfile;
29 
30 	CFOR_EACH_SOLDIER_INV_SLOT(i, s)
31 	{
32 		sum += i->usItem;
33 		sum += i->ubNumberOfObjects;
34 	}
35 
36 	return sum;
37 }
38 
39 
ExtractSoldierType(const BYTE * const data,SOLDIERTYPE * const s,bool stracLinuxFormat,UINT32 uiSavedGameVersion)40 void ExtractSoldierType(const BYTE* const data, SOLDIERTYPE* const s, bool stracLinuxFormat, UINT32 uiSavedGameVersion)
41 {
42 	UINT16 usPathingData[ MAX_PATH_LIST_SIZE ];
43 	UINT16 usPathDataSize;
44 	UINT16 usPathIndex;
45 
46 	*s = SOLDIERTYPE{};
47 
48 	DataReader d{data};
49 	EXTR_U8(d, s->ubID)
50 	EXTR_SKIP(d, 1)
51 	EXTR_U8(d, s->ubBodyType)
52 	EXTR_I8(d, s->bActionPoints)
53 	EXTR_I8(d, s->bInitialActionPoints)
54 	EXTR_SKIP(d, 3)
55 	EXTR_U32(d, s->uiStatusFlags)
56 	FOR_EACH_SOLDIER_INV_SLOT(i, *s)
57 	{
58 		ExtractObject(d, i);
59 	}
60 	EXTR_PTR(d, s->pTempObject)
61 	EXTR_PTR(d, s->pKeyRing)
62 	EXTR_I8(d, s->bOldLife)
63 	EXTR_U8(d, s->bInSector)
64 	EXTR_I8(d, s->bFlashPortraitFrame)
65 	EXTR_SKIP(d, 1)
66 	EXTR_I16(d, s->sFractLife)
67 	EXTR_I8(d, s->bBleeding)
68 	EXTR_I8(d, s->bBreath)
69 	EXTR_I8(d, s->bBreathMax)
70 	EXTR_I8(d, s->bStealthMode)
71 	EXTR_I16(d, s->sBreathRed)
72 	EXTR_BOOL(d, s->fDelayedMovement)
73 	EXTR_SKIP(d, 1);
74 	EXTR_U8(d, s->ubWaitActionToDo)
75 	EXTR_SKIP(d, 1)
76 	EXTR_I8(d, s->ubInsertionDirection)
77 	EXTR_SKIP(d, 1)
78 	EXTR_SOLDIER(d, s->opponent)
79 	EXTR_I8(d, s->bLastRenderVisibleValue)
80 	EXTR_SKIP(d, 1)
81 	EXTR_U8(d, s->ubAttackingHand)
82 	EXTR_SKIP(d, 2)
83 	EXTR_I16(d, s->sWeightCarriedAtTurnStart)
84 	if(stracLinuxFormat)
85 	{
86 		EXTR_SKIP(d, 2)
87 		s->name = d.readUTF32(SOLDIERTYPE_NAME_LENGTH);
88 	}
89 	else
90 	{
91 		s->name = d.readUTF16(SOLDIERTYPE_NAME_LENGTH);
92 	}
93 	EXTR_I8(d, s->bVisible)
94 	EXTR_I8(d, s->bActive)
95 	EXTR_I8(d, s->bTeam)
96 	EXTR_U8(d, s->ubGroupID)
97 	EXTR_BOOL(d, s->fBetweenSectors)
98 	EXTR_U8(d, s->ubMovementNoiseHeard)
99 	if(stracLinuxFormat)
100 	{
101 		EXTR_SKIP(d, 2)
102 	}
103 	EXTR_FLOAT(d, s->dXPos)
104 	EXTR_FLOAT(d, s->dYPos)
105 	EXTR_SKIP(d, 8)
106 	EXTR_I16(d, s->sInitialGridNo)
107 	EXTR_I16(d, s->sGridNo)
108 	EXTR_I8(d, s->bDirection)
109 	EXTR_SKIP(d, 1)
110 	EXTR_I16(d, s->sHeightAdjustment)
111 	EXTR_I16(d, s->sDesiredHeight)
112 	EXTR_I16(d, s->sTempNewGridNo)
113 	EXTR_SKIP(d, 2)
114 	EXTR_I8(d, s->bOverTerrainType)
115 	EXTR_SKIP(d, 1)
116 	EXTR_I8(d, s->bCollapsed)
117 	EXTR_I8(d, s->bBreathCollapsed)
118 	EXTR_U8(d, s->ubDesiredHeight)
119 	EXTR_SKIP(d, 1)
120 	EXTR_U16(d, s->usPendingAnimation)
121 	EXTR_U8(d, s->ubPendingStanceChange)
122 	EXTR_SKIP(d, 1)
123 	EXTR_U16(d, s->usAnimState)
124 	EXTR_BOOL(d, s->fNoAPToFinishMove)
125 	EXTR_BOOL(d, s->fPausedMove)
126 	EXTR_BOOL(d, s->fUIdeadMerc)
127 	EXTR_SKIP(d, 1)
128 	EXTR_BOOL(d, s->fUICloseMerc)
129 	EXTR_SKIP(d, 5)
130 	EXTR_I32(d, s->UpdateCounter)
131 	EXTR_I32(d, s->DamageCounter)
132 	EXTR_SKIP_I32(d)
133 	EXTR_SKIP(d, 4)
134 	EXTR_I32(d, s->AICounter)
135 	EXTR_I32(d, s->FadeCounter)
136 	EXTR_U8(d, s->ubSkillTrait1)
137 	EXTR_U8(d, s->ubSkillTrait2)
138 	EXTR_SKIP(d, 6)
139 	EXTR_I8(d, s->bDexterity)
140 	EXTR_I8(d, s->bWisdom)
141 	EXTR_SKIP_I16(d)
142 	EXTR_SOLDIER(d, s->attacker)
143 	EXTR_SOLDIER(d, s->previous_attacker)
144 	EXTR_BOOL(d, s->fTurnInProgress)
145 	EXTR_BOOL(d, s->fIntendedTarget)
146 	EXTR_BOOL(d, s->fPauseAllAnimation)
147 	EXTR_I8(d, s->bExpLevel)
148 	EXTR_I16(d, s->sInsertionGridNo)
149 	EXTR_BOOL(d, s->fContinueMoveAfterStanceChange)
150 	EXTR_SKIP(d, 15)
151 	EXTR_I8(d, s->bLife)
152 	EXTR_U8(d, s->bSide)
153 	EXTR_SKIP(d, 1)
154 	EXTR_I8(d, s->bNewOppCnt)
155 	EXTR_SKIP(d, 2)
156 	EXTR_U16(d, s->usAniCode)
157 	EXTR_U16(d, s->usAniFrame)
158 	EXTR_I16(d, s->sAniDelay)
159 	EXTR_I8(d, s->bAgility)
160 	EXTR_SKIP(d, 1)
161 	EXTR_I16(d, s->sDelayedMovementCauseGridNo)
162 	EXTR_I16(d, s->sReservedMovementGridNo)
163 	EXTR_I8(d, s->bStrength)
164 	EXTR_SKIP(d, 1)
165 	EXTR_I16(d, s->sTargetGridNo)
166 	EXTR_I8(d, s->bTargetLevel)
167 	EXTR_I8(d, s->bTargetCubeLevel)
168 	EXTR_I16(d, s->sLastTarget)
169 	EXTR_I8(d, s->bTilesMoved)
170 	EXTR_I8(d, s->bLeadership)
171 	EXTR_FLOAT(d, s->dNextBleed)
172 	EXTR_BOOL(d, s->fWarnedAboutBleeding)
173 	EXTR_BOOL(d, s->fDyingComment)
174 	EXTR_U8(d, s->ubTilesMovedPerRTBreathUpdate)
175 	EXTR_SKIP(d, 1)
176 	EXTR_U16(d, s->usLastMovementAnimPerRTBreathUpdate)
177 	EXTR_BOOL(d, s->fTurningToShoot)
178 	EXTR_SKIP(d, 1)
179 	EXTR_BOOL(d, s->fTurningUntilDone)
180 	EXTR_BOOL(d, s->fGettingHit)
181 	EXTR_BOOL(d, s->fInNonintAnim)
182 	EXTR_BOOL(d, s->fFlashLocator)
183 	EXTR_I16(d, s->sLocatorFrame)
184 	EXTR_BOOL(d, s->fShowLocator)
185 	EXTR_BOOL(d, s->fFlashPortrait)
186 	EXTR_I8(d, s->bMechanical)
187 	EXTR_I8(d, s->bLifeMax)
188 	EXTR_SKIP(d, 6)
189 	s->HeadPal = d.readUTF8(PaletteRepID_LENGTH, ST::substitute_invalid);
190 	s->PantsPal = d.readUTF8(PaletteRepID_LENGTH, ST::substitute_invalid);
191 	s->VestPal = d.readUTF8(PaletteRepID_LENGTH, ST::substitute_invalid);
192 	s->SkinPal = d.readUTF8(PaletteRepID_LENGTH, ST::substitute_invalid);
193 	EXTR_SKIP(d, 328)
194 	EXTR_I8(d, s->bMedical)
195 	EXTR_BOOL(d, s->fBeginFade)
196 	EXTR_U8(d, s->ubFadeLevel)
197 	EXTR_U8(d, s->ubServiceCount)
198 	EXTR_SOLDIER(d, s->service_partner)
199 	EXTR_I8(d, s->bMarksmanship)
200 	EXTR_I8(d, s->bExplosive)
201 	EXTR_SKIP(d, 1)
202 	EXTR_PTR(d, s->pThrowParams)
203 	EXTR_BOOL(d, s->fTurningFromPronePosition)
204 	EXTR_I8(d, s->bReverse)
205 	EXTR_SKIP(d, 2)
206 	EXTR_PTR(d, s->pLevelNode)
207 	EXTR_SKIP(d, 8)
208 	EXTR_I8(d, s->bDesiredDirection)
209 	EXTR_SKIP(d, 1)
210 	EXTR_I16(d, s->sDestXPos)
211 	EXTR_I16(d, s->sDestYPos)
212 	EXTR_SKIP(d, 2)
213 	EXTR_I16(d, s->sDestination)
214 	EXTR_I16(d, s->sFinalDestination)
215 	EXTR_I8(d, s->bLevel)
216 	EXTR_SKIP(d, 3)
217 
218 	// pathing info takes up 16 bit in the savegame but 8 bit in the engine
219 	EXTR_U16A(d, usPathingData, lengthof(usPathingData))
220 	EXTR_U16(d, usPathDataSize)
221 	EXTR_U16(d, usPathIndex)
222 	for (UINT8 i = 0; i < usPathDataSize && i < MAX_PATH_LIST_SIZE; i++) {
223 		s->ubPathingData[i] = (UINT8)usPathingData[i];
224 	}
225 	s->ubPathDataSize = (UINT8)usPathDataSize;
226 	s->ubPathIndex = (UINT8)usPathIndex;
227 
228 	EXTR_I16(d, s->sBlackList)
229 	EXTR_I8(d, s->bAimTime)
230 	EXTR_I8(d, s->bShownAimTime)
231 	EXTR_I8(d, s->bPathStored)
232 	EXTR_I8(d, s->bHasKeys)
233 	EXTR_SKIP(d, 18)
234 	EXTR_U8(d, s->ubStrategicInsertionCode)
235 	EXTR_SKIP(d, 1)
236 	EXTR_U16(d, s->usStrategicInsertionData)
237 	EXTR_SKIP(d, 8)
238 	EXTR_I8(d, s->bMuzFlashCount)
239 	EXTR_SKIP(d, 1)
240 	EXTR_I16(d, s->sX)
241 	EXTR_I16(d, s->sY)
242 	EXTR_U16(d, s->usOldAniState)
243 	EXTR_I16(d, s->sOldAniCode)
244 	EXTR_I8(d, s->bBulletsLeft)
245 	EXTR_U8(d, s->ubSuppressionPoints)
246 	EXTR_U32(d, s->uiTimeOfLastRandomAction)
247 	EXTR_SKIP(d, 2)
248 	EXTR_I8A(d, s->bOppList, lengthof(s->bOppList))
249 	EXTR_I8(d, s->bLastAction)
250 	EXTR_I8(d, s->bAction)
251 	EXTR_U16(d, s->usActionData)
252 	EXTR_I8(d, s->bNextAction)
253 	EXTR_SKIP(d, 1)
254 	EXTR_U16(d, s->usNextActionData)
255 	EXTR_I8(d, s->bActionInProgress)
256 	EXTR_I8(d, s->bAlertStatus)
257 	EXTR_I8(d, s->bOppCnt)
258 	EXTR_I8(d, s->bNeutral)
259 	EXTR_I8(d, s->bNewSituation)
260 	EXTR_I8(d, s->bNextTargetLevel)
261 	EXTR_I8(d, s->bOrders)
262 	EXTR_I8(d, s->bAttitude)
263 	EXTR_I8(d, s->bUnderFire)
264 	EXTR_I8(d, s->bShock)
265 	EXTR_SKIP(d, 1)
266 	EXTR_I8(d, s->bBypassToGreen)
267 	EXTR_SKIP(d, 1)
268 	EXTR_I8(d, s->bDominantDir)
269 	EXTR_I8(d, s->bPatrolCnt)
270 	EXTR_I8(d, s->bNextPatrolPnt)
271 	EXTR_I16A(d, s->usPatrolGrid, lengthof(s->usPatrolGrid))
272 	EXTR_I16(d, s->sNoiseGridno)
273 	EXTR_U8(d, s->ubNoiseVolume)
274 	EXTR_I8(d, s->bLastAttackHit)
275 	EXTR_SOLDIER(d, s->xrayed_by)
276 	EXTR_SKIP(d, 1)
277 	EXTR_FLOAT(d, s->dHeightAdjustment)
278 	EXTR_I8(d, s->bMorale)
279 	EXTR_I8(d, s->bTeamMoraleMod)
280 	EXTR_I8(d, s->bTacticalMoraleMod)
281 	EXTR_I8(d, s->bStrategicMoraleMod)
282 	EXTR_I8(d, s->bAIMorale)
283 	EXTR_U8(d, s->ubPendingAction)
284 	EXTR_U8(d, s->ubPendingActionAnimCount)
285 	EXTR_SKIP(d, 1)
286 	EXTR_U32(d, s->uiPendingActionData1)
287 	EXTR_I16(d, s->sPendingActionData2)
288 	EXTR_I8(d, s->bPendingActionData3)
289 	EXTR_I8(d, s->ubDoorHandleCode)
290 	EXTR_U32(d, s->uiPendingActionData4)
291 	EXTR_I8(d, s->bInterruptDuelPts)
292 	EXTR_I8(d, s->bPassedLastInterrupt)
293 	EXTR_I8(d, s->bIntStartAPs)
294 	EXTR_I8(d, s->bMoved)
295 	EXTR_I8(d, s->bHunting)
296 	EXTR_SKIP(d, 1)
297 	EXTR_U8(d, s->ubCaller)
298 	EXTR_SKIP(d, 1)
299 	EXTR_I16(d, s->sCallerGridNo)
300 	EXTR_U8(d, s->bCallPriority)
301 	EXTR_I8(d, s->bCallActedUpon)
302 	EXTR_I8(d, s->bFrenzied)
303 	EXTR_I8(d, s->bNormalSmell)
304 	EXTR_I8(d, s->bMonsterSmell)
305 	EXTR_I8(d, s->bMobility)
306 	EXTR_SKIP(d, 1)
307 	EXTR_I8(d, s->fAIFlags)
308 	EXTR_BOOL(d, s->fDontChargeReadyAPs)
309 	EXTR_SKIP(d, 1)
310 	EXTR_U16(d, s->usAnimSurface)
311 	EXTR_U16(d, s->sZLevel)
312 	EXTR_BOOL(d, s->fPrevInWater)
313 	EXTR_BOOL(d, s->fGoBackToAimAfterHit)
314 	EXTR_I16(d, s->sWalkToAttackGridNo)
315 	EXTR_I16(d, s->sWalkToAttackWalkToCost)
316 	EXTR_SKIP(d, 7)
317 	EXTR_BOOL(d, s->fForceShade)
318 	EXTR_SKIP(d, 2)
319 	EXTR_PTR(d, s->pForcedShade)
320 	EXTR_I8(d, s->bDisplayDamageCount)
321 	EXTR_I8(d, s->fDisplayDamage)
322 	EXTR_I16(d, s->sDamage)
323 	EXTR_I16(d, s->sDamageX)
324 	EXTR_I16(d, s->sDamageY)
325 	EXTR_SKIP(d, 1)
326 	EXTR_I8(d, s->bDoBurst)
327 	EXTR_I16(d, s->usUIMovementMode)
328 	EXTR_SKIP(d, 1)
329 	EXTR_BOOL(d, s->fUIMovementFast)
330 	EXTR_SKIP(d, 2)
331 	EXTR_I32(d, s->BlinkSelCounter)
332 	EXTR_I32(d, s->PortraitFlashCounter)
333 	EXTR_BOOL(d, s->fDeadSoundPlayed)
334 	EXTR_U8(d, s->ubProfile)
335 	EXTR_U8(d, s->ubQuoteRecord)
336 	EXTR_U8(d, s->ubQuoteActionID)
337 	EXTR_U8(d, s->ubBattleSoundID)
338 	EXTR_BOOL(d, s->fClosePanel)
339 	EXTR_BOOL(d, s->fClosePanelToDie)
340 	EXTR_U8(d, s->ubClosePanelFrame)
341 	EXTR_BOOL(d, s->fDeadPanel)
342 	EXTR_U8(d, s->ubDeadPanelFrame)
343 	EXTR_SKIP(d, 2)
344 	EXTR_I16(d, s->sPanelFaceX)
345 	EXTR_I16(d, s->sPanelFaceY)
346 	EXTR_I8(d, s->bNumHitsThisTurn)
347 	EXTR_SKIP(d, 1)
348 	EXTR_U16(d, s->usQuoteSaidFlags)
349 	EXTR_I8(d, s->fCloseCall)
350 	EXTR_I8(d, s->bLastSkillCheck)
351 	EXTR_I8(d, s->ubSkillCheckAttempts)
352 	EXTR_SKIP(d, 1)
353 	EXTR_I8(d, s->bStartFallDir)
354 	EXTR_I8(d, s->fTryingToFall)
355 	EXTR_U8(d, s->ubPendingDirection)
356 	EXTR_SKIP(d, 1)
357 	EXTR_U32(d, s->uiAnimSubFlags)
358 	EXTR_U8(d, s->bAimShotLocation)
359 	EXTR_U8(d, s->ubHitLocation)
360 	EXTR_SKIP(d, 16)
361 	EXTR_I16A(d, s->sSpreadLocations, lengthof(s->sSpreadLocations))
362 	EXTR_BOOL(d, s->fDoSpread)
363 	EXTR_SKIP(d, 1)
364 	EXTR_I16(d, s->sStartGridNo)
365 	EXTR_I16(d, s->sEndGridNo)
366 	EXTR_I16(d, s->sForcastGridno)
367 	EXTR_I16(d, s->sZLevelOverride)
368 	EXTR_I8(d, s->bMovedPriorToInterrupt)
369 	EXTR_SKIP(d, 3)
370 	EXTR_I32(d, s->iEndofContractTime)
371 	EXTR_I32(d, s->iStartContractTime)
372 	EXTR_I32(d, s->iTotalContractLength)
373 	EXTR_I32(d, s->iNextActionSpecialData)
374 	EXTR_U8(d, s->ubWhatKindOfMercAmI)
375 	EXTR_I8(d, s->bAssignment)
376 	EXTR_SKIP(d, 1)
377 	EXTR_BOOL(d, s->fForcedToStayAwake)
378 	EXTR_I8(d, s->bTrainStat)
379 	EXTR_SKIP(d, 1)
380 	EXTR_I16(d, s->sSectorX)
381 	EXTR_I16(d, s->sSectorY)
382 	EXTR_I8(d, s->bSectorZ)
383 	EXTR_SKIP(d, 1)
384 	EXTR_I32(d, s->iVehicleId)
385 	EXTR_PTR(d, s->pMercPath)
386 	EXTR_U8(d, s->fHitByGasFlags)
387 	EXTR_SKIP(d, 1)
388 	EXTR_U16(d, s->usMedicalDeposit)
389 	EXTR_U16(d, s->usLifeInsurance)
390 	EXTR_SKIP(d, 26)
391 	EXTR_I32(d, s->iStartOfInsuranceContract)
392 	EXTR_U32(d, s->uiLastAssignmentChangeMin)
393 	EXTR_I32(d, s->iTotalLengthOfInsuranceContract)
394 	EXTR_U8(d, s->ubSoldierClass)
395 	EXTR_U8(d, s->ubAPsLostToSuppression)
396 	EXTR_BOOL(d, s->fChangingStanceDueToSuppression)
397 	EXTR_SOLDIER(d, s->suppressor)
398 	EXTR_SKIP(d, 4)
399 	EXTR_U8(d, s->ubCivilianGroup)
400 	EXTR_SKIP(d, 3)
401 	EXTR_U32(d, s->uiChangeLevelTime)
402 	EXTR_U32(d, s->uiChangeHealthTime)
403 	EXTR_U32(d, s->uiChangeStrengthTime)
404 	EXTR_U32(d, s->uiChangeDexterityTime)
405 	EXTR_U32(d, s->uiChangeAgilityTime)
406 	EXTR_U32(d, s->uiChangeWisdomTime)
407 	EXTR_U32(d, s->uiChangeLeadershipTime)
408 	EXTR_U32(d, s->uiChangeMarksmanshipTime)
409 	EXTR_U32(d, s->uiChangeExplosivesTime)
410 	EXTR_U32(d, s->uiChangeMedicalTime)
411 	EXTR_U32(d, s->uiChangeMechanicalTime)
412 	EXTR_U32(d, s->uiUniqueSoldierIdValue)
413 	EXTR_I8(d, s->bBeingAttackedCount)
414 	EXTR_I8A(d, s->bNewItemCount, lengthof(s->bNewItemCount))
415 	EXTR_I8A(d, s->bNewItemCycleCount, lengthof(s->bNewItemCycleCount))
416 	EXTR_BOOL(d, s->fCheckForNewlyAddedItems)
417 	EXTR_I8(d, s->bEndDoorOpenCode)
418 	EXTR_U8(d, s->ubScheduleID)
419 	EXTR_I16(d, s->sEndDoorOpenCodeData)
420 	EXTR_I32(d, s->NextTileCounter)
421 	EXTR_BOOL(d, s->fBlockedByAnotherMerc)
422 	EXTR_I8(d, s->bBlockedByAnotherMercDirection)
423 	EXTR_U16(d, s->usAttackingWeapon)
424 	EXTR_I8(d, s->bWeaponMode)
425 	EXTR_SOLDIER(d, s->target)
426 	EXTR_I8(d, s->bAIScheduleProgress)
427 	EXTR_SKIP(d, 1)
428 	EXTR_I16(d, s->sOffWorldGridNo)
429 	EXTR_SKIP(d, 2)
430 	EXTR_PTR(d, s->pAniTile)
431 	EXTR_I8(d, s->bCamo)
432 	EXTR_SKIP(d, 1)
433 	EXTR_I16(d, s->sAbsoluteFinalDestination)
434 	EXTR_U8(d, s->ubHiResDirection)
435 	EXTR_SKIP(d, 1)
436 	EXTR_U8(d, s->ubLastFootPrintSound)
437 	EXTR_I8(d, s->bVehicleID)
438 	EXTR_I8(d, s->fPastXDest)
439 	EXTR_I8(d, s->fPastYDest)
440 	EXTR_I8(d, s->bMovementDirection)
441 	EXTR_SKIP(d, 1)
442 	EXTR_I16(d, s->sOldGridNo)
443 	EXTR_U16(d, s->usDontUpdateNewGridNoOnMoveAnimChange)
444 	EXTR_I16(d, s->sBoundingBoxWidth)
445 	EXTR_I16(d, s->sBoundingBoxHeight)
446 	EXTR_I16(d, s->sBoundingBoxOffsetX)
447 	EXTR_I16(d, s->sBoundingBoxOffsetY)
448 	EXTR_U32(d, s->uiTimeSameBattleSndDone)
449 	EXTR_I8(d, s->bOldBattleSnd)
450 	EXTR_SKIP(d, 1)
451 	EXTR_BOOL(d, s->fContractPriceHasIncreased)
452 	EXTR_SKIP(d, 1)
453 	EXTR_U32(d, s->uiBurstSoundID)
454 	EXTR_BOOL(d, s->fFixingSAMSite)
455 	EXTR_BOOL(d, s->fFixingRobot)
456 	EXTR_I8(d, s->bSlotItemTakenFrom)
457 	EXTR_BOOL(d, s->fSignedAnotherContract)
458 	EXTR_SOLDIER(d, s->auto_bandaging_medic)
459 	EXTR_BOOL(d, s->fDontChargeTurningAPs)
460 	EXTR_SOLDIER(d, s->robot_remote_holder)
461 	EXTR_SKIP(d, 1)
462 	EXTR_U32(d, s->uiTimeOfLastContractUpdate)
463 	EXTR_I8(d, s->bTypeOfLastContract)
464 	EXTR_I8(d, s->bTurnsCollapsed)
465 	EXTR_I8(d, s->bSleepDrugCounter)
466 	EXTR_U8(d, s->ubMilitiaKills)
467 	EXTR_I8A(d, s->bFutureDrugEffect, lengthof(s->bFutureDrugEffect))
468 	EXTR_I8A(d, s->bDrugEffectRate, lengthof(s->bDrugEffectRate))
469 	EXTR_I8A(d, s->bDrugEffect, lengthof(s->bDrugEffect))
470 	EXTR_I8A(d, s->bDrugSideEffectRate, lengthof(s->bDrugSideEffectRate))
471 	EXTR_I8A(d, s->bDrugSideEffect, lengthof(s->bDrugSideEffect))
472 	EXTR_SKIP(d, 2)
473 	EXTR_I8(d, s->bBlindedCounter)
474 	EXTR_BOOL(d, s->fMercCollapsedFlag)
475 	EXTR_BOOL(d, s->fDoneAssignmentAndNothingToDoFlag)
476 	EXTR_BOOL(d, s->fMercAsleep)
477 	EXTR_BOOL(d, s->fDontChargeAPsForStanceChange)
478 	EXTR_SKIP(d, 2)
479 	EXTR_U8(d, s->ubTurnsUntilCanSayHeardNoise)
480 	EXTR_U16(d, s->usQuoteSaidExtFlags)
481 	EXTR_U16(d, s->sContPathLocation)
482 	EXTR_I8(d, s->bGoodContPath)
483 	EXTR_SKIP(d, 1)
484 	EXTR_I8(d, s->bNoiseLevel)
485 	EXTR_I8(d, s->bRegenerationCounter)
486 	EXTR_I8(d, s->bRegenBoostersUsedToday)
487 	EXTR_I8(d, s->bNumPelletsHitBy)
488 	EXTR_I16(d, s->sSkillCheckGridNo)
489 	EXTR_U8(d, s->ubLastEnemyCycledID)
490 	EXTR_U8(d, s->ubPrevSectorID)
491 	EXTR_U8(d, s->ubNumTilesMovesSinceLastForget)
492 	EXTR_I8(d, s->bTurningIncrement)
493 	EXTR_U32(d, s->uiBattleSoundID)
494 	EXTR_BOOL(d, s->fSoldierWasMoving)
495 	EXTR_BOOL(d, s->fSayAmmoQuotePending)
496 	EXTR_U16(d, s->usValueGoneUp)
497 	EXTR_U8(d, s->ubNumLocateCycles)
498 	EXTR_U8(d, s->ubDelayedMovementFlags)
499 	EXTR_BOOL(d, s->fMuzzleFlash)
500 	EXTR_SOLDIER(d, s->CTGTTarget)
501 	EXTR_I32(d, s->PanelAnimateCounter)
502 	UINT32 checksum;
503 	EXTR_U32(d, checksum)
504 	EXTR_I8(d, s->bCurrentCivQuote)
505 	EXTR_I8(d, s->bCurrentCivQuoteDelta)
506 	EXTR_U8(d, s->ubMiscSoldierFlags)
507 	EXTR_U8(d, s->ubReasonCantFinishMove)
508 	EXTR_I16(d, s->sLocationOfFadeStart)
509 	EXTR_U8(d, s->bUseExitGridForReentryDirection)
510 	EXTR_SKIP(d, 1)
511 	EXTR_U32(d, s->uiTimeSinceLastSpoke)
512 	EXTR_U8(d, s->ubContractRenewalQuoteCode)
513 	EXTR_SKIP(d, 1)
514 	EXTR_I16(d, s->sPreTraversalGridNo)
515 	EXTR_U32(d, s->uiXRayActivatedTime)
516 	EXTR_I8(d, s->bTurningFromUI)
517 	EXTR_I8(d, s->bPendingActionData5)
518 	EXTR_I8(d, s->bDelayedStrategicMoraleMod)
519 	EXTR_U8(d, s->ubDoorOpeningNoise)
520 	EXTR_SKIP(d, 4)
521 	EXTR_U8(d, s->ubLeaveHistoryCode)
522 	EXTR_BOOL(d, s->fDontUnsetLastTargetFromTurn)
523 	EXTR_I8(d, s->bOverrideMoveSpeed)
524 	EXTR_BOOL(d, s->fUseMoverrideMoveSpeed)
525 	EXTR_U32(d, s->uiTimeSoldierWillArrive)
526 	EXTR_SKIP(d, 1)
527 	EXTR_BOOL(d, s->fUseLandingZoneForArrival)
528 	EXTR_BOOL(d, s->fFallClockwise)
529 	EXTR_I8(d, s->bVehicleUnderRepairID)
530 	EXTR_I32(d, s->iTimeCanSignElsewhere)
531 	EXTR_I8(d, s->bHospitalPriceModifier)
532 	EXTR_SKIP(d, 3)
533 	EXTR_U32(d, s->uiStartTimeOfInsuranceContract)
534 	EXTR_BOOL(d, s->fRTInNonintAnim)
535 	EXTR_BOOL(d, s->fDoingExternalDeath)
536 	EXTR_I8(d, s->bCorpseQuoteTolerance)
537 	EXTR_SKIP(d, 1)
538 	EXTR_I32(d, s->iPositionSndID)
539 	EXTR_U32(d, s->uiTuringSoundID)
540 	EXTR_U8(d, s->ubLastDamageReason)
541 	EXTR_BOOL(d, s->fComplainedThatTired)
542 	EXTR_I16A(d, s->sLastTwoLocations, lengthof(s->sLastTwoLocations))
543 	EXTR_SKIP(d, 2)
544 	EXTR_I32(d, s->uiTimeSinceLastBleedGrunt)
545 	EXTR_SOLDIER(d, s->next_to_previous_attacker)
546 	EXTR_SKIP(d, 39)
547 	if(stracLinuxFormat)
548 	{
549 		Assert(d.getConsumed() == 2352);
550 	}
551 	else
552 	{
553 		Assert(d.getConsumed() == 2328);
554 	}
555 
556 	if (checksum != MercChecksum(*s))
557 	{
558 		throw std::runtime_error("soldier checksum mismatch");
559 	}
560 }
561 
562 
InjectSoldierType(BYTE * const data,const SOLDIERTYPE * const s)563 void InjectSoldierType(BYTE* const data, const SOLDIERTYPE* const s)
564 {
565 	UINT16 usPathingData[ MAX_PATH_LIST_SIZE ];
566 	UINT16 usPathDataSize;
567 	UINT16 usPathIndex;
568 
569 	DataWriter d{data};
570 	INJ_U8(d, s->ubID)
571 	INJ_SKIP(d, 1)
572 	INJ_U8(d, s->ubBodyType)
573 	INJ_I8(d, s->bActionPoints)
574 	INJ_I8(d, s->bInitialActionPoints)
575 	INJ_SKIP(d, 3)
576 	INJ_U32(d, s->uiStatusFlags)
577 	CFOR_EACH_SOLDIER_INV_SLOT(i, *s)
578 	{
579 		InjectObject(d, i);
580 	}
581 	INJ_PTR(d, s->pTempObject)
582 	INJ_PTR(d, s->pKeyRing)
583 	INJ_I8(d, s->bOldLife)
584 	INJ_U8(d, s->bInSector)
585 	INJ_I8(d, s->bFlashPortraitFrame)
586 	INJ_SKIP(d, 1)
587 	INJ_I16(d, s->sFractLife)
588 	INJ_I8(d, s->bBleeding)
589 	INJ_I8(d, s->bBreath)
590 	INJ_I8(d, s->bBreathMax)
591 	INJ_I8(d, s->bStealthMode)
592 	INJ_I16(d, s->sBreathRed)
593 	INJ_BOOL(d, s->fDelayedMovement)
594 	INJ_SKIP(d, 1)
595 	INJ_U8(d, s->ubWaitActionToDo)
596 	INJ_SKIP(d, 1)
597 	INJ_I8(d, s->ubInsertionDirection)
598 	INJ_SKIP(d, 1)
599 	INJ_SOLDIER(d, s->opponent)
600 	INJ_I8(d, s->bLastRenderVisibleValue)
601 	INJ_SKIP(d, 1)
602 	INJ_U8(d, s->ubAttackingHand)
603 	INJ_SKIP(d, 2)
604 	INJ_I16(d, s->sWeightCarriedAtTurnStart)
605 	d.writeUTF16(s->name, SOLDIERTYPE_NAME_LENGTH);
606 	INJ_I8(d, s->bVisible)
607 	INJ_I8(d, s->bActive)
608 	INJ_I8(d, s->bTeam)
609 	INJ_U8(d, s->ubGroupID)
610 	INJ_BOOL(d, s->fBetweenSectors)
611 	INJ_U8(d, s->ubMovementNoiseHeard)
612 	INJ_FLOAT(d, s->dXPos)
613 	INJ_FLOAT(d, s->dYPos)
614 	INJ_SKIP(d, 8)
615 	INJ_I16(d, s->sInitialGridNo)
616 	INJ_I16(d, s->sGridNo)
617 	INJ_I8(d, s->bDirection)
618 	INJ_SKIP(d, 1)
619 	INJ_I16(d, s->sHeightAdjustment)
620 	INJ_I16(d, s->sDesiredHeight)
621 	INJ_I16(d, s->sTempNewGridNo)
622 	INJ_SKIP(d, 2)
623 	INJ_I8(d, s->bOverTerrainType)
624 	INJ_SKIP(d, 1)
625 	INJ_I8(d, s->bCollapsed)
626 	INJ_I8(d, s->bBreathCollapsed)
627 	INJ_U8(d, s->ubDesiredHeight)
628 	INJ_SKIP(d, 1)
629 	INJ_U16(d, s->usPendingAnimation)
630 	INJ_U8(d, s->ubPendingStanceChange)
631 	INJ_SKIP(d, 1)
632 	INJ_U16(d, s->usAnimState)
633 	INJ_BOOL(d, s->fNoAPToFinishMove)
634 	INJ_BOOL(d, s->fPausedMove)
635 	INJ_BOOL(d, s->fUIdeadMerc)
636 	INJ_SKIP(d, 1)
637 	INJ_BOOL(d, s->fUICloseMerc)
638 	INJ_SKIP(d, 5)
639 	INJ_I32(d, s->UpdateCounter)
640 	INJ_I32(d, s->DamageCounter)
641 	INJ_SKIP_I32(d)
642 	INJ_SKIP(d, 4)
643 	INJ_I32(d, s->AICounter)
644 	INJ_I32(d, s->FadeCounter)
645 	INJ_U8(d, s->ubSkillTrait1)
646 	INJ_U8(d, s->ubSkillTrait2)
647 	INJ_SKIP(d, 6)
648 	INJ_I8(d, s->bDexterity)
649 	INJ_I8(d, s->bWisdom)
650 	INJ_SKIP_I16(d)
651 	INJ_SOLDIER(d, s->attacker)
652 	INJ_SOLDIER(d, s->previous_attacker)
653 	INJ_BOOL(d, s->fTurnInProgress)
654 	INJ_BOOL(d, s->fIntendedTarget)
655 	INJ_BOOL(d, s->fPauseAllAnimation)
656 	INJ_I8(d, s->bExpLevel)
657 	INJ_I16(d, s->sInsertionGridNo)
658 	INJ_BOOL(d, s->fContinueMoveAfterStanceChange)
659 	INJ_SKIP(d, 15)
660 	INJ_I8(d, s->bLife)
661 	INJ_U8(d, s->bSide)
662 	INJ_SKIP(d, 1)
663 	INJ_I8(d, s->bNewOppCnt)
664 	INJ_SKIP(d, 2)
665 	INJ_U16(d, s->usAniCode)
666 	INJ_U16(d, s->usAniFrame)
667 	INJ_I16(d, s->sAniDelay)
668 	INJ_I8(d, s->bAgility)
669 	INJ_SKIP(d, 1)
670 	INJ_I16(d, s->sDelayedMovementCauseGridNo)
671 	INJ_I16(d, s->sReservedMovementGridNo)
672 	INJ_I8(d, s->bStrength)
673 	INJ_SKIP(d, 1)
674 	INJ_I16(d, s->sTargetGridNo)
675 	INJ_I8(d, s->bTargetLevel)
676 	INJ_I8(d, s->bTargetCubeLevel)
677 	INJ_I16(d, s->sLastTarget)
678 	INJ_I8(d, s->bTilesMoved)
679 	INJ_I8(d, s->bLeadership)
680 	INJ_FLOAT(d, s->dNextBleed)
681 	INJ_BOOL(d, s->fWarnedAboutBleeding)
682 	INJ_BOOL(d, s->fDyingComment)
683 	INJ_U8(d, s->ubTilesMovedPerRTBreathUpdate)
684 	INJ_SKIP(d, 1)
685 	INJ_U16(d, s->usLastMovementAnimPerRTBreathUpdate)
686 	INJ_BOOL(d, s->fTurningToShoot)
687 	INJ_SKIP(d, 1)
688 	INJ_BOOL(d, s->fTurningUntilDone)
689 	INJ_BOOL(d, s->fGettingHit)
690 	INJ_BOOL(d, s->fInNonintAnim)
691 	INJ_BOOL(d, s->fFlashLocator)
692 	INJ_I16(d, s->sLocatorFrame)
693 	INJ_BOOL(d, s->fShowLocator)
694 	INJ_BOOL(d, s->fFlashPortrait)
695 	INJ_I8(d, s->bMechanical)
696 	INJ_I8(d, s->bLifeMax)
697 	INJ_SKIP(d, 6)
698 	d.writeUTF8(s->HeadPal, PaletteRepID_LENGTH);
699 	d.writeUTF8(s->PantsPal, PaletteRepID_LENGTH);
700 	d.writeUTF8(s->VestPal, PaletteRepID_LENGTH);
701 	d.writeUTF8(s->SkinPal, PaletteRepID_LENGTH);
702 	INJ_SKIP(d, 328)
703 	INJ_I8(d, s->bMedical)
704 	INJ_BOOL(d, s->fBeginFade)
705 	INJ_U8(d, s->ubFadeLevel)
706 	INJ_U8(d, s->ubServiceCount)
707 	INJ_SOLDIER(d, s->service_partner)
708 	INJ_I8(d, s->bMarksmanship)
709 	INJ_I8(d, s->bExplosive)
710 	INJ_SKIP(d, 1)
711 	INJ_PTR(d, s->pThrowParams)
712 	INJ_BOOL(d, s->fTurningFromPronePosition)
713 	INJ_I8(d, s->bReverse)
714 	INJ_SKIP(d, 2)
715 	INJ_PTR(d, s->pLevelNode)
716 	INJ_SKIP(d, 8)
717 	INJ_I8(d, s->bDesiredDirection)
718 	INJ_SKIP(d, 1)
719 	INJ_I16(d, s->sDestXPos)
720 	INJ_I16(d, s->sDestYPos)
721 	INJ_SKIP(d, 2)
722 	INJ_I16(d, s->sDestination)
723 	INJ_I16(d, s->sFinalDestination)
724 	INJ_I8(d, s->bLevel)
725 	INJ_SKIP(d, 3)
726 
727 	// pathing info takes up 16 bit in the savegame but 8 bit in the engine
728 	usPathDataSize = s->ubPathDataSize > MAX_PATH_LIST_SIZE ? (UINT16)MAX_PATH_LIST_SIZE : (UINT16)s->ubPathDataSize;
729 	usPathIndex = (UINT16)s->ubPathIndex;
730 	std::fill_n(usPathingData, MAX_PATH_LIST_SIZE, 0);
731 	for (UINT8 i = 0; i < usPathDataSize; i++) {
732 		usPathingData[i] = (UINT16)s->ubPathingData[i];
733 	}
734 	INJ_U16A(d, usPathingData, lengthof(usPathingData))
735 	INJ_U16(d, usPathDataSize)
736 	INJ_U16(d, usPathIndex)
737 
738 	INJ_I16(d, s->sBlackList)
739 	INJ_I8(d, s->bAimTime)
740 	INJ_I8(d, s->bShownAimTime)
741 	INJ_I8(d, s->bPathStored)
742 	INJ_I8(d, s->bHasKeys)
743 	INJ_SKIP(d, 18)
744 	INJ_U8(d, s->ubStrategicInsertionCode)
745 	INJ_SKIP(d, 1)
746 	INJ_U16(d, s->usStrategicInsertionData)
747 	INJ_SKIP(d, 8)
748 	INJ_I8(d, s->bMuzFlashCount)
749 	INJ_SKIP(d, 1)
750 	INJ_I16(d, s->sX)
751 	INJ_I16(d, s->sY)
752 	INJ_U16(d, s->usOldAniState)
753 	INJ_I16(d, s->sOldAniCode)
754 	INJ_I8(d, s->bBulletsLeft)
755 	INJ_U8(d, s->ubSuppressionPoints)
756 	INJ_U32(d, s->uiTimeOfLastRandomAction)
757 	INJ_SKIP(d, 2)
758 	INJ_I8A(d, s->bOppList, lengthof(s->bOppList))
759 	INJ_I8(d, s->bLastAction)
760 	INJ_I8(d, s->bAction)
761 	INJ_U16(d, s->usActionData)
762 	INJ_I8(d, s->bNextAction)
763 	INJ_SKIP(d, 1)
764 	INJ_U16(d, s->usNextActionData)
765 	INJ_I8(d, s->bActionInProgress)
766 	INJ_I8(d, s->bAlertStatus)
767 	INJ_I8(d, s->bOppCnt)
768 	INJ_I8(d, s->bNeutral)
769 	INJ_I8(d, s->bNewSituation)
770 	INJ_I8(d, s->bNextTargetLevel)
771 	INJ_I8(d, s->bOrders)
772 	INJ_I8(d, s->bAttitude)
773 	INJ_I8(d, s->bUnderFire)
774 	INJ_I8(d, s->bShock)
775 	INJ_SKIP(d, 1)
776 	INJ_I8(d, s->bBypassToGreen)
777 	INJ_SKIP(d, 1)
778 	INJ_I8(d, s->bDominantDir)
779 	INJ_I8(d, s->bPatrolCnt)
780 	INJ_I8(d, s->bNextPatrolPnt)
781 	INJ_I16A(d, s->usPatrolGrid, lengthof(s->usPatrolGrid))
782 	INJ_I16(d, s->sNoiseGridno)
783 	INJ_U8(d, s->ubNoiseVolume)
784 	INJ_I8(d, s->bLastAttackHit)
785 	INJ_SOLDIER(d, s->xrayed_by)
786 	INJ_SKIP(d, 1)
787 	INJ_FLOAT(d, s->dHeightAdjustment)
788 	INJ_I8(d, s->bMorale)
789 	INJ_I8(d, s->bTeamMoraleMod)
790 	INJ_I8(d, s->bTacticalMoraleMod)
791 	INJ_I8(d, s->bStrategicMoraleMod)
792 	INJ_I8(d, s->bAIMorale)
793 	INJ_U8(d, s->ubPendingAction)
794 	INJ_U8(d, s->ubPendingActionAnimCount)
795 	INJ_SKIP(d, 1)
796 	INJ_U32(d, s->uiPendingActionData1)
797 	INJ_I16(d, s->sPendingActionData2)
798 	INJ_I8(d, s->bPendingActionData3)
799 	INJ_I8(d, s->ubDoorHandleCode)
800 	INJ_U32(d, s->uiPendingActionData4)
801 	INJ_I8(d, s->bInterruptDuelPts)
802 	INJ_I8(d, s->bPassedLastInterrupt)
803 	INJ_I8(d, s->bIntStartAPs)
804 	INJ_I8(d, s->bMoved)
805 	INJ_I8(d, s->bHunting)
806 	INJ_SKIP(d, 1)
807 	INJ_U8(d, s->ubCaller)
808 	INJ_SKIP(d, 1)
809 	INJ_I16(d, s->sCallerGridNo)
810 	INJ_U8(d, s->bCallPriority)
811 	INJ_I8(d, s->bCallActedUpon)
812 	INJ_I8(d, s->bFrenzied)
813 	INJ_I8(d, s->bNormalSmell)
814 	INJ_I8(d, s->bMonsterSmell)
815 	INJ_I8(d, s->bMobility)
816 	INJ_SKIP(d, 1)
817 	INJ_I8(d, s->fAIFlags)
818 	INJ_BOOL(d, s->fDontChargeReadyAPs)
819 	INJ_SKIP(d, 1)
820 	INJ_U16(d, s->usAnimSurface)
821 	INJ_U16(d, s->sZLevel)
822 	INJ_BOOL(d, s->fPrevInWater)
823 	INJ_BOOL(d, s->fGoBackToAimAfterHit)
824 	INJ_I16(d, s->sWalkToAttackGridNo)
825 	INJ_I16(d, s->sWalkToAttackWalkToCost)
826 	INJ_SKIP(d, 7)
827 	INJ_BOOL(d, s->fForceShade)
828 	INJ_SKIP(d, 2)
829 	INJ_PTR(d, s->pForcedShade)
830 	INJ_I8(d, s->bDisplayDamageCount)
831 	INJ_I8(d, s->fDisplayDamage)
832 	INJ_I16(d, s->sDamage)
833 	INJ_I16(d, s->sDamageX)
834 	INJ_I16(d, s->sDamageY)
835 	INJ_SKIP(d, 1)
836 	INJ_I8(d, s->bDoBurst)
837 	INJ_I16(d, s->usUIMovementMode)
838 	INJ_SKIP(d, 1)
839 	INJ_BOOL(d, s->fUIMovementFast)
840 	INJ_SKIP(d, 2)
841 	INJ_I32(d, s->BlinkSelCounter)
842 	INJ_I32(d, s->PortraitFlashCounter)
843 	INJ_BOOL(d, s->fDeadSoundPlayed)
844 	INJ_U8(d, s->ubProfile)
845 	INJ_U8(d, s->ubQuoteRecord)
846 	INJ_U8(d, s->ubQuoteActionID)
847 	INJ_U8(d, s->ubBattleSoundID)
848 	INJ_BOOL(d, s->fClosePanel)
849 	INJ_BOOL(d, s->fClosePanelToDie)
850 	INJ_U8(d, s->ubClosePanelFrame)
851 	INJ_BOOL(d, s->fDeadPanel)
852 	INJ_U8(d, s->ubDeadPanelFrame)
853 	INJ_SKIP(d, 2)
854 	INJ_I16(d, s->sPanelFaceX)
855 	INJ_I16(d, s->sPanelFaceY)
856 	INJ_I8(d, s->bNumHitsThisTurn)
857 	INJ_SKIP(d, 1)
858 	INJ_U16(d, s->usQuoteSaidFlags)
859 	INJ_I8(d, s->fCloseCall)
860 	INJ_I8(d, s->bLastSkillCheck)
861 	INJ_I8(d, s->ubSkillCheckAttempts)
862 	INJ_SKIP(d, 1)
863 	INJ_I8(d, s->bStartFallDir)
864 	INJ_I8(d, s->fTryingToFall)
865 	INJ_U8(d, s->ubPendingDirection)
866 	INJ_SKIP(d, 1)
867 	INJ_U32(d, s->uiAnimSubFlags)
868 	INJ_U8(d, s->bAimShotLocation)
869 	INJ_U8(d, s->ubHitLocation)
870 	INJ_SKIP(d, 16)
871 	INJ_I16A(d, s->sSpreadLocations, lengthof(s->sSpreadLocations))
872 	INJ_BOOL(d, s->fDoSpread)
873 	INJ_SKIP(d, 1)
874 	INJ_I16(d, s->sStartGridNo)
875 	INJ_I16(d, s->sEndGridNo)
876 	INJ_I16(d, s->sForcastGridno)
877 	INJ_I16(d, s->sZLevelOverride)
878 	INJ_I8(d, s->bMovedPriorToInterrupt)
879 	INJ_SKIP(d, 3)
880 	INJ_I32(d, s->iEndofContractTime)
881 	INJ_I32(d, s->iStartContractTime)
882 	INJ_I32(d, s->iTotalContractLength)
883 	INJ_I32(d, s->iNextActionSpecialData)
884 	INJ_U8(d, s->ubWhatKindOfMercAmI)
885 	INJ_I8(d, s->bAssignment)
886 	INJ_SKIP(d, 1)
887 	INJ_BOOL(d, s->fForcedToStayAwake)
888 	INJ_I8(d, s->bTrainStat)
889 	INJ_SKIP(d, 1)
890 	INJ_I16(d, s->sSectorX)
891 	INJ_I16(d, s->sSectorY)
892 	INJ_I8(d, s->bSectorZ)
893 	INJ_SKIP(d, 1)
894 	INJ_I32(d, s->iVehicleId)
895 	INJ_PTR(d, s->pMercPath)
896 	INJ_U8(d, s->fHitByGasFlags)
897 	INJ_SKIP(d, 1)
898 	INJ_U16(d, s->usMedicalDeposit)
899 	INJ_U16(d, s->usLifeInsurance)
900 	INJ_SKIP(d, 26)
901 	INJ_I32(d, s->iStartOfInsuranceContract)
902 	INJ_U32(d, s->uiLastAssignmentChangeMin)
903 	INJ_I32(d, s->iTotalLengthOfInsuranceContract)
904 	INJ_U8(d, s->ubSoldierClass)
905 	INJ_U8(d, s->ubAPsLostToSuppression)
906 	INJ_BOOL(d, s->fChangingStanceDueToSuppression)
907 	INJ_SOLDIER(d, s->suppressor)
908 	INJ_SKIP(d, 4)
909 	INJ_U8(d, s->ubCivilianGroup)
910 	INJ_SKIP(d, 3)
911 	INJ_U32(d, s->uiChangeLevelTime)
912 	INJ_U32(d, s->uiChangeHealthTime)
913 	INJ_U32(d, s->uiChangeStrengthTime)
914 	INJ_U32(d, s->uiChangeDexterityTime)
915 	INJ_U32(d, s->uiChangeAgilityTime)
916 	INJ_U32(d, s->uiChangeWisdomTime)
917 	INJ_U32(d, s->uiChangeLeadershipTime)
918 	INJ_U32(d, s->uiChangeMarksmanshipTime)
919 	INJ_U32(d, s->uiChangeExplosivesTime)
920 	INJ_U32(d, s->uiChangeMedicalTime)
921 	INJ_U32(d, s->uiChangeMechanicalTime)
922 	INJ_U32(d, s->uiUniqueSoldierIdValue)
923 	INJ_I8(d, s->bBeingAttackedCount)
924 	INJ_I8A(d, s->bNewItemCount, lengthof(s->bNewItemCount))
925 	INJ_I8A(d, s->bNewItemCycleCount, lengthof(s->bNewItemCycleCount))
926 	INJ_BOOL(d, s->fCheckForNewlyAddedItems)
927 	INJ_I8(d, s->bEndDoorOpenCode)
928 	INJ_U8(d, s->ubScheduleID)
929 	INJ_I16(d, s->sEndDoorOpenCodeData)
930 	INJ_I32(d, s->NextTileCounter)
931 	INJ_BOOL(d, s->fBlockedByAnotherMerc)
932 	INJ_I8(d, s->bBlockedByAnotherMercDirection)
933 	INJ_U16(d, s->usAttackingWeapon)
934 	INJ_I8(d, s->bWeaponMode)
935 	INJ_SOLDIER(d, s->target)
936 	INJ_I8(d, s->bAIScheduleProgress)
937 	INJ_SKIP(d, 1)
938 	INJ_I16(d, s->sOffWorldGridNo)
939 	INJ_SKIP(d, 2)
940 	INJ_PTR(d, s->pAniTile)
941 	INJ_I8(d, s->bCamo)
942 	INJ_SKIP(d, 1)
943 	INJ_I16(d, s->sAbsoluteFinalDestination)
944 	INJ_U8(d, s->ubHiResDirection)
945 	INJ_SKIP(d, 1)
946 	INJ_U8(d, s->ubLastFootPrintSound)
947 	INJ_I8(d, s->bVehicleID)
948 	INJ_I8(d, s->fPastXDest)
949 	INJ_I8(d, s->fPastYDest)
950 	INJ_I8(d, s->bMovementDirection)
951 	INJ_SKIP(d, 1)
952 	INJ_I16(d, s->sOldGridNo)
953 	INJ_U16(d, s->usDontUpdateNewGridNoOnMoveAnimChange)
954 	INJ_I16(d, s->sBoundingBoxWidth)
955 	INJ_I16(d, s->sBoundingBoxHeight)
956 	INJ_I16(d, s->sBoundingBoxOffsetX)
957 	INJ_I16(d, s->sBoundingBoxOffsetY)
958 	INJ_U32(d, s->uiTimeSameBattleSndDone)
959 	INJ_I8(d, s->bOldBattleSnd)
960 	INJ_SKIP(d, 1)
961 	INJ_BOOL(d, s->fContractPriceHasIncreased)
962 	INJ_SKIP(d, 1)
963 	INJ_U32(d, s->uiBurstSoundID)
964 	INJ_BOOL(d, s->fFixingSAMSite)
965 	INJ_BOOL(d, s->fFixingRobot)
966 	INJ_I8(d, s->bSlotItemTakenFrom)
967 	INJ_BOOL(d, s->fSignedAnotherContract)
968 	INJ_SOLDIER(d, s->auto_bandaging_medic)
969 	INJ_BOOL(d, s->fDontChargeTurningAPs)
970 	INJ_SOLDIER(d, s->robot_remote_holder)
971 	INJ_SKIP(d, 1)
972 	INJ_U32(d, s->uiTimeOfLastContractUpdate)
973 	INJ_I8(d, s->bTypeOfLastContract)
974 	INJ_I8(d, s->bTurnsCollapsed)
975 	INJ_I8(d, s->bSleepDrugCounter)
976 	INJ_U8(d, s->ubMilitiaKills)
977 	INJ_I8A(d, s->bFutureDrugEffect, lengthof(s->bFutureDrugEffect))
978 	INJ_I8A(d, s->bDrugEffectRate, lengthof(s->bDrugEffectRate))
979 	INJ_I8A(d, s->bDrugEffect, lengthof(s->bDrugEffect))
980 	INJ_I8A(d, s->bDrugSideEffectRate, lengthof(s->bDrugSideEffectRate))
981 	INJ_I8A(d, s->bDrugSideEffect, lengthof(s->bDrugSideEffect))
982 	INJ_SKIP(d, 2)
983 	INJ_I8(d, s->bBlindedCounter)
984 	INJ_BOOL(d, s->fMercCollapsedFlag)
985 	INJ_BOOL(d, s->fDoneAssignmentAndNothingToDoFlag)
986 	INJ_BOOL(d, s->fMercAsleep)
987 	INJ_BOOL(d, s->fDontChargeAPsForStanceChange)
988 	INJ_SKIP(d, 2)
989 	INJ_U8(d, s->ubTurnsUntilCanSayHeardNoise)
990 	INJ_U16(d, s->usQuoteSaidExtFlags)
991 	INJ_U16(d, s->sContPathLocation)
992 	INJ_I8(d, s->bGoodContPath)
993 	INJ_SKIP(d, 1)
994 	INJ_I8(d, s->bNoiseLevel)
995 	INJ_I8(d, s->bRegenerationCounter)
996 	INJ_I8(d, s->bRegenBoostersUsedToday)
997 	INJ_I8(d, s->bNumPelletsHitBy)
998 	INJ_I16(d, s->sSkillCheckGridNo)
999 	INJ_U8(d, s->ubLastEnemyCycledID)
1000 	INJ_U8(d, s->ubPrevSectorID)
1001 	INJ_U8(d, s->ubNumTilesMovesSinceLastForget)
1002 	INJ_I8(d, s->bTurningIncrement)
1003 	INJ_U32(d, s->uiBattleSoundID)
1004 	INJ_BOOL(d, s->fSoldierWasMoving)
1005 	INJ_BOOL(d, s->fSayAmmoQuotePending)
1006 	INJ_U16(d, s->usValueGoneUp)
1007 	INJ_U8(d, s->ubNumLocateCycles)
1008 	INJ_U8(d, s->ubDelayedMovementFlags)
1009 	INJ_BOOL(d, s->fMuzzleFlash)
1010 	INJ_SOLDIER(d, s->CTGTTarget)
1011 	INJ_I32(d, s->PanelAnimateCounter)
1012 	UINT32 const checksum = MercChecksum(*s);
1013 	INJ_U32(d, checksum)
1014 	INJ_I8(d, s->bCurrentCivQuote)
1015 	INJ_I8(d, s->bCurrentCivQuoteDelta)
1016 	INJ_U8(d, s->ubMiscSoldierFlags)
1017 	INJ_U8(d, s->ubReasonCantFinishMove)
1018 	INJ_I16(d, s->sLocationOfFadeStart)
1019 	INJ_U8(d, s->bUseExitGridForReentryDirection)
1020 	INJ_SKIP(d, 1)
1021 	INJ_U32(d, s->uiTimeSinceLastSpoke)
1022 	INJ_U8(d, s->ubContractRenewalQuoteCode)
1023 	INJ_SKIP(d, 1)
1024 	INJ_I16(d, s->sPreTraversalGridNo)
1025 	INJ_U32(d, s->uiXRayActivatedTime)
1026 	INJ_I8(d, s->bTurningFromUI)
1027 	INJ_I8(d, s->bPendingActionData5)
1028 	INJ_I8(d, s->bDelayedStrategicMoraleMod)
1029 	INJ_U8(d, s->ubDoorOpeningNoise)
1030 	INJ_SKIP(d, 4)
1031 	INJ_U8(d, s->ubLeaveHistoryCode)
1032 	INJ_BOOL(d, s->fDontUnsetLastTargetFromTurn)
1033 	INJ_I8(d, s->bOverrideMoveSpeed)
1034 	INJ_BOOL(d, s->fUseMoverrideMoveSpeed)
1035 	INJ_U32(d, s->uiTimeSoldierWillArrive)
1036 	INJ_SKIP(d, 1)
1037 	INJ_BOOL(d, s->fUseLandingZoneForArrival)
1038 	INJ_BOOL(d, s->fFallClockwise)
1039 	INJ_I8(d, s->bVehicleUnderRepairID)
1040 	INJ_I32(d, s->iTimeCanSignElsewhere)
1041 	INJ_I8(d, s->bHospitalPriceModifier)
1042 	INJ_SKIP(d, 3)
1043 	INJ_U32(d, s->uiStartTimeOfInsuranceContract)
1044 	INJ_BOOL(d, s->fRTInNonintAnim)
1045 	INJ_BOOL(d, s->fDoingExternalDeath)
1046 	INJ_I8(d, s->bCorpseQuoteTolerance)
1047 	INJ_SKIP(d, 1)
1048 	INJ_I32(d, s->iPositionSndID)
1049 	INJ_U32(d, s->uiTuringSoundID)
1050 	INJ_U8(d, s->ubLastDamageReason)
1051 	INJ_BOOL(d, s->fComplainedThatTired)
1052 	INJ_I16A(d, s->sLastTwoLocations, lengthof(s->sLastTwoLocations))
1053 	INJ_SKIP(d, 2)
1054 	INJ_I32(d, s->uiTimeSinceLastBleedGrunt)
1055 	INJ_SOLDIER(d, s->next_to_previous_attacker)
1056 	INJ_SKIP(d, 39)
1057 	Assert(d.getConsumed() == 2328);
1058 }
1059