Using anonymous structures to shrink size of Entity object.

This commit is contained in:
Steve 2018-01-28 08:30:53 +00:00
parent b56cb72aec
commit 53c8c4984e
54 changed files with 1582 additions and 1075 deletions

View File

@ -22,7 +22,7 @@ include common.mk
CXXFLAGS += `sdl2-config --cflags` -DVERSION=$(VERSION) -DREVISION=$(REVISION) -DDATA_DIR=\"$(DATA_DIR)\" -DLOCALE_DIR=\"$(LOCALE_DIR)\" CXXFLAGS += `sdl2-config --cflags` -DVERSION=$(VERSION) -DREVISION=$(REVISION) -DDATA_DIR=\"$(DATA_DIR)\" -DLOCALE_DIR=\"$(LOCALE_DIR)\"
CXXFLAGS += -Wall -Wempty-body -ansi -pedantic -Werror -Wstrict-prototypes -Werror=maybe-uninitialized -Warray-bounds CXXFLAGS += -Wall -Wempty-body -ansi -pedantic -Werror -Wstrict-prototypes -Werror=maybe-uninitialized -Warray-bounds
CXXFLAGS += -g -lefence CXXFLAGS += -g -lefence
CXXFLAGS += -fms-extensions CXXFLAGS += -fms-extensions -std=gnu11
LDFLAGS += `sdl2-config --libs` -lSDL2_mixer -lSDL2_image -lSDL2_ttf -lm LDFLAGS += `sdl2-config --libs` -lSDL2_mixer -lSDL2_image -lSDL2_ttf -lm

View File

