Leaderboard
Popular Content
Showing most liked content since 12/31/2025 in all areas
-
Packet interception demonstration for Conquer Online using MinHook + ImGui overlay. This is a feature I posted in the ConquerDX9.Hook thread and people liked it, so I decided to make it a separate dedicated project. Features: Real-time packet interception (before encryption) Packet injection (client encrypts automatically) ImGui overlay interface (toggle with INSERT key) Packet history with hex dump Automatic character ID extraction How I found it: Found SendPacket (0x007414F0) in IDA. // Address: 0x007414F0 (Conquer Online client version 6609) int __fastcall SendPacket( void* thisPtr, // Network object (ECX register) void* edx, // Unused (EDX register) void* data, // Packet data (NOT encrypted!) int len // Packet size ) Note: This address (0x007414F0) is specific to Conquer Online client version 6609 only. Usage: Version 6609 (Proxy Method): Rename original Chat.dll to OChat.dll in game folder Copy compiled Chat.dll to the same folder Launch game (no injector needed) Press INSERT to toggle ImGui interface Building: • Visual Studio (Release & Win32) • Output: Release/Chat.dll Rep: git/cnthigu/conquer-packet-interceptor Please like the project on GitHub? Libraries: • MinHook (included) • ImGui (included) Note: This is an educational project and example implementation, as a student. Use your creativity, there's so much more that can be done! If this helps you in any way, please consider giving it a star on GitHub!!!.5 likes
-
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.5 likes
-
Let me answer you, because not everyone is as smart as you can find it, and most people will get it quickly by using money Therefore, we only need to pay attention to how and why we do it, and we ignore what others do.3 likes
-
Oh yeah sure , so you were only trying to market for your sales here2 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.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
-
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 base2 likes
-
Hi, actually, I know him, but I didn't make it so obvious, but we can't control him to do so. Therefore, I think that open source should be limited. We provide you with an idea, a framework and some foundations, and we can't let these people copy and paste them and sell them.2 likes
-
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 !2 likes
-
[Update] Packet Interceptor System - Real-Time Interception & Injection I've added a packet interceptor system to the project that enables real-time packet interception and injection via function hooking. Features: Real-time packet capture (before encryption) Packet injection (client encrypts automatically) In-game ImGui interface for packet visualization Packet history with hex dump Automatic character ID extraction How I found it: Found SendPacket (0x007414F0) in IDA. Starting from Winsock's send() function (known entry point) Tracing XREFs backwards: send() → encryption function → SendPacket Validated in x32dbg using call stack analysis By hooking this function, we can capture packets before they get encrypted. Technical Details: The function signature (from IDA pseudo-code): int __thiscall SendPacket( void* this, // Network object (ECX register) unsigned __int16* data, // Packet data (not encrypted!) size_t length // Packet size ) Key Insight: The client encrypts packets automatically after SendPacket. When we inject, we just call SendPacket with unencrypted data, no encryption code needed! Note: This was tested on client version 6609 only. The address (0x007414F0) is specific to this version. For other versions, you'll need to find SendPacket; Preview Video: [PREVIEW] Conquer Online Packet Interceptor - Intercept & Inject Packets in Real-Time This is still an educational project. Learning as I go, feedback welcome! Will post on GitHub soon.2 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!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
-
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-S1 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
-
Thank you so much @Spirited I knew that this GPT is gonna make me mad at some point! I'll just follow the instructions you have for the client downloads thread and comment there if I have any questions. Just try to be patient with my newbie questions ^^ Thanks,1 like
-
If something is open source and the license explicitly allows redistribution, I don’t see an issue with someone packaging it so less-experienced users can use it without having to compile or set everything up themselves. Also, it’s not fair to paint @darkfox as a bad actor. He has personally helped me multiple times without ever asking for anything in return. He also continues to maintain ConquerLoader, and in many cases he didn’t even take credit for large parts of it, instead properly crediting the original authors.1 like
-
Hey @carniato! Thank you so much for this really, and sorry for the late reply I got busy with work so didn't have further time to debug the issue further on my end, I will give this one a try and will update here with the results, I hope it works! And if it does I maybe could also create a PR with my logger so that for the future it's more robust to catch such issues Will update you soon! : )1 like
-
@xFranko Thanks for the detailed crash report! Based on your logs, it looks like a cleanup order issue during DLL unload - Font_CloseSys accessing freed memory. I couldn't reproduce it here, but I created a potential fix in the `v1.0.1-beta` branch: https://github.com/cnthigu/conquer-packet-interceptor/tree/v1.0.1-beta It adds proper cleanup order and exception handling. Not sure if it'll fix it since I can't test the crash scenario, but maybe it helps? Could you test and let me know? If it works, I'll merge to main. Thanks!1 like
-
Doing it yourself is much faster than waiting for others to update, isn't it? developer1 like
-
Exploits was earned based on event points. Example, you have earned 350 points from CTF, so you earned 350 exploits, but they had no use at all. 1. It released with a percentual BP for rankings, later it changed to 100% to every position: - From 5180 to around the release of the Dragon Warrior profession, there was a percentual based on the Shared BP. You can check this out here: Guide - Guild Introduction - Features - Conquer Online - Official Site - Later it changed and every position would earn 100% of the Shared BP You can choose. 2. Just need to be from another guild. I just don't know exactly the calculations, but you could award 1-3-5-10 points based on battle power difference 3. Guide donation was always 1. Every level 1 point.1 like
-
Hey, Found some screenshots from 2013 1. Your total donation 2. Exploit donations once was used for event score, probably TQ planned to use it to make a store or something related to event participation, I remember they were used on Guild Contest, Guild PK and CTF at some point in time but they had no use. 3. PK Donation, Guide Donation, Flower Donation, Arsenal donation are updated as you receive their points. PK Donation increases or decrease when you kill or be killed; Guide donation when you uplevel a Teammate from 1-70; Flower donation when you receive a Flower/Gift; Arsenal score when you inscribe or remove items from guild arsenal. 4. Donation history, it's everyone's total donation, not daily. (afair) 5. Guild ranks are history calculated on current donation. Ranks depend on total accumulated donations over time. All you need to do is hit the daily score and you would achieve, as of: https://gitlab.com/world-conquer-online/canyon/canyon/-/blob/main/src/Canyon.Game/States/Syndicates/Syndicate.cs?ref_type=heads#L2871 like
-
1 like
-
Thanks! It's really cool to see it working! Thanks! I'm organizing everything to post on GitHub soon. Just to clarify: it's actually a "packet interceptor" (not a proxy), it's a function hook that intercepts packets before encryption. Small technical difference! Finishing up the documentation. Should be on GitHub in a few days!1 like
-
I can't either. Someone unfortunately copied the old wiki and rehosted it. It's not mine to give people access to. I'm working on a new wiki, but it'll take some time. You can start contributing to it early though, if you'd like. I can send you a link. @Konichu I'll include you as well since you're still contributing to the current wiki.1 like
-
Hey all, A new feature has been added to the board! You can now become a donor to help keep the board running. To be clear, there's no danger in this board going away. However, there is an annual cost for maintaining our domain, hosting, and software license. When donating to the board, you help support these costs and our ability to keep the board up-to-date. You also gain access to the Donor tier, which comes with a few benefits: the purple username, increased message storage, an annual name change credit, a higher upload limit, and animated photo uploads for profile pictures. I'm open for feedback on these benefits, as well. To my surprise, it seems that quite a few of you have already discovered donations and tested the system on your own! Thank you very much for your support, it's very appreciated. I'll be adding more payment options and polish to the system over the coming week. Thanks again for all of your interest and support for our little board. Best, Spirited & Staff1 like
-
Hello everyone, I've been part of the Conquer Online community for many years, especially in Brazil. In the past, I attempted twice to run private servers in Brazil, reaching peaks of around 300 players online. At that time, however, I was still very inexperienced. I made many technical mistakes, relied on poor practices and sources, and after some time I couldn’t maintain proper support or long-term stability so I eventually stepped away from hosting. Since then, my relationship with Conquer has changed. Today, I work with Conquer purely for learning, experimentation, and fun. I use it as a way to practice programming, build features, and understand systems more deeply, without the pressure of monetization or running a live server. I currently have a YouTube channel where I teach people how to start and understand Conquer servers, and a small community of around 200 members. The goal has always been educational, helping people learn, not selling illusions. Professionally, I’m a junior developer working in a Blue Team environment, and I’m constantly studying security, systems, and performance. I started with C# through existing Conquer sources, and for the last few years I've been learning and improving in C++, especially in low-level and server-related concepts. I'm far from being an elite programmer, but I'm consistent, curious, and always evolving. What really motivates me about this project is the long-term vision. In Brazil, the Conquer community is extremely underserved most servers are short-lived, scam-oriented, and poorly managed, with owners focused only on quick profits instead of quality, stability, and respect for players. I would be very interested in being part of this team, contributing where I can development, tooling, testing, features, documentation. More than anything, I want to be part of something serious, transparent, and future-oriented, built by a responsible team that actually cares about the community. Thank you for reading, and I wish success to the project regardless1 like
-
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