Adds the bash skill and the stunned state. Stunned enemies have disadvantage while stunned.
This commit is contained in:
parent
72772358bd
commit
9fe2edee85
Binary file not shown.
Before Width: | Height: | Size: 848 B After Width: | Height: | Size: 5.1 KiB |
|
@ -68,6 +68,9 @@
|
||||||
#define C_YELLOW (SDL_Color) { 255, 255, 0, 255 }
|
#define C_YELLOW (SDL_Color) { 255, 255, 0, 255 }
|
||||||
#define C_BLACK (SDL_Color) { 0, 0, 0, 255 }
|
#define C_BLACK (SDL_Color) { 0, 0, 0, 255 }
|
||||||
|
|
||||||
|
#define max(a, b) (a > b ? a : b)
|
||||||
|
#define min(a, b) (a < b ? a : b)
|
||||||
|
|
||||||
typedef enum Direction_t {
|
typedef enum Direction_t {
|
||||||
UP, DOWN, LEFT, RIGHT
|
UP, DOWN, LEFT, RIGHT
|
||||||
} Direction;
|
} Direction;
|
||||||
|
|
|
@ -231,7 +231,7 @@ lua_checkstats(lua_State *L, int index)
|
||||||
// Reset the stack
|
// Reset the stack
|
||||||
lua_pop(L, 6);
|
lua_pop(L, 6);
|
||||||
|
|
||||||
Stats stats = { hp, hp, dmg, atk, def, speed, 1 };
|
Stats stats = { hp, hp, dmg, atk, def, speed, 1, false, false };
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,9 @@ monster_set_sprite_clip_for_current_state(Monster *m)
|
||||||
case SLEEPING:
|
case SLEEPING:
|
||||||
m->stateIndicator.sprite->clip = CLIP16(16 * 10, 16 * 4);
|
m->stateIndicator.sprite->clip = CLIP16(16 * 10, 16 * 4);
|
||||||
break;
|
break;
|
||||||
|
case STUNNED:
|
||||||
|
m->stateIndicator.sprite->clip = CLIP16(16 * 13, 16 * 3);
|
||||||
|
break;
|
||||||
case SCANNING:
|
case SCANNING:
|
||||||
m->stateIndicator.sprite->clip = CLIP16(16 * 13, 16 * 4);
|
m->stateIndicator.sprite->clip = CLIP16(16 * 13, 16 * 4);
|
||||||
default:
|
default:
|
||||||
|
@ -64,6 +67,7 @@ monster_state_change(Monster *m, StateType newState)
|
||||||
if (m->state.current == newState)
|
if (m->state.current == newState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
m->state.last = m->state.current;
|
||||||
m->state.current = newState;
|
m->state.current = newState;
|
||||||
m->state.stepsSinceChange = 0;
|
m->state.stepsSinceChange = 0;
|
||||||
|
|
||||||
|
@ -72,12 +76,19 @@ monster_state_change(Monster *m, StateType newState)
|
||||||
else
|
else
|
||||||
m->stateIndicator.displayCount = 5;
|
m->stateIndicator.displayCount = 5;
|
||||||
|
|
||||||
|
if (newState == STUNNED)
|
||||||
|
m->stats.disadvantage = true;
|
||||||
|
else if (m->state.last == STUNNED)
|
||||||
|
m->stats.disadvantage = false;
|
||||||
|
|
||||||
monster_set_sprite_clip_for_current_state(m);
|
monster_set_sprite_clip_for_current_state(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
monster_behaviour_check_post_hit(Monster *m)
|
monster_behaviour_check_post_hit(Monster *m)
|
||||||
{
|
{
|
||||||
|
if (m->state.current == STUNNED)
|
||||||
|
return;
|
||||||
switch (m->behaviour) {
|
switch (m->behaviour) {
|
||||||
case PACIFIST:
|
case PACIFIST:
|
||||||
case COWARD:
|
case COWARD:
|
||||||
|
@ -156,7 +167,9 @@ monster_create(void)
|
||||||
0, // atk
|
0, // atk
|
||||||
0, // def
|
0, // def
|
||||||
1, // speed
|
1, // speed
|
||||||
1 // lvl
|
1, // lvl
|
||||||
|
false, // advantage
|
||||||
|
false // disadvantage
|
||||||
};
|
};
|
||||||
|
|
||||||
m->label = NULL;
|
m->label = NULL;
|
||||||
|
@ -350,6 +363,16 @@ monster_move(Monster *m, RoomMatrix *rm)
|
||||||
{
|
{
|
||||||
Position monsterRoomPos;
|
Position monsterRoomPos;
|
||||||
|
|
||||||
|
if (m->state.current == STUNNED) {
|
||||||
|
if (m->state.stepsSinceChange < 3) {
|
||||||
|
m->state.stepsSinceChange += 1;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
monster_state_change(m, m->state.last);
|
||||||
|
monster_behaviour_check_post_hit(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
monster_behaviour_check(m, rm);
|
monster_behaviour_check(m, rm);
|
||||||
|
|
||||||
monsterRoomPos = position_to_matrix_coords(&m->sprite->pos);
|
monsterRoomPos = position_to_matrix_coords(&m->sprite->pos);
|
||||||
|
@ -525,6 +548,12 @@ monster_set_behaviour(Monster *m, MonsterBehaviour behaviour)
|
||||||
monster_set_sprite_clip_for_current_state(m);
|
monster_set_sprite_clip_for_current_state(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
monster_set_stunned(Monster *m)
|
||||||
|
{
|
||||||
|
monster_state_change(m, STUNNED);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_destroy(Monster *m)
|
monster_destroy(Monster *m)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,11 +43,13 @@ typedef enum {
|
||||||
SCARED,
|
SCARED,
|
||||||
STATIONARY,
|
STATIONARY,
|
||||||
SLEEPING,
|
SLEEPING,
|
||||||
SCANNING
|
SCANNING,
|
||||||
|
STUNNED
|
||||||
} StateType;
|
} StateType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct State {
|
||||||
StateType current;
|
StateType current;
|
||||||
|
StateType last;
|
||||||
unsigned int stepsSinceChange;
|
unsigned int stepsSinceChange;
|
||||||
} State;
|
} State;
|
||||||
|
|
||||||
|
@ -94,6 +96,9 @@ monster_drop_loot(Monster*, Map*, Player*);
|
||||||
void
|
void
|
||||||
monster_set_behaviour(Monster *, MonsterBehaviour behaviour);
|
monster_set_behaviour(Monster *, MonsterBehaviour behaviour);
|
||||||
|
|
||||||
|
void
|
||||||
|
monster_set_stunned(Monster *m);
|
||||||
|
|
||||||
void
|
void
|
||||||
monster_destroy(Monster*);
|
monster_destroy(Monster*);
|
||||||
|
|
||||||
|
|
15
src/player.c
15
src/player.c
|
@ -35,11 +35,11 @@
|
||||||
#include "actiontextbuilder.h"
|
#include "actiontextbuilder.h"
|
||||||
#include "animation.h"
|
#include "animation.h"
|
||||||
|
|
||||||
#define ENGINEER_STATS { 12, 12, 5, 7, 2, 2, 1 }
|
#define ENGINEER_STATS { 12, 12, 5, 7, 2, 2, 1, false, false }
|
||||||
#define MAGE_STATS { 12, 12, 5, 7, 1, 2, 1 }
|
#define MAGE_STATS { 12, 12, 5, 7, 1, 2, 1, false, false }
|
||||||
#define PALADIN_STATS { 12, 12, 8, 9, 3, 1, 1 }
|
#define PALADIN_STATS { 12, 12, 8, 9, 3, 1, 1, false, false }
|
||||||
#define ROGUE_STATS { 12, 12, 5, 7, 1, 2, 1 }
|
#define ROGUE_STATS { 12, 12, 5, 7, 1, 2, 1, false, false }
|
||||||
#define WARRIOR_STATS { 12, 12, 8, 9, 3, 1, 1 }
|
#define WARRIOR_STATS { 12, 12, 8, 9, 3, 1, 1, false, false }
|
||||||
|
|
||||||
static void
|
static void
|
||||||
player_levelup(Player *player)
|
player_levelup(Player *player)
|
||||||
|
@ -428,8 +428,9 @@ player_create(class_t class, SDL_Renderer *renderer)
|
||||||
m_strcpy(asset, 100, "Commissions/Warrior.png");
|
m_strcpy(asset, 100, "Commissions/Warrior.png");
|
||||||
player->stats = (Stats) WARRIOR_STATS;
|
player->stats = (Stats) WARRIOR_STATS;
|
||||||
player->skills[0] = skill_create(FLURRY);
|
player->skills[0] = skill_create(FLURRY);
|
||||||
player->skills[1] = skill_create(CHARGE);
|
player->skills[1] = skill_create(BASH);
|
||||||
player->skills[2] = skill_create(DAGGER_THROW);
|
player->skills[2] = skill_create(CHARGE);
|
||||||
|
player->skills[3] = skill_create(DAGGER_THROW);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
#include "update_data.h"
|
#include "update_data.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
roommatrix_reset(RoomMatrix *m)
|
roommatrix_reset(RoomMatrix *m)
|
||||||
|
@ -152,25 +153,6 @@ void roommatrix_populate_from_map(RoomMatrix *rm, Map *m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Linus): These should probably be macros
|
|
||||||
#undef min
|
|
||||||
#ifndef min
|
|
||||||
static int
|
|
||||||
min(int a, int b)
|
|
||||||
{
|
|
||||||
return a > b ? b : a;
|
|
||||||
}
|
|
||||||
#endif // min
|
|
||||||
|
|
||||||
#undef max
|
|
||||||
#ifndef max
|
|
||||||
static int
|
|
||||||
max(int a, int b)
|
|
||||||
{
|
|
||||||
return a > b ? a : b;
|
|
||||||
}
|
|
||||||
#endif // max
|
|
||||||
|
|
||||||
void
|
void
|
||||||
roommatrix_add_lightsource(RoomMatrix *matrix, Position *pos)
|
roommatrix_add_lightsource(RoomMatrix *matrix, Position *pos)
|
||||||
{
|
{
|
||||||
|
|
63
src/skill.c
63
src/skill.c
|
@ -177,6 +177,67 @@ create_throw_dagger(void)
|
||||||
return skill;
|
return skill;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
skill_bash(Skill *skill, SkillData *data)
|
||||||
|
{
|
||||||
|
UNUSED (skill);
|
||||||
|
|
||||||
|
Position playerPos = position_to_matrix_coords(&data->player->sprite->pos);
|
||||||
|
Position targetPos = playerPos;
|
||||||
|
targetPos.x += (int) data->direction.x;
|
||||||
|
targetPos.y += (int) data->direction.y;
|
||||||
|
|
||||||
|
player_turn(data->player, &data->direction);
|
||||||
|
|
||||||
|
if (!position_in_roommatrix(&targetPos)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
animation_run(data->player->swordAnimation);
|
||||||
|
Monster *monster = data->matrix->spaces[targetPos.x][targetPos.y].monster;
|
||||||
|
mixer_play_effect(SWING1);
|
||||||
|
if (monster) {
|
||||||
|
gui_log("You bash %s with your shield", monster->lclabel);
|
||||||
|
unsigned int dmg = stats_fight(&data->player->stats, &monster->stats);
|
||||||
|
if (dmg > 0) {
|
||||||
|
gui_log("You hit for %u damage", dmg);
|
||||||
|
if (monster->stats.hp > 0) {
|
||||||
|
gui_log("%s seems dazed and confused", monster->label);
|
||||||
|
monster_set_stunned(monster);
|
||||||
|
}
|
||||||
|
mixer_play_effect(SWORD_HIT);
|
||||||
|
data->player->stat_data.hits += 1;
|
||||||
|
} else {
|
||||||
|
gui_log("You missed %s", monster->lclabel);
|
||||||
|
}
|
||||||
|
monster_hit(monster, dmg);
|
||||||
|
} else {
|
||||||
|
gui_log("You bash your shield at nothing");
|
||||||
|
}
|
||||||
|
player_monster_kill_check(data->player, monster);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Skill *
|
||||||
|
create_bash(void)
|
||||||
|
{
|
||||||
|
Texture *t = texturecache_add("Extras/Skills.png");
|
||||||
|
Sprite *s = sprite_create();
|
||||||
|
sprite_set_texture(s, t, 0);
|
||||||
|
s->dim = GAME_DIMENSION;
|
||||||
|
s->clip = CLIP32(96, 0);
|
||||||
|
s->fixed = true;
|
||||||
|
Skill *skill = create_default("Bash", s);
|
||||||
|
skill->levelcap = 3;
|
||||||
|
skill->instantUse = false;
|
||||||
|
skill->resetTime = 2;
|
||||||
|
skill->available = NULL;
|
||||||
|
skill->use = skill_bash;
|
||||||
|
skill->actionRequired = true;
|
||||||
|
return skill;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
skill_sip_health_available(Player *player)
|
skill_sip_health_available(Player *player)
|
||||||
{
|
{
|
||||||
|
@ -316,6 +377,8 @@ skill_create(enum SkillType t)
|
||||||
return create_charge();
|
return create_charge();
|
||||||
case DAGGER_THROW:
|
case DAGGER_THROW:
|
||||||
return create_throw_dagger();
|
return create_throw_dagger();
|
||||||
|
case BASH:
|
||||||
|
return create_bash();
|
||||||
default:
|
default:
|
||||||
fatal("Unknown SkillType %u", (unsigned int) t);
|
fatal("Unknown SkillType %u", (unsigned int) t);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -29,6 +29,7 @@ struct Player_t;
|
||||||
|
|
||||||
enum SkillType {
|
enum SkillType {
|
||||||
FLURRY,
|
FLURRY,
|
||||||
|
BASH,
|
||||||
CHARGE,
|
CHARGE,
|
||||||
DAGGER_THROW,
|
DAGGER_THROW,
|
||||||
SIP_HEALTH
|
SIP_HEALTH
|
||||||
|
|
15
src/stats.c
15
src/stats.c
|
@ -25,6 +25,7 @@
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
stats_fight(Stats *attacker, Stats *defender)
|
stats_fight(Stats *attacker, Stats *defender)
|
||||||
|
@ -32,11 +33,23 @@ stats_fight(Stats *attacker, Stats *defender)
|
||||||
int atkRoll, defRoll, dmgRoll;
|
int atkRoll, defRoll, dmgRoll;
|
||||||
bool critical = false;
|
bool critical = false;
|
||||||
|
|
||||||
|
if (attacker->advantage)
|
||||||
|
atkRoll = max(get_random(19), get_random(19)) + 1;
|
||||||
|
else if (attacker->disadvantage)
|
||||||
|
atkRoll = min(get_random(19), get_random(19)) + 1;
|
||||||
|
else
|
||||||
atkRoll = get_random(19) + 1;
|
atkRoll = get_random(19) + 1;
|
||||||
|
|
||||||
if (atkRoll == 20)
|
if (atkRoll == 20)
|
||||||
critical = true;
|
critical = true;
|
||||||
atkRoll += attacker->atk;
|
atkRoll += attacker->atk;
|
||||||
defRoll = (get_random(19) + 1) + defender->def;
|
|
||||||
|
if (defender->advantage)
|
||||||
|
defRoll = max(get_random(19), get_random(19)) + 1 + defender->def;
|
||||||
|
else if (defender->disadvantage)
|
||||||
|
defRoll = min(get_random(19), get_random(19)) + 1 + defender->def;
|
||||||
|
else
|
||||||
|
defRoll = get_random(19) + 1 + defender->def;
|
||||||
dmgRoll = 0;
|
dmgRoll = 0;
|
||||||
|
|
||||||
if (atkRoll >= defRoll) {
|
if (atkRoll >= defRoll) {
|
||||||
|
|
|
@ -27,6 +27,8 @@ typedef struct Stats_t {
|
||||||
int def; /* Defence rating */
|
int def; /* Defence rating */
|
||||||
unsigned int speed; /* Speed */
|
unsigned int speed; /* Speed */
|
||||||
unsigned int lvl; /* Level */
|
unsigned int lvl; /* Level */
|
||||||
|
bool advantage;
|
||||||
|
bool disadvantage;
|
||||||
} Stats;
|
} Stats;
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
|
|
Loading…
Reference in New Issue