-
Posts
81 -
Joined
-
Last visited
-
Days Won
3 -
Feedback
0%
CONTROL last won the day on June 30
CONTROL had the most liked content!
About CONTROL

Recent Profile Visitors
3701 profile views
CONTROL's Achievements
-
CONTROL started following In-Game Autopatcher
-
The idea of having an in-game patcher isn't bad at all, it's actually brilliant The only bad part is that he didn't use it the way modern games/apps do Modern games can handle missing textures, models, etc. properly, so they can still run without having every single asset downloaded With Metin2 though, missing assets can easily lead to undefined behavior or even crashes But still, you can simply prioritize your packs dynamicly with each update root -> true high priority, so it gets downloaded first & you can't log in without it. icon -> false can be downloaded while you're playing. Worst-case scenario, you just get a missing icon, which will be replaced once the download finishes anyway. You could also just ask the player to restart the game once everything is downloaded.
-
CONTROL started following RenderTarget - Rework , TEMP_BUFFER Copy/Move Problem and Battle Pass System
-
Update: Memory Leak Fix I found and fixed a real memory/VRAM leak in the RenderTarget lifecycle. The issue was that destroying a: ui.RenderTarget() did not release its corresponding CRenderTarget from CRenderTargetManager. The manager only supported clearing all RenderTargets at once through Destroy(), which only happened when teleporting: self.equipmentDialogDict = {} uiChat.DestroyChatInputSetWindow() if app.ENABLE_MODEL_RENDER_TARGET: renderTarget.Destroy() So every time a UI widget containing a RenderTarget was recreated, the old model and GPU texture stayed alive until the next teleport. Now imagine a big system that heavily creates and destroys ui.RenderTarget() widgets... Yes, the new system handles the indexing correctly, but the old RenderTargets would still remain inside the manager forever. The keys would keep increasing, along with RAM and VRAM usage. So I made a very simple fix. Per-index RenderTarget release void CRenderTargetManager::ReleaseRenderTarget(int index) { if (m_renderTargets.erase(index) > 0) { if (static_cast<uint32_t>(index) < m_smallestFree) m_smallestFree = index; } } And the widget now automatically releases its RenderTarget when it is destroyed: CUiRenderTarget::~CUiRenderTarget() { if (m_dwIndex != -1) CRenderTargetManager::Instance().ReleaseRenderTarget(m_dwIndex); } which makes m_renderTargets.erase(index) remove the RenderTarget from the manager, which also releases the model and GPU texture through the existing smart-pointer based resource ownership. Then: if (static_cast<uint32_t>(index) < m_smallestFree) m_smallestFree = index; allows the released index to be reused again. Everything happens automatically in the background. You don't have to manually manage or release anything from Python. This means RenderTargets are now properly cleaned up as part of their normal C++ lifecycle, without requiring an additional Python side pool (LIKE I DID ONCE) or manual cleanup system. The repository has been updated with this fix. Enjoy!
- 1 reply
-
- 2
-
-
This maybe irrelevant but I've built many apps over the past few years, and around 90% of them have been written in Python. Not because Python is necessarily my favorite language or the one I'm most comfortable with, but simply because I never took the time to learn ImGui — which would have made building this kind of application in C++ much more practical for me This is one of the hardest projects I've worked on so far I've spent months building it, and I still plan to spend more time polishing and improving it The idea behind the app is simple If you have a Discord webhook or bot, this app allows you to easily create and send Discord embeds without having to manually write JSON or build everything from scratch. What started as a simple Python script eventually grew into a fully structured and functional application with support for embeds, polls, batch sending, templates, plugins, and more. I know this might sound like a relatively simple or even useless idea to some people, but it's something I personally enjoy using and building. It became a new challenge for me — taking a small script and turning it into a complete application. I've put a lot of time and effort into this project, and I wanted to share it here, just in case it never gets the chance to see the light of day.
-
Mining System Rework I've always hated Metin2's mining system. From the first time I saw it, I knew it'd be my forever enemy. The timers, the fixed looping animation... everything about it felt absurd when it came to actually enjoying the game. Mining always felt like a chore rather than something you could genuinely enjoy while grinding. So I decided to completely rework the entire system, taking inspiration from a Roblox game called The Forge. What's changed? Real per-swing mining. Every pickaxe swing is processed through , CHARACTER::Attack() just like a normal melee attack. There are no timers, no scripted hit counts, and no random event deciding when the vein breaks. Every swing deals actual damage to the ore vein through the normal CHARACTER::Damage() pipeline, meaning HP, death, effects, and everything else are handled by the exact same combat system the game already uses. Mining now has complete freedom. You can swing your pickaxe anytime, even if there isn't an ore vein in front of you—exactly like using any normal weapon. No more being locked into a mining animation or waiting for the game to decide when you can swing. On every successful impact, the familiar mining effect is played alongside a subtle screen shake to make each hit feel satisfying. And for the first time ever, I can finally say... I'm actually enjoying mining !! preview
-
[experimental] UI Shaders kinda difficult but very satisfying, can work with any ui (Text/Images/etc) with many options like MaskChildren(True) etc with a call back (OnEndShader) and a decent python API bg.AddShader("Pearl", 4.0, True) bg.MaskChildren(False) bg.SetShaderPalette([ (1.00, 0.75, 0.85), (0.65, 0.50, 0.95), (0.55, 0.80, 1.00), (1.00, 0.95, 0.70), ]) bg.SetShaderColor("g_Color", 1.0, 1.0, 1.0, 0.7) bg.SetShaderFloat("g_Cycles", 2) bg.SetShaderFloat("g_MaskLow", 0.5) bg.SetShaderFloat("g_MaskHigh", 0.8)
-
Hi, thx for pointing that out. I was wondering why not simply delete the copy constructor and copy assignment operator if copying isn't actually needed or used (at least from what I've seen), and make TEMP_BUFFER a move-only type instead? Since it owns a unique buffer, move-only feels like a more natural fit to me. Is there any place where copy semantics are actually required ?
-
Updated the Repo & Added V2 which has a new class AnimatedTextBox which can be used sepratly if needed enjoy !
-
Random Party Matchmaking System This is a system I originally designed for a private Metin2 server to make finding dungeon parties much easier and to encourage players to play together instead of waiting around for party members. How it works ? * A player talks to the NPC and selects a dungeon. * The player becomes the party leader and starts a **Random Party Matchmaking** request. * Every online player who meets the dungeon requirements (level, conditions, etc.) instantly receives a popup invitation on their screen. * Multiple invitations can stack, allowing players to receive requests for different dungeons without missing any of them. Live Matchmaking As players accept the invitation: * The UI updates in real time for everyone who received the invitation. * Players can see the current participants joining the group, **but only their character portraits are displayed**—no names, levels, guilds, or any other information are revealed. This keeps the matchmaking anonymous and prevents players from judging or rejecting others based on their character. * Everyone has **10 seconds** to decide whether they want to participate. During this countdown: * Any invited player can cancel their participation. * The party leader can also cancel the matchmaking before it finishes. Party Creation Once the countdown reaches zero: * All confirmed players are automatically teleported to the leader using P2P. * A party is automatically created with all confirmed members. * After a short synchronization period (around 10 seconds), the entire party is warped together into the selected dungeon. Goal The purpose of this system is to break the ice between players and remove the hassle of manually searching for dungeon groups through chat. Instead of standing in town spamming messages like: > "Need 1 Sura" > "Looking for Healer" > "Need DPS" Players can simply queue for the dungeon and instantly be matched with other interested players, making dungeon content much more active and accessible. The anonymous preview is also intentional. Since players only see character portraits before the party is formed, they can't cherry-pick teammates based on level, equipment, or class, resulting in a more fair and spontaneous matchmaking experience. This concept was something I designed some time ago for a server owner, and I thought it would be nice to showcase it here since it may inspire other developers or help improve the multiplayer experience on their own servers. Preview
-
Advanced UI Debugger – Move, Inspect & Log UI Windows Easily
CONTROL replied to CONTROL's topic in Features & Metin2 Systems
I've updated the repository and moved the project to my GitHub. i've made several changes & fixes to the system enjoy ! -
Sorry for the delay! I've updated the repository and moved the project to my GitHub. Changes Removed the colors from the effect textures. The colors were already controlled through the code, but having colorless textures produces much cleaner and more accurate results. Uploaded the latest version to GitHub, including all fixes, improvements, and recent updates. Thanks for your patience! If you run into any issues or notice something I forgot, feel free to let me know.
-
Battle Pass System This is a Battle Pass system I made quite a long time ago. Since I'm currently working on a completely new version from scratch, I was originally going to delete this old one. However, I thought it would be better to release it instead—someone might find it useful or use parts of it in their own project. Before publishing it, I cleaned up the code, made a few improvements, fixed some issues, and polished it a bit to make it easier to understand and work with. Hopefully, it will be useful to someone. Features Daily & Weekly Missions * Fully randomized Daily missions. * Fully randomized Weekly missions. * Automatic mission refresh. * Duplicate mission prevention. * Individual mission reroll support. --- Battle Pass Progression * EXP-based leveling system. * Configurable maximum level. * Automatic level progression. * Premium & Free reward tracks. * Automatic monthly reset. --- Reward System * Free rewards. * Premium rewards. * Configurable reward tables - which Supports either: * Single reward table for every month. * Individual reward tables per month. Simply change: #define SINGLE_REWARDS_TABLE TRUE --- Mission System Supports multiple mission types. Examples * Kill monsters * Destroy Metins * Complete dungeons * Collect items * Fishing * Mining * Crafting * (and easily expandable) Mission objectives and rewards are fully configurable inside: char_battlepass.h --- Multi Mission Progress A single action can update every mission of the same type simultaneously. Example If two missions require killing monsters: * Kill 100 Monsters * Kill 500 Monsters Both missions can progress together. Can be enabled or disabled by changing: #define MULTI_MISSION_PROGRESS TRUE --- Automatic Timers The system automatically handles: * Daily reset * Weekly reset * Monthly Battle Pass reset No manual intervention required. --- Randomized Missions Mission requirements are randomized every reset. Different EXP rewards are automatically assigned depending on mission difficulty. --- Premium Upgrade Built-in Premium Battle Pass support. Players can upgrade their Battle Pass using an item. --- Instant Level Up Optional Battle Pass Level-Up item included. Perfect for shop integration. --- Mission Reroll Players can reroll an unfinished mission using a dedicated item. The new mission is guaranteed not to duplicate another active mission. --- Mission Skip Allows instantly completing the first unfinished mission. Useful for premium features or special items. --- Optimized Network Packets * Packed mission data. * Packed reward data. * Minimal packet overhead. * Reduced unnecessary allocations. --- Optimized Codebase The system has been written with performance in mind. Highlights include: * Modern C++ implementation. * Smart use of references. * Static random number generator. * Efficient packet construction. * Reduced unnecessary copies. * Minimal memory allocations. * Direct array access where appropriate. * Clean and maintainable architecture. --- Configuration Most configuration can be done directly inside: char_battlepass.h Including: * Mission list * Mission requirements * EXP values * Reward tables * Monthly rewards * Battle Pass limits --- Lastly, I may have missed or forgotten something while putting this together. If you notice anything missing or think there's an improvement worth adding, feel free to leave a comment. I'll review it and, if appropriate, add it to the repository so everyone can benefit.
- 2 replies
-
- 75
-
-
-
-
-
-
-
RenderTarget - Rework This is an extend to the original RenderTarget system with several quality-of-life features, rendering improvements, and a cleaner API, making it significantly easier to integrate into modern systems such as Wiki, Dungeon Info, Item Preview, Etc.. --- Features Automatic RenderTarget Index Allocation RenderTarget IDs are now allocated automatically by the engine. This completely removes manual index management and guarantees that multiple systems can safely create RenderTargets without conflicting IDs. ### Old Method def __init__(self): ui.Whatever.__init__(self) self.renderKey = 5 def OnRenderMob(self, race): self.modelRenderer = ui.RenderTarget() self.modelRenderer.SetParent(self.board) self.modelRenderer.SetSize(260, 170) self.modelRenderer.SetRenderTarget(self.renderKey) self.modelRenderer.Show() renderTarget.SetBackground(self.renderKey, "background.sub") renderTarget.SetVisibility(self.renderKey, True) renderTarget.SelectModel(self.renderKey, race) ### New Method def OnRenderMob(self, race): self.modelRenderer = ui.RenderTarget() self.modelRenderer.SetParent(self.board) self.modelRenderer.SetSize(260, 170) self.modelRenderer.Show() key = self.modelRenderer.GetRenderTargetIndex() renderTarget.SetBackground(key, "background.sub") renderTarget.SetVisibility(key, True) renderTarget.SelectModel(key, race) No manual IDs. No duplicated RenderTargets. Completely plug-and-play. Note this: key = self.modelRenderer.GetRenderTargetIndex() will only be available after: self.modelRenderer.SetSize(260, 170) not before ! Smooth Mouse Rotation Drag the model with the mouse to rotate it smoothly. Rotation uses inertia for a much more natural feeling. --- Smooth Mouse Wheel Zoom Zooming is velocity-based with damping instead of instantly jumping between positions. --- Automatic Camera Fitting The camera automatically adjusts itself based on the rendered model's height. This allows players, monsters, NPCs and objects to appear correctly centered without requiring manual camera values for every race. --- Hair Preview Camera Hair preview can automatically switch to a dedicated camera focused on the character's head. Example renderTarget.SetHair(key, hairCostumeVnum, True) # Hair Preview renderTarget.SetHair(key, hairCostumeVnum) # Normal Preview (False is the default value) Automatic Hair Model Detection Simply pass the costume hair VNUM. The RenderTarget automatically resolves the correct hair model internally without requiring manual `value(3)` extraction. --- Equipment Persistence The RenderTarget automatically remembers compatible equipment for every race. Supported parts: * Armor * Weapon * Hair * Acce * Weapon Shining * Armor Shining Switching between races automatically restores the appropriate equipment whenever possible. --- Optional Auto Rotation Auto rotation can be enabled per model. Example renderTarget.SelectModel(key, race, True) # Auto Rotate renderTarget.SelectModel(key, race) # Static Model (False is the default value) Automatic Weapon Selection for Weapon Shining If no weapon is equipped, the RenderTarget automatically equips a compatible default weapon before applying the weapon shining. This allows weapon shining previews to work correctly without requiring additional setup. --- Modern C++ Memory Management The RenderTarget has been modernized using smart pointers (`std::unique_ptr` / `std::shared_ptr`) for safer and cleaner resource management. --- Cleaner API Several APIs have been simplified to reduce boilerplate and make RenderTarget integration much easier for future systems. Final Note These improvements are not a drag-and-drop solution. Although they dramatically simplify the implementation process—especially for large systems like the Wiki—you still need to understand what you're doing. They are meant to eliminate a lot of the repetitive work and common headaches, making development much faster and cleaner, not replacing proper integration. If you've already gone through the features listed above, you'll notice that many tedious tasks are now handled automatically, allowing you to focus on building your system instead of dealing with render target management. Also, keep in mind that the GrpRenderTargetTexture implementation I shared is written for DirectX 9. If your source is still using DirectX 8, you'll likely need to make a few adjustments to ensure compatibility. - Lastly, I may have missed or forgotten something while putting this together. If you notice anything missing or think there's an improvement worth adding, feel free to leave a comment. I'll review it and, if appropriate, add it to the repository so everyone can benefit.
- 1 reply
-
- 40
-
-
-
-
-
-
Custom In-Game Wiki I never wanted to make my own wiki. Like... ever. Unfortunately, after reading pretty much every available wiki system, I couldn't find a single one that matched what I needed, so Overview The entire wiki is built around a custom content loader capable of loading and animating: * Text * Grids * Items * Images * Custom widgets * Basically anything I want Features ### Refine Wiki A complete refine wiki with data retrieved directly from the server. Monsters / Stones / Bosses / Ores Wiki A complete encyclopedia with server-driven data. All relevant information, including spawn locations, is retrieved directly from the server. For high-density content such as regular monsters, Metin Stones and Ores, location data is clustered server-side to reduce network traffic and improve efficiency while maintaining accurate results. ### Chests Wiki A complete chest wiki with server-driven data. ### Cube Wiki A complete cube wiki with server-driven recipes. ### Costume Viewer Create any costume set combination with ease. * Custom set names * Custom item combinations * Easy configuration ### Navigation System A fully working Back / Forward navigation system, similar to a web browser. ### Advanced Search Real-time search with related suggestions. The search only displays content that actually exists inside the wiki. Server-Driven Design The wiki follows a single-source-of-truth philosophy. Only the data that actually matters is transmitted from the server. I honestly hate wiki systems that require duplicated data, hardcoded pages, and manual synchronization every time something changes. If a refine recipe, cube recipe, drop table, chest content, or monster information changes, the wiki updates automatically without maintaining the same data in multiple places. Cross Referencing Every piece of data is indexed in both directions. An item can instantly show: * Where it drops * Which chests contain it * Which cube recipes use it * Which refine recipes require it * Which shops sell it No expensive runtime scans are required. Performance I built it like a fkn chef. The entire data structure was designed around O(1) lookups wherever possible. * No unnecessary scans * No duplicated data * No weird hardcoded stuff Everything is heavily indexed and optimized to keep searches and page loading extremely fast even with large datasets. Models & UI Loading To provide the smoothest experience possible: Every monster model is fully preloaded ahead of time, eliminating runtime asset loading and ensuring instant transitions across the entire wiki. This results in zero loading spikes and no noticeable FPS drops, even when browsing pages with a high number of monsters or NPCs. --- UI elements are loaded lazily and only when needed. * Models are preloaded in advance. * Content is generated dynamically. This keeps navigation responsive and avoids loading hiccups while browsing. --- Still a work in progress, but it has already replaced several standalone systems and made content maintenance significantly easier. Preview
-
[experimental] Texture Neon System Add emissive and neon effects to any GR2 model using an additional texture layer. Features Automatic detection of Neon textures Per-model emissive effects Color-driven Neon rendering Alpha-controlled Neon intensity Works with all GR2 models No model editing required Automatic fallback when no Neon texture exists Lightweight and easy to integrate Overview Texture Neon System allows artists to add emissive details to existing models without modifying the model itself. When a texture is loaded, the system automatically checks for a matching texture with the "_neon" suffix. If found, it is used as an additional emissive layer on top of the original texture. The Neon texture defines both the visible emissive areas and their colors. This makes it possible to create glowing lines, magical symbols, energy effects, armor details, weapon highlights, wing effects, and similar visual elements directly from the texture artwork. Neon intensity is controlled through the texture's alpha channel, allowing precise control over how strong each emissive area appears in-game. Models without a corresponding Neon texture continue to render normally, making the feature fully optional and compatible with existing content. Usage The original texture defines the model appearance, while the Neon texture defines the emissive regions. Artists can control: • Neon colors • Glow intensity • Visible emissive areas • Different visual styles for each asset No additional configuration, model changes, or special setup is required. To create a Neon effect, simply add a second texture using the same filename and the "_neon" suffix. Example weapon_choegogeup01_02_neon.dds for example - more alpha = more neon Preview the idea was something like this i didn't 100% get it but i'm very close the neon dosen't only shine in white btw it takes the texture color volcanic textures are alive !
