Compare commits

...

2 Commits

Author SHA1 Message Date
bgiraudr c45f31bd33 only handle event once for dialog 4 months ago
bgiraudr 367c61effd Only execute event once for area 4 months ago
  1. 66
      assets-cg/converters.py
  2. 5
      assets-cg/maps/1.tmx
  3. 5
      assets-cg/maps/inside/1.tmx
  4. 5
      assets-cg/maps/inside/2.tmx
  5. 5
      assets-cg/maps/testCarte.tmx
  6. 6
      include/capacite.h
  7. 6
      include/define.h
  8. 4
      include/map.h
  9. 10
      include/player.h
  10. 11
      include/talkable.h
  11. 3
      include/util.h
  12. 10
      src/battle.c
  13. 14
      src/capacite.c
  14. 10
      src/engine.c
  15. 4
      src/map.c
  16. 104
      src/player.c
  17. 15
      src/talkable.c
  18. 38
      src/util.c

@ -1,3 +1,4 @@
from random import randint
import fxconv
import json
import pathlib
@ -22,8 +23,6 @@ def convert(input, output, params, target):
elif params["custom-type"] == "table_type":
convert_table_type(input, output, params, target)
return 0
elif params["custom-type"] == "test":
test(input, output, params, target)
else:
return 1
@ -93,16 +92,21 @@ def convert_map(input, output, params, target):
teleporter = fxconv.Structure()
zone = fxconv.Structure()
try:
idmap = data["properties"][0]["value"]
except KeyError:
raise Exception("La carte n'a pas d'identifiant")
for layer in objectLayers:
if layer.get("name") == DIALOG_LAYOUT:
nbDialog = len(layer["objects"])
dialogs = parseDialog(layer)
dialogs = parseDialog(layer, idmap)
elif layer.get("name") == TELEPORTER_LAYOUT:
nbTelep = len(layer["objects"])
teleporter = parseTeleporter(layer)
elif layer.get("name") == ZONE_LAYOUT:
nbZone = len(layer["objects"])
zone = parseZone(layer)
zone = parseZone(layer, idmap)
else:
print("UNKNOWN LAYER FOUND : " + layer.get("name"))
@ -148,20 +152,59 @@ def convert_map(input, output, params, target):
#generate !
fxconv.elf(structMap, output, "_" + params["name"], **target)
def parseDialog(layer):
def parseDialog(layer, idmap):
dialogs = fxconv.Structure()
idDialog = 0
base_dialog = [
"Encore toi ? Tu n'as pas quelque chose d'autre à faire ?",
"Mais... Tu vas me lacher oui ?",
"re-bonjour, comment vas-tu depuis la dernière fois ?",
"Tu reviens me voir après tout ce temps ?",
"Toujours un plaisir de te revoir.",
"La vie est pleine de surprise, je ne m'attendais pas à te revoir !",
"Salut ! Belle journée n'est-ce pas ?",
"Il faut savoir apprécier les bonnes choses de la vie.",
"La dernière fois je suis tombé sur une horde de monstre, quelle panique !",
"As-tu visité notre belle région depuis la dernière fois ?",
"Prend le temps, on n'a qu'une seule vie n'est-ce pas !",
"Pour être honnête, je ne t'apprécie pas beaucoup."
]
for i in layer["objects"]:
dialogs += fxconv.u32(int(i["x"]/i["width"]))
#Tiled seem to start at the bottom y of the object
dialogs += fxconv.u32(int(i["y"]/i["width"])-1)
try:
dialogs += fxconv.u32(int(f"{idmap}{idDialog}{idmap}"))
listProper = set((a['name']) for a in i["properties"])
idDialog += 1
stoText = ""
for j in i["properties"]:
if(j["value"] == ""): j["value"] = " "
dialogs += fxconv.string(j["value"])
if(j["name"] == "name"): dialogs += fxconv.string(j["value"])
if(j["name"] == "text"):
dialogs += fxconv.string(j["value"])
stoText = j["value"]
if(j["name"] == "text2"): dialogs += fxconv.string(j["value"])
if not "text2" in listProper:
if "~" in stoText: dialogs += fxconv.string(base_dialog[randint(0, len(base_dialog)-1)])
else: dialogs += fxconv.string("")
if("exclusive" in listProper):
for j in i["properties"]:
if(j["name"] == "exclusive"):
if j["value"]: dialogs += fxconv.u32(1)
else: dialogs += fxconv.u32(0)
else:
if "~" in stoText: dialogs += fxconv.u32(1)
else: dialogs += fxconv.u32(0)
except KeyError:
dialogs += fxconv.string("default name")
dialogs += fxconv.string("default text")
dialogs += fxconv.string("default text2")
dialogs += fxconv.u32(0)
return dialogs
def parseTeleporter(layer):
@ -183,17 +226,22 @@ def parseTeleporter(layer):
raise Exception("parseTeleporter() : Un téléporteur est mal configuré")
return teleporter
def parseZone(layer):
def parseZone(layer, idmap):
zone = fxconv.Structure()
idZone = 0
for i in layer["objects"]:
origin = (int(i['x']/16), int(i['y']/16))
to = (int(origin[0]+i['width']/16)-1, int(origin[1]+i['height']/16)-1)
if len(i["properties"][0]["value"]) != 0:
zone += fxconv.u32(int(f"{idmap}{idZone}{idmap}")) #id zone is {mapid}{idzone}{mapid}
idZone+=1
else: zone += fxconv.u32(0)
zone += fxconv.u32(origin[0])
zone += fxconv.u32(origin[1])
zone += fxconv.u32(to[0])
zone += fxconv.u32(to[1])
event = bytes(i["properties"][0]["value"], "utf-8")
event += bytes(128 - len(event))
zone += event #event

