Replaced state logic with behaviours instead.

This commit is contained in:
Linus Probert 2018-05-19 17:55:10 +02:00
parent b905232d5e
commit 186cc7b514
4 changed files with 191 additions and 117 deletions

View File

@ -37,10 +37,12 @@ local texturePaths = {
}
local state = {
passive = 0,
agressive = 1,
scared = 2,
local behaviour = {
pacifist = 0,
normal = 1,
hostile = 2,
guerilla = 3,
coward = 4
}
local stats = {
@ -89,31 +91,31 @@ local pests = {
--{ texturePaths.pest0, texturePaths.pest1, stats.pest, 48, 0, "A Beetle" },
--{ texturePaths.pest0, texturePaths.pest1, stats.pest, 64, 0, "A Large Grub" },
--{ texturePaths.pest0, texturePaths.pest1, stats.pest, 80, 0, "A Small Grub" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 96, 0, "A Slim Worm" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 112, 0, "A Fat Worm" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 96, 0, "A Slim Worm", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 112, 0, "A Fat Worm", behaviour.pacifist },
--{ texturePaths.pest0, texturePaths.pest1, 0, 16, "Female Dragonfly" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 16, 16, "A Fly" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 16, 16, "A Fly", behaviour.pacifist },
--{ texturePaths.pest0, texturePaths.pest1, stats.pest, 32, 16, "A Larva" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 48, 16, "A Moth" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 48, 16, "A Moth", behaviour.pacifist },
--{ texturePaths.pest0, texturePaths.pest1, stats.pest, 64, 16 },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 80, 16, "A Gnat" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 80, 16, "A Gnat", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 0, 32, "A Small Spider" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 16, 32, "A Medium Spider" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 32, 32, "A Large Spider" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 48, 32, "A Small Scorpion" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 64, 32, "A Medium Scorpion" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 80, 32, "A Large Scorpion" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 0, 32, "A Small Spider", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 16, 32, "A Medium Spider", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 32, 32, "A Large Spider", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 48, 32, "A Small Scorpion", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 64, 32, "A Medium Scorpion", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 80, 32, "A Large Scorpion", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 0, 48, "A Slug" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 16, 48, "A Large Slug" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 0, 48, "A Slug", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 16, 48, "A Large Slug", behaviour.pacifist },
--{ texturePaths.pest0, texturePaths.pest1, 32, 48 },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 48, 48, "A Red Slug" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 64, 48, "A Large Red Slug" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 48, 48, "A Red Slug", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 64, 48, "A Large Red Slug", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 0, 64, "A Giant Brown Ant" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 16, 64, "A Giant Black Ant" },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 0, 64, "A Giant Brown Ant", behaviour.pacifist },
{ texturePaths.pest0, texturePaths.pest1, stats.pest, 16, 64, "A Giant Black Ant", behaviour.pacifist },
--{ texturePaths.pest0, texturePaths.pest1, stats.pest, 32, 64, "A Giant Gold Ant" },
--{ texturePaths.pest0, texturePaths.pest1, stats.pest, 48, 64, "A Giant Silver Ant" },
@ -134,61 +136,61 @@ local pests = {
local undead = {
-- UNDEAD
--{ texturePaths.undead0, texturePaths.undead1, 0, 0, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 16, 0, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 32, 0, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 48, 0, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 64, 0, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 80, 0, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 96, 0, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 112, 0, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 0, 0, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 16, 0, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 32, 0, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 48, 0, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 64, 0, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 80, 0, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 96, 0, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 112, 0, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 0, 16, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 16, 16, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 32, 16, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 48, 16, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 64, 16, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 80, 16, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 96, 16, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 112, 16, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 0, 16, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 16, 16, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 32, 16, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 48, 16, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 64, 16, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 80, 16, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 96, 16, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 112, 16, "", behaviour.normal };
{ texturePaths.undead0, texturePaths.undead1, stats.undead, 0, 32, "A Skeleton", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 16, 32, "An Umber Skeleton", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 32, 32, "A Caustic Skeleton", state.passive, state.agressive };
{ texturePaths.undead0, texturePaths.undead1, stats.undead, 48, 32, "A Black Skeleton", state.passive, state.agressive };
{ texturePaths.undead0, texturePaths.undead1, stats.undead, 64, 32, "A Zombie", state.passive, state.agressive };
{ texturePaths.undead0, texturePaths.undead1, stats.undead, 80, 32, "A Zombie", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 96, 32, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 112, 32, "", state.passive, state.scared };
{ texturePaths.undead0, texturePaths.undead1, stats.undead, 0, 32, "A Skeleton", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 16, 32, "An Umber Skeleton", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 32, 32, "A Caustic Skeleton", behaviour.normal };
{ texturePaths.undead0, texturePaths.undead1, stats.undead, 48, 32, "A Black Skeleton", behaviour.normal };
{ texturePaths.undead0, texturePaths.undead1, stats.undead, 64, 32, "A Zombie", behaviour.normal };
{ texturePaths.undead0, texturePaths.undead1, stats.undead, 80, 32, "A Zombie", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 96, 32, "", behaviour.normal };
--{ texturePaths.undead0, texturePaths.undead1, 112, 32, "", behaviour.normal };
}
local dogs = {
{ texturePaths.dog0, texturePaths.dog1, stats.dog, 0, 16, "A Rabid Dog", state.passive, state.agressive };
{ texturePaths.dog0, texturePaths.dog1, stats.dog, 16, 16, "An Angry Rabid Dog", state.agressive, state.agressive };
{ texturePaths.dog0, texturePaths.dog1, stats.dog, 0, 16, "A Rabid Dog", behaviour.normal };
{ texturePaths.dog0, texturePaths.dog1, stats.dog, 16, 16, "An Angry Rabid Dog", behaviour.hostile };
}
local reptile = {
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 0, 64, "A Small Brown Snake", state.passive, state.agressive };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 16, 64, "A Medium Brown Snake", state.passive, state.agressive };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 32, 64, "A Large Brown Snake", state.passive, state.agressive };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 48, 64, "A Small Black Snake", state.agressive, state.agressive };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 64, 64, "A Medium Black Snake", state.agressive, state.agressive };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 80, 64, "A Large Black Snake", state.agressive, state.agressive };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 0, 64, "A Small Brown Snake", behaviour.coward };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 16, 64, "A Medium Brown Snake", behaviour.guerilla };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 32, 64, "A Large Brown Snake", behaviour.hostile };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 48, 64, "A Small Black Snake", behaviour.coward };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 64, 64, "A Medium Black Snake", behaviour.guerilla };
{ texturePaths.reptile0, texturePaths.reptile1, stats.default, 80, 64, "A Large Black Snake", behaviour.hostile };
}
local platino = {
{ texturePaths.reptile0, texturePaths.reptile1, stats.platino, 48, 12*16, "Platino", state.agressive, state.agressive };
{ texturePaths.reptile0, texturePaths.reptile1, stats.platino, 48, 12*16, "Platino", behaviour.hostile };
}
local demon = {
{ texturePaths.demon0, texturePaths.demon1, stats.default, 0, 0, "A Demon", state.agressive, state.agressive };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 16, 0, "A Demon", state.agressive, state.agressive };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 32, 0, "A Demon", state.agressive, state.agressive };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 48, 0, "A Demon", state.agressive, state.agressive };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 64, 0, "A Demon", state.agressive, state.agressive };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 80, 0, "A Demon", state.agressive, state.agressive };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 96, 0, "A Demon", state.agressive, state.agressive };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 112, 0, "A Demon", state.agressive, state.agressive };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 0, 0, "A Demon", behaviour.hostile };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 16, 0, "A Demon", behaviour.hostile };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 32, 0, "A Demon", behaviour.hostile };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 48, 0, "A Demon", behaviour.hostile };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 64, 0, "A Demon", behaviour.hostile };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 80, 0, "A Demon", behaviour.hostile };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 96, 0, "A Demon", behaviour.hostile };
{ texturePaths.demon0, texturePaths.demon1, stats.default, 112, 0, "A Demon", behaviour.hostile };
}
local function concat(table1, table2)
@ -206,8 +208,7 @@ local function repack(data)
clipX = data[4],
clipY = data[5],
label = data[6] or "",
nstate = data[7] or state.passive,
cstate = data[8] or state.scared,
behaviour = data[7] or behaviour.normal,
}
end

