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 PlayerWeapon : MapObject;
23 bool hitEnemy; // mattock: prevent breaking solids when attacking enemies
24 bool blockedBySolids = true; // to whip and mattock won't kill enemies thru walls
25 bool slashing; // machete can slash bodies and some whip-immune enemies
26 bool prestrike; // for 'pre' weapons
27 bool ignoreWhipTimer; // should this weapon ignore object's `whipTimer`?
28 bool dontChangeWhipTimer; // should this weapon leave object's `whipTimer` alone?
35 bool collidesWithObject (MapObject o) {
36 //if (o && o.collidesWith(self)) writeln("weapon collides with '", GetClassName(o.Class), "' (", o.objType, "'");
37 return (o && o.collidesWith(self));
41 override void thinkFrame () {
42 if (alarmCounter > 0) {
43 if (--alarmCounter == 0) {
44 if (heldBy) heldBy.holdItem = none;
53 // Check for an item to nudge
54 // called by oWhip/oSlash/oMattockHit
55 final void scrCheckNudge () {
57 foreach (MapObject it; level.objGrid.inRectPix(ix, iy, 17, 17, level.objGrid.nextTag(), precise: true)) {
58 if (it !isa MapItem) continue;
59 it.nudgeIt(level.player.ix, level.player.iy);
62 foreach (MapObject it; level.objGrid.inRectPix(ix-32, iy-32, 32, 32, precise: false)) {
63 if (it !isa MapItem) continue;
64 if (!collidesWithObject(it)) continue;
65 if (!it.active || it.spectral || !it.canBeNudged) continue;
66 it.nudgeIt(level.player.ix, level.player.iy);
72 void onCollisionWithObject (MapObject o) {
73 if (o isa ItemWeb) o.onTouchedByPlayerWeapon(level.player, self);
81 activeWhenHeld = true;
82 spectralWhenHeld = false;
87 // ////////////////////////////////////////////////////////////////////////// //
88 class ItemMeleeWeaponBase : MapItem;
90 float newImageSpeed = 0.2;
93 // return `true` to stop player from throwing it
94 override bool onTryUseItem (PlayerPawn plr) {
96 if (plr.scrPlayerIsDucking()) {
97 if (!plr.whipping) plr.scrUsePutItemOnGround();
101 if (plr.pickedItem) return true;
103 if (!plr.whipping /*&& plr.platformCharacterIs(ON_GROUND)*/) {
107 auto sc = MonsterShopkeeper(level.findNearestObject(ix, iy, delegate bool (MapObject o) {
108 auto sc = MonsterShopkeeper(o);
109 if (!sc) return false;
110 //if (needCraps && sc.stype != 'Craps') return false;
111 if (sc.dead || sc.angered || sc.outlaw) return false;
115 level.scrShopkeeperAnger(GameLevel::SCAnger.ItemStolen);
117 plr.imageSpeed = newImageSpeed;
118 if (global.isTunnelMan) plr.setSprite('sTunnelAttackL');
119 else if (global.isDamsel) plr.setSprite('sDamselAttackL');
120 else plr.setSprite('sAttackLeft');
124 plr.scrHideItemToPocket(); // temporarily
132 canHitEnemies = true;
134 breaksOnCollision = false;
137 sellingToShopAllowed = true;