Пример #1
0
static void stalagmiteAttack()
{
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add a stalagmite");
		}

		loadProperties("item/stalagmite", e);

		setEntityAnimation(e, "STAND");

		e->x = self->x + self->w / 2;
		e->y = self->y + self->h / 2;

		e->targetX = player.x + player.w / 2 - e->w / 2;
		e->targetY = getMapFloor(self->x, self->y);

		e->startY = e->targetY - e->h;

		calculatePath(e->x, e->y, e->targetX, e->targetY, &e->dirX, &e->dirY);

		e->flags |= (NO_DRAW|HELPLESS|TELEPORTING|NO_END_TELEPORT_SOUND);

		playSoundToMap("sound/common/spell", -1, self->x, self->y, 0);

		e->head = self;

		e->face = RIGHT;

		setEntityAnimation(e, "STAND");

		e->action = &stalagmiteRise;

		e->draw = &drawLoopingAnimationToMap;

		e->touch = &entityTouch;

		e->damage = 2;

		e->takeDamage = &stalagmiteTakeDamage;

		e->die = &stalagmiteDie;

		e->head = self;

		e->face = self->face;

		e->type = ENEMY;

		e->thinkTime = 0;

		e->flags |= DO_NOT_PERSIST;

		self->mental--;

		if (self->mental <= 0)
		{
			self->thinkTime = 60;

			self->action = &stalagmiteAttackFinish;
		}

		else
		{
			self->thinkTime = 180;
		}
	}

	self->maxThinkTime--;

	checkToMap(self);
}
Пример #2
0
static void entityWait()
{
	int i;
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		self->mental = self->mental == 0 ? 1 : 0;

		self->thinkTime = 120;

		for (i=0;i<2;i++)
		{
			e = getFreeEntity();

			if (e == NULL)
			{
				showErrorAndExit("No free slots to add a Flame Statue Flame");
			}

			loadProperties("enemy/horizontal_flame", e);

			if (i == 0)
			{
				e->face = RIGHT;

				e->x = self->x + self->w;

				e->y = self->y + (self->mental == 1 ? self->offsetY : self->offsetX);
			}

			else
			{
				e->face = LEFT;

				e->x = self->x - e->w;

				e->y = self->y + (self->mental == 0 ? self->offsetY : self->offsetX);
			}

			e->action = &flameWait;
			e->draw = &drawLoopingAnimationToMap;
			e->touch = &flameTouch;

			e->head = self;

			e->thinkTime = self->thinkTime;

			if (i == 0)
			{
				e->endY = playSoundToMap("sound/enemy/fire_burner/flame", -1, self->x, self->y, -1);
			}

			else
			{
				e->endY = -1;
			}

			e->type = ENEMY;

			e->flags |= DO_NOT_PERSIST|PLAYER_TOUCH_ONLY;

			setEntityAnimation(e, "STAND");
		}

		self->action = &doFlame;
	}

	self->dirX = self->standingOn != NULL ? self->standingOn->dirX : 0;

	checkToMap(self);
}
Пример #3
0
static void lightningCageCreate()
{
	int i;
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		setEntityAnimation(self, "LIGHTNING_CAGE");

		self->x = player.x + player.w / 2 - self->w / 2;

		addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2);

		playSoundToMap("sound/common/spell", -1, self->x, self->y, 0);

		self->flags &= ~NO_DRAW;

		self->face = prand() % 2 == 0 ? LEFT : RIGHT;

		self->mental = 0;

		self->thinkTime = 60;

		self->maxThinkTime = 0;

		for (i=0;i<2;i++)
		{
			e = getFreeEntity();

			if (e == NULL)
			{
				showErrorAndExit("No free slots to add a lightning cage");
			}

			loadProperties("boss/azriel_lightning_cage_spell", e);

			e->action = &lightningCageWait;

			e->draw = &drawLoopingAnimationToMap;

			e->touch = &entityTouch;

			e->head = self;

			e->face = i == 0 ? LEFT : RIGHT;

			setEntityAnimation(e, "STAND");

			if (e->face == LEFT)
			{
				e->x = self->x + self->w - e->w - e->offsetX;
			}

			else
			{
				e->x = self->x + e->offsetX;
			}

			e->y = self->y + e->offsetY;
		}

		self->action = &lightningCageMoveAbovePlayer;
	}

	becomeTransparent();
}
Пример #4
0
static void acidStream()
{
	Entity *e;

	self->endY--;

	if (self->endY <= 0)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add Acid");
		}

		loadProperties("boss/cave_boss_acid", e);

		setEntityAnimation(e, "DOWN");

		if (self->face == LEFT)
		{
			e->x = self->x + self->w - self->offsetX;
		}

		else
		{
			e->x = self->x + self->offsetX;
		}

		e->y = self->y + self->offsetY;

		e->x -= e->w / 2;

		e->action = &fireFall;
		e->draw = &drawLoopingAnimationToMap;
		e->touch = &entityTouch;

		e->face = self->face;

		e->type = ENEMY;

		e->health = 0;

		self->endY = 6;
	}

	if (self->mental == 0)
	{
		self->thinkTime--;

		if (self->thinkTime <= 0)
		{
			setEntityAnimation(self, "NORMAL_ATTACK_DOWN_WALK");

			self->thinkTime = 60;

			self->mental = 1;

			self->dirX = self->face == LEFT ? self->speed : -self->speed;
		}
	}

	else
	{
		if (self->dirX == 0)
		{
			setEntityAnimation(self, "NORMAL_ATTACK_DOWN");

			self->thinkTime--;

			if (self->thinkTime <= 0)
			{
				self->targetX = getMapStartX() + SCREEN_WIDTH / 2 - self->w / 2;

				self->dirX = self->targetX < self->x ? -self->speed : self->speed;

				self->action = &acidStreamFinish;

				setEntityAnimation(self, "NORMAL_WALK");
			}
		}
	}

	checkToMap(self);
}
Пример #5
0
static void ceilingBurn()
{
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add Fire");
		}

		loadProperties("enemy/fire", e);

		setEntityAnimation(e, "UP");

		if (self->face == LEFT)
		{
			e->x = self->x + self->w - self->offsetX;
		}

		else
		{
			e->x = self->x + self->offsetX;
		}

		e->y = self->y + self->offsetY;

		e->x -= e->w / 2;

		e->action = &fireFall;
		e->draw = &drawLoopingAnimationToMap;
		e->touch = &entityTouch;

		e->face = self->face;

		e->type = ENEMY;

		e->flags |= FLY;

		e->thinkTime = 600;

		e->dirY = -15;

		self->mental--;

		if (self->mental <= 0)
		{
			self->endY += TILE_SIZE / 2 - e->w / 2;

			self->thinkTime = 30;

			self->action = &ceilingBurnWait;
		}

		else
		{
			self->thinkTime = 6;
		}
	}

	checkToMap(self);
}
Пример #6
0
static void createBody()
{
    char bodyName[MAX_VALUE_LENGTH];
    int i;
    Entity **body, *head;

    body = malloc(self->mental * sizeof(Entity *));

    if (body == NULL)
    {
        showErrorAndExit("Failed to allocate a whole %d bytes for Snake Boss body...", self->mental * (int)sizeof(Entity *));
    }

    snprintf(bodyName, sizeof(bodyName), "%s_body", self->name);

    for (i=self->mental-1; i>=0; i--)
    {
        body[i] = getFreeEntity();

        if (body[i] == NULL)
        {
            showErrorAndExit("No free slots to add a Snake Boss body part");
        }

        loadProperties(bodyName, body[i]);

        body[i]->x = self->x;
        body[i]->y = self->y;

        body[i]->action = &bodyWait;

        body[i]->draw = &drawLoopingAnimationToMap;
        body[i]->touch = &entityTouch;
        body[i]->die = &entityDieNoDrop;
        body[i]->takeDamage = &bodyTakeDamage;

        body[i]->creditsAction = &bodyWait;

        body[i]->type = ENEMY;

        body[i]->active = FALSE;

        body[i]->flags |= NO_DRAW;

        setEntityAnimation(body[i], "STAND");
    }

    /* Recreate the head so that it's on top */

    head = getFreeEntity();

    if (head == NULL)
    {
        showErrorAndExit("No free slots to add a Snake Boss head");
    }

    *head = *self;

    self->inUse = FALSE;

    self = head;

    /* Link the sections */

    for (i=self->mental-1; i>=0; i--)
    {
        if (i == 0)
        {
            self->target = body[i];
        }

        else
        {
            body[i - 1]->target = body[i];
        }

        body[i]->head = self;
    }

    free(body);
}
Пример #7
0
static void addSegments()
{
	char name[MAX_VALUE_LENGTH];
	int i, frameCount, mental;
	Entity *e, *prev;

	prev = self;

	if (strcmpignorecase(self->name, "enemy/green_centipede") == 0)
	{
		mental = 2;
	}

	else if (strcmpignorecase(self->name, "enemy/red_centipede") == 0)
	{
		mental = 1;
	}

	else
	{
		mental = 0;
	}

	snprintf(name, MAX_VALUE_LENGTH, "%s_segment", self->name);

	for (i=0;i<5;i++)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add a Centipede Segment");
		}

		loadProperties(name, e);

		e->action = &segmentInit;
		e->draw = &drawLoopingAnimationToMap;
		e->touch = &entityTouch;
		e->takeDamage = &segmentTakeDamage;
		e->die = &entityDieNoDrop;

		e->creditsAction = &segmentInit;

		e->type = ENEMY;

		e->face = self->face;

		e->target = prev;

		e->head = self;

		e->speed = self->speed;

		setEntityAnimation(e, "STAND");

		frameCount = getFrameCount(e);

		e->currentFrame = prand() % frameCount;

		e->x = self->x + self->w / 2 - e->w / 2;
		e->y = self->y;

		e->mental = mental;

		STRNCPY(e->objectiveName, self->name, sizeof(e->objectiveName));

		prev = e;

		if (i == 0)
		{
			self->head = e;
		}

		if (self->flags & SPAWNED_IN)
		{
			e->flags |= SPAWNED_IN;

			e->spawnTime = self->spawnTime;
		}
	}

	self->mental = mental;
}
Пример #8
0
static void init()
{
	int i, x, y, col;
	Entity *e, *prev;

	prev = self;

	x = self->x;
	y = self->y + self->h;

	col = 1;

	if (self->mental != 2)
	{
		for (i=0;i<50;i++)
		{
			/* 4 pegs per row, plus 1 score tile and 10 rows */

			e = getFreeEntity();

			if (e == NULL)
			{
				showErrorAndExit("No free slots to add a Mastermind Peg");
			}

			if (col == 5)
			{
				loadProperties("item/mastermind_score", e);

				col = 0;

				e->mental = 1;
			}

			else
			{
				loadProperties("item/mastermind_peg", e);

				e->mental = 0;
			}

			setEntityAnimation(e, "STAND");

			if (i == 0)
			{
				y -= TILE_SIZE;
			}

			if (i != 0 && i % 5 == 0)
			{
				x = self->x;
				y -= TILE_SIZE;
			}

			else if (i != 0)
			{
				x += TILE_SIZE;
			}

			e->face = RIGHT;

			e->x = x;
			e->y = y;

			e->action = &pegWait;

			e->draw = &drawLoopingAnimationToMap;

			prev->target = e;

			prev = e;

			e->target = NULL;

			col++;
		}

		generateSolution();

		addCursor();
	}

	self->action = &entityWait;
}
Пример #9
0
static void holdPersonSpellMove()
{
	Entity *e;

	if (self->target == NULL)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add the Sorceror's Hold Person");
		}

		loadProperties("boss/sorceror_hold_person_spell", e);

		setEntityAnimation(e, "BACK");

		e->face = RIGHT;

		e->action = &holdPersonBackWait;
		e->draw = &drawLoopingAnimationToMap;

		e->x = self->x;
		e->y = self->y;

		e->layer = BACKGROUND_LAYER;

		self->target = e;

		e->head = self;
	}

	switch (self->mental)
	{
		case 3:
			self->targetY = player.y + player.h / 2 - self->h / 2 - 16;
		break;

		case 2:
			self->targetY = player.y + player.h / 2 - self->h / 2;
		break;

		default:
			self->targetY = player.y + player.h / 2 - self->h / 2 + 16;
		break;
	}

	setCustomAction(&player, &stickToFloor, 3, 0, 0);

	if (self->y < self->targetY)
	{
		self->y += 12;

		if (self->y >= self->targetY)
		{
			self->y = self->targetY;

			self->face = player.face;
		}
	}

	else
	{
		if (self->mental == 3)
		{
			setInfoBoxMessage(0, 255, 255, 255, _("Quickly turn left and right to remove the hold person spell!"));
		}

		if (self->face != player.face)
		{
			self->face = player.face;

			self->health--;

			if (self->health <= 0)
			{
				setEntityAnimation(self, "LEFT_PIECE");

				self->layer = FOREGROUND_LAYER;

				self->dirX = -4;

				self->action = &holdPersonPieceMove;

				self->thinkTime = 30;
			}
		}
	}

	player.x = self->x + self->w / 2 - player.w / 2;
}
Пример #10
0
static void createIceBlock()
{
	int x, y;
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add Ice Block");
		}

		loadProperties("edgar/edgar_frozen", e);

		setEntityAnimation(e, "STAND");

		x = player.x + player.w / 2;
		y = self->y - 100 - (prand() % 60);

		e->x = x;
		e->y = y;

		if (isValidOnMap(e) == TRUE)
		{
			e->x = self->x + self->w / 2;
			e->y = self->y + self->h / 2;

			e->x -= e->w / 2;
			e->y -= e->h / 2;

			e->targetX = x;
			e->targetY = y;

			e->damage = 1;

			e->health = 50;

			calculatePath(e->x, e->y, e->targetX, e->targetY, &e->dirX, &e->dirY);

			e->flags |= (NO_DRAW|HELPLESS|TELEPORTING|NO_END_TELEPORT_SOUND);

			playSoundToMap("sound/common/spell", -1, self->x, self->y, 0);

			e->action = &iceBlockDrop;
			e->draw = &drawLoopingAnimationToMap;
			e->touch = &entityTouch;
			e->pain = &enemyPain;
			e->die = &iceBlockDie;

			e->head = self;

			e->face = self->face;

			e->type = ENEMY;

			e->thinkTime = 30;

			e->flags |= FLY|DO_NOT_PERSIST;

			self->endX--;

			if (self->endX <= 0)
			{
				self->thinkTime = 0;

				self->action = &castIceFinish;
			}

			else
			{
				self->thinkTime = 60;
			}
		}

		else
		{
			e->inUse = FALSE;
		}
	}

	checkToMap(self);

	hover();
}
Пример #11
0
static void entityWait()
{
	int frameCount = getFrameCount(self);
	Entity *e;

	if (self->active == TRUE)
	{
		self->thinkTime--;

		if (self->thinkTime % 120 == 0)
		{
			self->currentFrame++;

			if (self->currentFrame >= frameCount)
			{
				self->currentFrame = frameCount - 1;
			}
		}

		else if (self->thinkTime % 5 == 0)
		{
			e = getFreeEntity();

			if (e == NULL)
			{
				showErrorAndExit("No free slots to add the Fire");
			}

			loadProperties("boss/phoenix_die_fire", e);

			setEntityAnimation(e, "STAND");

			e->x = self->x + prand() % self->w;
			e->y = self->y + self->h - e->h;

			e->action = &fireWait;

			e->draw = &drawLoopingAnimationToMap;

			e->type = ENEMY;

			e->flags |= DO_NOT_PERSIST|FLY;

			e->thinkTime = 30;

			e->health = 0;

			e->maxHealth = 3 + prand() % 3;

			e->mental = 1;

			e->head = self;
		}

		if (self->thinkTime <= 0)
		{
			self->inUse = FALSE;
		}
	}

	else
	{
		self->frameSpeed = 0;

		self->thinkTime = frameCount * 120;
	}

	checkToMap(self);
}
Пример #12
0
static void createIceWall()
{
	int i, mapFloor;
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		mapFloor = getMapFloor(self->x, self->y);

		for (i=0;i<2;i++)
		{
			e = getFreeEntity();

			if (e == NULL)
			{
				showErrorAndExit("No free slots to add Ice Wall");
			}

			loadProperties("enemy/ice_wall", e);

			e->x = player.x + player.w / 2 + (i == 0 ? -200 : 200);
			e->y = mapFloor + 50;

			e->face = (i == 0 ? RIGHT : LEFT);

			e->targetY = mapFloor - e->h;

			e->x -= e->w / 2;

			e->action = &iceWallMove;
			e->draw = &drawLoopingAnimationToMap;
			e->touch = &iceWallTouch;

			e->head = self;

			e->type = ENEMY;

			e->flags |= DO_NOT_PERSIST;

			e->head = self;

			e->thinkTime = 60;

			setEntityAnimation(e, "STAND");
		}

		self->endX--;

		if (self->endX <= 0)
		{
			self->thinkTime = 0;

			self->action = &teleportToOtherSide;
		}

		else
		{
			self->thinkTime = 90;
		}
	}

	checkToMap(self);

	hover();
}
Пример #13
0
static void createLightningWave()
{
	int i, top, bottom, valid;
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		bottom = getMapFloor(self->x, self->y);
		top    = getMapCeiling(self->x, self->y);

		valid = TRUE;

		playSoundToMap("sound/enemy/thunder_cloud/lightning", -1, self->x, self->y, 0);

		for (i=top;i<bottom;i+=32)
		{
			e = getFreeEntity();

			if (e == NULL)
			{
				showErrorAndExit("No free slots to add lightning");
			}

			loadProperties("enemy/lightning", e);

			setEntityAnimation(e, "STAND");

			e->x = self->targetX + self->w / 2 - e->w / 2;
			e->y = i;

			e->action = &lightningWait;

			e->draw = &drawLoopingAnimationToMap;
			e->touch = &entityTouch;

			e->head = self;

			e->currentFrame = prand() % 6;

			e->face = RIGHT;

			e->thinkTime = 15;

			if (isValidOnMap(e) == FALSE)
			{
				valid = FALSE;

				e->inUse = FALSE;

				break;
			}
		}

		if (valid == TRUE)
		{
			e = addSmallRock(self->targetX, bottom, "common/small_rock");

			e->x += (self->w - e->w) / 2;
			e->y -= e->h;

			e->dirX = -3;
			e->dirY = -8;

			e = addSmallRock(self->targetX, bottom, "common/small_rock");

			e->x += (self->w - e->w) / 2;
			e->y -= e->h;

			e->dirX = 3;
			e->dirY = -8;

			self->targetX += self->face == RIGHT ? 64 : -64;

			self->thinkTime = 30;
		}

		else
		{
			self->action = &teleportToOtherSide;
		}
	}

	checkToMap(self);

	hover();
}
Пример #14
0
static void createBody(Entity *trapHead, Entity *trapBase)
{
	int i;
	Entity **body, *head;

	trapHead->x = trapHead->endX;
	trapHead->y = trapHead->endY;

	body = malloc(trapHead->mental * sizeof(Entity *));

	if (body == NULL)
	{
		showErrorAndExit("Failed to allocate a whole %d bytes for Fly Trap body...", trapHead->mental * (int)sizeof(Entity *));
	}

	for (i=trapHead->mental-1;i>=0;i--)
	{
		body[i] = getFreeEntity();

		if (body[i] == NULL)
		{
			showErrorAndExit("No free slots to add a Fly Trap body part");
		}

		loadProperties("enemy/fly_trap_body", body[i]);

		body[i]->x = trapHead->x;
		body[i]->y = trapHead->y;

		body[i]->action = &bodyWait;

		body[i]->draw = &drawLoopingAnimationToMap;
		body[i]->touch = &entityTouch;
		body[i]->die = &entityDieNoDrop;
		body[i]->takeDamage = &bodyTakeDamage;

		body[i]->creditsAction = &bodyWait;

		body[i]->type = ENEMY;

		body[i]->health = trapBase->health;

		setEntityAnimation(body[i], "STAND");
	}

	/* Recreate the head so that it's on top */

	head = getFreeEntity();

	if (head == NULL)
	{
		showErrorAndExit("No free slots to add a Fly Trap head");
	}

	*head = *trapHead;

	trapHead->inUse = FALSE;

	trapHead = head;

	/* Link the sections */

	for (i=trapHead->mental-1;i>=0;i--)
	{
		if (i == 0)
		{
			trapHead->target = body[i];
		}

		else
		{
			body[i - 1]->target = body[i];

			if (i == trapHead->mental - 1)
			{
				body[i]->endX = trapBase->x;
				body[i]->endY = trapBase->y;
			}
		}

		body[i]->head = trapHead;
	}

	free(body);

	trapHead->action = &headWait;

	trapHead->creditsAction = &headWait;
}
Пример #15
0
static void dieSplit()
{
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add a Blob Boss Part");
		}

		loadProperties("boss/blob_boss_part", e);

		e->flags |= LIMIT_TO_SCREEN;

		setEntityAnimation(e, "STAND");

		e->draw = &drawLoopingAnimationToMap;

		e->type = ENEMY;

		e->damage = 0;

		e->touch = NULL;

		e->head = self;

		e->action = &partFinalDie;

		e->die = &entityDieNoDrop;

		e->x = self->x + self->box.x + self->box.w / 2 - e->w / 2;

		e->y = self->y + self->box.y + self->box.h / 2 - e->h / 2;

		e->thinkTime = 120;

		e->dirX = 10 + prand() % 80;

		e->dirX /= 10;

		e->dirX *= prand() % 2 == 0 ? -1 : 1;

		e->dirY = -4 - prand() % 12;

		e->targetX = self->x + self->w / 2;

		self->mental--;

		if (self->mental == 0)
		{
			if (self->currentFrame == 0)
			{
				self->flags |= NO_DRAW;

				self->thinkTime = 120;

				self->action = &dieWait;

				return;
			}

			else
			{
				self->mental = 30;

				self->currentFrame--;

				setFrameData(self);
			}
		}

		self->thinkTime = 3;
	}

	checkToMap(self);
}
Пример #16
0
static void castLightningBolt()
{
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add lightning");
		}

		loadProperties("enemy/lightning", e);

		setEntityAnimation(e, "STAND");

		e->x = self->x + self->w / 2;
		e->y = self->y + self->h / 2;

		e->x -= e->w / 2;
		e->y -= e->h / 2;

		e->targetX = player.x + player.w / 2 - e->w / 2;
		e->targetY = getMapCeiling(self->x, self->y);

		e->startY = e->targetY;
		e->endY   = getMapFloor(e->targetX, e->targetY);

		calculatePath(e->x, e->y, e->targetX, e->targetY, &e->dirX, &e->dirY);

		e->flags |= (NO_DRAW|HELPLESS|TELEPORTING|NO_END_TELEPORT_SOUND);

		playSoundToMap("sound/common/spell", -1, self->x, self->y, 0);

		e->head = self;

		e->face = RIGHT;

		e->action = &lightningBolt;

		e->draw = &drawLoopingAnimationToMap;

		e->head = self;

		e->face = self->face;

		e->type = ENEMY;

		e->thinkTime = 0;

		e->flags |= FLY|DO_NOT_PERSIST;

		self->mental--;

		if (self->mental <= 0)
		{
			self->thinkTime = 60;

			self->action = &attackFinished;
		}

		else
		{
			self->thinkTime = 30;
		}
	}

	hover();
}
Пример #17
0
static void eatExplode()
{
	int i;
	Entity *e;
	Target *t;

	self->maxThinkTime = 0;

	t = getCenterTarget();

	self->startX = 0;

	for (i=0;i<60;i++)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add a Blob Boss Part");
		}

		loadProperties("boss/blob_boss_part", e);

		setEntityAnimation(e, "STAND");

		e->flags |= LIMIT_TO_SCREEN;

		e->x = self->x;
		e->y = self->y;

		e->x += prand() % self->w;

		e->y += prand() % (self->h - e->h);

		e->dirX = (10 + prand() % 20) * (prand() % 2 == 0 ? 1 : -1);

		e->dirX /= 10;

		e->dirY = -6 - prand() % 4;

		e->touch = &entityTouch;

		e->damage = 0;

		e->health = 600;

		e->action = &partWait;

		e->pain = &enemyPain;

		e->draw = &drawLoopingAnimationToMap;

		e->head = self;

		e->type = ENEMY;

		e->targetX = t->x;

		e->targetY = t->y;

		self->startX++;
	}

	self->target = NULL;

	self->thinkTime = 120;

	self->action = &explodeWait;

	setEntityAnimation(self, "WALK");

	self->flags |= NO_DRAW;

	self->frameSpeed = 0;

	self->maxThinkTime = 1;

	self->touch = NULL;
}
Пример #18
0
static void createShield()
{
	int i, x, y;
	Entity *shield, *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		if (self->mental == 0)
		{
			setEntityAnimation(self, "ATTACK_1");

			shield = getFreeEntity();

			if (shield == NULL)
			{
				showErrorAndExit("No free slots to add the Sorceror's Shield");
			}

			loadProperties("boss/sorceror_shield", shield);

			shield->x = self->x;
			shield->y = self->y;

			shield->action = &shieldCreateWait;

			shield->draw = &drawLoopingAnimationToMap;

			shield->touch = &entityTouch;

			shield->takeDamage = &shieldTakeDamage;

			shield->pain = &enemyPain;

			shield->die = &shieldDie;

			shield->type = ENEMY;

			shield->head = self;

			shield->alpha = 128;

			shield->face = RIGHT;

			shield->maxHealth = self->health;

			setEntityAnimation(shield, "STAND");

			shield->x = self->x + self->w / 2 - shield->w / 2;
			shield->y = self->y + self->h / 2 - shield->h / 2;

			shield->flags |= NO_DRAW;

			self->startX = 1;

			self->head = shield;

			shield->mental = 6;

			x = shield->x;
			y = shield->y;

			for (i=0;i<6;i++)
			{
				e = getFreeEntity();

				if (e == NULL)
				{
					showErrorAndExit("No free slots to add the Sorceror's Shield Piece");
				}

				loadProperties("boss/sorceror_shield_piece", e);

				setEntityAnimationByID(e, i);

				e->x = x;
				e->y = y;

				e->startX = e->x;
				e->startY = e->y;

				e->action = &pieceMoveToShield;

				e->draw = &drawLoopingAnimationToMap;

				e->type = ENEMY;

				e->alpha = 128;

				e->face = RIGHT;

				e->head = shield;

				if (x == shield->x)
				{
					x += e->w;
				}

				else
				{
					x = shield->x;

					y += e->h;
				}

				switch (i)
				{
					case 0:
						e->dirX = -12;
						e->dirY = -6;
					break;

					case 1:
						e->dirX = 12;
						e->dirY = -6;
					break;

					case 2:
						e->dirX = -12;
						e->dirY = 0;
					break;

					case 3:
						e->dirX = 12;
						e->dirY = 0;
					break;

					case 4:
						e->dirX = -12;
						e->dirY = 6;
					break;

					default:
						e->dirX = 12;
						e->dirY = 6;
					break;
				}

				e->x += e->dirX * 60;
				e->y += e->dirY * 60;

				e->dirX *= -1;
				e->dirY *= -1;
			}

			self->mental = 1;
		}

		else if (self->mental == 2)
		{
			self->thinkTime = 30;

			self->action = &createShieldFinish;
		}
	}
}
Пример #19
0
static void addChains()
{
	int i;
	Entity **chains, *chaos;

	chaos = getEntityByObjectiveName("CHAOS");

	if (chaos == NULL)
	{
		showErrorAndExit("Chaos Chain Base cannot find Chaos");
	}

	chains = malloc(self->mental * sizeof(Entity *));

	if (chains == NULL)
	{
		showErrorAndExit("Failed to allocate a whole %d bytes for Chaos's chains...", self->mental * (int)sizeof(Entity *));
	}

	for (i=self->mental-1;i>=0;i--)
	{
		chains[i] = getFreeEntity();

		if (chains[i] == NULL)
		{
			showErrorAndExit("No free slots to add a Chaos Chain");
		}

		loadProperties("item/chaos_chain", chains[i]);

		chains[i]->face = self->face;

		chains[i]->action = &chainWait;

		chains[i]->creditsAction = &creditsChainWait;

		chains[i]->draw = &drawLoopingAnimationToMap;

		setEntityAnimation(chains[i], "STAND");
	}

	/* Link the sections */

	for (i=self->mental-1;i>=0;i--)
	{
		if (i == 0)
		{
			self->target = chains[i];
		}

		else
		{
			chains[i - 1]->target = chains[i];
		}

		chains[i]->head = self;
	}

	free(chains);

	self->head = chaos;

	self->action = &chainBaseWait;

	self->creditsAction = &creditsChainBaseWait;
}
Пример #20
0
static void shieldDie()
{
	int i, x, y;
	Entity *e;

	x = self->x;
	y = self->y;

	playSoundToMap("sound/boss/sorceror/shield_die", -1, self->x, self->y, 0);

	for (i=0;i<6;i++)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add the Sorceror's Shield Piece");
		}

		loadProperties("boss/sorceror_shield_piece", e);

		e->x = x;
		e->y = y;

		e->action = &pieceWait;

		e->draw = &drawLoopingAnimationToMap;

		e->type = ENEMY;

		e->alpha = 128;

		e->face = RIGHT;

		setEntityAnimationByID(e, i);

		if (x == self->x)
		{
			x += e->w;
		}

		else
		{
			x = self->x;

			y += e->h;
		}

		switch (i)
		{
			case 0:
				e->dirX = -3;
				e->dirY = -1.5f;
			break;

			case 1:
				e->dirX = 3;
				e->dirY = -1.5f;
			break;

			case 2:
				e->dirX = -3;
			break;

			case 3:
				e->dirX = 3;
			break;

			case 4:
				e->dirX = -3;
				e->dirY = 1.5f;
			break;

			default:
				e->dirX = 3;
				e->dirY = 1.5f;
			break;
		}
	}

	self->head->startY = 0;

	self->head->startX = 0;

	self->inUse = FALSE;
}
Пример #21
0
static void incinerate()
{
	int x, startX, startY;
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add Fire");
		}

		loadProperties("enemy/fire", e);

		setEntityAnimation(e, "DOWN");

		if (self->face == LEFT)
		{
			e->x = self->x + self->w - self->offsetX;
		}

		else
		{
			e->x = self->x + self->offsetX;
		}

		e->y = self->y + self->offsetY;

		e->x -= e->w / 2;

		e->action = &fireFall;
		e->draw = &drawLoopingAnimationToMap;
		e->touch = &entityTouch;

		e->face = self->face;

		e->type = ENEMY;

		e->health = 0;

		self->mental++;

		if (self->mental == 60)
		{
			startX = getMapStartX();
			startY = getMapStartY() + SCREEN_HEIGHT - TILE_SIZE;

			x = 0;

			while (x < SCREEN_WIDTH)
			{
				e = getFreeEntity();

				if (e == NULL)
				{
					showErrorAndExit("No free slots to add the Fire");
				}

				loadProperties("boss/phoenix_die_fire", e);

				setEntityAnimation(e, "STAND");

				e->x = startX + x;
				e->y = startY - e->h;

				e->action = &fireWait;

				e->touch = &entityTouch;

				e->draw = &drawLoopingAnimationToMap;

				e->type = ENEMY;

				e->flags |= FLY;

				e->layer = FOREGROUND_LAYER;

				e->thinkTime = 30;

				e->damage = 1;

				e->health = 0;

				e->maxHealth = 5;

				e->mental = 1;

				e->head = self;

				x += e->w;

				self->endY++;
			}
		}

		else if (self->mental > 100)
		{
			self->thinkTime = 60;

			self->action = &incinerateWait;
		}

		else
		{
			self->thinkTime = 3;
		}
	}

	checkToMap(self);
}
Пример #22
0
static void finalAttack()
{
	Entity *temp;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		switch (self->mental)
		{
			case 0:
				setEntityAnimation(self, "ATTACK_4");

				addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2);

				playSoundToMap("sound/common/spell", -1, self->x, self->y, 0);

				self->flags &= ~NO_DRAW;

				self->face = RIGHT;

				createAutoDialogBox(_("Sorceror"), _("Enough! Prepare to die..."), 180);

				self->thinkTime = 180;

				self->mental = 1;

				temp = getFreeEntity();

				if (temp == NULL)
				{
					showErrorAndExit("No free slots to add a the staff");
				}

				loadProperties("boss/sorceror_staff", temp);

				temp->action = &staffMoveAroundSorceror;

				temp->draw = &drawLoopingAnimationToMap;

				temp->type = ENEMY;

				setEntityAnimationByID(temp, 0);

				temp->x = self->x + self->w / 2 - temp->w / 2;

				temp->y = self->y + self->h / 2 - temp->h / 2;

				temp->startX = temp->x;

				temp->startY = temp->y;

				temp->head = self;

				temp->health = self->health;

				temp->mental = self->box.w;
			break;

			case 1:
				temp = getFreeEntity();

				if (temp == NULL)
				{
					showErrorAndExit("No free slots to add a the Final Attack spell");
				}

				loadProperties("boss/sorceror_final_spell", temp);

				temp->action = &finalSpellWait;

				temp->draw = &drawLoopingAnimationToMap;

				temp->type = ENEMY;

				setEntityAnimationByID(temp, 0);

				temp->x = self->x + temp->offsetX;

				temp->y = self->y + temp->offsetY;

				temp->head = self;

				temp->thinkTime = 60;

				self->thinkTime = 660;

				self->mental = 2;

				temp->health = self->health;
			break;

			default:
				self->mental = 3;

				playSoundToMap("sound/common/massive_explosion", -1, self->x, self->y, 0);

				fadeFromColour(0, 0, 200, 30);

				/* Gib the player */

				temp = self;

				self = &player;

				freeEntityList(playerGib());

				self = temp;

				self->thinkTime = 120;

				self->action = &finalAttackFinish;
			break;
		}
	}

	else if (self->thinkTime <= 420 && self->mental == 2)
	{
		self->startX = 2;
	}
}
Пример #23
0
static void stunned()
{
	int i;
	long onGround = self->flags & ON_GROUND;
	Entity *e;

	checkToMap(self);

	if (self->flags & ON_GROUND)
	{
		if (onGround == 0)
		{
			for (i=0;i<2;i++)
			{
				e = getFreeEntity();

				if (e == NULL)
				{
					showErrorAndExit("No free slots to add the Cave Boss's Star");
				}

				loadProperties("boss/armour_boss_star", e);

				e->x = self->x;
				e->y = self->y;

				e->action = &starWait;

				e->draw = &drawLoopingAnimationToMap;

				e->thinkTime = self->thinkTime;

				e->head = self;

				setEntityAnimation(e, "STAND");

				e->currentFrame = (i == 0 ? 0 : 6);

				if (self->face == LEFT)
				{
					e->x = self->x + self->w - e->w - e->offsetX;
				}

				else
				{
					e->x = self->x + e->offsetX;
				}

				e->y = self->y + e->offsetY;
			}

			for (i=0;i<20;i++)
			{
				addSmoke(self->x + prand() % self->w, self->y + self->h - prand() % 10, "decoration/dust");
			}

			playSoundToMap("sound/common/crash", BOSS_CHANNEL, self->x, self->y, 0);
		}

		self->action = &stunFinish;
	}
}
Пример #24
0
static void riftAttack()
{
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		if (self->mental == 0)
		{
			self->y = getMapFloor(self->x + self->w / 2, self->y) - self->h;

			self->flags &= ~NO_DRAW;

			addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2);

			self->mental = 1;

			self->thinkTime = 60;
		}

		else
		{
			setEntityAnimation(self, "ATTACK_1");

			e = getFreeEntity();

			if (e == NULL)
			{
				showErrorAndExit("No free slots to add an Energy Rift");
			}

			loadProperties("enemy/energy_rift", e);

			e->damage = 1;

			e->action = &riftMove;

			e->touch = &entityTouch;

			e->draw = &drawLoopingAnimationToMap;

			e->type = ENEMY;

			setEntityAnimation(e, "STAND");

			if (self->face == LEFT)
			{
				e->x = self->x - e->w;
			}

			else
			{
				e->x = self->x + self->w;
			}

			e->thinkTime = 15;

			e->y = self->y;

			e->dirX = self->face == LEFT ? -e->speed : e->speed;

			e->head = self;

			e->targetX = getMapStartX() + SCREEN_WIDTH / 2 - e->w / 2;
			e->targetY = e->y;

			e->health = 0;

			playSoundToMap("sound/common/spell", -1, self->x, self->y, 0);

			self->mental = -1;

			self->action = &riftAttackWait;

			self->thinkTime = 60;
		}
	}

	checkToMap(self);
}
Пример #25
0
static void lightningBolt()
{
	int i, middle;
	Entity *e;

	self->flags |= NO_DRAW;

	self->thinkTime--;

	middle = -1;

	if (self->thinkTime <= 0)
	{
		playSoundToMap("sound/enemy/thunder_cloud/lightning", -1, self->targetX, self->startY, 0);

		for (i=self->startY;i<self->endY;i+=32)
		{
			e = getFreeEntity();

			if (e == NULL)
			{
				showErrorAndExit("No free slots to add lightning");
			}

			loadProperties("enemy/lightning", e);

			setEntityAnimation(e, "STAND");

			if (i == self->startY)
			{
				middle = self->targetX + self->w / 2 - e->w / 2;
			}

			e->x = middle;
			e->y = i;

			e->action = &lightningWait;

			e->draw = &drawLoopingAnimationToMap;
			e->touch = &entityTouch;

			e->head = self;

			e->currentFrame = prand() % 6;

			e->face = RIGHT;

			e->thinkTime = 15;
		}

		e = addSmallRock(self->x, self->endY, "common/small_rock");

		e->x += (self->w - e->w) / 2;
		e->y -= e->h;

		e->dirX = -3;
		e->dirY = -8;

		e = addSmallRock(self->x, self->endY, "common/small_rock");

		e->x += (self->w - e->w) / 2;
		e->y -= e->h;

		e->dirX = 3;
		e->dirY = -8;

		self->inUse = FALSE;
	}
}
Пример #26
0
static void disintegrationAttack()
{
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		if (self->mental == 0)
		{
			self->y = getMapFloor(self->x + self->w / 2, self->y) - self->h;

			self->flags &= ~NO_DRAW;

			addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2);

			self->mental = 1;

			self->thinkTime = 30;
		}

		else
		{
			e = getFreeEntity();

			if (e == NULL)
			{
				showErrorAndExit("No free slots to add the Disintegration Spell");
			}

			setEntityAnimation(self, "ATTACK_2");

			loadProperties("boss/sorceror_disintegration_spell", e);

			setEntityAnimation(e, "STAND");

			e->face = self->face;

			if (self->face == LEFT)
			{
				e->x = self->x + self->w - e->w - e->offsetX;
			}

			else
			{
				e->x = self->x + e->offsetX;
			}

			e->y = self->y + e->offsetY;

			e->action = &disintegrationSpellInit;

			e->thinkTime = 120;

			e->startX = e->x;
			e->startY = e->y;

			e->head = self;

			e->endX = player.x + player.w / 2;
			e->endY = player.y + player.h / 2;

			e->draw = &drawLoopingAnimationToMap;

			self->mental = 1;

			self->action = &disintegrationAttackWait;

			self->thinkTime = 30;
		}
	}
}
Пример #27
0
static void beamWait()
{
	int i, x, startX, floor;
	Entity *e;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		if (self->mental == 1)
		{
			self->thinkTime = 60;

			setEntityAnimation(self, "STAND_RED");

			self->action = &redBeamWait;
		}

		else
		{
			i = 0;

			floor = getMapFloor(self->head->x + self->head->w / 2, self->head->y);

			/* Left side of beam */

			x = self->x;

			startX = getMapStartX();

			for (;x>=startX;)
			{
				e = getFreeEntity();

				loadProperties("boss/azriel_ground_spikes", e);

				e->head = self;

				e->x = x - e->w;
				e->y = floor;

				e->startY = e->y - e->h;

				e->endY = e->y;

				e->action = &spikeRise;
				e->draw = &drawLoopingAnimationToMap;
				e->touch = &entityTouch;

				e->face = RIGHT;

				e->type = ENEMY;

				e->thinkTime = prand() % 30;

				x = e->x;

				i++;
			}

			/* Right side of beam */

			x = self->x + self->w;

			startX = getMapStartX() + SCREEN_WIDTH;

			for (;x<startX;)
			{
				e = getFreeEntity();

				loadProperties("boss/azriel_ground_spikes", e);

				e->head = self;

				e->x = x;
				e->y = floor;

				e->startY = e->y - e->h;

				e->endY = e->y;

				e->action = &spikeRise;
				e->draw = &drawLoopingAnimationToMap;
				e->touch = &entityTouch;

				e->face = RIGHT;

				e->type = ENEMY;

				e->thinkTime = prand() % 30;

				x = e->x + e->w;

				i++;
			}

			self->mental = i;

			self->thinkTime = 30;

			self->action = &beamFinish;
		}
	}
}
Пример #28
0
static void splitAttackInit()
{
	int i;
	Entity *e;
	Target *t;

	self->maxThinkTime = 0;

	t = getCenterTarget();

	for (i=0;i<60;i++)
	{
		e = getFreeEntity();

		if (e == NULL)
		{
			showErrorAndExit("No free slots to add a Blob Boss Part");
		}

		loadProperties("boss/blob_boss_part", e);

		e->flags |= LIMIT_TO_SCREEN;

		setEntityAnimation(e, "WALK");

		e->x = self->x;
		e->y = self->y;

		e->x += prand() % self->w;

		e->y += prand() % (self->h - e->h);

		e->dirX = (10 + prand() % 20) * (prand() % 2 == 0 ? 1 : -1);

		e->dirX /= 10;

		e->dirY = -6;

		e->action = &partAttack;

		e->touch = &partGrab;

		e->die = &partDie;

		e->pain = &enemyPain;

		e->draw = &drawLoopingAnimationToMap;

		e->takeDamage = &partTakeDamage;

		e->head = self;

		e->type = ENEMY;

		e->thinkTime = 60;

		e->targetX = t->x;

		e->targetY = t->y;
	}

	self->maxThinkTime = 60;

	self->action = &headWait;

	setEntityAnimation(self, "BLOCK");

	self->flags |= NO_DRAW;

	self->frameSpeed = 0;

	self->touch = NULL;
}
Пример #29
0
static void lightningCageWait()
{
	int i, middle;
	Entity *e;

	if (self->face == LEFT)
	{
		self->x = self->head->x + self->head->w - self->w - self->offsetX;
	}

	else
	{
		self->x = self->head->x + self->offsetX;
	}

	self->y = self->head->y + self->offsetY;

	middle = 0;

	e = NULL;

	if (self->head->mental == 1)
	{
		if (self->mental == 0)
		{
			self->endY = getMapFloor(self->x + self->w / 2, self->y);

			for (i=self->y;i<self->endY;i+=32)
			{
				e = getFreeEntity();

				if (e == NULL)
				{
					showErrorAndExit("No free slots to add lightning");
				}

				loadProperties("enemy/lightning", e);

				setEntityAnimation(e, "STAND");

				if (i == self->startY)
				{
					middle = self->targetX + self->w / 2 - e->w / 2;
				}

				e->x = middle;
				e->y = i;

				e->action = &cageLightningWait;

				e->draw = &drawLoopingAnimationToMap;
				e->touch = &entityTouch;

				e->head = self;

				e->currentFrame = prand() % 6;

				e->face = RIGHT;

				e->thinkTime = 15;
			}

			e->mental = 1;

			self->mental = 1;

			if (self->face == LEFT)
			{
				self->targetX = playSoundToMap("sound/boss/azriel/azriel_lightning_cage", -1, self->x, self->y, -1);
			}
		}
	}

	else if (self->head->mental == 2)
	{
		if (self->face == LEFT)
		{
			stopSound(self->targetX);
		}

		self->inUse = FALSE;
	}
}
Пример #30
0
static void riftAttack()
{
	int i, width;
	Entity *e;
	Target *t1, *t2;

	self->thinkTime--;

	if (self->thinkTime <= 0)
	{
		self->mental = 2;

		t1 = getTargetByName("CHAOS_TARGET_LEFT");

		t2 = getTargetByName("CHAOS_TARGET_RIGHT");

		if (t1 == NULL || t2 == NULL)
		{
			showErrorAndExit("Chaos cannot find target");
		}

		width = (t2->x - t1->x) / 2;

		for (i=0;i<self->mental;i++)
		{
			e = getFreeEntity();

			if (e == NULL)
			{
				showErrorAndExit("No free slots to add an Energy Rift");
			}

			loadProperties("enemy/energy_rift", e);

			e->damage = 2;

			e->action = &riftOpen;

			e->touch = &entityTouch;

			e->draw = &drawLoopingAnimationToMap;

			e->type = ENEMY;

			setEntityAnimation(e, "STAND");

			e->x = (i == 0 ? t1->x : t2->x) - e->w / 2;
			e->y = (i == 0 ? t1->y : t2->y);

			e->speed = width;

			e->thinkTime = 15;

			e->head = self;

			e->health = 0;
		}

		self->action = &riftAttackWait;

		self->thinkTime = 15;
	}

	self->maxThinkTime--;

	checkToMap(self);
}