qDiv-111.S is the latest stable Version

Client Downloads

Linux
Windows

Server Downloads

Linux
Windows

Source Code

qDiv-111.zip
qDiv-103.zip
qDiv-97.zip
qDiv-92.zip
qDiv-74.zip

What is qDiv?

qDiv is a free and open source 2D sandbox game with a topdown perspective. The objective is directly dependant on which of the 6 roles one plays, each representing a different playstyle. Progression is achieved by increasing ones qEnergy and fulfilling criteria in order to unlock artifacts, such as mining bronze to unlock a bronze shortsword.

How to play qDiv

Start by downloading qDivClient for your respective platform and open it. On Windows your anti-virus may complain, this will be fixed at a later date. If you're concerned about qDiv being malicious, feel free to inspect the source code and compile it yourself, you may need to use WSL for this though.
Once qDivClient is open, click "Settings" and right click the top prompt. Enter the username you'd like to play with, then exit settings by pressing the "Escape" Key. Now click "Play", you'll be met with a bunch of empty prompts, right click one of the prompts to enter a server address, then left click to join that server.
Once you're in the server, you can start making progress.
Here's a list of the controls:

From the last point you may be wondering, what are Artifacts? On the top left of your screen there should be a slot with a Pickaxe inside it, click that slot to get to the Artifact Menu. Artifacts are items that are used to achieve certain goals, Pickaxes are used to break blocks for example. To unlock Artifacts, you need to meet certain Criteria. To view these as well as a short description of what the Artifact does, right click it. Each Artifact belongs to one of 6 roles. To select an Artifact as well as it's respective Role, left click it. Here's a list of the roles in qDiv: WARNING

If you select a different role to the one you currently have selected, you won't be able to switch back for a while!