@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.8.2" orientation="orthogonal" renderorder="right-down" width="100" height="100" tilewidth="16" tileheight="16" infinite="0" nextlayerid="13" nextobjectid="45">
<map version="1.8" tiledversion="1.8.4" orientation="orthogonal" renderorder="right-down" width="100" height="100" tilewidth="16" tileheight="16" infinite="0" nextlayerid="13" nextobjectid="45">
<editorsettings>
<export target="interior_1.json" format="json"/>
</editorsettings>
<properties>
<property name="id" type="int" value="2"/>
</properties>
<tileset firstgid="1" source="tileset.tsx"/>
<layer id="5" name="1" width="100" height="100">
<data encoding="csv">

@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="12" height="10" tilewidth="16" tileheight="16" infinite="0" nextlayerid="13" nextobjectid="38">
<map version="1.8" tiledversion="1.8.4" orientation="orthogonal" renderorder="right-down" width="12" height="10" tilewidth="16" tileheight="16" infinite="0" nextlayerid="13" nextobjectid="38">
<editorsettings>
<export target="interior_1.json" format="json"/>
</editorsettings>
<properties>
<property name="id" type="int" value="3"/>
</properties>
<tileset firstgid="1" source="tileset_in.tsx"/>
<layer id="5" name="1" width="12" height="10">
<data encoding="csv">

@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.8.1" orientation="orthogonal" renderorder="right-down" width="15" height="10" tilewidth="16" tileheight="16" infinite="0" nextlayerid="16" nextobjectid="43">
<map version="1.8" tiledversion="1.8.4" orientation="orthogonal" renderorder="right-down" width="15" height="10" tilewidth="16" tileheight="16" infinite="0" nextlayerid="16" nextobjectid="43">
<editorsettings>
<export target="interior_1.json" format="json"/>
</editorsettings>
<properties>
<property name="id" type="int" value="4"/>
</properties>
<tileset firstgid="1" source="tileset_in.tsx"/>
<layer id="11" name="1" width="15" height="10">
<data encoding="csv">

