diff --git a/common.mk b/common.mk index 969be5a..3f500d2 100644 --- a/common.mk +++ b/common.mk @@ -9,6 +9,7 @@ SEARCHPATH += src/entities/blobs SEARCHPATH += src/entities/boss SEARCHPATH += src/entities/cannons SEARCHPATH += src/entities/decoration +SEARCHPATH += src/entities/evilBlobs SEARCHPATH += src/entities/items SEARCHPATH += src/entities/misc SEARCHPATH += src/entities/structures @@ -27,19 +28,19 @@ vpath %.h $(SEARCHPATH) DEPS += defs.h structs.h -OBJS += atlas.o atlasTest.o +OBJS += atlas.o atlasTest.o aquaBlob.o OBJS += battery.o blaze.o bob.o boss.o blobBoss.o OBJS += camera.o cannon.o cardReader.o cell.o cherry.o combat.o consumable.o OBJS += debris.o destructable.o door.o draw.o -OBJS += effects.o entities.o exit.o explosions.o eyeDroidCommander.o +OBJS += effects.o entities.o entityFactory.o exit.o explosions.o eyeDroidCommander.o evilBlob.o OBJS += fleshChunk.o frost.o -OBJS += game.o +OBJS += game.o grenade.o OBJS += heart.o horizontalDoor.o horizontalLaserTrap.o hub.o hud.o OBJS += i18n.o init.o infoPoint.o input.o io.o item.o items.o itemPad.o OBJS += cJSON.o OBJS += key.o keycard.o -OBJS += laserTrap.o lift.o lookup.o -OBJS += main.o map.o maths.o mia.o +OBJS += laser.o laserTrap.o lift.o lookup.o +OBJS += main.o map.o maths.o mia.o missile.o OBJS += objectives.o OBJS += particles.o player.o powerPoint.o powerPool.o pressurePlate.o pushBlock.o OBJS += quadtree.o diff --git a/src/combat/explosions.c b/src/combat/explosions.c index fbf0e24..c3ea130 100644 --- a/src/combat/explosions.c +++ b/src/combat/explosions.c @@ -64,7 +64,7 @@ void addExplosion(float x, float y, int radius, Entity *owner) if (e->type == ET_BOB) { - stunPlayer(); + stunBob(); } if (e->health <= 0) diff --git a/src/combat/explosions.h b/src/combat/explosions.h index 54e0419..b0344f4 100644 --- a/src/combat/explosions.h +++ b/src/combat/explosions.h @@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../common.h" extern int rrnd(int low, int high); -extern void stunPlayer(void); +extern void stunBob(void); extern void addExplosionEffect(int x, int y, int dx, int dy); extern void playSound(int snd, int ch); extern Entity **getAllEntsWithin(int x, int y, int w, int h, Entity *ignore); diff --git a/src/combat/grenade.c b/src/combat/grenade.c new file mode 100644 index 0000000..510f65c --- /dev/null +++ b/src/combat/grenade.c @@ -0,0 +1,132 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "grenade.h" + +static void tick(void); +static void touch(Entity *other); +static float bounce(float x); +static float (*superBounce)(float x); +static void die(void); +static void explode(void); + +void initGrenade(Bullet *b) +{ + b->flags |= EF_BOUNCES | EF_IGNORE_BULLETS | EF_KILL_OFFSCREEN | EF_FRICTIONLESS | EF_NO_TELEPORT; + + superBounce = b->bounce; + + b->tick = tick; + b->touch = touch; + b->bounce = bounce; + b->die = die; +} + +static void tick(void) +{ + Bullet *b; + + b = (Bullet*)self; + + b->health--; + + if (b->x <= 0 || b->y <= 0 || b->x >= (MAP_WIDTH * MAP_TILE_SIZE) - b->w || b->y >= (MAP_HEIGHT * MAP_TILE_SIZE) - b->h) + { + b->alive = ALIVE_DEAD; + } +} + +static void touch(Entity *other) +{ + Bullet *b; + + b = (Bullet*)self; + + if (b->alive == ALIVE_ALIVE) + { + /* don't bounce too high */ + if (b->dy < -8) + { + b->dy = -8; + } + + if (other != b->owner) + { + if (other != NULL && (!(other->flags & EF_IGNORE_BULLETS)) && !other->isSolid && b->owner->type != other->type && other->type != ET_LIFT) + { + if (other->flags & EF_EXPLODES) + { + addSparkParticles(b->x, b->y); + } + else + { + addSmallFleshChunk(b->x, b->y); + } + + if (b->owner->type == world.bob->type) + { + game.statShotsHit[WPN_GRENADES]++; + } + + if (!(other->flags & EF_BOMB_SHIELD)) + { + other->applyDamage(25); + } + + explode(); + } + } + } +} + +static float bounce(float x) +{ + Bullet *b; + + b = (Bullet*)self; + + if (b->environment == ENV_AIR) + { + playSound(SND_GRENADE_BOUNCE, CH_EFFECTS); + } + + return superBounce(x); +} + +static void die(void) +{ + explode(); +} + +static void explode(void) +{ + Bullet *b; + int mx, my; + + b = (Bullet*)self; + + addExplosion(b->x, b->y, 100, b->owner); + + b->alive = ALIVE_DEAD; + + mx = (int) ((b->x + (b->w / 2)) / MAP_TILE_SIZE); + my = (int) (b->y / MAP_TILE_SIZE) + 1; + addScorchDecal(mx, my); +} diff --git a/src/combat/grenade.h b/src/combat/grenade.h new file mode 100644 index 0000000..ecb707d --- /dev/null +++ b/src/combat/grenade.h @@ -0,0 +1,32 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +extern void playSound(int snd, int ch); +extern void initGrenade(Bullet *b); +extern void addSmallFleshChunk(float x, float y); +extern void addSparkParticles(float x, float y); +extern void addExplosion(float x, float y, int radius, Entity *owner); +extern void addScorchDecal(int x, int y); + +extern Entity *self; +extern Game game; +extern World world; diff --git a/src/combat/laser.c b/src/combat/laser.c new file mode 100644 index 0000000..b108722 --- /dev/null +++ b/src/combat/laser.c @@ -0,0 +1,87 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "laser.h" + +static void tick(void); +static void touch(Entity *other); + +void initLaser(Bullet *b) +{ + b->flags |= EF_WEIGHTLESS | EF_BOUNCES | EF_FRICTIONLESS | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS | EF_KILL_OFFSCREEN | EF_NO_TELEPORT; + + b->tick = tick; + b->touch = touch; +} + +static void tick(void) +{ + Bullet *b; + + b = (Bullet*)self; + + b->health--; + + if (b->x <= 0 || b->y <= 0 || b->x >= (MAP_WIDTH * MAP_TILE_SIZE) - b->w || b->y >= (MAP_HEIGHT * MAP_TILE_SIZE) - b->h) + { + b->alive = ALIVE_DEAD; + } +} + +static void touch(Entity *other) +{ + Bullet *b; + + b = (Bullet*)self; + + if (b->alive == ALIVE_ALIVE) + { + if (other != b->owner) + { + if (other != NULL && (!(other->flags & EF_IGNORE_BULLETS)) && b->owner->type != other->type) + { + if (other->flags & EF_EXPLODES) + { + addSparkParticles(b->x, b->y); + playSound(SND_METAL_HIT, CH_ANY); + } + else + { + addSmallFleshChunk(b->x, b->y); + playSound(SND_FLESH_HIT, CH_ANY); + } + + other->applyDamage(2); + + if (b->owner->type == world.bob->type) + { + game.statShotsHit[WPN_LASER]++; + } + + if (other->type == ET_BOB && !world.bob->stunTimer > 0) + { + other->dx = rrnd(-8, 8); + other->dy = rrnd(-12, 0); + stunBob(); + } + } + } + } +} diff --git a/src/combat/laser.h b/src/combat/laser.h new file mode 100644 index 0000000..32f3c93 --- /dev/null +++ b/src/combat/laser.h @@ -0,0 +1,32 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +extern void playSound(int snd, int ch); +extern int rrnd(int low, int high); +extern void initLaser(Bullet *b); +extern void addSmallFleshChunk(float x, float y); +extern void addSparkParticles(float x, float y); +extern void stunBob(void); + +extern Entity *self; +extern Game game; +extern World world; diff --git a/src/combat/missile.c b/src/combat/missile.c new file mode 100644 index 0000000..99a4cec --- /dev/null +++ b/src/combat/missile.c @@ -0,0 +1,71 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "missile.h" + +static void tick(void); +static void touch(Entity *other); + +void initMissile(Bullet *b) +{ + b->flags |= EF_WEIGHTLESS | EF_NO_ENVIRONMENT | EF_IGNORE_BULLETS | EF_KILL_OFFSCREEN | EF_NO_TELEPORT; + + b->tick = tick; + b->touch = touch; +} + +static void tick(void) +{ + Bullet *b; + + b = (Bullet*)self; + + b->health--; + + if (b->x <= 0 || b->y <= 0 || b->x >= (MAP_WIDTH * MAP_TILE_SIZE) - b->w || b->y >= (MAP_HEIGHT * MAP_TILE_SIZE) - b->h) + { + b->alive = ALIVE_DEAD; + } + + if (b->health % 2) + { + addFlameParticles(b->x + (b->facing * 35) + rrnd(-1, 1), b->y); + } +} + +static void touch(Entity *other) +{ + Bullet *b; + + b = (Bullet*)self; + + if (other == NULL) + { + addExplosion(b->x, b->y, 65, b->owner); + + b->alive = ALIVE_DEAD; + } + else if (other != b->owner && (!(other->flags & EF_IGNORE_BULLETS)) && b->owner->type != other->type) + { + addExplosion(b->x, b->y, 65, b->owner); + + b->alive = ALIVE_DEAD; + } +} diff --git a/src/combat/missile.h b/src/combat/missile.h new file mode 100644 index 0000000..d2b83e4 --- /dev/null +++ b/src/combat/missile.h @@ -0,0 +1,28 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +extern int rrnd(int low, int high); +extern void initMissile(Bullet *b); +extern void addExplosion(float x, float y, int radius, Entity *owner); +extern void addFlameParticles(float x, float y); + +extern Entity *self; diff --git a/src/combat/weapons.c b/src/combat/weapons.c index 899222f..18d343b 100644 --- a/src/combat/weapons.c +++ b/src/combat/weapons.c @@ -33,6 +33,9 @@ static int alienGrenadeSprite; static int shotgunPelletSprite; static int missileSprite[2]; +static void tick(void); +static void touch(Entity *other); + void initWeapons(void) { bulletSprite[0] = getSpriteIndex("BulletRight"); @@ -160,6 +163,8 @@ void fireLaser(Unit *owner) laser->health = FPS * 3; laser->sprite[0] = laser->sprite[1] = (owner->type == ET_BOB) ? laserSprite[0] : laserSprite[1]; + initLaser(laser); + owner->reload = owner->type == ET_BOB ? FPS / 2 : FPS; playSound(SND_LASER, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON); @@ -176,9 +181,10 @@ void fireGrenade(Unit *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; - grenade->dy = -6; + initGrenade(grenade); + owner->reload = FPS / 2; playSound(SND_THROW, owner->type == ET_BOB ? CH_PLAYER : CH_WEAPON); @@ -222,6 +228,8 @@ void fireMissile(Unit *owner) missile->sprite[0] = missileSprite[0]; missile->sprite[1] = missileSprite[1]; + initMissile(missile); + owner->reload = FPS / 2; playSound(SND_MISSILE, CH_WEAPON); @@ -235,6 +243,8 @@ Bullet *createBaseBullet(Unit *owner) memset(bullet, 0, sizeof(Bullet)); world.entityTail->next = (Entity*)bullet; world.entityTail = (Entity*)bullet; + + initEntity((Entity*)bullet); bullet->x = (owner->x + owner->w / 2); bullet->y = (owner->y + owner->h / 2) - 3; @@ -245,9 +255,86 @@ Bullet *createBaseBullet(Unit *owner) bullet->health = FPS * 3; bullet->flags |= EF_WEIGHTLESS | EF_IGNORE_BULLETS | EF_NO_ENVIRONMENT | EF_KILL_OFFSCREEN | EF_NO_TELEPORT; + bullet->tick = tick; + bullet->touch = touch; + return bullet; } +static void tick(void) +{ + Bullet *b; + + b = (Bullet*)self; + + b->health--; + + if (b->x <= 0 || b->y <= 0 || b->x >= (MAP_WIDTH * MAP_TILE_SIZE) - b->w || b->y >= (MAP_HEIGHT * MAP_TILE_SIZE) - b->h) + { + b->alive = ALIVE_DEAD; + } + + // don't allow the player to kill everything on the map by firing + // constantly + if (b->owner->type == ET_BOB) + { + if (b->x < camera.x || b->y < camera.y || b->x > camera.x + SCREEN_WIDTH || b->y > camera.y + SCREEN_HEIGHT) + { + b->alive = ALIVE_DEAD; + } + } +} + +static void touch(Entity *other) +{ + Bullet *b; + + b = (Bullet*)self; + + if (b->alive == ALIVE_ALIVE) + { + if (other == NULL) + { + addSparkParticles(b->x, b->y); + + b->alive = ALIVE_DEAD; + + if (rand() % 2) + { + playSound(SND_RICO_1, CH_ANY); + } + else + { + playSound(SND_RICO_2, CH_ANY); + } + } + else if (other != b->owner && (!(other->flags & EF_IGNORE_BULLETS)) && b->owner->type != other->type) + { + other->applyDamage(b->damage); + + if (other->flags & EF_EXPLODES) + { + playSound(SND_METAL_HIT, CH_ANY); + + addSparkParticles(b->x, b->y); + } + else + { + playSound(SND_FLESH_HIT, CH_ANY); + + addSmallFleshChunk(b->x, b->y); + } + + b->alive = ALIVE_DEAD; + + if (b->owner->type == world.bob->type) + { + game.statShotsHit[b->weaponType]++; + } + } + } +} + int getRandomPlayerWeapon(int excludeGrenades) { if (excludeGrenades) diff --git a/src/combat/weapons.h b/src/combat/weapons.h index 88ad97d..62f212a 100644 --- a/src/combat/weapons.h +++ b/src/combat/weapons.h @@ -24,5 +24,14 @@ extern int getSpriteIndex(char *name); extern void playSound(int snd, int ch); extern int rrnd(int low, int high); extern void getSlope(int x1, int y1, int x2, int y2, float *dx, float *dy); +extern void initLaser(Bullet *b); +extern void initGrenade(Bullet *b); +extern void initMissile(Bullet *b); +extern void initEntity(Entity *e); +extern void addSmallFleshChunk(float x, float y); +extern void addSparkParticles(float x, float y); +extern Camera camera; +extern Entity *self; +extern Game game; extern World world; diff --git a/src/entities/blobs/bob.c b/src/entities/blobs/bob.c index 0a14cf6..61ef481 100644 --- a/src/entities/blobs/bob.c +++ b/src/entities/blobs/bob.c @@ -20,9 +20,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "bob.h" -void initBob(Entity *e) +void initBob(void) { - e->type = ET_BOB; + Unit *u; + + u = createUnit(); + + u->type = ET_BOB; } void addBobItem(Item *i) diff --git a/src/entities/blobs/bob.h b/src/entities/blobs/bob.h index 11cd213..7b4541a 100644 --- a/src/entities/blobs/bob.h +++ b/src/entities/blobs/bob.h @@ -19,3 +19,5 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "../../common.h" + +extern Unit *createUnit(void); diff --git a/src/entities/blobs/mia.c b/src/entities/blobs/mia.c index 057ceed..842632a 100644 --- a/src/entities/blobs/mia.c +++ b/src/entities/blobs/mia.c @@ -26,13 +26,12 @@ static void touch(Entity *other); static void preTeleport(void); static void teleport(void); -void initMIA(Entity *e) +void initMIA(void) { MIA *m; - initUnit(e); - - m = (MIA*)e; + m = malloc(sizeof(MIA)); + memset(m, 0, sizeof(MIA)); m->type = ET_MIA; diff --git a/src/entities/blobs/mia.h b/src/entities/blobs/mia.h index 6071f69..fe46b9f 100644 --- a/src/entities/blobs/mia.h +++ b/src/entities/blobs/mia.h @@ -28,7 +28,6 @@ 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; diff --git a/src/entities/blobs/teeka.c b/src/entities/blobs/teeka.c index d45d7e7..0a9baad 100644 --- a/src/entities/blobs/teeka.c +++ b/src/entities/blobs/teeka.c @@ -29,13 +29,11 @@ static Entity *target; static int aimedSprite; static int exitMission; -void initTeeka(Entity *e) +void initTeeka(void) { Unit *u; - initUnit(e); - - u = (Unit*)e; + u = createUnit(); u->type = ET_TEEKA; @@ -49,7 +47,7 @@ void initTeeka(Entity *e) u->sprite[FACING_RIGHT] = getSpriteIndex("TeekaRight"); u->sprite[FACING_DIE] = getSpriteIndex("TeekaLeft"); - u->health = e->healthMax = 9999; + u->health = u->healthMax = 9999; u->tick = tick; diff --git a/src/entities/blobs/teeka.h b/src/entities/blobs/teeka.h index 78c3ba4..63d0174 100644 --- a/src/entities/blobs/teeka.h +++ b/src/entities/blobs/teeka.h @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../../common.h" -extern void initUnit(Entity *e); +extern Unit *createUnit(void); extern void unitTick(void); extern int getSpriteIndex(char *name); extern int rrnd(int low, int high); diff --git a/src/entities/cannons/cannon.c b/src/entities/cannons/cannon.c index 22319ef..126a728 100644 --- a/src/entities/cannons/cannon.c +++ b/src/entities/cannons/cannon.c @@ -28,13 +28,11 @@ static SDL_Rect *getBounds(void); static int canFire(Entity *target); static void preFire(void); -void initCannon(Entity *e) +void initCannon(void) { Unit *u; - initUnit(e); - - u = (Unit*)self; + u = createUnit(); u->type = ET_ENEMY; diff --git a/src/entities/cannons/cannon.h b/src/entities/cannons/cannon.h index 4ba3715..792f3f0 100644 --- a/src/entities/cannons/cannon.h +++ b/src/entities/cannons/cannon.h @@ -20,7 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../../common.h" -extern void initUnit(Entity *e); extern void addExplosion(float x, float y, int radius, Entity *owner); extern int rrnd(int low, int high); extern int getSpriteIndex(char *name); @@ -30,6 +29,7 @@ extern void updateObjective(char *targetName); extern void fireTriggers(char *targetName); extern void dropCarriedItem(void); extern void addScorchDecal(int x, int y); +extern Unit *createUnit(void); extern Dev dev; extern Entity *self; diff --git a/src/entities/entities.c b/src/entities/entities.c index 18af66e..8be1007 100644 --- a/src/entities/entities.c +++ b/src/entities/entities.c @@ -25,75 +25,10 @@ static void applyDamage(int damage); static float bounce(float x); static SDL_Rect *getBounds(void); -Entity *createEntity(int type) -{ - Entity *e; - - 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 = world.entityCounter++; - - return e; -} - void initEntity(Entity *e) { + e->uniqueId = world.entityCounter++; + e->sprite[0] = e->sprite[1] = e->sprite[2] = -1; e->environment = ENV_AIR; @@ -116,6 +51,9 @@ void initEntity(Entity *e) e->applyDamage = applyDamage; e->bounce = bounce; e->getBounds = getBounds; + + world.entityTail->next = e; + world.entityTail = e; } static SDL_Rect *getBounds(void) diff --git a/src/entities/entities.h b/src/entities/entities.h index e696d2a..484169b 100644 --- a/src/entities/entities.h +++ b/src/entities/entities.h @@ -23,5 +23,4 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern void addTeleportStars(Entity *e); extern Entity *self; -extern Game game; extern World world; diff --git a/src/entities/entityFactory.c b/src/entities/entityFactory.c new file mode 100644 index 0000000..7d5516e --- /dev/null +++ b/src/entities/entityFactory.c @@ -0,0 +1,68 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "entityFactory.h" + +static void addEntityDef(char *name, int type, Entity *(*initFunc)(void)); + +static EntityDef head; +static EntityDef *tail; + +void initEntityFactory(void) +{ + memset(&head, 0, sizeof(EntityDef)); + tail = &head; + + addEntityDef("AquaBlob", ET_ENEMY, initAquaBlob); + + addEntityDef("Bob", ET_BOB, initBob); +} + +Entity *createEntity(char *name) +{ + EntityDef *def; + + for (def = head.next ; def != NULL ; def = def->next) + { + if (strcmp(def->name, name) == 0) + { + return def->initFunc(); + } + } + + SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "No such entity definition '%s'", name); + exit(1); + + return NULL; +} + +static void addEntityDef(char *name, int type, Entity *(*initFunc)(void)) +{ + EntityDef *def; + + def = malloc(sizeof(EntityDef)); + memset(def, 0, sizeof(EntityDef)); + tail->next = def; + tail = def; + + STRNCPY(def->name, name, MAX_NAME_LENGTH); + def->type = type; + def->initFunc = initFunc; +} diff --git a/src/entities/entityFactory.h b/src/entities/entityFactory.h new file mode 100644 index 0000000..c9c3a8c --- /dev/null +++ b/src/entities/entityFactory.h @@ -0,0 +1,24 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../common.h" + +extern Entity *initAquaBlob(void); +extern Entity *initBob(void); diff --git a/src/entities/evilBlobs/aquaBlob.c b/src/entities/evilBlobs/aquaBlob.c new file mode 100644 index 0000000..b57cce5 --- /dev/null +++ b/src/entities/evilBlobs/aquaBlob.c @@ -0,0 +1,49 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "aquaBlob.h" + +static int canFire(Entity *target); + +void initAquaBlob(void) +{ + Unit *u; + + u = createUnit(); + + initEvilBlob(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("AquaBlobLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("AquaBlobRight"); + u->sprite[FACING_DIE] = getSpriteIndex("AquaBlobSpin"); + + u->weaponType = WPN_AIMED_PISTOL; + + u->flags |= EF_SWIMS | EF_WATER_BREATHING; + + u->maxShotsToFire = 3; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return 1; +} diff --git a/src/entities/evilBlobs/aquaBlob.h b/src/entities/evilBlobs/aquaBlob.h new file mode 100644 index 0000000..b0f5b52 --- /dev/null +++ b/src/entities/evilBlobs/aquaBlob.h @@ -0,0 +1,25 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../../common.h" + +extern Unit *createUnit(void); +extern void initEvilBlob(Unit *u); +extern int getSpriteIndex(char *name); diff --git a/src/entities/evilBlobs/evilBlob.c b/src/entities/evilBlobs/evilBlob.c new file mode 100644 index 0000000..b7a6c36 --- /dev/null +++ b/src/entities/evilBlobs/evilBlob.c @@ -0,0 +1,311 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "evilBlob.h" + +static void (*superAnimate)(void); +static void die(void); +static void die2(void); +static void returnToStart(void); +static void lookForPlayer(void); +static void walk(void); +static void animate(void); + +void initEvilBlob(Unit *u) +{ + u->reload = 0; + + u->returnToStartTimer = 0; + + u->flags |= EF_HALT_AT_EDGE; + + superAnimate = u->animate; + + u->walk = walk; + u->animate = animate; + u->die = die; +} + +static void die2(void) +{ + Unit *u; + int mx, my; + + u = (Unit*)self; + + u->health--; + + /* burst on impact, due to speed */ + if (u->dy > 15) + { + u->health = -FPS; + } + + if (u->health <= -FPS && (u->isOnGround || u->environment != ENV_AIR)) + { + dropCarriedItem(); + + u->alive = ALIVE_DEAD; + + throwFleshChunks(u->x + u->w / 2, u->y + u->h / 2, rrnd(3, 6)); + + if (rand() % 10 < 3) + { + addRandomWeapon(u->x, u->y); + } + + addRandomItems(u->x, u->y); + + updateObjective(u->name); + updateObjective("ENEMY"); + fireTriggers(u->name); + + if (u->isMissionTarget) + { + addDefeatedTarget(u->name); + } + + game.enemiesKilled++; + + mx = (int) ((u->x + (u->w / 2)) / MAP_TILE_SIZE); + my = (int) (u->y / MAP_TILE_SIZE) + 1; + addBloodDecal(mx, my); + + playSound(SND_SPLAT, CH_ANY); + } +} + +static void moveTowardsPlayer(void) +{ + Unit *u; + + u = (Unit*)self; + + if (world.bob->x < u->x) + { + u->dx = -2; + u->facing = FACING_LEFT; + } + else if (world.bob->x > u->x) + { + u->dx = 2; + u->facing = FACING_RIGHT; + } + + if (u->flags & EF_SWIMS) + { + u->dx = limit(u->dx, -1, 1); + + if (world.bob->y < u->y) + { + u->dy = -1; + } + else + { + u->dy = 1; + } + } +} + +static void patrol(void) +{ + Unit *u; + + u = (Unit*)self; + + if (u->returnToStartTimer > 0) + { + returnToStart(); + return; + } + + if (!u->spawnedIn && rand() % 100 < 25) + { + u->returnToStartTimer = FPS * 3; + } + + u->facing = rand() % 100 < 50 ? FACING_LEFT : FACING_RIGHT; + u->dx = rrnd(-1, 1); + u->thinkTime = rrnd(FPS / 2, FPS); + + if (u->dx == -1) + { + u->facing = FACING_LEFT; + } + else if (u->dx == 1) + { + u->facing = FACING_RIGHT; + } + + if (u->flags & EF_SWIMS) + { + u->dy = rrnd(-1, 1); + } +} + +static void returnToStart(void) +{ + Unit *u; + + u = (Unit*)self; + + u->returnToStartTimer--; + + u->thinkTime = 10; + + /* jump up if your start is above you */ + if (u->startY - u->y < -64 && u->isOnGround && u->dx == 0) + { + u->dy = JUMP_POWER; + u->isOnGround = 0; + } + + u->facing = u->startX < u->x ? FACING_LEFT : FACING_RIGHT; + u->dx = u->facing == FACING_LEFT ? -1 : 1; + if (!u->isOnGround) + { + u->thinkTime = 0; + u->returnToStartTimer = MAX(u->returnToStartTimer, FPS); + u->dx *= 2; + } + + if (u->flags & EF_SWIMS) + { + u->dy = u->startY < u->y ? -1 : -1; + } + + if (abs(u->startX - u->x) <= MAP_TILE_SIZE) + { + u->returnToStartTimer = 0; + } +} + +static void lookForPlayer(void) +{ + Unit *u; + float r; + + u = (Unit*)self; + + u->thinkTime = (int) rrnd(FPS / 2, FPS); + + if (world.state != WS_IN_PROGRESS || dev.cheatBlind) + { + patrol(); + return; + } + + 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, u->x, u->y) > 650) + { + patrol(); + return; + } + + if (!enemyCanSeePlayer(self)) + { + patrol(); + return; + } + + r = randF(); + if (u->isMissionTarget) + { + r = randF() * 0.3; + } + + if (r < 0.125) + { + moveTowardsPlayer(); + u->shotsToFire = rrnd(1, u->maxShotsToFire); + u->action = u->preFire; + } + else if (r < 0.25) + { + u->dx = 0; + u->shotsToFire = rrnd(1, u->maxShotsToFire); + u->action = u->preFire; + } + else if (r < 0.5) + { + u->dx = 0; + } + else + { + moveTowardsPlayer(); + } +} + +static void walk(void) +{ + self->action = lookForPlayer; +} + +static void die(void) +{ + Unit *u; + + u = (Unit*)self; + + u->flags |= EF_BOUNCES | EF_ALWAYS_PROCESS; + + u->action = die2; + + u->thinkTime = 0; + u->spriteTime = 0; + u->spriteFrame = 0; + + if (u->environment == ENV_AIR) + { + u->dy = -9; + } + + u->dx = (randF() - randF()) * 5; + + u->flags &= ~EF_HALT_AT_EDGE; + + switch (rand() % 3) + { + case 0: + playSound(SND_DEATH_1, CH_DEATH); + break; + + case 1: + playSound(SND_DEATH_2, CH_DEATH); + break; + + case 2: + playSound(SND_DEATH_3, CH_DEATH); + break; + } +} + +static void animate(void) +{ + if (self->dx != 0 || self->health <= 0) + { + superAnimate(); + } +} diff --git a/src/entities/evilBlobs/evilBlob.h b/src/entities/evilBlobs/evilBlob.h new file mode 100644 index 0000000..a048e56 --- /dev/null +++ b/src/entities/evilBlobs/evilBlob.h @@ -0,0 +1,41 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "../../common.h" + +extern void dropCarriedItem(void); +extern int getDistance(int x1, int y1, int x2, int y2); +extern double randF(void); +extern void throwFleshChunks(double x, double y, int amount); +extern void addRandomWeapon(double x, double y); +extern float limit(float i, float a, float b); +extern void playSound(int snd, int ch); +extern void addBloodDecal(int x, int y); +extern void updateObjective(char *targetName); +extern int enemyCanSeePlayer(Entity *e); +extern void addDefeatedTarget(char *name); +extern void fireTriggers(char *name); +extern void addRandomItems(float x, float y); +extern int rrnd(int low, int high); + +extern Dev dev; +extern Entity *self; +extern Game game; +extern World world; diff --git a/src/entities/evilBlobs/grenadeBlob.c b/src/entities/evilBlobs/grenadeBlob.c new file mode 100644 index 0000000..bf0c100 --- /dev/null +++ b/src/entities/evilBlobs/grenadeBlob.c @@ -0,0 +1,60 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "grenadeBlob.h" + +static void preFire2(void); +static int canFire(Entity *target); + +void initGrenadeBlob(Unit *u) +{ + initEvilBlob(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("GrenadeBlobLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("GrenadeBlobRight"); + u->sprite[FACING_DIE] = getSpriteIndex("GrenadeBlobSpin"); + + u->weaponType = WPN_GRENADES; + + u->preFire = preFire2; + u->canFire = canFire; +} + +static void preFire2(void) +{ + preFire(this); + + if (u->shotsToFire == 0) + { + if (rand() % 100 < 25) + { + u->weaponType = WPN_AIMED_PISTOL; + } + else + { + u->weaponType = WPN_GRENADES; + } + } +} + +static int canFire(Entity *target) +{ + return abs(target->y - self->y) <= MAP_TILE_SIZE * 2; +} diff --git a/src/entities/evilBlobs/laserBlob.c b/src/entities/evilBlobs/laserBlob.c new file mode 100644 index 0000000..d640497 --- /dev/null +++ b/src/entities/evilBlobs/laserBlob.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "laserBlob.h" + +static int canFire(Entity *target); + +void initLaserBlob(Unit *u) +{ + initEvilBlob(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("LaserBlobLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("LaserBlobRight"); + u->sprite[FACING_DIE] = getSpriteIndex("LaserBlobSpin"); + + u->weaponType = WPN_LASER; + + u->maxShotsToFire = 1; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return abs(target->y - self->y) <= MAP_TILE_SIZE * 2; +} diff --git a/src/entities/evilBlobs/machineGunBlob.c b/src/entities/evilBlobs/machineGunBlob.c new file mode 100644 index 0000000..5d7299d --- /dev/null +++ b/src/entities/evilBlobs/machineGunBlob.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "machineGunBlob.h" + +static int canFire(Entity *target); + +void initMachineGunBlob(Unit *u) +{ + initEvilBlob(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("MachineGunBlobLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("MachineGunBlobRight"); + u->sprite[FACING_DIE] = getSpriteIndex("MachineGunBlobSpin"); + + u->weaponType = WPN_MACHINE_GUN; + + u->maxShotsToFire = 5; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return abs(target->y - self->y) <= MAP_TILE_SIZE * 2; +} diff --git a/src/entities/evilBlobs/pistolBlob.c b/src/entities/evilBlobs/pistolBlob.c new file mode 100644 index 0000000..1c42946 --- /dev/null +++ b/src/entities/evilBlobs/pistolBlob.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "pistolBlob.h" + +static int canFire(Entity *target); + +void initPistolBlob(Unit *u) +{ + initEvilBlob(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("PistolBlobLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("PistolBlobRight"); + u->sprite[FACING_DIE] = getSpriteIndex("PistolBlobSpin"); + + u->weaponType = WPN_AIMED_PISTOL; + + u->maxShotsToFire = 3; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return true; +} diff --git a/src/entities/evilBlobs/plasmaBlob.c b/src/entities/evilBlobs/plasmaBlob.c new file mode 100644 index 0000000..e140a34 --- /dev/null +++ b/src/entities/evilBlobs/plasmaBlob.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "plasmaBlob.h" + +static int canFire(Entity *target); + +void initPlasmaBlob(Unit *u) +{ + initEvilBlob(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("PlasmaBlobLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("PlasmaBlobRight"); + u->sprite[FACING_DIE] = getSpriteIndex("PlasmaBlobSpin"); + + u->weaponType = WPN_PLASMA; + + u->maxShotsToFire = 6; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return abs(target->y - self->y) <= MAP_TILE_SIZE * 2; +} diff --git a/src/entities/evilBlobs/shotgunBlob.c b/src/entities/evilBlobs/shotgunBlob.c new file mode 100644 index 0000000..5faf95f --- /dev/null +++ b/src/entities/evilBlobs/shotgunBlob.c @@ -0,0 +1,44 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "shotgunBlob.h" + +static int canFire(Entity *target); + +void initShotgunBlob(Unit *u) +{ + initEvilBlob(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("ShotgunBlobLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("ShotgunBlobRight"); + u->sprite[FACING_DIE] = getSpriteIndex("ShotgunBlobSpin"); + + u->weaponType = WPN_SHOTGUN; + + u->maxShotsToFire = 2; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return true; +} + diff --git a/src/entities/evilBlobs/spreadGunBlob.c b/src/entities/evilBlobs/spreadGunBlob.c new file mode 100644 index 0000000..fb99d34 --- /dev/null +++ b/src/entities/evilBlobs/spreadGunBlob.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "spreadGunBlob.h" + +static int canFire(Entity *target); + +void initSpreadGunBlob(Unit *u) +{ + initEvilBlob(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("SpreadGunBlobLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("SpreadGunBlobRight"); + u->sprite[FACING_DIE] = getSpriteIndex("SpreadGunBlobSpin"); + + u->weaponType = WPN_SPREAD; + + u->maxShotsToFire = 3; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return abs(target->y - u->y) <= MAP_TILE_SIZE * 5; +} diff --git a/src/entities/eyeDroids/eyeDroid.c b/src/entities/eyeDroids/eyeDroid.c new file mode 100644 index 0000000..039b297 --- /dev/null +++ b/src/entities/eyeDroids/eyeDroid.c @@ -0,0 +1,243 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "eyeDroid.h" + +static void tick(void); +static void superTick(void); +static void touch(void); +static void superTouch(void); + +void initEyeDroid(void) +{ + u->flags |= FL_WEIGHTLESS | FL_HALT_AT_EDGE | FL_EXPLODES; + + superTick = u->tick; + superTouch = u->touch; + + u->tick = tick; + u->touch = touch; +} + +static void tick(void) +{ + Unit *u; + + u = (Unit*)self; + + superTick(); + + if (u->alive == ALIVE_DYING) + { + addSmokeParticles(u->x + (u->w / 2), u->y); + } +} + +static void touch(Entity *other) +{ + Unit *u; + int mx, my; + + u = (Unit*)self; + + superTouch(); + + if (u->alive == ALIVE_DYING && (other == NULL || other->isSolid)) + { + dropCarriedItem(); + + u->alive = ALIVE_DEAD; + + addExplosion(u->x, u->y, 80, self); + + throwDebris(u->x + u->w / 2, u->y + u->h / 2, rrnd(3, 5)); + + if (rand() % 100 < 30) + { + addRandomWeapon(u->x, u->y); + } + + addRandomItems((int) u->x, (int) u->y); + + updateObjectives(); + + if (u->isMissionTarget) + { + addDefeatedTarget(u->name); + } + + game.enemiesKilled++; + + mx = (int) ((u->x + (u->w / 2)) / MAP_TILE_SIZE); + my = (int) ((u->y + u->h) / MAP_TILE_SIZE) + 1; + addScorchDecal(mx, my); + } +} + + +static void unitDie(void) +{ + if (self->environment != Environment.AIR) + { + touch(NULL); + } +} + +static void die(void) +{ + Unit *u; + + u = (Unit*)self; + + u->dx = (fRand() - fRand()) * 3; + + u->spriteTime = 0; + u->spriteFrame = 0; + + u->action = unitDie; + u->thinkTime = 0; + u->flags |= EF_ALWAYS_PROCESS; + u->flags &= ~(EF_WEIGHTLESS | EF_HALT_AT_EDGE); + + u->dy = JUMP_POWER; + + if (rand() % 2) + { + playSound(SND_DROID_DIE_1, CH_DEATH); + } + else + { + playSound(SND_DROID_DIE_2, CH_DEATH); + } +} + +static void chase(void) +{ + Unit *u; + + u = (Unit*)self; + + u->dx = world.bob->x - u->x; + u->dy = world.bob->y - u->y; + + u->dx = limit(u->dx, -1, 1); + u->dy = limit(u->dy, -1, 1); + + u->thinkTime = (int) rrnd(FPS / 2, FPS); + + u->facing = (u->dx >= 0) ? FACING_RIGHT : FACING_LEFT; +} + +static void patrol(void) +{ + Unit *u; + + u = (Unit*)self; + + switch (rand() % 3) + { + case 0: + u->dx = 0; + u->facing = rand() % 2 ? FACING_LEFT : FACING_RIGHT; + u->thinkTime = rrnd(FPS / 2, FPS); + break; + + case 1: + u->dx = rrnd(-100, 100); + u->dy = rrnd(-100, 100); + u->dx *= 0.01; + u->dy *= 0.01; + u->thinkTime = rrnd(FPS / 2, FPS); + u->facing = (u->dx >= 0) ? FACING_RIGHT : FACING_LEFT; + break; + + case 2: + u->dx = 0; + u->thinkTime = rrnd(FPS / 2, FPS); + break; + } +} + +static void lookForPlayer(void) +{ + Unit *u; + double distance, r; + + u = (Unit*)self; + + u->dx *= 0.5; + u->dy *= 0.5; + + u->thinkTime = rrnd(FPS / 2, FPS); + + if (world.state != WS_IN_PROGRESS || game.cheatBlind) + { + patrol(); + return; + } + + distance = getDistance(world.bob->x, world.bob->y, u->x, u->y); + + if (distance > 650) + { + patrol(); + return; + } + + if (!enemyCanSeePlayer(self)) + { + patrol(); + return; + } + + r = fRand(); + if (u->isMissionTarget) + { + r = fRand() * 0.3; + } + + if (r < 0.125) + { + chase(); + u->shotsToFire = rrnd(1, u->maxShotsToFire); + u->action = preFire; + } + else if (r < 0.25) + { + u->dx = 0; + u->shotsToFire = rrnd(1, u->maxShotsToFire); + u->action = preFire; + } + else if (r < 0.5) + { + u->dx = 0; + } + else + { + chase(); + } + + u->thinkTime = rrnd(FPS / 2, FPS); +} + +static void walk(void) +{ + self->action = lookForPlayer; +} diff --git a/src/entities/eyeDroids/grenadeDroid.c b/src/entities/eyeDroids/grenadeDroid.c new file mode 100644 index 0000000..4a7f4e8 --- /dev/null +++ b/src/entities/eyeDroids/grenadeDroid.c @@ -0,0 +1,64 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "grenadeDroid.h" + +static void preFire2(void); +static int canFire(Entity *target); + +void initGrenadeDroid(Unit *u) +{ + initEyeDroid(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("GrenadeDroidLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("GrenadeDroidRight"); + u->sprite[FACING_DIE] = getSpriteIndex("GrenadeDroidDie"); + + u->weaponType = WPN_GRENADES; + + u->preFire = preFire2; + u->canFire = canFire; +} + +static void preFire2(void) +{ + Unit *u; + + u = (Unit*)self; + + preFire(self); + + if (u->shotsToFire == 0) + { + if (rand() % 100 < 25) + { + u->weaponType = WPN_AIMED_PISTOL; + } + else + { + u->weaponType = WPN_GRENADES; + } + } +} + +static int canFire(Entity *target) +{ + return abs(target->y - y) <= MAP_TILE_SIZE * 2; +} diff --git a/src/entities/eyeDroids/laserDroid.c b/src/entities/eyeDroids/laserDroid.c new file mode 100644 index 0000000..9355484 --- /dev/null +++ b/src/entities/eyeDroids/laserDroid.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "laserDroid.h" + +static int canFire(Entity *target); + +void initLaserDroid(Unit *u) +{ + initEyeDroid(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("LaserDroidLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("LaserDroidRight"); + u->sprite[FACING_DIE] = getSpriteIndex("LaserDroidDie"); + + u->weaponType = WPN_LASER; + + u->maxShotsToFire = 1; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return abs(target->y - self->y) <= MAP_TILE_SIZE * 2; +} \ No newline at end of file diff --git a/src/entities/eyeDroids/machineGunDroid.c b/src/entities/eyeDroids/machineGunDroid.c new file mode 100644 index 0000000..1f70237 --- /dev/null +++ b/src/entities/eyeDroids/machineGunDroid.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "machineGunDroid.h" + +static int canFire(Entity *target); + +void initMachineGunDroid(Unit *u) +{ + initEyeDroid(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("MachineGunDroidLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("MachineGunDroidRight"); + u->sprite[FACING_DIE] = getSpriteIndex("MachineGunDroidDie"); + + u->weaponType = WPN_MACHINE_GUN; + + u->maxShotsToFire = 5; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return abs(target->y - self->y) <= MAP_TILE_SIZE * 2; +} diff --git a/src/entities/eyeDroids/pistolDroid.c b/src/entities/eyeDroids/pistolDroid.c new file mode 100644 index 0000000..0636ca8 --- /dev/null +++ b/src/entities/eyeDroids/pistolDroid.c @@ -0,0 +1,41 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "pistolDroid.h" + +static int canFire(Entity *target); + +void initPistolDroid(Unit *u) +{ + u->sprite[FACING_LEFT] = getSpriteIndex("PistolDroidLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("PistolDroidRight"); + u->sprite[FACING_DIE] = getSpriteIndex("PistolDroidDie"); + + u->weaponType = WPN_AIMED_PISTOL; + + u->maxShotsToFire = 3; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return true; +} diff --git a/src/entities/eyeDroids/plasmaDroid.c b/src/entities/eyeDroids/plasmaDroid.c new file mode 100644 index 0000000..e066663 --- /dev/null +++ b/src/entities/eyeDroids/plasmaDroid.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "plasmaDroid.h" + +static int canFire(Entity *target); + +void initPlasmaDroid(Unit *u) +{ + initEyeDroid(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("PlasmaDroidLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("PlasmaDroidRight"); + u->sprite[FACING_DIE] = getSpriteIndex("PlasmaDroidDie"); + + u->weaponType = WPN_PLASMA; + + u->maxShotsToFire = 6; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return abs(target->y - self->y) <= MAP_TILE_SIZE * 2; +} diff --git a/src/entities/eyeDroids/shotgunDroid.c b/src/entities/eyeDroids/shotgunDroid.c new file mode 100644 index 0000000..ba58905 --- /dev/null +++ b/src/entities/eyeDroids/shotgunDroid.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "shotgunDroid.h" + +static int canFire(Entity *target); + +void initShotgunDroid(Unit *u) +{ + initEyeDroid(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("ShotgunDroidLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("ShotgunDroidRight"); + u->sprite[FACING_DIE] = getSpriteIndex("ShotgunDroidDie"); + + u->weaponType = WPN_SHOTGUN; + + u->maxShotsToFire = 2; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return true; +} diff --git a/src/entities/eyeDroids/spreadGunDroid.c b/src/entities/eyeDroids/spreadGunDroid.c new file mode 100644 index 0000000..5377e71 --- /dev/null +++ b/src/entities/eyeDroids/spreadGunDroid.c @@ -0,0 +1,43 @@ +/* +Copyright (C) 2018 Parallel Realities + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "spreadGunDroid.h" + +static int canFire(Entity *target); + +void initSpreadGunDroid(Unit *u) +{ + initEyeDroid(u); + + u->sprite[FACING_LEFT] = getSpriteIndex("SpreadGunDroidLeft"); + u->sprite[FACING_RIGHT] = getSpriteIndex("SpreadGunDroidRight"); + u->sprite[FACING_DIE] = getSpriteIndex("SpreadGunDroidDie"); + + u->weaponType = WPN_SPREAD; + + u->maxShotsToFire = 3; + + u->canFire = canFire; +} + +static int canFire(Entity *target) +{ + return abs(target->y - self->y) <= MAP_TILE_SIZE * 5; +} diff --git a/src/entities/traps/laserTrap.c b/src/entities/traps/laserTrap.c index 1f92796..d3c31c9 100644 --- a/src/entities/traps/laserTrap.c +++ b/src/entities/traps/laserTrap.c @@ -130,7 +130,7 @@ static void touch(Entity *other) if (other == (Entity*)world.bob && world.bob->stunTimer == 0) { - stunPlayer(); + stunBob(); } } diff --git a/src/entities/traps/laserTrap.h b/src/entities/traps/laserTrap.h index a933dc8..9577373 100644 --- a/src/entities/traps/laserTrap.h +++ b/src/entities/traps/laserTrap.h @@ -26,7 +26,7 @@ extern int isOnScreen(Entity *e); extern void setGameplayMessage(int type, char *format, ...); extern int getSpriteIndex(char *name); extern int rrnd(int low, int high); -extern void stunPlayer(void); +extern void stunBob(void); extern void addSparkParticles(float x, float y); extern void addSmallFleshChunk(float x, float y); diff --git a/src/entities/unit.c b/src/entities/unit.c index d2f4a3e..5553cbe 100644 --- a/src/entities/unit.c +++ b/src/entities/unit.c @@ -23,14 +23,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void unitTick(void); static void attack(void); static int canFire(Entity *target); +static void preFire(void); -void initUnit(Entity *e) +Unit *createUnit(void) { Unit *u; - initEntity(e); + u = malloc(sizeof(Unit)); + memset(u, 0, sizeof(Unit)); + world.entityTail->next = (Entity*)u; + world.entityTail = (Entity*)u; - u = (Unit*)e; + initEntity((Entity*)u); u->oxygen = MAX_OXYGEN; @@ -48,8 +52,11 @@ void initUnit(Entity *e) u->tick = unitTick; u->action = lookForPlayer; + u->preFire = preFire; u->attack = attack; u->canFire = canFire; + + return u; } void reInitUnit(Entity *e) @@ -177,6 +184,37 @@ static void attack(void) } } +static void preFire(void) +{ + Unit *u; + + u = (Unit*)self; + + if (!(u->flags & EF_WEIGHTLESS)) + { + if (world.bob->y < u->y && u->isOnGround && rand() % 4 == 0) + { + u->dy = JUMP_POWER; + } + } + + u->facing = (world.bob->x < u->x) ? FACING_LEFT : FACING_RIGHT; + + if (u->reload > 0) + { + return; + } + + u->attack(); + + u->shotsToFire--; + + if (u->shotsToFire == 0) + { + u->walk(); + } +} + static int canFire(Entity *target) { return 0; diff --git a/src/structs.h b/src/structs.h index 745aba1..a97296c 100644 --- a/src/structs.h +++ b/src/structs.h @@ -31,6 +31,7 @@ typedef struct HubMission HubMission; typedef struct Widget Widget; typedef struct Atlas Atlas; typedef struct Bucket Bucket; +typedef struct EntityDef EntityDef; typedef struct Entity Entity; typedef struct EntityExt EntityExt; @@ -92,6 +93,13 @@ struct Lookup { Lookup *next; }; +struct EntityDef { + char name[MAX_NAME_LENGTH]; + int type; + Entity *(*initFunc)(void); + EntityDef *next; +}; + typedef struct { void (*logic)(void); void (*draw)(void); @@ -160,7 +168,9 @@ struct Unit { int spawnedInTimer; int oxygen; int spawnedIn; + int returnToStartTimer; int startX, startY; + void (*preFire)(void); void (*attack)(void); int (*canFire)(Entity *target); }; diff --git a/src/system/init.c b/src/system/init.c index 3ff34a1..4e27847 100644 --- a/src/system/init.c +++ b/src/system/init.c @@ -72,7 +72,8 @@ void initGameSystem(void) initFonts, initAtlas, initSounds, - initSprites + initSprites, + initEntityFactory }; numInitFuns = sizeof(initFuncs) / sizeof(void*); diff --git a/src/system/init.h b/src/system/init.h index b030ce2..0427ac1 100644 --- a/src/system/init.h +++ b/src/system/init.h @@ -31,6 +31,7 @@ extern void initFonts(void); extern void initAtlas(void); extern void initSounds(void); extern void initSprites(void); +extern void initEntityFactory(void); extern void destroyLookups(void); extern void destroyFonts(void); extern void destroyTextures(void); diff --git a/src/world/items.c b/src/world/items.c index 8294952..d653807 100644 --- a/src/world/items.c +++ b/src/world/items.c @@ -167,7 +167,7 @@ void dropBattery(double x, double y) throwItem(i); } -void addRandomItems(double x, double y) +void addRandomItems(float x, float y) { if (rand() % 100 < 25) { diff --git a/src/world/items.h b/src/world/items.h index c4b62e7..d479146 100644 --- a/src/world/items.h +++ b/src/world/items.h @@ -23,5 +23,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern int rrnd(int low, int high); extern int getRandomPlayerWeapon(int excludeGrenades); extern int getSpriteIndex(char *name); +extern void addRandomItems(float x, float y); extern World world; diff --git a/src/world/player.c b/src/world/player.c index 2fff4f3..8e84232 100644 --- a/src/world/player.c +++ b/src/world/player.c @@ -20,6 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "player.h" -void stunPlayer(void) +void stunBob(void) { } diff --git a/src/world/worldLoader.c b/src/world/worldLoader.c index 8451a5c..d1f7078 100644 --- a/src/world/worldLoader.c +++ b/src/world/worldLoader.c @@ -128,7 +128,7 @@ static void loadBob(cJSON *root) { Bob *b; - b = (Bob*)createEntity(ET_BOB); + b = (Bob*)createEntity("Bob"); b->x = cJSON_GetObjectItem(root, "x")->valueint; b->y = cJSON_GetObjectItem(root, "y")->valueint; b->facing = lookup(cJSON_GetObjectItem(root, "facing")->valuestring); @@ -138,8 +138,32 @@ static void loadBob(cJSON *root) static void loadEntities(cJSON *root) { + cJSON *node; + + for (node = root->child ; node != NULL ; node = node->next) + { + createEntity(cJSON_GetObjectItem(node, "type")->valuestring); + } } static void loadObjectives(cJSON *root) { + Objective *o; + cJSON *node; + + for (node = root->child ; node != NULL ; node = node->next) + { + o = malloc(sizeof(Objective)); + memset(o, 0, sizeof(Objective)); + world.objectiveTail->next = o; + world.objectiveTail = o; + + STRNCPY(o->id, cJSON_GetObjectItem(node, "id")->valuestring, MAX_NAME_LENGTH); + STRNCPY(o->targetName, cJSON_GetObjectItem(node, "targetName")->valuestring, MAX_NAME_LENGTH); + STRNCPY(o->description, cJSON_GetObjectItem(node, "description")->valuestring, MAX_DESCRIPTION_LENGTH); + o->totalValue = cJSON_GetObjectItem(node, "totalValue")->valueint; + o->targetValue = cJSON_GetObjectItem(node, "totalValue")->valueint; + o->currentValue = cJSON_GetObjectItem(node, "currentValue")->valueint; + o->required = cJSON_GetObjectItem(node, "required")->valueint; + } } diff --git a/src/world/worldLoader.h b/src/world/worldLoader.h index 3b97654..53392ff 100644 --- a/src/world/worldLoader.h +++ b/src/world/worldLoader.h @@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern char *readFile(const char *filename); extern void loadSprite(cJSON *root); -extern Entity *createEntity(int type); +extern Entity *createEntity(char *typeStr); extern long lookup(const char *name); extern void initBob(Bob *b);