1 /**********************************************************************************
2 * Copyright (c) 2008, 2009 Derek Yu and Mossmouth, LLC
3 * Copyright (c) 2018, Ketmar Dark
5 * This file is part of Spelunky.
7 * You can redistribute and/or modify Spelunky, including its source code, under
8 * the terms of the Spelunky User License.
10 * Spelunky is distributed in the hope that it will be entertaining and useful,
11 * but WITHOUT WARRANTY. Please see the Spelunky User License for more details.
13 * The Spelunky User License should be available in "Game Information", which
14 * can be found in the Resource Explorer, or as an external file called COPYING.
15 * If not, please obtain a new copy of Spelunky from <http://spelunkyworld.com/>
17 **********************************************************************************/
18 class EnemyZombie['oZombie'] : MapEnemy;
30 override bool initialize () {
31 if (!::initialize()) return false;
32 setSprite('sZombieLeft');
33 dir = global.randOther(0, 1);
34 if (level.isWaterAtPoint(ix, iy)) swimming = true;
40 override void onAnimationLooped () {
41 if (spriteLName == spriteFlipName) setSprite(spriteNormalName);
46 override void thinkFrame () {
48 if (!isInstanceAlive) return;
52 yVel = fmin(yVel+myGrav, yVelLimit);
56 if (level.isSolidAtPoint(x+8, y+8)) hp = -999;
60 foreach (; 0..3) level.MakeMapObject(ix+8, iy+8, 'oBone');
61 auto skull = level.MakeMapObject(ix+8, iy+8, 'oSkull');
63 skull.yVel = -global.randOther(1, 3);
64 skull.xVel = global.randOther(0, 3)-global.randOther(0, 3);
66 if (countsAsKill) level.addKill(objName);
71 if (isCollisionRight(1)) xVel = -1;
72 if (isCollisionLeft(1)) xVel = 1;
74 bool colBot = !!isCollisionBottom(1);
77 auto dist = distanceToEntityCenter(level.player);
79 if (counter > 0) --counter;
80 else if (dist < 64) status = BOUNCE;
81 if (dist < 48) status = BOUNCE;
82 if (level.player.swimming) status = IDLE;
83 if (status == BOUNCE) playSound('sndZombie');
84 } else if (status == RECOVER) {
89 counter = global.randOther(40, 100);
91 } else if (status == BOUNCE) {
93 if (global.randOther(1, 4) == 1) {
94 yVel = -global.randOther(2, 4);
95 if (level.player.ix < x) { dir = Dir.Left; xVel = -3; } else { dir = Dir.Right; xVel = 3; }
97 yVel = -global.randOther(1, 2);
98 if (level.player.ix < x) { dir = Dir.Left; xVel = -1; } else { dir = Dir.Right; xVel = 1; }
103 } else if (status != DROWNED) {
108 if (isCollisionTop(1)) yVel = 1;
110 //if (isCollisionSolid()) y -= 2;
112 setSprite(!colBot ? 'sZombieJumpL' : 'sZombieLeft');
119 desc2 = "A well-dressed, territorial corpse, inhabited by a restless spirit.";
122 setCollisionBounds(0, 2, 16, 16);
131 doBasicPhysics = false;
132 flying = false; // don't fall
143 leavesBody = true; // we will do our own death sequence