v2.4.0: added two more trinkets

This commit is contained in:
Evan Debenham
2024-04-04 17:13:06 -04:00
parent 36d40650e3
commit 28e1c18694
9 changed files with 207 additions and 7 deletions

View File

@@ -121,7 +121,7 @@ public class Random {
//returns an inverse triangularly distributed int in the range [min, max]
//this makes results more likely as they get further from the middle of the range
public static int InvNormalIntRange( int min, int max){
public static int InvNormalIntRange( int min, int max ){
float roll1 = Float(), roll2 = Float();
if (Math.abs(roll1-0.5f) >= Math.abs(roll2-0.5f)){
return min + (int)(roll1*(max - min + 1));

View File

@@ -1294,6 +1294,10 @@ items.stones.stoneofshock.desc=This runestone unleashes a blast of electrical en
###trinkets
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.\n\nAt its current level, this trinket will increase the spawning rate of enemies by _%d%%_ when it is nighttime in real life (9pm to 7am).
items.trinkets.exoticcrystals.name=exotic crystals
items.trinkets.exoticcrystals.desc=These small pink crystals have the same shape as crystals of alchemical energy. While they can't be used for energy directly, they seem to be somehow influencing the potions and scrolls you find.\n\nAt its current level this trinket will replace %d%% of potion or scroll drops with their exotic equivalents. This does not affect potions of strength, scrolls of upgrade, or items that are generated to help solve hazard rooms.
@@ -1309,9 +1313,11 @@ items.trinkets.petrifiedseed.desc=This seed has been fossilised, either by slow
items.trinkets.ratskull.name=rat skull
items.trinkets.ratskull.desc=This macabre trinket isn't much larger than the skull of a normal rat, which is somehow a rarity down in this dungeon. The skull's magical influence seems to attract the more rare denizens of the dungeon, making them appear far more often.\n\nAt its current level this trinket will make rare exotic enemies _%dx_ as likely to appear. The skull is only half as effective at attracting crystal mimics and armored statues, however.
items.trinkets.dimensionalsundial.name=dimensional sundial
items.trinkets.dimensionalsundial.warning=Your sundial isn't casting a shadow, you feel uneasy.
items.trinkets.dimensionalsundial.desc=Despite being underground, this sundial is still casting a shadow according to the sun's position. 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.\n\nAt its current level, this trinket will increase the spawning rate of enemies by _%d%%_ when it is nighttime in real life (9pm to 7am).
items.trinkets.thirteenleafclover.name=thirteen leaf clover
items.trinkets.thirteenleafclover.desc=Somehow stewing in the alchemy pot has caused this clover to grow a bunch of extra leaves! It's not really clear if this trinket is lucky or unlucky, perhaps this trinket will make your luck more chaotic?\n\nNormally when dealing or blocking damage, the game makes numbers closer to the average more common. At its current level this trinket has a _%d%%_ chance to invert this, making numbers closer to the maximum or minimum more likely to appear instead.
items.trinkets.trapmechanism.name=trap mechanism
items.trinkets.trapmechanism.desc=The core mechanism of one of the dungeon's pitfall traps, carefully carved out of the floor so it can be carried. It seems to be magically tied to the dungeon itself, making terrain more hazardous for you and the dungeon's inhabitants.\n\nAt its current level this trinket will make _%d%%_ of regular floors become filled with either traps or chasms instead.
items.trinkets.trinketcatalyst.name=trinket catalyst
items.trinkets.trinketcatalyst.window_text=The water begins to glow as you use the catalyst. There are a few nearby items you could imbue with magical energy.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -100,6 +100,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRetributio
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfChallenge;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfPsionicBlast;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ThirteenLeafClover;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlastWave;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFireblast;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFrost;
@@ -593,7 +594,11 @@ public abstract class Char extends Actor {
//used for damage and blocking calculations, normally just calls NormalIntRange
// but may be affected by things that specifically impact combat number ranges
public static int combatRoll(int min, int max ){
return Random.NormalIntRange( min, max );
if (Random.Float() < ThirteenLeafClover.combatDistributionInverseChance()){
return ThirteenLeafClover.invCombatRoll(min, max);
} else {
return Random.NormalIntRange(min, max);
}
}
public int attackSkill( Char target ) {

View File

@@ -108,6 +108,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MossyClump;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ParchmentScrap;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.PetrifiedSeed;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.RatSkull;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ThirteenLeafClover;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.TrapMechanism;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.Trinket;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlastWave;
@@ -528,9 +530,11 @@ public class Generator {
PetrifiedSeed.class,
ExoticCrystals.class,
MossyClump.class,
DimensionalSundial.class
DimensionalSundial.class,
ThirteenLeafClover.class,
TrapMechanism.class
};
TRINKET.defaultProbs = new float[]{ 1, 1, 1, 1, 1, 1 };
TRINKET.defaultProbs = new float[]{ 1, 1, 1, 1, 1, 1, 1, 1 };
TRINKET.probs = TRINKET.defaultProbs.clone();
for (Category cat : Category.values()){

View File

@@ -0,0 +1,60 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2024 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;
import com.watabou.utils.Random;
public class ThirteenLeafClover extends Trinket {
{
image = ItemSpriteSheet.CLOVER;
}
@Override
protected int upgradeEnergyCost() {
return 1+level(); //TODO
}
@Override
public String desc() {
return Messages.get(this, "desc", (int)(100*combatDistributionInverseChance(buffedLvl())));
}
public static float combatDistributionInverseChance(){
return combatDistributionInverseChance(trinketLevel(ThirteenLeafClover.class));
}
public static float combatDistributionInverseChance( int level ){
if (level <= -1){
return 0;
} else {
return 0.25f + 0.25f*level;
}
}
public static int invCombatRoll( int min, int max){
return Random.InvNormalIntRange( min, max );
}
}

View File

@@ -0,0 +1,117 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2024 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.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
import java.util.ArrayList;
public class TrapMechanism extends Trinket {
{
image = ItemSpriteSheet.TRAP_MECHANISM;
}
@Override
protected int upgradeEnergyCost() {
return 1+level(); //TODO
}
@Override
public String desc() {
return Messages.get(this, "desc", (int)(100*overrideNormalLevelChance(buffedLvl())));
}
public static float overrideNormalLevelChance(){
return overrideNormalLevelChance(trinketLevel(TrapMechanism.class));
}
public static float overrideNormalLevelChance( int level ){
if (level == -1){
return 0f;
} else {
return 0.25f + 0.25f*level;
}
}
//true for traps, false for chasm
//ensures a little consistency of RNG
private ArrayList<Boolean> levelFeels = new ArrayList<>();
private int shuffles = 0;
public static Level.Feeling getNextFeeling(){
TrapMechanism mech = Dungeon.hero.belongings.getItem(TrapMechanism.class);
if (mech == null) {
return Level.Feeling.NONE;
}
if (mech.levelFeels.isEmpty()){
Random.pushGenerator(Dungeon.seed+1);
mech.levelFeels.add(true);
mech.levelFeels.add(true);
mech.levelFeels.add(true);
mech.levelFeels.add(false);
mech.levelFeels.add(false);
mech.levelFeels.add(false);
for (int i = 0; i <= mech.shuffles; i++) {
Random.shuffle(mech.levelFeels);
}
mech.shuffles++;
Random.popGenerator();
}
return mech.levelFeels.remove(0) ? Level.Feeling.TRAPS : Level.Feeling.CHASM;
}
private static final String FEELS = "feels";
private static final String SHUFFLES = "shuffles";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
if (!levelFeels.isEmpty()){
boolean[] storeFeels = new boolean[levelFeels.size()];
for (int i = 0; i < storeFeels.length; i++){
storeFeels[i] = levelFeels.get(i);
}
bundle.put(FEELS, storeFeels);
}
bundle.put( SHUFFLES, shuffles );
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
levelFeels.clear();
if (bundle.contains(FEELS)){
for (boolean b : bundle.getBooleanArray(FEELS)){
levelFeels.add(b);
}
}
shuffles = bundle.getInt( SHUFFLES );
}
}

View File

@@ -69,6 +69,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment;
import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MossyClump;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.DimensionalSundial;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.TrapMechanism;
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.TrinketCatalyst;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding;
@@ -262,8 +263,11 @@ public abstract class Level implements Bundlable {
feeling = Feeling.SECRETS;
break;
default:
//if-else statements are fine here as only one chance can be above 0 at a time
if (Random.Float() < MossyClump.overrideNormalLevelChance()){
feeling = MossyClump.getNextFeeling();
} else if (Random.Float() < TrapMechanism.overrideNormalLevelChance()) {
feeling = TrapMechanism.getNextFeeling();
} else {
feeling = Feeling.NONE;
}

View File

@@ -475,6 +475,8 @@ public class ItemSpriteSheet {
public static final int EXOTIC_CRYSTALS = TRINKETS+3;
public static final int MOSSY_CLUMP = TRINKETS+4;
public static final int SUNDIAL = TRINKETS+5;
public static final int CLOVER = TRINKETS+6;
public static final int TRAP_MECHANISM = TRINKETS+7;
static{
assignItemRect(RAT_SKULL, 16, 11);
assignItemRect(PARCHMENT_SCRAP, 10, 14);
@@ -482,6 +484,8 @@ public class ItemSpriteSheet {
assignItemRect(EXOTIC_CRYSTALS, 14, 13);
assignItemRect(MOSSY_CLUMP, 12, 11);
assignItemRect(SUNDIAL, 16, 12);
assignItemRect(CLOVER, 11, 15);
assignItemRect(TRAP_MECHANISM, 13, 15);
}
private static final int SCROLLS = xy(1, 19); //16 slots