mirror of
https://gitlab.com/drummyfish/anarch.git
synced 2024-12-21 23:08:49 -05:00
Add monster table
This commit is contained in:
parent
b4ceb1603b
commit
8745a04952
54
constants.h
54
constants.h
@ -267,6 +267,56 @@
|
||||
#define SFG_HUD_BAR_HEIGHT \
|
||||
(SFG_FONT_CHARACTER_SIZE * SFG_FONT_SIZE_MEDIUM + SFG_HUD_MARGIN * 2 + 1)
|
||||
|
||||
// ----------------------------
|
||||
// monsters
|
||||
|
||||
#define SFG_MONSTER_ATTACK_MELEE 0
|
||||
#define SFG_MONSTER_ATTACK_FIREBALL 1
|
||||
#define SFG_MONSTER_ATTACK_BULLET 2
|
||||
#define SFG_MONSTER_ATTACK_FIREBALL_BULLET 3
|
||||
#define SFG_MONSTER_ATTACK_PLASMA 4
|
||||
#define SFG_MONSTER_ATTACK_EXPLODE 5
|
||||
|
||||
#define SFG_MONSTER_ATTRIBUTE(attackType,aggressivity0to255,health0to255,spriteSize0to3) \
|
||||
((uint16_t) ( \
|
||||
attackType | \
|
||||
((aggressivity0to255 / 8) << 3) | \
|
||||
(spriteSize0to3 << 8) | \
|
||||
((health0to255 / 4) << 10)))
|
||||
|
||||
#define SFG_GET_MONSTER_ATTACK_TYPE(monsterNumber) \
|
||||
(SFG_monsterAttributeTable[monsterNumber] & 0x0007)
|
||||
|
||||
#define SFG_GET_MONSTER_AGGRESSIVITY(monsterNumber) \
|
||||
(((SFG_monsterAttributeTable[monsterNumber] >> 3) & 0x1F) * 8)
|
||||
|
||||
#define SFG_GET_MONSTER_SPRITE_SIZE(monsterNumber) \
|
||||
((SFG_monsterAttributeTable[monsterNumber] >> 8) & 0x03)
|
||||
|
||||
#define SFG_GET_MONSTER_MAX_HEALTH(monsterNumber) \
|
||||
(((SFG_monsterAttributeTable[monsterNumber] >> 10) & 0x3F) * 4)
|
||||
|
||||
/**
|
||||
Table of monster attributes, each as a 16bit word in format:
|
||||
|
||||
MSB hhhhhhssaaaattt LSB
|
||||
|
||||
ttt: attack type
|
||||
aaaaa: aggressivity (frequence of attacks), 0 to 31
|
||||
ss: sprite size
|
||||
hhhhhh: health, 0 to 63
|
||||
*/
|
||||
uint16_t SFG_monsterAttributeTable[SFG_MONSTERS_TOTAL] =
|
||||
{
|
||||
/* spider */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_FIREBALL,40,120,3),
|
||||
/* destr. */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_FIREBALL_BULLET,50,130,3),
|
||||
/* warrior */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_MELEE,255,70,2),
|
||||
/* plasma */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_PLASMA,55,92,2),
|
||||
/* ender */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_FIREBALL_BULLET,75,255,4),
|
||||
/* turret */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_BULLET,32,50,2),
|
||||
/* explod. */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_EXPLODE,255,60,2)
|
||||
};
|
||||
|
||||
// ----------------------------
|
||||
// weapons and projectiles
|
||||
|
||||
@ -296,7 +346,7 @@
|
||||
/**
|
||||
Table of weapon attributes, each as a byte in format:
|
||||
|
||||
cccccfff
|
||||
MSB cccccfff LSB
|
||||
|
||||
fff: fire type
|
||||
ccccc: fire cooldown in frames, i.e. time after which the next shot can be
|
||||
@ -334,7 +384,7 @@ SFG_PROGRAM_MEMORY uint8_t SFG_weaponAttributeTable[SFG_WEAPONS_TOTAL] =
|
||||
/**
|
||||
Table of projectile attributes, each as a byte in format:
|
||||
|
||||
lllllsss
|
||||
MSB lllllsss LSB
|
||||
|
||||
fff: half speed in game squares per second
|
||||
lllll: eigth of frames to live
|
||||
|
5
levels.h
5
levels.h
@ -102,6 +102,11 @@ typedef struct
|
||||
#define SFG_LEVEL_ELEMENT_MONSTER_TURRET 0x50
|
||||
#define SFG_LEVEL_ELEMENT_MONSTER_EXPLODER 0x60
|
||||
|
||||
#define SFG_MONSTERS_TOTAL 7
|
||||
|
||||
#define SFG_MONSTER_TYPE_TO_INDEX(monsterType) \
|
||||
((monsterType) >> 4)
|
||||
|
||||
#define SFG_LEVEL_ELEMENT_TYPE_IS_MOSTER(t) (((t) & 0x0f) == 0)
|
||||
|
||||
typedef struct
|
||||
|
124
main.c
124
main.c
@ -947,7 +947,8 @@ void SFG_setAndInitLevel(const SFG_Level *level)
|
||||
&(SFG_currentLevel.monsterRecords[SFG_currentLevel.monsterRecordCount]);
|
||||
|
||||
monster->stateType = e->type | 0;
|
||||
monster->health = 100;
|
||||
monster->health = SFG_GET_MONSTER_MAX_HEALTH(SFG_MONSTER_TYPE_TO_INDEX(e->type));
|
||||
|
||||
monster->coords[0] = e->coords[0] * 4;
|
||||
monster->coords[1] = e->coords[1] * 4;
|
||||
|
||||
@ -992,7 +993,7 @@ void SFG_init()
|
||||
|
||||
SFG_backgroundScroll = 0;
|
||||
|
||||
SFG_setAndInitLevel(&SFG_level1);
|
||||
SFG_setAndInitLevel(&SFG_level0);
|
||||
|
||||
SFG_lastFrameTimeMs = SFG_getTimeMs();
|
||||
}
|
||||
@ -1034,6 +1035,9 @@ uint8_t SFG_launchProjectile(
|
||||
RCL_Unit offsetDistance
|
||||
)
|
||||
{
|
||||
if (type == SFG_PROJECTILE_NONE)
|
||||
return;
|
||||
|
||||
SFG_ProjectileRecord p;
|
||||
|
||||
p.type = type;
|
||||
@ -1249,20 +1253,25 @@ void SFG_monsterPerformAI(SFG_MonsterRecord *monster)
|
||||
{
|
||||
uint8_t state = SFG_MR_STATE(*monster);
|
||||
uint8_t type = SFG_MR_TYPE(*monster);
|
||||
uint8_t monsterNumber = SFG_MONSTER_TYPE_TO_INDEX(type);
|
||||
uint8_t attackType = SFG_GET_MONSTER_ATTACK_TYPE(monsterNumber);
|
||||
|
||||
int8_t coordAdd[2];
|
||||
|
||||
coordAdd[0] = 0;
|
||||
coordAdd[1] = 0;
|
||||
|
||||
uint8_t melee = (type == SFG_LEVEL_ELEMENT_MONSTER_WARRIOR) ||
|
||||
(type == SFG_LEVEL_ELEMENT_MONSTER_EXPLODER);
|
||||
uint8_t notRanged =
|
||||
(attackType == SFG_MONSTER_ATTACK_MELEE) ||
|
||||
(attackType == SFG_MONSTER_ATTACK_EXPLODE);
|
||||
|
||||
if ( // sometimes randomly change state
|
||||
(SFG_random() < SFG_AI_RANDOM_CHANGE_PROBABILITY) &&
|
||||
(type != SFG_LEVEL_ELEMENT_MONSTER_EXPLODER))
|
||||
if ( // sometimes randomly attack
|
||||
!notRanged &&
|
||||
(SFG_random() <
|
||||
SFG_GET_MONSTER_AGGRESSIVITY(SFG_MONSTER_TYPE_TO_INDEX(type)))
|
||||
)
|
||||
{
|
||||
if (!melee && (SFG_random() % 4 != 0))
|
||||
if (!notRanged && (SFG_random() % 4 != 0))
|
||||
{
|
||||
// attack
|
||||
|
||||
@ -1281,9 +1290,35 @@ void SFG_monsterPerformAI(SFG_MonsterRecord *monster)
|
||||
|
||||
dir = RCL_normalize(dir);
|
||||
|
||||
uint8_t projectile;
|
||||
|
||||
switch (SFG_GET_MONSTER_ATTACK_TYPE(monsterNumber))
|
||||
{
|
||||
case SFG_MONSTER_ATTACK_FIREBALL:
|
||||
projectile = SFG_PROJECTILE_FIREBALL;
|
||||
break;
|
||||
|
||||
case SFG_MONSTER_ATTACK_BULLET:
|
||||
projectile = SFG_PROJECTILE_BULLET;
|
||||
break;
|
||||
|
||||
case SFG_MONSTER_ATTACK_PLASMA:
|
||||
projectile = SFG_PROJECTILE_PLASMA;
|
||||
break;
|
||||
|
||||
case SFG_MONSTER_ATTACK_FIREBALL_BULLET:
|
||||
projectile = (SFG_random() < 128) ?
|
||||
SFG_PROJECTILE_FIREBALL :
|
||||
SFG_PROJECTILE_BULLET;
|
||||
break;
|
||||
|
||||
default:
|
||||
projectile = SFG_PROJECTILE_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
SFG_launchProjectile(
|
||||
type != SFG_LEVEL_ELEMENT_MONSTER_PLASMABOT ?
|
||||
SFG_PROJECTILE_FIREBALL : SFG_PROJECTILE_PLASMA,
|
||||
projectile,
|
||||
pos,
|
||||
SFG_floorHeightAt(
|
||||
SFG_MONSTER_COORD_TO_SQUARES(monster->coords[0]),
|
||||
@ -1300,23 +1335,33 @@ void SFG_monsterPerformAI(SFG_MonsterRecord *monster)
|
||||
}
|
||||
else if (state == SFG_MONSTER_STATE_IDLE)
|
||||
{
|
||||
if (melee)
|
||||
if (notRanged)
|
||||
{
|
||||
// melee monsters walk towards player
|
||||
// non-ranged monsters walk towards player
|
||||
|
||||
uint8_t mX = SFG_MONSTER_COORD_TO_SQUARES(monster->coords[0]);
|
||||
uint8_t mY = SFG_MONSTER_COORD_TO_SQUARES(monster->coords[1]);
|
||||
|
||||
if (!( // exploder will explode when close
|
||||
(type == SFG_LEVEL_ELEMENT_MONSTER_EXPLODER) &&
|
||||
(((mX > SFG_player.squarePosition[0]) ?
|
||||
(mX - SFG_player.squarePosition[0]) :
|
||||
(SFG_player.squarePosition[0] - mX)) <= 1) &&
|
||||
(((mY > SFG_player.squarePosition[1]) ?
|
||||
(mY - SFG_player.squarePosition[1]) :
|
||||
(SFG_player.squarePosition[1] - mY)) <= 1)
|
||||
))
|
||||
uint8_t isClose = // close to player?
|
||||
(
|
||||
(
|
||||
(mX > SFG_player.squarePosition[0]) ?
|
||||
(mX - SFG_player.squarePosition[0]) :
|
||||
(SFG_player.squarePosition[0] - mX)
|
||||
) <= 1
|
||||
) &&
|
||||
(
|
||||
(
|
||||
(mY > SFG_player.squarePosition[1]) ?
|
||||
(mY - SFG_player.squarePosition[1]) :
|
||||
(SFG_player.squarePosition[1] - mY)
|
||||
) <= 1
|
||||
);
|
||||
|
||||
if (!isClose)
|
||||
{
|
||||
// walk towards player
|
||||
|
||||
if (mX > SFG_player.squarePosition[0])
|
||||
{
|
||||
if (mY > SFG_player.squarePosition[1])
|
||||
@ -1345,22 +1390,32 @@ void SFG_monsterPerformAI(SFG_MonsterRecord *monster)
|
||||
}
|
||||
else
|
||||
{
|
||||
// exploder explodes
|
||||
if (attackType == SFG_MONSTER_ATTACK_MELEE)
|
||||
{
|
||||
// melee attack
|
||||
|
||||
uint8_t properties;
|
||||
state = SFG_MONSTER_STATE_ATTACKING;
|
||||
}
|
||||
else // SFG_MONSTER_ATTACK_EXPLODE
|
||||
{
|
||||
// explode
|
||||
|
||||
SFG_TileDefinition tile =
|
||||
SFG_getMapTile(SFG_currentLevel.levelPointer,mX,mY,&properties);
|
||||
|
||||
SFG_createExplosion(mX * RCL_UNITS_PER_SQUARE ,mY * RCL_UNITS_PER_SQUARE,
|
||||
SFG_TILE_FLOOR_HEIGHT(tile) * SFG_WALL_HEIGHT_STEP + SFG_WALL_HEIGHT_STEP);
|
||||
uint8_t properties;
|
||||
|
||||
monster->health = 0;
|
||||
SFG_TileDefinition tile =
|
||||
SFG_getMapTile(SFG_currentLevel.levelPointer,mX,mY,&properties);
|
||||
|
||||
SFG_createExplosion(mX * RCL_UNITS_PER_SQUARE ,mY * RCL_UNITS_PER_SQUARE,
|
||||
SFG_TILE_FLOOR_HEIGHT(tile) * SFG_WALL_HEIGHT_STEP + SFG_WALL_HEIGHT_STEP);
|
||||
|
||||
monster->health = 0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else // ranged monsters
|
||||
{
|
||||
// ranged monsters choose direction randomly
|
||||
// choose walk direction randomly
|
||||
|
||||
switch (SFG_random() % 8)
|
||||
{
|
||||
@ -1382,7 +1437,12 @@ void SFG_monsterPerformAI(SFG_MonsterRecord *monster)
|
||||
}
|
||||
else
|
||||
{
|
||||
int8_t add = type != SFG_LEVEL_ELEMENT_MONSTER_EXPLODER ? 1 : 3;
|
||||
int8_t add = 1;
|
||||
|
||||
if (attackType == SFG_MONSTER_ATTACK_MELEE)
|
||||
add = 2;
|
||||
else if (attackType == SFG_MONSTER_ATTACK_EXPLODE)
|
||||
add = 3;
|
||||
|
||||
if (state == SFG_MONSTER_STATE_GOING_E ||
|
||||
state == SFG_MONSTER_STATE_GOING_NE ||
|
||||
|
Loading…
Reference in New Issue
Block a user