fixes for API renaming
[k8vacspelynky.git] / mapent / enemies / blob.vc
blob192402b63652841dfce024f1b8bdface26033120
1 /**********************************************************************************
2  * Copyright (c) 2008, 2009 Derek Yu and Mossmouth, LLC
3  * Copyright (c) 2010, Moloch
4  * Copyright (c) 2018, Ketmar Dark
5  *
6  * This file is part of Spelunky.
7  *
8  * You can redistribute and/or modify Spelunky, including its source code, under
9  * the terms of the Spelunky User License.
10  *
11  * Spelunky is distributed in the hope that it will be entertaining and useful,
12  * but WITHOUT WARRANTY.  Please see the Spelunky User License for more details.
13  *
14  * The Spelunky User License should be available in "Game Information", which
15  * can be found in the Resource Explorer, or as an external file called COPYING.
16  * If not, please obtain a new copy of Spelunky from <http://spelunkyworld.com/>
17  *
18  **********************************************************************************/
19 class EnemyBlob['oBlob'] : MapEnemy;
22 IDLE = 0;
23 WALK = 1;
24 ATTACK = 2;
25 STUNNED = 98;
26 DEAD = 99;
29 override bool initialize () {
30   if (!::initialize()) return false;
31   setSprite('sBlobStand');
32   //counter = global.randOther(10, 30);
33   //value = 4000+global.levelType*2000;
34   return true;
38 override bool onTouchedByPlayerWeapon (PlayerPawn plr, PlayerWeapon wobj) {
39   hp -= 5;
40   countsAsKill = true;
41   scrCreateBloblets(xCenter, yCenter, 1);
42   plr.playSound('sndHit');
43   return true;
47 // for dead players too
48 // first, the code will call `onObjectTouched()` for player
49 // if it returned `false`, the code will call this handler
50 // note that player's handler is called *after* its frame thinker,
51 // but object handler is called *before* frame thinker for the object
52 // return `true` to skip thinker on this frame
53 override bool onTouchedByPlayer (PlayerPawn plr) {
54   if (plr.dead) return false;
56   // slow player down and absorb poison
57   imageAlpha = 0.7;
59   //if collision_point(x+8, y+8, oCharacter, 0, 0)
60   if (fabs(plr.xVel) == 0 && plr.iy <= iy+8 && plr.status != CLIMBING) {
61     if (plr.ix > ix+8) plr.fltx -= 1; else if (plr.ix < ix+8) plr.fltx += 1;
62   }
64   plr.xVel += xVel;
66   return false;
70 override bool onExplosionTouch (MapObject xplo) {
71   if (invincible) return false;
73   scrCreateBloblets(xCenter, yCenter, 5);
75   if (countsAsKill) level.addKill(objName);
76   instanceRemove();
78   return true;
82 override void thinkFrame () {
83   ::thinkFrame();
84   if (!isInstanceAlive) return;
86   moveRel(xVel, yVel);
88   yVel = fmin(yVel+myGrav, yVelLimit);
90   if (level.isSolidAtPoint(ix+8, iy+8)) hp = 0;
92   if (hp < 1) {
93     scrCreateBloblets(ix+8, iy+8, global.randOther(2, 4));
94     if (countsAsKill) level.addKill(objName);
95     instanceRemove();
96     return;
97   }
99   if (isCollisionBottom(1) && status != STUNNED) yVel = 0;
101   depth = 40;
102   imageAlpha = 0.9;
104   if (status == IDLE) {
105     setSprite('sBlobStand');
106     if (counter > 0) --counter; else { dir = global.randOther(0, 1); status = WALK; }
107   } else if (status == WALK) {
108     /* in the original
109     if (isCollisionLeft(1) or isCollisionRight(1)) {
110       if (facing == LEFT) facing = RIGHT; else facing = LEFT;
111     }
112     */
113     int x = ix, y = iy;
115          if (dir == Dir.Left && !level.isSolidAtPoint(x-1, y+16)) dir = Dir.Right;
116     else if (dir == Dir.Right && !level.isSolidAtPoint(x+16, y+16)) dir = Dir.Left;
118     if ((!level.isSolidAtPoint(x-1, y+16) || level.isSolidAtPoint(x-1, y)) &&
119         (!level.isSolidAtPoint(x+16, y+16) || level.isSolidAtPoint(x+16, y)))
120     {
121       dir = (level.isSolidAtPoint(x-1, y) ? Dir.Right : Dir.Left);
122       xVel = 0;
123     } else if (dir == Dir.Left) {
124       xVel = -0.5;
125     } else {
126       xVel = 0.5;
127     }
129     if (global.randOther(1, 120) == 1) {
130       status = IDLE;
131       counter = global.randOther(50, 100);
132       xVel = 0;
133     }
134   } else if (status == ATTACK) {
135     // ?
136   }
138   if (isCollision()) flty -= 2;
140   if (status != STUNNED) {
141     imageSpeed = (xVel == 0 ? 0.2 : 0.3);
142     setSprite('sBlobWalkL');
143   }
145   if (status == IDLE) setSprite('sBlobStand');
147   /* in the original
148   if (status != STUNNED and facing == RIGHT) {
149     if (xVel == 0) image_speed = 0.2; else image_speed = 0.4;
150     sprite_index = sSnakeWalkR;
151   }
152   */
156 defaultproperties {
157   objName = 'Blob';
158   desc = "Blob";
159   desc2 = "Hardly more than an annoyance, this mass of goo feeds on decomposing matter.";
161   setCollisionBounds(2, 0, 14, 16);
162   xVel = 0.5;
163   imageSpeed = 0.3;
165   // stats
166   hp = 99;
167   invincible = 0;
168   bloodless = true;
170   status = IDLE;
172   bounced = false;
173   dead = false;
174   counter = 0;
176   dir = Dir.Right;
178   doBasicPhysics = false;
179   flying = false; // don't fall
181   countsAsKill = true;
182   leavesBody = true; // we will do our own death sequence
184   depth = 40;