Begins #42 Add boss 2 & 3

- Added "The cleric" for level 10.
This commit is contained in:
Linus Probert 2018-08-22 13:13:54 +02:00
parent f1b0045829
commit 6326a64111
9 changed files with 101 additions and 29 deletions

View File

@ -45,7 +45,8 @@ local behaviour = {
guerilla = 3, guerilla = 3,
coward = 4, coward = 4,
sentinel = 5, sentinel = 5,
fire_demon = 6 fire_demon = 6,
sorcerer = 7
} }
local stats = { local stats = {
@ -93,17 +94,17 @@ local stats = {
}, },
boss = { boss = {
hp = 60, hp = 60,
dmg = 4, dmg = 3,
atk = 1, atk = 1,
def = 0, def = 0,
speed = 1 speed = 1
}, },
platino = { platino = {
hp = 60, hp = 30,
dmg = 60, dmg = 0,
atk = 60, atk = 0,
def = 60, def = 0,
speed = 3 speed = 2
} }
} }
@ -212,7 +213,7 @@ local orcs = {
{ stats.orc, 48, 4*16, "An Orc Sentry", behaviour.sentinel }, { stats.orc, 48, 4*16, "An Orc Sentry", behaviour.sentinel },
{ stats.orc, 64, 4*16, "An Orc Brute", behaviour.guerilla }, { stats.orc, 64, 4*16, "An Orc Brute", behaviour.guerilla },
{ stats.orc, 80, 4*16, "An Orc Captain", behaviour.hostile }, { stats.orc, 80, 4*16, "An Orc Captain", behaviour.hostile },
{ stats.orc, 80, 4*16, "An Orc Pyro", behaviour.fire_demon }, { stats.orc, 96, 4*16, "An Orc Pyro", behaviour.fire_demon },
} }
for i=1,#orcs do for i=1,#orcs do
orcs[i] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, orcs[i]) orcs[i] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, orcs[i])
@ -220,7 +221,7 @@ end
local bosses = { local bosses = {
{ stats.boss, 16, 5*16, "The Hell Hound", behaviour.fire_demon, true }, { stats.boss, 16, 5*16, "The Hell Hound", behaviour.fire_demon, true },
{ stats.boss, 32, 23*16, "The Cleric", behaviour.sentinel, true }, { stats.boss, 16, 23*16, "The Cleric", behaviour.sorcerer, true },
} }
bosses[1] = concat({ texturePaths.dog0, texturePaths.dog1 }, bosses[1]) bosses[1] = concat({ texturePaths.dog0, texturePaths.dog1 }, bosses[1])
bosses[2] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, bosses[2]) bosses[2] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, bosses[2])
@ -233,7 +234,8 @@ local platino = {
48, 48,
12*16, 12*16,
"Platino", "Platino",
behaviour.sentinel behaviour.sentinel,
true
} }
} }
@ -303,7 +305,7 @@ function module.add_monsters_to_room(room, roomx, roomy)
end end
function module.add_boss_to_room(room, roomx, roomy) function module.add_boss_to_room(room, roomx, roomy)
local boss = bosses[1] local boss = bosses[CURRENT_LEVEL / 5]
local success = false local success = false
while not success do while not success do
local rx = random(13) + 1 local rx = random(13) + 1

View File

@ -304,7 +304,7 @@ static void
startGame(void *unused) startGame(void *unused)
{ {
UNUSED(unused); UNUSED(unused);
cLevel = 1; cLevel = 5;
gGameState = PLAYING; gGameState = PLAYING;
if (gPlayer) if (gPlayer)
player_destroy(gPlayer); player_destroy(gPlayer);
@ -626,10 +626,13 @@ check_next_level(void)
if (tile->levelExit) { if (tile->levelExit) {
mixer_play_effect(NEXT_LEVEL); mixer_play_effect(NEXT_LEVEL);
++cLevel; ++cLevel;
if (cLevel % 5 == 0) if (cLevel % 5 == 0) {
gui_log("You sense something powerful in the vicinity");
gui_event_message("Something powerful lurks in the dark");
mixer_play_music(BOSS_MUSIC0); mixer_play_music(BOSS_MUSIC0);
else } else {
mixer_play_music(GAME_MUSIC0 + get_random(2)); mixer_play_music(GAME_MUSIC0 + get_random(2));
}
resetGame(); resetGame();
} }
} }

