full rename

rename of folder, subfolders and main.py
This commit is contained in:
2026-09-28 09:47:18 +02:00
parent ac40f2176b
commit 17d4e9cdf3
57 changed files with 41 additions and 13 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

+133
View File
@@ -0,0 +1,133 @@
# Light & Dark — Prototype
A 2D platformer built with **Pygame**. You switch between two forms — **Light** and **Shade** — each with different movement, combat, and ability behavior, all driven by a single shared resource: **Charge (Flow)**.
> Note: this is a prototype. All progress (quests, boss tokens, broken walls, defeated bosses) is **in-memory** and resets when you restart the game — intentional, for fast testing.
---
## Running the game
```
python main.py
```
Requires Python 3.10+ and `pygame`. Game data (rooms, items, sets, enemies, drops) lives in `data/`. Rooms are edited with the included browser tool: `level_editor_v43.html`.
---
## Controls
| Action | Key |
|---|---|
| Move | A / D |
| Jump | W |
| Move down / drop | S |
| Heal | Space (hold) |
| Melee attack | E |
| Ranged shot | Q |
| Dash | Tab |
| Shatterstep | R |
| Tether | X |
| Reality Break | C |
| Toggle Light/Shade | Left Shift |
| Interact / Talk | F |
| Inventory | I |
| Stats overlay | H |
| Pause / Settings | Esc |
---
## The two forms
**Light** — faster movement, higher jump, and charge **refills** over time. You take contact damage from enemies.
**Shade** — slower but tanky: **immune to enemy contact damage**, deals double melee damage, and can use shade-specific gear bonuses. But being in Shade **drains Charge** (and Shade is forced off when Charge hits 0). Shade also drains Charge **twice as fast while clipping inside an enemy**.
**Charge (Flow)** — base max 100, refills at 20/s in Light, drains at 40/s in Shade. Standing near a **lantern/light source** doubles Charge regeneration. Attacks, dash (Light), ranged shots, and healing all cost Charge.
---
## Abilities (by form)
| Ability | Key | Light | Shade |
|---|---|---|---|
| **Melee** | E | 1 damage, costs 1 Charge | **2 damage**, costs 1 Charge |
| **Dash** | Tab | Costs 10 Charge; **stuns** enemies hit | Costs 1 HP; deals **4 damage** to enemies hit |
| **Ranged** | Q | Costs 5 Charge, 0.45s cooldown, 0.5 damage; **breaks green ability walls** | Same, but 1.0 damage |
| **Shatterstep** | R | Spawns a **platform under your feet** while airborne (extra jumps) | On landing, creates a damaging **shockwave AOE** below you |
| **Tether** | X | **Binds** the enemy (3s) and **fears** it (runs away) | **Insta-kills** enemies below a HP threshold (normal ⅓, miniboss 20%, boss 5%); otherwise **slows** them |
| **Reality Break** | C | Doubles drop & coin rates and glows enemies | **Instantly kills all enemies** but halves drop & coin rates |
| **Heal** | Space | Spend Charge to heal over ~2s (slower while healing) | Unavailable |
---
## Combat notes
- Enemy contact damage only applies in **Light** form.
- Boss **shockwave attacks poison** you for 4 seconds: the health bar turns green and you lose 1 HP per second.
- Attacks and hits use invincibility frames and knockback; your melee hitbox covers ~30% into your body so close/overlapping hits always connect.
---
## Equipment & Armor Sets
Slots: **helmet, chest, pants, necklace**. Pieces roll stats (move speed, heal, charge, health, etc.).
**Rarities:** `tempered` (tier 1) → `attuned` (tier 2) → `awakened` (tier 3, unlocks ability slots). The **Upgrader** NPC turns 5 tempered copies of an item into 1 attuned copy.
**Sets** (3 pieces of the same set, attuned or better):
| Set | Summary |
|---|---|
| Dawnrunner | +HP; awakened adds Light move speed |
| Gravemark | +max Charge; awakened adds Charge regen |
| Vitalweave | +HP; awakened adds +heal |
| Duskwarrior | +Shade damage; awakened restores Charge on Shade hits |
| Twister | Removes Shade speed penalty; awakened gives move speed after switching forms |
| Paladin | Chance to negate incoming damage; awakened adds +HP |
| Luminal Growth | +Charge regen while standing still in Light; awakened also negates damage |
| Abyss Cleaver | Chance to heal on kill; awakened also gives move speed on kill |
| Umbraflow | Reduces Shade Charge drain |
| Adaptive Traveller | Move speed after switching forms; awakened restores Charge on switch |
The shade-focused sets (**Duskwarrior, Umbraflow, Abyss Cleaver, Adaptive Traveller**) are intentionally **excluded** from early boss and town-shop loot, so you can always complete the remaining sets.
---
## NPCs (Town 1: Gloomreach)
- **Vendor** — sells basic armor pieces.
- **Necklace Vendor** — sells necklaces.
- **Upgrader** — attunes 5× tempered → attuned.
- **Combat Master** — upgrades your boss token to unlock the **Hard** boss variant.
- **Boss Diary** — an interactable book: view your collected boss tokens in a grid, slot/unslot them, and start refights.
---
## Rooms & Progression
- `room_01` — tutorial. Contains a **quest object** (pink): accept the **"First Kills"** quest (kill 4 normal enemies → 5–15 light coins, repeatable).
- `room_02` — first enemies.
- `room_07` — hub, branching to the boss, reward room, and town.
- `room_boss_01` — **Gloom Warden** fight. Defeating him drops his **boss token**.
- `room_reward_01` — reward chest + the **Ranged** ability, locked behind green ability walls.
- `room_town_gloomreach` — Town 1 (NPCs above).
- `room_boss_refight_01` — diary refight room (same arena, no exits until the boss dies or you die).
---
## Boss Diary & Tokens
1. Beat the world boss → collect his **token** (teal pickup).
2. Bring it to the diary in town and **slot** it (or keep it in your inventory).
3. Slotting unlocks **Fight (Normal)**. Upgrading the token at the Combat Master unlocks **Fight (Hard)** — the boss moves and shoots twice as fast.
4. Dying in a refight returns you to the diary. Removing a token from the diary sends it back to your inventory, disabling the fight until you re-slot it.
---
## HUD & Stats
- Top-right: health bar (turns **green while poisoned**), Charge bar, coin counts.
- Ability icons with cooldown indicators (top-left).
- **H** toggles a detailed overlay: exact HP/Charge, move speeds (both forms), heal duration, attack rate, Charge regen, the lantern buff, and any stat bonuses from gear.
+61
View File
@@ -0,0 +1,61 @@
# Light & Dark — Roadmap
Destination: **polished vertical slice** — Regions 1–2, save system, skill upgrades.
Proves the core loop is fun before scaling to the full vision.
## Design decisions (locked)
- **Death penalty**: on death, drop light/dark coins at the death spot; reclaim them or lose them permanently on a second death. The fairy hovers over the spot as the marker.
- **Skill upgrades**:
- **Vendor** (smith/trainer) gives direct linear power upgrades. Upgrades one selected spell; changing selection costs coins.
- **Gems / rings** give alternate behaviors / sidegrades.
- **Ranged identity**: keep the bolt, add upgrades (no charge-up / homing rework).
- **Fairy (in slice)**: guide + ambient light source (bonus flow regen near player). Scout mode, teleport, fairy holes deferred to regions 3+.
- **Ascended armor**: cut for now. Awakened is good enough at the start; less balancing needed.
## Milestones
### M0 — Foundation (the game remembers)
| Item | Effort | Notes |
|---|---|---|
| ~~Save/persistence system~~ | L | **DONE (2026-09-28)**: JSON save to `saves/`, save via pause menu. Stores player state, room, coins, equipment, inventory, quests, tokens, boss diary, defeated bosses, broken doors. |
| Charge -> Flow rename | S | Code + UI + configs. |
| ~~Main menu~~ | M | **DONE (2026-09-28)**: Select Game (greyed with no saves), New Game (name entry), Settings (rebinding), Quit. Wipe-all-saves button (bottom right) with confirmation dialog. |
### M1 — Region 1 complete loop
| Item | Effort | Notes |
|---|---|---|
| Death penalty (drop coins, reclaim at death spot; fairy marks it; lose on 2nd death) | M | Save system exists now; drop-position data needed. Ties into fairy. |
| Fairy companion (guide + ambient light source -> bonus flow regen) | M | Wakes player at start, tutorial dialogue. |
| More quests (repeatable + one-time; system exists) | S | Just content. |
| Lore dialogue for fairy / NPCs | S | Needs written copy. |
### M2 — Skill upgrades
| Item | Effort | Notes |
|---|---|---|
| Vendor (smith/trainer) NPC | M | Reuses NPC + coin systems. |
| Vendor upgrades (linear): Dash = lower cooldown, Ranged = more damage, Tether = longer bind/fear | S | Data + UI. |
| Ring slot + gems (sidegrades): Dash = speed-stacks / refund-on-kill / afterimage taunt; Ranged = pierce (light) / aoe (shade) / kill-stacks; Tether = boss effects / higher threshold | L | New slot, new item type, build UI. |
### M3 — Region 2: shade matters
| Item | Effort | Notes |
|---|---|---|
| Shade-gated interactions (doors, an NPC, an area) | S-M | Room JSON + existing toggle. |
| New enemy behaviors (patrol, dodge-and-leap, burrow-shooter) | M | Enemy system supports it. |
| Quick recharge pickup | S | Mid-battle refill. |
| Ability tweaks: ranged upgrades, ground-slam knockback/iframe, light-step buffs | M | Picks up remaining notes ideas. |
| Region-2 boss + ability pacing | M | Re-align pacing (Ranged already exists). |
### Stretch / core (post-slice, in order)
- Fast travel (rune stones)
- Fairy scout + bond teleport + fairy holes
- Regions 3-5 per pacing notes
- World-change weapon (stretch-end, decide variant)
### Cut
- Ascended armor (removed).
## Dependencies
- Save is the keystone: death penalty, main menu, and any progress feature hang off it.
- Fairy and Flow rename can run in parallel with M0.
@@ -0,0 +1,8 @@
{
"player_idle": {
"frame_time": 0.8,
"start_delay": 0.15,
"bob_amp": 2,
"bob_speed": 2.0
}
}
@@ -0,0 +1,13 @@
{
"enemy": {
"light": { "min": 1, "max": 3 },
"dark_shade": { "weights": [0.5, 0.5] }
},
"miniboss": {
"light": { "min": 3, "max": 5 },
"dark_shade": { "weights": [0.34, 0.33, 0.33] }
},
"boss": {
"light": { "min": 5, "max": 10 }
}
}
+47
View File
@@ -0,0 +1,47 @@
{
"bg": [30, 30, 30],
"player": {
"light": [200, 200, 200],
"dark": [60, 60, 60],
"hit": [255, 255, 0]
},
"platform": [80, 80, 80],
"bars": {
"charge_bg": [40, 40, 40],
"charge_fill": [0, 180, 255],
"health_bg": [60, 0, 0],
"health_fill": [255, 0, 0]
},
"enemy": {
"normal": [200, 50, 50],
"normal_hit": [255, 150, 150],
"miniboss": [170, 40, 210],
"miniboss_hit": [220, 140, 255],
"boss": [240, 220, 80],
"boss_hit": [255, 245, 160]
},
"healing": {
"dark": [0, 80, 0],
"light": [120, 255, 120]
},
"loot": {
"awakened": [255, 170, 0],
"attuned": [20, 40, 120],
"tempered": [200, 200, 200]
},
"ui": {
"panel_bg": [20, 20, 20],
"panel_border": [120, 120, 120],
"panel_inner": [25, 25, 25],
"panel_inner_border": [70, 70, 70],
"hint_text": [160, 160, 160],
"text": [230, 230, 230]
}
}
@@ -0,0 +1,75 @@
{
"window": {
"width": 1300,
"height": 800,
"caption": "Light_and_Dark Prototype",
"fps": 60
},
"colors": {
"bg": [30, 30, 30],
"player_light": [200, 200, 200],
"player_dark": [60, 60, 60],
"platform": [80, 80, 80],
"charge_bg": [40, 40, 40],
"charge_fill": [0, 180, 255],
"health_bg": [60, 0, 0],
"health_fill": [255, 0, 0],
"enemy": [200, 50, 50],
"enemy_hit": [255, 150, 150],
"miniboss": [170, 40, 210],
"miniboss_hit": [220, 140, 255],
"boss": [240, 220, 80],
"boss_hit": [255, 245, 160],
"player_hit": [255, 255, 0],
"heal_dark": [0, 80, 0],
"heal_light": [120, 255, 120]
},
"loot_colors": {
"awakened": [255, 170, 0],
"attuned": [20, 40, 120],
"tempered": [200, 200, 200]
},
"resources": {
"base_max_charge": 100.0,
"charge_drain_rate": 40.0,
"charge_refill_rate": 20.0,
"base_max_health": 10,
"invincibility_duration": 1.0
},
"healing": {
"heal_duration": 2.0,
"heal_cost_flat": 50.0,
"heal_slow_mult": 0.30
},
"boss_shockwave": {
"slam_cooldown": 3.0,
"trigger_close": 140,
"trigger_far": 520,
"jump_vel": -16.0,
"speed": 600.0,
"lifetime": 2.0,
"height": 14,
"damage": 2
},
"assets": {
"player_sprite": "Player_01.png",
"player_sprite_shade": "Player_02.png"
},
"player": {
"sprite_offset_x": 0,
"sprite_offset_y": 0,
"sprite_scale": 1.6,
"hitbox_w": 48,
"hitbox_h": 72
},
"debug": {
"drop_debug_print": true
}
}
+38
View File
@@ -0,0 +1,38 @@
{
"talk_range": 110,
"trade_cost": 20,
"defaults": {
"vendor": {
"trade_cost": 20,
"offers": [
{ "slot": "helmet", "label": "Helmet", "rarity": "tempered" },
{ "slot": "chest", "label": "Chestplate", "rarity": "tempered" },
{ "slot": "pants", "label": "Greaves", "rarity": "tempered" }
],
"greet_light": "Greetings, little light!",
"greet_shade": "Stay away from me, evil!",
"greet_hint": "(Press F to interact)"
},
"upgrader": {
"trade_cost": 0,
"offers": [
{ "type": "upgrade_attune", "required_count": 5 }
],
"greet_light": "Bring me five tempered copies.",
"greet_shade": "Not here for your darkness.",
"greet_hint": "(Press F to upgrade)"
},
"necklace_vendor": {
"trade_cost": 20,
"offers": [
{ "type": "sell_specific", "item_id": "necklace_placeholder", "label": "Plain Necklace", "cost": 10 },
{ "type": "sell_specific", "item_id": "necklace_vigor", "label": "Charm of Vigor", "cost": 20 },
{ "type": "sell_specific", "item_id": "necklace_flow", "label": "Charm of Flow", "cost": 20 },
{ "type": "sell_specific", "item_id": "necklace_haste", "label": "Charm of Haste", "cost": 20 }
],
"greet_light": "Choose a necklace.",
"greet_shade": "No shade trinkets yet.",
"greet_hint": "(Press F to browse)"
}
}
}
+44
View File
@@ -0,0 +1,44 @@
{
"player": {
"speed_light": 5.0,
"speed_shade": 3.5,
"jump_light": -12.0,
"jump_shade": -9.0,
"gravity_light": 0.5,
"gravity_shade": 0.4
},
"resources": {
"base_max_charge": 100.0,
"charge_drain_rate": 40.0,
"charge_refill_rate": 20.0,
"base_max_health": 10,
"invincibility_duration": 1.0
},
"healing": {
"heal_duration": 2.0,
"heal_cost_flat": 50.0,
"heal_slow_mult": 0.30
},
"boss_shockwave": {
"slam_cooldown": 3.0,
"trigger_close": 140.0,
"trigger_far": 520.0,
"jump_vel": -16.0,
"shockwave_speed": 600.0,
"shockwave_lifetime": 2.0,
"shockwave_height": 14,
"shockwave_damage": 2
},
"loot_physics": {
"gravity": 900.0,
"terminal_vel": 900.0,
"bounce": 0.0,
"friction": 0.85,
"bob_amp": 3.0,
"bob_speed": 2.2
}
}
+10
View File
@@ -0,0 +1,10 @@
{
"charge_cost": 5.0,
"damage_mult": 0.5,
"cooldown": 0.45,
"projectile": {
"speed": 650.0,
"lifetime": 1.2,
"size": [14, 6]
}
}
@@ -0,0 +1,6 @@
{
"room_id": "room_reward_01.json",
"chest_pos": [520, 330],
"ability_pos": [820, 210],
"chest_coins": [30, 30]
}
+28
View File
@@ -0,0 +1,28 @@
{
"coins_hud": {
"icon_size": 14,
"icon_gap": 6,
"x_start_offset": 220,
"y": 72,
"group_spacing": 90
},
"inventory_ui": {
"panel": { "x": 20, "y": 20, "w": 560, "h": 545, "pad": 10 },
"list": { "w": 360, "line_h": 18, "header_h": 40, "pad_y": 6, "pad_right": 14 },
"icons": { "size": 16, "gap": 6 },
"details": { "stats_h": 155, "hint_h": 24, "gap": 8 },
"equipped": { "line_gap": 4 }
},
"pickup_feed": {
"max_lines": 6,
"duration": 3.0,
"fade_time": 0.6,
"pad_x": 10,
"pad_y": 6,
"line_gap": 4,
"x": 14,
"y_offset_from_center": -10
}
}
@@ -0,0 +1,20 @@
{
"normal": {
"rolls": 0,
"rarity_table": { "none": 1.0 }
},
"miniboss": {
"default_pool": "armor",
"rolls": 1,
"rarity_table": { "tempered": 0.85, "attuned": 0.15, "none": 0.0 }
},
"boss": {
"default_pool": "armor",
"guaranteed": [
{ "rarity": "attuned", "count": 1 },
{ "item_pool": "necklace", "count": 1 }
],
"rolls": 1,
"rarity_table": { "awakened": 0.15, "none": 0.85 }
}
}
@@ -0,0 +1,31 @@
{
"enemy": {
"rect": [40, 60],
"health": 3,
"speed": 2.2,
"air_speed": 2.0,
"detection_range": 240,
"contact_damage": 1,
"drop_profile": "normal"
},
"miniboss": {
"rect": [70, 95],
"health": 18,
"speed": 1.8,
"air_speed": 1.6,
"detection_range": 360,
"contact_damage": 2,
"drop_profile": "miniboss"
},
"boss": {
"rect": [110, 120],
"health": 10,
"speed": 1.6,
"air_speed": 1.4,
"detection_range": 500,
"contact_damage": 3,
"drop_profile": "boss"
}
}
+373
View File
@@ -0,0 +1,373 @@
{
"items": [
{
"id": "dawnrunner_helm",
"name": "Dawnrunner Helmet",
"set": "dawnrunner",
"slot": "helmet",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "move_speed_light_pct": 0.1 } },
"attuned": { "extra_stats": { "move_speed_light_pct": 0.1, "heal_speed_pct": 0.1 } },
"awakened": { "extra_stats": { "move_speed_light_pct": 0.15, "heal_speed_pct": 0.2 } }
}
},
{
"id": "dawnrunner_chest",
"name": "Dawnrunner Chestplate",
"set": "dawnrunner",
"slot": "chest",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge": 10 } },
"attuned": { "extra_stats": { "charge": 15, "move_speed_light_pct": 0.05 } },
"awakened": { "extra_stats": { "charge": 15, "move_speed_light_pct": 0.05, "heal_plus": 1 } }
}
},
{
"id": "dawnrunner_greaves",
"name": "Dawnrunner Greaves",
"set": "dawnrunner",
"slot": "pants",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "heal_speed_pct": 0.1 } },
"attuned": { "extra_stats": { "heal_speed_pct": 0.1, "move_speed_light_pct": 0.1 } },
"awakened": { "extra_stats": { "heal_speed_pct": 0.15, "move_speed_light_pct": 0.15 } }
}
},
{
"id": "gravemark_helm",
"name": "Gravemark Helmet",
"set": "gravemark",
"slot": "helmet",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge": 10 } },
"attuned": { "extra_stats": { "charge": 15, "charge_regen_pct": 0.1 } },
"awakened": { "extra_stats": { "charge": 15, "charge_regen_pct": 0.15, "health": 5 } }
}
},
{
"id": "gravemark_chest",
"name": "Gravemark Chestplate",
"set": "gravemark",
"slot": "chest",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge_regen_pct": 0.1 } },
"attuned": { "extra_stats": { "charge_regen_pct": 0.1, "health": 5 } },
"awakened": { "extra_stats": { "charge_regen_pct": 0.2, "health": 10 } }
}
},
{
"id": "gravemark_greaves",
"name": "Gravemark Greaves",
"set": "gravemark",
"slot": "pants",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge": 10 } },
"attuned": { "extra_stats": { "charge": 10, "health": 5 } },
"awakened": { "extra_stats": { "charge": 20, "health": 5 } }
}
},
{
"id": "vitalweave_helm",
"name": "Vitalweave Helmet",
"set": "vitalweave",
"slot": "helmet",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "health": 5 } },
"attuned": { "extra_stats": { "health": 10 } },
"awakened": { "extra_stats": { "health": 15 } }
}
},
{
"id": "vitalweave_chest",
"name": "Vitalweave Chestplate",
"set": "vitalweave",
"slot": "chest",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "heal_speed_pct": 0.1 } },
"attuned": { "extra_stats": { "heal_speed_pct": 0.15 } },
"awakened": { "extra_stats": { "heal_speed_pct": 0.15, "health": 5 } }
}
},
{
"id": "vitalweave_greaves",
"name": "Vitalweave Greaves",
"set": "vitalweave",
"slot": "pants",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge_regen_pct": 0.1 } },
"attuned": { "extra_stats": { "charge_regen_pct": 0.15 } },
"awakened": { "extra_stats": { "charge_regen_pct": 0.35 } }
}
},
{
"id": "duskwarrior_helm",
"name": "Duskwarrior Helmet",
"set": "duskwarrior",
"slot": "helmet",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge": 10 } },
"attuned": { "extra_stats": { "charge": 10, "health": 5 } },
"awakened": { "extra_stats": { "charge": 15, "health": 5, "charge_regen_pct": 0.1 } }
}
},
{
"id": "duskwarrior_chest",
"name": "Duskwarrior Chestplate",
"set": "duskwarrior",
"slot": "chest",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "health": 5 } },
"attuned": { "extra_stats": { "health": 10, "move_speed_shade_pct": 0.1 } },
"awakened": { "extra_stats": { "health": 10, "move_speed_shade_pct": 0.2 } }
}
},
{
"id": "duskwarrior_greaves",
"name": "Duskwarrior Greaves",
"set": "duskwarrior",
"slot": "pants",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "move_speed_shade_pct": 0.15 } },
"attuned": { "extra_stats": { "move_speed_shade_pct": 0.25 } },
"awakened": { "extra_stats": { "move_speed_shade_pct": 0.25, "charge": 10 } }
}
},
{
"id": "twister_helm",
"name": "Twister Helmet",
"set": "twister",
"slot": "helmet",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "attack_speed_pct": 0.1 } },
"attuned": { "extra_stats": { "attack_speed_pct": 0.15 } },
"awakened": { "extra_stats": { "attack_speed_pct": 0.15, "charge_regen_pct": 0.15 } }
}
},
{
"id": "twister_chest",
"name": "Twister Chestplate",
"set": "twister",
"slot": "chest",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge": 10 } },
"attuned": { "extra_stats": { "charge": 15, "health": 5 } },
"awakened": { "extra_stats": { "charge": 15, "health": 10, "move_speed_pct": 0.1 } }
}
},
{
"id": "twister_greaves",
"name": "Twister Greaves",
"set": "twister",
"slot": "pants",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "move_speed_pct": 0.1 } },
"attuned": { "extra_stats": { "move_speed_pct": 0.15 } },
"awakened": { "extra_stats": { "move_speed_pct": 0.25 } }
}
},
{
"id": "paladin_helm",
"name": "Paladin Helmet",
"set": "paladin",
"slot": "helmet",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "health": 5 } },
"attuned": { "extra_stats": { "health": 10, "negate_damage_chance": 0.05 } },
"awakened": { "extra_stats": { "health": 15, "negate_damage_chance": 0.1, "knockback_resistance": 0.25 } }
}
},
{
"id": "paladin_chest",
"name": "Paladin Chestplate",
"set": "paladin",
"slot": "chest",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "health": 5 } },
"attuned": { "extra_stats": { "health": 10, "charge": 10 } },
"awakened": { "extra_stats": { "health": 10, "charge": 10, "negate_damage_chance": 0.1 } }
}
},
{
"id": "paladin_greaves",
"name": "Paladin Greaves",
"set": "paladin",
"slot": "pants",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "health": 5 } },
"attuned": { "extra_stats": { "health": 10, "charge_regen_pct": 0.1 } },
"awakened": { "extra_stats": { "health": 15, "charge_regen_pct": 0.2 } }
}
},
{
"id": "luminal_growth_helm",
"name": "Luminal Growth Helmet",
"set": "luminal_growth",
"slot": "helmet",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge_regen_pct": 0.1 } },
"attuned": { "extra_stats": { "charge_regen_pct": 0.1, "health": 5 } },
"awakened": { "extra_stats": { "charge_regen_pct": 0.15, "health": 10, "negate_damage_chance": 0.05 } }
}
},
{
"id": "luminal_growth_chest",
"name": "Luminal Growth Chestplate",
"set": "luminal_growth",
"slot": "chest",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "health": 5 } },
"attuned": { "extra_stats": { "health": 5, "charge_regen_pct": 0.15 } },
"awakened": { "extra_stats": { "health": 10, "charge_regen_pct": 0.2 } }
}
},
{
"id": "luminal_growth_greaves",
"name": "Luminal Growth Greaves",
"set": "luminal_growth",
"slot": "pants",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge": 10 } },
"attuned": { "extra_stats": { "charge": 15 } },
"awakened": { "extra_stats": { "charge": 15, "charge_regen_pct": 0.1, "health": 5 } }
}
},
{
"id": "abyss_cleaver_helm",
"name": "Abyss Cleaver Helmet",
"set": "abyss_cleaver",
"slot": "helmet",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "shade_double_damage_chance": 0.05, "charge": 5 } },
"attuned": { "extra_stats": { "shade_double_damage_chance": 0.1, "charge": 10 } },
"awakened": { "extra_stats": { "shade_double_damage_chance": 0.15, "charge": 10, "health": 5 } }
}
},
{
"id": "abyss_cleaver_chest",
"name": "Abyss Cleaver Chestplate",
"set": "abyss_cleaver",
"slot": "chest",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "attack_speed_pct": 0.1 } },
"attuned": { "extra_stats": { "attack_speed_pct": 0.1, "shade_double_damage_chance": 0.05 } },
"awakened": { "extra_stats": { "attack_speed_pct": 0.15, "shade_double_damage_chance": 0.05 } }
}
},
{
"id": "abyss_cleaver_greaves",
"name": "Abyss Cleaver Greaves",
"set": "abyss_cleaver",
"slot": "pants",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge": 10 } },
"attuned": { "extra_stats": { "charge": 15, "health": 5 } },
"awakened": { "extra_stats": { "charge": 15, "health": 10, "attack_speed_pct": 0.1 } }
}
},
{
"id": "umbraflow_helm",
"name": "Umbraflow Helmet",
"set": "umbraflow",
"slot": "helmet",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "jump_height_shade_pct": 0.1 } },
"attuned": { "extra_stats": { "jump_height_shade_pct": 0.2 } },
"awakened": { "extra_stats": { "jump_height_shade_pct": 0.25, "shade_damage_flat": 1 } }
}
},
{
"id": "umbraflow_chest",
"name": "Umbraflow Chestplate",
"set": "umbraflow",
"slot": "chest",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge": 10 } },
"attuned": { "extra_stats": { "charge": 15 } },
"awakened": { "extra_stats": { "charge": 25 } }
}
},
{
"id": "umbraflow_greaves",
"name": "Umbraflow Greaves",
"set": "umbraflow",
"slot": "pants",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "move_speed_shade_pct": 0.1 } },
"attuned": { "extra_stats": { "move_speed_shade_pct": 0.15 } },
"awakened": { "extra_stats": { "move_speed_shade_pct": 0.2, "health": 10 } }
}
},
{
"id": "adaptive_traveller_helm",
"name": "Adaptive Traveller's Helmet",
"set": "adaptive_traveller",
"slot": "helmet",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "charge": 10 } },
"attuned": { "extra_stats": { "charge": 15 } },
"awakened": { "extra_stats": { "charge": 15, "charge_regen_pct": 0.15 } }
}
},
{
"id": "adaptive_traveller_chest",
"name": "Adaptive Traveller's Chestplate",
"set": "adaptive_traveller",
"slot": "chest",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "health": 5 } },
"attuned": { "extra_stats": { "health": 5, "move_speed_light_pct": 0.1 } },
"awakened": { "extra_stats": { "health": 10, "move_speed_light_pct": 0.15 } }
}
},
{
"id": "adaptive_traveller_greaves",
"name": "Adaptive Traveller's Greaves",
"set": "adaptive_traveller",
"slot": "pants",
"base_stats": {},
"rarity_overrides": {
"tempered": { "extra_stats": { "health": 5 } },
"attuned": { "extra_stats": { "health": 5, "move_speed_shade_pct": 0.1 } },
"awakened": { "extra_stats": { "health": 10, "move_speed_shade_pct": 0.15 } }
}
}
]
}
+32
View File
@@ -0,0 +1,32 @@
{
"items": [
{
"id": "necklace_placeholder",
"name": "Plain Necklace",
"slot": "necklace",
"item_type": "necklace",
"base_stats": { "health": 2 }
},
{
"id": "necklace_vigor",
"name": "Charm of Vigor",
"slot": "necklace",
"item_type": "necklace",
"base_stats": { "health": 5 }
},
{
"id": "necklace_flow",
"name": "Charm of Flow",
"slot": "necklace",
"item_type": "necklace",
"base_stats": { "charge": 10 }
},
{
"id": "necklace_haste",
"name": "Charm of Haste",
"slot": "necklace",
"item_type": "necklace",
"base_stats": { "move_speed_pct": 0.10 }
}
]
}
+5
View File
@@ -0,0 +1,5 @@
{
"tempered": { "tier": 1, "allows_abilities": false },
"attuned": { "tier": 2, "allows_abilities": false },
"awakened": { "tier": 3, "allows_abilities": true }
}
+177
View File
@@ -0,0 +1,177 @@
{
"dawnrunner": {
"required_pieces": 3,
"attuned": {
"type": "passive",
"effects": { "health": 5 }
},
"awakened": {
"type": "passive",
"effects": { "health": 10, "move_speed_light_pct": 0.10 }
}
},
"gravemark": {
"required_pieces": 3,
"attuned": {
"type": "passive",
"effects": { "charge": 5 }
},
"awakened": {
"type": "passive",
"effects": { "charge": 10, "charge_regen_pct": 0.10 }
}
},
"vitalweave": {
"required_pieces": 3,
"attuned": {
"type": "passive",
"effects": { "health": 5 }
},
"awakened": {
"type": "passive",
"effects": { "health": 10, "heal_plus": 2 }
}
},
"duskwarrior": {
"required_pieces": 3,
"attuned": {
"type": "passive",
"effects": { "shade_damage_flat": 1 }
},
"awakened": {
"type": "passive",
"effects": { "shade_damage_flat": 1 },
"conditional_effects": [
{
"condition": "on_hit_in_shade",
"effects": { "restore_charge": 5 }
}
]
}
},
"twister": {
"required_pieces": 3,
"attuned": {
"type": "passive",
"effects": { "charge": -10, "negate_shade_speed_penalty": true }
},
"awakened": {
"type": "passive",
"effects": { "negate_shade_speed_penalty": true },
"conditional_effects": [
{
"condition": "after_form_switch",
"duration_sec": 2.0,
"effects": { "move_speed_pct": 0.15 }
}
]
}
},
"paladin": {
"required_pieces": 3,
"attuned": {
"type": "passive",
"effects": { "negate_damage_chance": 0.05 }
},
"awakened": {
"type": "passive",
"effects": { "negate_damage_chance": 0.05, "health": 10 }
}
},
"luminal_growth": {
"required_pieces": 3,
"attuned": {
"type": "passive",
"conditional_effects": [
{
"condition": "standing_still_in_light",
"effects": { "charge_regen_pct": 0.20 }
}
]
},
"awakened": {
"type": "passive",
"conditional_effects": [
{
"condition": "standing_still_in_light",
"effects": { "charge_regen_pct": 0.20, "negate_damage_chance": 0.10 }
}
]
}
},
"abyss_cleaver": {
"required_pieces": 3,
"attuned": {
"type": "passive",
"conditional_effects": [
{
"condition": "on_kill",
"chance": 0.05,
"effects": { "heal_flat": 1 }
}
]
},
"awakened": {
"type": "passive",
"conditional_effects": [
{
"condition": "on_kill",
"chance": 0.10,
"effects": { "heal_flat": 1 }
},
{
"condition": "on_kill",
"duration_sec": 2.0,
"effects": { "move_speed_pct": 0.20 }
}
]
}
},
"umbraflow": {
"required_pieces": 3,
"attuned": {
"type": "passive",
"effects": { "shade_charge_drain_reduction_pct": 0.20 }
},
"awakened": {
"type": "passive",
"effects": { "shade_charge_drain_reduction_pct": 0.35 }
}
},
"adaptive_traveller": {
"required_pieces": 3,
"attuned": {
"type": "passive",
"conditional_effects": [
{
"condition": "after_form_switch",
"duration_sec": 2.0,
"effects": { "move_speed_pct": 0.15 }
}
]
},
"awakened": {
"type": "passive",
"conditional_effects": [
{
"condition": "after_form_switch",
"duration_sec": 2.0,
"effects": { "move_speed_pct": 0.25 }
},
{
"condition": "on_form_switch",
"effects": { "restore_charge": 10 }
}
]
}
}
}
+8
View File
@@ -0,0 +1,8 @@
{
"objects": {
"lamp": {
"type": "light_source",
"charge_regen_range": 180
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

@@ -0,0 +1,143 @@
{
"meta": {
"id": "room_01",
"name": "Room 01 - Tutorial Steps"
},
"player_spawn": [
-260,
500
],
"bounds": {
"kill_y": 2000
},
"platforms": {
"ground": [
[
-500,
640,
2060,
460
],
[
-500,
560,
520,
80
],
[
1560,
220,
120,
880
],
[
-1100,
-520,
600,
1620
],
[
1680,
-100,
920,
1200
],
[
-500,
-520,
940,
840
],
[
440,
-520,
2160,
420
]
],
"floating": [
[
800,
220,
320,
40
],
[
880,
520,
240,
40
],
[
500,
400,
320,
40
],
[
440,
280,
200,
40
],
[
1220,
220,
340,
40
]
]
},
"enemies": [],
"exits": [
{
"rect": [
-420,
480,
90,
80
],
"to": "room_reward_01",
"spawn": [
120,
300
],
"hint": "Reward"
},
{
"rect": [
1560,
100,
120,
120
],
"to": "room_02",
"spawn": [
-420,
300
],
"hint": "",
"spawn_id": "entry_1"
}
],
"ability_doors": [],
"entry_spawns": {},
"props": [
{
"type": "light_source",
"pos": [
0,
560
],
"radius": 180
},
{
"type": "quest_giver",
"quest_id": "quest_first_kills",
"pos": [
300,
600
]
}
]
}
@@ -0,0 +1,205 @@
{
"meta": {
"id": "room_02",
"name": "Room 02 - First Enemies"
},
"player_spawn": [
-320,
300
],
"bounds": {
"kill_y": 2000
},
"platforms": {
"ground": [
[
-500,
360,
2440,
660
],
[
-760,
-580,
260,
1600
],
[
1940,
-580,
240,
1600
],
[
-760,
-820,
2940,
240
]
],
"floating": [
[
260,
260,
140,
18
],
[
520,
220,
140,
18
],
[
760,
180,
140,
18
],
[
940,
120,
170,
18
],
[
1200,
160,
170,
18
],
[
1460,
100,
170,
18
],
[
1200,
-20,
280,
40
],
[
40,
-140,
1100,
60
],
[
-500,
-140,
460,
60
],
[
-500,
-260,
260,
40
],
[
-500,
-380,
160,
40
],
[
-320,
-500,
1380,
40
],
[
1140,
-440,
340,
40
],
[
1560,
-380,
380,
40
]
]
},
"enemies": [
{
"type": "enemy",
"pos": [
240,
-200
]
},
{
"type": "enemy",
"pos": [
620,
140
]
},
{
"type": "enemy",
"pos": [
860,
-200
]
},
{
"type": "enemy",
"pos": [
480,
-530
]
},
{
"type": "enemy",
"pos": [
1740,
280
]
}
],
"exits": [
{
"rect": [
-500,
300,
80,
60
],
"to": "room_01",
"spawn": [
1560,
140
],
"hint": "Back"
},
{
"rect": [
1860,
-500,
80,
120
],
"to": "room_07",
"spawn": [
180,
240
],
"hint": ""
}
],
"ability_doors": [],
"entry_spawns": {
"entry_1": [
-420,
300
],
"entry_3": [
1840,
-440
]
}
}
@@ -0,0 +1,426 @@
{
"name": "room_07",
"display_name": "room_07",
"meta": {
"id": "room_07",
"name": "room_07"
},
"bounds": {
"kill_y": 3200
},
"player_spawn": [
200,
220
],
"entry_spawns": {
"entry_1": [
180,
240
],
"entry_2": [
4200,
2720
],
"entry_3": [
-320,
2720
]
},
"platforms": [
{
"x": 60,
"y": 320,
"w": 1460,
"h": 40,
"group": "ground"
},
{
"x": -1160,
"y": 2780,
"w": 5500,
"h": 120,
"group": "ground"
},
{
"x": -1160,
"y": -300,
"w": 1220,
"h": 2480,
"group": "ground"
},
{
"x": -1280,
"y": -300,
"w": 120,
"h": 3200,
"group": "ground"
},
{
"x": 2300,
"y": 1860,
"w": 2040,
"h": 320,
"group": "ground"
},
{
"x": 4340,
"y": -300,
"w": 100,
"h": 3200,
"group": "ground"
},
{
"x": 60,
"y": -300,
"w": 4280,
"h": 80,
"group": "ground"
},
{
"x": 60,
"y": 1860,
"w": 1600,
"h": 320,
"group": "ground"
},
{
"x": 1600,
"y": 440,
"w": 1060,
"h": 40,
"group": "ground"
},
{
"x": 2780,
"y": 320,
"w": 580,
"h": 40,
"group": "ground"
},
{
"x": 3280,
"y": 800,
"w": 1060,
"h": 60,
"group": "ground"
},
{
"x": 1660,
"y": 1920,
"w": 360,
"h": 20,
"group": "ground"
},
{
"x": 1940,
"y": 2040,
"w": 360,
"h": 20,
"group": "ground"
},
{
"x": 1660,
"y": 2160,
"w": 360,
"h": 20,
"group": "ground"
},
{
"x": 1940,
"y": 2280,
"w": 360,
"h": 20,
"group": "ground"
},
{
"x": 1660,
"y": 2400,
"w": 360,
"h": 20,
"group": "ground"
},
{
"x": 1940,
"y": 2520,
"w": 360,
"h": 20,
"group": "ground"
},
{
"x": 1660,
"y": 2640,
"w": 360,
"h": 20,
"group": "ground"
},
{
"x": 1940,
"y": 2720,
"w": 360,
"h": 20,
"group": "ground"
},
{
"x": 2660,
"y": 880,
"w": 520,
"h": 40,
"group": "ground"
},
{
"x": 2140,
"y": 880,
"w": 380,
"h": 40,
"group": "ground"
},
{
"x": 1940,
"y": 880,
"w": 120,
"h": 40,
"group": "ground"
},
{
"x": 1680,
"y": 880,
"w": 100,
"h": 40,
"group": "ground"
},
{
"x": 1440,
"y": 880,
"w": 80,
"h": 40,
"group": "ground"
},
{
"x": 1220,
"y": 880,
"w": 80,
"h": 40,
"group": "ground"
},
{
"x": 940,
"y": 880,
"w": 180,
"h": 40,
"group": "ground"
},
{
"x": 660,
"y": 820,
"w": 180,
"h": 40,
"group": "ground"
},
{
"x": 300,
"y": 740,
"w": 260,
"h": 60,
"group": "ground"
},
{
"x": 260,
"y": 640,
"w": 40,
"h": 1100,
"group": "ground"
},
{
"x": 300,
"y": 1260,
"w": 4040,
"h": 40,
"group": "ground"
},
{
"x": 3240,
"y": 980,
"w": 60,
"h": 40,
"group": "ground"
},
{
"x": 3100,
"y": 1060,
"w": 60,
"h": 40,
"group": "ground"
},
{
"x": 3240,
"y": 1140,
"w": 60,
"h": 40,
"group": "ground"
},
{
"x": 3380,
"y": 440,
"w": 300,
"h": 40,
"group": "ground"
},
{
"x": 3700,
"y": 560,
"w": 300,
"h": 40,
"group": "ground"
},
{
"x": 4020,
"y": 680,
"w": 320,
"h": 40,
"group": "ground"
}
],
"enemies": [
{
"x": 2080,
"y": 360,
"type": "enemy"
},
{
"x": 280,
"y": 2680,
"type": "miniboss"
},
{
"x": 520,
"y": 2700,
"type": "enemy"
},
{
"x": 680,
"y": 2700,
"type": "enemy"
},
{
"x": 980,
"y": 2700,
"type": "enemy"
},
{
"x": 840,
"y": 2700,
"type": "enemy"
},
{
"x": 820,
"y": 1160,
"type": "enemy"
},
{
"x": 1040,
"y": 1160,
"type": "enemy"
},
{
"x": 1340,
"y": 1160,
"type": "enemy"
},
{
"x": 1700,
"y": 1160,
"type": "enemy"
},
{
"x": 2140,
"y": 1160,
"type": "enemy"
},
{
"x": 2480,
"y": 1160,
"type": "enemy"
},
{
"x": 2700,
"y": 1160,
"type": "enemy"
},
{
"x": 2740,
"y": 1720,
"type": "miniboss"
}
],
"props": [],
"exits": [
{
"x": -1160,
"y": 2640,
"w": 100,
"h": 140,
"to": "room_town_gloomreach",
"spawn_id": "",
"spawn": [
120,
300
],
"hint": ""
},
{
"x": -420,
"y": 2720,
"w": 80,
"h": 60,
"to": "room_boss_01",
"spawn_id": "entry_2",
"spawn": [
-360,
300
],
"hint": ""
},
{
"x": 4240,
"y": 2700,
"w": 100,
"h": 80,
"to": "room_reward_01",
"spawn_id": "",
"spawn": [
1760,
300
],
"hint": ""
},
{
"x": 60,
"y": 180,
"w": 100,
"h": 140,
"to": "room_02",
"spawn_id": "",
"spawn": [
1840,
-440
],
"hint": ""
}
],
"ability_doors": [
{
"x": -980,
"y": 2180,
"w": 80,
"h": 600
},
{
"x": 4100,
"y": 2180,
"w": 40,
"h": 600
}
],
"room_w": 1600,
"room_h": 900
}
@@ -0,0 +1,71 @@
{
"meta": {
"id": "room_boss_01",
"name": "room_boss_01"
},
"player_spawn": [
-240,
300
],
"bounds": {
"kill_y": 1400
},
"platforms": {
"ground": [
[
-500,
360,
1500,
240
]
]
},
"enemies": [
{
"type": "boss",
"pos": [
280,
200
]
}
],
"exits": [
{
"rect": [
-460,
300,
80,
60
],
"to": "room_07",
"spawn": [
-320,
2720
],
"hint": "Retreat",
"spawn_id": "entry_3"
},
{
"rect": [
880,
260,
120,
100
],
"to": "room_reward_01",
"spawn": [
100,
300
],
"hint": "Reward",
"spawn_id": "entry_2"
}
],
"ability_doors": [],
"entry_spawns": {
"entry_2": [
-360,
300
]
}
}
@@ -0,0 +1,48 @@
{
"meta": {
"id": "room_boss_refight_01",
"name": "room_boss_refight_01"
},
"player_spawn": [
-240,
300
],
"bounds": {
"kill_y": 1400
},
"platforms": {
"ground": [
[
-500,
360,
1500,
240
]
]
},
"enemies": [
{
"type": "boss",
"pos": [
280,
200
]
}
],
"exits": [
{
"rect": [
-460,
300,
80,
60
],
"to": "room_town_gloomreach",
"spawn_id": "entry_diary",
"hint": "Leave",
"requires_boss_dead": true
}
],
"ability_doors": [],
"entry_spawns": {}
}
@@ -0,0 +1,116 @@
{
"meta": {
"id": "room_reward_01",
"name": "room_reward_01"
},
"player_spawn": [
140,
300
],
"bounds": {
"kill_y": 2000
},
"platforms": {
"ground": [
[
-500,
360,
2400,
240
]
],
"floating": [
[
650,
260,
220,
18
],
[
1100,
260,
220,
18
]
]
},
"enemies": [],
"exits": [
{
"rect": [
0,
300,
80,
60
],
"to": "room_boss_01",
"spawn_id": "entry_2",
"spawn": [
110,
260
],
"hint": "Back"
},
{
"rect": [
1840,
300,
60,
60
],
"to": "room_07",
"spawn_id": "entry_2",
"spawn": [
4200,
2720
],
"hint": "Forward"
}
],
"ability_doors": [
{
"rect": [
1700,
60,
60,
300
]
},
{
"rect": [
1580,
60,
40,
300
]
}
],
"entry_spawns": {
"entry_2": [
100,
300
],
"entry_1": [
1800,
300
]
},
"props": [
{
"type": "reward_chest",
"pos": [
520,
330
],
"radius": 180
},
{
"type": "ability_pickup",
"pos": [
820,
210
],
"radius": 180
}
]
}
@@ -0,0 +1,91 @@
{
"meta": {
"id": "room_town_gloomreach",
"name": "room_town_gloomreach"
},
"player_spawn": [
80,
260
],
"bounds": {
"kill_y": 2000
},
"platforms": {
"ground": [
[
-500,
360,
2400,
240
]
]
},
"enemies": [],
"exits": [
{
"rect": [
10,
300,
80,
60
],
"to": "room_07",
"spawn": [
-1000,
2720
],
"hint": "Back"
}
],
"ability_doors": [],
"entry_spawns": {
"entry_1": [
120,
300
],
"entry_diary": [
180,
300
]
},
"props": [
{
"type": "diary",
"pos": [
180,
310
]
}
],
"npcs": [
{
"type": "vendor",
"pos": [
700,
306
]
},
{
"type": "upgrader",
"pos": [
860,
306
]
},
{
"type": "necklace_vendor",
"pos": [
1020,
306
]
},
{
"type": "combat_master",
"pos": [
400,
306
],
"trade_cost": 0
}
]
}
File diff suppressed because it is too large Load Diff
+36
View File
@@ -0,0 +1,36 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>e4b51f4c-e0be-4f9e-8a8e-d814a78b30c5</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>main.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<Name>light_and_dark</Name>
<RootNamespace>light_and_dark</RootNamespace>
<TestFramework>unittest</TestFramework>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<ItemGroup>
<Compile Include="main.py" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets" />
<!-- Uncomment the CoreCompile target to enable the Build command in
Visual Studio and specify your pre- and post-build commands in
the BeforeBuild and AfterBuild targets below. -->
<!--<Target Name="CoreCompile" />-->
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
</Project>
File diff suppressed because it is too large Load Diff
+130
View File
@@ -0,0 +1,130 @@
New skills
Tether
- hit an enemy, inflict a visual bind for a few seconds, end effect depends on which form the player is in when it ends
- light form: blind enemy (make them walk the other direction)
- shade form: instakill after a certain enemy HP threshold, slow otherwise
Reality Break
- light form: make all enemies double their drop rates
- shade form: instantly kill all enemies, halves drop rates
Shatterstep
- light form: for X seconds, create a platform below your feet when jumping, allowing for multiple jumps in the air
- shade form: when jumping, create aoe below you upon landing
Skill upgrades
Dash
- Refund cost upon successful stun/kill
- lower cooldown
- more range
- build up movement speed stacks with every dash, lose stacks upon getting hit
- more damage against targets that are stunned (inflict mark?)
- leave behind afterimage (enemy taunt)
Ranged Attack
- hold to charge, release for stronger attack (more damage and stun)
- faster speed, higher charge cost
- slower speed but more damage
- upgrade light form: pierce and slow
- upgrade shade form: aoe
- for every enemy kill collect stacks that increase damage, lose stacks upon not finishing enemies
Tether
- light form: higher hp threshold for kill; if used against boss: slower attacks
- shade form: longer fear; if used against boss: slower movement speed
How to obtain skill upgrades
- vendor (smith? trainer?) that can upgrade one spell (selection can be changed but requires paying for it every time)
- item (gem?) that can be slotted into armor to unlock a skill upgrade
- ring to go with necklaces (no synergy to not force those even more like armor already does)
Ascended armor
- select one awakened armor piece as the main piece and one as the sacrifice
- select X number of traits from the sacrifice to merge onto the main piece
- sacrifice gets destroyed in the process, creating an Ascended armor piece
- cost: many coins/rare resource?
Further ideas
Quests:
Repeatable
- usually has a loot pool of items but the player also gains resources to buy stuff from this loot pool (as some sort of pity system)
One-time
- fixed reward
- essential or useful for progression
Boss Tokens
- bosses drop an item (unique per boss) that can be "collected" (diary) to fight them again
- token can be brought to a specific NPC to upgrade it to fight harder bosses
Rework for Charge -> Flow, butterflies (for lore) instead of Lanterns
Regions
1st region: Shade mode is a thing, but not widely used. Player gets used to FLOW. First easy quest.
2nd region: Shade mode is needed for a handful of interactions, but not really for combat. First boss fight. First ability. Town 1.
3rd region: Shade mode is required to access areas or NPCs. New boss which unlocks region 4, but is optional for now.
4th region: Access through third area boss. Shade mode is required to traverse (unique environmental effects). Boss fight that has special targeting projectiles
if the player isn't in shade mode. New ability. Fast travel to 5th region/Town 2?
5th region: Alternate to 4th region in terms of progress. Light area. Town 2. Quest board/NPCs/player housing (for accessing the diary)
Ability changes (ideas)
Ranged:
- pierce
- less dmg for less flow cost
- faster/ramp up traveling speed/scale damage with speed
- more damage to specific enemies
- bigger but slower
- other directions (up/diagonal?)
- hold button to charge/release, first enemy hit will be marked for ? seconds, further shots will home in on marked enemy
Ground slam shade:
- knockback
- dmg immunity when hitting 1+ enemies
Light step:
- dmg up for ? seconds after/when touching platform
- speed increase after/when touching platform
Companion (fairy)
- interaction/guide
- ability: fairy bond teleport?
Fairy bond
- reinforce bond with fairy companion: allow fairy scout mode (fly and look but no interactions) and later on teleport to companion if it flies
ahead in this mode
- access to this bond mode takes a few seconds (channel) to not make the light step ability unneccessary
- fairy can make light at the expense of the player's flow
- fairy holes (environmental features/shortcuts) where player can teleport through with bond teleport
Fast travel
- items found all over the map (rune stones) which can be slotted into special devices to link those together as fast travel points
Enemies
design/behavior?
- slow patrol, move/jump in player direction
- slow patrol, doge backwards and leap at player
- stationary, shoot at player, burrow to somewhere else nearby
Quick recharge
- player can collect something in advance to refill charge mid-battle with a quick press of a button
Death
- what does the player lose?
- upgrades to lose less?
Lore
- player character is a being of light and dark, created by a forbidden love between a light and dark being
- gods? -> forbidden child <- banished and sleeping -> woken up long later by fairy companion (this is where the game starts)?
- parents of player character sent companion to support and guide the player back to their parents
- flow/charge is not inheritently dark or light, it is simply a resource that exists in the player character and a few other things in the world
World change
- mid game progress: unique weapon that the player can choose to take
- world changes if weapon is taken
- if weapon is not taken, player can still explore and return later to take the weapon unless they trigger a different event which would also change the world
(but differently compared to when they'd take the weapon) -> do they still get that weapon but in a different variant?
+28
View File
@@ -0,0 +1,28 @@
{
"version": 1,
"saved_at": "2026-09-28T09:46:05",
"player": {
"room_id": "room_02.json",
"x": -45,
"y": 360,
"health": 10,
"charge": 100.0,
"shade": false,
"coins_light": 23,
"coins_dark": 2,
"has_ranged": false,
"reward_chest_opened": false,
"equipment": {}
},
"inventory": [],
"quests": {
"active": {},
"completed_one_time": [],
"tokens": 0
},
"boss_diary": {
"slotted": {}
},
"defeated_bosses": [],
"broken_doors": []
}