View File

@ -281,7 +281,7 @@ l_add_monster(lua_State *L)
{
Monster *monster;
Map *map;
int x, y, clip_x, clip_y, nstate, cstate;
int x, y, clip_x, clip_y, behaviour;
const char *texture_path_1, *texture_path_2, *tmp_label;
char *label;
Texture *texture1, *texture2;
@ -301,17 +301,15 @@ l_add_monster(lua_State *L)
lua_getfield(L, 4, "stats");
lua_getfield(L, 4, "clipX");
lua_getfield(L, 4, "clipY");
lua_getfield(L, 4, "nstate");
lua_getfield(L, 4, "cstate");
lua_getfield(L, 4, "behaviour");
tmp_label = luaL_checkstring(L, -8);
texture_path_1 = luaL_checkstring(L, -7);
texture_path_2 = luaL_checkstring(L, -6);
stats = lua_checkstats(L, -5);
clip_x = (int) luaL_checkinteger(L, -4);
clip_y = (int) luaL_checkinteger(L, -3);
nstate = (int) luaL_checkinteger(L, -2);
cstate = (int) luaL_checkinteger(L, -1);
tmp_label = luaL_checkstring(L, -7);
texture_path_1 = luaL_checkstring(L, -6);
texture_path_2 = luaL_checkstring(L, -5);
stats = lua_checkstats(L, -4);
clip_x = (int) luaL_checkinteger(L, -3);
clip_y = (int) luaL_checkinteger(L, -2);
behaviour = (int) luaL_checkinteger(L, -1);
texture1 = texturecache_add(texture_path_1);
texture2 = texturecache_add(texture_path_2);
@ -328,7 +326,7 @@ l_add_monster(lua_State *L)
monster_update_pos(monster, (Position) { x, y });
sprite_set_texture(monster->sprite, texture1, 0);
sprite_set_texture(monster->sprite, texture2, 1);
monster_set_states(monster, nstate, cstate);
monster_set_behaviour(monster, behaviour);
if (strlen(label)) {
monster->label = label;
monster->lclabel = to_lower(label);

View File

@ -34,6 +34,82 @@
#include "actiontextbuilder.h"
#include "texturecache.h"
static void
monster_set_sprite_clip_for_current_state(Monster *m)
{
switch (m->state.current) {
case AGRESSIVE:
m->stateIndicator.sprite->clip = CLIP16(16 * 11, 16 * 3);
break;
case STATIONARY:
case PASSIVE:
m->stateIndicator.sprite->clip = CLIP16(16 * 10, 16);
break;
case SCARED:
m->stateIndicator.sprite->clip = CLIP16(16 * 12, 16 * 3);
break;
default:
break;
}
}
static void
monster_state_change(Monster *m, StateType newState)
{
if (m->state.current == newState)
return;
m->state.current = newState;
m->state.stepsSinceChange = 0;
m->stateIndicator.displayCount = 5;
monster_set_sprite_clip_for_current_state(m);
}
static void
monster_behaviour_check_post_hit(Monster *m)
{
switch (m->behaviour) {
case NORMAL:
monster_state_change(m, AGRESSIVE);
break;
case PACIFIST:
case COWARD:
monster_state_change(m, SCARED);
break;
default:
break;
}
}
static void
monster_behaviour_check_post_attack(Monster *m)
{
switch (m->behaviour) {
case GUERILLA:
monster_state_change(m, SCARED);
break;
default:
break;
}
}
static void
monster_behaviour_check(Monster *m, RoomMatrix *rm)
{
UNUSED(rm);
switch (m->behaviour) {
case GUERILLA:
if (m->state.stepsSinceChange > 8
&& m->state.current == SCARED) {
monster_state_change(m, AGRESSIVE);
}
break;
default:
break;
}
}
Monster*
monster_create(void)
{
@ -61,7 +137,7 @@ monster_create(void)
m->stateIndicator.sprite->dim = GAME_DIMENSION;
m->stateIndicator.displayCount = 0;
m->stateIndicator.shownOnPlayerRoomEnter = false;
monster_set_states(m, PASSIVE, AGRESSIVE);
monster_set_behaviour(m, NORMAL);
return m;
}
@ -98,6 +174,7 @@ has_collided(Monster *monster, RoomMatrix *matrix, Vector2d direction)
} else {
gui_log("%s missed you", monster->label);
}
monster_behaviour_check_post_attack(monster);
}
return space->occupied || space->lethal;
@ -239,6 +316,8 @@ monster_move(Monster *m, RoomMatrix *rm)
rm->spaces[monsterRoomPos.x][monsterRoomPos.y].occupied = false;
rm->spaces[monsterRoomPos.x][monsterRoomPos.y].monster = NULL;
monster_behaviour_check(m, rm);
switch (m->state.current) {
case PASSIVE:
monster_drunk_walk(m, rm);
@ -249,6 +328,9 @@ monster_move(Monster *m, RoomMatrix *rm)
case SCARED:
monster_coward_walk(m, rm);
break;
case STATIONARY:
default:
break;
};
monster_update_pos(m, m->sprite->pos);
@ -261,6 +343,7 @@ monster_move(Monster *m, RoomMatrix *rm)
if (m->steps >= m->stats.speed) {
if (m->stateIndicator.displayCount > 0)
m->stateIndicator.displayCount -= 1;
m->state.stepsSinceChange += 1;
m->steps = 0;
return true;
}
@ -284,36 +367,6 @@ monster_update(Monster *m, UpdateData *data)
}
}
static void
monster_set_sprite_clip_for_current_state(Monster *m)
{
switch (m->state.current) {
case AGRESSIVE:
m->stateIndicator.sprite->clip = CLIP16(16 * 11, 16 * 3);
break;
case PASSIVE:
m->stateIndicator.sprite->clip = CLIP16(16 * 10, 16);
break;
case SCARED:
m->stateIndicator.sprite->clip = CLIP16(16 * 12, 16 * 3);
break;
default:
break;
}
}
static void
monster_state_change(Monster *m)
{
if (m->state.current == m->state.challenge)
return;
m->state.current = m->state.challenge;
m->stateIndicator.displayCount = 5;
monster_set_sprite_clip_for_current_state(m);
}
void
monster_hit(Monster *monster, unsigned int dmg)
{
@ -333,8 +386,7 @@ monster_hit(Monster *monster, unsigned int dmg)
C_YELLOW,
&monster->sprite->pos);
}
monster_state_change(monster);
monster_behaviour_check_post_hit(monster);
}
void
@ -410,11 +462,21 @@ monster_render(Monster *m, Camera *cam)
}
void
monster_set_states(Monster *m, StateType normal, StateType challenge)
monster_set_behaviour(Monster *m, MonsterBehaviour behaviour)
{
m->state.normal = normal;
m->state.current = normal;
m->state.challenge = challenge;
m->behaviour = behaviour;
switch (behaviour) {
case HOSTILE:
case GUERILLA:
case COWARD:
m->state.current = AGRESSIVE;
break;
case PACIFIST:
case NORMAL:
default:
m->state.current = PASSIVE;
break;
}
monster_set_sprite_clip_for_current_state(m);
}

View File

@ -28,12 +28,24 @@
struct UpdateData_t;
typedef enum { PASSIVE, AGRESSIVE, SCARED } StateType;
typedef enum {
PACIFIST,
NORMAL,
HOSTILE,
GUERILLA,
COWARD
} MonsterBehaviour;
typedef enum {
PASSIVE,
AGRESSIVE,
SCARED,
STATIONARY
} StateType;
typedef struct {
StateType current;
StateType normal;
StateType challenge;
unsigned int stepsSinceChange;
} State;
typedef struct MonsterStateIndicator {
@ -49,6 +61,7 @@ typedef struct Monster_t {
Stats stats;
State state;
MonsterStateIndicator stateIndicator;
MonsterBehaviour behaviour;
unsigned int steps;
} Monster;
@ -76,7 +89,7 @@ void
monster_drop_loot(Monster*, Map*, Player*);
void
monster_set_states(Monster *, StateType normal, StateType challenge);
monster_set_behaviour(Monster *, MonsterBehaviour m);
void
monster_destroy(Monster*);