@ -3,6 +3,9 @@
<editorsettings>
<export target="testCarte.json" format="json"/>
</editorsettings>
<properties>
<property name="identifiant" type="int" value="1"/>
</properties>
<tileset firstgid="1" source="tileset.tsx"/>
<layer id="5" name="1" width="100" height="38">
<data encoding="csv">
@ -187,8 +190,10 @@
</object>
<object id="62" gid="267" x="448" y="432" width="16" height="16">
<properties>
<property name="exclusive" type="bool" value="false"/>
<property name="name" value="Pancarte"/>
<property name="text" value="Cadeau;~type:Administrateur"/>
<property name="text2" value="Hop hop hop, tu as déjà reçu mon cadeau"/>
</properties>
</object>
</objectgroup>

@ -25,7 +25,6 @@ struct Capacities {
enum status {
MISS,
SUCCESS,
CRIT,
HEAL,
ATK,
DEF,
@ -43,7 +42,7 @@ enum categorie {
struct Move default_move();
struct Move get_move_id(int id);
void draw_move(int x, int y, int x2, int y2, struct Move *move);
void draw_move(int x, int y, int x2, int y2, struct Move *move, int selected);
void draw_classic_move(int x, int y, struct Move *move);
int execute_move(struct Stats *player_stats, struct Stats *monster_stats, struct Move *move, int ismonster);
int calc_damage(struct Stats *attacker, struct Stats *target, struct Move *move);
@ -53,4 +52,5 @@ float crit(struct Stats *attacker);
int is_crit();
int is_miss(struct Move *move);
int self_effect(struct Stats *stats, struct Move *move);
float stab(char *type, char *move);
float stab(char *type, char *move);
void draw_special_move(int x, int y, struct Move *move, int selected);

@ -1,9 +1,9 @@
#pragma once
/*the size of one tile*/
#define TILE_SIZE 16
#define NB_INTERIORS 2
#define NB_PLAYER_MOVES 3
#define NB_PLAYER_ITEMS 30
#define NB_TYPES 4
#define NB_TYPES 4
#define NB_STO_ZONE 300
#define NB_STO_DIALOG 300

@ -9,6 +9,7 @@ struct Teleporter {
};
struct Zone {
int id;
int start_x, start_y;
int end_x, end_y;
char event[128];
@ -58,4 +59,5 @@ struct Vec2 locate_tile(struct Map const *map, int tile);
struct Teleporter get_teleporter_xy(struct Map *map, struct Vec2 pos);
int is_in_zone(struct Player *player, struct Map *map);
struct Zone get_zone(struct Player *player, struct Map *map);
struct Zone get_zone(struct Player *player, struct Map *map);
void addZoneToPlayer(struct Player *player, struct Zone zone);

@ -32,6 +32,8 @@ struct Player {
/*the current animation*/
int idle;
struct AnimData anim;
int eventListZone[NB_STO_ZONE];
int eventListDialog[NB_STO_DIALOG];
};
struct LevelUp {
@ -50,7 +52,7 @@ struct Player init_player(void);
void add_move(struct Player *player, struct Move move);
void draw_player_moves(struct Player *player);
void replace_capacities(struct Player *player, struct Move move);
void draw_ui(struct Player *player);
void draw_ui(struct Player *player, int curr_select);
int get_nb_moves(struct Player *player);
void reset_pp(struct Player *player);
void check_level(struct Player *player, int prec_level);
@ -58,4 +60,8 @@ void add_xp(struct Player *player, int xp);
int select_capacity(struct Player *player, char* context, bool allow_back);
void add_pp(struct Player *player, int amount);
void change_type(struct Player *player, struct Type type);
int yes_no_question(char const *format, ...);
bool has_move(struct Player *player, struct Move move);
int get_nb_eventzone(struct Player *player);
bool check_eventzone(struct Player *player, int id);
int get_nb_eventdialog(struct Player *player);
bool check_eventdialog(struct Player *player, int id);

@ -1,20 +1,23 @@
#pragma once
#include "map.h"
#include "game.h"
#include <stdbool.h>
struct Talkable {
/*the position of the tile*/
int x, y;
int x, y, id;
/*the name*/
char *name;
/*the text to display*/
char *text;
/*the text to display after the action*/
char *text_after;
/*if event, repeat it or no*/
int exclusive;
};
/*draw the dialog of a specified talkable tile*/
void draw_dialog(struct Game *game);
/*find the talkable tile using the player's position*/
struct Talkable* get_dialog_xy(struct Map *map, int x, int y);
char *word_boundary_before(char *str, char *limit);
char *skip_spaces(char *str);
void format_text_opt(int x, int y, int width, int height, const int color, char const *format, ...);
void addDialogToPlayer(struct Player *player, int id);

@ -5,4 +5,5 @@ void wait_for_input(int input);
int rand_range(int low, int high);
void format_text_opt(int x, int y, int width, int height, const int color, char const *format, ...);
char *word_boundary_before(char *str, char *limit);
char *skip_spaces(char *str);
char *skip_spaces(char *str);
int yes_no_question(char const *format, ...);

@ -76,9 +76,6 @@ void check_move_status(int status, struct Player *player, struct Monster *monste
draw_battle(player, monster);
switch(status){
case CRIT:
draw_status(name, "réalise un coup critique !");
break;
case MISS:
draw_status(name, "rate son attaque !");
break;
@ -108,6 +105,11 @@ void check_move_status(int status, struct Player *player, struct Monster *monste
dupdate();
wait_for_input(KEY_SHIFT);
}
if(is_crit() && (status == LESS_EFFECTIVE || status == SUPER_EFFECTIVE)) {
draw_status(name, "réalise un coup critique !");
dupdate();
wait_for_input(KEY_SHIFT);
}
}
/*When a battle is finish, compute xp gain and gain level*/
@ -153,7 +155,7 @@ int select_move(struct Player *player, struct Monster *monster, int prec_selecte
dclear(C_RGB(25,25,25));
draw_battle(player, monster);
draw_ui(player);
draw_ui(player, selection);
dtext(58 + (selection * 130), DHEIGHT-15 , C_RED, "[X]");
dupdate();

@ -49,12 +49,13 @@ struct Move *copy_move(struct Move move) {
return copyMove;
}
void draw_move(int x, int y, int x2, int y2, struct Move *move) {
void draw_move(int x, int y, int x2, int y2, struct Move *move, int selected) {
extern bopti_image_t img_capacite;
extern bopti_image_t img_categories;
const int font_size = 8;
draw_change_one_color(x, y, &img_capacite, 0xE6D6, getTypeFromName(move->type).color);
if(!selected) draw_change_one_color(x, y, &img_capacite, 0xE6D6, getTypeFromName(move->type).color);
else draw_change_one_color(x, y, &img_capacite, 0xE6D6, 0x0FE0);
dsubimage(x+96, y+7, &img_categories, 20*move->categorie, 0, 20, 10, DIMAGE_NONE);
int color = move->pp > 0 ? C_BLACK : C_RED;
@ -73,8 +74,12 @@ void draw_move(int x, int y, int x2, int y2, struct Move *move) {
}
}
void draw_special_move(int x, int y, struct Move *move, int selected) {
draw_move(x, y, x+125, y+60, move, selected);
}
void draw_classic_move(int x, int y, struct Move *move) {
draw_move(x, y, x+125, y+60, move);
draw_move(x, y, x+125, y+60, move, 0);
}
int execute_move(struct Stats *player_stats, struct Stats *monster_stats, struct Move *move, int ismonster) {
@ -98,7 +103,6 @@ int execute_move(struct Stats *player_stats, struct Stats *monster_stats, struct
if(typeEffect == 2) return SUPER_EFFECTIVE;
if(typeEffect == 0.5) return LESS_EFFECTIVE;
if(typeEffect == 0) return NOT_EFFECTIVE;
if(is_crit()) return CRIT;
} else {
if(ismonster) {
return self_effect(monster_stats, move);
@ -137,7 +141,7 @@ float stab(char *type, char *move) {
int is_crit() {
//une chance sur 16 d'avoir un coup critique
const int proba_crit = 16;
const int proba_crit = 2;
return rand_range(0,proba_crit)==0;
}

@ -32,6 +32,8 @@ void engine_draw(struct Game const *game) {
dprint(1,1,C_WHITE,"%d:%d",game->player->pos.x, game->player->pos.y);
dprint(1,20,C_WHITE,"%d",game->player->sprint);
dprint(1,40,C_WHITE,"%d",get_nb_eventdialog(game->player));
dprint(1,60,C_WHITE,"%d",game->player->eventListDialog[get_nb_eventdialog(game->player)-1 > 0 ? get_nb_eventdialog(game->player)-1 : 0]);
}
void engine_draw_map(struct Game const *game) {
@ -152,7 +154,13 @@ void engine_check_position(struct Game *game) {
static struct Vec2 old_pos;
if(is_in_zone(game->player, game->map)) {
struct Zone zone = get_zone(game->player, game->map);
if(strcmp(zone.event, "")) handle_event(game, zone.event);
if(!check_eventzone(game->player, zone.id)) {
if(strcmp(zone.event, "")) {
if(handle_event(game, zone.event)) {
addZoneToPlayer(game->player, zone);
}
}
}
}
int player_curr_tile = map_get_player_tile(game);

@ -95,4 +95,8 @@ struct Zone get_zone(struct Player *player, struct Map *map) {
if(zone.start_x <= posx && zone.start_y <= posy && zone.end_x >= posx && zone.end_y >= posy) return zone;
}
return default_zone;
}
void addZoneToPlayer(struct Player *player, struct Zone zone) {
player->eventListZone[get_nb_eventzone(player)] = zone.id;
}

@ -98,18 +98,32 @@ int get_nb_moves(struct Player *player) {
return NB_PLAYER_MOVES;
}
bool has_move(struct Player *player, struct Move move) {
int index = get_nb_moves(player);
for(int i = 0; i < index; i++) {
if(player->moves[i]->id == move.id) return true;
}
return false;
}
void add_move(struct Player *player, struct Move move) {
int index = get_nb_moves(player);
if(index != NB_PLAYER_MOVES) {
draw_text(50, DHEIGHT-47, C_BLACK, "Vous apprenez %s !", move.name);
dupdate();
wait_for_input(KEY_SHIFT);
player->moves[index] = copy_move(move);
if(!has_move(player, move)) {
if(index != NB_PLAYER_MOVES) {
draw_text(50, DHEIGHT-47, C_BLACK, "Vous apprenez %s !", move.name);
dupdate();
wait_for_input(KEY_SHIFT);
player->moves[index] = copy_move(move);
} else {
draw_text(50, DHEIGHT-47, C_BLACK, "Vous pouvez apprendre %s !", move.name);
dupdate();
wait_for_input(KEY_SHIFT);
replace_capacities(player, move);
}
} else {
draw_text(50, DHEIGHT-47, C_BLACK, "Vous pouvez apprendre %s !", move.name);
draw_text(50, DHEIGHT-47, C_BLACK, "Vous connaissez déjà la capacité %s !", move.name);
dupdate();
wait_for_input(KEY_SHIFT);
replace_capacities(player, move);
}
}
@ -184,11 +198,11 @@ int select_capacity(struct Player *player, char* context, bool allow_back) {
return selection;
}
void draw_ui(struct Player *player) {
void draw_ui(struct Player *player, int curr_select) {
int index = get_nb_moves(player);
for(int i = 0; i < index; i++) {
draw_classic_move(2+132*i,DHEIGHT-70, player->moves[i]);
draw_special_move(2+132*i,DHEIGHT-70, player->moves[i], i == curr_select);
}
}
@ -226,44 +240,6 @@ void add_pp(struct Player *player, int amount) {
wait_for_input(KEY_SHIFT);
}
int yes_no_question(char const *format, ...) {
char text_arg[512];
va_list args;
va_start(args, format);
vsnprintf(text_arg, 512, format, args);
va_end(args);
int selection = 0;
int buffer = keydown(KEY_SHIFT);
while(1) {
clearevents();
dclear(C_WHITE);
selection += keydown(KEY_RIGHT) - keydown(KEY_LEFT);
if(selection > 1) selection = 1;
if(selection < 0) selection = 0;
format_text_opt(95,10, 200, 13, C_BLACK, text_arg);
dtext(95,150,C_BLACK, "NON");
dtext(285,150,C_BLACK, "OUI");
dtext(95 + (selection * 190), DHEIGHT-47, C_RED, "[X]");
dupdate();
if(keydown(KEY_SHIFT)) {
if(buffer) buffer = 0;
else break;
}
if(keydown(KEY_EXIT)) {
selection = 0;
break;
}
while(keydown_any(KEY_LEFT,KEY_RIGHT, KEY_SHIFT,0)) clearevents();
}
return selection;
}
void change_type(struct Player *player, struct Type type) {
if(strcmp(player->stats.type, type.name) != 0) {
int selection = yes_no_question("Voulez vous changer votre type %s en %s ?", player->stats.type, type.name);
@ -273,4 +249,38 @@ void change_type(struct Player *player, struct Type type) {
dupdate();
wait_for_input(KEY_SHIFT);
}
}
int get_nb_eventzone(struct Player *player) {
for(int i = 0; i < NB_STO_ZONE; i++) {
if(player->eventListZone[i] == 0) {
return i;
}
}
return 0;
}
int get_nb_eventdialog(struct Player *player) {
for(int i = 0; i < NB_STO_DIALOG; i++) {
if(player->eventListDialog[i] == 0) {
return i;
}
}
return 0;
}
bool check_eventzone(struct Player *player, int id) {
for(int i = 0; i < NB_STO_ZONE; i++) {
if(player->eventListZone[i] == id) return true;
if(player->eventListZone[i] == 0) return false;
}
return false;
}
bool check_eventdialog(struct Player *player, int id) {
for(int i = 0; i < NB_STO_DIALOG; i++) {
if(player->eventListDialog[i] == id) return true;
if(player->eventListDialog[i] == 0) return false;
}
return false;
}

@ -17,7 +17,9 @@ struct Talkable default_value = {
.x = 0,
.y = 0,
.name = "default name",
.text = "default dialog"
.text = "default dialog",
.text_after = "",
.exclusive = 0
};
/*draw the dialog of a specified talkable tile*/
@ -30,6 +32,13 @@ void draw_dialog(struct Game *game) {
struct Talkable *talk = get_dialog_xy(game->map, game->player->pos.x + dx, game->player->pos.y + dy);
char *str = strdup(talk->text);
if(talk->exclusive) {
if(check_eventdialog(game->player, talk->id)) {
str = strdup(talk->text_after);
} else {
addDialogToPlayer(game->player, talk->id);
}
}
char *curr_line = strtok(str, delim);
while(curr_line != NULL) {
@ -54,4 +63,8 @@ struct Talkable* get_dialog_xy(struct Map *map, int x, int y) {
i++;
}
return &default_value;
}
void addDialogToPlayer(struct Player *player, int id) {
player->eventListDialog[get_nb_eventdialog(player)] = id;
}

@ -66,4 +66,42 @@ void format_text_opt(int x, int y, int width, int height, const int color, char
text = skip_spaces(last_word);
y += LINE_HEIGHT;
}
}
int yes_no_question(char const *format, ...) {
char text_arg[512];
va_list args;
va_start(args, format);
vsnprintf(text_arg, 512, format, args);
va_end(args);
int selection = 0;
int buffer = keydown(KEY_SHIFT);
while(1) {
clearevents();
dclear(C_WHITE);
selection += keydown(KEY_RIGHT) - keydown(KEY_LEFT);
if(selection > 1) selection = 1;
if(selection < 0) selection = 0;
format_text_opt(95,10, 200, 13, C_BLACK, text_arg);
dtext(95,150,C_BLACK, "NON");
dtext(285,150,C_BLACK, "OUI");
dtext(95 + (selection * 190), DHEIGHT-47, C_RED, "[X]");
dupdate();
if(keydown(KEY_SHIFT)) {
if(buffer) buffer = 0;
else break;
}
if(keydown(KEY_EXIT)) {
selection = 0;
break;
}
while(keydown_any(KEY_LEFT,KEY_RIGHT, KEY_SHIFT,0)) clearevents();
}
return selection;
}
Loading…
Cancel
Save