View File

@ -106,6 +106,7 @@ monster_behaviour_check_post_hit(Monster *m)
monster_state_change(m, SCARED); monster_state_change(m, SCARED);
break; break;
case GUERILLA: case GUERILLA:
case SORCERER:
case FIRE_DEMON: case FIRE_DEMON:
break; break;
default: default:
@ -119,6 +120,7 @@ monster_behaviour_check_post_attack(Monster *m)
{ {
switch (m->behaviour) { switch (m->behaviour) {
case GUERILLA: case GUERILLA:
case SORCERER:
case FIRE_DEMON: case FIRE_DEMON:
monster_state_change(m, SCARED); monster_state_change(m, SCARED);
break; break;
@ -154,6 +156,7 @@ monster_behaviour_check(Monster *m, RoomMatrix *rm)
{ {
switch (m->behaviour) { switch (m->behaviour) {
case GUERILLA: case GUERILLA:
case SORCERER:
case FIRE_DEMON: case FIRE_DEMON:
if (m->state.stepsSinceChange > 8 if (m->state.stepsSinceChange > 8
&& m->state.current == SCARED) { && m->state.current == SCARED) {
@ -379,6 +382,33 @@ 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);
r->monster->stats.hp -= 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);
r->player->stats.hp -= dmg;
gui_log("You take %d damage from the explosion", dmg);
}
}
}
}
bool bool
monster_move(Monster *m, RoomMatrix *rm, Map *map) monster_move(Monster *m, RoomMatrix *rm, Map *map)
{ {
@ -395,10 +425,18 @@ monster_move(Monster *m, RoomMatrix *rm, Map *map)
} }
monster_behaviour_check(m, rm); monster_behaviour_check(m, rm);
Position origPos = m->sprite->pos; Position origPos = m->sprite->pos;
Position originalMPos = Position originalMPos =
position_to_matrix_coords(&m->sprite->pos); position_to_matrix_coords(&m->sprite->pos);
if (m->state.current == AGRESSIVE && m->behaviour == SORCERER) {
if (position_proximity(1, &originalMPos, &rm->playerRoomPos)) {
sorcerer_blast(m, rm);
monster_behaviour_check_post_attack(m);
return true;
}
}
rm->spaces[originalMPos.x][originalMPos.y].occupied = false; rm->spaces[originalMPos.x][originalMPos.y].occupied = false;
rm->spaces[originalMPos.x][originalMPos.y].monster = NULL; rm->spaces[originalMPos.x][originalMPos.y].monster = NULL;
@ -442,12 +480,19 @@ monster_move(Monster *m, RoomMatrix *rm, Map *map)
} }
if (!position_equals(&origPos, &m->sprite->pos) if (!position_equals(&origPos, &m->sprite->pos)) {
&& (rm->modifier->type == RMOD_TYPE_FIRE || m->behaviour == FIRE_DEMON)) { if (rm->modifier->type == RMOD_TYPE_FIRE || m->behaviour == FIRE_DEMON) {
Object *o = object_create_fire(); Object *o = object_create_fire();
o->sprite->pos = origPos; o->sprite->pos = origPos;
o->damage *= m->stats.lvl; o->damage *= m->stats.lvl;
linkedlist_push(&map->objects, o); linkedlist_push(&map->objects, o);
}
if (m->behaviour == SORCERER) {
Object *o = object_create_green_gas();
o->sprite->pos = origPos;
o->damage *= m->stats.lvl;
linkedlist_push(&map->objects, o);
}
} }
m->steps++; m->steps++;
@ -542,7 +587,7 @@ monster_drop_loot(Monster *monster, Map *map, Player *player)
linkedlist_append(&map->items, treasure); linkedlist_append(&map->items, treasure);
} }
if (monster->stats.lvl > 2 && get_random(19) == 0) { if (monster->stats.lvl > 2 && get_random(29) == 0) {
Artifact *a = artifact_create_random(player, 1); Artifact *a = artifact_create_random(player, 1);
a->sprite->pos = monster->sprite->pos; a->sprite->pos = monster->sprite->pos;
linkedlist_append(&map->artifacts, a); linkedlist_append(&map->artifacts, a);
@ -613,6 +658,7 @@ monster_set_behaviour(Monster *m, MonsterBehaviour behaviour)
switch (behaviour) { switch (behaviour) {
case HOSTILE: case HOSTILE:
case GUERILLA: case GUERILLA:
case SORCERER:
case COWARD: case COWARD:
case FIRE_DEMON: case FIRE_DEMON:
m->state.current = AGRESSIVE; m->state.current = AGRESSIVE;

View File

@ -35,7 +35,8 @@ typedef enum {
GUERILLA, GUERILLA,
COWARD, COWARD,
SENTINEL, SENTINEL,
FIRE_DEMON FIRE_DEMON,
SORCERER
} MonsterBehaviour; } MonsterBehaviour;
typedef enum { typedef enum {

View File

@ -49,6 +49,21 @@ object_create_fire()
return o; return o;
} }
Object *
object_create_green_gas()
{
Object *o = object_create();
Texture *t0 = texturecache_add("Objects/Effect0.png");
Texture *t1 = texturecache_add("Objects/Effect1.png");
sprite_set_texture(o->sprite, t0, 0);
sprite_set_texture(o->sprite, t1, 1);
o->sprite->dim = GAME_DIMENSION;
o->sprite->clip = CLIP16(32, 24*16);
o->damage = 3;
o->timeout = 3;
return o;
}
void void
object_render(Object *o, Camera *cam) object_render(Object *o, Camera *cam)
{ {

View File

@ -38,6 +38,9 @@ object_create(void);
Object * Object *
object_create_fire(void); object_create_fire(void);
Object *
object_create_green_gas(void);
void void
object_render(Object*, Camera*); object_render(Object*, Camera*);

View File

@ -156,10 +156,10 @@ create_explosion(Position pos, Dimension dim, unsigned int c_count, ...)
x = get_random(dim.width) + pos.x; x = get_random(dim.width) + pos.x;
y = get_random(dim.height) + pos.y; y = get_random(dim.height) + pos.y;
xv = get_random(600) - 300; xv = get_random(500) - 300;
yv = get_random(600) - 300; yv = get_random(500) - 300;
lt = get_random(10); lt = get_random(20);
p = create_rect_particle(); p = create_rect_particle();
p->particle.rect.pos = (Position) { x, y }; p->particle.rect.pos = (Position) { x, y };
@ -167,6 +167,7 @@ create_explosion(Position pos, Dimension dim, unsigned int c_count, ...)
p->velocity = (Vector2d) { (float) xv, (float) yv }; p->velocity = (Vector2d) { (float) xv, (float) yv };
p->movetime = lt; p->movetime = lt;
p->lifetime = lt; p->lifetime = lt;
p->blend_mode = SDL_BLENDMODE_BLEND;
p->color = colors[get_random((unsigned int) c_count-1)]; p->color = colors[get_random((unsigned int) c_count-1)];
linkedlist_append(&engine->game_particles, p); linkedlist_append(&engine->game_particles, p);
} }

View File

@ -531,7 +531,7 @@ player_hit(Player *p, unsigned int dmg)
Position pos = p->sprite->pos; Position pos = p->sprite->pos;
pos.x += 8; pos.x += 8;
pos.y += 8; pos.y += 8;
particle_engine_bloodspray(pos, (Dimension) { 8, 8 }, dmg); particle_engine_bloodspray(pos, DIM(8, 8), dmg);
mixer_play_effect(PLAYER_HIT0 + get_random(2)); mixer_play_effect(PLAYER_HIT0 + get_random(2));
char msg[5]; char msg[5];
m_sprintf(msg, 5, "-%d", dmg); m_sprintf(msg, 5, "-%d", dmg);

View File

@ -67,10 +67,11 @@ stats_fight(Stats *attacker, Stats *defender)
bool critical = false; bool critical = false;
int atkRoll = get_attack_roll(attacker); int atkRoll = get_attack_roll(attacker);
if (atkRoll - attacker->atk == 20)
critical = true;
int defRoll = get_defence_roll(defender); int defRoll = get_defence_roll(defender);
if (atkRoll - attacker->atk == 20)
critical = get_attack_roll(attacker) > defRoll;
int dmgRoll = 0; int dmgRoll = 0;
if (atkRoll >= defRoll) { if (atkRoll >= defRoll) {
if (attacker->dmg > 0) if (attacker->dmg > 0)