blobwarsAttrition/src/entities/eyeDroids/eyeDroid.c

259 lines
4.3 KiB
C

/*
Copyright (C) 2018-2019 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 die(void);
static void tick(void);
static void lookForPlayer(void);
static void touch(Entity *other);
static void (*superTick)(void);
static void (*superTouch)(Entity *other);
Unit *createEyeDroid(void)
{
Unit *u;
u = createUnit();
u->flags |= EF_WEIGHTLESS | EF_HALT_AT_EDGE | EF_EXPLODES;
superTick = u->tick;
superTouch = u->touch;
u->walk = lookForPlayer;
u->action = lookForPlayer;
u->tick = tick;
u->touch = touch;
u->die = die;
return u;
}
static void tick(void)
{
Unit *u;
u = (Unit*)self;
superTick();
if (u->alive == ALIVE_DYING)
{
addSmokeParticles(u->x + (u->w / 2), u->y, 0);
}
}
static void touch(Entity *other)
{
Unit *u;
int mx, my;
u = (Unit*)self;
superTouch(other);
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 < 35)
{
addRandomWeapon(u->x, u->y);
}
addRandomItems(u->x, u->y);
updateObjective(u->name);
updateObjective("ENEMY");
fireTriggers(u->name);
if (u->isMissionTarget)
{
game.stats[STAT_TARGETS_DEFEATED]++;
}
game.stats[STAT_ENEMIES_KILLED]++;
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 != ENV_AIR)
{
touch(NULL);
}
}
static void die(void)
{
Unit *u;
u = (Unit*)self;
u->dx = (randF() - randF()) * 3;
u->facing = FACING_DIE;
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 | EF_GONE);
u->dy = JUMP_POWER;
if (rand() % 2)
{
playBattleSound(SND_DROID_DIE_1, u->uniqueId % MAX_SND_CHANNELS, u->x, u->y);
}
else
{
playBattleSound(SND_DROID_DIE_2, u->uniqueId % MAX_SND_CHANNELS, u->x, u->y);
}
}
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 || dev.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 = randF();
if (world.missionType == MT_OUTPOST || game.plus)
{
r = randF() * 0.65;
}
if (u->isMissionTarget)
{
r = randF() * 0.3;
}
if (r < 0.1)
{
chase();
u->shotsToFire = rrnd(1, u->maxShotsToFire);
u->action = u->preFire;
}
else if (r < 0.2)
{
u->dx = 0;
u->shotsToFire = rrnd(1, u->maxShotsToFire);
u->action = u->preFire;
}
else if (r < 0.5)
{
u->dx = 0;
}
else
{
chase();
}
u->thinkTime = rrnd(FPS / 2, FPS);
}