/// <summary>First in, First out caching</summary> /// <param name="capacity"></param> /// <param name="objectDestroyer"> /// When an object is kicked out of the cache, this will be used to process its destruction, /// in case special code needs to be executed. This is also called for each value when the cache is cleared usinc <see cref="Clear"/> /// </param> public FIFOCachingPool(int capacity, ObjectDestroyer objectDestroyer = null) { Capacity = capacity; _Keys = new Queue <object>(capacity); _Cache = new Dictionary <object, object>(capacity); _ObjectDestroyer = objectDestroyer; }
public override NodeState Evaluate() { if ((Vector3)blackboard.GetValue("currentFoodLocation") == Vector3.zero) { return(NodeState.SUCCESS); } if (isEating) { if (timer >= eatAnimationLength) { ObjectDestroyer.DestroyObjectAtGivenPosition((Vector3)blackboard.GetValue("currentFoodLocation"), LayerMask.GetMask("Food")); int foodEaten = (int)globalBlackboard.GetValue("foodEaten") + 1; globalBlackboard.UpdateValue("foodEaten", foodEaten); return(NodeState.SUCCESS); } else { timer += Time.deltaTime; } } else { anim.SetTrigger("Attack"); agent.isStopped = true; isEating = true; } return(NodeState.RUNNING); }
// Use this for initialization void Start() { anim = GetComponent <Animator>(); Gun = GetComponentInChildren <AIShootingScript>(); clearBodies = GetComponent <ObjectDestroyer>(); enemyAlive = true; Player = GameObject.Find("Cowboy").transform; }
public override void Process(string scene, UnityEngine.Object changeObj) { if (scene != _sceneName) { return; } ObjectDestroyer.Destroy(_sceneName, _destroyName); }
protected virtual void Initialize() { nma = GetComponent <NavMeshAgent>(); if (target == null) { target = GameObject.FindGameObjectWithTag("Player").transform; } lastTargetPos = target.position; anim = GetComponent <Animator>(); clearBodies = GetComponent <ObjectDestroyer>(); isAlive = true; mRB = GetComponent <Rigidbody>(); mCollider = GetComponentInChildren <Collider>(); initialized = true; }
/// <summary> /// Triggers the object destroyer if necessary /// </summary> void OnDestroy() { // if theres a destroyer attached if (objectDestroyerName != "") { // find and save the trigger, then check if it actually exists ObjectDestroyer objDes = GameObject.Find(objectDestroyerName).GetComponent <ObjectDestroyer> (); if (objDes != null) { objDes.TriggerDestroyer(); } } // trigger some dialogue if necessary if (dialogueTriggerName != "") { DialogueTrigger.TriggerDialogue(dialogueTriggerName); } }
public void GiveCardBack(Card card) { for (int slot = 0; slot < cards.Length; slot++) { Card cardInSlot = GetReferenceToCardAt(slot); if (card.IsAnotherInstanceOf(cardInSlot)) { amountOfEachCard[slot]++; UpdateCardColorAndAmountText(slot); ChildMaker.AdoptAndScaleAndSmoothlyMoveToParent (slots[slot], card.GetRectTransform(), repositionAnimationDurationInSeconds); const float DELAY_FROM_ANIMATION_END_TO_DESTRUCTION = 0.2f; ObjectDestroyer.DestroyObjectInTime(card.gameObject, repositionAnimationDurationInSeconds + DELAY_FROM_ANIMATION_END_TO_DESTRUCTION); return; } } L.ogError("Couldn't find card of same type to give the card back.", this); }
/* * Room changes required for the randomizer to function on any mode * For example, removing certain vanilla item locations which can't be handled by RandomizerAction */ public static void ApplyRandomizerChanges(Scene newScene) { switch (newScene.name) { // Prevent Grimm encounter which gives Grimmchild case SceneNames.Grimm_Main_Tent: PlayerData.instance.metGrimm = true; break; // Prevent reading tablet which gives completion percentage case SceneNames.Room_Final_Boss_Atrium: GameObject.Find("Tut_tablet_top").LocateMyFSM("Inspection").GetState("Init").ClearTransitions(); break; // Removes the prompt to donate to the 3000 geo fountain in Basin case SceneNames.Abyss_04: Object.Destroy(GameObject.Find("Fountain Donation")); break; // Opens lifeblood door in Abyss with any amount of blue health case SceneNames.Abyss_06_Core: if (PlayerData.instance.healthBlue > 0 || PlayerData.instance.joniHealthBlue > 0 || GameManager.instance.entryGateName == "left1") { PlayerData.instance.SetBoolInternal("blueVineDoor", true); PlayMakerFSM BlueDoorFSM = GameObject.Find("Blue Door").LocateMyFSM("Control"); BlueDoorFSM.GetState("Init").RemoveTransitionsTo("Got Charm"); } break; // Removes trigger for Void Heart sequence case SceneNames.Abyss_15: GameObject.Find("Dream Enter Abyss").LocateMyFSM("Control").GetState("Init").RemoveTransitionsTo("Idle"); GameObject.Find("Dream Enter Abyss").LocateMyFSM("Control").GetState("Init").AddTransition("FINISHED", "Inactive"); break; // Automatically unlock Godseeker and add an action to the Godtuner spot to remove simple key on purchase case SceneNames.GG_Waterways: PlayerData.instance.SetBool("godseekerUnlocked", true); if (GameObject.Find("Randomizer Shiny") != null) { PlayMakerFSM godtuner = GameObject.Find("Randomizer Shiny").LocateMyFSM("Shiny Control"); godtuner.GetState(godtuner.GetState("Charm?").Transitions.First(t => t.EventName == "YES").ToState).AddFirstAction(new RandomizerExecuteLambda(() => PlayerData.instance.DecrementInt("simpleKeys"))); } break; // Spawns mawlek shard out of bounds and moves it inbounds when mawlek is killed case SceneNames.Crossroads_09: if (GameObject.Find("Randomizer Shiny") is GameObject mawlekShard) { mawlekShard.transform.SetPositionY(100f); IEnumerator mawlekDead() { yield return(new WaitUntil(() => PlayerData.instance.killedMawlek)); mawlekShard.transform.SetPositionY(10f); mawlekShard.transform.SetPositionX(61.5f); } GameManager.instance.StartCoroutine(mawlekDead()); } break; // Removes Grubfather rewards corresponding to randomizer items case SceneNames.Crossroads_38: Object.Destroy(GameObject.Find("Reward 5")); //Mask Object.Destroy(GameObject.Find("Reward 10")); //Charm Object.Destroy(GameObject.Find("Reward 16")); //Rancid Egg Object.Destroy(GameObject.Find("Reward 23")); //Relic Object.Destroy(GameObject.Find("Reward 31")); //Pale Ore Object.Destroy(GameObject.Find("Reward 38")); //Relic Object.Destroy(GameObject.Find("Reward 46")); //Charm break; // Remove gate from Ancestral Mound case SceneNames.Crossroads_ShamanTemple: Object.Destroy(GameObject.Find("Bone Gate")); break; // Remove Beast's Den hardsave, allow rear access from entrance, destroy Herrah case SceneNames.Deepnest_Spider_Town: GameManager.instance.sceneData.SaveMyState(new PersistentBoolData { sceneName = "Deepnest_Spider_Town", id = "Collapser Small (12)", activated = true, semiPersistent = false }); FsmState denHardSave = GameObject.Find("RestBench Spider").LocateMyFSM("Fade").GetState("Land"); denHardSave.RemoveActionsOfType <CallMethodProper>(); denHardSave.RemoveActionsOfType <SendMessage>(); denHardSave.RemoveActionsOfType <SetPlayerDataBool>(); Object.Destroy(GameObject.Find("Dreamer Hegemol")); Object.Destroy(GameObject.Find("Dream Enter")); Object.Destroy(GameObject.Find("Dream Impact")); Object.Destroy(GameObject.Find("Shield")); break; // Edits Dream Nail location to change scene to seer case SceneNames.Dream_Nailcollection: FSMUtility.LocateFSM(GameObject.Find("Randomizer Shiny"), "Shiny Control").GetState("Finish") .AddAction(new RandomizerChangeScene("RestingGrounds_07", "right1")); break; // Edit Hornet room to open gates after boss fight, and removes dreamer cutscene case SceneNames.Fungus1_04: foreach (PlayMakerFSM childFSM in GameObject.Find("Cloak Corpse") .GetComponentsInChildren <PlayMakerFSM>(true)) { if (childFSM.FsmName == "Shiny Control") { SendEvent openGate = new SendEvent { eventTarget = new FsmEventTarget { target = FsmEventTarget.EventTarget.BroadcastAll, excludeSelf = true }, sendEvent = FsmEvent.FindEvent("BG OPEN"), delay = 0, everyFrame = false }; childFSM.GetState("Destroy").AddFirstAction(openGate); childFSM.GetState("Finish").AddFirstAction(openGate); break; } } ObjectDestroyer.Destroy("Dreamer Scene 1"); ObjectDestroyer.Destroy("Hornet Saver"); ObjectDestroyer.Destroy("Cutscene Dreamer"); ObjectDestroyer.Destroy("Dream Scene Activate"); if (!Ref.PD.hornet1Defeated) { Object.Destroy(FSMUtility.LocateFSM(GameObject.Find("Camera Locks Boss"), "FSM")); } break; // Make city crest gate openable infinite times and not hard save case SceneNames.Fungus2_21: FSMUtility.LocateFSM(GameObject.Find("City Gate Control"), "Conversation Control") .GetState("Activate").RemoveActionsOfType <SetPlayerDataBool>(); FsmState gateSlam = FSMUtility.LocateFSM(GameObject.Find("Ruins_gate_main"), "Open") .GetState("Slam"); gateSlam.RemoveActionsOfType <SetPlayerDataBool>(); gateSlam.RemoveActionsOfType <CallMethodProper>(); gateSlam.RemoveActionsOfType <SendMessage>(); break; // Removes Leg Eater dialogue tree, preventing him from dying case SceneNames.Fungus2_26: PlayMakerFSM legEater = FSMUtility.LocateFSM(GameObject.Find("Leg Eater"), "Conversation Control"); FsmState legEaterChoice = legEater.GetState("Convo Choice"); legEaterChoice.RemoveTransitionsTo("Convo 1"); legEaterChoice.RemoveTransitionsTo("Convo 2"); legEaterChoice.RemoveTransitionsTo("Convo 3"); legEaterChoice.RemoveTransitionsTo("Infected Crossroad"); legEaterChoice.RemoveTransitionsTo("Bought Charm"); legEaterChoice.RemoveTransitionsTo("Gold Convo"); legEaterChoice.RemoveTransitionsTo("All Gold"); legEaterChoice.RemoveTransitionsTo("Ready To Leave"); legEater.GetState("All Gold?").RemoveTransitionsTo("No Shop"); Ref.PD.legEaterLeft = false; break; // Destroy Monomon and remove Quirrel encounter case SceneNames.Fungus3_archive_02: PlayerData.instance.SetBool("summonedMonomon", true); Object.Destroy(GameObject.Find("Inspect Region")); Object.Destroy(GameObject.Find("Quirrel Wounded")); Object.Destroy(GameObject.Find("Quirrel")); Object.Destroy(GameObject.Find("Monomon")); Object.Destroy(GameObject.Find("Dream Enter")); Object.Destroy(GameObject.Find("Dream Impact")); Object.Destroy(GameObject.Find("Shield")); break; // Make tolls always interactable, in the rare case that lantern is not randomized but RG access through the dark room is expected case SceneNames.Mines_33: if (RandomizerMod.Instance.Settings.DarkRooms && !RandomizerMod.Instance.Settings.RandomizeKeys) { GameObject[] tolls = new GameObject[] { GameObject.Find("Toll Gate Machine"), GameObject.Find("Toll Gate Machine (1)") }; foreach (GameObject toll in tolls) { Object.Destroy(FSMUtility.LocateFSM(toll, "Disable if No Lantern")); } } break; // Move Seer back to make room for items, and remove essence rewards case SceneNames.RestingGrounds_07: GameObject.Find("Dream Moth").transform.Translate(new Vector3(-5f, 0f)); PlayMakerFSM moth = FSMUtility.LocateFSM(GameObject.Find("Dream Moth"), "Conversation Control"); PlayerData.instance.dreamReward1 = true; moth.FsmVariables.GetFsmBool("Got Reward 1").Value = true; //Relic PlayerData.instance.dreamReward3 = true; moth.FsmVariables.GetFsmBool("Got Reward 3").Value = true; //Pale Ore PlayerData.instance.dreamReward4 = true; moth.FsmVariables.GetFsmBool("Got Reward 4").Value = true; //Charm PlayerData.instance.dreamReward5 = true; moth.FsmVariables.GetFsmBool("Got Reward 5").Value = true; //Vessel Fragment PlayerData.instance.dreamReward5b = true; moth.FsmVariables.GetFsmBool("Got Reward 5b").Value = true; //Skill PlayerData.instance.dreamReward6 = true; moth.FsmVariables.GetFsmBool("Got Reward 6").Value = true; //Relic PlayerData.instance.dreamReward7 = true; moth.FsmVariables.GetFsmBool("Got Reward 7").Value = true; //Mask Shard PlayerData.instance.dreamReward8 = true; moth.FsmVariables.GetFsmBool("Got Reward 8").Value = true; //Skill break; // Make Sly pickup send Sly back upstairs -- warps player out to prevent resulting softlock from trying to enter the shop from a missing transition case SceneNames.Room_Sly_Storeroom: FsmState slyFinish = FSMUtility.LocateFSM(GameObject.Find("Randomizer Shiny"), "Shiny Control").GetState("Finish"); slyFinish.AddAction(new RandomizerSetBool("SlyCharm", true)); slyFinish.AddAction(new RandomizerChangeScene("Town", "door_sly")); break; // Many changes to make the desolate dive pickup work properly case SceneNames.Ruins1_24: // Stop spell container from destroying itself PlayMakerFSM quakePickup = FSMUtility.LocateFSM(GameObject.Find("Quake Pickup"), "Pickup"); quakePickup.GetState("Idle").RemoveActionsOfType <IntCompare>(); foreach (PlayMakerFSM childFSM in quakePickup.gameObject.GetComponentsInChildren <PlayMakerFSM>(true)) { if (childFSM.FsmName == "Shiny Control") { // Make spell container spawn shiny instead quakePickup.GetState("Appear").GetActionsOfType <ActivateGameObject>()[1].gameObject .GameObject.Value = childFSM.gameObject; // Make shiny open gates on pickup/destroy SendEvent openGate = new SendEvent { eventTarget = new FsmEventTarget { target = FsmEventTarget.EventTarget.BroadcastAll, excludeSelf = true }, sendEvent = FsmEvent.FindEvent("BG OPEN"), delay = 0, everyFrame = false }; childFSM.GetState("Destroy").AddFirstAction(openGate); childFSM.GetState("Finish").AddFirstAction(openGate); break; } } // Stop the weird invisible floor from appearing if dive has been obtained if (Ref.PD.quakeLevel > 0) { Object.Destroy(GameObject.Find("Roof Collider Battle")); } // Change battle gate to be destroyed if Soul Master is dead instead of it the player has quake FsmState checkQuake = FSMUtility.LocateFSM(GameObject.Find("Battle Gate (1)"), "Destroy if Quake").GetState("Check"); checkQuake.RemoveActionsOfType <FsmStateAction>(); checkQuake.AddAction(new RandomizerBoolTest(nameof(PlayerData.killedMageLord), null, "DESTROY", true)); break; // Prevent simple key softlocks case SceneNames.Ruins2_04: FsmState hotSpringsKey = GameObject.Find("Inspect").LocateMyFSM("Conversation Control").GetState("Got Key?"); hotSpringsKey.RemoveActionsOfType <IntCompare>(); hotSpringsKey.AddAction(new RandomizerExecuteLambda(() => { if (GameManager.instance.GetPlayerDataInt("simpleKeys") > 1 || (PlayerData.instance.openedWaterwaysManhole && GameManager.instance.GetPlayerDataInt("simpleKeys") > 0)) { PlayMakerFSM.BroadcastEvent("YES"); } else { PlayMakerFSM.BroadcastEvent("NO"); } })); break; // Destroy Lurien case SceneNames.Ruins2_Watcher_Room: Object.Destroy(GameObject.Find("Dreamer Lurien")); Object.Destroy(GameObject.Find("Dream Enter")); Object.Destroy(GameObject.Find("Dream Impact")); Object.Destroy(GameObject.Find("Shield")); break; // Open all colosseum trials case SceneNames.Room_Colosseum_01: PlayerData.instance.colosseumBronzeOpened = true; PlayerData.instance.colosseumSilverOpened = true; PlayerData.instance.colosseumGoldOpened = true; GameObject.Find("Silver Trial Board").LocateMyFSM("Conversation Control").GetState("Hero Anim").ClearTransitions(); GameObject.Find("Silver Trial Board").LocateMyFSM("Conversation Control").GetState("Hero Anim").AddTransition("FINISHED", "Box Up YN"); GameObject.Find("Gold Trial Board").LocateMyFSM("Conversation Control").GetState("Hero Anim").ClearTransitions(); GameObject.Find("Gold Trial Board").LocateMyFSM("Conversation Control").GetState("Hero Anim").AddTransition("FINISHED", "Box Up YN"); break; // Destroy Grey Mourner after the flower has been delivered case SceneNames.Room_Mansion: if (PlayerData.instance.xunFlowerGiven) { PlayerData.instance.xunRewardGiven = true; } break; // Removes King's Brand cutscene trigger case SceneNames.Room_Wyrm: Object.Destroy(GameObject.Find("Avalanche End")); break; // Open Colosseum gates after picking up resp. items case SceneNames.Room_Colosseum_Bronze: GameObject.Find("Colosseum Manager").LocateMyFSM("Geo Pool").GetState("Open Gates").AddFirstAction(new RandomizerSetBool("colosseumBronzeCompleted", true, true)); break; case SceneNames.Room_Colosseum_Silver: GameObject.Find("Colosseum Manager").LocateMyFSM("Geo Pool").GetState("Open Gates").AddFirstAction(new RandomizerSetBool("colosseumSilverCompleted", true, true)); break; // Prevent simple key softlocks case SceneNames.Town: FsmState jijiKey = GameObject.Find("Jiji Door").LocateMyFSM("Conversation Control").GetState("Key?"); jijiKey.RemoveActionsOfType <GetPlayerDataInt>(); jijiKey.RemoveActionsOfType <IntCompare>(); jijiKey.AddAction(new RandomizerExecuteLambda(() => { if (GameManager.instance.GetPlayerDataInt("simpleKeys") > 1 || (PlayerData.instance.openedWaterwaysManhole && GameManager.instance.GetPlayerDataInt("simpleKeys") > 0)) { PlayMakerFSM.BroadcastEvent("KEY"); } else { PlayMakerFSM.BroadcastEvent("NOKEY"); } })); break; } }
// Use this for initialization void Awake() { mInstance = this; this.enabled = false; }
private static void ApplyGeneralChanges(Scene newScene) { switch (newScene.name) { case SceneNames.Crossroads_38: // Faster daddy PlayMakerFSM grubDaddy = FSMUtility.LocateFSM(GameObject.Find("Grub King"), "King Control"); grubDaddy.GetState("Final Reward?").RemoveTransitionsTo("Recover"); grubDaddy.GetState("Final Reward?").AddTransition("FINISHED", "Recheck"); grubDaddy.GetState("Recheck").RemoveTransitionsTo("Gift Anim"); grubDaddy.GetState("Recheck").AddTransition("FINISHED", "Activate Reward"); // Terrible code to make a terrible fsm work not terribly int geoTotal = 0; grubDaddy.GetState("All Given").AddAction(new RandomizerAddGeo(grubDaddy.gameObject, 0, true)); grubDaddy.GetState("Recheck").AddAction(new RandomizerExecuteLambda(() => grubDaddy.GetState("All Given").GetActionsOfType <RandomizerAddGeo>()[0].SetGeo(geoTotal))); foreach (PlayMakerFSM grubFsm in grubDaddy.gameObject.GetComponentsInChildren <PlayMakerFSM>(true)) { if (grubFsm.FsmName == "grub_reward_geo") { FsmState grubGeoState = grubFsm.GetState("Remaining?"); int geo = grubGeoState.GetActionsOfType <IntCompare>()[0].integer1.Value; grubGeoState.RemoveActionsOfType <FsmStateAction>(); grubGeoState.AddAction(new RandomizerExecuteLambda(() => geoTotal += geo)); grubGeoState.AddTransition("FINISHED", "End"); } } break; case SceneNames.Deepnest_East_16: // Great Hopper% GameObject hopper1 = newScene.FindGameObject("Giant Hopper"); GameObject hopper2 = newScene.FindGameObject("Giant Hopper (1)"); for (int i = 0; i < 10; i++) { GameObject newHopper1 = Object.Instantiate(hopper1, hopper1.transform.parent); GameObject newHopper2 = Object.Instantiate(hopper2, hopper2.transform.parent); // Don't want people abusing the easter egg as a geo farm HealthManager hopper1HM = newHopper1.GetComponent <HealthManager>(); hopper1HM.SetGeoSmall(0); hopper1HM.SetGeoMedium(0); hopper1HM.SetGeoLarge(0); HealthManager hopper2HM = newHopper2.GetComponent <HealthManager>(); hopper2HM.SetGeoSmall(0); hopper2HM.SetGeoMedium(0); hopper2HM.SetGeoLarge(0); Vector3 hopper1Pos = newHopper1.transform.localPosition; hopper1Pos = new Vector3( hopper1Pos.x + Rnd.Next(5), hopper1Pos.y, hopper1Pos.z); newHopper1.transform.localPosition = hopper1Pos; Vector3 hopper2Pos = newHopper2.transform.localPosition; hopper2Pos = new Vector3( hopper2Pos.x + Rnd.Next(5) - 4, hopper2Pos.y, hopper2Pos.z); newHopper2.transform.localPosition = hopper2Pos; } break; case SceneNames.Fungus1_04: // Open gates after Hornet fight foreach (PlayMakerFSM childFSM in GameObject.Find("Cloak Corpse") .GetComponentsInChildren <PlayMakerFSM>(true)) { if (childFSM.FsmName == "Shiny Control") { SendEvent openGate = new SendEvent { eventTarget = new FsmEventTarget { target = FsmEventTarget.EventTarget.BroadcastAll, excludeSelf = true }, sendEvent = FsmEvent.FindEvent("BG OPEN"), delay = 0, everyFrame = false }; childFSM.GetState("Destroy").AddFirstAction(openGate); childFSM.GetState("Finish").AddFirstAction(openGate); break; } } // Destroy everything relating to the dreamer cutscene // This stuff is in another scene and doesn't exist immediately, so I can't use Object.Destroy ObjectDestroyer.Destroy("Dreamer Scene 1"); ObjectDestroyer.Destroy("Hornet Saver"); ObjectDestroyer.Destroy("Cutscene Dreamer"); ObjectDestroyer.Destroy("Dream Scene Activate"); // Fix the camera lock zone by removing the FSM that destroys it if (!Ref.PD.hornet1Defeated) { Object.Destroy(FSMUtility.LocateFSM(GameObject.Find("Camera Locks Boss"), "FSM")); } break; case SceneNames.Mines_35: // Make descending dark spikes pogoable like on old patches foreach (NonBouncer nonBounce in Object.FindObjectsOfType <NonBouncer>()) { if (nonBounce.gameObject.name.StartsWith("Spike Collider")) { nonBounce.active = false; nonBounce.gameObject.AddComponent <RandomizerTinkEffect>(); } } break; case SceneNames.RestingGrounds_04: // Make dream nail plaque not take 20 years to activate FsmState dreamerPlaqueInspect = FSMUtility .LocateFSM(GameObject.Find("Dreamer Plaque Inspect"), "Conversation Control") .GetState("Hero Anim"); dreamerPlaqueInspect.RemoveActionsOfType <ActivateGameObject>(); dreamerPlaqueInspect.RemoveTransitionsTo("Fade Up"); dreamerPlaqueInspect.AddTransition("FINISHED", "Map Msg?"); PlayMakerFSM dreamerScene2 = FSMUtility.LocateFSM(GameObject.Find("Dreamer Scene 2"), "Control"); dreamerScene2.GetState("Take Control").RemoveTransitionsTo("Blast"); dreamerScene2.GetState("Take Control").AddTransition("FINISHED", "Fade Out"); dreamerScene2.GetState("Fade Out").RemoveTransitionsTo("Dial Wait"); dreamerScene2.GetState("Fade Out").AddTransition("FINISHED", "Set Compass Point"); break; case SceneNames.Ruins1_05b when AreaRando.Instance.Settings.Lemm: // Lemm sell all PlayMakerFSM lemm = FSMUtility.LocateFSM(GameObject.Find("Relic Dealer"), "npc_control"); lemm.GetState("Convo End").AddAction(new RandomizerSellRelics()); break; } }
// Use this for initialization void Awake() { instance = this; }