Merge remote-tracking branch 'origin/dev'

This commit is contained in:
mibi88 2024-08-01 11:02:17 +02:00
commit b5759bd95d
102 changed files with 2392 additions and 1516 deletions

12
.clang-format Normal file
View file

@ -0,0 +1,12 @@
BasedOnStyle: LLVM
IndentWidth: 4
PointerAlignment: Right
SpaceBeforeAssignmentOperators: true
SpaceBeforeRangeBasedForLoopColon: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpaceBeforeParens: Never
IndentCaseBlocks: true
IncludeBlocks: Regroup
AllowShortBlocksOnASingleLine: Empty
ColumnLimit: 80

2
.gitignore vendored
View file

@ -2,6 +2,7 @@
/build-fx /build-fx
/build-cg /build-cg
/build-cg-push /build-cg-push
/build-fxg3a
/*.g1a /*.g1a
/*.g3a /*.g3a
@ -13,5 +14,4 @@ __pycache__/
*.sublime-workspace *.sublime-workspace
.vscode .vscode
level*.json
tilesetnpp.json tilesetnpp.json

6
.gitmodules vendored Normal file
View file

@ -0,0 +1,6 @@
[submodule "assets/tinytiled"]
path = assets/tinytiled
url = https://git.planet-casio.com/mibi88/tinytiled
[submodule "assets/--force"]
path = assets/--force
url = https://git.planet-casio.com/mibi88/tinytiled

View file

@ -4,18 +4,24 @@
cmake_minimum_required(VERSION 3.15) cmake_minimum_required(VERSION 3.15)
project(MyAddin) project(MyAddin)
#set the color mode either to 1b or 2b
set(COLORMODE_fx 1b)
#set the color mode either to 1b, 2b or EGA64
set(COLORMODE_cg EGA64)
if(NOT "${COLORMODE_cg}" STREQUAL EGA64)
set(FXSDK_PLATFORM_LONG fx9860G_G3A)
set(FXSDK_PLATFORM fx)
endif()
include(GenerateG1A) include(GenerateG1A)
include(GenerateG3A) include(GenerateG3A)
include(Fxconv) include(Fxconv)
find_package(Gint 2.9 REQUIRED) find_package(Gint 2.11 REQUIRED)
# Gint 2.11 is required, because we're using the new macros like GINT_RENDER_RGB
find_package(LibProf 2.4 REQUIRED) find_package(LibProf 2.4 REQUIRED)
#set the color mode either to 1b or 2b
set(COLORMODE_fx 2b)
#set the color mode either to 1b, 2b or EGA64
set(COLORMODE_cg EGA64)
fxconv_declare_converters(assets/converters.py) fxconv_declare_converters(assets/converters.py)
set(SOURCES set(SOURCES
@ -26,44 +32,53 @@ set(SOURCES
src/game.c src/game.c
src/dialogs.c src/dialogs.c
src/npc.c src/npc.c
src/events.c
# ... # ...
) )
# Shared assets, fx-9860G-only assets and fx-CG-50-only assets # Shared assets, fx-9860G-only assets and fx-CG-50-only assets
set(ASSETS set(ASSETS
assets/WorldRPG.world assets/level0_dialogs.json
assets/level1_dialogs.json
assets/level2_dialogs.json
assets/level3_dialogs.json
assets/level4_dialogs.json
assets/level0.tmx
assets/level1.tmx
assets/level2.tmx
assets/level3.tmx
assets/level4.tmx
assets/interior1_0_dialogs.json
assets/interior1_0.tmx
# ... # ...
) )
set(ASSETS_cg set(ASSETS_cg
assets-cg/demo_player.png assets-cg/player_male.png
assets-cg/demo_PNJ.png assets-cg/player_female.png
assets-cg/npc/char/npc_male.png
assets-cg/npc/char/npc_female.png
assets-cg/npc/char/npc_milkman.png
assets-cg/npc/char/npc_police.png
assets-cg/SignAction.png assets-cg/SignAction.png
assets-cg/NPC_Icon.png assets-cg/npc/face/npc_male.png
assets-cg/npc/face/npc_female.png
assets-cg/npc/face/npc_milkman.png
assets-cg/npc/face/npc_police.png
assets-cg/SGN_Icon.png assets-cg/SGN_Icon.png
assets-cg/INFO_Icon.png assets-cg/INFO_Icon.png
assets-cg/player_face.png assets-cg/player_face.png
assets-cg/font.png assets-cg/font.png
) )
set(ASSETS_cg_1b
assets-cg/1b/tileset/tileset1b_CG.png
)
set(ASSETS_cg_2b
assets-cg/2b/tileset/tileset2b_CG.png
)
set(ASSETS_cg_EGA64 set(ASSETS_cg_EGA64
assets-cg/ega64/tileset/tilesetEGA64_CG.png assets-cg/ega64/tileset/tilesetEGA64_CG.png
) )
set(ASSETS_fx set(ASSETS_fx
assets-fx/demo_player.png assets-fx/player_male.png
assets-fx/demo_PNJ.png assets-fx/player_female.png
assets-fx/SignAction.png assets-fx/SignAction.png
assets-fx/NPC_Icon.png
assets-fx/SGN_Icon.png assets-fx/SGN_Icon.png
assets-fx/INFO_Icon.png
assets-fx/player_face.png assets-fx/player_face.png
assets-fx/font.png assets-fx/font.png
# ... # ...
@ -71,11 +86,29 @@ set(ASSETS_fx
set(ASSETS_fx_1b set(ASSETS_fx_1b
assets-fx/1b/tileset/tileset1b.png assets-fx/1b/tileset/tileset1b.png
assets-fx/1b/npc/char/npc_male.png
assets-fx/1b/npc/char/npc_female.png
assets-fx/1b/npc/char/npc_milkman.png
assets-fx/1b/npc/char/npc_police.png
assets-fx/1b/npc/face/npc_male.png
assets-fx/1b/npc/face/npc_female.png
assets-fx/1b/npc/face/npc_milkman.png
assets-fx/1b/npc/face/npc_police.png
assets-fx/1b/INFO_Icon.png
# ... # ...
) )
set(ASSETS_fx_2b set(ASSETS_fx_2b
assets-fx/2b/tileset/tileset2b.png assets-fx/2b/tileset/tileset2b.png
assets-fx/2b/npc/char/npc_male.png
assets-fx/2b/npc/char/npc_female.png
assets-fx/2b/npc/char/npc_milkman.png
assets-fx/2b/npc/char/npc_police.png
assets-fx/2b/npc/face/npc_male.png
assets-fx/2b/npc/face/npc_female.png
assets-fx/2b/npc/face/npc_milkman.png
assets-fx/2b/npc/face/npc_police.png
assets-fx/1b/INFO_Icon.png
# ... # ...
) )
@ -85,29 +118,8 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_fx}} ) add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_fx}} )
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_cg}} ) add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_cg}} )
endif() elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
add_executable(myaddin ${SOURCES} ${ASSETS} ${ASSETS_${FXSDK_PLATFORM}} ${ASSETS_${FXSDK_PLATFORM}_${COLORMODE_fx}} )
# fx colormode
if("${COLORMODE_fx}" STREQUAL 1b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR1BIT)
endif()
if("${COLORMODE_fx}" STREQUAL 2b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR2BIT)
endif()
# cg colormode
if("${COLORMODE_cg}" STREQUAL 1b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR1BIT)
endif()
if("${COLORMODE_cg}" STREQUAL 2b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOR2BIT)
endif()
if("${COLORMODE_cg}" STREQUAL EGA64)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -DCOLOREGA)
endif() endif()
target_link_options(myaddin PRIVATE -Wl,-Map=Build_Addin.map -Wl,--print-memory-usage) target_link_options(myaddin PRIVATE -Wl,-Map=Build_Addin.map -Wl,--print-memory-usage)
@ -115,6 +127,14 @@ target_link_libraries(myaddin LibProf::LibProf Gint::Gint)
if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G) if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
# fx colormode
if("${COLORMODE_fx}" STREQUAL 1b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -g -DCOLOR1BIT)
endif()
if("${COLORMODE_fx}" STREQUAL 2b)
target_compile_options(myaddin PRIVATE -Wall -Wextra -Os -g -DCOLOR2BIT)
endif()
if("${COLORMODE_fx}" STREQUAL 1b) if("${COLORMODE_fx}" STREQUAL 1b)
generate_g1a(TARGET myaddin OUTPUT "RPG_1b.g1a" generate_g1a(TARGET myaddin OUTPUT "RPG_1b.g1a"
@ -127,16 +147,21 @@ if("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G)
endif() endif()
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50) elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
# cg colormode
if("${COLORMODE_cg}" STREQUAL EGA64)
target_compile_options(myaddin PRIVATE -Wall -Wextra -O0 -g -DCOLOREGA)
endif()
if("${COLORMODE_cg}" STREQUAL 1b) if("${COLORMODE_cg}" STREQUAL 1b)
generate_g3a(TARGET myaddin OUTPUT "RPG_1b.g3a" generate_g3a(TARGET myaddin OUTPUT "RPG_1bfx.g3a"
NAME "RPG PC 1b" ICONS assets-cg/1b/icon-uns-1b.png assets-cg/1b/icon-sel-1b.png) NAME "RPG PC 1b fx" ICONS assets-cg/1b/icon-uns-1b.png assets-cg/1b/icon-sel-1b.png)
endif() endif()
if("${COLORMODE_cg}" STREQUAL 2b) if("${COLORMODE_cg}" STREQUAL 2b)
generate_g3a(TARGET myaddin OUTPUT "RPG_2b.g3a" generate_g3a(TARGET myaddin OUTPUT "RPG_2bfx.g3a"
NAME "RPG PC 2b" ICONS assets-cg/2b/icon-uns-2b.png assets-cg/2b/icon-sel-2b.png) NAME "RPG PC 2b fx" ICONS assets-cg/2b/icon-uns-2b.png assets-cg/2b/icon-sel-2b.png)
endif() endif()
if("${COLORMODE_cg}" STREQUAL EGA64) if("${COLORMODE_cg}" STREQUAL EGA64)
@ -144,4 +169,19 @@ elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fxCG50)
NAME "RPG PC EGA" ICONS assets-cg/ega64/icon-uns-ega64.png assets-cg/ega64/icon-sel-ega64.png) NAME "RPG PC EGA" ICONS assets-cg/ega64/icon-uns-ega64.png assets-cg/ega64/icon-sel-ega64.png)
endif() endif()
elseif("${FXSDK_PLATFORM_LONG}" STREQUAL fx9860G_G3A)
if("${COLORMODE_fx}" STREQUAL 1b)
generate_g3a(TARGET myaddin OUTPUT "RPG_1bfx.g3a"
NAME "RPG PC 1b fx" ICONS assets-cg/1b/icon-uns-1b.png assets-cg/1b/icon-sel-1b.png)
endif()
if("${COLORMODE_fx}" STREQUAL 2b)
generate_g3a(TARGET myaddin OUTPUT "RPG_2bfx.g3a"
NAME "RPG PC 2b fx" ICONS assets-cg/2b/icon-uns-2b.png assets-cg/2b/icon-sel-2b.png)
endif()
endif() endif()

26
PROJECT_STRUCTURE.md Normal file
View file

@ -0,0 +1,26 @@
# Project structure
* `assets` contains the tiled maps, and the tiled map converters.
* `assets-cg` contains the assets for cg calculators like the cg-50.
* `assets-fx` contains the assets for monochrome calculators.
* `captures` contains screenshots.
* `src` This folder contains the source code.
* `config.h` This header file contains defines for the size of various
things on screen, like the size of a tile in the tilemap, the size of the
dialog box, etc.
* `dialogs.c` and `dialogs.h` contain various functions to display dialogs
and also let the user respond.
* `events.c` and `events.h` parse tags in the messages that are displayed
using the dialogs procedures to modify variables (and soon, call
procedures).
* `game.c` and `game.h` handles the rendering, the input, etc.
* `main.c` handles the USB connection and the gint gray rendering, for 2bpp
rendering on monochrome calculators. Contains the mainloop. Also contains
code to display debug informations.
* `map.c` and `map.h` contain code to render, get a tile in the map, see if
the tile is walkable, etc.
* `mapdata.h` contains the available maps.
* `memory.c` and `memory.h` procedures to handle arrays (currently: search
in an array of short ints).
* `npc.c` and `npc.h` npc rendering and movement (and soon pathfinding).
* `player.c` and `player.h` handle the player movement, collision, etc.

View file

@ -2,7 +2,12 @@
Plus d'infos sur ce projet ici : [Le projet Collaboratif de PC](https://www.planet-casio.com/Fr/forums/topic17343-last-projet-collaboratif-avec-toute-la-commu.html) Plus d'infos sur ce projet ici : [Le projet Collaboratif de PC](https://www.planet-casio.com/Fr/forums/topic17343-last-projet-collaboratif-avec-toute-la-commu.html)
## Avencement du projet ## Contribuer!
Style du code [STYLE.md](STYLE.md).
Structure du projet [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md).
## Avancement du projet
A ce stade, on a déjà implémenté : A ce stade, on a déjà implémenté :
@ -13,12 +18,13 @@ A ce stade, on a déjà implémenté :
- [x] Multiple cartes avec importation automatique des fichiers `world` issus de Tiled - [x] Multiple cartes avec importation automatique des fichiers `world` issus de Tiled
- [x] Carte Multilayer (Background, Foreground + accessibilité / Dommages) avec transparence du calque Foreground - [x] Carte Multilayer (Background, Foreground + accessibilité / Dommages) avec transparence du calque Foreground
- [x] Personnage - [x] Personnage
- [x] Dialogues avec fichiers externes `json` et séquenceage possible de ceux-ci via un arbre d'histoire (sauts de lignes et mots plus grands que l'écran pas supportés) - [x] Dialogues avec fichiers externes `json` et séquenceage possible de ceux-ci via un arbre d'histoire (sauts de lignes et mots plus grands que l'écran pas supportés + limite d'un kibibyte)
- [x] Fontes de caractères - [x] Fontes de caractères
- [x] Interaction - [x] Interaction
- [ ] NPC - [ ] NPC
- [x] Changement de map durant le jeu - [x] Changement de map durant le jeu
- [ ] Système d'événements - [ ] Système d'événements
- [ ] Pathfinding
## Crédits ## Crédits

44
README_en.md Normal file
View file

@ -0,0 +1,44 @@
# Planet Casio Collaborative Project
(maybe I should've used google translate)
More informations can be found here (in french):
[Le projet Collaboratif de PC](https://www.planet-casio.com/Fr/forums/topic17343-last-projet-collaboratif-avec-toute-la-commu.html)
## Contribute!
Style guidelines [STYLE.md](STYLE.md).
Project structure [PROJECT_STRUCTURE.md](PROJECT_STRUCTURE.md).
## Current state
What we've implemented so far:
- [x] Screenshots via USB
- [x] Displaying the current map at the players position
- [x] Handling keyboard inputs
- [x] Handling collisions.
- [x] Multiple maps with automatic `world` files import (made with Tiled)
- [x] Multilayer map (Background, Foreground + accessibility / damage) with
foreground layer transparency.
- [x] Player character.
- [x] Dialogs from external `json` files (line jumps and words bigger than the
screen are unsupported + 1 kibibyte per message limit)
- [x] Font
- [x] Interaction
- [ ] NPC
- [x] Changing map in game.
- [ ] Event system
- [ ] Pathfinding
## Credits
The tiles are from Game Boy Top-down RPG Fantasy Tileset (FREE)
"Background Assets by Gumpy Function (gumpyfunction.itch.io)"
[Tiles Background Assets by Gumpy Function](https://gumpyfunction.itch.io/game-boy-rpg-fantasy-tileset-free)
Converted to greyscale with gimp.
1-bit (black and white) version by Shadow15510
CG (palette EGA64) color version by Fcalva

14
STYLE.md Normal file
View file

@ -0,0 +1,14 @@
# Style guidelines in Collab RPG
(Mibi88) Fcalva, SlyVTT: What do you think of this?
Variables names in sneak_case.
Name your procedures as following: `filename_whatitdoes`.
The procedures are documented using sphinx.
We're using `clang-formatter` to keep the code readable. Please run it before
committing your code as following: `clang-format -i *` in the `src` folder.
Have I forgotten something?

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7 KiB

After

Width:  |  Height:  |  Size: 920 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

After

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 683 B

After

Width:  |  Height:  |  Size: 637 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

BIN
assets-cg/ega64/tileset/tilesetEGA64_CG.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -1,11 +1,7 @@
*.png: *.png:
custom-type: custom-image custom-type: bopti-image
name_regex: (.*)\.png \1_img name_regex: (.*)\.png \1_img
profile: p8 profile: p8
scale: 2
demo_PNG.png:
scale: 1
font.png: font.png:
name: fontRPG name: fontRPG

View file

@ -0,0 +1,15 @@
npc_male.png:
type: bopti-image
name: tiny_npc_male
npc_female.png:
type: bopti-image
name: tiny_npc_female
npc_milkman.png:
type: bopti-image
name: tiny_npc_milkman
npc_police.png:
type: bopti-image
name: tiny_npc_police

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

View file

@ -0,0 +1,12 @@
npc_male.png:
type: bopti-image
name: npc_male
npc_female.png:
type: bopti-image
name: npc_female
npc_milkman.png:
type: bopti-image
name: npc_milkman
npc_police.png:
type: bopti-image
name: npc_police

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,000 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 246 B

BIN
assets-cg/player_female.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

BIN
assets-cg/player_male.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

BIN
assets-fx/1b/INFO_Icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

View file

@ -0,0 +1,3 @@
INFO_Icon.png:
type: bopti-image
name: INFO_Icon_img

View file

@ -0,0 +1,12 @@
npc_male.png:
type: bopti-image
name: tiny_npc_male
npc_female.png:
type: bopti-image
name: tiny_npc_female
npc_milkman.png:
type: bopti-image
name: tiny_npc_milkman
npc_police.png:
type: bopti-image
name: tiny_npc_police

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 B

View file

@ -0,0 +1,12 @@
npc_male.png:
type: bopti-image
name: npc_male
npc_female.png:
type: bopti-image
name: npc_female
npc_milkman.png:
type: bopti-image
name: npc_milkman
npc_police.png:
type: bopti-image
name: npc_police

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -0,0 +1,3 @@
INFO_Icon.png:
type: bopti-image
name: INFO_Icon_img

View file

@ -0,0 +1,12 @@
npc_male.png:
type: bopti-image
name: tiny_npc_male
npc_female.png:
type: bopti-image
name: tiny_npc_female
npc_milkman.png:
type: bopti-image
name: tiny_npc_milkman
npc_police.png:
type: bopti-image
name: tiny_npc_police

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 B

View file

@ -0,0 +1,12 @@
npc_male.png:
type: bopti-image
name: npc_male
npc_female.png:
type: bopti-image
name: npc_female
npc_milkman.png:
type: bopti-image
name: npc_milkman
npc_police.png:
type: bopti-image
name: npc_police

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
assets-fx/2bpp_palette.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 B

View file

@ -1,10 +1,9 @@
demo_player.png: player_male.png:
type: bopti-image type: bopti-image
name: demo_player_img name: player_male_img
player_female.png:
demo_PNJ.png:
type: bopti-image type: bopti-image
name: demo_PNJ_img name: player_female_img
player_face.png: player_face.png:
type: bopti-image type: bopti-image
@ -14,14 +13,6 @@ SignAction.png:
type: bopti-image type: bopti-image
name: SignAction_img name: SignAction_img
INFO_Icon.png:
type: bopti-image
name: INFO_Icon_img
NPC_Icon.png:
type: bopti-image
name: NPC_Icon_img
SGN_Icon.png: SGN_Icon.png:
type: bopti-image type: bopti-image
name: SGN_Icon_img name: SGN_Icon_img

BIN
assets-fx/player_female.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

BIN
assets-fx/player_male.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

View file

@ -27,6 +27,13 @@
"width": 384, "width": 384,
"x": 384, "x": 384,
"y": 192 "y": 192
},
{
"fileName": "level4.tmx",
"height": 192,
"width": 384,
"x": 384,
"y": 384
} }
], ],
"onlyShowAdjacentMaps": false, "onlyShowAdjacentMaps": false,

View file

@ -1,405 +1,392 @@
from random import randint """
from PIL import Image This is the main converter script. It uses the tiled.py script to handle the
import fxconv tiled maps.
We're trying to follow the PEP, so please read PEP 8 (if you haven't already):
https://peps.python.org/pep-0008/, so please write variable names in sneak_case
and class names in PascalCase.
To improve the lisibility of this code, please document your methods, add
comments (yes, it's hard to add the right amount of comments), and add type
hints, to avoid bugs and make it easy to understand how to use them.
To document your methods, you should read PEP 257:
https://peps.python.org/pep-0257/.
Thanks,
Mibi88
"""
import xml.etree.ElementTree as ET
import json import json
import pathlib
import csv
import os import os
import sys
# Add the assets folder to the path, to be able to import the tiled script.
def convert(input, output, params, target): sys.path.append("../assets/")
if params["custom-type"] == "map": import fxconv
print("ERROR : Asset ", params["name"], " has legacy type map") from tinytiled import *
return 1
elif params["custom-type"] == "world": # If the output of the converter should be verbose.
convert_world(input, output, params, target) VERBOSE = 1
return 0 # The sign types, used to find the sign icon.
elif params["custom-type"] == "custom-image": SIGN_TYPES = ["SGN", "INFO"]
convert_custom_image(input, output, params, target) # The NPC faces, used to find the face id.
return 0 FACES = ["MALE", "FEMALE", "MILKMAN", "POLICE"]
elif params["custom-type"] == "font": # The precision of the fixed point numbers.
convert_font(input, output, params, target) # WARNING: The PRECISION define in config.h should contain the same value!
return 0 PRECISION = 8
elif params["custom-type"] == "dialogs":
print("ERROR : Asset ", params["name"], " has legacy type dialog") def convert(input: str, output: str, params: dict, target):
#convert_dialogs(input, output, params, target) """
return 0 This method gets called by fxconv for each asset to convert.
else: """
return 1 if params["custom-type"] == "tmx":
convert_map(input, output, params, target)
return 0
elif params["custom-type"] == "dialog":
def convert_world(input, output, params, target): convert_dialog(input, output, params, target)
print( "WE ARE COMPUTING THE WORLD", input ) return 0
data = json.load(open(input, "r")) def convert_map(input: str, output: str, params: dict, target):
nbMaps = ["fileName" in i for i in data["maps"]].count(True) """
print( "We have to treat ", nbMaps, " maps") Convert a map.
print( "So let's go ... ") """
if VERBOSE: print(f"INFO: Converting map {input} -> {output}")
structWorld = fxconv.Structure() input_map = Map(input)
#structExtra = fxconv.Structure() dialog_file = ""
background_layer = []
for i in range(nbMaps): foreground_layer = []
nameMap = data["maps"][i]["fileName"].replace(".tmx","") walkable_layer = []
nameMapFree = nameMap.split("/")[-1] map_x = 0
#count the number of "back" (cd ..) to locate the map on the computer map_y = 0
nbRetour = nameMap.count("..")+1 width = 0
#create the map absolute path height = 0
outdoor_tileset = None
nameTMX = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".tmx" walkable_tileset = None
nameJSON = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json" dialog_num = 0
dialog_ids = []
commandline = 'tiled --export-map json ' + nameTMX + ' ' + nameJSON
print( "TILED COMMAND LINE FOR MAPS : ", commandline ) npc_paths = {}
os.system( commandline ) npcs = {}
signs = {}
mapPath = "/".join(input.split("/")[:-nbRetour]) + "/" + nameMap + ".json" portals = {}
print("Map ", i , " name : ", mapPath )
name = os.path.splitext(os.path.basename(input))[0]
xmin = data["maps"][i]["x"]
print( "xmin = ", xmin ) map_struct = fxconv.Structure()
ymin = data["maps"][i]["y"] # Get the dialog file
print( "ymin = ", ymin ) try:
if VERBOSE: print("INFO: Getting the dialog file")
xmax = data["maps"][i]["x"] + data["maps"][i]["width"] dialog_file = input_map.get_property("dialogFile")
print( "xmax = ", xmax ) if VERBOSE: print(f"INFO: Dialog file: {dialog_file}.")
except Exception as e:
ymax = data["maps"][i]["y"] + data["maps"][i]["height"] # Show a simple error message on failure.
print( "ymax = ", ymax ) sys.stderr.write(f"ERROR: Failed to get the dialog file.\n"
+ f" Error message: {e}\n")
map = get_tile_map_data( mapPath, output, params, target, xmin, ymin, xmax, ymax) sys.exit(1)
print( "Map = ", map )
structWorld += fxconv.ptr( map ) # Get the map position
try:
structWorld += fxconv.u32(0) if VERBOSE: print("INFO: Getting the map position")
map_x = int(input_map.get_property("mapX"))
#generate ! map_y = int(input_map.get_property("mapY"))
fxconv.elf(structWorld, output, "_" + params["name"], **target) if VERBOSE: print(f"INFO: Map position: ({map_x}, {map_y}).")
except Exception as e:
# Show a simple error message on failure.
def get_tile_map_data(input, output, params, target, xmin, ymin, xmax, ymax): sys.stderr.write(f"ERROR: Failed to get the map position.\n"
print( "WE ARE COMPUTING THE MAP : ", input ) + f" Error message: {e}\n")
data = json.load(open(input, "r")) sys.exit(1)
#find the tileset in use. it's a relative path (like ../tileset.tsx) # Get informations about dialogs
nameTileset = data["tilesets"][0]["source"].replace(".tsx","") try:
print(nameTileset) if VERBOSE: print("INFO: Getting informations about dialogs")
#the name of the tileset without the .something with open(f"{input_map.parent_dir}/{dialog_file}", "r") as file:
nameTilesetFree = nameTileset.split("/")[-1] dialog_data = json.load(file)
#count the number of "back" (cd ..) to locate the tileset on the computer dialog_num = len(dialog_data["dialogs"])
nbRetour = nameTileset.count("..")+1 for i in dialog_data["dialogs"]:
#create the tileset absolute path dialog_ids.append(i["ID"])
tilesetTSX = "/".join(input.split("/")[:-nbRetour]) + "/" + nameTileset + ".tsx" except Exception as e:
tilesetJSON = "/".join(input.split("/")[:-nbRetour]) + "/" + nameTileset + ".json" # Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get informations about dialogs.\n"
commandline = 'tiled --export-tileset json ' + tilesetTSX + ' ' + tilesetJSON + f" Error message: {e}\n")
print( "TILED COMMAND LINE FOR TILESET : ", commandline ) sys.exit(1)
os.system( commandline )
# Get the outdoor tileset
tileset = open(tilesetJSON, "r") try:
data_tileset = json.load(tileset) if VERBOSE: print("INFO: Getting the outdoor tileset")
tileset_size = data_tileset.get("columns") outdoor_tileset = input_map.get_tileset_by_firstgid(1)
tileset.close() except Exception as e:
# Show a simple error message on failure.
#find the ID of the first tile in the walkable tileset () sys.stderr.write(f"ERROR: Failed to get the outdoor tileset.\n"
indexWalkable = data["tilesets"][1]["firstgid"] + f" Error message: {e}\n")
print(indexWalkable) sys.exit(1)
#Extract from the json the width, height # Get the walkable tileset
w, h = data["width"], data["height"] try:
if VERBOSE: print("INFO: Getting the walkable tileset")
#nbTileLayer is the number of "true" layers (without ObjectsLayer) walkable_tileset = input_map.get_tileset_by_firstgid(409)
nbTilelayer = ["data" in i for i in data["layers"]].count(True) - 1 except Exception as e:
print( nbTilelayer) # Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the walkable tileset.\n"
#index of the various layers (may change from one map to another) + f" Error message: {e}\n")
layer_walkable = 0 sys.exit(1)
layer_foreground = 0
layer_background = 0 # Get the background
try:
#create the structure of the map if VERBOSE: print("INFO: Getting the background layer")
structMap = fxconv.Structure() bg_layer = input_map.get_layer_by_name("Background")
# The bg layer will be used to set the map width and height.
structMap += fxconv.u32(w) + fxconv.u32(h) + fxconv.u32(nbTilelayer) width = bg_layer.get_width()
structMap += fxconv.u32(tileset_size) height = bg_layer.get_height()
if VERBOSE: print(f"INFO: Map size: ({width}, {height}).")
structMap += fxconv.u32(xmin) + fxconv.u32(ymin) + fxconv.u32(xmax) + fxconv.u32(ymax) # Get the layer data himself
background_layer = bg_layer.get_data_with_tileset(outdoor_tileset)
structMap += fxconv.ref(f"img_{nameTilesetFree}") # Check if the size of the layer data is correct.
if len(background_layer) != width*height:
raise Exception("Bad layer size!")
#extraction of the data contained in the layer "Walkable" of the map if VERBOSE: print("INFO: Layer data has the right size.")
for i in range(nbTilelayer+1): except Exception as e:
datavalid = data["layers"][i] # Show a simple error message on failure.
if datavalid["name"]=="Walkable": sys.stderr.write(f"ERROR: Failed to get the background layer.\n"
layer_walkable = i + f" Error message: {e}\n")
print( "Walkable Tile Data in layer : ", layer_walkable) sys.exit(1)
break
elif i==nbTilelayer: # Get the foreground
print( "ERROR : No Walkable layer data !!!" ) try:
if VERBOSE: print("INFO: Getting the foreground layer")
walk_data = bytes() fg_layer = input_map.get_layer_by_name("Foreground")
layer = data["layers"][layer_walkable] # Get the layer data himself
for tile in layer["data"]: foreground_layer = fg_layer.get_data_with_tileset(outdoor_tileset)
#print( tile ) # Check if the size of the layer data is correct.
if tile == 0: walk_data += fxconv.u8(tile) #if walkable_data = 0 then it is a blanck cell so nothing to change if len(foreground_layer) != width*height:
else : walk_data += fxconv.u8(tile-indexWalkable) #if !=0 than we need to shift the tile number by considering the first tileID (given by indexwalkable) raise Exception("Bad layer size!")
structMap += fxconv.ptr(walk_data) if VERBOSE: print("INFO: Layer data has the right size.")
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the foreground layer.\n"
+ f" Error message: {e}\n")
nbextra = 0 sys.exit(1)
extradata = fxconv.Structure()
# Get the walkable layer
nbextra, extradata = get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax) try:
if VERBOSE: print("INFO: Getting the walkable layer")
if (nbextra==0): wk_layer = input_map.get_layer_by_name("Walkable")
structMap += fxconv.u32( 0 ) # Get the layer data himself
structMap += fxconv.u32( 0 ) walkable_layer = wk_layer.get_data_with_tileset(walkable_tileset)
else: # Check if the size of the layer data is correct.
structMap += fxconv.u32( int(nbextra) ) if len(walkable_layer) != width*height:
structMap += fxconv.ptr( extradata ) raise Exception("Bad layer size!")
if VERBOSE: print("INFO: Layer data has the right size.")
except Exception as e:
# Show a simple error message on failure.
sys.stderr.write(f"ERROR: Failed to get the walkable layer.\n"
nameDialog = data["properties"][0]["value"] + f" Error message: {e}\n")
dialogfile = "/".join(input.split("/")[:-nbRetour]) + "/" + nameDialog sys.exit(1)
print( "THE DIALOGS ARE CONTAINED IN THE FILE : ", dialogfile )
# Get the extra data
nbdiag = 0 try:
diagdata = fxconv.Structure() if VERBOSE: print("INFO: Getting the extra data")
ed_objgroup = input_map.get_objectgroup_by_name("ExtraData")
nbdiag, diagdata = convert_dialogs(dialogfile, output, params, target) # Get the paths the NPCs take.
for object in ed_objgroup.objects:
if (nbdiag==0): if object.get_data_type() == "polyline":
structMap += fxconv.u32( 0 ) npc_paths[object.id] = object.get_data()
structMap += fxconv.u32( 0 ) # Get the NPCs
else: for object in ed_objgroup.objects:
structMap += fxconv.u32( int(nbdiag) ) if object.get_data_type() == "point" and object.type == "NPC":
structMap += fxconv.ptr( diagdata ) path = [0, 0]
if int(object.get_property("hasPath")):
if object.get_property("path") in npc_paths:
path = npc_paths[object.get_property("path")]
#extraction of the data contained in the layer "Background" and "Foreground" of the map else:
raise Exception("Path required but not found!")
dialog_id = 0
#import the Background layer of the map has_dialog = 0
for i in range(nbTilelayer+1): try:
datavalid = data["layers"][i] dialog_id = int(object.get_property("dialogID"))
if datavalid["name"]=="Background": has_dialog = 1
layer_background = i except:
print( "Background Tile Data in layer : ", layer_background) pass
break data = {
elif i==nbTilelayer: "position": object.get_data(),
print( "ERROR : No Background layer data !!!" ) "name": object.name,
"needAction": int(object.get_property("needAction")),
layer_data = bytes() "dialogID": dialog_id,
layer = data["layers"][layer_background] "hasDialog": has_dialog,
for tile in layer["data"]: "face": FACES.index(object.get_property("face")),
layer_data += fxconv.u16(tile-1) "path": path
structMap += fxconv.ptr(layer_data) }
npcs[object.id] = data
# Get the signs
for object in ed_objgroup.objects:
#import the foreground layer of the map if object.get_data_type() == "point" and object.type in SIGN_TYPES:
for i in range(nbTilelayer+1): data = {
datavalid = data["layers"][i] "position": object.get_data(),
if datavalid["name"]=="Foreground": "name": object.name,
layer_foreground = i "needAction": int(object.get_property("needAction")),
print( "Foreground Tile Data in layer : ", layer_foreground) "dialogID": int(object.get_property("dialogID")),
break "icon": SIGN_TYPES.index(object.type)
elif i==nbTilelayer: }
printf( "ERROR : No Foreground layer data !!!" ) signs[object.id] = data
# Get the portals
layer_data = bytes() for object in ed_objgroup.objects:
layer = data["layers"][layer_foreground] if (object.get_data_type() == "rectangle"
for tile in layer["data"]: and object.type == "PORTAL"):
layer_data += fxconv.u16(tile-1) data = {
structMap += fxconv.ptr(layer_data) "rect": object.get_data(),
"name": object.name,
"dest": object.get_property("dest"),
return structMap "destPortal": object.get_property("destPortal")
}
portals[object.id] = data
except Exception as e:
def get_extra_map_data(input, output, params, target, xmin, ymin, xmax, ymax): # Show a simple error message on failure.
print( "WE ARE COMPUTING THE EXTRA DATA OF THE MAP : ", input ) sys.stderr.write(f"ERROR: Failed to get the extra data.\n"
data = json.load(open(input, "r")) + f" Error message: {e}\n")
sys.exit(1)
nblayer = ["id" in i for i in data["layers"]].count(True) - 1 # Generate the structs
print( "I found ", nblayer, " of extradata") # Map struct
map_struct += fxconv.u32(map_x)
#index of the various layers (may change from one map to another) map_struct += fxconv.u32(map_y)
layer_extradata = 0 map_struct += fxconv.u32(width)
map_struct += fxconv.u32(height)
#import the foreground layer of the map map_struct += fxconv.u32(3)
for i in range(nblayer+1): map_struct += fxconv.u32(outdoor_tileset.columns)
datavalid = data["layers"][i] tileset_name = os.path.splitext(os.path.basename(outdoor_tileset.source))[0]
if datavalid["name"]=="ExtraData": map_struct += fxconv.ref(f"img_{tileset_name}")
layer_extradata = i
print( "Extra Data in layer : ", layer_extradata) # Store the walkable layer
break walkable_data = bytes()
elif i==nblayer: for i in walkable_layer:
print( "ERROR : No ExtraData layer data !!!" ) if i < 0: i = 0
return 0, fxconv.u32(0) walkable_data += fxconv.u8(i)
map_struct += fxconv.ptr(walkable_data)
#create the structure of the map
structData = fxconv.Structure() # Load NPCs
map_struct += fxconv.u32(len(npcs))
nbExtraData = 0 npc_struct = fxconv.Structure()
layer = data["layers"][layer_extradata] for i in npcs.values():
for i in layer["objects"]: # Convert currentpos to a fixed point value.
npc_struct += fxconv.u32((i["position"][0]+i["path"][0])<<PRECISION)
#get the type of the item npc_struct += fxconv.u32((i["position"][1]+i["path"][1])<<PRECISION)
tpe = i["type"] npc_struct += fxconv.u32(i["position"][0])
npc_struct += fxconv.u32(i["position"][1])
#we check if the type corresponds to a items of type Point in Tiled npc_struct += fxconv.u16(i["face"])
if tpe in ( "SGN", "NPC", "INFO" ): npc_struct += fxconv.u8(0)
npc_struct += fxconv.u8(i["hasDialog"])
nbExtraData = nbExtraData + 1 npc_struct += fxconv.u32(i["dialogID"])
x = i["x"] + xmin npc_struct += fxconv.u32(i["needAction"])
y = i["y"] + ymin npc_struct += fxconv.string(i["name"])
nme = i["name"] npc_struct += fxconv.u32(len(i["path"]) > 2)
npc_struct += fxconv.u32(len(i["path"])//2)
npc_struct += fxconv.u32(0)
dialogID = None
needAction = None xpath = bytes()
path = 0 ypath = bytes()
path_length = 0 x = True
xdata = None for n in i["path"]:
ydata = None if x: xpath += fxconv.u16(n)
else: ypath += fxconv.u16(n)
#we now fill all the properties of this item x = not x
for j in i["properties"]:
#property "dialog" npc_struct += fxconv.ptr(xpath)
if j["name"]=="dialogID": dialogID = j[ "value" ] npc_struct += fxconv.ptr(ypath)
#property "isQuestion"
elif j["name"]=="needAction": needAction = j[ "value" ] npc_struct += fxconv.u32(0) # TODO: Type
npc_struct += fxconv.u8(0) # TODO: Group
else: npc_struct += fxconv.u8(0) # TODO: Hostile to
#Extra properties for NPCs (path) npc_struct += fxconv.u16(0) # TODO: Padding (what is it ?)
if tpe=="NPC": map_struct += fxconv.ptr(npc_struct)
if j["name"]=="hasPath": # Load signs
pathID = None map_struct += fxconv.u32(len(signs))
path = j[ "value" ] sign_struct = fxconv.Structure()
if path==1: for i in signs.values():
print( "PNJ has path - NOW LOOKING FOR RELEVANT DATA" ) # Create a sign struct for each sign.
sign_struct += fxconv.u32(i["position"][0])
# we start looking for path data with first the ID of the path Object sign_struct += fxconv.u32(i["position"][1])
for u in i["properties"]: sign_struct += fxconv.u32(i["icon"])
if u["name"]=="path": sign_struct += fxconv.string(i["name"])
pathID = u[ "value" ] sign_struct += fxconv.u32(i["dialogID"])
print( "path ID is identified : ID= ", pathID ) sign_struct += fxconv.u32(i["needAction"])
map_struct += fxconv.ptr(sign_struct)
for v in layer["objects"]: # Load portals
if v[ "id" ] == pathID: map_struct += fxconv.u32(len(portals))
print( "path data found : " ) portal_struct = fxconv.Structure()
for i in portals.values():
xdata = bytes() dest_file_name = os.path.splitext(os.path.basename(i["dest"]))[0]
ydata = bytes() dest_portal = i["destPortal"]
portal_name = i["name"]
for w in v[ "polyline" ]: if VERBOSE: print(f"INFO: Storing portal {name}_{portal_name}")
path_length = path_length + 1 portal_struct += fxconv.sym(f"{name}_{portal_name}")
print( "X= ", w[ "x" ], " Y= ", w[ "y" ] ) # Add the collider
xdata += fxconv.u16( int( w[ "x" ] ) ) rect = i["rect"]
ydata += fxconv.u16( int( w[ "y" ] ) ) portal_struct += fxconv.u32(rect[0])
portal_struct += fxconv.u32(rect[1])
else: portal_struct += fxconv.u32(rect[2])
print( "PNJ has no Path" ) portal_struct += fxconv.u32(rect[3])
# Add a reference to the destination portal
else: portal_struct += fxconv.ref(f"{dest_file_name}_{dest_portal}")
print( "UNIDENTIFIED PROPERTY : ", j["name"]) portal_struct += fxconv.ref(f"{dest_file_name}")
map_struct += fxconv.ptr(portal_struct)
print( "OBJECT X= ", x, " Y= ", y, "STR= ", dialogID ) map_struct += fxconv.u32(dialog_num)
print( " Type= ", tpe, " Name= ", nme )
print( " Action?= ", needAction ) # Get the name of the dialog file and create a reference to it: it is built
# separately.
dialog_name = os.path.splitext(os.path.basename(dialog_file))[0]
map_struct += fxconv.ref(f"_{dialog_name}")
structData += fxconv.u32( int(x) )
structData += fxconv.u32( int(y) ) # Store the background layer
structData += fxconv.string( nme ) background_data = bytes()
structData += fxconv.string( tpe ) for i in background_layer:
structData += fxconv.u32( int(dialogID) ) background_data += fxconv.u16(i)
structData += fxconv.u32( int(needAction) ) map_struct += fxconv.ptr(background_data)
if path==0: # Store the foreground layer
structData += fxconv.u32(0) foreground_data = bytes()
structData += fxconv.u32(0) for i in foreground_layer:
structData += fxconv.u32(0) foreground_data += fxconv.u16(i)
structData += fxconv.u32(0) map_struct += fxconv.ptr(foreground_data)
else:
o_xdata = fxconv.Structure() # Create the fxconv object
o_xdata += xdata fxconv.elf(map_struct, output, f"_{name}", **target)
o_ydata = fxconv.Structure()
o_ydata += ydata def convert_dialog(input: str, output: str, params: dict, target):
"""
structData += fxconv.u32(path) Convert a JSON dialog file.
structData += fxconv.u32(path_length) """
structData += fxconv.ptr(o_xdata) if VERBOSE: print(f"INFO: Converting dialog file {input} -> {output}")
structData += fxconv.ptr(o_ydata)
# Load the JSON dialog file.
#else we do nothing (yet) dialog_data = None
else: try:
print( "Skip this object" ) with open(input, "r") as file:
dialog_data = json.load(file)
except Exception as e:
return nbExtraData, structData sys.stderr.write(f"ERROR: Failed parse json.\n"
+ f" Error message: {e}\n")
sys.exit(1)
def convert_custom_image(input, output, params, target):
scale = int(params.get("scale", 1)) # Create the dialog struct
dialog_struct = fxconv.Structure()
# Upscale image before converting try:
im = Image.open(input) for i in dialog_data["dialogs"]:
im = im.resize((im.width * scale, im.height * scale), # Create a dialog structure for each dialog.
resample=Image.NEAREST) dialog_id = i["ID"]
dialog_struct += fxconv.u32(dialog_id)
o = fxconv.convert_image_cg(im, params) dialog_struct += fxconv.string(i["dialog"])
fxconv.elf(o, output, "_" + params["name"], **target) dialog_struct += fxconv.u32(i["isQuestion"])
dialog_struct += fxconv.string(i["choice"].replace('$', '\0'))
dialog_struct += fxconv.string(i["conclusion1"])
dialog_struct += fxconv.u32(i["next1"])
def convert_font(input, output, params, target): dialog_struct += fxconv.string(i["conclusion2"])
o = fxconv.convert_topti(input, params) dialog_struct += fxconv.u32(i["next2"])
fxconv.elf(o, output, "_" + params["name"], **target) dialog_struct += fxconv.u32(i["nextOther"])
# Save this struct
name = os.path.splitext(os.path.basename(input))[0]
fxconv.elf(dialog_struct, output, f"__{name}", **target)
def convert_dialogs(input, output, params, target): except Exception as e:
# Show an error message if the conversion fails.
print( "WE ARE COMPUTING THE DIALOGS FROM : ", input ) sys.stderr.write(f"ERROR: Failed convert dialogs.\n"
data = json.load(open(input, "r")) + f" Error message: {e}\n")
sys.exit(1)
structDialogs = fxconv.Structure()
nbdialogs = 0
for d in data["dialogs"]:
print( int(d[ "ID" ]))
# print( d[ "dialog" ] )
print( int(d[ "isQuestion" ]) )
# print( d[ "choice" ].replace('$', chr(0)) )
# print( d[ "conclusion1" ] )
# print( int(d[ "next1" ] ) )
# print( d[ "conclusion2" ] )
# print( int(d[ "next2" ] ) )
# print( int(d[ "nextOther" ]) )
nbdialogs = nbdialogs + 1
structDialogs += fxconv.u32( int(d[ "ID" ] ) )
structDialogs += fxconv.string( d[ "dialog" ] )
structDialogs += fxconv.u32( int(d[ "isQuestion" ] ) )
structDialogs += fxconv.string( d[ "choice" ].replace('$', chr(0)) )
structDialogs += fxconv.string( d[ "conclusion1" ] )
structDialogs += fxconv.u32( int(d[ "next1" ] ) )
structDialogs += fxconv.string( d[ "conclusion2" ] )
structDialogs += fxconv.u32( int(d[ "next2" ] ) )
structDialogs += fxconv.u32( int(d[ "nextOther" ] ) )
return nbdialogs, structDialogs
#fxconv.elf(structDialogs, output, "_" + params["name"], **target)

View file

@ -1,7 +1,47 @@
WorldRPG.world: level0.tmx:
custom-type: world custom-type: tmx
name: worldRPG name: level0
#DialogsRPG.json: level1.tmx:
# custom-type: dialogs custom-type: tmx
# name: dialogRPG name: level1
level2.tmx:
custom-type: tmx
name: level2
level3.tmx:
custom-type: tmx
name: level3
level4.tmx:
custom-type: tmx
name: level4
level0_dialogs.json:
custom-type: dialog
name: level0_dialogs
level1_dialogs.json:
custom-type: dialog
name: level1_dialogs
level2_dialogs.json:
custom-type: dialog
name: level2_dialogs
level3_dialogs.json:
custom-type: dialog
name: level3_dialogs
level4_dialogs.json:
custom-type: dialog
name: level4_dialogs
interior1_0.tmx:
custom-type: tmx
name: level0
interior1_0_dialogs.json:
custom-type: dialog
name: interior1_0_dialogs

54
assets/interior1_0.tmx Normal file
View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="12" height="8" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="3">
<properties>
<property name="dialogFile" type="file" value="interior1_0_dialogs.json"/>
<property name="mapX" type="int" value="65536"/>
<property name="mapY" type="int" value="65536"/>
</properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/>
<layer id="1" name="Background" width="12" height="8">
<data encoding="csv">
86,90,91,89,90,91,89,90,91,89,90,92,
110,114,115,113,114,115,113,114,115,113,114,116,
86,93,94,1,1,1,1,1,9,10,1,92,
110,117,118,1,1,1,1,1,33,34,1,116,
86,1,1,1,1,1,1,1,1,1,1,92,
110,1,1,1,1,133,2,1,1,1,1,116,
110,1,1,1,1,2,2,1,1,1,1,92,
110,114,114,114,114,114,114,114,114,114,114,116
</data>
</layer>
<layer id="2" name="Foreground" width="12" height="8">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="3" name="Walkable" width="12" height="8">
<data encoding="csv">
410,410,410,410,410,410,410,410,410,410,410,410,
410,410,410,410,410,410,410,410,410,410,410,410,
410,410,410,0,0,0,0,0,410,0,0,410,
410,410,410,0,0,0,0,0,410,0,0,410,
410,0,0,0,0,0,0,0,0,0,0,410,
410,0,0,0,0,0,0,0,0,0,0,410,
410,0,0,0,0,0,0,0,0,0,0,410,
410,410,410,410,410,410,410,410,410,410,410,410
</data>
</layer>
<objectgroup id="4" name="ExtraData">
<object id="2" name="porte" type="PORTAL" x="39.6736" y="40.0979" width="15.8058" height="15.9119">
<properties>
<property name="dest" type="file" value="level0.tmx"/>
<property name="destPortal" value="taverne"/>
</properties>
</object>
</objectgroup>
</map>

View file

@ -0,0 +1,13 @@
{ "dialogs":[
{ "ID":0,
"dialog":"_",
"isQuestion":0,
"choice":"_",
"conclusion1":"_",
"next1":-1,
"conclusion2":"_",
"next2":-1,
"nextOther":1
}
]
}

View file

@ -1,32 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="8" nextobjectid="14"> <map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="8" nextobjectid="17">
<editorsettings> <editorsettings>
<export target="level0.json" format="json"/> <export target="level0.json" format="json"/>
</editorsettings> </editorsettings>
<properties> <properties>
<property name="dialogFile" type="file" value="DialogsLvl0.json"/> <property name="dialogFile" type="file" value="level0_dialogs.json"/>
<property name="mapX" type="int" value="0"/>
<property name="mapY" type="int" value="0"/>
</properties> </properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/> <tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/> <tileset firstgid="409" source="Walkable.tsx"/>
<layer id="1" name="Background" width="48" height="24"> <layer id="1" name="Background" width="48" height="24">
<data encoding="csv"> <data encoding="csv">
2,297,298,299,300,2,386,297,298,299,300,2,2,2,2,2,2,337,338,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,2,2,2,345,346,347,348,2,337,338, 2,297,298,299,300,2,386,297,298,299,300,2,2,2,2,2,2,337,338,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,2,2,2,345,346,347,348,2,337,338,
253,205,229,205,229,280,179,180,179,156,156,156,158,157,179,180,253,361,362,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,25,26,27,117,118,28,369,370,371,372,2,361,362, 253,205,229,205,229,280,179,180,179,156,156,156,158,157,179,180,253,361,362,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,25,358,359,117,118,28,369,370,371,372,2,361,362,
301,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,301,2,386,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,49,9,10,134,135,52,393,394,395,396,337,338,2, 301,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,301,2,386,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,382,9,10,134,135,360,393,394,395,396,337,338,2,
325,149,150,151,152,2,2,327,374,375,327,2,2,185,374,375,325,387,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,73,33,34,74,219,76,2,2,2,2,361,362,2, 325,149,150,151,152,2,2,327,374,375,327,2,2,185,374,375,325,387,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,406,33,34,2,219,384,2,2,2,2,361,362,2,
257,2,2,385,2,2,385,2,265,266,2,2,208,209,352,353,257,2,2,2,2,2,2,297,298,299,300,2,2,2,2,25,26,27,27,97,98,99,98,99,100,26,26,27,28,131,2,2, 257,2,2,385,2,2,385,2,265,266,2,2,208,209,352,353,257,2,2,2,2,2,2,297,298,299,300,2,2,2,2,25,358,359,358,97,407,408,407,408,100,358,358,359,28,131,2,2,
281,176,2,2,2,2,176,385,289,290,2,2,232,233,376,377,281,2,326,2,154,153,190,2,2,2,2,2,2,2,2,49,2,2,2,121,59,60,60,61,124,2,2,2,52,132,2,2, 281,176,2,2,2,2,176,385,289,290,2,2,232,233,376,377,281,2,326,2,154,153,190,2,2,2,2,2,2,2,2,382,2,2,2,121,59,60,60,61,124,2,2,2,360,132,2,2,
2,2,2,2,2,385,2,2,265,266,2,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,73,2,2,2,145,83,84,84,85,148,2,2,2,76,132,2,2, 2,2,2,2,2,385,2,2,265,266,2,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,406,2,2,2,145,83,84,84,85,148,2,2,2,384,132,2,2,
2,2,2,2,326,2,385,2,265,266,2,2,2,2,2,2,2,2,2,2,2,2,190,2,2,2,2,2,2,385,2,49,404,405,2,169,107,108,108,109,172,2,402,403,76,132,2,2, 2,2,2,2,326,2,385,2,265,266,2,2,2,2,2,2,2,2,2,2,2,2,190,2,2,2,2,2,2,385,2,406,404,405,2,169,107,108,108,109,172,2,402,403,384,132,2,2,
2,2,2,2,2,2,2,2,289,290,2,258,259,260,238,239,260,260,261,262,262,263,264,2,2,2,2,2,2,2,385,49,134,135,2,2,2,2,2,2,2,2,134,135,52,132,297,298, 2,2,2,2,2,2,2,2,289,290,2,258,259,260,238,239,260,260,261,262,262,263,264,2,2,2,2,2,2,2,385,382,134,135,2,2,2,2,2,2,2,2,134,135,360,132,297,298,
2,2,2,2,2,2,2,2,265,266,2,282,283,284,285,285,285,285,285,285,286,287,288,297,298,299,300,2,117,118,2,73,373,2,217,2,190,373,373,190,2,219,2,373,76,132,2,2, 2,2,2,2,2,2,2,2,265,266,2,282,283,284,285,285,285,285,285,285,286,287,288,297,298,299,300,2,117,118,2,382,373,2,217,2,190,373,373,190,2,219,2,373,384,132,2,2,
297,298,299,300,2,2,2,2,290,2,2,306,307,308,309,308,309,308,309,310,310,311,312,131,2,339,340,2,134,135,2,97,98,99,99,98,99,2,2,98,98,99,98,99,100,132,2,2, 297,298,299,300,2,2,2,2,290,2,2,306,307,308,309,308,309,308,309,310,310,311,312,131,2,339,340,2,134,135,2,97,407,408,408,408,408,19,18,407,408,408,407,408,100,132,2,2,
2,2,2,386,2,2,2,2,2,2,2,330,331,332,333,332,333,332,333,334,334,335,336,132,2,363,364,2,2,2,2,121,122,122,122,123,124,81,82,121,122,123,122,123,124,132,2,2, 2,2,2,386,2,2,2,2,2,2,2,330,331,332,333,332,333,332,333,334,334,335,336,132,2,363,364,2,2,2,2,121,122,122,122,123,124,81,82,121,122,123,122,123,124,132,2,2,
2,2,2,386,297,298,299,300,2,290,2,162,163,164,165,162,163,164,165,162,163,164,165,132,2,2,2,2,2,2,2,145,146,146,146,147,148,57,58,145,146,147,146,147,148,132,2,2, 2,2,2,386,297,298,299,300,2,290,2,162,163,164,165,162,163,164,165,162,163,164,165,132,2,2,2,2,2,2,2,145,146,146,146,147,148,57,58,145,146,147,146,147,148,132,2,2,
2,2,2,2,2,2,2,2,2,2,2,86,87,88,89,186,187,188,189,86,87,88,89,132,385,2,2,2,2,2,2,169,170,170,170,171,172,81,82,169,170,171,14,15,27,26,27,27, 2,2,2,2,2,2,2,2,2,2,2,86,87,88,89,186,187,188,189,86,87,88,89,132,385,2,2,2,2,2,2,169,170,170,170,171,172,81,82,169,170,171,14,15,42,358,359,359,
2,2,2,2,270,271,271,271,272,2,2,110,111,112,113,210,211,212,213,110,111,112,113,133,2,2,2,2,2,2,2,2,2,2,2,2,2,290,265,265,266,266,38,39,2,2,2,51, 2,2,2,2,270,271,271,271,272,2,2,110,111,112,113,210,211,212,213,110,111,112,113,133,2,2,2,2,2,2,2,2,2,2,2,2,2,290,265,265,266,266,38,39,19,2,2,2,
298,299,300,2,294,1,1,1,296,2,2,2,2,2,2,234,290,265,237,2,2,2,339,340,385,2,2,2,2,2,2,327,2,2,2,160,161,386,266,289,290,265,62,63,73,74,75,75, 298,299,300,2,294,1,1,1,296,2,2,2,2,2,2,234,290,265,237,2,2,2,339,340,385,2,2,2,2,2,2,327,2,2,2,160,161,386,266,289,290,265,62,63,406,2,2,2,
2,2,2,2,294,1,1,1,296,2,2,160,161,265,266,266,265,266,290,2,2,2,363,364,2,297,298,299,300,2,2,2,2,2,2,2,2,266,290,2,2,2,2,2,97,98,99,99, 2,2,2,2,294,1,1,1,296,2,2,160,161,265,266,266,265,266,290,2,2,2,363,364,2,297,298,299,300,2,2,2,2,2,2,2,2,266,290,2,2,2,2,2,97,407,408,408,
2,2,2,2,318,319,319,319,320,2,386,266,266,289,290,265,266,241,265,266,266,265,266,241,385,2,2,2,241,265,266,266,265,386,265,266,266,265,266,2,2,2,2,2,121,122,123,123, 2,2,2,2,318,319,319,319,320,2,386,266,266,289,290,265,266,241,265,266,266,265,266,241,385,2,2,2,241,265,266,266,265,386,265,266,266,265,266,2,2,2,2,2,121,122,123,123,
2,2,2,2,2,2,2,2,2,385,289,290,386,265,265,2,2,241,289,290,265,266,290,266,265,266,266,386,266,289,290,265,266,290,289,385,265,266,290,2,2,2,2,2,145,146,147,147, 2,2,2,2,2,2,2,2,2,385,289,290,386,265,265,2,2,241,289,290,265,266,290,266,265,266,266,386,266,289,290,265,266,290,289,385,265,266,290,2,2,2,2,2,145,146,147,147,
2,2,2,2,2,2,2,2,2,2,2,2,2,265,386,2,2,2,2,2,2,2,241,241,289,290,265,266,290,241,2,2,2,2,2,2,21,22,23,24,2,2,254,255,169,170,171,171, 2,2,2,2,2,2,2,2,2,2,2,2,2,265,386,2,2,2,2,2,2,2,241,241,289,290,265,266,290,241,2,2,2,2,2,2,21,22,23,24,2,2,254,255,169,170,171,171,
@ -68,28 +70,28 @@
<data encoding="csv"> <data encoding="csv">
0,0,410,410,0,0,0,0,410,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,410,410,410,410,0,410,410, 0,0,410,410,0,0,0,0,410,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,410,410,410,410,0,410,410,
410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,410,410, 410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,410,410,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,0,0,0,0,410,410,410,410,410,410,410,0, 410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,0,0,0,0,410,410,410,410,410,410,410,0,
410,410,410,410,410,0,0,410,410,410,410,0,0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,410,410,0, 410,410,410,410,410,0,0,410,410,410,410,0,0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,410,410,0,
410,0,0,0,0,0,0,0,0,0,0,0,410,411,411,411,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0, 410,0,0,412,0,0,0,0,0,0,0,0,410,411,411,411,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,411,411,411,411,410,0,410,0,410,410,410,0,0,0,0,0,0,0,0,410,0,0,0,410,410,410,410,410,410,0,0,0,410,0,0,0, 410,0,0,0,0,0,0,0,0,0,0,0,411,411,411,411,410,0,410,0,410,410,410,0,0,0,0,0,0,0,0,410,0,0,0,410,410,410,410,410,410,0,0,0,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,0,0,0,410,410,410,410,410,410,0,0,0,410,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,0,0,0,410,410,410,410,410,410,0,0,0,410,0,0,0,
0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,410,410,0,410,410,0,0,410,410,0,410,410,410,0,0,0, 0,0,0,0,410,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,412,0,410,410,410,0,410,410,0,0,410,410,0,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,410, 0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,412,410,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,410,
0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,410,410,0,0,410,410,0,410,0,0,0,0,410,0,0,410,0,0,0,0,410,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,410,410,0,0,410,410,0,410,0,0,0,0,410,0,0,410,0,0,0,0,410,0,0,0,
0,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,0,0,0, 0,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,0,0,0, 0,0,0,412,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,410,410,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,0,0,0, 0,0,0,412,0,410,410,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,0,0,410,410,410, 0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,412,0,0,0,0,0,0,410,410,410,410,410,410,0,0,410,410,410,410,0,0,410,410,410,
0,0,0,0,412,412,412,412,412,0,0,410,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,412,412,412,412,412,0,0,410,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
410,410,0,0,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,410,0,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0, 410,410,0,0,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,412,0,0,0,0,0,0,410,0,0,0,410,410,0,0,0,0,0,0,410,410,0,0,0,
0,0,0,0,412,412,412,412,412,0,0,410,410,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410, 0,0,0,0,412,412,412,412,412,0,0,410,410,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,
0,0,0,0,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410, 0,0,0,0,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,410,410,410,410,410,410, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,410,410,410,410,410,410,
410,410,0,0,0,0,0,410,410,410,410,410,0,0,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0, 410,410,0,0,0,0,0,410,410,410,410,410,0,0,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,410,410,410,410,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,0,0,0,0,0,0,0, 0,0,412,0,0,0,0,410,410,410,410,410,0,0,0,0,410,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,410,410,410,410,410,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,410,410,410,410,410,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,410,410,0,410,410,410,410,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0 0,0,0,0,410,410,0,410,410,410,410,410,0,0,0,0,410,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0
</data> </data>
</layer> </layer>
<objectgroup id="4" name="ExtraData"> <objectgroup id="4" name="ExtraData">
@ -117,6 +119,7 @@
<object id="12" name="PNJ3" type="NPC" x="267.25" y="125.75"> <object id="12" name="PNJ3" type="NPC" x="267.25" y="125.75">
<properties> <properties>
<property name="dialogID" type="int" value="12"/> <property name="dialogID" type="int" value="12"/>
<property name="face" value="FEMALE"/>
<property name="hasPath" type="int" value="1"/> <property name="hasPath" type="int" value="1"/>
<property name="needAction" type="int" value="1"/> <property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="13"/> <property name="path" type="object" value="13"/>
@ -126,6 +129,7 @@
<object id="2" name="PNJ2" type="NPC" x="164" y="132"> <object id="2" name="PNJ2" type="NPC" x="164" y="132">
<properties> <properties>
<property name="dialogID" type="int" value="5"/> <property name="dialogID" type="int" value="5"/>
<property name="face" value="MALE"/>
<property name="hasPath" type="int" value="0"/> <property name="hasPath" type="int" value="0"/>
<property name="needAction" type="int" value="1"/> <property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="0"/> <property name="path" type="object" value="0"/>
@ -135,6 +139,7 @@
<object id="10" name="PNJ1" type="NPC" x="252" y="164"> <object id="10" name="PNJ1" type="NPC" x="252" y="164">
<properties> <properties>
<property name="dialogID" type="int" value="7"/> <property name="dialogID" type="int" value="7"/>
<property name="face" value="MILKMAN"/>
<property name="hasPath" type="int" value="1"/> <property name="hasPath" type="int" value="1"/>
<property name="needAction" type="int" value="1"/> <property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="9"/> <property name="path" type="object" value="9"/>
@ -168,5 +173,11 @@
<object id="13" name="Chemin 100pas Client Auberge" type="TRJ" x="267.25" y="126.25"> <object id="13" name="Chemin 100pas Client Auberge" type="TRJ" x="267.25" y="126.25">
<polyline points="0,0 -30.5,16.75 -182.5,15.75 -195.25,-26 -183.25,16.5 -29.25,18.5"/> <polyline points="0,0 -30.5,16.75 -182.5,15.75 -195.25,-26 -183.25,16.5 -29.25,18.5"/>
</object> </object>
<object id="16" name="taverne" type="PORTAL" x="128.974" y="111.676" width="14.7688" height="7.99134">
<properties>
<property name="dest" type="file" value="interior1_0.tmx"/>
<property name="destPortal" value="porte"/>
</properties>
</object>
</objectgroup> </objectgroup>
</map> </map>

View file

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="4"> <map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="4">
<properties> <properties>
<property name="dialogFile" type="file" value="DialogsLvl1.json"/> <property name="dialogFile" type="file" value="level1_dialogs.json"/>
<property name="mapX" type="int" value="48"/>
<property name="mapY" type="int" value="0"/>
</properties> </properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/> <tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/> <tileset firstgid="409" source="Walkable.tsx"/>
@ -20,10 +22,10 @@
2,2,269,1,1,1,1,1,1,319,319,269,1,1,1,316,271,316,271,317,1,1,1,1,319,319,319,268,268,319,319,319,268,319,320,2,2,318,319,320,268,269,1,1,1,1,1,1, 2,2,269,1,1,1,1,1,1,319,319,269,1,1,1,316,271,316,271,317,1,1,1,1,319,319,319,268,268,319,319,319,268,319,320,2,2,318,319,320,268,269,1,1,1,1,1,1,
2,2,2,269,1,1,1,1,320,2,2,2,269,1,1,1,1,1,1,1,1,1,267,2,2,2,2,2,2,2,2,2,2,2,2,2,2,219,2,2,2,318,319,320,269,1,1,1, 2,2,2,269,1,1,1,1,320,2,2,2,269,1,1,1,1,1,1,1,1,1,267,2,2,2,2,2,2,2,2,2,2,2,2,2,2,219,2,2,2,318,319,320,269,1,1,1,
2,2,2,2,319,268,319,320,2,2,2,2,318,319,269,1,1,1,1,1,1,267,2,2,2,2,313,265,242,266,241,219,314,313,242,241,2,2,219,2,2,2,2,2,2,269,1,1, 2,2,2,2,319,268,319,320,2,2,2,2,318,319,269,1,1,1,1,1,1,267,2,2,2,2,313,265,242,266,241,219,314,313,242,241,2,2,219,2,2,2,2,2,2,269,1,1,
27,26,27,26,27,28,2,2,2,2,2,2,2,2,318,319,319,268,268,319,319,320,2,2,2,219,2,2,2,2,266,241,289,290,266,265,2,2,2,297,298,299,300,2,2,318,319,320, 359,358,359,358,359,28,2,2,2,2,2,2,2,2,318,319,319,268,268,319,319,320,2,2,2,219,2,2,2,2,266,241,289,290,266,265,2,2,2,297,298,299,300,2,2,318,319,320,
2,50,51,51,99,100,132,2,2,2,2,2,2,2,2,2,2,2,2,314,265,2,2,2,2,313,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,18,407,100,132,2,2,2,2,2,2,2,2,2,2,2,2,314,265,2,2,2,2,313,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,74,75,76,16,17,133,2,2,2,2,2,2,2,2,2,2,2,241,219,290,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,42,16,17,133,2,2,2,2,2,2,2,2,2,2,2,241,219,290,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
98,98,99,100,40,41,290,314,297,298,299,300,2,2,2,2,2,219,219,289,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,2, 408,407,407,408,40,41,290,314,297,298,299,300,2,2,2,2,2,219,219,289,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,2,
121,122,123,124,64,65,265,289,313,289,241,265,219,2,2,2,2,290,314,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,402,403,2,374,375,2,404,405,2,2,2,2,2,2, 121,122,123,124,64,65,265,289,313,289,241,265,219,2,2,2,2,290,314,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,402,403,2,374,375,2,404,405,2,2,2,2,2,2,
145,146,147,148,132,2,2,2,2,2,2,314,314,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 145,146,147,148,132,2,2,2,2,2,2,314,314,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
169,170,171,172,133,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,2,2,2, 169,170,171,172,133,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,385,2,2,2,2,2,2,2,2,2,2,2,2,
@ -79,13 +81,13 @@
410,410,410,410,410,410,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,412,412,412, 410,410,410,410,410,410,0,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,412,412,412,
0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0, 410,410,409,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,
410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,0,410,410,0,410,410,0,0,0,0,0,0, 410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,410,410,0,410,410,0,410,410,0,0,0,0,0,0,
410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
410,410,410,410,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 410,410,410,410,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,410,410,0, 0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,410,410,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data> </data>
</layer> </layer>
@ -100,13 +102,14 @@
<object id="2" name="Gardien" type="NPC" x="303.636" y="117.273"> <object id="2" name="Gardien" type="NPC" x="303.636" y="117.273">
<properties> <properties>
<property name="dialogID" type="int" value="1"/> <property name="dialogID" type="int" value="1"/>
<property name="face" value="POLICE"/>
<property name="hasPath" type="int" value="1"/> <property name="hasPath" type="int" value="1"/>
<property name="needAction" type="int" value="1"/> <property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="3"/> <property name="path" type="object" value="3"/>
</properties> </properties>
<point/> <point/>
</object> </object>
<object id="3" name="Chemin Gardien" x="303.818" y="117.455"> <object id="3" name="Chemin Gardien" type="TRJ" x="303.818" y="117.455">
<properties> <properties>
<property name="dialogID" type="int" value="0"/> <property name="dialogID" type="int" value="0"/>
<property name="needAction" type="int" value="1"/> <property name="needAction" type="int" value="1"/>

View file

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="5"> <map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="5">
<properties> <properties>
<property name="dialogFile" type="file" value="DialogsLvl2.json"/> <property name="dialogFile" type="file" value="level2_dialogs.json"/>
<property name="mapX" type="int" value="0"/>
<property name="mapY" type="int" value="24"/>
</properties> </properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/> <tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/> <tileset firstgid="409" source="Walkable.tsx"/>
@ -11,13 +13,13 @@
2,2,2,2,2,386,2,2,2,2,2,277,2,386,266,2,349,385,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2, 2,2,2,2,2,386,2,2,2,2,2,277,2,386,266,2,349,385,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,2,2,2,
298,299,300,2,2,2,2,385,385,2,2,301,2,266,290,2,349,2,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 298,299,300,2,2,2,2,385,385,2,2,301,2,266,290,2,349,2,385,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2,386,2,2,256,2,265,266,2,257,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,297,298,299,258,259,262,330,333,333,336,262,263,264,2,2,2, 2,2,2,2,2,2,2,2,386,2,2,256,2,265,266,2,257,2,2,2,2,2,2,2,2,2,2,2,297,298,299,300,297,298,299,258,259,262,330,333,333,336,262,263,264,2,2,2,
2,2,2,2,2,2,2,2,386,386,2,281,2,266,290,2,280,2,2,2,2,2,2,2,2,2,386,2,2,2,2,2,2,2,2,283,283,3,91,87,88,92,3,312,288,2,385,2, 2,2,2,2,2,2,2,2,386,386,2,281,2,266,290,2,280,2,2,2,2,2,2,2,2,2,386,2,2,2,2,2,2,2,2,283,283,5,91,87,88,92,5,312,288,2,385,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,290,266,2,2,2,385,2,297,298,299,300,2,2,2,2,2,2,2,9,10,2,2,283,283,3,115,111,112,113,3,312,312,131,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,290,266,2,2,2,385,2,297,298,299,300,2,2,2,2,2,2,2,9,10,2,2,283,283,5,115,111,112,113,5,312,312,131,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,386,266,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,33,34,385,2,283,283,3,114,114,115,114,3,312,312,132,385,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,386,266,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,33,34,385,2,283,283,5,114,114,115,114,5,312,312,132,385,2,
2,386,2,2,2,2,2,2,2,2,2,2,2,313,290,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,288,132,2,2, 2,386,2,2,2,2,2,2,2,2,2,2,2,313,290,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,5,5,5,5,5,5,312,288,132,2,2,
2,2,2,297,298,299,300,2,345,346,347,348,2,265,266,2,2,374,375,151,152,149,150,151,152,149,150,374,375,149,150,151,152,2,2,282,283,3,3,3,3,3,3,287,288,132,2,2, 2,2,2,297,298,299,300,2,345,346,347,348,2,265,266,2,2,374,375,151,152,149,150,151,152,149,150,374,375,149,150,151,152,2,2,282,283,5,5,5,5,5,5,287,288,132,2,2,
2,2,2,2,2,2,2,386,369,370,371,372,2,266,290,208,209,352,353,2,2,385,2,2,2,2,385,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,312,132,2,2, 2,2,2,2,2,2,2,386,369,370,371,372,2,266,290,208,209,352,353,2,2,385,2,2,2,2,385,2,2,2,2,2,2,2,2,282,283,5,5,5,5,5,5,312,312,132,2,2,
2,2,2,2,2,2,386,2,393,394,395,396,2,290,266,232,233,376,377,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,3,3,3,3,3,3,312,288,132,2,2, 2,2,2,2,2,2,386,2,393,394,395,396,2,290,266,232,233,376,377,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,282,283,5,5,5,5,5,5,312,288,132,2,2,
2,2,2,2,2,385,2,2,2,2,2,2,2,386,313,2,2,149,149,374,375,149,150,151,152,374,375,151,152,149,150,151,152,2,2,282,330,308,308,308,308,308,308,311,312,132,2,2, 2,2,2,2,2,385,2,2,2,2,2,2,2,386,313,2,2,149,149,374,375,149,150,151,152,374,375,151,152,149,150,151,152,2,2,282,330,308,308,308,308,308,308,311,312,132,2,2,
2,2,2,2,2,2,2,2,2,2,2,2,2,266,290,2,2,2,2,2,2,2,2,2,2,385,2,2,385,2,2,2,2,2,2,330,331,331,331,331,331,331,331,331,336,132,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,266,290,2,2,2,2,2,2,2,2,2,2,385,2,2,385,2,2,2,2,2,2,330,331,331,331,331,331,331,331,331,336,132,2,2,
2,297,298,299,300,2,2,2,2,2,2,2,2,265,266,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,90,91,92,162,163,164,165,90,91,92,132,2,2, 2,297,298,299,300,2,2,2,2,2,2,2,2,265,266,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,90,91,92,162,163,164,165,90,91,92,132,2,2,
@ -37,7 +39,7 @@
<data encoding="csv"> <data encoding="csv">
250,251,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,297,298,299,300,0,0,0,225,226,227,228,225,226,227,228,0,0,0,0,0,273,274,275,276,0,0,0, 250,251,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,297,298,299,300,0,0,0,225,226,227,228,225,226,227,228,0,0,0,0,0,273,274,275,276,0,0,0,
274,275,276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,201,202,203,204,0,0,0,0,249,250,251,252,249,250,251,252,0,0,258,259,263,264,0,0,0,0,0,0, 274,275,276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,201,202,203,204,0,0,0,0,249,250,251,252,249,250,251,252,0,0,258,259,263,264,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,225,226,227,228,0,0,0,0,273,274,275,276,273,274,275,276,0,0,282,3,3,288,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,225,226,227,228,0,0,0,0,273,274,275,276,273,274,275,276,0,0,282,307,311,288,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,250,251,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,250,251,252,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,201,202,203,204,0,0,0,0,0,0,0,0,0,0,0,0,0,273,274,275,276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,201,202,203,204,0,0,0,0,0,0,0,0,0,0,0,0,0,273,274,275,276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,225,226,227,228,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,225,226,227,228,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -63,30 +65,30 @@
</layer> </layer>
<layer id="3" name="Walkable" width="48" height="24"> <layer id="3" name="Walkable" width="48" height="24">
<data encoding="csv"> <data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410, 0,0,0,0,412,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,
0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0, 0,0,0,0,0,412,0,0,0,0,0,410,0,0,0,0,410,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,
410,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 410,410,0,0,0,0,0,412,412,0,0,410,0,0,0,0,410,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,0,0,0,0,0,0,412,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,0,0,0,0,0,0,412,412,0,410,0,0,0,0,410,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,412,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,412,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,410,410,0,0,410,410,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,0,0,410,410,0,0,410,410,410,410,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,410,411,411,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,0,0,0,0,0,412,410,410,410,410,0,0,0,410,411,411,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,411,411,411,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,0,0,0,0,412,0,410,410,410,410,0,0,0,411,411,411,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,410,410,410,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,410,410,410,410,0,0,0, 0,412,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,410,410,410,410,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,
0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,410,410,412,0,0,0,0,0,0,412,412,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,410,410,410,410,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,410,410,410,410,0,0,0,412,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,412,412,412,0,0,0,412,0,0,0,0,0,412,0,0,412,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data> </data>
</layer> </layer>
<objectgroup id="4" name="ExtraData"> <objectgroup id="4" name="ExtraData">

View file

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.1" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="6"> <map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="5" nextobjectid="6">
<properties> <properties>
<property name="dialogFile" type="file" value="DialogsLvl3.json"/> <property name="dialogFile" type="file" value="level3_dialogs.json"/>
<property name="mapX" type="int" value="48"/>
<property name="mapY" type="int" value="24"/>
</properties> </properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/> <tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/> <tileset firstgid="409" source="Walkable.tsx"/>
@ -30,7 +32,7 @@
289,290,265,266,290,2,2,2,2,2,2,2,2,265,266,2,110,111,112,114,114,111,112,210,211,212,213,116,133,2,2,2,2,2,2,2,2,2,2,386,2,2,45,46,47,48,2,2, 289,290,265,266,290,2,2,2,2,2,2,2,2,265,266,2,110,111,112,114,114,111,112,210,211,212,213,116,133,2,2,2,2,2,2,2,2,2,2,386,2,2,45,46,47,48,2,2,
2,2,2,2,2,2,2,2,2,386,2,2,2,265,266,2,2,2,2,2,2,2,2,2,265,266,2,2,2,2,345,346,347,348,2,339,340,2,2,2,2,2,69,70,71,72,2,2, 2,2,2,2,2,2,2,2,2,386,2,2,2,265,266,2,2,2,2,2,2,2,2,2,265,266,2,2,2,2,345,346,347,348,2,339,340,2,2,2,2,2,69,70,71,72,2,2,
2,297,298,299,300,2,2,339,340,2,2,2,2,289,290,266,265,266,266,265,386,265,266,266,289,290,2,160,161,2,369,370,371,372,2,363,364,2,2,2,2,2,2,2,2,2,2,2, 2,297,298,299,300,2,2,339,340,2,2,2,2,289,290,266,265,266,266,265,386,265,266,266,289,290,2,160,161,2,369,370,371,372,2,363,364,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,386,2,2,363,364,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,385,2,393,394,395,396,2,2,2,2,2,2,2,387,2,2,2,386,2,2 2,2,2,2,386,2,2,363,364,2,2,2,2,2,2,2,2,2,2,2,265,265,2,2,2,2,2,2,385,2,393,394,395,396,2,2,2,2,2,2,2,387,2,2,2,386,2,2
</data> </data>
</layer> </layer>
<layer id="2" name="Foreground" width="48" height="24"> <layer id="2" name="Foreground" width="48" height="24">
@ -64,29 +66,29 @@
<layer id="3" name="Walkable" width="48" height="24"> <layer id="3" name="Walkable" width="48" height="24">
<data encoding="csv"> <data encoding="csv">
0,0,0,0,410,410,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,410,410,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,0,410,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,0,410,410, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,0,0,410,410,0,0,0,0,410,0,0,412,0,0,412,0,410,410,410,410,410,410,410,410,410,410,0,410,410,
410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,410,410, 410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,410,410,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0, 410,412,412,412,0,412,412,412,412,0,412,412,412,412,410,0,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0, 410,412,412,412,0,412,412,412,412,0,412,412,412,412,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0, 410,412,412,412,0,412,412,412,412,0,412,412,412,412,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,410,410,410,410,0,0,410,0,0,0, 410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,410,0,0,410,410,410,410,0,0,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,410,410,0,0,0,410,410,410,410,0,0,410,410,410,410,0,0,0, 410,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,410,0,0,0,0,0,0,0,0,0,410,0,0,0,410,410,0,0,0,410,410,410,410,0,0,410,410,410,410,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,410,410,410,410,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,410,410,410,410,0,0,0,410,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,410,410,410,410,410,410,410,410,0,410,410,410,410,0,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,0,0,410, 0,0,410,410,410,410,410,410,410,410,0,410,410,410,410,0,410,410,410,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,412,0,0,410,
0,0,410,0,0,0,0,0,0,410,0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,410,0,0,0,0,0,0,410,0,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,410,0,0,0,0,0,0,410,0,410,410,410,410,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0, 0,0,410,0,0,0,0,0,0,410,0,410,410,410,410,0,0,0,0,0,0,412,410,410,0,412,0,0,0,0,0,0,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,0,
0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0, 0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,
0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0, 0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,
0,0,410,0,0,410,410,410,410,410,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0, 0,0,410,0,0,410,410,410,410,410,0,0,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,
0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,410,410,0,0, 0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,0,0,0,0,410,0,0,0,0,410,410,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,412,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0, 0,0,0,412,0,0,0,0,410,410,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,410,410,410,410,0,0,410,410,0,0,0,0,0,0,412,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,410,410,410,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,410,410,410,410,410,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,410,410,410,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,410,410,410,410,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,412,0,0,410,410,410,410,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,410,410,0,0,0,0,0,410,410,410,410,0,0, 0,0,0,0,0,0,0,0,0,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,410,410,0,0,0,0,0,410,410,410,410,0,0,
0,0,410,410,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,410,410,410,0,410,410,0,0,0,0,0,0,0,0,0,0,0, 0,0,410,410,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,0,410,410,410,410,0,410,410,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,0,0,0,0,0,410,0,0,0,0,0,0 0,0,0,0,412,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,0,410,410,410,410,0,0,0,0,0,0,0,410,0,0,0,412,0,0
</data> </data>
</layer> </layer>
<objectgroup id="4" name="ExtraData"> <objectgroup id="4" name="ExtraData">

126
assets/level4.tmx Normal file
View file

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="48" height="24" tilewidth="8" tileheight="8" infinite="0" nextlayerid="6" nextobjectid="9">
<properties>
<property name="dialogFile" type="file" value="level4_dialogs.json"/>
<property name="mapX" type="int" value="48"/>
<property name="mapY" type="int" value="48"/>
</properties>
<tileset firstgid="1" source="tilesetnpp.tsx"/>
<tileset firstgid="409" source="Walkable.tsx"/>
<layer id="1" name="Background" width="48" height="24">
<data encoding="csv">
385,386,2,2,385,386,385,2,2,2,2,2,2,2,2,2,385,386,385,265,266,385,386,385,386,385,121,122,123,122,123,122,124,2,2,2,2,2,2,2,2,386,2,2,2,2,2,2,
385,386,385,386,385,386,385,386,2,2,218,219,385,386,385,386,385,386,385,289,241,385,386,385,386,385,145,146,147,147,146,147,148,385,386,385,385,386,2,2,2,217,218,219,385,2,2,386,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,313,314,25,358,359,358,359,145,146,146,146,147,146,148,358,359,28,385,386,385,386,385,217,218,219,385,386,385,386,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,387,265,266,382,2,2,176,2,169,170,170,170,171,170,172,2,176,360,385,386,385,386,385,217,218,219,363,364,385,386,
385,386,385,386,176,386,385,386,385,386,385,386,385,386,385,386,385,386,385,289,290,97,98,19,2,2,121,122,59,60,61,123,124,2,2,384,385,149,150,151,152,153,154,386,176,177,178,386,
385,385,386,218,385,386,386,219,218,219,385,176,385,386,217,218,219,386,385,313,314,121,122,406,2,2,145,146,83,84,85,147,148,2,2,360,385,386,385,386,385,386,385,386,385,386,385,386,
385,386,25,26,26,26,26,238,239,28,385,386,385,386,217,218,219,386,385,265,241,14,15,43,254,255,169,170,107,108,109,171,172,254,255,360,385,387,149,150,151,152,153,154,385,217,218,219,
385,386,73,74,74,74,74,74,75,76,385,386,385,386,25,26,27,28,385,289,290,38,39,19,2,2,2,2,2,2,2,176,2,2,177,384,385,386,385,386,385,386,385,386,385,217,218,219,
385,386,97,98,98,98,98,98,99,100,385,386,385,386,73,74,75,76,385,313,314,62,63,97,407,407,408,407,407,408,407,407,408,98,99,100,385,149,150,151,152,153,154,218,219,386,385,386,
385,386,162,163,163,163,163,163,164,165,385,386,385,386,97,98,99,100,385,265,266,2,2,197,198,199,200,197,198,199,200,197,198,199,200,197,385,386,385,386,385,386,217,361,362,386,385,386,
25,26,86,87,88,89,186,187,188,189,359,358,359,26,87,88,187,188,28,241,290,160,161,221,222,223,224,221,222,223,224,221,222,223,224,221,385,386,385,386,385,386,385,386,385,386,385,386,
49,50,110,111,112,113,210,211,212,213,177,2,11,12,111,112,211,212,52,313,314,2,2,245,246,247,248,245,246,247,248,245,246,247,248,245,385,386,385,386,385,386,385,386,385,386,385,386,
73,74,75,74,75,176,234,235,236,237,2,2,35,36,75,74,74,75,76,265,266,265,266,265,266,265,266,241,266,313,314,265,266,265,266,265,241,265,266,313,314,265,266,265,266,265,266,265,
97,98,99,98,99,407,408,407,408,407,408,408,407,98,99,98,98,99,100,289,290,289,313,241,290,289,290,289,290,289,290,289,313,241,290,289,290,289,290,289,290,289,290,313,314,313,290,289,
121,122,14,15,16,17,14,15,16,17,14,15,16,17,122,59,60,61,124,265,266,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,
145,146,38,39,40,41,38,39,40,41,38,39,40,41,146,83,84,85,148,289,290,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,
169,170,62,63,64,65,62,63,64,65,62,63,64,65,170,107,108,109,172,265,266,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,
385,386,187,188,87,88,187,188,87,88,187,188,87,88,265,266,266,289,290,241,290,385,386,385,386,385,386,385,386,385,386,385,386,304,305,385,386,385,386,385,386,385,386,385,386,385,386,385,
385,386,211,212,111,112,211,212,111,112,211,212,111,112,289,290,241,313,314,313,314,21,22,23,24,217,386,385,217,218,219,217,386,328,329,385,386,176,386,217,218,219,386,385,386,385,386,385,
385,386,289,241,265,266,289,290,241,266,289,290,265,266,241,290,385,386,385,385,386,45,46,47,48,217,386,385,217,218,219,217,386,385,386,385,386,385,386,217,218,219,386,385,386,385,386,385,
385,386,313,314,289,290,241,314,289,290,313,241,289,290,313,314,385,386,385,385,386,69,70,71,72,217,386,385,217,218,219,217,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,385,386,385,386,385,386,385,304,305,386,176,386,385,386,385,386,385,386,385,386,385,386,385,386,385,217,304,305,385,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,385,386,385,386,385,386,385,328,329,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,217,328,329,385,
385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385,386,385
</data>
</layer>
<layer id="2" name="Foreground" width="48" height="24">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,339,340,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,126,127,128,129,130,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,206,207,0,0,0,0,0,0,0,206,207,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,214,215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,230,231,0,0,0,0,0,0,0,230,231,0,0,0,125,126,127,128,129,130,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,125,126,127,128,129,130,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,337,338,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,136,137,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="3" name="Walkable" width="48" height="24">
<data encoding="csv">
412,412,409,409,412,412,412,409,409,409,409,409,409,409,409,409,412,412,412,0,0,412,412,412,412,412,410,410,410,410,410,410,410,409,409,409,409,409,409,409,409,412,409,409,409,409,409,409,
412,412,412,412,412,412,412,412,409,409,412,412,412,412,412,412,412,412,412,0,0,412,412,412,412,412,410,0,0,0,0,0,410,412,412,412,412,412,409,409,409,412,412,412,412,409,409,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,410,410,410,410,410,410,0,0,0,0,0,410,410,410,410,412,412,412,412,412,412,412,412,410,410,412,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,410,0,0,410,0,0,0,0,410,0,0,0,0,0,410,0,0,410,412,412,412,412,412,412,412,412,410,410,412,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,410,0,0,0,0,410,0,410,410,410,0,410,0,0,410,412,410,410,410,410,410,410,412,412,412,412,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,0,0,410,410,0,0,0,410,0,410,410,410,0,410,0,0,410,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,410,410,410,410,410,410,410,410,412,412,412,412,412,412,412,412,412,0,0,0,0,0,410,410,410,410,410,0,410,410,410,410,410,410,412,410,410,410,410,410,410,410,412,412,412,412,
412,412,410,0,0,0,0,0,0,410,412,412,412,412,410,410,410,410,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,410,0,0,0,0,0,0,410,412,412,412,412,410,0,0,410,412,0,0,0,410,410,0,0,0,0,0,0,0,0,0,0,0,410,412,410,410,410,410,410,410,410,410,412,412,412,
412,412,410,0,0,0,410,410,410,410,412,412,412,412,410,410,410,410,412,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,412,412,412,412,412,412,412,410,410,412,412,412,
410,410,410,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,410,410,410,0,0,0,0,0,0,0,0,0,0,0,410,412,412,412,412,412,412,412,412,412,412,412,412,
410,0,410,410,410,410,410,0,0,410,0,0,0,0,410,410,0,0,410,0,0,0,0,410,410,410,410,410,410,410,410,410,410,410,410,410,412,412,412,412,412,412,412,412,412,412,412,412,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,410,410,410,410,0,0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,0,410,410,0,0,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,410,410,410,410,410,410,410,410,410,410,410,410,0,0,0,0,0,0,0,412,412,412,412,412,412,412,412,412,412,412,412,410,410,412,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,409,409,410,410,0,0,410,410,0,0,410,410,0,0,0,0,0,0,0,410,410,410,410,412,412,412,412,412,412,412,412,410,410,412,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,410,410,410,410,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,0,0,0,0,0,0,0,0,0,0,0,0,0,0,412,412,412,412,412,410,410,410,410,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,410,410,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,410,410,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,410,410,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,410,410,412,
412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412
</data>
</layer>
<objectgroup id="4" name="ExtraData">
<object id="3" name="SGN1" type="SGN" x="176.852" y="88.7417">
<properties>
<property name="dialogID" type="int" value="1"/>
<property name="needAction" type="int" value="1"/>
</properties>
<point/>
</object>
<object id="6" name="NPC1" type="NPC" x="147.952" y="62.6849">
<properties>
<property name="dialogID" type="int" value="0"/>
<property name="face" value="MALE"/>
<property name="hasPath" type="int" value="1"/>
<property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="8"/>
</properties>
<point/>
</object>
<object id="7" name="ENEMY1" type="NPC" x="182.215" y="181.047">
<properties>
<property name="dialogID" type="int" value="2"/>
<property name="face" value="MALE"/>
<property name="hasPath" type="int" value="0"/>
<property name="needAction" type="int" value="1"/>
<property name="path" type="object" value="0"/>
</properties>
<point/>
</object>
<object id="8" name="CHEMIN_FERMIER" type="TRJ" x="147.952" y="63.0743">
<polyline points="0,0 13.6272,31.1478 50.6152,79.4269 13.6272,74.7547 -7.3976,102.009 -15.5739,71.6399 -17.91,116.804 47.8897,112.132 71.6399,87.2138 131.21,112.132 176.374,91.1073 218.424,89.9393 131.599,59.1808 74.3654,64.2423 50.2258,44.775 29.9798,42.4389 3.50413,3.50413"/>
</object>
</objectgroup>
</map>

View file

@ -0,0 +1,37 @@
{
"dialogs": [
{
"ID": 0,
"dialog": "Pas sur que tu trouves grand chose ici, je suis le seul ici depuis cinquante ans.",
"isQuestion": 0,
"choice": "_",
"conclusion1": "_",
"next1": -1,
"conclusion2": "_",
"next2": -1,
"nextOther": -1
},
{
"ID": 1,
"dialog": "L'eglise de Champdubouc",
"isQuestion": 0,
"choice": "_",
"conclusion1": "_",
"next1": -1,
"conclusion2": "_",
"next2": -1,
"nextOther": -1
},
{
"ID": 2,
"dialog": "Passe moi ton fric !",
"isQuestion": 0,
"choice": "_",
"conclusion1": "_",
"next1": -1,
"conclusion2": "_",
"next2": -1,
"nextOther": -1
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 37 B

1
assets/tileset.png Symbolic link
View file

@ -0,0 +1 @@
../assets-fx/2b/tileset/tileset2b.png

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 37 B

1
assets/tinytiled Submodule

@ -0,0 +1 @@
Subproject commit b084ecda91a2352a72a5d1a61b37e0009228ee40

1
clean
View file

@ -6,6 +6,7 @@ cd ..
rm -r build-cg rm -r build-cg
rm -r build-cg-push rm -r build-cg-push
rm -r build-fx rm -r build-fx
rm -r build-fxg3a
rm *.g1a rm *.g1a
rm *.g3a rm *.g3a

View file

@ -1,28 +1,53 @@
#ifndef CONFIG_H #ifndef CONFIG_H
#define CONFIG_H #define CONFIG_H
#if !defined(FXCG50) && defined(COLOR2BIT)
#define GRAYMODEOK 1
#endif
#define USB_FEATURE 0 #define USB_FEATURE 0
#define DEBUGMODE 0 #define DEBUGMODE 0
#define PRECISION 8
#ifdef FXCG50 #include <gint/display.h>
#define T_HEIGHT 16
#define T_WIDTH 16 /* Enable GrayMode on either FX and FX_G3A targets */
#if GINT_RENDER_MONO && defined(COLOR2BIT)
#define GRAYMODEOK 1
#endif
#if GINT_RENDER_RGB
/* The tile size */
#define T_HEIGHT 16
#define T_WIDTH 16
/* The size of a pixel */
#define PXSIZE 2
#define PATH_COLOR C_RED
/* The size of the player */
#define P_WIDTH 16
#define P_HEIGHT 16
#else #else
#define T_HEIGHT 8 /* The tile size */
#define T_WIDTH 8 #define T_HEIGHT 8
#define T_WIDTH 8
/* The pixel size */
#define PXSIZE 1
#define PATH_COLOR C_BLACK
/* The player size */
#define P_WIDTH 8
#define P_HEIGHT 8
#endif #endif
#ifdef FXCG50 /* SPEED should NOT be 8 or bigger: it may cause bugs when handling
#define PXSIZE 2 * collisions! */
#define SPEED (PXSIZE * 2)
/* The face size (in the dialogs) */
#define F_WIDTH (32 * PXSIZE)
#define F_HEIGHT (32 * PXSIZE)
/* the color of the text to go to the next dialog phase */
/* it improves readability to have something lighter */
#if GRAYMODEOK || (GINT_RENDER_RGB && !defined(COLOR1BIT))
#define NEXT_COLOR C_DARK
#else #else
#define PXSIZE 1 #define NEXT_COLOR C_BLACK
#endif #endif
#endif #endif

