sceptre and alienboss psychic waves now makes shopkeepers angry
[k8vacspelynky.git] / mapent / weapons / sceptre.vc
blobc05a18013cf7041285ce53d0abe59675cceb89a0
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 class ItemWeaponSceptre['oSceptre'] : MapItem;
21 override bool initialize () {
22   if (!::initialize()) return false;
23   setSprite('sSceptreLeft', 'sSceptreRight');
24   return true;
28 // called only if object was succesfully put into player hands
29 override void onPickedUp (PlayerPawn plr) {
30   if (!wasCollected) { wasCollected = true; level.addCollect(objName); }
34 // return `true` to stop player from throwing it
35 override bool onTryUseItem (PlayerPawn plr) {
36   // put it down?
37   if (plr.scrPlayerIsDucking()) {
38     plr.scrUsePutItemOnGround();
39     return true;
40   }
42   if (plr.firing || plr.scrPlayerIsDucking()) return true;
44   int xsgn = (plr.dir == Dir.Left ? -1 : 1);
45   int xofs = 12*xsgn;
47   foreach (; 0..3) {
48     auto obj = level.MakeMapObject(ix+xofs, iy+4, 'oPsychicCreateP');
49     if (obj) {
50       obj.xVel = xsgn*global.randOther(1, 3);
51       obj.yVel = -global.randOtherFloat(2);
52     }
53   }
54   auto obj = level.MakeMapObject(ix+xofs, iy-2, 'oPsychicWaveP');
55   if (obj) obj.xVel = xsgn*6;
56   playSound('sndPsychic');
57   plr.firing = PlayerPawn::firingPistolMax;
59   return true;
63 defaultproperties {
64   objName = 'Sceptre';
65   desc = "Sceptre";
66   desc2 = "An ancient artifact with great psychic powers."; // "powered by the tortured souls of seventy-two lawyers" wrong tone?
67   shopDesc = "A SCEPTRE";
68   setCollisionBounds(-4, -4, 4, 4);
69   cost = 80000;
71   invincible = true;
72   canPickUp = true;
73   canHitEnemies = true;
74   sellingToShopAllowed = true;
75   fixedPrice = true;
77   holdYOfs = 2;
78   depth = 101;
82 // ////////////////////////////////////////////////////////////////////////// //
83 class ItemSfxPsychicCreate['oPsychicCreateP'] : MapObject;
86 override bool initialize () {
87   if (!::initialize()) return false;
88   setSprite('sPsychicCreate');
89   return true;
93 override void onAnimationLooped () {
94   instanceRemove();
98 override void thinkFrame () {
99   setCollisionBoundsFromFrame();
100   shiftY(yVel);
101   yVel = fmin(yVel+0.6, 6);
102   if (isCollision()) {
103     instanceRemove();
104     return;
105   }
109 defaultproperties {
110   objName = 'Psychic Wave';
111   xVel = 0;
112   yVel = 0;
113   imageSpeed = 0.2;
114   spectral = true;
115   depth = 1;
119 // ////////////////////////////////////////////////////////////////////////// //
120 class ItemProjPsychicWave['oPsychicWaveP'] : MapObject;
122 float dirAngle;
125 override bool initialize () {
126   if (!::initialize()) return false;
127   setSprite('sPsychicWaveP');
128   return true;
132 override void onAnimationLooped () {
133   instanceRemove();
137 override void thinkFrame () {
138   setCollisionBoundsFromFrame();
140   if (counter > 0) {
141     --counter;
142     shiftX(xVel);
143     dirAngle = (xVel > 0 ? 0 : 180);
144   } else {
145     auto enemy = level.findNearestObject(ix, iy, delegate bool (MapObject o) {
146       if (o isa EnemyAlienBoss) return false;
147       auto dms = MonsterDamsel(o);
148       if (dms) {
149         //if (e.stunned || e.status >= STUNNED) return false;
150         if (/*dms.dead || dms.status == DEAD ||*/ !dms.active) return false;
151         return true;
152       }
153       auto enemy = MapEnemy(o);
154       if (enemy) {
155         //if (e.stunned || e.status >= STUNNED) return false;
156         if (/*enemy.dead || enemy.status == DEAD ||*/ !enemy.active) return false;
157         return true;
158       }
159       return false;
160     }, castClass:MapEnemy);
161     if (enemy) dirAngle = pointDirection(ix, iy, enemy.ix+8, enemy.iy+8);
162     shiftXY(
163       2*cos(dirAngle),
164      -2*sin(dirAngle)
165     );
166   }
168   level.isObjectInRect(x0, y0, width, height, delegate bool (MapObject o) {
169     if (o isa EnemyAlienBoss) return false;
170     if (/*o.dead ||*/ o.invincible) return false;
171     // shopkeeper
172     auto scp = MonsterShopkeeper(o);
173     if (scp && !scp.angered) scp.status = ATTACK;
174     // damsel
175     auto dms = MonsterDamsel(o);
176     if (dms) {
177       if (dms.status == DEAD) return false;
178       dms.xVel = global.randOther(0, 2)-global.randOther(1, 2);
179       dms.xVel = -1;
180       dms.yVel = -6;
181       if (dms.hp > 0) {
182         dms.hp -= damage;
183         dms.spillBlood();
184         dms.status = THROWN;
185         dms.counter = 120;
186         dms.kissCount = min(1, dms.kissCount);
187         //playSound('sndDamsel');
188       }
189       instanceRemove(); //???
190       return true;
191     }
192     // enemy
193     auto enemy = MapEnemy(o);
194     if (enemy) {
195       //if (enemy.status == DEAD) return false;
196       if (enemy.hp > 0) {
197         enemy.hp -= damage;
198         enemy.spillBlood();
199       }
200       enemy.xVel = global.randOther(0, 2)-global.randOther(1, 2);
201       enemy.xVel = -1;
202       enemy.yVel = -6;
203       return false;
204     }
205     return false;
206   });
210 defaultproperties {
211   objName = 'Psychic Wave';
212   damage = 1;
213   yVel = 0;
214   yAcc = 0.6;
215   imageSpeed = 0.25;
216   counter = 5;
217   dirAngle = 0;
218   //dir = Dir.Left;
219   depth = 1;