diff --git a/common.mk b/common.mk index ee22f89..3897eb2 100644 --- a/common.mk +++ b/common.mk @@ -22,7 +22,7 @@ OBJS += particles.o player.o OBJS += quadtree.o OBJS += sound.o sprites.o OBJS += text.o textures.o title.o triggers.o -OBJS += util.o +OBJS += unit.o util.o OBJS += weapons.o widgets.o # top-level rule to create the program. diff --git a/src/combat/combat.c b/src/combat/combat.c index bb29e8a..b80b7b7 100644 --- a/src/combat/combat.c +++ b/src/combat/combat.c @@ -23,6 +23,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static int isBlockedByMap(Entity *src, Entity *dest); static int isBlockedByEntities(Entity *src, Entity *dest); +void lookForPlayer(void) +{ + +} + void preFire(Entity *e) { if (e->flags & EF_WEIGHTLESS) @@ -123,3 +128,8 @@ int enemyCanSeePlayer(Entity *e) { return hasLineOfSight(e, world.bob); } + +int canFire(Entity *target) +{ + return 0; +} diff --git a/src/defs.h b/src/defs.h index e99f398..005ccfa 100644 --- a/src/defs.h +++ b/src/defs.h @@ -76,7 +76,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_SPRITE_FRAMES 8 -#define JUMP_POWER 1 +#define JUMP_POWER -12 +#define MAX_OXYGEN (FPS * 10) #define MAX_KEY_TYPES 12 #define MAX_WIDGET_OPTIONS 8 @@ -135,7 +136,8 @@ enum enum { FACING_RIGHT, - FACING_LEFT + FACING_LEFT, + FACING_DIE }; enum @@ -154,7 +156,8 @@ enum enum { - ALIVE_ALIVE + ALIVE_ALIVE, + ALIVE_DEAD }; enum @@ -193,7 +196,10 @@ enum enum { - ENV_AIR + ENV_AIR, + ENV_WATER, + ENV_SLIME, + ENV_LAVA }; enum @@ -258,6 +264,7 @@ enum enum { + CH_ANY = -1, CH_PLAYER, CH_EXPLODE, CH_WEAPON, diff --git a/src/main.h b/src/main.h index 1b2c175..8f89f2e 100644 --- a/src/main.h +++ b/src/main.h @@ -33,5 +33,6 @@ App app; Camera camera; Colors colors; Dev dev; +Entity *self; Game game; World world; diff --git a/src/structs.h b/src/structs.h index 49c2173..ae20642 100644 --- a/src/structs.h +++ b/src/structs.h @@ -94,6 +94,9 @@ struct Entity { int health; int healthMax; int alive; + int oxygen; + int startX; + int startY; float dx; float dy; int tx; @@ -111,15 +114,21 @@ struct Entity { int thinkTime; int plane; int value; + int canCarryItem; + int spawnedIn; + int spawnedInTimer; long flags; SDL_Rect bounds; int sprite[3]; int spriteTime; int spriteFrame; + Entity *carriedItem; Entity *owner; + void (*currentAction)(void); void (*walk)(void); void (*attack)(void); void (*touch)(Entity *other); + void (*tick)(void); Entity *next; }; @@ -301,8 +310,10 @@ typedef struct { Entity entityHead, *entityTail; Particle particleHead, *particleTail; int allObjectivesComplete; + int frameCounter; int currentStatus; int isBossMission; + int isOutpostMission; Quadtree quadtree; Objective objectiveHead, *objectiveTail; Trigger triggerHead, *triggerTail; diff --git a/src/world/entities.c b/src/world/entities.c index b5f265a..b795677 100644 --- a/src/world/entities.c +++ b/src/world/entities.c @@ -76,7 +76,12 @@ SDL_Rect *getEntityBounds(Entity *e) int getCurrentEntitySprite(Entity *e) { - return e->sprite[e->facing]; + if (e->alive == ALIVE_ALIVE) + { + return e->sprite[e->facing]; + } + + return e->sprite[FACING_DIE]; } void animateEntity(Entity *e) @@ -143,6 +148,29 @@ void activateEntities(char *names, int activate) { } -void applyEntityDamage(Entity *e, int amount) +void applyEntityDamage(Entity *e, int damage) { + if (e->health < 0) + { + e->health = 0; + e->alive = ALIVE_ALIVE; + } + + e->health -= damage; + + if (e->health > 0) + { + e->thinkTime = 0; + + e->facing = e->x < world.bob->x ? FACING_RIGHT : FACING_LEFT; + + if (e->isMissionTarget && rand() % 10 == 0) + { + e->currentAction = unitReappear; + e->flags |= EF_GONE; + e->thinkTime = rand() % FPS; + addTeleportStars(e); + playSound(SND_APPEAR, CH_ANY); + } + } } diff --git a/src/world/entities.h b/src/world/entities.h index 8417d02..53a495d 100644 --- a/src/world/entities.h +++ b/src/world/entities.h @@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern Sprite *getSpriteByIndex(int x); extern float wrap(float value, float low, float high); extern void addTeleportStars(Entity *e); +extern void unitReappear(void); +extern void playSound(int snd, int ch); extern Game game; extern World world; diff --git a/src/world/unit.c b/src/world/unit.c new file mode 100644 index 0000000..d49274c --- /dev/null +++ b/src/world/unit.c @@ -0,0 +1,179 @@ +/* +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 "unit.h" + +static void tick(void); +static void attack(void); + +void initUnit(Entity *e) +{ + initEntity(e); + + e->oxygen = MAX_OXYGEN; + + e->canCarryItem = rand() % 100 < 85; + + if (world.isOutpostMission) + { + e->canCarryItem = 1; + e->health = e->healthMax = rrnd(1, 4); + } + + e->spriteFrame = 0; + + e->startX = e->startY = -1; + + e->tick = tick; + e->currentAction = lookForPlayer; + e->attack = attack; +} + +void reInitUnit(Entity *e) +{ + if (e->startX == -1 && e->startY == -1) + { + e->startX = (int) e->x; + e->startY = (int) e->y; + } + + if (e->isMissionTarget) + { + e->flags |= EF_BOMB_SHIELD; + } +} + +static void tick(void) +{ + if (self->alive == ALIVE_ALIVE) + { + self->reload = limit(self->reload - 1, 0, FPS); + } + + switch (self->environment) + { + case ENV_AIR: + self->oxygen = limit(self->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) + { + self->health--; + } + break; + + case ENV_SLIME: + case ENV_LAVA: + if (self->alive == ALIVE_ALIVE) + { + self->health = 0; + } + break; + } + + if (self->flags & EF_WATER_BREATHING) + { + self->oxygen = MAX_OXYGEN; + } + + if (self->spawnedIn) + { + if (getDistance(self->x, self->y, world.bob->x, world.bob->y) < 1000) + { + self->spawnedInTimer = FPS * 5; + } + + self->spawnedInTimer--; + if (self->spawnedInTimer <= 0) + { + self->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)) + { + switch (self->weaponType) + { + case WPN_AIMED_PISTOL: + fireAimedShot(self); + break; + + case WPN_MACHINE_GUN: + fireMachineGun(self); + break; + + case WPN_GRENADES: + fireGrenade(self); + break; + + case WPN_PLASMA: + firePlasma(self); + break; + + case WPN_SPREAD: + fireSpread(self, 3); + break; + + case WPN_LASER: + fireLaser(self); + break; + + case WPN_SHOTGUN: + fireShotgun(self); + break; + + case WPN_MISSILE: + fireMissile(self); + break; + + default: + printf("Can't fire weapon: %d\n", self->weaponType); + break; + } + } +} + + diff --git a/src/world/unit.h b/src/world/unit.h new file mode 100644 index 0000000..3bfc598 --- /dev/null +++ b/src/world/unit.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 initEntity(Entity *e); +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 void addTeleportStars(Entity *e); +extern void playSound(int snd, int ch); +extern int canFire(Entity *target); +extern void fireAimedShot(Entity *e); +extern void fireMachineGun(Entity *e); +extern void fireGrenade(Entity *e); +extern void firePlasma(Entity *e); +extern void fireSpread(Entity *e, int n); +extern void fireLaser(Entity *e); +extern void fireShotgun(Entity *e); +extern void fireMissile(Entity *e); + +extern Entity *self; +extern World world;