====== Non-Java Modding Techniques ======
Remixed Dungeon provides extensive modding capabilities without requiring Java programming knowledge. This guide covers all the non-Java modding techniques you can use to create modifications.
===== Resource Override Modding =====
The simplest type of modding involves replacing game resources directly.
==== Sprite Replacement ====
* Locate original sprites in the assets directory
* Create new sprites with the same dimensions and format
* Place them in the same directory structure in your mod folder
Example directory structure:
MyMod/
├── sprites/
│ ├── items/
│ │ ├── weapon/
│ │ │ ├── sword.png (your custom sword sprite)
│ │ │ └── dagger.png (your custom dagger sprite)
│ │ └── armor/
│ │ └── armor.png (your custom armor sprite)
│ └── mobs/
│ └── rat.png (your custom rat sprite)
└── version.json
==== Sound and Music Replacement ====
* Replace sound effects by placing new files in ''sounds/'' directory
* Replace background music by placing new files in ''music/'' directory
* Keep the same filenames to ensure the game loads your replacements
==== Text and Localization ====
* Modify game text by creating ''res/values/strings.json'' with string overrides
* Add new languages by creating ''res/values-[lang-code]/strings.json''
* Format: {"original_key": "your_new_text"}
===== JSON-Based Modding =====
JSON files control most game content and mechanics in Remixed Dungeon.
==== Item Modding ====
Create custom items by defining them in JSON files:
{
"class": "com.watabou.pixeldungeon.items.weapon.melee.Sword",
"name:en": "Flaming Sword",
"name:ru": "Пылающий меч",
"desc:en": "This sword is engulfed in magical flames that burn enemies.",
"desc:ru": "Этот меч окутан магическим пламенем, которое сжигает врагов.",
"damageMin": 8,
"damageMax": 15,
"imageIndex": 5,
"AC": "ATTACK",
"script": "items/flaming_sword.lua",
"onHit": "onHit"
}
==== Mob Modding ====
Create or modify creatures:
{
"class": "com.watabou.pixeldungeon.actors.mobs.Rat",
"name:en": "Fire Rat",
"HP": 20,
"damageMin": 5,
"damageMax": 10,
"defenseSkill": 5,
"exp": 3,
"loot": "gold",
"lootChance": 0.5,
"properties": ["hostile", "small"],
"onDeath": "fire_explosion",
"imageIndex": 3
}
==== Level Modding ====
Design custom levels using JSON:
{
"name": "Custom Level",
"width": 32,
"height": 32,
"map": [
"################################",
"#..............................#",
"#..............................#",
"################################"
],
"mobs": [
{
"class": "com.watabou.pixeldungeon.actors.mobs.Rat",
"x": 10,
"y": 10
}
],
"items": [
{
"class": "com.watabou.pixeldungeon.items.Gold",
"x": 15,
"y": 15,
"quantity": 50
}
]
}
==== Dungeon Structure ====
Modify how levels connect by editing ''levelsDesc/Dungeon.json'':
{
"connections": [
{"from": 1, "to": 2},
{"from": 2, "to": 3}
],
"branches": [
{"level": 3, "branch": "sewers"}
]
}
===== Lua Scripting =====
Lua scripts provide dynamic behavior without Java coding.
==== Basic Lua Structure ====
local RPD = require "scripts/lib/commonClasses"
local item = require "scripts/lib/item"
local M = {}
return item.init{
desc = function()
return {
image = 0,
imageFile = "items.png",
name = "Custom Item Name",
info = "Custom Item Description",
stackable = false,
upgradable = true,
isFlies = false,
defaultAction = "Custom Action Name"
}
end,
-- Function that can be called from JSON
execute = function(self, item, hero, action)
if action == "Custom Action Name" then
-- Add fire damage
RPD.affectBuff(hero, RPD.Buffs.Burning, 3) -- Apply burn for 3 turns
RPD.glog("The item burns you!")
end
end
}
==== Correct Lua Functions ====
* ''target:damage(amount, source)'' - Deal damage to a target (e.g., victim:damage(10, caster))
* ''target:heal(amount, source)'' - Heal a target (e.g., target:heal(5, caster))
* ''RPD.affectBuff(target, buffClass, duration)'' - Apply a buff/debuff to a target
* ''RPD.permanentBuff(target, buffClass)'' - Apply a permanent buff to a target
* ''RPD.removeBuff(target, buffClass)'' - Remove a buff from a target
* ''RPD.glog(message)'' - Display a message in game log
* ''RPD.spawnMob(className, cell, mobDesc)'' - Create a new mob at a cell location
* ''RPD.item(itemClass, quantity)'' - Create an item
* ''RPD.GameAction'' - Check if currently in game (not in menu)
* ''RPD.GameLoop.currentTurn'' - Current turn count
* ''RPD.Dungeon.level()'' - Current level object
* ''RPD.Dungeon.hero'' - Player character
* ''RPD.Dungeon.level():mobs()'' - All mobs on current level
* ''RPD.Dungeon.level():cell(x, y)'' - Cell at coordinate
* ''RPD.Dungeon.level():distance(pos1, pos2)'' - Distance between positions
* ''RPD.Terrain.WALL'', ''RPD.Terrain.EMPTY'', etc. - Terrain constants
* ''RPD.Blobs.Fire'', ''RPD.Blobs.Water'', etc. - Environmental effects
* ''math.random()'' - Generate random number (use instead of G.chance())
==== Item Scripts ====
local RPD = require "scripts/lib/commonClasses"
local item = require "scripts/lib/item"
return item.init{
desc = function()
return {
image = 1,
imageFile = "items.png",
name = "Explosive Item",
info = "An explosive item that damages enemies.",
stackable = false,
upgradable = false,
isFlies = true,
defaultAction = "EXPLODE"
}
end,
actions = function()
return {RPD.Actions.EXPLODE}
end,
-- Called when item is used
execute = function(self, item, hero, action)
if action == RPD.Actions.EXPLODE then
local level = RPD.Dungeon.level()
local cell = hero:getPos()
-- Damage all creatures in radius
local mobs = level:mobs()
for i = 0, mobs:size()-1 do
local mob = mobs:get(i)
if level:distance(mob:getPos(), cell) <= 2 then
mob:damage(10, hero) -- Damage mob, source is hero
RPD.glog("Explosion damages " .. mob:name() .. "!")
end
end
-- Also damage the hero slightly
hero:damage(5, item) -- Source is item itself
RPD.glog("The explosion hurts you too!")
end
end
}
==== Mob Scripts ====
local RPD = require "scripts/lib/commonClasses"
local mob = require "scripts/lib/mob"
return mob.init{
spawn = function(self, level)
-- Called when the mob is created
RPD.glog("A healing mob appears!")
end,
act = function(self)
-- Called each turn when mob is active
local hero = RPD.Dungeon.hero
local distance = RPD.Dungeon.level():distance(self:getPos(), hero:getPos())
if distance <= 2 then
-- Heal the mob
self:heal(5, self) -- Heal 5 HP, source is mob itself
RPD.glog("The healing mob glows softly!")
end
-- Spend time for this turn
self:spend(1)
end,
-- Called when mob is attacked
onAttackProc = function(self, enemy, damage)
-- Chance to counter-attack
if math.random() < 0.3 then -- 30% chance
enemy:damage(5, self) -- Damage attacker, source is this mob
end
return damage
end,
die = function(self, cause)
-- Handle death
RPD.glog("The healing mob fades away.")
end
}
==== Buff Scripts ====
local RPD = require "scripts/lib/commonClasses"
local buff = require "scripts/lib/buff"
return buff.init{
desc = function()
return {
icon = 10,
name = "Custom Buff Name",
info = "Custom buff description with %d turns remaining."
}
end,
attach = function(self, target)
-- Called when buff is applied
RPD.glog("You feel different...")
return true
end,
act = function(self)
-- Called each turn while buff is active
if math.random() < 0.1 then -- 10% chance per turn
self.target:heal(1, self.target) -- Heal 1 HP occasionally, source is target itself
end
-- Continue for another turn
return true
end,
detach = function(self)
-- Called when buff is removed
RPD.glog("The effect fades...")
end
}
===== Tiled Level Editor =====
Create complex custom levels using the Tiled map editor:
==== Getting Tiled ====
* Download Tiled from https://www.mapeditor.org/
* Use the custom Tiled extension provided with Remixed Dungeon
==== Level Structure ====
* Create a new tilemap with the correct dimensions
* Use the original tilesets as a base or create new ones
* Place special objects for spawns, items, and exits
* Export as JSON format for use in the game
==== Object Types ====
* ''mob_spawn'' - Places a mob at the location
* ''item_spawn'' - Places an item at the location
* ''exit'' - Level exit point
* ''entrance'' - Level entrance point
* ''feature'' - Special level features
===== Configuration Files =====
==== version.json ====
{
"version": 1,
"name": "My Mod",
"author": "Your Name",
"description": "A brief description of your mod",
"requiredCoreVersion": "32.0",
"dependencies": ["required_mod_name"]
}
==== Bestiary Configuration ====
Control what mobs appear where:
{
"level_1": [
{"class": "com.watabou.pixeldungeon.actors.mobs.Rat", "weight": 10},
{"class": "com.watabou.pixeldungeon.actors.mobs.Gnoll", "weight": 5}
],
"level_5": [
{"class": "com.watabou.pixeldungeon.actors.mobs.Swarm", "weight": 8},
{"class": "com.watabou.pixeldungeon.actors.mobs.Eye", "weight": 3}
]
}
===== Tips for Successful Non-Java Modding =====
==== Planning Your Mod ====
* Start with simple resource swaps before moving to complex JSON configurations
* Look at existing game files as examples for your own
* Test frequently to avoid accumulating errors
* Keep backups of working configurations
==== File Organization ====
* Follow the same directory structure as the original game
* Use clear, descriptive names for your files
* Group related content in subdirectories
* Document complex mods with a README file
==== Testing and Debugging ====
* Enable your mod in-game and start a new game to test
* Check the game's log files for errors if something doesn't work
* Test on multiple save files to ensure compatibility
* Use simple test cases before implementing complex features
==== Community Resources ====
* Share your work on the Remixed Dungeon Discord server
* Look at other mod authors' work for inspiration and techniques
* Collaborate with other modders for complex projects
* Report bugs or request features through the official channels
With these techniques, you can create extensive modifications to Remixed Dungeon without writing a single line of Java code!