static void touch(Entity *other) { Entity *e; pushEntity(other); if (other->standingOn == self) { if (self->thinkTime < 5) { playSoundToMap("sound/item/inflate", -1, self->x, self->y, 0); self->health++; } if (self->health == 3) { if (self->thinkTime < 5) { e = addBubble(self->x, self->y, "item/bubble"); e->x = self->face == LEFT ? getLeftEdge(self) : getRightEdge(self); e->x += self->face == LEFT ? -e->w : e->w; e->y = self->y + self->h / 2 - e->h / 2; e->dirX = self->face == LEFT ? -e->speed : e->speed; } self->thinkTime = 60; } else if (self->health > 3) { self->health = 3; self->thinkTime = 60; } else { self->thinkTime = 10; } setEntityAnimationByID(self, self->health + 3); } }
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 takeDamage(Entity *other, int damage) { Entity *temp; if (!(self->flags & INVULNERABLE)) { /* Can't be hurt if not facing the player unless using pickaxe */ if (self->face == other->face) { if (strcmpignorecase(other->name, "weapon/pickaxe") != 0) { playSoundToMap("sound/common/dink", -1, self->x, self->y, 0); setCustomAction(self, &invulnerableNoFlash, HIT_INVULNERABLE_TIME, 0, 0); if (other->reactToBlock != NULL) { temp = self; self = other; self->reactToBlock(temp); self = temp; } if (prand() % 10 == 0) { setInfoBoxMessage(60, 255, 255, 255, _("This weapon is not having any effect...")); } damage = 0; } else { entityTakeDamageNoFlinch(other, damage * 5); } } else { entityTakeDamageNoFlinch(other, damage); } } }
static void shotAttack() { Entity *e; self->thinkTime--; if (self->thinkTime <= 0) { playSoundToMap("sound/boss/snake_boss/snake_boss_shot", BOSS_CHANNEL, self->x, self->y, 0); if (prand() % 4 == 0 && self->startX == 0) { e = addProjectile("boss/snake_boss_special_shot", self, self->x + self->w / 2, self->y + self->h / 2, (self->face == RIGHT ? 7 : -7), 0); e->action = &specialShotMove; e->reactToBlock = &specialShotBlock; self->startX = 1; } else { e = addProjectile("boss/snake_boss_normal_shot", self, self->x + self->w / 2, self->y + self->h / 2, (self->face == RIGHT ? 7 : -7), 0); e->reactToBlock = &bounceOffShield; } e->y -= e->h / 2; self->x += (self->face == LEFT ? 10 : -10); self->maxThinkTime--; if (self->maxThinkTime <= 0) { self->action = &attackFinished; } else { self->thinkTime = 10; } } alignBodyToHead(); }
static void walk() { if (self->active == FALSE) { self->flags &= ~ATTACKING; self->damage = 0; setEntityAnimation(self, "STAND"); checkToMap(self); } else { self->damage = 1; self->flags |= ATTACKING; setEntityAnimation(self, "WALK"); if (self->offsetX != 0) { if (self->maxThinkTime == 0) { playSoundToMap("sound/enemy/centurion/walk", -1, self->x, self->y, 0); self->maxThinkTime = 1; } self->dirX = 0; } else { self->maxThinkTime = 0; } checkToMap(self); if (self->offsetX != 0) { self->dirX = (self->face == RIGHT ? self->speed : -self->speed); } } }
static void recharge() { self->thinkTime--; if (self->thinkTime <= 0) { self->health++; setChargeState(); playSoundToMap("sound/item/charge_beep", -1, self->x, self->y, 0); self->thinkTime = 180; } checkToMap(self); }
static void entityWait() { self->thinkTime--; if (self->thinkTime <= 0) { playDefaultBossMusic(); playSoundToMap("sound/boss/boulder_boss/roll", BOSS_CHANNEL, self->x, self->y, -1); setEntityAnimation(self, "WALK"); self->action = &chasePlayer; self->thinkTime = 1; } }
static void fireDropMoveAbovePlayer() { if (self->face == RIGHT) { self->targetX = player.x - self->offsetX + player.w / 2; } else { self->targetX = player.x - (self->w - self->offsetX) + player.w / 2; } if (abs(self->x - self->targetX) <= abs(self->dirX)) { self->x = self->targetX; self->dirX = 0; self->thinkTime = 3; if (player.health > 0) { playSoundToMap("sound/enemy/fireball/fireball", BOSS_CHANNEL, self->x, self->y, 0); self->mental = 10; setEntityAnimation(self, "FIRE_ATTACK_DOWN"); self->action = &fireDrop; } else { setEntityAnimation(self, "FIRE_ATTACK_DOWN"); } } else { self->dirX = self->targetX < self->x ? -player.speed * 2 : player.speed * 2; setEntityAnimation(self, "FIRE_WALK"); } checkToMap(self); }
static void move() { moveLeftToRight(); hover(); self->health--; if (self->health <= 0) { playSoundToMap("sound/enemy/ghost/ghost", -1, self->x, self->y, 0); self->health = (6 + prand() % 10) * 60; } self->box.h = self->endY - self->y; }
static void sprayRepellent(int val) { Entity *e; if (self->thinkTime <= 0 && game.status == IN_GAME && player.element != WATER) { e = getFreeEntity(); if (e == NULL) { showErrorAndExit("No free slots to add Repellent Spray"); } loadProperties("item/repellent_spray", e); e->x = player.x + (player.face == RIGHT ? player.w : 0); e->y = player.y + player.h / 2; setEntityAnimation(e, "STAND"); e->x -= player.face == RIGHT ? e->box.x : e->box.x + e->box.w; e->y -= e->h / 2; e->type = ITEM; e->face = RIGHT; e->action = &sprayMove; e->touch = &sprayTouch; e->draw = &drawLoopingAnimationToMap; e->active = FALSE; self->thinkTime = self->maxThinkTime; e->dirX = player.face == RIGHT ? 2 + player.speed : -2 - player.speed; e->thinkTime = 30; e->flags |= DO_NOT_PERSIST; playSoundToMap("sound/item/spray", -1, player.x, player.y, 0); } }
static void drop() { if (self->flags & ON_GROUND) { self->thinkTime = 30; playSoundToMap("sound/common/crash", -1, self->x, self->y, 0); shakeScreen(STRONG, self->thinkTime / 2); addDust(); self->action = &entityWait; } checkToMap(self); }
static void smallTouch(Entity *other) { if (other->type == PLAYER && other->dirY > 0) { self->touch = &entityTouch; playSoundToMap("sound/enemy/splitter/splat", -1, self->x, self->y, 0); setEntityAnimation(self, "DIE"); self->thinkTime = 120; self->action = &smallDie; self->dirX = 0; } }
static void createElectricity() { Entity *e = getFreeEntity(); if (e == NULL) { showErrorAndExit("No free slots to add Tortoise electricity"); } loadProperties("enemy/tortoise_electricity", e); playSoundToMap("sound/enemy/tortoise/tortoise_electric", -1, self->x, self->y, 0); setEntityAnimation(e, "STAND"); e->action = &doElectricity; e->creditsAction = &doElectricity; e->touch = &entityTouch; e->takeDamage = &takeDamage; e->draw = &drawLoopingAnimationToMap; e->target = self; e->face = self->face; e->x = self->x; e->y = self->y; self->target = e; self->frameSpeed = 1; setEntityAnimation(self, "ATTACK_1"); self->action = &electrify; self->creditsAction = &electrify; self->thinkTime = 120; }
static void spikeRise() { Entity *e; self->thinkTime--; if (self->thinkTime <= 0) { if (self->y > self->startY) { self->y -= self->speed * 2; } else { playSoundToMap("sound/common/crumble", BOSS_CHANNEL, self->x, self->y, 0); shakeScreen(MEDIUM, 15); e = addSmallRock(self->x, self->y, "common/small_rock"); e->x += (self->w - e->w) / 2; e->y += (self->h - e->h) / 2; e->dirX = -3; e->dirY = -8; e = addSmallRock(self->x, self->y, "common/small_rock"); e->x += (self->w - e->w) / 2; e->y += (self->h - e->h) / 2; e->dirX = 3; e->dirY = -8; self->y = self->startY; self->health = 15; self->thinkTime = 120; self->action = &spikeWait; } } }
static void skullAttack() { Entity *e; self->thinkTime--; if (self->thinkTime <= 0) { setEntityAnimation(self, "ATTACK"); e = addProjectile("enemy/skull_shot", self, self->x, self->y, self->face == LEFT ? -6 : 6, 0); playSoundToMap("sound/boss/snake_boss/snake_boss_shot", -1, self->x, self->y, 0); if (self->face == LEFT) { e->x = self->x + self->w - e->w - self->offsetX; } else { e->x = self->x + self->offsetX; } e->y = self->y + self->offsetY; e->face = self->face; e->action = &skullShotMove; e->flags |= FLY; e->reactToBlock = &skullShotReflect; e->thinkTime = 1200; e->mental = 2; self->thinkTime = 60; self->action = &skullAttackFinish; } checkToMap(self); }
static void sprayGas() { int i; Entity *e; self->thinkTime--; if (self->thinkTime <= 0) { setEntityAnimation(self, "ATTACK_1"); for (i=0;i<2;i++) { e = getFreeEntity(); if (e == NULL) { showErrorAndExit("No free slots to add a Gas Plant Spray"); } loadProperties("enemy/gas_plant_spray", e); e->action = &sprayMove; e->draw = &drawLoopingAnimationToMap; e->touch = &entityTouch; e->type = ENEMY; e->dirX = i == 0 ? -e->speed : e->speed; e->x = self->x + self->w / 2 - e->w / 2; e->y = self->y + e->offsetY; } playSoundToMap("sound/item/spray", -1, self->x, self->y, 0); self->mental = self->mental >= 0 ? 0 : -3; self->action = &sprayGasWait; self->thinkTime = 30; } checkToMap(self); }
static void die() { int i; long onGround; setEntityAnimation(self, "DIE"); self->action = ¨ self->damage = 0; self->flags &= ~FLY; 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"); } fireTrigger(self->objectiveName); fireGlobalTrigger(self->objectiveName); self->die = &entityDieNoDrop; self->action = &dieWait; clearContinuePoint(); increaseKillCount(); freeBossHealthBar(); fadeBossMusic(); } }
static void stalagmiteTakeDamage(Entity *other, int damage) { Entity *temp; if (strcmpignorecase(self->requires, other->name) == 0) { self->health -= damage; setCustomAction(self, &flashWhite, 6, 0, 0); setCustomAction(self, &invulnerableNoFlash, HIT_INVULNERABLE_TIME, 0, 0); if (self->health <= 0) { self->damage = 0; self->die(); } } else { setCustomAction(self, &invulnerableNoFlash, HIT_INVULNERABLE_TIME, 0, 0); playSoundToMap("sound/common/dink", -1, self->x, self->y, 0); if (other->reactToBlock != NULL) { temp = self; self = other; self->reactToBlock(temp); self = temp; } if (other->type != PROJECTILE && prand() % 10 == 0) { setInfoBoxMessage(60, 255, 255, 255, _("This weapon is not having any effect...")); } damage = 0; } }
static void entityWait() { int i; self->thinkTime--; facePlayer(); hover(); if (self->thinkTime <= 0 && player.health > 0) { i = self->health <= (self->maxHealth / 10) ? prand() % 10 : prand() % 4; switch (i) { case 0: self->action = &bulletFireInit; break; case 1: self->action = &headButtInit; break; case 2: self->thinkTime = 120 + prand() % 180; self->action = &dropInit; break; case 3: self->action = &slimeFireInit; break; default: self->action = &stingAttackInit; break; } self->damage = 1; playSoundToMap("sound/boss/fly_boss/buzz", BOSS_CHANNEL, self->x, self->y, 0); } }
static void entityWait() { EntityList *el, *entities; entities = getEntities(); setEntityAnimation(self, self->active == FALSE ? "STAND" : "WALK"); if (self->active == TRUE) { if (self->health == -1) { self->health = playSoundToMap("sound/item/rift", -1, self->x, self->y, -1); } self->thinkTime--; if (self->thinkTime <= 0) { for (el=entities->next;el!=NULL;el=el->next) { if (el->entity->inUse == TRUE && el->entity->type == ENEMY && collision(self->x - self->mental, self->y, self->mental * 2, self->mental * 2, el->entity->x, el->entity->y, el->entity->w, el->entity->h) == 1) { setCustomAction(el->entity, &attract, self->maxThinkTime, 0, (el->entity->x < (self->x + self->w / 2) ? self->speed : -self->speed)); } } self->thinkTime = self->maxThinkTime; if (collision(self->x - self->mental, self->y, self->mental * 2, self->mental * 2, player.x, player.y, player.w, player.h) == 1) { setCustomAction(&player, &attract, self->maxThinkTime, 0, (player.x < (self->x + self->w / 2) ? self->speed : -self->speed)); } stopSound(self->health); } if (prand() % 3 == 0) { addRiftEnergy(self->x + self->w / 2, self->y + self->h / 2); } } }
static void spit() { Entity *e; int x, y; x = self->x + self->w / 2; y = self->y + 5; e = addProjectile("common/green_blob", self, x, y, -6, 0); e->flags |= FLY; e->reactToBlock = &bounceOffShield; e = addProjectile("common/green_blob", self, x, y, -6, -6); e->flags |= FLY; e->reactToBlock = &bounceOffShield; e = addProjectile("common/green_blob", self, x, y, 0, -6); e->flags |= FLY; e->reactToBlock = &bounceOffShield; e = addProjectile("common/green_blob", self, x, y, 6, -6); e->flags |= FLY; e->reactToBlock = &bounceOffShield; e = addProjectile("common/green_blob", self, x, y, 6, 0); e->flags |= FLY; e->reactToBlock = &bounceOffShield; playSoundToMap("sound/common/pop", -1, self->x, self->y, 0); setEntityAnimation(self, "ATTACK_2"); self->animationCallback = &spitFinish; }
static void throwMeat(int val) { Entity *e; if (self->thinkTime <= 0 && game.status == IN_GAME && player.element != WATER) { e = addEntity(*self, player.x + (player.face == RIGHT ? player.w : 0), player.y); e->flags &= ~ON_GROUND; e->health = 5; e->dirX = player.face == LEFT ? -6 : 6; e->dirY = ITEM_JUMP_HEIGHT; e->action = &generalItemAction; e->touch = &touch; e->thinkTime = 1200; e->fallout = &meatFallout; e->flags |= DO_NOT_PERSIST; setCustomAction(e, &invulnerableNoFlash, 60, 0, 0); playSoundToMap("sound/common/throw", -1, player.x, player.y, 0); self->health--; if (self->health <= 0) { self->inUse = FALSE; } else { self->thinkTime = 120; } } }
static void sprayIce(int val) { Entity *e; if (self->thinkTime <= 0 && game.status == IN_GAME && player.element != WATER) { e = addIceCube(player.x + (player.face == RIGHT ? player.w : 0), player.y + player.h / 2, "item/ice_cube"); e->dirX = player.face == LEFT ? -5 : 5; e->dirY = ITEM_JUMP_HEIGHT; e->face = player.face; playSoundToMap("sound/item/spray", -1, player.x, player.y, 0); self->thinkTime = 30; } }
static void bite() { checkToMap(self); if (self->flags & ON_GROUND) { self->action = &biteFinish; self->touch = &touch; setEntityAnimation(self, "STAND"); self->flags |= FLY; self->thinkTime = 120; playSoundToMap("sound/enemy/floating_snapper/chomp", -1, self->x, self->y, 0); } }
static void die() { Entity *e; if (prand() % 3 == 0) { e = addKeyItem("item/spike_ball", self->x + self->w / 2, self->y); e->x -= e->w / 2; e->action = &generalItemAction; e->flags |= DO_NOT_PERSIST; } playSoundToMap("sound/enemy/armadillo/armadillo_die", -1, self->x, self->y, 0); entityDie(); }
static void burnStart() { self->health = 1; if (self->startY == -1) { self->startX = playSoundToMap("sound/enemy/fire_burner/flame", -1, self->x, self->y, 0); } self->thinkTime = self->maxThinkTime; setEntityAnimation(self, "WALK"); self->animationCallback = &burn; self->touch = &entityTouch; self->action = &burnWait; }
static void iceDrop() { int i; Entity *e; checkToMap(self); self->thinkTime--; if (self->thinkTime <= 0) { self->flags &= ~FLY; } if (self->flags & ON_GROUND) { playSoundToMap("sound/common/shatter", -1, self->x, self->y, 0); for (i=0;i<8;i++) { e = addTemporaryItem("misc/ice_spike_piece", self->x, self->y, RIGHT, 0, 0); e->x = self->x + self->w / 2; e->x -= e->w / 2; e->y = self->y + self->h / 2; e->y -= e->h / 2; e->dirX = (prand() % 4) * (prand() % 2 == 0 ? -1 : 1); e->dirY = ITEM_JUMP_HEIGHT * 2 + (prand() % ITEM_JUMP_HEIGHT); setEntityAnimationByID(e, i); e->thinkTime = 60 + (prand() % 60); e->touch = NULL; } self->head->mental--; self->inUse = FALSE; } }
static void reform() { checkToMap(self); if (self->thinkTime > 0) { self->thinkTime--; if (self->flags & ON_GROUND) { self->dirX = 0; } } else { self->health--; if (fabs(self->targetX - self->x) <= fabs(self->dirX) || self->health <= 0) { self->head->startX--; self->head->flags &= ~NO_DRAW; self->inUse = FALSE; if (((int)self->head->startX) % 10 == 0) { self->head->currentFrame++; } playSoundToMap("sound/boss/blob_boss/plop", BOSS_CHANNEL, self->x, self->y, 0); } if (self->flags & ON_GROUND) { self->dirX = (self->x < self->targetX ? self->speed : -self->speed); self->dirY = -6; } } }
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); } } }