View file

@ -1,209 +1,223 @@
#include "dialogs.h" #include "dialogs.h"
#include <gint/keyboard.h>
#include <gint/cpu.h>
#include <string.h>
#include "config.h" #include "config.h"
#include "events.h"
#include "game.h" #include "game.h"
#include "npc.h" #include "npc.h"
#include <gint/cpu.h>
#include <gint/keyboard.h>
#include <string.h>
#define BOX_HEIGHT (F_HEIGHT/PXSIZE+8) #define BOX_HEIGHT (F_HEIGHT / PXSIZE + 8)
#define CHOICE_BOX_HEIGHT 10 #define CHOICE_BOX_HEIGHT 10
#define CHOICE_BOX_PADDING_TOP 3 #define CHOICE_BOX_PADDING_TOP 3
extern font_t fontRPG; extern font_t fontRPG;
#define FONT_USED fontRPG #define FONT_USED fontRPG
#if GRAYMODEOK #if GRAYMODEOK
#include <gint/gray.h> #include <gint/gray.h>
uint32_t *lightVRAMnext, *darkVRAMnext; uint32_t *lightVRAMnext, *darkVRAMnext;
uint32_t *lightVRAMcurrent, *darkVRAMcurrent; uint32_t *lightVRAMcurrent, *darkVRAMcurrent;
#endif //GRAYMODEOK #endif // GRAYMODEOK
/* the color of the text to go to the next dialog phase */ void blit() {
/* it improves readability to have somathing lighter */ dupdate();
#if GRAYMODEOK || (defined(FXCG50) && !defined(COLOR1BIT))
#define NEXT_COLOR C_DARK #if GRAYMODEOK && !GINT_HW_CG
#else dgray_getvram(&lightVRAMnext, &darkVRAMnext);
#define NEXT_COLOR C_BLACK dgray_getscreen(&lightVRAMcurrent, &darkVRAMcurrent);
memcpy(lightVRAMnext, lightVRAMcurrent, 256 * sizeof(uint32_t));
memcpy(darkVRAMnext, darkVRAMcurrent, 256 * sizeof(uint32_t));
#endif #endif
void blit()
{
dupdate();
#if GRAYMODEOK
dgray_getvram( &lightVRAMnext, &darkVRAMnext );
dgray_getscreen( &lightVRAMcurrent, &darkVRAMcurrent );
memcpy( lightVRAMnext, lightVRAMcurrent, 256*sizeof( uint32_t) );
memcpy( darkVRAMnext, darkVRAMcurrent, 256*sizeof( uint32_t) );
#endif
} }
int dialogs_text_opt(Game *game, bopti_image_t *face, char *text,
int showtext_opt(Game *game, bopti_image_t *face, char *text, int call_before_end(Game *game, unsigned int i),
int call_before_end(Game *game, unsigned int i), bool start_anim, bool end_anim,
bool start_anim, void for_each_screen(Game *game, unsigned int i),
bool end_anim, int line_duration, bool update_screen,
void for_each_screen(Game *game, unsigned int i), unsigned int start_i, bool wait_continue) {
int line_duration, bool update_screen, unsigned int start_i, text = events_parse_string(&game->handler, text);
bool wait_continue) {
dfont(&FONT_USED); dfont(&FONT_USED);
unsigned int i, n, y = PXSIZE, l = 0; unsigned int i, n, y = PXSIZE, l = 0;
int line_max_chars, return_int = 0; int line_max_chars, return_int = 0;
unsigned int max_lines_amount = (BOX_HEIGHT-2)*PXSIZE/ unsigned int max_lines_amount =
(FONT_USED.line_height+PXSIZE); (BOX_HEIGHT - 2) * PXSIZE / (FONT_USED.line_height + PXSIZE);
const char *c; const char *c;
if(start_anim){ if(start_anim) {
/* Run a little fancy animation. */ /* Run a little fancy animation. */
for(i=0;i<=BOX_HEIGHT;i++){ for(i = 0; i <= BOX_HEIGHT; i++) {
/* Redrawing the entire screen, because maybe there was no dialog /* Redrawing the entire screen, because maybe there was no dialog
displayed before. */ displayed before. */
update_npc(game); update_npcs(game);
draw(game); game_draw(game);
/* Fill the dialog box with white */ /* Fill the dialog box with white */
drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); drect(0, 0, DWIDTH, i * PXSIZE, C_WHITE);
/* Draw a thick black line on the bottom of the dialog. */ /* Draw a thick black line on the bottom of the dialog. */
drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); drect(0, i * PXSIZE, DWIDTH, (i + 1) * PXSIZE, C_BLACK);
/* Draw the part of the face of the player that can fit correctly in /* Draw the part of the face of the player that can fit correctly in
* the dialog drawn. */ * the dialog drawn. */
dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE, dsubimage(4 * PXSIZE, 2 * PXSIZE, face, 0, 0, F_WIDTH,
DIMAGE_NONE); (i - 8) * PXSIZE, DIMAGE_NONE);
blit(); blit();
while(game->frame_duration < 20) sleep(); while(game->frame_duration < 20)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
}else{ } else {
/* Here I'm drawing the same as if start_anim is true, but whitout /* Here I'm drawing the same as if start_anim is true, but whitout
* making an animation. */ * making an animation. */
draw(game); game_draw(game);
drect(0, 0, DWIDTH, BOX_HEIGHT*PXSIZE, C_WHITE); drect(0, 0, DWIDTH, BOX_HEIGHT * PXSIZE, C_WHITE);
drect(0, BOX_HEIGHT*PXSIZE, DWIDTH, (BOX_HEIGHT+1)*PXSIZE, C_BLACK); drect(0, BOX_HEIGHT * PXSIZE, DWIDTH, (BOX_HEIGHT + 1) * PXSIZE,
dimage(4*PXSIZE, 2*PXSIZE, face); C_BLACK);
dimage(4 * PXSIZE, 2 * PXSIZE, face);
if(update_screen){ if(update_screen) {
blit(); blit();
while(game->frame_duration < 20) sleep(); while(game->frame_duration < 20)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
} }
/* We should start to drawing the text on the x axis at BOX_HEIGHT to avoid /* We should start to drawing the text on the x axis at BOX_HEIGHT to avoid
* drawing on the face. */ * drawing on the face. */
for(i=start_i;i<strlen(text);i++){ for(i = start_i; i < strlen(text); i++) {
if(!l && for_each_screen) for_each_screen(game, i); if(!l && for_each_screen)
for_each_screen(game, i);
/* Get how many chars we can draw on screen with a padding on the left /* Get how many chars we can draw on screen with a padding on the left
* of BOX_HEIGHT px and on the right of 1 px. */ * of BOX_HEIGHT px and on the right of 1 px. */
c = drsize(text+i, &FONT_USED, DWIDTH-(BOX_HEIGHT*PXSIZE+PXSIZE), NULL); c = drsize(text + i, &FONT_USED,
DWIDTH - (BOX_HEIGHT * PXSIZE + PXSIZE), NULL);
/* c is a pointer to the last char that can be drawn. So: */ /* c is a pointer to the last char that can be drawn. So: */
line_max_chars = c-(text+i); line_max_chars = c - (text + i);
/* TODO: Handle lines that are longer than what I can draw and '\n'. */ /* TODO: Handle lines that are longer than what I can draw and '\n'. */
/* Loop from the end to the start for word wrap. */ /* Loop from the end to the start for word wrap. */
if(*c){ if(*c) {
/* If we are not drawing the end of the text. */ /* If we are not drawing the end of the text. */
for(n=line_max_chars; n>0; n--) { for(n = line_max_chars; n > 0; n--) {
/* If we found a space, we can draw this line and do the same /* If we found a space, we can draw this line and do the same
* for the next line. */ * for the next line. */
if(text[i+n] == ' '){ if(text[i + n] == ' ') {
dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT, dtext_opt(BOX_HEIGHT * PXSIZE, y, C_BLACK, C_NONE,
DTEXT_TOP, text+i, n); /* Draw everything. */ DTEXT_LEFT, DTEXT_TOP, text + i,
n); /* Draw everything. */
/* Increment y by the line height. */ /* Increment y by the line height. */
y += FONT_USED.line_height+PXSIZE; y += FONT_USED.line_height + PXSIZE;
i += n; /* We drew everything to i+n */ i += n; /* We drew everything to i+n */
l++; /* We drew one more line. */ l++; /* We drew one more line. */
break; break;
} }
} }
}else{ } else {
/* If it is the last line of the text. */ /* If it is the last line of the text. */
dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT, dtext_opt(BOX_HEIGHT * PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT,
DTEXT_TOP, text+i, line_max_chars); DTEXT_TOP, text + i, line_max_chars);
y += FONT_USED.line_height+PXSIZE; y += FONT_USED.line_height + PXSIZE;
i += line_max_chars; i += line_max_chars;
l++; l++;
} }
if(l>=max_lines_amount-1){ if(l >= max_lines_amount - 1) {
/* We drew one entire screen, reset everything to draw the next one. /* We drew one entire screen, reset everything to draw the next one.
*/ */
/* Make a little animation :). */ /* Make a little animation :). */
if(update_screen) blit(); if(update_screen)
while(game->frame_duration < line_duration) sleep(); blit();
while(game->frame_duration < line_duration)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
/* Ask the user to press SHIFT to continue. */ /* Ask the user to press SHIFT to continue. */
dtext(BOX_HEIGHT*PXSIZE, y, NEXT_COLOR, "[SHIFT] : suite..."); dtext(BOX_HEIGHT * PXSIZE, y, NEXT_COLOR, "[SHIFT] : suite...");
} }
/* Make a little animation :). */ /* Make a little animation :). */
if(update_screen) blit(); if(update_screen)
if(l>=max_lines_amount-1){ blit();
if(l >= max_lines_amount - 1) {
/* If we drew one entire screen. */ /* If we drew one entire screen. */
/* Wait that the SHIFT key is pressed if we should. */ /* Wait that the SHIFT key is pressed if we should. */
if(wait_continue) while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & ~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT) sleep(); if(wait_continue) {
while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT &
~GETKEY_MOD_ALPHA,
NULL)
.key != KEY_SHIFT) {
sleep();
}
}
/* Clear the text area. */ /* Clear the text area. */
drect(BOX_HEIGHT*PXSIZE, 0, DWIDTH, (BOX_HEIGHT-1)*PXSIZE-2, drect(BOX_HEIGHT * PXSIZE, 0, DWIDTH, (BOX_HEIGHT - 1) * PXSIZE - 2,
C_WHITE); C_WHITE);
/* Reset y and l. */ /* Reset y and l. */
y = PXSIZE; y = PXSIZE;
l = 0; l = 0;
} } else {
else{
/* Else, wait a bit for the animation. */ /* Else, wait a bit for the animation. */
while(game->frame_duration < line_duration) sleep(); while(game->frame_duration < line_duration)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
} }
if(l<max_lines_amount-1){ if(l < max_lines_amount - 1) {
/* If we have not filled everthing with text at the end. */ /* If we have not filled everthing with text at the end. */
/* Make a little animation :). */ /* Make a little animation :). */
if(update_screen) blit(); if(update_screen)
while(game->frame_duration < line_duration) sleep(); blit();
while(game->frame_duration < line_duration)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
/* Ask the user to press SHIFT to continue. */ /* Ask the user to press SHIFT to continue. */
dtext(BOX_HEIGHT*PXSIZE, y, NEXT_COLOR, "[SHIFT] : suite..."); dtext(BOX_HEIGHT * PXSIZE, y, NEXT_COLOR, "[SHIFT] : suite...");
/* Update the screen and wait for SHIFT being pressed, if needed. */ /* Update the screen and wait for SHIFT being pressed, if needed. */
if(update_screen) blit(); if(update_screen)
if(wait_continue) while(getkey_opt( GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & ~GETKEY_MOD_ALPHA, NULL).key != KEY_SHIFT) sleep(); blit();
if(wait_continue) {
while(getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT &
~GETKEY_MOD_ALPHA,
NULL)
.key != KEY_SHIFT) {
sleep();
}
}
} }
if(call_before_end) return_int = call_before_end(game, i); if(call_before_end)
if(end_anim){ return_int = call_before_end(game, i);
if(end_anim) {
/* Run another little fancy animation if we should. */ /* Run another little fancy animation if we should. */
for(i=BOX_HEIGHT;i>0;i--){ for(i = BOX_HEIGHT; i > 0; i--) {
/* It is the same as the start animation. */ /* It is the same as the start animation. */
update_npc(game); update_npcs(game);
draw(game); game_draw(game);
drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); drect(0, 0, DWIDTH, i * PXSIZE, C_WHITE);
drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); drect(0, i * PXSIZE, DWIDTH, (i + 1) * PXSIZE, C_BLACK);
dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE, dsubimage(4 * PXSIZE, 2 * PXSIZE, face, 0, 0, F_WIDTH,
DIMAGE_NONE); (i - 8) * PXSIZE, DIMAGE_NONE);
dupdate(); dupdate();
while(game->frame_duration < 20) sleep(); while(game->frame_duration < 20)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
} }
return return_int; return return_int;
} }
void showtext_dialog(Game *game, bopti_image_t *face, char *text, void dialogs_text(Game *game, bopti_image_t *face, char *text,
bool dialog_start, bool dialog_end) { bool dialog_start, bool dialog_end) {
/* Run showtext_opt with some default values. It makes it easier to use in /* Run showtext_opt with some default values. It makes it easier to use in
* simple dialogs. */ * simple dialogs. */
showtext_opt(game, face, text, NULL, dialog_start, dialog_end, NULL, 100, dialogs_text_opt(game, face, text, NULL, dialog_start, dialog_end, NULL,
true, 0, true); 100, true, 0, true);
} }
/* Some variables and pointers used to get some arguments passed in /* Some variables and pointers used to get some arguments passed in
* showtext_dialog_ask in _choice_call_before_end. */ * showtext_dialog_ask in _choice_call_before_end. */
char *_choices, *_text; char *_choices, *_text;
@ -213,31 +227,33 @@ unsigned int _i;
/* Get where I started drawing a dialog page, to be able to redraw the last page /* Get where I started drawing a dialog page, to be able to redraw the last page
* for the end animation in _choice_call_before_end. */ * for the end animation in _choice_call_before_end. */
void _choice_screen_call( [[maybe_unused]] Game *game, unsigned int i) { void _choice_screen_call([[maybe_unused]] Game *game, unsigned int i) {
_i = i; _i = i;
} }
int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) { int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) {
int i, key; int i, key;
/* Make a little animation because we looove little animations ;) */ /* Make a little animation because we looove little animations ;) */
for(i=0;i<DWIDTH/8+1;i++){ for(i = 0; i < DWIDTH / 8 + 1; i++) {
/* Fill the interaction box with white */ /* Fill the interaction box with white */
drect(0, (BOX_HEIGHT+1)*PXSIZE+1, i*(DWIDTH/8), drect(0, (BOX_HEIGHT + 1) * PXSIZE + 1, i * (DWIDTH / 8),
(BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); (BOX_HEIGHT + CHOICE_BOX_HEIGHT) * PXSIZE, C_WHITE);
/* Draw a thick border on the right of the box. */ /* Draw a thick border on the right of the box. */
drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1, drect(i * (DWIDTH / 8), BOX_HEIGHT * PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); i * (DWIDTH / 8) + PXSIZE - 1,
(BOX_HEIGHT + CHOICE_BOX_HEIGHT + 1) * PXSIZE, C_BLACK);
/* Draw a thick border on the bottom of the box. */ /* Draw a thick border on the bottom of the box. */
drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), drect(0, (BOX_HEIGHT + CHOICE_BOX_HEIGHT) * PXSIZE, i * (DWIDTH / 8),
(BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); (BOX_HEIGHT + CHOICE_BOX_HEIGHT + 1) * PXSIZE, C_BLACK);
/* Show everyting on screen. */ /* Show everyting on screen. */
blit(); blit();
/* Wait some ms so that the animation isn't too fast. */ /* Wait some ms so that the animation isn't too fast. */
while(game->frame_duration < 20) sleep(); while(game->frame_duration < 20)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
/* Calculate the maximal size of a choice. */ /* Calculate the maximal size of a choice. */
const int choice_size = DWIDTH/_choices_amount; const int choice_size = DWIDTH / _choices_amount;
/* arrow_width: The space taken by the arrow that shows the selected item. /* arrow_width: The space taken by the arrow that shows the selected item.
* arrow_height: The height of the arrow used to show which item is choosen. * arrow_height: The height of the arrow used to show which item is choosen.
* Used to calculate the size of the rectangle used to remove * Used to calculate the size of the rectangle used to remove
@ -253,29 +269,32 @@ int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) {
dsize(">", &FONT_USED, &arrow_width, &arrow_height); dsize(">", &FONT_USED, &arrow_width, &arrow_height);
/* Add the character spacing of the font to it. */ /* Add the character spacing of the font to it. */
arrow_width += FONT_USED.char_spacing; arrow_width += FONT_USED.char_spacing;
for(i=0;i<_choices_amount;i++){ for(i = 0; i < _choices_amount; i++) {
dtext(i*choice_size+arrow_width+PXSIZE, dtext(i * choice_size + arrow_width + PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, C_BLACK, (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE, C_BLACK,
_choices+pos); _choices + pos);
pos += strlen(_choices+pos)+1; pos += strlen(_choices + pos) + 1;
} }
do{ do {
/* Display the diffrent choices. */ /* Display the diffrent choices. */
for(i=0;i<_choices_amount;i++){ for(i = 0; i < _choices_amount; i++) {
if(i == selected) dtext(i*choice_size+PXSIZE, if(i == selected)
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, dtext(i * choice_size + PXSIZE,
C_BLACK, ">"); (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE, C_BLACK,
">");
} }
blit(); blit();
key = getkey_opt( GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & ~GETKEY_MOD_ALPHA, NULL).key; key = getkey_opt(GETKEY_DEFAULT & ~GETKEY_MOD_SHIFT & ~GETKEY_MOD_ALPHA,
NULL)
.key;
/* If the player pressed the left arrow key and has not already selected /* If the player pressed the left arrow key and has not already selected
* the first possible choice. */ * the first possible choice. */
if(key == KEY_LEFT && selected > 0){ if(key == KEY_LEFT && selected > 0) {
/* Remove the old arrow. */ /* Remove the old arrow. */
drect(selected*choice_size+PXSIZE, drect(selected * choice_size + PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE,
selected*choice_size+PXSIZE+arrow_width, selected * choice_size + PXSIZE + arrow_width,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE+arrow_height, (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE + arrow_height,
C_WHITE); C_WHITE);
/* Move the selection arrow and update the selected item. */ /* Move the selection arrow and update the selected item. */
@ -283,35 +302,37 @@ int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) {
} }
/* If the player pressed the right arrow key and has not already /* If the player pressed the right arrow key and has not already
* selected the last possible choice. */ * selected the last possible choice. */
else if(key == KEY_RIGHT && selected < _choices_amount-1){ else if(key == KEY_RIGHT && selected < _choices_amount - 1) {
/* Remove the old arrow. */ /* Remove the old arrow. */
drect(selected*choice_size+PXSIZE, drect(selected * choice_size + PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE,
selected*choice_size+PXSIZE+arrow_width, selected * choice_size + PXSIZE + arrow_width,
(BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE+arrow_height, (BOX_HEIGHT + CHOICE_BOX_PADDING_TOP) * PXSIZE + arrow_height,
C_WHITE); C_WHITE);
/* Move the selection arrow and update the selected item. */ /* Move the selection arrow and update the selected item. */
selected++; selected++;
} }
/* If the user has not validated his choice by pressing SHIFT, we loop one /* If the user has not validated his choice by pressing SHIFT, we loop
* more time. */ * one more time. */
}while(key != KEY_SHIFT); } while(key != KEY_SHIFT);
/* Make a little animation because we looove little animations ;) */ /* Make a little animation because we looove little animations ;) */
for(i=DWIDTH/8+1;i>0;i--){ for(i = DWIDTH / 8 + 1; i > 0; i--) {
/* I'm drawing the same box as on the start animation */ /* I'm drawing the same box as on the start animation */
update_npc(game); update_npcs(game);
draw(game); game_draw(game);
showtext_opt(game, _face, _text, NULL, false, false, NULL, 0, false, dialogs_text_opt(game, _face, _text, NULL, false, false, NULL, 0, false,
_i, false); _i, false);
drect(0, (BOX_HEIGHT+1)*PXSIZE+1, i*(DWIDTH/8), drect(0, (BOX_HEIGHT + 1) * PXSIZE + 1, i * (DWIDTH / 8),
(BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); (BOX_HEIGHT + CHOICE_BOX_HEIGHT) * PXSIZE, C_WHITE);
drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1, drect(i * (DWIDTH / 8), BOX_HEIGHT * PXSIZE,
(BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); i * (DWIDTH / 8) + PXSIZE - 1,
drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT + CHOICE_BOX_HEIGHT + 1) * PXSIZE, C_BLACK);
(BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); drect(0, (BOX_HEIGHT + CHOICE_BOX_HEIGHT) * PXSIZE, i * (DWIDTH / 8),
(BOX_HEIGHT + CHOICE_BOX_HEIGHT + 1) * PXSIZE, C_BLACK);
dupdate(); dupdate();
while(game->frame_duration < 20) sleep(); while(game->frame_duration < 20)
sleep();
game->frame_duration = 0; game->frame_duration = 0;
} }
/* Return the selected item because he'll also be returned by showtext_opt. /* Return the selected item because he'll also be returned by showtext_opt.
@ -319,9 +340,9 @@ int _choice_call_before_end(Game *game, [[maybe_unused]] unsigned int org_i) {
return selected; return selected;
} }
int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, int dialogs_ask(Game *game, bopti_image_t *face, char *text, bool start,
bool end, char *choices, int choices_amount, bool end, char *choices, int choices_amount,
int default_choice) { int default_choice) {
/* Put some arguments in global pointers and variables to make them /* Put some arguments in global pointers and variables to make them
* accessible by _choice_call_before_end. */ * accessible by _choice_call_before_end. */
_choices = choices; _choices = choices;
@ -331,50 +352,45 @@ int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start,
_text = text; _text = text;
/* Run showtext_opt and return his return value (the return value of /* Run showtext_opt and return his return value (the return value of
*_choice_call_before_end) */ *_choice_call_before_end) */
return showtext_opt(game, face, text, _choice_call_before_end, start, end, return dialogs_text_opt(game, face, text, _choice_call_before_end, start,
_choice_screen_call, 100, true, 0, true); end, _choice_screen_call, 100, true, 0, true);
} }
void dialogs_initiate_sequence(Game *game, bopti_image_t *face,
uint32_t dialogNumber) {
Dialog *currentDiag = &game->map_level->dialogs[dialogNumber];
/* we collect the information */
char *text = currentDiag->dialog;
char *choices = currentDiag->choices;
char *conclusion1 = currentDiag->conclusion1;
int next1 = currentDiag->next1;
char *conclusion2 = currentDiag->conclusion2;
int next2 = currentDiag->next2;
int nextOther = currentDiag->nextOther;
int isQuestion = currentDiag->isQuestion;
void initiate_dialog_sequence(Game *game, bopti_image_t *face, uint32_t dialogNumber ) /* we treat the action - i.e. we show a dialog */
{ if(isQuestion == 1) {
Dialog *currentDiag = &game->map_level->dialogs[ dialogNumber ]; /* we have to manage a question */
int answer = dialogs_ask(game, face, text, true, true, choices, 2, 0);
/* we collect the information */ /* TO DO we need to split the strings conclusion1 and conclusion2 */
char *text = currentDiag->dialog; /* to extract the "gift" part */
char *choices = currentDiag->choices ; if(answer == 0) {
char *conclusion1 = currentDiag->conclusion1; dialogs_text(game, face, conclusion1, true, true);
int next1 = currentDiag->next1; if(next1 != -1)
char *conclusion2 = currentDiag->conclusion2; dialogs_initiate_sequence(game, face, next1);
int next2 = currentDiag->next2; } else {
int nextOther = currentDiag->nextOther; dialogs_text(game, face, conclusion2, true, true);
int isQuestion = currentDiag->isQuestion; if(next2 != -1)
dialogs_initiate_sequence(game, face, next2);
/* we treat the action - i.e. we show a dialog */
if (isQuestion == 1) /* we have to manage a question */
{
int answer = showtext_dialog_ask( game, face, text, true, true, choices, 2, 0 );
/* TO DO we need to split the strings conclusion1 and conclusion2 */
/* to extract the "gift" part */
if (answer==0)
{
showtext_dialog( game, face, conclusion1, true, true );
if (next1!=-1) initiate_dialog_sequence( game, face, next1 );
}
else
{
showtext_dialog( game, face, conclusion2, true, true );
if (next2!=-1) initiate_dialog_sequence( game, face, next2 );
}
}
else
{
showtext_dialog( game, face, text, true, true );
if (nextOther!=-1) initiate_dialog_sequence( game, face, nextOther );
} }
} else {
dialogs_text(game, face, text, true, true);
if(nextOther != -1)
dialogs_initiate_sequence(game, face, nextOther);
}
} }

View file

@ -1,15 +1,14 @@
#ifndef DIALOG_H #ifndef DIALOG_H
#define DIALOG_H #define DIALOG_H
#include <gint/display.h> #include "config.h"
#include <string.h>
#include "game.h" #include "game.h"
#include "map.h" #include "map.h"
#define F_WIDTH (32*PXSIZE) #include <gint/display.h>
#define F_HEIGHT (32*PXSIZE) #include <string.h>
/* showtext_opt() /* dialogs_text_opt()
* *
* Show some text in a box with word wrap for dialogs. * Show some text in a box with word wrap for dialogs.
* *
@ -37,17 +36,16 @@
* wait_continue: If I should wait that EXE is pressed after drawing a page. * wait_continue: If I should wait that EXE is pressed after drawing a page.
*/ */
int showtext_opt(Game *game, bopti_image_t *face, char *text, int dialogs_text_opt(Game *game, bopti_image_t *face, char *text,
int call_before_end(Game *game, unsigned int i), int call_before_end(Game *game, unsigned int i),
bool start_anim, bool start_anim, bool end_anim,
bool end_anim, void for_each_screen(Game *game, unsigned int i),
void for_each_screen(Game *game, unsigned int i), int line_duration, bool update_screen,
int line_duration, bool update_screen, unsigned int start_i, unsigned int start_i, bool wait_continue);
bool wait_continue);
/* showtext_dialog() /* dialogs_text()
* *
* Calls showtext_opt with default parameters. * Calls dialogs_text_opt with default parameters.
* *
* game: The game struct of the current game. * game: The game struct of the current game.
* face: A bopti_image_t of the face of the person who's saying this * face: A bopti_image_t of the face of the person who's saying this
@ -60,12 +58,12 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text,
* shown at the end of showtext_opt. * shown at the end of showtext_opt.
*/ */
void showtext_dialog(Game *game, bopti_image_t *face, char *text, void dialogs_text(Game *game, bopti_image_t *face, char *text,
bool dialog_start, bool dialog_end); bool dialog_start, bool dialog_end);
/* showtext_dialog_ask() /* dialogs_ask()
* *
* Like showtext_dialog, but lets the user choose between multiple possible * Like dialogs_text, but lets the user choose between multiple possible
* choices after displaying the text. * choices after displaying the text.
* *
* game: The game struct of the current game. * game: The game struct of the current game.
@ -85,10 +83,12 @@ void showtext_dialog(Game *game, bopti_image_t *face, char *text,
* default_choice: The choice choosen by default when the dialog just opened. * default_choice: The choice choosen by default when the dialog just opened.
*/ */
int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, int dialogs_ask(Game *game, bopti_image_t *face, char *text, bool start,
bool end, char *choices, int choices_amount, bool end, char *choices, int choices_amount,
int default_choice); int default_choice);
void initiate_dialog_sequence(Game *game, bopti_image_t *face, uint32_t dialogNumber ); /* TODO: Doc. */
void dialogs_initiate_sequence(Game *game, bopti_image_t *face,
uint32_t dialogNumber);
#endif #endif

110
src/events.c Normal file
View file

@ -0,0 +1,110 @@
#include "events.h"
#include <stdlib.h>
#include <string.h>
void events_init_handler(EventHandler *handler) { handler->vars = 0; }
int events_bind_variable(EventHandler *handler, int *var, char *name) {
if(handler->vars < MAX_VARIABLES) {
handler->variables[handler->vars] = var;
handler->var_names[handler->vars++] = name;
} else {
return 1;
}
return 0;
}
char op_chars[OP_AMOUNT + 1] = " =+-/*%";
int _op_null(int a, int b) { return 0; }
int _op_set(int a, int b) { return b; }
int _op_add(int a, int b) { return a + b; }
int _op_sub(int a, int b) { return a - b; }
int _op_div(int a, int b) {
if(b == 0)
return 0;
return a / b;
}
int _op_mul(int a, int b) { return a * b; }
int _op_mod(int a, int b) {
if(b == 0)
return 0;
return a % b;
}
int (*_operations[OP_AMOUNT])(int, int) = {_op_null, _op_set, _op_add, _op_sub,
_op_div, _op_mul, _op_mod};
#define MIN(a, b) a < b ? a : b
char _message_buffer[MESSAGE_BUFFER_SZ];
char *events_parse_string(EventHandler *handler, char *message) {
size_t message_pos = 0;
char in_token = 0;
char var_name[TOKEN_MAX_SZ];
size_t name_pos = 0;
Operation var_op = OP_NULL;
char num[TOKEN_MAX_SZ];
size_t num_pos = 0;
Token tok_type = T_NULL;
char c;
size_t i, n;
int *var;
for(i = 0; i < strlen(message); i++) {
c = message[i];
if(c == '`') {
in_token = !in_token;
if(!in_token) {
if(tok_type == T_VAR_EDIT) {
/* Do the calculation */
var_name[MIN(name_pos, TOKEN_MAX_SZ)] = '\0';
num[MIN(num_pos, TOKEN_MAX_SZ)] = '\0';
for(n = 0; n < handler->vars; n++) {
if(!strcmp(var_name, handler->var_names[n])) {
var = handler->variables[n];
if(var_op) {
*var = _operations[var_op](*var, atoi(num));
}
break;
}
}
}
/* Reset everything */
tok_type = T_NULL;
name_pos = 0;
var_op = OP_NULL;
num_pos = 0;
}
} else if(!in_token) {
if(message_pos < TOKEN_MAX_SZ)
_message_buffer[message_pos++] = c;
}
if(in_token && c != ' ') {
if(tok_type == T_VAR_EDIT) {
if(var_op != OP_NULL) {
if(num_pos < TOKEN_MAX_SZ)
num[num_pos++] = c;
}
if(strchr(op_chars, c)) {
var_op = (Operation)(strchr(op_chars, c) - op_chars);
}
if(var_op == OP_NULL) {
if(name_pos < TOKEN_MAX_SZ)
var_name[name_pos++] = c;
}
}
if(c == '$') {
tok_type = T_VAR_EDIT;
}
}
}
_message_buffer[MIN(message_pos, MESSAGE_BUFFER_SZ)] = '\0';
return _message_buffer;
}

60
src/events.h Normal file
View file

@ -0,0 +1,60 @@
#ifndef EVENTS_H
#define EVENTS_H
/* The max amount of variables that can be bound. */
#define MAX_VARIABLES 32
/* The max. size of the message buffer.
* WARNING: Bigger messages will be truncated! */
#define MESSAGE_BUFFER_SZ 1024
/* The maximal size of a token. Bigger tokens will be truncated. */
#define TOKEN_MAX_SZ 1024
typedef struct {
int *variables[MAX_VARIABLES];
char *var_names[MAX_VARIABLES];
unsigned int vars;
} EventHandler;
typedef enum { T_NULL, T_VAR_EDIT, T_AMOUNT } Token;
typedef enum {
OP_NULL,
OP_SET,
OP_ADD,
OP_SUB,
OP_DIV,
OP_MUL,
OP_MOD,
OP_AMOUNT
} Operation;
/* events_init_handler()
*
* Initialize an event handler.
* handler: The Event handler to initialize.
*/
void events_init_handler(EventHandler *handler);
/* events_bind_variable()
*
* Bind a variable. Binding a variable allows it to be modified by messages
* passed to the event handler using tags written as following:
* `variable+number` (The backticks delimit the tag). Available operators:
* '=': Assign a value to the variable.
* '+': Addition.
* '-': Substraction.
* '*': Multiplication.
* '/': Division.
* '%': Modulo.
* handler: The event handler.
* var: A pointer to the variable to bind.
* name: The name of the variable. This is the name that will be used to
* refer to this variable in a tag.
*/
int events_bind_variable(EventHandler *handler, int *var, char *name);
/* events_parse_string()
* handler: The event handler.
* message: The message to parse.
*/
char *events_parse_string(EventHandler *handler, char *message);
#endif

View file

@ -1,77 +1,69 @@
#include "game.h" #include "game.h"
#include "map.h"
#include "config.h" #include "config.h"
#include "map.h"
#include <stdlib.h>
#include <string.h>
#include <gint/keyboard.h>
#include <gint/cpu.h>
#include <gint/display.h>
#include "npc.h" #include "npc.h"
#include <gint/cpu.h>
#include <gint/display.h>
#include <gint/keyboard.h>
#include <stdlib.h>
#include <string.h>
extern bopti_image_t SignAction_img; extern bopti_image_t SignAction_img;
extern Dialog *dialogRPG; extern Dialog *dialogRPG;
extern NPC *npcRPG; // extern NPC *npcRPG;
extern uint32_t nbNPC; // extern uint32_t nbNPC;
#define MAX_INTERACTION_DISTANCE 12 #define MAX_INTERACTION_DISTANCE 12
void interaction_available(Game *game) {
uint32_t i;
void game_logic(Game *game) { /*NPCs take priority over signs*/
update_npc( game ); for(uint32_t i = 0; i < game->map_level->nbNPC; i++) {
if(!game->map_level->npcs[i].has_dialog)
continue;
/* we check if interactions are possible close to the player */
for( uint32_t i=0; i<game->map_level->nbextradata; i++ )
{
/* simple distance check along X and Y axis */ /* simple distance check along X and Y axis */
/* Be careful to use world coordinates, not local (i.e.map) ones */ /* Be careful to use world coordinates, not local (i.e.map) ones */
if ( (abs((int) game->player.wx - if((abs((int)game->player.x -
(int) game->map_level->extradata[i].x*PXSIZE ) (int)(game->map_level->npcs[i].curx >> PRECISION) * PXSIZE) <
< MAX_INTERACTION_DISTANCE*PXSIZE) MAX_INTERACTION_DISTANCE * PXSIZE) &&
&& (abs((int) game->player.wy - (abs((int)game->player.y -
(int) game->map_level->extradata[i].y*PXSIZE ) (int)(game->map_level->npcs[i].cury >> PRECISION) * PXSIZE) <
< MAX_INTERACTION_DISTANCE*PXSIZE) MAX_INTERACTION_DISTANCE * PXSIZE)) {
&& strcmp( game->map_level->extradata[i].type, "NPC") !=0 )
{
/* the player can do something */ /* the player can do something */
game->player.canDoSomething = true; game->player.canDoSomething = true;
/* we mark the action for futur treatment in player_action() */ /* we mark the action for futur treatment in player_action() */
game->player.whichAction = i; game->player.whichAction = i;
/* this is an interraction with a NPC */
game->player.isInteractingWithNPC = true;
return;
}
}
for(i = 0; i < game->map_level->nbSign; i++) {
/* simple distance check along X and Y axis */
/* Be careful to use world coordinates, not local (i.e.map) ones */
if((abs((int)game->player.x -
(int)game->map_level->signs[i].x * PXSIZE) <
MAX_INTERACTION_DISTANCE * PXSIZE) &&
(abs((int)game->player.y -
(int)game->map_level->signs[i].y * PXSIZE) <
MAX_INTERACTION_DISTANCE * PXSIZE)) {
/* the player can do something */
game->player.canDoSomething = true;
/* we mark the action for future treatment in player_action() */
game->player.whichAction = i;
/* this is not an interraction with a NPC */ /* this is not an interraction with a NPC */
game->player.isInteractingWithNPC = false; game->player.isInteractingWithNPC = false;
return; return;
} }
} }
for( uint32_t i=0; i<nbNPC; i++ )
{
/* simple distance check along X and Y axis */
/* Be careful to use world coordinates, not local (i.e.map) ones */
if ( (abs((int) game->player.wx -
(int) npcRPG[i].curx*PXSIZE )
< MAX_INTERACTION_DISTANCE*PXSIZE)
&& (abs((int) game->player.wy -
(int) npcRPG[i].cury*PXSIZE )
< MAX_INTERACTION_DISTANCE*PXSIZE)
&& strcmp( game->map_level->extradata[i].type, "NPC") !=0 )
{
/* the player can do something */
game->player.canDoSomething = true;
/* we mark the action for futur treatment in player_action() */
game->player.whichAction = i;
/* this is not an interraction with a NPC */
game->player.isInteractingWithNPC = true;
return;
}
}
/* else nothing to be done here */ /* else nothing to be done here */
game->player.canDoSomething = false; game->player.canDoSomething = false;
game->player.whichAction = -1; game->player.whichAction = -1;
@ -79,47 +71,101 @@ void game_logic(Game *game) {
return; return;
} }
void game_logic(Game *game) {
void render_indicator(Game *game) update_npcs(game);
{
/* nothing to do for the player so we quit */
if (game->player.canDoSomething==false)
return;
/* else we draw a small indicator on the screen */ /* we check if interactions are possible close to the player */
dimage(5, 5, &SignAction_img);
interaction_available(game);
} }
void game_render_indicator(Game *game) {
/* nothing to do for the player so we quit */
if(game->player.canDoSomething)
dimage(5, 5, &SignAction_img);
int i;
Player *player = &game->player;
for(i = 0; i < game->map_level->nbPortal; i++) {
Portal *portal = &game->map_level->portals[i];
if(player->x >= portal->collider.x1 * PXSIZE &&
player->x < portal->collider.x2 * PXSIZE &&
player->y >= portal->collider.y1 * PXSIZE &&
player->y < portal->collider.y2 * PXSIZE) {
dimage(5, 5, &SignAction_img);
break;
}
}
}
void draw(Game *game) { void game_draw(Game *game) {
/* Draw everything. */ /* Draw everything. */
render_map_by_layer(game, BACKGROUND); dclear(C_WHITE);
npc_draw( game ); map_render_by_layer(game, BACKGROUND);
npc_draw(game);
player_draw(game); player_draw(game);
render_map_by_layer(game, FOREGROUND); map_render_by_layer(game, FOREGROUND);
render_indicator( game ); game_render_indicator(game);
/*DEBUG*/
dprint(8, 8, C_BLACK, "Lifes: %d", game->player.life);
dprint(8, 16, C_BLACK, "Mana: %d", game->mana);
dprint(8, 24, C_BLACK, "X: %d Y: %d", game->player.x, game->player.y);
} }
/* Key management */ /* Key management */
void get_inputs(Game *game) { void game_get_inputs(Game *game) {
key_event_t ev; clearevents();
while((ev = pollevent()).type != KEYEV_NONE){
/**/
}
/* Key binding for the Player action */ /* Key binding for the Player action */
/*************************************/ /*************************************/
if(keydown(KEY_EXIT)) game->exittoOS = true; if(keydown(KEY_EXIT))
game->exittoOS = true;
/* Player actions - Prototypes in player.h and implementation in player.c */ /* Player actions - Prototypes in player.h and implementation in player.c */
if(keydown(KEY_LEFT)) player_move(game, D_LEFT); if(keydown(KEY_LEFT))
if(keydown(KEY_RIGHT)) player_move(game, D_RIGHT); player_move(game, D_LEFT);
if(keydown(KEY_UP)) player_move(game, D_UP); if(keydown(KEY_RIGHT))
if(keydown(KEY_DOWN)) player_move(game, D_DOWN); player_move(game, D_RIGHT);
if(keydown(KEY_SHIFT)) player_action(game); if(keydown(KEY_UP))
player_move(game, D_UP);
if(keydown(KEY_DOWN))
player_move(game, D_DOWN);
if(keydown(KEY_SHIFT))
player_action(game);
if(keydown(KEY_OPTN)) {
game->player.is_male = !game->player.is_male;
/* TODO: Make something cleaner */
while(keydown(KEY_OPTN)) {
clearevents();
sleep();
}
}
Player *player = &game->player;
if(keydown(KEY_SHIFT)) {
int i;
for(i = 0; i < game->map_level->nbPortal; i++) {
Portal *portal = &game->map_level->portals[i];
if(player->x >= portal->collider.x1 * PXSIZE &&
player->x < portal->collider.x2 * PXSIZE &&
player->y >= portal->collider.y1 * PXSIZE &&
player->y < portal->collider.y2 * PXSIZE) {
Portal *dest_portal = (Portal *)portal->portal;
Collider dest_collider = dest_portal->collider;
Map *dest_map = (Map *)portal->map;
player->x = (dest_collider.x1 + dest_collider.x2) / 2 * PXSIZE;
player->y = (dest_collider.y1 + dest_collider.y2) / 2 * PXSIZE;
game->map_level = dest_map;
/* TODO: Make something cleaner */
while(keydown(KEY_SHIFT)) {
clearevents();
sleep();
}
}
}
}
/* Display Debug Information on screen */ /* Display Debug Information on screen */
#if DEBUGMODE #if DEBUGMODE
@ -134,13 +180,13 @@ void get_inputs(Game *game) {
} }
#endif #endif
/* if USB is enabled - keybinding for screencapture */ /* if USB is enabled - keybinding for screencapture */
#if USB_FEATURE #if USB_FEATURE
if(keydown(KEY_7)) game->screenshot = true; if(keydown(KEY_7))
if(keydown(KEY_8)) game->record = !game->record; game->screenshot = true;
if(keydown(KEY_8))
game->record = !game->record;
#endif //USB_FEATURE #endif // USB_FEATURE
} }

View file

@ -1,37 +1,29 @@
#ifndef GAME_H #ifndef GAME_H
#define GAME_H #define GAME_H
#include "events.h"
#include <gint/display.h> #include <gint/display.h>
#include <stdint.h> #include <stdint.h>
/* The direction where the player is going to. */ /* The direction where the player is going to. */
typedef enum { typedef enum { D_UP, D_DOWN, D_LEFT, D_RIGHT } Direction;
D_UP,
D_DOWN,
D_LEFT,
D_RIGHT
} Direction;
typedef enum { typedef enum { P_LEFTUP = -1, P_CENTER = 0, P_RIGHTDOWN = 1 } Checkpos;
P_LEFTUP = -1,
P_CENTER = 0,
P_RIGHTDOWN = 1
} Checkpos;
typedef struct {
uint32_t x1, y1;
uint32_t x2, y2;
} Collider;
/* Struct that define player parameters */ /* Struct that define player parameters */
typedef struct { typedef struct {
int16_t x, y; /* The position of the player int the current map */ int16_t x, y; /* The position of the player in the current map */
uint16_t px, py; /* The position of the player on screen */ uint16_t px, py; /* The position of the player on screen */
int16_t wx, wy; /* position of the player in the world */ int8_t life; /* How many lives the player still has between 0 and 100. */
int8_t life; /* How many lives the player still has between 0 and 100. */
int8_t speed; /* The speed of the movement of the player. */ int8_t speed; /* The speed of the movement of the player. */
/* set to true if a action can be done in the current position of the map */ /* set to true if a action can be done in the current position of the map */
bool canDoSomething; bool canDoSomething;
/* indicates which data are relevant to the current action in the */ /* indicates which data are relevant to the current action in the */
@ -41,9 +33,9 @@ typedef struct {
bool isDoingAction; bool isDoingAction;
/* the player is interacting with a NPC */ /* the player is interacting with a NPC */
bool isInteractingWithNPC; bool isInteractingWithNPC;
bool is_male;
} Player; } Player;
typedef struct { typedef struct {
uint32_t ID; uint32_t ID;
/* data to be shown in the dialog*/ /* data to be shown in the dialog*/
@ -61,47 +53,77 @@ typedef struct {
int32_t nextOther; int32_t nextOther;
} Dialog; } Dialog;
typedef struct { typedef struct {
/* position of the item */ /* position of the item */
uint32_t x; uint32_t x;
uint32_t y; uint32_t y;
/* its name */ /*id of it's icon*/
uint32_t icon;
char *name; char *name;
/* its class (NPC, SGN, INFO, ... )*/
char *type;
/* the ID of the first element of the dialog */ /* the ID of the first element of the dialog */
/* (to be aligned with "dialogs.json" IDs)*/ /* (to be aligned with "dialogs.json" IDs)*/
uint32_t dialogID; uint32_t dialogID;
/* 0 if imperative dialog (story mode) */ /*if the dialog is interactive or not*/
/* or 1 if the player need to press [SHIFT] to initiate the sequence*/
uint32_t needAction; uint32_t needAction;
} Sign;
typedef struct {
/* current coordinates of the NPC */
uint32_t curx;
uint32_t cury;
/* initial coordinates of the NPC (needed to get absolute coordinates of
* path) */
uint32_t x;
uint32_t y;
/* id of it's face */
uint16_t face;
uint8_t paused;
uint8_t has_dialog;
/* the ID of the first element of the dialog */
/* (to be aligned with "dialogs.json" IDs)*/
uint32_t dialogID;
/*if the dialog is interactive or not*/
uint32_t needAction;
char *name;
/* data for NPC's trajectories */ /* data for NPC's trajectories */
uint32_t hasPath; uint32_t hasPath;
uint32_t path_length; uint32_t path_length;
uint32_t currentPoint;
int16_t *xpath; int16_t *xpath;
int16_t *ypath; int16_t *ypath;
/* ... this can be extended as per needs ... */ int type : 32;
} ExtraData;
uint8_t current_group;
uint8_t hostile_to_group;
uint16_t __padding;
} NPC;
typedef struct {
Collider collider;
/* The destination portal */
void *portal;
/* The destination map */
void *map;
} Portal;
typedef struct { typedef struct {
/* width, height and the number of layer of the map */ /* width, height and the number of layer of the map */
uint32_t x;
uint32_t y;
uint32_t w; uint32_t w;
uint32_t h; uint32_t h;
uint32_t nblayers; uint32_t nblayers;
uint32_t tileset_size; uint32_t tileset_size;
/* world coordinates of the upper left and bootom right*/
/* corners of the current map to be multiplied in game by PXSIZE */
uint32_t xmin;
uint32_t ymin;
uint32_t xmax;
uint32_t ymax;
/* the tileset to use */ /* the tileset to use */
bopti_image_t *tileset; bopti_image_t *tileset;
@ -109,11 +131,14 @@ typedef struct {
/* this is given by the layer Walkable of the map in Tiled */ /* this is given by the layer Walkable of the map in Tiled */
uint8_t *walkable; uint8_t *walkable;
/* structure that contains all the items on the map to interract with */ uint32_t nbNPC;
/* each portion of the map has its own list to avoid scrutinizing too much */ NPC *npcs;
/* data when lloking for proximity of items */
uint32_t nbextradata; uint32_t nbSign;
ExtraData *extradata; Sign *signs;
uint32_t nbPortal;
Portal *portals;
/* structure that contains all the dialogs for that part of the map */ /* structure that contains all the dialogs for that part of the map */
uint32_t nbdialogsdata; uint32_t nbdialogsdata;
@ -121,16 +146,16 @@ typedef struct {
/* list of all the tiles to draw the background and the foreground layers */ /* list of all the tiles to draw the background and the foreground layers */
uint16_t *layers[]; uint16_t *layers[];
} Map; } Map;
/* This struct will contain all the data of the game. It will make it possible /* This struct will contain all the data of the game. It will make it possible
* to pass it to the NPCs to let them interact with the player and the rest of * to pass it to the NPCs to let them interact with the player and the rest of
* the world. */ * the world. */
typedef struct { typedef struct {
Map *map_level; /* The level that the player is currently playing */ Map *map_level; /* The level that the player is currently playing */
Player player; /* The player data (see player.h). */ Player player; /* The player data. */
EventHandler handler; /* The event handler (see events.h). */
/* Some global variables */ /* Some global variables */
/* Set to true when asked for exit */ /* Set to true when asked for exit */
bool exittoOS; bool exittoOS;
@ -145,20 +170,33 @@ typedef struct {
bool debug_map; bool debug_map;
bool debug_player; bool debug_player;
bool debug_extra; bool debug_extra;
int mana; /* Only for testing events TODO: Remove this! */
} Game; } Game;
/* (Mibi88) TODO: Describe what this function is doing. */ /* (Mibi88) TODO: Describe what this function is doing. */
void game_logic(Game *game); void game_logic(Game *game);
/* Draws everything on screen. */ /* game_draw()
void draw(Game *game); *
* Draws everything on screen.
* game: The game struct.
*/
void game_draw(Game *game);
/* This render a small sign on the upper lecft corner of the screen */ /* game_render_indicator()
/* if the player can do an action */ *
void render_indicator(Game *game); * This render a small sign on the upper left corner of the screen
* if the player can do an action
* game: The game struct.
*/
void game_render_indicator(Game *game);
/* Handle key presses. */ /* game_get_inputs()
void get_inputs(Game *game); *
* Handle key presses.
* game: The game struct.
*/
void game_get_inputs(Game *game);
#endif #endif

View file

@ -1,83 +1,86 @@
#include "config.h"
#include <fxlibc/printf.h>
#include <gint/cpu.h>
#include <gint/display.h> #include <gint/display.h>
#include <gint/keyboard.h> #include <gint/keyboard.h>
#include <gint/timer.h> #include <gint/timer.h>
#include <gint/cpu.h>
#include <fxlibc/printf.h>
#include "config.h"
#include "npc.h"
#if USB_FEATURE #if USB_FEATURE
#include <gint/usb-ff-bulk.h> #include <gint/usb-ff-bulk.h>
#include <gint/usb.h> #include <gint/usb.h>
#endif //USB_FEATURE #endif // USB_FEATURE
#if GRAYMODEOK #if GRAYMODEOK
#include <gint/gray.h> #include <gint/gray.h>
#endif //GRAYMODEOK #endif // GRAYMODEOK
#include <stdint.h> #if DEBUGMODE
#include <stdbool.h> #include <gint/gdb.h>
#endif /*DEBUGMODE*/
#include "dialogs.h"
#include "game.h" #include "game.h"
#include "mapdata.h" #include "mapdata.h"
#include "dialogs.h" #include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
extern bopti_image_t player_face_img; extern bopti_image_t player_face_img;
extern Map *worldRPG[]; extern Map *worldRPG[];
/* Game data (defined in "game.h")*/ /* Game data (defined in "game.h")*/
Game game = { Game game = {
NULL, NULL,
{12*PXSIZE, 36*PXSIZE, 0, 0, 12*PXSIZE, 36*PXSIZE, 100, SPEED, false, 0, false, false}, {12 * PXSIZE, 36 * PXSIZE, 0, 0, 100, SPEED, false, 0, false, false, true},
false, false, false, 0 {{}, {}, 0},
false,
false,
false,
0,
/* debug variables*/ /* debug variables*/
, false, false, false false,
}; false,
false,
100};
/* screen capture management code */ /* screen capture management code. TODO: Clean this up! */
#if USB_FEATURE #if USB_FEATURE
void USB_feature( void ) void USB_feature(void) {
{ if(game.screenshot && usb_is_open()) {
if (game.screenshot && usb_is_open()) {
#if GRAYMODEOK // This is a trick, if GRAYMODEOK is defined then #if GRAYMODEOK // This is a trick, if GRAYMODEOK is defined then
// we make the code accessible // we make the code accessible
if (dgray_enabled()) if(dgray_enabled())
usb_fxlink_screenshot_gray(false); usb_fxlink_screenshot_gray(false);
else else
#endif #endif
// else we just let the usual screeshot function // else we just let the usual screeshot function
usb_fxlink_screenshot(false); usb_fxlink_screenshot(false);
game.screenshot = false; game.screenshot = false;
} }
if(game.record && usb_is_open()) {
if (game.record && usb_is_open()) { #if GRAYMODEOK
#if GRAYMODEOK if(dgray_enabled())
usb_fxlink_videocapture_gray(false);
else
if (dgray_enabled()) #endif
usb_fxlink_videocapture_gray(false);
else
#endif
usb_fxlink_videocapture(false); usb_fxlink_videocapture(false);
}
} }
}
#endif #endif
@ -90,47 +93,50 @@ int update_time(void) {
int main(void) { int main(void) {
#if DEBUGMODE
gdb_start_on_exception();
#endif /*DEBUGMODE*/
__printf_enable_fp(); __printf_enable_fp();
int timer; int timer;
timer = timer_configure(TIMER_TMU, 1000, GINT_CALL(update_time)); timer = timer_configure(TIMER_TMU, 1000, GINT_CALL(update_time));
if(timer < 0){ if(timer < 0) {
return -1; return -1;
} }
timer_start(timer); timer_start(timer);
game.map_level = worldRPG[0]; game.map_level = worldRPG[0];
events_init_handler(&game.handler);
events_bind_variable(&game.handler, (int *)&game.player.life, "life");
events_bind_variable(&game.handler, &game.mana, "mana");
reload_npc(&game); // reload_npc(&game);
#if USB_FEATURE
usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL};
usb_open(interfaces, GINT_CALL_NULL);
#endif
#if USB_FEATURE
usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL};
usb_open(interfaces, GINT_CALL_NULL);
#endif
/* start grayscale engine */ /* start grayscale engine */
#if GRAYMODEOK #if GRAYMODEOK
dgray(DGRAY_ON); dgray(DGRAY_ON);
#endif #endif
/* #if DEBUGMODE
showtext_dialog(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, true); dupdate();
int in = showtext_dialog_ask(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, false, "Lorem\0Ipsum\0Dolor", 3, 0); getkey();
if(in==2) showtext_dialog(&game, &player_face_img, "You choosed Dolor", false, true); #endif
else if(in==1) showtext_dialog(&game, &player_face_img, "You choosed Ipsum", false, true);
else showtext_dialog(&game, &player_face_img, "You choosed Lorem", false, true);
*/
do{ do {
/* clear screen */ /* clear screen */
dclear(C_WHITE); dclear(C_WHITE);
/* render the map */ /* render the map */
draw(&game); game_draw(&game);
#if DEBUGMODE && FXCG50 /*#if DEBUGMODE && GINT_RENDER_RGB
if (game.debug_map) if (game.debug_map)
{ {
dfont( NULL ); dfont( NULL );
@ -160,14 +166,15 @@ int main(void) {
{ {
dfont( NULL ); dfont( NULL );
for (int i=0; i<game.map_level->nbextradata; i++ ) for (int i=0; i<game.map_level->nbextradata; i++ )
dprint( 10, 90+i*15, C_RED, "X= %d - Y= %d - T: %d - ID: %d - S: %c", dprint( 10, 90+i*15, C_RED, "X= %d - Y= %d - T: %d - ID: %d
game.map_level->extradata[i].x, - S: %c", game.map_level->extradata[i].x,
game.map_level->extradata[i].y, game.map_level->extradata[i].y,
game.map_level->extradata[i].dialogID, game.map_level->extradata[i].dialogID,
game.map_level->dialogs[ game.map_level->extradata[i].dialogID ].ID, game.map_level->dialogs[
game.map_level->dialogs[ game.map_level->extradata[i].dialogID ].conclusion1[0] ); game.map_level->extradata[i].dialogID ].ID, game.map_level->dialogs[
game.map_level->extradata[i].dialogID ].conclusion1[0] );
} }
#endif #endif*/
/* start the logic of the game */ /* start the logic of the game */
game_logic(&game); game_logic(&game);
@ -175,33 +182,30 @@ int main(void) {
/* Screen blit */ /* Screen blit */
dupdate(); dupdate();
/* Screen capture feature if enabled */ /* Screen capture feature if enabled */
#if USB_FEATURE #if USB_FEATURE
USB_feature(); USB_feature();
#endif #endif
/* Management of the inputs */ /* Management of the inputs */
get_inputs(&game); game_get_inputs(&game);
/* Run the game at max. 50fps */ /* Run the game at max. 50fps */
while(game.frame_duration < 20) sleep(); while(game.frame_duration < 20)
sleep();
/* Reset frame_duration for the next frame */ /* Reset frame_duration for the next frame */
game.frame_duration = 0; game.frame_duration = 0;
}while(!game.exittoOS); // want to exit ? } while(!game.exittoOS); // want to exit ?
/* shutdown grayengine*/
#if GRAYMODEOK
dgray(DGRAY_OFF);
#endif
/* close USB */
/* shutdown grayengine*/ #if USB_FEATURE
#if GRAYMODEOK usb_close();
dgray(DGRAY_OFF); #endif
#endif
/* close USB */
#if USB_FEATURE
usb_close();
#endif
timer_stop(timer); timer_stop(timer);
return 1; return 1;
} }

182
src/map.c
View file

@ -1,14 +1,22 @@
#include "map.h" #include "map.h"
#include "config.h" #include "config.h"
#include "game.h" #include "game.h"
#include <gint/display.h> #include <gint/display.h>
#include <gint/keyboard.h>
extern Map *worldRPG[]; extern Map level0;
//extern ExtraData *extraRPG[]; extern Map level1;
extern Map level2;
extern Map level3;
extern Map level4;
Map *worldRPG[] = {&level0, &level1, &level2, &level3, &level4, NULL};
void render_map(Game *game) { // extern ExtraData *extraRPG[];
void map_render(Game *game) {
Map *map_level = game->map_level; Map *map_level = game->map_level;
Player *player = &game->player; Player *player = &game->player;
@ -25,9 +33,10 @@ void render_map(Game *game) {
unsigned char mx, my; unsigned char mx, my;
/* dw and dh contain the amount of tiles that will be drawn on x and on /* dw and dh contain the amount of tiles that will be drawn on x and on
* y. */ * y. */
unsigned char dw = DWIDTH/T_WIDTH+2, dh = DHEIGHT/T_HEIGHT+1; unsigned char dw = DWIDTH / T_WIDTH + 2, dh = DHEIGHT / T_HEIGHT + 1;
/* mw and mh will contain the height and the width of the map. */ /* mw and mh will contain the height and the width of the map. */
unsigned short int mw = map_level->w*T_WIDTH, mh = map_level->h*T_HEIGHT; unsigned short int mw = map_level->w * T_WIDTH,
mh = map_level->h * T_HEIGHT;
/* tile contains the tile to draw. */ /* tile contains the tile to draw. */
short int tile; short int tile;
/* The position where I start drawing */ /* The position where I start drawing */
@ -39,62 +48,62 @@ void render_map(Game *game) {
/* The index of the current tile we're drawing in the layer. */ /* The index of the current tile we're drawing in the layer. */
int current_index; int current_index;
/* Fix sx. */ /* Fix sx. */
if(player->x<DWIDTH/2){ if(player->x < DWIDTH / 2) {
/* If I can't center the player because I'm near the left border of /* If I can't center the player because I'm near the left border of
* the map. */ * the map. */
player->px = player->x; player->px = player->x;
sx = 0; sx = 0;
}else if(player->x+DWIDTH/2>mw){ } else if(player->x + DWIDTH / 2 > mw) {
/* If I can't center the player because I'm near the right border of /* If I can't center the player because I'm near the right border of
* the map. */ * the map. */
sx = mw-DWIDTH; sx = mw - DWIDTH;
player->px = player->x-sx; player->px = player->x - sx;
}else{ } else {
/* I can center the player. */ /* I can center the player. */
player->px = DWIDTH/2; player->px = DWIDTH / 2;
sx = player->x-player->px; sx = player->x - player->px;
} }
/* Fix sy. */ /* Fix sy. */
if(player->y<DHEIGHT/2){ if(player->y < DHEIGHT / 2) {
/* If I can't center the player because I'm near the top border of /* If I can't center the player because I'm near the top border of
* the map. */ * the map. */
player->py = player->y; player->py = player->y;
sy = 0; sy = 0;
}else if(player->y+DHEIGHT/2>mh){ } else if(player->y + DHEIGHT / 2 > mh) {
/* If I can't center the player because I'm near the bottom border /* If I can't center the player because I'm near the bottom border
* of the map. */ * of the map. */
sy = mh-DHEIGHT; sy = mh - DHEIGHT;
player->py = player->y-sy; player->py = player->y - sy;
}else{ } else {
/* I can center the player. */ /* I can center the player. */
player->py = DHEIGHT/2; player->py = DHEIGHT / 2;
sy = player->y-player->py; sy = player->y - player->py;
} }
tx = sx/T_WIDTH; tx = sx / T_WIDTH;
ty = sy/T_HEIGHT; ty = sy / T_HEIGHT;
mx = sx-tx*T_WIDTH; mx = sx - tx * T_WIDTH;
my = sy-ty*T_HEIGHT; my = sy - ty * T_HEIGHT;
for (l = 0; l < map_level->nblayers-1; l++){ for(l = 0; l < map_level->nblayers - 1; l++) {
/* Draw a layer of the map on screen. */ /* Draw a layer of the map on screen. */
for(y=0;y<dh;y++){ for(y = 0; y < dh; y++) {
for(x=0;x<dw;x++){ for(x = 0; x < dw; x++) {
/* I get the tile number if his position is inside the map. Then /* I get the tile number if his position is inside the map. Then
* I draw it. */ * I draw it. */
if(tx+x>=0 && tx+x < map_level->w && if(tx + x >= 0 && tx + x < map_level->w && ty + y >= 0 &&
ty+y>=0 && ty+y < map_level->h){ ty + y < map_level->h) {
/* index of the current tile */ /* index of the current tile */
current_index = (y+ty) * map_level->w + tx+x; current_index = (y + ty) * map_level->w + tx + x;
/* we get the ID of the tile in the current drawable layers /* we get the ID of the tile in the current drawable layers
*/ */
tile = map_level->layers[l][current_index]; tile = map_level->layers[l][current_index];
/* tile == -1 means nothing to be drawn */ /* tile == -1 means nothing to be drawn */
if(tile >= 0){ if(tile >= 0) {
/* get x and y position in the tileset image */ /* get x and y position in the tileset image */
xtile = (tile % map_level->tileset_size) * T_WIDTH; xtile = (tile % map_level->tileset_size) * T_WIDTH;
ytile = (tile / map_level->tileset_size) * T_HEIGHT; ytile = (tile / map_level->tileset_size) * T_HEIGHT;
/* render */ /* render */
dsubimage(x*T_WIDTH-mx, y*T_HEIGHT-my, dsubimage(x * T_WIDTH - mx, y * T_HEIGHT - my,
map_level->tileset, xtile, ytile, T_WIDTH, map_level->tileset, xtile, ytile, T_WIDTH,
T_HEIGHT, DIMAGE_NONE); T_HEIGHT, DIMAGE_NONE);
} }
@ -104,7 +113,7 @@ void render_map(Game *game) {
} }
} }
void render_map_by_layer(Game *game, int layer) { void map_render_by_layer(Game *game, int layer) {
Map *map_level = game->map_level; Map *map_level = game->map_level;
Player *player = &game->player; Player *player = &game->player;
@ -121,9 +130,10 @@ void render_map_by_layer(Game *game, int layer) {
unsigned char mx, my; unsigned char mx, my;
/* dw and dh contain the amount of tiles that will be drawn on x and on /* dw and dh contain the amount of tiles that will be drawn on x and on
* y. */ * y. */
unsigned char dw = DWIDTH/T_WIDTH+2, dh = DHEIGHT/T_HEIGHT+1; unsigned char dw = DWIDTH / T_WIDTH + 2, dh = DHEIGHT / T_HEIGHT + 1;
/* mw and mh will contain the height and the width of the map. */ /* mw and mh will contain the height and the width of the map. */
unsigned short int mw = map_level->w*T_WIDTH, mh = map_level->h*T_HEIGHT; unsigned short int mw = map_level->w * T_WIDTH,
mh = map_level->h * T_HEIGHT;
/* tile contains the tile to draw. */ /* tile contains the tile to draw. */
short int tile; short int tile;
/* The position where I start drawing */ /* The position where I start drawing */
@ -131,109 +141,101 @@ void render_map_by_layer(Game *game, int layer) {
/* The position of the tile in the tileset. */ /* The position of the tile in the tileset. */
unsigned short int xtile, ytile; unsigned short int xtile, ytile;
/* Fix sx. */ /* Fix sx. */
if(player->x<DWIDTH/2){ if(player->x < DWIDTH / 2) {
/* If I can't center the player because I'm near the left border of /* If I can't center the player because I'm near the left border of
* the map. */ * the map. */
player->px = player->x; player->px = player->x;
sx = 0; sx = 0;
}else if(player->x+DWIDTH/2>mw){ } else if(player->x + DWIDTH / 2 > mw) {
/* If I can't center the player because I'm near the right border of /* If I can't center the player because I'm near the right border of
* the map. */ * the map. */
sx = mw-DWIDTH; sx = mw - DWIDTH;
player->px = player->x-sx; player->px = player->x - sx;
}else{ } else {
/* I can center the player. */ /* I can center the player. */
player->px = DWIDTH/2; player->px = DWIDTH / 2;
sx = player->x-player->px; sx = player->x - player->px;
} }
/* Fix sy. */ /* Fix sy. */
if(player->y<DHEIGHT/2){ if(player->y < DHEIGHT / 2) {
/* If I can't center the player because I'm near the top border of /* If I can't center the player because I'm near the top border of
* the map. */ * the map. */
player->py = player->y; player->py = player->y;
sy = 0; sy = 0;
}else if(player->y+DHEIGHT/2>mh){ } else if(player->y + DHEIGHT / 2 > mh) {
/* If I can't center the player because I'm near the bottom border /* If I can't center the player because I'm near the bottom border
* of the map. */ * of the map. */
sy = mh-DHEIGHT; sy = mh - DHEIGHT;
player->py = player->y-sy; player->py = player->y - sy;
}else{ } else {
/* I can center the player. */ /* I can center the player. */
player->py = DHEIGHT/2; player->py = DHEIGHT / 2;
sy = player->y-player->py; sy = player->y - player->py;
} }
tx = sx/T_WIDTH; tx = sx / T_WIDTH;
ty = sy/T_HEIGHT; ty = sy / T_HEIGHT;
mx = sx-tx*T_WIDTH; mx = sx - tx * T_WIDTH;
my = sy-ty*T_HEIGHT; my = sy - ty * T_HEIGHT;
/* Draw a layer of the map on screen. */ /* Draw a layer of the map on screen. */
for(y=0;y<dh;y++){ for(y = 0; y < dh; y++) {
for(x=0;x<dw;x++){ for(x = 0; x < dw; x++) {
/* I get the tile number if his position is inside the map. Then /* I get the tile number if his position is inside the map. Then
* I draw it. */ * I draw it. */
if(tx+x>=0 && tx+x < map_level->w && if(tx + x >= 0 && tx + x < map_level->w && ty + y >= 0 &&
ty+y>=0 && ty+y < map_level->h){ ty + y < map_level->h) {
/* index of the current tile */ /* index of the current tile */
int currentIndex = (y+ty) * map_level->w + tx+x; int currentIndex = (y + ty) * map_level->w + tx + x;
/* we get the ID of the tile in the current drawable layers /* we get the ID of the tile in the current drawable layers
*/ */
tile = map_level->layers[layer][currentIndex]; tile = map_level->layers[layer][currentIndex];
/* tile == -1 means nothing to be drawn */ /* tile == -1 means nothing to be drawn */
if(tile >= 0){ if(tile >= 0) {
/* get x and y position in the tileset image */ /* get x and y position in the tileset image */
xtile = (tile % map_level->tileset_size) * T_WIDTH; xtile = (tile % map_level->tileset_size) * T_WIDTH;
ytile = (tile / map_level->tileset_size) * T_HEIGHT; ytile = (tile / map_level->tileset_size) * T_HEIGHT;
/* render */ /* render */
dsubimage(x*T_WIDTH-mx, y*T_HEIGHT-my, dsubimage(x * T_WIDTH - mx, y * T_HEIGHT - my,
map_level->tileset, xtile, ytile, T_WIDTH, map_level->tileset, xtile, ytile, T_WIDTH,
T_HEIGHT, DIMAGE_NONE); T_HEIGHT, DIMAGE_NONE);
} }
} }
} }
} }
} }
short int get_tile(Game *game, int x, int y, int l) { short int map_get_tile(Game *game, int x, int y, int l) {
Map *map_level = game->map_level; Map *map_level = game->map_level;
/* Get the tile at (x, y) on layer l. Returns the tile ID or MAP_OUTSIDE if /* Get the tile at (x, y) on layer l. Returns the tile ID or MAP_OUTSIDE if
* it's not found. */ * it's not found. */
return (x>=0 && x < (int) map_level->w && y>=0 && y < (int) map_level->h) ? return (x >= 0 && x < (int)map_level->w && y >= 0 && y < (int)map_level->h)
map_level->layers[l][y * map_level->w + x] : MAP_OUTSIDE; ? map_level->layers[l][y * map_level->w + x]
: MAP_OUTSIDE;
} }
short int get_walkable(Game *game, int x, int y) { short int map_get_walkable(Game *game, int x, int y) {
Map *map_level = game->map_level; Map *map_level = game->map_level;
/* Get the tile at (x, y). Returns the tile ID or MAP_OUTSIDE if she's not /* Get the tile at (x, y). Returns the tile ID or MAP_OUTSIDE if she's not
* found. */ * found. */
return (x>=0 && x < (int) map_level->w && y>=0 && y < (int) map_level->h) ? return (x >= 0 && x < (int)map_level->w && y >= 0 && y < (int)map_level->h)
map_level->walkable[y * map_level->w + x] : MAP_OUTSIDE; ? map_level->walkable[y * map_level->w + x]
: MAP_OUTSIDE;
} }
/* return the pointer to the map containing the given position */ Map *map_get_for_tile(Game *game, int x, int y) {
Map *get_map_for_coordinates( Game *game, int x, int y )
{
/* check if the current map contains the point */
if (x>= (int)game->map_level->xmin && x< (int)game->map_level->xmax &&
y>= (int)game->map_level->ymin && y< (int)game->map_level->ymax)
return game->map_level;
/* else we check in worldRPG if there is a mal containing that point */
int i = 0; int i = 0;
Map *current = worldRPG[i]; Map *map = worldRPG[i];
do do {
{ int rx = x - map->x;
if (x>= (int)current->xmin && x< (int)current->xmax && int ry = y - map->y;
y>= (int)current->ymin && y< (int)current->ymax) if(rx >= 0 && rx < (int)map->w && ry >= 0 && ry < (int)map->h) {
return current; return map;
}
i++; i++;
current = worldRPG[i]; map = worldRPG[i];
} } while(map != NULL);
while (current!=NULL); return game->map_level;
/* else we return NULL cause the point is a not within a map */
return NULL;
} }

View file

@ -1,39 +1,55 @@
#ifndef MAP_H #ifndef MAP_H
#define MAP_H #define MAP_H
#define BACKGROUND 0 #define BACKGROUND 0
#define FOREGROUND 1 #define FOREGROUND 1
#define MAP_OUTSIDE -2 /* Returned by get_tile_at_pos if the point is outside of #define MAP_OUTSIDE \
* the map. */ -2 /* Returned by get_tile_at_pos if the point is outside of \
* the map. */
#include "game.h" #include "game.h"
#include "player.h" #include "player.h"
/* Structure 'Map' has been moved to game.h */ /* Structure 'Map' has been moved to game.h */
/* to avoid circular references between map.h, game.h and player.h */ /* to avoid circular references between map.h, game.h and player.h */
/* only methods propotypes are now in dedicated header files */ /* only methods propotypes are now in dedicated header files */
/* map_render()
*
/* Draws the map map on the entire screen to be viewed by the player player. */ * Draws the map map on the entire screen to be viewed by the player player.
void render_map(Game *game); * game: The game struct.
/* Draws the map layer on the entire screen to be viewed by the player player.
*/ */
void render_map_by_layer(Game *game, int layer); void map_render(Game *game);
/* Get the tile at (x, y) of the map map. If the tile is located outside of the /* map_render_by_layer()
* screen, MAP_OUTSIDE is returned. */ *
short int get_tile(Game *game, int x, int y, int l); * Draws the map layer on the entire screen to be viewed by the player player.
* game: The game struct.
* layer: The layer to render.
*/
void map_render_by_layer(Game *game, int layer);
/* Returns what is in the walkable layer at (x, y). */ /* map_get_tile()
short int get_walkable(Game *game, int x, int y); *
* Get the tile at (x, y) of the map map. If the tile is located outside of the
* screen, MAP_OUTSIDE is returned.
* game: The game struct.
* x: The coordinates of the tile.
* y: The coordinates of the tile.
* l: The layer of the tile.
*/
short int map_get_tile(Game *game, int x, int y, int l);
/* return the pointer to the map containing the given position */ /* map_get_walkable()
Map* get_map_for_coordinates(Game *game, int x, int y ); *
* Returns what is in the walkable layer at (x, y).
* game: The game struct.
* x: The coordinates of the tile.
* y: The coordinates of the tile.
*/
short int map_get_walkable(Game *game, int x, int y);
Map *map_get_for_tile(Game *game, int x, int y);
#endif #endif

View file

@ -1,10 +1,10 @@
#ifndef MAPDATA_H #ifndef MAPDATA_H
#define MAPDATA_H #define MAPDATA_H
#include <stdint.h>
#include "game.h" #include "game.h"
#include <stdint.h>
extern Map *worldRPG[]; extern Map *worldRPG[];
#endif #endif

View file

@ -1,12 +1,11 @@
#include "memory.h" #include "memory.h"
bool is_in(short int *array, short int array_length, short int item) { bool memory_is_in(short int *array, short int array_length, short int item) {
short int i; short int i;
for(i=0;i<array_length;i++){ for(i = 0; i < array_length; i++) {
if(array[i] == item){ if(array[i] == item) {
return true; return true;
} }
} }
return false; return false;
} }

View file

@ -2,8 +2,13 @@
#define MEMORY_H #define MEMORY_H
#include <stdbool.h> #include <stdbool.h>
/* memory_is_in()
bool is_in(short int *array, short int array_length, short int item); *
* returns true if item is in array.
* array: The array to search in.
* array_length: The length of the array.
* item: The item to search for.
*/
bool memory_is_in(short int *array, short int array_length, short int item);
#endif #endif

403
src/npc.c
View file

@ -1,208 +1,275 @@
#include "npc.h" #include "npc.h"
#include "config.h"
#include "dialogs.h" #include "dialogs.h"
#include "game.h" #include "game.h"
#include "map.h" #include "map.h"
#include "config.h"
#include <gint/display.h> #include <gint/display.h>
#include <gint/keyboard.h> /*debug*/ #include <gint/keyboard.h> /*debug*/
#include <math.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
extern bopti_image_t tiny_npc_male;
extern bopti_image_t tiny_npc_female;
extern bopti_image_t tiny_npc_milkman;
extern bopti_image_t tiny_npc_police;
extern bopti_image_t demo_PNJ_img; // NPC *npcRPG;
// uint32_t nbNPC = 0;
float length(float x, float y) { return sqrtf(x * x + y * y); }
/* the color of the text to go to the next dialog phase */ int npc_clear_path(NPC *npc) {
/* it improves readability to have somathing lighter */ npc->currentPoint = 0;
#if defined(FXCG50) npc->hasPath = 0;
#define PATH_COLOR C_RED npc->path_length = 0;
#else free(npc->xpath);
#define PATH_COLOR C_BLACK free(npc->ypath);
#endif npc->xpath = malloc(4);
npc->ypath = malloc(4);
if(npc->xpath == NULL || npc->ypath == NULL)
NPC *npcRPG; return 1;
uint32_t nbNPC = 0; return 0;
float length( float x, float y )
{
return sqrtf( x*x+y*y );
} }
void update_npc( [[maybe_unused]] Game *game) int npc_append_path(uint16_t x, uint16_t y, NPC *npc) {
{ npc->xpath = realloc(npc->xpath, npc->path_length * 2 + 2);
for( uint32_t u=0; u<nbNPC; u++ ) npc->ypath = realloc(npc->ypath, npc->path_length * 2 + 2);
{ if(npc->xpath == NULL || npc->ypath == NULL)
/* if the NPC has a path to follow AND is not currently in pause */ return 1;
/* (talking with the player) */ npc->path_length++;
if (npcRPG[u].hasPath==1 && npcRPG[u].paused==false) npc->xpath[npc->path_length - 1] = x - npc->x;
{ npc->ypath[npc->path_length - 1] = y - npc->y;
float vecX = (float) (npcRPG[u].xpath[ npcRPG[u].currentPoint ] + return 0;
npcRPG[u].x) - npcRPG[u].curx;
float vecY = (float) (npcRPG[u].ypath[ npcRPG[u].currentPoint ] +
npcRPG[u].y) - npcRPG[u].cury;
float vecN = length(vecX, vecY);
if (vecN>0.5f)
{
vecX /= vecN*2.0;
vecY /= vecN*2.0;
}
else
{
npcRPG[u].currentPoint++;
npcRPG[u].currentPoint = npcRPG[u].currentPoint % npcRPG[u].path_length;
}
npcRPG[u].curx += vecX;
npcRPG[u].cury += vecY;
}
}
} }
void reload_npc(Game *game) void as_clean(uint8_t *visited, uint8_t *gscore, uint8_t *fscore) {
{ free(visited);
if (npcRPG!=NULL) free(gscore);
{ free(fscore);
free(npcRPG); }
npcRPG = NULL;
} int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t spos,
int16_t dest, NPC *npc) {
if(npc_clear_path(npc))
goto as_recons_fail;
nbNPC = 0; int16_t next = came_from[dest];
unsigned int i;
for (uint32_t u=0; u<game->map_level->nbextradata; u++) //uint pour enlever un warning for(i = 0; i < 64; i++) {
{ if(npc_append_path((next % w) * T_WIDTH, (next / h) * T_HEIGHT, npc)) {
ExtraData *Data = &game->map_level->extradata[u]; goto as_recons_fail;
}
if (strcmp(Data->type, "NPC")==0) /* the current data is a NPC */ next = came_from[next];
{ if(next == spos) {
nbNPC++; if(npc_append_path((spos % w) * T_WIDTH, (spos / h) * T_HEIGHT,
npc))
goto as_recons_fail;
break;
} }
} }
npcRPG = (NPC*) malloc( nbNPC * sizeof(NPC) ); uint16_t tx, ty;
int currentNPC=0;
for (uint32_t u=0; u<game->map_level->nbextradata; u++) //uint pour enlever un warning // Flip the path because it started from the end
{
ExtraData *Data = &game->map_level->extradata[u];
if (strcmp(Data->type, "NPC")==0) /* the current data is a NPC */ for(i = 0; i < npc->path_length / 2; i++) {
{ tx = npc->xpath[i];
npcRPG[currentNPC].curx = (float) Data->x; ty = npc->ypath[i];
npcRPG[currentNPC].cury = (float) Data->y; npc->xpath[i] = npc->xpath[npc->path_length - i - 1];
npcRPG[currentNPC].x = Data->x; npc->ypath[i] = npc->ypath[npc->path_length - i - 1];
npcRPG[currentNPC].y = Data->y; npc->ypath[npc->path_length - i - 1] = tx;
npcRPG[currentNPC].dialogID = Data->dialogID; npc->ypath[npc->path_length - i - 1] = ty;
npcRPG[currentNPC].currentPoint = 1; }
npcRPG[currentNPC].hasPath = Data->hasPath;
npcRPG[currentNPC].path_length = Data->path_length; free(came_from);
npcRPG[currentNPC].xpath = Data->xpath;
npcRPG[currentNPC].ypath = Data->ypath; npc->hasPath = true;
npcRPG[currentNPC].paused = false;
currentNPC++; return 0;
as_recons_fail:
free(came_from);
return 1;
}
// Returns non zero error code on failure
// Custom a* implemetation
// Unoptimized, may become an issue
int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
int32_t i, j;
int32_t w = full_map->w;
int32_t h = full_map->h;
int32_t x = (npc->curx >> PRECISION) / T_WIDTH;
int32_t y = (npc->cury >> PRECISION) / T_HEIGHT;
dest_x /= T_WIDTH;
dest_y /= T_HEIGHT;
int32_t spos = y * w + x;
uint8_t *map = full_map->walkable;
if(dest_x < 0 || dest_x > w || dest_y < 0 || dest_x > h)
return 2;
if(map[spos])
return 2;
if(map[dest_y * w + dest_x])
return 2;
npc_clear_path(npc);
uint8_t *visited = malloc(w * h);
for(i = 0; i < w * h; i++)
visited[i] = 1;
visited[spos] = 0;
int16_t *came_from = malloc(w * h * 2);
for(i = 0; i < w * h; i++)
came_from[i] = -1;
uint8_t *gscore = malloc(w * h * 2);
for(i = 0; i < w * h; i++)
gscore[i] = 255;
gscore[spos] = 0;
uint8_t *fscore = malloc(w * h * 2);
for(i = 0; i < w * h; i++)
fscore[i] = 255;
fscore[spos] = length(dest_x - x, dest_y - y);
uint8_t bscore;
int32_t bx = x;
int32_t by = y;
for(int iter = 0; iter < 64; iter++) {
bscore = 255;
// Cheapest known tile
for(i = 0; i <= w * h; i++) {
if(visited[i])
continue;
if(map[i] == 1)
continue;
if(fscore[i] > bscore)
continue;
bx = i % w;
by = i / w;
bscore = fscore[i];
}
if(bx == dest_x && by == dest_y) {
as_clean(visited, gscore, fscore);
return as_reconstruct_path(came_from, w, h, spos,
dest_y * w + dest_x, npc);
}
visited[by * w + bx] = 1;
int att_score;
for(i = bx - 1; i < bx + 2; i++) {
if(i > w)
break;
for(j = by - 1; j < by + 2; j++) {
if(j > h)
break;
if(map[j * w + i] == 1)
continue;
if(i == bx && j == by)
continue;
att_score = gscore[by * w + bx] + round(length(bx - i, by - j));
if(att_score < gscore[j * w + i]) {
came_from[j * w + i] = by * w + bx;
gscore[j * w + i] = att_score;
fscore[j * w + i] =
att_score + round(length(dest_x - i, dest_y - j));
if(visited[j * w + i])
visited[j * w + i] = 0;
}
}
} }
} }
as_clean(visited, gscore, fscore);
free(came_from);
return 3;
}
// Refactoring to make adding complexity cleaner
void update_npcs(Game *game) {
for(uint32_t u = 0; u < game->map_level->nbNPC; u++) {
update_npc(&game->map_level->npcs[u]);
}
}
void update_npc(NPC *npc) {
/* if the NPC has no path or is paused, skip it */
if(!npc->hasPath || npc->paused == true)
return;
float vecX = (float)(npc->xpath[npc->currentPoint] + npc->x) -
(npc->curx >> PRECISION);
float vecY = (float)(npc->ypath[npc->currentPoint] + npc->y) -
(npc->cury >> PRECISION);
float vecN = length(vecX, vecY);
if(vecN > 0.5f) {
vecX /= vecN * 2.0;
vecY /= vecN * 2.0;
} else {
npc->currentPoint++;
npc->currentPoint = npc->currentPoint % npc->path_length;
}
npc->curx += vecX * (float)(1 << PRECISION);
npc->cury += vecY * (float)(1 << PRECISION);
} }
void npc_draw(Game *game) { void npc_draw(Game *game) {
Player *pl = &game->player; Player *pl = &game->player;
size_t i;
const bopti_image_t *npc_sprites[FACES] = {
&tiny_npc_male, &tiny_npc_female, &tiny_npc_milkman, &tiny_npc_police};
for (uint32_t u=0; u<nbNPC; u++) //uint pour enlever un warning for(uint32_t u = 0; u < game->map_level->nbNPC; u++) {
{ NPC *Data = &game->map_level->npcs[u];
NPC *Data = &npcRPG[u];
/* TODO : This is for debugging purpose, JUste to render the path */ /* Render the path if in debug*/
/* to be followed by the NPC when this will be implemented */ #if DEBUGMODE
#if DEBUGMODE if(!Data->hasPath)
if (Data->hasPath==1) /* this NPC has a trajectory */ continue; /* this NPC has a trajectory */
{ int NbPoints = Data->path_length + 1;
int NbPoints = Data->path_length+1; for(int v = 0; v < NbPoints; v++) {
for(int v=0; v<NbPoints; v++)
{
int16_t deltaX1=((int16_t) (Data->x + int16_t deltaX1 =
Data->xpath[v % NbPoints]) * PXSIZE) ((int16_t)(Data->x + Data->xpath[v % NbPoints]) * PXSIZE) -
-(int16_t) pl->wx; (int16_t)pl->wx;
int16_t deltaY1=((int16_t) (Data->y + int16_t deltaY1 =
Data->ypath[v % NbPoints]) * PXSIZE) ((int16_t)(Data->y + Data->ypath[v % NbPoints]) * PXSIZE) -
-(int16_t) pl->wy; (int16_t)pl->wy;
int16_t deltaX2=((int16_t) (Data->x + int16_t deltaX2 =
Data->xpath[(v+1) % NbPoints]) * PXSIZE) ((int16_t)(Data->x + Data->xpath[(v + 1) % NbPoints]) *
-(int16_t) pl->wx; PXSIZE) -
int16_t deltaY2=((int16_t) (Data->y + (int16_t)pl->wx;
Data->ypath[(v+1) % NbPoints]) * PXSIZE) int16_t deltaY2 =
-(int16_t) pl->wy; ((int16_t)(Data->y + Data->ypath[(v + 1) % NbPoints]) *
PXSIZE) -
dline( pl->px + deltaX1, pl->py + deltaY1, (int16_t)pl->wy;
pl->px + deltaX2, pl->py + deltaY2,
PATH_COLOR);
}
}
#endif // DEBUGMODE
int16_t delX=((int16_t) (Data->curx * PXSIZE))-(int16_t) pl->wx;
int16_t delY=((int16_t) (Data->cury * PXSIZE))-(int16_t) pl->wy;
dimage( pl->px-P_WIDTH/2+delX, pl->py-P_HEIGHT/2+delY, &demo_PNJ_img);
}
}
void OLD_npc_draw(Game *game) {
Player *player = &game->player;
for (uint32_t u=0; u<game->map_level->nbextradata; u++) //uint pour enlever un warning
{
ExtraData *Data = &game->map_level->extradata[u];
if (strcmp(Data->type, "NPC")==0) /* the current data is a NPC */
{
/* TODO : This is for debugging purpose, JUste to render the path */
/* to be followed by the NPC when this will be implemented */
#if DEBUGMODE
if (Data->hasPath==1) /* this NPC has a trajectory */
{
int NbPoints = Data->path_length+1;
for(int v=0; v<NbPoints; v++)
{
int16_t deltaX1=((int16_t) (Data->x + Data->xpath[v % NbPoints]) * PXSIZE)-(int16_t) player->wx;
int16_t deltaY1=((int16_t) (Data->y + Data->ypath[v % NbPoints]) * PXSIZE)-(int16_t) player->wy;
int16_t deltaX2=((int16_t) (Data->x + Data->xpath[(v+1) % NbPoints]) * PXSIZE)-(int16_t) player->wx;
int16_t deltaY2=((int16_t) (Data->y + Data->ypath[(v+1) % NbPoints]) * PXSIZE)-(int16_t) player->wy;
dline( player->px + deltaX1, player->py + deltaY1,
player->px + deltaX2, player->py + deltaY2,
PATH_COLOR);
}
}
#endif // DEBUGMODE
int16_t deltaX=((int16_t) (Data->x * PXSIZE))-(int16_t) player->wx;
int16_t deltaY=((int16_t) (Data->y * PXSIZE))-(int16_t) player->wy;
dimage( player->px-P_WIDTH/2+deltaX,
player->py-P_HEIGHT/2+deltaY,
&demo_PNJ_img);
dline(pl->px + deltaX1, pl->py + deltaY1, pl->px + deltaX2,
pl->py + deltaY2, PATH_COLOR);
} }
#endif // DEBUGMODE
int16_t delX = ((Data->curx * PXSIZE) >> PRECISION) - (int16_t)pl->x;
int16_t delY = ((Data->cury * PXSIZE) >> PRECISION) - (int16_t)pl->y;
bopti_image_t *face = npc_sprites[Data->face];
dimage(pl->px - P_WIDTH / 2 + delX, pl->py - P_HEIGHT / 2 + delY, face);
} }
} }

Some files were not shown because too many files have changed in this diff Show more