Batch #16644 by ragnarok-clanker: no function's compiled code changes; checked with 593 compiled unit(s), including every includer of Source/Client/Application/Registry.h, Source/Client/Application/RegistryKey.h, Source/Client/Application/Timer.h, Source/Client/Mode/ModeFade.h, Source/Client/Mode/ModeFadeOut.h, Source/Client/Mode/ModeScreenshot.h, Source/Client/Replay/Replay.h, Source/Client/Replay/ReplayRecordOption.h, Source/Client/Session/Session.h, Source/Contents/Actors/ActorPickNode.h, Source/Contents/Effects/Core/RagEffectState.h, Source/Contents/Effects/Particles/Particle.h, Source/Contents/Movies/BinkMovie.h, Source/Contents/Sprites/SpriteLayerDrawing.h, Source/File/NFileLog.h, Source/Network/NIPAddr.h, Source/Network/Packets/ActorNamePacket.h, Source/Network/Packets/ClientKeepalive.h, Source/Network/Packets/ClientOptionPacket.h, Source/Network/Packets/ExecutableDigestPacket.h, Source/Network/Packets/GameTickPacket.h, Source/Render/DX7/QueuedDrawingDX7.h, Source/Render/DX7/RendererDX7.h, Source/Render/DX9/RenderSystemDX9.h, Source/Render/Device/DeviceSelection.h, Source/Render/Device/Direct3DErrors.h, Source/Render/Device/DisplayMode.h, Source/Render/Device/RenderAdapter.h, Source/Render/Device/RenderBackends.h, Source/Render/Drawing/ActionSpriteDrawing.h, Source/Render/Drawing/BitmapDrawing.h, Source/Render/Drawing/BlendColor.h, Source/Render/Drawing/SpriteGeometry.h, Source/Render/Drawing/TextureStageModes.h, Source/Render/Primitives/AuxiliarySubmission.h, Source/Render/Primitives/SpriteQuad.h, Source/Render/Primitives/TextureQuad.h, Source/Render/Projection/ScreenGeometry.h, Source/Render/Projection/ScreenRectangle.h, Source/Resource/Audio/BinkRuntime.h, Source/Resource/Bitmap/EmblemResource.h, Source/Resource/Bitmap/GifLzw.h, Source/Resource/Bitmap/GifResource.h, Source/Resource/Bitmap/PaletteResource.h, Source/Resource/Bitmap/SkinPalette.h, Source/Resource/Bitmap/TextureNames.h, Source/Resource/Effects/EZeffectResource.h, Source/Resource/Json/JsonCppLoader.h, Source/Resource/Models/RmaResource.h, Source/Resource/Sprites/ImfResource.h, Source/Resource/Xml/XmlNode.h, Source/Security/FileSignatureVerifier.h, Source/Security/ProcessSecurity.h, Source/UI/Achievement/UIAchWnd.h, Source/UI/AdventureGuide/UIAdventureGuide.h, Source/UI/Buttons/UIBalloonOpenBtn.h, Source/UI/Buttons/UIMiniBtnWnd.h, Source/UI/Buttons/UISlotBitmap.h, Source/UI/Buttons/UIStaticBitmap.h, Source/UI/Buttons/UIStaticItem.h, Source/UI/Buttons/UIWindowCallBtnWnd.h, Source/UI/CashEmotion/UICashEmotionSprBtn.h, Source/UI/CashShop/UIMileageWnd.h, Source/UI/CashShop/UIPayConfirmWnd.h, Source/UI/Chat/UIChatRoomWnd.h, Source/UI/Dialogs/UIAccountLimitedToolWnd.h, Source/UI/Dialogs/UICntWnd.h, Source/UI/Dialogs/UILoadingWnd.h, Source/UI/Dialogs/UIMessageBox.h, Source/UI/Dialogs/UIMessageBoxAutoreturn.h, Source/UI/Dialogs/UINormalMB.h, Source/UI/Dialogs/UINoteWnd.h, Source/UI/Dialogs/UINoticeWnd.h, Source/UI/Dialogs/UIRPImageWnd.h, Source/UI/Dialogs/UIRPImageWnd2.h, Source/UI/Dialogs/UITalkboxTrapInputWnd.h, Source/UI/Dialogs/UITransMenuWnd.h, Source/UI/Dialogs/UIVideoWnd.h, Source/UI/Dialogs/UIWordDisplayWnd.h, Source/UI/Edit/UIItemTagCtrl.h, Source/UI/Enchant/EnchantUI.h, Source/UI/Events/UICheckAttendanceWnd.h, Source/UI/Events/UIOpenRoulletteWnd.h, Source/UI/Events/UIRoulletteWnd.h, Source/UI/Exchange/UIExchangeUI.h, Source/UI/GameSettings/GameSettingsUI.h, Source/UI/GameSettings/UIBattleMsgOptionWnd.h, Source/UI/GameSettings/UIEscOptionWnd.h, Source/UI/GameSettings/UIHotKeyWnd.h, Source/UI/GameSettings/UIHotkeyGuideWnd.h, Source/UI/GameSettings/UIViewCameraInfoWnd.h, Source/UI/Gauges/UIBarGraph.h, Source/UI/Guild/UIEmblemWnd.h, Source/UI/Guild/UIGuildWnd.h, Source/UI/Items/UIChangeMaterialWnd.h, Source/UI/Items/UICollectionSystemWnd.h, Source/UI/Items/UIEquipmentPropertiesWnd.h, Source/UI/Items/UIGradeEnchantWnd.h, Source/UI/Items/UIIngredientInfoWnd.h, Source/UI/Items/UIItemBaseWnd.h, Source/UI/Items/UIItemCollectionWnd.h, Source/UI/Items/UIItemMoveInfo.h, Source/UI/Items/UIItemPurchaseWnd.h, Source/UI/Items/UIItemReformWnd.h, Source/UI/Items/UIItemSellWnd.h, Source/UI/Items/UIItemSellWnd2.h, Source/UI/Items/UIItemShopWnd.h, Source/UI/Items/UIItemShopWnd2.h, Source/UI/Items/UIItemStoreComboBox.h, Source/UI/Items/UIItemStoreFindWnd.h, Source/UI/Items/UIItemStoreSubWnd.h, Source/UI/Items/UIItemStoreWnd.h, Source/UI/Items/UIItemWnd.h, Source/UI/Items/UILapineScrollBar.h, Source/UI/Items/UILapineUpgradeBoxWnd.h, Source/UI/Items/UIMerchantItemLogWnd.h, Source/UI/Items/UIParaItemShopWnd.h, Source/UI/Items/UIPreviewEquipWnd.h, Source/UI/Items/UIRefiningWnd.h, Source/UI/Items/UISecondCostumeWnd.h, Source/UI/Items/UISelectCartWnd.h, Source/UI/Lists/UIComboBoxEx.h, Source/UI/Lists/UIScrollBarVariants.h, Source/UI/Lists/UIScrollWnd.h, Source/UI/Lists/UITagListBox.h, Source/UI/Login/FuncDrawWNDChar.h, Source/UI/Login/UIChangeNameWnd.h, Source/UI/Login/UIDescriptRace.h, Source/UI/Login/UIEmailAddressWnd.h, Source/UI/Login/UILoginOTPWnd.h, Source/UI/Login/UILoginWnd.h, Source/UI/Login/UIMakeCharWnd.h, Source/UI/Login/UINewMakeCharWnd.h, Source/UI/Login/UINewSelectCharWnd.h, Source/UI/Login/UIPasswordWnd.h, Source/UI/Login/UISecondPasswordEditWnd.h, Source/UI/Login/UISelCharForUServerWnd.h, Source/UI/Login/UISelectServerWnd.h, Source/UI/Login/UIWaitDBSaveWnd.h, Source/UI/Macro/UICaptchaPreviewWnd.h, Source/UI/Macro/UICaptchaRegisterWnd.h, Source/UI/Macro/UIMacroBlackListCheckWnd.h, Source/UI/Macro/UIMacroDetectorWnd.h, Source/UI/Macro/UIMacroReport.h, Source/UI/Macro/UIMacroUserInfoWnd.h, Source/UI/Monster/UIMonsterDisplayWnd.h, Source/UI/Monster/UIMonsterInfoWnd.h, Source/UI/Navigation/NavigationLink.h, Source/UI/Navigation/UIChooseWarpWnd.h, Source/UI/Navigation/UIListBoxNavi.h, Source/UI/Navigation/UIListBoxNaviSearch.h, Source/UI/Navigation/UIMemorialDunWnd.h, Source/UI/Navigation/UIMiniMapWnd.h, Source/UI/Navigation/UIMinimapZoomWnd.h, Source/UI/Navigation/UINavigationHelpWnd.h, Source/UI/Navigation/UINavigationWnd.h, Source/UI/Navigation/UIRoMapWnd.h, Source/UI/Navigation/UIScrollBarNavi.h, Source/UI/Navigation/UIShowWarpWnd.h, Source/UI/Party/MiniPartyGrid.h, Source/UI/Party/MiniPartyPlacement.h, Source/UI/Party/MiniPartyWndAreaMgr.h, Source/UI/Party/UIJobSlotButton.h, Source/UI/Party/UIPartyBookingHelpWnd.h, Source/UI/Party/UISeekPartyListWnd.h, Source/UI/Party/UISeekPartyMBWnd.h, Source/UI/Party/UISeekPartyWnd.h, Source/UI/ProbabilityTable/UIProbabilityTable.h, Source/UI/Quest/UINotifyQuestWnd.h, Source/UI/Quest/UIOngoingQuestInfo.h, Source/UI/Quest/UIRecommendedQuestInfo.h, Source/UI/Quest/UIRenewQuestUI.h, Source/UI/Quest/UIRenewQuestWnd.h, Source/UI/Replay/UIReplayButton.h, Source/UI/Replay/UIReplayControlWnd.h, Source/UI/Replay/UIReplayListBox.h, Source/UI/Replay/UIReplayRECControlWnd.h, Source/UI/Replay/UISelectReplayDataWnd.h, Source/UI/Repute/UIReputeWnd.h, Source/UI/Rodex/UIOpenMailBoxWnd.h, Source/UI/Rodex/UIRodexContentsWnd.h, Source/UI/Rodex/UIRodexInboxWnd.h, Source/UI/RuneSystem/UIRuneSystemWindows.h, Source/UI/RuneSystem/UIRuneSystemWnd.h, Source/UI/SelectPackageItemBox/SelectPackageItemBox.h, Source/UI/SelectPackageItemBox/UIPackageBoxNameList.h, Source/UI/Shop/PriceCommission.h, Source/UI/Shop/UIBank_NewWnd.h, Source/UI/Shop/UIBartermarketWnd.h, Source/UI/Shop/UIMerchantItemMyShopWnd.h, Source/UI/Shop/UIMerchantItemPurchaseWnd.h, Source/UI/Shop/UIMerchantItemShopWnd.h, Source/UI/Shop/UIMerchantItemWnd.h, Source/UI/Shop/UIMerchantMirrorItemWnd.h, Source/UI/Shop/UISerachStoreInfoWnd.h, Source/UI/Shop/UInCash_CallWnd.h, Source/UI/Skill/UIDebuffRemoveWnd.h, Source/UI/Skill/UIGraffiStrboxWnd.h, Source/UI/Skill/UINewSkillListWnd.h, Source/UI/SkillDelayInfo/SkillDelayInfo.h, Source/UI/Status/UIBasicInfoWnd.h, Source/UI/Status/UIHomunInfoWnd.h, Source/UI/Status/UIJobListWnd.h, Source/UI/Status/UIMerInfoWnd.h, Source/UI/Status/UIPetEvolutionWnd.h, Source/UI/Status/UIPetInfoWnd.h, Source/UI/Status/UIPetTamingDeceiveWnd.h, Source/UI/Status/UIRebirthWnd.h, Source/UI/StylingShop/UIStylingShopWnd.h, Source/UI/Text/TextTags.h, Source/UI/Text/UIBroadcastBalloon.h, Source/UI/Text/UIRoundBoxTooltipWnd.h, Source/UI/Window/FrameSkin.h, Source/UI/Window/UIBasicCtrl.h, Source/UI/Window/UIControl.h, Source/UI/Window/UIWindowMgr.inl, Source/Utility/Cipher/EncryptedName.h, Source/Utility/Hash/CRC32.h, Source/Utility/Hash/GGHash.h, Source/Utility/Hash/GGHashMgr.h, Source/Utility/Hash/Md5State.h, Source/Utility/Hash/SHA3.h, Source/Utility/Hash/XxHash3.h, Source/Utility/Text/GuidParse.h, Source/Utility/Text/Tokenizer.h, Source/Utility/Zlib.h, Source/ActorPickNode.h, Source/Client/ModeFade.h, Source/Client/ModeFadeOut.h, Source/Client/ModeScreenshot.h, Source/Client/Registry.h, Source/Client/Replay.h, Source/Client/ReplayRecordOption.h, Source/Client/Session.h, Source/Client/Timer.h, Source/Network/ActorNamePacket.h, Source/Network/ClientKeepalive.h, Source/Network/ClientOptionPacket.h, Source/Network/ExecutableDigestPacket.h, Source/Network/GameTickPacket.h, Source/Render/ActionSpriteDrawing.h, Source/Render/AuxiliarySubmission.h, Source/Render/BitmapDrawing.h, Source/Render/BlendColor.h, Source/Render/DeviceSelection.h, Source/Render/Direct3DErrors.h, Source/Render/DisplayMode.h, Source/Render/RenderAdapter.h, Source/Render/RenderBackends.h, Source/Render/RendererDX7.h, Source/Render/ScreenGeometry.h, Source/Render/ScreenRectangle.h, Source/Render/SpriteGeometry.h, Source/Render/SpriteQuad.h, Source/Render/TextureQuad.h, Source/Render/TextureStageModes.h, Source/Resource/BinkRuntime.h, Source/Resource/EZeffectResource.h, Source/Resource/EmblemResource.h, Source/Resource/GifLzw.h, Source/Resource/GifResource.h, Source/Resource/ImfResource.h, Source/Resource/PaletteResource.h, Source/Resource/RmaResource.h, Source/Resource/SkinPalette.h, Source/Resource/TextureNames.h, Source/Resource/XmlNode.h, Source/UI/Buttons/UICashEmotionSprBtn.h, Source/UI/Buttons/UIDescriptRace.h, Source/UI/Buttons/UIItemMoveInfo.h, Source/UI/Buttons/UIJobSlotButton.h, Source/UI/Buttons/UIReplayButton.h, Source/UI/Dialogs/UIChooseWarpWnd.h, Source/UI/Dialogs/UIEmailAddressWnd.h, Source/UI/Dialogs/UIGraffiStrboxWnd.h, Source/UI/Dialogs/UIMemorialDunWnd.h, Source/UI/Dialogs/UIMiniMapWnd.h, Source/UI/Dialogs/UIMinimapZoomWnd.h, Source/UI/Dialogs/UINotifyQuestWnd.h, Source/UI/Dialogs/UIPasswordWnd.h, Source/UI/Dialogs/UIPetTamingDeceiveWnd.h, Source/UI/Dialogs/UISecondPasswordEditWnd.h, Source/UI/Dialogs/UISelectCartWnd.h, Source/UI/Dialogs/UIWaitDBSaveWnd.h, Source/UI/FrameSkin.h, Source/UI/Item/UIEquipmentPropertiesWnd.h, Source/UI/Item/UIItemBaseWnd.h, Source/UI/Item/UIItemPurchaseWnd.h, Source/UI/Item/UIItemSellWnd.h, Source/UI/Item/UIItemSellWnd2.h, Source/UI/Item/UIItemShopWnd.h, Source/UI/Item/UIItemShopWnd2.h, Source/UI/Item/UIItemStoreFindWnd.h, Source/UI/Item/UIItemStoreSubWnd.h, Source/UI/Item/UIItemStoreWnd.h, Source/UI/Item/UIItemWnd.h, Source/UI/Item/UIMerchantItemLogWnd.h, Source/UI/Item/UIParaItemShopWnd.h, Source/UI/Lists/UIItemStoreComboBox.h, Source/UI/Lists/UIListBoxNavi.h, Source/UI/Lists/UIListBoxNaviSearch.h, Source/UI/Lists/UIPackageBoxNameList.h, Source/UI/Lists/UIReplayListBox.h, Source/UI/Lists/UIScrollBarNavi.h, Source/UI/MiniPartyGrid.h, Source/UI/MiniPartyPlacement.h, Source/UI/PriceCommission.h, Source/UI/Text/NavigationLink.h, Source/UI/Text/UIAchWnd.h, Source/UI/TextTags.h, Source/UI/UIBarGraph.h, Source/UI/UIBartermarketWnd.h, Source/UI/UIBasicCtrl.h, Source/UI/UIBroadcastBalloon.h, Source/UI/UICaptchaPreviewWnd.h, Source/UI/UICaptchaRegisterWnd.h, Source/UI/UIChangeMaterialWnd.h, Source/UI/UICheckAttendanceWnd.h, Source/UI/UIGradeEnchantWnd.h, Source/UI/UIHotkeyGuideWnd.h, Source/UI/UIIngredientInfoWnd.h, Source/UI/UIItemReformWnd.h, Source/UI/UILapineScrollBar.h, Source/UI/UILapineUpgradeBoxWnd.h, Source/UI/UIMacroBlackListCheckWnd.h, Source/UI/UIMacroDetectorWnd.h, Source/UI/UIMacroReport.h, Source/UI/UIMacroUserInfoWnd.h, Source/UI/UIPreviewEquipWnd.h, Source/UI/UIRefiningWnd.h, Source/UI/UIReputeWnd.h, Source/UI/UIRoundBoxTooltipWnd.h, Source/UI/UIScrollWnd.h, Source/UI/UISlotBitmap.h, Source/UI/UIStaticBitmap.h, Source/UI/UIStaticItem.h, Source/UI/Window/FuncDrawWNDChar.h, Source/UI/Window/MiniPartyWndAreaMgr.h, Source/UI/Window/UIAccountLimitedToolWnd.h, Source/UI/Window/UIBalloonOpenBtn.h, Source/UI/Window/UIBank_NewWnd.h, Source/UI/Window/UIBasicInfoWnd.h, Source/UI/Window/UIBattleMsgOptionWnd.h, Source/UI/Window/UIChangeNameWnd.h, Source/UI/Window/UIChatRoomWnd.h, Source/UI/Window/UICntWnd.h, Source/UI/Window/UICollectionSystemWnd.h, Source/UI/Window/UIDebuffRemoveWnd.h, Source/UI/Window/UIEmblemWnd.h, Source/UI/Window/UIEscOptionWnd.h, Source/UI/Window/UIHomunInfoWnd.h, Source/UI/Window/UIHotKeyWnd.h, Source/UI/Window/UIJobListWnd.h, Source/UI/Window/UILoginOTPWnd.h, Source/UI/Window/UILoginWnd.h, Source/UI/Window/UIMakeCharWnd.h, Source/UI/Window/UIMerInfoWnd.h, Source/UI/Window/UIMessageBox.h, Source/UI/Window/UIMessageBoxAutoreturn.h, Source/UI/Window/UIMileageWnd.h, Source/UI/Window/UIMiniBtnWnd.h, Source/UI/Window/UIMonsterDisplayWnd.h, Source/UI/Window/UIMonsterInfoWnd.h, Source/UI/Window/UINavigationHelpWnd.h, Source/UI/Window/UINavigationWnd.h, Source/UI/Window/UINewMakeCharWnd.h, Source/UI/Window/UINewSelectCharWnd.h, Source/UI/Window/UINewSkillListWnd.h, Source/UI/Window/UINormalMB.h, Source/UI/Window/UINoteWnd.h, Source/UI/Window/UINoticeWnd.h, Source/UI/Window/UIOpenMailBoxWnd.h, Source/UI/Window/UIOpenRoulletteWnd.h, Source/UI/Window/UIPartyBookingHelpWnd.h, Source/UI/Window/UIPayConfirmWnd.h, Source/UI/Window/UIPetEvolutionWnd.h, Source/UI/Window/UIPetInfoWnd.h, Source/UI/Window/UIRPImageWnd.h, Source/UI/Window/UIRPImageWnd2.h, Source/UI/Window/UIRebirthWnd.h, Source/UI/Window/UIReplayControlWnd.h, Source/UI/Window/UIReplayRECControlWnd.h, Source/UI/Window/UIRoMapWnd.h, Source/UI/Window/UIRodexContentsWnd.h, Source/UI/Window/UIRoulletteWnd.h, Source/UI/Window/UISecondCostumeWnd.h, Source/UI/Window/UISeekPartyListWnd.h, Source/UI/Window/UISeekPartyMBWnd.h, Source/UI/Window/UISeekPartyWnd.h, Source/UI/Window/UISelCharForUServerWnd.h, Source/UI/Window/UISelectReplayDataWnd.h, Source/UI/Window/UISelectServerWnd.h, Source/UI/Window/UISerachStoreInfoWnd.h, Source/UI/Window/UIShowWarpWnd.h, Source/UI/Window/UITalkboxTrapInputWnd.h, Source/UI/Window/UITransMenuWnd.h, Source/UI/Window/UIVideoWnd.h, Source/UI/Window/UIViewCameraInfoWnd.h, Source/UI/Window/UIWindowCallBtnWnd.h, Source/UI/Window/UIWordDisplayWnd.h, Source/Utility/CRC32.h, Source/Utility/Compression/Zlib.h, Source/Utility/EncryptedName.h, Source/Utility/FileSignatureVerifier.h, Source/Utility/GGHash.h, Source/Utility/GGHashMgr.h, Source/Utility/GuidParse.h, Source/Utility/JsonCppLoader.h, Source/Utility/Md5State.h, Source/Utility/NFileLog.h, Source/Utility/NIPAddr.h, Source/Utility/ProcessSecurity.h, Source/Utility/RegistryKey.h, Source/Utility/SHA3.h, Source/Utility/Tokenizer.h, Source/Utility/XxHash3.h. Adds to the build: Source/Client/Application/ClientOptions.cpp, Source/Client/Application/Registry.cpp, Source/Client/Application/RegistryKey.cpp, Source/Client/Application/Timer.cpp, Source/Client/Mode/EntityInit.cpp, Source/Client/Mode/ModeBaseEvents.cpp, Source/Client/Mode/ModeCursorDrawing.cpp, Source/Client/Mode/ModeFade.cpp, Source/Client/Mode/ModeFadeOut.cpp, Source/Client/Mode/ModeScreenshot.cpp, Source/Client/Mode/ModeTransitions.cpp, Source/Client/Replay/Replay.cpp, Source/Client/Replay/ReplayControl.cpp, Source/Client/Replay/ReplayPacketRecorder.cpp, Source/Client/Session/Session.cpp, Source/Client/Session/SessionAchievements.cpp, Source/Client/Session/SessionParty.cpp, Source/Client/Session/SessionPredicates.cpp, Source/Client/Session/SessionState.cpp, Source/Contents/Actors/ActorPickNode.cpp, Source/File/NFileLog.cpp, Source/Network/NIPAddr.cpp, Source/Network/Packets/ActorNamePacket.cpp, Source/Network/Packets/ClientKeepalive.cpp, Source/Network/Packets/ClientOptionPacket.cpp, Source/Network/Packets/ExecutableDigestPacket.cpp, Source/Network/Packets/GameTickPacket.cpp, Source/Render/DX7/AlphaQueuesDX7.cpp, Source/Render/DX7/AuxiliaryQueuesDX7.cpp, Source/Render/DX7/OpaqueQueuesDX7.cpp, Source/Render/DX7/RendererDX7.cpp, Source/Render/DX9/DeviceCapabilitiesDX9.cpp, Source/Render/Device/DeviceSelection.cpp, Source/Render/Device/Direct3DErrors.cpp, Source/Render/Device/DisplayMode.cpp, Source/Render/Device/RenderAdapter.cpp, Source/Render/Device/RenderBackends.cpp, Source/Render/Drawing/ActionSpriteDrawing.cpp, Source/Render/Drawing/BitmapDrawing.cpp, Source/Render/Drawing/BlendColor.cpp, Source/Render/Drawing/SpriteGeometry.cpp, Source/Render/Primitives/AlphaRectangle.cpp, Source/Render/Primitives/AuxiliarySubmission.cpp, Source/Render/Primitives/SpriteQuad.cpp, Source/Render/Primitives/TextureQuad.cpp, Source/Render/Primitives/UIRPDataDrawing.cpp, Source/Render/Projection/ScreenGeometry.cpp, Source/Render/Projection/ScreenRectangle.cpp, Source/Render/Projection/ViewportProjection.cpp, Source/Resource/Bitmap/EmblemResource.cpp, Source/Resource/Bitmap/GifLzw.cpp, Source/Resource/Bitmap/GifResource.cpp, Source/Resource/Bitmap/PaletteResource.cpp, Source/Resource/Bitmap/SkinPalette.cpp, Source/Resource/Bitmap/TextureNames.cpp, Source/Resource/Effects/EZeffectResource.cpp, Source/Resource/Json/JsonCppLoader.cpp, Source/Resource/Models/RmaResource.cpp, Source/Resource/Sprites/ImfLayerIndex.cpp, Source/Resource/Sprites/ImfResource.cpp, Source/Resource/Xml/XmlNode.cpp, Source/Resource/Xml/XmlParsing.cpp, Source/Security/FileSignatureVerifier.cpp, Source/Security/ProcessSecurity.cpp, Source/Security/UnknownA68.cpp, Source/UI/Achievement/UIAchWnd.cpp, Source/UI/Buttons/UIBalloonOpenBtn.cpp, Source/UI/Buttons/UIMiniBtnWnd.cpp, Source/UI/Buttons/UISlotBitmap.cpp, Source/UI/Buttons/UIStaticBitmap.cpp, Source/UI/Buttons/UIStaticItem.cpp, Source/UI/CashShop/UIMileageWnd.cpp, Source/UI/Chat/UIZeroChatWnd.cpp, Source/UI/Dialogs/UIAccountLimitedToolWnd.cpp, Source/UI/Dialogs/UILocaleTextWnd.cpp, Source/UI/Dialogs/UIMessageBox.cpp, Source/UI/Dialogs/UINormalMB.cpp, Source/UI/Dialogs/UINoteWnd.cpp, Source/UI/Dialogs/UINoticeWnd.cpp, Source/UI/Dialogs/UIRPImageWnd.cpp, Source/UI/Dialogs/UIRPImageWnd2.cpp, Source/UI/Dialogs/UITransMenuWnd.cpp, Source/UI/Dialogs/UIVideoWnd.cpp, Source/UI/Dialogs/UIWordDisplayWnd.cpp, Source/UI/Events/UICheckAttendanceWnd.cpp, Source/UI/Events/UIOpenRoulletteWnd.cpp, Source/UI/Events/UIRoulletteWnd.cpp, Source/UI/GameSettings/UIBattleMsgOptionWnd.cpp, Source/UI/GameSettings/UIEscOptionWnd.cpp, Source/UI/GameSettings/UIHotKeyWnd.cpp, Source/UI/GameSettings/UIHotkeyGuideWnd.cpp, Source/UI/GameSettings/UIViewCameraInfoWnd.cpp, Source/UI/Gauges/UIBarGraph.cpp, Source/UI/Guild/UIEmblemWnd.cpp, Source/UI/Items/UIChangeMaterialWnd.cpp, Source/UI/Items/UICollectionSystemWnd.cpp, Source/UI/Items/UIEquipmentPropertiesWnd.cpp, Source/UI/Items/UIGradeEnchantWnd.cpp, Source/UI/Items/UIItemMoveInfo.cpp, Source/UI/Items/UIItemReformWnd.cpp, Source/UI/Items/UIItemStoreComboBox.cpp, Source/UI/Items/UIItemStoreWnd.cpp, Source/UI/Items/UILapineBoxWnd.cpp, Source/UI/Items/UILapineScrollBar.cpp, Source/UI/Items/UILapineUpgradeBoxWnd.cpp, Source/UI/Items/UIMerchantItemLogWnd.cpp, Source/UI/Items/UIParaItemShopWnd.cpp, Source/UI/Items/UIPreviewEquipWnd.cpp, Source/UI/Items/UIRefiningWnd.cpp, Source/UI/Items/UISecondCostumeWnd.cpp, Source/UI/Lists/UIScrollWnd.cpp, Source/UI/Login/FuncDrawWNDChar.cpp, Source/UI/Login/UIChangeNameWnd.cpp, Source/UI/Login/UIDescriptRace.cpp, Source/UI/Login/UIEmailAddressWnd.cpp, Source/UI/Login/UILoginWnd.cpp, Source/UI/Login/UINewMakeCharWnd.cpp, Source/UI/Login/UINewSelectCharWnd.cpp, Source/UI/Login/UIPasswordWnd.cpp, Source/UI/Login/UISelCharForUServerWnd.cpp, Source/UI/Login/UIWaitDBSaveWnd.cpp, Source/UI/Macro/UICaptchaPreviewWnd.cpp, Source/UI/Macro/UICaptchaRegisterWnd.cpp, Source/UI/Macro/UIMacroBlackListCheckWnd.cpp, Source/UI/Macro/UIMacroDetectorWnd.cpp, Source/UI/Macro/UIMacroReport.cpp, Source/UI/Macro/UIMacroUserInfoWnd.cpp, Source/UI/Navigation/NavigationLink.cpp, Source/UI/Navigation/UIListBoxNavi.cpp, Source/UI/Navigation/UIMinimapZoomWnd.cpp, Source/UI/Navigation/UINavigationHelpWnd.cpp, Source/UI/Navigation/UINavigationWnd.cpp, Source/UI/Navigation/UIRoMapWnd.cpp, Source/UI/Navigation/UIScrollBarNavi.cpp, Source/UI/Navigation/UIShowWarpWnd.cpp, Source/UI/Party/MiniPartyGrid.cpp, Source/UI/Party/MiniPartyManager.cpp, Source/UI/Party/MiniPartyPlacement.cpp, Source/UI/Party/MiniPartyUsableArea.cpp, Source/UI/Party/UIJobSlotButton.cpp, Source/UI/Party/UIPartyBookingHelpWnd.cpp, Source/UI/Party/UISeekPartyListWnd.cpp, Source/UI/Party/UISeekPartyMBWnd.cpp, Source/UI/Party/UISeekPartyWnd.cpp, Source/UI/Repute/UIReputeWnd.cpp, Source/UI/Rodex/UIOpenMailBoxWnd.cpp, Source/UI/Rodex/UIRodexContentsWnd.cpp, Source/UI/SelectPackageItemBox/UIPackageBoxNameList.cpp, Source/UI/Shop/PriceCommission.cpp, Source/UI/Shop/UIBartermarketWnd.cpp, Source/UI/Shop/UISerachStoreInfoWnd.cpp, Source/UI/Skill/UIDebuffRemoveWnd.cpp, Source/UI/Skill/UIGraffiStrboxWnd.cpp, Source/UI/Skill/UINewSkillListWnd.cpp, Source/UI/Skill/UINewSkillListWndHitTest.cpp, Source/UI/Status/UIBasicInfoWnd.cpp, Source/UI/Status/UIJobListWnd.cpp, Source/UI/Status/UIPetEvolutionWnd.cpp, Source/UI/Status/UIRebirthWnd.cpp, Source/UI/Text/TextTagExtraction.cpp, Source/UI/Text/TextTagRegistry.cpp, Source/UI/Text/UIBroadcastBalloon.cpp, Source/UI/Text/UIRoundBoxTooltipWnd.cpp, Source/UI/Window/FrameSkin.cpp, Source/UI/Window/UIBasicCtrl.cpp, Source/UI/Window/WindowBackground.cpp, Source/UI/Window/WindowLowerBorder.cpp, Source/UI/Window/WindowOverlay.cpp, Source/UI/Window/WindowSprite.cpp, Source/UI/Window/WindowTitlebar.cpp, Source/Utility/BoolStubs.cpp, Source/Utility/Hash/CRC32.cpp, Source/Utility/Hash/GGHash.cpp, Source/Utility/Hash/GGHashMgr.cpp, Source/Utility/Hash/Md5State.cpp, Source/Utility/Hash/SHA3.cpp, Source/Utility/Hash/XxHash3.cpp, Source/Utility/Lexicon/LexiconTrie.cpp, Source/Utility/Text/GuidParse.cpp, Source/Utility/Text/Tokenizer.cpp Deletes: Source/ActorPickNode.cpp, Source/ActorPickNode.h, Source/Archive/UnknownA68.cpp, Source/Client/ClientOptions.cpp, Source/Client/ModeBaseEvents.cpp, Source/Client/ModeCursorDrawing.cpp, Source/Client/ModeFade.cpp, Source/Client/ModeFade.h, Source/Client/ModeFadeOut.cpp, Source/Client/ModeFadeOut.h, Source/Client/ModeScreenshot.cpp, Source/Client/ModeScreenshot.h, Source/Client/ModeTransitions.cpp, Source/Client/Registry.cpp, Source/Client/Registry.h, Source/Client/Replay.cpp, Source/Client/Replay.h, Source/Client/ReplayControl.cpp, Source/Client/ReplayPacketRecorder.cpp, Source/Client/ReplayRecordOption.h, Source/Client/Session.cpp, Source/Client/Session.h, Source/Client/SessionAchievements.cpp, Source/Client/SessionParty.cpp, Source/Client/SessionPredicates.cpp, Source/Client/SessionState.cpp, Source/Client/Timer.cpp, Source/Client/Timer.h, Source/EntityInit.cpp, Source/Interface/BoolStubs.cpp, Source/LexiconTrie.cpp, Source/Network/ActorNamePacket.cpp, Source/Network/ActorNamePacket.h, Source/Network/ClientKeepalive.cpp, Source/Network/ClientKeepalive.h, Source/Network/ClientOptionPacket.cpp, Source/Network/ClientOptionPacket.h, Source/Network/ExecutableDigestPacket.cpp, Source/Network/ExecutableDigestPacket.h, Source/Network/GameTickPacket.cpp, Source/Network/GameTickPacket.h, Source/Render/ActionSpriteDrawing.cpp, Source/Render/ActionSpriteDrawing.h, Source/Render/AlphaQueuesDX7.cpp, Source/Render/AlphaRectangle.cpp, Source/Render/AuxiliaryQueuesDX7.cpp, Source/Render/AuxiliarySubmission.cpp, Source/Render/AuxiliarySubmission.h, Source/Render/BitmapDrawing.cpp, Source/Render/BitmapDrawing.h, Source/Render/BlendColor.cpp, Source/Render/BlendColor.h, Source/Render/DeviceCapabilitiesDX9.cpp, Source/Render/DeviceSelection.cpp, Source/Render/DeviceSelection.h, Source/Render/Direct3DErrors.cpp, Source/Render/Direct3DErrors.h, Source/Render/DisplayMode.cpp, Source/Render/DisplayMode.h, Source/Render/OpaqueQueuesDX7.cpp, Source/Render/RenderAdapter.cpp, Source/Render/RenderAdapter.h, Source/Render/RenderBackends.cpp, Source/Render/RenderBackends.h, Source/Render/RendererDX7.cpp, Source/Render/RendererDX7.h, Source/Render/ScreenGeometry.cpp, Source/Render/ScreenGeometry.h, Source/Render/ScreenRectangle.cpp, Source/Render/ScreenRectangle.h, Source/Render/SpriteGeometry.cpp, Source/Render/SpriteGeometry.h, Source/Render/SpriteQuad.cpp, Source/Render/SpriteQuad.h, Source/Render/TextureQuad.cpp, Source/Render/TextureQuad.h, Source/Render/TextureStageModes.h, Source/Render/UIRPDataDrawing.cpp, Source/Render/ViewportProjection.cpp, Source/Resource/BinkRuntime.h, Source/Resource/EZeffectResource.cpp, Source/Resource/EZeffectResource.h, Source/Resource/EmblemResource.cpp, Source/Resource/EmblemResource.h, Source/Resource/GifLzw.cpp, Source/Resource/GifLzw.h, Source/Resource/GifResource.cpp, Source/Resource/GifResource.h, Source/Resource/ImfLayerIndex.cpp, Source/Resource/ImfResource.cpp, Source/Resource/ImfResource.h, Source/Resource/PaletteResource.cpp, Source/Resource/PaletteResource.h, Source/Resource/RmaResource.cpp, Source/Resource/RmaResource.h, Source/Resource/SkinPalette.cpp, Source/Resource/SkinPalette.h, Source/Resource/TextureNames.cpp, Source/Resource/TextureNames.h, Source/Resource/XmlNode.cpp, Source/Resource/XmlNode.h, Source/Resource/XmlParsing.cpp, Source/UI/Buttons/UICashEmotionSprBtn.h, Source/UI/Buttons/UIDescriptRace.cpp, Source/UI/Buttons/UIDescriptRace.h, Source/UI/Buttons/UIItemMoveInfo.cpp, Source/UI/Buttons/UIItemMoveInfo.h, Source/UI/Buttons/UIJobSlotButton.cpp, Source/UI/Buttons/UIJobSlotButton.h, Source/UI/Buttons/UIReplayButton.h, Source/UI/Dialogs/UIChooseWarpWnd.h, Source/UI/Dialogs/UIEmailAddressWnd.cpp, Source/UI/Dialogs/UIEmailAddressWnd.h, Source/UI/Dialogs/UIGraffiStrboxWnd.cpp, Source/UI/Dialogs/UIGraffiStrboxWnd.h, Source/UI/Dialogs/UIMemorialDunWnd.h, Source/UI/Dialogs/UIMiniMapWnd.h, Source/UI/Dialogs/UIMinimapZoomWnd.cpp, Source/UI/Dialogs/UIMinimapZoomWnd.h, Source/UI/Dialogs/UINotifyQuestWnd.h, Source/UI/Dialogs/UIPasswordWnd.cpp, Source/UI/Dialogs/UIPasswordWnd.h, Source/UI/Dialogs/UIPetTamingDeceiveWnd.h, Source/UI/Dialogs/UISecondPasswordEditWnd.h, Source/UI/Dialogs/UISelectCartWnd.h, Source/UI/Dialogs/UIWaitDBSaveWnd.cpp, Source/UI/Dialogs/UIWaitDBSaveWnd.h, Source/UI/FrameSkin.cpp, Source/UI/FrameSkin.h, Source/UI/Item/UIEquipmentPropertiesWnd.cpp, Source/UI/Item/UIEquipmentPropertiesWnd.h, Source/UI/Item/UIItemBaseWnd.h, Source/UI/Item/UIItemPurchaseWnd.h, Source/UI/Item/UIItemSellWnd.h, Source/UI/Item/UIItemSellWnd2.h, Source/UI/Item/UIItemShopWnd.h, Source/UI/Item/UIItemShopWnd2.h, Source/UI/Item/UIItemStoreFindWnd.h, Source/UI/Item/UIItemStoreSubWnd.h, Source/UI/Item/UIItemStoreWnd.cpp, Source/UI/Item/UIItemStoreWnd.h, Source/UI/Item/UIItemWnd.h, Source/UI/Item/UIMerchantItemLogWnd.cpp, Source/UI/Item/UIMerchantItemLogWnd.h, Source/UI/Item/UIParaItemShopWnd.cpp, Source/UI/Item/UIParaItemShopWnd.h, Source/UI/Lists/UIItemStoreComboBox.cpp, Source/UI/Lists/UIItemStoreComboBox.h, Source/UI/Lists/UIListBoxNavi.cpp, Source/UI/Lists/UIListBoxNavi.h, Source/UI/Lists/UIListBoxNaviSearch.h, Source/UI/Lists/UIPackageBoxNameList.cpp, Source/UI/Lists/UIPackageBoxNameList.h, Source/UI/Lists/UIReplayListBox.h, Source/UI/Lists/UIScrollBarNavi.cpp, Source/UI/Lists/UIScrollBarNavi.h, Source/UI/MiniPartyGrid.cpp, Source/UI/MiniPartyGrid.h, Source/UI/MiniPartyManager.cpp, Source/UI/MiniPartyPlacement.cpp, Source/UI/MiniPartyPlacement.h, Source/UI/MiniPartyUsableArea.cpp, Source/UI/PriceCommission.cpp, Source/UI/PriceCommission.h, Source/UI/Text/NavigationLink.cpp, Source/UI/Text/NavigationLink.h, Source/UI/Text/UIAchWnd.cpp, Source/UI/Text/UIAchWnd.h, Source/UI/TextTagExtraction.cpp, Source/UI/TextTagRegistry.cpp, Source/UI/TextTags.h, Source/UI/UIBarGraph.cpp, Source/UI/UIBarGraph.h, Source/UI/UIBartermarketWnd.cpp, Source/UI/UIBartermarketWnd.h, Source/UI/UIBasicCtrl.cpp, Source/UI/UIBasicCtrl.h, Source/UI/UIBroadcastBalloon.cpp, Source/UI/UIBroadcastBalloon.h, Source/UI/UICaptchaPreviewWnd.cpp, Source/UI/UICaptchaPreviewWnd.h, Source/UI/UICaptchaRegisterWnd.cpp, Source/UI/UICaptchaRegisterWnd.h, Source/UI/UIChangeMaterialWnd.cpp, Source/UI/UIChangeMaterialWnd.h, Source/UI/UICheckAttendanceWnd.cpp, Source/UI/UICheckAttendanceWnd.h, Source/UI/UIGradeEnchantWnd.cpp, Source/UI/UIGradeEnchantWnd.h, Source/UI/UIHotkeyGuideWnd.cpp, Source/UI/UIHotkeyGuideWnd.h, Source/UI/UIIngredientInfoWnd.h, Source/UI/UIItemReformWnd.cpp, Source/UI/UIItemReformWnd.h, Source/UI/UILapineBoxWnd.cpp, Source/UI/UILapineScrollBar.cpp, Source/UI/UILapineScrollBar.h, Source/UI/UILapineUpgradeBoxWnd.cpp, Source/UI/UILapineUpgradeBoxWnd.h, Source/UI/UIMacroBlackListCheckWnd.cpp, Source/UI/UIMacroBlackListCheckWnd.h, Source/UI/UIMacroDetectorWnd.cpp, Source/UI/UIMacroDetectorWnd.h, Source/UI/UIMacroReport.cpp, Source/UI/UIMacroReport.h, Source/UI/UIMacroUserInfoWnd.cpp, Source/UI/UIMacroUserInfoWnd.h, Source/UI/UIPreviewEquipWnd.cpp, Source/UI/UIPreviewEquipWnd.h, Source/UI/UIRefiningWnd.cpp, Source/UI/UIRefiningWnd.h, Source/UI/UIReputeWnd.cpp, Source/UI/UIReputeWnd.h, Source/UI/UIRoundBoxTooltipWnd.cpp, Source/UI/UIRoundBoxTooltipWnd.h, Source/UI/UIScrollWnd.cpp, Source/UI/UIScrollWnd.h, Source/UI/UISlotBitmap.cpp, Source/UI/UISlotBitmap.h, Source/UI/UIStaticBitmap.cpp, Source/UI/UIStaticBitmap.h, Source/UI/UIStaticItem.cpp, Source/UI/UIStaticItem.h, Source/UI/Window/FuncDrawWNDChar.cpp, Source/UI/Window/FuncDrawWNDChar.h, Source/UI/Window/MiniPartyWndAreaMgr.h, Source/UI/Window/UIAccountLimitedToolWnd.cpp, Source/UI/Window/UIAccountLimitedToolWnd.h, Source/UI/Window/UIBalloonOpenBtn.cpp, Source/UI/Window/UIBalloonOpenBtn.h, Source/UI/Window/UIBank_NewWnd.h, Source/UI/Window/UIBasicInfoWnd.cpp, Source/UI/Window/UIBasicInfoWnd.h, Source/UI/Window/UIBattleMsgOptionWnd.cpp, Source/UI/Window/UIBattleMsgOptionWnd.h, Source/UI/Window/UIChangeNameWnd.cpp, Source/UI/Window/UIChangeNameWnd.h, Source/UI/Window/UIChatRoomWnd.h, Source/UI/Window/UICntWnd.h, Source/UI/Window/UICollectionSystemWnd.cpp, Source/UI/Window/UICollectionSystemWnd.h, Source/UI/Window/UIDebuffRemoveWnd.cpp, Source/UI/Window/UIDebuffRemoveWnd.h, Source/UI/Window/UIEmblemWnd.cpp, Source/UI/Window/UIEmblemWnd.h, Source/UI/Window/UIEscOptionWnd.cpp, Source/UI/Window/UIEscOptionWnd.h, Source/UI/Window/UIHomunInfoWnd.h, Source/UI/Window/UIHotKeyWnd.cpp, Source/UI/Window/UIHotKeyWnd.h, Source/UI/Window/UIJobListWnd.cpp, Source/UI/Window/UIJobListWnd.h, Source/UI/Window/UILocaleTextWnd.cpp, Source/UI/Window/UILoginOTPWnd.h, Source/UI/Window/UILoginWnd.cpp, Source/UI/Window/UILoginWnd.h, Source/UI/Window/UIMakeCharWnd.h, Source/UI/Window/UIMerInfoWnd.h, Source/UI/Window/UIMessageBox.cpp, Source/UI/Window/UIMessageBox.h, Source/UI/Window/UIMessageBoxAutoreturn.h, Source/UI/Window/UIMileageWnd.cpp, Source/UI/Window/UIMileageWnd.h, Source/UI/Window/UIMiniBtnWnd.cpp, Source/UI/Window/UIMiniBtnWnd.h, Source/UI/Window/UIMonsterDisplayWnd.h, Source/UI/Window/UIMonsterInfoWnd.h, Source/UI/Window/UINavigationHelpWnd.cpp, Source/UI/Window/UINavigationHelpWnd.h, Source/UI/Window/UINavigationWnd.cpp, Source/UI/Window/UINavigationWnd.h, Source/UI/Window/UINewMakeCharWnd.cpp, Source/UI/Window/UINewMakeCharWnd.h, Source/UI/Window/UINewSelectCharWnd.cpp, Source/UI/Window/UINewSelectCharWnd.h, Source/UI/Window/UINewSkillListWnd.cpp, Source/UI/Window/UINewSkillListWnd.h, Source/UI/Window/UINewSkillListWndHitTest.cpp, Source/UI/Window/UINormalMB.cpp, Source/UI/Window/UINormalMB.h, Source/UI/Window/UINoteWnd.cpp, Source/UI/Window/UINoteWnd.h, Source/UI/Window/UINoticeWnd.cpp, Source/UI/Window/UINoticeWnd.h, Source/UI/Window/UIOpenMailBoxWnd.cpp, Source/UI/Window/UIOpenMailBoxWnd.h, Source/UI/Window/UIOpenRoulletteWnd.cpp, Source/UI/Window/UIOpenRoulletteWnd.h, Source/UI/Window/UIPartyBookingHelpWnd.cpp, Source/UI/Window/UIPartyBookingHelpWnd.h, Source/UI/Window/UIPayConfirmWnd.h, Source/UI/Window/UIPetEvolutionWnd.cpp, Source/UI/Window/UIPetEvolutionWnd.h, Source/UI/Window/UIPetInfoWnd.h, Source/UI/Window/UIRPImageWnd.cpp, Source/UI/Window/UIRPImageWnd.h, Source/UI/Window/UIRPImageWnd2.cpp, Source/UI/Window/UIRPImageWnd2.h, Source/UI/Window/UIRebirthWnd.cpp, Source/UI/Window/UIRebirthWnd.h, Source/UI/Window/UIReplayControlWnd.h, Source/UI/Window/UIReplayRECControlWnd.h, Source/UI/Window/UIRoMapWnd.cpp, Source/UI/Window/UIRoMapWnd.h, Source/UI/Window/UIRodexContentsWnd.cpp, Source/UI/Window/UIRodexContentsWnd.h, Source/UI/Window/UIRoulletteWnd.cpp, Source/UI/Window/UIRoulletteWnd.h, Source/UI/Window/UISecondCostumeWnd.cpp, Source/UI/Window/UISecondCostumeWnd.h, Source/UI/Window/UISeekPartyListWnd.cpp, Source/UI/Window/UISeekPartyListWnd.h, Source/UI/Window/UISeekPartyMBWnd.cpp, Source/UI/Window/UISeekPartyMBWnd.h, Source/UI/Window/UISeekPartyWnd.cpp, Source/UI/Window/UISeekPartyWnd.h, Source/UI/Window/UISelCharForUServerWnd.cpp, Source/UI/Window/UISelCharForUServerWnd.h, Source/UI/Window/UISelectReplayDataWnd.h, Source/UI/Window/UISelectServerWnd.h, Source/UI/Window/UISerachStoreInfoWnd.cpp, Source/UI/Window/UISerachStoreInfoWnd.h, Source/UI/Window/UIShowWarpWnd.cpp, Source/UI/Window/UIShowWarpWnd.h, Source/UI/Window/UITalkboxTrapInputWnd.h, Source/UI/Window/UITransMenuWnd.cpp, Source/UI/Window/UITransMenuWnd.h, Source/UI/Window/UIVideoWnd.cpp, Source/UI/Window/UIVideoWnd.h, Source/UI/Window/UIViewCameraInfoWnd.cpp, Source/UI/Window/UIViewCameraInfoWnd.h, Source/UI/Window/UIWindowCallBtnWnd.h, Source/UI/Window/UIWordDisplayWnd.cpp, Source/UI/Window/UIWordDisplayWnd.h, Source/UI/Window/UIZeroChatWnd.cpp, Source/UI/WindowBackground.cpp, Source/UI/WindowLowerBorder.cpp, Source/UI/WindowOverlay.cpp, Source/UI/WindowSprite.cpp, Source/UI/WindowTitlebar.cpp, Source/Utility/CRC32.cpp, Source/Utility/CRC32.h, Source/Utility/Compression/Zlib.h, Source/Utility/EncryptedName.h, Source/Utility/FileSignatureVerifier.cpp, Source/Utility/FileSignatureVerifier.h, Source/Utility/GGHash.cpp, Source/Utility/GGHash.h, Source/Utility/GGHashMgr.cpp, Source/Utility/GGHashMgr.h, Source/Utility/GuidParse.cpp, Source/Utility/GuidParse.h, Source/Utility/JsonCppLoader.cpp, Source/Utility/JsonCppLoader.h, Source/Utility/Md5State.cpp, Source/Utility/Md5State.h, Source/Utility/NFileLog.cpp, Source/Utility/NFileLog.h, Source/Utility/NIPAddr.cpp, Source/Utility/NIPAddr.h, Source/Utility/ProcessSecurity.cpp, Source/Utility/ProcessSecurity.h, Source/Utility/RegistryKey.cpp, Source/Utility/RegistryKey.h, Source/Utility/SHA3.cpp, Source/Utility/SHA3.h, Source/Utility/Tokenizer.cpp, Source/Utility/Tokenizer.h, Source/Utility/XxHash3.cpp, Source/Utility/XxHash3.h
1111 lines
37 KiB
C++
1111 lines
37 KiB
C++
#include "Client/Application/ErrorDialog.h"
|
|
#include "Client/Session/Session.h"
|
|
#include "File/File.h"
|
|
#include "File/ResourcePath.h"
|
|
#include "Render/DeviceContext/DCSurface.h"
|
|
#include "Render/Renderer.h"
|
|
#include "Render/Textures/Texture.h"
|
|
#include "Render/Textures/TextureCache.h"
|
|
#include "Resource/Bitmap/BitmapResource.h"
|
|
#include "Resource/Models/AnimatedModelResource.h"
|
|
#include "Resource/Models/GrannyModelResource.h"
|
|
#include "Resource/Models/ModelResource.h"
|
|
#include "Utility/Math/AffineMatrix.h"
|
|
#include "Resource/ResourceMgr.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <list>
|
|
#include <string>
|
|
|
|
// GLOBAL: gl_24708
|
|
char g_modelPath[MAX_PATH];
|
|
// GLOBAL: gl_24734
|
|
char g_animationPath[MAX_PATH];
|
|
// GLOBAL: gl_24707
|
|
unsigned g_animationJobs[10] = {1288, 722, 1324, 1000, 1000, 1000, 1000, 1286, 1285, 1287};
|
|
// GLOBAL: gl_24706
|
|
const char* g_animationNames[5] = {"stand", "move", "attack", "dead", "damage"};
|
|
|
|
struct ShadeVector {
|
|
ShadeVector() : x(0.0f), y(0.0f), z(0.0f) {
|
|
}
|
|
|
|
/* 0000 */ float x;
|
|
/* 0004 */ float y;
|
|
/* 0008 */ float z;
|
|
};
|
|
|
|
static_assert(sizeof(ShadeVector) == 12);
|
|
|
|
struct ModelFaceRecordV1 {
|
|
// INLINED
|
|
void CopyTo(ModelFace& face) const {
|
|
for (int index = 0; index < 3; ++index) {
|
|
face.vertices[index] = this->vertices[index];
|
|
}
|
|
|
|
for (int index = 0; index < 3; ++index) {
|
|
face.textureVertices[index] = this->textureVertices[index];
|
|
}
|
|
|
|
face.texture = this->texture;
|
|
face.twoSided = this->twoSided;
|
|
}
|
|
|
|
/* 0000 */ std::uint16_t vertices[3];
|
|
/* 0006 */ std::uint16_t textureVertices[3];
|
|
/* 000C */ std::uint16_t texture;
|
|
/* 000E */ std::uint16_t padding;
|
|
/* 0010 */ std::uint32_t twoSided;
|
|
};
|
|
|
|
struct ModelFaceRecord : ModelFaceRecordV1 {
|
|
/* 0014 */ std::uint32_t smoothGroup;
|
|
};
|
|
|
|
struct ModelVolumeRecordV1 {
|
|
// INLINED
|
|
void CopyTo(ModelVolume& volume) const {
|
|
for (int index = 0; index < 3; ++index) {
|
|
volume.position[index] = this->position[index];
|
|
}
|
|
|
|
for (int index = 0; index < 3; ++index) {
|
|
volume.rotation[index] = this->rotation[index];
|
|
}
|
|
|
|
for (int index = 0; index < 3; ++index) {
|
|
volume.size[index] = this->size[index];
|
|
}
|
|
}
|
|
|
|
/* 0000 */ float size[3];
|
|
/* 000C */ float position[3];
|
|
/* 0018 */ float rotation[3];
|
|
};
|
|
|
|
struct ModelVolumeRecord : ModelVolumeRecordV1 {
|
|
/* 0024 */ int flag;
|
|
};
|
|
|
|
static_assert(sizeof(ModelFaceRecordV1) == 20);
|
|
static_assert(sizeof(ModelFaceRecord) == 24);
|
|
static_assert(sizeof(ModelVolumeRecordV1) == 36);
|
|
static_assert(sizeof(ModelVolumeRecord) == 40);
|
|
|
|
// OFFSET: 0x00756D60
|
|
// FUNCTION: fn_07997
|
|
AnimatedModelRecord::~AnimatedModelRecord() {
|
|
delete[] this->names;
|
|
}
|
|
|
|
// OFFSET: 0x00755630
|
|
// FUNCTION: fn_07985
|
|
ModelNode::ModelNode() : model(nullptr), parent(nullptr), alpha(255) {
|
|
}
|
|
|
|
// OFFSET: 0x007568E0
|
|
// FUNCTION: fn_07996
|
|
ModelNode::~ModelNode() {
|
|
for (std::vector<CTexture*>::iterator it = this->textures.begin(); it != this->textures.end(); ++it) {
|
|
if (*it) {
|
|
(*it)->Release();
|
|
g_texMgr.Remove(*it);
|
|
}
|
|
}
|
|
|
|
this->textures.clear();
|
|
|
|
if (this->mesh) {
|
|
delete this->mesh.get();
|
|
this->mesh.release();
|
|
}
|
|
|
|
this->children.clear();
|
|
}
|
|
|
|
// INLINED
|
|
__forceinline ModelNodeV1::ModelNodeV1() = default;
|
|
|
|
// INLINED
|
|
ModelNodeV1::~ModelNodeV1() = default;
|
|
|
|
// INLINED
|
|
ModelNodeV2::~ModelNodeV2() = default;
|
|
|
|
// OFFSET: 0x007553E0
|
|
// FUNCTION: fn_07982
|
|
__declspec(noinline) C3dModelRes::C3dModelRes() : major(0), shade(0), alpha(255) {
|
|
}
|
|
|
|
// OFFSET: 0x007567B0
|
|
// FUNCTION: fn_07995
|
|
C3dModelRes::~C3dModelRes() = default;
|
|
|
|
// OFFSET: 0x00755560
|
|
// FUNCTION: fn_07983
|
|
C3dModelResV1::C3dModelResV1() : animationLength(0) {
|
|
}
|
|
|
|
// INLINED
|
|
C3dModelResV1::~C3dModelResV1() = default;
|
|
|
|
// OFFSET: 0x00750A70
|
|
// FUNCTION: fn_07949
|
|
C3dModelResV1* C3dModelResV1::Create() {
|
|
return new C3dModelResV1;
|
|
}
|
|
|
|
// OFFSET: 0x007593C0
|
|
// FUNCTION: fn_08012
|
|
__declspec(noinline) ModelNode* C3dModelRes::FindNode(const char* name) const {
|
|
for (std::list<ModelNode*>::const_iterator it = this->nodes.begin(); it != this->nodes.end(); ++it) {
|
|
if ((*it)->name.compare(name) == 0) {
|
|
return *it;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// OFFSET: 0x00750950
|
|
// FUNCTION: fn_07948
|
|
void C3dModelRes::Unload() {
|
|
for (ModelNode* node : this->nodes) {
|
|
delete node;
|
|
}
|
|
|
|
this->nodes.clear();
|
|
this->rootNames.clear();
|
|
this->meshes.clear();
|
|
|
|
for (ModelVolume* volume : this->volumes) {
|
|
delete volume;
|
|
}
|
|
|
|
this->volumes.clear();
|
|
this->movieNames.clear();
|
|
}
|
|
|
|
// INLINED
|
|
__forceinline void C3dModelResV1::ReadNode(CFile& file, unsigned minor, const std::vector<std::string>& textureNames) {
|
|
ModelNodeV1* node = new ModelNodeV1;
|
|
node->model = this;
|
|
node->alpha = this->alpha;
|
|
char field[40]{};
|
|
file.Read(field, sizeof(field));
|
|
node->name = field;
|
|
file.Read(field, sizeof(field));
|
|
node->parentName = field;
|
|
int textureCount = 0;
|
|
file.Read(&textureCount, 4);
|
|
|
|
for (int index = 0; index < textureCount; ++index) {
|
|
int textureIndex = 0;
|
|
file.Read(&textureIndex, 4);
|
|
CTexture* texture = g_texMgr.Load(textureNames[textureIndex].c_str(), 0, false, true, false);
|
|
node->textures.push_back(texture);
|
|
|
|
if (texture) {
|
|
texture->Retain();
|
|
}
|
|
}
|
|
|
|
float matrix[12];
|
|
file.Read(matrix, sizeof(matrix));
|
|
file.Read(node->position, sizeof(node->position));
|
|
file.Read(&node->angle, 4);
|
|
file.Read(node->axis, sizeof(node->axis));
|
|
file.Read(node->scale, sizeof(node->scale));
|
|
node->mesh = std::make_unique<ModelMesh>();
|
|
ModelMesh& mesh = *node->mesh;
|
|
int vertexCount = 0;
|
|
file.Read(&vertexCount, 4);
|
|
mesh.vertexCount = vertexCount;
|
|
ShadeVector* vertices = new ShadeVector[vertexCount];
|
|
file.Read(vertices, static_cast<unsigned>(vertexCount) * 12u);
|
|
mesh.vertices = reinterpret_cast<std::array<float, 3>*>(vertices);
|
|
|
|
for (int index = 0; index < vertexCount; ++index) {
|
|
ShadeVector& vertex = vertices[index];
|
|
const float y = ((vertex.x * matrix[1] + vertex.y * matrix[4]) + matrix[7] * vertex.z) + matrix[10];
|
|
const float z = ((vertex.x * matrix[2] + vertex.y * matrix[5]) + matrix[8] * vertex.z) + matrix[11];
|
|
vertex.x = ((vertex.x * matrix[0] + vertex.y * matrix[3]) + vertex.z * matrix[6]) + matrix[9];
|
|
vertex.y = y;
|
|
vertex.z = z;
|
|
}
|
|
|
|
int textureVertexCount = 0;
|
|
file.Read(&textureVertexCount, 4);
|
|
mesh.textureVertexCount = textureVertexCount;
|
|
ModelTextureVertex* textureVertices = new ModelTextureVertex[textureVertexCount];
|
|
|
|
if (minor == 1) {
|
|
for (int index = 0; index < textureVertexCount; ++index) {
|
|
float uv[2];
|
|
file.Read(uv, sizeof(uv));
|
|
textureVertices[index].shaded = 0xFFFFFFFFu;
|
|
textureVertices[index].u = uv[0];
|
|
textureVertices[index].v = uv[1];
|
|
}
|
|
} else {
|
|
file.Read(textureVertices, static_cast<unsigned>(textureVertexCount) * 12u);
|
|
}
|
|
|
|
mesh.textureVertices = textureVertices;
|
|
int faceCount = 0;
|
|
file.Read(&faceCount, 4);
|
|
mesh.faceCount = faceCount;
|
|
ModelFace* faces = new ModelFace[faceCount];
|
|
|
|
if (minor == 1) {
|
|
for (int index = 0; index < faceCount; ++index) {
|
|
ModelFace& face = faces[index];
|
|
ModelFaceRecordV1 record;
|
|
file.Read(&record, sizeof(record));
|
|
record.CopyTo(face);
|
|
|
|
if (face.smoothing.empty()) {
|
|
face.smoothing.push_back(0);
|
|
}
|
|
}
|
|
} else {
|
|
for (int index = 0; index < faceCount; ++index) {
|
|
ModelFace& face = faces[index];
|
|
ModelFaceRecord record;
|
|
file.Read(&record, sizeof(record));
|
|
record.CopyTo(face);
|
|
|
|
if (face.smoothing.empty()) {
|
|
face.smoothing.push_back(record.smoothGroup);
|
|
}
|
|
}
|
|
}
|
|
|
|
mesh.faces = faces;
|
|
// INLINED
|
|
std::sort(mesh.faces, mesh.faces + mesh.faceCount, [](const ModelFace& a, const ModelFace& b) { return a.texture < b.texture; });
|
|
mesh.CalculateNormals();
|
|
static_cast<ModelKeyList2&>(node->rotationKeys).Read(file);
|
|
|
|
this->nodes.push_back(node);
|
|
this->meshes[node->name] = node->mesh.get();
|
|
}
|
|
|
|
// OFFSET: 0x00750B10
|
|
// FUNCTION: fn_07950
|
|
bool C3dModelResV1::Load(const char* name) {
|
|
CFile file;
|
|
|
|
if (!file.Open(name, 0, true, false)) {
|
|
return false;
|
|
}
|
|
|
|
char magic[5]{};
|
|
file.Read(magic, 4);
|
|
|
|
if (std::strcmp(magic, "GRSM") != 0) {
|
|
constexpr char message[] = "모델파일이 아닙니다. 형식을 다시한번 확인해주세요.";
|
|
ShowErrorDialog(GetRenderSystemHolder()->system, message, 0);
|
|
return false;
|
|
}
|
|
|
|
unsigned char major = 0;
|
|
file.Read(&major, 1);
|
|
this->major = major;
|
|
unsigned char minor = 0;
|
|
file.Read(&minor, 1);
|
|
|
|
if (major != 1 || minor > 5) {
|
|
constexpr char message[] = "지원되지 않는 버젼입니다. 내용물이 깨져있을 수 있습니다";
|
|
ShowErrorDialog(GetRenderSystemHolder()->system, message, 0);
|
|
return false;
|
|
}
|
|
|
|
file.Read(&this->animationLength, 4);
|
|
file.Read(&this->shade, 4);
|
|
|
|
if (minor < 4) {
|
|
this->alpha = 255;
|
|
} else {
|
|
file.Read(&this->alpha, 1);
|
|
}
|
|
|
|
unsigned char reserved[16]{};
|
|
file.Read(reserved, sizeof(reserved));
|
|
std::vector<std::string> textureNames;
|
|
int textureCount = 0;
|
|
file.Read(&textureCount, 4);
|
|
char textureName[40]{};
|
|
|
|
for (int index = 0; index < textureCount; ++index) {
|
|
file.Read(textureName, sizeof(textureName));
|
|
textureNames.push_back(textureName);
|
|
|
|
if (std::strstr(textureName, ".bik")) {
|
|
this->movieNames.push_back(textureName);
|
|
}
|
|
}
|
|
|
|
char rootName[40]{};
|
|
file.Read(rootName, sizeof(rootName));
|
|
int nodeCount = 0;
|
|
file.Read(&nodeCount, 4);
|
|
|
|
for (int index = 0; index < nodeCount; ++index) {
|
|
this->ReadNode(file, minor, textureNames);
|
|
}
|
|
|
|
for (ModelNode* node : this->nodes) {
|
|
if (!node->parentName.empty()) {
|
|
node->parent = this->FindNode(node->parentName.c_str());
|
|
node->parent->children.push_back(node);
|
|
}
|
|
}
|
|
|
|
this->rootNames.push_back(rootName);
|
|
int volumeCount = 0;
|
|
file.Read(&volumeCount, 4);
|
|
|
|
if (major == 1) {
|
|
if (minor >= 3) {
|
|
for (int index = 0; index < volumeCount; ++index) {
|
|
auto* volume = new ModelVolume;
|
|
std::memset(volume, 0, 132);
|
|
unsigned char record[40]{};
|
|
file.Read(record, sizeof(record));
|
|
std::memcpy(&volume->flag, record + 36, 4);
|
|
std::memcpy(volume, record, 36);
|
|
|
|
if (volume->flag == 0) {
|
|
volume->size[0] = volume->size[0] + 3.0f;
|
|
volume->size[2] = volume->size[2] + 3.0f;
|
|
}
|
|
|
|
this->volumes.push_back(volume);
|
|
}
|
|
} else if (minor == 2) {
|
|
for (int index = 0; index < volumeCount; ++index) {
|
|
auto* volume = new ModelVolume;
|
|
std::memset(volume, 0, 132);
|
|
unsigned char record[36]{};
|
|
file.Read(record, sizeof(record));
|
|
volume->flag = 0;
|
|
std::memcpy(volume, record, 36);
|
|
this->volumes.push_back(volume);
|
|
}
|
|
}
|
|
}
|
|
|
|
this->sourceName = name;
|
|
file.Close();
|
|
|
|
return true;
|
|
}
|
|
|
|
// OFFSET: 0x007577E0
|
|
// FUNCTION: fn_08006
|
|
void C3dGrannyModelRes::RebindMeshes(const C3dGrannyModelRes& target) {
|
|
GrannyModelInstance* instance = this->instance;
|
|
for (int index = 0; index < this->instance->meshCount; ++index) {
|
|
GrannyMeshEntry& entry = instance->meshes[index];
|
|
GrannyFreeMeshBinding(entry.binding);
|
|
entry.binding = GrannyNewMeshBinding(entry.mesh, this->skeleton, target.skeleton);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00758E40
|
|
// FUNCTION: fn_08009
|
|
void C3dGrannyModelRes::InstantiateModel(GrannyModelInstance* target, const granny_model* model) {
|
|
auto findTexture = [this](const granny_texture* texture) -> GrannyTextureEntry* {
|
|
if (texture) {
|
|
for (int index = 0; index < this->textureCount; ++index) {
|
|
if (std::strcmp(this->textures[index].name, texture->fromFileName) == 0) {
|
|
return &this->textures[index];
|
|
}
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
};
|
|
|
|
const int boneCount = model->skeleton->boneCount;
|
|
if (this->maxBoneCount < boneCount) {
|
|
this->maxBoneCount = boneCount;
|
|
}
|
|
|
|
target->instance = GrannyInstantiateModel(model);
|
|
target->worldPose = GrannyNewWorldPose(boneCount);
|
|
target->meshCount = model->meshBindingCount;
|
|
target->meshes = new GrannyMeshEntry[target->meshCount];
|
|
|
|
for (int index = 0; index < target->meshCount; ++index) {
|
|
GrannyMeshEntry& entry = target->meshes[index];
|
|
granny_mesh* mesh = model->meshBindings[index].mesh;
|
|
entry.mesh = mesh;
|
|
granny_skeleton* skeleton = GrannyGetSourceSkeleton(target->instance);
|
|
entry.binding = GrannyNewMeshBinding(mesh, skeleton, skeleton);
|
|
|
|
const unsigned int indexCount = GrannyGetMeshIndexCount(mesh);
|
|
entry.indices = new std::uint16_t[indexCount];
|
|
if (indexCount != 0) {
|
|
GrannyCopyMeshIndices(mesh, 2, entry.indices);
|
|
}
|
|
|
|
const int vertexBytes = GrannyGetMeshVertexCount(mesh) * 32;
|
|
entry.vertices = nullptr;
|
|
if (GrannyMeshIsRigid(mesh)) {
|
|
entry.vertices = new unsigned char[vertexBytes];
|
|
GrannyCopyMeshVertices(mesh, GrannyPNT332VertexType, entry.vertices);
|
|
entry.deformer = nullptr;
|
|
} else {
|
|
if (this->deformBufferSize < vertexBytes) {
|
|
this->deformBufferSize = vertexBytes;
|
|
}
|
|
|
|
entry.deformer = GrannyNewMeshDeformer(GrannyGetMeshVertexType(mesh), GrannyPNT332VertexType, 2);
|
|
if (!entry.deformer) {
|
|
ShowErrorDialog("Granny didn't find a matching deformer for the vertex format used by mesh", 0);
|
|
}
|
|
}
|
|
|
|
entry.materialCount = mesh->materialBindingCount;
|
|
entry.textures = new GrannyTextureEntry*[entry.materialCount];
|
|
|
|
for (int material = 0; material < entry.materialCount; ++material) {
|
|
entry.textures[material] = findTexture(GrannyGetMaterialTextureByType(mesh->materialBindings[material].material, 2));
|
|
}
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00759090
|
|
// FUNCTION: fn_08010
|
|
CTexture* C3dGrannyModelRes::CreateTexture(const granny_texture* texture, int) {
|
|
const bool hasAlpha = GrannyTextureHasAlpha(texture);
|
|
const int width = texture->width;
|
|
const int height = texture->height;
|
|
unsigned char* source = new unsigned char[height * width * 4];
|
|
unsigned char* pixels = new unsigned char[height * width * 4];
|
|
GrannyCopyTextureImage(texture, 0, 0, GrannyRGBA8888PixelFormat, width, height, width * 4, source);
|
|
|
|
int format;
|
|
int offset = 0;
|
|
if (hasAlpha) {
|
|
for (int y = 0; y < height; ++y) {
|
|
for (int x = 0; x < width; ++x) {
|
|
const unsigned char red = source[offset + 0];
|
|
const unsigned char green = source[offset + 1];
|
|
const unsigned char blue = source[offset + 2];
|
|
const unsigned char alpha = source[offset + 3];
|
|
pixels[offset + 0] = blue;
|
|
pixels[offset + 1] = green;
|
|
pixels[offset + 2] = red;
|
|
pixels[offset + 3] = alpha;
|
|
offset += 4;
|
|
}
|
|
}
|
|
|
|
format = 1;
|
|
} else {
|
|
for (int y = 0; y < height; ++y) {
|
|
for (int x = 0; x < width; ++x) {
|
|
const unsigned char red = source[offset + 0];
|
|
const unsigned char green = source[offset + 1];
|
|
const unsigned char blue = source[offset + 2];
|
|
pixels[offset + 0] = blue;
|
|
pixels[offset + 1] = green;
|
|
pixels[offset + 2] = red;
|
|
pixels[offset + 3] = 0xFF;
|
|
offset += 4;
|
|
}
|
|
}
|
|
|
|
format = 0;
|
|
}
|
|
|
|
CTexture* result = g_texMgr.Upload(width, height, reinterpret_cast<const std::uint32_t*>(pixels), format, 0, false, false, false);
|
|
delete[] pixels;
|
|
delete[] source;
|
|
return result;
|
|
}
|
|
|
|
// OFFSET: 0x00759330
|
|
// FUNCTION: fn_08011
|
|
void C3dGrannyModelRes::FreeControl(granny_control* control) {
|
|
if (control) {
|
|
GrannySetControlActive(control, false);
|
|
GrannyFreeControl(control);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x007598B0
|
|
// FUNCTION: fn_08019
|
|
granny_file* GrannyAnimationLibrary::ReadAnimationFile(const char* name, const char* suffix) {
|
|
std::string path;
|
|
CFile file;
|
|
std::sprintf(g_animationPath, "%s%s.gr2", name, suffix);
|
|
|
|
if (!file.Open(g_animationPath, 0, true, false)) {
|
|
ShowErrorDialog(GetRenderSystemHolder()->system, (std::string("Cannot find File : ") + std::string(g_animationPath)).c_str(), 0);
|
|
return nullptr;
|
|
}
|
|
|
|
granny_file* result = GrannyReadEntireFileFromMemory(file.GetSize(), file.GetData());
|
|
file.Close();
|
|
return result;
|
|
}
|
|
|
|
// OFFSET: 0x007594B0
|
|
// FUNCTION: fn_08013
|
|
__declspec(noinline) void GrannyAnimationLibrary::FreeInstance() {
|
|
if (GrannyModelInstance* instance = this->instance) {
|
|
for (int index = 0; index < instance->meshCount; ++index) {
|
|
GrannyMeshEntry& entry = instance->meshes[index];
|
|
GrannyFreeMeshBinding(entry.binding);
|
|
GrannyFreeMeshDeformer(entry.deformer);
|
|
delete entry.indices;
|
|
}
|
|
|
|
GrannyFreeModelInstance(instance->instance);
|
|
GrannyFreeWorldPose(instance->worldPose);
|
|
delete[] instance->meshes;
|
|
}
|
|
|
|
delete this->instance;
|
|
this->instance = nullptr;
|
|
}
|
|
|
|
// OFFSET: 0x00759550
|
|
// FUNCTION: fn_08014
|
|
void C3dModelRes::ForEachRootName(std::function<void(const std::string&)> callback) const {
|
|
std::for_each(this->rootNames.begin(), this->rootNames.end(), callback);
|
|
}
|
|
|
|
// OFFSET: 0x007597A0
|
|
// FUNCTION: fn_08015
|
|
int C3dGrannyModelRes::GetTriangleCount(int mesh) const {
|
|
return GrannyGetMeshIndexCount(this->instance->meshes[mesh].mesh) / 3;
|
|
}
|
|
|
|
// OFFSET: 0x007597E0
|
|
// FUNCTION: fn_08016
|
|
unsigned char* C3dGrannyModelRes::GetRigidVertices(int mesh) const {
|
|
const GrannyMeshEntry& entry = this->instance->meshes[mesh];
|
|
|
|
if (GrannyMeshIsRigid(entry.mesh)) {
|
|
return entry.vertices;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// OFFSET: 0x00759820
|
|
// FUNCTION: fn_08017
|
|
void GrannyAnimationLibrary::Initialize() {
|
|
}
|
|
|
|
// OFFSET: 0x00759830
|
|
// FUNCTION: fn_08018
|
|
bool C3dModelRes::Load(const char*) {
|
|
return false;
|
|
}
|
|
|
|
// OFFSET: 0x00757390
|
|
// FUNCTION: fn_08005
|
|
bool GrannyAnimationLibrary::Load(const char* name, int job, int action) {
|
|
bool result = false;
|
|
|
|
if (!GrannyVersionsMatch_(2, 1, 0, 5)) {
|
|
ShowErrorDialog("doesn't match the .h file used during compilation", 0);
|
|
return false;
|
|
}
|
|
|
|
this->modelCount = 0;
|
|
this->maxBoneCount = 0;
|
|
this->textureCount = 0;
|
|
this->animationMode = 0;
|
|
CFile file;
|
|
|
|
if (!file.Open(name, 0, true, false)) {
|
|
return false;
|
|
}
|
|
|
|
this->file = GrannyReadEntireFileFromMemory(file.GetSize(), file.GetData());
|
|
file.Close();
|
|
|
|
if (!this->file) {
|
|
return false;
|
|
}
|
|
|
|
granny_file_info* info = GrannyGetFileInfo(this->file);
|
|
std::strcpy(this->fileName, name);
|
|
|
|
if (info) {
|
|
this->textureCount = info->textureCount;
|
|
this->modelCount = info->modelCount;
|
|
|
|
if (this->instance) {
|
|
this->FreeInstance();
|
|
}
|
|
|
|
GrannyModelInstance* instance = new GrannyModelInstance;
|
|
this->instance = instance;
|
|
granny_model* model = info->models[0];
|
|
const int boneCount = model->skeleton->boneCount;
|
|
|
|
if (this->maxBoneCount < boneCount) {
|
|
this->maxBoneCount = boneCount;
|
|
}
|
|
|
|
instance->instance = GrannyInstantiateModel(model);
|
|
instance->worldPose = GrannyNewWorldPose(boneCount);
|
|
instance->meshCount = model->meshBindingCount;
|
|
instance->meshes = new GrannyMeshEntry[instance->meshCount];
|
|
|
|
for (int index = 0; index < instance->meshCount; ++index) {
|
|
GrannyMeshEntry& entry = instance->meshes[index];
|
|
granny_mesh* mesh = model->meshBindings[index].mesh;
|
|
entry.mesh = mesh;
|
|
granny_skeleton* skeleton = GrannyGetSourceSkeleton(instance->instance);
|
|
entry.binding = GrannyNewMeshBinding(mesh, skeleton, skeleton);
|
|
|
|
const unsigned int indexCount = GrannyGetMeshIndexCount(mesh);
|
|
entry.indices = new std::uint16_t[indexCount];
|
|
if (indexCount != 0) {
|
|
GrannyCopyMeshIndices(mesh, 2, entry.indices);
|
|
}
|
|
|
|
const int vertexBytes = GrannyGetMeshVertexCount(mesh) * 32;
|
|
if (GrannyMeshIsRigid(mesh)) {
|
|
entry.deformer = nullptr;
|
|
} else {
|
|
if (this->deformBufferSize < vertexBytes) {
|
|
this->deformBufferSize = vertexBytes;
|
|
}
|
|
|
|
entry.deformer = GrannyNewMeshDeformer(GrannyGetMeshVertexType(mesh), GrannyPNT332VertexType, 2);
|
|
if (!entry.deformer) {
|
|
ShowErrorDialog("Granny didn't find a matching deformer for the vertex format used by mesh", 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (info->animationCount != 0) {
|
|
granny_animation* animation = nullptr;
|
|
|
|
if (char* extension = std::strchr(this->fileName, '.')) {
|
|
*extension = '\0';
|
|
}
|
|
|
|
if (granny_file* animationFile = this->ReadAnimationFile(this->fileName, "")) {
|
|
if (granny_file_info* animationInfo = GrannyGetFileInfo(animationFile)) {
|
|
if (!instance->instance || animationInfo->animationCount != 1) {
|
|
ShowErrorDialog("This sample only supports single-animation files", 0);
|
|
this->animations[job][action] = nullptr;
|
|
return false;
|
|
}
|
|
|
|
animation = animationInfo->animations[0];
|
|
}
|
|
}
|
|
|
|
this->animations[job][action] = animation;
|
|
|
|
if (!animation) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
this->localPose = GrannyNewLocalPose(this->maxBoneCount);
|
|
|
|
if (this->deformBufferSize != 0) {
|
|
this->animationMode = 4;
|
|
}
|
|
|
|
result = true;
|
|
} else {
|
|
ShowErrorDialog("Unable to access file data .gr2", 0);
|
|
}
|
|
|
|
GrannyFreeFileSection(this->file, 1);
|
|
GrannyFreeFileSection(this->file, 2);
|
|
GrannyFreeFileSection(this->file, 4);
|
|
GrannyFreeFileSection(this->file, 5);
|
|
this->animationDuration = 1920.0f;
|
|
return result;
|
|
}
|
|
|
|
// OFFSET: 0x00757270
|
|
// FUNCTION: fn_08004
|
|
granny_control* C3dGrannyModelRes::PlayAnimation(unsigned action, granny_model_instance* instance, granny_control* control, int loopCount) {
|
|
if (!control) {
|
|
const unsigned job = this->job;
|
|
GrannyAnimationLibrary* library = this->animations;
|
|
granny_animation* const& animation = library->animations[job][action];
|
|
|
|
if (!animation) {
|
|
g_modelPath[0] = '\0';
|
|
|
|
if (job > 9 || action > 4) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (action == 0) {
|
|
std::sprintf(g_modelPath, "model\\3dmob\\%s", g_session.GetJobName(g_animationJobs[job], -1));
|
|
} else {
|
|
std::sprintf(g_modelPath, "model\\3dmob_bone\\%d_%s.gr2", job, g_animationNames[action]);
|
|
}
|
|
|
|
if (!g_modelPath[0] || !ResourceExists(g_modelPath, 0)) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (job != 1) {
|
|
library->Load(g_modelPath, job, action);
|
|
}
|
|
|
|
if (!animation) {
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
granny_control* result = GrannyPlayControlledAnimation(0.0f, animation, instance);
|
|
if (result) {
|
|
GrannySetControlLoopCount(result, loopCount);
|
|
return result;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
GrannySetControlActive(control, true);
|
|
return control;
|
|
}
|
|
|
|
// OFFSET: 0x00758710
|
|
// FUNCTION: fn_08008
|
|
bool C3dGrannyModelRes::ProjectBounds(float* rect, const matrix& view, const matrix& world, const float* eye) const {
|
|
matrix matrix;
|
|
matrix.MakeZRotation(3.141592f);
|
|
const float* m = matrix.values;
|
|
const float x = this->position[1] * m[3] + this->position[0] * m[0] + this->position[2] * m[6] + m[9];
|
|
const float y = this->position[0] * m[1] + this->position[1] * m[4] + this->position[2] * m[7] + m[10];
|
|
const float z = this->position[0] * m[2] + this->position[1] * m[5] + this->position[2] * m[8] + m[11];
|
|
matrix.Compose(world, view);
|
|
|
|
const float screenX = y * m[3] + x * m[0] + z * m[6] + m[9];
|
|
const float screenY = x * m[1] + y * m[4] + z * m[7] + m[10];
|
|
const float depth = y * m[5] + x * m[2] + z * m[8] + m[11];
|
|
const float deltaY = eye[1] - y;
|
|
const float deltaX = eye[0] - x;
|
|
const float deltaZ = eye[2] - z;
|
|
const float distance = SquareRoot(deltaY * deltaY + deltaX * deltaX + deltaZ * deltaZ);
|
|
const float slope = std::min(std::fabs(1.0f / distance * deltaY), 1.0f);
|
|
const float height = this->topHeight - (this->topHeight - this->baseHeight) * slope;
|
|
const float halfWidth = SquareRoot(this->baseHeight * this->baseHeight * 0.5f);
|
|
const float halfHeight = SquareRoot(height * height * 0.5f);
|
|
const float inverseDepth = 1.0f / depth;
|
|
|
|
rect[4] = inverseDepth;
|
|
rect[0] = (screenX - halfWidth) * g_renderer->viewport.scaleX * inverseDepth + static_cast<float>(g_renderer->viewport.clipCenterX);
|
|
rect[1] = (screenY - halfHeight) * g_renderer->viewport.scaleY * inverseDepth + static_cast<float>(g_renderer->viewport.clipCenterY);
|
|
rect[2] = (halfWidth + screenX) * g_renderer->viewport.scaleX * inverseDepth + static_cast<float>(g_renderer->viewport.clipCenterX);
|
|
rect[3] = (halfHeight + screenY) * g_renderer->viewport.scaleY * inverseDepth + static_cast<float>(g_renderer->viewport.clipCenterY);
|
|
|
|
return !(static_cast<unsigned>(rect[0]) > g_renderer->viewport.width && static_cast<unsigned>(rect[2]) > g_renderer->viewport.width &&
|
|
static_cast<unsigned>(rect[1]) > g_renderer->viewport.height && static_cast<unsigned>(rect[3]) > g_renderer->viewport.height);
|
|
}
|
|
|
|
// OFFSET: 0x00757850
|
|
// FUNCTION: fn_08007
|
|
void AnimatedModelNode::Shade(const float* matrix, int frame, const float* light, const float* diffuse, const float* ambient, int shadeType, int alpha) {
|
|
// GLOBAL: gl_24735
|
|
static ShadeVector faceNormals[30000];
|
|
// GLOBAL: gl_24736
|
|
static ShadeVector vertexNormals[30000];
|
|
std::list<int> groups[32];
|
|
auto faceColors = [this](int index) { return reinterpret_cast<std::uint32_t*>(this->faceNormals[index].data()); };
|
|
|
|
switch (shadeType) {
|
|
case 0: {
|
|
for (int index = 0; index < this->faceCount; ++index) {
|
|
const std::uint32_t color = (alpha << 24) + 0xFFFFFF;
|
|
faceColors(index)[0] = color;
|
|
faceColors(index)[1] = color;
|
|
faceColors(index)[2] = color;
|
|
}
|
|
break;
|
|
}
|
|
case 1: {
|
|
for (int index = 0; index < this->faceCount; ++index) {
|
|
const AnimatedModelFace& face = this->faces[index];
|
|
const std::array<float, 3>* vertices = this->frames[frame].vertices;
|
|
const std::array<float, 3>& v0 = vertices[face.vertices[0]];
|
|
const std::array<float, 3>& v1 = vertices[face.vertices[1]];
|
|
const std::array<float, 3>& v2 = vertices[face.vertices[2]];
|
|
const float x2 = v2[0] * matrix[0] + v2[1] * matrix[3] + v2[2] * matrix[6] + matrix[9];
|
|
const float y2 = v2[0] * matrix[1] + v2[1] * matrix[4] + v2[2] * matrix[7] + matrix[10];
|
|
const float z2 = v2[0] * matrix[2] + v2[1] * matrix[5] + v2[2] * matrix[8] + matrix[11];
|
|
const float ax = x2 - (matrix[0] * v0[0] + v0[1] * matrix[3] + v0[2] * matrix[6] + matrix[9]);
|
|
const float ay = y2 - (matrix[1] * v0[0] + matrix[4] * v0[1] + matrix[7] * v0[2] + matrix[10]);
|
|
const float az = z2 - (matrix[2] * v0[0] + matrix[5] * v0[1] + matrix[8] * v0[2] + matrix[11]);
|
|
const float bx = x2 - (v1[0] * matrix[0] + v1[1] * matrix[3] + v1[2] * matrix[6] + matrix[9]);
|
|
const float by = y2 - (v1[0] * matrix[1] + v1[1] * matrix[4] + v1[2] * matrix[7] + matrix[10]);
|
|
const float bz = z2 - (v1[0] * matrix[2] + v1[1] * matrix[5] + v1[2] * matrix[8] + matrix[11]);
|
|
const float nx = by * az - bz * ay;
|
|
const float ny = bz * ax - bx * az;
|
|
const float nz = bx * ay - by * ax;
|
|
const float inverse = 1.0f / SquareRoot(ny * ny + nx * nx + nz * nz);
|
|
const float dot = nx * inverse * light[0] + ny * inverse * light[1] + nz * inverse * light[2];
|
|
const float intensity = 0.0f > dot ? 0.0f : dot;
|
|
const float redLevel = intensity * diffuse[0] + ambient[0];
|
|
const float red = 1.0f < redLevel ? 1.0f : redLevel;
|
|
const float greenLevel = intensity * diffuse[1] + ambient[1];
|
|
const float green = 1.0f < greenLevel ? 1.0f : greenLevel;
|
|
const float blueLevel = intensity * diffuse[2] + ambient[2];
|
|
const float blue = 1.0f < blueLevel ? 1.0f : blueLevel;
|
|
|
|
for (int corner = 0; corner < 3; ++corner) {
|
|
const int source = this->sharedTextureVertices == 0 ? frame : 0;
|
|
const float scale = this->frames[source].textureVertices[face.textureVertices[corner]].shaded ? 128.0f : 255.0f;
|
|
faceColors(index)[corner] = ((((alpha << 8) | static_cast<int>(scale * red)) << 8 | static_cast<int>(scale * green)) << 8) | static_cast<int>(scale * blue);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 2: {
|
|
for (int index = 0; index < this->faceCount; ++index) {
|
|
const AnimatedModelFace& face = this->faces[index];
|
|
const std::array<float, 3>* vertices = this->frames[frame].vertices;
|
|
const std::array<float, 3>& v0 = vertices[face.vertices[0]];
|
|
const std::array<float, 3>& v1 = vertices[face.vertices[1]];
|
|
const std::array<float, 3>& v2 = vertices[face.vertices[2]];
|
|
const float x2 = v2[0] * matrix[0] + v2[1] * matrix[3] + v2[2] * matrix[6] + matrix[9];
|
|
const float y2 = v2[0] * matrix[1] + v2[1] * matrix[4] + v2[2] * matrix[7] + matrix[10];
|
|
const float z2 = v2[0] * matrix[2] + v2[1] * matrix[5] + v2[2] * matrix[8] + matrix[11];
|
|
const float ax = x2 - (v0[0] * matrix[0] + v0[1] * matrix[3] + v0[2] * matrix[6] + matrix[9]);
|
|
const float ay = y2 - (matrix[1] * v0[0] + matrix[4] * v0[1] + matrix[7] * v0[2] + matrix[10]);
|
|
const float az = z2 - (matrix[2] * v0[0] + matrix[5] * v0[1] + matrix[8] * v0[2] + matrix[11]);
|
|
const float bx = x2 - (v1[0] * matrix[0] + v1[1] * matrix[3] + v1[2] * matrix[6] + matrix[9]);
|
|
const float by = y2 - (v1[0] * matrix[1] + v1[1] * matrix[4] + v1[2] * matrix[7] + matrix[10]);
|
|
const float bz = z2 - (v1[0] * matrix[2] + v1[1] * matrix[5] + v1[2] * matrix[8] + matrix[11]);
|
|
ShadeVector& normal = faceNormals[index];
|
|
normal.x = by * az - bz * ay;
|
|
normal.y = ax * bz - bx * az;
|
|
normal.z = bx * ay - ax * by;
|
|
const float inverse = 1.0f / SquareRoot(normal.y * normal.y + normal.x * normal.x + normal.z * normal.z);
|
|
normal.x = inverse * normal.x;
|
|
normal.y = inverse * normal.y;
|
|
normal.z = inverse * normal.z;
|
|
groups[face.smoothGroup].push_back(index);
|
|
}
|
|
|
|
for (int group = 0; group < 32; ++group) {
|
|
if (groups[group].empty()) {
|
|
continue;
|
|
}
|
|
|
|
for (int vertex = 0; vertex < this->vertexCount; ++vertex) {
|
|
ShadeVector& normal = vertexNormals[vertex];
|
|
normal.x = 0.0f;
|
|
normal.y = 0.0f;
|
|
normal.z = 0.0f;
|
|
|
|
for (int index = 0; index < this->faceCount; ++index) {
|
|
const AnimatedModelFace& face = this->faces[index];
|
|
if (face.smoothGroup == group && (face.vertices[0] == vertex || face.vertices[1] == vertex || face.vertices[2] == vertex)) {
|
|
normal.x = faceNormals[index].x + normal.x;
|
|
normal.y = faceNormals[index].y + normal.y;
|
|
normal.z = normal.z + faceNormals[index].z;
|
|
}
|
|
}
|
|
|
|
if (SquareRoot(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z) != 0.0f) {
|
|
const float inverse = 1.0f / SquareRoot(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z);
|
|
normal.x = inverse * normal.x;
|
|
normal.y = inverse * normal.y;
|
|
normal.z = inverse * normal.z;
|
|
}
|
|
}
|
|
|
|
for (int index : groups[group]) {
|
|
const AnimatedModelFace& face = this->faces[index];
|
|
|
|
for (int corner = 0; corner < 3; ++corner) {
|
|
const ShadeVector& normal = vertexNormals[face.vertices[corner]];
|
|
const int source = this->sharedTextureVertices == 0 ? frame : 0;
|
|
const float dot = normal.y * light[1] + light[0] * normal.x + normal.z * light[2];
|
|
const float intensity = 0.0f > dot ? 0.0f : dot;
|
|
const float redLevel = intensity * diffuse[0] + ambient[0];
|
|
const float red = 1.0f < redLevel ? 1.0f : redLevel;
|
|
const float greenLevel = intensity * diffuse[1] + ambient[1];
|
|
const float green = 1.0f < greenLevel ? 1.0f : greenLevel;
|
|
const float blueLevel = intensity * diffuse[2] + ambient[2];
|
|
const float blue = 1.0f < blueLevel ? 1.0f : blueLevel;
|
|
const float scale = this->frames[source].textureVertices[face.textureVertices[corner]].shaded ? 128.0f : 255.0f;
|
|
faceColors(index)[corner] = ((((alpha << 8) | static_cast<int>(scale * red)) << 8 | static_cast<int>(green * scale)) << 8) | static_cast<int>(blue * scale);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
for (int index = 0; index < this->faceCount; ++index) {
|
|
const std::uint32_t color = (alpha << 24) + 0xFFFFFF;
|
|
faceColors(index)[0] = color;
|
|
faceColors(index)[1] = color;
|
|
faceColors(index)[2] = color;
|
|
}
|
|
|
|
ShowErrorDialog("Invalid Shade Type", 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (AnimatedModelNode* child : this->children) {
|
|
child->Shade(matrix, frame, light, diffuse, ambient, shadeType, alpha);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x0075CB30
|
|
// FUNCTION: fn_08025
|
|
const void* C3dGrannyModelRes::GetMeshRenderData(
|
|
int mesh, CTexture** texture, std::uint16_t** indices, int* triangleCount, matrix* transform, granny_world_pose* pose
|
|
) {
|
|
return this->GetMeshRenderData(this->instance, mesh, texture, indices, triangleCount, transform, pose);
|
|
}
|
|
|
|
// OFFSET: 0x0075CB60
|
|
// FUNCTION: fn_08026
|
|
const void* C3dGrannyModelRes::GetMeshRenderData(
|
|
GrannyModelInstance* model, int mesh, CTexture** texture, std::uint16_t** indices, int* triangleCount, matrix* transform,
|
|
granny_world_pose* pose
|
|
) {
|
|
if (pose == nullptr) {
|
|
pose = model->worldPose;
|
|
}
|
|
|
|
const float* matrices = GrannyControlModelsNext(pose);
|
|
GrannyMeshEntry* meshes = model->meshes;
|
|
const std::int32_t* boneIndices = GrannyGetMeshBindingToBoneIndices(meshes[mesh].binding);
|
|
const std::int32_t vertexCount = GrannyGetMeshVertexCount(meshes[mesh].mesh);
|
|
const granny_tri_material_group* groups = GrannyGetMeshTriangleGroups(meshes[mesh].mesh);
|
|
GrannyTextureEntry* entry = meshes[mesh].textures[groups->materialIndex];
|
|
*texture = entry != nullptr && meshes[mesh].materialCount > groups->materialIndex ? entry->texture : nullptr;
|
|
|
|
if (GrannyMeshIsRigid(meshes[mesh].mesh)) {
|
|
const float* composite = GrannyGetWorldPoseComposite4x4(model->worldPose, boneIndices[0]);
|
|
transform->values[0] = composite[0];
|
|
transform->values[1] = composite[1];
|
|
transform->values[2] = composite[2];
|
|
transform->values[3] = composite[4];
|
|
transform->values[4] = composite[5];
|
|
transform->values[5] = composite[6];
|
|
transform->values[6] = composite[8];
|
|
transform->values[7] = composite[9];
|
|
transform->values[8] = composite[10];
|
|
transform->values[9] = composite[12];
|
|
transform->values[10] = composite[13];
|
|
transform->values[11] = composite[14];
|
|
|
|
const void* vertices = meshes[mesh].vertices;
|
|
*indices = meshes[mesh].indices;
|
|
*triangleCount = GrannyGetMeshIndexCount(meshes[mesh].mesh) / 3;
|
|
if (std::strstr(meshes[mesh].mesh->name, "hair_pivot") != nullptr && this->hairPivot != nullptr) {
|
|
this->hairPivot->transform = *transform;
|
|
}
|
|
|
|
return vertices;
|
|
}
|
|
|
|
if (meshes[mesh].deformer != nullptr) {
|
|
GrannyDeformVertices(meshes[mesh].deformer, boneIndices, matrices, vertexCount, GrannyGetMeshVertices(meshes[mesh].mesh), this->deformBuffer);
|
|
GrannyGetMeshBytesPerIndex(meshes[mesh].mesh);
|
|
GrannyGetMeshIndices(meshes[mesh].mesh);
|
|
const void* vertices = this->deformBuffer;
|
|
*indices = meshes[mesh].indices;
|
|
*triangleCount = GrannyGetMeshIndexCount(meshes[mesh].mesh) / 3;
|
|
std::memcpy(transform->values, g_identityMatrix, sizeof(g_identityMatrix));
|
|
return vertices;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
// OFFSET: 0x0075CD90
|
|
// FUNCTION: fn_08027
|
|
bool C3dGrannyModelRes::FindHairPivot() {
|
|
if (this->hairPivot == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
for (int mesh = 0; mesh < this->instance->meshCount; ++mesh) {
|
|
if (std::strstr(this->instance->meshes[mesh].mesh->name, "hair_pivot") != nullptr) {
|
|
this->hairPivot->mesh = mesh;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// OFFSET: 0x0075CFC0
|
|
// FUNCTION: fn_08029
|
|
granny_world_pose* C3dGrannyModelRes::Animate(float seconds, granny_model_instance* instance) {
|
|
GrannyModelInstance* model = this->instance;
|
|
if (model == nullptr) {
|
|
return nullptr;
|
|
}
|
|
|
|
granny_skeleton* skeleton = GrannyGetSourceSkeleton(instance);
|
|
const std::int32_t boneCount = skeleton->boneCount;
|
|
GrannySetModelClock(instance, seconds);
|
|
GrannySampleModelAnimations(instance, 0, boneCount, static_cast<granny_local_pose*>(this->localPose));
|
|
GrannyBuildWorldPose(skeleton, 0, boneCount, static_cast<granny_local_pose*>(this->localPose), nullptr, model->worldPose);
|
|
GrannyFreeCompletedModelControls(instance);
|
|
return model->worldPose;
|
|
}
|
|
|
|
// OFFSET: 0x0075CA20
|
|
// FUNCTION: fn_08024
|
|
void C3dGrannyModelRes::Release() {
|
|
if (GrannyModelInstance* instance = this->instance) {
|
|
for (int index = 0; index < instance->meshCount; ++index) {
|
|
GrannyMeshEntry& entry = instance->meshes[index];
|
|
GrannyFreeMeshBinding(entry.binding);
|
|
GrannyFreeMeshDeformer(entry.deformer);
|
|
delete[] entry.textures;
|
|
delete entry.indices;
|
|
if (entry.vertices != nullptr) {
|
|
delete entry.vertices;
|
|
}
|
|
}
|
|
|
|
GrannyFreeModelInstance(instance->instance);
|
|
GrannyFreeWorldPose(instance->worldPose);
|
|
delete[] instance->meshes;
|
|
}
|
|
|
|
for (int index = 0; index < this->textureCount; ++index) {
|
|
if (this->textures[index].texture != nullptr) {
|
|
delete this->textures[index].texture;
|
|
}
|
|
}
|
|
|
|
delete[] this->textures;
|
|
GrannyFreeLocalPose(static_cast<granny_local_pose*>(this->localPose));
|
|
GrannyFreeFile(this->file);
|
|
delete this->instance;
|
|
this->instance = nullptr;
|
|
}
|
|
|
|
// INLINED
|
|
C3dModelResV1::C3dModelResV1(const char* extension, const char* prefix) {
|
|
ResourceMgr::Instance().Register(extension, prefix, this);
|
|
}
|
|
|
|
// GLOBAL: gl_25560
|
|
C3dModelResV1 g_rsmPrototype("rsm", "model\\");
|