protected internal override void OnInit() { List <SynchedMissionObject> synchedMissionObjectList = this.GameEntity.CollectObjectsWithTag <SynchedMissionObject>("rope"); if (synchedMissionObjectList.Count > 0) { this._rope = synchedMissionObjectList[0]; } this._body = this.GameEntity.CollectObjectsWithTag <SynchedMissionObject>("body")[0]; this.RotationObject = this._body; this._verticalAdjuster = this.GameEntity.CollectChildrenEntitiesWithTag("vertical_adjuster")[0]; if ((NativeObject)this._verticalAdjuster.Skeleton != (NativeObject)null) { this._verticalAdjuster.Skeleton.SetAnimationAtChannel(this.MangonelAimAnimation, 0); } this._verticalAdjusterStartingLocalFrame = this._verticalAdjuster.GetFrame(); this._verticalAdjusterStartingLocalFrame = this._body.GameEntity.GetBoneEntitialFrameWithIndex((byte)0).TransformToLocal(this._verticalAdjusterStartingLocalFrame); base.OnInit(); this.timeGapBetweenShootActionAndProjectileLeaving = 0.23f; this.timeGapBetweenShootingEndAndReloadingStart = 0.0f; this._rotateStandingPoints = new List <StandingPoint>(); if (this.StandingPoints != null) { foreach (StandingPoint standingPoint in this.StandingPoints) { if (standingPoint.GameEntity.HasTag("rotate")) { if (standingPoint.GameEntity.HasTag("left") && this._rotateStandingPoints.Count > 0) { this._rotateStandingPoints.Insert(0, standingPoint); } else { this._rotateStandingPoints.Add(standingPoint); } } } MatrixFrame globalFrame = this._body.GameEntity.GetGlobalFrame(); this._standingPointLocalIKFrames = new MatrixFrame[this.StandingPoints.Count]; for (int index = 0; index < this.StandingPoints.Count; ++index) { this._standingPointLocalIKFrames[index] = this.StandingPoints[index].GameEntity.GetGlobalFrame().TransformToLocal(globalFrame); this.StandingPoints[index].AddComponent((UsableMissionObjectComponent) new ClearHandInverseKinematicsOnStopUsageComponent()); } } this._missileBoneIndex = (byte)Skeleton.GetBoneIndexFromName(this.SkeletonOwnerObjects[0].GameEntity.Skeleton.GetName(), this.MissileBoneName); this.ApplyAimChange(); foreach (StandingPoint reloadStandingPoint in this.ReloadStandingPoints) { if (reloadStandingPoint != this.PilotStandingPoint) { this._reloadWithoutPilot = reloadStandingPoint; } } this.EnemyRangeToStopUsing = 7f; this.SetScriptComponentToTick(this.GetTickRequirement()); }
protected override void HandleAgentStopUsingStandingPoint( Agent agent, StandingPoint standingPoint) { if (standingPoint is StandingPointWithVolumeBox && agent.IsUsingGameObject) { agent.DisableScriptedCombatMovement(); } base.HandleAgentStopUsingStandingPoint(agent, standingPoint); }
protected override float GetDetachmentWeightAux(BattleSideEnum side) { if (this.IsDisabledForBattleSideAI(side)) { return(float.MinValue); } this._usableStandingPoints.Clear(); int num = 0; foreach (StonePile.ThrowingPoint throwingPoint in this._throwingPoints) { if (this.IsThrowingPointAssignable(throwingPoint)) { ++num; } } bool flag1 = false; bool flag2 = false; for (int index = 0; index < this.StandingPoints.Count; ++index) { StandingPoint standingPoint = this.StandingPoints[index]; if (standingPoint.GameEntity.HasTag(this.AmmoPickUpTag) && num > 0) { --num; if (standingPoint.IsUsableBySide(side)) { if (!standingPoint.HasAIMovingTo) { if (!flag2) { this._usableStandingPoints.Clear(); } flag2 = true; } else if (flag2 || standingPoint.MovingAgents.FirstOrDefault <KeyValuePair <Agent, UsableMissionObject.MoveInfo> >().Key.Formation.Team.Side != side) { continue; } flag1 = true; this._usableStandingPoints.Add((index, standingPoint)); } } } this._areUsableStandingPointsVacant = flag2; if (!flag1) { return(float.MinValue); } if (flag2) { return(1f); } return(!this._isDetachmentRecentlyEvaluated ? 0.1f : 0.01f); }
public static Agent GetSuitableAgentForStandingPoint( StonePile usableMachine, StandingPoint standingPoint, IEnumerable <Agent> agents, List <Agent> usedAgents) { float num = float.MinValue; Agent agent1 = (Agent)null; foreach (Agent agent2 in agents) { if (StonePileAI.IsAgentAssignable(agent2) && !standingPoint.IsDisabledForAgent(agent2) && (double)standingPoint.GetUsageScoreForAgent(agent2) > (double)num) { num = standingPoint.GetUsageScoreForAgent(agent2); agent1 = agent2; } } return(agent1); }
public static Agent GetSuitableAgentForStandingPoint( StonePile stonePile, StandingPoint standingPoint, IEnumerable <AgentValuePair <float> > agents, List <Agent> usedAgents, float weight) { float num = float.MinValue; Agent agent1 = (Agent)null; foreach (AgentValuePair <float> agent2 in agents) { Agent agent3 = agent2.Agent; if (StonePileAI.IsAgentAssignable(agent3) && !standingPoint.IsDisabledForAgent(agent3) && (double)standingPoint.GetUsageScoreForAgent(agent3) > (double)num) { num = standingPoint.GetUsageScoreForAgent(agent3); agent1 = agent3; } } return(agent1); }
public static Agent GetSuitableAgentForStandingPoint( UsableMachine usableMachine, StandingPoint standingPoint, IEnumerable <Agent> agents, List <Agent> usedAgents) { if (usableMachine.AmmoPickUpPoints.Contains(standingPoint) && usableMachine.StandingPoints.Any <StandingPoint>((Func <StandingPoint, bool>)(standingPoint2 => (standingPoint2.IsDeactivated || standingPoint2.HasUser || standingPoint2.HasAIMovingTo) && !standingPoint2.GameEntity.HasTag(usableMachine.AmmoPickUpTag) && standingPoint2 is StandingPointWithWeaponRequirement))) { return((Agent)null); } IEnumerable <Agent> source = agents.Where <Agent>((Func <Agent, bool>)(a => { if (usedAgents.Contains(a) || !a.IsAIControlled || (!a.IsActive() || a.IsRunningAway) || (a.AIUseGameObjectIsEnabled() || a.AIMoveToGameObjectIsEnabled() || standingPoint.IsDisabledForAgent(a))) { return(false); } return(a.Formation == null || !a.Formation.IsUnitDetached(a)); })); return(!source.Any <Agent>() ? (Agent)null : source.MaxBy <Agent, float>((Func <Agent, float>)(a => standingPoint.GetUsageScoreForAgent(a)))); }
private bool AssignAgentToStandingPoint(StandingPoint standingPoint, Agent agent) { if (standingPoint == null || agent == null || !StonePileAI.IsAgentAssignable(agent)) { return(false); } int slotIndex = this.StandingPoints.IndexOf(standingPoint); if (slotIndex >= 0) { ((IDetachment)this).AddAgent(agent, slotIndex); if (agent.Formation != null) { agent.Formation.DetachUnit(agent, this.IsLoose); agent.Detachment = (IDetachment)this; agent.DetachmentWeight = this.GetWeightOfStandingPoint(standingPoint); return(true); } } return(false); }
float?IDetachment.GetWeightOfAgentAtNextSlot( IEnumerable <Agent> candidates, out Agent match) { BattleSideEnum side = candidates.First <Agent>().Team.Side; StandingPoint standingPointFor = this.GetSuitableStandingPointFor(side, (Agent)null, candidates, (IEnumerable <AgentValuePair <float> >)null); if (standingPointFor != null) { match = StonePileAI.GetSuitableAgentForStandingPoint(this, standingPointFor, candidates, new List <Agent>()); if (match == null) { return(new float?()); } float?weightOfNextSlot = ((IDetachment)this).GetWeightOfNextSlot(side); float num = 1f; return(!weightOfNextSlot.HasValue ? new float?() : new float?(weightOfNextSlot.GetValueOrDefault() * num)); } match = (Agent)null; return(new float?()); }
public static Agent GetSuitableAgentForStandingPoint( UsableMachine usableMachine, StandingPoint standingPoint, IEnumerable <AgentValuePair <float> > agents, List <Agent> usedAgents, float weight) { if (usableMachine.IsStandingPointNotUsedOnAccountOfBeingAmmoLoad(standingPoint)) { return((Agent)null); } IEnumerable <AgentValuePair <float> > source = agents.Where <AgentValuePair <float> >((Func <AgentValuePair <float>, bool>)(ap => { Agent agent = ap.Agent; if (usedAgents.Contains(agent) || !agent.IsAIControlled || (!agent.IsActive() || agent.IsRunningAway) || (agent.AIUseGameObjectIsEnabled() || agent.AIMoveToGameObjectIsEnabled() || standingPoint.IsDisabledForAgent(agent))) { return(false); } return(agent.Formation == null || !agent.Formation.IsUnitDetached(agent) || (double)agent.DetachmentWeight * 0.400000005960464 > (double)weight); })); return(!source.Any <AgentValuePair <float> >() ? (Agent)null : source.MaxBy <AgentValuePair <float>, float>((Func <AgentValuePair <float>, float>)(a => standingPoint.GetUsageScoreForAgent(a))).Agent); }
public override StandingPoint GetBestPointAlternativeTo( StandingPoint standingPoint, Agent agent) { if (!this.AmmoPickUpPoints.Contains(standingPoint)) { return(standingPoint); } Vec3 globalPosition = standingPoint.GameEntity.GlobalPosition; float num1 = globalPosition.DistanceSquared(agent.Position); StandingPoint standingPoint1 = standingPoint; foreach (StandingPoint ammoPickUpPoint in this.AmmoPickUpPoints) { globalPosition = ammoPickUpPoint.GameEntity.GlobalPosition; float num2 = globalPosition.DistanceSquared(agent.Position); if ((double)num2 < (double)num1 && (!ammoPickUpPoint.HasUser && !ammoPickUpPoint.HasAIMovingTo || ammoPickUpPoint.IsInstantUse) && (!ammoPickUpPoint.IsDeactivated && !ammoPickUpPoint.IsDisabledForAgent(agent))) { num1 = num2; standingPoint1 = ammoPickUpPoint; } } return(standingPoint1); }
protected internal override void OnTick(float dt) { base.OnTick(dt); if (!this.GameEntity.IsVisibleIncludeParents()) { return; } if (this.State == RangedSiegeWeapon.WeaponState.WaitingBeforeProjectileLeaving) { this.UpdateProjectilePosition(); } if ((NativeObject)this._verticalAdjuster.Skeleton != (NativeObject)null) { this._verticalAdjuster.Skeleton.SetAnimationParameterAtChannel(0, (float)(((double)this.currentReleaseAngle - (double)this.BottomReleaseAngleRestriction) / ((double)this.TopReleaseAngleRestriction - (double)this.BottomReleaseAngleRestriction))); } MatrixFrame parent = this.SkeletonOwnerObjects[0].GameEntity.GetBoneEntitialFrameWithIndex((byte)0).TransformToParent(this._verticalAdjusterStartingLocalFrame); this._verticalAdjuster.SetFrame(ref parent); MatrixFrame globalFrame = this._body.GameEntity.GetGlobalFrame(); for (int index = 0; index < this.StandingPoints.Count; ++index) { if (this.StandingPoints[index].HasUser) { if (MBMath.IsBetween((int)this.StandingPoints[index].UserAgent.GetCurrentActionType(0), 44, 48)) { this.StandingPoints[index].UserAgent.ClearHandInverseKinematics(); } else if (this.StandingPoints[index] != this.PilotStandingPoint) { if (this.StandingPoints[index].UserAgent.GetCurrentAction(1) != this._reload2IdleActionIndex) { this.StandingPoints[index].UserAgent.SetHandInverseKinematicsFrameFromActionChannel(1, this._standingPointLocalIKFrames[index], globalFrame); } else { this.StandingPoints[index].UserAgent.ClearHandInverseKinematics(); } } else { this.StandingPoints[index].UserAgent.SetHandInverseKinematicsFrameFromActionChannel(1, this._standingPointLocalIKFrames[index], globalFrame); } } } if (!GameNetwork.IsClientOrReplay) { for (int index = 0; index < this._rotateStandingPoints.Count; ++index) { StandingPoint rotateStandingPoint = this._rotateStandingPoints[index]; if (rotateStandingPoint.HasUser && !rotateStandingPoint.UserAgent.SetActionChannel(1, index == 0 ? this._rotateLeftAnimationActionIndex : this._rotateRightAnimationActionIndex)) { rotateStandingPoint.UserAgent.StopUsingGameObject(); } } if (this.PilotAgent != null) { ActionIndexCache currentAction = this.PilotAgent.GetCurrentAction(1); if (this.State == RangedSiegeWeapon.WeaponState.WaitingBeforeProjectileLeaving) { if (MBMath.IsBetween((int)this.PilotAgent.GetCurrentActionType(0), 44, 48)) { if (this.PilotAgent.GetCurrentAction(0) != Mangonel.act_strike_bent_over) { this.PilotAgent.SetActionChannel(0, Mangonel.act_strike_bent_over); } } else if (!this.PilotAgent.SetActionChannel(1, this._shootAnimationActionIndex)) { this.PilotAgent.StopUsingGameObject(); } } else if (!this.PilotAgent.SetActionChannel(1, this._idleAnimationActionIndex) && currentAction != this._reload1AnimationActionIndex && currentAction != this._shootAnimationActionIndex) { this.PilotAgent.StopUsingGameObject(); } } if (this._reloadWithoutPilot.HasUser) { Agent userAgent = this._reloadWithoutPilot.UserAgent; if (!userAgent.SetActionChannel(1, this._reload2IdleActionIndex) && userAgent.GetCurrentAction(1) != this._reload2AnimationActionIndex) { userAgent.StopUsingGameObject(); } } foreach (StandingPointWithWeaponRequirement pickUpStandingPoint in this.AmmoPickUpStandingPoints) { if (pickUpStandingPoint.HasUser) { Agent userAgent = pickUpStandingPoint.UserAgent; ActionIndexCache currentAction = userAgent.GetCurrentAction(1); if (!(currentAction == Mangonel.act_pickup_boulder_begin)) { if (currentAction == Mangonel.act_pickup_boulder_end) { MissionWeapon weapon = new MissionWeapon(this.OriginalMissileItem, (ItemModifier)null, (Banner)null, (short)1); userAgent.EquipWeaponToExtraSlotAndWield(ref weapon); userAgent.StopUsingGameObject(); this.ConsumeAmmo(); if (!this.IsDeactivated && !this.LoadAmmoStandingPoint.HasUser && (!this.LoadAmmoStandingPoint.HasAIMovingTo && this.HasAIPickingUpAmmo) && this.CurrentlyUsedAmmoPickUpPoint == pickUpStandingPoint) { this.LoadAmmoStandingPoint.SetIsDeactivatedSynched(false); if (userAgent.IsAIControlled) { StandingPoint standingPointFor = this.GetSuitableStandingPointFor(this.Side, userAgent); if (standingPointFor != null) { ((IDetachment)this).AddAgent(userAgent); if (userAgent.Formation != null) { userAgent.Formation.DetachUnit(userAgent, this.IsLoose); userAgent.Detachment = (IDetachment)this; userAgent.DetachmentWeight = this.GetWeightOfStandingPoint(standingPointFor); } } } } } else if (!userAgent.SetActionChannel(1, Mangonel.act_pickup_boulder_begin)) { userAgent.StopUsingGameObject(); } } } } } switch (this.State) { case RangedSiegeWeapon.WeaponState.LoadingAmmo: if (GameNetwork.IsClientOrReplay || !this.LoadAmmoStandingPoint.HasUser) { break; } Agent userAgent1 = this.LoadAmmoStandingPoint.UserAgent; if (userAgent1.GetCurrentAction(1) == this._loadAmmoEndAnimationActionIndex) { EquipmentIndex wieldedItemIndex = userAgent1.GetWieldedItemIndex(Agent.HandIndex.MainHand); if (wieldedItemIndex != EquipmentIndex.None && userAgent1.Equipment[wieldedItemIndex].CurrentUsageItem.WeaponClass == this.OriginalMissileItem.PrimaryWeapon.WeaponClass) { this.ChangeProjectileEntityServer(userAgent1, userAgent1.Equipment[wieldedItemIndex].Item.StringId); userAgent1.RemoveEquippedWeapon(wieldedItemIndex); this._timeElapsedAfterLoading = 0.0f; this.Projectile.SetVisibleSynched(true); this.State = RangedSiegeWeapon.WeaponState.WaitingBeforeIdle; break; } this.LoadAmmoStandingPoint.UserAgent.StopUsingGameObject(); break; } if (!(userAgent1.GetCurrentAction(1) != this._loadAmmoBeginAnimationActionIndex) || this.LoadAmmoStandingPoint.UserAgent.SetActionChannel(1, this._loadAmmoBeginAnimationActionIndex)) { break; } for (EquipmentIndex equipmentIndex = EquipmentIndex.WeaponItemBeginSlot; equipmentIndex < EquipmentIndex.NumAllWeaponSlots; ++equipmentIndex) { if (!userAgent1.Equipment[equipmentIndex].IsEmpty && userAgent1.Equipment[equipmentIndex].CurrentUsageItem.WeaponClass == this.OriginalMissileItem.PrimaryWeapon.WeaponClass) { userAgent1.RemoveEquippedWeapon(equipmentIndex); } } this.LoadAmmoStandingPoint.UserAgent.StopUsingGameObject(); break; case RangedSiegeWeapon.WeaponState.WaitingBeforeIdle: this._timeElapsedAfterLoading += dt; if ((double)this._timeElapsedAfterLoading <= 1.0) { break; } this.State = RangedSiegeWeapon.WeaponState.Idle; break; case RangedSiegeWeapon.WeaponState.Reloading: using (List <StandingPoint> .Enumerator enumerator = this.ReloadStandingPoints.GetEnumerator()) { while (enumerator.MoveNext()) { StandingPoint current = enumerator.Current; if (current.HasUser) { ActionIndexCache currentAction = current.UserAgent.GetCurrentAction(1); if (currentAction == this._reload1AnimationActionIndex || currentAction == this._reload2AnimationActionIndex) { current.UserAgent.SetCurrentActionProgress(1, this._body.GameEntity.Skeleton.GetAnimationParameterAtChannel(0)); } else if (!GameNetwork.IsClientOrReplay) { ActionIndexCache actionIndexCache = current == this.PilotStandingPoint ? this._reload1AnimationActionIndex : this._reload2AnimationActionIndex; if (!current.UserAgent.SetActionChannel(1, actionIndexCache, startProgress: this._body.GameEntity.Skeleton.GetAnimationParameterAtChannel(0))) { current.UserAgent.StopUsingGameObject(); } } } } break; } } }
protected virtual void OnTick( Func <Agent, bool> isAgentManagedByThisMachineAI, Team potentialUsersTeam, float dt) { this._tickCounter = ++this._tickCounter % 200; foreach (StandingPoint standingPoint in this.UsableMachine.StandingPoints) { if (isAgentManagedByThisMachineAI(standingPoint.UserAgent)) { Agent userAgent = standingPoint.UserAgent; if (this.HasActionCompleted || potentialUsersTeam != null && this.UsableMachine.IsDisabledForBattleSideAI(potentialUsersTeam.Side) || userAgent.IsRunningAway) { this.HandleAgentStopUsingStandingPoint(userAgent, standingPoint); } } List <KeyValuePair <Agent, UsableMissionObject.MoveInfo> > list = standingPoint.MovingAgents.ToList <KeyValuePair <Agent, UsableMissionObject.MoveInfo> >(); List <Agent> agentList = new List <Agent>(); for (int index = list.Count - 1; index >= 0; --index) { Agent key = list[index].Key; if (isAgentManagedByThisMachineAI(key)) { if (this.HasActionCompleted || potentialUsersTeam != null && this.UsableMachine.IsDisabledForBattleSideAI(potentialUsersTeam.Side) || key.IsRunningAway) { this.HandleAgentStopUsingStandingPoint(key, standingPoint); } else { if (standingPoint.HasAlternative() && this.UsableMachine.IsInRangeToCheckAlternativePoints(key)) { StandingPoint pointAlternativeTo = this.UsableMachine.GetBestPointAlternativeTo(standingPoint, key); if (pointAlternativeTo != standingPoint) { standingPoint.OnMoveToStopped(key); key.AIMoveToGameObjectEnable((UsableMissionObject)pointAlternativeTo, this.GetScriptedFrameFlags(key)); if (standingPoint == this.UsableMachine.CurrentlyUsedAmmoPickUpPoint) { this.UsableMachine.CurrentlyUsedAmmoPickUpPoint = pointAlternativeTo; continue; } continue; } } if (standingPoint.HasUserPositionsChanged(key)) { WorldFrame userFrameForAgent = standingPoint.GetUserFrameForAgent(key); string debugString = this.UsableMachine.GameEntity.Name + " Id:" + (object)this.UsableMachine.Id.Id + " " + standingPoint.GameEntity.Name; key.SetScriptedPositionAndDirection(ref userFrameForAgent.Origin, userFrameForAgent.Rotation.f.AsVec2.RotationInRadians, false, this.GetScriptedFrameFlags(key), debugString); } if (!standingPoint.IsDisabled && !standingPoint.HasUser && !key.IsAIPaused() && key.CanReachAndUseObject((UsableMissionObject)standingPoint, standingPoint.GetUserFrameForAgent(key).Origin.GetGroundVec3().DistanceSquared(key.Position))) { key.UseGameObject((UsableMissionObject)standingPoint); key.SetScriptedFlags(key.GetScriptedFlags() & ~standingPoint.DisableScriptedFrameFlags); agentList.Add(key); } } } } } if (!((NativeObject)this._lastActiveWaitStandingPoint != (NativeObject)this.UsableMachine.WaitEntity)) { return; } foreach (Formation formation in potentialUsersTeam.FormationsIncludingSpecial.Where <Formation>((Func <Formation, bool>)(f => f.IsUsingMachine(this.UsableMachine) && f.MovementOrder.OrderEnum == MovementOrder.MovementOrderEnum.FollowEntity && (NativeObject)f.MovementOrder.TargetEntity == (NativeObject)this._lastActiveWaitStandingPoint))) { formation.MovementOrder = !(this is SiegeTowerAI) ? MovementOrder.MovementOrderFollowEntity(this.UsableMachine.WaitEntity) : this.NextOrder; } this._lastActiveWaitStandingPoint = this.UsableMachine.WaitEntity; }
protected virtual void HandleAgentStopUsingStandingPoint( Agent agent, StandingPoint standingPoint) { agent.StopUsingGameObject(); }
protected override StandingPoint GetSuitableStandingPointFor( BattleSideEnum side, Agent agent = null, IEnumerable <Agent> agents = null, IEnumerable <AgentValuePair <float> > agentValuePairs = null) { List <Agent> agentList = new List <Agent>(); if (agents == null) { if (agent != null) { agentList.Add(agent); } else if (agentValuePairs != null) { foreach (AgentValuePair <float> agentValuePair in agentValuePairs) { agentList.Add(agentValuePair.Agent); } } } else { agentList = new List <Agent>(agents); } bool flag1 = false; StandingPoint standingPoint1 = (StandingPoint)null; for (int index1 = 0; index1 < this._throwingPoints.Count && standingPoint1 == null; ++index1) { StonePile.ThrowingPoint throwingPoint = this._throwingPoints[index1]; if (this.IsThrowingPointAssignable(throwingPoint)) { bool flag2 = agentList == null; for (int index2 = 0; !flag2 && index2 < agentList.Count; ++index2) { flag2 = !throwingPoint.StandingPoint.IsDisabledForAgent(agentList[index2]); } if (flag2) { if (standingPoint1 == null) { standingPoint1 = (StandingPoint)throwingPoint.StandingPoint; } } else { flag1 = true; } } } for (int index1 = 0; index1 < this.StandingPoints.Count && standingPoint1 == null; ++index1) { StandingPoint standingPoint2 = this.StandingPoints[index1]; if (!standingPoint2.IsDeactivated && (standingPoint2.IsInstantUse || !standingPoint2.HasUser && !standingPoint2.HasAIMovingTo) && (!standingPoint2.GameEntity.HasTag(this.ThrowingPointTag) && (flag1 || !standingPoint2.GameEntity.HasTag(this.AmmoPickUpTag)))) { for (int index2 = 0; index2 < agentList.Count && standingPoint1 == null; ++index2) { if (!standingPoint2.IsDisabledForAgent(agentList[index2])) { standingPoint1 = standingPoint2; } } if (agentList.Count == 0) { standingPoint1 = standingPoint2; } } } return(standingPoint1); }