Better labels, more treasure

This commit is contained in:
Linus_Probert 2018-01-25 10:45:05 +01:00
parent 574e34ce4b
commit 969af2f8c2
13 changed files with 201 additions and 63 deletions

View File

@ -46,39 +46,39 @@ local state = {
local enemies = {
-- PESTS
{ texturePaths.pest0, texturePaths.pest1, 0, 0, "Beetle" },
{ texturePaths.pest0, texturePaths.pest1, 16, 0, "Beetle" },
{ texturePaths.pest0, texturePaths.pest1, 32, 0, "Beetle" },
{ texturePaths.pest0, texturePaths.pest1, 48, 0, "Beetle" },
{ texturePaths.pest0, texturePaths.pest1, 64, 0, "Large Grub" },
{ texturePaths.pest0, texturePaths.pest1, 80, 0, "Small Grub" },
{ texturePaths.pest0, texturePaths.pest1, 96, 0, "Slim Worm" },
{ texturePaths.pest0, texturePaths.pest1, 112, 0, "Fat Worm" },
{ texturePaths.pest0, texturePaths.pest1, 0, 0, "A Beetle" },
{ texturePaths.pest0, texturePaths.pest1, 16, 0, "A Beetle" },
{ texturePaths.pest0, texturePaths.pest1, 32, 0, "A Beetle" },
{ texturePaths.pest0, texturePaths.pest1, 48, 0, "A Beetle" },
{ texturePaths.pest0, texturePaths.pest1, 64, 0, "A Large Grub" },
{ texturePaths.pest0, texturePaths.pest1, 80, 0, "A Small Grub" },
{ texturePaths.pest0, texturePaths.pest1, 96, 0, "A Slim Worm" },
{ texturePaths.pest0, texturePaths.pest1, 112, 0, "A Fat Worm" },
--{ texturePaths.pest0, texturePaths.pest1, 0, 16, "Female Dragonfly" },
{ texturePaths.pest0, texturePaths.pest1, 16, 16, "Fly" },
{ texturePaths.pest0, texturePaths.pest1, 32, 16, "Larva" },
{ texturePaths.pest0, texturePaths.pest1, 48, 16, "Moth" },
{ texturePaths.pest0, texturePaths.pest1, 16, 16, "A Fly" },
{ texturePaths.pest0, texturePaths.pest1, 32, 16, "A Larva" },
{ texturePaths.pest0, texturePaths.pest1, 48, 16, "A Moth" },
--{ texturePaths.pest0, texturePaths.pest1, 64, 16 },
{ texturePaths.pest0, texturePaths.pest1, 80, 16, "Gnat" },
{ texturePaths.pest0, texturePaths.pest1, 80, 16, "A Gnat" },
{ texturePaths.pest0, texturePaths.pest1, 0, 32, "Small Spider" },
{ texturePaths.pest0, texturePaths.pest1, 16, 32, "Medium Spider" },
{ texturePaths.pest0, texturePaths.pest1, 32, 32, "Large Spider" },
{ texturePaths.pest0, texturePaths.pest1, 48, 32, "Small Scorpion" },
{ texturePaths.pest0, texturePaths.pest1, 64, 32, "Medium Scorpion" },
{ texturePaths.pest0, texturePaths.pest1, 80, 32, "Large Scorpion" },
{ texturePaths.pest0, texturePaths.pest1, 0, 32, "A Small Spider" },
{ texturePaths.pest0, texturePaths.pest1, 16, 32, "A Medium Spider" },
{ texturePaths.pest0, texturePaths.pest1, 32, 32, "A Large Spider" },
{ texturePaths.pest0, texturePaths.pest1, 48, 32, "A Small Scorpion" },
{ texturePaths.pest0, texturePaths.pest1, 64, 32, "A Medium Scorpion" },
{ texturePaths.pest0, texturePaths.pest1, 80, 32, "A Large Scorpion" },
{ texturePaths.pest0, texturePaths.pest1, 0, 48, "Slug" },
{ texturePaths.pest0, texturePaths.pest1, 16, 48, "Large Slug" },
{ texturePaths.pest0, texturePaths.pest1, 0, 48, "A Slug" },
{ texturePaths.pest0, texturePaths.pest1, 16, 48, "A Large Slug" },
--{ texturePaths.pest0, texturePaths.pest1, 32, 48 },
{ texturePaths.pest0, texturePaths.pest1, 48, 48, "Red Slug" },
{ texturePaths.pest0, texturePaths.pest1, 64, 48, "Large Red Slug" },
{ texturePaths.pest0, texturePaths.pest1, 48, 48, "A Red Slug" },
{ texturePaths.pest0, texturePaths.pest1, 64, 48, "A Large Red Slug" },
{ texturePaths.pest0, texturePaths.pest1, 0, 64, "Giant Brown Ant" },
{ texturePaths.pest0, texturePaths.pest1, 16, 64, "Giant Black Ant" },
{ texturePaths.pest0, texturePaths.pest1, 32, 64, "Giant Gold Ant" },
{ texturePaths.pest0, texturePaths.pest1, 48, 64, "Giant Silver Ant" },
{ texturePaths.pest0, texturePaths.pest1, 0, 64, "A Giant Brown Ant" },
{ texturePaths.pest0, texturePaths.pest1, 16, 64, "A Giant Black Ant" },
{ texturePaths.pest0, texturePaths.pest1, 32, 64, "A Giant Gold Ant" },
{ texturePaths.pest0, texturePaths.pest1, 48, 64, "A Giant Silver Ant" },
--{ texturePaths.pest0, texturePaths.pest1, 0, 80 },
--{ texturePaths.pest0, texturePaths.pest1, 16, 80 },
@ -113,10 +113,10 @@ local enemies = {
--{ 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, 32, "Skeleton", state.passive, state.agressive };
{ texturePaths.undead0, texturePaths.undead1, 16, 32, "Umber Skeleton", state.passive, state.agressive };
{ texturePaths.undead0, texturePaths.undead1, 32, 32, "Caustic Skeleton", state.passive, state.agressive };
{ texturePaths.undead0, texturePaths.undead1, 48, 32, "Black Skeleton", state.passive, state.agressive };
{ texturePaths.undead0, texturePaths.undead1, 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, 48, 32, "A Black Skeleton", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 64, 32, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 80, 32, "", state.passive, state.agressive };
--{ texturePaths.undead0, texturePaths.undead1, 96, 32, "", state.passive, state.agressive };

View File

@ -8,6 +8,8 @@ item_create(void)
Item *item = ec_malloc(sizeof(Item));
item->sprite = NULL;
item->collected = false;
m_strcpy(item->label, 50, "");
item->value = 0.0;
item->effect = NULL;
return item;
}

View File

@ -11,6 +11,8 @@
typedef struct Item_t {
Sprite *sprite;
bool collected;
char label[50];
double value;
void (*effect)(struct Item_t *, Player *);
} Item;

View File

@ -36,44 +36,114 @@ load_texture(const char *path)
}
static void
add_health(Item *item, Player *player)
eat_flesh(Item *item, Player *player)
{
UNUSED(item);
int original_hp = player->stats.hp;
player->stats.hp += 2;
player->stats.hp += item->value;
if (player->stats.hp > player->stats.maxhp)
player->stats.hp = player->stats.maxhp;
gui_log("You gained %d health", player->stats.hp - original_hp);
gui_log("You eat some foul meat and gain %d health", player->stats.hp - original_hp);
}
static void
drink_health(Item *item, Player *player)
{
int original_hp = player->stats.hp;
player->stats.hp += item->value;
if (player->stats.hp > player->stats.maxhp)
player->stats.hp = player->stats.maxhp;
gui_log("You drink a health potion and gain %d health", player->stats.hp - original_hp);
}
static Item *
create_health(void)
create_item(const char *path, SDL_Rect clip, void (*cb)(Item*, Player*))
{
Texture *t;
Item *item;
item = item_create();
t = load_texture("assets/Items/Potion.png");
t = load_texture(path);
item->sprite = sprite_create();
sprite_set_texture(item->sprite, t, 0);
item->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 };
item->effect = &add_health;
item->sprite->clip = clip;
item->effect = cb;
return item;
}
static void
pickup_gold(Item *item, Player *player)
{
player->gold += item->value;
gui_log("You pick up %s", &item->label);
}
static Item *
create_treasure(void)
{
unsigned int value = rand() % TREASURE_COUNT;
double amt = (unsigned int) rand() % 40;
char label[50];
SDL_Rect clip = { 0, 0, 16, 16 };
switch (value) {
case COPPER:
m_sprintf(&label[0], 50, "%d copper", amt);
amt /= 100;
break;
case SILVER:
m_sprintf(&label[0], 50, "%d silver", amt);
clip.x = 48;
amt /= 10;
break;
case GOLD:
m_sprintf(&label[0], 50, "%d gold", amt);
clip.y = 16;
break;
case PLATINUM:
m_sprintf(&label[0], 50, "%d platinum", amt);
clip.x = 48;
clip.y = 16;
amt *= 10;
break;
default:
break;
}
if (amt > 15 && amt < 30)
clip.x += 16;
else if (amt <= 15)
clip.x += 32;
Item *item = create_item("assets/Items/Money.png", clip, &pickup_gold);
m_strcpy(item->label, 50, label);
item->value = amt;
return item;
}
Item *
item_builder_build_item(ItemKey key)
{
static const char *path_flesh = "assets/Items/Flesh.png";
static const char *path_potion = "assets/Items/Potion.png";
check_builder();
Item *item = NULL;
switch (key) {
case TREASURE:
item = create_treasure();
break;
case FLESH:
item = create_item(path_flesh, (SDL_Rect) { 0, 0, 16, 16 }, &eat_flesh);
item->value = 1;
break;
case HEALTH:
item = create_health();
item = create_item(path_potion, (SDL_Rect) { 0, 0, 16, 16 }, &drink_health);
item->value = 1 + (rand() % 2);
break;
default:
fatal("in item_builder_build() : Unhandled item key %d", key);

View File

@ -10,7 +10,18 @@ typedef struct {
} ItemBuilder;
typedef enum {
HEALTH
COPPER,
SILVER,
GOLD,
PLATINUM,
TREASURE_COUNT
} Treasure;
typedef enum {
TREASURE,
FLESH,
HEALTH,
ITEM_COUNT
} ItemKey;
void

View File

@ -106,13 +106,12 @@ map_clear_dead_monsters(Map *map)
else
last->next = current->next;
// TODO(Linus): We should really move this code somewhere else, perhaps to monster.c?
// Create a health drop
Monster *monster = current->data;
Item *item = item_builder_build_item(HEALTH);
item->sprite->pos = monster->sprite->pos;
// Loot drops
Item *item = monster_drop_loot(monster);
if (item)
linkedlist_append(&map->items, item);
gui_log("%s dropped a health potion", monster->label);
monster_destroy(monster);
current->data = NULL;

View File

@ -207,8 +207,10 @@ l_add_monster(lua_State *L)
monster->state.normal = nstate;
monster->state.challenge = cstate;
monster->state.current = nstate;
if (strlen(label))
if (strlen(label)) {
monster->label = label;
monster->lclabel = to_lower(label);
}
map_add_monster(map, monster);

View File

@ -1,11 +1,14 @@
#include <stdlib.h>
#include <assert.h>
#include "monster.h"
#include "util.h"
#include "player.h"
#include "monster.h"
#include "random.h"
#include "gui.h"
#include "item.h"
#include "item_builder.h"
static void
monster_load_texts(Monster *m, SDL_Renderer *renderer)
@ -36,6 +39,7 @@ monster_create(SDL_Renderer *renderer)
m->state.challenge = AGRESSIVE;
m->state.current = m->state.normal;
m->label = NULL;
m->lclabel = NULL;
monster_load_texts(m, renderer);
@ -69,9 +73,9 @@ has_collided(Monster *monster, RoomMatrix *matrix)
player_hit(space->player, dmg);
if (dmg > 0)
gui_log("Monster '%s' hit you for %u damage", monster->label, dmg);
gui_log("%s hit you for %u damage", monster->label, dmg);
else
gui_log("Monster '%s' missed you", monster->label);
gui_log("%s missed you", monster->label);
}
return space->occupied;
@ -234,6 +238,23 @@ monster_hit(Monster *monster, unsigned int dmg)
monster->state.current = monster->state.challenge;
}
Item *
monster_drop_loot(Monster *monster)
{
static unsigned int drop_chance = 3;
unsigned int drop;
if ((rand() % drop_chance) != 0)
return NULL;
drop = rand() % ITEM_COUNT;
Item *item = item_builder_build_item(drop);
item->sprite->pos = monster->sprite->pos;
gui_log("%s dropped something", monster->label);
return item;
}
void
monster_render(Monster *m, Camera *cam)
{
@ -250,6 +271,8 @@ monster_destroy(Monster *m)
sprite_destroy(m->sprite);
if (m->label)
free(m->label);
if (m->lclabel)
free(m->lclabel);
if (m->hitText)
actiontext_destroy(m->hitText);
if (m->missText)

View File

@ -16,6 +16,7 @@ typedef struct {
typedef struct Monster_t {
char *label;
char *lclabel;
Sprite *sprite;
ActionText *hitText;
ActionText *missText;
@ -33,6 +34,8 @@ void monster_render(Monster*, Camera*);
void monster_hit(Monster*, unsigned int dmg);
Item *monster_drop_loot(Monster*);
void monster_destroy(Monster*);
#endif // MONSTER_H_

View File

@ -20,7 +20,8 @@ has_collided(Player *player, RoomMatrix *matrix)
bool collided = false;
Position roomCoord = position_to_room_coords(&player->sprite->pos);
if (roomCoord.x != matrix->roomPos.x || roomCoord.y != matrix->roomPos.y) {
if (roomCoord.x != matrix->roomPos.x
|| roomCoord.y != matrix->roomPos.y) {
return collided;
}
@ -39,16 +40,18 @@ has_collided(Player *player, RoomMatrix *matrix)
player->misses += 1;
if (hit > 0)
gui_log("You hit '%s' for %u damage", space->monster->label, hit);
gui_log("You hit %s for %u damage",
space->monster->lclabel, hit);
else
gui_log("You missed '%s'", space->monster->label);
gui_log("You missed %s", space->monster->lclabel);
if (space->monster->stats.hp <= 0) {
// TODO(Linus): This needs some love later on.
player->kills += 1;
player->xp += 10;
gui_log("You killed '%s' and gained %d xp", space->monster->label, 10);
gui_log("You killed %s and gained %d xp",
space->monster->lclabel, 10);
}
} else if (collided) {
gui_log("Ouch! There is something in the way");
@ -177,6 +180,7 @@ player_create(class_t class, SDL_Renderer *renderer)
player->hits = 0;
player->kills = 0;
player->misses = 0;
player->gold = 0;
char asset[100];
switch (class) {
@ -244,6 +248,7 @@ player_print(Player *p)
debug("--------=== <[ Player Stats ]> ===--------");
debug("HP: %d", p->stats.hp);
debug("Level: %u\tXP:\t%u", p->stats.lvl, p->xp);
debug("Gold: %.2f", p->gold);
debug("Hits: %u\tMisses:\t%u", p->hits, p->misses);
debug("Kills: %u", p->kills);
debug("Steps: %u", p->total_steps);

View File

@ -21,6 +21,7 @@ typedef struct Player_t {
unsigned int hits;
unsigned int kills;
unsigned int misses;
double gold;
void (*handle_event)(struct Player_t*, RoomMatrix*, SDL_Event*);
} Player;

View File

@ -3,6 +3,7 @@
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <ctype.h>
#include "defines.h"
@ -140,3 +141,19 @@ timestamp(char *tstamp, size_t sz)
free(tm_info);
#endif // _MSC_VER
}
char *
to_lower(const char *str)
{
char *lcstr;
unsigned int i;
lcstr = ec_malloc((strlen(str) + 1) * sizeof(char));
for (i = 0; i < strlen(str); ++i) {
lcstr[i] = tolower(str[i]);
}
lcstr[i] = '\0';
return lcstr;
}

View File

@ -28,4 +28,7 @@ m_sprintf(char *dest, size_t destsz, const char *format, ...);
void
timestamp(char *tstamp, size_t sz);
char *
to_lower(const char *str);
#endif // UTIL_H_