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(); }
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(); }
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"); } }
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"); } }
static void die() { int i; self->action = ¨ 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; } }
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); }
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; } }
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); }
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(); }
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); }
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(); }
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; } }
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(); } }
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); } }
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); } }
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); }
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; } } }
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); }
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); }
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); }
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); }
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); }
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 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; } }