@ -32,33 +32,6 @@ void lookForPlayer(void)
} }
void preFire(Entity *e)
{
if (e->flags & EF_WEIGHTLESS)
{
if (world.bob->y < e->y && e->isOnGround && (int) (rand() % 4) == 0)
{
e->dy = JUMP_POWER;
}
}
e->facing = (world.bob->x < e->x) ? FACING_LEFT : FACING_RIGHT;
if (e->reload > 0)
{
return;
}
e->attack();
e->shotsToFire--;
if (e->shotsToFire == 0)
{
e->walk();
}
}
int hasLineOfSight(Entity *src, Entity *dest) int hasLineOfSight(Entity *src, Entity *dest)
{ {
return (!isBlockedByMap(src, dest) && !isBlockedByEntities(src, dest)); return (!isBlockedByMap(src, dest) && !isBlockedByEntities(src, dest));
@ -130,10 +103,5 @@ static int isBlockedByEntities(Entity *src, Entity *dest)
int enemyCanSeePlayer(Entity *e) int enemyCanSeePlayer(Entity *e)
{ {
return hasLineOfSight(e, world.bob); return hasLineOfSight(e, (Entity*)world.bob);
}
int canFire(Entity *target)
{
return 0;
} }

View File

@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "weapons.h" #include "weapons.h"
Bullet *createBaseBullet(Entity *owner); Bullet *createBaseBullet(Unit *owner);
static int bulletSprite[2]; static int bulletSprite[2];
static int plasmaSprite[2]; static int plasmaSprite[2];
@ -58,7 +58,7 @@ void initWeapons(void)
missileSprite[1] = getSpriteIndex("MissileLeft"); missileSprite[1] = getSpriteIndex("MissileLeft");
} }
void firePistol(Entity *owner) void firePistol(Unit *owner)
{ {
Bullet *bullet; Bullet *bullet;
@ -73,7 +73,7 @@ void firePistol(Entity *owner)
playSound(SND_PISTOL, CH_PLAYER); playSound(SND_PISTOL, CH_PLAYER);
} }
void fireAimedShot(Entity *owner) void fireAimedShot(Unit *owner)
{ {
int x, y; int x, y;
float dx, dy; float dx, dy;
@ -96,7 +96,7 @@ void fireAimedShot(Entity *owner)
playSound(SND_PISTOL, CH_WEAPON); playSound(SND_PISTOL, CH_WEAPON);
} }
void fireMachineGun(Entity *owner) void fireMachineGun(Unit *owner)
{ {
Bullet *bullet; Bullet *bullet;
@ -109,7 +109,7 @@ void fireMachineGun(Entity *owner)
playSound(SND_MACHINE_GUN, CH_WEAPON); playSound(SND_MACHINE_GUN, CH_WEAPON);
} }
void firePlasma(Entity *owner) void firePlasma(Unit *owner)
{ {
Bullet *bullet; Bullet *bullet;
@ -124,7 +124,7 @@ void firePlasma(Entity *owner)
playSound(SND_PLASMA, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON); playSound(SND_PLASMA, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON);
} }
void fireSpread(Entity *owner, int numberOfShots) void fireSpread(Unit *owner, int numberOfShots)
{ {
Bullet *bullet; Bullet *bullet;
int i; int i;
@ -148,7 +148,7 @@ void fireSpread(Entity *owner, int numberOfShots)
playSound(SND_SPREAD, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON); playSound(SND_SPREAD, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON);
} }
void fireLaser(Entity *owner) void fireLaser(Unit *owner)
{ {
Bullet *laser; Bullet *laser;
@ -157,7 +157,6 @@ void fireLaser(Entity *owner)
laser->y = owner->y + owner->h / 2; laser->y = owner->y + owner->h / 2;
laser->facing = owner->facing; laser->facing = owner->facing;
laser->dx = owner->facing == FACING_RIGHT ? 20 : -20; laser->dx = owner->facing == FACING_RIGHT ? 20 : -20;
laser->owner = owner;
laser->health = FPS * 3; laser->health = FPS * 3;
laser->sprite[0] = laser->sprite[1] = (owner->type == ET_BOB) ? laserSprite[0] : laserSprite[1]; laser->sprite[0] = laser->sprite[1] = (owner->type == ET_BOB) ? laserSprite[0] : laserSprite[1];
@ -166,7 +165,7 @@ void fireLaser(Entity *owner)
playSound(SND_LASER, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON); playSound(SND_LASER, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON);
} }
void fireGrenade(Entity *owner) void fireGrenade(Unit *owner)
{ {
Bullet *grenade; Bullet *grenade;
@ -174,7 +173,6 @@ void fireGrenade(Entity *owner)
grenade->x = owner->x + owner->w / 2; grenade->x = owner->x + owner->w / 2;
grenade->y = owner->y; grenade->y = owner->y;
grenade->facing = owner->facing; grenade->facing = owner->facing;
grenade->owner = owner;
grenade->health = FPS * 3; grenade->health = FPS * 3;
grenade->dx = owner->facing == FACING_RIGHT ? 8 : -8; grenade->dx = owner->facing == FACING_RIGHT ? 8 : -8;
grenade->sprite[0] = grenade->sprite[1] = (owner->type == ET_BOB) ? grenadeSprite : alienGrenadeSprite; grenade->sprite[0] = grenade->sprite[1] = (owner->type == ET_BOB) ? grenadeSprite : alienGrenadeSprite;
@ -186,7 +184,7 @@ void fireGrenade(Entity *owner)
playSound(SND_THROW, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON); playSound(SND_THROW, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON);
} }
void fireShotgun(Entity *owner) void fireShotgun(Unit *owner)
{ {
int i; int i;
float dx, dy; float dx, dy;
@ -211,7 +209,7 @@ void fireShotgun(Entity *owner)
playSound(SND_SHOTGUN, CH_WEAPON); playSound(SND_SHOTGUN, CH_WEAPON);
} }
void fireMissile(Entity *owner) void fireMissile(Unit *owner)
{ {
Bullet *missile; Bullet *missile;
@ -220,7 +218,6 @@ void fireMissile(Entity *owner)
missile->y = owner->y + 10; missile->y = owner->y + 10;
missile->facing = owner->facing; missile->facing = owner->facing;
missile->dx = owner->facing == FACING_RIGHT ? 10 : -10; missile->dx = owner->facing == FACING_RIGHT ? 10 : -10;
missile->owner = owner;
missile->health = FPS * 3; missile->health = FPS * 3;
missile->sprite[0] = missileSprite[0]; missile->sprite[0] = missileSprite[0];
missile->sprite[1] = missileSprite[1]; missile->sprite[1] = missileSprite[1];
@ -230,21 +227,21 @@ void fireMissile(Entity *owner)
playSound(SND_MISSILE, CH_WEAPON); playSound(SND_MISSILE, CH_WEAPON);
} }
Bullet *createBaseBullet(Entity *owner) Bullet *createBaseBullet(Unit *owner)
{ {
Bullet *bullet; Bullet *bullet;
bullet = malloc(sizeof(Bullet)); bullet = malloc(sizeof(Bullet));
memset(bullet, 0, sizeof(Bullet)); memset(bullet, 0, sizeof(Bullet));
world.bulletTail->next = bullet; world.entityTail->next = (Entity*)bullet;
world.bulletTail = bullet; world.entityTail = (Entity*)bullet;
bullet->x = (owner->x + owner->w / 2); bullet->x = (owner->x + owner->w / 2);
bullet->y = (owner->y + owner->h / 2) - 3; bullet->y = (owner->y + owner->h / 2) - 3;
bullet->dx = owner->facing == FACING_RIGHT ? 15 : -15; bullet->dx = owner->facing == FACING_RIGHT ? 15 : -15;
bullet->facing = owner->facing; bullet->facing = owner->facing;
bullet->damage = 1; bullet->damage = 1;
bullet->owner = owner; bullet->owner = (Entity*)owner;
bullet->health = FPS * 3; bullet->health = FPS * 3;
bullet->flags |= EF_WEIGHTLESS | EF_IGNORE_BULLETS | EF_NO_ENVIRONMENT | EF_KILL_OFFSCREEN | EF_NO_TELEPORT; bullet->flags |= EF_WEIGHTLESS | EF_IGNORE_BULLETS | EF_NO_ENVIRONMENT | EF_KILL_OFFSCREEN | EF_NO_TELEPORT;

View File

@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
typedef struct Texture Texture; typedef struct Texture Texture;
typedef struct Lookup Lookup; typedef struct Lookup Lookup;
typedef struct Quadtree Quadtree; typedef struct Quadtree Quadtree;
typedef struct Entity Entity;
typedef struct Objective Objective; typedef struct Objective Objective;
typedef struct Trigger Trigger; typedef struct Trigger Trigger;
typedef struct Marker Marker; typedef struct Marker Marker;
@ -31,7 +30,18 @@ typedef struct Tuple Tuple;
typedef struct HubMission HubMission; typedef struct HubMission HubMission;
typedef struct Widget Widget; typedef struct Widget Widget;
typedef struct Atlas Atlas; typedef struct Atlas Atlas;
typedef struct Entity Entity;
typedef struct EntityExt EntityExt;
typedef struct Bob Bob;
typedef struct Boss Boss;
typedef struct Bullet Bullet; typedef struct Bullet Bullet;
typedef struct Decoration Decoration;
typedef struct Item Item;
typedef struct MIA MIA;
typedef struct Structure Structure;
typedef struct Trap Trap;
typedef struct Unit Unit;
typedef struct { typedef struct {
int debug; int debug;
@ -91,97 +101,131 @@ typedef struct {
struct Entity { struct Entity {
unsigned long uniqueId; unsigned long uniqueId;
char name[MAX_NAME_LENGTH];
char spriteName[MAX_NAME_LENGTH];
char targetNames[MAX_DESCRIPTION_LENGTH];
int type; int type;
float x; char name[MAX_NAME_LENGTH];
float y; float x, y;
int w; int w, h;
int h; int tx, ty;
int health; float dx, dy;
int healthMax; int health, healthMax;
int alive; int alive;
int oxygen; int active;
int startX; int environment;
int startY; int thinkTime;
float dx;
float dy;
int tx;
int ty;
int reload;
int isOnGround;
int effectType;
int bleedTime;
int facing; int facing;
int damage; int sprite[3];
int plane;
int isSolid;
int isStatic;
int isOnGround;
int isMissionTarget;
SDL_Rect bounds;
unsigned long flags;
void (*init)(void);
void (*action)(void);
void (*touch)(Entity *other);
void (*tick)(void);
void (*reset)(void);
void (*die)(void);
void (*animate)(void);
void (*walk)(void);
void (*setSize)(void);
float (*bounce)(float x);
void (*teleport)(float tx, float ty);
void (*activate)(int active);
void (*applyDamage)(int amount);
void (*changeEnvironment)(void);
int (*getCurrentSprite)(void);
int (*preSave)(void);
SDL_Rect *(*getBounds)(void);
Entity *next;
};
struct EntityExt {
struct Entity;
char spriteName[MAX_NAME_LENGTH];
int spriteTime;
int spriteFrame;
Item *carriedItem;
};
struct Unit {
struct EntityExt;
int weaponType; int weaponType;
int canCarryItem;
int reload;
int shotsToFire; int shotsToFire;
int maxShotsToFire; int maxShotsToFire;
int isSolid;
int environment;
int isStatic;
int isMissionTarget;
int thinkTime;
int plane;
int value;
int canCarryItem;
int spawnedIn;
int spawnedInTimer; int spawnedInTimer;
int oxygen;
int spawnedIn;
int startX, startY;
void (*attack)(void);
int (*canFire)(Entity *target);
};
struct MIA {
struct Unit;
int shudderTimer; int shudderTimer;
int starTimer; int starTimer;
int teleportTimer; int teleportTimer;
int stunTimer; };
struct Boss {
struct Unit;
int weakAgainst; int weakAgainst;
int teleportTimer;
int stunTimer;
};
struct Item {
struct EntityExt;
int startX, startY;
int power; int power;
int powerMax; int value;
int weaponType;
int provided;
int collected; int collected;
int canBeCarried; int canBeCarried;
int canBePickedUp; int canBePickedUp;
int provided; };
int firstTouch;
int active; struct Bob {
float sinVal; struct Unit;
int stunTimer;
int power, powerMax;
};
struct Structure {
struct EntityExt;
int bobTouching; int bobTouching;
int messageTimer;
char message[MAX_DESCRIPTION_LENGTH];
char requiredCard[MAX_NAME_LENGTH];
char requiredKey[MAX_NAME_LENGTH];
char requiredItem[MAX_NAME_LENGTH]; char requiredItem[MAX_NAME_LENGTH];
int requiredPower; char targetNames[MAX_DESCRIPTION_LENGTH];
long flags; char message[MAX_DESCRIPTION_LENGTH];
SDL_Rect bounds;
int sprite[3];
int spriteTime;
int spriteFrame;
int isLocked;
int closedX;
int closedY;
int state; int state;
int speed;
int waitTime; int waitTime;
int startX, startY;
int closedX, closedY;
int isLocked;
int speed;
int messageTimer;
int firstTouch;
int requiredPower;
int isWeighted; int isWeighted;
float weightApplied; int weightApplied;
float sinVal;
};
struct Decoration {
struct Entity;
int effectType;
int bleedTime;
};
struct Trap {
struct EntityExt;
int onTime; int onTime;
int offTime; int offTime;
Entity *carriedItem;
Entity *owner;
void (*init)(void);
void (*action)(void);
void (*walk)(void);
void (*attack)(void);
void (*touch)(Entity *other);
void (*tick)(void);
void (*die)(void);
int (*canFire)(Entity *target);
void (*reset)(void);
void (*activate)(int active);
void (*changeEnvironment)(void);
int (*getCurrentSprite)(void);
void (*animate)(void);
void (*applyDamage)(int amount);
SDL_Rect (*getBounds)(void);
Entity *next;
}; };
struct Objective { struct Objective {
@ -357,24 +401,17 @@ struct Particle {
}; };
struct Bullet { struct Bullet {
int x; struct Entity;
int y;
int facing;
int damage; int damage;
int health;
int weaponType; int weaponType;
float dx;
float dy;
int sprite[2];
long flags;
Entity *owner; Entity *owner;
Bullet *next;
}; };
typedef struct { typedef struct {
char id[MAX_NAME_LENGTH]; char id[MAX_NAME_LENGTH];
int state; int state;
Entity *bob, *boss; Bob *bob;
Boss *boss;
Map map; Map map;
int allObjectivesComplete; int allObjectivesComplete;
int frameCounter; int frameCounter;
@ -388,7 +425,6 @@ typedef struct {
Quadtree quadtree; Quadtree quadtree;
Entity entityHead, *entityTail; Entity entityHead, *entityTail;
Particle particleHead, *particleTail; Particle particleHead, *particleTail;
Bullet bulletHead, *bulletTail;
Objective objectiveHead, *objectiveTail; Objective objectiveHead, *objectiveTail;
Trigger triggerHead, *triggerTail; Trigger triggerHead, *triggerTail;
} World; } World;

View File

@ -40,12 +40,12 @@ void addExplosionEffect(int x, int y, float dx, float dy)
void addSmallFleshChunk(double x, double y) void addSmallFleshChunk(double x, double y)
{ {
Entity *chunk; Decoration *chunk;
chunk = malloc(sizeof(Entity)); chunk = malloc(sizeof(Decoration));
memset(chunk, 0, sizeof(Entity)); memset(chunk, 0, sizeof(Decoration));
world.entityTail->next = chunk; world.entityTail->next = (Entity*)chunk;
world.entityTail = chunk; world.entityTail = (Entity*)chunk;
chunk->x = x; chunk->x = x;
chunk->y = y; chunk->y = y;
@ -58,14 +58,14 @@ void addSmallFleshChunk(double x, double y)
void throwFleshChunks(double x, double y, int amount) void throwFleshChunks(double x, double y, int amount)
{ {
int i; int i;
Entity *chunk; Decoration *chunk;
for (i = 0; i < amount; i++) for (i = 0; i < amount; i++)
{ {
chunk = malloc(sizeof(Entity)); chunk = malloc(sizeof(Decoration));
memset(chunk, 0, sizeof(Entity)); memset(chunk, 0, sizeof(Decoration));
world.entityTail->next = chunk; world.entityTail->next = (Entity*)chunk;
world.entityTail = chunk; world.entityTail = (Entity*)chunk;
chunk->x = x; chunk->x = x;
chunk->y = y; chunk->y = y;

View File

@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "bob.h" #include "bob.h"
void addBobItem(Entity *e) void addBobItem(Item *i)
{ {
} }

View File

@ -28,24 +28,30 @@ static void teleport(void);
void initMIA(Entity *e) void initMIA(Entity *e)
{ {
e->tx = e->ty = -1; MIA *m;
initUnit(e);
m = (MIA*)e;
m->tx = m->ty = -1;
e->sprite[FACING_LEFT] = getSpriteIndex("MIA"); m->sprite[FACING_LEFT] = getSpriteIndex("MIA");
e->sprite[FACING_RIGHT] = getSpriteIndex("MIA"); m->sprite[FACING_RIGHT] = getSpriteIndex("MIA");
e->sprite[FACING_DIE] = getSpriteIndex("MIA"); m->sprite[FACING_DIE] = getSpriteIndex("MIA");
e->flags |= EF_IGNORE_BULLETS; m->flags |= EF_IGNORE_BULLETS;
/* blink at random intervals */ /* blink at random intervals */
e->spriteFrame = 0; m->spriteFrame = 0;
e->spriteTime = rand() % 180; m->spriteTime = rand() % 180;
e->action = nothing; m->action = nothing;
e->reset = reset; m->reset = reset;
e->tick = tick; m->tick = tick;
e->touch = touch; m->touch = touch;
e->isMissionTarget = 1; m->isMissionTarget = 1;
} }
void reinitMIA(Entity *e) void reinitMIA(Entity *e)
@ -64,56 +70,72 @@ static void reset(void)
static void tick(void) static void tick(void)
{ {
self->shudderTimer--; MIA *m;
if (self->shudderTimer <= 0)
m = (MIA*)self;
m->shudderTimer--;
if (m->shudderTimer <= 0)
{ {
self->x = (self->tx + rand() % 4); m->x = (m->tx + rand() % 4);
self->shudderTimer = 2; m->shudderTimer = 2;
} }
if (self->action != nothing) if (m->action != nothing)
{ {
self->starTimer--; m->starTimer--;
if (self->starTimer <= 0) if (m->starTimer <= 0)
{ {
addMIATeleportStars(self->x + rand() % self->w, self->y + rand() % self->h); addMIATeleportStars(m->x + rand() % m->w, m->y + rand() % m->h);
self->starTimer = 1; m->starTimer = 1;
} }
} }
} }
static void touch(Entity *other) static void touch(Entity *other)
{ {
if (self->action == nothing && other == world.bob) MIA *m;
m = (MIA*)self;
if (m->action == nothing && other == (Entity*)world.bob)
{ {
self->action = preTeleport; m->action = preTeleport;
self->teleportTimer = FPS * 3; m->teleportTimer = FPS * 3;
setGameplayMessage(MSG_OBJECTIVE, "Rescued %s", self->name); setGameplayMessage(MSG_OBJECTIVE, "Rescued %s", m->name);
self->isMissionTarget = 0; m->isMissionTarget = 0;
self->flags |= EF_ALWAYS_PROCESS; m->flags |= EF_ALWAYS_PROCESS;
playSound(SND_MIA, CH_ANY); playSound(SND_MIA, CH_ANY);
} }
} }
static void preTeleport(void) static void preTeleport(void)
{ {
self->teleportTimer--; MIA *m;
if (self->teleportTimer <= FPS)
m = (MIA*)self;
m->teleportTimer--;
if (m->teleportTimer <= FPS)
{ {
self->action = teleport; m->action = teleport;
self->flags |= (EF_NO_CLIP | EF_WEIGHTLESS); m->flags |= (EF_NO_CLIP | EF_WEIGHTLESS);
self->dy = -5; m->dy = -5;
} }
} }
static void teleport(void) static void teleport(void)
{ {
self->teleportTimer--; MIA *m;
if (self->teleportTimer <= 0)
m = (MIA*)self;
m->teleportTimer--;
if (m->teleportTimer <= 0)
{ {
addTeleportStars(self); addTeleportStars(self);
addRescuedMIA(self->name); addRescuedMIA(m->name);
updateObjective("MIA"); updateObjective("MIA");
self->alive = ALIVE_DEAD; m->alive = ALIVE_DEAD;
} }
} }

View File

@ -28,6 +28,7 @@ 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 void addRescuedMIA(char *name);
extern void initUnit(Entity *e);
extern Entity *self; extern Entity *self;
extern World world; extern World world;

View File

@ -31,23 +31,29 @@ static int exitMission;
void initTeeka(Entity *e) void initTeeka(Entity *e)
{ {
e->type = ET_TEEKA; Unit *u;
initUnit(e);
u = (Unit*)e;
u->type = ET_TEEKA;
u->flags |= EF_IMMUNE;
u->action = lookForEnemies;
u->weaponType = WPN_AIMED_PISTOL;
u->sprite[FACING_LEFT] = getSpriteIndex("TeekaLeft");
u->sprite[FACING_RIGHT] = getSpriteIndex("TeekaRight");
u->sprite[FACING_DIE] = getSpriteIndex("TeekaLeft");
u->health = e->healthMax = 9999;
u->tick = tick;
aimedSprite = getSpriteIndex("AimedShot"); aimedSprite = getSpriteIndex("AimedShot");
e->flags |= EF_IMMUNE;
e->action = lookForEnemies;
e->weaponType = WPN_AIMED_PISTOL;
e->sprite[FACING_LEFT] = getSpriteIndex("TeekaLeft");
e->sprite[FACING_RIGHT] = getSpriteIndex("TeekaRight");
e->sprite[FACING_DIE] = getSpriteIndex("TeekaLeft");
e->health = e->healthMax = 9999;
e->tick = tick;
} }
static void tick(void) static void tick(void)
@ -73,8 +79,11 @@ static void lookForEnemies(void)
{ {
Entity *e; Entity *e;
float distance, range; float distance, range;
Unit *u;
self->thinkTime = rrnd(FPS / 2, FPS); u = (Unit*)self;
u->thinkTime = rrnd(FPS / 2, FPS);
target = NULL; target = NULL;
@ -84,7 +93,7 @@ static void lookForEnemies(void)
{ {
if (e->type == ET_ENEMY) if (e->type == ET_ENEMY)
{ {
range = getDistance(self->x, self->y, e->x, e->y); range = getDistance(u->x, u->y, e->x, e->y);
if (range < distance) if (range < distance)
{ {
@ -99,41 +108,45 @@ static void lookForEnemies(void)
if (target != NULL) if (target != NULL)
{ {
self->shotsToFire = rrnd(3, 5); u->shotsToFire = rrnd(3, 5);
self->action = preFire; u->action = preFire;
} }
else if (exitMission) else if (exitMission)
{ {
addTeleportStars(self); addTeleportStars(self);
self->alive = ALIVE_DEAD; u->alive = ALIVE_DEAD;
playSound(SND_APPEAR, CH_ANY); playSound(SND_APPEAR, CH_ANY);
} }
else else
{ {
self->facing = rand() % 2 == 0 ? FACING_LEFT : FACING_RIGHT; u->facing = rand() % 2 == 0 ? FACING_LEFT : FACING_RIGHT;
} }
} }
static void preFire(void) static void preFire(void)
{ {
if (self->reload > 0) Unit *u;
u = (Unit*)self;
if (u->reload > 0)
{ {
return; return;
} }
if (target->y < self->y && self->isOnGround && rand() % 10 == 0) if (target->y < u->y && u->isOnGround && rand() % 10 == 0)
{ {
self->dy = JUMP_POWER; u->dy = JUMP_POWER;
} }
attack(); attack();
self->shotsToFire--; u->shotsToFire--;
if (self->shotsToFire == 0) if (u->shotsToFire == 0)
{ {
self->thinkTime = FPS; u->thinkTime = FPS;
} }
} }
@ -144,7 +157,7 @@ static void attack(void)
getSlope(target->x, target->y, self->x, self->y, &dx, &dy); getSlope(target->x, target->y, self->x, self->y, &dx, &dy);
bullet = createBaseBullet(self); bullet = createBaseBullet((Unit*)self);
bullet->x = self->x; bullet->x = self->x;
bullet->y = (self->y + self->h / 2) - 3; bullet->y = (self->y + self->h / 2) - 3;
bullet->facing = self->facing; bullet->facing = self->facing;
@ -157,7 +170,7 @@ static void attack(void)
bullet->sprite[0] = bullet->sprite[1] = aimedSprite; bullet->sprite[0] = bullet->sprite[1] = aimedSprite;
bullet->health *= 2; bullet->health *= 2;
self->reload = 5; ((Unit*)self)->reload = 5;
} }
void teekaExitMission(void) void teekaExitMission(void)

View File

@ -20,10 +20,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../../../common.h" #include "../../../common.h"
extern void initUnit(Entity *e);
extern void unitTick(void); extern void unitTick(void);
extern int getSpriteIndex(char *name); extern int getSpriteIndex(char *name);
extern int rrnd(int low, int high); extern int rrnd(int low, int high);
extern Bullet *createBaseBullet(Entity *owner); extern Bullet *createBaseBullet(Unit *owner);
extern void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy); extern void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy);
extern int getDistance(int x1, int y1, int x2, int y2); extern int getDistance(int x1, int y1, int x2, int y2);
extern int hasLineOfSight(Entity *src, Entity *dest); extern int hasLineOfSight(Entity *src, Entity *dest);

View File

@ -22,13 +22,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void initBlaze(Entity *e) void initBlaze(Entity *e)
{ {
initBlobBoss(e); Boss *b;
e->weakAgainst = ENV_WATER; b = (Boss*)e;
STRNCPY(e->name, "Blaze", MAX_NAME_LENGTH); initBlobBoss(b);
b->weakAgainst = ENV_WATER;
STRNCPY(b->name, "Blaze", MAX_NAME_LENGTH);
e->sprite[FACING_LEFT] = getSpriteIndex("BlazeLeft"); b->sprite[FACING_LEFT] = getSpriteIndex("BlazeLeft");
e->sprite[FACING_RIGHT] = getSpriteIndex("BlazeRight"); b->sprite[FACING_RIGHT] = getSpriteIndex("BlazeRight");
e->sprite[FACING_DIE] = getSpriteIndex("BlazeSpin"); b->sprite[FACING_DIE] = getSpriteIndex("BlazeSpin");
} }

View File

@ -20,5 +20,5 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../../../common.h" #include "../../../common.h"
extern void initBlobBoss(Entity *e); extern void initBlobBoss(Boss *b);
extern int getSpriteIndex(char *name); extern int getSpriteIndex(char *name);

View File

@ -38,24 +38,28 @@ static int aimedSprite;
void initBlobBoss(Entity *e) void initBlobBoss(Entity *e)
{ {
Boss *b;
initBoss(e); initBoss(e);
b = (Boss*)e;
b->flags |= EF_HALT_AT_EDGE;
b->health = b->healthMax = 250;
b->teleportTimer = FPS * rrnd(4, 6);
b->activate = activate;
b->walk = walk;
b->tick = tick;
b->changeEnvironment = changeEnvironment;
b->getCurrentSprite = getCurrentSprite;
b->animate = animate;
b->applyDamage = applyDamage;
b->die = die1;
aimedSprite = getSpriteIndex("AimedShot"); aimedSprite = getSpriteIndex("AimedShot");
e->flags |= EF_HALT_AT_EDGE;
e->health = e->healthMax = 250;
e->teleportTimer = FPS * rrnd(4, 6);
e->activate = activate;
e->walk = walk;
e->tick = tick;
e->changeEnvironment = changeEnvironment;
e->getCurrentSprite = getCurrentSprite;
e->animate = animate;
e->applyDamage = applyDamage;
e->die = die1;
} }
static void activate(int activate) static void activate(int activate)
@ -74,32 +78,36 @@ static void activate(int activate)
static void tick(void) static void tick(void)
{ {
if (self->health > 0) Boss *b;
b = (Boss*)self;
if (b->health > 0)
{ {
self->stunTimer = MAX(self->stunTimer - 1, 0); b->stunTimer = MAX(b->stunTimer - 1, 0);
if (self->environment == self->weakAgainst) if (b->environment == b->weakAgainst)
{ {
self->health -= 2; b->health -= 2;
world.boss = self; world.boss = b;
} }
if (self->stunTimer == 0) if (b->stunTimer == 0)
{ {
self->facing = (world.bob->x < self->x) ? FACING_LEFT : FACING_RIGHT; b->facing = (world.bob->x < b->x) ? FACING_LEFT : FACING_RIGHT;
self->reload = limit(--self->reload, 0, FPS); b->reload = limit(--b->reload, 0, FPS);
self->teleportTimer = limit(self->teleportTimer - 1, 0, 9999); b->teleportTimer = limit(b->teleportTimer - 1, 0, 9999);
if (self->isOnGround) if (b->isOnGround)
{ {
self->flags |= EF_HALT_AT_EDGE; b->flags |= EF_HALT_AT_EDGE;
} }
else else
{ {
self->flags &= ~EF_HALT_AT_EDGE; b->flags &= ~EF_HALT_AT_EDGE;
} }
} }
} }
@ -107,35 +115,43 @@ static void tick(void)
static void changeEnvironment() static void changeEnvironment()
{ {
if (self->environment == self->weakAgainst) Boss *b;
b = (Boss*)self;
if (b->environment == b->weakAgainst)
{ {
self->teleportTimer = 0; b->teleportTimer = 0;
self->stunTimer = 90; b->stunTimer = 90;
self->spriteFrame = self->spriteTime = 0; b->spriteFrame = b->spriteTime = 0;
} }
else else
{ {
self->teleportTimer = 0; b->teleportTimer = 0;
} }
} }
static void die1(void) static void die1(void)
{ {
self->flags |= EF_BOUNCES; Boss *b;
b = (Boss*)self;
b->flags |= EF_BOUNCES;
self->thinkTime = 0; b->thinkTime = 0;
self->spriteTime = 0; b->spriteTime = 0;
self->spriteFrame = 0; b->spriteFrame = 0;
if (self->environment == ENV_AIR) if (b->environment == ENV_AIR)
{ {
self->dy = -9; b->dy = -9;
} }
self->dx = (randF() - randF()) * 5; b->dx = (randF() - randF()) * 5;
self->flags &= ~EF_HALT_AT_EDGE; b->flags &= ~EF_HALT_AT_EDGE;
switch (rand() % 3) switch (rand() % 3)
{ {
@ -152,22 +168,30 @@ static void die1(void)
break; break;
} }
self->action = die2; b->action = die2;
} }
static int getCurrentSprite(void) static int getCurrentSprite(void)
{ {
if (self->stunTimer > 0 || self->health <= 0) Boss *b;
b = (Boss*)self;
if (b->stunTimer > 0 || b->health <= 0)
{ {
return self->sprite[FACING_DIE]; return b->sprite[FACING_DIE];
} }
return self->sprite[self->facing]; return b->sprite[b->facing];
} }
static void animate(void) static void animate(void)
{ {
if (self->dx != 0 || self->health <= 0 || self->stunTimer > 0) Boss *b;
b = (Boss*)self;
if (b->dx != 0 || b->health <= 0 || b->stunTimer > 0)
{ {
animateEntity(self); animateEntity(self);
} }
@ -175,9 +199,13 @@ static void animate(void)
static void lookForPlayer(void) static void lookForPlayer(void)
{ {
self->thinkTime = rrnd(0, FPS / 2); Boss *b;
b = (Boss*)self;
b->thinkTime = rrnd(0, FPS / 2);
if (getDistance(world.bob->x, world.bob->y, self->x, self->y) > 650) if (getDistance(world.bob->x, world.bob->y, b->x, b->y) > 650)
{ {
moveTowardsPlayer(); moveTowardsPlayer();
return; return;
@ -191,8 +219,8 @@ static void lookForPlayer(void)
if (rand() % 100 < 15) if (rand() % 100 < 15)
{ {
self->shotsToFire = rrnd(1, 12); b->shotsToFire = rrnd(1, 12);
self->action = preFire; b->action = preFire;
} }
moveTowardsPlayer(); moveTowardsPlayer();
@ -200,48 +228,56 @@ static void lookForPlayer(void)
static void moveTowardsPlayer(void) static void moveTowardsPlayer(void)
{ {
self->dx = 0; Boss *b;
b = (Boss*)self;
b->dx = 0;
if (rand() % 100 < 20) if (rand() % 100 < 20)
{ {
if (world.bob->x < self->x) if (world.bob->x < b->x)
{ {
self->dx = -3.5; b->dx = -3.5;
} }
if (world.bob->x > self->x) if (world.bob->x > b->x)
{ {
self->dx = 3.5; b->dx = 3.5;
} }
if (world.bob->y <= self->y && rand() % 2 == 0 && self->isOnGround) if (world.bob->y <= b->y && rand() % 2 == 0 && b->isOnGround)
{ {
self->dy = JUMP_POWER; b->dy = JUMP_POWER;
} }
} }
if (self->stunTimer == 0 && self->teleportTimer == 0) if (b->stunTimer == 0 && b->teleportTimer == 0)
{ {
teleport(); teleport();
self->teleportTimer = FPS * rrnd(4, 6); b->teleportTimer = FPS * rrnd(4, 6);
} }
} }
static void preFire(void) static void preFire(void)
{ {
if (self->reload > 0) Boss *b;
b = (Boss*)self;
if (b->reload > 0)
{ {
return; return;
} }
attack(); attack();
self->shotsToFire--; b->shotsToFire--;
if (self->shotsToFire == 0) if (b->shotsToFire == 0)
{ {
self->walk(); b->walk();
} }
} }
@ -256,7 +292,7 @@ static void attack(void)
getSlope(bx, by, self->x, self->y, &dx, &dy); getSlope(bx, by, self->x, self->y, &dx, &dy);
bullet = createBaseBullet(self); bullet = createBaseBullet((Unit*)self);
bullet->x = self->x; bullet->x = self->x;
bullet->y = (self->y + self->h / 2) - 3; bullet->y = (self->y + self->h / 2) - 3;
bullet->facing = self->facing; bullet->facing = self->facing;
@ -268,7 +304,7 @@ static void attack(void)
bullet->dy = dy * 12; bullet->dy = dy * 12;
bullet->sprite[0] = bullet->sprite[1] = aimedSprite; bullet->sprite[0] = bullet->sprite[1] = aimedSprite;
self->reload = 4; ((Boss*)self)->reload = 4;
playSound(SND_MACHINE_GUN, CH_WEAPON); playSound(SND_MACHINE_GUN, CH_WEAPON);
} }
@ -315,7 +351,7 @@ static void applyDamage(int amount)
teleport(); teleport();
} }
world.boss = self; world.boss = (Boss*)self;
} }
static void teleport(void) static void teleport(void)
@ -329,19 +365,23 @@ static void teleport(void)
static void die2(void) static void die2(void)
{ {
self->health--; Boss *b;
b = (Boss*)self;
b->health--;
if (self->health <= -FPS) if (b->health <= -FPS)
{ {
addTeleportStars(self); addTeleportStars(self);
playSound(SND_APPEAR, CH_ANY); playSound(SND_APPEAR, CH_ANY);
self->alive = ALIVE_DEAD; b->alive = ALIVE_DEAD;
updateObjective(self->name); updateObjective(b->name);
addDefeatedTarget(self->name); addDefeatedTarget(b->name);
game.enemiesKilled++; game.enemiesKilled++;
} }

View File

@ -29,7 +29,7 @@ extern float limit(float i, float a, float b);
extern double randF(void); extern double randF(void);
extern void playSound(int snd, int ch); extern void playSound(int snd, int ch);
extern void animateEntity(Entity *e); extern void animateEntity(Entity *e);
extern Bullet *createBaseBullet(Entity *owner); extern Bullet *createBaseBullet(Unit *owner);
extern int getSpriteIndex(char *name); extern int getSpriteIndex(char *name);
extern int getDistance(int x1, int y1, int x2, int y2); 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 void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy);

View File

@ -22,18 +22,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void initBoss(Entity *e) void initBoss(Entity *e)
{ {
Boss *b;
initEntity(e); initEntity(e);
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex("Boss"); b = (Boss*)e;
e->isMissionTarget = 1; b->sprite[FACING_LEFT] = b->sprite[FACING_RIGHT] = b->sprite[FACING_DIE] = getSpriteIndex("Boss");
b->isMissionTarget = 1;
e->action = lookForPlayer; b->action = lookForPlayer;
e->spriteFrame = 0; b->spriteFrame = 0;
e->spriteTime = 0; b->spriteTime = 0;
world.boss = e; world.boss = b;
e->flags |= EF_ALWAYS_PROCESS | EF_BOMB_SHIELD | EF_GONE; b->flags |= EF_ALWAYS_PROCESS | EF_BOMB_SHIELD | EF_GONE;
} }

View File

@ -42,23 +42,27 @@ static int plasmaSprite[2];
void initEyeDroidCommander(Entity *e) void initEyeDroidCommander(Entity *e)
{ {
Boss *b;
initBoss(e); initBoss(e);
STRNCPY(e->name, "EyeDroid Commander", MAX_NAME_LENGTH); b = (Boss*)e;
e->sprite[FACING_LEFT] = getSpriteIndex("DroidCommanderLeft");
e->sprite[FACING_RIGHT] = getSpriteIndex("DroidCommanderRight");
e->sprite[FACING_DIE] = getSpriteIndex("DroidCommanderDie");
e->flags |= EF_WEIGHTLESS | EF_EXPLODES; STRNCPY(b->name, "EyeDroid Commander", MAX_NAME_LENGTH);
e->health = e->healthMax = 250; b->sprite[FACING_LEFT] = getSpriteIndex("DroidCommanderLeft");
b->sprite[FACING_RIGHT] = getSpriteIndex("DroidCommanderRight");
b->sprite[FACING_DIE] = getSpriteIndex("DroidCommanderDie");
e->walk = walk; b->flags |= EF_WEIGHTLESS | EF_EXPLODES;
e->tick = tick;
e->activate = activate; b->health = b->healthMax = 250;
e->applyDamage = applyDamage;
e->getCurrentSprite = getCurrentSprite; b->walk = walk;
b->tick = tick;
b->activate = activate;
b->applyDamage = applyDamage;
b->getCurrentSprite = getCurrentSprite;
brakingTimer = 0; brakingTimer = 0;
@ -84,23 +88,27 @@ static void activate(int activate)
static void tick(void) static void tick(void)
{ {
if (self->health > 0) Boss *b;
b = (Boss*)self;
if (b->health > 0)
{ {
self->facing = (world.bob->x < self->x) ? FACING_LEFT : FACING_RIGHT; b->facing = (world.bob->x < b->x) ? FACING_LEFT : FACING_RIGHT;
self->reload = (int) limit(self->reload - 1, 0, FPS); b->reload = (int) limit(b->reload - 1, 0, FPS);
brakingTimer = (int) limit(--brakingTimer, 0, FPS); brakingTimer = (int) limit(--brakingTimer, 0, FPS);
if (brakingTimer > 0) if (brakingTimer > 0)
{ {
self->dx *= 0.95; b->dx *= 0.95;
self->dy *= 0.95; b->dy *= 0.95;
} }
} }
else else
{ {
addSmokeParticles(self->x + (self->w / 2), self->y); addSmokeParticles(b->x + (b->w / 2), b->y);
} }
} }
@ -135,23 +143,27 @@ static void lookForPlayer(void)
static void selectWeapon(void) static void selectWeapon(void)
{ {
Boss *b;
b = (Boss*)self;
if (world.bob->isOnGround || abs(self->y - world.bob->y) > 64) if (world.bob->isOnGround || abs(self->y - world.bob->y) > 64)
{ {
self->weaponType = WPN_AIMED_PISTOL; b->weaponType = WPN_AIMED_PISTOL;
self->shotsToFire = rrnd(1, 12); b->shotsToFire = rrnd(1, 12);
self->action = preFire; b->action = preFire;
} }
else if (rand() % 4 == 0) else if (rand() % 4 == 0)
{ {
self->weaponType = WPN_MISSILE; b->weaponType = WPN_MISSILE;
self->shotsToFire = rrnd(1, 3); b->shotsToFire = rrnd(1, 3);
self->action = preFire; b->action = preFire;
} }
else else
{ {
self->weaponType = WPN_PLASMA; b->weaponType = WPN_PLASMA;
self->shotsToFire = rrnd(1, 12); b->shotsToFire = rrnd(1, 12);
self->action = preFire; b->action = preFire;
} }
} }
@ -191,24 +203,32 @@ static void moveTowardsPlayer(void)
static void preFire(void) static void preFire(void)
{ {
if (self->reload > 0) Boss *b;
b = (Boss*)self;
if (b->reload > 0)
{ {
return; return;
} }
attack(); attack();
self->shotsToFire--; b->shotsToFire--;
if (self->shotsToFire == 0) if (b->shotsToFire == 0)
{ {
self->walk(); b->walk();
} }
} }
static void attack(void) static void attack(void)
{ {
switch (self->weaponType) Boss *b;
b = (Boss*)self;
switch (b->weaponType)
{ {
case WPN_AIMED_PISTOL: case WPN_AIMED_PISTOL:
attackPistol(); attackPistol();
@ -229,13 +249,16 @@ static void attackPistol(void)
int bx, by; int bx, by;
float dx, dy; float dx, dy;
Bullet *bullet; Bullet *bullet;
Boss *b;
b = (Boss*)self;
bx = world.bob->x + rrnd(-8, 24); bx = world.bob->x + rrnd(-8, 24);
by = world.bob->y + rrnd(-8, 24); by = world.bob->y + rrnd(-8, 24);
getSlope(bx, by, self->x, self->y, &dx, &dy); getSlope(bx, by, self->x, self->y, &dx, &dy);
bullet = createBaseBullet(self); bullet = createBaseBullet((Unit*)self);
bullet->x = (self->x + self->w / 2); bullet->x = (self->x + self->w / 2);
bullet->y = (self->y + self->h / 2) - 3; bullet->y = (self->y + self->h / 2) - 3;
bullet->facing = self->facing; bullet->facing = self->facing;
@ -247,16 +270,19 @@ static void attackPistol(void)
bullet->dy = dy * 12; bullet->dy = dy * 12;
bullet->sprite[0] = bullet->sprite[1] = aimedSprite; bullet->sprite[0] = bullet->sprite[1] = aimedSprite;
self->reload = 4; b->reload = 4;
playSound(SND_MACHINE_GUN, CH_WEAPON); playSound(SND_MACHINE_GUN, CH_WEAPON);
} }
static void attackPlasma(void) static void attackPlasma(void)
{ {
Boss *b;
Bullet *bullet; Bullet *bullet;
bullet = createBaseBullet(self); b = (Boss*)self;
bullet = createBaseBullet((Unit*)self);
bullet->x = (self->x + self->w / 2); bullet->x = (self->x + self->w / 2);
bullet->y = (self->y + self->h / 2) - 3; bullet->y = (self->y + self->h / 2) - 3;
bullet->facing = self->facing; bullet->facing = self->facing;
@ -269,26 +295,29 @@ static void attackPlasma(void)
bullet->sprite[0] = plasmaSprite[0]; bullet->sprite[0] = plasmaSprite[0];
bullet->sprite[1] = plasmaSprite[1]; bullet->sprite[1] = plasmaSprite[1];
self->reload = 4; b->reload = 4;
playSound(SND_PLASMA, CH_WEAPON); playSound(SND_PLASMA, CH_WEAPON);
} }
static void attackMissile(void) static void attackMissile(void)
{ {
Boss *b;
Bullet *missile; Bullet *missile;
missile = createBaseBullet(self); b = (Boss*)self;
missile->x = self->x + self->w / 2;
missile->y = self->y + self->h / 2; missile = createBaseBullet((Unit*)self);
missile->facing = self->facing; missile->x = b->x + b->w / 2;
missile->dx = self->facing == FACING_RIGHT ? 15 : -15; missile->y = b->y + b->h / 2;
missile->facing = b->facing;
missile->dx = b->facing == FACING_RIGHT ? 15 : -15;
missile->owner = self; missile->owner = self;
missile->health = FPS * 3; missile->health = FPS * 3;
missile->sprite[0] = missileSprite[0]; missile->sprite[0] = missileSprite[0];
missile->sprite[1] = missileSprite[1]; missile->sprite[1] = missileSprite[1];
self->reload = 15; b->reload = 15;
playSound(SND_MISSILE, CH_WEAPON); playSound(SND_MISSILE, CH_WEAPON);
} }
@ -306,16 +335,20 @@ static void applyDamage(int amount)
static void die1(void) static void die1(void)
{ {
self->dx = (randF() - randF()) * 3; Boss *b;
b = (Boss*)self;
b->dx = (randF() - randF()) * 3;
self->spriteTime = 0; b->spriteTime = 0;
self->spriteFrame = 0; b->spriteFrame = 0;
self->action = die2; b->action = die2;
self->thinkTime = 0; b->thinkTime = 0;
self->flags &= ~(EF_WEIGHTLESS | EF_HALT_AT_EDGE); b->flags &= ~(EF_WEIGHTLESS | EF_HALT_AT_EDGE);
self->dy = JUMP_POWER; b->dy = JUMP_POWER;
if (rand() % 2) if (rand() % 2)
{ {
@ -329,17 +362,21 @@ static void die1(void)
static void die2() static void die2()
{ {
if (self->isOnGround) Boss *b;
b = (Boss*)self;
if (b->isOnGround)
{ {
addTeleportStars(self); addTeleportStars(self);
playSound(SND_APPEAR, CH_ANY); playSound(SND_APPEAR, CH_ANY);
self->alive = ALIVE_DEAD; b->alive = ALIVE_DEAD;
updateObjective(self->name); updateObjective(b->name);
addDefeatedTarget(self->name); addDefeatedTarget(b->name);
game.enemiesKilled++; game.enemiesKilled++;
} }

View File

@ -33,7 +33,7 @@ extern void addDefeatedTarget(char *name);
extern void updateObjective(char *targetName); extern void updateObjective(char *targetName);
extern double randF(void); extern double randF(void);
extern void playSound(int snd, int ch); extern void playSound(int snd, int ch);
extern Bullet *createBaseBullet(Entity *owner); extern Bullet *createBaseBullet(Unit *owner);
extern void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy); extern void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy);
extern void addExplosion(float x, float y, int radius, Entity *owner); extern void addExplosion(float x, float y, int radius, Entity *owner);

View File

@ -22,13 +22,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void initFrost(Entity *e) void initFrost(Entity *e)
{ {
Boss *b;
initBlobBoss(e); initBlobBoss(e);
e->weakAgainst = ENV_LAVA; b = (Boss*)e;
STRNCPY(e->name, "Frost", MAX_NAME_LENGTH); b->weakAgainst = ENV_LAVA;
STRNCPY(b->name, "Frost", MAX_NAME_LENGTH);
e->sprite[FACING_LEFT] = getSpriteIndex("FrostLeft"); b->sprite[FACING_LEFT] = getSpriteIndex("FrostLeft");
e->sprite[FACING_RIGHT] = getSpriteIndex("FrostRight"); b->sprite[FACING_RIGHT] = getSpriteIndex("FrostRight");
e->sprite[FACING_DIE] = getSpriteIndex("FrostSpin"); b->sprite[FACING_DIE] = getSpriteIndex("FrostSpin");
} }

View File

@ -29,7 +29,7 @@ static void die1(void);
static void die2(void); static void die2(void);
static void attack(void); static void attack(void);
static void applyDamage(int amount); static void applyDamage(int amount);
static SDL_Rect getBounds(void); static SDL_Rect *getBounds(void);
static void preFire(void); static void preFire(void);
static void selectWeapon(void); static void selectWeapon(void);
static void moveTowardsPlayer(void); static void moveTowardsPlayer(void);
@ -41,28 +41,32 @@ static int aimedSprite;
void initTankCommander(Entity *e) void initTankCommander(Entity *e)
{ {
Boss *b;
initBoss(e); initBoss(e);
b = (Boss*)e;
STRNCPY(e->name, "Tank Commander", MAX_NAME_LENGTH); STRNCPY(e->name, "Tank Commander", MAX_NAME_LENGTH);
e->sprite[FACING_LEFT] = getSpriteIndex("TankCommanderLeft"); b->sprite[FACING_LEFT] = getSpriteIndex("TankCommanderLeft");
e->sprite[FACING_RIGHT] = getSpriteIndex("TankCommanderRight"); b->sprite[FACING_RIGHT] = getSpriteIndex("TankCommanderRight");
e->sprite[FACING_DIE] = getSpriteIndex("TankCommanderDie"); b->sprite[FACING_DIE] = getSpriteIndex("TankCommanderDie");
e->flags |= EF_EXPLODES; b->flags |= EF_EXPLODES;
e->health = e->healthMax = 400; b->health = e->healthMax = 400;
e->activate = activate; b->activate = activate;
e->walk = walk; b->walk = walk;
e->tick = tick; b->tick = tick;
e->die = die1; b->die = die1;
e->applyDamage = applyDamage; b->applyDamage = applyDamage;
e->getBounds = getBounds; b->getBounds = getBounds;
brakingTimer = 0; brakingTimer = 0;
world.boss = e; world.boss = b;
aimedSprite = getSpriteIndex("AimedShot"); aimedSprite = getSpriteIndex("AimedShot");
@ -74,7 +78,11 @@ void initTankCommander(Entity *e)
static void activate(int activate) static void activate(int activate)
{ {
self->flags &= ~EF_GONE; Boss *b;
b = (Boss*)self;
b->flags &= ~EF_GONE;
tankTrack->flags &= ~EF_GONE; tankTrack->flags &= ~EF_GONE;
world.isBossActive = 1; world.isBossActive = 1;
@ -87,32 +95,40 @@ static void activate(int activate)
static void tick(void) static void tick(void)
{ {
if (self->health > 0) Boss *b;
b = (Boss*)self;
if (b->health > 0)
{ {
self->facing = (world.bob->x < self->x) ? FACING_LEFT : FACING_RIGHT; b->facing = (world.bob->x < b->x) ? FACING_LEFT : FACING_RIGHT;
self->reload = limit(self->reload - 1, 0, FPS); b->reload = limit(b->reload - 1, 0, FPS);
brakingTimer = limit(brakingTimer - 1, 0, FPS); brakingTimer = limit(brakingTimer - 1, 0, FPS);
if (brakingTimer > 0) if (brakingTimer > 0)
{ {
self->dx *= 0.9; b->dx *= 0.9;
self->dy *= 0.9; b->dy *= 0.9;
} }
} }
} }
static void lookForPlayer(void) static void lookForPlayer(void)
{ {
self->thinkTime = rrnd(0, FPS / 2); Boss *b;
b = (Boss*)self;
b->thinkTime = rrnd(0, FPS / 2);
if (rand() % 10 == 0) if (rand() % 10 == 0)
{ {
brakingTimer = rrnd(60, 120); brakingTimer = rrnd(60, 120);
} }
if (getDistance(world.bob->x, world.bob->y, self->x, self->y) > 650) if (getDistance(world.bob->x, world.bob->y, b->x, b->y) > 650)
{ {
moveTowardsPlayer(); moveTowardsPlayer();
return; return;
@ -157,23 +173,31 @@ static void moveTowardsPlayer(void)
static void selectWeapon(void) static void selectWeapon(void)
{ {
if (abs(self->y - world.bob->y) > 64) Boss *b;
b = (Boss*)self;
if (abs(b->y - world.bob->y) > 64)
{ {
self->weaponType = WPN_AIMED_PISTOL; b->weaponType = WPN_AIMED_PISTOL;
self->shotsToFire = rrnd(4, 12); b->shotsToFire = rrnd(4, 12);
self->action = preFire; b->action = preFire;
} }
else else
{ {
self->weaponType = WPN_MISSILE; b->weaponType = WPN_MISSILE;
self->shotsToFire = rrnd(1, 3); b->shotsToFire = rrnd(1, 3);
self->action = preFire; b->action = preFire;
} }
} }
static void preFire(void) static void preFire(void)
{ {
if (self->reload > 0) Boss *b;
b = (Boss*)self;
if (b->reload > 0)
{ {
moveTowardsPlayer(); moveTowardsPlayer();
return; return;
@ -181,17 +205,21 @@ static void preFire(void)
attack(); attack();
self->shotsToFire--; b->shotsToFire--;
if (self->shotsToFire == 0) if (b->shotsToFire == 0)
{ {
self->walk(); b->walk();
} }
} }
static void attack(void) static void attack(void)
{ {
switch (self->weaponType) Boss *b;
b = (Boss*)self;
switch (b->weaponType)
{ {
case WPN_AIMED_PISTOL: case WPN_AIMED_PISTOL:
attackPistol(); attackPistol();
@ -209,16 +237,19 @@ static void attackPistol(void)
int bx, by; int bx, by;
float dx, dy; float dx, dy;
Bullet *bullet; Bullet *bullet;
Boss *b;
b = (Boss*)self;
bx = world.bob->x + rrnd(-8, 24); bx = world.bob->x + rrnd(-8, 24);
by = world.bob->y + rrnd(-8, 24); by = world.bob->y + rrnd(-8, 24);
getSlope(bx, by, self->x, self->y, &dx, &dy); getSlope(bx, by, b->x, b->y, &dx, &dy);
bullet = createBaseBullet(self); bullet = createBaseBullet((Unit*)self);
bullet->x = (self->x + self->w / 2); bullet->x = (b->x + b->w / 2);
bullet->y = self->y + 30; bullet->y = b->y + 30;
bullet->facing = self->facing; bullet->facing = b->facing;
bullet->damage = 1; bullet->damage = 1;
bullet->owner = self; bullet->owner = self;
bullet->health = FPS * 3; bullet->health = FPS * 3;
@ -227,7 +258,7 @@ static void attackPistol(void)
bullet->dy = dy * 12; bullet->dy = dy * 12;
bullet->sprite[0] = bullet->sprite[1] = aimedSprite; bullet->sprite[0] = bullet->sprite[1] = aimedSprite;
self->reload = 4; b->reload = 4;
playSound(SND_MACHINE_GUN, CH_WEAPON); playSound(SND_MACHINE_GUN, CH_WEAPON);
} }
@ -235,12 +266,15 @@ static void attackPistol(void)
static void attackMissile(void) static void attackMissile(void)
{ {
Bullet *missile; Bullet *missile;
Boss *b;
b = (Boss*)self;
missile = createBaseBullet(self); missile = createBaseBullet((Unit*)self);
missile->x = self->x + self->w / 2; missile->x = b->x + b->w / 2;
missile->y = self->y + 30; missile->y = b->y + 30;
missile->facing = self->facing; missile->facing = b->facing;
missile->dx = self->facing == FACING_RIGHT ? 15 : -15; missile->dx = b->facing == FACING_RIGHT ? 15 : -15;
missile->dy = world.bob->y - missile->y; missile->dy = world.bob->y - missile->y;
missile->dy *= 0.01; missile->dy *= 0.01;
missile->owner = self; missile->owner = self;
@ -248,50 +282,57 @@ static void attackMissile(void)
missile->sprite[0] = missileSprite[0]; missile->sprite[0] = missileSprite[0];
missile->sprite[1] = missileSprite[1]; missile->sprite[1] = missileSprite[1];
self->reload = 15; b->reload = 15;
playSound(SND_MISSILE, CH_WEAPON); playSound(SND_MISSILE, CH_WEAPON);
} }
static void die1(void) static void die1(void)
{ {
self->flags |= EF_BOUNCES; Boss *b;
b = (Boss*)self;
b->flags |= EF_BOUNCES;
self->action = die2; b->action = die2;
self->thinkTime = 0; b->thinkTime = 0;
self->spriteTime = 0; b->spriteTime = 0;
self->spriteFrame = 0; b->spriteFrame = 0;
} }
static void die2(void) static void die2(void)
{ {
int mx, my; int mx, my;
Boss *b;
b = (Boss*)self;
self->health--; b->health--;
if (self->health % 3 == 0) if (b->health % 3 == 0)
{ {
mx = (int) ((self->x + (self->w / 2)) / MAP_TILE_SIZE); mx = (int) ((b->x + (b->w / 2)) / MAP_TILE_SIZE);
my = (int) ((self->y + self->h) / MAP_TILE_SIZE); my = (int) ((b->y + b->h) / MAP_TILE_SIZE);
addScorchDecal(mx, my); addScorchDecal(mx, my);
addExplosion(self->x + rand() % self->w, self->y + rand() % self->h, 50, self); addExplosion(b->x + rand() % b->w, b->y + rand() % b->h, 50, self);
} }
if (self->health <= -100) if (b->health <= -100)
{ {
addTeleportStars(self); addTeleportStars(self);
addTeleportStars(tankTrack); addTeleportStars(tankTrack);
playSound(SND_APPEAR, CH_ANY); playSound(SND_APPEAR, CH_ANY);
self->alive = tankTrack->alive = ALIVE_DEAD; b->alive = tankTrack->alive = ALIVE_DEAD;
updateObjective(self->name); updateObjective(b->name);
addDefeatedTarget(self->name); addDefeatedTarget(b->name);
game.enemiesKilled++; game.enemiesKilled++;
} }
@ -308,7 +349,7 @@ static void applyDamage(int amount)
} }
} }
static SDL_Rect getBounds(void) static SDL_Rect *getBounds(void)
{ {
if (self->facing == FACING_LEFT) if (self->facing == FACING_LEFT)
{ {
@ -325,5 +366,5 @@ static SDL_Rect getBounds(void)
self->bounds.h = self->h; self->bounds.h = self->h;
} }
return self->bounds; return &self->bounds;
} }

View File

@ -31,7 +31,7 @@ extern int enemyCanSeePlayer(Entity *e);
extern void addDefeatedTarget(char *name); extern void addDefeatedTarget(char *name);
extern void updateObjective(char *targetName); extern void updateObjective(char *targetName);
extern void playSound(int snd, int ch); extern void playSound(int snd, int ch);
extern Bullet *createBaseBullet(Entity *owner); extern Bullet *createBaseBullet(Unit *owner);
extern void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy); extern void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy);
extern void addExplosion(float x, float y, int radius, Entity *owner); extern void addExplosion(float x, float y, int radius, Entity *owner);
extern void addScorchDecal(int x, int y); extern void addScorchDecal(int x, int y);

View File

@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static Entity *tankCommander; static Entity *tankCommander;
static void tick(void); static void tick(void);
static void touch(Entity *other); static void touch(Entity *other);
static SDL_Rect getBounds(void); static SDL_Rect *getBounds(void);
static void animate(void); static void animate(void);
static void (*superAnimate)(void); static void (*superAnimate)(void);
@ -72,7 +72,7 @@ static void touch(Entity *other)
{ {
if (other != NULL) if (other != NULL)
{ {
if (other == world.bob && !world.bob->stunTimer && (world.bob->flags & EF_IMMUNE) == 0) if (other == (Entity*)world.bob && !world.bob->stunTimer && (world.bob->flags & EF_IMMUNE) == 0)
{ {
playSound(SND_FLESH_HIT, CH_ANY); playSound(SND_FLESH_HIT, CH_ANY);
world.bob->dx = rrnd(-5, 5); world.bob->dx = rrnd(-5, 5);
@ -88,14 +88,14 @@ static void touch(Entity *other)
} }
} }
static SDL_Rect getBounds(void) static SDL_Rect *getBounds(void)
{ {
self->bounds.x = self->x + 16; self->bounds.x = self->x + 16;
self->bounds.y = self->y; self->bounds.y = self->y;
self->bounds.w = self->w - 32; self->bounds.w = self->w - 32;
self->bounds.h = self->h; self->bounds.h = self->h;
return self->bounds; return &self->bounds;
} }
static void animate(void) static void animate(void)

View File

@ -24,36 +24,40 @@ static void applyDamage(int damage);
static void walk(void); static void walk(void);
static void die(void); static void die(void);
static void animate(void); static void animate(void);
static SDL_Rect getBounds(void); static SDL_Rect *getBounds(void);
static int canFire(Entity *target); static int canFire(Entity *target);
static void preFire(void); static void preFire(void);
void initCannon(Entity *e) void initCannon(Entity *e)
{ {
Unit *u;
initUnit(e); initUnit(e);
u = (Unit*)self;
e->sprite[FACING_LEFT] = getSpriteIndex("CannonLeft"); u->sprite[FACING_LEFT] = getSpriteIndex("CannonLeft");
e->sprite[FACING_RIGHT] = getSpriteIndex("CannonRight"); u->sprite[FACING_RIGHT] = getSpriteIndex("CannonRight");
e->sprite[FACING_DIE] = getSpriteIndex("CannonLeft"); u->sprite[FACING_DIE] = getSpriteIndex("CannonLeft");
e->weaponType = WPN_MISSILE; u->weaponType = WPN_MISSILE;
e->maxShotsToFire = 4; u->maxShotsToFire = 4;
e->reload = 0; u->reload = 0;
e->canCarryItem = 1; u->canCarryItem = 1;
e->health = e->healthMax = 50; u->health = u->healthMax = 50;
e->flags |= EF_EXPLODES; u->flags |= EF_EXPLODES;
e->animate = animate; u->animate = animate;
e->applyDamage = applyDamage; u->applyDamage = applyDamage;
e->walk = walk; u->walk = walk;
e->die = die; u->die = die;
e->getBounds= getBounds; u->getBounds= getBounds;
e->canFire = canFire; u->canFire = canFire;
} }
static void applyDamage(int damage) static void applyDamage(int damage)
@ -70,28 +74,31 @@ static void applyDamage(int damage)
static void die(void) static void die(void)
{ {
Unit *u;
int mx, my; int mx, my;
u = (Unit*)self;
self->health--; u->health--;
if (self->health % 3 == 0) if (u->health % 3 == 0)
{ {
mx = (int) ((self->x + (self->w / 2)) / MAP_TILE_SIZE); mx = (int) ((u->x + (u->w / 2)) / MAP_TILE_SIZE);
my = (int) ((self->y + self->h) / MAP_TILE_SIZE); my = (int) ((u->y + u->h) / MAP_TILE_SIZE);
addScorchDecal(mx, my); addScorchDecal(mx, my);
addExplosion(self->x, self->y, 50, self); addExplosion(u->x, u->y, 50, self);
} }
if (self->health <= -50) if (u->health <= -50)
{ {
updateObjective(self->name); updateObjective(u->name);
updateObjective("ENEMY"); updateObjective("ENEMY");
fireTriggers(self->name); fireTriggers(u->name);
dropCarriedItem(); dropCarriedItem();
self->alive = ALIVE_DEAD; u->alive = ALIVE_DEAD;
} }
} }
@ -104,9 +111,12 @@ static void patrol(void)
static void lookForPlayer(void) static void lookForPlayer(void)
{ {
Unit *u;
int r; int r;
u = (Unit*)self;
self->thinkTime = rrnd(FPS / 2, FPS); u->thinkTime = rrnd(FPS / 2, FPS);
if (world.state != WS_IN_PROGRESS || dev.cheatBlind) if (world.state != WS_IN_PROGRESS || dev.cheatBlind)
{ {
@ -114,13 +124,13 @@ static void lookForPlayer(void)
return; return;
} }
if ((self->facing == FACING_LEFT && world.bob->x > self->x) || (self->facing == FACING_RIGHT && world.bob->x < self->x)) if ((u->facing == FACING_LEFT && world.bob->x > u->x) || (u->facing == FACING_RIGHT && world.bob->x < u->x))
{ {
patrol(); patrol();
return; return;
} }
if (getDistance(world.bob->x, world.bob->y, self->x, self->y) > 650) if (getDistance(world.bob->x, world.bob->y, u->x, u->y) > 650)
{ {
patrol(); patrol();
return; return;
@ -134,34 +144,38 @@ static void lookForPlayer(void)
r = rand() % 100; r = rand() % 100;
if (self->isMissionTarget) if (u->isMissionTarget)
{ {
r = rand() % 20; r = rand() % 20;
} }
if (r < 15) if (r < 15)
{ {
self->shotsToFire = rrnd(1, self->maxShotsToFire); u->shotsToFire = rrnd(1, u->maxShotsToFire);
self->action = preFire; u->action = preFire;
} }
} }
static void preFire(void) static void preFire(void)
{ {
self->facing = (world.bob->x < self->x) ? FACING_LEFT : FACING_RIGHT; Unit *u;
u = (Unit*)self;
u->facing = (world.bob->x < u->x) ? FACING_LEFT : FACING_RIGHT;
if (self->reload > 0) if (u->reload > 0)
{ {
return; return;
} }
self->attack(); u->attack();
self->shotsToFire--; u->shotsToFire--;
if (self->shotsToFire == 0) if (u->shotsToFire == 0)
{ {
self->walk(); u->walk();
} }
} }
@ -175,14 +189,14 @@ static void animate(void)
} }
static SDL_Rect getBounds(void) static SDL_Rect *getBounds(void)
{ {
self->bounds.x = self->x + 36; self->bounds.x = self->x + 36;
self->bounds.y = self->y; self->bounds.y = self->y;
self->bounds.w = 36; self->bounds.w = 36;
self->bounds.h = self->h; self->bounds.h = self->h;
return self->bounds; return &self->bounds;
} }
static int canFire(Entity *target) static int canFire(Entity *target)

View File

@ -26,15 +26,19 @@ static void touch(Entity *other);
void initDebris(Entity *e) void initDebris(Entity *e)
{ {
Decoration *d;
initEntity(e); initEntity(e);
e->effectType = rand() % 2; d = (Decoration*)self;
d->effectType = rand() % 2;
e->flags |= EF_BOUNCES | EF_IGNORE_BULLETS | EF_KILL_OFFSCREEN | EF_NO_TELEPORT; d->flags |= EF_BOUNCES | EF_IGNORE_BULLETS | EF_KILL_OFFSCREEN | EF_NO_TELEPORT;
e->tick = tick; d->tick = tick;
e->action = action; d->action = action;
e->touch = touch; d->touch = touch;
} }
static void tick(void) static void tick(void)
@ -44,13 +48,17 @@ static void tick(void)
static void action(void) static void action(void)
{ {
if (self->effectType == 0) Decoration *d;
d = (Decoration*)self;
if (d->effectType == 0)
{ {
addFlameParticles(self->x + (rand() % self->w), self->y + (rand() % self->h)); addFlameParticles(d->x + (rand() % d->w), d->y + (rand() % d->h));
} }
else else
{ {
addSmokeParticles(self->x + (rand() % self->w), self->y + (rand() % self->h)); addSmokeParticles(d->x + (rand() % d->w), d->y + (rand() % d->h));
} }
self->thinkTime = 1; self->thinkTime = 1;
@ -58,8 +66,12 @@ static void action(void)
static void touch(Entity *other) static void touch(Entity *other)
{ {
Decoration *d;
d = (Decoration*)self;
if (other == NULL) if (other == NULL)
{ {
self->dx *= 0.9; d->dx *= 0.9;
} }
} }

View File

@ -26,31 +26,43 @@ static void touch(Entity *other);
void initFleshChunk(Entity *e) void initFleshChunk(Entity *e)
{ {
Decoration *d;
initEntity(e); initEntity(e);
d = (Decoration*)e;
e->flags |= EF_BOUNCES | EF_IGNORE_BULLETS | EF_KILL_OFFSCREEN | EF_NO_TELEPORT; d->flags |= EF_BOUNCES | EF_IGNORE_BULLETS | EF_KILL_OFFSCREEN | EF_NO_TELEPORT;
e->bleedTime = FPS * 3; d->bleedTime = FPS * 3;
e->tick = tick; d->tick = tick;
e->action = action; d->action = action;
e->touch = touch; d->touch = touch;
} }
static void tick(void) static void tick(void)
{ {
self->health--; Decoration *d;
self->bleedTime--;
d = (Decoration*)self;
d->health--;
d->bleedTime--;
} }
static void action(void) static void action(void)
{ {
if (self->bleedTime > 0) Decoration *d;
d = (Decoration*)self;
if (d->bleedTime > 0)
{ {
addBlood(self->x + (rand() % self->w), self->y + (rand() % self->h)); addBlood(d->x + (rand() % d->w), d->y + (rand() % d->h));
} }
self->thinkTime = 1; d->thinkTime = 1;
} }
static void touch(Entity *other) static void touch(Entity *other)

View File

@ -22,16 +22,71 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void animateEntity(void); void animateEntity(void);
static void applyDamage(int damage); static void applyDamage(int damage);
static float bounce(float x);
static SDL_Rect *getBounds(void);
Entity *createEntity(void) Entity *createEntity(int type)
{ {
Entity *e; Entity *e;
e = malloc(sizeof(Entity)); switch (type)
memset(e, 0, sizeof(Entity)); {
case ET_BOB:
e = malloc(sizeof(Bob));
memset(e, 0, sizeof(Bob));
break;
case ET_ENEMY:
case ET_TEEKA:
e = malloc(sizeof(Unit));
memset(e, 0, sizeof(Unit));
break;
case ET_BOSS:
e = malloc(sizeof(Boss));
memset(e, 0, sizeof(Boss));
break;
case ET_HEART_CELL:
case ET_KEY:
case ET_ITEM:
case ET_CONSUMABLE:
e = malloc(sizeof(Item));
memset(e, 0, sizeof(Item));
break;
case ET_MIA:
e = malloc(sizeof(MIA));
memset(e, 0, sizeof(MIA));
break;
case ET_DECORATION:
e = malloc(sizeof(Decoration));
memset(e, 0, sizeof(Decoration));
break;
case ET_DOOR:
case ET_LIFT:
case ET_PUSHBLOCK:
case ET_DESTRUCTABLE:
case ET_POWER_POINT:
case ET_CARD_READER:
case ET_PRESSURE_PLATE:
case ET_TELEPORTER:
case ET_ITEM_PAD:
case ET_POOL:
case ET_TRAP:
case ET_EXIT:
case ET_INFO_POINT:
e = malloc(sizeof(Structure));
memset(e, 0, sizeof(Structure));
break;
}
world.entityTail->next = e; world.entityTail->next = e;
world.entityTail = e; world.entityTail = e;
e->type = type;
e->uniqueId = game.entityCounter++; e->uniqueId = game.entityCounter++;
return e; return e;
@ -49,38 +104,31 @@ void initEntity(Entity *e)
e->isStatic = 0; e->isStatic = 0;
e->isMissionTarget = 0; e->isMissionTarget = 0;
e->health = e->healthMax = 1; e->health = 1;
e->facing = FACING_LEFT; e->facing = FACING_LEFT;
e->spriteFrame = -1;
e->spriteTime = 0;
e->dx = e->dy = 0;
e->flags = 0; e->flags = 0;
e->owner = NULL;
e->thinkTime = 0; e->thinkTime = 0;
e->plane = PLANE_BACKGROUND;
e->animate = animateEntity; e->animate = animateEntity;
e->applyDamage = applyDamage; e->applyDamage = applyDamage;
e->bounce = bounce;
e->getBounds = getBounds;
} }
SDL_Rect *getEntityBounds(Entity *e) static SDL_Rect *getBounds(void)
{ {
e->bounds.x = e->x; self->bounds.x = self->x;
e->bounds.y = e->y; self->bounds.y = self->y;
e->bounds.w = e->w; self->bounds.w = self->w;
e->bounds.h = e->h; self->bounds.h = self->h;
return &e->bounds; return &self->bounds;
} }
int getCurrentEntitySprite(Entity *e) int getCurrentEntitySprite(EntityExt *e)
{ {
if (e->alive == ALIVE_ALIVE) if (e->alive == ALIVE_ALIVE)
{ {
@ -92,39 +140,19 @@ int getCurrentEntitySprite(Entity *e)
void animateEntity(void) void animateEntity(void)
{ {
Sprite *spr;
if (self->spriteTime != -1)
{
self->spriteTime--;
if (self->spriteTime <= 0)
{
spr = getSpriteByIndex(getCurrentEntitySprite(self));
self->spriteFrame = wrap(self->spriteFrame + 1, 0, 1);
self->spriteTime = 0;
self->w = spr->w;
self->h = spr->h;
}
}
} }
void setEntitySize(Entity *e) void setEntitySize(Entity *e)
{ {
Sprite *spr;
spr = getSpriteByIndex(getCurrentEntitySprite(e));
e->w = spr->w;
e->h = spr->h;
} }
float bounce(Entity *e, float x) static float bounce(float x)
{ {
if (!(e->flags & EF_BOUNCES)) if (!(self->flags & EF_BOUNCES))
{ {
return 0; return 0;
} }
else if (e->flags & EF_FRICTIONLESS) else if (self->flags & EF_FRICTIONLESS)
{ {
return -x; return -x;
} }
@ -133,7 +161,7 @@ float bounce(Entity *e, float x)
if (x > -1 && x < 1) if (x > -1 && x < 1)
{ {
e->flags &= ~EF_BOUNCES; self->flags &= ~EF_BOUNCES;
x = 0; x = 0;
} }
@ -160,27 +188,29 @@ void teleportEntity(Entity *e, float tx, float ty)
static void applyDamage(int damage) static void applyDamage(int damage)
{ {
if (self->health < 0)
}
void dropCarriedItem(void)
{
EntityExt *e;
Item *i;
e = (EntityExt*)self;
if (e->carriedItem != NULL)
{ {
self->health = 0; i = e->carriedItem;
self->alive = ALIVE_ALIVE;
} i->x = (e->x + e->w / 2) - i->w / 2;
i->y = e->y;
self->health -= damage; i->dx = i->dy = 0;
if (self->health > 0) world.entityTail->next = (Entity*)i;
{ world.entityTail = (Entity*)i;
self->thinkTime = 0; world.entityTail->next = NULL;
self->facing = self->x < world.bob->x ? FACING_RIGHT : FACING_LEFT; e->carriedItem = NULL;
if (self->isMissionTarget && rand() % 10 == 0)
{
self->action = unitReappear;
self->flags |= EF_GONE;
self->thinkTime = rand() % FPS;
addTeleportStars(self);
playSound(SND_APPEAR, CH_ANY);
}
} }
} }

View File

@ -22,19 +22,27 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void initBattery(Entity *e) void initBattery(Entity *e)
{ {
Item *i;
initConsumable(e); initConsumable(e);
i = (Item*)e;
e->spriteFrame = 0; i->spriteFrame = 0;
e->spriteTime = -1; i->spriteTime = -1;
} }
void touch(Entity *other) void touch(Entity *other)
{ {
Item *i;
i = (Item*)self;
if (touchedPlayer(other)) if (touchedPlayer(other))
{ {
world.bob->power = MIN(world.bob->power + self->power, world.bob->powerMax); world.bob->power = MIN(world.bob->power + i->power, world.bob->powerMax);
setGameplayMessage(MSG_STANDARD, "Picked up a %s", self->name); setGameplayMessage(MSG_STANDARD, "Picked up a %s", i->name);
pickupItem(); pickupItem();

View File

@ -24,18 +24,22 @@ static void touch(Entity *other);
void initCell(Entity *e) void initCell(Entity *e)
{ {
Item *i;
initItem(e); initItem(e);
i = (Item*)self;
e->isMissionTarget = 1; i->isMissionTarget = 1;
STRNCPY(e->spriteName, "Battery", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "Battery", MAX_NAME_LENGTH);
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("Battery"); i->sprite[0] = i->sprite[1] = i->sprite[2] = getSpriteIndex("Battery");
e->spriteFrame = 0; i->spriteFrame = 0;
e->spriteTime = -1; i->spriteTime = -1;
e->touch = touch; i->touch = touch;
} }
static void touch(Entity *other) static void touch(Entity *other)

View File

@ -31,11 +31,15 @@ void initCherry(Entity *e)
static void touch(Entity *other) static void touch(Entity *other)
{ {
Item *i;
i = (Item*)self;
if (touchedPlayer(other)) if (touchedPlayer(other))
{ {
world.bob->health = limit(world.bob->health + self->value, 0, world.bob->healthMax); world.bob->health = limit(world.bob->health + i->value, 0, world.bob->healthMax);
setGameplayMessage(MSG_STANDARD, "Picked up a %s", self->name); setGameplayMessage(MSG_STANDARD, "Picked up a %s", i->name);
pickupItem(); pickupItem();

View File

@ -35,20 +35,24 @@ void initConsumable(Entity *e)
static void tick(void) static void tick(void)
{ {
if (self->isOnGround) Item *i;
i = (Item*)self;
if (i->isOnGround)
{ {
self->dx *= 0.05; i->dx *= 0.05;
} }
self->health--; i->health--;
if ((int) self->health == FPS * 2) if ((int) i->health == FPS * 2)
{ {
self->flags |= EF_FLICKER; i->flags |= EF_FLICKER;
} }
else if (self->health <= 0) else if (i->health <= 0)
{ {
self->alive = ALIVE_DEAD; i->alive = ALIVE_DEAD;
} }
} }
@ -59,12 +63,16 @@ int touchedPlayer(Entity *other)
void pickupItem(void) void pickupItem(void)
{ {
self->alive = (self->environment == ENV_AIR) ? ALIVE_DYING : ALIVE_DEAD; Item *i;
self->health = FPS / 2;
self->thinkTime = 0; i = (Item*)self;
self->dy = -2;
self->dx = 0; i->alive = (i->environment == ENV_AIR) ? ALIVE_DYING : ALIVE_DEAD;
self->flags |= EF_FLICKER | EF_WEIGHTLESS; i->health = FPS / 2;
i->thinkTime = 0;
i->dy = -2;
i->dx = 0;
i->flags |= EF_FLICKER | EF_WEIGHTLESS;
} }
static void die(void) static void die(void)

View File

@ -25,19 +25,23 @@ static void touch(Entity *other);
void initHeart(Entity *e) void initHeart(Entity *e)
{ {
Item *i;
initItem(e); initItem(e);
i = (Item*)e;
e->isMissionTarget = 1; i->isMissionTarget = 1;
STRNCPY(e->spriteName, "Heart", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "Heart", MAX_NAME_LENGTH);
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("Heart"); i->sprite[0] = i->sprite[1] = i->sprite[2] = getSpriteIndex("Heart");
e->spriteFrame = 0; i->spriteFrame = 0;
e->spriteTime = -1; i->spriteTime = -1;
e->action = action; i->action = action;
e->touch = touch; i->touch = touch;
} }
static void action(void) static void action(void)

View File

@ -25,36 +25,44 @@ static void tick(void);
static void touch(Entity *other); static void touch(Entity *other);
static void changeEnvironment(void); static void changeEnvironment(void);
static void die(void); static void die(void);
static void destructablePickupItem(Entity *e); static void destructablePickupItem(Structure *s);
static void enemyPickupItem(Entity *e); static void enemyPickupItem(Unit *u);
static void bobPickupItem(void); static void bobPickupItem(void);
void initItem(Entity *e) void initItem(Entity *e)
{ {
Item *i;
initEntity(e); initEntity(e);
i = (Item*)e;
STRNCPY(e->spriteName, "Weapon", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "Weapon", MAX_NAME_LENGTH);
e->flags |= EF_IGNORE_BULLETS; i->flags |= EF_IGNORE_BULLETS;
e->isMissionTarget = 1; i->isMissionTarget = 1;
e->canBePickedUp = 1; i->canBePickedUp = 1;
e->canBeCarried = 0; i->canBeCarried = 0;
e->collected = 0; i->collected = 0;
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex(e->spriteName); i->sprite[FACING_LEFT] = i->sprite[FACING_RIGHT] = i->sprite[FACING_DIE] = getSpriteIndex(i->spriteName);
e->tick = tick; i->tick = tick;
e->touch = touch; i->touch = touch;
e->changeEnvironment = changeEnvironment; i->changeEnvironment = changeEnvironment;
e->reset = reset; i->reset = reset;
e->die = die; i->die = die;
} }
static void reset(void) static void reset(void)
{ {
self->startX = (int) self->x; Item *i;
self->startY = (int) self->y;
i = (Item*)self;
i->startX = (int) self->x;
i->startY = (int) self->y;
} }
static void tick(void) static void tick(void)
@ -70,7 +78,11 @@ static void tick(void)
static void touch(Entity *other) static void touch(Entity *other)
{ {
if (self->alive == ALIVE_ALIVE && other != NULL && self->canBePickedUp) Item *i;
i = (Item*)self;
if (i->alive == ALIVE_ALIVE && other != NULL && i->canBePickedUp)
{ {
if (other->type == ET_BOB && !world.bob->stunTimer) if (other->type == ET_BOB && !world.bob->stunTimer)
{ {
@ -78,27 +90,31 @@ static void touch(Entity *other)
} }
else if (other->type == ET_ENEMY) else if (other->type == ET_ENEMY)
{ {
enemyPickupItem(other); enemyPickupItem((Unit*)other);
} }
else if (other->type == ET_DESTRUCTABLE) else if (other->type == ET_DESTRUCTABLE)
{ {
destructablePickupItem(other); destructablePickupItem((Structure*)other);
} }
} }
} }
static void bobPickupItem(void) static void bobPickupItem(void)
{ {
if (!self->isMissionTarget) Item *i;
i = (Item*)self;
if (!i->isMissionTarget)
{ {
if (self->thinkTime == 0) if (i->thinkTime == 0)
{ {
self->alive = ALIVE_DEAD; i->alive = ALIVE_DEAD;
addKey(self->name); addKey(i->name);
game.keysFound++; game.keysFound++;
updateObjective("KEY"); updateObjective("KEY");
setGameplayMessage(MSG_STANDARD, "Picked up a %s", self->name); setGameplayMessage(MSG_STANDARD, "Picked up a %s", i->name);
playSound(SND_KEY, CH_ITEM); playSound(SND_KEY, CH_ITEM);
} }
@ -107,21 +123,21 @@ static void bobPickupItem(void)
setGameplayMessage(MSG_GAMEPLAY, "Can't carry any more keys"); setGameplayMessage(MSG_GAMEPLAY, "Can't carry any more keys");
} }
} }
else if (self->canBeCarried) else if (i->canBeCarried)
{ {
if (numCarriedItems() < MAX_ITEMS) if (numCarriedItems() < MAX_ITEMS)
{ {
self->flags |= EF_GONE; i->flags |= EF_GONE;
if (!self->collected) if (!i->collected)
{ {
updateObjective(self->name); updateObjective(i->name);
self->collected = 1; i->collected = 1;
} }
addBobItem(self); addBobItem(i);
setGameplayMessage(MSG_STANDARD, "Picked up a %s", self->name); setGameplayMessage(MSG_STANDARD, "Picked up a %s", i->name);
playSound(SND_ITEM, CH_ITEM); playSound(SND_ITEM, CH_ITEM);
} }
@ -132,45 +148,57 @@ static void bobPickupItem(void)
} }
else else
{ {
self->alive = ALIVE_DEAD; i->alive = ALIVE_DEAD;
updateObjective(self->name); updateObjective(i->name);
if (strcmp(world.id, "teeka") != 0) if (strcmp(world.id, "teeka") != 0)
{ {
setGameplayMessage(MSG_STANDARD, "Picked up a %s", self->name); setGameplayMessage(MSG_STANDARD, "Picked up a %s", i->name);
} }
playSound(SND_ITEM, CH_ITEM); playSound(SND_ITEM, CH_ITEM);
} }
} }
static void enemyPickupItem(Entity *e) static void enemyPickupItem(Unit *u)
{ {
if (e->canCarryItem && e->carriedItem == NULL && e->alive == ALIVE_ALIVE) Item *i;
i = (Item*)self;
if (u->canCarryItem && u->carriedItem == NULL && u->alive == ALIVE_ALIVE)
{ {
e->carriedItem = self; u->carriedItem = i;
self->flags |= EF_GONE; i->flags |= EF_GONE;
} }
} }
static void destructablePickupItem(Entity *e) static void destructablePickupItem(Structure *s)
{ {
if (e->carriedItem == NULL && e->alive == ALIVE_ALIVE) Item *i;
i = (Item*)self;
if (s->carriedItem == NULL && s->alive == ALIVE_ALIVE)
{ {
e->carriedItem = self; s->carriedItem = i;
self->flags |= EF_GONE; i->flags |= EF_GONE;
} }
} }
static void changeEnvironment(void) static void changeEnvironment(void)
{ {
if (self->environment == ENV_SLIME || self->environment == ENV_LAVA) Item *i;
i = (Item*)self;
if (i->environment == ENV_SLIME || i->environment == ENV_LAVA)
{ {
addTeleportStars(self); addTeleportStars(self);
self->x = self->startX; i->x = i->startX;
self->y = self->startY; i->y = i->startY;
addTeleportStars(self); addTeleportStars(self);
playSound(SND_APPEAR, CH_ANY); playSound(SND_APPEAR, CH_ANY);
} }

View File

@ -25,7 +25,7 @@ extern void setGameplayMessage(int type, char *format, ...);
extern void addTeleportStars(Entity *e); extern void addTeleportStars(Entity *e);
extern void initEntity(Entity *e); extern void initEntity(Entity *e);
extern int getSpriteIndex(char *name); extern int getSpriteIndex(char *name);
extern void addBobItem(Entity *e); extern void addBobItem(Item *i);
extern int numCarriedItems(void); extern int numCarriedItems(void);
extern void addKey(char *name); extern void addKey(char *name);
extern void updateObjective(char *targetName); extern void updateObjective(char *targetName);

View File

@ -22,24 +22,36 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void initBronzeKey(Entity *e) void initBronzeKey(Entity *e)
{ {
Item *i;
initItem(e); initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Bronze Key", MAX_NAME_LENGTH); STRNCPY(i->name, "Bronze Key", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "BronzeKey", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "BronzeKey", MAX_NAME_LENGTH);
} }
void initSilverKey(Entity *e) void initSilverKey(Entity *e)
{ {
Item *i;
initItem(e); initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Silver Key", MAX_NAME_LENGTH); STRNCPY(i->name, "Silver Key", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "SilverKey", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "SilverKey", MAX_NAME_LENGTH);
} }
void initGoldKey(Entity *e) void initGoldKey(Entity *e)
{ {
Item *i;
initItem(e); initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Gold Key", MAX_NAME_LENGTH); STRNCPY(i->name, "Gold Key", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "GoldKey", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "GoldKey", MAX_NAME_LENGTH);
} }

View File

@ -25,53 +25,73 @@ static void touchWhiteKeycard(Entity *other);
void initRedKeycard(Entity *e) void initRedKeycard(Entity *e)
{ {
Item *i;
initItem(e); initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Red Keycard", MAX_NAME_LENGTH); STRNCPY(i->name, "Red Keycard", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "RedKeycard", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "RedKeycard", MAX_NAME_LENGTH);
} }
void initBlueKeycard(Entity *e) void initBlueKeycard(Entity *e)
{ {
Item *i;
initItem(e); initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Blue Keycard", MAX_NAME_LENGTH); STRNCPY(i->name, "Blue Keycard", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "BlueKeycard", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "BlueKeycard", MAX_NAME_LENGTH);
} }
void initGreenKeycard(Entity *e) void initGreenKeycard(Entity *e)
{ {
Item *i;
initItem(e); initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Green Keycard", MAX_NAME_LENGTH); STRNCPY(i->name, "Green Keycard", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "GreenKeycard", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "GreenKeycard", MAX_NAME_LENGTH);
} }
void initYellowKeycard(Entity *e) void initYellowKeycard(Entity *e)
{ {
Item *i;
initItem(e); initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Yellow Keycard", MAX_NAME_LENGTH); STRNCPY(i->name, "Yellow Keycard", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "YellowKeycard", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "YellowKeycard", MAX_NAME_LENGTH);
} }
void initWhiteKeycard(Entity *e) void initWhiteKeycard(Entity *e)
{ {
Item *i;
initItem(e); initItem(e);
i = (Item*)e;
STRNCPY(e->name, "White Keycard", MAX_NAME_LENGTH); STRNCPY(i->name, "White Keycard", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "WhiteKeycard", MAX_NAME_LENGTH); STRNCPY(i->spriteName, "WhiteKeycard", MAX_NAME_LENGTH);
itemTouch = e->touch; itemTouch = i->touch;
e->touch = touchWhiteKeycard; i->touch = touchWhiteKeycard;
} }
static void touchWhiteKeycard(Entity *other) static void touchWhiteKeycard(Entity *other)
{ {
itemTouch(other); itemTouch(other);
if (other == world.bob) if (other == (Entity*)world.bob)
{ {
updateObjective("White Keycard"); updateObjective("White Keycard");

View File

@ -34,51 +34,63 @@ static char *description[] = {
void initWeaponPickup(Entity *e) void initWeaponPickup(Entity *e)
{ {
Item *i;
initConsumable(e); initConsumable(e);
i = (Item*)e;
e->weaponType = WPN_PISTOL; i->weaponType = WPN_PISTOL;
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("Weapon"); i->sprite[0] = i->sprite[1] = i->sprite[2] = getSpriteIndex("Weapon");
e->spriteFrame = e->weaponType; i->spriteFrame = i->weaponType;
e->spriteTime = -1; i->spriteTime = -1;
setEntitySize(e); setEntitySize(e);
if (e->provided) if (i->provided)
{ {
e->health = 9999; i->health = 9999;
} }
itemTick = e->tick; itemTick = i->tick;
e->tick = tick; i->tick = tick;
e->touch = touch; i->touch = touch;
} }
static void tick(void) static void tick(void)
{ {
Item *i;
i = (Item*)self;
itemTick(); itemTick();
if (self->provided && self->alive == ALIVE_ALIVE) if (i->provided && i->alive == ALIVE_ALIVE)
{ {
self->health = 9999; i->health = 9999;
} }
} }
static void touch(Entity *other) static void touch(Entity *other)
{ {
Item *i;
i = (Item*)self;
if (touchedPlayer(other)) if (touchedPlayer(other))
{ {
world.bob->weaponType = self->weaponType; world.bob->weaponType = i->weaponType;
switch (self->weaponType) switch (i->weaponType)
{ {
case WPN_GRENADES: case WPN_GRENADES:
setGameplayMessage(MSG_STANDARD, "Got some Grenades"); setGameplayMessage(MSG_STANDARD, "Got some Grenades");
break; break;
default: default:
setGameplayMessage(MSG_STANDARD, "Picked up a %s", description[self->weaponType]); setGameplayMessage(MSG_STANDARD, "Picked up a %s", description[i->weaponType]);
break; break;
} }

View File

@ -25,20 +25,24 @@ static void action(void);
void initDestructable(Entity *e) void initDestructable(Entity *e)
{ {
Structure *s;
initEntity(e); initEntity(e);
e->isMissionTarget = 1; s = (Structure*)e;
STRNCPY(e->spriteName, "Crate4", MAX_NAME_LENGTH);
e->flags |= EF_EXPLODES;
e->health = e->healthMax = 10;
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex(e->spriteName); s->isMissionTarget = 1;
STRNCPY(s->spriteName, "Crate4", MAX_NAME_LENGTH);
s->flags |= EF_EXPLODES;
s->health = s->healthMax = 10;
e->applyDamage = applyDamage; s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex(s->spriteName);
e->action = action;
s->applyDamage = applyDamage;
s->action = action;
} }
static void applyDamage(int amount) static void applyDamage(int amount)
@ -51,35 +55,38 @@ static void applyDamage(int amount)
static void action(void) static void action(void)
{ {
Structure *s;
int mx, my; int mx, my;
if (self->health <= 0) s = (Structure*)self;
if (s->health <= 0)
{ {
self->health--; s->health--;
if (self->health % 3 == 0) if (s->health % 3 == 0)
{ {
mx = (int) ((self->x + (self->w / 2)) / MAP_TILE_SIZE); mx = (int) ((s->x + (s->w / 2)) / MAP_TILE_SIZE);
my = (int) ((self->y + self->h) / MAP_TILE_SIZE); my = (int) ((s->y + s->h) / MAP_TILE_SIZE);
addScorchDecal(mx, my); addScorchDecal(mx, my);
addExplosion(self->x, self->y, 50, self); addExplosion(s->x, s->y, 50, self);
self->dx = rrnd(-10, 10); s->dx = rrnd(-10, 10);
self->dy = rrnd(-10, 10); s->dy = rrnd(-10, 10);
} }
if (self->health <= -50) if (s->health <= -50)
{ {
dropCarriedItem(); dropCarriedItem();
updateObjective(self->name); updateObjective(s->name);
if (strlen(self->targetNames) > 0) if (strlen(s->targetNames) > 0)
{ {
activateEntities(self->targetNames, 1); activateEntities(s->targetNames, 1);
} }
self->alive = ALIVE_DEAD; s->alive = ALIVE_DEAD;
} }
} }
} }

View File

@ -25,57 +25,68 @@ static void touch(Entity *other);
void initInfoPoint(Entity *e) void initInfoPoint(Entity *e)
{ {
Structure *s;
initEntity(e); initEntity(e);
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("InfoPoint"); s = (Structure*)e;
e->flags |= EF_WEIGHTLESS | EF_IGNORE_BULLETS | EF_NO_CLIP | EF_NO_ENVIRONMENT;
e->ty = e->y; s->sprite[0] = s->sprite[1] = s->sprite[2] = getSpriteIndex("InfoPoint");
e->firstTouch = 1; s->flags |= EF_WEIGHTLESS | EF_IGNORE_BULLETS | EF_NO_CLIP | EF_NO_ENVIRONMENT;
e->tick = tick; s->ty = s->y;
e->touch = touch;
s->firstTouch = 1;
s->tick = tick;
s->touch = touch;
} }
static void tick(void) static void tick(void)
{ {
self->sinVal -= 0.05; Structure *s;
self->y += (float) sin(self->sinVal) * 0.1;
s = (Structure*)self;
s->sinVal -= 0.05;
s->y += (float) sin(s->sinVal) * 0.1;
} }
static void touch(Entity *other) static void touch(Entity *other)
{ {
Structure *s;
int showMessage; int showMessage;
if (other == world.bob) s = (Structure*)self;
if (other == (Entity*)world.bob)
{ {
showMessage = 0; showMessage = 0;
if (self->firstTouch) if (s->firstTouch)
{ {
self->firstTouch = 0; s->firstTouch = 0;
showMessage = 1; showMessage = 1;
self->messageTimer = FPS; s->messageTimer = FPS;
} }
else if (world.bob->dx == 0 && world.bob->dy == 0 && world.bob->isOnGround) else if (world.bob->dx == 0 && world.bob->dy == 0 && world.bob->isOnGround)
{ {
self->messageTimer++; s->messageTimer++;
if (self->messageTimer == FPS) if (s->messageTimer == FPS)
{ {
showMessage = 1; showMessage = 1;
} }
} }
else else
{ {
self->messageTimer = 0; s->messageTimer = 0;
} }
if (showMessage) if (showMessage)
{ {
showInfoMessage(self->message); showInfoMessage(s->message);
} }
} }
} }

View File

@ -25,60 +25,72 @@ static void touch(Entity *other);
void initCardReader(Entity *e) void initCardReader(Entity *e)
{ {
Structure *s;
initEntity(e); initEntity(e);
e->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS | EF_NO_TELEPORT; s = (Structure*)e;
STRNCPY(e->requiredCard, "Black Keycard", MAX_NAME_LENGTH);
e->isStatic = 1;
if (!e->active) s->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS | EF_NO_TELEPORT;
STRNCPY(s->requiredItem, "Black Keycard", MAX_NAME_LENGTH);
s->isStatic = 1;
if (!s->active)
{ {
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex("CardReaderIdle"); s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex("CardReaderIdle");
} }
else else
{ {
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex("CardReader"); s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex("CardReader");
} }
e->tick = tick; s->tick = tick;
e->touch = touch; s->touch = touch;
} }
static void tick(void) static void tick(void)
{ {
if (!self->active) Structure *s;
s = (Structure*)self;
if (!s->active)
{ {
self->bobTouching = MAX(self->bobTouching - 1, 0); s->bobTouching = MAX(s->bobTouching - 1, 0);
} }
} }
static void touch(Entity *other) static void touch(Entity *other)
{ {
if (!self->active && other->type == ET_BOB) Structure *s;
s = (Structure*)self;
if (!s->active && other->type == ET_BOB)
{ {
if (hasItem(self->requiredCard) || dev.cheatKeys) if (hasItem(s->requiredItem) || dev.cheatKeys)
{ {
activateEntities(self->targetNames, 1); activateEntities(s->targetNames, 1);
setGameplayMessage(MSG_GAMEPLAY, "%s removed", self->requiredCard); setGameplayMessage(MSG_GAMEPLAY, "%s removed", s->requiredItem);
removeItem(self->requiredCard); removeItem(s->requiredItem);
self->active = 1; s->active = 1;
self->sprite[FACING_LEFT] = self->sprite[FACING_RIGHT] = self->sprite[FACING_DIE] = getSpriteIndex("CardReader"); s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex("CardReader");
self->spriteTime = 0; s->spriteTime = 0;
self->spriteFrame = 0; s->spriteFrame = 0;
playSound(SND_CONFIRMED, CH_TOUCH); playSound(SND_CONFIRMED, CH_TOUCH);
} }
else if (self->bobTouching == 0) else if (s->bobTouching == 0)
{ {
setGameplayMessage(MSG_GAMEPLAY, "%s required", self->requiredCard); setGameplayMessage(MSG_GAMEPLAY, "%s required", s->requiredItem);
playSound(SND_DENIED, CH_TOUCH); playSound(SND_DENIED, CH_TOUCH);
} }
self->bobTouching = 2; s->bobTouching = 2;
} }
} }

View File

@ -29,103 +29,123 @@ static int isClosing(void);
void initDoor(Entity *e) void initDoor(Entity *e)
{ {
Structure *s;
initEntity(e); initEntity(e);
e->isSolid = 1; s = (Structure*)e;
e->flags |= EF_WEIGHTLESS | EF_NO_ENVIRONMENT | EF_NO_CLIP | EF_EXPLODES | EF_NO_TELEPORT;
e->closedX = e->closedY = -1;
e->state = DOOR_CLOSED;
e->speed = 8;
e->isLocked = 1;
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("Door");
if (e->closedX == -1 && e->closedY == -1) s->isSolid = 1;
s->flags |= EF_WEIGHTLESS | EF_NO_ENVIRONMENT | EF_NO_CLIP | EF_EXPLODES | EF_NO_TELEPORT;
s->closedX = s->closedY = -1;
s->state = DOOR_CLOSED;
s->speed = 8;
s->isLocked = 1;
s->sprite[0] = s->sprite[1] = s->sprite[2] = getSpriteIndex("Door");
if (s->closedX == -1 && s->closedY == -1)
{ {
e->closedX = (int) e->x; s->closedX = (int) s->x;
e->closedY = (int) e->y; s->closedY = (int) s->y;
} }
e->tick = tick; s->tick = tick;
e->touch = touch; s->touch = touch;
} }
void initBronzeDoor(Entity *e) void initBronzeDoor(Entity *e)
{ {
Structure *s;
initDoor(e); initDoor(e);
STRNCPY(e->requiredKey, "Bronze Key", MAX_NAME_LENGTH); s = (Structure*)e;
STRNCPY(s->requiredItem, "Bronze Key", MAX_NAME_LENGTH);
e->speed = 2; s->speed = 2;
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("BronzeDoor"); s->sprite[0] = s->sprite[1] = s->sprite[2] = getSpriteIndex("BronzeDoor");
} }
void initSilverDoor(Entity *e) void initSilverDoor(Entity *e)
{ {
Structure *s;
initDoor(e); initDoor(e);
STRNCPY(e->requiredKey, "Silver Key", MAX_NAME_LENGTH); s = (Structure*)e;
STRNCPY(s->requiredItem, "Silver Key", MAX_NAME_LENGTH);
e->speed = 2; s->speed = 2;
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("SilverDoor"); s->sprite[0] = s->sprite[1] = s->sprite[2] = getSpriteIndex("SilverDoor");
} }
void initGoldDoor(Entity *e) void initGoldDoor(Entity *e)
{ {
Structure *s;
initDoor(e); initDoor(e);
STRNCPY(e->requiredKey, "Gold Key", MAX_NAME_LENGTH); s = (Structure*)e;
STRNCPY(s->requiredItem, "Gold Key", MAX_NAME_LENGTH);
e->speed = 2; s->speed = 2;
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("GoldDoor"); s->sprite[0] = s->sprite[1] = e->sprite[2] = getSpriteIndex("GoldDoor");
} }
static void tick(void) static void tick(void)
{ {
self->dx = self->dy = 0; Structure *s;
s = (Structure*)self;
s->dx = s->dy = 0;
if (isOpening()) if (isOpening())
{ {
getSlope(self->tx, self->ty, self->x, self->y, &self->dx, &self->dy); getSlope(s->tx, s->ty, s->x, s->y, &s->dx, &s->dy);
self->dx *= self->speed; s->dx *= s->speed;
self->dy *= self->speed; s->dy *= s->speed;
if (abs(self->x - self->tx) < self->speed && abs(self->y - self->ty) < self->speed) if (abs(s->x - s->tx) < s->speed && abs(s->y - s->ty) < s->speed)
{ {
self->x = self->tx; s->x = s->tx;
self->y = self->ty; s->y = s->ty;
} }
self->isStatic = 0; s->isStatic = 0;
} }
else if (isClosing()) else if (isClosing())
{ {
getSlope(self->closedX, self->closedY, self->x, self->y, &self->dx, &self->dy); getSlope(s->closedX, s->closedY, s->x, s->y, &s->dx, &s->dy);
self->dx *= self->speed; s->dx *= s->speed;
self->dy *= self->speed; s->dy *= s->speed;
if (abs(self->x - self->closedX) < self->speed && abs(self->y - self->closedY) < self->speed) if (abs(s->x - s->closedX) < s->speed && abs(self->y - s->closedY) < s->speed)
{ {
self->x = self->closedX; s->x = s->closedX;
self->y = self->closedY; s->y = s->closedY;
} }
self->isStatic = 0; s->isStatic = 0;
} }
if (self->dx == 0 && self->dy == 0 && !self->isStatic) if (s->dx == 0 && s->dy == 0 && !s->isStatic)
{ {
self->isStatic = 1; s->isStatic = 1;
playSound(SND_DOOR_FINISH, CH_MECHANICAL); playSound(SND_DOOR_FINISH, CH_MECHANICAL);
} }
@ -133,27 +153,31 @@ static void tick(void)
static void touch(Entity *other) static void touch(Entity *other)
{ {
if ((other->type != ET_BOB && self->isLocked) || (other->type != ET_BOB && other->type != ET_ENEMY)) Structure *s;
s = (Structure*)self;
if ((other->type != ET_BOB && s->isLocked) || (other->type != ET_BOB && other->type != ET_ENEMY))
{ {
return; return;
} }
if (self->isLocked && !dev.cheatKeys) if (s->isLocked && !dev.cheatKeys)
{ {
if (isClosed()) if (isClosed())
{ {
if (strlen(self->requiredKey) != 0) if (strlen(s->requiredItem) != 0)
{ {
openWithKey(); openWithKey();
} }
else if (self->thinkTime == 0) else if (s->thinkTime == 0)
{ {
setGameplayMessage(MSG_GAMEPLAY, "Door is locked"); setGameplayMessage(MSG_GAMEPLAY, "Door is locked");
playSound(SND_DENIED, CH_MECHANICAL); playSound(SND_DENIED, CH_MECHANICAL);
} }
self->thinkTime = 2; s->thinkTime = 2;
return; return;
} }
@ -163,56 +187,66 @@ static void touch(Entity *other)
} }
} }
if (self->state != DOOR_OPEN) if (s->state != DOOR_OPEN)
{ {
playSound(SND_DOOR_START, CH_MECHANICAL); playSound(SND_DOOR_START, CH_MECHANICAL);
} }
self->state = DOOR_OPEN; s->state = DOOR_OPEN;
} }
static void openWithKey(void) static void openWithKey(void)
{ {
if (hasItem(self->requiredKey)) Structure *s;
s = (Structure*)self;
if (hasItem(s->requiredItem))
{ {
if (self->thinkTime <= 0) if (s->thinkTime <= 0)
{ {
setGameplayMessage(MSG_GAMEPLAY, "%s required", self->requiredKey); setGameplayMessage(MSG_GAMEPLAY, "%s required", s->requiredItem);
playSound(SND_DENIED, CH_MECHANICAL); playSound(SND_DENIED, CH_MECHANICAL);
} }
self->thinkTime = 2; s->thinkTime = 2;
return; return;
} }
removeItem(self->requiredKey); removeItem(s->requiredItem);
setGameplayMessage(MSG_GAMEPLAY, "%s removed", self->requiredKey); setGameplayMessage(MSG_GAMEPLAY, "%s removed", s->requiredItem);
STRNCPY(self->requiredKey, "", MAX_NAME_LENGTH); STRNCPY(s->requiredItem, "", MAX_NAME_LENGTH);
self->isLocked = 0; s->isLocked = 0;
if (self->state != DOOR_OPEN) if (s->state != DOOR_OPEN)
{ {
playSound(SND_DOOR_START, CH_MECHANICAL); playSound(SND_DOOR_START, CH_MECHANICAL);
} }
self->state = DOOR_OPEN; s->state = DOOR_OPEN;
} }
static int isOpening(void) static int isOpening(void)
{ {
return (self->state == DOOR_OPEN && ((int) self->x != (int) self->tx || (int) self->y != (int) self->ty)); Structure *s = (Structure*)self;
return (s->state == DOOR_OPEN && ((int) s->x != (int) s->tx || (int) s->y != (int) s->ty));
} }
static int isClosing(void) static int isClosing(void)
{ {
return (self->state == DOOR_CLOSED && ((int) self->x != self->closedX || (int) self->y != self->closedY)); Structure *s = (Structure*)self;
return (s->state == DOOR_CLOSED && ((int) s->x != s->closedX || (int) s->y != s->closedY));
} }
static int isClosed(void) static int isClosed(void)
{ {
return (self->state == DOOR_CLOSED && ((int) self->x == self->closedX && (int) self->y == self->closedY)); Structure *s = (Structure*)self;
return (s->state == DOOR_CLOSED && ((int) s->x == s->closedX && (int) s->y == s->closedY));
} }

View File

@ -23,75 +23,92 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void tick(void); static void tick(void);
static void action(void); static void action(void);
static void touch(Entity *other); static void touch(Entity *other);
static SDL_Rect getBounds(void); static SDL_Rect *getBounds(void);
void initExit(Entity *e) void initExit(Entity *e)
{ {
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex("Exit"); Structure *s;
e->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS;
e->isStatic = 1;
e->active = 0;
if (!e->active) initEntity(e);
s = (Structure*)e;
s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex("Exit");
s->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS;
s->isStatic = 1;
s->active = 0;
if (!s->active)
{ {
e->spriteFrame = 0; s->spriteFrame = 0;
} }
else else
{ {
e->spriteFrame = 1; s->spriteFrame = 1;
} }
e->spriteTime = -1; s->spriteTime = -1;
e->tick = tick; s->tick = tick;
e->action = action; s->action = action;
e->touch = touch; s->touch = touch;
e->getBounds = getBounds; s->getBounds = getBounds;
} }
static void tick(void) static void tick(void)
{ {
if (!self->active) Structure *s;
s = (Structure*)self;
if (!s->active)
{ {
self->bobTouching = MAX(self->bobTouching - 1, 0); s->bobTouching = MAX(s->bobTouching - 1, 0);
} }
} }
static void action(void) static void action(void)
{ {
Objective *o; Objective *o;
Structure *s;
if (!self->active) s = (Structure*)self;
if (!s->active)
{ {
self->active = 1; s->active = 1;
for (o = world.objectiveHead.next ; o != NULL ; o = o->next) for (o = world.objectiveHead.next ; o != NULL ; o = o->next)
{ {
if (o->required && strcmp(o->targetName, "EXIT") != 0 && o->currentValue < o->targetValue) if (o->required && strcmp(o->targetName, "EXIT") != 0 && o->currentValue < o->targetValue)
{ {
self->active = 0; s->active = 0;
} }
} }
if (self->active) if (s->active)
{ {
self->spriteFrame = 1; s->spriteFrame = 1;
} }
} }
self->thinkTime = FPS; s->thinkTime = FPS;
} }
static void touch(Entity *other) static void touch(Entity *other)
{ {
Structure *s;
s = (Structure*)self;
if (other->type == ET_BOB && !world.isReturnVisit) if (other->type == ET_BOB && !world.isReturnVisit)
{ {
if (self->bobTouching == 0) if (s->bobTouching == 0)
{ {
if (self->active) if (s->active)
{ {
updateObjective("EXIT"); updateObjective("EXIT");
world.missionCompleteTimer = (int) (FPS * 1.5); world.missionCompleteTimer = (int) (FPS * 1.5);
@ -105,16 +122,16 @@ static void touch(Entity *other)
} }
} }
self->bobTouching = 2; s->bobTouching = 2;
} }
} }
static SDL_Rect getBounds(void) static SDL_Rect *getBounds(void)
{ {
self->bounds.x = self->x + 64; self->bounds.x = self->x + 64;
self->bounds.y = self->y; self->bounds.y = self->y;
self->bounds.w = 2; self->bounds.w = 2;
self->bounds.h = self->h; self->bounds.h = self->h;
return self->bounds; return &self->bounds;
} }

View File

@ -24,6 +24,7 @@ extern int getSpriteIndex(char *name);
extern void updateObjective(char *targetName); extern void updateObjective(char *targetName);
extern void setGameplayMessage(int type, char *format, ...); extern void setGameplayMessage(int type, char *format, ...);
extern void stopMusic(void); extern void stopMusic(void);
extern void initEntity(Entity *e);
extern Entity *self; extern Entity *self;
extern World world; extern World world;

View File

@ -31,19 +31,19 @@ void initBronzeHorizontalDoor(Entity *e)
{ {
initHorizontalDoor(e); initHorizontalDoor(e);
STRNCPY(e->requiredKey, "Bronze Key", MAX_NAME_LENGTH); STRNCPY(((Structure*)e)->requiredItem, "Bronze Key", MAX_NAME_LENGTH);
} }
void initSilverHorizontalDoor(Entity *e) void initSilverHorizontalDoor(Entity *e)
{ {
initHorizontalDoor(e); initHorizontalDoor(e);
STRNCPY(e->requiredKey, "Silver Key", MAX_NAME_LENGTH); STRNCPY(((Structure*)e)->requiredItem, "Silver Key", MAX_NAME_LENGTH);
} }
void initGoldHorizontalDoor(Entity *e) void initGoldHorizontalDoor(Entity *e)
{ {
initHorizontalDoor(e); initHorizontalDoor(e);
STRNCPY(e->requiredKey, "Gold Key", MAX_NAME_LENGTH); STRNCPY(((Structure*)e)->requiredItem, "Gold Key", MAX_NAME_LENGTH);
} }

View File

@ -48,16 +48,23 @@ void initItemPad(Entity *e)
static void tick(void) static void tick(void)
{ {
self->bobTouching = MAX(self->bobTouching - 1, 0); Structure *s;
s = (Structure*)self;
s->bobTouching = MAX(s->bobTouching - 1, 0);
} }
static void touch(Entity *other) static void touch(Entity *other)
{ {
Entity *i; Structure *s;
Item *i;
if (other->type == ET_BOB && !self->active) s = (Structure*)self;
if (other->type == ET_BOB && !s->active)
{ {
i = getItem(self->requiredItem); i = getItem(s->requiredItem);
if (i != NULL) if (i != NULL)
{ {
@ -65,26 +72,26 @@ static void touch(Entity *other)
i->flags &= ~EF_GONE; i->flags &= ~EF_GONE;
i->x = self->x + (self->w / 2) - (i->w / 2); i->x = s->x + (s->w / 2) - (i->w / 2);
i->y = self->y - i->h; i->y = s->y - i->h;
i->canBeCarried = i->canBePickedUp = i->isMissionTarget = 0; i->canBeCarried = i->canBePickedUp = i->isMissionTarget = 0;
self->active = 1; s->active = 1;
setGameplayMessage(MSG_GAMEPLAY, "%s removed", self->requiredItem); setGameplayMessage(MSG_GAMEPLAY, "%s removed", s->requiredItem);
self->sprite[FACING_LEFT] = self->sprite[FACING_RIGHT] = self->sprite[FACING_DIE] = getSpriteIndex("ItemPadActive"); s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex("ItemPadActive");
self->spriteFrame = 0; s->spriteFrame = 0;
updateObjective(self->name); updateObjective(s->name);
} }
else if (!self->bobTouching) else if (!s->bobTouching)
{ {
setGameplayMessage(MSG_GAMEPLAY, "%s required", self->requiredItem); setGameplayMessage(MSG_GAMEPLAY, "%s required", s->requiredItem);
} }
self->bobTouching = 2; s->bobTouching = 2;
} }
} }

View File

@ -25,6 +25,6 @@ extern int getSpriteIndex(char *name);
extern void updateObjective(char *targetName); extern void updateObjective(char *targetName);
extern void setGameplayMessage(int type, char *format, ...); extern void setGameplayMessage(int type, char *format, ...);
extern void removeItem(char *name); extern void removeItem(char *name);
extern Entity *getItem(char *name); extern Item *getItem(char *name);
extern Entity *self; extern Entity *self;

View File

@ -25,62 +25,70 @@ static void activate(int active);
void initLift(Entity *e) void initLift(Entity *e)
{ {
Structure *s;
initEntity(e); initEntity(e);
e->state = LIFT_GOTO_FINISH; s = (Structure*)e;
e->flags |= EF_WEIGHTLESS | EF_NO_ENVIRONMENT | EF_EXPLODES | EF_NO_CLIP | EF_ALWAYS_PROCESS | EF_NO_TELEPORT;
e->speed = 2;
e->waitTime = 2;
e->startX = e->startY = -1;
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("Lift");
e->active = 1;
e->action = action; s->state = LIFT_GOTO_FINISH;
e->activate = activate;
s->flags |= EF_WEIGHTLESS | EF_NO_ENVIRONMENT | EF_EXPLODES | EF_NO_CLIP | EF_ALWAYS_PROCESS | EF_NO_TELEPORT;
s->speed = 2;
s->waitTime = 2;
s->startX = s->startY = -1;
s->sprite[0] = s->sprite[1] = s->sprite[2] = getSpriteIndex("Lift");
s->active = 1;
s->action = action;
s->activate = activate;
} }
static void action(void) static void action(void)
{ {
self->dx = self->dy = 0; Structure *s;
s = (Structure*)self;
s->dx = s->dy = 0;
if (self->active) if (s->active)
{ {
if (self->state == LIFT_GOTO_START) if (s->state == LIFT_GOTO_START)
{ {
getSlope(self->startX, self->startY, self->x, self->y, &self->dx, &self->dy); getSlope(s->startX, s->startY, s->x, s->y, &s->dx, &s->dy);
self->dx *= self->speed; s->dx *= s->speed;
self->dy *= self->speed; s->dy *= s->speed;
if (abs(self->x - self->startX) < self->speed && abs(self->y - self->startY) < self->speed) if (abs(s->x - s->startX) < s->speed && abs(s->y - s->startY) < s->speed)
{ {
self->x = self->startX; s->x = s->startX;
self->y = self->startY; s->y = s->startY;
self->state = LIFT_GOTO_FINISH; s->state = LIFT_GOTO_FINISH;
self->thinkTime = self->waitTime * FPS; s->thinkTime = s->waitTime * FPS;
self->dx = self->dy = 0; s->dx = s->dy = 0;
} }
} }
else if (self->state == LIFT_GOTO_FINISH) else if (s->state == LIFT_GOTO_FINISH)
{ {
getSlope(self->tx, self->ty, self->x, self->y, &self->dx, &self->dy); getSlope(s->tx, s->ty, s->x, s->y, &s->dx, &s->dy);
self->dx *= self->speed; s->dx *= s->speed;
self->dy *= self->speed; s->dy *= s->speed;
if (abs(self->x - self->tx) < self->speed && abs(self->y - self->ty) < self->speed) if (abs(s->x - s->tx) < s->speed && abs(s->y - s->ty) < s->speed)
{ {
self->x = self->tx; s->x = s->tx;
self->y = self->ty; s->y = s->ty;
self->state = LIFT_GOTO_START; s->state = LIFT_GOTO_START;
self->thinkTime = self->waitTime * FPS; s->thinkTime = s->waitTime * FPS;
self->dx = self->dy = 0; s->dx = s->dy = 0;
} }
} }
} }

View File

@ -26,72 +26,88 @@ static void touch(Entity *other);
void initPowerPoint(Entity *e) void initPowerPoint(Entity *e)
{ {
initEntity(e); Structure *s;
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex("PowerPoint");
e->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS;
e->requiredPower = 100;
e->isStatic = 1;
e->tick = tick; initEntity(e);
e->action = action;
e->touch = touch; s = (Structure*)e;
s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex("PowerPoint");
s->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS;
s->requiredPower = 100;
s->isStatic = 1;
s->tick = tick;
s->action = action;
s->touch = touch;
} }
static void tick(void) static void tick(void)
{ {
if (!self->active) Structure *s;
s = (Structure*)self;
if (!s->active)
{ {
self->bobTouching = MAX(self->bobTouching - 1, 0); s->bobTouching = MAX(s->bobTouching - 1, 0);
if (self->bobTouching == 0) if (s->bobTouching == 0)
{ {
self->spriteFrame = 0; s->spriteFrame = 0;
self->spriteTime = -1; s->spriteTime = -1;
self->thinkTime = FPS / 2; s->thinkTime = FPS / 2;
} }
} }
} }
static void action(void) static void action(void)
{ {
self->spriteFrame = MIN(self->spriteFrame + 1, 3); Structure *s;
s = (Structure*)self;
s->spriteFrame = MIN(s->spriteFrame + 1, 3);
if (!self->active && self->spriteFrame == 3) if (!s->active && s->spriteFrame == 3)
{ {
activateEntities(self->targetNames, 1); activateEntities(s->targetNames, 1);
setGameplayMessage(MSG_GAMEPLAY, self->message); setGameplayMessage(MSG_GAMEPLAY, s->message);
if (!dev.cheatPower) if (!dev.cheatPower)
{ {
world.bob->power -= self->requiredPower; world.bob->power -= s->requiredPower;
} }
self->requiredPower = 0; s->requiredPower = 0;
self->active = 1; s->active = 1;
} }
else else
{ {
self->thinkTime = FPS / 2; s->thinkTime = FPS / 2;
} }
} }
static void touch(Entity *other) static void touch(Entity *other)
{ {
if (!self->active && other->type == ET_BOB && other->dx == 0) Structure *s;
s = (Structure*)self;
if (!s->active && other->type == ET_BOB && other->dx == 0)
{ {
if (world.bob->power < self->requiredPower && self->bobTouching == 0 && !dev.cheatPower) if (world.bob->power < s->requiredPower && s->bobTouching == 0 && !dev.cheatPower)
{ {
setGameplayMessage(MSG_GAMEPLAY, "Not enough power (%d units required)", self->requiredPower); setGameplayMessage(MSG_GAMEPLAY, "Not enough power (%d units required)", s->requiredPower);
} }
else else
{ {
self->bobTouching = 2; s->bobTouching = 2;
} }
} }
} }

View File

@ -26,57 +26,75 @@ static void touch(Entity *other);
void initPowerPool(Entity *e) void initPowerPool(Entity *e)
{ {
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex("PowerPool"); Structure *s;
e->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_IGNORE_BULLETS;
e->plane = PLANE_FOREGROUND;
e->isStatic = 1;
e->tick = tick; initEntity(e);
e->action = action;
e->touch = touch; s = (Structure*)e;
s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex("PowerPool");
s->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_IGNORE_BULLETS;
s->plane = PLANE_FOREGROUND;
s->isStatic = 1;
s->tick = tick;
s->action = action;
s->touch = touch;
} }
static void tick(void) static void tick(void)
{ {
if (self->active) Structure *s;
s = (Structure*)self;
if (s->active)
{ {
self->spriteTime--; s->spriteTime--;
if (self->spriteTime <= 0) if (s->spriteTime <= 0)
{ {
self->spriteFrame = (int) (1 + (rand() % 6)); s->spriteFrame = (int) (1 + (rand() % 6));
self->spriteTime = 12; s->spriteTime = 12;
} }
} }
} }
static void action(void) static void action(void)
{ {
self->active = 1; Structure *s;
s = (Structure*)self;
s->active = 1;
if (self->spriteFrame == 0) if (s->spriteFrame == 0)
{ {
self->spriteFrame = (int) (1 + (rand() % 6)); s->spriteFrame = (int) (1 + (rand() % 6));
self->spriteTime = 12; s->spriteTime = 12;
} }
self->thinkTime = FPS * 99999; s->thinkTime = FPS * 99999;
} }
static void touch(Entity *other) static void touch(Entity *other)
{ {
if (self->active && other->type == ET_BOB && world.bob->power < world.bob->powerMax) Structure *s;
s = (Structure*)self;
if (s->active && other->type == ET_BOB && world.bob->power < world.bob->powerMax)
{ {
world.bob->power = MIN(world.bob->power + 0.05, world.bob->powerMax); world.bob->power = MIN(world.bob->power + 0.05, world.bob->powerMax);
if (world.bob->power == world.bob->powerMax) if (world.bob->power == world.bob->powerMax)
{ {
self->thinkTime = FPS * 10; s->thinkTime = FPS * 10;
self->spriteTime = -1; s->spriteTime = -1;
self->spriteFrame = 0; s->spriteFrame = 0;
self->active = 0; s->active = 0;
} }
} }
} }

View File

@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../../../common.h" #include "../../../common.h"
extern int getSpriteIndex(char *name); extern int getSpriteIndex(char *name);
extern void initEntity(Entity *e);
extern Entity *self; extern Entity *self;
extern World world; extern World world;

View File

@ -25,49 +25,61 @@ static void touch(Entity *other);
void initPressurePlate(Entity *e) void initPressurePlate(Entity *e)
{ {
Structure *s;
initEntity(e); initEntity(e);
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex("PressurePlate"); s = (Structure*)e;
e->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS;
e->plane = PLANE_FOREGROUND;
e->isStatic = 1;
e->tick = tick; s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex("PressurePlate");
e->touch = touch;
s->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS;
s->plane = PLANE_FOREGROUND;
s->isStatic = 1;
s->tick = tick;
s->touch = touch;
} }
static void tick(void) static void tick(void)
{ {
if (self->isWeighted) Structure *s;
s = (Structure*)self;
if (s->isWeighted)
{ {
self->weightApplied = MAX(self->weightApplied - 1, 0); s->weightApplied = MAX(s->weightApplied - 1, 0);
if (self->active && self->weightApplied == 0) if (s->active && s->weightApplied == 0)
{ {
self->active = 0; s->active = 0;
self->spriteFrame = 0; s->spriteFrame = 0;
activateEntities(self->targetNames, 0); activateEntities(s->targetNames, 0);
} }
} }
} }
static void touch(Entity *other) static void touch(Entity *other)
{ {
Structure *s;
s = (Structure*)self;
if (other->type == ET_BOB || other->type == ET_PUSHBLOCK) if (other->type == ET_BOB || other->type == ET_PUSHBLOCK)
{ {
if (!self->active) if (!s->active)
{ {
activateEntities(self->targetNames, 1); activateEntities(s->targetNames, 1);
playSound(SND_PRESSURE_PLATE, CH_MECHANICAL); playSound(SND_PRESSURE_PLATE, CH_MECHANICAL);
} }
self->active = 1; s->active = 1;
self->spriteFrame = 1; s->spriteFrame = 1;
self->weightApplied = 5; s->weightApplied = 5;
} }
} }

View File

@ -24,25 +24,33 @@ static void activate(int active);
void initPushBlock(Entity *e) void initPushBlock(Entity *e)
{ {
Structure *s;
initEntity(e); initEntity(e);
e->isSolid = 1; s = (Structure*)e;
e->startX = e->startY = -1;
e->flags |= EF_EXPLODES | EF_ALWAYS_PROCESS;
e->activate = activate; s->isSolid = 1;
s->startX = s->startY = -1;
s->flags |= EF_EXPLODES | EF_ALWAYS_PROCESS;
s->activate = activate;
} }
static void activate(int active) static void activate(int active)
{ {
Structure *s;
s = (Structure*)self;
if (self->active) if (self->active)
{ {
addTeleportStars(self); addTeleportStars(self);
self->x = self->startX; s->x = s->startX;
self->y = self->startY; s->y = s->startY;
self->dx = self->dy = 0; s->dx = s->dy = 0;
addTeleportStars(self); addTeleportStars(self);
playSound(SND_APPEAR, CH_ANY); playSound(SND_APPEAR, CH_ANY);
} }

View File

@ -28,22 +28,26 @@ static void activate(int active);
void initLaserTrap(Entity *e) void initLaserTrap(Entity *e)
{ {
Trap *t;
initEntity(e); initEntity(e);
e->flags |= EF_WEIGHTLESS | EF_IGNORE_BULLETS | EF_NO_ENVIRONMENT | EF_NO_CLIP | EF_ALWAYS_PROCESS; t = (Trap*)e;
e->onTime = FPS * 2;
e->offTime = FPS * 2;
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("LaserTrap");
e->active = 1;
e->init = init; t->flags |= EF_WEIGHTLESS | EF_IGNORE_BULLETS | EF_NO_ENVIRONMENT | EF_NO_CLIP | EF_ALWAYS_PROCESS;
e->tick = tick;
e->action = action; t->onTime = FPS * 2;
e->touch = touch; t->offTime = FPS * 2;
e->activate = activate;
t->sprite[0] = t->sprite[1] = t->sprite[2] = getSpriteIndex("LaserTrap");
t->active = 1;
t->init = init;
t->tick = tick;
t->action = action;
t->touch = touch;
t->activate = activate;
} }
static void init(void) static void init(void)
@ -56,40 +60,52 @@ static void init(void)
static void tick(void) static void tick(void)
{ {
if (!self->active && self->spriteTime == -1) Trap *t;
t = (Trap*)self;
if (!t->active && t->spriteTime == -1)
{ {
self->flags |= EF_GONE; t->flags |= EF_GONE;
} }
} }
static void action(void) static void action(void)
{ {
if (self->offTime != 0) Trap *t;
t = (Trap*)self;
if (t->offTime != 0)
{ {
if (!self->active) if (!t->active)
{ {
self->thinkTime = self->onTime; t->thinkTime = t->onTime;
self->spriteFrame = 0; t->spriteFrame = 0;
self->spriteTime = 0; t->spriteTime = 0;
self->flags &= ~EF_GONE; t->flags &= ~EF_GONE;
} }
else if (self->offTime > 0) else if (t->offTime > 0)
{ {
self->thinkTime = self->offTime; t->thinkTime = t->offTime;
self->spriteTime = 0; t->spriteTime = 0;
} }
self->active = !self->active; t->active = !t->active;
} }
else else
{ {
self->spriteTime = -1; t->spriteTime = -1;
self->spriteFrame = 4; t->spriteFrame = 4;
} }
} }
static void touch(Entity *other) static void touch(Entity *other)
{ {
Trap *t;
t = (Trap*)self;
if (other != NULL && (other->type == ET_BOB || other->type == ET_ENEMY)) if (other != NULL && (other->type == ET_BOB || other->type == ET_ENEMY))
{ {
if (!(other->flags & EF_IMMUNE)) if (!(other->flags & EF_IMMUNE))
@ -99,7 +115,7 @@ static void touch(Entity *other)
other->dx = rrnd(-12, 12); other->dx = rrnd(-12, 12);
other->dy = rrnd(-8, 0); other->dy = rrnd(-8, 0);
if (self->offTime != 0) if (t->offTime != 0)
{ {
other->applyDamage((int) (other->healthMax / 4)); other->applyDamage((int) (other->healthMax / 4));
} }
@ -110,7 +126,7 @@ static void touch(Entity *other)
} }
} }
if (other == world.bob && world.bob->stunTimer == 0) if (other == (Entity*)world.bob && world.bob->stunTimer == 0)
{ {
stunPlayer(); stunPlayer();
} }
@ -118,11 +134,11 @@ static void touch(Entity *other)
if (other->flags & EF_EXPLODES) if (other->flags & EF_EXPLODES)
{ {
addSparkParticles(self->x, self->y); addSparkParticles(t->x, t->y);
} }
else else
{ {
addSmallFleshChunk(self->x, self->y); addSmallFleshChunk(t->x, t->y);
} }
} }
} }

View File

@ -22,120 +22,121 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void unitTick(void); void unitTick(void);
static void attack(void); static void attack(void);
static int canFire(Entity *target);
void initUnit(Entity *e) void initUnit(Entity *e)
{ {
Unit *u;
initEntity(e); initEntity(e);
e->oxygen = MAX_OXYGEN; u = (Unit*)e;
u->oxygen = MAX_OXYGEN;
e->canCarryItem = rand() % 100 < 85; u->canCarryItem = rand() % 100 < 85;
if (world.isOutpostMission) if (world.isOutpostMission)
{ {
e->canCarryItem = 1; u->canCarryItem = 1;
e->health = e->healthMax = rrnd(1, 4); u->health = u->healthMax = rrnd(1, 4);
} }
e->spriteFrame = 0; u->spriteFrame = 0;
e->startX = e->startY = -1; u->startX = u->startY = -1;
e->tick = unitTick; u->tick = unitTick;
e->action = lookForPlayer; u->action = lookForPlayer;
e->attack = attack; u->attack = attack;
u->canFire = canFire;
} }
void reInitUnit(Entity *e) void reInitUnit(Entity *e)
{ {
if (e->startX == -1 && e->startY == -1) Unit *u;
u = (Unit*)self;
if (u->startX == -1 && u->startY == -1)
{ {
e->startX = (int) e->x; u->startX = (int) u->x;
e->startY = (int) e->y; u->startY = (int) u->y;
} }
if (e->isMissionTarget) if (u->isMissionTarget)
{ {
e->flags |= EF_BOMB_SHIELD; u->flags |= EF_BOMB_SHIELD;
} }
} }
void unitTick(void) void unitTick(void)
{ {
if (self->alive == ALIVE_ALIVE) Unit *u;
u = (Unit*)self;
if (u->alive == ALIVE_ALIVE)
{ {
self->reload = limit(self->reload - 1, 0, FPS); u->reload = limit(u->reload - 1, 0, FPS);
} }
switch (self->environment) switch (u->environment)
{ {
case ENV_AIR: case ENV_AIR:
self->oxygen = limit(self->oxygen + 4, 0, MAX_OXYGEN); u->oxygen = limit(u->oxygen + 4, 0, MAX_OXYGEN);
break; break;
case ENV_WATER: case ENV_WATER:
self->oxygen = limit(self->oxygen - 1, 0, MAX_OXYGEN); u->oxygen = limit(u->oxygen - 1, 0, MAX_OXYGEN);
if (self->oxygen == 0 && world.frameCounter % 30 == 0) if (u->oxygen == 0 && world.frameCounter % 30 == 0)
{ {
self->health--; u->health--;
} }
break; break;
case ENV_SLIME: case ENV_SLIME:
case ENV_LAVA: case ENV_LAVA:
if (self->alive == ALIVE_ALIVE) if (u->alive == ALIVE_ALIVE)
{ {
self->health = 0; u->health = 0;
} }
break; break;
} }
if (self->flags & EF_WATER_BREATHING) if (u->flags & EF_WATER_BREATHING)
{ {
self->oxygen = MAX_OXYGEN; u->oxygen = MAX_OXYGEN;
} }
if (self->spawnedIn) if (u->spawnedIn)
{ {
if (getDistance(self->x, self->y, world.bob->x, world.bob->y) < 1000) if (getDistance(u->x, u->y, world.bob->x, world.bob->y) < 1000)
{ {
self->spawnedInTimer = FPS * 5; u->spawnedInTimer = FPS * 5;
} }
self->spawnedInTimer--; u->spawnedInTimer--;
if (self->spawnedInTimer <= 0) if (u->spawnedInTimer <= 0)
{ {
self->alive = ALIVE_DEAD; u->alive = ALIVE_DEAD;
} }
} }
} }
void dropCarriedItem(Entity *e)
{
if (e->carriedItem != NULL)
{
e->carriedItem->x = (e->x + e->w / 2) - e->carriedItem->w / 2;
e->carriedItem->y = e->y;
e->carriedItem->dx = e->carriedItem->dy = 0;
world.entityTail->next = e->carriedItem;
world.entityTail = e->carriedItem;
world.entityTail->next = NULL;
e->carriedItem = NULL;
}
}
void unitReappear(void) void unitReappear(void)
{ {
} }
static void attack(void) static void attack(void)
{ {
if (canFire(world.bob)) Unit *u;
u = (Unit*)self;
if (u->canFire((Entity*)world.bob))
{ {
switch (self->weaponType) switch (u->weaponType)
{ {
case WPN_AIMED_PISTOL: case WPN_AIMED_PISTOL:
fireAimedShot(self); fireAimedShot(self);
@ -170,10 +171,13 @@ static void attack(void)
break; break;
default: default:
printf("Can't fire weapon: %d\n", self->weaponType); printf("Can't fire weapon: %d\n", u->weaponType);
break; break;
} }
} }
} }
static int canFire(Entity *target)
{
return 0;
}

View File

@ -25,7 +25,6 @@ extern void lookForPlayer(void);
extern int rrnd(int low, int high); extern int rrnd(int low, int high);
extern float limit(float i, float a, float b); extern float limit(float i, float a, float b);
extern int getDistance(int x1, int y1, int x2, int y2); extern int getDistance(int x1, int y1, int x2, int y2);
extern int canFire(Entity *target);
extern void fireAimedShot(Entity *e); extern void fireAimedShot(Entity *e);
extern void fireMachineGun(Entity *e); extern void fireMachineGun(Entity *e);
extern void fireGrenade(Entity *e); extern void fireGrenade(Entity *e);

View File

@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "items.h" #include "items.h"
static void throwItem(Entity *e); static void throwItem(Item *i);
static int getRandomPlayerWeaponAt(int x, int y); static int getRandomPlayerWeaponAt(int x, int y);
static int wpnIconSprite; static int wpnIconSprite;
@ -39,13 +39,13 @@ void initItems(void)
void addRandomWeapon(double x, double y) void addRandomWeapon(double x, double y)
{ {
Entity *wpn; Item *wpn;
int type; int type;
wpn = malloc(sizeof(Entity)); wpn = malloc(sizeof(Item));
memset(wpn, 0, sizeof(Entity)); memset(wpn, 0, sizeof(Item));
world.entityTail->next = wpn; world.entityTail->next = (Entity*)wpn;
world.entityTail = wpn; world.entityTail = (Entity*)wpn;
wpn->x = x; wpn->x = x;
wpn->y = y; wpn->y = y;
@ -89,82 +89,82 @@ static int getRandomPlayerWeaponAt(int x, int y)
void dropRandomCherry(double x, double y) void dropRandomCherry(double x, double y)
{ {
Entity *e; Item *i;
double r; double r;
e = malloc(sizeof(Entity)); i = malloc(sizeof(Item));
memset(e, 0, sizeof(Entity)); memset(i, 0, sizeof(Item));
world.entityTail->next = e; world.entityTail->next = (Entity*)i;
world.entityTail = e; world.entityTail = (Entity*)i;
r = rand() % 100; r = rand() % 100;
if (r < 1) if (r < 1)
{ {
STRNCPY(e->name, "bunch of cherries", MAX_NAME_LENGTH); STRNCPY(i->name, "bunch of cherries", MAX_NAME_LENGTH);
e->value = 10; i->value = 10;
e->sprite[0] = e->sprite[1] = e->sprite[2] = cherrySprite[2]; i->sprite[0] = i->sprite[1] = i->sprite[2] = cherrySprite[2];
} }
else if (r < 10) else if (r < 10)
{ {
STRNCPY(e->name, "pair of cherries", MAX_NAME_LENGTH); STRNCPY(i->name, "pair of cherries", MAX_NAME_LENGTH);
e->value = 3; i->value = 3;
e->sprite[0] = e->sprite[1] = e->sprite[2] = cherrySprite[1]; i->sprite[0] = i->sprite[1] = i->sprite[2] = cherrySprite[1];
} }
else else
{ {
STRNCPY(e->name, "small cherry", MAX_NAME_LENGTH); STRNCPY(i->name, "small cherry", MAX_NAME_LENGTH);
e->value = 1; i->value = 1;
e->sprite[0] = e->sprite[1] = e->sprite[2] = cherrySprite[0]; i->sprite[0] = i->sprite[1] = i->sprite[2] = cherrySprite[0];
} }
e->x = x; i->x = x;
e->y = y; i->y = y;
throwItem(e); throwItem(i);
} }
void dropBattery(double x, double y) void dropBattery(double x, double y)
{ {
Entity *e; Item *i;
double r; double r;
e = malloc(sizeof(Entity)); i = malloc(sizeof(Item));
memset(e, 0, sizeof(Entity)); memset(i, 0, sizeof(Item));
world.entityTail->next = e; world.entityTail->next = (Entity*)i;
world.entityTail = e; world.entityTail = (Entity*)i;
r = rand() % 100; r = rand() % 100;
if (r < 1) if (r < 1)
{ {
STRNCPY(e->name, "full battery", MAX_NAME_LENGTH); STRNCPY(i->name, "full battery", MAX_NAME_LENGTH);
e->value = 4; i->value = 4;
} }
else if (r < 10) else if (r < 10)
{ {
STRNCPY(e->name, "battery", MAX_NAME_LENGTH); STRNCPY(i->name, "battery", MAX_NAME_LENGTH);
e->value = 3; i->value = 3;
} }
else if (r < 25) else if (r < 25)
{ {
STRNCPY(e->name, "used battery", MAX_NAME_LENGTH); STRNCPY(i->name, "used battery", MAX_NAME_LENGTH);
e->value = 2; i->value = 2;
} }
else else
{ {
STRNCPY(e->name, "weak battery", MAX_NAME_LENGTH); STRNCPY(i->name, "weak battery", MAX_NAME_LENGTH);
e->value = 1; i->value = 1;
} }
e->sprite[0] = e->sprite[1] = e->sprite[2] = batterySprite; i->sprite[0] = i->sprite[1] = i->sprite[2] = batterySprite;
e->spriteTime = -1; i->spriteTime = -1;
e->spriteFrame = e->value; i->spriteFrame = i->value;
e->x = x; i->x = x;
e->y = y; i->y = y;
throwItem(e); throwItem(i);
} }
void addRandomItems(double x, double y) void addRandomItems(double x, double y)
@ -180,8 +180,8 @@ void addRandomItems(double x, double y)
} }
} }
static void throwItem(Entity *e) static void throwItem(Item *i)
{ {
e->dx = rrnd(-3, 3); i->dx = rrnd(-3, 3);
e->dy = rrnd(-7, -5); i->dy = rrnd(-7, -5);
} }