From 6326a641117a23f8ad4e339e5a1eeec7b3da402b Mon Sep 17 00:00:00 2001 From: Linus Probert Date: Wed, 22 Aug 2018 13:13:54 +0200 Subject: [PATCH] Begins #42 Add boss 2 & 3 - Added "The cleric" for level 10. --- data/monstergen.lua | 24 +++++++++-------- src/main.c | 9 ++++--- src/monster.c | 62 +++++++++++++++++++++++++++++++++++++------ src/monster.h | 3 ++- src/object.c | 15 +++++++++++ src/object.h | 3 +++ src/particle_engine.c | 7 ++--- src/player.c | 2 +- src/stats.c | 5 ++-- 9 files changed, 101 insertions(+), 29 deletions(-) diff --git a/data/monstergen.lua b/data/monstergen.lua index 6331efe..b0f49d5 100644 --- a/data/monstergen.lua +++ b/data/monstergen.lua @@ -45,7 +45,8 @@ local behaviour = { guerilla = 3, coward = 4, sentinel = 5, - fire_demon = 6 + fire_demon = 6, + sorcerer = 7 } local stats = { @@ -93,17 +94,17 @@ local stats = { }, boss = { hp = 60, - dmg = 4, + dmg = 3, atk = 1, def = 0, speed = 1 }, platino = { - hp = 60, - dmg = 60, - atk = 60, - def = 60, - speed = 3 + hp = 30, + dmg = 0, + atk = 0, + def = 0, + speed = 2 } } @@ -212,7 +213,7 @@ local orcs = { { stats.orc, 48, 4*16, "An Orc Sentry", behaviour.sentinel }, { 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 Pyro", behaviour.fire_demon }, + { stats.orc, 96, 4*16, "An Orc Pyro", behaviour.fire_demon }, } for i=1,#orcs do orcs[i] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, orcs[i]) @@ -220,7 +221,7 @@ end local bosses = { { 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[2] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, bosses[2]) @@ -233,7 +234,8 @@ local platino = { 48, 12*16, "Platino", - behaviour.sentinel + behaviour.sentinel, + true } } @@ -303,7 +305,7 @@ function module.add_monsters_to_room(room, roomx, roomy) end function module.add_boss_to_room(room, roomx, roomy) - local boss = bosses[1] + local boss = bosses[CURRENT_LEVEL / 5] local success = false while not success do local rx = random(13) + 1 diff --git a/src/main.c b/src/main.c index 1aff808..d9a3102 100644 --- a/src/main.c +++ b/src/main.c @@ -304,7 +304,7 @@ static void startGame(void *unused) { UNUSED(unused); - cLevel = 1; + cLevel = 5; gGameState = PLAYING; if (gPlayer) player_destroy(gPlayer); @@ -626,10 +626,13 @@ check_next_level(void) if (tile->levelExit) { mixer_play_effect(NEXT_LEVEL); ++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); - else + } else { mixer_play_music(GAME_MUSIC0 + get_random(2)); + } resetGame(); } } diff --git a/src/monster.c b/src/monster.c index 6d27f87..264a3d9 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 SORCERER: case FIRE_DEMON: break; default: @@ -119,6 +120,7 @@ monster_behaviour_check_post_attack(Monster *m) { switch (m->behaviour) { case GUERILLA: + case SORCERER: case FIRE_DEMON: monster_state_change(m, SCARED); break; @@ -154,6 +156,7 @@ monster_behaviour_check(Monster *m, RoomMatrix *rm) { switch (m->behaviour) { case GUERILLA: + case SORCERER: case FIRE_DEMON: if (m->state.stepsSinceChange > 8 && 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 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); - Position origPos = m->sprite->pos; Position originalMPos = 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].monster = NULL; @@ -442,12 +480,19 @@ monster_move(Monster *m, RoomMatrix *rm, Map *map) } - if (!position_equals(&origPos, &m->sprite->pos) - && (rm->modifier->type == RMOD_TYPE_FIRE || m->behaviour == FIRE_DEMON)) { - Object *o = object_create_fire(); - o->sprite->pos = origPos; - o->damage *= m->stats.lvl; - linkedlist_push(&map->objects, o); + if (!position_equals(&origPos, &m->sprite->pos)) { + if (rm->modifier->type == RMOD_TYPE_FIRE || m->behaviour == FIRE_DEMON) { + Object *o = object_create_fire(); + o->sprite->pos = origPos; + o->damage *= m->stats.lvl; + 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++; @@ -542,7 +587,7 @@ monster_drop_loot(Monster *monster, Map *map, Player *player) 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); a->sprite->pos = monster->sprite->pos; linkedlist_append(&map->artifacts, a); @@ -613,6 +658,7 @@ monster_set_behaviour(Monster *m, MonsterBehaviour behaviour) switch (behaviour) { case HOSTILE: case GUERILLA: + case SORCERER: case COWARD: case FIRE_DEMON: m->state.current = AGRESSIVE; diff --git a/src/monster.h b/src/monster.h index 91ebd1b..e99a0fb 100644 --- a/src/monster.h +++ b/src/monster.h @@ -35,7 +35,8 @@ typedef enum { GUERILLA, COWARD, SENTINEL, - FIRE_DEMON + FIRE_DEMON, + SORCERER } MonsterBehaviour; typedef enum { diff --git a/src/object.c b/src/object.c index 3cd9098..c566432 100644 --- a/src/object.c +++ b/src/object.c @@ -49,6 +49,21 @@ object_create_fire() 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 object_render(Object *o, Camera *cam) { diff --git a/src/object.h b/src/object.h index 4ca2190..9011151 100644 --- a/src/object.h +++ b/src/object.h @@ -38,6 +38,9 @@ object_create(void); Object * object_create_fire(void); +Object * +object_create_green_gas(void); + void object_render(Object*, Camera*); diff --git a/src/particle_engine.c b/src/particle_engine.c index f776bd4..40d1d66 100644 --- a/src/particle_engine.c +++ b/src/particle_engine.c @@ -156,10 +156,10 @@ create_explosion(Position pos, Dimension dim, unsigned int c_count, ...) x = get_random(dim.width) + pos.x; y = get_random(dim.height) + pos.y; - xv = get_random(600) - 300; - yv = get_random(600) - 300; + xv = get_random(500) - 300; + yv = get_random(500) - 300; - lt = get_random(10); + lt = get_random(20); p = create_rect_particle(); 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->movetime = lt; p->lifetime = lt; + p->blend_mode = SDL_BLENDMODE_BLEND; p->color = colors[get_random((unsigned int) c_count-1)]; linkedlist_append(&engine->game_particles, p); } diff --git a/src/player.c b/src/player.c index 41f8558..1e9f6e3 100644 --- a/src/player.c +++ b/src/player.c @@ -531,7 +531,7 @@ player_hit(Player *p, unsigned int dmg) Position pos = p->sprite->pos; pos.x += 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)); char msg[5]; m_sprintf(msg, 5, "-%d", dmg); diff --git a/src/stats.c b/src/stats.c index f713abc..8a5e393 100644 --- a/src/stats.c +++ b/src/stats.c @@ -67,10 +67,11 @@ stats_fight(Stats *attacker, Stats *defender) bool critical = false; int atkRoll = get_attack_roll(attacker); - if (atkRoll - attacker->atk == 20) - critical = true; int defRoll = get_defence_roll(defender); + if (atkRoll - attacker->atk == 20) + critical = get_attack_roll(attacker) > defRoll; + int dmgRoll = 0; if (atkRoll >= defRoll) { if (attacker->dmg > 0)