Leaderboard
Popular Content
Showing most liked content since 01/21/2026 in all areas
-
Map viewer built around my export format (JSON + JPEG atlases + sprite strips). Three.js, no server needed, just open index.html. The C++ version will be posted in the next few days separately, both projects have enough features on their own to keep each post short and they can be used independently. Some ideas for usage: overlay Mobs/NPC/guard positions on the map, player backtrack/movement history, heatmaps for player activity zones, or just browsing maps without the client. I hope someone find this useful & get creative with it. References: wiki/Dmap, wiki/DmapLayerType & EO-Map implementation. Preview: webmappreview.mp4 There are few maps that you can try in the live demo, depending on the map, it will take longer to load. tc: 33MB, desert: 15MB, desert10: 5MB, island: 11MB Live demo: web-map-viewer-demo. Repository: web-map-viewer12 likes
-
Enjoy. References: wiki/Dmap & spirited/floor (so basically shoutout to: @Spirited ) Preview: floorEditorOld.mp4 Live demo: web-demo Repository: cpp-version (win32 + imgui/dx11 and basic optimizations) & web-version (three.js).9 likes
-
Hey Folks, Happy Friday, and hope everyone is doing well. I tend to be more a lurker on forums, but figured I could do an introduction and get out of my shell lol My name is Chuck, and I used to play Conquer in early to mid 2000s. I stopped a year or two after TQ added the fan and tower items in. I followed epvp quite a bit (same username there) and got into learning programming from the folks posting sources there. One memorable part was when Pro4never released a proxy base and me and my friend added botting functionality over a weekend, which also got him into learning to code . I’ve been a professional dev for just over a decade now, mostly working in fintech and a bit in advertising. Currently I mostly work with the JVM, using Kotlin, Spring, and Flink. I started teaching myself Elixir/Erlang about a month ago after seeing some of the awesome features of the OTP. I don't have a lot of free time, but as I learn Ive been slowly working on implementing a classic server with it. So far I have most of the shared parts working (ciphers, packet ser/der, protocols) + the auth server. I’m also using this server to experiment with a distributed architecture as well. So Im setting up the project with a few distinct components that can be deployed separately. The auth, gateways (handle connections + protocol), map servers (hand 1 or more maps), and world server for coordination and stuff. I’ll most likely make a thread with a github link once I get the source in decent shape that Im happy with. But so far I am really liking Elixir and functional programming. The pattern matching construct is awesome, especially on binary data. Anyways I appreciate this forum being run to keep the community for these games alive!6 likes
-
Oh yeah sure , so you were only trying to market for your sales here5 likes
-
I have developed an in-game voice chat system for Conquer Online. This makes communication much easier and faster, without the need to use Discord. Do you have any suggestions to help improve the voice quality? I did face an issue related to microphone control: when there are two accounts, each one in a different channel, and I press Alt + Tab, the voice system disconnects from the first account and switches to the second one. I would like to hear your opinions, friends.4 likes
-
C3 Blender Add-On A Blender add-on for importing and animating C3 model format files, with support for multiple PHY types and animation keyframe formats. Download Latest Release https://github.com/abdouthematrix/c3-blender-addon/releases/download/latest/c3-blender-addon-latest.zip Or browse all releases: https://github.com/abdouthematrix/c3-blender-addon/releases Features: - Import C3 Models - Import Texture - Import/Replace Animation - Import/Replace Mesh Parts Installation: 1. Download the latest release zip file from the link above 2. In Blender, go to `Edit > Preferences > Add-ons` 3. Click `Install` and select the downloaded zip file 4. Enable the add-on by checking the box next to "Import-Export: C3 Add-On" Note: Do not unzip the file - Blender will install it directly from the zip. Usage: # Importing a C3 Model: 1. Go to the top menu bar and click `C3 Add-On > Import .C3 Model` 2. Browse to your `.c3` file and select it 3. Options: - New Scene : Import into a new scene (enabled by default) - debugpy : Enable remote debugging (for development) 4. Click `Import .C3 Model` # Importing a Texture 1. Select a mesh object 2. Go to `C3 Add-On > Import Texture` 3. Select a texture file (DDS, TGA, PNG, or JPG) 4. The texture will be applied to the selected mesh # Importing/Replacing Animation 1. Select a mesh object that was previously imported from a C3 file 2. Go to `C3 Add-On > Import Animation` 3. Options: - Use Original File: Uses the stored file path from the original import (enabled by default) 4. Click `Import Animation` # Credits - Author: abdoumatrix - Development Assistance: Claude (Anthropic) - Inspired by: [C3-Operator] by Tachyon-S3 likes
-
I'm actually working on that, should have something worth releasing sometime this year, all depending on life work and my kid lol (specifically working on a 5517 client, and a older version of an andriod client).2 likes
-
The web map viewer has been updated. I added a few official maps (about 85% quality, I'll upload lower/faster ones soon ). Updated / Added: - NPC positions and names - Mob and guard positions/zones with names - Mobile support - Removed the old dmap access grid format and switched to direct dmap access (https://co-stuff.github.io/web-floor-editor/) Maps ready to view (v6609 maps/npcs/mobs): - TwinCity (n-newplain) - Forest (woods) - Desert - MysticCastle (d_antre01) - Island - Stable (horse) - Canyon - MineCave (mine01) - NPCJail (mine-one) webmap3.mp42 likes
-
Amazing work! I was wondering if something was off with your TC due to trees on the water, but no, just a dumb TQ thing because my editor does the same lol. It's interesting your trees don't load on the grassy area since they're the same type as the desert trees, maybe you forgot to convert them? I would strongly suggest reading directly from the .dds files, on of my first versions converted the entire map to .png's and that took so much longer than needed. If you ever need help with anything related to mapping, just let me know! I've now spent years slowly building too many versions of a map editor to build some new custom maps. I don't release mine since I've seen people on other forums already attempting to sell the freely released maps I've created so I don't want to give other people free money for the hard work that I've done.2 likes
-
For those too lazy to look for a function to hook to receive packets... constexpr uintptr_t RECV_PACKET_ADDRESS = 0x0073CE61; typedef void*(__cdecl* RecvPacketFunc)(void* data, int len);2 likes
-
Lol at the hubris. buddy youre acting like you had made some massive breakthrough and people were rallying to go check out your ugly vc ui lmfao. Its not a rare feature because its incredibly difficult or something, its because its niche... how many people actually would want this feature? and out of the people that would want it who would even get to fully utilize it in the era of conquer that we live in today? Its cute, its novel, its interesting, its cool... but thats it. You really think one of your 12 players (really 4 guys with multiple accounts) showed up just to try to copy your vc feature?2 likes
-
Similarity doesn’t mean copying. The implementation is what matters. I’m not in competition with anyone. Everyone has their own work.2 likes
-
For the latest versions most functions can be disabled by feature flags and lua scripts on ini folder. (Forge itself you can remove almost everything via LUA), a lots of icons and stuff also can be removed there as well the classes from everywhere (reincarnation, role selection etc). Issue is that you need the new encryption/decryption for those files, since they're all encrypted now.1 like
-
hello im new to this coding stuff but i had make this imgui with my source that i got with help with ai i just wanna release this for people to have or whatever. im not good with word and stuff but here is the source. so far it can login to my server both acc and game but i cant get it to render the map and stuff https://drive.google.com/file/d/1M_00gEnZ53_CZAcWysZQp3a-PACL0P9x/view?usp=sharing1 like
-
As curious as this is, this is not within our community guidelines. Game preservation and contributions are a human activity. If the majority of your project is AI generated, then that's not a human contributing.1 like
-
Wow, I'm genuinely surprised AI was able to get you this far. I'll be following this vibe project out of pure intrigue of how far you get this way. GL1 like
-
I love seeing projects like this. You got so many nice details into this, like the drawn sound ranges. You even got the waterfalls and such animated! Great work.1 like
-
Based on surface values, refs: [og] [cpp] [web]. This was simply to improve the visual appearance, rather than relying on the usual green and red accent colors.1 like
-
Great work dude I'm not commenting on your work, but you didn't hook the "send" function. You hooked a pre-send function. ( Before encryption ) That doesn't constitute an issue in the post. However, this information is for those who will be changing the project version. for another clients You have to hook earlier "Send" to get clear packet without client encryption shits1 like
-
1 like
-
since this looks around the 5730-6609 patch you can definitely just swap the files, guildwar map is faction. so just take the files from the map and ani folders for a direct swap. .dmap map/map .pul map/puzzle some files have swapped to .pux around 6609 from what ive seen and they did change the GW map somewhat when they went full 3.0 and swapped TC to the Market/TC design but it should be an extremely easy direct swap. i dont recall if you need more than that but i have spent quite a bit of time making maps and editing maps so you shouldnt have much of a problem adding/fixing that. just make a copy of what you swap incase something goofy happens but its like a 30 second fix.1 like
-
i know this is an old post and you probably found it already but for others who may have the same question, it is located in c3/effect/CountB and if that file is not there you can either get it from c3.wdf or you can make the folder yourself and it will replace the originals with the dds images you made as long as everything is named correctly and is the proper file type. hope this helps you and/or others1 like
-
Welcome to the board! Looking forward to seeing more about your distributed server project - reminds me a lot of something I was working on a long time ago now.1 like
-
Welcome, Chuck! Love the idea of building a classic server in Elixir, I don't see this language around much! Looking forward to seeing the GitHub link when you’re ready. Glad to have you here!1 like
-
Actually, I coded this into my server about two months ago, and my players are already using it. I wish you had created your own custom design instead of copying it. Still, there's effort involved. Congratulations! Zephyr_Conquer_Voice_System (1).mp41 like
-
Thank you, this looks good! I think it would be nicer if you format the thread properly because it's a bit harder to read, what you pasted was meant for .md formats but the forum doesn't support rendering it.1 like
-
Oh wow that's amazing! I thought I would only see such thing in Tow Conquer, now we got this too!1 like
-
This thread already have some documentation about it. But you do bitwise operations to check the map flag. Example: /// <summary> /// Checks if the map is a pk field. Wont add pk points. /// </summary> public bool IsPkField() { return Type.HasFlag(MapTypeFlag.PkField); } /// <summary> /// Disable teleporting by skills or scrolls. /// </summary> public bool IsChgMapDisable() { return Type.HasFlag(MapTypeFlag.ChangeMapDisable); } /// <summary> /// Disable recording the map position into the database. /// </summary> public bool IsRecordDisable() { return Type.HasFlag(MapTypeFlag.RecordDisable); } /// <summary> /// Disable team creation into the map. /// </summary> public bool IsTeamDisable() { return Type.HasFlag(MapTypeFlag.TeamDisable); } /// <summary> /// Disable use of pk on the map. /// </summary> public bool IsPkDisable() { return Type.HasFlag(MapTypeFlag.PkDisable); } /// <summary> /// Disable teleporting by actions. /// </summary> public bool IsTeleportDisable() { return Type.HasFlag(MapTypeFlag.TeleportDisable); } /// <summary> /// Checks if the map is a syndicate map /// </summary> /// <returns></returns> public bool IsSynMap() { return Type.HasFlag(MapTypeFlag.GuildMap); } /// <summary> /// Checks if the map is a prision /// </summary> public bool IsPrisionMap() { return Type.HasFlag(MapTypeFlag.PrisonMap); } /// <summary> /// If the map enable the fly skill. /// </summary> public bool IsWingDisable() { return Type.HasFlag(MapTypeFlag.WingDisable); } /// <summary> /// Check if the map is in war. /// </summary> public bool IsWarTime() { return (Flag & 1) != 0; } /// <summary> /// Check if the map is the training ground. [1039] /// </summary> public bool IsTrainingMap() { return Identity == 1039; } /// <summary> /// Check if its the family (clan) map. /// </summary> public bool IsFamilyMap() { return Type.HasFlag(MapTypeFlag.House); } /// <summary> /// If the map enables booth to be built. /// </summary> public bool IsBoothEnable() { return Type.HasFlag(MapTypeFlag.BoothEnable); } /// <summary> /// Check if the map allows user to revive here. /// </summary> /// <returns></returns> public bool IsRebornNowEnable() { return Type.HasFlag(MapTypeFlag.RebornNowEnable); }1 like
-
It's a bitmask, you can break down the flags it has enabled, but you need to cross reference them with the flags for whatever version you have. Idk what values that is, but here's a python script I use. Can/should be adjusted per the flags you want to check according to the version you're using, etc. import tkinter as tk from tkinter import messagebox MAP_FLAGS = { 0x0000: "Normal", 0x0001: "PK_FIELD", 0x0002: "CHANGE_MAP_DISABLE", 0x0004: "RECORD_DISABLE", 0x0008: "PK_DISABLE", 0x0010: "BOOTH_ENABLE", 0x0020: "TEAM_DISABLE", 0x0040: "TELEPORT_DISABLE", 0x0080: "GUILD_MAP", 0x0100: "PRISON_MAP", 0x0200: "WING_DISABLE", 0x0400: "FAMILY", 0x0800: "MINE_FIELD", 0x1000: "PK_GAME", 0x2000: "NEVER_WOUND", 0x4000: "DEAD_ISLAND", 0x20000: "SKILL_MAP", 0x40000: "LINE_SKILL_ONLY" } def decode_flags(value): result = [] undefined_bits = value for bit, name in MAP_FLAGS.items(): if value & bit: result.append(name) undefined_bits &= ~bit if value == 0: result.append("Normal") undefined_bits = 0 if undefined_bits: result.append(f"Undefined flags: 0x{undefined_bits:04X}") return result def on_check(): try: val = int(entry.get(), 0) flags = decode_flags(val) output.config(state='normal') output.delete('1.0', tk.END) output.insert(tk.END, "\n".join(flags)) output.config(state='disabled') except ValueError: messagebox.showerror("Error", "Please enter a valid number (decimal or 0x hex).") root = tk.Tk() root.title("Map Flag Checker") tk.Label(root, text="Enter Flag Value (e.g. 1234 or 0x4C):").pack() entry = tk.Entry(root) entry.pack() tk.Button(root, text="Check Flags", command=on_check).pack() output = tk.Text(root, height=10, width=50, state='disabled') output.pack() root.mainloop()1 like
-
namespace Comet.Network.Security { using System; using System.Threading; /// <summary> /// TQ Digital Entertainment's in-house asymmetric counter-based XOR-cipher. Counters /// are separated by encryption direction to create cipher streams. This implementation /// implements both directions for encrypting and decrypting data on the server side. /// </summary> /// <remarks> /// This cipher algorithm does not provide effective security, and does not make use /// of any NP-hard calculations for encryption or key generation. Key derivations are /// susceptible to brute-force or static key attacks. Only implemented for /// interoperability with the pre-existing game client. Do not use, otherwise. /// </remarks> public sealed class TQCipher : ICipher { private const int KEY_SIZE = 0x100; // Local fields and properties private byte[] mCryptKey1; private byte[] mCryptKey2; private byte[] mCryptKey3; private byte[] mCryptKey4; private int mDecryptCounter; private int mEncryptCounter; private bool mExchanged; /// <summary> /// Instantiates a new instance of <see cref="TQCipher"/> with initial IV keys. /// </summary> public TQCipher() { this.mExchanged = false; this.mDecryptCounter = 0; this.mEncryptCounter = 0; CreateKeys(); } /// <summary> /// Generate the initialization vector keys using static seed values. /// </summary> private void CreateKeys() { this.mCryptKey1 = new byte[KEY_SIZE]; this.mCryptKey2 = new byte[KEY_SIZE]; byte iKey1 = 0x1F; byte iKey2 = 0x3F; for (int i = 0; i < KEY_SIZE; i++) { this.mCryptKey1[i] = iKey1; this.mCryptKey2[i] = iKey2; iKey1 = (byte)(((byte)(iKey1 << 5) + 0xFD) * iKey1 + 7); iKey2 = (byte)((iKey2 * 0x7A - 0x31) * iKey2 - 0x1B); } } /// <summary> /// Generates keys for the game server using the player's token and account ID /// as key derivation variables. Invoked after the first packet is received on /// the game server. /// </summary> /// <param name="seeds">Array of seeds for generating keys (expects Token and AccountID as uint)</param> public void GenerateKeys(object[] seeds) { uint token = Convert.ToUInt32(seeds[0]); uint accountId = Convert.ToUInt32(seeds[1]); this.mCryptKey3 = new byte[KEY_SIZE]; this.mCryptKey4 = new byte[KEY_SIZE]; int tmpkey1 = (int)((token + accountId) ^ 0x4321 ^ token); int tmpkey2 = tmpkey1 * tmpkey1; byte[] tmp1 = BitConverter.GetBytes(tmpkey1); byte[] tmp2 = BitConverter.GetBytes(tmpkey2); for (int i = 0; i < KEY_SIZE; i++) { this.mCryptKey3[i] = (byte)(this.mCryptKey1[i] ^ tmp1[i % 4]); this.mCryptKey4[i] = (byte)(this.mCryptKey2[i] ^ tmp2[i % 4]); } this.mExchanged = true; } /// <summary> /// Decrypts the specified span by XORing the source span with the cipher's /// keystream. The source and destination may be the same slice, but otherwise /// should not overlap. /// </summary> /// <param name="src">Source span that requires decrypting</param> /// <param name="dst">Destination span to contain the decrypted result</param> public void Decrypt(Span<byte> src, Span<byte> dst) { for (int i = 0; i < src.Length; i++) { byte key1Index = (byte)(this.mDecryptCounter & 0xFF); byte key2Index = (byte)(this.mDecryptCounter >> 8); if (this.mExchanged) { dst[i] = (byte)(src[i] ^ (this.mCryptKey4[key2Index] ^ this.mCryptKey3[key1Index])); } else { dst[i] = (byte)(src[i] ^ (this.mCryptKey2[key2Index] ^ this.mCryptKey1[key1Index])); } Interlocked.Increment(ref this.mDecryptCounter); } } /// <summary> /// Encrypt the specified span by XORing the source span with the cipher's /// keystream. The source and destination may be the same slice, but otherwise /// should not overlap. /// </summary> /// <param name="src">Source span that requires encrypting</param> /// <param name="dst">Destination span to contain the encrypted result</param> public void Encrypt(Span<byte> src, Span<byte> dst) { for (int i = 0; i < src.Length; i++) { byte key1Index = (byte)(this.mEncryptCounter & 0xFF); byte key2Index = (byte)(this.mEncryptCounter >> 8); dst[i] = (byte)(src[i] ^ (this.mCryptKey1[key1Index] ^ this.mCryptKey2[key2Index])); Interlocked.Increment(ref this.mEncryptCounter); } } /// <summary> /// Reset both encryption and decryption counters. /// </summary> public void ResetCounters() { this.mEncryptCounter = 0; this.mDecryptCounter = 0; } } } namespace Comet.Network.Security { using System; using Comet.Core.Mathematics; /// <summary> /// Rivest Cipher 5 is implemented for interoperability with the Conquer Online game /// client's login procedure. Passwords are encrypted in RC5 by the client, and decrypted /// on the server to be hashed and compared to the database saved password hash. In /// newer clients, this was replaced with SRP-6A (a hash based exchange protocol). /// </summary> /// <remarks> /// RC5 has a 32, 64 or 128-bit block size and a variable key length from /// 1 bit up to 2040 bits. It is a Feistel-like cipher using between 1 to /// 255 rounds. The suggested values are respectively 128, 64 and 12, although /// 12-round RC5 (with 64-bit blocks) is susceptible to a differential attack /// using 2^44 chosen plaintexts. To be still an effective cipher, 18-20 rounds /// are now suggested. /// </remarks> public sealed class RC5 : ICipher { // Constants and static properties private const int KEY_SIZE = 16; // The key size in bytes (0-255, 16 suggested) private const int BLOCK_SIZE = 8; // The block size in bytes (4, 8, or 16, 8 suggested) private const int ROUNDS = 12; // The number of rounds (1-255, 12 suggested) // Magic values private const uint RC5_PW32 = 0xB7E15163; private const uint RC5_QW32 = 0x61C88647; // Internal key sizes for uint32 arrays private const int RC5_SUB = (ROUNDS * 2) + 2; private const int RC5_KEY = KEY_SIZE / 4; // Local fields and properties private readonly uint[] mKey; private readonly uint[] mSub; /// <summary> /// Initializes a new instance of <see cref="RC5"/> to be interoperable with /// the Conquer Online game client. Automatically generates keys using the /// default seed. In later versions of the client, a random buffer is used /// to seed the cipher. /// </summary> public RC5() { this.mKey = new uint[RC5_KEY]; this.mSub = new uint[RC5_SUB]; // Zero-fill arrays for security purposes Array.Clear(this.mKey, 0, this.mKey.Length); Array.Clear(this.mSub, 0, this.mSub.Length); // Generate keys with default seed GenerateKeys(new object[] { new byte[] { 0x3C, 0xDC, 0xFE, 0xE8, 0xC4, 0x54, 0xD6, 0x7E, 0x16, 0xA6, 0xF8, 0x1A, 0xE8, 0xD0, 0x38, 0xBE } }); } /// <summary> /// Generates keys and the subkey words for RC5 using a shared seed, whether /// that seed is shared statically or shared using a method of transport. Though /// only one seed is expected to generate keys, multiple may be used. Seed must be /// divisible by the selected cipher word size (16 bytes in this implementation). /// </summary> /// <param name="seeds">An array of seeds used to generate keys</param> public void GenerateKeys(object[] seeds) { var aSeed = seeds[0] as byte[]; // Copy seed into key array for (int i = 0; i < RC5_KEY; i++) { this.mKey[i] = BitConverter.ToUInt32(aSeed, i * 4); } // Initialize sub-key array this.mSub[0] = RC5_PW32; for (int i = 1; i < RC5_SUB; i++) { this.mSub[i] = this.mSub[i - 1] - RC5_QW32; } // Generate key schedule uint x = 0, y = 0; int iIdx = 0, jIdx = 0; int iterations = 3 * Math.Max(RC5_KEY, RC5_SUB); for (int k = 0; k < iterations; k++) { this.mSub[iIdx] = (this.mSub[iIdx] + x + y).RotateLeft(3); x = this.mSub[iIdx]; iIdx = (iIdx + 1) % RC5_SUB; this.mKey[jIdx] = (this.mKey[jIdx] + x + y).RotateLeft((int)(x + y)); y = this.mKey[jIdx]; jIdx = (jIdx + 1) % RC5_KEY; } } /// <summary> /// Decrypts bytes from the client. The buffer length must be a multiple of /// the BLOCK_SIZE constant (8 bytes). The source and destination may be the /// same slice. /// </summary> /// <param name="src">Source span that requires decrypting</param> /// <param name="dst">Destination span to contain the decrypted result</param> public void Decrypt(Span<byte> src, Span<byte> dst) { int blockCount = src.Length / BLOCK_SIZE; for (int i = 0; i < blockCount; i++) { int offset = i * BLOCK_SIZE; uint ld = BitConverter.ToUInt32(src.Slice(offset, 4)); uint rd = BitConverter.ToUInt32(src.Slice(offset + 4, 4)); // Decrypt rounds for (int j = ROUNDS; j >= 1; j--) { rd = ((rd - this.mSub[2 * j + 1]).RotateRight((int)ld)) ^ ld; ld = ((ld - this.mSub[2 * j]).RotateRight((int)rd)) ^ rd; } uint a = rd - this.mSub[1]; uint b = ld - this.mSub[0]; BitConverter.GetBytes(b).CopyTo(dst.Slice(offset, 4)); BitConverter.GetBytes(a).CopyTo(dst.Slice(offset + 4, 4)); } } /// <summary> /// Encrypts bytes from the server. The buffer length must be a multiple of the /// BLOCK_SIZE constant (8 bytes). The source and destination may be the same slice. /// </summary> /// <param name="src">Source span that requires encrypting</param> /// <param name="dst">Destination span to contain the encrypted result</param> public void Encrypt(Span<byte> src, Span<byte> dst) { int blockCount = src.Length / BLOCK_SIZE; for (int i = 0; i < blockCount; i++) { int offset = i * BLOCK_SIZE; uint a = BitConverter.ToUInt32(src.Slice(offset, 4)); uint b = BitConverter.ToUInt32(src.Slice(offset + 4, 4)); uint le = a + this.mSub[0]; uint re = b + this.mSub[1]; // Encrypt rounds for (int j = 1; j < ROUNDS; j++) { le = ((le ^ re).RotateLeft((int)re)) + this.mSub[2 * j]; re = ((re ^ le).RotateLeft((int)le)) + this.mSub[2 * j + 1]; } BitConverter.GetBytes(le).CopyTo(dst.Slice(offset, 4)); BitConverter.GetBytes(re).CopyTo(dst.Slice(offset + 4, 4)); } } } } work with comet base1 like
-
Most likely he is waiting him to post it on Github so that he will start selling a proxy he been doing the same for over 5 years already. Checking for free releases then sells it on his blog for 50$ maybe , open source has its bad sides also. I can see on his own community group someone released a source for free along with an open loader , he deleted his post and probably removed the guy from the group and he sells it on his own blog now and he sells the loader as well. I also can see another guy already selling the a broken ShowString hook edits on his other group. That's why so many people already have such features and even more advanced and not gonna share to community , Everything you post openly it becomes the source of living for other people . This is full disrespect to the person who shared and the amount of time he spent developing it. That's why Conquer Development Communities are DEAD. If you share anything openly its just like bringing more and more of potential scammers into the domain. Their most famous words are " Share for the community to improve " " If you share the servers will be better" " Share for education " and their best friends are " Jet brains " , " Il Spy " , " Ghidra " and next day it ends with your hard work is being sold , it cant be maintained , new scammers spotted !1 like
-
Most of you probably already know this, but it’s still a good idea to document it here. Sometimes you may want to remove annoying buttons you never use, or simply rearrange or resize parts of the UI. This tutorial will be split into two sections: Deleting a button Moving & Resizing In this part, we’ll focus on deleting a button. We’ll be using Resource Hacker to modify Conquer.exe, editing the GUI.INI, GUI800X600.ini, Control.ani files, and removing some .dds image files. Note 1: Make a backup of anything you will modify in case you break your GUI! Note 2: This has been tested on 6609 I'm not sure about the behavior on older clients. ____________________________________________________________________________________________________________ [1.1] Example: Removing the “Poker” Button First, type the following command in the game Talk chat: /enablefocus (Credits goes to @Spirited for this command) This allows you to identify a button’s ID by simply hovering over it. When you hover over the button, look at the top-left corner of the screen. You’ll see information displayed in this format: [parent -child] You’ll also see the ANI reference name, which points to the DDS image controlling that button. The first number is the parent window ID The second number is the child window/button ID under that parent For example: [579 - 3055] 579 → parent container (this holds most of the icons at the top-right area btw) 3055 → the specific ID of the Poker button This exact same format is used inside the GUI.INI files (along with x, y, width, height, etc.). ____________________________________________________________________________________________________________ [1.2] Editing Conquer.exe with Resource Hacker Now that we have the button ID, open Resource Hacker and load Conquer.exe Click Open Make sure you edit the correct executable (in my case, I’m using the DX9 version, so I edit the exe inside ENV_DX9) Next: Expand the Dialog section You’ll only see parent windows, so search for 579 Inside this dialog, you’ll see an approximate layout of all the buttons in that container. Each line represents a child control under parent 579, written in something similar to a CSV format. The second value in each line is the button ID we found in-game: CONTROL "ShowHand", 3055, BUTTON, BS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 82, 62, 14, 13 To disable the button: Replace WS_VISIBLE with WS_DISABLED Updated line: CONTROL "ShowHand", 3055, BUTTON, BS_OWNERDRAW | WS_CHILD | WS_DISABLED | WS_TABSTOP, 82, 62, 14, 13 Now Compile [1] and Save [2] (Make sure to close the client first), a backup will be created automatically under the name Conquer.old.exe in the same file you can keep or delete it. At this point, the button will no longer be clickable, but the image will still be visible. ____________________________________________________________________________________________________________ [1.3] Removing the Button Image Next, open GUI.INI or GUI800X600 and search for the button entry: This section defines: Button position and size The ANI section that controls its image Now open: ani/Control.ani Search for: [Dentrance_DentranceBtn] You’ll find four frames, each pointing to a DDS image used for different button states: Simply delete this entire section. Once removed, the button will be completely gone when you open the client. ____________________________________________________________________________________________________________ [1.4] Optional Cleanup For extra cleanup, you can also delete the DDS image files from their directory since they’re no longer needed alongside the entries from GUI.ini However, removing the ANI section alone is enough to fully hide the button. ____________________________________________________________________________________________________________ [1.5] Alternative Method (Without /enablefocus) If you can’t use the /enablefocus command, you can use WinSpy instead. Drag the WinSpy finder tool (shown in the screenshot below) Drop it on the button you want to remove WinSpy will give you the Caption, which matches the first string in the Resource Hacker control entry. Note: WinSpy does not provide the window ID So you’ll need to: Search for that caption string in Resource Hacker using CTRL + F Locate the matching control manually And that’s it. ____________________________________________________________________________________________________________ [2.1] Resizing/Moving a button By now, resizing should be straightforward. Simply adjust the size values in the GUI.INI file. Make sure to apply the same changes in GUI800X600.ini as well, so the button displays correctly at both resolutions. If you prefer a visual approach, you can use the /enablefocus command. This allows you to resize a button by dragging its corners. For example, if the nobility icon appears too large, you can reduce its size by dragging the edges of the red selection box. You can also move the button by dragging it, and the new position will be automatically saved to your GUI.INI file. Note 1: I recommend avoiding direct visual editing when possible. It’s easy to accidentally click another button (such as a nearby button), and sometimes the UI may behave unpredictably. In some cases, the button can end up outside the window boundaries and become invisible. Note 2: Resizing won't work for most types of buttons because their sizes will depend only on the actual DDS image, what you will control is the area that's clickable (the red square) when resizing. Note 3: You will often make the button unclickable when moving it with the command, to fix that just restart the client and it will be clickable in its new position. Note 4: If you wanna move an element, you won't be able to move it outside its parent container (you can know the element boundaries by [RED] edges and parent by [YELLOW] edges when hovering with the command enabled) for example the settings button, you won't be able to move it (if someone figures out a solution maybe they can drop in comments! ) After Resize : Note 5: You can also use WinSpy if you want to experiment with a button’s position without restarting the client or using in-game commands. This helps reduce the risk of breaking something, since WinSpy changes are applied only in memory and will be discarded once the client is restarted.1 like
-
@soulfly I mean this in the most sincere way I can express this: I think you could really benefit from some online programming courses or something (maybe a community college near you?). At this point, you really should learn how to debug more thoroughly, and learn more about client-server architecture, data types, data structures, and networking. I think you could really use some online supplements to bridge the gaps you're experiencing. Especially with how long you've been interested in private server development for. Feel free to ignore this advice, but it may help unblock you with a lot of the work you want to accomplish.1 like
-
No, it's actually just removing some GUI configurations from the client and changing the GUI to a nostalgic theme. This isn't a lie, because I've also tried it, and it's feasible.1 like
-
I've got it running on Win11... basically u need VC6.0, DX81 libs and headers being loaded AFTER default system libraries and headers and some patience. If you import DX libs before default VC++ libs it will break into thousand errors on compilation. But Demons can be compiled and with some (a lot) effort it can be converted into an old CO client. But idk if its worth, maybe looking into it and converting to a newer DX would be better, but this requires a lot of changes since 8.1 doesnt use shaders and after 9 a lot of things are handled on shaders.1 like
-
I can't believe I made an account just to post this. I was planing on testing the Unknown flags at some point but I stopped working on the server altogether years ago. Good luck. [Flags] public enum MapFlagType : long { None = 0, PkField = 1L << 0, ChangeMapDisabled = 1L << 1, SaveLocationDisabled = 1L << 2, PlayerKillDisabled = 1L << 3, Vending = 1L << 4, TeamDisabled = 1L << 5, TeleportDisabled = 1L << 6, GuildWarMap = 1L << 7, PrisonMap = 1L << 8, FlyDisabled = 1L << 9, HouseMap = 1L << 10, Mining = 1L << 11, CallNewbieDisable = 1L << 12, RebornNowEnable = 1L << 13, NewbieProtect = 1L << 14, TrainingDisable = 1L << 15, Unknown16 = 1L << 16, Unknown17 = 1L << 17, RideDisable = 1L << 18, Unknown19 = 1L << 19, Unknown20 = 1L << 20, ArenicMap = 1L << 21, DoublePkMap = 1L << 22, Unknown23 = 1L << 23, Unknown24 = 1L << 24, RaceTrackMap = 1L << 25, Unknown26 = 1L << 26, FamilyArenicMap = 1L << 27, FactionPkMap = 1L << 28, ElitePkMap = 1L << 29, Unknown30 = 1L << 30, Unknown31 = 1L << 31, TeamPkArenicMap = 1L << 32, Unknown33 = 1L << 33, Unknown34 = 1L << 34, Unknown35 = 1L << 35, Unknown36 = 1L << 36, TeamArenaMap = 1L << 37, Unknown38 = 1L << 38, TeamPopPkMap = 1L << 39, AutoHangUpDisable = 1L << 40, Unknown41 = 1L << 41, Unknown42 = 1L << 42, Unknown43 = 1L << 43, ForbidCampMap = 1L << 44, GoldenLeagueMap = 1L << 45, JiangHuMap = 1L << 46, Unknown47 = 1L << 47, Unknown48 = 1L << 48, Unknown49 = 1L << 49, UseItemDisabled = 1L << 50, ReviveDisabled = 1L << 51, GarmentDisabled = 1L << 52, WeaponPassiveDisabled = 1L << 53, StaminaCostDisabled = 1L << 54 }1 like
-
That's fine. We should be adapting and building on other people's success. That's how we continue to grow the open source community for Conquer Online.1 like