oops: water top fixing in great lake was broken
[k8vacspelynky.git] / PlayerPowerup.vc
blob139018fa7363b55bda7f25ce2b567fafb825fb5f
1 /**********************************************************************************
2  * Copyright (c) 2008, 2009 Derek Yu and Mossmouth, LLC
3  * Copyright (c) 2018, Ketmar Dark
4  *
5  * This file is part of Spelunky.
6  *
7  * You can redistribute and/or modify Spelunky, including its source code, under
8  * the terms of the Spelunky User License.
9  *
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.
12  *
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/>
16  *
17  **********************************************************************************/
18 // recoded by Ketmar // Invisible Vector
19 class PlayerPowerup : Object abstract;
21 name id;
22 PlayerPawn owner;
23 int renderPriority; // from lower to higher
24 bool lostOnDeath = true;
25 bool active;
26 bool prePreDucking; // for cape
29 // called when the player get it for the first time
30 bool onActivate () {
31   active = true;
32   return true;
36 // called when the player lost it (for some reason)
37 bool onDeactivate (optional bool forced) {
38   active = false;
39   return true;
43 void onPlayerDied () {
44   onDeactivate(forced:true);
48 void onPreThink () {
52 void onPostThink () {
56 void preDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
60 void postDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
64 void lastDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
68 // ////////////////////////////////////////////////////////////////////////// //
69 class PPCape : PlayerPowerup;
71 bool visible;
72 int dx, dy;
73 name sprName;
74 bool beforePlayer;
75 bool open;
78 // called when the player get it for the first time
79 override bool onActivate () {
80   owner.global.hasCape = true;
81   visible = true;
82   active = true;
83   //open = false;
84   return true;
88 // called when the player lost it (for some reason)
89 override bool onDeactivate (optional bool forced) {
90   owner.global.hasCape = false;
91   visible = false;
92   active = false;
93   open = false;
94   return true;
98 override void onPostThink () {
99   visible = (owner.status != MapObject::DUCKTOHANG);
101   /*
102   if (instance_exists(oTransition) && !instance_exists(oPDummy))
103   {
104       instance_destroy();
105   }
106   */
108   /*
109   else if (instance_exists(oPDummy))
110   {
111       if (oPDummy.sprite_index == sPExit || oPDummy.sprite_index == sDamselExit || oPDummy.sprite_index == sTunnelExit)
112       {
113           x = oPDummy.x;
114           y = oPDummy.y+4;
115           sprite_index = sCapeBack;
116           depth = 0;
117       }
118       else
119       {
120           x = oPDummy.x - 4;
121           y = oPDummy.y - 2;
122           if (oPDummy.sprite_index == sRunLeft || oPDummy.sprite_index == sDamselRunL || oPDummy.sprite_index == sTunnelRunL) sprite_index = sCapeRight;
123           else sprite_index = sCapeDR;
124           depth = 100;
125       }
126   }
127   */
129   if (!owner.whipping && (owner.status == MapObject::CLIMBING || owner.isExitingSprite())) {
130     dx = 0;
131     dy = 4;
132     sprName = 'sCapeBack';
133     //depth = 0;
134     beforePlayer = true;
135   }
136   else if (owner.dir == MapObject::Dir.Right) {
137     dx = -4;
138     dy = (owner.status == MapObject::DUCKING || owner.stunned ? 2 : -2);
139          if (open) sprName = 'sCapeUR';
140     else if (fabs(owner.xVel) > 0 && owner.status != MapObject::DUCKING) sprName = 'sCapeRight';
141     else sprName = 'sCapeDR';
142     //depth = 111;
143     beforePlayer = false;
144   } else {
145     // left
146     dx = 4;
147     dy = (owner.status == MapObject::DUCKING || owner.stunned ? 2 : -2);
148          if (open) sprName = 'sCapeUL';
149     else if (fabs(owner.xVel) > 0 && owner.status != MapObject::DUCKING) sprName = 'sCapeLeft';
150     else sprName = 'sCapeDL';
151     //depth = 111;
152     beforePlayer = false;
153   }
155   //writeln("CAPE: '", sprName, "'; before=", beforePlayer);
159 final void doDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
160   if (!sprName) return;
162   auto spr = owner.level.sprStore[sprName];
163   if (!spr || spr.frames.length < 1) return;
164   auto spf = spr.frames[0];
165   if (!spf || spf.width < 1 || spf.height < 1) return;
167   int xi, yi;
168   owner.getInterpCoords(currFrameDelta, scale, out xi, out yi);
170   xi += dx*scale;
171   yi += dy*scale;
173   xi -= spf.xofs*scale;
174   yi -= spf.yofs*scale;
176   spf.tex.blitAt(xi-xpos, yi-ypos, scale);
180 override void preDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
181   if (!visible || beforePlayer) return;
182   doDrawWithOfs(xpos, ypos, scale, currFrameDelta);
186 override void lastDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
187   if (!visible || !beforePlayer) return;
188   doDrawWithOfs(xpos, ypos, scale, currFrameDelta);
192 defaultproperties {
193   id = 'Cape';
194   renderPriority = 1010; // behind the bricks
195   sprName = 'sCapeRight';
196   prePreDucking = true;
200 // ////////////////////////////////////////////////////////////////////////// //
201 class PPParachute : PlayerPowerup;
203 const int dx = -8;
204 const int dy = -16;
205 int imageFrame = 0;
206 bool opening;
208 // called when the player get it for the first time
209 override bool onActivate () {
210   active = true;
211   opening = true;
212   imageFrame = 0;
213   return true;
217 // called when the player lost it (for some reason)
218 override bool onDeactivate (optional bool forced) {
219   active = false;
220   return true;
224 override void onPostThink () {
225   if (opening) {
226     auto spr = owner.level.sprStore['sParaOpen'];
227     ++imageFrame;
228     if (imageFrame >= spr.frames.length) {
229       opening = false;
230       imageFrame = 0;
231     }
232   } else {
233     imageFrame = 0;
234   }
238 final void doDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
239   auto spr = owner.level.sprStore[opening ? 'sParaOpen' : 'sParachute'];
240   if (!spr || spr.frames.length < 1) return;
241   auto spf = spr.frames[imageFrame];
242   if (!spf || spf.width < 1 || spf.height < 1) return;
244   int xi, yi;
245   owner.getInterpCoords(currFrameDelta, scale, out xi, out yi);
247   xi += dx*scale;
248   yi += dy*scale;
250   xi -= spf.xofs*scale;
251   yi -= spf.yofs*scale;
253   spf.tex.blitAt(xi-xpos, yi-ypos, scale);
257 override void preDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
258   doDrawWithOfs(xpos, ypos, scale, currFrameDelta);
262 defaultproperties {
263   id = 'Parachute';
264   renderPriority = 1010; // behind the bricks