Beispiel #1
0
// IMPORTANT: This same callback is used both for initial training and for continue training prompt
// use 'gfYesNoPromptIsForContinue' flag to tell them apart
void PayMilitiaTrainingYesNoBoxCallback( UINT8 bExitValue )
{
	CHAR16 sString[ 128 ];

	Assert( giTotalCostOfTraining > 0 );

	// yes
  if( bExitValue == MSG_BOX_RETURN_YES )
	{
		// does the player have enough
		if( LaptopSaveInfo.iCurrentBalance >= giTotalCostOfTraining )
		{
			if( gfYesNoPromptIsForContinue )
			{
				ContinueTrainingInThisSector();
			}
			else
			{
				StartTrainingInAllUnpaidTrainableSectors();
			}

#ifdef JA2BETAVERSION
			// put this BEFORE training gets handled to avoid detecting an error everytime a sector completes training
			VerifyTownTrainingIsPaidFor();
#endif

			// this completes the training prompt sequence
			pMilitiaTrainerSoldier = NULL;
		}
		else	// can't afford it
		{
			StopTimeCompression();

			swprintf( sString, L"%s", pMilitiaConfirmStrings[ 2 ] );
			DoMapMessageBox( MSG_BOX_BASIC_STYLE, sString, MAP_SCREEN, MSG_BOX_FLAG_OK, CantTrainMilitiaOkBoxCallback );
		}
	}
	else if( bExitValue == MSG_BOX_RETURN_NO )
	{
		StopTimeCompression();

		MilitiaTrainingRejected();
	}

	return;
}
Beispiel #2
0
BOOLEAN StrategicRemoveMerc( SOLDIERTYPE *pSoldier )
{
	UINT8	ubHistoryCode=0;


	if ( gfInContractMenuFromRenewSequence )
	{
		EndCurrentContractRenewal( );
	}

	// ATE: Determine which HISTORY ENTRY to use...
	if ( pSoldier->ubLeaveHistoryCode == 0 )
	{
		// Default use contract expired reason...
		pSoldier->ubLeaveHistoryCode = HISTORY_MERC_CONTRACT_EXPIRED;
	}

	ubHistoryCode = pSoldier->ubLeaveHistoryCode;

	//if the soldier is DEAD
	if( pSoldier->stats.bLife <= 0 )
	{
		AddCharacterToDeadList( pSoldier );
	}

	//else if the merc was fired
	else if( ubHistoryCode == HISTORY_MERC_FIRED || pSoldier->bAssignment == ASSIGNMENT_POW )
	{
		AddCharacterToFiredList( pSoldier );
	}

	//The merc is leaving for some other reason
	else
	{
		AddCharacterToOtherList( pSoldier );
	}


	if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC )
	{
		SetupProfileInsertionDataForSoldier( pSoldier );
	}

	if (IsVehicle(pSoldier))
	{
		// for some reason, vehicles have their own idea of handling group ids
		RemovePlayerFromGroup(pVehicleList[ pSoldier->bVehicleID ].ubMovementGroup, pSoldier);
	}
	//remove him from the soldier structure
	if( pSoldier->bAssignment >= ON_DUTY )
	{
		// is he/she in a mvt group, if so, remove and destroy the group
		if( pSoldier->ubGroupID )
		{
			if ( pSoldier->bAssignment != VEHICLE )
			{ //Can only remove groups if they aren't persistant (not in a squad or vehicle)
				RemoveGroup( pSoldier->ubGroupID );
			}
			else
			{
				// remove him from any existing merc slot he could be in
				RemoveMercSlot( pSoldier );
		TakeSoldierOutOfVehicle( pSoldier );
			}
		}

	}
	else
	{
		RemoveCharacterFromSquads( pSoldier );
	}

	// if the merc is not dead
	if( gMercProfiles[ pSoldier->ubProfile ].bMercStatus != MERC_IS_DEAD )
	{
		//Set the status to returning home ( delay the merc for rehire )
		gMercProfiles[ pSoldier->ubProfile ].bMercStatus = MERC_RETURNING_HOME;

		// specify how long the merc will continue to be unavailable
		gMercProfiles[ pSoldier->ubProfile ].uiDayBecomesAvailable = 1 + Random(2);		// 1-2 days

		HandleSoldierLeavingWithLowMorale( pSoldier );
		HandleSoldierLeavingForAnotherContract( pSoldier );
	}


	//add an entry in the history page for the firing/quiting of the merc
	// ATE: Don't do this if they are already dead!
	if ( !( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) )
	{
		AddHistoryToPlayersLog( ubHistoryCode, pSoldier->ubProfile, GetWorldTotalMin(), pSoldier->sSectorX, pSoldier->sSectorY );
	}

	//if the merc was a POW, remember it becuase the merc cant show up in AIM or MERC anymore
	if( pSoldier->bAssignment	== ASSIGNMENT_POW )
	{
		gMercProfiles[ pSoldier->ubProfile ].bMercStatus = MERC_FIRED_AS_A_POW;
	}

	//else the merc CAN get his medical deposit back
	else
	{
		//Determine how much of a Medical deposit is going to be refunded to the player
		CalculateMedicalDepositRefund( pSoldier );
	}

	//remove the merc from the tactical
	TacticalRemoveSoldier( pSoldier->ubID );

	// Check if we should remove loaded world...
	CheckAndHandleUnloadingOfCurrentWorld();

	if ( guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN )
	{
		ReBuildCharactersList( );
	}

	fMapPanelDirty = TRUE;
	fTeamPanelDirty = TRUE;
	fCharacterInfoPanelDirty = TRUE;

	// stop time compression so player can react to the departure
	StopTimeCompression();

	// WDS: This allows for replacing dead IMP mercs.	See "BtnIMPBeginScreenDoneCallback" in "IMP Begin Screen.cpp"
	if( ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__PLAYER_CHARACTER ) &&
		( gMercProfiles[ pSoldier->ubProfile ].bMercStatus == MERC_IS_DEAD ) ) {
		// Replace the name with an empty string
		wcsncpy( gMercProfiles[ pSoldier->ubProfile ].zName, L"", 1 );
	}

	// ATE: update team panels....
	UpdateTeamPanelAssignments( );
 
	// And unpause the @#$@#$ interface
	UnLockPauseState();
	UnPauseGame();


	if (is_client)
		send_dismiss(pSoldier->ubID);

	return( TRUE );
}
void UpdateBuddyAndHatedCounters( void )
{
	INT8									bMercID;
	INT32									iLoop;
	INT8									bOtherID;
	INT8									bLastTeamID;
	UINT8									ubOtherProfileID;
	SOLDIERTYPE						*pSoldier;
	SOLDIERTYPE						*pOtherSoldier;
	MERCPROFILESTRUCT			*pProfile;
	BOOLEAN								fSameGroupOnly;

	BOOLEAN								fUpdatedTimeTillNextHatedComplaint = FALSE;

	bMercID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
	bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;

	//loop though all the mercs
  for ( pSoldier = MercPtrs[ bMercID ]; bMercID <= bLastTeamID; bMercID++,pSoldier++)
	{	
		fSameGroupOnly = FALSE;

		//if the merc is active and on a combat assignment
		if ( pSoldier->bActive && pSoldier->bAssignment < ON_DUTY )
		{
			pProfile = &(gMercProfiles[ pSoldier->ubProfile ]);

			// if we're moving, we only check vs other people in our squad
			if (pSoldier->ubGroupID != 0 && PlayerIDGroupInMotion( pSoldier->ubGroupID ))
			{
				fSameGroupOnly = TRUE;
			}

			fUpdatedTimeTillNextHatedComplaint = FALSE;

			bOtherID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;

			for ( pOtherSoldier = MercPtrs[ bOtherID ]; bOtherID <= bLastTeamID; bOtherID++, pOtherSoldier++)
			{	
				// is this guy in the same sector and on active duty (or in the same moving group)

				if (bOtherID != bMercID && pOtherSoldier->bActive && pOtherSoldier->bAssignment < ON_DUTY )
				{
					if (fSameGroupOnly)
					{
						// all we have to check is the group ID
						if (pSoldier->ubGroupID != pOtherSoldier->ubGroupID)
						{
							continue;
						}
					}
					else
					{
						// check to see if the location is the same
						if (pOtherSoldier->sSectorX != pSoldier->sSectorX ||
							  pOtherSoldier->sSectorY != pSoldier->sSectorY ||
								pOtherSoldier->bSectorZ != pSoldier->bSectorZ)
						{
							continue;
						}
						
						// if the OTHER soldier is in motion then we don't do anything!
						if (pOtherSoldier->ubGroupID != 0 && PlayerIDGroupInMotion( pOtherSoldier->ubGroupID ))
						{
							continue;
						}
					}

					ubOtherProfileID = pOtherSoldier->ubProfile;

					for ( iLoop = 0; iLoop < 4; iLoop++ )
					{
						switch( iLoop )
						{
							case 0:
							case 1:
								if (pProfile->bHated[iLoop] == ubOtherProfileID)
								{
									// arrgs, we're on assignment with the person we loathe!
									if ( pProfile->bHatedCount[iLoop] > 0 )
									{
										pProfile->bHatedCount[iLoop]--;
										if ( pProfile->bHatedCount[iLoop] == 0 && pSoldier->bInSector && gTacticalStatus.fEnemyInSector )
										{
											// just reduced count to 0 but we have enemy in sector... 
											pProfile->bHatedCount[iLoop] = 1;
										}
										else if (pProfile->bHatedCount[iLoop] > 0 && (pProfile->bHatedCount[iLoop] == pProfile->bHatedTime[iLoop] / 2 || ( pProfile->bHatedCount[iLoop] < pProfile->bHatedTime[iLoop] / 2 && pProfile->bHatedCount[iLoop] % TIME_BETWEEN_HATED_COMPLAINTS == 0 ) ) )
										{
											// complain!
											if (iLoop == 0)
											{
												TacticalCharacterDialogue( pSoldier, QUOTE_HATED_MERC_ONE );
											}
											else
											{
												TacticalCharacterDialogue( pSoldier, QUOTE_HATED_MERC_TWO );
											}
											StopTimeCompression();
										}
										else if ( pProfile->bHatedCount[iLoop] == 0 )
										{
											// zero count!
											if (pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC || pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC )
											{
												// MERC mercs leave now!
												if (iLoop == 0)
												{
													TacticalCharacterDialogue( pSoldier, QUOTE_MERC_QUIT_HATED1 );
												}
												else
												{
													TacticalCharacterDialogue( pSoldier, QUOTE_MERC_QUIT_HATED2 );
												}

												// Leave now! ( handle equipment too )....
												TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING, 0,0 );

												pSoldier->ubLeaveHistoryCode = HISTORY_MERC_QUIT;
											}
											else
											{
												// complain!
												if (iLoop == 0)
												{
													TacticalCharacterDialogue( pSoldier, QUOTE_HATED_MERC_ONE );
												}
												else
												{
													TacticalCharacterDialogue( pSoldier, QUOTE_HATED_MERC_TWO );
												}
												pProfile->ubTimeTillNextHatedComplaint = TIME_BETWEEN_HATED_COMPLAINTS - 1;
											}
										}
									}
									else
									{
										// if we haven't updated the time till our next complaint, do so
										// if it's 0, gripe.
										if ( !fUpdatedTimeTillNextHatedComplaint )
										{
											if ( pProfile->ubTimeTillNextHatedComplaint == 0 )
											{
												pProfile->ubTimeTillNextHatedComplaint = TIME_BETWEEN_HATED_COMPLAINTS - 1;
											}
											else
											{
												pProfile->ubTimeTillNextHatedComplaint--;
											}
											fUpdatedTimeTillNextHatedComplaint = TRUE;
										}

										if ( pProfile->ubTimeTillNextHatedComplaint == 0 )
										{
											// complain!
											if (iLoop == 0)
											{
												TacticalCharacterDialogue( pSoldier, QUOTE_HATED_MERC_ONE );
											}
											else
											{
												TacticalCharacterDialogue( pSoldier, QUOTE_HATED_MERC_TWO );
											}
										}									
									}
								}
								break;
							case 2:
								if (pProfile->bLearnToHate == ubOtherProfileID)
								{
									if ( pProfile->bLearnToHateCount > 0 )
									{
										pProfile->bLearnToHateCount--;
										if ( pProfile->bLearnToHateCount == 0 && pSoldier->bInSector && gTacticalStatus.fEnemyInSector )
										{
											// just reduced count to 0 but we have enemy in sector... 
											pProfile->bLearnToHateCount = 1;
										}
										else if (pProfile->bLearnToHateCount > 0 && (pProfile->bLearnToHateCount == pProfile->bLearnToHateTime / 2 || pProfile->bLearnToHateCount < pProfile->bLearnToHateTime / 2 && pProfile->bLearnToHateCount % TIME_BETWEEN_HATED_COMPLAINTS == 0 ) )
										{
											// complain!
											TacticalCharacterDialogue( pSoldier, QUOTE_LEARNED_TO_HATE_MERC );
											StopTimeCompression();
										}
										else if (pProfile->bLearnToHateCount == 0)
										{
											// set as bHated[2];
											pProfile->bHated[2] = pProfile->bLearnToHate;
											pProfile->bMercOpinion[ubOtherProfileID] = HATED_OPINION;

											if (pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC || (pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC && (pSoldier->ubProfile == DEVIN || pSoldier->ubProfile == SLAY || pSoldier->ubProfile == IGGY || pSoldier->ubProfile == CONRAD ) ) )
											{
												// Leave now! ( handle equipment too )....
												TacticalCharacterDialogue( pSoldier, QUOTE_MERC_QUIT_LEARN_TO_HATE );
												TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING, 0,0 );
												pSoldier->ubLeaveHistoryCode = HISTORY_MERC_QUIT;

											}
											else if (pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC)
											{
												// whine again
												TacticalCharacterDialogue( pSoldier, QUOTE_LEARNED_TO_HATE_MERC );
											}

										}									
										if (pProfile->bLearnToHateCount < pProfile->bLearnToHateTime / 2)
										{
											// gradual opinion drop
											pProfile->bMercOpinion[ubOtherProfileID] += (HATED_OPINION - pProfile->bMercOpinion[ubOtherProfileID]) / (pProfile->bLearnToHateCount + 1);
										}
									}
									else
									{
										if ( !fUpdatedTimeTillNextHatedComplaint )
										{
											if ( pProfile->ubTimeTillNextHatedComplaint == 0 )
											{
												pProfile->ubTimeTillNextHatedComplaint = TIME_BETWEEN_HATED_COMPLAINTS - 1;
											}
											else
											{
												pProfile->ubTimeTillNextHatedComplaint--;
											}
											fUpdatedTimeTillNextHatedComplaint = TRUE;
										}

										if ( pProfile->ubTimeTillNextHatedComplaint == 0 )
										{
											// complain!
											TacticalCharacterDialogue( pSoldier, QUOTE_LEARNED_TO_HATE_MERC );										
										}
									}
								}							
								break;
							case 3:
								if (pProfile->bLearnToLikeCount > 0	&& pProfile->bLearnToLike == ubOtherProfileID)
								{
									pProfile->bLearnToLikeCount--;
									if (pProfile->bLearnToLikeCount == 0)
									{
										// add to liked!
										pProfile->bBuddy[2] = pProfile->bLearnToLike;
										pProfile->bMercOpinion[ubOtherProfileID] = BUDDY_OPINION;
									}
									else if (pProfile->bLearnToLikeCount < pProfile->bLearnToLikeTime / 2)
									{								
										// increase opinion of them!
										pProfile->bMercOpinion[ubOtherProfileID] += (BUDDY_OPINION - pProfile->bMercOpinion[ubOtherProfileID]) / (pProfile->bLearnToLikeCount + 1);
										break;
									}
								}
								break;
						}																	
					}
				}
			}
		}
	}
}
void IssueHeadMinerQuote( INT8 bMineIndex, UINT8 ubQuoteType )
{
	UINT8 ubHeadMinerIndex = 0;
	UINT16 usHeadMinerProfileId = 0;
	INT8 bQuoteNum = 0;
	UINT8 ubFaceIndex = 0;
	BOOLEAN fForceMapscreen = FALSE;
	INT16 sXPos, sYPos;


	Assert( ( bMineIndex >= 0 ) && ( bMineIndex < MAX_NUMBER_OF_MINES ) );
	Assert( ubQuoteType < NUM_HEAD_MINER_STRATEGIC_QUOTES );
	Assert( CheckFact( FACT_MINERS_PLACED, 0 ) );

	ubHeadMinerIndex = GetHeadMinerIndexForMine( bMineIndex );
	usHeadMinerProfileId = gHeadMinerData[ ubHeadMinerIndex ].usProfileId;

	// make sure the miner ain't dead
	if (gMercProfiles[ usHeadMinerProfileId ].bLife < OKLIFE)
	{
		// debug message
		ScreenMsg( MSG_FONT_RED, MSG_DEBUG, L"Head Miner #%s can't talk (quote #%d)", gMercProfiles[ usHeadMinerProfileId ].zNickname, ubQuoteType);
		return;
	}

	bQuoteNum = gHeadMinerData[ ubHeadMinerIndex ].bQuoteNum[ ubQuoteType ];
	Assert( bQuoteNum != -1 );

	ubFaceIndex = ( UINT8 ) uiExternalStaticNPCFaces[ gHeadMinerData[ ubHeadMinerIndex ].ubExternalFace ];

	// transition to mapscreen is not necessary for "creatures gone" quote - player is IN that mine, so he'll know
	if ( ubQuoteType != HEAD_MINER_STRATEGIC_QUOTE_CREATURES_GONE )
	{
		fForceMapscreen = TRUE;
	}


	// decide where the miner's face and text box should be positioned in order to not obscure the mine he's in as it flashes
	switch ( bMineIndex )
	{
		case MINE_GRUMM:
			sXPos = DEFAULT_EXTERN_PANEL_X_POS, sYPos = DEFAULT_EXTERN_PANEL_Y_POS;
			break;
		case MINE_CAMBRIA:
			sXPos = DEFAULT_EXTERN_PANEL_X_POS, sYPos = DEFAULT_EXTERN_PANEL_Y_POS;
			break;
		case MINE_ALMA:
			sXPos = DEFAULT_EXTERN_PANEL_X_POS, sYPos = DEFAULT_EXTERN_PANEL_Y_POS;
			break;
		case MINE_DRASSEN:
			sXPos = DEFAULT_EXTERN_PANEL_X_POS, sYPos = 135;
			break;
		case MINE_CHITZENA:
			sXPos = DEFAULT_EXTERN_PANEL_X_POS, sYPos = 117;
			break;

		// there's no head miner in San Mona, this is an error!
		case MINE_SAN_MONA:
		default:
			Assert( FALSE );
			sXPos = DEFAULT_EXTERN_PANEL_X_POS, sYPos = DEFAULT_EXTERN_PANEL_Y_POS;
			break;
	}

	SetExternMapscreenSpeechPanelXY( sXPos, sYPos );

	// cause this quote to come up for this profile id and an indicator to flash over the mine sector
	HandleMinerEvent( gHeadMinerData[ ubHeadMinerIndex ].ubExternalFace, gMineLocation[ bMineIndex ].sSectorX, gMineLocation[ bMineIndex ].sSectorY, (INT16) bQuoteNum, fForceMapscreen );

	// stop time compression with any miner quote - these are important events.
	StopTimeCompression();
}
void HandleExitsFromMapScreen( void )
{
	// if going somewhere
	if ( gbExitingMapScreenToWhere != -1 )
	{
		// delay all exits by one frame...
		if( gfOneFramePauseOnExit == TRUE )
		{
			gfOneFramePauseOnExit = FALSE;
			return;
		}

		// make sure it's still legal to do this!
		if ( AllowedToExitFromMapscreenTo( gbExitingMapScreenToWhere ) )
		{
			// see where we're trying to go
			switch ( gbExitingMapScreenToWhere )
			{
				case MAP_EXIT_TO_LAPTOP:
					fLapTop = TRUE;
					SetPendingNewScreen(LAPTOP_SCREEN);

					if( gfExtraBuffer )
					{ //Then initiate the transition animation from the mapscreen to laptop...
						BlitBufferToBuffer( FRAME_BUFFER, guiEXTRABUFFER, 0, 0, 640, 480 );
						gfStartMapScreenToLaptopTransition = TRUE;
					}
					break;

				case MAP_EXIT_TO_TACTICAL:
					#ifdef JA2DEMO
						HandleLeavingOfMapScreenDuringDemo( );
						gfDontStartTransitionFromLaptop = TRUE;
					#else
						SetCurrentWorldSector( sSelMapX, sSelMapY, ( UINT8 )iCurrentMapSectorZ );
					#endif

					break;

				case MAP_EXIT_TO_OPTIONS:
					guiPreviousOptionScreen = guiCurrentScreen;
					SetPendingNewScreen( OPTIONS_SCREEN );
					break;

				case MAP_EXIT_TO_SAVE:
				case MAP_EXIT_TO_LOAD:
					gfCameDirectlyFromGame = TRUE;
					guiPreviousOptionScreen = guiCurrentScreen;
					SetPendingNewScreen( SAVE_LOAD_SCREEN );
					break;

				default:
					// invalid exit type
					Assert( FALSE );
			}

			// time compression during mapscreen exit doesn't seem to cause any problems, but turn it off as early as we can
			StopTimeCompression();

			// now leaving mapscreen
			fLeavingMapScreen = TRUE;
		}

		// cancel exit, either we're on our way, or we're not allowed to go
		gbExitingMapScreenToWhere = -1;
	}
}
Beispiel #6
0
BOOLEAN HandleStrategicDeath( SOLDIERTYPE *pSoldier )
{
	// add the guy to the dead list
	//AddCharacterToDeadList( pSoldier );

	// If in a vehicle, remove them!
	if( ( pSoldier->bAssignment == VEHICLE ) && ( pSoldier->iVehicleId != -1 ) )
	{
		// remove from vehicle
		TakeSoldierOutOfVehicle( pSoldier );
	}

	// if not in mapscreen
	if ( !(guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
	{
		// ATE; At least make them dead!
		if( ( pSoldier->bAssignment != ASSIGNMENT_DEAD ) )
		{
			SetTimeOfAssignmentChangeForMerc( pSoldier );
		}

		ChangeSoldiersAssignment( pSoldier, ASSIGNMENT_DEAD );
	}
	else if( ( pSoldier->stats.bLife == 0 )&&( pSoldier->bAssignment != ASSIGNMENT_DEAD ) )
	{
		// died in mapscreen

		fReDrawFace = TRUE;

		// dead
		if( ( pSoldier->bAssignment != ASSIGNMENT_DEAD ) )
		{
			SetTimeOfAssignmentChangeForMerc( pSoldier );
		}

		ChangeSoldiersAssignment( pSoldier, ASSIGNMENT_DEAD );

		//s et breath and breath max to 0
		pSoldier->bBreath = pSoldier->bBreathMax = 0;

		// rebuild list
		ReBuildCharactersList( );

		// ste merc as dead
		// pSoldier->flags.fUIdeadMerc = TRUE;

		// attempt to remove character from squad
		RemoveCharacterFromSquads( pSoldier );

		// handle any passign comments by grunts
		HandleSoldierDeadComments( pSoldier );

		// put the dead guys down
		AddDeadSoldierToUnLoadedSector( ( UINT8 ) ( pSoldier->sSectorX ), ( UINT8 )( pSoldier->sSectorY ), pSoldier->bSectorZ, pSoldier, RandomGridNo(), ADD_DEAD_SOLDIER_TO_SWEETSPOT );

		fTeamPanelDirty = TRUE;
		fMapPanelDirty = TRUE;
		fCharacterInfoPanelDirty = TRUE;

		StopTimeCompression();
	}

	return( TRUE );
}