Added Blob Bosses code; Blaze and Frost.
This commit is contained in:
parent
7a2529d250
commit
9e9de85e7e
|
@ -12,6 +12,7 @@ SEARCHPATH += src/widgets
|
||||||
SEARCHPATH += src/world
|
SEARCHPATH += src/world
|
||||||
SEARCHPATH += src/world/entities
|
SEARCHPATH += src/world/entities
|
||||||
SEARCHPATH += src/world/entities/blobs
|
SEARCHPATH += src/world/entities/blobs
|
||||||
|
SEARCHPATH += src/world/entities/boss
|
||||||
|
|
||||||
vpath %.c $(SEARCHPATH)
|
vpath %.c $(SEARCHPATH)
|
||||||
vpath %.h $(SEARCHPATH)
|
vpath %.h $(SEARCHPATH)
|
||||||
|
@ -19,9 +20,11 @@ vpath %.h $(SEARCHPATH)
|
||||||
DEPS += defs.h structs.h
|
DEPS += defs.h structs.h
|
||||||
|
|
||||||
OBJS += atlas.o
|
OBJS += atlas.o
|
||||||
|
OBJS += blaze.o boss.o blobBoss.o
|
||||||
OBJS += camera.o combat.o
|
OBJS += camera.o combat.o
|
||||||
OBJS += draw.o
|
OBJS += draw.o
|
||||||
OBJS += effects.o entities.o explosions.o
|
OBJS += effects.o entities.o explosions.o
|
||||||
|
OBJS += frost.o
|
||||||
OBJS += game.o
|
OBJS += game.o
|
||||||
OBJS += hub.o hud.o
|
OBJS += hub.o hud.o
|
||||||
OBJS += init.o input.o io.o items.o
|
OBJS += init.o input.o io.o items.o
|
||||||
|
|
|
@ -55,11 +55,11 @@ void addExplosion(float x, float y, int radius, Entity *owner)
|
||||||
{
|
{
|
||||||
if (e->flags & EF_BOMB_SHIELD)
|
if (e->flags & EF_BOMB_SHIELD)
|
||||||
{
|
{
|
||||||
applyEntityDamage(e, 2);
|
e->applyDamage(2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
applyEntityDamage(e, (int) power);
|
e->applyDamage((int) power);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e->type == ET_BOB)
|
if (e->type == ET_BOB)
|
||||||
|
|
|
@ -80,6 +80,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
#define MAX_OXYGEN (FPS * 10)
|
#define MAX_OXYGEN (FPS * 10)
|
||||||
#define MAX_KEY_TYPES 12
|
#define MAX_KEY_TYPES 12
|
||||||
|
|
||||||
|
#define MAX_CHECKPOINTS 15
|
||||||
|
|
||||||
#define MAX_WIDGET_OPTIONS 8
|
#define MAX_WIDGET_OPTIONS 8
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -268,6 +270,7 @@ enum
|
||||||
CH_PLAYER,
|
CH_PLAYER,
|
||||||
CH_EXPLODE,
|
CH_EXPLODE,
|
||||||
CH_WEAPON,
|
CH_WEAPON,
|
||||||
|
CH_DEATH,
|
||||||
CH_MAX
|
CH_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,34 @@ void initGame(void)
|
||||||
game.timePlayed = 0;
|
game.timePlayed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addRescuedMIA(char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < game.totalMIAs ; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(game.mias[i], "") == 0)
|
||||||
|
{
|
||||||
|
STRNCPY(game.mias[i], name, MAX_NAME_LENGTH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addDefeatedTarget(char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < game.totalTargets ; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(game.targets[i], "") == 0)
|
||||||
|
{
|
||||||
|
STRNCPY(game.targets[i], name, MAX_NAME_LENGTH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public void updateTimePlayedString()
|
public void updateTimePlayedString()
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,6 +55,11 @@ struct Texture {
|
||||||
Texture *next;
|
Texture *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
} PointF;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SDL_Color red;
|
SDL_Color red;
|
||||||
SDL_Color orange;
|
SDL_Color orange;
|
||||||
|
@ -120,6 +125,8 @@ struct Entity {
|
||||||
int shudderTimer;
|
int shudderTimer;
|
||||||
int starTimer;
|
int starTimer;
|
||||||
int teleportTimer;
|
int teleportTimer;
|
||||||
|
int stunTimer;
|
||||||
|
int weakAgainst;
|
||||||
long flags;
|
long flags;
|
||||||
SDL_Rect bounds;
|
SDL_Rect bounds;
|
||||||
int sprite[3];
|
int sprite[3];
|
||||||
|
@ -127,12 +134,18 @@ struct Entity {
|
||||||
int spriteFrame;
|
int spriteFrame;
|
||||||
Entity *carriedItem;
|
Entity *carriedItem;
|
||||||
Entity *owner;
|
Entity *owner;
|
||||||
void (*currentAction)(void);
|
void (*action)(void);
|
||||||
void (*walk)(void);
|
void (*walk)(void);
|
||||||
void (*attack)(void);
|
void (*attack)(void);
|
||||||
void (*touch)(Entity *other);
|
void (*touch)(Entity *other);
|
||||||
void (*tick)(void);
|
void (*tick)(void);
|
||||||
|
void (*die)(void);
|
||||||
void (*reset)(void);
|
void (*reset)(void);
|
||||||
|
void (*activate)(int active);
|
||||||
|
void (*changeEnvironment)(void);
|
||||||
|
int (*getCurrentSprite)(void);
|
||||||
|
void (*animate)(void);
|
||||||
|
void (*applyDamage)(int amount);
|
||||||
Entity *next;
|
Entity *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -309,7 +322,7 @@ struct Particle {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Entity *bob;
|
Entity *bob, *boss;
|
||||||
Map map;
|
Map map;
|
||||||
Entity entityHead, *entityTail;
|
Entity entityHead, *entityTail;
|
||||||
Particle particleHead, *particleTail;
|
Particle particleHead, *particleTail;
|
||||||
|
@ -317,7 +330,9 @@ typedef struct {
|
||||||
int frameCounter;
|
int frameCounter;
|
||||||
int currentStatus;
|
int currentStatus;
|
||||||
int isBossMission;
|
int isBossMission;
|
||||||
|
int isBossActive;
|
||||||
int isOutpostMission;
|
int isOutpostMission;
|
||||||
|
PointF checkpoints[MAX_CHECKPOINTS];
|
||||||
Quadtree quadtree;
|
Quadtree quadtree;
|
||||||
Objective objectiveHead, *objectiveTail;
|
Objective objectiveHead, *objectiveTail;
|
||||||
Trigger triggerHead, *triggerTail;
|
Trigger triggerHead, *triggerTail;
|
||||||
|
|
|
@ -73,6 +73,11 @@ void playSound(int snd, int ch)
|
||||||
Mix_PlayChannel(ch, sounds[snd], 0);
|
Mix_PlayChannel(ch, sounds[snd], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int isPlayingMusic(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static Mix_Chunk *loadSound(char *filename)
|
static Mix_Chunk *loadSound(char *filename)
|
||||||
{
|
{
|
||||||
return Mix_LoadWAV(getFileLocation(filename));
|
return Mix_LoadWAV(getFileLocation(filename));
|
||||||
|
|
|
@ -25,7 +25,6 @@ static void tick(void);
|
||||||
static void touch(Entity *other);
|
static void touch(Entity *other);
|
||||||
static void preTeleport(void);
|
static void preTeleport(void);
|
||||||
static void teleport(void);
|
static void teleport(void);
|
||||||
static void addRescuedMIA(void);
|
|
||||||
|
|
||||||
void initMIA(Entity *e)
|
void initMIA(Entity *e)
|
||||||
{
|
{
|
||||||
|
@ -41,7 +40,7 @@ void initMIA(Entity *e)
|
||||||
e->spriteFrame = 0;
|
e->spriteFrame = 0;
|
||||||
e->spriteTime = rand() % 180;
|
e->spriteTime = rand() % 180;
|
||||||
|
|
||||||
e->currentAction = nothing;
|
e->action = nothing;
|
||||||
e->reset = reset;
|
e->reset = reset;
|
||||||
e->tick = tick;
|
e->tick = tick;
|
||||||
e->touch = touch;
|
e->touch = touch;
|
||||||
|
@ -72,7 +71,7 @@ static void tick(void)
|
||||||
self->shudderTimer = 2;
|
self->shudderTimer = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->currentAction != nothing)
|
if (self->action != nothing)
|
||||||
{
|
{
|
||||||
self->starTimer--;
|
self->starTimer--;
|
||||||
if (self->starTimer <= 0)
|
if (self->starTimer <= 0)
|
||||||
|
@ -85,9 +84,9 @@ static void tick(void)
|
||||||
|
|
||||||
static void touch(Entity *other)
|
static void touch(Entity *other)
|
||||||
{
|
{
|
||||||
if (self->currentAction == nothing && other == world.bob)
|
if (self->action == nothing && other == world.bob)
|
||||||
{
|
{
|
||||||
self->currentAction = preTeleport;
|
self->action = preTeleport;
|
||||||
self->teleportTimer = FPS * 3;
|
self->teleportTimer = FPS * 3;
|
||||||
setGameplayMessage(MSG_OBJECTIVE, "Rescued %s", self->name);
|
setGameplayMessage(MSG_OBJECTIVE, "Rescued %s", self->name);
|
||||||
self->isMissionTarget = 0;
|
self->isMissionTarget = 0;
|
||||||
|
@ -101,7 +100,7 @@ static void preTeleport(void)
|
||||||
self->teleportTimer--;
|
self->teleportTimer--;
|
||||||
if (self->teleportTimer <= FPS)
|
if (self->teleportTimer <= FPS)
|
||||||
{
|
{
|
||||||
self->currentAction = teleport;
|
self->action = teleport;
|
||||||
self->flags |= (EF_NO_CLIP | EF_WEIGHTLESS);
|
self->flags |= (EF_NO_CLIP | EF_WEIGHTLESS);
|
||||||
self->dy = -5;
|
self->dy = -5;
|
||||||
}
|
}
|
||||||
|
@ -113,22 +112,8 @@ static void teleport(void)
|
||||||
if (self->teleportTimer <= 0)
|
if (self->teleportTimer <= 0)
|
||||||
{
|
{
|
||||||
addTeleportStars(self);
|
addTeleportStars(self);
|
||||||
addRescuedMIA();
|
addRescuedMIA(self->name);
|
||||||
updateObjective("MIA");
|
updateObjective("MIA");
|
||||||
self->alive = ALIVE_DEAD;
|
self->alive = ALIVE_DEAD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addRescuedMIA(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0 ; i < game.totalMIAs ; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(game.mias[i], "") == 0)
|
|
||||||
{
|
|
||||||
STRNCPY(game.mias[i], self->name, MAX_NAME_LENGTH);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern void addTeleportStars(Entity *e);
|
||||||
extern void setGameplayMessage(int type, char *format, ...);
|
extern void setGameplayMessage(int type, char *format, ...);
|
||||||
extern void playSound(int snd, int ch);
|
extern void playSound(int snd, int ch);
|
||||||
extern void updateObjective(char *targetName);
|
extern void updateObjective(char *targetName);
|
||||||
|
extern void addRescuedMIA(char *name);
|
||||||
|
|
||||||
extern Entity *self;
|
extern Entity *self;
|
||||||
extern Game game;
|
extern Game game;
|
||||||
|
|
|
@ -37,7 +37,7 @@ void initTeeka(Entity *e)
|
||||||
|
|
||||||
e->flags |= EF_IMMUNE;
|
e->flags |= EF_IMMUNE;
|
||||||
|
|
||||||
e->currentAction = lookForEnemies;
|
e->action = lookForEnemies;
|
||||||
|
|
||||||
e->weaponType = WPN_AIMED_PISTOL;
|
e->weaponType = WPN_AIMED_PISTOL;
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ static void tick(void)
|
||||||
{
|
{
|
||||||
target = NULL;
|
target = NULL;
|
||||||
|
|
||||||
self->currentAction = lookForEnemies;
|
self->action = lookForEnemies;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ static void lookForEnemies(void)
|
||||||
{
|
{
|
||||||
self->shotsToFire = rrnd(3, 5);
|
self->shotsToFire = rrnd(3, 5);
|
||||||
|
|
||||||
self->currentAction = preFire;
|
self->action = preFire;
|
||||||
}
|
}
|
||||||
else if (exitMission)
|
else if (exitMission)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2018 Parallel Realities
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blaze.h"
|
||||||
|
|
||||||
|
void initBlaze(Entity *e)
|
||||||
|
{
|
||||||
|
initBlobBoss(e);
|
||||||
|
|
||||||
|
e->weakAgainst = ENV_WATER;
|
||||||
|
|
||||||
|
STRNCPY(e->name, "Blaze", MAX_NAME_LENGTH);
|
||||||
|
|
||||||
|
e->sprite[FACING_LEFT] = getSpriteIndex("BlazeLeft");
|
||||||
|
e->sprite[FACING_RIGHT] = getSpriteIndex("BlazeRight");
|
||||||
|
e->sprite[FACING_DIE] = getSpriteIndex("BlazeSpin");
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2018 Parallel Realities
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../common.h"
|
||||||
|
|
||||||
|
extern void initBlobBoss(Entity *e);
|
||||||
|
extern int getSpriteIndex(char *name);
|
|
@ -0,0 +1,346 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2018 Parallel Realities
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blobBoss.h"
|
||||||
|
|
||||||
|
static void activate(int activate);
|
||||||
|
static void tick(void);
|
||||||
|
static void changeEnvironment(void);
|
||||||
|
static int getCurrentSprite(void);
|
||||||
|
static void animate(void);
|
||||||
|
static void applyDamage(int amount);
|
||||||
|
static void moveTowardsPlayer(void);
|
||||||
|
static void preFire(void);
|
||||||
|
static void teleport(void);
|
||||||
|
static void attack(void);
|
||||||
|
static void die1(void);
|
||||||
|
static void die2(void);
|
||||||
|
|
||||||
|
static int aimedSprite;
|
||||||
|
|
||||||
|
void initBlobBoss(Entity *e)
|
||||||
|
{
|
||||||
|
initBoss(e);
|
||||||
|
|
||||||
|
aimedSprite = getSpriteIndex("AimedShot");
|
||||||
|
|
||||||
|
e->flags |= EF_HALT_AT_EDGE;
|
||||||
|
|
||||||
|
e->health = e->healthMax = 250;
|
||||||
|
|
||||||
|
e->teleportTimer = FPS * rrnd(4, 6);
|
||||||
|
|
||||||
|
e->activate = activate;
|
||||||
|
e->tick = tick;
|
||||||
|
e->changeEnvironment = changeEnvironment;
|
||||||
|
e->getCurrentSprite = getCurrentSprite;
|
||||||
|
e->animate = animate;
|
||||||
|
e->applyDamage = applyDamage;
|
||||||
|
e->die = die1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void activate(int activate)
|
||||||
|
{
|
||||||
|
self->flags &= ~EF_GONE;
|
||||||
|
|
||||||
|
world.isBossActive = 1;
|
||||||
|
|
||||||
|
addTeleportStars(self);
|
||||||
|
|
||||||
|
if (!isPlayingMusic())
|
||||||
|
{
|
||||||
|
playMusic("", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tick(void)
|
||||||
|
{
|
||||||
|
if (self->health > 0)
|
||||||
|
{
|
||||||
|
self->stunTimer = MAX(self->stunTimer - 1, 0);
|
||||||
|
|
||||||
|
if (self->environment == self->weakAgainst)
|
||||||
|
{
|
||||||
|
self->health -= 2;
|
||||||
|
|
||||||
|
world.boss = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->stunTimer == 0)
|
||||||
|
{
|
||||||
|
self->facing = (world.bob->x < self->x) ? FACING_LEFT : FACING_RIGHT;
|
||||||
|
|
||||||
|
self->reload = limit(--self->reload, 0, FPS);
|
||||||
|
|
||||||
|
self->teleportTimer = limit(self->teleportTimer - 1, 0, 9999);
|
||||||
|
|
||||||
|
if (self->isOnGround)
|
||||||
|
{
|
||||||
|
self->flags |= EF_HALT_AT_EDGE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self->flags &= ~EF_HALT_AT_EDGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void changeEnvironment()
|
||||||
|
{
|
||||||
|
if (self->environment == self->weakAgainst)
|
||||||
|
{
|
||||||
|
self->teleportTimer = 0;
|
||||||
|
self->stunTimer = 90;
|
||||||
|
self->spriteFrame = self->spriteTime = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self->teleportTimer = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void die1(void)
|
||||||
|
{
|
||||||
|
self->flags |= EF_BOUNCES;
|
||||||
|
|
||||||
|
self->thinkTime = 0;
|
||||||
|
|
||||||
|
self->spriteTime = 0;
|
||||||
|
self->spriteFrame = 0;
|
||||||
|
|
||||||
|
if (self->environment == ENV_AIR)
|
||||||
|
{
|
||||||
|
self->dy = -9;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->dx = (randF() - randF()) * 5;
|
||||||
|
|
||||||
|
self->flags &= ~EF_HALT_AT_EDGE;
|
||||||
|
|
||||||
|
switch (rand() % 3)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
playSound(SND_DEATH_1, CH_DEATH);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
playSound(SND_DEATH_2, CH_DEATH);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
playSound(SND_DEATH_3, CH_DEATH);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->action = die2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getCurrentSprite(void)
|
||||||
|
{
|
||||||
|
if (self->stunTimer > 0 || self->health <= 0)
|
||||||
|
{
|
||||||
|
return self->sprite[FACING_DIE];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self->sprite[self->facing];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void animate(void)
|
||||||
|
{
|
||||||
|
if (self->dx != 0 || self->health <= 0 || self->stunTimer > 0)
|
||||||
|
{
|
||||||
|
animateEntity(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lookForPlayer(void)
|
||||||
|
{
|
||||||
|
self->thinkTime = rrnd(0, FPS / 2);
|
||||||
|
|
||||||
|
if (getDistance(world.bob->x, world.bob->y, self->x, self->y) > 650)
|
||||||
|
{
|
||||||
|
moveTowardsPlayer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!enemyCanSeePlayer(self))
|
||||||
|
{
|
||||||
|
moveTowardsPlayer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rand() % 100 < 15)
|
||||||
|
{
|
||||||
|
self->shotsToFire = rrnd(1, 12);
|
||||||
|
self->action = preFire;
|
||||||
|
}
|
||||||
|
|
||||||
|
moveTowardsPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void moveTowardsPlayer(void)
|
||||||
|
{
|
||||||
|
self->dx = 0;
|
||||||
|
|
||||||
|
if (rand() % 100 < 20)
|
||||||
|
{
|
||||||
|
if (world.bob->x < self->x)
|
||||||
|
{
|
||||||
|
self->dx = -3.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.bob->x > self->x)
|
||||||
|
{
|
||||||
|
self->dx = 3.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world.bob->y <= self->y && rand() % 2 == 0 && self->isOnGround)
|
||||||
|
{
|
||||||
|
self->dy = JUMP_POWER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self->stunTimer == 0 && self->teleportTimer == 0)
|
||||||
|
{
|
||||||
|
teleport();
|
||||||
|
|
||||||
|
self->teleportTimer = FPS * rrnd(4, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void preFire(void)
|
||||||
|
{
|
||||||
|
if (self->reload > 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
attack();
|
||||||
|
|
||||||
|
self->shotsToFire--;
|
||||||
|
|
||||||
|
if (self->shotsToFire == 0)
|
||||||
|
{
|
||||||
|
self->walk();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void attack(void)
|
||||||
|
{
|
||||||
|
Entity *bullet;
|
||||||
|
float dx, dy;
|
||||||
|
int bx, by;
|
||||||
|
|
||||||
|
bx = (int) (world.bob->x + rrnd(-8, 24));
|
||||||
|
by = (int) (world.bob->y + rrnd(-8, 24));
|
||||||
|
|
||||||
|
getSlope(bx, by, self->x, self->y, &dx, &dy);
|
||||||
|
|
||||||
|
bullet = createBaseBullet(self);
|
||||||
|
bullet->x = self->x;
|
||||||
|
bullet->y = (self->y + self->h / 2) - 3;
|
||||||
|
bullet->facing = self->facing;
|
||||||
|
bullet->damage = 1;
|
||||||
|
bullet->owner = self;
|
||||||
|
bullet->health = FPS * 3;
|
||||||
|
bullet->weaponType = WPN_AIMED_PISTOL;
|
||||||
|
bullet->dx = dx * 12;
|
||||||
|
bullet->dy = dy * 12;
|
||||||
|
bullet->sprite[0] = bullet->sprite[1] = aimedSprite;
|
||||||
|
|
||||||
|
self->reload = 4;
|
||||||
|
|
||||||
|
playSound(SND_MACHINE_GUN, CH_WEAPON);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void walk(void)
|
||||||
|
{
|
||||||
|
self->action = (self->health > 0) ? lookForPlayer : die2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reappear(void)
|
||||||
|
{
|
||||||
|
int valid, r;
|
||||||
|
|
||||||
|
valid = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
r = (int) (rand() % MAX_CHECKPOINTS);
|
||||||
|
self->x = world.checkpoints[r].x;
|
||||||
|
self->y = world.checkpoints[r].y;
|
||||||
|
valid = (self->x != 0 && self->y != 0);
|
||||||
|
}
|
||||||
|
while (!valid);
|
||||||
|
|
||||||
|
self->y -= (self->h + 10);
|
||||||
|
|
||||||
|
walk();
|
||||||
|
|
||||||
|
self->flags &= ~EF_GONE;
|
||||||
|
|
||||||
|
addTeleportStars(self);
|
||||||
|
|
||||||
|
playSound(SND_APPEAR, CH_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void applyDamage(int amount)
|
||||||
|
{
|
||||||
|
self->health -= amount;
|
||||||
|
|
||||||
|
self->thinkTime = 0;
|
||||||
|
|
||||||
|
if (rand() % 10 == 0)
|
||||||
|
{
|
||||||
|
teleport();
|
||||||
|
}
|
||||||
|
|
||||||
|
world.boss = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void teleport(void)
|
||||||
|
{
|
||||||
|
self->action = reappear;
|
||||||
|
self->flags |= EF_GONE;
|
||||||
|
self->thinkTime = FPS * rrnd(3, 6);
|
||||||
|
addTeleportStars(self);
|
||||||
|
playSound(SND_APPEAR, CH_ANY);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void die2(void)
|
||||||
|
{
|
||||||
|
self->health--;
|
||||||
|
|
||||||
|
if (self->health <= -FPS)
|
||||||
|
{
|
||||||
|
addTeleportStars(self);
|
||||||
|
|
||||||
|
playSound(SND_APPEAR, CH_ANY);
|
||||||
|
|
||||||
|
self->alive = ALIVE_DEAD;
|
||||||
|
|
||||||
|
updateObjective(self->name);
|
||||||
|
|
||||||
|
addDefeatedTarget(self->name);
|
||||||
|
|
||||||
|
game.enemiesKilled++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2018 Parallel Realities
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../common.h"
|
||||||
|
|
||||||
|
extern void initBoss(Entity *e);
|
||||||
|
extern int rrnd(int low, int high);
|
||||||
|
extern void addTeleportStars(Entity *e);
|
||||||
|
extern void playMusic(char *filename, int loop);
|
||||||
|
extern int isPlayingMusic(void);
|
||||||
|
extern float limit(float i, float a, float b);
|
||||||
|
extern double randF(void);
|
||||||
|
extern void playSound(int snd, int ch);
|
||||||
|
extern void animateEntity(Entity *e);
|
||||||
|
extern Entity *createBaseBullet(Entity *owner);
|
||||||
|
extern int getSpriteIndex(char *name);
|
||||||
|
extern int getDistance(int x1, int y1, int x2, int y2);
|
||||||
|
extern void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy);
|
||||||
|
extern int enemyCanSeePlayer(Entity *e);
|
||||||
|
extern void updateObjective(char *targetName);
|
||||||
|
extern void addDefeatedTarget(char *name);
|
||||||
|
|
||||||
|
extern Entity *self;
|
||||||
|
extern Game game;
|
||||||
|
extern World world;
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2018 Parallel Realities
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "boss.h"
|
||||||
|
|
||||||
|
void initBoss(Entity *e)
|
||||||
|
{
|
||||||
|
initEntity(e);
|
||||||
|
|
||||||
|
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex("Boss");
|
||||||
|
|
||||||
|
e->isMissionTarget = 1;
|
||||||
|
|
||||||
|
e->action = lookForPlayer;
|
||||||
|
|
||||||
|
e->spriteFrame = 0;
|
||||||
|
e->spriteTime = 0;
|
||||||
|
|
||||||
|
world.boss = e;
|
||||||
|
|
||||||
|
e->flags |= EF_ALWAYS_PROCESS | EF_BOMB_SHIELD | EF_GONE;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2018 Parallel Realities
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../common.h"
|
||||||
|
|
||||||
|
extern void initEntity(Entity *e);
|
||||||
|
extern void lookForPlayer(void);
|
||||||
|
extern int getSpriteIndex(char *name);
|
||||||
|
|
||||||
|
extern World world;
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2018 Parallel Realities
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "frost.h"
|
||||||
|
|
||||||
|
void initFrost(Entity *e)
|
||||||
|
{
|
||||||
|
initBlobBoss(e);
|
||||||
|
|
||||||
|
e->weakAgainst = ENV_LAVA;
|
||||||
|
|
||||||
|
STRNCPY(e->name, "Frost", MAX_NAME_LENGTH);
|
||||||
|
|
||||||
|
e->sprite[FACING_LEFT] = getSpriteIndex("FrostLeft");
|
||||||
|
e->sprite[FACING_RIGHT] = getSpriteIndex("FrostRight");
|
||||||
|
e->sprite[FACING_DIE] = getSpriteIndex("FrostSpin");
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2018 Parallel Realities
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../common.h"
|
||||||
|
|
||||||
|
extern void initBlobBoss(Entity *e);
|
||||||
|
extern int getSpriteIndex(char *name);
|
|
@ -20,6 +20,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#include "entities.h"
|
#include "entities.h"
|
||||||
|
|
||||||
|
void animateEntity(void);
|
||||||
|
static void applyDamage(int damage);
|
||||||
|
|
||||||
Entity *createEntity(void)
|
Entity *createEntity(void)
|
||||||
{
|
{
|
||||||
Entity *e;
|
Entity *e;
|
||||||
|
@ -62,6 +65,9 @@ void initEntity(Entity *e)
|
||||||
e->thinkTime = 0;
|
e->thinkTime = 0;
|
||||||
|
|
||||||
e->plane = PLANE_BACKGROUND;
|
e->plane = PLANE_BACKGROUND;
|
||||||
|
|
||||||
|
e->animate = animateEntity;
|
||||||
|
e->applyDamage = applyDamage;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Rect *getEntityBounds(Entity *e)
|
SDL_Rect *getEntityBounds(Entity *e)
|
||||||
|
@ -84,21 +90,21 @@ int getCurrentEntitySprite(Entity *e)
|
||||||
return e->sprite[FACING_DIE];
|
return e->sprite[FACING_DIE];
|
||||||
}
|
}
|
||||||
|
|
||||||
void animateEntity(Entity *e)
|
void animateEntity(void)
|
||||||
{
|
{
|
||||||
Sprite *spr;
|
Sprite *spr;
|
||||||
|
|
||||||
if (e->spriteTime != -1)
|
if (self->spriteTime != -1)
|
||||||
{
|
{
|
||||||
e->spriteTime--;
|
self->spriteTime--;
|
||||||
|
|
||||||
if (e->spriteTime <= 0)
|
if (self->spriteTime <= 0)
|
||||||
{
|
{
|
||||||
spr = getSpriteByIndex(getCurrentEntitySprite(e));
|
spr = getSpriteByIndex(getCurrentEntitySprite(self));
|
||||||
e->spriteFrame = wrap(e->spriteFrame + 1, 0, 1);
|
self->spriteFrame = wrap(self->spriteFrame + 1, 0, 1);
|
||||||
e->spriteTime = 0;
|
self->spriteTime = 0;
|
||||||
e->w = spr->w;
|
self->w = spr->w;
|
||||||
e->h = spr->h;
|
self->h = spr->h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,28 +154,28 @@ void activateEntities(char *names, int activate)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void applyEntityDamage(Entity *e, int damage)
|
static void applyDamage(int damage)
|
||||||
{
|
{
|
||||||
if (e->health < 0)
|
if (self->health < 0)
|
||||||
{
|
{
|
||||||
e->health = 0;
|
self->health = 0;
|
||||||
e->alive = ALIVE_ALIVE;
|
self->alive = ALIVE_ALIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
e->health -= damage;
|
self->health -= damage;
|
||||||
|
|
||||||
if (e->health > 0)
|
if (self->health > 0)
|
||||||
{
|
{
|
||||||
e->thinkTime = 0;
|
self->thinkTime = 0;
|
||||||
|
|
||||||
e->facing = e->x < world.bob->x ? FACING_RIGHT : FACING_LEFT;
|
self->facing = self->x < world.bob->x ? FACING_RIGHT : FACING_LEFT;
|
||||||
|
|
||||||
if (e->isMissionTarget && rand() % 10 == 0)
|
if (self->isMissionTarget && rand() % 10 == 0)
|
||||||
{
|
{
|
||||||
e->currentAction = unitReappear;
|
self->action = unitReappear;
|
||||||
e->flags |= EF_GONE;
|
self->flags |= EF_GONE;
|
||||||
e->thinkTime = rand() % FPS;
|
self->thinkTime = rand() % FPS;
|
||||||
addTeleportStars(e);
|
addTeleportStars(self);
|
||||||
playSound(SND_APPEAR, CH_ANY);
|
playSound(SND_APPEAR, CH_ANY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,5 +26,6 @@ extern void addTeleportStars(Entity *e);
|
||||||
extern void unitReappear(void);
|
extern void unitReappear(void);
|
||||||
extern void playSound(int snd, int ch);
|
extern void playSound(int snd, int ch);
|
||||||
|
|
||||||
|
extern Entity *self;
|
||||||
extern Game game;
|
extern Game game;
|
||||||
extern World world;
|
extern World world;
|
||||||
|
|
|
@ -42,7 +42,7 @@ void initUnit(Entity *e)
|
||||||
e->startX = e->startY = -1;
|
e->startX = e->startY = -1;
|
||||||
|
|
||||||
e->tick = unitTick;
|
e->tick = unitTick;
|
||||||
e->currentAction = lookForPlayer;
|
e->action = lookForPlayer;
|
||||||
e->attack = attack;
|
e->attack = attack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue