IdleQuest is an idle/incremental game based on EverQuest, the iconic MMO released in 1999. Designed to progress on its own, players interact by making strategic choices to determine how the game plays out in an automated way. The goal is to recreate as much of the original EverQuest experience as possible using a database dump from the EverQuest emulator (EQEmu) project, which itself is data from scraping the original game. This data, rooted in the original game, allows for a nostalgic and detailed exploration of EverQuest’s world in a more casual, low commitment way.
The game content and mechanics are as true to the original experience as can be reasonably done with a single developer - the interface, classes, races, zones, items, NPCs, loot drops, skills, spells, etc are all very close to original EverQuest content. It has, so far, implemented ChatGPT-based questing with over 5000 NPCs to exchange dialogue with, 26000 items, 16000 NPCs, 185 zones, and 3900 spells. It's incremental/idle combat based system also accurately drops loot for 20000+ spawns, with items and probabilities true to the original EverQuest experience.
Though there may be implementation of 3D graphics in the future, the current focus on this project is text-based adventuring with some visual aids. EverQuest was originally created from the era of MUDs (multi-user dungeons) which were basically EverQuest without graphics. It's fun to now return to the MUD heritage of the game, but with the addition of LLMs for dynamic quests, dialogue, and storytelling.
I would like to give credit to Eric Fredricksen, the creator of ProgressQuest from 2002, which is also interestingly the example project used for the "idle games" article on Wikipedia. Though ProgressQuest is much simpler in nature and doesn't contain content from the real game, I want to recognize that this isn't a wholly original idea on my behalf, and I have fond memories of playing ProgressQuest 20+ years ago.
This project is very much in its early phase, and the casual nature of the README and documentation reflect this.
This project is built using React/TypeScript and Zustand. Long term this will probably transition to having a RESTful API backend but is currently all running locally off a SQLite database.
To run it:
pnp run dev
There is also an assortment of one-off scripts in the /data folder, for example:
python ./data/add_table_to_db_from_csv.py
as needed, but also don't do this bc it makes all fields text values
The data in the SQLite file is fairly comprehensive at this point though, so it is unlikely much more data import work will need to be done.
- https://docs.eqemu.io/schema/characters/char_create_combinations/ (and other pages)
- https://github.com/EQEmu/Server
- UI examples for classic character creation: https://www.youtube.com/watch?v=EjWDRHu9mhU
- Every NPC photo here, though with Luclin graphics: https://mqemulator.net/npc.php?id=174250
- Lots of NPC descriptions here: https://wiki.project1999.com/Biggle_Limbokker (look for h3 containing "Description" then look for contenst of the next
)
- Really good NPC descriptions here but URL isn't easy to use for automated retrieval: https://www.giantbomb.com/brutol-rhaksen/3005-19742/
- Info on stats: https://wiki.project1999.com/Mana#Primary_Stats
TLDR: NPCs have a loottable ID, loottables have lootdrops, lootdrops have items.
-
NPCs: Characters not controlled by players. Each has a
loottable_id
determining potential item drops. -
loottable: Lists possible item sets an NPC can drop. Each row is a unique set identified by an id.
-
loottable_entries: Links loot tables to items. Each row represents a possible item drop, connecting
loottable_id
tolootdrop_id
. -
lootdrop: Represents collections of items that can be dropped together. Each row is a unique collection.
-
lootdrop_entries: Links loot drops to actual items. Each row represents an item in a loot drop, connecting
lootdrop_id
toitem_id
.
- Check NPC's
loottable_id
- Find matching rows in
loottable_entries
- For each row, check
lootdrop_id
- Find matching rows in
lootdrop_entries
- Use
item_id
to identify actual items
This structure allows for flexibility, enabling multiple NPCs to share loot tables and multiple loot tables to include the same loot drops.
Example SQL Query:
SELECT items.
FROM items
INNER JOIN lootdrop_entries ON items.id = lootdrop_entries.item_id
INNER JOIN loottable_entries ON lootdrop_entries.lootdrop_id = loottable_entries.lootdrop_id
INNER JOIN npc_types ON loottable_entries.loottable_id = npc_types.loottable_id
WHERE npc_types.id = #;
The NPC spawn system is managed through three SQL tables originally named: spawngroup
, spawn2
, and spawnentry
.
I've renamed "spawn2" to "spawnlocation" because the name makes much more sense.
-
Define a spawngroup (spawngroup table)
- Assign a unique ID
- Give the spawngroup a name
-
Add mobs to the spawngroup (spawnentry table)
- Specify the spawngroup ID
- Add NPC IDs
- Set spawn chances for each NPC
-
Specify spawn locations (spawnlocation table)
- Link to the spawngroup ID
- Set zone and coordinates
- Configure respawn time and other parameters
-
Create spawngroup
INSERT INTO spawngroup (id, name) VALUES (1, 'Plane of Disease Rats');
-
Add mobs to spawngroup
INSERT INTO spawnentry (spawngroupID, npcID, chance) VALUES (1, 40010, 20), -- a_diseased_rat lvl 50 (1, 40011, 20), -- a_diseased_rat lvl 51 (1, 40012, 10), -- a_diseased_rat lvl 52 (1, 40020, 25), -- a_swamp_rat lvl 52 (1, 40021, 25); -- a_swamp_rat lvl 54
-
Set spawn locations
INSERT INTO spawnlocation (id, spawngroupID, zone, x, y, z, heading, respawntime) VALUES (1, 1, 'podisease', 1000, 10, 100, 0, 120), (2, 1, 'podisease', 500, 500, 100, 0, 120);
variance
in spawnlocation adds randomness to respawn time, useful for boss monsters.pathgrid
in spawnlocation sets a movement path for spawned NPCs.timeleft
in spawnlocation is used by the game to track respawn timers.
(from simple boilerplate this project started from)
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- @vitejs/plugin-react uses Babel for Fast Refresh
- @vitejs/plugin-react-swc uses SWC for Fast Refresh
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
- Configure the top-level
parserOptions
property like this:
export default tseslint.config({
languageOptions: {
// other options...
parserOptions: {
project: ["./tsconfig.node.json", "./tsconfig.app.json"],
tsconfigRootDir: import.meta.dirname,
},
},
});
- Replace
tseslint.configs.recommended
totseslint.configs.recommendedTypeChecked
ortseslint.configs.strictTypeChecked
- Optionally add
...tseslint.configs.stylisticTypeChecked
- Install eslint-plugin-react and update the config:
// eslint.config.js
import react from "eslint-plugin-react";
export default tseslint.config({
// Set the react version
settings: { react: { version: "18.3" } },
plugins: {
// Add the react plugin
react,
},
rules: {
// other rules...
// Enable its recommended rules
...react.configs.recommended.rules,
...react.configs["jsx-runtime"].rules,
},
});
Similar to ProgressQuest, this project falls under fair use because it transforms elements of the original EverQuest game for a different purpose—an idle game experience rather than an active MMORPG. It does not replicate the gameplay mechanics or experience in a 1:1 manner but instead serves as a commentary and nostalgic parody of EverQuest’s legacy, which fits within the definition of transformative use. Additionally, IdleQuest is non-commercial, and the use of EverQuest’s content is limited and for purposes that add new meaning, context, and value.
Many game elements and assets are owned by Daybreak Game Company LLC. This project has no affiliation with them and probably no one else either.
This project uses a slightly modified very cool dice library which also has its own credits to previous works.
This project includes code licensed under the MIT License, which I'm including here because I think it's what I'm supposed to do?
The MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.