From: Niki Date: Thu, 17 Apr 2025 15:16:57 +0000 (+0200) Subject: tower: select target wip X-Git-Url: http://git.nikiroo.be/?a=commitdiff_plain;h=eccce052ad899251d48aef4fe9923ff778b981e4;p=tdef.git tower: select target wip --- diff --git a/src/tdef/tower.c b/src/tdef/tower.c index 6eabe08..68ffd57 100644 --- a/src/tdef/tower.c +++ b/src/tdef/tower.c @@ -21,6 +21,12 @@ #include #include "tower.h" +#include "path.h" + +array_t *enemies_in_range(tower_t *self, array_t *enemies); +array_t *paths_in_range(tower_t *self, array_t *paths); +int at_p_in(int x, int y, path_t *path, int speed); +path_t *get_target(tower_t *self, array_t *enemies, array_t *paths); tower_t *new_tower(tower_base_t *base, int x, int y) { tower_t *self = malloc(sizeof(tower_t)); @@ -80,29 +86,109 @@ void tower_rearm(tower_t *self) { } proj_t *tower_fire(tower_t *self, int current_tick, array_t *enemies, - array_t *path) { + array_t *paths) { if (self->fire_delayed > 0) return NULL; - // TODO: - // select target (3 modes) - // check target expected position - // fire at position if <= range - // (skip to next if not) - - // If not found: return NULL; + path_t *target = get_target(self, enemies, paths); + if (!target) + return NULL; int attack = self->base->stats[self->lvl_attack].attack; - int speed = self->base->stats[self->lvl_speed].speed; + int speed = self->base->stats[self->lvl_speed ].speed; + int range = self->base->stats[self->lvl_range ].range; - proj_t *proj = new_proj(3, 0); // TODO + proj_t *proj = new_proj(target->x, target->y); proj->desc = self->projectile; proj->desc.damage = attack; proj->boom_tick = current_tick + 3; // TODO: compute from speed - self->fire_delayed = self->base->stats[self->lvl_speed].attack; + self->fire_delayed = speed; return proj; } +array_t *enemies_in_range(tower_t *self, array_t *enemies) { + array_t *in_range = new_array(sizeof(enemy_t*), enemies->count/2+1); + + return in_range; +} + +array_t *paths_in_range(tower_t *self, array_t *paths) { + array_t *in_range = new_array(sizeof(path_t *), paths->count/2+1); + + return in_range; +} + +int at_p_in(int x, int y, path_t *path, int speed) { + // TODO + return 1; +} + +path_t *get_target(tower_t *self, array_t *enemies, array_t *paths) { + enemy_t *e_target = NULL; + path_t *p_target = NULL; + + // TODO: move to configurable + #define TARGET_FIRST 0 + #define TARGET_LAST 1 + #define TARGET_WEAKER 2 + #define TARGET_STRONGER 3 + int mode = TARGET_FIRST; + + + // TODO: move paths_in_range as a member of tower_t, cache it + array_t *e_in_range = enemies_in_range(self, enemies); + array_t *p_in_range = (e_in_range->count) ? + paths_in_range(self, paths) + : new_array(sizeof(enemy_t*), 0); + + if (e_in_range->count && p_in_range->count) + array_loop (p_in_range, pptr, path_t*) { + path_t *p = *pptr; + int proj_at_p_in = at_p_in( + self->x, self->y, p, self->proj_speed + ); + + array_loop (e_in_range, eptr, enemy_t*) { + enemy_t *e = *eptr; + path_t *e_p = (path_t*)array_get(paths, e->index); + int enemy_at_p_in = at_p_in( + e_p->x, e_p->y, p, e->base->speed + ); + + if (proj_at_p_in == enemy_at_p_in) { + int take_it = 0; + switch(mode) { + case TARGET_FIRST: + if (!e_target) + take_it = 1; + break; + case TARGET_LAST: + take_it = 1; + break; + case TARGET_WEAKER: + if (!e_target || e->hp < e_target->hp) + take_it = 1; + break; + case TARGET_STRONGER: + if (!e_target || e->hp > e_target->hp) + take_it = 1; + break; + } + + if (take_it) { + e_target = e; + p_target = p; + } + } + } + } + + free_array(p_in_range); + free_array(e_in_range); + + return p_target; +} +