Adds monster bloodlust
- Introduces the beginning of an event listener system - Introduces fairies. When they are killed monsters in the room rage!
This commit is contained in:
parent
d749861477
commit
fd3a625249
|
@ -181,6 +181,7 @@ add_executable(breakhack
|
||||||
src/sprite
|
src/sprite
|
||||||
src/sprite_util
|
src/sprite_util
|
||||||
src/util
|
src/util
|
||||||
|
src/event
|
||||||
src/player
|
src/player
|
||||||
src/map
|
src/map
|
||||||
src/map_lua
|
src/map_lua
|
||||||
|
|
|
@ -169,6 +169,18 @@ for i=1,#misc do
|
||||||
misc[i] = concat({ texturePaths.misc0, texturePaths.misc1 }, misc[i])
|
misc[i] = concat({ texturePaths.misc0, texturePaths.misc1 }, misc[i])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local fairies = {
|
||||||
|
{ stats.misc, 0, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
{ stats.misc, 16, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
{ stats.misc, 32, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
{ stats.misc, 48, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
{ stats.misc, 64, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
{ stats.misc, 80, 48, "A Fairy", behaviour.pacifist },
|
||||||
|
}
|
||||||
|
for i=1,#fairies do
|
||||||
|
fairies[i] = concat({ texturePaths.humanoid0, texturePaths.humanoid1 }, fairies[i])
|
||||||
|
end
|
||||||
|
|
||||||
local reanimated = {
|
local reanimated = {
|
||||||
{ stats.undead, 0, 32, "A Skeleton", behaviour.normal },
|
{ stats.undead, 0, 32, "A Skeleton", behaviour.normal },
|
||||||
{ stats.undead, 48, 32, "A Black Skeleton", behaviour.normal },
|
{ stats.undead, 48, 32, "A Black Skeleton", behaviour.normal },
|
||||||
|
@ -273,7 +285,6 @@ local eastereggs = {
|
||||||
{ stats.misc, 0*16, 7*16, "Adnis, the Ranger", behaviour.passive },
|
{ stats.misc, 0*16, 7*16, "Adnis, the Ranger", behaviour.passive },
|
||||||
{ stats.misc, 7*16, 8*16, "Ti, the Mage", behaviour.passive },
|
{ stats.misc, 7*16, 8*16, "Ti, the Mage", behaviour.passive },
|
||||||
}
|
}
|
||||||
|
|
||||||
for i=1,#eastereggs do
|
for i=1,#eastereggs do
|
||||||
eastereggs[i] = concat({ texturePaths.player0, texturePaths.player1 }, eastereggs[i])
|
eastereggs[i] = concat({ texturePaths.player0, texturePaths.player1 }, eastereggs[i])
|
||||||
end
|
end
|
||||||
|
@ -360,6 +371,7 @@ if(CURRENT_LEVEL > 0) then
|
||||||
end
|
end
|
||||||
|
|
||||||
local addSpecialInLevel = random(100) == 1
|
local addSpecialInLevel = random(100) == 1
|
||||||
|
local addFairyToLevel = random(3) == 1;
|
||||||
|
|
||||||
local function add_monster_to_tile(room, roomx, roomy, rx, ry, monster)
|
local function add_monster_to_tile(room, roomx, roomy, rx, ry, monster)
|
||||||
local x = (roomx * 512) + rx * 32
|
local x = (roomx * 512) + rx * 32
|
||||||
|
@ -372,7 +384,8 @@ local function add_monster_to_tile(room, roomx, roomy, rx, ry, monster)
|
||||||
end
|
end
|
||||||
|
|
||||||
function module.add_monsters_to_room(room, roomx, roomy)
|
function module.add_monsters_to_room(room, roomx, roomy)
|
||||||
local addSpecial = addSpecialInLevel and random(5) == 1
|
local addSpecial = addSpecialInLevel and random(2) == 1
|
||||||
|
local addFairy = random(2) == 1
|
||||||
local count = random(3)
|
local count = random(3)
|
||||||
if (CURRENT_LEVEL > 3) then
|
if (CURRENT_LEVEL > 3) then
|
||||||
count = random(4)
|
count = random(4)
|
||||||
|
@ -387,6 +400,9 @@ function module.add_monsters_to_room(room, roomx, roomy)
|
||||||
addSpecialInLevel = false
|
addSpecialInLevel = false
|
||||||
addSpecial = false
|
addSpecial = false
|
||||||
add_monster_to_tile(room, roomx, roomy, rx, ry, eastereggs[random(#eastereggs)])
|
add_monster_to_tile(room, roomx, roomy, rx, ry, eastereggs[random(#eastereggs)])
|
||||||
|
elseif addFairyToLevel and addFairy then
|
||||||
|
addFairyToLevel = false
|
||||||
|
add_monster_to_tile(room, roomx, roomy, rx, ry, fairies[random(#fairies)])
|
||||||
else
|
else
|
||||||
add_monster_to_tile(room, roomx, roomy, rx, ry, enemies[random(#enemies)])
|
add_monster_to_tile(room, roomx, roomy, rx, ry, enemies[random(#enemies)])
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "event.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "linkedlist.h"
|
||||||
|
|
||||||
|
static LinkedList *callbacks = NULL;
|
||||||
|
|
||||||
|
void
|
||||||
|
event_register_listener(EventCallback cb)
|
||||||
|
{
|
||||||
|
linkedlist_append(&callbacks, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
event_clear_listeners(void)
|
||||||
|
{
|
||||||
|
while (callbacks)
|
||||||
|
linkedlist_pop(&callbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
event_trigger(Event *event)
|
||||||
|
{
|
||||||
|
LinkedList *cbs = callbacks;
|
||||||
|
while (cbs) {
|
||||||
|
((EventCallback) cbs->data)(event);
|
||||||
|
cbs = cbs->next;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* BreakHack - A dungeone crawler RPG
|
||||||
|
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
typedef enum EventType {
|
||||||
|
MONSTER_KILLED_EVENT
|
||||||
|
} EventType;
|
||||||
|
|
||||||
|
typedef struct MonsterKilledEvent {
|
||||||
|
EventType *type;
|
||||||
|
Player *player;
|
||||||
|
Monster *monster;
|
||||||
|
} MonsterKilledEvent;
|
||||||
|
|
||||||
|
typedef union Event {
|
||||||
|
EventType type;
|
||||||
|
MonsterKilledEvent monsterKilled;
|
||||||
|
} Event;
|
||||||
|
|
||||||
|
typedef void (*EventCallback)(Event*);
|
||||||
|
|
||||||
|
void
|
||||||
|
event_register_listener(EventCallback cb);
|
||||||
|
|
||||||
|
void
|
||||||
|
event_clear_listeners(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
event_trigger(Event *event);
|
20
src/main.c
20
src/main.c
|
@ -56,6 +56,7 @@
|
||||||
#include "gamecontroller.h"
|
#include "gamecontroller.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include "sprite_util.h"
|
#include "sprite_util.h"
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
#ifdef STEAM_BUILD
|
#ifdef STEAM_BUILD
|
||||||
#include "steam/steamworks_api_wrapper.h"
|
#include "steam/steamworks_api_wrapper.h"
|
||||||
|
@ -646,6 +647,22 @@ resetGame(void)
|
||||||
repopulate_roommatrix();
|
repopulate_roommatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_event_callback(Event *event)
|
||||||
|
{
|
||||||
|
if (event->type == MONSTER_KILLED_EVENT) {
|
||||||
|
if (strcmp(event->monsterKilled.monster->label, "A Fairy") == 0) {
|
||||||
|
LinkedList *monsters = gMap->monsters;
|
||||||
|
while (monsters) {
|
||||||
|
Monster *monster = monsters->data;
|
||||||
|
monsters = monsters->next;
|
||||||
|
if (position_in_room(&monster->sprite->pos, &gMap->currentRoom))
|
||||||
|
monster_set_bloodlust(monster, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
init(void)
|
init(void)
|
||||||
{
|
{
|
||||||
|
@ -668,6 +685,8 @@ init(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event_register_listener(on_event_callback);
|
||||||
|
|
||||||
settings_init();
|
settings_init();
|
||||||
hiscore_init();
|
hiscore_init();
|
||||||
initMainMenu();
|
initMainMenu();
|
||||||
|
@ -1333,6 +1352,7 @@ void close(void)
|
||||||
#endif // STEAM_BUILD
|
#endif // STEAM_BUILD
|
||||||
|
|
||||||
gamecontroller_close();
|
gamecontroller_close();
|
||||||
|
event_clear_listeners();
|
||||||
SDL_DestroyRenderer(gRenderer);
|
SDL_DestroyRenderer(gRenderer);
|
||||||
SDL_DestroyWindow(gWindow);
|
SDL_DestroyWindow(gWindow);
|
||||||
gWindow = NULL;
|
gWindow = NULL;
|
||||||
|
|
|
@ -265,6 +265,7 @@ monster_create(void)
|
||||||
m->stateIndicator.shownOnPlayerRoomEnter = false;
|
m->stateIndicator.shownOnPlayerRoomEnter = false;
|
||||||
m->state.forceCount = 0;
|
m->state.forceCount = 0;
|
||||||
m->boss = false;
|
m->boss = false;
|
||||||
|
m->bloodlust = false;
|
||||||
monster_set_behaviour(m, NORMAL);
|
monster_set_behaviour(m, NORMAL);
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
@ -697,6 +698,12 @@ monster_drop_loot(Monster *monster, Map *map, Player *player)
|
||||||
linkedlist_append(&map->items, treasure);
|
linkedlist_append(&map->items, treasure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(monster->label, "A Fairy") == 0) {
|
||||||
|
Item *treasure = item_builder_build_treasure(PLATINUM, 3 * monster->stats.lvl);
|
||||||
|
treasure->sprite->pos = monsterTilePos;
|
||||||
|
linkedlist_append(&map->items, treasure);
|
||||||
|
}
|
||||||
|
|
||||||
if (monster->stats.lvl > 2 && get_random(29) == 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 = monsterTilePos;
|
a->sprite->pos = monsterTilePos;
|
||||||
|
@ -748,6 +755,13 @@ monster_render(Monster *m, Camera *cam)
|
||||||
if (m->stats.hp <= 0)
|
if (m->stats.hp <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (m->bloodlust) {
|
||||||
|
Position pos = m->sprite->pos;
|
||||||
|
pos.x += 6;
|
||||||
|
pos.y += 6;
|
||||||
|
particle_engine_sparkle(pos, DIM(20, 20), C_RED, false);
|
||||||
|
}
|
||||||
|
|
||||||
sprite_render(m->sprite, cam);
|
sprite_render(m->sprite, cam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,6 +846,35 @@ monster_push(Monster *m, Player *p, RoomMatrix *rm, Vector2d direction)
|
||||||
player_monster_kill_check(p, m);
|
player_monster_kill_check(p, m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
monster_set_bloodlust(Monster *m, bool bloodlust)
|
||||||
|
{
|
||||||
|
if (m->bloodlust == bloodlust || m->stats.hp <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m->bloodlust = bloodlust;
|
||||||
|
if (bloodlust) {
|
||||||
|
gui_log("%s rages with bloodlust", m->label);
|
||||||
|
monster_set_behaviour(m, HOSTILE);
|
||||||
|
m->stats.advantage = true;
|
||||||
|
m->stats.atk += 2;
|
||||||
|
m->stats.def += 2;
|
||||||
|
m->stats.dmg += 2;
|
||||||
|
m->stats.hp += 10;
|
||||||
|
m->stats.maxhp += 10;
|
||||||
|
} else {
|
||||||
|
gui_log("%s calms down from it's bloodlust", m->label);
|
||||||
|
monster_set_behaviour(m, NORMAL);
|
||||||
|
m->stats.advantage = false;
|
||||||
|
m->stats.atk -= 2;
|
||||||
|
m->stats.def -= 2;
|
||||||
|
m->stats.dmg -= 2;
|
||||||
|
m->stats.hp -= 10;
|
||||||
|
m->stats.maxhp -= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_destroy(Monster *m)
|
monster_destroy(Monster *m)
|
||||||
{
|
{
|
||||||
|
|
|
@ -73,6 +73,7 @@ typedef struct Monster {
|
||||||
MonsterBehaviour behaviour;
|
MonsterBehaviour behaviour;
|
||||||
unsigned int steps;
|
unsigned int steps;
|
||||||
bool boss;
|
bool boss;
|
||||||
|
bool bloodlust;
|
||||||
} Monster;
|
} Monster;
|
||||||
|
|
||||||
Monster* monster_create(void);
|
Monster* monster_create(void);
|
||||||
|
@ -113,6 +114,9 @@ monster_push(Monster *, Player *, RoomMatrix*, Vector2d dir);
|
||||||
void
|
void
|
||||||
monster_reset_steps(Monster *m);
|
monster_reset_steps(Monster *m);
|
||||||
|
|
||||||
|
void
|
||||||
|
monster_set_bloodlust(Monster*, bool bloodlust);
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_destroy(Monster*);
|
monster_destroy(Monster*);
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "animation.h"
|
#include "animation.h"
|
||||||
#include "trap.h"
|
#include "trap.h"
|
||||||
#include "gamecontroller.h"
|
#include "gamecontroller.h"
|
||||||
|
#include "event.h"
|
||||||
|
|
||||||
#ifdef STEAM_BUILD
|
#ifdef STEAM_BUILD
|
||||||
#include "steam/steamworks_api_wrapper.h"
|
#include "steam/steamworks_api_wrapper.h"
|
||||||
|
@ -610,6 +611,12 @@ player_monster_kill_check(Player *player, Monster *monster)
|
||||||
if (strcmp("The Trader", monster->label) == 0) {
|
if (strcmp("The Trader", monster->label) == 0) {
|
||||||
player->stateData.shopOwnerKiller = true;
|
player->stateData.shopOwnerKiller = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Event event;
|
||||||
|
event.type = MONSTER_KILLED_EVENT;
|
||||||
|
event.monsterKilled.monster = monster;
|
||||||
|
event.monsterKilled.player = player;
|
||||||
|
event_trigger(&event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue