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 += -Wall -Wempty-body -ansi -pedantic -Werror -Wstrict-prototypes -Werror=maybe-uninitialized -Warray-bounds
CXXFLAGS += -g -lefence
CXXFLAGS += -fms-extensions
CXXFLAGS += -fms-extensions -std=gnu11
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)
{
return (!isBlockedByMap(src, dest) && !isBlockedByEntities(src, dest));
@ -130,10 +103,5 @@ static int isBlockedByEntities(Entity *src, Entity *dest)
int enemyCanSeePlayer(Entity *e)
{
return hasLineOfSight(e, world.bob);
}
int canFire(Entity *target)
{
return 0;
return hasLineOfSight(e, (Entity*)world.bob);
}

View File

@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "weapons.h"
Bullet *createBaseBullet(Entity *owner);
Bullet *createBaseBullet(Unit *owner);
static int bulletSprite[2];
static int plasmaSprite[2];
@ -58,7 +58,7 @@ void initWeapons(void)
missileSprite[1] = getSpriteIndex("MissileLeft");
}
void firePistol(Entity *owner)
void firePistol(Unit *owner)
{
Bullet *bullet;
@ -73,7 +73,7 @@ void firePistol(Entity *owner)
playSound(SND_PISTOL, CH_PLAYER);
}
void fireAimedShot(Entity *owner)
void fireAimedShot(Unit *owner)
{
int x, y;
float dx, dy;
@ -96,7 +96,7 @@ void fireAimedShot(Entity *owner)
playSound(SND_PISTOL, CH_WEAPON);
}
void fireMachineGun(Entity *owner)
void fireMachineGun(Unit *owner)
{
Bullet *bullet;
@ -109,7 +109,7 @@ void fireMachineGun(Entity *owner)
playSound(SND_MACHINE_GUN, CH_WEAPON);
}
void firePlasma(Entity *owner)
void firePlasma(Unit *owner)
{
Bullet *bullet;
@ -124,7 +124,7 @@ void firePlasma(Entity *owner)
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;
int i;
@ -148,7 +148,7 @@ void fireSpread(Entity *owner, int numberOfShots)
playSound(SND_SPREAD, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON);
}
void fireLaser(Entity *owner)
void fireLaser(Unit *owner)
{
Bullet *laser;
@ -157,7 +157,6 @@ void fireLaser(Entity *owner)
laser->y = owner->y + owner->h / 2;
laser->facing = owner->facing;
laser->dx = owner->facing == FACING_RIGHT ? 20 : -20;
laser->owner = owner;
laser->health = FPS * 3;
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);
}
void fireGrenade(Entity *owner)
void fireGrenade(Unit *owner)
{
Bullet *grenade;
@ -174,7 +173,6 @@ void fireGrenade(Entity *owner)
grenade->x = owner->x + owner->w / 2;
grenade->y = owner->y;
grenade->facing = owner->facing;
grenade->owner = owner;
grenade->health = FPS * 3;
grenade->dx = owner->facing == FACING_RIGHT ? 8 : -8;
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);
}
void fireShotgun(Entity *owner)
void fireShotgun(Unit *owner)
{
int i;
float dx, dy;
@ -211,7 +209,7 @@ void fireShotgun(Entity *owner)
playSound(SND_SHOTGUN, CH_WEAPON);
}
void fireMissile(Entity *owner)
void fireMissile(Unit *owner)
{
Bullet *missile;
@ -220,7 +218,6 @@ void fireMissile(Entity *owner)
missile->y = owner->y + 10;
missile->facing = owner->facing;
missile->dx = owner->facing == FACING_RIGHT ? 10 : -10;
missile->owner = owner;
missile->health = FPS * 3;
missile->sprite[0] = missileSprite[0];
missile->sprite[1] = missileSprite[1];
@ -230,21 +227,21 @@ void fireMissile(Entity *owner)
playSound(SND_MISSILE, CH_WEAPON);
}
Bullet *createBaseBullet(Entity *owner)
Bullet *createBaseBullet(Unit *owner)
{
Bullet *bullet;
bullet = malloc(sizeof(Bullet));
memset(bullet, 0, sizeof(Bullet));
world.bulletTail->next = bullet;
world.bulletTail = bullet;
world.entityTail->next = (Entity*)bullet;
world.entityTail = (Entity*)bullet;
bullet->x = (owner->x + owner->w / 2);
bullet->y = (owner->y + owner->h / 2) - 3;
bullet->dx = owner->facing == FACING_RIGHT ? 15 : -15;
bullet->facing = owner->facing;
bullet->damage = 1;
bullet->owner = owner;
bullet->owner = (Entity*)owner;
bullet->health = FPS * 3;
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 Lookup Lookup;
typedef struct Quadtree Quadtree;
typedef struct Entity Entity;
typedef struct Objective Objective;
typedef struct Trigger Trigger;
typedef struct Marker Marker;
@ -31,7 +30,18 @@ typedef struct Tuple Tuple;
typedef struct HubMission HubMission;
typedef struct Widget Widget;
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 Decoration Decoration;
typedef struct Item Item;
typedef struct MIA MIA;
typedef struct Structure Structure;
typedef struct Trap Trap;
typedef struct Unit Unit;
typedef struct {
int debug;
@ -91,97 +101,131 @@ typedef struct {
struct Entity {
unsigned long uniqueId;
char name[MAX_NAME_LENGTH];
char spriteName[MAX_NAME_LENGTH];
char targetNames[MAX_DESCRIPTION_LENGTH];
int type;
float x;
float y;
int w;
int h;
int health;
int healthMax;
char name[MAX_NAME_LENGTH];
float x, y;
int w, h;
int tx, ty;
float dx, dy;
int health, healthMax;
int alive;
int oxygen;
int startX;
int startY;
float dx;
float dy;
int tx;
int ty;
int reload;
int isOnGround;
int effectType;
int bleedTime;
int active;
int environment;
int thinkTime;
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 canCarryItem;
int reload;
int shotsToFire;
int maxShotsToFire;
int isSolid;
int environment;
int isStatic;
int isMissionTarget;
int thinkTime;
int plane;
int value;
int canCarryItem;
int spawnedIn;
int spawnedInTimer;
int oxygen;
int spawnedIn;
int startX, startY;
void (*attack)(void);
int (*canFire)(Entity *target);
};
struct MIA {
struct Unit;
int shudderTimer;
int starTimer;
int teleportTimer;
int stunTimer;
};
struct Boss {
struct Unit;
int weakAgainst;
int teleportTimer;
int stunTimer;
};
struct Item {
struct EntityExt;
int startX, startY;
int power;
int powerMax;
int value;
int weaponType;
int provided;
int collected;
int canBeCarried;
int canBePickedUp;
int provided;
int firstTouch;
int active;
float sinVal;
};
struct Bob {
struct Unit;
int stunTimer;
int power, powerMax;
};
struct Structure {
struct EntityExt;
int bobTouching;
int messageTimer;
char message[MAX_DESCRIPTION_LENGTH];
char requiredCard[MAX_NAME_LENGTH];
char requiredKey[MAX_NAME_LENGTH];
char requiredItem[MAX_NAME_LENGTH];
int requiredPower;
long flags;
SDL_Rect bounds;
int sprite[3];
int spriteTime;
int spriteFrame;
int isLocked;
int closedX;
int closedY;
char targetNames[MAX_DESCRIPTION_LENGTH];
char message[MAX_DESCRIPTION_LENGTH];
int state;
int speed;
int waitTime;
int startX, startY;
int closedX, closedY;
int isLocked;
int speed;
int messageTimer;
int firstTouch;
int requiredPower;
int isWeighted;
float weightApplied;
int weightApplied;
float sinVal;
};
struct Decoration {
struct Entity;
int effectType;
int bleedTime;
};
struct Trap {
struct EntityExt;
int onTime;
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 {
@ -357,24 +401,17 @@ struct Particle {
};
struct Bullet {
int x;
int y;
int facing;
struct Entity;
int damage;
int health;
int weaponType;
float dx;
float dy;
int sprite[2];
long flags;
Entity *owner;
Bullet *next;
};
typedef struct {
char id[MAX_NAME_LENGTH];
int state;
Entity *bob, *boss;
Bob *bob;
Boss *boss;
Map map;
int allObjectivesComplete;
int frameCounter;
@ -388,7 +425,6 @@ typedef struct {
Quadtree quadtree;
Entity entityHead, *entityTail;
Particle particleHead, *particleTail;
Bullet bulletHead, *bulletTail;
Objective objectiveHead, *objectiveTail;
Trigger triggerHead, *triggerTail;
} World;

View File

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

View File

@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#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)
{
e->tx = e->ty = -1;
MIA *m;
initUnit(e);
m = (MIA*)e;
m->tx = m->ty = -1;
e->sprite[FACING_LEFT] = getSpriteIndex("MIA");
e->sprite[FACING_RIGHT] = getSpriteIndex("MIA");
e->sprite[FACING_DIE] = getSpriteIndex("MIA");
m->sprite[FACING_LEFT] = getSpriteIndex("MIA");
m->sprite[FACING_RIGHT] = getSpriteIndex("MIA");
m->sprite[FACING_DIE] = getSpriteIndex("MIA");
e->flags |= EF_IGNORE_BULLETS;
m->flags |= EF_IGNORE_BULLETS;
/* blink at random intervals */
e->spriteFrame = 0;
e->spriteTime = rand() % 180;
m->spriteFrame = 0;
m->spriteTime = rand() % 180;
e->action = nothing;
e->reset = reset;
e->tick = tick;
e->touch = touch;
m->action = nothing;
m->reset = reset;
m->tick = tick;
m->touch = touch;
e->isMissionTarget = 1;
m->isMissionTarget = 1;
}
void reinitMIA(Entity *e)
@ -64,56 +70,72 @@ static void reset(void)
static void tick(void)
{
self->shudderTimer--;
if (self->shudderTimer <= 0)
MIA *m;
m = (MIA*)self;
m->shudderTimer--;
if (m->shudderTimer <= 0)
{
self->x = (self->tx + rand() % 4);
self->shudderTimer = 2;
m->x = (m->tx + rand() % 4);
m->shudderTimer = 2;
}
if (self->action != nothing)
if (m->action != nothing)
{
self->starTimer--;
if (self->starTimer <= 0)
m->starTimer--;
if (m->starTimer <= 0)
{
addMIATeleportStars(self->x + rand() % self->w, self->y + rand() % self->h);
self->starTimer = 1;
addMIATeleportStars(m->x + rand() % m->w, m->y + rand() % m->h);
m->starTimer = 1;
}
}
}
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;
self->teleportTimer = FPS * 3;
setGameplayMessage(MSG_OBJECTIVE, "Rescued %s", self->name);
self->isMissionTarget = 0;
self->flags |= EF_ALWAYS_PROCESS;
m->action = preTeleport;
m->teleportTimer = FPS * 3;
setGameplayMessage(MSG_OBJECTIVE, "Rescued %s", m->name);
m->isMissionTarget = 0;
m->flags |= EF_ALWAYS_PROCESS;
playSound(SND_MIA, CH_ANY);
}
}
static void preTeleport(void)
{
self->teleportTimer--;
if (self->teleportTimer <= FPS)
MIA *m;
m = (MIA*)self;
m->teleportTimer--;
if (m->teleportTimer <= FPS)
{
self->action = teleport;
self->flags |= (EF_NO_CLIP | EF_WEIGHTLESS);
self->dy = -5;
m->action = teleport;
m->flags |= (EF_NO_CLIP | EF_WEIGHTLESS);
m->dy = -5;
}
}
static void teleport(void)
{
self->teleportTimer--;
if (self->teleportTimer <= 0)
MIA *m;
m = (MIA*)self;
m->teleportTimer--;
if (m->teleportTimer <= 0)
{
addTeleportStars(self);
addRescuedMIA(self->name);
addRescuedMIA(m->name);
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 updateObjective(char *targetName);
extern void addRescuedMIA(char *name);
extern void initUnit(Entity *e);
extern Entity *self;
extern World world;

View File

@ -31,23 +31,29 @@ static int exitMission;
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");
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)
@ -73,8 +79,11 @@ static void lookForEnemies(void)
{
Entity *e;
float distance, range;
Unit *u;
self->thinkTime = rrnd(FPS / 2, FPS);
u = (Unit*)self;
u->thinkTime = rrnd(FPS / 2, FPS);
target = NULL;
@ -84,7 +93,7 @@ static void lookForEnemies(void)
{
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)
{
@ -99,41 +108,45 @@ static void lookForEnemies(void)
if (target != NULL)
{
self->shotsToFire = rrnd(3, 5);
u->shotsToFire = rrnd(3, 5);
self->action = preFire;
u->action = preFire;
}
else if (exitMission)
{
addTeleportStars(self);
self->alive = ALIVE_DEAD;
u->alive = ALIVE_DEAD;
playSound(SND_APPEAR, CH_ANY);
}
else
{
self->facing = rand() % 2 == 0 ? FACING_LEFT : FACING_RIGHT;
u->facing = rand() % 2 == 0 ? FACING_LEFT : FACING_RIGHT;
}
}
static void preFire(void)
{
if (self->reload > 0)
Unit *u;
u = (Unit*)self;
if (u->reload > 0)
{
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();
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);
bullet = createBaseBullet(self);
bullet = createBaseBullet((Unit*)self);
bullet->x = self->x;
bullet->y = (self->y + self->h / 2) - 3;
bullet->facing = self->facing;
@ -157,7 +170,7 @@ static void attack(void)
bullet->sprite[0] = bullet->sprite[1] = aimedSprite;
bullet->health *= 2;
self->reload = 5;
((Unit*)self)->reload = 5;
}
void teekaExitMission(void)

View File

@ -20,10 +20,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "../../../common.h"
extern void initUnit(Entity *e);
extern void unitTick(void);
extern int getSpriteIndex(char *name);
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 int getDistance(int x1, int y1, int x2, int y2);
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)
{
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");
e->sprite[FACING_RIGHT] = getSpriteIndex("BlazeRight");
e->sprite[FACING_DIE] = getSpriteIndex("BlazeSpin");
b->sprite[FACING_LEFT] = getSpriteIndex("BlazeLeft");
b->sprite[FACING_RIGHT] = getSpriteIndex("BlazeRight");
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"
extern void initBlobBoss(Entity *e);
extern void initBlobBoss(Boss *b);
extern int getSpriteIndex(char *name);

View File

@ -38,24 +38,28 @@ static int aimedSprite;
void initBlobBoss(Entity *e)
{
Boss *b;
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");
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)
@ -74,32 +78,36 @@ static void activate(int activate)
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
{
self->flags &= ~EF_HALT_AT_EDGE;
b->flags &= ~EF_HALT_AT_EDGE;
}
}
}
@ -107,35 +115,43 @@ static void tick(void)
static void changeEnvironment()
{
if (self->environment == self->weakAgainst)
Boss *b;
b = (Boss*)self;
if (b->environment == b->weakAgainst)
{
self->teleportTimer = 0;
self->stunTimer = 90;
self->spriteFrame = self->spriteTime = 0;
b->teleportTimer = 0;
b->stunTimer = 90;
b->spriteFrame = b->spriteTime = 0;
}
else
{
self->teleportTimer = 0;
b->teleportTimer = 0;
}
}
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;
self->spriteFrame = 0;
b->spriteTime = 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)
{
@ -152,22 +168,30 @@ static void die1(void)
break;
}
self->action = die2;
b->action = die2;
}
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)
{
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);
}
@ -175,9 +199,13 @@ static void animate(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();
return;
@ -191,8 +219,8 @@ static void lookForPlayer(void)
if (rand() % 100 < 15)
{
self->shotsToFire = rrnd(1, 12);
self->action = preFire;
b->shotsToFire = rrnd(1, 12);
b->action = preFire;
}
moveTowardsPlayer();
@ -200,48 +228,56 @@ static void lookForPlayer(void)
static void moveTowardsPlayer(void)
{
self->dx = 0;
Boss *b;
b = (Boss*)self;
b->dx = 0;
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();
self->teleportTimer = FPS * rrnd(4, 6);
b->teleportTimer = FPS * rrnd(4, 6);
}
}
static void preFire(void)
{
if (self->reload > 0)
Boss *b;
b = (Boss*)self;
if (b->reload > 0)
{
return;
}
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);
bullet = createBaseBullet(self);
bullet = createBaseBullet((Unit*)self);
bullet->x = self->x;
bullet->y = (self->y + self->h / 2) - 3;
bullet->facing = self->facing;
@ -268,7 +304,7 @@ static void attack(void)
bullet->dy = dy * 12;
bullet->sprite[0] = bullet->sprite[1] = aimedSprite;
self->reload = 4;
((Boss*)self)->reload = 4;
playSound(SND_MACHINE_GUN, CH_WEAPON);
}
@ -315,7 +351,7 @@ static void applyDamage(int amount)
teleport();
}
world.boss = self;
world.boss = (Boss*)self;
}
static void teleport(void)
@ -329,19 +365,23 @@ static void teleport(void)
static void die2(void)
{
self->health--;
Boss *b;
b = (Boss*)self;
b->health--;
if (self->health <= -FPS)
if (b->health <= -FPS)
{
addTeleportStars(self);
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++;
}

View File

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

View File

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

View File

@ -33,7 +33,7 @@ extern void addDefeatedTarget(char *name);
extern void updateObjective(char *targetName);
extern double randF(void);
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 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)
{
Boss *b;
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");
e->sprite[FACING_RIGHT] = getSpriteIndex("FrostRight");
e->sprite[FACING_DIE] = getSpriteIndex("FrostSpin");
b->sprite[FACING_LEFT] = getSpriteIndex("FrostLeft");
b->sprite[FACING_RIGHT] = getSpriteIndex("FrostRight");
b->sprite[FACING_DIE] = getSpriteIndex("FrostSpin");
}

View File

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

View File

@ -24,36 +24,40 @@ static void applyDamage(int damage);
static void walk(void);
static void die(void);
static void animate(void);
static SDL_Rect getBounds(void);
static SDL_Rect *getBounds(void);
static int canFire(Entity *target);
static void preFire(void);
void initCannon(Entity *e)
{
Unit *u;
initUnit(e);
u = (Unit*)self;
e->sprite[FACING_LEFT] = getSpriteIndex("CannonLeft");
e->sprite[FACING_RIGHT] = getSpriteIndex("CannonRight");
e->sprite[FACING_DIE] = getSpriteIndex("CannonLeft");
u->sprite[FACING_LEFT] = getSpriteIndex("CannonLeft");
u->sprite[FACING_RIGHT] = getSpriteIndex("CannonRight");
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;
e->applyDamage = applyDamage;
e->walk = walk;
e->die = die;
e->getBounds= getBounds;
e->canFire = canFire;
u->animate = animate;
u->applyDamage = applyDamage;
u->walk = walk;
u->die = die;
u->getBounds= getBounds;
u->canFire = canFire;
}
static void applyDamage(int damage)
@ -70,28 +74,31 @@ static void applyDamage(int damage)
static void die(void)
{
Unit *u;
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);
my = (int) ((self->y + self->h) / MAP_TILE_SIZE);
mx = (int) ((u->x + (u->w / 2)) / MAP_TILE_SIZE);
my = (int) ((u->y + u->h) / MAP_TILE_SIZE);
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");
fireTriggers(self->name);
fireTriggers(u->name);
dropCarriedItem();
self->alive = ALIVE_DEAD;
u->alive = ALIVE_DEAD;
}
}
@ -104,9 +111,12 @@ static void patrol(void)
static void lookForPlayer(void)
{
Unit *u;
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)
{
@ -114,13 +124,13 @@ static void lookForPlayer(void)
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();
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();
return;
@ -134,34 +144,38 @@ static void lookForPlayer(void)
r = rand() % 100;
if (self->isMissionTarget)
if (u->isMissionTarget)
{
r = rand() % 20;
}
if (r < 15)
{
self->shotsToFire = rrnd(1, self->maxShotsToFire);
self->action = preFire;
u->shotsToFire = rrnd(1, u->maxShotsToFire);
u->action = preFire;
}
}
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;
}
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.y = self->y;
self->bounds.w = 36;
self->bounds.h = self->h;
return self->bounds;
return &self->bounds;
}
static int canFire(Entity *target)

View File

@ -26,15 +26,19 @@ static void touch(Entity *other);
void initDebris(Entity *e)
{
Decoration *d;
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;
e->action = action;
e->touch = touch;
d->tick = tick;
d->action = action;
d->touch = touch;
}
static void tick(void)
@ -44,13 +48,17 @@ static void tick(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
{
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;
@ -58,8 +66,12 @@ static void action(void)
static void touch(Entity *other)
{
Decoration *d;
d = (Decoration*)self;
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)
{
Decoration *d;
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;
e->action = action;
e->touch = touch;
d->tick = tick;
d->action = action;
d->touch = touch;
}
static void tick(void)
{
self->health--;
self->bleedTime--;
Decoration *d;
d = (Decoration*)self;
d->health--;
d->bleedTime--;
}
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)

View File

@ -22,16 +22,71 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void animateEntity(void);
static void applyDamage(int damage);
static float bounce(float x);
static SDL_Rect *getBounds(void);
Entity *createEntity(void)
Entity *createEntity(int type)
{
Entity *e;
e = malloc(sizeof(Entity));
memset(e, 0, sizeof(Entity));
switch (type)
{
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 = e;
e->type = type;
e->uniqueId = game.entityCounter++;
return e;
@ -49,38 +104,31 @@ void initEntity(Entity *e)
e->isStatic = 0;
e->isMissionTarget = 0;
e->health = e->healthMax = 1;
e->health = 1;
e->facing = FACING_LEFT;
e->spriteFrame = -1;
e->spriteTime = 0;
e->dx = e->dy = 0;
e->flags = 0;
e->owner = NULL;
e->thinkTime = 0;
e->plane = PLANE_BACKGROUND;
e->animate = animateEntity;
e->applyDamage = applyDamage;
e->bounce = bounce;
e->getBounds = getBounds;
}
SDL_Rect *getEntityBounds(Entity *e)
static SDL_Rect *getBounds(void)
{
e->bounds.x = e->x;
e->bounds.y = e->y;
e->bounds.w = e->w;
e->bounds.h = e->h;
self->bounds.x = self->x;
self->bounds.y = self->y;
self->bounds.w = self->w;
self->bounds.h = self->h;
return &e->bounds;
return &self->bounds;
}
int getCurrentEntitySprite(Entity *e)
int getCurrentEntitySprite(EntityExt *e)
{
if (e->alive == ALIVE_ALIVE)
{
@ -92,39 +140,19 @@ int getCurrentEntitySprite(Entity *e)
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)
{
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;
}
else if (e->flags & EF_FRICTIONLESS)
else if (self->flags & EF_FRICTIONLESS)
{
return -x;
}
@ -133,7 +161,7 @@ float bounce(Entity *e, float x)
if (x > -1 && x < 1)
{
e->flags &= ~EF_BOUNCES;
self->flags &= ~EF_BOUNCES;
x = 0;
}
@ -160,27 +188,29 @@ void teleportEntity(Entity *e, float tx, float ty)
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;
self->alive = ALIVE_ALIVE;
}
i = e->carriedItem;
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)
{
self->thinkTime = 0;
world.entityTail->next = (Entity*)i;
world.entityTail = (Entity*)i;
world.entityTail->next = NULL;
self->facing = self->x < world.bob->x ? FACING_RIGHT : FACING_LEFT;
if (self->isMissionTarget && rand() % 10 == 0)
{
self->action = unitReappear;
self->flags |= EF_GONE;
self->thinkTime = rand() % FPS;
addTeleportStars(self);
playSound(SND_APPEAR, CH_ANY);
}
e->carriedItem = NULL;
}
}

View File

@ -22,19 +22,27 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
void initBattery(Entity *e)
{
Item *i;
initConsumable(e);
i = (Item*)e;
e->spriteFrame = 0;
e->spriteTime = -1;
i->spriteFrame = 0;
i->spriteTime = -1;
}
void touch(Entity *other)
{
Item *i;
i = (Item*)self;
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();

View File

@ -24,18 +24,22 @@ static void touch(Entity *other);
void initCell(Entity *e)
{
Item *i;
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;
e->spriteTime = -1;
i->spriteFrame = 0;
i->spriteTime = -1;
e->touch = touch;
i->touch = touch;
}
static void touch(Entity *other)

View File

@ -31,11 +31,15 @@ void initCherry(Entity *e)
static void touch(Entity *other)
{
Item *i;
i = (Item*)self;
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();

View File

@ -35,20 +35,24 @@ void initConsumable(Entity *e)
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)
{
self->alive = (self->environment == ENV_AIR) ? ALIVE_DYING : ALIVE_DEAD;
self->health = FPS / 2;
self->thinkTime = 0;
self->dy = -2;
self->dx = 0;
self->flags |= EF_FLICKER | EF_WEIGHTLESS;
Item *i;
i = (Item*)self;
i->alive = (i->environment == ENV_AIR) ? ALIVE_DYING : ALIVE_DEAD;
i->health = FPS / 2;
i->thinkTime = 0;
i->dy = -2;
i->dx = 0;
i->flags |= EF_FLICKER | EF_WEIGHTLESS;
}
static void die(void)

View File

@ -25,19 +25,23 @@ static void touch(Entity *other);
void initHeart(Entity *e)
{
Item *i;
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;
e->spriteTime = -1;
i->spriteFrame = 0;
i->spriteTime = -1;
e->action = action;
e->touch = touch;
i->action = action;
i->touch = touch;
}
static void action(void)

View File

@ -25,36 +25,44 @@ static void tick(void);
static void touch(Entity *other);
static void changeEnvironment(void);
static void die(void);
static void destructablePickupItem(Entity *e);
static void enemyPickupItem(Entity *e);
static void destructablePickupItem(Structure *s);
static void enemyPickupItem(Unit *u);
static void bobPickupItem(void);
void initItem(Entity *e)
{
Item *i;
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;
e->canBePickedUp = 1;
e->canBeCarried = 0;
e->collected = 0;
i->isMissionTarget = 1;
i->canBePickedUp = 1;
i->canBeCarried = 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;
e->touch = touch;
e->changeEnvironment = changeEnvironment;
e->reset = reset;
e->die = die;
i->tick = tick;
i->touch = touch;
i->changeEnvironment = changeEnvironment;
i->reset = reset;
i->die = die;
}
static void reset(void)
{
self->startX = (int) self->x;
self->startY = (int) self->y;
Item *i;
i = (Item*)self;
i->startX = (int) self->x;
i->startY = (int) self->y;
}
static void tick(void)
@ -70,7 +78,11 @@ static void tick(void)
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)
{
@ -78,27 +90,31 @@ static void touch(Entity *other)
}
else if (other->type == ET_ENEMY)
{
enemyPickupItem(other);
enemyPickupItem((Unit*)other);
}
else if (other->type == ET_DESTRUCTABLE)
{
destructablePickupItem(other);
destructablePickupItem((Structure*)other);
}
}
}
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;
addKey(self->name);
i->alive = ALIVE_DEAD;
addKey(i->name);
game.keysFound++;
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);
}
@ -107,21 +123,21 @@ static void bobPickupItem(void)
setGameplayMessage(MSG_GAMEPLAY, "Can't carry any more keys");
}
}
else if (self->canBeCarried)
else if (i->canBeCarried)
{
if (numCarriedItems() < MAX_ITEMS)
{
self->flags |= EF_GONE;
i->flags |= EF_GONE;
if (!self->collected)
if (!i->collected)
{
updateObjective(self->name);
self->collected = 1;
updateObjective(i->name);
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);
}
@ -132,45 +148,57 @@ static void bobPickupItem(void)
}
else
{
self->alive = ALIVE_DEAD;
updateObjective(self->name);
i->alive = ALIVE_DEAD;
updateObjective(i->name);
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);
}
}
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)
{
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);
self->x = self->startX;
self->y = self->startY;
i->x = i->startX;
i->y = i->startY;
addTeleportStars(self);
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 initEntity(Entity *e);
extern int getSpriteIndex(char *name);
extern void addBobItem(Entity *e);
extern void addBobItem(Item *i);
extern int numCarriedItems(void);
extern void addKey(char *name);
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)
{
Item *i;
initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Bronze Key", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "BronzeKey", MAX_NAME_LENGTH);
STRNCPY(i->name, "Bronze Key", MAX_NAME_LENGTH);
STRNCPY(i->spriteName, "BronzeKey", MAX_NAME_LENGTH);
}
void initSilverKey(Entity *e)
{
Item *i;
initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Silver Key", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "SilverKey", MAX_NAME_LENGTH);
STRNCPY(i->name, "Silver Key", MAX_NAME_LENGTH);
STRNCPY(i->spriteName, "SilverKey", MAX_NAME_LENGTH);
}
void initGoldKey(Entity *e)
{
Item *i;
initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Gold Key", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "GoldKey", MAX_NAME_LENGTH);
STRNCPY(i->name, "Gold Key", 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)
{
Item *i;
initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Red Keycard", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "RedKeycard", MAX_NAME_LENGTH);
STRNCPY(i->name, "Red Keycard", MAX_NAME_LENGTH);
STRNCPY(i->spriteName, "RedKeycard", MAX_NAME_LENGTH);
}
void initBlueKeycard(Entity *e)
{
Item *i;
initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Blue Keycard", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "BlueKeycard", MAX_NAME_LENGTH);
STRNCPY(i->name, "Blue Keycard", MAX_NAME_LENGTH);
STRNCPY(i->spriteName, "BlueKeycard", MAX_NAME_LENGTH);
}
void initGreenKeycard(Entity *e)
{
Item *i;
initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Green Keycard", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "GreenKeycard", MAX_NAME_LENGTH);
STRNCPY(i->name, "Green Keycard", MAX_NAME_LENGTH);
STRNCPY(i->spriteName, "GreenKeycard", MAX_NAME_LENGTH);
}
void initYellowKeycard(Entity *e)
{
Item *i;
initItem(e);
i = (Item*)e;
STRNCPY(e->name, "Yellow Keycard", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "YellowKeycard", MAX_NAME_LENGTH);
STRNCPY(i->name, "Yellow Keycard", MAX_NAME_LENGTH);
STRNCPY(i->spriteName, "YellowKeycard", MAX_NAME_LENGTH);
}
void initWhiteKeycard(Entity *e)
{
Item *i;
initItem(e);
i = (Item*)e;
STRNCPY(e->name, "White Keycard", MAX_NAME_LENGTH);
STRNCPY(e->spriteName, "WhiteKeycard", MAX_NAME_LENGTH);
STRNCPY(i->name, "White Keycard", 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)
{
itemTouch(other);
if (other == world.bob)
if (other == (Entity*)world.bob)
{
updateObjective("White Keycard");

View File

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

View File

@ -25,20 +25,24 @@ static void action(void);
void initDestructable(Entity *e)
{
Structure *s;
initEntity(e);
e->isMissionTarget = 1;
STRNCPY(e->spriteName, "Crate4", MAX_NAME_LENGTH);
e->flags |= EF_EXPLODES;
e->health = e->healthMax = 10;
s = (Structure*)e;
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;
e->action = action;
s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex(s->spriteName);
s->applyDamage = applyDamage;
s->action = action;
}
static void applyDamage(int amount)
@ -51,35 +55,38 @@ static void applyDamage(int amount)
static void action(void)
{
Structure *s;
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);
my = (int) ((self->y + self->h) / MAP_TILE_SIZE);
mx = (int) ((s->x + (s->w / 2)) / MAP_TILE_SIZE);
my = (int) ((s->y + s->h) / MAP_TILE_SIZE);
addScorchDecal(mx, my);
addExplosion(self->x, self->y, 50, self);
self->dx = rrnd(-10, 10);
self->dy = rrnd(-10, 10);
addExplosion(s->x, s->y, 50, self);
s->dx = rrnd(-10, 10);
s->dy = rrnd(-10, 10);
}
if (self->health <= -50)
if (s->health <= -50)
{
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)
{
Structure *s;
initEntity(e);
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("InfoPoint");
e->flags |= EF_WEIGHTLESS | EF_IGNORE_BULLETS | EF_NO_CLIP | EF_NO_ENVIRONMENT;
s = (Structure*)e;
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;
e->touch = touch;
s->ty = s->y;
s->firstTouch = 1;
s->tick = tick;
s->touch = touch;
}
static void tick(void)
{
self->sinVal -= 0.05;
self->y += (float) sin(self->sinVal) * 0.1;
Structure *s;
s = (Structure*)self;
s->sinVal -= 0.05;
s->y += (float) sin(s->sinVal) * 0.1;
}
static void touch(Entity *other)
{
Structure *s;
int showMessage;
if (other == world.bob)
s = (Structure*)self;
if (other == (Entity*)world.bob)
{
showMessage = 0;
if (self->firstTouch)
if (s->firstTouch)
{
self->firstTouch = 0;
s->firstTouch = 0;
showMessage = 1;
self->messageTimer = FPS;
s->messageTimer = FPS;
}
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;
}
}
else
{
self->messageTimer = 0;
s->messageTimer = 0;
}
if (showMessage)
{
showInfoMessage(self->message);
showInfoMessage(s->message);
}
}
}

View File

@ -25,60 +25,72 @@ static void touch(Entity *other);
void initCardReader(Entity *e)
{
Structure *s;
initEntity(e);
e->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS | EF_NO_TELEPORT;
STRNCPY(e->requiredCard, "Black Keycard", MAX_NAME_LENGTH);
e->isStatic = 1;
s = (Structure*)e;
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
{
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;
e->touch = touch;
s->tick = tick;
s->touch = touch;
}
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)
{
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;
self->sprite[FACING_LEFT] = self->sprite[FACING_RIGHT] = self->sprite[FACING_DIE] = getSpriteIndex("CardReader");
self->spriteTime = 0;
self->spriteFrame = 0;
s->active = 1;
s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex("CardReader");
s->spriteTime = 0;
s->spriteFrame = 0;
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);
}
self->bobTouching = 2;
s->bobTouching = 2;
}
}

View File

@ -29,103 +29,123 @@ static int isClosing(void);
void initDoor(Entity *e)
{
Structure *s;
initEntity(e);
e->isSolid = 1;
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");
s = (Structure*)e;
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;
e->closedY = (int) e->y;
s->closedX = (int) s->x;
s->closedY = (int) s->y;
}
e->tick = tick;
e->touch = touch;
s->tick = tick;
s->touch = touch;
}
void initBronzeDoor(Entity *e)
{
Structure *s;
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)
{
Structure *s;
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)
{
Structure *s;
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)
{
self->dx = self->dy = 0;
Structure *s;
s = (Structure*)self;
s->dx = s->dy = 0;
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;
self->dy *= self->speed;
s->dx *= s->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;
self->y = self->ty;
s->x = s->tx;
s->y = s->ty;
}
self->isStatic = 0;
s->isStatic = 0;
}
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;
self->dy *= self->speed;
s->dx *= s->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;
self->y = self->closedY;
s->x = s->closedX;
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);
}
@ -133,27 +153,31 @@ static void tick(void)
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;
}
if (self->isLocked && !dev.cheatKeys)
if (s->isLocked && !dev.cheatKeys)
{
if (isClosed())
{
if (strlen(self->requiredKey) != 0)
if (strlen(s->requiredItem) != 0)
{
openWithKey();
}
else if (self->thinkTime == 0)
else if (s->thinkTime == 0)
{
setGameplayMessage(MSG_GAMEPLAY, "Door is locked");
playSound(SND_DENIED, CH_MECHANICAL);
}
self->thinkTime = 2;
s->thinkTime = 2;
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);
}
self->state = DOOR_OPEN;
s->state = DOOR_OPEN;
}
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);
}
self->thinkTime = 2;
s->thinkTime = 2;
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);
self->isLocked = 0;
STRNCPY(s->requiredItem, "", MAX_NAME_LENGTH);
s->isLocked = 0;
if (self->state != DOOR_OPEN)
if (s->state != DOOR_OPEN)
{
playSound(SND_DOOR_START, CH_MECHANICAL);
}
self->state = DOOR_OPEN;
s->state = DOOR_OPEN;
}
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)
{
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)
{
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 action(void);
static void touch(Entity *other);
static SDL_Rect getBounds(void);
static SDL_Rect *getBounds(void);
void initExit(Entity *e)
{
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex("Exit");
e->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS;
e->isStatic = 1;
e->active = 0;
Structure *s;
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
{
e->spriteFrame = 1;
s->spriteFrame = 1;
}
e->spriteTime = -1;
s->spriteTime = -1;
e->tick = tick;
e->action = action;
e->touch = touch;
e->getBounds = getBounds;
s->tick = tick;
s->action = action;
s->touch = touch;
s->getBounds = getBounds;
}
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)
{
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)
{
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)
{
Structure *s;
s = (Structure*)self;
if (other->type == ET_BOB && !world.isReturnVisit)
{
if (self->bobTouching == 0)
if (s->bobTouching == 0)
{
if (self->active)
if (s->active)
{
updateObjective("EXIT");
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.y = self->y;
self->bounds.w = 2;
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 setGameplayMessage(int type, char *format, ...);
extern void stopMusic(void);
extern void initEntity(Entity *e);
extern Entity *self;
extern World world;

View File

@ -31,19 +31,19 @@ void initBronzeHorizontalDoor(Entity *e)
{
initHorizontalDoor(e);
STRNCPY(e->requiredKey, "Bronze Key", MAX_NAME_LENGTH);
STRNCPY(((Structure*)e)->requiredItem, "Bronze Key", MAX_NAME_LENGTH);
}
void initSilverHorizontalDoor(Entity *e)
{
initHorizontalDoor(e);
STRNCPY(e->requiredKey, "Silver Key", MAX_NAME_LENGTH);
STRNCPY(((Structure*)e)->requiredItem, "Silver Key", MAX_NAME_LENGTH);
}
void initGoldHorizontalDoor(Entity *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)
{
self->bobTouching = MAX(self->bobTouching - 1, 0);
Structure *s;
s = (Structure*)self;
s->bobTouching = MAX(s->bobTouching - 1, 0);
}
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)
{
@ -65,26 +72,26 @@ static void touch(Entity *other)
i->flags &= ~EF_GONE;
i->x = self->x + (self->w / 2) - (i->w / 2);
i->y = self->y - i->h;
i->x = s->x + (s->w / 2) - (i->w / 2);
i->y = s->y - i->h;
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 setGameplayMessage(int type, char *format, ...);
extern void removeItem(char *name);
extern Entity *getItem(char *name);
extern Item *getItem(char *name);
extern Entity *self;

View File

@ -25,62 +25,70 @@ static void activate(int active);
void initLift(Entity *e)
{
Structure *s;
initEntity(e);
e->state = LIFT_GOTO_FINISH;
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;
s = (Structure*)e;
e->action = action;
e->activate = activate;
s->state = LIFT_GOTO_FINISH;
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)
{
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;
self->dy *= self->speed;
s->dx *= s->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;
self->y = self->startY;
self->state = LIFT_GOTO_FINISH;
self->thinkTime = self->waitTime * FPS;
self->dx = self->dy = 0;
s->x = s->startX;
s->y = s->startY;
s->state = LIFT_GOTO_FINISH;
s->thinkTime = s->waitTime * FPS;
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;
self->dy *= self->speed;
s->dx *= s->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;
self->y = self->ty;
self->state = LIFT_GOTO_START;
self->thinkTime = self->waitTime * FPS;
self->dx = self->dy = 0;
s->x = s->tx;
s->y = s->ty;
s->state = LIFT_GOTO_START;
s->thinkTime = s->waitTime * FPS;
s->dx = s->dy = 0;
}
}
}

View File

@ -26,72 +26,88 @@ static void touch(Entity *other);
void initPowerPoint(Entity *e)
{
initEntity(e);
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;
Structure *s;
e->tick = tick;
e->action = action;
e->touch = touch;
initEntity(e);
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)
{
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;
self->spriteTime = -1;
self->thinkTime = FPS / 2;
s->spriteFrame = 0;
s->spriteTime = -1;
s->thinkTime = FPS / 2;
}
}
}
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)
{
world.bob->power -= self->requiredPower;
world.bob->power -= s->requiredPower;
}
self->requiredPower = 0;
s->requiredPower = 0;
self->active = 1;
s->active = 1;
}
else
{
self->thinkTime = FPS / 2;
s->thinkTime = FPS / 2;
}
}
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
{
self->bobTouching = 2;
s->bobTouching = 2;
}
}
}

