v3.3.0: implemented the cracked spyglass trinket (with WIP art)
This also involved repositioning some item sprites, and changing trinket crafting to show the 4th option
This commit is contained in:
@@ -1404,6 +1404,12 @@ items.trinkets.chaoticcenser.desc=After some time in the alchemy pot this incens
|
||||
items.trinkets.chaoticcenser.typical_stats_desc=Typically this trinket will spawn a harmful gas near an enemy roughly every _%d_ turns. Gasses will only appear when enemies are present. At higher levels these gases are more likely to be exotic and powerful.
|
||||
items.trinkets.chaoticcenser.stats_desc=At its current level, this trinket will spawn a harmful gas near an enemy roughly every _%d_ turns. Gasses will only appear when enemies are present. At higher levels these gases are more likely to be exotic and powerful.
|
||||
|
||||
items.trinkets.crackedspyglass.name=cracked spyglass
|
||||
items.trinkets.crackedspyglass.desc=This handheld telescope would be a demonstration of great and precise workmanship, if it weren't for the crack along its front lens. The spyglass seems to be helping you by revealing new items in the dungeon, but due to its flaw the revealed items are quite hard to see!
|
||||
items.trinkets.crackedspyglass.typical_stats_desc=Typically this trinket has a _%1$s%% chance_ to create an extra hidden item on each non-boss floor.
|
||||
items.trinkets.crackedspyglass.stats_desc=At its current level, this trinket has a _%1$s%% chance_ to create an extra hidden item on each non-boss floor.
|
||||
items.trinkets.crackedspyglass.stats_desc_upgraded=At its current level, this trinket has a _100%% chance_ to create an extra hidden item on each non-boss floor, and a _%1$s%% chance_ to create a second extra hidden item.
|
||||
|
||||
items.trinkets.dimensionalsundial.name=dimensional sundial
|
||||
items.trinkets.dimensionalsundial.warning=Your sundial isn't casting a shadow, you feel uneasy.
|
||||
items.trinkets.dimensionalsundial.desc=This small handheld sundial is somehow able to cast a shadow in the depths of the dungeon, even if you aren't holding it upright. Even more strangely, the shadow's position seems to have no relation to the sun in this world. When no shadow is cast, the sundial seems to attract danger.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
@@ -110,6 +110,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfFlock;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfShock;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ChaoticCenser;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.CrackedSpyglass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.DimensionalSundial;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ExoticCrystals;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.EyeOfNewt;
|
||||
@@ -590,9 +591,10 @@ public class Generator {
|
||||
VialOfBlood.class,
|
||||
ShardOfOblivion.class,
|
||||
ChaoticCenser.class,
|
||||
FerretTuft.class
|
||||
FerretTuft.class,
|
||||
CrackedSpyglass.class
|
||||
};
|
||||
TRINKET.defaultProbs = new float[]{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
TRINKET.defaultProbs = new float[]{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
TRINKET.probs = TRINKET.defaultProbs.clone();
|
||||
|
||||
for (Category cat : Category.values()){
|
||||
|
||||
@@ -77,6 +77,7 @@ public class Heap implements Bundlable {
|
||||
public boolean seen = false;
|
||||
public boolean haunted = false;
|
||||
public boolean autoExplored = false; //used to determine if this heap should count for exploration bonus
|
||||
public boolean hidden = false; //sets alpha to 15%
|
||||
|
||||
public LinkedList<Item> items = new LinkedList<>();
|
||||
|
||||
@@ -150,6 +151,7 @@ public class Heap implements Bundlable {
|
||||
}
|
||||
|
||||
public void drop( Item item ) {
|
||||
hidden = false;
|
||||
|
||||
if (item.stackable && type != Type.FOR_SALE) {
|
||||
|
||||
@@ -183,6 +185,7 @@ public class Heap implements Bundlable {
|
||||
}
|
||||
|
||||
public void replace( Item a, Item b ) {
|
||||
hidden = false;
|
||||
int index = items.indexOf( a );
|
||||
if (index != -1) {
|
||||
items.remove( index );
|
||||
@@ -197,6 +200,7 @@ public class Heap implements Bundlable {
|
||||
}
|
||||
|
||||
public void remove( Item a ){
|
||||
hidden = false;
|
||||
items.remove(a);
|
||||
if (items.isEmpty()){
|
||||
destroy();
|
||||
@@ -206,6 +210,7 @@ public class Heap implements Bundlable {
|
||||
}
|
||||
|
||||
public void burn() {
|
||||
hidden = false;
|
||||
|
||||
if (type != Type.HEAP) {
|
||||
return;
|
||||
@@ -257,6 +262,7 @@ public class Heap implements Bundlable {
|
||||
|
||||
//Note: should not be called to initiate an explosion, but rather by an explosion that is happening.
|
||||
public void explode() {
|
||||
hidden = false;
|
||||
|
||||
//breaks open most standard containers, mimics die.
|
||||
if (type == Type.CHEST || type == Type.SKELETON) {
|
||||
@@ -415,6 +421,7 @@ public class Heap implements Bundlable {
|
||||
private static final String ITEMS = "items";
|
||||
private static final String HAUNTED = "haunted";
|
||||
private static final String AUTO_EXPLORED = "auto_explored";
|
||||
private static final String HIDDEN = "hidden";
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@@ -440,6 +447,7 @@ public class Heap implements Bundlable {
|
||||
|
||||
haunted = bundle.getBoolean( HAUNTED );
|
||||
autoExplored = bundle.getBoolean( AUTO_EXPLORED );
|
||||
hidden = bundle.getBoolean( HIDDEN );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -450,6 +458,7 @@ public class Heap implements Bundlable {
|
||||
bundle.put( ITEMS, items );
|
||||
bundle.put( HAUNTED, haunted );
|
||||
bundle.put( AUTO_EXPLORED, autoExplored );
|
||||
bundle.put( HIDDEN, hidden );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2025 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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.items.trinkets;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
|
||||
|
||||
public class CrackedSpyglass extends Trinket{
|
||||
|
||||
{
|
||||
image = ItemSpriteSheet.SPYGLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int upgradeEnergyCost() {
|
||||
//6 -> 8(14) -> 10(24) -> 12(36)
|
||||
return 6+2*level();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String statsDesc() {
|
||||
if (isIdentified()){
|
||||
if (buffedLvl() >= 2){
|
||||
return Messages.get(this, "stats_desc_upgraded", Messages.decimalFormat("#.##", 100 * (extraLootChance(buffedLvl())-1f)));
|
||||
} else {
|
||||
return Messages.get(this, "stats_desc", Messages.decimalFormat("#.##", 100 * extraLootChance(buffedLvl())));
|
||||
}
|
||||
} else {
|
||||
return Messages.get(this, "typical_stats_desc", Messages.decimalFormat("#.##", 100 * extraLootChance(0)));
|
||||
}
|
||||
}
|
||||
|
||||
public static float extraLootChance(){
|
||||
return extraLootChance(trinketLevel(CrackedSpyglass.class));
|
||||
}
|
||||
|
||||
public static float extraLootChance(int level ){
|
||||
if (level <= -1){
|
||||
return 0;
|
||||
} else {
|
||||
return 0.4f*(level+1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -158,7 +158,7 @@ public class TrinketCatalyst extends Item {
|
||||
private static final int BTN_GAP = 4;
|
||||
private static final int GAP = 2;
|
||||
|
||||
private static final int NUM_TRINKETS = 4; //last one is a random choice
|
||||
private static final int NUM_TRINKETS = 4;
|
||||
|
||||
public WndTrinket( TrinketCatalyst cata ){
|
||||
|
||||
@@ -174,7 +174,7 @@ public class TrinketCatalyst extends Item {
|
||||
add( message );
|
||||
|
||||
//roll new trinkets if trinkets were not already rolled
|
||||
while (cata.rolledTrinkets.size() < NUM_TRINKETS-1){
|
||||
while (cata.rolledTrinkets.size() < NUM_TRINKETS){
|
||||
cata.rolledTrinkets.add((Trinket) Generator.random(Generator.Category.TRINKET));
|
||||
}
|
||||
|
||||
@@ -185,11 +185,7 @@ public class TrinketCatalyst extends Item {
|
||||
ShatteredPixelDungeon.scene().addToFront(new RewardWindow(item()));
|
||||
}
|
||||
};
|
||||
if (i == NUM_TRINKETS-1){
|
||||
btnReward.item(new RandomTrinket());
|
||||
} else {
|
||||
btnReward.item(cata.rolledTrinkets.get(i));
|
||||
}
|
||||
btnReward.item(cata.rolledTrinkets.get(i));
|
||||
btnReward.setRect( (i+1)*(WIDTH - BTN_GAP) / NUM_TRINKETS - BTN_SIZE, message.top() + message.height() + BTN_GAP, BTN_SIZE, BTN_SIZE );
|
||||
add( btnReward );
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.journal.RegionLorePage;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.CrystalKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.GoldenKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.Key;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.CrackedSpyglass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.TrinketCatalyst;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Document;
|
||||
@@ -675,6 +676,19 @@ public abstract class RegularLevel extends Level {
|
||||
}
|
||||
Random.popGenerator();
|
||||
|
||||
//extra spyglass loot
|
||||
Random.pushGenerator(Random.Long());
|
||||
int items = (int)(Random.Float() + CrackedSpyglass.extraLootChance());
|
||||
for (int i = 0; i < items; i++){
|
||||
int cell = randomDropCell();
|
||||
if (map[cell] == Terrain.HIGH_GRASS || map[cell] == Terrain.FURROWED_GRASS) {
|
||||
map[cell] = Terrain.GRASS;
|
||||
losBlocking[cell] = false;
|
||||
}
|
||||
drop( Generator.randomUsingDefaults(), cell).hidden = true;
|
||||
}
|
||||
Random.popGenerator();
|
||||
|
||||
}
|
||||
|
||||
private static HashMap<Document, Dungeon.LimitedDrops> limitedDocs = new HashMap<>();
|
||||
|
||||
@@ -213,25 +213,31 @@ public class ItemSprite extends MovieClip {
|
||||
if (heap.size() <= 0 || heap.items == null){
|
||||
return view( 0, null );
|
||||
}
|
||||
|
||||
|
||||
switch (heap.type) {
|
||||
case HEAP: case FOR_SALE:
|
||||
return view( heap.peek() );
|
||||
view( heap.peek() ); break;
|
||||
case CHEST:
|
||||
return view( ItemSpriteSheet.CHEST, null );
|
||||
view( ItemSpriteSheet.CHEST, null ); break;
|
||||
case LOCKED_CHEST:
|
||||
return view( ItemSpriteSheet.LOCKED_CHEST, null );
|
||||
view( ItemSpriteSheet.LOCKED_CHEST, null ); break;
|
||||
case CRYSTAL_CHEST:
|
||||
return view( ItemSpriteSheet.CRYSTAL_CHEST, null );
|
||||
view( ItemSpriteSheet.CRYSTAL_CHEST, null ); break;
|
||||
case TOMB:
|
||||
return view( ItemSpriteSheet.TOMB, null );
|
||||
view( ItemSpriteSheet.TOMB, null ); break;
|
||||
case SKELETON:
|
||||
return view( ItemSpriteSheet.BONES, null );
|
||||
view( ItemSpriteSheet.BONES, null ); break;
|
||||
case REMAINS:
|
||||
return view( ItemSpriteSheet.REMAINS, null );
|
||||
view( ItemSpriteSheet.REMAINS, null ); break;
|
||||
default:
|
||||
return view( 0, null );
|
||||
view( 0, null );
|
||||
}
|
||||
|
||||
if (heap.hidden){
|
||||
alpha(0.15f);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemSprite view( int image, Glowing glowing ) {
|
||||
|
||||
@@ -434,7 +434,7 @@ public class ItemSpriteSheet {
|
||||
assignItemRect(i, 8, 10);
|
||||
}
|
||||
|
||||
private static final int ARTIFACTS = xy(1, 16); //24 slots
|
||||
private static final int ARTIFACTS = xy(1, 16); //32 slots
|
||||
public static final int ARTIFACT_CLOAK = ARTIFACTS+0;
|
||||
public static final int ARTIFACT_ARMBAND = ARTIFACTS+1;
|
||||
public static final int ARTIFACT_CAPE = ARTIFACTS+2;
|
||||
@@ -486,7 +486,7 @@ public class ItemSpriteSheet {
|
||||
assignItemRect(ARTIFACT_TOME, 14, 16);
|
||||
}
|
||||
|
||||
private static final int TRINKETS = xy(9, 17); //24 slots
|
||||
private static final int TRINKETS = xy(1, 18); //32 slots
|
||||
public static final int RAT_SKULL = TRINKETS+0;
|
||||
public static final int PARCHMENT_SCRAP = TRINKETS+1;
|
||||
public static final int PETRIFIED_SEED = TRINKETS+2;
|
||||
@@ -503,6 +503,7 @@ public class ItemSpriteSheet {
|
||||
public static final int OBLIVION_SHARD = TRINKETS+13;
|
||||
public static final int CHAOTIC_CENSER = TRINKETS+14;
|
||||
public static final int FERRET_TUFT = TRINKETS+15;
|
||||
public static final int SPYGLASS = TRINKETS+16;
|
||||
static{
|
||||
assignItemRect(RAT_SKULL, 16, 11);
|
||||
assignItemRect(PARCHMENT_SCRAP, 10, 14);
|
||||
@@ -520,9 +521,10 @@ public class ItemSpriteSheet {
|
||||
assignItemRect(OBLIVION_SHARD, 7, 14);
|
||||
assignItemRect(CHAOTIC_CENSER, 13, 15);
|
||||
assignItemRect(FERRET_TUFT, 16, 15);
|
||||
assignItemRect(SPYGLASS, 15, 15);
|
||||
}
|
||||
|
||||
private static final int SCROLLS = xy(1, 19); //16 slots
|
||||
private static final int SCROLLS = xy(1, 20); //16 slots
|
||||
public static final int SCROLL_KAUNAN = SCROLLS+0;
|
||||
public static final int SCROLL_SOWILO = SCROLLS+1;
|
||||
public static final int SCROLL_LAGUZ = SCROLLS+2;
|
||||
@@ -543,7 +545,7 @@ public class ItemSpriteSheet {
|
||||
assignItemRect(ARCANE_RESIN , 12, 11);
|
||||
}
|
||||
|
||||
private static final int EXOTIC_SCROLLS = xy(1, 20); //16 slots
|
||||
private static final int EXOTIC_SCROLLS = xy(1, 21); //16 slots
|
||||
public static final int EXOTIC_KAUNAN = EXOTIC_SCROLLS+0;
|
||||
public static final int EXOTIC_SOWILO = EXOTIC_SCROLLS+1;
|
||||
public static final int EXOTIC_LAGUZ = EXOTIC_SCROLLS+2;
|
||||
@@ -561,7 +563,7 @@ public class ItemSpriteSheet {
|
||||
assignItemRect(i, 15, 14);
|
||||
}
|
||||
|
||||
private static final int STONES = xy(1, 21); //16 slots
|
||||
private static final int STONES = xy(1, 22); //16 slots
|
||||
public static final int STONE_AGGRESSION = STONES+0;
|
||||
public static final int STONE_AUGMENTATION = STONES+1;
|
||||
public static final int STONE_FEAR = STONES+2;
|
||||
@@ -579,7 +581,7 @@ public class ItemSpriteSheet {
|
||||
assignItemRect(i, 14, 12);
|
||||
}
|
||||
|
||||
private static final int POTIONS = xy(1, 22); //16 slots
|
||||
private static final int POTIONS = xy(1, 23); //16 slots
|
||||
public static final int POTION_CRIMSON = POTIONS+0;
|
||||
public static final int POTION_AMBER = POTIONS+1;
|
||||
public static final int POTION_GOLDEN = POTIONS+2;
|
||||
@@ -600,7 +602,7 @@ public class ItemSpriteSheet {
|
||||
assignItemRect(LIQUID_METAL, 8, 15);
|
||||
}
|
||||
|
||||
private static final int EXOTIC_POTIONS = xy(1, 23); //16 slots
|
||||
private static final int EXOTIC_POTIONS = xy(1, 24); //16 slots
|
||||
public static final int EXOTIC_CRIMSON = EXOTIC_POTIONS+0;
|
||||
public static final int EXOTIC_AMBER = EXOTIC_POTIONS+1;
|
||||
public static final int EXOTIC_GOLDEN = EXOTIC_POTIONS+2;
|
||||
@@ -618,7 +620,7 @@ public class ItemSpriteSheet {
|
||||
assignItemRect(i, 12, 13);
|
||||
}
|
||||
|
||||
private static final int SEEDS = xy(1, 24); //16 slots
|
||||
private static final int SEEDS = xy(1, 25); //16 slots
|
||||
public static final int SEED_ROTBERRY = SEEDS+0;
|
||||
public static final int SEED_FIREBLOOM = SEEDS+1;
|
||||
public static final int SEED_SWIFTTHISTLE = SEEDS+2;
|
||||
@@ -636,7 +638,7 @@ public class ItemSpriteSheet {
|
||||
assignItemRect(i, 10, 10);
|
||||
}
|
||||
|
||||
private static final int BREWS = xy(1, 25); //8 slots
|
||||
private static final int BREWS = xy(1, 26); //8 slots
|
||||
public static final int BREW_INFERNAL = BREWS+0;
|
||||
public static final int BREW_BLIZZARD = BREWS+1;
|
||||
public static final int BREW_SHOCKING = BREWS+2;
|
||||
@@ -644,7 +646,7 @@ public class ItemSpriteSheet {
|
||||
public static final int BREW_AQUA = BREWS+4;
|
||||
public static final int BREW_UNSTABLE = BREWS+5;
|
||||
|
||||
private static final int ELIXIRS = xy(9, 25); //8 slots
|
||||
private static final int ELIXIRS = xy(9, 26); //8 slots
|
||||
public static final int ELIXIR_HONEY = ELIXIRS+0;
|
||||
public static final int ELIXIR_AQUA = ELIXIRS+1;
|
||||
public static final int ELIXIR_MIGHT = ELIXIRS+2;
|
||||
@@ -660,8 +662,6 @@ public class ItemSpriteSheet {
|
||||
assignItemRect(BREW_AQUA, 9, 11);
|
||||
}
|
||||
|
||||
//16 free slots
|
||||
|
||||
private static final int SPELLS = xy(1, 27); //16 slots
|
||||
public static final int WILD_ENERGY = SPELLS+0;
|
||||
public static final int PHASE_SHIFT = SPELLS+1;
|
||||
|
||||
Reference in New Issue
Block a user