mirror of
https://git.planet-casio.com/Slyvtt/Collab_RPG.git
synced 2024-12-29 13:03:43 +01:00
Compare commits
6 commits
ee3b25a366
...
35e1d498f9
Author | SHA1 | Date | |
---|---|---|---|
|
35e1d498f9 | ||
|
1c978dbefa | ||
|
e4be83213b | ||
|
e15109b220 | ||
|
b96e5b6a3f | ||
|
98c52fe29e |
14 changed files with 527 additions and 85 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -15,3 +15,5 @@ __pycache__/
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
tilesetnpp.json
|
tilesetnpp.json
|
||||||
|
|
||||||
|
docs/
|
||||||
|
|
305
Doxyfile
Normal file
305
Doxyfile
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
DOXYFILE_ENCODING = UTF-8
|
||||||
|
PROJECT_NAME = "Collab RPG"
|
||||||
|
PROJECT_NUMBER =
|
||||||
|
PROJECT_BRIEF =
|
||||||
|
PROJECT_LOGO =
|
||||||
|
OUTPUT_DIRECTORY = docs
|
||||||
|
CREATE_SUBDIRS = NO
|
||||||
|
CREATE_SUBDIRS_LEVEL = 8
|
||||||
|
ALLOW_UNICODE_NAMES = NO
|
||||||
|
OUTPUT_LANGUAGE = English
|
||||||
|
BRIEF_MEMBER_DESC = YES
|
||||||
|
REPEAT_BRIEF = YES
|
||||||
|
ABBREVIATE_BRIEF = "The $name class" \
|
||||||
|
"The $name widget" \
|
||||||
|
"The $name file" \
|
||||||
|
is \
|
||||||
|
provides \
|
||||||
|
specifies \
|
||||||
|
contains \
|
||||||
|
represents \
|
||||||
|
a \
|
||||||
|
an \
|
||||||
|
the
|
||||||
|
ALWAYS_DETAILED_SEC = NO
|
||||||
|
INLINE_INHERITED_MEMB = NO
|
||||||
|
FULL_PATH_NAMES = YES
|
||||||
|
STRIP_FROM_PATH =
|
||||||
|
STRIP_FROM_INC_PATH =
|
||||||
|
SHORT_NAMES = NO
|
||||||
|
JAVADOC_AUTOBRIEF = NO
|
||||||
|
JAVADOC_BANNER = NO
|
||||||
|
QT_AUTOBRIEF = NO
|
||||||
|
MULTILINE_CPP_IS_BRIEF = NO
|
||||||
|
PYTHON_DOCSTRING = YES
|
||||||
|
INHERIT_DOCS = YES
|
||||||
|
SEPARATE_MEMBER_PAGES = NO
|
||||||
|
TAB_SIZE = 4
|
||||||
|
ALIASES =
|
||||||
|
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||||
|
OPTIMIZE_OUTPUT_JAVA = NO
|
||||||
|
OPTIMIZE_FOR_FORTRAN = NO
|
||||||
|
OPTIMIZE_OUTPUT_VHDL = NO
|
||||||
|
OPTIMIZE_OUTPUT_SLICE = NO
|
||||||
|
EXTENSION_MAPPING =
|
||||||
|
MARKDOWN_SUPPORT = YES
|
||||||
|
TOC_INCLUDE_HEADINGS = 5
|
||||||
|
MARKDOWN_ID_STYLE = DOXYGEN
|
||||||
|
AUTOLINK_SUPPORT = YES
|
||||||
|
BUILTIN_STL_SUPPORT = NO
|
||||||
|
CPP_CLI_SUPPORT = NO
|
||||||
|
SIP_SUPPORT = NO
|
||||||
|
IDL_PROPERTY_SUPPORT = YES
|
||||||
|
DISTRIBUTE_GROUP_DOC = NO
|
||||||
|
GROUP_NESTED_COMPOUNDS = NO
|
||||||
|
SUBGROUPING = YES
|
||||||
|
INLINE_GROUPED_CLASSES = NO
|
||||||
|
INLINE_SIMPLE_STRUCTS = NO
|
||||||
|
TYPEDEF_HIDES_STRUCT = NO
|
||||||
|
LOOKUP_CACHE_SIZE = 0
|
||||||
|
NUM_PROC_THREADS = 1
|
||||||
|
TIMESTAMP = DATETIME
|
||||||
|
EXTRACT_ALL = YES
|
||||||
|
EXTRACT_PRIVATE = NO
|
||||||
|
EXTRACT_PRIV_VIRTUAL = NO
|
||||||
|
EXTRACT_PACKAGE = NO
|
||||||
|
EXTRACT_STATIC = NO
|
||||||
|
EXTRACT_LOCAL_CLASSES = YES
|
||||||
|
EXTRACT_LOCAL_METHODS = NO
|
||||||
|
EXTRACT_ANON_NSPACES = NO
|
||||||
|
RESOLVE_UNNAMED_PARAMS = YES
|
||||||
|
HIDE_UNDOC_MEMBERS = NO
|
||||||
|
HIDE_UNDOC_CLASSES = NO
|
||||||
|
HIDE_FRIEND_COMPOUNDS = NO
|
||||||
|
HIDE_IN_BODY_DOCS = NO
|
||||||
|
INTERNAL_DOCS = NO
|
||||||
|
CASE_SENSE_NAMES = SYSTEM
|
||||||
|
HIDE_SCOPE_NAMES = YES
|
||||||
|
HIDE_COMPOUND_REFERENCE= NO
|
||||||
|
SHOW_HEADERFILE = YES
|
||||||
|
SHOW_INCLUDE_FILES = YES
|
||||||
|
SHOW_GROUPED_MEMB_INC = NO
|
||||||
|
FORCE_LOCAL_INCLUDES = NO
|
||||||
|
INLINE_INFO = YES
|
||||||
|
SORT_MEMBER_DOCS = YES
|
||||||
|
SORT_BRIEF_DOCS = NO
|
||||||
|
SORT_MEMBERS_CTORS_1ST = NO
|
||||||
|
SORT_GROUP_NAMES = NO
|
||||||
|
SORT_BY_SCOPE_NAME = NO
|
||||||
|
STRICT_PROTO_MATCHING = NO
|
||||||
|
GENERATE_TODOLIST = YES
|
||||||
|
GENERATE_TESTLIST = YES
|
||||||
|
GENERATE_BUGLIST = YES
|
||||||
|
GENERATE_DEPRECATEDLIST= YES
|
||||||
|
ENABLED_SECTIONS =
|
||||||
|
MAX_INITIALIZER_LINES = 30
|
||||||
|
SHOW_USED_FILES = YES
|
||||||
|
SHOW_FILES = YES
|
||||||
|
SHOW_NAMESPACES = YES
|
||||||
|
FILE_VERSION_FILTER =
|
||||||
|
LAYOUT_FILE =
|
||||||
|
CITE_BIB_FILES =
|
||||||
|
QUIET = NO
|
||||||
|
WARNINGS = YES
|
||||||
|
WARN_IF_UNDOCUMENTED = YES
|
||||||
|
WARN_IF_DOC_ERROR = YES
|
||||||
|
WARN_IF_INCOMPLETE_DOC = YES
|
||||||
|
WARN_NO_PARAMDOC = NO
|
||||||
|
WARN_IF_UNDOC_ENUM_VAL = NO
|
||||||
|
WARN_AS_ERROR = NO
|
||||||
|
WARN_FORMAT = "$file:$line: $text"
|
||||||
|
WARN_LINE_FORMAT = "at line $line of file $file"
|
||||||
|
WARN_LOGFILE =
|
||||||
|
INPUT = src
|
||||||
|
INPUT_ENCODING = UTF-8
|
||||||
|
INPUT_FILE_ENCODING =
|
||||||
|
FILE_PATTERNS = *.h \
|
||||||
|
*.md
|
||||||
|
RECURSIVE = YES
|
||||||
|
EXCLUDE =
|
||||||
|
EXCLUDE_SYMLINKS = NO
|
||||||
|
EXCLUDE_PATTERNS =
|
||||||
|
EXCLUDE_SYMBOLS =
|
||||||
|
EXAMPLE_PATH =
|
||||||
|
EXAMPLE_PATTERNS = *
|
||||||
|
EXAMPLE_RECURSIVE = NO
|
||||||
|
IMAGE_PATH =
|
||||||
|
INPUT_FILTER =
|
||||||
|
FILTER_PATTERNS =
|
||||||
|
FILTER_SOURCE_FILES = NO
|
||||||
|
FILTER_SOURCE_PATTERNS =
|
||||||
|
USE_MDFILE_AS_MAINPAGE =
|
||||||
|
FORTRAN_COMMENT_AFTER = 72
|
||||||
|
SOURCE_BROWSER = YES
|
||||||
|
INLINE_SOURCES = NO
|
||||||
|
STRIP_CODE_COMMENTS = YES
|
||||||
|
REFERENCED_BY_RELATION = NO
|
||||||
|
REFERENCES_RELATION = NO
|
||||||
|
REFERENCES_LINK_SOURCE = YES
|
||||||
|
SOURCE_TOOLTIPS = YES
|
||||||
|
USE_HTAGS = NO
|
||||||
|
VERBATIM_HEADERS = YES
|
||||||
|
CLANG_ASSISTED_PARSING = NO
|
||||||
|
CLANG_ADD_INC_PATHS = YES
|
||||||
|
CLANG_OPTIONS =
|
||||||
|
CLANG_DATABASE_PATH =
|
||||||
|
ALPHABETICAL_INDEX = YES
|
||||||
|
IGNORE_PREFIX =
|
||||||
|
GENERATE_HTML = YES
|
||||||
|
HTML_OUTPUT = html
|
||||||
|
HTML_FILE_EXTENSION = .html
|
||||||
|
HTML_HEADER =
|
||||||
|
HTML_FOOTER =
|
||||||
|
HTML_STYLESHEET =
|
||||||
|
HTML_EXTRA_STYLESHEET =
|
||||||
|
HTML_EXTRA_FILES =
|
||||||
|
HTML_COLORSTYLE = AUTO_LIGHT
|
||||||
|
HTML_COLORSTYLE_HUE = 359
|
||||||
|
HTML_COLORSTYLE_SAT = 0
|
||||||
|
HTML_COLORSTYLE_GAMMA = 240
|
||||||
|
HTML_DYNAMIC_MENUS = YES
|
||||||
|
HTML_DYNAMIC_SECTIONS = NO
|
||||||
|
HTML_CODE_FOLDING = YES
|
||||||
|
HTML_INDEX_NUM_ENTRIES = 100
|
||||||
|
GENERATE_DOCSET = NO
|
||||||
|
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||||
|
DOCSET_FEEDURL =
|
||||||
|
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||||
|
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||||
|
DOCSET_PUBLISHER_NAME = Publisher
|
||||||
|
GENERATE_HTMLHELP = NO
|
||||||
|
CHM_FILE =
|
||||||
|
HHC_LOCATION =
|
||||||
|
GENERATE_CHI = NO
|
||||||
|
CHM_INDEX_ENCODING =
|
||||||
|
BINARY_TOC = NO
|
||||||
|
TOC_EXPAND = NO
|
||||||
|
SITEMAP_URL =
|
||||||
|
GENERATE_QHP = NO
|
||||||
|
QCH_FILE =
|
||||||
|
QHP_NAMESPACE = org.doxygen.Project
|
||||||
|
QHP_VIRTUAL_FOLDER = doc
|
||||||
|
QHP_CUST_FILTER_NAME =
|
||||||
|
QHP_CUST_FILTER_ATTRS =
|
||||||
|
QHP_SECT_FILTER_ATTRS =
|
||||||
|
QHG_LOCATION =
|
||||||
|
GENERATE_ECLIPSEHELP = NO
|
||||||
|
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||||
|
DISABLE_INDEX = NO
|
||||||
|
GENERATE_TREEVIEW = YES
|
||||||
|
FULL_SIDEBAR = NO
|
||||||
|
ENUM_VALUES_PER_LINE = 4
|
||||||
|
TREEVIEW_WIDTH = 250
|
||||||
|
EXT_LINKS_IN_WINDOW = NO
|
||||||
|
OBFUSCATE_EMAILS = YES
|
||||||
|
HTML_FORMULA_FORMAT = png
|
||||||
|
FORMULA_FONTSIZE = 10
|
||||||
|
FORMULA_MACROFILE =
|
||||||
|
USE_MATHJAX = NO
|
||||||
|
MATHJAX_VERSION = MathJax_2
|
||||||
|
MATHJAX_FORMAT = HTML-CSS
|
||||||
|
MATHJAX_RELPATH =
|
||||||
|
MATHJAX_EXTENSIONS =
|
||||||
|
MATHJAX_CODEFILE =
|
||||||
|
SEARCHENGINE = YES
|
||||||
|
SERVER_BASED_SEARCH = NO
|
||||||
|
EXTERNAL_SEARCH = NO
|
||||||
|
SEARCHENGINE_URL =
|
||||||
|
SEARCHDATA_FILE = searchdata.xml
|
||||||
|
EXTERNAL_SEARCH_ID =
|
||||||
|
EXTRA_SEARCH_MAPPINGS =
|
||||||
|
GENERATE_LATEX = NO
|
||||||
|
LATEX_OUTPUT = latex
|
||||||
|
LATEX_CMD_NAME =
|
||||||
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
LATEX_MAKEINDEX_CMD = makeindex
|
||||||
|
COMPACT_LATEX = YES
|
||||||
|
PAPER_TYPE = a4
|
||||||
|
EXTRA_PACKAGES =
|
||||||
|
LATEX_HEADER =
|
||||||
|
LATEX_FOOTER =
|
||||||
|
LATEX_EXTRA_STYLESHEET =
|
||||||
|
LATEX_EXTRA_FILES =
|
||||||
|
PDF_HYPERLINKS = NO
|
||||||
|
USE_PDFLATEX = YES
|
||||||
|
LATEX_BATCHMODE = NO
|
||||||
|
LATEX_HIDE_INDICES = NO
|
||||||
|
LATEX_BIB_STYLE = plain
|
||||||
|
LATEX_EMOJI_DIRECTORY =
|
||||||
|
GENERATE_RTF = YES
|
||||||
|
RTF_OUTPUT = rtf
|
||||||
|
COMPACT_RTF = YES
|
||||||
|
RTF_HYPERLINKS = NO
|
||||||
|
RTF_STYLESHEET_FILE =
|
||||||
|
RTF_EXTENSIONS_FILE =
|
||||||
|
GENERATE_MAN = NO
|
||||||
|
MAN_OUTPUT = man
|
||||||
|
MAN_EXTENSION = .3
|
||||||
|
MAN_SUBDIR =
|
||||||
|
MAN_LINKS = NO
|
||||||
|
GENERATE_XML = NO
|
||||||
|
XML_OUTPUT = xml
|
||||||
|
XML_PROGRAMLISTING = YES
|
||||||
|
XML_NS_MEMB_FILE_SCOPE = NO
|
||||||
|
GENERATE_DOCBOOK = NO
|
||||||
|
DOCBOOK_OUTPUT = docbook
|
||||||
|
GENERATE_AUTOGEN_DEF = NO
|
||||||
|
GENERATE_SQLITE3 = NO
|
||||||
|
SQLITE3_OUTPUT = sqlite3
|
||||||
|
SQLITE3_RECREATE_DB = YES
|
||||||
|
GENERATE_PERLMOD = NO
|
||||||
|
PERLMOD_LATEX = NO
|
||||||
|
PERLMOD_PRETTY = YES
|
||||||
|
PERLMOD_MAKEVAR_PREFIX =
|
||||||
|
ENABLE_PREPROCESSING = YES
|
||||||
|
MACRO_EXPANSION = NO
|
||||||
|
EXPAND_ONLY_PREDEF = NO
|
||||||
|
SEARCH_INCLUDES = YES
|
||||||
|
INCLUDE_PATH =
|
||||||
|
INCLUDE_FILE_PATTERNS =
|
||||||
|
PREDEFINED =
|
||||||
|
EXPAND_AS_DEFINED =
|
||||||
|
SKIP_FUNCTION_MACROS = YES
|
||||||
|
TAGFILES =
|
||||||
|
GENERATE_TAGFILE =
|
||||||
|
ALLEXTERNALS = NO
|
||||||
|
EXTERNAL_GROUPS = YES
|
||||||
|
EXTERNAL_PAGES = YES
|
||||||
|
HIDE_UNDOC_RELATIONS = YES
|
||||||
|
HAVE_DOT = NO
|
||||||
|
DOT_NUM_THREADS = 0
|
||||||
|
DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10"
|
||||||
|
DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10"
|
||||||
|
DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4"
|
||||||
|
DOT_FONTPATH =
|
||||||
|
CLASS_GRAPH = TEXT
|
||||||
|
COLLABORATION_GRAPH = YES
|
||||||
|
GROUP_GRAPHS = YES
|
||||||
|
UML_LOOK = NO
|
||||||
|
UML_LIMIT_NUM_FIELDS = 10
|
||||||
|
DOT_UML_DETAILS = NO
|
||||||
|
DOT_WRAP_THRESHOLD = 17
|
||||||
|
TEMPLATE_RELATIONS = NO
|
||||||
|
INCLUDE_GRAPH = YES
|
||||||
|
INCLUDED_BY_GRAPH = YES
|
||||||
|
CALL_GRAPH = NO
|
||||||
|
CALLER_GRAPH = NO
|
||||||
|
GRAPHICAL_HIERARCHY = YES
|
||||||
|
DIRECTORY_GRAPH = YES
|
||||||
|
DIR_GRAPH_MAX_DEPTH = 1
|
||||||
|
DOT_IMAGE_FORMAT = png
|
||||||
|
INTERACTIVE_SVG = NO
|
||||||
|
DOT_PATH =
|
||||||
|
DOTFILE_DIRS =
|
||||||
|
DIA_PATH =
|
||||||
|
DIAFILE_DIRS =
|
||||||
|
PLANTUML_JAR_PATH =
|
||||||
|
PLANTUML_CFG_FILE =
|
||||||
|
PLANTUML_INCLUDE_PATH =
|
||||||
|
DOT_GRAPH_MAX_NODES = 50
|
||||||
|
MAX_DOT_GRAPH_DEPTH = 0
|
||||||
|
DOT_MULTI_TARGETS = NO
|
||||||
|
GENERATE_LEGEND = YES
|
||||||
|
DOT_CLEANUP = YES
|
||||||
|
MSCGEN_TOOL =
|
||||||
|
MSCFILE_DIRS =
|
2
STYLE.md
2
STYLE.md
|
@ -6,7 +6,7 @@ Variables names in sneak_case.
|
||||||
|
|
||||||
Name your procedures as following: `filename_whatitdoes`.
|
Name your procedures as following: `filename_whatitdoes`.
|
||||||
|
|
||||||
The procedures are documented using sphinx.
|
The procedures are documented using doxygen in the Java style.
|
||||||
|
|
||||||
We're using `clang-formatter` to keep the code readable. Please run it before
|
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.
|
committing your code as following: `clang-format -i *` in the `src` folder.
|
||||||
|
|
|
@ -428,3 +428,9 @@ def convert_dialog(input: str, output: str, params: dict, target):
|
||||||
sys.stderr.write(f"ERROR: Failed convert dialogs.\n"
|
sys.stderr.write(f"ERROR: Failed convert dialogs.\n"
|
||||||
+ f" Error message: {e}\n")
|
+ f" Error message: {e}\n")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
def convert_world(input: str, output: str, params: dict, target):
|
||||||
|
# (Mibi88) WIP
|
||||||
|
world_struct = fxconv.Structure()
|
||||||
|
name = os.path.splitext(os.path.basename(input))[0]
|
||||||
|
fxconv.elf(world_struct, output, f"_{name}", **target)
|
||||||
|
|
41
assets/worldRPG.world
Normal file
41
assets/worldRPG.world
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"maps": [
|
||||||
|
{
|
||||||
|
"fileName": "level0.tmx",
|
||||||
|
"height": 192,
|
||||||
|
"width": 384,
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fileName": "level1.tmx",
|
||||||
|
"height": 192,
|
||||||
|
"width": 384,
|
||||||
|
"x": 384,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fileName": "level2.tmx",
|
||||||
|
"height": 192,
|
||||||
|
"width": 384,
|
||||||
|
"x": 0,
|
||||||
|
"y": 192
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fileName": "level3.tmx",
|
||||||
|
"height": 192,
|
||||||
|
"width": 384,
|
||||||
|
"x": 384,
|
||||||
|
"y": 192
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fileName": "level4.tmx",
|
||||||
|
"height": 192,
|
||||||
|
"width": 384,
|
||||||
|
"x": 384,
|
||||||
|
"y": 384
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"onlyShowAdjacentMaps": false,
|
||||||
|
"type": "world"
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
- Compétences primaires uniquement : Intelligence, Force, Agilité, Charisme, Rapidité, Courage (Et peut être d'autres ?) :
|
- Compétences primaires uniquement : Intelligence, Force, Agilité, Charisme, Rapidité, Courage (Et peut être d'autres ?) :
|
||||||
|
|
||||||
* L'intelligence influant sur la magie, le cooldown des sorts, leur quantité et niveau max. ..., et l'apprentissage : on pourrait avoir un bonus/malus de vitesse d’apprentissage suivant l'intelligence , surtout si la magie n'est pas si puissante.
|
* L'intelligence influant sur la magie, [le cooldown des sorts,] leur quantité et niveau max. ..., et l'apprentissage : on pourrait avoir un bonus/malus de vitesse d’apprentissage suivant l'intelligence , surtout si la magie n'est pas si puissante.
|
||||||
*
|
*
|
||||||
|
|
||||||
* La Force influe sur les dégâts au corps a corps, peut être le nombre de slots d'inventaire si un système du genre est implémenté.
|
* La Force influe sur les dégâts au corps a corps, peut être le nombre de slots d'inventaire si un système du genre est implémenté.
|
||||||
|
@ -83,6 +83,64 @@ Structure du personnage à mettre en place en concordance:
|
||||||
|
|
||||||
Note: matrice d’interaction à définir en parallèle pour savoir ce qui joue sur quoi si on garde l'idée.
|
Note: matrice d’interaction à définir en parallèle pour savoir ce qui joue sur quoi si on garde l'idée.
|
||||||
|
|
||||||
|
Après y avoir réfléchi pour implémenter dans d'autres de mes projets, un système avec un dictionnaire comportant les caractéristiques de bases d'un item (dégats de base, chance de coup critique, enchantements acceptés ou peu importe) et une seconde liste avec les instances des items
|
||||||
|
|
||||||
|
Implémentation (rusée) exemple:
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
|
||||||
|
struct {
|
||||||
|
|
||||||
|
int damage;//negatif pour soigner
|
||||||
|
|
||||||
|
int crit\_chance;
|
||||||
|
|
||||||
|
int durability\_max; //Utilisé comme un max de stack si stackable
|
||||||
|
|
||||||
|
bool stackable;
|
||||||
|
|
||||||
|
bool use\_self;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct{
|
||||||
|
|
||||||
|
int heal;
|
||||||
|
|
||||||
|
int crit\_chance;
|
||||||
|
|
||||||
|
int stack\_max;
|
||||||
|
|
||||||
|
bool stackable:
|
||||||
|
|
||||||
|
bool use\_self;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}ItemDef;
|
||||||
|
|
||||||
|
typedef enum{
|
||||||
|
|
||||||
|
struct {
|
||||||
|
|
||||||
|
int quantity; //Durabilité si non-stackable
|
||||||
|
|
||||||
|
//Enchant enchant; //Par exemple
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
|
||||||
|
int durability;
|
||||||
|
|
||||||
|
//Enchant enchant;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} ItemInstance;
|
||||||
|
|
||||||
|
Un système comme ça permet de minimiser la taille des items (enum) et de couvrir la plupart des cas
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
* Univers :
|
* Univers :
|
||||||
|
@ -172,16 +230,36 @@ Je comprends pas trop le coup des "pnjs importants" (par exemple un des anciens
|
||||||
|
|
||||||
Combats temps réel : III
|
Combats temps réel : III
|
||||||
|
|
||||||
Combats tour par tour : II (Shadow avait l'ai pour mais n'a pas confirmé)
|
Combats tour par tour : II (Shadow avait l'air pour mais n'a pas confirmé)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Pour sommariser avant que je me mette à implémenter :
|
||||||
|
|
||||||
|
- Combats temps réel en open world
|
||||||
|
|
||||||
|
- Pnjs pouvant attaquer des monstres/bandits dans des zones (comme des guardes/guerriers
|
||||||
|
|
||||||
|
- Ennemis : Monstres /bandits directement hostiles
|
||||||
|
|
||||||
|
Mécaniques requises de ce que je suppose :
|
||||||
|
|
||||||
|
- Système de dégâts
|
||||||
|
|
||||||
|
- Pathfinding (déja majoritairement implémenté de ce que j'ai compris) et priorisation de cibles (basique)
|
||||||
|
|
||||||
|
- Détéction d'hostiles
|
||||||
|
|
||||||
|
- Appartion d'ennemis
|
||||||
|
|
||||||
# Map
|
# Map
|
||||||
|
|
||||||
[]C'est un open world :[]
|
[]C'est un open world :[]
|
||||||
|
|
||||||
Donc pas d'obstructions arbitraires a l'exploration de la map
|
Donc pas d'obstructions arbitraires a l'exploration de la map
|
||||||
|
|
||||||
|
Pour préciser : Style Elden Ring, donc si tu vas dans une zone avec des ennemis beaucoup plus forts que toi, tant pis pour toi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Pour le moment il y a une capitale, il y aurait des forteresses et des dongeons répartis et une chaîne de montagnes.
|
Pour le moment il y a une capitale, il y aurait des forteresses et des dongeons répartis et une chaîne de montagnes.
|
||||||
|
@ -254,4 +332,13 @@ PNJs / classes de personnages à intégrer
|
||||||
* marchands (dialogues + acheter/vendre des objets)
|
* marchands (dialogues + acheter/vendre des objets)
|
||||||
* soldats/guerriers (dialogues ? + baston)
|
* soldats/guerriers (dialogues ? + baston)
|
||||||
* bandits/monstres (baston directe ?)
|
* bandits/monstres (baston directe ?)
|
||||||
* boss (par exemples les fameux 5/7 anciens dirigeants) (la totale : dialogues + baston + donner des objets ou compétence)
|
* boss (par exemples les fameux 5/7 anciens dirigeants) (la totale : dialogues + baston + donner des objets ou compétence)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
108
src/dialogs.h
108
src/dialogs.h
|
@ -8,32 +8,37 @@
|
||||||
#include <gint/display.h>
|
#include <gint/display.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* 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.
|
||||||
*
|
*
|
||||||
* game: The game struct of the current game.
|
* @param game The game struct of the current game.
|
||||||
* face: A bopti_image_t of the face of the person who's saying this
|
* @param face A bopti_image_t of the face of the person who's saying
|
||||||
* text. This bopti_image_t should have a width of F_WIDTH and
|
* this text. This bopti_image_t should have a width of
|
||||||
* a height of F_HEIGHT.
|
* F_WIDTH and a height of F_HEIGHT.
|
||||||
* text: The text to display.
|
* @param text The text to display.
|
||||||
* call_before_end: A function called when the end of the text was displayed and
|
* @param call_before_end A function called when the end of the text was
|
||||||
* the user pressed EXE (or wait_continue was true). His
|
* displayed and the user pressed SHIFT (or wait_continue
|
||||||
* parameter game is the game struct passed to showtext_opt,
|
* was true). His parameter game is the game struct
|
||||||
* and i is the current position in text.
|
* passed to showtext_opt, and i is the current position
|
||||||
* start_anim: A boolean, that, if he's true, makes that a little animation
|
* in text.
|
||||||
* is shown at the start of showtext_opt.
|
* @param start_anim A boolean, that, if he's true, makes that a little
|
||||||
* end_anim: A boolean, that, if he's true, makes that a little animation
|
* animation is shown at the start of showtext_opt.
|
||||||
* is shown at the end of showtext_opt.
|
* @param end_anim A boolean, that, if he's true, makes that a little
|
||||||
* for_each_screen: A function called before a page of the dialog gets drawn.
|
* animation is shown at the end of showtext_opt.
|
||||||
* His parameter game is the game struct passed to
|
* @param for_each_screen A function called before a page of the dialog gets
|
||||||
* showtext_opt, and i is the current position in text.
|
* drawn.
|
||||||
* line_duration: How many ms showtext_opt will wait after a line has been
|
* His parameter game is the game struct passed to
|
||||||
* drawn.
|
* showtext_opt, and i is the current position in text.
|
||||||
* update_screen: When he's true showtext_opt will update the screen after
|
* @param line_duration How many ms showtext_opt will wait after a line has
|
||||||
* drawing a line etc.
|
* been drawn.
|
||||||
* start_i: At which position I start displaying the text.
|
* @param update_screen When he's true showtext_opt will update the screen
|
||||||
* wait_continue: If I should wait that EXE is pressed after drawing a page.
|
* after drawing a line etc.
|
||||||
|
* @param start_i At which position I start displaying the text.
|
||||||
|
* @param wait_continue If I should wait that EXE is pressed after drawing a
|
||||||
|
* page.
|
||||||
|
*
|
||||||
|
* @return TODO
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int dialogs_text_opt(Game *game, bopti_image_t *face, char *text,
|
int dialogs_text_opt(Game *game, bopti_image_t *face, char *text,
|
||||||
|
@ -43,51 +48,54 @@ int dialogs_text_opt(Game *game, bopti_image_t *face, char *text,
|
||||||
int line_duration, bool update_screen,
|
int line_duration, bool update_screen,
|
||||||
unsigned int start_i, bool wait_continue);
|
unsigned int start_i, bool wait_continue);
|
||||||
|
|
||||||
/* dialogs_text()
|
/**
|
||||||
*
|
*
|
||||||
* Calls dialogs_text_opt with default parameters.
|
* Calls dialogs_text_opt with default parameters.
|
||||||
*
|
*
|
||||||
* game: The game struct of the current game.
|
* @param game The game struct of the current game.
|
||||||
* face: A bopti_image_t of the face of the person who's saying this
|
* @param face A bopti_image_t of the face of the person who's saying
|
||||||
* text. This bopti_image_t should have a width of F_WIDTH and a
|
* this text. This bopti_image_t should have a width of
|
||||||
* height of F_HEIGHT.
|
* F_WIDTH and a height of F_HEIGHT.
|
||||||
* text: The text to display.
|
* @param text The text to display.
|
||||||
* dialog_start: A boolean, that, if he's true, makes that a little animation is
|
* @param dialog_start A boolean, that, if he's true, makes that a little
|
||||||
* shown at the start of showtext_opt.
|
* animation is shown at the start of showtext_opt.
|
||||||
* dialog_end: A boolean, that, if he's true, makes that a little animation is
|
* @param dialog_end A boolean, that, if he's true, makes that a little
|
||||||
* shown at the end of showtext_opt.
|
* animation is shown at the end of showtext_opt.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void dialogs_text(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);
|
||||||
|
|
||||||
/* dialogs_ask()
|
/**
|
||||||
*
|
*
|
||||||
* Like dialogs_text, 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.
|
* @param game The game struct of the current game.
|
||||||
* face: A bopti_image_t of the face of the person who's saying this
|
* @param face A bopti_image_t of the face of the person who's saying
|
||||||
* text. This bopti_image_t should have a width of F_WIDTH and a
|
* this text. This bopti_image_t should have a width of
|
||||||
* height of F_HEIGHT.
|
* F_WIDTH and a height of F_HEIGHT.
|
||||||
* text: The text to display.
|
* @param text The text to display.
|
||||||
* start: A boolean, that, if he's true, makes that a little animation
|
* @param start A boolean, that, if he's true, makes that a little
|
||||||
* is shown at the start of showtext_opt.
|
* animation is shown at the start of showtext_opt.
|
||||||
* end: A boolean, that, if he's true, makes that a little animation
|
* @param end A boolean, that, if he's true, makes that a little
|
||||||
* is shown at the end of showtext_opt.
|
* animation is shown at the end of showtext_opt.
|
||||||
* choices: A pointer to null-terminated strings that are one after the
|
* @param choices A pointer to null-terminated strings that are one after
|
||||||
* other in memory. They should be one null-terminated string
|
* the other in memory. They should be one null-terminated
|
||||||
* for each possible choice.
|
* string for each possible choice.
|
||||||
* choice_amount: The amount of possible choices in the choices zero-terminated
|
* @param choice_amount The amount of possible choices in the choices
|
||||||
* strings.
|
* zero-terminated strings.
|
||||||
* default_choice: The choice choosen by default when the dialog just opened.
|
* @param default_choice The choice choosen by default when the dialog just
|
||||||
|
* opened.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int dialogs_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);
|
||||||
|
|
||||||
/* TODO: Doc. */
|
/**
|
||||||
|
* TODO: Doc.
|
||||||
|
*/
|
||||||
void dialogs_initiate_sequence(Game *game, bopti_image_t *face,
|
void dialogs_initiate_sequence(Game *game, bopti_image_t *face,
|
||||||
uint32_t dialogNumber);
|
uint32_t dialogNumber);
|
||||||
|
|
||||||
|
|
|
@ -32,13 +32,13 @@ typedef enum {
|
||||||
OP_AMOUNT
|
OP_AMOUNT
|
||||||
} Operation;
|
} Operation;
|
||||||
|
|
||||||
/* events_init_handler()
|
/**
|
||||||
*
|
*
|
||||||
* Initialize an event handler.
|
* Initialize an event handler.
|
||||||
* handler: The Event handler to initialize.
|
* handler: The Event handler to initialize.
|
||||||
*/
|
*/
|
||||||
void events_init_handler(EventHandler *handler);
|
void events_init_handler(EventHandler *handler);
|
||||||
/* events_bind_variable()
|
/**
|
||||||
*
|
*
|
||||||
* Bind a variable. Binding a variable allows it to be modified by messages
|
* Bind a variable. Binding a variable allows it to be modified by messages
|
||||||
* passed to the event handler using tags written as following:
|
* passed to the event handler using tags written as following:
|
||||||
|
@ -55,7 +55,7 @@ void events_init_handler(EventHandler *handler);
|
||||||
* refer to this variable in a tag.
|
* refer to this variable in a tag.
|
||||||
*/
|
*/
|
||||||
int events_bind_variable(EventHandler *handler, int *var, char *name);
|
int events_bind_variable(EventHandler *handler, int *var, char *name);
|
||||||
/* events_parse_string()
|
/**
|
||||||
* handler: The event handler.
|
* handler: The event handler.
|
||||||
* message: The message to parse.
|
* message: The message to parse.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -279,15 +279,9 @@ void game_get_inputs(Game *game) {
|
||||||
mynpc->xpath = NULL;
|
mynpc->xpath = NULL;
|
||||||
mynpc->ypath = NULL;
|
mynpc->ypath = NULL;
|
||||||
}
|
}
|
||||||
while(keydown(KEY_F1)) {
|
|
||||||
clearevents();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(keydown(KEY_F2)) {
|
if(keydown(KEY_F2)) {
|
||||||
npc_remove_pos(0);
|
npc_remove_pos(0);
|
||||||
while(keydown(KEY_F2)) {
|
|
||||||
clearevents();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display Debug Information on screen */
|
/* Display Debug Information on screen */
|
||||||
|
|
12
src/game.h
12
src/game.h
|
@ -229,20 +229,20 @@ typedef struct {
|
||||||
int mana; /* Only for testing events TODO: Remove this! */
|
int mana; /* Only for testing events TODO: Remove this! */
|
||||||
} Game;
|
} Game;
|
||||||
|
|
||||||
/* TODO: Doc! */
|
/** TODO: Doc! */
|
||||||
void game_init(Game *game);
|
void game_init(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);
|
||||||
|
|
||||||
/* game_draw()
|
/**
|
||||||
*
|
*
|
||||||
* Draws everything on screen.
|
* Draws everything on screen.
|
||||||
* game: The game struct.
|
* game: The game struct.
|
||||||
*/
|
*/
|
||||||
void game_draw(Game *game);
|
void game_draw(Game *game);
|
||||||
|
|
||||||
/* game_render_indicator()
|
/**
|
||||||
*
|
*
|
||||||
* This render a small sign on the upper left corner of the screen
|
* This render a small sign on the upper left corner of the screen
|
||||||
* if the player can do an action
|
* if the player can do an action
|
||||||
|
@ -250,14 +250,14 @@ void game_draw(Game *game);
|
||||||
*/
|
*/
|
||||||
void game_render_indicator(Game *game);
|
void game_render_indicator(Game *game);
|
||||||
|
|
||||||
/* game_get_inputs()
|
/**
|
||||||
*
|
*
|
||||||
* Handle key presses.
|
* Handle key presses.
|
||||||
* game: The game struct.
|
* game: The game struct.
|
||||||
*/
|
*/
|
||||||
void game_get_inputs(Game *game);
|
void game_get_inputs(Game *game);
|
||||||
|
|
||||||
/* TODO: Doc! */
|
/** TODO: Doc! */
|
||||||
void game_update_animations(Game *game, unsigned char ms);
|
void game_update_animations(Game *game, unsigned char ms);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,14 +15,14 @@
|
||||||
/* 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.
|
||||||
* game: The game struct.
|
* game: The game struct.
|
||||||
*/
|
*/
|
||||||
void map_render(Game *game);
|
void map_render(Game *game);
|
||||||
|
|
||||||
/* map_render_by_layer()
|
/**
|
||||||
*
|
*
|
||||||
* Draws the map layer on the entire screen to be viewed by the player player.
|
* Draws the map layer on the entire screen to be viewed by the player player.
|
||||||
* game: The game struct.
|
* game: The game struct.
|
||||||
|
@ -30,7 +30,7 @@ void map_render(Game *game);
|
||||||
*/
|
*/
|
||||||
void map_render_by_layer(Game *game, int layer);
|
void map_render_by_layer(Game *game, int layer);
|
||||||
|
|
||||||
/* map_get_tile()
|
/**
|
||||||
*
|
*
|
||||||
* Get the tile at (x, y) of the map map. If the tile is located outside of the
|
* Get the tile at (x, y) of the map map. If the tile is located outside of the
|
||||||
* screen, MAP_OUTSIDE is returned.
|
* screen, MAP_OUTSIDE is returned.
|
||||||
|
@ -41,7 +41,7 @@ void map_render_by_layer(Game *game, int layer);
|
||||||
*/
|
*/
|
||||||
short int map_get_tile(Game *game, int x, int y, int l);
|
short int map_get_tile(Game *game, int x, int y, int l);
|
||||||
|
|
||||||
/* map_get_walkable()
|
/**
|
||||||
*
|
*
|
||||||
* Returns what is in the walkable layer at (x, y).
|
* Returns what is in the walkable layer at (x, y).
|
||||||
* game: The game struct.
|
* game: The game struct.
|
||||||
|
@ -50,6 +50,7 @@ short int map_get_tile(Game *game, int x, int y, int l);
|
||||||
*/
|
*/
|
||||||
short int map_get_walkable(Game *game, int x, int y);
|
short int map_get_walkable(Game *game, int x, int y);
|
||||||
|
|
||||||
|
/// TODO: Doc
|
||||||
Map *map_get_for_tile(Game *game, int x, int y);
|
Map *map_get_for_tile(Game *game, int x, int y);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define MEMORY_H
|
#define MEMORY_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
/* memory_is_in()
|
/**
|
||||||
*
|
*
|
||||||
* returns true if item is in array.
|
* returns true if item is in array.
|
||||||
* array: The array to search in.
|
* array: The array to search in.
|
||||||
|
|
10
src/npc.c
10
src/npc.c
|
@ -48,8 +48,6 @@ void npc_remove(NPC *npc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t move_size = sizeof(NPC) * (npc_count - pos);
|
uint32_t move_size = sizeof(NPC) * (npc_count - pos);
|
||||||
if(move_size + pos > NPC_STACK_SIZE)
|
|
||||||
move_size = NPC_STACK_SIZE - pos;
|
|
||||||
|
|
||||||
memmove(npc, &npc_stack[++pos], move_size);
|
memmove(npc, &npc_stack[++pos], move_size);
|
||||||
if(npc_count)
|
if(npc_count)
|
||||||
|
@ -132,8 +130,8 @@ int npc_pathfind(int32_t dest_x, int32_t dest_y, Map *full_map, NPC *npc) {
|
||||||
dest_x /= PXSIZE;
|
dest_x /= PXSIZE;
|
||||||
dest_y /= PXSIZE;
|
dest_y /= PXSIZE;
|
||||||
|
|
||||||
if(dest_x < 0 || dest_y < 0 || dest_x >= w * T_WIDTH ||
|
if(dest_x < 0 || dest_y < 0 || dest_x >= (int32_t)(w * T_WIDTH) ||
|
||||||
dest_y >= h * T_HEIGHT)
|
dest_y >= (int32_t)(h * T_HEIGHT))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
/*if(map[(dest_y/T_HEIGHT)*w + dest_x/T_WIDTH])
|
/*if(map[(dest_y/T_HEIGHT)*w + dest_x/T_WIDTH])
|
||||||
|
@ -179,9 +177,9 @@ int as_reconstruct_path(int16_t *came_from, int w, int h, int16_t start,
|
||||||
goto as_recons_fail;
|
goto as_recons_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t tx, ty;
|
/*uint16_t tx, ty;*/
|
||||||
|
|
||||||
// Flip the path because it started from the end
|
/* Flip the path because it started from the end */
|
||||||
|
|
||||||
/*for(i = 0; i < npc->path_length / 2; i++) {
|
/*for(i = 0; i < npc->path_length / 2; i++) {
|
||||||
tx = npc->xpath[i];
|
tx = npc->xpath[i];
|
||||||
|
|
10
src/player.h
10
src/player.h
|
@ -20,7 +20,7 @@ typedef struct {
|
||||||
/* 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 */
|
||||||
|
|
||||||
/* player_draw()
|
/**
|
||||||
*
|
*
|
||||||
* Draws the player. This function should be called after drawing the
|
* Draws the player. This function should be called after drawing the
|
||||||
* map!
|
* map!
|
||||||
|
@ -28,7 +28,7 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
void player_draw(Game *game);
|
void player_draw(Game *game);
|
||||||
|
|
||||||
/* player_move()
|
/**
|
||||||
*
|
*
|
||||||
* Move the player in a direction.
|
* Move the player in a direction.
|
||||||
* game: The game struct.
|
* game: The game struct.
|
||||||
|
@ -40,7 +40,7 @@ void player_move(Game *game, Direction direction);
|
||||||
* is pressed)*/
|
* is pressed)*/
|
||||||
void player_action(Game *game);
|
void player_action(Game *game);
|
||||||
|
|
||||||
/* player_collision()
|
/**
|
||||||
*
|
*
|
||||||
* Check if the player is in collision with the map or a NPC. Checkpos is used
|
* Check if the player is in collision with the map or a NPC. Checkpos is used
|
||||||
* to check the axis where the player is not moving.
|
* to check the axis where the player is not moving.
|
||||||
|
@ -51,7 +51,7 @@ void player_action(Game *game);
|
||||||
bool player_collision(Game *game, Direction direction,
|
bool player_collision(Game *game, Direction direction,
|
||||||
Checkpos nomov_axis_check);
|
Checkpos nomov_axis_check);
|
||||||
|
|
||||||
/* player_fix_position()
|
/**
|
||||||
*
|
*
|
||||||
* Fix the position of the player so that he's not a bit inside of a hard block
|
* Fix the position of the player so that he's not a bit inside of a hard block
|
||||||
* after a collision.
|
* after a collision.
|
||||||
|
@ -61,7 +61,7 @@ bool player_collision(Game *game, Direction direction,
|
||||||
*/
|
*/
|
||||||
void player_fix_position(Game *game, bool fix_x, bool fix_y);
|
void player_fix_position(Game *game, bool fix_x, bool fix_y);
|
||||||
|
|
||||||
/* player_damage()
|
/**
|
||||||
*
|
*
|
||||||
* Apply damage to player
|
* Apply damage to player
|
||||||
* game: The game struct.
|
* game: The game struct.
|
||||||
|
|
Loading…
Reference in a new issue