diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/database/Database/Implementation/HotfixDatabase.cpp | 5 | ||||
-rw-r--r-- | src/server/database/Database/Implementation/HotfixDatabase.h | 3 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2LoadInfo.h | 17 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.cpp | 2 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Stores.h | 1 | ||||
-rw-r--r-- | src/server/game/DataStores/DB2Structure.h | 7 | ||||
-rw-r--r-- | src/server/game/Entities/GameObject/GameObjectData.h | 52 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 23 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 124 | ||||
-rw-r--r-- | src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp | 28 | ||||
-rw-r--r-- | src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp | 28 |
11 files changed, 226 insertions, 64 deletions
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp index 0f31dcbe4b2..f9e5dd7d9ae 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.cpp +++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp @@ -593,6 +593,11 @@ void HotfixDatabaseConnection::DoPrepareStatements() PREPARE_LOCALE_STMT(HOTFIX_SEL_FRIENDSHIP_REPUTATION, "SELECT ID, Description_lang, StandingModified_lang, StandingChanged_lang" " FROM friendship_reputation_locale WHERE (`VerifiedBuild` > 0) = ? AND locale = ?", CONNECTION_SYNCH); + // GameobjectArtKit.db2 + PrepareStatement(HOTFIX_SEL_GAMEOBJECT_ART_KIT, "SELECT ID, AttachModelFileID, TextureVariationFileID1, TextureVariationFileID2, " + "TextureVariationFileID3 FROM gameobject_art_kit WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH); + PREPARE_MAX_ID_STMT(HOTFIX_SEL_GAMEOBJECT_ART_KIT, "SELECT MAX(ID) + 1 FROM gameobject_art_kit", CONNECTION_SYNCH); + // GameobjectDisplayInfo.db2 PrepareStatement(HOTFIX_SEL_GAMEOBJECT_DISPLAY_INFO, "SELECT ID, GeoBoxMinX, GeoBoxMinY, GeoBoxMinZ, GeoBoxMaxX, GeoBoxMaxY, GeoBoxMaxZ, " "FileDataID, ObjectEffectPackageID, OverrideLootEffectScale, OverrideNameScale FROM gameobject_display_info WHERE (`VerifiedBuild` > 0) = ?", CONNECTION_SYNCH); diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h index 0b1c8dc4cab..befc2fbfbd5 100644 --- a/src/server/database/Database/Implementation/HotfixDatabase.h +++ b/src/server/database/Database/Implementation/HotfixDatabase.h @@ -342,6 +342,9 @@ enum HotfixDatabaseStatements : uint32 HOTFIX_SEL_FRIENDSHIP_REPUTATION_MAX_ID, HOTFIX_SEL_FRIENDSHIP_REPUTATION_LOCALE, + HOTFIX_SEL_GAMEOBJECT_ART_KIT, + HOTFIX_SEL_GAMEOBJECT_ART_KIT_MAX_ID, + HOTFIX_SEL_GAMEOBJECT_DISPLAY_INFO, HOTFIX_SEL_GAMEOBJECT_DISPLAY_INFO_MAX_ID, diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h index 087be6f4eba..e415251a315 100644 --- a/src/server/game/DataStores/DB2LoadInfo.h +++ b/src/server/game/DataStores/DB2LoadInfo.h @@ -2083,6 +2083,23 @@ struct FriendshipReputationLoadInfo } }; +struct GameobjectArtKitLoadInfo +{ + static DB2LoadInfo const* Instance() + { + static DB2FieldMeta const fields[] = + { + { false, FT_INT, "ID" }, + { true, FT_INT, "AttachModelFileID" }, + { true, FT_INT, "TextureVariationFileID1" }, + { true, FT_INT, "TextureVariationFileID2" }, + { true, FT_INT, "TextureVariationFileID3" }, + }; + static DB2LoadInfo const loadInfo(&fields[0], std::extent<decltype(fields)>::value, GameObjectArtKitMeta::Instance(), HOTFIX_SEL_GAMEOBJECT_ART_KIT); + return &loadInfo; + } +}; + struct GameobjectDisplayInfoLoadInfo { static DB2LoadInfo const* Instance() diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp index 111b428a600..a24540434f4 100644 --- a/src/server/game/DataStores/DB2Stores.cpp +++ b/src/server/game/DataStores/DB2Stores.cpp @@ -134,6 +134,7 @@ DB2Storage<FactionEntry> sFactionStore("Faction.db2", Fac DB2Storage<FactionTemplateEntry> sFactionTemplateStore("FactionTemplate.db2", FactionTemplateLoadInfo::Instance()); DB2Storage<FriendshipRepReactionEntry> sFriendshipRepReactionStore("FriendshipRepReaction.db2", FriendshipRepReactionLoadInfo::Instance()); DB2Storage<FriendshipReputationEntry> sFriendshipReputationStore("FriendshipReputation.db2", FriendshipReputationLoadInfo::Instance()); +DB2Storage<GameObjectArtKitEntry> sGameObjectArtKitStore("GameObjectArtKit.db2", GameobjectArtKitLoadInfo::Instance()); DB2Storage<GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore("GameObjectDisplayInfo.db2", GameobjectDisplayInfoLoadInfo::Instance()); DB2Storage<GameObjectsEntry> sGameObjectsStore("GameObjects.db2", GameobjectsLoadInfo::Instance()); DB2Storage<GarrAbilityEntry> sGarrAbilityStore("GarrAbility.db2", GarrAbilityLoadInfo::Instance()); @@ -708,6 +709,7 @@ uint32 DB2Manager::LoadStores(std::string const& dataPath, LocaleConstant defaul LOAD_DB2(sFriendshipRepReactionStore); LOAD_DB2(sFriendshipReputationStore); LOAD_DB2(sGameObjectsStore); + LOAD_DB2(sGameObjectArtKitStore); LOAD_DB2(sGameObjectDisplayInfoStore); LOAD_DB2(sGarrAbilityStore); LOAD_DB2(sGarrBuildingStore); diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h index 68b558c3622..c06cf1df70d 100644 --- a/src/server/game/DataStores/DB2Stores.h +++ b/src/server/game/DataStores/DB2Stores.h @@ -102,6 +102,7 @@ TC_GAME_API extern DB2Storage<FactionEntry> sFactionStor TC_GAME_API extern DB2Storage<FactionTemplateEntry> sFactionTemplateStore; TC_GAME_API extern DB2Storage<FriendshipRepReactionEntry> sFriendshipRepReactionStore; TC_GAME_API extern DB2Storage<FriendshipReputationEntry> sFriendshipReputationStore; +TC_GAME_API extern DB2Storage<GameObjectArtKitEntry> sGameObjectArtKitStore; TC_GAME_API extern DB2Storage<GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore; TC_GAME_API extern DB2Storage<GameObjectsEntry> sGameObjectsStore; TC_GAME_API extern DB2Storage<GarrAbilityEntry> sGarrAbilityStore; diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h index 10ce3fdfa7a..153e9630ca7 100644 --- a/src/server/game/DataStores/DB2Structure.h +++ b/src/server/game/DataStores/DB2Structure.h @@ -1530,6 +1530,13 @@ struct FriendshipReputationEntry EnumFlag<FriendshipReputationFlags> GetFlags() const { return static_cast<FriendshipReputationFlags>(Flags); } }; +struct GameObjectArtKitEntry +{ + uint32 ID; + int32 AttachModelFileID; + int32 TextureVariationFileID[3]; +}; + struct GameObjectDisplayInfoEntry { uint32 ID; diff --git a/src/server/game/Entities/GameObject/GameObjectData.h b/src/server/game/Entities/GameObject/GameObjectData.h index 242f25f7d38..6bfa3d61e59 100644 --- a/src/server/game/Entities/GameObject/GameObjectData.h +++ b/src/server/game/Entities/GameObject/GameObjectData.h @@ -24,6 +24,7 @@ #include "SharedDefines.h" #include "SpawnData.h" #include "WorldPacket.h" +#include <array> #include <string> // from `gameobject_template` @@ -1085,6 +1086,7 @@ struct GameObjectTemplateAddon : public GameObjectOverride { uint32 Mingold; uint32 Maxgold; + std::array<uint32, 5> ArtKits = { }; uint32 WorldEffectID; uint32 AIAnimKitID; }; @@ -1116,4 +1118,54 @@ struct GameObjectData : public SpawnData uint8 artKit = 0; }; +enum class GameObjectActions : uint32 +{ + // Name from client executable // Comments + None = 0, // -NONE- + AnimateCustom0 = 1, // Animate Custom0 + AnimateCustom1 = 2, // Animate Custom1 + AnimateCustom2 = 3, // Animate Custom2 + AnimateCustom3 = 4, // Animate Custom3 + Disturb = 5, // Disturb // Triggers trap + Unlock = 6, // Unlock // Resets GO_FLAG_LOCKED + Lock = 7, // Lock // Sets GO_FLAG_LOCKED + Open = 8, // Open // Sets GO_STATE_ACTIVE + OpenAndUnlock = 9, // Open + Unlock // Sets GO_STATE_ACTIVE and resets GO_FLAG_LOCKED + Close = 10, // Close // Sets GO_STATE_READY + ToggleOpen = 11, // Toggle Open + Destroy = 12, // Destroy // Sets GO_STATE_DESTROYED + Rebuild = 13, // Rebuild // Resets from GO_STATE_DESTROYED + Creation = 14, // Creation + Despawn = 15, // Despawn + MakeInert = 16, // Make Inert // Disables interactions + MakeActive = 17, // Make Active // Enables interactions + CloseAndLock = 18, // Close + Lock // Sets GO_STATE_READY and sets GO_FLAG_LOCKED + UseArtKit0 = 19, // Use ArtKit0 // 46904: 121 + UseArtKit1 = 20, // Use ArtKit1 // 36639: 81, 46903: 122 + UseArtKit2 = 21, // Use ArtKit2 + UseArtKit3 = 22, // Use ArtKit3 + SetTapList = 23, // Set Tap List + GoTo1stFloor = 24, // Go to 1st floor + GoTo2ndFloor = 25, // Go to 2nd floor + GoTo3rdFloor = 26, // Go to 3rd floor + GoTo4thFloor = 27, // Go to 4th floor + GoTo5thFloor = 28, // Go to 5th floor + GoTo6thFloor = 29, // Go to 6th floor + GoTo7thFloor = 30, // Go to 7th floor + GoTo8thFloor = 31, // Go to 8th floor + GoTo9thFloor = 32, // Go to 9th floor + GoTo10thFloor = 33, // Go to 10th floor + UseArtKit4 = 34, // Use ArtKit4 + PlayAnimKit = 35, // Play Anim Kit "{AnimKit}" + OpenAndPlayAnimKit = 36, // Open + Play Anim Kit "{AnimKit}" + CloseAndPlayAnimKit = 37, // Close + Play Anim Kit "{AnimKit}" + PlayOneShotAnimKit = 38, // Play One-shot Anim Kit "{AnimKit}" + StopAnimKit = 39, // Stop Anim Kit + OpenAndStopAnimKit = 40, // Open + Stop Anim Kit + CloseAndStopAnimKit = 41, // Close + Stop Anim Kit + PlaySpellVisual = 42, // Play Spell Visual "{SpellVisual}" + StopSpellVisual = 43, // Stop Spell Visual + SetTappedToChallengePlayers = 44, // Set Tapped to Challenge Players +}; + #endif // GameObjectData_h__ diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index a3148067269..51be3ecef7d 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7810,8 +7810,8 @@ void ObjectMgr::LoadGameObjectTemplateAddons() { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 4 5 6 - QueryResult result = WorldDatabase.Query("SELECT entry, faction, flags, mingold, maxgold, WorldEffectID, AIAnimKitID FROM gameobject_template_addon"); + // 0 1 2 3 4 5 6 7 8 9 10 11 + QueryResult result = WorldDatabase.Query("SELECT entry, faction, flags, mingold, maxgold, artkit0, artkit1, artkit2, artkit3, artkit4, WorldEffectID, AIAnimKitID FROM gameobject_template_addon"); if (!result) { @@ -7838,8 +7838,23 @@ void ObjectMgr::LoadGameObjectTemplateAddons() gameObjectAddon.Flags = fields[2].GetUInt32(); gameObjectAddon.Mingold = fields[3].GetUInt32(); gameObjectAddon.Maxgold = fields[4].GetUInt32(); - gameObjectAddon.WorldEffectID = fields[5].GetUInt32(); - gameObjectAddon.AIAnimKitID = fields[6].GetUInt32(); + gameObjectAddon.WorldEffectID = fields[10].GetUInt32(); + gameObjectAddon.AIAnimKitID = fields[11].GetUInt32(); + + for (uint32 i = 0; i < gameObjectAddon.ArtKits.size(); ++i) + { + uint32 artKitID = fields[5 + i].GetUInt32(); + if (!artKitID) + continue; + + if (!sGameObjectArtKitStore.LookupEntry(artKitID)) + { + TC_LOG_ERROR("sql.sql", "GameObject (Entry: %u) has invalid `artkit%d` (%d) defined, set to zero instead.", entry, i, artKitID); + continue; + } + + gameObjectAddon.ArtKits[i] = artKitID; + } // checks if (gameObjectAddon.Faction && !sFactionTemplateStore.LookupEntry(gameObjectAddon.Faction)) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 01ea58864e8..8ddd4574525 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3292,12 +3292,128 @@ void Spell::EffectActivateObject() if (!gameObjTarget) return; - ScriptInfo activateCommand; - activateCommand.command = SCRIPT_COMMAND_ACTIVATE_OBJECT; + GameObjectActions action = GameObjectActions(effectInfo->MiscValue); - // int32 unk = effectInfo->MiscValue; // This is set for EffectActivateObject spells; needs research + switch (action) + { + case GameObjectActions::AnimateCustom0: + case GameObjectActions::AnimateCustom1: + case GameObjectActions::AnimateCustom2: + case GameObjectActions::AnimateCustom3: + gameObjTarget->SendCustomAnim(uint32(action) - uint32(GameObjectActions::AnimateCustom0)); + break; + case GameObjectActions::Disturb: // What's the difference with Open? + case GameObjectActions::Open: + if (Unit* unitCaster = m_caster->ToUnit()) + gameObjTarget->Use(unitCaster); + break; + case GameObjectActions::OpenAndUnlock: + if (Unit* unitCaster = m_caster->ToUnit()) + gameObjTarget->UseDoorOrButton(0, false, unitCaster); + [[fallthrough]]; + case GameObjectActions::Unlock: + gameObjTarget->RemoveFlag(GO_FLAG_LOCKED); + break; + case GameObjectActions::Lock: + gameObjTarget->AddFlag(GO_FLAG_LOCKED); + break; + case GameObjectActions::Close: + case GameObjectActions::Rebuild: + gameObjTarget->ResetDoorOrButton(); + break; + case GameObjectActions::Despawn: + gameObjTarget->DespawnOrUnsummon(); + break; + case GameObjectActions::MakeInert: + gameObjTarget->AddFlag(GO_FLAG_NOT_SELECTABLE); + break; + case GameObjectActions::MakeActive: + gameObjTarget->RemoveFlag(GO_FLAG_NOT_SELECTABLE); + break; + case GameObjectActions::CloseAndLock: + gameObjTarget->ResetDoorOrButton(); + gameObjTarget->AddFlag(GO_FLAG_LOCKED); + break; + case GameObjectActions::Destroy: + if (Unit* unitCaster = m_caster->ToUnit()) + gameObjTarget->UseDoorOrButton(0, true, unitCaster); + break; + case GameObjectActions::UseArtKit0: + case GameObjectActions::UseArtKit1: + case GameObjectActions::UseArtKit2: + case GameObjectActions::UseArtKit3: + case GameObjectActions::UseArtKit4: + { + GameObjectTemplateAddon const* templateAddon = gameObjTarget->GetTemplateAddon(); + + uint32 artKitIndex = action != GameObjectActions::UseArtKit4 ? uint32(action) - uint32(GameObjectActions::UseArtKit0) : 4; - gameObjTarget->GetMap()->ScriptCommandStart(activateCommand, 0, m_caster, gameObjTarget); + uint32 artKitValue = 0; + if (templateAddon != nullptr) + artKitValue = templateAddon->ArtKits[artKitIndex]; + + if (artKitValue == 0) + TC_LOG_ERROR("sql.sql", "GameObject %d hit by spell %d needs `artkit%d` in `gameobject_template_addon`", gameObjTarget->GetEntry(), m_spellInfo->Id, artKitIndex); + else + gameObjTarget->SetGoArtKit(artKitValue); + + break; + } + case GameObjectActions::GoTo1stFloor: + case GameObjectActions::GoTo2ndFloor: + case GameObjectActions::GoTo3rdFloor: + case GameObjectActions::GoTo4thFloor: + case GameObjectActions::GoTo5thFloor: + case GameObjectActions::GoTo6thFloor: + case GameObjectActions::GoTo7thFloor: + case GameObjectActions::GoTo8thFloor: + case GameObjectActions::GoTo9thFloor: + case GameObjectActions::GoTo10thFloor: + if (gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_TRANSPORT) + gameObjTarget->SetTransportState(GO_STATE_TRANSPORT_STOPPED, uint32(action) - uint32(GameObjectActions::GoTo1stFloor)); + else + TC_LOG_ERROR("spell", "Spell %d targeted non-transport gameobject for transport only action \"Go to Floor\" %d in effect %d", m_spellInfo->Id, int32(action), int32(effectInfo->EffectIndex)); + break; + case GameObjectActions::PlayAnimKit: + gameObjTarget->SetAnimKitId(effectInfo->MiscValueB, false); + break; + case GameObjectActions::OpenAndPlayAnimKit: + if (Unit* unitCaster = m_caster->ToUnit()) + gameObjTarget->UseDoorOrButton(0, false, unitCaster); + gameObjTarget->SetAnimKitId(effectInfo->MiscValueB, false); + break; + case GameObjectActions::CloseAndPlayAnimKit: + gameObjTarget->ResetDoorOrButton(); + gameObjTarget->SetAnimKitId(effectInfo->MiscValueB, false); + break; + case GameObjectActions::PlayOneShotAnimKit: + gameObjTarget->SetAnimKitId(effectInfo->MiscValueB, true); + break; + case GameObjectActions::StopAnimKit: + gameObjTarget->SetAnimKitId(0, false); + break; + case GameObjectActions::OpenAndStopAnimKit: + if (Unit* unitCaster = m_caster->ToUnit()) + gameObjTarget->UseDoorOrButton(0, false, unitCaster); + gameObjTarget->SetAnimKitId(0, false); + break; + case GameObjectActions::CloseAndStopAnimKit: + gameObjTarget->ResetDoorOrButton(); + gameObjTarget->SetAnimKitId(0, false); + break; + case GameObjectActions::PlaySpellVisual: + gameObjTarget->SetSpellVisualId(effectInfo->MiscValueB, m_originalCasterGUID); + break; + case GameObjectActions::StopSpellVisual: + gameObjTarget->SetSpellVisualId(0); + break; + case GameObjectActions::None: + TC_LOG_FATAL("spell", "Spell %d has action type NONE in effect %d", m_spellInfo->Id, int32(effectInfo->EffectIndex)); + break; + default: + TC_LOG_ERROR("spell", "Spell %d has unhandled action %d in effect %d", m_spellInfo->Id, int32(action), int32(effectInfo->EffectIndex)); + break; + } } void Spell::EffectApplyGlyph() diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp index 0def31e0ce6..3e76591ad7d 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp @@ -223,36 +223,8 @@ class npc_voljin_zulaman : public CreatureScript } }; -// 45226 - Banging the Gong -class spell_banging_the_gong : public SpellScriptLoader -{ - public: - spell_banging_the_gong() : SpellScriptLoader("spell_banging_the_gong") { } - - class spell_banging_the_gong_SpellScript : public SpellScript - { - PrepareSpellScript(spell_banging_the_gong_SpellScript); - - void Activate(SpellEffIndex index) - { - PreventHitDefaultEffect(index); - GetHitGObj()->SendCustomAnim(0); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_banging_the_gong_SpellScript::Activate, EFFECT_1, SPELL_EFFECT_ACTIVATE_OBJECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_banging_the_gong_SpellScript(); - } -}; void AddSC_zulaman() { new npc_voljin_zulaman(); - new spell_banging_the_gong(); } diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp index d4f53f9afd3..95e284b1eb5 100644 --- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp +++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp @@ -344,33 +344,6 @@ class spell_anhuur_disable_beacon_beams : public SpellScriptLoader } }; -class spell_anhuur_activate_beacons : public SpellScriptLoader -{ - public: - spell_anhuur_activate_beacons() : SpellScriptLoader("spell_anhuur_activate_beacons") { } - - class spell_anhuur_activate_beacons_SpellScript : public SpellScript - { - PrepareSpellScript(spell_anhuur_activate_beacons_SpellScript); - - void Activate(SpellEffIndex index) - { - PreventHitDefaultEffect(index); - GetHitGObj()->RemoveFlag(GO_FLAG_NOT_SELECTABLE); - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_anhuur_activate_beacons_SpellScript::Activate, EFFECT_0, SPELL_EFFECT_ACTIVATE_OBJECT); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_anhuur_activate_beacons_SpellScript(); - } -}; - class spell_anhuur_divine_reckoning : public SpellScriptLoader { public: @@ -407,6 +380,5 @@ void AddSC_boss_temple_guardian_anhuur() new boss_temple_guardian_anhuur(); new spell_anhuur_shield_of_light(); new spell_anhuur_disable_beacon_beams(); - new spell_anhuur_activate_beacons(); new spell_anhuur_divine_reckoning(); } |