Brandling Safari: LAN safari-zone creature catching on the HD-2D engine
- Authoritative 30 Hz server (ENet, SQLite): accounts, characters, wild AI, tall grass / water / wandering spawns, fishing, captures, follower chains, clock + weather, LAN beacon - Client: title / join / character creator / play screens, prediction + reconciliation, interpolated players and parties, HD-2D UI (dialogue with Professor Henry, HUD, collection) - Shared deterministic zone generator, movement, protocol, roster, appearance - Paper-doll character art pipeline (PixelLab base walk + per-item animation edits) - Brandling roster from the company list (logo colors, jev types), Blender safari props - Headless test bot
4
.env.example
Normal file
@@ -0,0 +1,4 @@
|
||||
# Only needed to (re)generate art; the game itself needs no keys.
|
||||
# The tools also read ../.env (the folder that holds this repo and its siblings).
|
||||
PIXELLAB_API_KEY=
|
||||
OPENROUTER_API_KEY=
|
||||
5
.gitattributes
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
* text=auto eol=lf
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.glb binary
|
||||
*.ttf binary
|
||||
36
.gitignore
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# Secrets (PIXELLAB_API_KEY / OPENROUTER_API_KEY)
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Private source data: the ClickUp export holds client contact details and logins.
|
||||
# Only the derived roster (names, domains, types) is committed.
|
||||
*.csv
|
||||
|
||||
# Build output
|
||||
build/
|
||||
build_*/
|
||||
build-*/
|
||||
cmake-build-*/
|
||||
compile_commands.json
|
||||
|
||||
# Runtime output
|
||||
screenshots/
|
||||
*.db
|
||||
*.db-wal
|
||||
*.db-shm
|
||||
|
||||
# Tool caches
|
||||
art_src/.pending/
|
||||
art_src/creatures/cache/logos/
|
||||
art_src/preview/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# Editors / OS
|
||||
.cache/
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*~
|
||||
.DS_Store
|
||||
93
CMakeLists.txt
Normal file
@@ -0,0 +1,93 @@
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
project(brandling_safari LANGUAGES C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
option(BS_BUILD_CLIENT "Build the game client (needs OpenGL + the HD-2D engine)" ON)
|
||||
option(BS_BUILD_SERVER "Build the dedicated server" ON)
|
||||
set(HD2D_ENGINE_DIR "${CMAKE_SOURCE_DIR}/../Vibe-HD-2D" CACHE PATH "Path to the Vibe-HD-2D engine checkout")
|
||||
set(HD2D_ENGINE_GIT "ssh://git@git.gabjimmy.com:30009/Gabe/Vibe-HD-2D.git" CACHE STRING "Engine repo used when HD2D_ENGINE_DIR is missing")
|
||||
|
||||
include(FetchContent)
|
||||
# Old third-party CMakeLists (ENet) still declare cmake_minimum_required < 3.5.
|
||||
set(CMAKE_POLICY_VERSION_MINIMUM 3.5)
|
||||
|
||||
# --- Dependencies -------------------------------------------------------------
|
||||
find_package(glm QUIET)
|
||||
if(NOT TARGET glm::glm)
|
||||
FetchContent_Declare(glm GIT_REPOSITORY https://github.com/g-truc/glm.git GIT_TAG 1.0.1)
|
||||
FetchContent_MakeAvailable(glm)
|
||||
endif()
|
||||
|
||||
find_package(nlohmann_json 3 QUIET)
|
||||
if(NOT TARGET nlohmann_json::nlohmann_json)
|
||||
FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz)
|
||||
FetchContent_MakeAvailable(json)
|
||||
endif()
|
||||
|
||||
FetchContent_Declare(enet GIT_REPOSITORY https://github.com/lsalzman/enet.git GIT_TAG v1.3.18)
|
||||
FetchContent_MakeAvailable(enet)
|
||||
target_include_directories(enet PUBLIC ${enet_SOURCE_DIR}/include)
|
||||
|
||||
# --- Shared game core (no graphics) ---------------------------------------------
|
||||
add_library(bs_shared STATIC
|
||||
shared/Appearance.cpp shared/Net.cpp shared/Protocol.cpp shared/Roster.cpp shared/Zone.cpp)
|
||||
target_include_directories(bs_shared PUBLIC shared)
|
||||
target_link_libraries(bs_shared PUBLIC glm::glm nlohmann_json::nlohmann_json enet)
|
||||
target_compile_definitions(bs_shared PUBLIC GLM_FORCE_RADIANS GLM_ENABLE_EXPERIMENTAL
|
||||
BS_ASSET_DIR="${CMAKE_SOURCE_DIR}/assets")
|
||||
if(MSVC)
|
||||
target_compile_options(bs_shared PRIVATE /W4)
|
||||
target_link_libraries(bs_shared PUBLIC ws2_32 winmm)
|
||||
else()
|
||||
target_compile_options(bs_shared PRIVATE -Wall -Wextra -Wno-unused-parameter)
|
||||
endif()
|
||||
|
||||
# --- Server -------------------------------------------------------------------
|
||||
if(BS_BUILD_SERVER)
|
||||
find_package(SQLite3 REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
file(GLOB BS_SERVER_SOURCES CONFIGURE_DEPENDS server/*.cpp)
|
||||
add_executable(safari_server ${BS_SERVER_SOURCES})
|
||||
target_link_libraries(safari_server PRIVATE bs_shared SQLite::SQLite3 Threads::Threads)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(safari_server PRIVATE -Wall -Wextra -Wno-unused-parameter)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --- Headless test bot (no graphics) ------------------------------------------
|
||||
add_executable(safari_bot bot/main.cpp)
|
||||
target_link_libraries(safari_bot PRIVATE bs_shared)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(safari_bot PRIVATE -Wall -Wextra -Wno-unused-parameter)
|
||||
endif()
|
||||
|
||||
# --- Client -------------------------------------------------------------------
|
||||
if(BS_BUILD_CLIENT)
|
||||
if(NOT EXISTS "${HD2D_ENGINE_DIR}/CMakeLists.txt")
|
||||
FetchContent_Declare(hd2d_engine GIT_REPOSITORY ${HD2D_ENGINE_GIT} GIT_TAG main)
|
||||
FetchContent_GetProperties(hd2d_engine)
|
||||
if(NOT hd2d_engine_POPULATED)
|
||||
FetchContent_Populate(hd2d_engine)
|
||||
endif()
|
||||
set(HD2D_ENGINE_DIR ${hd2d_engine_SOURCE_DIR})
|
||||
endif()
|
||||
set(HD2D_BUILD_DEMO OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(${HD2D_ENGINE_DIR} hd2d)
|
||||
|
||||
file(GLOB BS_CLIENT_SOURCES CONFIGURE_DEPENDS client/*.cpp)
|
||||
add_executable(safari_client ${BS_CLIENT_SOURCES})
|
||||
target_link_libraries(safari_client PRIVATE bs_shared hd2d)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(safari_client PRIVATE -Wall -Wextra -Wno-unused-parameter)
|
||||
endif()
|
||||
# The client launches the dedicated server for "Host game" from its own folder.
|
||||
if(BS_BUILD_SERVER)
|
||||
add_dependencies(safari_client safari_server)
|
||||
endif()
|
||||
endif()
|
||||
202
README.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Brandling Safari
|
||||
|
||||
A small LAN-multiplayer creature-catching game set in a safari zone, rendered in the
|
||||
**HD-2D** style (Octopath Traveler / Triangle Strategy) with the
|
||||
[Vibe-HD-2D](../Vibe-HD-2D) engine. The creatures, **Brandlings**, are named after real
|
||||
companies: each one's sprite is generated by [Company_Sprite_Gen](../Company_Sprite_Gen) from
|
||||
the company name, recolored with its logo's brand colors, and its type comes from the jev
|
||||
business classifier.
|
||||
|
||||

|
||||
|
||||
| | |
|
||||
| --- | --- |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  |  |
|
||||
|  | |
|
||||
|
||||
## Features
|
||||
|
||||
- **Meadow Safari Zone**: terraced grass diorama with a north ridge and an east plateau, a lake
|
||||
with a fishing dock, a pond, eight tall-grass patches, an entrance gate and plaza with
|
||||
Professor Henry's field tent, lamps, fences and props (3D models built in Blender, pixel-art
|
||||
ground and foliage).
|
||||
- **Character creator** (persists server-side): masculine / feminine base body, 6 skin tones, 5
|
||||
hair styles, 3 hats, 5 tops, 4 bottoms, 3 shoes, any color per slot. Every combination is
|
||||
animated by one shared walk cycle (see [Character art](#character-art)).
|
||||
- **Professor Henry** greets new rangers with an intro, hands out 30 Safari Capsules and
|
||||
restocks them later.
|
||||
- **Finding Brandlings**: they burst out of tall grass around you as you walk (more often when
|
||||
running), swim in the lake and surface with splashes, wander the meadow, and bite on a
|
||||
fishing line cast from the shore or dock.
|
||||
- **Catching**: throw a Safari Capsule (closer and calmer = better odds; hooked ones are dazed);
|
||||
misses can make them flee. Caught Brandlings join your party (up to 6) and follow behind you
|
||||
in a chain, bouncing and turning to face their direction; the rest go to your box.
|
||||
- **Multiplayer**: dedicated authoritative server, LAN discovery, client-side prediction with
|
||||
server reconciliation, interpolated remote players and their parties, chat bubbles.
|
||||
- **World state from the server**: time of day (dawn, day, dusk, night with stars, moon and
|
||||
lantern light) and weather (clear, cloudy, rain, thunderstorm, mist) change the look on every
|
||||
client and which Brandlings appear.
|
||||
|
||||
## Building
|
||||
|
||||
Requirements: CMake >= 3.21, a C++20 compiler, OpenGL 4.5, `libepoxy`, SQLite 3, and the
|
||||
engine checked out next to this repo (`../Vibe-HD-2D`; set `HD2D_ENGINE_DIR` otherwise, or
|
||||
leave it missing to fetch it from `HD2D_ENGINE_GIT`). GLFW, GLM, stb, cgltf and Dear ImGui
|
||||
come from the engine; nlohmann/json is used from the system or fetched, ENet is always fetched.
|
||||
|
||||
```sh
|
||||
# Arch / CachyOS
|
||||
sudo pacman -S cmake ninja glfw glm libepoxy stb sqlite nlohmann-json
|
||||
|
||||
cmake -S . -B build -G Ninja
|
||||
ninja -C build # safari_client, safari_server, safari_bot
|
||||
```
|
||||
|
||||
Server only (no GPU needed): `cmake -S . -B build_srv -G Ninja -DBS_BUILD_CLIENT=OFF`.
|
||||
|
||||
## Playing
|
||||
|
||||
```sh
|
||||
./build/safari_client # title screen: Host & Play, or Join a LAN Game
|
||||
```
|
||||
|
||||
- **Host & Play** starts `safari_server` next to the client on port 27420 and joins it.
|
||||
Other players on the network see it under **Join a LAN Game** (UDP broadcast on 27421) or
|
||||
can type the host's address.
|
||||
- A dedicated server: `./build/safari_server [--port 27420] [--name "My Safari"]`.
|
||||
|
||||
| Input | Action |
|
||||
| --- | --- |
|
||||
| WASD / arrows | Move (camera-relative); hold Shift to run |
|
||||
| Space | Throw a Safari Capsule at the targeted Brandling |
|
||||
| F | Cast a line toward the water you face / reel in when it bites |
|
||||
| E | Talk to Professor Henry (advances dialogue too) |
|
||||
| Tab | Your Brandlings: Enter moves one between party and box |
|
||||
| Enter / T | Chat |
|
||||
| Q / E, right-drag, wheel | Camera |
|
||||
| Esc | Menu |
|
||||
| F1 / F12 | Render tuning panels / screenshot |
|
||||
|
||||
Your identity is a random token in `~/.local/share/brandling-safari/client.json`; the server
|
||||
keys your ranger, Brandlings and dex to it. `--profile NAME` uses a separate identity (several
|
||||
clients on one machine).
|
||||
|
||||
### Server
|
||||
|
||||
```
|
||||
safari_server [--port N] [--name NAME] [--db PATH] [--seed N] [--zone meadow]
|
||||
[--roster PATH] [--manifest PATH] [--day-minutes M] [--hour H]
|
||||
[--weather clear|cloudy|rain|storm|fog]
|
||||
```
|
||||
|
||||
Everything is saved in SQLite (`~/.local/share/brandling-safari/world.db` by default):
|
||||
players (name, look, position, capsules, intro), caught Brandlings, the per-player dex, the
|
||||
world clock and weather. Console commands: `help`, `players`, `time <h>`,
|
||||
`weather <name>`, `give <player> capsules <n>`, `spawn <species>`, `save`, `quit`.
|
||||
|
||||
`safari_bot` is a headless test client that walks into tall grass, throws capsules, fishes and
|
||||
talks to Henry, printing everything it receives.
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph Server [safari_server, 30 Hz, authoritative]
|
||||
G[Game: players, wild AI, spawns,<br/>fishing, captures, followers,<br/>clock + weather]
|
||||
DB[(SQLite)]
|
||||
G <--> DB
|
||||
end
|
||||
subgraph Client [safari_client]
|
||||
N[NetClient] --> W[World: prediction,<br/>interpolation, effects]
|
||||
W --> R[HD-2D Renderer]
|
||||
A[App: screens + UI] --> N
|
||||
end
|
||||
N <-- "ENet UDP: inputs, actions /<br/>snapshots, events" --> G
|
||||
S[shared/: Protocol, Zone,<br/>Movement, Roster, Appearance] --- G
|
||||
S --- W
|
||||
```
|
||||
|
||||
- `shared/` is compiled into both programs. `Zone` generates the whole zone deterministically
|
||||
from `(zone id, seed)`, so the server (collision, spawn points, water, tall grass) and every
|
||||
client (terrain, props, decoration) agree on the map and only the id + seed go over the
|
||||
wire. `Movement` is the single player-movement function: the server applies it once per
|
||||
input command, the client predicts with it and replays unacknowledged inputs when a
|
||||
snapshot arrives.
|
||||
- Clients send only intents: movement inputs (unreliable, last 4 resent) and actions (throw,
|
||||
cast, reel, talk, party, chat). The server validates everything (ranges, capsules, speed
|
||||
budget, walkability) and broadcasts snapshots (unreliable, 30 Hz) and events (reliable:
|
||||
emerge, splash, throw, capture result, bite, hook, catch...).
|
||||
- Protocol: `shared/Protocol.h`. Bump `kProtocolVersion` on any wire change.
|
||||
|
||||
| Path | What |
|
||||
| --- | --- |
|
||||
| `shared/` | protocol, ENet wrapper + LAN discovery, zone generator, movement, roster + appearance |
|
||||
| `server/` | dedicated server: game simulation, spawns, creatures, SQLite persistence |
|
||||
| `client/` | `App` (screens, HUD, input), `World` (scene, entities, effects), `CharacterSprite` (paper-doll compositor), `NetClient` |
|
||||
| `bot/` | headless test client |
|
||||
| `assets/` | characters, creatures (roster + sprites), models (`safari.glb`), dialogue |
|
||||
| `tools/` | art + data pipelines (below) |
|
||||
| `art_src/` | raw PixelLab output, caches and reports the tools build from |
|
||||
|
||||
## Content pipelines
|
||||
|
||||
The game ships the generated assets; the tools are only needed to change them. API keys go in
|
||||
`.env` here or in the parent folder (see `.env.example`).
|
||||
|
||||
### Brandlings (`tools/build_roster.py`)
|
||||
|
||||
```sh
|
||||
python3 tools/build_roster.py --csv ../clickup_web_design_export.csv [--limit N] [--jobs 16]
|
||||
```
|
||||
|
||||
Reads only the company name, domain, staging-site URL (logo search only, never stored), service
|
||||
list and logo-note colour words from the ClickUp export (the export itself holds private client
|
||||
data and is never committed). For each company: logo fetched from its domain, then its staging
|
||||
site (`Company_Sprite_Gen/logo_fetch.py`; a logo shared by 2+ companies is a template and is
|
||||
dropped), type from the jev classifier, sprite from Company_Sprite_Gen coloured from the logo
|
||||
(else the logo note's colour words, else a per-creature shade of the type colour), plus
|
||||
deterministic rarity, catch/flee rates and habitat. Writes `assets/creatures/roster.json`,
|
||||
`assets/creatures/sprites/`, a review `contact_sheet.png` and `art_src/creatures/report.json`
|
||||
(counts, logo hit rate by method, type histogram). Logos, classifier answers and renders are
|
||||
cached in `art_src/creatures/cache/`, so reruns only do new work. Later this will read from the
|
||||
ClickUp API instead of the CSV.
|
||||
|
||||
Species ids are permanent, because saved creatures store them and the loader requires
|
||||
`id == index`. The first run numbers species by slug; later runs keep every slug's id, append
|
||||
new companies after the last id, and keep companies that left the CSV as `"retired": true`
|
||||
entries (sprite kept) so no id is reused. A `--limit N` test run leaves unsampled species as
|
||||
they were. Retired Brandlings stay in players' collections but no longer spawn.
|
||||
|
||||
### Character art
|
||||
|
||||
`tools/character_art.py` builds the player layer library and Professor Henry with PixelLab;
|
||||
see [docs/CHARACTER_ART.md](docs/CHARACTER_ART.md) for how one base walk cycle animates every
|
||||
outfit and skin tone with 20 generations per item.
|
||||
|
||||
### 3D props
|
||||
|
||||
```sh
|
||||
python3 tools/safari_textures.py # painted textures -> assets/models/src/
|
||||
blender -b -P tools/blender_safari.py # -> assets/models/safari.glb
|
||||
```
|
||||
|
||||
Gate, tent, fences, lamps, signposts, dock, crates, barrels, benches and hay bales, following
|
||||
the engine's glTF conventions (see the engine README). Trees, bushes and rocks come from the
|
||||
engine's `scenery.glb`.
|
||||
|
||||
## Verification
|
||||
|
||||
Captures render in a hidden window into an offscreen target, so nothing appears on screen and
|
||||
keyboard input cannot disturb them:
|
||||
|
||||
```sh
|
||||
./build/safari_server --port 27500 --db /tmp/test.db &
|
||||
./build/safari_client --screenshot /tmp/play.png --frames 600 --connect 127.0.0.1:27500 \
|
||||
--auto-create --auto-dialogue --profile test --move 0.8,0.6 --run --key 450:space
|
||||
```
|
||||
|
||||
`--look body,skin,hair,hat,top,bottom,shoes[,colors]` sets the look, `--screen creator`
|
||||
captures the creator, `--hour` / `--weather` set the title backdrop, `--key frame:key`
|
||||
presses space / e / f / tab / enter on a frame, `--show` makes the window visible.
|
||||
19
art_src/characters/female/character.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"character_id": "8da7fe51-6fa3-4e15-b632-ccc8d58a0a8e",
|
||||
"payload": {
|
||||
"description": "young adult woman, bald shaved head, kind smiling face with big friendly eyes and eyelashes, plain white t-shirt, plain grey shorts, barefoot, light skin, pokemon trainer overworld sprite style",
|
||||
"image_size": {
|
||||
"width": 48,
|
||||
"height": 48
|
||||
},
|
||||
"view": "low top-down",
|
||||
"proportions": {
|
||||
"type": "preset",
|
||||
"name": "chibi"
|
||||
},
|
||||
"outline": "single color black outline",
|
||||
"shading": "basic shading",
|
||||
"detail": "medium detail",
|
||||
"seed": 2202
|
||||
}
|
||||
}
|
||||
4
art_src/characters/female/items/bottom_cargo/edit.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "change her grey shorts into baggy bright pure green cargo pants with side pockets that reach the ankles; keep the face, body, pose and everything else exactly identical",
|
||||
"seed": 93780
|
||||
}
|
||||
BIN
art_src/characters/female/items/bottom_cargo/frame_0.png
Normal file
|
After Width: | Height: | Size: 708 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_1.png
Normal file
|
After Width: | Height: | Size: 676 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_10.png
Normal file
|
After Width: | Height: | Size: 626 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_11.png
Normal file
|
After Width: | Height: | Size: 600 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_12.png
Normal file
|
After Width: | Height: | Size: 612 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_13.png
Normal file
|
After Width: | Height: | Size: 621 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_14.png
Normal file
|
After Width: | Height: | Size: 606 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_2.png
Normal file
|
After Width: | Height: | Size: 635 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_3.png
Normal file
|
After Width: | Height: | Size: 655 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_4.png
Normal file
|
After Width: | Height: | Size: 697 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_5.png
Normal file
|
After Width: | Height: | Size: 620 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_6.png
Normal file
|
After Width: | Height: | Size: 621 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_7.png
Normal file
|
After Width: | Height: | Size: 706 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_8.png
Normal file
|
After Width: | Height: | Size: 603 B |
BIN
art_src/characters/female/items/bottom_cargo/frame_9.png
Normal file
|
After Width: | Height: | Size: 708 B |
4
art_src/characters/female/items/bottom_pants/edit.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "change her grey shorts into bright pure green long straight pants that reach the ankles; keep the face, body, pose and everything else exactly identical",
|
||||
"seed": 11238
|
||||
}
|
||||
BIN
art_src/characters/female/items/bottom_pants/frame_0.png
Normal file
|
After Width: | Height: | Size: 633 B |
BIN
art_src/characters/female/items/bottom_pants/frame_1.png
Normal file
|
After Width: | Height: | Size: 627 B |
BIN
art_src/characters/female/items/bottom_pants/frame_10.png
Normal file
|
After Width: | Height: | Size: 541 B |
BIN
art_src/characters/female/items/bottom_pants/frame_11.png
Normal file
|
After Width: | Height: | Size: 580 B |
BIN
art_src/characters/female/items/bottom_pants/frame_12.png
Normal file
|
After Width: | Height: | Size: 563 B |
BIN
art_src/characters/female/items/bottom_pants/frame_13.png
Normal file
|
After Width: | Height: | Size: 536 B |
BIN
art_src/characters/female/items/bottom_pants/frame_14.png
Normal file
|
After Width: | Height: | Size: 551 B |
BIN
art_src/characters/female/items/bottom_pants/frame_2.png
Normal file
|
After Width: | Height: | Size: 581 B |
BIN
art_src/characters/female/items/bottom_pants/frame_3.png
Normal file
|
After Width: | Height: | Size: 608 B |
BIN
art_src/characters/female/items/bottom_pants/frame_4.png
Normal file
|
After Width: | Height: | Size: 628 B |
BIN
art_src/characters/female/items/bottom_pants/frame_5.png
Normal file
|
After Width: | Height: | Size: 590 B |
BIN
art_src/characters/female/items/bottom_pants/frame_6.png
Normal file
|
After Width: | Height: | Size: 604 B |
BIN
art_src/characters/female/items/bottom_pants/frame_7.png
Normal file
|
After Width: | Height: | Size: 622 B |
BIN
art_src/characters/female/items/bottom_pants/frame_8.png
Normal file
|
After Width: | Height: | Size: 581 B |
BIN
art_src/characters/female/items/bottom_pants/frame_9.png
Normal file
|
After Width: | Height: | Size: 666 B |
4
art_src/characters/female/items/bottom_skirt/edit.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "change her grey shorts into a bright pure green pleated knee-length skirt; keep the face, body, pose and everything else exactly identical",
|
||||
"seed": 26568
|
||||
}
|
||||
BIN
art_src/characters/female/items/bottom_skirt/frame_0.png
Normal file
|
After Width: | Height: | Size: 603 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_1.png
Normal file
|
After Width: | Height: | Size: 584 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_10.png
Normal file
|
After Width: | Height: | Size: 548 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_11.png
Normal file
|
After Width: | Height: | Size: 559 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_12.png
Normal file
|
After Width: | Height: | Size: 568 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_13.png
Normal file
|
After Width: | Height: | Size: 562 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_14.png
Normal file
|
After Width: | Height: | Size: 571 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_2.png
Normal file
|
After Width: | Height: | Size: 578 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_3.png
Normal file
|
After Width: | Height: | Size: 576 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_4.png
Normal file
|
After Width: | Height: | Size: 592 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_5.png
Normal file
|
After Width: | Height: | Size: 580 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_6.png
Normal file
|
After Width: | Height: | Size: 550 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_7.png
Normal file
|
After Width: | Height: | Size: 628 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_8.png
Normal file
|
After Width: | Height: | Size: 540 B |
BIN
art_src/characters/female/items/bottom_skirt/frame_9.png
Normal file
|
After Width: | Height: | Size: 653 B |
4
art_src/characters/female/items/hair_curly/edit.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "give her big round curly afro hair colored bright pure green; keep the face, body, pose and everything else exactly identical",
|
||||
"seed": 20341
|
||||
}
|
||||
BIN
art_src/characters/female/items/hair_curly/frame_0.png
Normal file
|
After Width: | Height: | Size: 1022 B |
BIN
art_src/characters/female/items/hair_curly/frame_1.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
art_src/characters/female/items/hair_curly/frame_10.png
Normal file
|
After Width: | Height: | Size: 748 B |
BIN
art_src/characters/female/items/hair_curly/frame_11.png
Normal file
|
After Width: | Height: | Size: 811 B |
BIN
art_src/characters/female/items/hair_curly/frame_12.png
Normal file
|
After Width: | Height: | Size: 755 B |
BIN
art_src/characters/female/items/hair_curly/frame_13.png
Normal file
|
After Width: | Height: | Size: 798 B |
BIN
art_src/characters/female/items/hair_curly/frame_14.png
Normal file
|
After Width: | Height: | Size: 803 B |
BIN
art_src/characters/female/items/hair_curly/frame_2.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
art_src/characters/female/items/hair_curly/frame_3.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
art_src/characters/female/items/hair_curly/frame_4.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
art_src/characters/female/items/hair_curly/frame_5.png
Normal file
|
After Width: | Height: | Size: 935 B |
BIN
art_src/characters/female/items/hair_curly/frame_6.png
Normal file
|
After Width: | Height: | Size: 993 B |
BIN
art_src/characters/female/items/hair_curly/frame_7.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
art_src/characters/female/items/hair_curly/frame_8.png
Normal file
|
After Width: | Height: | Size: 1007 B |
BIN
art_src/characters/female/items/hair_curly/frame_9.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
4
art_src/characters/female/items/hair_long/edit.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "give her long straight hair down past the shoulders, colored bright pure green; keep the face, body, pose and everything else exactly identical",
|
||||
"seed": 21166
|
||||
}
|
||||
BIN
art_src/characters/female/items/hair_long/frame_0.png
Normal file
|
After Width: | Height: | Size: 751 B |
BIN
art_src/characters/female/items/hair_long/frame_1.png
Normal file
|
After Width: | Height: | Size: 739 B |
BIN
art_src/characters/female/items/hair_long/frame_10.png
Normal file
|
After Width: | Height: | Size: 503 B |
BIN
art_src/characters/female/items/hair_long/frame_11.png
Normal file
|
After Width: | Height: | Size: 554 B |
BIN
art_src/characters/female/items/hair_long/frame_12.png
Normal file
|
After Width: | Height: | Size: 476 B |
BIN
art_src/characters/female/items/hair_long/frame_13.png
Normal file
|
After Width: | Height: | Size: 533 B |
BIN
art_src/characters/female/items/hair_long/frame_14.png
Normal file
|
After Width: | Height: | Size: 528 B |
BIN
art_src/characters/female/items/hair_long/frame_2.png
Normal file
|
After Width: | Height: | Size: 715 B |
BIN
art_src/characters/female/items/hair_long/frame_3.png
Normal file
|
After Width: | Height: | Size: 740 B |
BIN
art_src/characters/female/items/hair_long/frame_4.png
Normal file
|
After Width: | Height: | Size: 628 B |
BIN
art_src/characters/female/items/hair_long/frame_5.png
Normal file
|
After Width: | Height: | Size: 688 B |
BIN
art_src/characters/female/items/hair_long/frame_6.png
Normal file
|
After Width: | Height: | Size: 680 B |
BIN
art_src/characters/female/items/hair_long/frame_7.png
Normal file
|
After Width: | Height: | Size: 740 B |
BIN
art_src/characters/female/items/hair_long/frame_8.png
Normal file
|
After Width: | Height: | Size: 675 B |
BIN
art_src/characters/female/items/hair_long/frame_9.png
Normal file
|
After Width: | Height: | Size: 718 B |
4
art_src/characters/female/items/hair_ponytail/edit.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"description": "give her hair tied back in a high ponytail, colored bright pure green; keep the face, body, pose and everything else exactly identical",
|
||||
"seed": 40553
|
||||
}
|
||||
BIN
art_src/characters/female/items/hair_ponytail/frame_0.png
Normal file
|
After Width: | Height: | Size: 730 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_1.png
Normal file
|
After Width: | Height: | Size: 714 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_10.png
Normal file
|
After Width: | Height: | Size: 662 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_11.png
Normal file
|
After Width: | Height: | Size: 653 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_12.png
Normal file
|
After Width: | Height: | Size: 629 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_13.png
Normal file
|
After Width: | Height: | Size: 642 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_14.png
Normal file
|
After Width: | Height: | Size: 614 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_2.png
Normal file
|
After Width: | Height: | Size: 680 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_3.png
Normal file
|
After Width: | Height: | Size: 763 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_4.png
Normal file
|
After Width: | Height: | Size: 741 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_5.png
Normal file
|
After Width: | Height: | Size: 754 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_6.png
Normal file
|
After Width: | Height: | Size: 751 B |
BIN
art_src/characters/female/items/hair_ponytail/frame_7.png
Normal file
|
After Width: | Height: | Size: 803 B |