View File

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

View File

@ -25,49 +25,61 @@ static void touch(Entity *other);
void initPressurePlate(Entity *e)
{
Structure *s;
initEntity(e);
e->sprite[FACING_LEFT] = e->sprite[FACING_RIGHT] = e->sprite[FACING_DIE] = getSpriteIndex("PressurePlate");
e->flags |= EF_WEIGHTLESS | EF_NO_CLIP | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS;
e->plane = PLANE_FOREGROUND;
e->isStatic = 1;
s = (Structure*)e;
e->tick = tick;
e->touch = touch;
s->sprite[FACING_LEFT] = s->sprite[FACING_RIGHT] = s->sprite[FACING_DIE] = getSpriteIndex("PressurePlate");
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)
{
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;
self->spriteFrame = 0;
s->active = 0;
s->spriteFrame = 0;
activateEntities(self->targetNames, 0);
activateEntities(s->targetNames, 0);
}
}
}
static void touch(Entity *other)
{
Structure *s;
s = (Structure*)self;
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);
}
self->active = 1;
self->spriteFrame = 1;
self->weightApplied = 5;
s->active = 1;
s->spriteFrame = 1;
s->weightApplied = 5;
}
}

View File

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

View File

@ -28,22 +28,26 @@ static void activate(int active);
void initLaserTrap(Entity *e)
{
Trap *t;
initEntity(e);
e->flags |= EF_WEIGHTLESS | EF_IGNORE_BULLETS | EF_NO_ENVIRONMENT | EF_NO_CLIP | EF_ALWAYS_PROCESS;
e->onTime = FPS * 2;
e->offTime = FPS * 2;
e->sprite[0] = e->sprite[1] = e->sprite[2] = getSpriteIndex("LaserTrap");
e->active = 1;
t = (Trap*)e;
e->init = init;
e->tick = tick;
e->action = action;
e->touch = touch;
e->activate = activate;
t->flags |= EF_WEIGHTLESS | EF_IGNORE_BULLETS | EF_NO_ENVIRONMENT | EF_NO_CLIP | EF_ALWAYS_PROCESS;
t->onTime = FPS * 2;
t->offTime = FPS * 2;
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)
@ -56,40 +60,52 @@ static void init(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)
{
if (self->offTime != 0)
Trap *t;
t = (Trap*)self;
if (t->offTime != 0)
{
if (!self->active)
if (!t->active)
{
self->thinkTime = self->onTime;
self->spriteFrame = 0;
self->spriteTime = 0;
self->flags &= ~EF_GONE;
t->thinkTime = t->onTime;
t->spriteFrame = 0;
t->spriteTime = 0;
t->flags &= ~EF_GONE;
}
else if (self->offTime > 0)
else if (t->offTime > 0)
{
self->thinkTime = self->offTime;
self->spriteTime = 0;
t->thinkTime = t->offTime;
t->spriteTime = 0;
}
self->active = !self->active;
t->active = !t->active;
}
else
{
self->spriteTime = -1;
self->spriteFrame = 4;
t->spriteTime = -1;
t->spriteFrame = 4;
}
}
static void touch(Entity *other)
{
Trap *t;
t = (Trap*)self;
if (other != NULL && (other->type == ET_BOB || other->type == ET_ENEMY))
{
if (!(other->flags & EF_IMMUNE))
@ -99,7 +115,7 @@ static void touch(Entity *other)
other->dx = rrnd(-12, 12);
other->dy = rrnd(-8, 0);
if (self->offTime != 0)
if (t->offTime != 0)
{
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();
}
@ -118,11 +134,11 @@ static void touch(Entity *other)
if (other->flags & EF_EXPLODES)
{
addSparkParticles(self->x, self->y);
addSparkParticles(t->x, t->y);
}
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);
static void attack(void);
static int canFire(Entity *target);
void initUnit(Entity *e)
{
Unit *u;
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)
{
e->canCarryItem = 1;
e->health = e->healthMax = rrnd(1, 4);
u->canCarryItem = 1;
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;
e->action = lookForPlayer;
e->attack = attack;
u->tick = unitTick;
u->action = lookForPlayer;
u->attack = attack;
u->canFire = canFire;
}
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;
e->startY = (int) e->y;
u->startX = (int) u->x;
u->startY = (int) u->y;
}
if (e->isMissionTarget)
if (u->isMissionTarget)
{
e->flags |= EF_BOMB_SHIELD;
u->flags |= EF_BOMB_SHIELD;
}
}
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:
self->oxygen = limit(self->oxygen + 4, 0, MAX_OXYGEN);
u->oxygen = limit(u->oxygen + 4, 0, MAX_OXYGEN);
break;
case ENV_WATER:
self->oxygen = limit(self->oxygen - 1, 0, MAX_OXYGEN);
if (self->oxygen == 0 && world.frameCounter % 30 == 0)
u->oxygen = limit(u->oxygen - 1, 0, MAX_OXYGEN);
if (u->oxygen == 0 && world.frameCounter % 30 == 0)
{
self->health--;
u->health--;
}
break;
case ENV_SLIME:
case ENV_LAVA:
if (self->alive == ALIVE_ALIVE)
if (u->alive == ALIVE_ALIVE)
{
self->health = 0;
u->health = 0;
}
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--;
if (self->spawnedInTimer <= 0)
u->spawnedInTimer--;
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)
{
}
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:
fireAimedShot(self);
@ -170,10 +171,13 @@ static void attack(void)
break;
default:
printf("Can't fire weapon: %d\n", self->weaponType);
printf("Can't fire weapon: %d\n", u->weaponType);
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 float limit(float i, float a, float b);
extern int getDistance(int x1, int y1, int x2, int y2);
extern int canFire(Entity *target);
extern void fireAimedShot(Entity *e);
extern void fireMachineGun(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"
static void throwItem(Entity *e);
static void throwItem(Item *i);
static int getRandomPlayerWeaponAt(int x, int y);
static int wpnIconSprite;
@ -39,13 +39,13 @@ void initItems(void)
void addRandomWeapon(double x, double y)
{
Entity *wpn;
Item *wpn;
int type;
wpn = malloc(sizeof(Entity));
memset(wpn, 0, sizeof(Entity));
world.entityTail->next = wpn;
world.entityTail = wpn;
wpn = malloc(sizeof(Item));
memset(wpn, 0, sizeof(Item));
world.entityTail->next = (Entity*)wpn;
world.entityTail = (Entity*)wpn;
wpn->x = x;
wpn->y = y;
@ -89,82 +89,82 @@ static int getRandomPlayerWeaponAt(int x, int y)
void dropRandomCherry(double x, double y)
{
Entity *e;
Item *i;
double r;
e = malloc(sizeof(Entity));
memset(e, 0, sizeof(Entity));
world.entityTail->next = e;
world.entityTail = e;
i = malloc(sizeof(Item));
memset(i, 0, sizeof(Item));
world.entityTail->next = (Entity*)i;
world.entityTail = (Entity*)i;
r = rand() % 100;
if (r < 1)
{
STRNCPY(e->name, "bunch of cherries", MAX_NAME_LENGTH);
e->value = 10;
e->sprite[0] = e->sprite[1] = e->sprite[2] = cherrySprite[2];
STRNCPY(i->name, "bunch of cherries", MAX_NAME_LENGTH);
i->value = 10;
i->sprite[0] = i->sprite[1] = i->sprite[2] = cherrySprite[2];
}
else if (r < 10)
{
STRNCPY(e->name, "pair of cherries", MAX_NAME_LENGTH);
e->value = 3;
e->sprite[0] = e->sprite[1] = e->sprite[2] = cherrySprite[1];
STRNCPY(i->name, "pair of cherries", MAX_NAME_LENGTH);
i->value = 3;
i->sprite[0] = i->sprite[1] = i->sprite[2] = cherrySprite[1];
}
else
{
STRNCPY(e->name, "small cherry", MAX_NAME_LENGTH);
e->value = 1;
e->sprite[0] = e->sprite[1] = e->sprite[2] = cherrySprite[0];
STRNCPY(i->name, "small cherry", MAX_NAME_LENGTH);
i->value = 1;
i->sprite[0] = i->sprite[1] = i->sprite[2] = cherrySprite[0];
}
e->x = x;
e->y = y;
i->x = x;
i->y = y;
throwItem(e);
throwItem(i);
}
void dropBattery(double x, double y)
{
Entity *e;
Item *i;
double r;
e = malloc(sizeof(Entity));
memset(e, 0, sizeof(Entity));
world.entityTail->next = e;
world.entityTail = e;
i = malloc(sizeof(Item));
memset(i, 0, sizeof(Item));
world.entityTail->next = (Entity*)i;
world.entityTail = (Entity*)i;
r = rand() % 100;
if (r < 1)
{
STRNCPY(e->name, "full battery", MAX_NAME_LENGTH);
e->value = 4;
STRNCPY(i->name, "full battery", MAX_NAME_LENGTH);
i->value = 4;
}
else if (r < 10)
{
STRNCPY(e->name, "battery", MAX_NAME_LENGTH);
e->value = 3;
STRNCPY(i->name, "battery", MAX_NAME_LENGTH);
i->value = 3;
}
else if (r < 25)
{
STRNCPY(e->name, "used battery", MAX_NAME_LENGTH);
e->value = 2;
STRNCPY(i->name, "used battery", MAX_NAME_LENGTH);
i->value = 2;
}
else
{
STRNCPY(e->name, "weak battery", MAX_NAME_LENGTH);
e->value = 1;
STRNCPY(i->name, "weak battery", MAX_NAME_LENGTH);
i->value = 1;
}
e->sprite[0] = e->sprite[1] = e->sprite[2] = batterySprite;
e->spriteTime = -1;
e->spriteFrame = e->value;
i->sprite[0] = i->sprite[1] = i->sprite[2] = batterySprite;
i->spriteTime = -1;
i->spriteFrame = i->value;
e->x = x;
e->y = y;
i->x = x;
i->y = y;
throwItem(e);
throwItem(i);
}
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);
e->dy = rrnd(-7, -5);
i->dx = rrnd(-3, 3);
i->dy = rrnd(-7, -5);
}