public void CreatePortal() { string[] portalsId = Storage.GenWorld.GenericPortal(1, SaveLoadData.TypePrefabs.PortalBlue); foreach (string idPortal in portalsId) { if (ReaderScene.ExistID(idPortal)) { var info = ReaderScene.GetInfoID(idPortal); ModelNPC.PortalData portalNext = info.Data as ModelNPC.PortalData; if (portalNext != null) { Portals.Add(portalNext); //... Check on Real string fieldName = string.Empty; Helper.GetNameFieldByPosit(ref fieldName, portalNext.Position); bool isZonaReal = Helper.IsValidPiontInZona(portalNext.Position.x, portalNext.Position.y); if (!isZonaReal) { portalNext.IsReality = false; } if (!portalNext.IsReality && isZonaReal) { Storage.GenGrid.LoadObjectToReal(fieldName); } //else // portalNext.IsReality = false; } } } }
private static void CeckJobPass(ref ModelNPC.ObjectData result, ModelNPC.GameDataAlien dataAlien) { dataAlien.JobPass++; if (dataAlien.JobPass > 2) { Debug.Log(Storage.EventsUI.ListLogAdd = "[[[ JobPass Go To Home ]]] " + dataAlien.NameObject); if (dataAlien.PortalId == null) { Storage.PortalsManager.SetHome(dataAlien); } var info = ReaderScene.GetInfoID(dataAlien.PortalId); if (info != null) { if (dataAlien.JobPass >= 5) { result = info.Data; } else { var portal = info.Data as ModelNPC.PortalData; if (portal != null && portal.Resources == null && portal.Resources.Count > 0) { result = info.Data; } } } dataAlien.JobPass = 0; } }
public static void AddConstruction(ModelNPC.ObjectData spawnedBuild, ModelNPC.GameDataAlien alien) { if (string.IsNullOrEmpty(spawnedBuild.PortalId)) { Debug.Log(Storage.EventsUI.ListLogAdd = "### Portal AddConstruction = spawnedBuild.PortalId - is null"); return; } ModelNPC.PortalData portal = Storage.PortalsManager.Portals.Find(p => p.Id == spawnedBuild.PortalId); // info.Data as ModelNPC.PortalData; if (portal == null) { Debug.Log(Storage.EventsUI.ListLogAdd = "### Portal AddConstruction = Storage.PortalsManager.Portals - not found = " + spawnedBuild.PortalId); Storage.PortalsManager.SetHome(alien); spawnedBuild.PortalId = alien.PortalId; var info = ReaderScene.GetInfoID(spawnedBuild.PortalId); if (info == null) { Debug.Log(Storage.EventsUI.ListLogAdd = "### Portal AddConstruction = spawnedBuild.Id - not found = " + spawnedBuild.Id); } else { portal = info.Data as ModelNPC.PortalData; } } //%CLUSTER FILL if (spawnedBuild.IsFloor()) { Vector2Int posField = Helper.GetFieldPositByWorldPosit(spawnedBuild.Position); int clusterFill = AlienJobsManager.GetClusterSize(posField.x, posField.y, spawnedBuild.TypePrefab); (spawnedBuild as ModelNPC.TerraData).ClusterFillSize = clusterFill; (spawnedBuild as ModelNPC.TerraData).DataCreate = DateTime.Now; } if (portal != null) { portal.AddConstruction(spawnedBuild.TypePrefab, spawnedBuild.Id); } else { Debug.Log(Storage.EventsUI.ListLogAdd = "### Portal AddConstruction = portal is null"); } }
private bool IsFreeLocationPortalConstruction( ref Dictionary <Vector2Int, bool> excludedFreeFileds, int x, int y, int lenSize, SaveLoadData.TypePrefabs buildType, ModelNPC.PortalData portal) { ReaderScene.DataObjectInfoID infoNext; Vector2 requestPosition = new Vector2(x, y); Vector2 biuldPosition; int portaBuildingyardSize = 2; List <string> bouldingId; portal.ConstructionsId.TryGetValue(buildType, out bouldingId); if (bouldingId == null) { return(true); } biuldPosition = Helper.GetFieldPositByWorldPosit(portal.Position); if (Vector3.Distance(requestPosition, biuldPosition) < portaBuildingyardSize) { return(false); } foreach (var nextID in bouldingId) { infoNext = ReaderScene.GetInfoID(nextID); if (infoNext == null || infoNext.Data == null) { continue; } biuldPosition = Helper.GetFieldPositByWorldPosit(infoNext.Data.Position); if (Vector3.Distance(requestPosition, biuldPosition) < lenSize) { return(false); } } return(true); }
public bool ChildrenPreparationIncubation() { string id; int fieldX_NPC = 0; int fieldY_NPC = 0; int fieldX_Portal = 0; int fieldY_Portal = 0; bool isParkingLock = false; Helper.GetFieldPositByWorldPosit(ref fieldX_Portal, ref fieldY_Portal, Position); if (!Storage.Instance.ReaderSceneIsValid) { return(false); } for (int i = ChildrensId.Count - 1; i >= 0; i--) { id = ChildrensId[i]; var dataNPC = ReaderScene.GetInfoID(id); if (dataNPC == null) { ChildrensId.RemoveAt(i); } else { Helper.GetFieldPositByWorldPosit(ref fieldX_NPC, ref fieldY_NPC, dataNPC.Data.Position); isParkingLock = fieldX_NPC == fieldX_Portal && fieldY_NPC == fieldY_Portal; if (isParkingLock) { return(false); } } } if (ChildrensId.Count == 0) { return(true); } return(true); }
public void FindJobBuildLocation(ref ModelNPC.ObjectData result, ref AlienJob job, ModelNPC.GameDataAlien dataAien, int distantionWay) { if (!Storage.Person.CollectionAlienJob.ContainsKey(dataAien.TypePrefab)) { return; } ReaderScene.DataObjectInfoID info; ModelNPC.PortalData portal = null; List <string> listId; TypesBiomNPC biomType = Helper.GetBiomByTypeModel(dataAien.TypePrefab); SaveLoadData.TypePrefabs floorType = PortalBiomFloorsBase[biomType]; result = null; if (string.IsNullOrEmpty(dataAien.PortalId)) { return; } info = ReaderScene.GetInfoID(dataAien.PortalId); if (info == null) { return; } portal = info.Data as ModelNPC.PortalData; portal.ConstructionsId.TryGetValue(floorType, out listId); if (listId == null) { return; } List <AlienJob> jobs = null; Vector2Int test_fieldPos = Vector2Int.zero; Vector2Int keyField; int x = 0; int y = 0; string nameField = string.Empty; string key = string.Empty; bool isFieldJobValid = true; bool isValidFieldBuildFar = true; bool isValidFar = true; bool isInventoryContainTargetResource = false; temp_excludedFreeFileds.Clear(); //Get jobs Storage.Person.CollectionAlienJob.TryGetValue(dataAien.TypePrefab, out jobs); Helper.GetFieldPositByWorldPosit(ref x, ref y, dataAien.Position); temp_findedFloorsIdForBuild.Clear(); //Fill floors portal for building System.Random rnd = new System.Random(); temp_findedFloorsIdForBuild = listId.OrderBy(p => rnd.Next()).ToList(); List <ModelNPC.TerraData> floorsData = new List <ModelNPC.TerraData>(); foreach (string nextRndID in temp_findedFloorsIdForBuild) { info = ReaderScene.GetInfoID(nextRndID); if (info == null) { continue; } if (!(info.Data is ModelNPC.TerraData)) { continue; } floorsData.Add(info.Data as ModelNPC.TerraData); } //Floors portal foreach (ModelNPC.TerraData floorData in floorsData.OrderBy(p => p.ClusterFillSize)) { isValidFieldBuildFar = true; isFieldJobValid = true; keyField = Helper.GetFieldPositByWorldPosit(floorData.Position); //Select job by target resource foreach (AlienJob jobItem in jobs.Where(p => p.TargetResource == floorData.TypePrefab)) //fix all jobs for type Resource { job = jobItem; if (job != null) { if (job.Job != TypesJobs.Build) { continue; } // Test field on free PoolGameObjects.TypePoolPrefabs typePoolResult = AlienJobsManager.CheckFieldJobValid(ref isFieldJobValid, job, floorData); //Filter: Build switch (job.Job) { case TypesJobs.Build: isValidFar = false; //Test inventory filled isInventoryContainTargetResource = dataAien.Inventory != null && dataAien.Inventory.EqualsInv(job.ResourceResult); if (!isInventoryContainTargetResource) { isValidFar = false; } else if (typePoolResult == PoolGameObjects.TypePoolPrefabs.PoolFloor) { //test near objects type of me (Cluster) //AlienJobsManager.IsMeCluster(ref isValidFar, keyField.x, keyField.y, job.ResourceResult, job.ClusterSize); job = null; continue; } else { //Build Prefab if (isValidFieldBuildFar) //Test Free location { //isValidFieldBuildFar = IsFreeLocationPortalConstruction(ref temp_excludedFreeFileds, // keyField.x, keyField.y, job.BuildingyardSize, dataAien.Inventory.TypePrefabObject, portal); //TypesBiomNPC isValidFieldBuildFar = IsFreeLocationPortalConstruction(ref temp_excludedFreeFileds, keyField.x, keyField.y, job.BuildingyardSize, job.ResourceResult, portal); //TypesBiomNPC } isValidFar = isValidFieldBuildFar; } if (!isValidFar || !isFieldJobValid) { job = null; continue; } break; } result = floorData; return; } } } temp_findedFloorsIdForBuild.Clear(); dataAien.JobPass = 0; job = null; }
/* * public static bool CheckJobAlien(ModelNPC.GameDataAlien p_dataNPC, GameActionPersonController controller = null) * { * AlienJob job = p_dataNPC.Job; * if (job != null) * { * string fieldAlien = string.Empty; * string fieldTarget = string.Empty; * Helper.GetNameFieldByPosit(ref fieldAlien, p_dataNPC.Position); * SaveLoadData.TypePrefabs jobResourceTarget = job.TargetResource; * //Target object * ReaderScene.DataObjectInfoID targetInfo = ReaderScene.GetInfoID(p_dataNPC.TargetID); * if (targetInfo != null) * { * if (!targetInfo.TestIsValud()) * { * p_dataNPC.TargetID = null; * } * else * { * int distField = 0; * Helper.GetDistatntionFields(ref distField, targetInfo.Data.Position, p_dataNPC.Position); * Helper.GetNameFieldByPosit(ref fieldTarget, targetInfo.Data.Position); * * ModelNPC.PortalData portal = targetInfo.Data as ModelNPC.PortalData; * if (distField < 2) * { * bool isExitTargetResource = false; * if (p_dataNPC.Inventory == null) * { * p_dataNPC.Inventory = DataObjectInventory.EmptyInventory(); * //Debug.Log(Storage.EventsUI.ListLogAdd = "## JOB: dataNPC.Inventory is null"); * } else * isExitTargetResource = job.TargetResource.ToString() == p_dataNPC.Inventory.TypeInventoryObject.ToString(); * * // --- TO PORTAL * if (portal != null) * { * if (isExitTargetResource) * { * //***** Back to HOME **** (trget is Portal) * //p_dataNPC.InventoryObject is ModelNPC; * Storage.PortalsManager.AddResourceFromAlien(portal, p_dataNPC); * } * // --- TAKE RESOURCE * bool checkStorageResource = Storage.PortalsManager.CheckStorageResourceForAlien(portal, p_dataNPC); * if (!checkStorageResource && isExitTargetResource) * { * //End job * p_dataNPC.Job = null; * p_dataNPC.TargetID = string.Empty; * p_dataNPC.TargetPosition = Vector3.zero; * } * //Continue job * if (p_dataNPC.Job != null && p_dataNPC.Job.Job != TypesJobs.Bathering) * return true; * } * // --- TO LOOT && BUILD * else * { * //Test job on target //@JOB@ * if (targetInfo.Data.TypePrefab == jobResourceTarget) * { * //if (!job.IsJobCompleted && !job.IsJobRun) * //if (p_dataNPC.CurrentAction == GameActionPersonController.NameActionsPerson.Target.ToString()) * //p_dataNPC.CurrentAction != GameActionPersonController.NameActionsPerson.Work.ToString()) * if (p_dataNPC.CurrentAction != GameActionPersonController.NameActionsPerson.CompletedLoot.ToString() && * p_dataNPC.CurrentAction != GameActionPersonController.NameActionsPerson.Work.ToString()) * { * //job.IsJobRun = true; * //p_dataNPC.CurrentAction = GameActionPersonController.NameActionsPerson.Target.ToString(); * //GameActionPersonController.RequestActionNPC(p_dataNPC, GameActionPersonController.NameActionsPerson.Work, null); * GameActionPersonController.ExecuteActionNPC(p_dataNPC, GameActionPersonController.NameActionsPerson.Work, controller, true); * } * //if(job.IsJobCompleted) * if (p_dataNPC.CurrentAction == GameActionPersonController.NameActionsPerson.CompletedLoot.ToString()) * { * if (job.Job == TypesJobs.Build) * { * if (p_dataNPC.Inventory == null || p_dataNPC.Inventory.IsEmpty || p_dataNPC.Inventory.TypeInventoryObject.ToString() != job.ResourceResult.ToString()) * { * Debug.Log(Storage.EventsUI.ListLogAdd = "### JOB BUILD: Inventory is Empty >> " + job.Job.ToString() + " " + job.TargetResource + " R:" + job.ResourceResult); * //p_dataNPC.Inventory = DataObjectInventory.EmptyInventory(); * return false; * } * } * //p_dataNPC.CurrentAction = GameActionPersonController.NameActionsPerson.Target.ToString(); * GameActionPersonController.ExecuteActionNPC(p_dataNPC, GameActionPersonController.NameActionsPerson.Move, controller, true); * // **** FIND RESOURCE **** * //---Replace object * //1. Remove resource * Vector3 posTarget = targetInfo.Data.Position; * * bool isTargetTypeTrue = false; * PoolGameObjects.TypePoolPrefabs typePoolResource = CheckFieldJobValid(ref isTargetTypeTrue, job, targetInfo.Data); * if (job.Job == TypesJobs.Build) * { * if (typePoolResource == PoolGameObjects.TypePoolPrefabs.PoolFloor) * GenericWorldManager.ClearLayerObject(targetInfo.Data); * //---- TEST * //else * // Debug.Log(Storage.EventsUI.ListLogAdd = "TypesJobs.Build .. Not Remove resource: " + job.ResourceResult.ToString() + " >> " + targetInfo.Data.NameObject); * } * else * GenericWorldManager.ClearLayerObject(targetInfo.Data); * //2. Create new resource * if (job.ResourceResult != SaveLoadData.TypePrefabs.PrefabField) * { * bool isTestMe = false; * PaletteMapController.SelCheckOptDel deleteOpt = PaletteMapController.SelCheckOptDel.None; * PaletteMapController.SelCheckOptDel checkOpt = PaletteMapController.SelCheckOptDel.DelTerra; * if (typePoolResource != PoolGameObjects.TypePoolPrefabs.PoolFloor && * typePoolResource != PoolGameObjects.TypePoolPrefabs.PoolPerson) * { * checkOpt = PaletteMapController.SelCheckOptDel.DelPrefab; * isTestMe = true; * } * * //Storage.GenWorld.GenericPrefabOnWorld(job.ResourceResult, posTarget); * ModelNPC.ObjectData spawnObject = Storage.GenWorld.GetCreatePrefab(job.ResourceResult, targetInfo.Field); * bool isSpawned = Storage.Data.AddDataObjectInGrid(spawnObject, * targetInfo.Field, "CheckJobAlien", * p_modeDelete: deleteOpt, * p_modeCheck: checkOpt, * p_dataNPC: p_dataNPC); * spawnObject.PortalId = p_dataNPC.PortalId; * if (!isSpawned) * Debug.Log(Storage.EventsUI.ListLogAdd = "### JOB [" + job.Job.ToString() + "]: Not Spawn " + spawnObject.NameObject); * else if(job.Job == TypesJobs.Build) * ManagerPortals.AddConstruction(spawnObject, p_dataNPC); * } * bool isZonaReal = Helper.IsValidPiontInZona(targetInfo.Data.Position.x, targetInfo.Data.Position.y); * //if (!targetInfo.Data.IsReality && isZonaReal) * if (isZonaReal) * { * Storage.GenGrid.LoadObjectToReal(targetInfo.Field); * } * * //3. Add resource in Inventory (where not Ground) * p_dataNPC.Inventory = targetInfo.Data.LootObjectToInventory(p_dataNPC); * * //4. Set target to target location * if (job.JobTo == TypesJobTo.ToPortal) * { * //GameActionPersonController.RequestActionNPC(p_dataNPC, GameActionPersonController.NameActionsPerson.Idle, null); * //GameActionPersonController.RequestActionNPC(p_dataNPC, GameActionPersonController.NameActionsPerson.Target, null); * } * } * //continue work... * return true; * } * } * } * } * } * } * return false; * } */ public static void GetAlienNextTargetObject(ref ModelNPC.ObjectData result, ref AlienJob job, ModelNPC.GameDataAlien dataAlien) { int versionSearching = 2;// 1; //@JOB@ if (Storage.Person.PersonPriority == null) { Storage.EventsUI.ListLogAdd = "### GetAlienNextTargetObject >> PersonPriority is null"; Storage.Person.LoadPriorityPerson(); result = null; return; } if (dataAlien == null) { Storage.EventsUI.ListLogAdd = "### GetAlienNextTargetObject >> dataAlien is null"; result = null; return; } //m_prioritysGet = PersonPriority[dataAlien.TypePrefab]; //int distantionFind = UnityEngine.Random.Range(2, 15); //v.1 if (versionSearching == 1) { //result = FindFromLocation(dataAlien.Position, distantionFind, prioritys, dataAlien.Id, dataAlien.TypePrefab); //result = Helper.FindFromLocation(dataAlien, distantionFind); temp_distantionFind = UnityEngine.Random.Range(2, 15); Helper.FindFromLocation_Cache(ref result, dataAlien, temp_distantionFind); } else //v.3 { if (job != null) { //fix job bool isCompletedMission = job != null && dataAlien.Inventory != null && dataAlien.Inventory.NameInventopyObject == job.TargetResource.ToString(); switch (job.JobTo) { case TypesJobTo.ToPortal: if (isCompletedMission) { if (dataAlien.PortalId == null) { Storage.PortalsManager.SetHome(dataAlien); } var info = ReaderScene.GetInfoID(dataAlien.PortalId); if (info != null) { result = info.Data; } } break; default: job = null; break; } } if (result == null) { temp_distantionFind = UnityEngine.Random.Range(2, 150); if (dataAlien.Inventory != null && !dataAlien.Inventory.IsEmpty && dataAlien.Inventory.TypeInventoryObject.IsPrefab())//FIX%CLUSTER { Storage.PortalsManager.FindJobBuildLocation(ref result, ref job, dataAlien, temp_distantionFind); } if (result == null) { CeckJobPass(ref result, dataAlien); if (result == null) { Storage.Person.FindJobResouceLocation(ref result, ref job, dataAlien, temp_distantionFind); } } if (result == null) { temp_distantionFind = UnityEngine.Random.Range(2, 25);//15 Helper.FindFromLocation_Cache(ref result, dataAlien, temp_distantionFind); } } } //v.2 //if (versionSearching == 2) //{ // string fieldName = Helper.GetNameFieldPosit(dataAlien.Position.x, dataAlien.Position.y); // Vector2 posField = Helper.GetPositByField(fieldName); // Vector2Int posFieldInt = new Vector2Int((int)posField.x, (int)posField.y); // ReaderScene.DataInfoFinder finder = ReaderScene.GetDataInfoLocationFromID((int)posFieldInt.x, (int)posFieldInt.y, distantionFind, dataAlien.TypePrefab, dataAlien.Id); }
public static bool CheckJobAlien(ModelNPC.GameDataAlien p_dataNPC, GameActionPersonController controller = null, bool isCheckDistance = true) { AlienJob job = p_dataNPC.Job; if (job == null) { return(false); } ReaderScene.DataObjectInfoID targetInfo = ReaderScene.GetInfoID(p_dataNPC.TargetID); if (targetInfo == null) { return(false); } if (!targetInfo.TestIsValud()) { p_dataNPC.TargetID = null; return(false); } if (isCheckDistance) { if (!Helper.DistanceIsFinish(targetInfo.Data.Position, p_dataNPC.Position)) { return(true); } } string fieldTarget = string.Empty; string fieldAlien = string.Empty; bool isExitTargetResource = false; Helper.GetNameFieldByPosit(ref fieldTarget, targetInfo.Data.Position); ModelNPC.PortalData portal = targetInfo.Data as ModelNPC.PortalData; SaveLoadData.TypePrefabs jobResourceTarget = job.TargetResource; Helper.GetNameFieldByPosit(ref fieldAlien, p_dataNPC.Position); if (p_dataNPC.Inventory == null) { p_dataNPC.Inventory = DataObjectInventory.EmptyInventory(); //Debug.Log(Storage.EventsUI.ListLogAdd = "## JOB: dataNPC.Inventory is null"); } else { isExitTargetResource = job.TargetResource.ToString() == p_dataNPC.Inventory.TypeInventoryObject.ToString(); } // --- TO PORTAL if (portal != null) { if (isExitTargetResource) { //***** Back to HOME **** (trget is Portal) //p_dataNPC.InventoryObject is ModelNPC; Storage.PortalsManager.AddResourceFromAlien(portal, p_dataNPC); } // --- TAKE RESOURCE bool checkStorageResource = Storage.PortalsManager.CheckStorageResourceForAlien(portal, p_dataNPC); if (!checkStorageResource && isExitTargetResource) { //End job p_dataNPC.Job = null; p_dataNPC.TargetID = string.Empty; p_dataNPC.TargetPosition = Vector3.zero; } //Continue job if (p_dataNPC.Job != null && p_dataNPC.Job.Job != TypesJobs.Bathering) { return(true); } } // --- TO LOOT && BUILD else { //Test job on target //@JOB@ if (targetInfo.Data.TypePrefab != jobResourceTarget) { return(false); } if (p_dataNPC.CurrentAction != GameActionPersonController.NameActionsPerson.CompletedLoot.ToString() && p_dataNPC.CurrentAction != GameActionPersonController.NameActionsPerson.Work.ToString()) { GameActionPersonController.ExecuteActionNPC(p_dataNPC, GameActionPersonController.NameActionsPerson.Work, controller, true); } if (p_dataNPC.CurrentAction == GameActionPersonController.NameActionsPerson.CompletedLoot.ToString()) { if (job.Job == TypesJobs.Build) { if (p_dataNPC.Inventory == null || p_dataNPC.Inventory.IsEmpty || p_dataNPC.Inventory.TypeInventoryObject.ToString() != job.ResourceResult.ToString()) { Debug.Log(Storage.EventsUI.ListLogAdd = "### JOB BUILD: Inventory is Empty >> " + job.Job.ToString() + " " + job.TargetResource + " R:" + job.ResourceResult); //p_dataNPC.Inventory = DataObjectInventory.EmptyInventory(); return(false); } } GameActionPersonController.ExecuteActionNPC(p_dataNPC, GameActionPersonController.NameActionsPerson.Move, controller, true); // **** FIND RESOURCE **** //---Replace object //1. Remove resource //Vector3 posTarget = targetInfo.Data.Position; bool isTargetTypeTrue = false; PoolGameObjects.TypePoolPrefabs typePoolResource = CheckFieldJobValid(ref isTargetTypeTrue, job, targetInfo.Data); if (job.Job == TypesJobs.Build) { if (typePoolResource == PoolGameObjects.TypePoolPrefabs.PoolFloor) { GenericWorldManager.ClearLayerObject(targetInfo.Data); } //---- TEST //else // Debug.Log(Storage.EventsUI.ListLogAdd = "TypesJobs.Build .. Not Remove resource: " + job.ResourceResult.ToString() + " >> " + targetInfo.Data.NameObject); } else { GenericWorldManager.ClearLayerObject(targetInfo.Data); } //2. Create new resource if (job.ResourceResult != SaveLoadData.TypePrefabs.PrefabField) { CreateNewResource(typePoolResource, job, targetInfo, p_dataNPC); } bool isZonaReal = Helper.IsValidPiontInZona(targetInfo.Data.Position.x, targetInfo.Data.Position.y); if (isZonaReal) { Storage.GenGrid.LoadObjectToReal(targetInfo.Field); } //3. Add resource in Inventory (where not Ground) p_dataNPC.Inventory = targetInfo.Data.LootObjectToInventory(p_dataNPC); //4. Set target to target location //if (job.JobTo == TypesJobTo.ToPortal) //{ //GameActionPersonController.RequestActionNPC(p_dataNPC, GameActionPersonController.NameActionsPerson.Idle, null); //GameActionPersonController.RequestActionNPC(p_dataNPC, GameActionPersonController.NameActionsPerson.Target, null); //} } //continue work... return(true); } return(false); }