The first thing you'll want to do is collect the most important resource of qDiv, that being qEnergy.
qEnergy is a score, progress indicator and even a second health bar all at the same time. The amount of qEnergy you currently have is displayed on the bottom left of your screen. The primary way to obtain it is by mining, whether or not some block can give you qEnergy is indicated by the block selection at your cursor and changes as you get more. The selection is green if it can give you qEnergy and red if it can't, the displayed number is how much qEnergy the block has. For the nerds of you who want to fully understand what this value means, here is a formula where P is the qEnergy of the Player and B is the qEnergy of the Block.
Block gives qEnergy if: B <= max(P, 100) && B > P * 0.8
Some Artifacts (such as Spells) may consume qEnergy. As I previously hinted at, it also depletes when something hurts you. Please note that the value you see on the bottom left is different to the criterion "qEnergy", it differs in the sense that it represents the maximum amount you've ever had rather than the current amount. Over time it may become evident that there are a bunch of blocks that have very high qEnergy none of which you can get any from. By the time you reach 100 qEnergy, it's time to locate a Redwood Forest (as can be seen in the background image above) as that is where you'll find cavern entrances that look like black holes. Also make sure to get enough wood for lamps, these are able to provide light in the dark caverns but keep in mind that they need to be relit with qEnergy by interacting with them every 10 minutes. Now that you're in the caverns, you need to find metals to progress. The order is as follows: The afore mentioned metals vary in rarity, though none of them should take too long to find (unless you're me you took 2 hours to find Iron). There is really not much else to do down there.

To be continued

How to modify qDiv

In order to modify qDiv, any instance of Linux is required. If your computer runs Windows, you may consider using WSL. Now download the source code of qDiv to your Linux instance and extract the zip archive.
qDiv is compiled by running the bash script "compile.sh", but only if you have the following installed:

If you have everything installed and I didn't mess up this instruction, compilation should now succeed.

Source Structure

Here's a list of what every file in the source code does.

And here are some utility functions that may come in handy for your modding adventure. Where "entitySelf" refers to the entity of the client user and "Locals" refers to the 9 chunks that surround entitySelf. It is very likely this section is out of date.

Client

void localPositions();
Applies Field Coordinates to Locals.

bool hoverCheck(float minX, float minY, float maxX, float maxY);
Checks if the Mouse Cursor is within the square specified by minX, minY, maxX and maxY. If it is, the function returns true.

void screenToBlock(float inX, float inY, int32_t* outX, int32_t* outY, int32_t* lclX, int32_t* lclY);
Converts the cursor coordinates inX and inY to a block with the block coordinates *outX and *outY and *lclX and *lclY relative to the bottom left Local.

void fillVertices(float* restrict meshIQ, int32_t vertexSL, float posX, float posY, float posXP, float posYP);
void fillHorizontal(float* restrict meshIQ, int32_t vertexSL, float posX, float posY, float posXP, float posYP);
Fills the buffer of type "float" pointed to by meshIQ with a graphical primitive. posX is the left side, posY is the bottom side, posXP is the right side and posYP is the top side of the primitive.
The horizontal variation is rotated by 90° clockwise.

void setAtlasArea(float inX, float inY, float inSize);
Sets the texture coordinates of the main vertex buffer. inX and inY specify the bottom left of the cutout whereas inSize specifies how far up and right the cutout should reach.

void void loadTexture(uint32_t *texture, element_t* file);
Loads file as a texture into texture so it can be bound and rendered throughout runtime.

color_t getLocalLight(int32_t lclX, int32_t lclY, int32_t posX, int32_t posY);
Reads Block Lighting at from the block coordinates posX and posY and lclX and lclY relative to the bottom left Local.

void renderText(int8_t* restrict textIQ, float initX, float initY, float chSC, int32_t typeIQ);
Renders textIQ with a character size of chSC. If typeIQ is TEXT_LEFT, initX and initY will be where the text starts rendering, if typeIQ is TEXT_RIGHT, initX and initY will be where the text stops rendering, if typeIQ is TEXT_CENTER, the text will be centered around initX and initY.

void spawnParticle(qint_t identity, float parameter, float posX, float posY);
Spawns a particle at posX and posY relative to where the player is. Identity determines how the particle renders, the meanings of this value can be looked up in elements/shaders/particleVS.glsl and elements/shaders/particleFS.glsl. The meaning of parameter is determined by identity.

bool hasEffect(qint_t effectSL);
Checks whether or not entitySelf has the effect effectSL. If it does, the function returns true.

void applyFlicker(float damageTM);
Used for Entity coloration in response to its damage immunity value (entity_t.damageTM) being greater than 0. The coloration is determined by damageTM and the current role of entitySelf.

bool qri_RenderButton(float posX, float posY, float scale, int32_t length, int8_t* textIQ);
Renders a clickable button at posX and posY with a size of scale and a length of length. textIQ is rendered in the center of the button. The function returns true if the button was clicked.

bool qri_RenderPrompt(float posX, float posY, float scale, int32_t length, int8_t* textIQ, size_t lengthIQ);
Renders a text prompt at posX and posY with a size of scale and a length of length (+1 if you include the Enter button). textIQ is rendered to the left of the prompt and is required not to be constant. lengthIQ specifies how much text is allowed to be entered into the prompt. The function returns true if the Enter key or the Enter button is pressed.

void qri_RenderSlider(qint_t identity, float posX, float* value, int8_t* textIQ, int8_t* textVL);
Renders a slider at X position posX. identity is used to keep track of whether or not the slider is being set. textIQ is rendered centered above the slider. value is a pointer that retrieves the slider setting, it reaches the values 0.0 to 1.0 and textVL can be used to render an appropriate translation of that value depending on the usecase.

int32_t screenToArtifact();
Returns the numeric ID of the artifact currently being hovered in the Artifact Menu

uint32_t makeShaderProgram(int8_t* alias, uint32_t* vertexIQ, uint32_t* fragmentIQ, element_t* vertexSC, element_t* fragmentSC);
Compiles vertexSC to a vertex shader pointed to by vertexIQ and compiles fragmentSC to a fragment shader pointed to by fragmentIQ. These shaders are then linked into a shader program that the function returns. alias is used to identify shaders that failed to compile.

void createGenericBuffer(uint32_t* arrayIQ, uint32_t* bufferIQ, float* vertexIQ, size_t vertexSZ);
Creates a Vertex Array pointed to by arrayIQ and a Vertex Buffer pointed to by bufferIQ. Those use vertexIQ as their vertex data and vertexSZ is the size of that data.

Server

void syncEntityRemoval(int32_t slot);
Notifies all nearby clients that the entity pointed to by entity + slot no longer exists.

void streamPrint(int8_t* textIQ);
Writes textIQ to the Stream.

void triggerEvent(qint_t eventSL, qint_t zone, int32_t fldX, int32_t fldY, float posX, float posY);
Triggers eventSL in zone at fldX, fldY, posX and posY.

int32_t getFieldSlot(qint_t inZone, int32_t inFldX, int32_t inFldY);
Gets the slot of the field located in inZone at inFldX and inFldY. If the field is not in memory, the function returns -1, if the field is loaded, the function returns its slot, if the field is in memory despite being unloaded, it returns settings.MAX_FIELDS + its slot.

void collapseEntityList(entityList_t** listST);
Collapses an Entity List pointed to by listST.

static inline void removeEntity(entity_t* entityIQ);
Removes an entity pointed to by entityIQ.

void removePlayer(entity_t* entityIQ);
Removes an entity pointed to by entityIQ, then saves its player data.

void knockEntityBack(entity_t* entityIQ, entity_t* entityTG);
Knocks back an entity pointed to by entityTG according to the current movement speed of the entity pointed to by entityIQ.

static bool hasEffect(entity_t* entityIQ, qint_t effectSL);
Checks whether or not the entity pointed to by entityIQ has the effect effectSL. If it does, the function returns true.

void teleportEntity(entity_t* entityIQ, qint_t zone, int32_t fldX, int32_t fldY, float posX, float posY);
Teleports the entity pointed to by entityIQ to zone at fldX, fldY, posX and posY.

void setBlock(qint_t blockSL, field_t* fieldIQ, int32_t posX, int32_t posY, int32_t layer);
Sets the block at posX and posY on layer in fieldIQ to be blockSL.

uint64_t getDefenseProfile(entity_t* entityIQ, qint_t subType);
The function returns how much decay the entity pointed to by entityIQ is able to resist from the Damage Type subType. If the function returns IMMUNE, the damageEntity() function will not only not decay the entity but it also won't take any damage, which would happen in every other circumstance.

bool damageEntity(entity_t* entityIQ, bool multiFactor, uint64_t decay, qint_t subType);
Decays the entity pointed to by entityIQ of decay qEnergy with a Damage Type of subType. If multiFactor is true, the entity will also take damage, unless it still has immunity frames. The function returns true if the entity dies.

bool performPlayerAttack(entity_t* entityAT, entity_t* entityIQ, uint64_t decay, qint_t subType);
Runs damageEntity(entityIQ, true, decay, subType). entityAT points to the entity of the attacking player and is used for player specific postprocessing.

bool qEnergyConsume(uint64_t energyIQ, entity_t* entityIQ);
Attempts to have the entity pointed to by entityIQ consume energyIQ qEnergy. The function returns true if the consumption was unnecessary or successful and false if the entity does not have enough qEnergy.

uint64_t qEnergyAmount(entity_t* entityIQ, block_st* blockIQ);
Returns the amount of qEnergy an entity pointed to by entityIQ will get if it mines a block with the shared block type blockIQ.

bool isEntityPresent(entity_t* entityIQ, int32_t fldX, int32_t fldY, float posX, float posY);
Checks whether or not an entity pointed to by entityIQ is present at fldX, fldY, posX and posY.

bool isEntityPresentInRange(entity_t* entityIQ, int32_t fldX, int32_t fldY, float centerX, float centerY, float range);
Checks whether or not an entity pointed to by entityIQ is present in a square with a side length of range * 2 around the field coordinates fldX and fldY and the block coordinates centerX and centerY.

void applyEffect(entity_t* entityIQ, qint_t effectSL, float duration);
Applies the effect effectSL to an entity pointed to by entityIQ for duration seconds.

bool isEntityObstructed(entity_t* entityIQ, int32_t direction);
Checks if an entity pointed to by entityIQ is able to move further in direction.

static inline float getSpeed(entity_t* entityIQ);
Returns how fast an entity pointed to by entityIQ would move if it did.

bool astar_interpretPath(entity_t* entityIQ, astar_path_t* pathIQ);
Moves an entity pointed to by entityIQ along pathIQ. Returns false if the destination of pathIQ was reached.

bool astar_findPath(entity_t* entityIQ, astar_path_t* pathIQ, int32_t range, int32_t endX, int32_t endY);
Calculates the fastest route to endX and endY relative to the bottom left of the bottom left Local of the entity pointed to by entityIQ. The search will only run within range blocks. If a path has successfully been traced, the function returns true.

void astar_resetPath(astar_path_t* pathIQ);
Resets the path pointed to by pathIQ.

void ambientMovement(entity_t* entityIQ);
Randomly moves an entity pointed to by entityIQ.

entity_t* getTargetInRange(entity_t* entityIQ, float range);
Searches for a random player that is up to range blocks away from an entity pointed to by entityIQ. Players capable of combat are prioritized.

int32_t spawnEntity(int8_t* name, uint8_t* uuid, qint_t subType, qint_t zone, int32_t fldX, int32_t fldY, float posX, float posY);
Spawns an Entity named name with a uuid of uuid, the type subType in zone at fldX, fldY, posX and posY. If uuid is not NULL, the function will attempt to read the entity from a file. The values of modded entity subtypes are not initialized by default. The function returns the slot of the spawned entity or -1 if it failed to spawn.

int32_t spawnEntity(int8_t* name, uint8_t* uuid, qint_t subType, qint_t zone, int32_t fldX, int32_t fldY, float posX, float posY);
Spawns an Entity named name with a uuid of uuid, the type subType in zone at fldX, fldY, posX and posY. If uuid is not NULL, the function will attempt to read the entity from a file. The values of modded entity subtypes are not initialized by default. The function returns the slot of the spawned entity or -1 if it failed to spawn.

Shared

void send_encrypted(uint8_t prefix, void* payload, size_t payloadSZ, client_t* clientIQ);
Sends the payloadSZ bytes pointed to by payload with a packet prefix of prefix to clientIQ in encrypted form.

void byteToHex(uint8_t* byte, size_t byteSZ, int8_t* hex, size_t hexSZ);
Converts an array of bytes pointed to by byte with a size of byteSZ to a null terminated string of hexadecimal numbers pointed to by hex with a size of hexSZ. Memory needs to be allocated in advance for byte and hex. hexSZ must be (byteSZ * 2) + 1 for the function not to fail.

void hexToByte(int8_t* hex, size_t hexSZ, uint8_t* byte, size_t byteSZ);
Converts a null terminated string of hexadecimal numbers pointed to by hex with a size of hexSZ to an array of bytes pointed to by byte with a size of byteSZ. Memory needs to be allocated in advance for byte and hex. hexSZ must be (byteSZ * 2) + 1 for the function not to fail.

bool isEntityLocal(entity_t* entityIQ, entity_t* entityAS);
Checks whether or not an entity pointed to by entityIQ is up to one field away from an entity pointed to by entityAS.

int32_t getOccupiedLayer(uint16_t* blockPos);
blockPos points to two blocks on layer 0 and 1 respectively. The function returns the highest layer on which there is a block, it thus returns -1 if there is no block on layer 0 or 1.

uint32_t getPortDistance(entity_t* entityIQ);
Returns how far away the entity pointed to by entityIQ is from its Portstone.

bool isArtifactUnlocked(int32_t roleSL, int32_t artifactSL, player_t* playerIQ);
Checks whether or not the player partially pointed to by playerIQ is able to switch to the artifact with a corresponding role of roleSL and a numeric ID or artifactSL. If it is, the function returns true.

bool inGroup(int32_t elementIQ, group_st* groupIQ);
Checks whether or not elementIQ is in groupIQ. If it is, the function returns true.

Audio

void playSound(element_t* file, float relPosX, float relPosY);
Plays a sound from file at relPosX and relPosY relative to entitySelf.

void playMusic(element_t* file);
Plays music from file. It is not safe to run this while music is still playing.

Actions

These are function pointers, it is therefore more important to know when they are called than what they do. effect_st.main
Runs every tick on every entity that has the effect.

effect_st.init
Runs on every entity that the effect is applied to.

entity_st.main
Runs every tick on every entity with that subtype.

entity_st.collision
Runs on any entity with that type that slamms into a wall.

entity_st.renderer
Runs every frame on every entity with that subtype. This action is client specific.

block_st.main
Runs every second on every block with that subtype.

block_st.usage
Runs on every block with that type that a player interacts with.

block_st.stepOn
Runs on every block with that type that an entity steps on.

artifact_st.primary.main
Runs every tick on every player that uses the primary action of the artifact.

artifact_st.secondary.main
Runs every tick on every player that uses the secondary action of the artifact.

Changelog

qDiv-111.S

qDiv-103.S

qDiv-97.S

qDiv-92.S

qDiv-74.S