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 ItemWeaponSceptre['oSceptre'] : MapItem;
21 override bool initialize () {
22 if (!::initialize()) return false;
23 setSprite('sSceptreLeft', 'sSceptreRight');
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) {
37 if (plr.scrPlayerIsDucking()) {
38 plr.scrUsePutItemOnGround();
42 if (plr.firing || plr.scrPlayerIsDucking()) return true;
44 int xsgn = (plr.dir == Dir.Left ? -1 : 1);
48 auto obj = level.MakeMapObject(ix+xofs, iy+4, 'oPsychicCreateP');
50 obj.xVel = xsgn*global.randOther(1, 3);
51 obj.yVel = -global.randOtherFloat(2);
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;
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);
74 sellingToShopAllowed = true;
82 // ////////////////////////////////////////////////////////////////////////// //
83 class ItemSfxPsychicCreate['oPsychicCreateP'] : MapObject;
86 override bool initialize () {
87 if (!::initialize()) return false;
88 setSprite('sPsychicCreate');
93 override void onAnimationLooped () {
98 override void thinkFrame () {
99 setCollisionBoundsFromFrame();
101 yVel = fmin(yVel+0.6, 6);
110 objName = 'Psychic Wave';
119 // ////////////////////////////////////////////////////////////////////////// //
120 class ItemProjPsychicWave['oPsychicWaveP'] : MapObject;
125 override bool initialize () {
126 if (!::initialize()) return false;
127 setSprite('sPsychicWaveP');
132 override void onAnimationLooped () {
137 override void thinkFrame () {
138 setCollisionBoundsFromFrame();
143 dirAngle = (xVel > 0 ? 0 : 180);
145 auto enemy = level.findNearestObject(ix, iy, delegate bool (MapObject o) {
146 if (o isa EnemyAlienBoss) return false;
147 auto dms = MonsterDamsel(o);
149 //if (e.stunned || e.status >= STUNNED) return false;
150 if (/*dms.dead || dms.status == DEAD ||*/ !dms.active) return false;
153 auto enemy = MapEnemy(o);
155 //if (e.stunned || e.status >= STUNNED) return false;
156 if (/*enemy.dead || enemy.status == DEAD ||*/ !enemy.active) return false;
160 }, castClass:MapEnemy);
161 if (enemy) dirAngle = pointDirection(ix, iy, enemy.ix+8, enemy.iy+8);
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;
172 auto scp = MonsterShopkeeper(o);
173 if (scp && !scp.angered) scp.status = ATTACK;
175 auto dms = MonsterDamsel(o);
177 if (dms.status == DEAD) return false;
178 dms.xVel = global.randOther(0, 2)-global.randOther(1, 2);
186 dms.kissCount = min(1, dms.kissCount);
187 //playSound('sndDamsel');
189 instanceRemove(); //???
193 auto enemy = MapEnemy(o);
195 //if (enemy.status == DEAD) return false;
200 enemy.xVel = global.randOther(0, 2)-global.randOther(1, 2);
211 objName = 'Psychic Wave';