Compare commits
7 Commits
12b42af7a3
...
81ea791125
Author | SHA1 | Date |
---|---|---|
Xavier Del Campo Romero | 81ea791125 | |
Xavier Del Campo Romero | e3339dc1f0 | |
Xavier Del Campo Romero | 7d66f04ae6 | |
Xavier Del Campo Romero | a790bbf0e8 | |
Xavier Del Campo Romero | 431e13d9af | |
Xavier Del Campo Romero | 972196a653 | |
Xavier Del Campo Romero | 6fb41e4daa |
|
@ -84,9 +84,14 @@ function(level)
|
|||
cmake_parse_arguments(LEVEL "${options}" "${oneValueArgs}"
|
||||
"${multiValueArgs}" ${ARGN})
|
||||
|
||||
file(COPY ${LEVEL_NAME}.txt DESTINATION ${cdroot})
|
||||
add_custom_command(OUTPUT ${cdroot}/${LEVEL_NAME}.txt
|
||||
COMMAND cp ${LEVEL_NAME}.txt ${cdroot}/${LEVEL_NAME}.txt
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
DEPENDS ${LEVEL_NAME}.txt
|
||||
VERBATIM)
|
||||
add_custom_target(${LEVEL_NAME}_lvl
|
||||
DEPENDS ${cdroot}/${LEVEL_NAME})
|
||||
DEPENDS ${cdroot}/${LEVEL_NAME}.txt)
|
||||
add_dependencies(${PROJECT_NAME} ${LEVEL_NAME}_lvl)
|
||||
endfunction()
|
||||
|
||||
function(container)
|
||||
|
|
|
@ -31,7 +31,6 @@ struct building_cfg
|
|||
void building_create(const struct building_cfg *cfg, struct building *b);
|
||||
void building_set_alive_cb(void (*f)(const struct util_rect *dim, bool alive, void *p), void *p);
|
||||
int building_render(const struct building *b, const struct camera *cam, bool sel);
|
||||
instance_hp building_maxhp(const struct building *b);
|
||||
const char *building_str(const struct building *b);
|
||||
|
||||
extern struct sprite building_sprites[MAX_BUILDING_TYPES];
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
enum building_type
|
||||
{
|
||||
BUILDING_TYPE_BARRACKS,
|
||||
|
||||
MAX_BUILDING_TYPES
|
||||
};
|
||||
|
||||
|
|
|
@ -6,16 +6,6 @@
|
|||
|
||||
struct sprite building_sprites[MAX_BUILDING_TYPES];
|
||||
|
||||
instance_hp building_maxhp(const struct building *const b)
|
||||
{
|
||||
static const instance_hp hp[] =
|
||||
{
|
||||
[BUILDING_TYPE_BARRACKS] = 100
|
||||
};
|
||||
|
||||
return hp[b->type];
|
||||
}
|
||||
|
||||
int building_render(const struct building *const b,
|
||||
const struct camera *const cam, const bool sel)
|
||||
{
|
||||
|
@ -33,8 +23,7 @@ int building_render(const struct building *const b,
|
|||
.prim_type = INSTANCE_RENDER_CFG_SPRITE,
|
||||
.prim = {.s = s},
|
||||
.cam = cam,
|
||||
.sel = sel,
|
||||
.max_hp = building_maxhp(b)
|
||||
.sel = sel
|
||||
};
|
||||
|
||||
return instance_render(&cfg);
|
||||
|
@ -46,10 +35,7 @@ static void get_dimensions(const enum building_type type, short *const w,
|
|||
static const struct dim
|
||||
{
|
||||
short w, h;
|
||||
} dim[] =
|
||||
{
|
||||
[BUILDING_TYPE_BARRACKS] = {.w = 68, .h = 66}
|
||||
};
|
||||
} dim[1];
|
||||
|
||||
const struct dim *const d = &dim[type];
|
||||
*w = d->w;
|
||||
|
@ -69,7 +55,6 @@ void building_create(const struct building_cfg *const cfg,
|
|||
i->r.x = cfg->x;
|
||||
i->r.y = cfg->y;
|
||||
i->alive = true;
|
||||
i->hp = building_maxhp(b);
|
||||
|
||||
if (cb)
|
||||
cb(&i->r, i->alive, op);
|
||||
|
@ -84,10 +69,7 @@ void building_set_alive_cb(void (*const f)(const struct util_rect *, bool, void
|
|||
|
||||
const char *building_str(const struct building *const b)
|
||||
{
|
||||
static const char *const str[] =
|
||||
{
|
||||
[BUILDING_TYPE_BARRACKS] = "Barracks"
|
||||
};
|
||||
static const char *const str[1];
|
||||
|
||||
return str[b->type];
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ struct camera
|
|||
} dim;
|
||||
|
||||
int x, y, x_speed, y_speed;
|
||||
unsigned int xt, yt;
|
||||
unsigned xt, yt;
|
||||
bool pan;
|
||||
|
||||
struct cursor
|
||||
{
|
||||
unsigned int x, y, x_init, y_init;
|
||||
unsigned x, y, x_init, y_init;
|
||||
enum
|
||||
{
|
||||
CURSOR_STATE_IDLE,
|
||||
|
|
|
@ -13,8 +13,8 @@ extern "C"
|
|||
|
||||
enum
|
||||
{
|
||||
CAMERA_CURSOR_WIDTH = 20,
|
||||
CAMERA_CURSOR_HEIGHT = 20
|
||||
CAMERA_CURSOR_WIDTH = 16,
|
||||
CAMERA_CURSOR_HEIGHT = 16
|
||||
};
|
||||
|
||||
void camera_update_pos(struct camera *cam);
|
||||
|
|
|
@ -57,13 +57,17 @@ int cursor_render(const struct cursor *const c)
|
|||
break;
|
||||
}
|
||||
|
||||
sprite_sort(s);
|
||||
return 0;
|
||||
const int ret = sprite_sort(s);
|
||||
|
||||
if (ret)
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cursor_init(struct cursor *const c)
|
||||
{
|
||||
const unsigned int x = (screen_w / 2) - CAMERA_CURSOR_WIDTH,
|
||||
const unsigned x = (screen_w / 2) - CAMERA_CURSOR_WIDTH,
|
||||
y = (screen_h / 2) - CAMERA_CURSOR_HEIGHT;
|
||||
|
||||
*c = (const struct cursor)
|
||||
|
|
|
@ -26,11 +26,6 @@ struct container
|
|||
struct sprite *sprite;
|
||||
struct sound *sound;
|
||||
} data;
|
||||
|
||||
struct container_rt
|
||||
{
|
||||
struct container *c;
|
||||
} *rt;
|
||||
};
|
||||
|
||||
int container_load_ex(const char *path, const struct container *list, size_t n);
|
||||
|
|
|
@ -86,7 +86,12 @@ static int renderstr(const enum font f, const short x, short y,
|
|||
s->v += v;
|
||||
s->x = rx;
|
||||
s->y = y;
|
||||
sprite_sort(s);
|
||||
|
||||
if (sprite_sort(s))
|
||||
{
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
rx += cfg->fs;
|
||||
|
|
|
@ -30,6 +30,7 @@ struct game_cfg
|
|||
|
||||
size_t n;
|
||||
union peripheral *p;
|
||||
const char *map;
|
||||
};
|
||||
|
||||
int game_resinit(void);
|
||||
|
|
|
@ -14,8 +14,11 @@ int game(const struct game_cfg *const cfg)
|
|||
struct human_player human;
|
||||
struct terrain_map map;
|
||||
|
||||
terrain_init(&map);
|
||||
building_set_alive_cb(terrain_block_update, &map);
|
||||
if (terrain_init(cfg->map, &map))
|
||||
{
|
||||
fprintf(stderr, "%s: terrain_init failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const struct human_player_cfg hcfg =
|
||||
{
|
||||
|
|
|
@ -12,7 +12,45 @@
|
|||
#include <unit.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static const struct container c[1];
|
||||
static const struct container c[] =
|
||||
{
|
||||
{
|
||||
.path = "sidewalk",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &terrain_sprites[SIDEWALK]
|
||||
},
|
||||
{
|
||||
.path = "roof1",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &terrain_sprites[ROOF1]
|
||||
},
|
||||
{
|
||||
.path = "roof2",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &terrain_sprites[ROOF2]
|
||||
},
|
||||
{
|
||||
.path = "cursor",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &cursor_sprite
|
||||
},
|
||||
{
|
||||
.path = "btn_left",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &gui_button_sprites[GUI_BUTTON_LEFT]
|
||||
},
|
||||
{
|
||||
.path = "btn_mid",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &gui_button_sprites[GUI_BUTTON_MID]
|
||||
},
|
||||
{
|
||||
.path = "btn_right",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data.sprite = &gui_button_sprites[GUI_BUTTON_RIGHT]
|
||||
},
|
||||
};
|
||||
|
||||
static bool init;
|
||||
|
||||
void game_free(void)
|
||||
|
|
|
@ -17,14 +17,14 @@ int gfx_set_fullscreen(short w, short h);
|
|||
bool gfx_fullscreen_available(void);
|
||||
bool gfx_fullscreen(void);
|
||||
int gfx_display_size(short *w, short *h);
|
||||
void sprite_sort(struct sprite *s);
|
||||
int sprite_sort(struct sprite *s);
|
||||
int sprite_clone(const struct sprite *src, struct sprite *dst);
|
||||
void rect_init(struct rect *r);
|
||||
void semitrans_rect_init(struct rect *r);
|
||||
void stp_4line_init(struct stp_4line *l);
|
||||
void quad_sort(struct quad *q);
|
||||
void rect_sort(struct rect *r);
|
||||
void stp_4line_sort(struct stp_4line *l);
|
||||
int quad_sort(struct quad *q);
|
||||
int rect_sort(struct rect *r);
|
||||
int stp_4line_sort(struct stp_4line *l);
|
||||
int sprite_from_fp(struct sprite *s, FILE *f);
|
||||
int quad_from_sprite(const struct sprite *s, struct quad *q);
|
||||
bool gfx_inside_drawenv(short x, short y, short w, short h);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <gfx_private.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static unsigned int sel;
|
||||
static unsigned sel;
|
||||
static size_t heap_i;
|
||||
|
||||
void gfx_swapheap(void)
|
||||
|
|
|
@ -19,24 +19,28 @@ static void add_to_list(union gfx_sznext *const p)
|
|||
last = p;
|
||||
}
|
||||
|
||||
void sprite_sort(struct sprite *const s)
|
||||
int sprite_sort(struct sprite *const s)
|
||||
{
|
||||
add_to_list(&s->sznext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void quad_sort(struct quad *const q)
|
||||
int quad_sort(struct quad *const q)
|
||||
{
|
||||
add_to_list(&q->sznext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rect_sort(struct rect *const r)
|
||||
int rect_sort(struct rect *const r)
|
||||
{
|
||||
add_to_list(&r->sznext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stp_4line_sort(struct stp_4line *const l)
|
||||
int stp_4line_sort(struct stp_4line *const l)
|
||||
{
|
||||
add_to_list(&l->sznext);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gfx_sync(void)
|
||||
|
@ -61,7 +65,7 @@ int gfx_draw(void)
|
|||
|
||||
add_to_list(&term);
|
||||
|
||||
void gpu_ctrl(unsigned int command, unsigned int param);
|
||||
void gpu_ctrl(unsigned command, unsigned param);
|
||||
|
||||
gfx_sync();
|
||||
gfx_swapbuffers();
|
||||
|
|
|
@ -98,7 +98,10 @@ static int resize_screen(int w, int h, const bool full_screen)
|
|||
|
||||
for (size_t i = 0; i < list_len; i++)
|
||||
if (sprite_screen_resize_ev(list[i]))
|
||||
{
|
||||
fprintf(stderr, "%s: sprite_screen_resize_ev failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
screen_w = w;
|
||||
screen_h = h;
|
||||
|
@ -152,14 +155,16 @@ static int get_resize_events(void)
|
|||
const SDL_ResizeEvent *const res = &ev.resize;
|
||||
|
||||
if (resize_screen(res->w, res->h, false))
|
||||
{
|
||||
fprintf(stderr, "%s: resize_screen failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: SDL_PeepEvents: %s\n",
|
||||
__func__, SDL_GetError());
|
||||
fprintf(stderr, "%s: SDL_PeepEvents: %s\n", __func__, SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -208,6 +213,5 @@ int gfx_draw(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
get_resize_events();
|
||||
return 0;
|
||||
return get_resize_events();
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ void semitrans_stp_4line_init(struct stp_4line *r)
|
|||
{
|
||||
}
|
||||
|
||||
void stp_4line_sort(struct stp_4line *const r)
|
||||
int stp_4line_sort(struct stp_4line *const r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ int quad_from_sprite(const struct sprite *const s, struct quad *const q)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void quad_sort(struct quad *const q)
|
||||
int quad_sort(struct quad *const q)
|
||||
{
|
||||
const bool xflip = q->x0 > q->x1;
|
||||
|
||||
|
@ -40,5 +40,10 @@ void quad_sort(struct quad *const q)
|
|||
SDL_Surface *const s = xflip ? q->s_x : q->s;
|
||||
|
||||
if (SDL_BlitSurface(s, &clip, gfx_screen(), &r))
|
||||
{
|
||||
fprintf(stderr, "SDL_BlitSurface: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <sdl-1.2/gfx_private.h>
|
||||
#include <SDL.h>
|
||||
|
||||
void rect_sort(struct rect *const r)
|
||||
int rect_sort(struct rect *const r)
|
||||
{
|
||||
SDL_Rect rct =
|
||||
{
|
||||
|
@ -19,8 +19,10 @@ void rect_sort(struct rect *const r)
|
|||
if (SDL_FillRect(screen, &rct, map))
|
||||
{
|
||||
fprintf(stderr, "SDL_FillRect: %s\n", SDL_GetError());
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rect_init(struct rect *const r)
|
||||
|
|
|
@ -126,7 +126,7 @@ int sprite_from_fp(struct sprite *const s, FILE *const f)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void sprite_sort(struct sprite *const s)
|
||||
int sprite_sort(struct sprite *const s)
|
||||
{
|
||||
SDL_Rect r =
|
||||
{
|
||||
|
@ -143,5 +143,10 @@ void sprite_sort(struct sprite *const s)
|
|||
};
|
||||
|
||||
if (SDL_BlitSurface(s->s, &clip, gfx_screen(), &r))
|
||||
{
|
||||
fprintf(stderr, "SDL_BlitSurface: %s\n", SDL_GetError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -15,8 +15,13 @@ static int render_topleft(const struct gui_bar *const b, const short x,
|
|||
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
sprite_sort(s);
|
||||
return 0;
|
||||
|
||||
const int ret = sprite_sort(s);
|
||||
|
||||
if (ret)
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int render_topright(const struct gui_bar *const b, const short x,
|
||||
|
@ -29,7 +34,12 @@ static int render_topright(const struct gui_bar *const b, const short x,
|
|||
|
||||
s->x = x + b->w - s->w;
|
||||
s->y = y;
|
||||
sprite_sort(s);
|
||||
|
||||
const int ret = sprite_sort(s);
|
||||
|
||||
if (ret)
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -66,7 +76,11 @@ static int render_topmid(const struct gui_bar *const b, const short x,
|
|||
else
|
||||
m->w = mid_w;
|
||||
|
||||
sprite_sort(m);
|
||||
if (sprite_sort(m))
|
||||
{
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -13,8 +13,13 @@ int gui_button_render_sprite(const struct gui_button *const b)
|
|||
return -1;
|
||||
|
||||
gui_coords(&b->common, &s->x, &s->y);
|
||||
sprite_sort(s);
|
||||
return 0;
|
||||
|
||||
const int ret = sprite_sort(s);
|
||||
|
||||
if (ret)
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void gui_button_get_dim_sprite(const struct gui_button *const b,
|
||||
|
|
|
@ -19,7 +19,13 @@ static int render_left(const struct gui_button *const b,
|
|||
|
||||
s->x = *x;
|
||||
s->y = y;
|
||||
sprite_sort(s);
|
||||
|
||||
if (sprite_sort(s))
|
||||
{
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*x = s->x + s->w;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,13 @@ static int render_left(const struct gui_line_edit *const l,
|
|||
|
||||
s->x = *x;
|
||||
s->y = y;
|
||||
sprite_sort(s);
|
||||
|
||||
if (sprite_sort(s))
|
||||
{
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*x = s->x + s->w;
|
||||
return 0;
|
||||
}
|
||||
|
@ -66,7 +72,12 @@ static int render_mid(const struct gui_line_edit *const l,
|
|||
else
|
||||
m->w = mid_w;
|
||||
|
||||
sprite_sort(m);
|
||||
if (sprite_sort(m))
|
||||
{
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*x += m->w;
|
||||
}
|
||||
}
|
||||
|
@ -85,8 +96,13 @@ static int render_right(const short x, const short y)
|
|||
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
sprite_sort(s);
|
||||
return 0;
|
||||
|
||||
const int ret = sprite_sort(s);
|
||||
|
||||
if (ret)
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int render(const struct gui_common *const g)
|
||||
|
|
|
@ -19,7 +19,12 @@ static int render_top(const struct gui_rounded_rect *const r,
|
|||
|
||||
left->x = x;
|
||||
left->y = y;
|
||||
sprite_sort(left);
|
||||
|
||||
if (sprite_sort(left))
|
||||
{
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -33,7 +38,12 @@ static int render_top(const struct gui_rounded_rect *const r,
|
|||
|
||||
right->x = x + r->w - ref->w;
|
||||
right->y = y;
|
||||
sprite_sort(right);
|
||||
|
||||
if (sprite_sort(right))
|
||||
{
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -12,17 +12,12 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
typedef unsigned int instance_hp;
|
||||
|
||||
struct instance
|
||||
{
|
||||
bool alive, dying;
|
||||
unsigned int hp;
|
||||
bool alive;
|
||||
struct util_rect r;
|
||||
};
|
||||
|
||||
typedef bool (*instance_attacked_cb)(struct instance *i, unsigned int ap);
|
||||
typedef bool (*instance_sheltered_cb)(struct instance *self, struct instance *other);
|
||||
typedef void (*instance_done_cb)(struct instance *i, void *op);
|
||||
|
||||
struct instance_render_cfg
|
||||
|
@ -48,15 +43,12 @@ struct instance_render_cfg
|
|||
} prim;
|
||||
|
||||
bool sel;
|
||||
instance_hp max_hp;
|
||||
const struct instance_render_off
|
||||
{
|
||||
short x, y;
|
||||
} *off;
|
||||
};
|
||||
|
||||
bool instance_attacked(struct instance *self, unsigned int ap);
|
||||
void instance_clear_pools(void);
|
||||
int instance_render(const struct instance_render_cfg *cfg);
|
||||
int instance_render_target(const struct instance *const i, const struct camera *cam);
|
||||
void instance_cyclic(void);
|
||||
|
|
|
@ -8,19 +8,6 @@
|
|||
static unsigned char line_g;
|
||||
static bool line_g_flip;
|
||||
|
||||
bool instance_attacked(struct instance *const self, const instance_hp ap)
|
||||
{
|
||||
if (self->hp > ap)
|
||||
self->hp -= ap;
|
||||
else
|
||||
{
|
||||
self->hp = 0;
|
||||
self->alive = false;
|
||||
}
|
||||
|
||||
return !self->alive;
|
||||
}
|
||||
|
||||
void instance_cyclic(void)
|
||||
{
|
||||
if (!line_g_flip)
|
||||
|
|
|
@ -74,7 +74,8 @@ int menu(void)
|
|||
|
||||
const struct game_cfg gcfg =
|
||||
{
|
||||
.p = &c.p
|
||||
.p = &c.p,
|
||||
.map = "city1.txt"
|
||||
};
|
||||
|
||||
return game(&gcfg);
|
||||
|
|
|
@ -40,7 +40,7 @@ union peripheral
|
|||
struct mouse mouse;
|
||||
struct keyboard keyboard;
|
||||
bool long_press;
|
||||
unsigned int lp_t;
|
||||
unsigned lp_t;
|
||||
} kbm;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
typedef unsigned int player_team;
|
||||
typedef unsigned player_team;
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -278,8 +278,8 @@ static void update_selected(struct human_player *const h)
|
|||
{
|
||||
struct sel_instance *const si = &h->sel[i];
|
||||
|
||||
if (si->d.i && (!si->d.i->alive || si->d.i->dying
|
||||
|| si->type == INSTANCE_TYPE_UNIT))
|
||||
if (si->d.i
|
||||
&& (!si->d.i->alive || si->type == INSTANCE_TYPE_UNIT))
|
||||
{
|
||||
si->d.i = NULL;
|
||||
h->n_sel--;
|
||||
|
|
|
@ -61,43 +61,6 @@ int player_create_building(const struct building_cfg *const cfg, struct player *
|
|||
|
||||
int player_init(const struct player_cfg *const cfg, struct player *const pl)
|
||||
{
|
||||
const unsigned long x = cfg->x, y = cfg->y;
|
||||
|
||||
const struct building_cfg bcfg =
|
||||
{
|
||||
.type = BUILDING_TYPE_BARRACKS,
|
||||
.x = x,
|
||||
.y = y
|
||||
};
|
||||
|
||||
const struct unit_cfg cfgs[] =
|
||||
{
|
||||
{
|
||||
.type = UNIT_TYPE_PEASANT,
|
||||
.x = x + 80,
|
||||
.y = y
|
||||
},
|
||||
|
||||
{
|
||||
.type = UNIT_TYPE_PEASANT,
|
||||
.x = x + 80,
|
||||
.y = y + 40
|
||||
},
|
||||
|
||||
{
|
||||
.type = UNIT_TYPE_PEASANT,
|
||||
.x = x + 100,
|
||||
.y = y + 20
|
||||
}
|
||||
};
|
||||
|
||||
if (player_create_building(&bcfg, pl))
|
||||
return -1;
|
||||
|
||||
for (size_t i = 0; i < sizeof cfgs / sizeof *cfgs; i++)
|
||||
if (player_create_unit(&cfgs[i], pl))
|
||||
return -1;
|
||||
|
||||
pl->alive = true;
|
||||
pl->color = cfg->color;
|
||||
pl->team = cfg->team;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
add_library(terrain "src/terrain.c")
|
||||
add_library(terrain
|
||||
"src/init.c"
|
||||
"src/render.c"
|
||||
"src/update.c"
|
||||
)
|
||||
target_include_directories(terrain PUBLIC "inc")
|
||||
target_link_libraries(terrain PUBLIC container camera gfx util)
|
||||
|
|
|
@ -21,26 +21,64 @@ enum
|
|||
|
||||
enum terrain_type
|
||||
{
|
||||
TERRAIN_TYPE_GRASS
|
||||
ROOF1_1_NW,
|
||||
ROOF1_1_N,
|
||||
ROOF1_1_NE,
|
||||
ROOF1_2_NW,
|
||||
ROOF1_2_NE,
|
||||
ROOF1_3_NW,
|
||||
ROOF1_3_N,
|
||||
ROOF1_3_NE,
|
||||
ROOF1_4_N,
|
||||
|
||||
ROOF1_1_W,
|
||||
ROOF1_1_C,
|
||||
ROOF1_1_E,
|
||||
ROOF1_2_SW,
|
||||
ROOF1_2_SE,
|
||||
ROOF1_3_SW,
|
||||
ROOF1_3_S,
|
||||
ROOF1_3_SE,
|
||||
ROOF1_4_C,
|
||||
|
||||
ROOF1_1_SW,
|
||||
ROOF1_1_S,
|
||||
ROOF1_1_SE,
|
||||
ROOF1_5_W,
|
||||
ROOF1_5_C,
|
||||
ROOF1_5_E,
|
||||
ROOF1_6,
|
||||
ROOF1_4_S,
|
||||
|
||||
ROOF1_START = ROOF1_1_NW,
|
||||
ROOF1_END = ROOF1_4_S
|
||||
};
|
||||
|
||||
struct terrain_map
|
||||
{
|
||||
struct terrain_tile
|
||||
{
|
||||
enum terrain_type t;
|
||||
unsigned char bl;
|
||||
unsigned char t, obj;
|
||||
} m[MAP_TILES][MAP_TILES];
|
||||
|
||||
int nx, ny, last_w, last_h;
|
||||
};
|
||||
|
||||
void terrain_init(struct terrain_map *map);
|
||||
int terrain_init(const char *path, struct terrain_map *map);
|
||||
void terrain_update(struct terrain_map *map);
|
||||
int terrain_render(const struct terrain_map *map, const struct camera *cam);
|
||||
void terrain_block_update(const struct util_rect *dim, bool alive, void *p);
|
||||
|
||||
extern struct sprite grass_sprite;
|
||||
enum
|
||||
{
|
||||
SIDEWALK,
|
||||
ROOF1,
|
||||
ROOF2,
|
||||
BUILDING1,
|
||||
|
||||
MAX_TERRAIN_SPRITES
|
||||
};
|
||||
|
||||
extern struct sprite terrain_sprites[MAX_TERRAIN_SPRITES];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
#include <terrain.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static int read_token(FILE *const f, char *const s, const size_t n)
|
||||
{
|
||||
uint8_t c;
|
||||
size_t i = 0;
|
||||
|
||||
while (fread(&c, sizeof c, 1, f))
|
||||
{
|
||||
if (isspace(c))
|
||||
{
|
||||
if (i)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else if (!isalnum(c))
|
||||
{
|
||||
fprintf(stderr, "%s: invalid character %" PRIx8 " at offset %ld\n",
|
||||
__func__, c, ftell(f));
|
||||
return -1;
|
||||
}
|
||||
else if (i + 1 >= n)
|
||||
{
|
||||
fprintf(stderr, "%s: exceeded maximum token size %zu\n",
|
||||
__func__, n);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s[i++] = c;
|
||||
}
|
||||
|
||||
if (!i)
|
||||
{
|
||||
fprintf(stderr, "%s: feof=%d, ferror=%d\n", __func__, feof(f),
|
||||
ferror(f));
|
||||
return -1;
|
||||
}
|
||||
|
||||
s[i] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_num(FILE *const f, char *const s, const size_t n,
|
||||
unsigned *const out, const int base, const int limit)
|
||||
{
|
||||
if (read_token(f, s, n))
|
||||
return -1;
|
||||
|
||||
errno = 0;
|
||||
|
||||
char *end;
|
||||
const unsigned long value = strtoul(s, &end, 10);
|
||||
|
||||
if (errno)
|
||||
{
|
||||
fprintf(stderr, "%s: strtoul(3): %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if (*end)
|
||||
{
|
||||
fprintf(stderr, "%s: invalid number %s\n", __func__, s);
|
||||
return -1;
|
||||
}
|
||||
else if (value > limit)
|
||||
{
|
||||
fprintf(stderr, "%s: %lu exceeds maximum range %d\n", __func__, value,
|
||||
limit);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*out = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_dec(FILE *const f, unsigned *const out)
|
||||
{
|
||||
char s[sizeof "65535"];
|
||||
|
||||
return read_num(f, s, sizeof s, out, 10, UINT16_MAX);
|
||||
}
|
||||
|
||||
static int read_hex(FILE *const f, unsigned *const out)
|
||||
{
|
||||
char s[sizeof "0000"];
|
||||
|
||||
return read_num(f, s, sizeof s, out, 16, UINT16_MAX);
|
||||
}
|
||||
|
||||
static int read_dimensions(FILE *const f, unsigned *const w, unsigned *const h)
|
||||
{
|
||||
if (read_dec(f, w) || read_dec(f, h))
|
||||
return -1;
|
||||
else if (*w > MAP_TILES || *h > MAP_TILES)
|
||||
{
|
||||
fprintf(stderr, "%s: map size (%ux%u) exceeded, max %dx%d\n",
|
||||
__func__, *w, *h, MAP_TILES, MAP_TILES);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_map(FILE *const f, const unsigned w, const unsigned h,
|
||||
struct terrain_map *const map)
|
||||
{
|
||||
for (unsigned j = 0; j < h; j++)
|
||||
for (unsigned i = 0; i < w; i++)
|
||||
{
|
||||
unsigned tile;
|
||||
|
||||
if (read_hex(f, &tile))
|
||||
return -1;
|
||||
|
||||
map->m[j][i].t = tile;
|
||||
map->m[j][i].obj = tile >> 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int terrain_init(const char *const path, struct terrain_map *const map)
|
||||
{
|
||||
int ret = -1;
|
||||
FILE *const f = fopen(path, "rb");
|
||||
unsigned w, h;
|
||||
|
||||
if (!f)
|
||||
{
|
||||
fprintf(stderr, "%s: fopen(3): %s\n", __func__, strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
else if (read_dimensions(f, &w, &h) || read_map(f, w, h, map))
|
||||
goto end;
|
||||
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
if (f && fclose(f))
|
||||
{
|
||||
fprintf(stderr, "%s: fclose(3): %s\n", __func__, strerror(errno));
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
#include <terrain.h>
|
||||
#include <camera.h>
|
||||
#include <gfx.h>
|
||||
#include <util.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct sprite terrain_sprites[MAX_TERRAIN_SPRITES];
|
||||
|
||||
static int render_tile(const struct terrain_tile *const t, const short x,
|
||||
const short y)
|
||||
{
|
||||
static const struct tile
|
||||
{
|
||||
const struct sprite *s;
|
||||
int start, end;
|
||||
} tiles[] =
|
||||
{
|
||||
{
|
||||
.s = &terrain_sprites[ROOF1],
|
||||
.start = ROOF1_START,
|
||||
.end = ROOF1_END
|
||||
}
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof tiles / sizeof *tiles; i++)
|
||||
{
|
||||
const struct tile *const rt = &tiles[i];
|
||||
|
||||
if (t->t >= rt->start && t->t <= rt->end)
|
||||
{
|
||||
sprite_get_or_ret(s, -1);
|
||||
|
||||
if (sprite_clone(rt->s, s))
|
||||
{
|
||||
fprintf(stderr, "%s: sprite_clone failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const unsigned char pos = t->t - rt->start;
|
||||
const short tx = pos % TERRAIN_SZ, ty = pos / TERRAIN_SZ;
|
||||
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
s->w = TERRAIN_SZ;
|
||||
s->h = TERRAIN_SZ;
|
||||
s->u = tx * TERRAIN_SZ;
|
||||
s->v = ty * TERRAIN_SZ;
|
||||
|
||||
const int ret = sprite_sort(s);
|
||||
|
||||
if (ret)
|
||||
fprintf(stderr, "%s: sprite_sort failed\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: unknown tile %#hhx\n", __func__, t->t);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int terrain_render(const struct terrain_map *const map,
|
||||
const struct camera *const cam)
|
||||
{
|
||||
const int start_x = abs(cam->x / TERRAIN_SZ),
|
||||
start_y = abs(cam->y / TERRAIN_SZ);
|
||||
|
||||
const int remx = cam->x % TERRAIN_SZ,
|
||||
remy = cam->y % TERRAIN_SZ;
|
||||
|
||||
int nx = map->nx, ny = map->ny;
|
||||
|
||||
if (abs(remx))
|
||||
nx++;
|
||||
|
||||
if (abs(remy))
|
||||
ny++;
|
||||
|
||||
struct m
|
||||
{
|
||||
size_t i;
|
||||
long p;
|
||||
};
|
||||
|
||||
for (struct m x = {.i = start_x, .p = remx};
|
||||
x.i < nx + start_x; x.i++, x.p += TERRAIN_SZ)
|
||||
for (struct m y = {.i = start_y, .p = remy};
|
||||
y.i < ny + start_y; y.i++, y.p += TERRAIN_SZ)
|
||||
{
|
||||
const struct terrain_tile *const t = &map->m[y.i][x.i];
|
||||
|
||||
if (render_tile(t, x.p, y.p))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
#include <terrain.h>
|
||||
#include <camera.h>
|
||||
#include <gfx.h>
|
||||
#include <util.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct sprite grass_sprite;
|
||||
|
||||
void terrain_update(struct terrain_map *const map)
|
||||
{
|
||||
if (map->last_w != screen_w)
|
||||
{
|
||||
const int extra = !!(screen_w % TERRAIN_SZ);
|
||||
|
||||
map->nx = screen_w / TERRAIN_SZ + extra;
|
||||
map->last_w = screen_w;
|
||||
}
|
||||
|
||||
if (map->last_h != screen_h)
|
||||
{
|
||||
const int extra = !!(screen_h % TERRAIN_SZ);
|
||||
|
||||
map->ny = screen_h / TERRAIN_SZ + extra;
|
||||
map->last_h = screen_h;
|
||||
}
|
||||
}
|
||||
|
||||
struct block
|
||||
{
|
||||
size_t x0, x1, y0, y1;
|
||||
};
|
||||
|
||||
void terrain_block_update(const struct util_rect *const dim, const bool alive,
|
||||
void *const p)
|
||||
{
|
||||
const struct block b =
|
||||
{
|
||||
.x0 = dim->x / TERRAIN_SZ,
|
||||
.x1 = (dim->x + dim->w) / TERRAIN_SZ,
|
||||
.y0 = dim->y / TERRAIN_SZ,
|
||||
.y1 = (dim->y + dim->h) / TERRAIN_SZ
|
||||
};
|
||||
|
||||
for (size_t x = b.x0; x <= b.x1; x++)
|
||||
for (size_t y = b.y0; y <= b.y1; y++)
|
||||
for (size_t i = 0; i < 2; i++)
|
||||
for (size_t j = 0; j < 2; j++)
|
||||
{
|
||||
const struct util_rect sub =
|
||||
{
|
||||
.x = x * TERRAIN_SZ + i * (TERRAIN_SZ / 2),
|
||||
.y = y * TERRAIN_SZ + j * (TERRAIN_SZ / 2),
|
||||
.w = TERRAIN_SZ / 2,
|
||||
.h = TERRAIN_SZ / 2
|
||||
};
|
||||
|
||||
if (util_collision(dim, &sub))
|
||||
{
|
||||
const enum
|
||||
{
|
||||
NO_SUB = 0,
|
||||
UPPER_LEFT = 1 << 0,
|
||||
UPPER_RIGHT = 1 << 1,
|
||||
LOWER_LEFT = 1 << 2,
|
||||
LOWER_RIGHT = 1 << 3,
|
||||
ALL_BLOCKS = UPPER_LEFT | UPPER_RIGHT
|
||||
| LOWER_LEFT | LOWER_RIGHT
|
||||
} sub = 1 << (i + j * 2);
|
||||
|
||||
struct terrain_map *const map = p;
|
||||
unsigned char *const bl = &map->m[y][x].bl;
|
||||
|
||||
*bl = alive ? *bl | sub : *bl & ~sub;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int terrain_render(const struct terrain_map *const map,
|
||||
const struct camera *const cam)
|
||||
{
|
||||
const int start_x = abs(cam->x / TERRAIN_SZ),
|
||||
start_y = abs(cam->y / TERRAIN_SZ);
|
||||
|
||||
const int remx = cam->x % TERRAIN_SZ,
|
||||
remy = cam->y % TERRAIN_SZ;
|
||||
|
||||
int nx = map->nx, ny = map->ny;
|
||||
|
||||
if (abs(remx))
|
||||
nx++;
|
||||
|
||||
if (abs(remy))
|
||||
ny++;
|
||||
|
||||
struct m
|
||||
{
|
||||
size_t i;
|
||||
long p;
|
||||
};
|
||||
|
||||
for (struct m x = {.i = start_x, .p = remx};
|
||||
x.i < nx + start_x; x.i++, x.p += TERRAIN_SZ)
|
||||
for (struct m y = {.i = start_y, .p = remy};
|
||||
y.i < ny + start_y; y.i++, y.p += TERRAIN_SZ)
|
||||
{
|
||||
const struct terrain_tile *const t = &map->m[y.i][x.i];
|
||||
|
||||
sprite_get_or_ret(s, -1);
|
||||
|
||||
switch (t->t)
|
||||
{
|
||||
case TERRAIN_TYPE_GRASS:
|
||||
if (sprite_clone(&grass_sprite, s))
|
||||
return -1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
s->x = x.p;
|
||||
s->y = y.p;
|
||||
sprite_sort(s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void terrain_init(struct terrain_map *const map)
|
||||
{
|
||||
*map = (const struct terrain_map){0};
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
#include <terrain.h>
|
||||
|
||||
void terrain_update(struct terrain_map *const map)
|
||||
{
|
||||
if (map->last_w != screen_w)
|
||||
{
|
||||
const int extra = !!(screen_w % TERRAIN_SZ);
|
||||
|
||||
map->nx = screen_w / TERRAIN_SZ + extra;
|
||||
map->last_w = screen_w;
|
||||
}
|
||||
|
||||
if (map->last_h != screen_h)
|
||||
{
|
||||
const int extra = !!(screen_h % TERRAIN_SZ);
|
||||
|
||||
map->ny = screen_h / TERRAIN_SZ + extra;
|
||||
map->last_h = screen_h;
|
||||
}
|
||||
}
|
|
@ -25,8 +25,6 @@ struct unit_target
|
|||
{
|
||||
struct instance *ins;
|
||||
enum unit_state state;
|
||||
instance_sheltered_cb shelter;
|
||||
instance_attacked_cb attack;
|
||||
instance_done_cb done;
|
||||
void *op;
|
||||
};
|
||||
|
@ -73,9 +71,7 @@ bool unit_can_harvest(const struct unit *u);
|
|||
bool unit_target_valid(const struct unit *u, const struct unit_target *t);
|
||||
void unit_set_target(struct unit *u, const struct unit_target *t);
|
||||
void unit_move_to(struct unit *u, unsigned long x, unsigned long y);
|
||||
bool unit_attacked(struct instance *, instance_hp ap);
|
||||
void unit_update(struct unit *u);
|
||||
instance_hp unit_maxhp(const struct unit *u);
|
||||
const char *unit_str(const struct unit *u);
|
||||
|
||||
enum
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
enum unit_type
|
||||
{
|
||||
UNIT_TYPE_PEASANT,
|
||||
|
||||
MAX_UNIT_TYPES
|
||||
};
|
||||
|
||||
|
|
|
@ -64,14 +64,7 @@ static void get_speed(const struct unit *const u, fix16_t *const x,
|
|||
static const struct speed
|
||||
{
|
||||
fix16_t x, y;
|
||||
} speed[] =
|
||||
{
|
||||
[UNIT_TYPE_PEASANT] =
|
||||
{
|
||||
.x = FIX16_C_FROM_INT(1),
|
||||
.y = FIX16_C_FROM_INT(1)
|
||||
}
|
||||
};
|
||||
} speed[1];
|
||||
|
||||
const struct speed *const s = &speed[u->type];
|
||||
const int dx = abs(u->rx - u->tx);
|
||||
|
@ -216,16 +209,6 @@ void unit_move_to(struct unit *const u, const unsigned long x, const unsigned lo
|
|||
u->ty = y > y_off ? fix16_from_int(y - y_off) : 0;
|
||||
}
|
||||
|
||||
instance_hp unit_maxhp(const struct unit *const u)
|
||||
{
|
||||
static const instance_hp hp[] =
|
||||
{
|
||||
[UNIT_TYPE_PEASANT] = 25
|
||||
};
|
||||
|
||||
return hp[u->type];
|
||||
}
|
||||
|
||||
static int get_ux(const struct unit *const u)
|
||||
{
|
||||
switch (u->dir)
|
||||
|
@ -268,6 +251,7 @@ typedef const struct
|
|||
|
||||
static anim_dim *peasant_anim(const struct unit *const u)
|
||||
{
|
||||
#if 0
|
||||
static anim_dim t[] =
|
||||
{
|
||||
{
|
||||
|
@ -322,6 +306,9 @@ static anim_dim *peasant_anim(const struct unit *const u)
|
|||
return NULL;
|
||||
|
||||
return &t[ux];
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct render_cfg
|
||||
|
@ -377,10 +364,7 @@ static int unit_quad(const struct unit *const u, struct render_cfg *const rcfg)
|
|||
{
|
||||
struct instance_render_quad *const qcfg = &rcfg->qcfg;
|
||||
|
||||
static anim_dim *(*const f[])(const struct unit *) =
|
||||
{
|
||||
[UNIT_TYPE_PEASANT] = peasant_quad
|
||||
};
|
||||
static anim_dim *(*const f[1])(const struct unit *);
|
||||
|
||||
anim_dim *const dim = f[u->type](u);
|
||||
|
||||
|
@ -416,7 +400,6 @@ int unit_render(const struct unit *const u, const struct camera *const cam,
|
|||
.prim = {.quad = &rcfg.qcfg},
|
||||
.cam = cam,
|
||||
.sel = sel,
|
||||
.max_hp = unit_maxhp(u),
|
||||
.off = &rcfg.off
|
||||
};
|
||||
|
||||
|
@ -429,10 +412,7 @@ static void get_dimensions(const enum unit_type type, short *const w,
|
|||
static const struct dim
|
||||
{
|
||||
short w, h;
|
||||
} dim[] =
|
||||
{
|
||||
[UNIT_TYPE_PEASANT] = {.w = 36, .h = 36}
|
||||
};
|
||||
} dim[1];
|
||||
|
||||
const struct dim *const d = &dim[type];
|
||||
*w = d->w;
|
||||
|
@ -448,7 +428,6 @@ void unit_create(const struct unit_cfg *const cfg, struct unit *const u)
|
|||
.instance =
|
||||
{
|
||||
.alive = true,
|
||||
.hp = unit_maxhp(u)
|
||||
},
|
||||
|
||||
.type = cfg->type,
|
||||
|
@ -463,10 +442,7 @@ void unit_create(const struct unit_cfg *const cfg, struct unit *const u)
|
|||
|
||||
const char *unit_str(const struct unit *const u)
|
||||
{
|
||||
static const char *const str[] =
|
||||
{
|
||||
[UNIT_TYPE_PEASANT] = "Peasant"
|
||||
};
|
||||
static const char *const str[1];
|
||||
|
||||
return str[u->type];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue