Remove resource, tech and old game resources
This commit is contained in:
parent
39ecbd690b
commit
0aef4f319c
|
@ -20,7 +20,6 @@ set(components
|
|||
pad
|
||||
peripheral
|
||||
player
|
||||
resource
|
||||
settings
|
||||
sfx
|
||||
system
|
||||
|
@ -31,7 +30,6 @@ set(components
|
|||
)
|
||||
|
||||
set(interfaces
|
||||
tech
|
||||
)
|
||||
|
||||
target_compile_options(${PROJECT_NAME} PUBLIC ${cflags})
|
||||
|
|
|
@ -9,7 +9,6 @@ target_link_libraries(game PUBLIC peripheral PRIVATE
|
|||
instance
|
||||
pad
|
||||
player
|
||||
resource
|
||||
system
|
||||
terrain
|
||||
unit)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <gfx.h>
|
||||
#include <human_player.h>
|
||||
#include <player.h>
|
||||
#include <resource.h>
|
||||
#include <system.h>
|
||||
#include <terrain.h>
|
||||
#include <stddef.h>
|
||||
|
@ -38,30 +37,6 @@ int game(const struct game_cfg *const cfg)
|
|||
if (human_player_init(&hcfg, &human))
|
||||
goto end;
|
||||
|
||||
struct resource res[MAP_RESOURCES] = {0};
|
||||
|
||||
resource_set_alive_cb(terrain_block_update, &map);
|
||||
|
||||
if (resource_create(&(const struct resource_cfg)
|
||||
{
|
||||
.type = RESOURCE_TYPE_GOLD,
|
||||
.x = 50,
|
||||
.y = 200
|
||||
}, res, sizeof res / sizeof *res)
|
||||
|| resource_create(&(const struct resource_cfg)
|
||||
{
|
||||
.type = RESOURCE_TYPE_WOOD,
|
||||
.x = 180,
|
||||
.y = 200
|
||||
}, res, sizeof res / sizeof *res)
|
||||
|| resource_create(&(const struct resource_cfg)
|
||||
{
|
||||
.type = RESOURCE_TYPE_WOOD,
|
||||
.x = 240,
|
||||
.y = 200
|
||||
}, res, sizeof res / sizeof *res))
|
||||
goto end;
|
||||
|
||||
bool exit = false;
|
||||
|
||||
while (!exit)
|
||||
|
@ -70,11 +45,7 @@ int game(const struct game_cfg *const cfg)
|
|||
|
||||
if (human.pl.alive)
|
||||
{
|
||||
struct player_others o =
|
||||
{
|
||||
.res = res,
|
||||
.n_res = sizeof res / sizeof *res
|
||||
};
|
||||
struct player_others o;
|
||||
|
||||
human_player_update(&human, &o);
|
||||
exit |= human.periph->common.exit;
|
||||
|
|
|
@ -8,284 +8,11 @@
|
|||
#include <gui/line_edit.h>
|
||||
#include <gui/rounded_rect.h>
|
||||
#include <gui/checkbox.h>
|
||||
#include <resource.h>
|
||||
#include <terrain.h>
|
||||
#include <unit.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static const struct container c[] =
|
||||
{
|
||||
{
|
||||
.path = "barracks",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &building_sprites[BUILDING_TYPE_BARRACKS]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "worker_n",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &unit_sprites[UNIT_SPRITE_N]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "worker_ne",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &unit_sprites[UNIT_SPRITE_NE]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "worker_e",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &unit_sprites[UNIT_SPRITE_E]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "worker_se",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &unit_sprites[UNIT_SPRITE_SE]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "worker_s",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &unit_sprites[UNIT_SPRITE_S]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "grass",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &grass_sprite
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "cursor",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &cursor_sprite
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "gui_bar_left",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_bar_sprites[GUI_BAR_LEFT]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "gui_bar_mid",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_bar_sprites[GUI_BAR_MID]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "gui_bar_right",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_bar_sprites[GUI_BAR_RIGHT]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "sel_up_left",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_UP_LEFT]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "sel_up_right",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_UP_RIGHT]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "sel_down_left",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_DOWN_LEFT]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "sel_down_right",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_DOWN_RIGHT]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "sel_mid",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_MID]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "sel_mid_v",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_rounded_rect_sprites[GUI_ROUNDED_RECT_MID_VERT]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "font",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &font_sprite
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "gold_mine",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &resource_sprites[RESOURCE_TYPE_GOLD]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "tree",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &resource_sprites[RESOURCE_TYPE_WOOD]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "acknowledge_01",
|
||||
.type = CONTAINER_TYPE_SOUND,
|
||||
.data =
|
||||
{
|
||||
.sound = &unit_sounds[UNIT_SOUND_MOVE]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "acknowledge_02",
|
||||
.type = CONTAINER_TYPE_SOUND,
|
||||
.data =
|
||||
{
|
||||
.sound = &unit_sounds[UNIT_SOUND_MOVE_2]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "selected_01",
|
||||
.type = CONTAINER_TYPE_SOUND,
|
||||
.data =
|
||||
{
|
||||
.sound = &unit_sounds[UNIT_SOUND_SELECTED]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.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]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "line_edit_left",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_line_edit_sprites[GUI_LINE_EDIT_LEFT]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "line_edit_mid",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_line_edit_sprites[GUI_LINE_EDIT_MID]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "line_edit_right",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_line_edit_sprites[GUI_LINE_EDIT_RIGHT]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
.path = "checkbox",
|
||||
.type = CONTAINER_TYPE_SPRITE,
|
||||
.data =
|
||||
{
|
||||
.sprite = &gui_checkbox_sprite
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const struct container c[1];
|
||||
static bool init;
|
||||
|
||||
void game_free(void)
|
||||
|
@ -301,7 +28,7 @@ int game_resinit(void)
|
|||
{
|
||||
if (!init)
|
||||
{
|
||||
if (container_load("rts.cnt", c, sizeof c / sizeof *c))
|
||||
if (container_load("jancity.cnt", c, sizeof c / sizeof *c))
|
||||
{
|
||||
perror("container_load");
|
||||
return -1;
|
||||
|
|
|
@ -75,5 +75,10 @@ int menu(void)
|
|||
peripheral_init(&cfg, &c.p);
|
||||
settings_load("settings.ini", &c.s);
|
||||
|
||||
return menu_main(&c);
|
||||
const struct game_cfg gcfg =
|
||||
{
|
||||
.p = &c.p
|
||||
};
|
||||
|
||||
return game(&gcfg);
|
||||
}
|
||||
|
|
|
@ -14,8 +14,6 @@ target_link_libraries(player
|
|||
input
|
||||
mouse
|
||||
pad
|
||||
resource
|
||||
tech
|
||||
unit
|
||||
util
|
||||
PRIVATE
|
||||
|
|
|
@ -39,8 +39,7 @@ struct human_player
|
|||
enum sel_type
|
||||
{
|
||||
INSTANCE_TYPE_UNIT,
|
||||
INSTANCE_TYPE_BUILDING,
|
||||
INSTANCE_TYPE_RESOURCE
|
||||
INSTANCE_TYPE_BUILDING
|
||||
} type;
|
||||
|
||||
union sel_data
|
||||
|
@ -61,8 +60,6 @@ struct human_player
|
|||
} target;
|
||||
|
||||
size_t n_sel;
|
||||
bool top_gui;
|
||||
uint32_t gui_res[MAX_RESOURCE_TYPES];
|
||||
};
|
||||
|
||||
int human_player_init(const struct human_player_cfg *cfg, struct human_player *h);
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#include <camera.h>
|
||||
#include <instance.h>
|
||||
#include <pad.h>
|
||||
#include <resource.h>
|
||||
#include <tech.h>
|
||||
#include <unit.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
@ -36,13 +34,7 @@ struct player
|
|||
bool alive;
|
||||
struct unit units[PLAYER_MAX_UNITS];
|
||||
struct building buildings[PLAYER_MAX_BUILDINGS];
|
||||
uint32_t resources[MAX_RESOURCE_TYPES];
|
||||
unsigned char pop, bpop;
|
||||
|
||||
struct
|
||||
{
|
||||
struct unit_tech u;
|
||||
} tree;
|
||||
};
|
||||
|
||||
struct player_cfg
|
||||
|
@ -55,8 +47,7 @@ struct player_cfg
|
|||
struct player_others
|
||||
{
|
||||
struct player *pl;
|
||||
struct resource *res;
|
||||
size_t n_pl, n_res;
|
||||
size_t n_pl;
|
||||
};
|
||||
|
||||
int player_init(const struct player_cfg *cfg, struct player *pl);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <input.h>
|
||||
#include <keyboard.h>
|
||||
#include <pad.h>
|
||||
#include <resource.h>
|
||||
#include <unit.h>
|
||||
#include <util.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -42,61 +41,49 @@ static bool select_units(struct human_player *const h, const short x,
|
|||
const struct unit *const u = &pl->units[i];
|
||||
const struct instance *const in = &u->instance;
|
||||
|
||||
if (in->alive)
|
||||
if (!in->alive)
|
||||
continue;
|
||||
|
||||
const union sel_data d = {.u = u};
|
||||
|
||||
if (!instance_selected(h, &d)
|
||||
&& cursor_collision(&h->cam, &in->r)
|
||||
&& h->n_sel < sizeof h->sel / sizeof *h->sel)
|
||||
{
|
||||
switch (u->state)
|
||||
struct sel_instance *sel = NULL;
|
||||
|
||||
if (excl)
|
||||
{
|
||||
default:
|
||||
sel = h->sel;
|
||||
h->n_sel = 1;
|
||||
|
||||
for (size_t i = 1; i < sizeof h->sel / sizeof *h->sel; i++)
|
||||
h->sel[i].d.u = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < sizeof h->sel / sizeof *h->sel; i++)
|
||||
{
|
||||
const union sel_data d = {.u = u};
|
||||
struct sel_instance *const s = &h->sel[i];
|
||||
|
||||
if (!instance_selected(h, &d)
|
||||
&& cursor_collision(&h->cam, &in->r)
|
||||
&& h->n_sel < sizeof h->sel / sizeof *h->sel)
|
||||
if (!s->d.u)
|
||||
{
|
||||
struct sel_instance *sel = NULL;
|
||||
|
||||
if (excl)
|
||||
{
|
||||
sel = h->sel;
|
||||
h->n_sel = 1;
|
||||
|
||||
for (size_t i = 1; i < sizeof h->sel / sizeof *h->sel; i++)
|
||||
h->sel[i].d.u = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < sizeof h->sel / sizeof *h->sel; i++)
|
||||
{
|
||||
struct sel_instance *const s = &h->sel[i];
|
||||
|
||||
if (!s->d.u)
|
||||
{
|
||||
sel = s;
|
||||
h->n_sel++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sel)
|
||||
{
|
||||
sel->type = INSTANCE_TYPE_UNIT;
|
||||
sel->d.u = u;
|
||||
sfx_play(&unit_sounds[UNIT_SOUND_SELECTED]);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
sel = s;
|
||||
h->n_sel++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case UNIT_STATE_SHELTERED:
|
||||
/* Fall through. */
|
||||
case UNIT_STATE_HARVESTING_GOLD:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sel)
|
||||
{
|
||||
sel->type = INSTANCE_TYPE_UNIT;
|
||||
sel->d.u = u;
|
||||
sfx_play(&unit_sounds[UNIT_SOUND_SELECTED]);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,62 +148,6 @@ static bool select_buildings(struct human_player *const h, const short x,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool select_resources(struct human_player *const h, const short x,
|
||||
const short y, const struct player_others *const o, const bool excl)
|
||||
{
|
||||
for (size_t i = 0; i < o->n_res; i++)
|
||||
{
|
||||
const struct resource *const r = &o->res[i];
|
||||
const struct instance *const in = &r->instance;
|
||||
|
||||
if (in->alive)
|
||||
{
|
||||
const union sel_data d = {.r = r};
|
||||
|
||||
if (!instance_selected(h, &d)
|
||||
&& cursor_collision(&h->cam, &in->r)
|
||||
&& h->n_sel < sizeof h->sel / sizeof *h->sel)
|
||||
{
|
||||
struct sel_instance *sel = NULL;
|
||||
|
||||
if (excl)
|
||||
{
|
||||
sel = h->sel;
|
||||
h->n_sel = 1;
|
||||
|
||||
for (size_t i = 1; i < sizeof h->sel / sizeof *h->sel; i++)
|
||||
h->sel[i].d.r = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < sizeof h->sel / sizeof *h->sel; i++)
|
||||
{
|
||||
struct sel_instance *const s = &h->sel[i];
|
||||
|
||||
if (!s->d.r)
|
||||
{
|
||||
sel = s;
|
||||
h->n_sel++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sel)
|
||||
{
|
||||
sel->type = INSTANCE_TYPE_RESOURCE;
|
||||
sel->d.r = r;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool select_instances(struct human_player *const h,
|
||||
const struct player_others *const o, const bool excl,
|
||||
const bool same_type)
|
||||
|
@ -227,8 +158,7 @@ static bool select_instances(struct human_player *const h,
|
|||
|
||||
if (!same_type || !h->n_sel)
|
||||
return select_buildings(h, x, y, excl)
|
||||
|| select_units(h, x, y, excl)
|
||||
|| select_resources(h, x, y, o, excl);
|
||||
|| select_units(h, x, y, excl);
|
||||
else
|
||||
{
|
||||
switch (h->sel->type)
|
||||
|
@ -238,9 +168,6 @@ static bool select_instances(struct human_player *const h,
|
|||
|
||||
case INSTANCE_TYPE_BUILDING:
|
||||
return select_buildings(h, x, y, excl);
|
||||
|
||||
case INSTANCE_TYPE_RESOURCE:
|
||||
select_resources(h, x, y, o, excl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,62 +180,6 @@ static bool instance_collision(const struct camera *const cam,
|
|||
return in->alive && cursor_collision(cam, &in->r);
|
||||
}
|
||||
|
||||
static void resources_stored(struct instance *const i, void *const op)
|
||||
{
|
||||
struct player *const p = op;
|
||||
struct unit *const u = (struct unit *)i;
|
||||
struct unit_harvester *const uh = &u->us.harvester;
|
||||
|
||||
p->resources[uh->type] += uh->carry;
|
||||
uh->carry = 0;
|
||||
unit_set_target(u, &uh->prev_target);
|
||||
}
|
||||
|
||||
static void harvest_done(struct instance *const ins, void *const op)
|
||||
{
|
||||
struct player *const p = op;
|
||||
struct unit *const u = (struct unit *)ins;
|
||||
struct resource *const res = (struct resource *)u->target.ins;
|
||||
|
||||
if (res->type == RESOURCE_TYPE_GOLD)
|
||||
{
|
||||
struct resource_gold *const g = &res->res.gold;
|
||||
|
||||
for (size_t i = 0; i < sizeof g->miners / sizeof *g->miners; i++)
|
||||
{
|
||||
struct instance **const pi = &g->miners[i];
|
||||
|
||||
if (*pi == ins)
|
||||
{
|
||||
*pi = NULL;
|
||||
g->n_miners--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof p->buildings / sizeof *p->buildings; i++)
|
||||
{
|
||||
struct building *const b = &p->buildings[i];
|
||||
|
||||
if (b->instance.alive && b->type == BUILDING_TYPE_BARRACKS)
|
||||
{
|
||||
const struct unit_target t =
|
||||
{
|
||||
.ins = &b->instance,
|
||||
.state = UNIT_STATE_CARRYING,
|
||||
.done = resources_stored,
|
||||
.op = p
|
||||
/* TODO .state = UNIT_STATE_SHELTERED */
|
||||
};
|
||||
|
||||
u->us.harvester.prev_target = u->target;
|
||||
unit_set_target(u, &t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool target_from_own(struct player *const p,
|
||||
const struct camera *const cam, struct unit_target *const t)
|
||||
{
|
||||
|
@ -332,101 +203,6 @@ static bool target_from_own(struct player *const p,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool target_from_others(const struct player *const p,
|
||||
const struct player_others *const o,
|
||||
const struct camera *const cam, struct unit_target *const t)
|
||||
{
|
||||
for (size_t i = 0; i < o->n_pl; i++)
|
||||
{
|
||||
struct player *const pl = &o->pl[i];
|
||||
|
||||
if (p->team != pl->team)
|
||||
{
|
||||
for (size_t i = 0; i < sizeof pl->units / sizeof *pl->units; i++)
|
||||
{
|
||||
struct unit *const u = &pl->units[i];
|
||||
struct instance *const in = &u->instance;
|
||||
|
||||
if (instance_collision(cam, in))
|
||||
{
|
||||
*t = (const struct unit_target)
|
||||
{
|
||||
.ins = in,
|
||||
.attack = unit_attacked,
|
||||
.state = UNIT_STATE_ATTACKING
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof pl->buildings / sizeof *pl->buildings; i++)
|
||||
{
|
||||
struct building *const b = &pl->buildings[i];
|
||||
struct instance *const in = &b->instance;
|
||||
|
||||
if (instance_collision(cam, in))
|
||||
{
|
||||
*t = (const struct unit_target)
|
||||
{
|
||||
.ins = in,
|
||||
.state = UNIT_STATE_ATTACKING
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static enum unit_state target_state_from_res(const struct resource *const res)
|
||||
{
|
||||
switch (res->type)
|
||||
{
|
||||
case RESOURCE_TYPE_GOLD:
|
||||
return UNIT_STATE_HARVESTING_GOLD;
|
||||
|
||||
case RESOURCE_TYPE_WOOD:
|
||||
return UNIT_STATE_HARVESTING_WOOD;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return UNIT_STATE_IDLE_MOVING;
|
||||
}
|
||||
|
||||
static bool target_from_res(struct player *const p,
|
||||
const struct player_others *const o,
|
||||
const struct camera *const cam, struct unit_target *const t)
|
||||
{
|
||||
for (size_t i = 0; i < o->n_res; i++)
|
||||
{
|
||||
struct resource *const res = &o->res[i];
|
||||
struct instance *const in = &res->instance;
|
||||
|
||||
if (instance_collision(cam, in))
|
||||
{
|
||||
*t = (const struct unit_target)
|
||||
{
|
||||
.ins = in,
|
||||
.attack = resource_harvested,
|
||||
.shelter = resource_shelter(res),
|
||||
.state = target_state_from_res(res),
|
||||
.done = harvest_done,
|
||||
.op = p
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void set_target(struct human_player *const h, struct unit *const u,
|
||||
const struct unit_target *const t)
|
||||
{
|
||||
|
@ -443,9 +219,7 @@ static void target_from_pos(struct player *const p,
|
|||
const struct player_others *const o,
|
||||
const struct camera *const cam, struct unit_target *const t)
|
||||
{
|
||||
if (!target_from_own(p, cam, t)
|
||||
&& !target_from_others(p, o, cam, t)
|
||||
&& !target_from_res(p, o, cam, t))
|
||||
if (!target_from_own(p, cam, t))
|
||||
t->ins = NULL;
|
||||
}
|
||||
|
||||
|
@ -472,7 +246,7 @@ static void move_units(struct human_player *const h,
|
|||
{
|
||||
struct unit *const u = si->d.rw_u;
|
||||
|
||||
if (!t.ins || !unit_target_valid(u, &t))
|
||||
if (!t.ins)
|
||||
unit_move_to(u, x, y);
|
||||
else
|
||||
set_target(h, u, &t);
|
||||
|
@ -506,9 +280,7 @@ 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
|
||||
&& (si->d.u->state == UNIT_STATE_HARVESTING_GOLD
|
||||
|| si->d.u->state == UNIT_STATE_SHELTERED))))
|
||||
|| si->type == INSTANCE_TYPE_UNIT))
|
||||
{
|
||||
si->d.i = NULL;
|
||||
h->n_sel--;
|
||||
|
@ -552,8 +324,6 @@ static void update_from_pad(struct human_player *const h,
|
|||
move_units(h, o);
|
||||
else if (input_pad_justpressed(in, p, PAD_KEY_C))
|
||||
deselect_instances(h);
|
||||
else if (input_pad_justpressed(in, p, PAD_KEY_E))
|
||||
h->top_gui ^= true;
|
||||
}
|
||||
|
||||
static void update_from_touch(struct human_player *const h,
|
||||
|
@ -686,30 +456,12 @@ static int render_own_buildings(const struct human_player *const h)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int render_resources(const struct human_player *const h,
|
||||
const struct resource *const res, const size_t n)
|
||||
{
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
const struct resource *const r = &res[i];
|
||||
const union sel_data d = {.r = r};
|
||||
const bool sel = instance_selected(h, &d);
|
||||
|
||||
if (resource_render(r, &h->cam, sel))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int human_player_render(const struct human_player *const h,
|
||||
const struct player_others *const o)
|
||||
{
|
||||
if (render_target(h)
|
||||
|| render_own_units(h)
|
||||
|| render_own_buildings(h)
|
||||
|| render_resources(h, o->res, o->n_res)
|
||||
|| human_player_gui_render(h)
|
||||
|| input_render(&h->in, h->periph))
|
||||
return -1;
|
||||
|
||||
|
@ -742,9 +494,5 @@ int human_player_init(const struct human_player_cfg *const cfg,
|
|||
cursor_init(&h->cam.cursor);
|
||||
h->periph = cfg->p;
|
||||
h->cam.dim = cfg->dim;
|
||||
h->top_gui = true;
|
||||
UTIL_STATIC_ASSERT(sizeof h->gui_res == sizeof h->pl.resources,
|
||||
"unexpected sizeof for h->gui_res");
|
||||
memmove(h->gui_res, h->pl.resources, sizeof h->gui_res);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -17,68 +17,8 @@
|
|||
|
||||
enum {X_OFF = 8, Y_OFF = 8, HP_Y = 32};
|
||||
|
||||
static int draw_hp(const struct instance *const i, const instance_hp max_hp,
|
||||
struct gui_common *const r)
|
||||
{
|
||||
enum {WIDTH = 64, HEIGHT = 4};
|
||||
struct gui_progress_bar pb;
|
||||
|
||||
gui_progress_bar_init(&pb);
|
||||
pb.common.x = X_OFF;
|
||||
pb.common.y = HP_Y - 8;
|
||||
pb.progress = ((unsigned)GUI_PROGRESS_BAR_MAX * i->hp) / max_hp;
|
||||
pb.fg.g = UCHAR_MAX >> 1;
|
||||
pb.bg.r = UCHAR_MAX >> 1;
|
||||
pb.w = WIDTH;
|
||||
pb.h = HEIGHT;
|
||||
pb.stp = true;
|
||||
gui_add_child(r, &pb.common);
|
||||
|
||||
return gui_render(r);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int draw_miners(const struct resource *const r)
|
||||
{
|
||||
const struct resource_gold *const g = &r->res.gold;
|
||||
|
||||
if (!g->n_miners)
|
||||
return 0;
|
||||
|
||||
for (size_t i = 0, n = 0; i < sizeof g->miners / sizeof *g->miners; i++)
|
||||
{
|
||||
if (g->miners[i])
|
||||
{
|
||||
enum {OFFSET = 112, SZ = 16, GAP = 4};
|
||||
|
||||
rect_get_or_ret(r, -1);
|
||||
semitrans_rect_init(r);
|
||||
r->x = OFFSET + n * (SZ + GAP);
|
||||
r->y = screen_h - 40;
|
||||
r->r = r->g = r->b = 127;
|
||||
r->w = r->h = SZ;
|
||||
rect_sort(r);
|
||||
|
||||
if (++n >= g->n_miners)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void human_player_gui_update(struct human_player *const h)
|
||||
{
|
||||
struct player *const pl = &h->pl;
|
||||
|
||||
for (size_t i = 0; i < sizeof pl->resources / sizeof *pl->resources; i++)
|
||||
{
|
||||
if (h->gui_res[i] > pl->resources[i])
|
||||
h->gui_res[i]--;
|
||||
else if (h->gui_res[i] < pl->resources[i])
|
||||
h->gui_res[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
static int render_sel_single_building(const struct human_player *const h,
|
||||
|
@ -110,7 +50,7 @@ static int render_sel_single_building(const struct human_player *const h,
|
|||
hpl.text = hp_str;
|
||||
gui_add_child(r, &hpl.common);
|
||||
|
||||
return draw_hp(in, max_hp, r);
|
||||
return gui_render(r);
|
||||
}
|
||||
|
||||
static int render_sel_single_unit(const struct human_player *const h,
|
||||
|
@ -144,60 +84,7 @@ static int render_sel_single_unit(const struct human_player *const h,
|
|||
hpl.text = hp_str;
|
||||
gui_add_child(r, &hpl.common);
|
||||
|
||||
char c_str[sizeof "255"];
|
||||
struct gui_label cl;
|
||||
|
||||
if (unit_can_harvest(u))
|
||||
{
|
||||
const struct unit_harvester *const uh = &u->us.harvester;
|
||||
|
||||
if (uh->carry)
|
||||
{
|
||||
const int rs = snprintf(c_str, sizeof c_str, "%hhu", uh->carry);
|
||||
|
||||
if (rs < 0 || rs >= sizeof c_str)
|
||||
return -1;
|
||||
|
||||
gui_label_init(&cl);
|
||||
cl.common.x = CARRY_X;
|
||||
cl.common.y = CARRY_Y;
|
||||
cl.text = c_str;
|
||||
gui_add_child(r, &cl.common);
|
||||
}
|
||||
}
|
||||
|
||||
return draw_hp(in, max_hp, r);
|
||||
}
|
||||
|
||||
static int render_sel_single_resource(const struct human_player *const h,
|
||||
const struct sel_instance *const sel, struct gui_common *const r)
|
||||
{
|
||||
const struct resource *const res = sel->d.r;
|
||||
const struct instance *const in = &res->instance;
|
||||
const instance_hp hp = in->hp, max_hp = resource_maxhp(res);
|
||||
struct gui_label rl;
|
||||
|
||||
gui_label_init(&rl);
|
||||
rl.common.x = X_OFF;
|
||||
rl.common.y = Y_OFF;
|
||||
rl.text = resource_str(res);
|
||||
gui_add_child(r, &rl.common);
|
||||
|
||||
char hp_str[sizeof "65535/65535"];
|
||||
const int rs = snprintf(hp_str, sizeof hp_str, "%u/%u", hp, max_hp);
|
||||
|
||||
if (rs < 0 || rs >= sizeof hp_str)
|
||||
return -1;
|
||||
|
||||
struct gui_label hpl;
|
||||
|
||||
gui_label_init(&hpl);
|
||||
hpl.common.x = X_OFF;
|
||||
hpl.common.y = HP_Y;
|
||||
hpl.text = hp_str;
|
||||
gui_add_child(r, &hpl.common);
|
||||
|
||||
return draw_hp(in, max_hp, r);
|
||||
return gui_render(r);
|
||||
}
|
||||
|
||||
static int render_sel_single(const struct human_player *const h,
|
||||
|
@ -216,14 +103,11 @@ static int render_sel_single(const struct human_player *const h,
|
|||
|
||||
case INSTANCE_TYPE_UNIT:
|
||||
return render_sel_single_unit(h, sel, r);
|
||||
|
||||
case INSTANCE_TYPE_RESOURCE:
|
||||
return render_sel_single_resource(h, sel, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Unreachable. */
|
||||
fprintf(stderr, "%s: unreachable\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -262,83 +146,8 @@ static int render_sel(const struct human_player *const h)
|
|||
return render_sel_multiple(h, &r.common);
|
||||
}
|
||||
|
||||
static int render_top(const struct human_player *const h)
|
||||
{
|
||||
const struct player *const pl = &h->pl;
|
||||
struct gui_container c;
|
||||
struct gui_bar b;
|
||||
|
||||
gui_bar_init(&b);
|
||||
b.w = screen_w;
|
||||
gui_container_init(&c);
|
||||
c.mode = GUI_CONTAINER_MODE_H;
|
||||
c.spacing = 16;
|
||||
c.common.hcentered = true;
|
||||
c.common.vcentered = true;
|
||||
gui_add_child(&b.common, &c.common);
|
||||
|
||||
char wood_str[sizeof "Wood=429496729"];
|
||||
|
||||
{
|
||||
const int rs = snprintf(wood_str, sizeof wood_str,
|
||||
"Wood=%" PRIu32, h->gui_res[RESOURCE_TYPE_WOOD]);
|
||||
|
||||
if (rs < 0 || rs >= sizeof wood_str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct gui_label wl;
|
||||
|
||||
gui_label_init(&wl);
|
||||
wl.common.vcentered = true;
|
||||
wl.text = wood_str;
|
||||
gui_add_child(&c.common, &wl.common);
|
||||
|
||||
char gold_str[sizeof "Gold=429496729"];
|
||||
|
||||
{
|
||||
const int rs = snprintf(gold_str, sizeof gold_str,
|
||||
"Gold=%" PRIu32, h->gui_res[RESOURCE_TYPE_GOLD]);
|
||||
|
||||
if (rs < 0 || rs >= sizeof wood_str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct gui_label gl;
|
||||
|
||||
gui_label_init(&gl);
|
||||
wl.common.vcentered = true;
|
||||
gl.text = gold_str;
|
||||
gui_add_child(&c.common, &gl.common);
|
||||
|
||||
char pop_str[sizeof "Pop.=255/255"];
|
||||
|
||||
{
|
||||
const int rs = snprintf(pop_str, sizeof pop_str,
|
||||
"Pop.=%hhu/%zu", pl->pop, sizeof pl->units / sizeof *pl->units);
|
||||
|
||||
if (rs < 0 || rs >= sizeof wood_str)
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct gui_label popl;
|
||||
|
||||
gui_label_init(&popl);
|
||||
wl.common.vcentered = true;
|
||||
popl.text = pop_str;
|
||||
gui_add_child(&c.common, &popl.common);
|
||||
|
||||
if (gui_render(&b.common))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int human_player_gui_render(const struct human_player *const h)
|
||||
{
|
||||
if (h->top_gui && render_top(h))
|
||||
return -1;
|
||||
|
||||
if (h->n_sel && render_sel(h))
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ void player_update(struct player *const p)
|
|||
{
|
||||
struct unit *const u = &p->units[i];
|
||||
|
||||
unit_update(&p->tree.u, u);
|
||||
unit_update(u);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,13 +98,6 @@ int player_init(const struct player_cfg *const cfg, struct player *const pl)
|
|||
if (player_create_unit(&cfgs[i], pl))
|
||||
return -1;
|
||||
|
||||
for (size_t i = 0; i < sizeof pl->resources / sizeof *pl->resources; i++)
|
||||
{
|
||||
enum {DEFAULT_RES = 120};
|
||||
|
||||
pl->resources[i] = DEFAULT_RES;
|
||||
}
|
||||
|
||||
pl->alive = true;
|
||||
pl->color = cfg->color;
|
||||
pl->team = cfg->team;
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
add_library(resource "src/resource.c")
|
||||
target_include_directories(resource PUBLIC "inc")
|
||||
target_link_libraries(resource PUBLIC camera gfx instance util)
|
|
@ -1,58 +0,0 @@
|
|||
#ifndef RESOURCE_H
|
||||
#define RESOURCE_H
|
||||
|
||||
#include <camera.h>
|
||||
#include <container.h>
|
||||
#include <gfx.h>
|
||||
#include <instance.h>
|
||||
#include <resource_type.h>
|
||||
#include <util.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
enum {RESOURCE_GOLD_CAPACITY = 2};
|
||||
|
||||
struct resource
|
||||
{
|
||||
struct instance instance;
|
||||
enum resource_type type;
|
||||
|
||||
union
|
||||
{
|
||||
struct resource_gold
|
||||
{
|
||||
struct instance *miners[RESOURCE_GOLD_CAPACITY];
|
||||
size_t n_miners;
|
||||
} gold;
|
||||
} res;
|
||||
};
|
||||
|
||||
UTIL_STATIC_ASSERT(!offsetof(struct resource, instance), "must be at offset zero");
|
||||
|
||||
struct resource_cfg
|
||||
{
|
||||
enum resource_type type;
|
||||
unsigned long x, y;
|
||||
};
|
||||
|
||||
const struct container_list *resource_res(void);
|
||||
void resource_set_alive_cb(void (*f)(const struct util_rect *dim, bool alive, void *p), void *p);
|
||||
int resource_create(const struct resource_cfg *cfg, struct resource *list, size_t n);
|
||||
int resource_render(const struct resource *res, const struct camera *cam, bool sel);
|
||||
instance_sheltered_cb resource_shelter(const struct resource *res);
|
||||
bool resource_harvested(struct instance *i, instance_hp ap);
|
||||
instance_hp resource_maxhp(const struct resource *res);
|
||||
const char *resource_str(const struct resource *res);
|
||||
|
||||
extern struct sprite resource_sprites[MAX_RESOURCE_TYPES];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RESOURCE_H */
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef RESOURCE_TYPE_H
|
||||
#define RESOURCE_TYPE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
enum resource_type
|
||||
{
|
||||
RESOURCE_TYPE_WOOD,
|
||||
RESOURCE_TYPE_GOLD,
|
||||
|
||||
MAX_RESOURCE_TYPES
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RESOURCE_TYPE_H */
|
|
@ -1,177 +0,0 @@
|
|||
#include <resource.h>
|
||||
#include <gfx.h>
|
||||
#include <instance.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct sprite resource_sprites[MAX_RESOURCE_TYPES];
|
||||
static void (*cb)(const struct util_rect *, bool, void *);
|
||||
static void *op;
|
||||
|
||||
static bool gold_shelter(struct instance *const self,
|
||||
struct instance *const other)
|
||||
{
|
||||
struct resource *const res = (struct resource *)self;
|
||||
struct resource_gold *const g = &res->res.gold;
|
||||
|
||||
for (size_t i = 0; i < sizeof g->miners / sizeof *g->miners; i++)
|
||||
{
|
||||
struct instance **const ins = &g->miners[i];
|
||||
|
||||
if (!*ins)
|
||||
{
|
||||
*ins = other;
|
||||
g->n_miners++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
instance_sheltered_cb resource_shelter(const struct resource *res)
|
||||
{
|
||||
static const instance_sheltered_cb s[] =
|
||||
{
|
||||
[RESOURCE_TYPE_GOLD] = gold_shelter
|
||||
};
|
||||
|
||||
return s[res->type];
|
||||
}
|
||||
|
||||
bool resource_harvested(struct instance *const self, const instance_hp ap)
|
||||
{
|
||||
const bool ret = instance_attacked(self, ap);
|
||||
|
||||
if (ret && cb)
|
||||
cb(&self->r, self->alive, op);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
instance_hp resource_maxhp(const struct resource *const res)
|
||||
{
|
||||
static const instance_hp hp[] =
|
||||
{
|
||||
[RESOURCE_TYPE_GOLD] = 1000,
|
||||
[RESOURCE_TYPE_WOOD] = 45
|
||||
};
|
||||
|
||||
return hp[res->type];
|
||||
}
|
||||
|
||||
int resource_render(const struct resource *const res,
|
||||
const struct camera *const cam, const bool sel)
|
||||
{
|
||||
const struct instance *const in = &res->instance;
|
||||
|
||||
if (!in->alive)
|
||||
return 0;
|
||||
|
||||
sprite_get_or_ret(s, -1);
|
||||
|
||||
if (sprite_clone(&resource_sprites[res->type], s))
|
||||
return -1;
|
||||
|
||||
const struct instance_render_off *off = NULL;
|
||||
|
||||
switch (res->type)
|
||||
{
|
||||
case RESOURCE_TYPE_GOLD:
|
||||
s->h = in->r.h;
|
||||
|
||||
if (res->res.gold.n_miners)
|
||||
s->v += s->h;
|
||||
|
||||
break;
|
||||
|
||||
case RESOURCE_TYPE_WOOD:
|
||||
{
|
||||
static const struct instance_render_off w_off =
|
||||
{
|
||||
.y = -30
|
||||
};
|
||||
|
||||
off = &w_off;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const struct instance_render_cfg cfg =
|
||||
{
|
||||
.i = &res->instance,
|
||||
.prim_type = INSTANCE_RENDER_CFG_SPRITE,
|
||||
.prim = {.s = s},
|
||||
.cam = cam,
|
||||
.sel = sel,
|
||||
.max_hp = resource_maxhp(res),
|
||||
.off = off
|
||||
};
|
||||
|
||||
return instance_render(&cfg);
|
||||
}
|
||||
|
||||
static void get_dimensions(const enum resource_type type, short *const w,
|
||||
short *const h)
|
||||
{
|
||||
static const struct dim
|
||||
{
|
||||
short w, h;
|
||||
} dim[] =
|
||||
{
|
||||
[RESOURCE_TYPE_GOLD] = {.w = 96, .h = 96},
|
||||
[RESOURCE_TYPE_WOOD] = {.w = 32, .h = 16}
|
||||
};
|
||||
|
||||
const struct dim *const d = &dim[type];
|
||||
*w = d->w;
|
||||
*h = d->h;
|
||||
}
|
||||
|
||||
int resource_create(const struct resource_cfg *const cfg, struct resource *const list,
|
||||
const size_t n)
|
||||
{
|
||||
for (size_t i = 0; i < n; i++)
|
||||
{
|
||||
struct resource *const r = &list[i];
|
||||
struct instance *const in = &r->instance;
|
||||
|
||||
if (!in->alive)
|
||||
{
|
||||
get_dimensions(cfg->type, &in->r.w, &in->r.h);
|
||||
r->type = cfg->type;
|
||||
in->r.x = cfg->x;
|
||||
in->r.y = cfg->y;
|
||||
in->alive = true;
|
||||
in->hp = resource_maxhp(r);
|
||||
|
||||
if (cb)
|
||||
cb(&in->r, in->alive, op);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void resource_set_alive_cb(void (*const f)(const struct util_rect *, bool, void *),
|
||||
void *const p)
|
||||
{
|
||||
cb = f;
|
||||
op = p;
|
||||
}
|
||||
|
||||
const char *resource_str(const struct resource *const res)
|
||||
{
|
||||
static const char *const str[] =
|
||||
{
|
||||
[RESOURCE_TYPE_GOLD] = "Gold mine",
|
||||
[RESOURCE_TYPE_WOOD] = "Pine tree"
|
||||
};
|
||||
|
||||
return str[res->type];
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
add_library(tech INTERFACE)
|
||||
target_include_directories(tech INTERFACE "inc")
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef TECH_H
|
||||
#define TECH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
enum tech_level
|
||||
{
|
||||
TECH_LEVEL_1,
|
||||
TECH_LEVEL_2,
|
||||
TECH_LEVEL_3
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TECH_H */
|
|
@ -14,7 +14,7 @@ extern "C"
|
|||
enum
|
||||
{
|
||||
MAP_TILES = 64,
|
||||
TERRAIN_SZ = 32,
|
||||
TERRAIN_SZ = 16,
|
||||
MAP_W = MAP_TILES * TERRAIN_SZ,
|
||||
MAP_H = MAP_TILES * TERRAIN_SZ
|
||||
};
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
add_library(unit "src/unit.c")
|
||||
target_include_directories(unit PUBLIC "inc")
|
||||
target_link_libraries(unit PUBLIC fixmath container camera gfx instance resource sfx tech util)
|
||||
target_link_libraries(unit
|
||||
PUBLIC
|
||||
fixmath
|
||||
container
|
||||
camera
|
||||
gfx
|
||||
instance
|
||||
sfx
|
||||
util
|
||||
)
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#include <gfx.h>
|
||||
#include <sfx.h>
|
||||
#include <instance.h>
|
||||
#include <resource_type.h>
|
||||
#include <tech.h>
|
||||
#include <unit_type.h>
|
||||
#include <util.h>
|
||||
#include <fixmath.h>
|
||||
|
@ -18,19 +16,9 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
struct unit_tech
|
||||
{
|
||||
enum tech_level carry;
|
||||
};
|
||||
|
||||
enum unit_state
|
||||
{
|
||||
UNIT_STATE_IDLE_MOVING,
|
||||
UNIT_STATE_SHELTERED,
|
||||
UNIT_STATE_HARVESTING_WOOD,
|
||||
UNIT_STATE_HARVESTING_GOLD,
|
||||
UNIT_STATE_CARRYING,
|
||||
UNIT_STATE_ATTACKING
|
||||
UNIT_STATE_IDLE_MOVING
|
||||
};
|
||||
|
||||
struct unit_target
|
||||
|
@ -67,18 +55,7 @@ struct unit
|
|||
unsigned char t, i;
|
||||
} frame;
|
||||
|
||||
union
|
||||
{
|
||||
struct unit_harvester
|
||||
{
|
||||
enum resource_type type;
|
||||
unsigned char carry, t;
|
||||
struct unit_target prev_target;
|
||||
} harvester;
|
||||
} us;
|
||||
|
||||
fix16_t rx, ry, tx, ty;
|
||||
|
||||
struct unit_target target;
|
||||
};
|
||||
|
||||
|
@ -97,7 +74,7 @@ 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(const struct unit_tech *t, struct unit *u);
|
||||
void unit_update(struct unit *u);
|
||||
instance_hp unit_maxhp(const struct unit *u);
|
||||
const char *unit_str(const struct unit *u);
|
||||
|
||||
|
|
|
@ -115,16 +115,6 @@ static enum unit_dir get_direction(const struct unit *const u)
|
|||
return dir;
|
||||
}
|
||||
|
||||
static instance_hp attack_points(const struct unit *const u)
|
||||
{
|
||||
static instance_hp ap[] =
|
||||
{
|
||||
[UNIT_TYPE_PEASANT] = 1
|
||||
};
|
||||
|
||||
return ap[u->type];
|
||||
}
|
||||
|
||||
static void unit_stop(struct unit *const u)
|
||||
{
|
||||
u->tx = u->rx;
|
||||
|
@ -151,68 +141,18 @@ static void target_interact(struct unit *const u)
|
|||
const struct instance *const ins = t->ins;
|
||||
|
||||
/* TODO: lose u->ti if not visible. */
|
||||
if (ins->alive)
|
||||
if (!ins->alive)
|
||||
{
|
||||
if (t->state != u->state)
|
||||
{
|
||||
struct instance *const ui = &u->instance;
|
||||
|
||||
if (util_collision(&ins->r, &ui->r))
|
||||
{
|
||||
switch (t->state)
|
||||
{
|
||||
case UNIT_STATE_CARRYING:
|
||||
u->target.done(&u->instance, u->target.op);
|
||||
break;
|
||||
|
||||
case UNIT_STATE_ATTACKING:
|
||||
t->attack(t->ins, attack_points(u));
|
||||
u->state = t->state;
|
||||
break;
|
||||
|
||||
case UNIT_STATE_HARVESTING_WOOD:
|
||||
{
|
||||
struct unit_harvester *const uh = &u->us.harvester;
|
||||
|
||||
if (uh->type != RESOURCE_TYPE_WOOD)
|
||||
uh->carry = 0;
|
||||
|
||||
uh->type = RESOURCE_TYPE_WOOD;
|
||||
u->state = t->state;
|
||||
unit_stop(u);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNIT_STATE_HARVESTING_GOLD:
|
||||
{
|
||||
struct unit_harvester *const uh = &u->us.harvester;
|
||||
|
||||
if (uh->type != RESOURCE_TYPE_GOLD)
|
||||
uh->carry = 0;
|
||||
|
||||
uh->type = RESOURCE_TYPE_GOLD;
|
||||
|
||||
if (t->shelter(t->ins, ui))
|
||||
u->state = t->state;
|
||||
else
|
||||
unit_stop(u);
|
||||
}
|
||||
break;
|
||||
|
||||
case UNIT_STATE_SHELTERED:
|
||||
u->state = t->state;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
unit_chase(ins, u);
|
||||
}
|
||||
}
|
||||
else
|
||||
target_reset(u);
|
||||
return;
|
||||
}
|
||||
else if (t->state == u->state)
|
||||
return;
|
||||
|
||||
struct instance *const ui = &u->instance;
|
||||
|
||||
if (!util_collision(&ins->r, &ui->r))
|
||||
unit_chase(ins, u);
|
||||
}
|
||||
|
||||
static bool must_move(const struct unit *const u)
|
||||
|
@ -220,164 +160,40 @@ static bool must_move(const struct unit *const u)
|
|||
return u->rx != u->tx || u->ry != u->ty;
|
||||
}
|
||||
|
||||
static void update_harvest(const struct unit_tech *const t, struct unit *const u)
|
||||
{
|
||||
static const unsigned char carry[] =
|
||||
{
|
||||
[TECH_LEVEL_1] = 10,
|
||||
[TECH_LEVEL_2] = 15,
|
||||
[TECH_LEVEL_3] = 25
|
||||
};
|
||||
|
||||
static const char inc[] =
|
||||
{
|
||||
[TECH_LEVEL_1] = 10,
|
||||
[TECH_LEVEL_2] = 50,
|
||||
[TECH_LEVEL_3] = 25
|
||||
};
|
||||
|
||||
struct unit_harvester *const uh = &u->us.harvester;
|
||||
bool ret = false;
|
||||
|
||||
if (++uh->t >= inc[t->carry])
|
||||
{
|
||||
if (uh->carry < carry[t->carry])
|
||||
{
|
||||
++uh->carry;
|
||||
ret = u->target.attack(u->target.ins, 1);
|
||||
}
|
||||
|
||||
uh->t = 0;
|
||||
}
|
||||
|
||||
if (ret || uh->carry >= carry[t->carry])
|
||||
{
|
||||
u->state = UNIT_STATE_CARRYING;
|
||||
u->target.done(&u->instance, u->target.op);
|
||||
}
|
||||
}
|
||||
|
||||
void unit_update(const struct unit_tech *const t, struct unit *const u)
|
||||
void unit_update(struct unit *const u)
|
||||
{
|
||||
const struct instance *const i = &u->instance;
|
||||
|
||||
if (i->alive)
|
||||
{
|
||||
if (u->target.ins)
|
||||
target_interact(u);
|
||||
if (!i->alive)
|
||||
return;
|
||||
|
||||
switch (u->state)
|
||||
if (u->target.ins)
|
||||
target_interact(u);
|
||||
else if (must_move(u))
|
||||
{
|
||||
fix16_t x_step, y_step;
|
||||
|
||||
u->dir = get_direction(u);
|
||||
get_speed(u, &x_step, &y_step);
|
||||
move_unit(u, x_step, y_step);
|
||||
|
||||
enum {FRAME_RATE = 6};
|
||||
|
||||
if (++u->frame.t >= FRAME_RATE)
|
||||
{
|
||||
case UNIT_STATE_SHELTERED:
|
||||
break;
|
||||
u->frame.t = 0;
|
||||
|
||||
case UNIT_STATE_HARVESTING_GOLD:
|
||||
/* Fall through. */
|
||||
case UNIT_STATE_HARVESTING_WOOD:
|
||||
update_harvest(t, u);
|
||||
break;
|
||||
|
||||
case UNIT_STATE_ATTACKING:
|
||||
if (must_move(u))
|
||||
u->state = UNIT_STATE_IDLE_MOVING;
|
||||
|
||||
break;
|
||||
|
||||
case UNIT_STATE_CARRYING:
|
||||
/* Fall through. */
|
||||
case UNIT_STATE_IDLE_MOVING:
|
||||
|
||||
if (must_move(u))
|
||||
{
|
||||
fix16_t x_step, y_step;
|
||||
|
||||
u->dir = get_direction(u);
|
||||
get_speed(u, &x_step, &y_step);
|
||||
move_unit(u, x_step, y_step);
|
||||
|
||||
enum {FRAME_RATE = 6};
|
||||
|
||||
if (++u->frame.t >= FRAME_RATE)
|
||||
{
|
||||
u->frame.t = 0;
|
||||
|
||||
if (++u->frame.i >= N_FRAMES)
|
||||
u->frame.i = 0;
|
||||
}
|
||||
|
||||
u->state = UNIT_STATE_IDLE_MOVING;
|
||||
}
|
||||
else
|
||||
u->frame.i = 0;
|
||||
|
||||
u->instance.r.x = fix16_to_int(u->rx);
|
||||
u->instance.r.y = fix16_to_int(u->ry);
|
||||
break;
|
||||
if (++u->frame.i >= N_FRAMES)
|
||||
u->frame.i = 0;
|
||||
}
|
||||
|
||||
u->state = UNIT_STATE_IDLE_MOVING;
|
||||
}
|
||||
}
|
||||
else
|
||||
u->frame.i = 0;
|
||||
|
||||
bool can_attack(const struct unit *const u)
|
||||
{
|
||||
static const bool a[] =
|
||||
{
|
||||
[UNIT_TYPE_PEASANT] = true
|
||||
};
|
||||
|
||||
return a[u->type];
|
||||
}
|
||||
|
||||
static bool can_shelter(const struct unit *const u)
|
||||
{
|
||||
static const bool s[] =
|
||||
{
|
||||
[UNIT_TYPE_PEASANT] = true
|
||||
};
|
||||
|
||||
return s[u->type];
|
||||
}
|
||||
|
||||
bool unit_can_harvest(const struct unit *const u)
|
||||
{
|
||||
static const bool h[] =
|
||||
{
|
||||
[UNIT_TYPE_PEASANT] = true
|
||||
};
|
||||
|
||||
return h[u->type];
|
||||
}
|
||||
|
||||
bool unit_attacked(struct instance *const i, const instance_hp ap)
|
||||
{
|
||||
return instance_attacked(i, ap);
|
||||
}
|
||||
|
||||
bool unit_target_valid(const struct unit *const u,
|
||||
const struct unit_target *const t)
|
||||
{
|
||||
switch (t->state)
|
||||
{
|
||||
case UNIT_STATE_HARVESTING_GOLD:
|
||||
/* Fall through. */
|
||||
case UNIT_STATE_HARVESTING_WOOD:
|
||||
return unit_can_harvest(u);
|
||||
|
||||
case UNIT_STATE_ATTACKING:
|
||||
return can_attack(u);
|
||||
|
||||
case UNIT_STATE_SHELTERED:
|
||||
if (t->shelter)
|
||||
return can_shelter(u);
|
||||
else
|
||||
break;
|
||||
|
||||
case UNIT_STATE_IDLE_MOVING:
|
||||
/* Fall through. */
|
||||
case UNIT_STATE_CARRYING:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
u->instance.r.x = fix16_to_int(u->rx);
|
||||
u->instance.r.y = fix16_to_int(u->ry);
|
||||
}
|
||||
|
||||
void unit_set_target(struct unit *const u, const struct unit_target *const t)
|
||||
|
@ -582,9 +398,7 @@ static int unit_quad(const struct unit *const u, struct render_cfg *const rcfg)
|
|||
int unit_render(const struct unit *const u, const struct camera *const cam,
|
||||
const bool sel)
|
||||
{
|
||||
if (!u->instance.alive
|
||||
|| u->state == UNIT_STATE_SHELTERED
|
||||
|| u->state == UNIT_STATE_HARVESTING_GOLD)
|
||||
if (!u->instance.alive)
|
||||
return 0;
|
||||
|
||||
struct render_cfg rcfg;
|
||||
|
|
Loading…
Reference in New Issue