diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties index 983feb4f8..f992ae6d6 100644 --- a/core/src/main/assets/messages/items/items.properties +++ b/core/src/main/assets/messages/items/items.properties @@ -858,6 +858,21 @@ items.quest.ratskull.desc=A surprisingly large rat skull. It would make a great +###remains +items.remains.remainsitem.ac_use=USE +items.remains.bowfragment.name=bow fragment +items.remains.bowfragment.desc=This broken fragment of wood was once part of a lost huntress' spirit bow. You can still feel a little nature energy left in the fragment, you can use the fragment to grow some high grass around you. Doing this will destroy the fragment however. +items.remains.brokenhilt.name=broken hilt +items.remains.brokenhilt.desc=This broken hilt looks like it came from a defeated Duelist's weapon. You can still feel a little martial power left in the hilt, you can use it to get a little bonus damage on your next two melee attacks. Doing this will destroy the hilt however. +items.remains.brokenstaff.name=broken staff +items.remains.brokenstaff.desc=This Mage's staff has been broken in half after its owner met their demise. You can still feel some magical energy left in the staff, you can use it to give your wands a little boost. Doing this will destroy the staff however. +items.remains.cloakscrap.name=scrap of fabric +items.remains.cloakscrap.desc=This scrap of translucent fabric looks like it came from a late Rogue's cloak of shadows. You can still feel a little mystical energy left in it, you can use it to give your artifacts a little boost. Doing this will destroy the fabric however +items.remains.sealshard.name=seal shard +items.remains.sealshard.desc=This tiny shard of red wax looks like it came from the seal of a fallen Warrior. You can still feel a bit of willpower clinging to the seal, you can use it to give yourself a bit of shielding. Doing this will destroy the seal shard however. + + + ###rings items.rings.ring.diamond=diamond ring items.rings.ring.opal=opal ring diff --git a/core/src/main/assets/sprites/items.png b/core/src/main/assets/sprites/items.png index 40de034d6..2a763756f 100644 Binary files a/core/src/main/assets/sprites/items.png and b/core/src/main/assets/sprites/items.png differ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Bones.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Bones.java index 7f2406b58..db563edc1 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Bones.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Bones.java @@ -22,10 +22,12 @@ package com.shatteredpixel.shatteredpixeldungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Gold; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.Artifact; +import com.shatteredpixel.shatteredpixeldungeon.items.remains.RemainsItem; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon; import com.watabou.utils.Bundle; import com.watabou.utils.FileUtils; @@ -43,11 +45,14 @@ public class Bones { private static final String LEVEL = "level"; private static final String BRANCH = "branch"; private static final String ITEM = "item"; + private static final String HERO_CLASS = "hero_class"; private static int depth = -1; private static int branch = -1; + private static Item item; - + private static HeroClass heroClass; + public static void leave() { //remains will usually drop on the floor the hero died on @@ -67,6 +72,7 @@ public class Bones { Bundle bundle = new Bundle(); bundle.put( LEVEL, depth ); bundle.put( ITEM, item ); + bundle.put( HERO_CLASS, heroClass ); try { FileUtils.bundleToFile( BONES_FILE, bundle ); @@ -78,14 +84,10 @@ public class Bones { private static Item pickItem(Hero hero){ Item item = null; - //seeded runs always leave gold + //seeded runs don't leave items //This is to prevent using specific seeds to transport items to regular runs if (!Dungeon.customSeedText.isEmpty()){ - if (Dungeon.gold > 100) { - return new Gold( Random.NormalIntRange( 50, Dungeon.gold/2 ) ); - } else { - return new Gold( 50 ); - } + return null; } if (Random.Int(3) != 0) { @@ -125,28 +127,29 @@ public class Bones { ArrayList items = new ArrayList<>(); while (iterator.hasNext()){ curItem = iterator.next(); - if (curItem.bones) + if (curItem.bones) { items.add(curItem); + } } + //if there are few items, there is an increasingly high chance of leaving nothing if (Random.Int(3) < items.size()) { item = Random.element(items); if (item.stackable){ item.quantity(Random.NormalIntRange(1, (item.quantity() + 1) / 2)); + if (item.quantity() > 3){ + item.quantity(3); + } } } else { - if (Dungeon.gold > 100) { - item = new Gold( Random.NormalIntRange( 50, Dungeon.gold/2 ) ); - } else { - item = new Gold( 50 ); - } + item = null; } } return item; } - public static Item get() { + public static ArrayList get() { //daily runs do not interact with remains if (Dungeon.daily){ return null; @@ -160,7 +163,16 @@ public class Bones { depth = bundle.getInt( LEVEL ); branch = bundle.getInt( BRANCH ); if (depth > 0) { - item = (Item) bundle.get(ITEM); + if (bundle.contains(ITEM)) { + item = (Item) bundle.get(ITEM); + } else { + item = null; + } + if (bundle.contains(HERO_CLASS)){ + heroClass = bundle.getEnum(HERO_CLASS, HeroClass.class); + } else { + heroClass = null; + } } return get(); @@ -181,13 +193,9 @@ public class Bones { } depth = 0; - //challenged or seeded runs will always find 10 gold + //challenged or seeded runs don't get items from prior runs if (Dungeon.challenges != 0 || !Dungeon.customSeedText.isEmpty()){ - item = new Gold(10); - } - - if (item == null) { - item = new Gold(50); + item = null; } //Enforces artifact uniqueness @@ -197,37 +205,47 @@ public class Bones { //generates a new artifact of the same type, always +0 Artifact artifact = Reflection.newInstance(((Artifact)item).getClass()); - if (artifact == null){ - return new Gold(item.value()); + if (artifact != null){ + artifact.cursed = true; + artifact.cursedKnown = true; } - artifact.cursed = true; - artifact.cursedKnown = true; - - return artifact; + item = artifact; } else { - return new Gold(item.value()); + item = new Gold(item.value()); } } - - if (item.isUpgradable() && !(item instanceof MissileWeapon)) { - item.cursed = true; - item.cursedKnown = true; - } - - if (item.isUpgradable()) { - //caps at +3 - if (item.level() > 3) { - item.degrade( item.level() - 3 ); + + if (item != null) { + if (item.isUpgradable() && !(item instanceof MissileWeapon)) { + item.cursed = true; + item.cursedKnown = true; } - //thrown weapons are always IDed, otherwise set unknown - item.levelKnown = item instanceof MissileWeapon; + + if (item.isUpgradable()) { + //caps at +3 + if (item.level() > 3) { + item.degrade(item.level() - 3); + } + //thrown weapons are always IDed, otherwise set unknown + item.levelKnown = item instanceof MissileWeapon; + } + + item.reset(); } - - item.reset(); - - return item; + + ArrayList result = new ArrayList<>(); + + if (heroClass != null) { + result.add(RemainsItem.get(heroClass)); + } + + if (item != null) { + result.add(item); + } + + return result.isEmpty() ? null : result; } else { return null; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/BowFragment.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/BowFragment.java new file mode 100644 index 000000000..b21ca9618 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/BowFragment.java @@ -0,0 +1,78 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2023 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.items.remains; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; +import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle; +import com.shatteredpixel.shatteredpixeldungeon.levels.Level; +import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; +import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +public class BowFragment extends RemainsItem { + + { + image = ItemSpriteSheet.BOW_FRAGMENT; + } + + @Override + protected void doEffect(Hero hero) { + ArrayList grassCells = new ArrayList<>(); + for (int i : PathFinder.NEIGHBOURS9){ + grassCells.add(hero.pos+i); + } + Random.shuffle(grassCells); + for (int grassCell : grassCells){ + if (Dungeon.level.map[grassCell] == Terrain.EMPTY || + Dungeon.level.map[grassCell] == Terrain.EMBERS || + Dungeon.level.map[grassCell] == Terrain.EMPTY_DECO){ + Level.set(grassCell, Terrain.GRASS); + GameScene.updateMap(grassCell); + } + CellEmitter.get(grassCell).burst(LeafParticle.LEVEL_SPECIFIC, 4); + } + // 5 cells total + int totalGrassCells = 5; + while (grassCells.size() > totalGrassCells){ + grassCells.remove(0); + } + for (int grassCell : grassCells){ + int t = Dungeon.level.map[grassCell]; + if ((t == Terrain.EMPTY || t == Terrain.EMPTY_DECO || t == Terrain.EMBERS + || t == Terrain.GRASS || t == Terrain.FURROWED_GRASS) + && Dungeon.level.plants.get(grassCell) == null){ + Level.set(grassCell, Terrain.HIGH_GRASS); + GameScene.updateMap(grassCell); + } + } + Dungeon.observe(); + Sample.INSTANCE.play(Assets.Sounds.PLANT); + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/BrokenHilt.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/BrokenHilt.java new file mode 100644 index 000000000..af74495de --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/BrokenHilt.java @@ -0,0 +1,42 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2023 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.items.remains; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.PhysicalEmpower; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class BrokenHilt extends RemainsItem { + + { + image = ItemSpriteSheet.BROKEN_HILT; + } + + @Override + protected void doEffect(Hero hero) { + Buff.affect( hero, PhysicalEmpower.class).set(Math.max(2, hero.lvl/3), 2); + Sample.INSTANCE.play(Assets.Sounds.UNLOCK); + } +} \ No newline at end of file diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/BrokenStaff.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/BrokenStaff.java new file mode 100644 index 000000000..ab3c708c3 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/BrokenStaff.java @@ -0,0 +1,43 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2023 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.items.remains; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRecharging; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class BrokenStaff extends RemainsItem { + + { + image = ItemSpriteSheet.BROKEN_STAFF; + } + + @Override + protected void doEffect(Hero hero) { + hero.belongings.charge(1f); + ScrollOfRecharging.charge(hero); + Sample.INSTANCE.play( Assets.Sounds.CHARGEUP ); + } + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/CloakScrap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/CloakScrap.java new file mode 100644 index 000000000..364d40875 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/CloakScrap.java @@ -0,0 +1,48 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2023 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.items.remains; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.Artifact; +import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRecharging; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class CloakScrap extends RemainsItem { + + { + image = ItemSpriteSheet.CLOAK_SCRAP; + } + + @Override + protected void doEffect(Hero hero) { + for (Buff b : hero.buffs()){ + if (b instanceof Artifact.ArtifactBuff){ + if (!((Artifact.ArtifactBuff) b).isCursed()) ((Artifact.ArtifactBuff) b).charge(hero, 4); + } + } + ScrollOfRecharging.charge(hero); + Sample.INSTANCE.play( Assets.Sounds.CHARGEUP ); + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/RemainsItem.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/RemainsItem.java new file mode 100644 index 000000000..4962c38ec --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/RemainsItem.java @@ -0,0 +1,89 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2023 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.items.remains; + +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; +import com.shatteredpixel.shatteredpixeldungeon.items.Item; + +import java.util.ArrayList; + +public abstract class RemainsItem extends Item { + + { + bones = false; + + defaultAction = AC_USE; + } + + public static final String AC_USE = "USE"; + + @Override + public ArrayList actions(Hero hero) { + ArrayList actions = super.actions(hero); + actions.add(AC_USE); + return actions; + } + + @Override + public void execute(Hero hero, String action) { + super.execute(hero, action); + + if (action.equals(AC_USE)){ + hero.sprite.operate(hero.pos); + + doEffect(hero); + + hero.spendAndNext(Actor.TICK); + detach(hero.belongings.backpack); + } + } + + protected abstract void doEffect(Hero hero); + + @Override + public boolean isIdentified() { + return true; + } + + @Override + public int value() { + return 50; + } + + public static RemainsItem get(HeroClass cls){ + switch (cls){ + case WARRIOR: default: + return new SealShard(); + case MAGE: + return new BrokenStaff(); + case ROGUE: + return new CloakScrap(); + case HUNTRESS: + return new BowFragment(); + case DUELIST: + return new BrokenHilt(); + } + } + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/SealShard.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/SealShard.java new file mode 100644 index 000000000..782d9d1ca --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/remains/SealShard.java @@ -0,0 +1,43 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2023 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.items.remains; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barrier; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; +import com.watabou.noosa.audio.Sample; + +public class SealShard extends RemainsItem { + + { + image = ItemSpriteSheet.SEAL_SHARD; + } + + @Override + protected void doEffect(Hero hero) { + Buff.affect(hero, Barrier.class).incShield(hero.HT/10); + Sample.INSTANCE.play(Assets.Sounds.UNLOCK); + } + +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java index aaea586a5..905c5548e 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java @@ -212,14 +212,18 @@ public class CavesBossLevel extends Level { @Override protected void createItems() { - Item item = Bones.get(); - if (item != null) { - int pos; - do { - pos = randomRespawnCell(null); - } while (pos == entrance()); - drop( item, pos ).setHauntedIfCursed().type = Heap.Type.REMAINS; - } + Random.pushGenerator(Random.Long()); + ArrayList bonesItems = Bones.get(); + if (bonesItems != null) { + int pos; + do { + pos = randomRespawnCell(null); + } while (pos == entrance()); + for (Item i : bonesItems) { + drop(i, pos).setHauntedIfCursed().type = Heap.Type.REMAINS; + } + } + Random.popGenerator(); } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java index 957fde74a..ffa6f779b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java @@ -260,14 +260,18 @@ public class CityBossLevel extends Level { @Override protected void createItems() { - Item item = Bones.get(); - if (item != null) { - int pos; - do { - pos = randomRespawnCell(null); - } while (pos == entrance()); - drop( item, pos ).setHauntedIfCursed().type = Heap.Type.REMAINS; - } + Random.pushGenerator(Random.Long()); + ArrayList bonesItems = Bones.get(); + if (bonesItems != null) { + int pos; + do { + pos = randomRespawnCell(null); + } while (pos == entrance()); + for (Item i : bonesItems) { + drop(i, pos).setHauntedIfCursed().type = Heap.Type.REMAINS; + } + } + Random.popGenerator(); } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/DeadEndLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/DeadEndLevel.java index e2befe488..ce43fb274 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/DeadEndLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/DeadEndLevel.java @@ -30,6 +30,9 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.levels.features.LevelTransition; +import com.watabou.utils.Random; + +import java.util.ArrayList; public class DeadEndLevel extends Level { @@ -102,10 +105,14 @@ public class DeadEndLevel extends Level { @Override protected void createItems() { - Item item = Bones.get(); - if (item != null) { - drop( item, entrance()-width() ).setHauntedIfCursed().type = Heap.Type.REMAINS; - } + Random.pushGenerator(Random.Long()); + ArrayList bonesItems = Bones.get(); + if (bonesItems != null) { + for (Item i : bonesItems) { + drop(i, entrance()-width()).setHauntedIfCursed().type = Heap.Type.REMAINS; + } + } + Random.popGenerator(); } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java index 461f54e24..b74a9d7fa 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java @@ -198,14 +198,18 @@ public class HallsBossLevel extends Level { @Override protected void createItems() { - Item item = Bones.get(); - if (item != null) { - int pos; - do { - pos = randomRespawnCell(null); - } while (pos == entrance()); - drop( item, pos ).setHauntedIfCursed().type = Heap.Type.REMAINS; - } + Random.pushGenerator(Random.Long()); + ArrayList bonesItems = Bones.get(); + if (bonesItems != null) { + int pos; + do { + pos = randomRespawnCell(null); + } while (pos == entrance()); + for (Item i : bonesItems) { + drop(i, pos).setHauntedIfCursed().type = Heap.Type.REMAINS; + } + } + Random.popGenerator(); } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java index bcd0f8ede..045d082a5 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java @@ -118,14 +118,18 @@ public class LastShopLevel extends RegularLevel { @Override protected void createItems() { - Item item = Bones.get(); - if (item != null) { - int pos; - do { - pos = pointToCell(roomEntrance.random()); - } while (pos == entrance()); - drop( item, pos ).setHauntedIfCursed().type = Heap.Type.REMAINS; - } + Random.pushGenerator(Random.Long()); + ArrayList bonesItems = Bones.get(); + if (bonesItems != null) { + int pos; + do { + pos = pointToCell(roomEntrance.random()); + } while (pos == entrance()); + for (Item i : bonesItems) { + drop(i, pos).setHauntedIfCursed().type = Heap.Type.REMAINS; + } + } + Random.popGenerator(); } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/MiningLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/MiningLevel.java index 3af258cf2..5b67886e0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/MiningLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/MiningLevel.java @@ -164,15 +164,19 @@ public class MiningLevel extends CavesLevel { @Override protected void createItems() { - Item item = Bones.get(); - if (item != null) { - int cell = randomDropCell(); - if (map[cell] == Terrain.HIGH_GRASS || map[cell] == Terrain.FURROWED_GRASS) { - map[cell] = Terrain.GRASS; - losBlocking[cell] = false; + Random.pushGenerator(Random.Long()); + ArrayList bonesItems = Bones.get(); + if (bonesItems != null) { + int cell = randomDropCell(); + if (map[cell] == Terrain.HIGH_GRASS || map[cell] == Terrain.FURROWED_GRASS) { + map[cell] = Terrain.GRASS; + losBlocking[cell] = false; + } + for (Item i : bonesItems) { + drop(i, cell).setHauntedIfCursed().type = Heap.Type.REMAINS; + } } - drop( item, cell ).setHauntedIfCursed().type = Heap.Type.REMAINS; - } + Random.popGenerator(); int cell = randomDropCell(); if (map[cell] == Terrain.HIGH_GRASS || map[cell] == Terrain.FURROWED_GRASS) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java index 3e6f6712f..1b8c5a73b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java @@ -565,10 +565,19 @@ public class PrisonBossLevel extends Level { @Override protected void createItems() { - Item item = Bones.get(); - if (item != null) { - drop( item, randomRespawnCell( null ) ).setHauntedIfCursed().type = Heap.Type.REMAINS; - } + Random.pushGenerator(Random.Long()); + ArrayList bonesItems = Bones.get(); + if (bonesItems != null) { + int pos; + do { + pos = randomRespawnCell(null); + } while (pos == entrance()); + for (Item i : bonesItems) { + drop(i, pos).setHauntedIfCursed().type = Heap.Type.REMAINS; + } + } + Random.popGenerator(); + drop(new IronKey(10), randomPrisonCellPos()); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java index b919fae24..992377d6d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java @@ -437,14 +437,16 @@ public abstract class RegularLevel extends Level { Random.popGenerator(); Random.pushGenerator( Random.Long() ); - Item item = Bones.get(); - if (item != null) { + ArrayList bonesItems = Bones.get(); + if (bonesItems != null) { int cell = randomDropCell(); if (map[cell] == Terrain.HIGH_GRASS || map[cell] == Terrain.FURROWED_GRASS) { map[cell] = Terrain.GRASS; losBlocking[cell] = false; } - drop( item, cell ).setHauntedIfCursed().type = Heap.Type.REMAINS; + for (Item i : bonesItems) { + drop(i, cell).setHauntedIfCursed().type = Heap.Type.REMAINS; + } } Random.popGenerator(); @@ -457,7 +459,7 @@ public abstract class RegularLevel extends Level { for (int i=1; i <= petalsNeeded; i++) { //the player may miss a single petal and still max their rose. if (rose.droppedPetals < 11) { - item = new DriedRose.Petal(); + Item item = new DriedRose.Petal(); int cell = randomDropCell(); drop( item, cell ).type = Heap.Type.HEAP; if (map[cell] == Terrain.HIGH_GRASS || map[cell] == Terrain.FURROWED_GRASS) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java index 32fb02eff..c380660cd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java @@ -139,14 +139,18 @@ public class SewerBossLevel extends SewerLevel { @Override protected void createItems() { - Item item = Bones.get(); - if (item != null) { - int pos; - do { - pos = pointToCell(roomEntrance.random()); - } while (pos == entrance() || solid[pos]); - drop( item, pos ).setHauntedIfCursed().type = Heap.Type.REMAINS; - } + Random.pushGenerator(Random.Long()); + ArrayList bonesItems = Bones.get(); + if (bonesItems != null) { + int pos; + do { + pos = pointToCell(roomEntrance.random()); + } while (pos == entrance() || solid[pos]); + for (Item i : bonesItems) { + drop(i, pos).setHauntedIfCursed().type = Heap.Type.REMAINS; + } + } + Random.popGenerator(); } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java index 375214df7..e1ea96d0c 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java @@ -125,7 +125,7 @@ public class ItemSpriteSheet { assignItemRect(EBONY_CHEST, 16, 14); } - private static final int MISC_CONSUMABLE = xy(1, 4); //16 slots + private static final int MISC_CONSUMABLE = xy(1, 4); //32 slots public static final int ANKH = MISC_CONSUMABLE +0; public static final int STYLUS = MISC_CONSUMABLE +1; public static final int SEAL = MISC_CONSUMABLE +2; @@ -142,6 +142,12 @@ public class ItemSpriteSheet { public static final int AMULET = MISC_CONSUMABLE +13; public static final int MASTERY = MISC_CONSUMABLE +14; public static final int KIT = MISC_CONSUMABLE +15; + public static final int SEAL_SHARD = MISC_CONSUMABLE +16; + public static final int BROKEN_STAFF = MISC_CONSUMABLE +17; + public static final int CLOAK_SCRAP = MISC_CONSUMABLE +18; + public static final int BOW_FRAGMENT = MISC_CONSUMABLE +19; + public static final int BROKEN_HILT = MISC_CONSUMABLE +20; + static{ assignItemRect(ANKH, 10, 16); assignItemRect(STYLUS, 12, 13); @@ -161,9 +167,16 @@ public class ItemSpriteSheet { assignItemRect(AMULET, 16, 16); assignItemRect(MASTERY, 13, 16); assignItemRect(KIT, 16, 15); + + //TODO improve these placeholder images + assignItemRect(SEAL_SHARD, 6, 9); + assignItemRect(BROKEN_STAFF, 15, 11); + assignItemRect(CLOAK_SCRAP, 5, 9); + assignItemRect(BOW_FRAGMENT, 12, 7); + assignItemRect(BROKEN_HILT, 6, 7); } - private static final int BOMBS = xy(1, 5); //16 slots + private static final int BOMBS = xy(1, 6); //16 slots public static final int BOMB = BOMBS+0; public static final int DBL_BOMB = BOMBS+1; public static final int FIRE_BOMB = BOMBS+2; @@ -192,9 +205,6 @@ public class ItemSpriteSheet { assignItemRect(SHRAPNEL_BOMB, 10, 13); } - - //16 free slots - private static final int WEP_TIER1 = xy(1, 7); //8 slots public static final int WORN_SHORTSWORD = WEP_TIER1+0; public static final int CUDGEL = WEP_TIER1+1;