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_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 {
|
||||
UP, DOWN, LEFT, RIGHT
|
||||
} Direction;
|
||||
|
|
|
@ -231,7 +231,7 @@ lua_checkstats(lua_State *L, int index)
|
|||
// Reset the stack
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,9 @@ monster_set_sprite_clip_for_current_state(Monster *m)
|
|||
case SLEEPING:
|
||||
m->stateIndicator.sprite->clip = CLIP16(16 * 10, 16 * 4);
|
||||
break;
|
||||
case STUNNED:
|
||||
m->stateIndicator.sprite->clip = CLIP16(16 * 13, 16 * 3);
|
||||
break;
|
||||
case SCANNING:
|
||||
m->stateIndicator.sprite->clip = CLIP16(16 * 13, 16 * 4);
|
||||
default:
|
||||
|
@ -64,6 +67,7 @@ monster_state_change(Monster *m, StateType newState)
|
|||
if (m->state.current == newState)
|
||||
return;
|
||||
|
||||
m->state.last = m->state.current;
|
||||
m->state.current = newState;
|
||||
m->state.stepsSinceChange = 0;
|
||||
|
||||
|
@ -72,12 +76,19 @@ monster_state_change(Monster *m, StateType newState)
|
|||
else
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
monster_behaviour_check_post_hit(Monster *m)
|
||||
{
|
||||
if (m->state.current == STUNNED)
|
||||
return;
|
||||
switch (m->behaviour) {
|
||||
case PACIFIST:
|
||||
case COWARD:
|
||||
|
@ -156,7 +167,9 @@ monster_create(void)
|
|||
0, // atk
|
||||
0, // def
|
||||
1, // speed
|
||||
1 // lvl
|
||||
1, // lvl
|
||||
false, // advantage
|
||||
false // disadvantage
|
||||
};
|
||||
|
||||
m->label = NULL;
|
||||
|
@ -350,6 +363,16 @@ monster_move(Monster *m, RoomMatrix *rm)
|
|||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
monster_set_stunned(Monster *m)
|
||||
{
|
||||
monster_state_change(m, STUNNED);
|
||||
}
|
||||
|
||||
void
|
||||
monster_destroy(Monster *m)
|
||||
{
|
||||
|
|
|
@ -43,11 +43,13 @@ typedef enum {
|
|||
SCARED,
|
||||
STATIONARY,
|
||||
SLEEPING,
|
||||
SCANNING
|
||||
SCANNING,
|
||||
STUNNED
|
||||
} StateType;
|
||||
|
||||
typedef struct {
|
||||
typedef struct State {
|
||||
StateType current;
|
||||
StateType last;
|
||||
unsigned int stepsSinceChange;
|
||||
} State;
|
||||
|
||||
|
@ -94,6 +96,9 @@ monster_drop_loot(Monster*, Map*, Player*);
|
|||
void
|
||||
monster_set_behaviour(Monster *, MonsterBehaviour behaviour);
|
||||
|
||||
void
|
||||
monster_set_stunned(Monster *m);
|
||||
|
||||
void
|
||||
monster_destroy(Monster*);
|
||||
|
||||
|
|
15
src/player.c
15
src/player.c
|
@ -35,11 +35,11 @@
|
|||
#include "actiontextbuilder.h"
|
||||
#include "animation.h"
|
||||
|
||||
#define ENGINEER_STATS { 12, 12, 5, 7, 2, 2, 1 }
|
||||
#define MAGE_STATS { 12, 12, 5, 7, 1, 2, 1 }
|
||||
#define PALADIN_STATS { 12, 12, 8, 9, 3, 1, 1 }
|
||||
#define ROGUE_STATS { 12, 12, 5, 7, 1, 2, 1 }
|
||||
#define WARRIOR_STATS { 12, 12, 8, 9, 3, 1, 1 }
|
||||
#define ENGINEER_STATS { 12, 12, 5, 7, 2, 2, 1, false, false }
|
||||
#define MAGE_STATS { 12, 12, 5, 7, 1, 2, 1, false, false }
|
||||
#define PALADIN_STATS { 12, 12, 8, 9, 3, 1, 1, false, false }
|
||||
#define ROGUE_STATS { 12, 12, 5, 7, 1, 2, 1, false, false }
|
||||
#define WARRIOR_STATS { 12, 12, 8, 9, 3, 1, 1, false, false }
|
||||
|
||||
static void
|
||||
player_levelup(Player *player)
|
||||
|
@ -428,8 +428,9 @@ player_create(class_t class, SDL_Renderer *renderer)
|
|||
m_strcpy(asset, 100, "Commissions/Warrior.png");
|
||||
player->stats = (Stats) WARRIOR_STATS;
|
||||
player->skills[0] = skill_create(FLURRY);
|
||||
player->skills[1] = skill_create(CHARGE);
|
||||
player->skills[2] = skill_create(DAGGER_THROW);
|
||||
player->skills[1] = skill_create(BASH);
|
||||
player->skills[2] = skill_create(CHARGE);
|
||||
player->skills[3] = skill_create(DAGGER_THROW);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "player.h"
|
||||
#include "item.h"
|
||||
#include "update_data.h"
|
||||
#include "defines.h"
|
||||
|
||||
static void
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
skill_sip_health_available(Player *player)
|
||||
{
|
||||
|
@ -316,6 +377,8 @@ skill_create(enum SkillType t)
|
|||
return create_charge();
|
||||
case DAGGER_THROW:
|
||||
return create_throw_dagger();
|
||||
case BASH:
|
||||
return create_bash();
|
||||
default:
|
||||
fatal("Unknown SkillType %u", (unsigned int) t);
|
||||
return NULL;
|
||||
|
|
|
@ -29,6 +29,7 @@ struct Player_t;
|
|||
|
||||
enum SkillType {
|
||||
FLURRY,
|
||||
BASH,
|
||||
CHARGE,
|
||||
DAGGER_THROW,
|
||||
SIP_HEALTH
|
||||
|
|
17
src/stats.c
17
src/stats.c
|
@ -25,6 +25,7 @@
|
|||
#include "stats.h"
|
||||
#include "random.h"
|
||||
#include "util.h"
|
||||
#include "defines.h"
|
||||
|
||||
unsigned int
|
||||
stats_fight(Stats *attacker, Stats *defender)
|
||||
|
@ -32,11 +33,23 @@ stats_fight(Stats *attacker, Stats *defender)
|
|||
int atkRoll, defRoll, dmgRoll;
|
||||
bool critical = false;
|
||||
|
||||
atkRoll = get_random(19) + 1;
|
||||
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;
|
||||
|
||||
if (atkRoll == 20)
|
||||
critical = true;
|
||||
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;
|
||||
|
||||
if (atkRoll >= defRoll) {
|
||||
|
|
|
@ -27,6 +27,8 @@ typedef struct Stats_t {
|
|||
int def; /* Defence rating */
|
||||
unsigned int speed; /* Speed */
|
||||
unsigned int lvl; /* Level */
|
||||
bool advantage;
|
||||
bool disadvantage;
|
||||
} Stats;
|
||||
|
||||
unsigned int
|
||||
|
|
Loading…
Reference in New Issue