diff --git a/data/monstergen.lua b/data/monstergen.lua index 542883f..719d705 100644 --- a/data/monstergen.lua +++ b/data/monstergen.lua @@ -46,7 +46,8 @@ local behaviour = { coward = 4, sentinel = 5, fire_demon = 6, - sorcerer = 7 + sorcerer = 7, + assassin = 8 } local stats = { @@ -239,12 +240,23 @@ for i=1,#orcs do orcs[i] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, orcs[i]) end +local assassins = { + { stats.misc, 1*16, 6*16, "A Reaper", behaviour.assassin }, + { stats.misc, 0*16, 7*16, "An Assassin", behaviour.assassin }, + { stats.misc, 1*16, 7*16, "A Royal Assassin", behaviour.assassin }, +} +for i=1,#assassins do + assassins[i] = concat({ texturePaths.undead0, texturePaths.undead1 }, assassins[i]) +end + local bosses = { { stats.boss, 16, 5*16, "The Hell Hound", behaviour.fire_demon, true }, { stats.boss, 16, 23*16, "The Cleric", behaviour.sorcerer, true }, + { stats.boss, 16, 8*16, "The Shadow", behaviour.assassin, true }, } bosses[1] = concat({ texturePaths.dog0, texturePaths.dog1 }, bosses[1]) bosses[2] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, bosses[2]) +bosses[3] = concat({ texturePaths.undead0, texturePaths.undead1 }, bosses[3]) local platino = { { @@ -282,6 +294,7 @@ if(CURRENT_LEVEL > 0) then enemies = {} enemies = concat(enemies, undead) enemies = concat(enemies, orcs) + enemies = concat(enemies, assassins) elseif (CURRENT_LEVEL > 10) then enemies = {} enemies = concat(enemies, undead) diff --git a/src/monster.c b/src/monster.c index 82460d8..936a158 100644 --- a/src/monster.c +++ b/src/monster.c @@ -106,6 +106,7 @@ monster_behaviour_check_post_hit(Monster *m) monster_state_change(m, SCARED); break; case GUERILLA: + case ASSASSIN: case SORCERER: case FIRE_DEMON: break; @@ -115,6 +116,48 @@ monster_behaviour_check_post_hit(Monster *m) } } +static void +damage_surroundings(Monster *m, RoomMatrix *rm) +{ + Position roomPos = position_to_matrix_coords(&m->sprite->pos); + for (Sint32 i = -1; i <= 1; ++i) { + for (Sint32 j = -1; j <= 1; ++j) { + if (i == 0 && j == 0) + continue; + RoomSpace *r = &rm->spaces[roomPos.x + i][roomPos.y + j]; + if (r->monster) { + int dmg = stats_fight(&m->stats, &r->monster->stats); + monster_hit(r->monster, dmg); + gui_log("%s takes %d damage from the explosion", r->monster->label, dmg); + } else if (r->player) { + int dmg = stats_fight(&m->stats, &r->player->stats); + player_hit(r->player, dmg); + gui_log("You take %d damage from the explosion", dmg); + } + } + } +} + +static void +sorcerer_blast(Monster *m, RoomMatrix *rm) +{ + gui_log("%s creates a magical explosion", m->label); + particle_engine_eldritch_explosion(m->sprite->pos, DIM(TILE_DIMENSION, TILE_DIMENSION)); + + damage_surroundings(m, rm); +} + +static void +assassin_cloak_effect(Monster *m, bool cloak) +{ + if (cloak) + gui_log("%s dissappears from sight", m->label); + else + gui_log("%s reappears, filled with rage", m->label); + particle_engine_fire_explosion(m->sprite->pos, DIM(TILE_DIMENSION, TILE_DIMENSION)); +} + + static void monster_behaviour_check_post_attack(Monster *m) { @@ -124,6 +167,10 @@ monster_behaviour_check_post_attack(Monster *m) case FIRE_DEMON: monster_state_change(m, SCARED); break; + case ASSASSIN: + assassin_cloak_effect(m, true); + monster_state_change(m, SCARED); + break; default: break; } @@ -163,6 +210,13 @@ monster_behaviour_check(Monster *m, RoomMatrix *rm) monster_state_change(m, AGRESSIVE); } break; + case ASSASSIN: + if (m->state.stepsSinceChange > 5 + && m->state.current == SCARED) { + assassin_cloak_effect(m, false); + monster_state_change(m, AGRESSIVE); + } + break; case SENTINEL: handle_sentinel_behaviour(m, rm); break; @@ -382,31 +436,6 @@ monster_coward_walk(Monster *m, RoomMatrix *rm) } } -static void -sorcerer_blast(Monster *m, RoomMatrix *rm) -{ - gui_log("%s creates a magical explosion", m->label); - particle_engine_eldritch_explosion(m->sprite->pos, DIM(TILE_DIMENSION, TILE_DIMENSION)); - - Position roomPos = position_to_matrix_coords(&m->sprite->pos); - for (Sint32 i = -1; i <= 1; ++i) { - for (Sint32 j = -1; j <= 1; ++j) { - if (i == 0 && j == 0) - continue; - RoomSpace *r = &rm->spaces[roomPos.x + i][roomPos.y + j]; - if (r->monster) { - int dmg = stats_fight(&m->stats, &r->monster->stats); - monster_hit(r->monster, dmg); - gui_log("%s takes %d damage from the explosion", r->monster->label, dmg); - } else if (r->player) { - int dmg = stats_fight(&m->stats, &r->player->stats); - player_hit(r->player, dmg); - gui_log("You take %d damage from the explosion", dmg); - } - } - } -} - bool monster_move(Monster *m, RoomMatrix *rm, Map *map) { @@ -644,6 +673,9 @@ monster_render(Monster *m, Camera *cam) if (m->stats.hp <= 0) return; + if (m->behaviour == ASSASSIN && m->state.current != AGRESSIVE) + return; + sprite_render(m->sprite, cam); } @@ -653,6 +685,9 @@ monster_render_top_layer(Monster *m, Camera *cam) if (m->stats.hp <= 0) return; + if (m->behaviour == ASSASSIN && m->state.current != AGRESSIVE) + return; + if (m->stateIndicator.displayCount != 0) sprite_render(m->stateIndicator.sprite, cam); } @@ -664,6 +699,7 @@ monster_set_behaviour(Monster *m, MonsterBehaviour behaviour) switch (behaviour) { case HOSTILE: case GUERILLA: + case ASSASSIN: case SORCERER: case COWARD: case FIRE_DEMON: diff --git a/src/monster.h b/src/monster.h index e35d09c..da201fa 100644 --- a/src/monster.h +++ b/src/monster.h @@ -36,7 +36,8 @@ typedef enum { COWARD, SENTINEL, FIRE_DEMON, - SORCERER + SORCERER, + ASSASSIN } MonsterBehaviour; typedef enum {