static void disintegrationAttackInit() { int rand; Target *t; rand = prand() % 2; t = getTargetByName(rand == 0 ? "SORCEROR_LEFT_TARGET" : "SORCEROR_RIGHT_TARGET"); if (t == NULL) { showErrorAndExit("Sorceror cannot find target"); } addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->x = t->x; self->face = rand == 0 ? RIGHT : LEFT; playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->flags |= NO_DRAW; self->thinkTime = 30; self->mental = 0; self->action = &disintegrationAttack; }
static void finalAttackInit() { Target *t; t = getTargetByName("SORCEROR_MID_TARGET"); if (t == NULL) { showErrorAndExit("Sorceror cannot find target"); } addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->x = t->x; self->y = t->y; playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->flags |= NO_DRAW; self->thinkTime = 30; self->action = &finalAttack; self->mental = 0; hover(); }
static void scytheThrowTeleportAway() { Target *t; self->thinkTime--; if (self->thinkTime <= 0) { self->flags |= NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); t = getTargetByName("AZRIEL_TOP_TARGET"); if (t == NULL) { showErrorAndExit("Azriel cannot find target"); } self->x = t->x; self->y = t->y; self->action = &scytheThrowFinish; self->thinkTime = 30; } }
static void lightningCageInit() { Target *t; t = getTargetByName("AZRIEL_TOP_TARGET"); if (t == NULL) { showErrorAndExit("Azriel cannot find target"); } addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->x = t->x; self->y = t->y; playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->flags |= NO_DRAW; self->thinkTime = 30; self->action = &lightningCageCreate; self->mental = 0; self->target->layer = BACKGROUND_LAYER; becomeTransparent(); }
static void lightningCageFinish() { Target *t; self->thinkTime--; if (self->thinkTime <= 0) { self->mental = 2; t = getTargetByName("AZRIEL_TOP_TARGET"); if (t == NULL) { showErrorAndExit("Azriel cannot find target"); } addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->x = t->x; self->y = t->y; playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->flags |= NO_DRAW; self->thinkTime = 30; self->action = &lightningCageTeleportAway; } becomeTransparent(); }
static void flameWaveDropInit() { Target *t; setEntityAnimation(self, "ATTACK_3"); playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->flags |= NO_DRAW; t = getTargetByName("SORCEROR_TOP_TARGET"); if (t == NULL) { showErrorAndExit("Sorceror cannot find target"); } self->y = t->y; self->thinkTime = 60; self->action = &flameWaveDrop; }
static void soulStealFinish() { self->thinkTime--; if (self->thinkTime <= 0) { if (player.health == 0) { self->target->inUse = FALSE; } setEntityAnimation(self, "STAND"); self->flags &= ~NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->action = &attackFinished; } checkToMap(self); becomeTransparent(); }
void doTeleport() { int i; float speed; Entity *e; if (abs(self->x - self->targetX) < TELEPORT_SPEED && abs(self->y - self->targetY) < TELEPORT_SPEED) { self->flags &= ~(NO_DRAW|HELPLESS|TELEPORTING); self->x = self->targetX; self->y = self->targetY; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->dirY = self->dirX = 0; self->standingOn = NULL; if (!(self->flags & NO_END_TELEPORT_SOUND)) { playSoundToMap("sound/common/teleport", -1, self->x, self->y, 0); } } else { self->flags |= NO_DRAW|HELPLESS|INVULNERABLE; speed = getDistance(self->x, self->y, self->targetX, self->targetY) / 20; speed = speed < TELEPORT_SPEED ? TELEPORT_SPEED : (speed > 30 ? 30 : speed); normalize(&self->dirX, &self->dirY); self->dirX *= speed; self->dirY *= speed; self->x += self->dirX; self->y += self->dirY; for (i=0;i<5;i++) { e = addBasicDecoration(self->x, self->y, "decoration/particle"); if (e != NULL) { e->x += prand() % self->w; e->y += prand() % self->h; e->thinkTime = 5 + prand() % 30; setEntityAnimationByID(e, prand() % 5); } } } }
static void teleportPlayerToDungeon(Entity *other) { player.flags |= NO_DRAW; self->inUse = FALSE; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/teleport", EDGAR_CHANNEL, self->x, self->y, 0); }
static void scytheThrowFinish() { self->thinkTime--; if (self->thinkTime <= 0) { self->flags &= ~NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->action = &attackFinished; } }
static void teleportOut() { self->thinkTime--; if (self->thinkTime <= 0) { self->touch = NULL; self->flags |= NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/spell", BOSS_CHANNEL, self->x, self->y, 0); self->action = &teleportWait; self->head->mental++; #if DEV == 1 printf("%d / %d : %d / %d\n", self->head->mental, self->head->damage, self->head->health, self->head->maxHealth); #endif self->thinkTime = 60 + prand() % 120; /* Choose if they attack again, or their partner */ if (self->active == TRUE) { if (prand() % 2 == 0) { self->target->thinkTime = 60 + prand() % 120; self->target->active = FALSE; } else { self->thinkTime = 60 + prand() % 120; self->active = FALSE; self->target->active = TRUE; } } } checkToMap(self); }
static void superFireballAttackInit() { facePlayer(); playSoundToMap("sound/common/spell", BOSS_CHANNEL, self->x, self->y, 0); self->flags &= ~NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->action = &superFireballAttack; self->touch = &entityTouch; self->thinkTime = -1; self->head->mental = 0; }
static void soulStealInit() { self->flags |= NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->thinkTime = 30; self->action = &soulStealMoveToPlayer; checkToMap(self); becomeTransparent(); }
static void flameWaveDrop() { int i; long onGround; if (self->thinkTime > 0) { self->flags |= INVULNERABLE; self->thinkTime--; self->x = player.x + player.w / 2 - self->w / 2; if (self->thinkTime <= 0) { playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->flags &= ~(FLY|NO_DRAW); self->dirY = 0; } } onGround = self->flags & ON_GROUND; checkToMap(self); if (landedOnGround(onGround) == TRUE) { playSoundToMap("sound/enemy/red_grub/thud", BOSS_CHANNEL, self->x, self->y, 0); shakeScreen(LIGHT, 15); for (i=0;i<20;i++) { addSmoke(self->x + prand() % self->w, self->y + self->h - prand() % 10, "decoration/dust"); } self->mental = 5; self->thinkTime = 30; self->action = &flameWaveAttack; } }
static void disintegrationAttack() { self->thinkTime--; if (self->thinkTime <= 0) { self->head->mental = -1; self->inUse = FALSE; if (self->mental == 1) { player.flags |= NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/teleport", EDGAR_CHANNEL, self->x, self->y, 0); } } }
static void teleportAwayFinish() { self->thinkTime--; if (self->thinkTime <= 0) { setEntityAnimation(self, "STAND"); addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->flags &= ~NO_DRAW; self->action = &attackFinished; self->endY = self->y; self->endX = 0; } checkToMap(self); }
static void superDropAttackInit() { int minX, maxX; self->thinkTime--; if (self->thinkTime <= 0) { minX = getCameraMinX(); maxX = getCameraMaxX(); setEntityAnimation(self, "ATTACK_3"); self->flags &= ~(NO_DRAW|FLY); self->x = player.x + player.w / 2 - self->w / 2; if (self->x < minX) { self->x = minX; } else if (self->x + self->w >= maxX) { self->x = maxX - self->w - 1; } self->y = self->head->y; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/spell", BOSS_CHANNEL, self->x, self->y, 0); self->touch = &entityTouch; self->action = &superDropAttack; checkToMap(self); } }
static void dieShudder() { Target *t; self->x = self->startX + sin(DEG_TO_RAD(self->targetY)) * 4; self->targetY += 90; if (self->targetY >= 360) { self->targetY = 0; } self->thinkTime--; if (self->thinkTime <= 0) { self->flags |= NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); t = getTargetByName("AZRIEL_TOP_TARGET"); if (t == NULL) { showErrorAndExit("Azriel cannot find target"); } self->x = t->x; self->y = self->startY; self->action = &dieMoveToTop; self->thinkTime = 60; self->mental = 0; } }
static void dropAttackInit() { int minX, maxX; minX = getCameraMinX(); maxX = getCameraMaxX(); setEntityAnimation(self, "ATTACK_3"); self->flags &= ~NO_DRAW; self->x = player.x + player.w / 2 - self->w / 2; if (self->x < minX) { self->x = minX; } else if (self->x + self->w >= maxX) { self->x = maxX - self->w - 1; } self->y = self->head->y; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->action = &dropAttack; self->thinkTime = 60; self->dirY = 0; self->touch = &entityTouch; checkToMap(self); }
static void lightningCageTeleportAway() { self->thinkTime--; if (self->thinkTime <= 0) { setEntityAnimation(self, "STAND"); self->flags &= ~NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->target->layer = MID_GROUND_LAYER; self->action = &attackFinished; } checkToMap(self); becomeTransparent(); }
static void superDropAttack() { checkToMap(self); if (self->flags & ON_GROUND) { self->mental--; if (self->mental <= 0) { addSmokeAlongBody(); playSoundToMap("sound/enemy/red_grub/thud", -1, self->x, self->y, 0); self->action = &superDropAttackFinished; } else { addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->flags |= (FLY|NO_DRAW); self->thinkTime = 90; self->x = player.x + player.w / 2 - self->w / 2; self->y = self->head->y; self->dirY = 0; self->action = &superDropAttackInit; self->head->mental = 0; } } }
static void teleportAway() { int rand; Target *t; self->thinkTime--; if (self->thinkTime <= 0) { rand = prand() % 2; t = getTargetByName(rand == 0 ? "SORCEROR_LEFT_TARGET" : "SORCEROR_RIGHT_TARGET"); if (t == NULL) { showErrorAndExit("Sorceror cannot find target"); } playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->flags |= NO_DRAW|FLY; self->x = t->x; self->y = t->y; self->face = rand == 0 ? RIGHT : LEFT; self->action = &teleportAwayFinish; self->thinkTime = 30; } checkToMap(self); }
static void fireballAttackInit() { Target *t = getTargetByName((prand() % 2 == 0) ? "AWESOME_TARGET_LEFT" : "AWESOME_TARGET_RIGHT"); if (t == NULL) { showErrorAndExit("Awesome Boss cannot find target"); } self->x = t->x + (prand() % 16) * (prand() % 2 == 0 ? 1 : -1); self->y = t->y; facePlayer(); playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->flags &= ~NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->action = &fireballAttack; self->touch = &entityTouch; self->thinkTime = -1; }
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; } } }
static void soulSteal() { Target *t; setCustomAction(&player, &stickToFloor, 3, 0, 0); self->thinkTime--; player.x = self->targetX; self->maxThinkTime += self->mental; if (self->maxThinkTime > 255) { self->maxThinkTime = 255; self->mental *= -1; } else if (self->maxThinkTime < 0) { self->maxThinkTime = 0; self->mental *= -1; } player.alpha = self->maxThinkTime; if (self->thinkTime <= 0) { self->flags |= NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); t = getTargetByName("AZRIEL_TOP_TARGET"); if (t == NULL) { showErrorAndExit("Azriel cannot find target"); } self->x = t->x; self->y = t->y; self->head->health++; self->head->alpha = self->head->health * 64; if (self->head->alpha > 255) { self->head->alpha = 255; } self->head->thinkTime = self->head->maxThinkTime; self->head->mental = 0; player.alpha = self->targetY; player.alpha -= 64; if (player.alpha <= 0) { player.alpha = 0; player.thinkTime = 600; player.health = 0; setPlayerLocked(TRUE); } self->thinkTime = 30; self->action = &soulStealFinish; } checkToMap(self); becomeTransparent(); }
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(); }
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(); }
static void dieMoveToTop() { EntityList *l, *list; Entity *e; self->thinkTime--; if (self->thinkTime <= 0) { switch (self->mental) { case 0: self->target->inUse = FALSE; stopSound(self->target->endX); setEntityAnimation(self, "INTRO"); self->flags &= ~NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->thinkTime = 90; self->mental = 1; break; case 1: createAutoDialogBox(_("Azriel"), _("Until we meet again..."), 120); self->mental = 2; self->thinkTime = 180; break; default: list = createPixelsFromSprite(getCurrentSprite(self)); for (l=list->next;l!=NULL;l=l->next) { e = l->entity; e->dirX = prand() % 30 * (e->x < self->x + self->w / 2 ? -1 : 1); e->dirY = prand() % 30 * (e->y < self->y + self->h / 2 ? -1 : 1); e->dirX /= 10; e->dirY /= 10; e->thinkTime = 180 + prand() % 180; } self->flags |= NO_DRAW; freeEntityList(list); self->thinkTime = 120; self->action = &dieWait; playSoundToMap("sound/boss/azriel/azriel_die", BOSS_CHANNEL, self->x, self->y, 0); break; } } }
static void destroyFloor() { EntityList *list; EntityList *l; Entity *e; self->thinkTime--; if (self->thinkTime <= 0) { if (self->mental == 0) { self->y = getMapFloor(self->x + self->w / 2, self->y) - self->h; playSoundToMap("sound/common/spell", -1, self->x, self->y, 0); self->flags &= ~NO_DRAW; addParticleExplosion(self->x + self->w / 2, self->y + self->h / 2); self->thinkTime = 60; self->mental = 1; } else if (self->mental == 1) { setEntityAnimation(self, "ATTACK_1"); self->mental = 2; self->thinkTime = 600; list = getEntitiesByObjectiveName("SORCEROR_FLOOR"); for (l=list->next;l!=NULL;l=l->next) { e = l->entity; e->active = TRUE; } freeEntityList(list); } else if (self->mental == 2) { setEntityAnimation(self, "STAND"); list = getEntitiesByObjectiveName("SORCEROR_FLOOR"); for (l=list->next;l!=NULL;l=l->next) { e = l->entity; e->active = FALSE; } freeEntityList(list); self->thinkTime = 30; self->action = &teleportAway; } } if (player.y >= getMapMaxY()) { self->thinkTime = 5; self->mental = 2; } checkToMap(self); }
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); }