vines and ladders are invincible in the original
[k8vacspelynky.git] / PlayerPowerup.vc
blobee4cbc1cfa36eb9aad073b388c1136eb559ba8a6
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 // recoded by Ketmar // Invisible Vector
20 class PlayerPowerup : Object abstract;
22 name id;
23 PlayerPawn owner;
24 int renderPriority; // from lower to higher
25 bool lostOnDeath = true;
26 bool active;
27 bool prePreDucking; // for cape
30 // called when the player get it for the first time
31 bool onActivate () {
32   active = true;
33   return true;
37 // called when the player lost it (for some reason)
38 bool onDeactivate (optional bool forced) {
39   active = false;
40   return true;
44 void onPlayerDied () {
45   onDeactivate(forced:true);
49 void onPreThink () {
53 void onPostThink () {
57 void prePreDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
61 void preDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
65 void postDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
69 void lastDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
73 // ////////////////////////////////////////////////////////////////////////// //
74 class PPCape : PlayerPowerup;
76 bool visible;
77 int dx, dy;
78 name sprName;
79 bool beforePlayer;
80 bool open;
83 // called when the player get it for the first time
84 override bool onActivate () {
85   owner.global.hasCape = true;
86   visible = true;
87   active = true;
88   //open = false;
89   return true;
93 // called when the player lost it (for some reason)
94 override bool onDeactivate (optional bool forced) {
95   owner.global.hasCape = false;
96   visible = false;
97   active = false;
98   open = false;
99   return true;
103 override void onPostThink () {
104   visible = (owner.status != MapObject::DUCKTOHANG);
106   if (!owner.whipping && (owner.status == MapObject::CLIMBING || owner.isExitingSprite())) {
107     dx = 0;
108     dy = 4;
109     sprName = 'sCapeBack';
110     //depth = 0;
111     beforePlayer = true;
112   } else if (owner.dir == MapObject::Dir.Right) {
113     dx = -4;
114     dy = (owner.status == MapObject::DUCKING || owner.stunned ? 2 : -2);
115          if (open) sprName = 'sCapeUR';
116     else if (fabs(owner.xVel) > 0.4 && owner.status != MapObject::DUCKING) sprName = 'sCapeRight';
117     else sprName = 'sCapeDR';
118     //depth = 111;
119     beforePlayer = false;
120   } else {
121     // left
122     dx = 4;
123     dy = (owner.status == MapObject::DUCKING || owner.stunned ? 2 : -2);
124          if (open) sprName = 'sCapeUL';
125     else if (fabs(owner.xVel) > 0.4 && owner.status != MapObject::DUCKING) sprName = 'sCapeLeft';
126     else sprName = 'sCapeDL';
127     //depth = 111;
128     beforePlayer = false;
129   }
131   //writeln("CAPE: '", sprName, "'; before=", beforePlayer);
135 final void doDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
136   if (!sprName) return;
138   auto spr = owner.level.sprStore[sprName];
139   if (!spr || spr.frames.length < 1) return;
140   auto spf = spr.frames[0];
141   if (!spf || spf.width < 1 || spf.height < 1) return;
143   int xi, yi;
144   owner.getInterpCoords(currFrameDelta, scale, out xi, out yi);
146   xi += dx*scale;
147   yi += dy*scale;
149   xi -= spf.xofs*scale;
150   yi -= spf.yofs*scale;
152   spf.tex.blitAt(xi-xpos, yi-ypos, scale);
156 override void prePreDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
157   if (!visible || owner.status != MapObject::DUCKING) return;
158   doDrawWithOfs(xpos, ypos, scale, currFrameDelta);
162 override void preDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
163   if (!visible || beforePlayer || owner.status == MapObject::DUCKING) return;
164   doDrawWithOfs(xpos, ypos, scale, currFrameDelta);
168 override void lastDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
169   if (!visible || !beforePlayer) return;
170   doDrawWithOfs(xpos, ypos, scale, currFrameDelta);
174 defaultproperties {
175   id = 'Cape';
176   renderPriority = 1010; // behind the bricks
177   sprName = 'sCapeRight';
181 // ////////////////////////////////////////////////////////////////////////// //
182 class PPParachute : PlayerPowerup;
184 const int dx = -8;
185 const int dy = -16;
186 int imageFrame = 0;
187 bool opening;
189 // called when the player get it for the first time
190 override bool onActivate () {
191   active = true;
192   opening = true;
193   imageFrame = 0;
194   return true;
198 // called when the player lost it (for some reason)
199 override bool onDeactivate (optional bool forced) {
200   active = false;
201   return true;
205 override void onPostThink () {
206   if (opening) {
207     auto spr = owner.level.sprStore['sParaOpen'];
208     ++imageFrame;
209     if (imageFrame >= spr.frames.length) {
210       opening = false;
211       imageFrame = 0;
212     }
213   } else {
214     imageFrame = 0;
215   }
219 final void doDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
220   auto spr = owner.level.sprStore[opening ? 'sParaOpen' : 'sParachute'];
221   if (!spr || spr.frames.length < 1) return;
222   auto spf = spr.frames[imageFrame];
223   if (!spf || spf.width < 1 || spf.height < 1) return;
225   int xi, yi;
226   owner.getInterpCoords(currFrameDelta, scale, out xi, out yi);
228   xi += dx*scale;
229   yi += dy*scale;
231   xi -= spf.xofs*scale;
232   yi -= spf.yofs*scale;
234   spf.tex.blitAt(xi-xpos, yi-ypos, scale);
238 override void preDrawWithOfs (int xpos, int ypos, int scale, float currFrameDelta) {
239   doDrawWithOfs(xpos, ypos, scale, currFrameDelta);
243 defaultproperties {
244   id = 'Parachute';
245   renderPriority = 1010; // behind the bricks