Beispiel #1
0
static void lightningCageMoveBackToPlayer()
{
	self->targetX = player.x - self->w / 2 + player.w / 2;

	checkToMap(self);

	/* Position above the player */

	if (abs(self->x - self->targetX) <= player.speed / 2)
	{
		self->action = &lightningCage;

		self->targetX = self->face == LEFT ? getMapStartX() : getMapStartX() + SCREEN_WIDTH - self->w - 1;

		self->dirX = self->targetX < self->x ? -player.speed / 2 : player.speed / 2;

		self->thinkTime = 30;
	}

	else
	{
		self->dirX = self->targetX < self->x ? -player.speed / 2 : player.speed / 2;
	}

	becomeTransparent();
}
Beispiel #2
0
static void lightningCageMoveAbovePlayer()
{
	self->thinkTime--;

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

			self->maxThinkTime = 2;

			self->mental = 1;
		}

		else
		{
			self->action = &lightningCage;

			self->targetX = self->face == LEFT ? getMapStartX() : getMapStartX() + SCREEN_WIDTH - self->w - 1;

			self->dirX = self->targetX < self->x ? -player.speed / 2 : player.speed / 2;

			self->thinkTime = 30;
		}
	}

	checkToMap(self);

	becomeTransparent();
}
Beispiel #3
0
static void acidStreamMoveToTop()
{
	checkToMap(self);

	if (self->dirY < 0 && self->y <= self->targetY)
	{
		self->y = self->targetY;

		self->dirY = 0;

		setEntityAnimation(self, "NORMAL_WALK");

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

		self->targetX = self->face == LEFT ? getMapStartX() : getMapStartX() + SCREEN_WIDTH - self->w - 1;

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

	else if (abs(self->x - self->targetX) <= abs(self->dirX))
	{
		self->x = self->targetX;

		self->dirX = 0;

		self->thinkTime = 120;

		self->endY = 0;

		self->action = &acidStream;

		setEntityAnimation(self, "NORMAL_ATTACK_DOWN");
	}
}
Beispiel #4
0
static void icicleDropMoveToTop()
{
	checkToMap(self);

	if (self->dirY < 0 && self->y <= self->targetY)
	{
		self->y = self->targetY;

		self->dirY = 0;

		setEntityAnimation(self, "ICE_WALK");

		self->face = self->targetX < self->x ? LEFT : RIGHT;

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

	else if (abs(self->x - self->targetX) <= abs(self->dirX))
	{
		self->x = self->targetX;

		self->dirX = 0;

		self->mental = 30;

		self->thinkTime = 3;

		self->action = &icicleDrop;

		self->endY = getMapStartX();

		setEntityAnimation(self, "ICE_ATTACK_UP");
	}
}
Beispiel #5
0
static void die()
{
	int i;

	self->action = &die;

	setCustomAction(self, &invulnerableNoFlash, 240, 0, 0);

	setEntityAnimation(self, "STUNNED");

	self->flags &= ~FLY;

	self->dirX = 0;

	self->mental = self->x < getMapStartX() + SCREEN_WIDTH / 2 ? 0 : 1;

	checkToMap(self);

	if (self->flags & ON_GROUND)
	{
		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->thinkTime = 120;

		self->endY = 0;

		self->action = &dieFinish;
	}
}
Beispiel #6
0
static void dropEgg()
{
	self->thinkTime--;

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

		if (self->mental <= 0)
		{
			self->action = &attackFinished;
		}

		else
		{
			self->targetX = getMapStartX();

			self->targetX += prand() % (SCREEN_WIDTH - self->w);

			self->action = &eggDropMove;

			setEntityAnimation(self, "ICE_WALK");
		}
	}

	checkToMap(self);
}
Beispiel #7
0
static void flameWaveMove()
{
	int startX, x;
	Entity *e;

	switch (self->maxThinkTime)
	{
		case 1:
			startX = getMapStartX();

			x = self->x + (self->face == RIGHT ? -self->w : self->w);

			if (!(x <= startX || x >= startX + SCREEN_WIDTH - self->w))
			{
				e = getFreeEntity();

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

				loadProperties("boss/sorceror_flame_wave", e);

				setEntityAnimation(e, "GROW_INIT");

				e->face = self->face;

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

				e->action = &flameWaveMove;

				e->draw = &drawLoopingAnimationToMap;

				e->touch = &entityTouch;

				e->animationCallback = &flameWaveAnim;
			}

			setEntityAnimation(self, "GROW");

			self->animationCallback = &flameWaveAnim;

			self->maxThinkTime = 2;
		break;

		case 3:
			self->inUse = FALSE;
		break;

		default:

		break;
	}
}
Beispiel #8
0
static void icicleDropWait()
{
	Entity *e;

	self->thinkTime--;

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

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

		loadProperties("enemy/ice_spike", e);

		setEntityAnimation(e, "STAND");

		e->x = self->endY;
		e->y = getMapStartY() - e->h;

		e->flags |= PLAYER_TOUCH_ONLY|FLY;

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

		e->face = self->face;

		e->type = ENEMY;

		e->health = 120;

		e->thinkTime = 60;

		e->head = self;

		self->endY += e->w;

		self->mental++;

		if (self->endY >= getMapStartX() + SCREEN_WIDTH)
		{
			self->action = &icicleDropFinish;
		}

		else
		{
			self->thinkTime = 10;
		}
	}

	checkToMap(self);
}
Beispiel #9
0
static void spikeAttackMoveToTopTarget()
{
	Entity *e;

	if (atTarget())
	{
		self->thinkTime--;

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

			loadProperties("boss/azriel_light_beam", e);

			setEntityAnimation(e, "APPEAR");

			e->animationCallback = &beamAppearFinish;

			e->head = self;

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

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

			e->startY = e->y;

			e->action = &beamWait;
			e->draw = &drawBeam;
			e->touch = &entityTouch;

			e->face = RIGHT;

			e->type = ENEMY;

			e->thinkTime = 240;

			e->mental = prand() % 3 == 0 ? 1 : 0;

			e->targetX = playSoundToMap("sound/boss/grimlore/grimlore_summon", -1, e->x, e->y, -1);

			self->action = &spikeAttackWait;

			self->mental = 1;
		}
	}

	checkToMap(self);

	becomeTransparent();
}
Beispiel #10
0
static void ceilingBurnWait()
{
	Entity *e;

	self->thinkTime--;

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

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

		loadProperties("enemy/fire", e);

		setEntityAnimation(e, "DOWN");

		e->x = self->endY;
		e->y = getMapStartY() - e->h;

		e->flags |= PLAYER_TOUCH_ONLY;

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

		e->face = self->face;

		e->type = ENEMY;

		e->health = 120;

		self->endY += TILE_SIZE;

		if (self->endY >= getMapStartX() + SCREEN_WIDTH)
		{
			self->action = &attackFinished;
		}

		else
		{
			self->thinkTime = 5;
		}
	}

	checkToMap(self);
}
Beispiel #11
0
static void lightningCage()
{
	int playerMid, startX;

	if (fabs(self->x - self->targetX) <= fabs(self->dirX))
	{
		self->x = self->targetX;

		self->dirX = 0;

		self->thinkTime--;

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

			if (self->maxThinkTime <= 0)
			{
				self->action = &lightningCageFinish;
			}

			else
			{
				startX = getMapStartX();

				self->targetX = self->x != startX ? startX : startX + SCREEN_WIDTH - self->w;

				self->dirX = self->targetX < self->x ? -player.speed / 2 : player.speed / 2;
			}

			self->thinkTime = 30;
		}
	}

	else
	{
		self->x += self->dirX;

		playerMid = player.x + player.w / 2;

		if (player.health > 0 && !(playerMid >= self->x && playerMid <= self->x + self->w))
		{
			self->action = &lightningCageMoveBackToPlayer;
		}
	}

	becomeTransparent();
}
Beispiel #12
0
static void changeToFireInit()
{
	int startX;
	Target *t;

	startX = getMapStartX() + SCREEN_WIDTH / 2;

	t = getTargetByName(self->x < startX ? "CAVE_BOSS_TARGET_LEFT" : "CAVE_BOSS_TARGET_RIGHT");

	if (t == NULL)
	{
		showErrorAndExit("Cave Boss cannot find target");
	}

	self->targetX = t->x;
	self->targetY = t->y;

	if (self->x != self->targetX && self->y != self->targetY)
	{
		t = getTargetByName("CAVE_BOSS_TARGET_TOP");

		if (t == NULL)
		{
			showErrorAndExit("Cave Boss cannot find target");
		}

		self->targetY = t->y;

		if (self->y > self->targetY)
		{
			setEntityAnimation(self, "NORMAL_WALK_UP");
		}

		self->dirX = 0;
		self->dirY = -self->speed;

		self->action = &moveToTarget;

		self->resumeNormalFunction = &changeToFire;
	}

	else
	{
		self->action = &changeToFire;
	}
}
Beispiel #13
0
void drawCursor()
{
	Entity *e;

	if (cursor.type == TILES)
	{
		drawImage(tileImage(cursor.tileID), cursor.x, cursor.y, FALSE, 255);

		drawImage(tileImage(BLANK_TILE), cursor.x, cursor.y, FALSE, 255);
	}

	else
	{
		e = isSpaceEmpty(&cursor.entity);

		if (isValidOnMap(&cursor.entity) == 0 || e != NULL)
		{
			drawBox(game.screen, cursor.x, cursor.y, cursor.entity.w, cursor.entity.h, 255, 0, 0);
		}

		if (e != NULL)
		{
			setStatusPanelMessage("%s : %d %d", (strlen(e->objectiveName) == 0 ? e->name : e->objectiveName), (int)e->x, (int)e->y);
		}

		else
		{
			setStatusPanelMessage("");
		}

		cursor.entity.x = getMapStartX() + cursor.x;
		cursor.entity.y = getMapStartY() + cursor.y;

		self = &cursor.entity;

		self->draw();
	}
}
Beispiel #14
0
static void eggDropMoveToTop()
{
	checkToMap(self);

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

		self->dirY = 0;

		self->mental = 1 + prand() % 2;

		self->action = &eggDropMove;

		setEntityAnimation(self, "ICE_WALK");

		facePlayer();

		self->targetX = getMapStartX();

		self->targetX += prand() % (SCREEN_WIDTH - self->w);
	}
}
Beispiel #15
0
static void ceilingBurnMoveToTop()
{
	checkToMap(self);

	if (self->dirY < 0 && self->y <= self->targetY)
	{
		self->y = self->targetY;

		self->dirY = 0;

		setEntityAnimation(self, "FIRE_WALK");

		self->face = self->targetX < self->x ? LEFT : RIGHT;

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

	else if (abs(self->x - self->targetX) <= abs(self->dirX))
	{
		self->x = self->targetX;

		self->dirX = 0;

		self->mental = 30;

		self->thinkTime = 3;

		self->action = &ceilingBurn;

		self->endY = getMapStartX();

		setEntityAnimation(self, "FIRE_ATTACK_UP");

		playSoundToMap("sound/enemy/fireball/fireball", BOSS_CHANNEL, self->x, self->y, 0);
	}
}
Beispiel #16
0
static void spearAttack()
{
	int i, j, startX;
	Entity *e;

	self->thinkTime--;

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

		startX = getMapStartX();

		j = 1;

		for (i=self->x;i>=startX;)
		{
			e = getFreeEntity();

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

			loadProperties("enemy/ground_spear", e);

			setEntityAnimation(e, "STAND");

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

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

			e->endY = e->y;

			e->thinkTime = 15 * j;

			e->damage = 2;

			e->touch = &entityTouch;

			e->action = &spearWait;

			e->draw = &drawLoopingAnimationToMap;

			e->head = self;

			i -= e->w * 2;

			self->mental++;

			j++;
		}

		j = 1;

		for (;i<self->x;)
		{
			e = getFreeEntity();

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

			loadProperties("enemy/ground_spear", e);

			setEntityAnimation(e, "STAND");

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

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

			e->endY = e->y;

			e->thinkTime = 15 * j;

			e->damage = 2;

			e->touch = &entityTouch;

			e->action = &spearWait;

			e->draw = &drawLoopingAnimationToMap;

			e->head = self;

			i += e->w * 2;

			self->mental++;

			j++;
		}

		self->action = &spearAttackFinished;
	}

	self->maxThinkTime--;

	checkToMap(self);
}
Beispiel #17
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;
		}
	}
}
Beispiel #18
0
void doCursor()
{
	char name[MAX_VALUE_LENGTH];
	int x, y;

	cursor.x = input.mouseX;
	cursor.y = input.mouseY;

	if (cursor.type == TILES || cursor.snapToGrid == 1)
	{
		cursor.x /= TILE_SIZE;
		cursor.y /= TILE_SIZE;

		cursor.x *= TILE_SIZE;
		cursor.y *= TILE_SIZE;
	}

	if (cursor.y >= SCREEN_HEIGHT - TILE_SIZE)
	{
		cursor.y = SCREEN_HEIGHT - TILE_SIZE * 2;
	}

	if (input.left == 1)
	{
		mapStartXNext(-TILE_SIZE);
	}

	else if (input.right == 1)
	{
		mapStartXNext(TILE_SIZE);
	}

	if (input.up == 1)
	{
		mapStartYNext(-TILE_SIZE);
	}

	else if (input.down == 1)
	{
		mapStartYNext(TILE_SIZE);
	}

	if (input.snap == 1)
	{
		cursor.snapToGrid = 1 - cursor.snapToGrid;

		input.snap = 0;
	}

	if (input.activate == 1)
	{
		cursor.entity.face = (cursor.entity.face == RIGHT ? LEFT : RIGHT);

		input.activate = 0;
	}

	if (input.block == 1)
	{
		if (cursor.type == TILES)
		{
			x = (getMapStartX() + cursor.x) / TILE_SIZE;
			y = (getMapStartY() + cursor.y) / TILE_SIZE;

			while (mapTileAt(x, y) == BLANK_TILE && x >= 0)
			{
				setTileAt(x, y, cursor.tileID);

				x--;
			}

			x = (getMapStartX() + cursor.x) / TILE_SIZE;

			x++;

			while (mapTileAt(x, y) == BLANK_TILE && x < MAX_MAP_X)
			{
				setTileAt(x, y, cursor.tileID);

				x++;
			}
		}
	}

	if (input.add == 1)
	{
		if (cursor.type == TILES)
		{
			setTileAt((getMapStartX() + cursor.x) / TILE_SIZE, (getMapStartY() + cursor.y) / TILE_SIZE, cursor.tileID);
		}

		else
		{
			/* Entities can only be placed in blank spaces */

			if (isValidOnMap(&cursor.entity) == 1 && isSpaceEmpty(&cursor.entity) == NULL)
			{
				if (cursor.entityType == 0)
				{
					setPlayerLocation(getMapStartX() + cursor.x, getMapStartY() + cursor.y);
				}

				else
				{
					if (strcmpignorecase(cursor.entity.name, "lift/lift_target") == 0)
					{
						snprintf(name, sizeof(name), "NEW_TARGET_%03d", targetID);

						addTarget(getMapStartX() + cursor.x, getMapStartY() + cursor.y, name);

						targetID++;
					}

					else
					{
						cursor.entity.startX = getMapStartX() + cursor.x;
						cursor.entity.startY = getMapStartY() + cursor.y;

						cursor.entity.endX = getMapStartX() + cursor.x;
						cursor.entity.endY = getMapStartY() + cursor.y;

						addEntity(cursor.entity, getMapStartX() + cursor.x, getMapStartY() + cursor.y);
					}
				}
			}

			input.add = 0;
		}
	}

	else if (input.remove == 1)
	{
		if (cursor.type == TILES)
		{
			setTileAt((getMapStartX() + cursor.x) / TILE_SIZE, (getMapStartY() + cursor.y) / TILE_SIZE, BLANK_TILE);
		}

		else
		{
			self = isSpaceEmpty(&cursor.entity);

			if (self != NULL)
			{
				self->inUse = FALSE;
			}
		}
	}

	if (input.cut == 1)
	{
		if (cursor.type != TILES)
		{
			self = isSpaceEmpty(&cursor.entity);

			if (self != NULL)
			{
				cursor.entity = *self;

				self->inUse = FALSE;
			}
		}

		input.cut = 0;
	}

	if (input.previous == 1)
	{
		if (cursor.type == TILES)
		{
			cursor.tileID = prevTile(cursor.tileID);
		}

		else
		{
			cursor.entityType--;

			if (cursor.entityType < 0)
			{
				cursor.entityType = entityNamesLength - 1;
			}

			memset(&cursor.entity, 0, sizeof(Entity));

			cursor.entity.draw = &drawLoopingAnimationToMap;

			cursor.entity.weight = 0;

			cursor.entity.originalWeight = 0;

			cursor.entity.inUse = TRUE;

			loadProperties(entityNames[cursor.entityType], &cursor.entity);

			cursor.entity.active = TRUE;

			cursor.entity.alpha = 255;

			if (cursor.entity.weight == 0)
			{
				cursor.entity.weight = 1;

				cursor.entity.originalWeight = 1;
			}
		}

		input.previous = 0;
	}

	else if (input.next == 1)
	{
		if (cursor.type == TILES)
		{
			cursor.tileID = nextTile(cursor.tileID);
		}

		else
		{
			cursor.entityType++;

			if (cursor.entityType >= entityNamesLength)
			{
				cursor.entityType = 0;
			}

			memset(&cursor.entity, 0, sizeof(Entity));

			cursor.entity.draw = &drawLoopingAnimationToMap;

			cursor.entity.weight = 0;

			cursor.entity.originalWeight = 1;

			cursor.entity.inUse = TRUE;

			loadProperties(entityNames[cursor.entityType], &cursor.entity);

			cursor.entity.active = TRUE;

			cursor.entity.alpha = 255;

			if (cursor.entity.weight == 0)
			{
				cursor.entity.weight = 1;

				cursor.entity.originalWeight = 1;
			}
		}

		input.next = 0;
	}

	if (input.save == 1)
	{
		if (saveMap() == TRUE)
		{
			setStatusPanelMessage("Saved");
		}

		else
		{
			setStatusPanelMessage("Saving Failed");
		}

		input.save = 0;
	}
	/*
	if (input.load == 1)
	{
		loadMap(map.filename);

		printf("Loaded\n");

		input.load = 0;
	}
	*/
	if (input.left == 1 || input.right == 1 || input.up == 1 || input.down == 1)
	{
		SDL_Delay(30);
	}

	if (input.toggle == 1)
	{
		if (cursor.type == TILES)
		{
			cursor.type = ENTITIES;
		}

		else
		{
			cursor.type = TILES;
		}

		input.toggle = 0;
	}

	centerMapOnEntity(NULL);
}
Beispiel #19
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);
}
Beispiel #20
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);
}
Beispiel #21
0
static void breatheFire()
{
	Entity *e;

	self->thinkTime--;

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

		switch (prand() % 4)
		{
			case 0:
				createAutoDialogBox(_("Chaos"), _("Burn to ashes!"), 180);
			break;

			case 1:
				createAutoDialogBox(_("Chaos"), _("Feel my power!"), 180);
			break;

			case 2:
				createAutoDialogBox(_("Chaos"), _("I will destroy you!"), 180);
			break;

			default:
				createAutoDialogBox(_("Chaos"), _("Suffer!"), 180);
			break;
		}

		e = getFreeEntity();

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

		loadProperties("boss/chaos_flame", e);

		e->face = self->face;

		e->action = &flameWait;

		e->creditsAction = &flameWait;

		e->draw = &drawLoopingAnimationToMap;

		e->thinkTime = 300;

		if (game.status != IN_CREDITS)
		{
			shakeScreen(LIGHT, 300);
		}

		e->mental = 1;

		e->health = 1200;

		e->head = self;

		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->dirX = 14;

		e->startX = e->x;

		e->endX = e->face == LEFT ? getMapStartX() - SCREEN_WIDTH : getMapStartX() + SCREEN_WIDTH;

		playSoundToMap("sound/boss/chaos/breathe_fire", BOSS_CHANNEL, self->x, self->y, 0);

		self->thinkTime = 30;

		self->mental = 1;

		self->action = &breatheFireFinish;

		self->creditsAction = &breatheFireFinish;
	}

	checkToMap(self);
}
Beispiel #22
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);
}
Beispiel #23
0
static void soulStealMoveToPlayer()
{
	int mid;
	Entity *e;
	Target *t;

	self->thinkTime--;

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

		self->flags &= ~NO_DRAW;

		t = getTargetByName("AZRIEL_LEFT_TARGET");

		if (t == NULL)
		{
			showErrorAndExit("Azriel cannot find target");
		}

		mid = getMapStartX() + SCREEN_WIDTH / 2;

		self->x = player.x < mid ? player.x + player.w + 24 : player.x - self->w - 24;

		self->y = t->y;

		self->targetX = player.x;

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

		facePlayer();

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

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

		self->action = &soulSteal;

		self->thinkTime = 600;

		self->maxThinkTime = player.alpha;

		self->targetY = player.alpha;

		self->mental = -3;

		e = getFreeEntity();

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

		loadProperties("boss/azriel_soul_steal_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 = &soulStealSpellAttack;

		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 = &drawSoulStealSpell;

		e->flags &= ~NO_DRAW;
	}

	checkToMap(self);

	becomeTransparent();
}
Beispiel #24
0
static void spinnerMove()
{
	int i;
	Entity *e;

	if (!(self->flags & NO_DRAW))
	{
		for (i=0;i<8;i++)
		{
			e = getFreeEntity();

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

			loadProperties("boss/snake_boss_special_shot", e);

			setEntityAnimation(e, "STAND");

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

			e->startX = i * 30;

			e->mental = 0;

			e->damage = 2;

			e->health = 30;

			e->speed = 3;

			e->flags |= FLY;

			e->head = self;

			e->face = RIGHT;

			e->action = &rotateAroundTarget;

			e->touch = &entityTouch;

			e->die = &spinnerPartDie;

			e->draw = &drawLoopingAnimationToMap;

			e->type = ENEMY;
		}

		self->flags |= NO_DRAW;

		self->targetX = getMapStartX() - 128;

		self->dirX = -1;
	}

	checkToMap(self);

	if (self->x <= self->targetX && (self->flags & NO_DRAW))
	{
		self->head->mental = 0;

		self->inUse = FALSE;
	}
}