v2.4.0: roughly implemented two more trinkets
This commit is contained in:
@@ -1291,6 +1291,15 @@ items.stones.stoneofshock.desc=This runestone unleashes a blast of electrical en
|
||||
|
||||
|
||||
###trinkets
|
||||
items.trinkets.exoticcrystal.name=exotic crystal
|
||||
items.trinkets.exoticcrystal.desc=...\n\nAt its current level it will replace %d%% of potion or scroll drops with their exotic equivalents. This trinket does not affect potions of strength or scrolls of upgrade.
|
||||
|
||||
items.trinkets.parchmentscrap.name=parchment scrap
|
||||
items.trinkets.parchmentscrap.desc=This little scrap of parchment looks like it came from a scroll. It has regained some of its magic, and it seems to be influencing weapons and armor found in the dungeon.\n\nAt its current level it will make enchantments/glyphs _%dx_ as common, and curses on weapons and armor _%sx_ as common. Curses on wands, rings, or artifacts are not affected.
|
||||
|
||||
items.trinkets.petrifiedseed.name=petrified seed
|
||||
items.trinkets.petrifiedseed.desc=This seed has been fossilised, either by slow geological processes or by magic. The seed seems to be magically influencing the flora of the dungeon, occasionally replacing plant seeds with runestones.\n\nAt its current level it will cause trampled grass to drop runestones instead of seeds _%1$d%%_ of the time, and will also cause high grass to drop items _%2$d%%_ more often.
|
||||
|
||||
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 it 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.
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -31,6 +31,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.quest.DarkGold;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.quest.Pickaxe;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ParchmentScrap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
|
||||
@@ -466,7 +467,7 @@ public class Blacksmith extends NPC {
|
||||
|
||||
// 30% base chance to be enchanted, stored separately so status isn't revealed early
|
||||
float enchantRoll = Random.Float();
|
||||
if (enchantRoll <= 0.3f){
|
||||
if (enchantRoll <= 0.3f * ParchmentScrap.enchantChanceMultiplier()){
|
||||
smithEnchant = Weapon.Enchantment.random();
|
||||
smithGlyph = Armor.Glyph.random();
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.armor.LeatherArmor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.MailArmor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.PlateArmor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.ScaleArmor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ParchmentScrap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.journal.Notes;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.SewerLevel;
|
||||
@@ -349,7 +350,7 @@ public class Ghost extends NPC {
|
||||
|
||||
// 20% base chance to be enchanted, stored separately so status isn't revealed early
|
||||
float enchantRoll = Random.Float();
|
||||
if (enchantRoll < 0.20f){
|
||||
if (enchantRoll < 0.2f * ParchmentScrap.enchantChanceMultiplier()){
|
||||
enchant = Weapon.Enchantment.random();
|
||||
glyph = Armor.Glyph.random();
|
||||
}
|
||||
|
||||
@@ -100,6 +100,10 @@ import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfFear;
|
||||
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.ParchmentScrap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.PetrifiedSeed;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.RatSkull;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.Trinket;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlastWave;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfCorrosion;
|
||||
@@ -186,6 +190,8 @@ import java.util.LinkedHashMap;
|
||||
public class Generator {
|
||||
|
||||
public enum Category {
|
||||
TRINKET ( 0, 0, Trinket.class),
|
||||
|
||||
WEAPON ( 2, 2, MeleeWeapon.class),
|
||||
WEP_T1 ( 0, 0, MeleeWeapon.class),
|
||||
WEP_T2 ( 0, 0, MeleeWeapon.class),
|
||||
@@ -509,6 +515,16 @@ public class Generator {
|
||||
ARTIFACT.defaultProbs = new float[]{ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
ARTIFACT.probs = ARTIFACT.defaultProbs.clone();
|
||||
|
||||
//Trinkets are unique like artifacts, but unlike them you can only have one at once
|
||||
//So we don't need the same enforcement of uniqueness
|
||||
TRINKET.classes = new Class<?>[]{
|
||||
RatSkull.class,
|
||||
ParchmentScrap.class,
|
||||
PetrifiedSeed.class
|
||||
};
|
||||
TRINKET.defaultProbs = new float[]{ 1, 1, 1 };
|
||||
TRINKET.probs = TRINKET.defaultProbs.clone();
|
||||
|
||||
for (Category cat : Category.values()){
|
||||
if (cat.defaultProbs2 != null){
|
||||
cat.defaultProbsTotal = new float[cat.defaultProbs.length];
|
||||
|
||||
@@ -58,6 +58,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Swiftness;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Thorns;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Viscosity;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfArcana;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ParchmentScrap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.HeroSprite;
|
||||
@@ -545,10 +546,10 @@ public class Armor extends EquipableItem {
|
||||
//30% chance to be cursed
|
||||
//15% chance to be inscribed
|
||||
float effectRoll = Random.Float();
|
||||
if (effectRoll < 0.3f) {
|
||||
if (effectRoll < 0.3f * ParchmentScrap.curseChanceMultiplier()) {
|
||||
inscribe(Glyph.randomCurse());
|
||||
cursed = true;
|
||||
} else if (effectRoll >= 0.85f){
|
||||
} else if (effectRoll >= 1f - (0.15f * ParchmentScrap.enchantChanceMultiplier())){
|
||||
inscribe();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public class ParchmentScrap extends Trinket {
|
||||
|
||||
{
|
||||
image = ItemSpriteSheet.PARCHMENT_SCRAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int upgradeEnergyCost() {
|
||||
return 1 + level(); //TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public String desc() {
|
||||
return Messages.get(this, "desc", (int)enchantChanceMultiplier(buffedLvl()), Messages.decimalFormat("#.##", curseChanceMultiplier(buffedLvl())));
|
||||
}
|
||||
|
||||
public static float enchantChanceMultiplier(){
|
||||
return enchantChanceMultiplier(trinketLevel(ParchmentScrap.class));
|
||||
}
|
||||
|
||||
public static float enchantChanceMultiplier( int level ){
|
||||
switch (level){
|
||||
default:
|
||||
return 1;
|
||||
case 0:
|
||||
return 2;
|
||||
case 1:
|
||||
return 4;
|
||||
case 2:
|
||||
return 7;
|
||||
case 3:
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
public static float curseChanceMultiplier(){
|
||||
return curseChanceMultiplier(trinketLevel(ParchmentScrap.class));
|
||||
}
|
||||
|
||||
public static float curseChanceMultiplier( int level ){
|
||||
switch (level){
|
||||
default:
|
||||
return 1;
|
||||
case 0:
|
||||
return 1.5f;
|
||||
case 1:
|
||||
return 2f;
|
||||
case 2:
|
||||
return 1f;
|
||||
case 3:
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public class PetrifiedSeed extends Trinket {
|
||||
|
||||
{
|
||||
image = ItemSpriteSheet.PETRIFIED_SEED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int upgradeEnergyCost() {
|
||||
return 1 + level(); //TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public String desc() {
|
||||
return Messages.get(this, "desc", (int)(100*stoneInsteadOfSeedChance(buffedLvl())), (int)Math.round(100*(grassLootMultiplier(buffedLvl())-1f)));
|
||||
}
|
||||
|
||||
public static float grassLootMultiplier(){
|
||||
return grassLootMultiplier(trinketLevel(PetrifiedSeed.class));
|
||||
}
|
||||
|
||||
public static float grassLootMultiplier( int level ){
|
||||
return 1f + .4f*level/3f;
|
||||
}
|
||||
|
||||
public static float stoneInsteadOfSeedChance(){
|
||||
return stoneInsteadOfSeedChance(trinketLevel(PetrifiedSeed.class));
|
||||
}
|
||||
|
||||
public static float stoneInsteadOfSeedChance( int level ){
|
||||
if (level == -1){
|
||||
return 0f;
|
||||
} else {
|
||||
return 0.35f + .05f*level;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public class RatSkull extends Trinket {
|
||||
|
||||
@Override
|
||||
protected int upgradeEnergyCost() {
|
||||
return 5 + 10*level();
|
||||
return 1 + level(); //TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -119,7 +119,9 @@ public class TrinketCatalyst extends Item {
|
||||
ShatteredPixelDungeon.scene().addToFront(new RewardWindow(item()));
|
||||
}
|
||||
};
|
||||
btnReward.item(Generator.randomUsingDefaults());
|
||||
//TODO we need to persist these through save/load in case someone quits when the window is up
|
||||
//alternatively we could just 'peek' at the items and then actually remove them when one is awarded.
|
||||
btnReward.item(Generator.random(Generator.Category.TRINKET));
|
||||
btnReward.setRect( i*(WIDTH - BTN_GAP) / NUM_TRINKETS - BTN_SIZE, message.top() + message.height() + BTN_GAP, BTN_SIZE, BTN_SIZE );
|
||||
add( btnReward );
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.KindOfWeapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfArcana;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfForce;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfFuror;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ParchmentScrap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.curses.Annoying;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.curses.Dazzling;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.curses.Displacing;
|
||||
@@ -316,10 +317,10 @@ abstract public class Weapon extends KindOfWeapon {
|
||||
//30% chance to be cursed
|
||||
//10% chance to be enchanted
|
||||
float effectRoll = Random.Float();
|
||||
if (effectRoll < 0.3f) {
|
||||
if (effectRoll < 0.3f * ParchmentScrap.curseChanceMultiplier()) {
|
||||
enchant(Enchantment.randomCurse());
|
||||
cursed = true;
|
||||
} else if (effectRoll >= 0.9f){
|
||||
} else if (effectRoll >= 1f - (0.1f * ParchmentScrap.enchantChanceMultiplier())){
|
||||
enchant();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Camouflage;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.SandalsOfNature;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.Berry;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.PetrifiedSeed;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.MiningLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
@@ -122,8 +123,18 @@ public class HighGrass {
|
||||
|
||||
if (naturalismLevel >= 0) {
|
||||
// Seed, scales from 1/25 to 1/9
|
||||
if (Random.Int(25 - (naturalismLevel * 4)) == 0) {
|
||||
level.drop(Generator.random(Generator.Category.SEED), pos).sprite.drop();
|
||||
float lootChance = 1/(25f - naturalismLevel*4f);
|
||||
|
||||
//absolute max drop rate is ~1/6.5 with footwear of nature, ~1/18 without
|
||||
lootChance *= PetrifiedSeed.grassLootMultiplier();
|
||||
|
||||
if (Random.Float() < lootChance) {
|
||||
if (Random.Float() < PetrifiedSeed.stoneInsteadOfSeedChance()) {
|
||||
//TODO do we want to use decks here in some way?
|
||||
level.drop(Generator.randomUsingDefaults(Generator.Category.STONE), pos).sprite.drop();
|
||||
} else {
|
||||
level.drop(Generator.random(Generator.Category.SEED), pos).sprite.drop();
|
||||
}
|
||||
}
|
||||
|
||||
// Dew, scales from 1/6 to 1/4
|
||||
|
||||
@@ -470,8 +470,12 @@ public class ItemSpriteSheet {
|
||||
|
||||
private static final int TRINKETS = xy(9, 17); //24 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;
|
||||
static{
|
||||
assignItemRect(RAT_SKULL, 16, 11);
|
||||
assignItemRect(RAT_SKULL, 16, 11);
|
||||
assignItemRect(PARCHMENT_SCRAP, 10, 14);
|
||||
assignItemRect(PETRIFIED_SEED, 10, 10);
|
||||
}
|
||||
|
||||
private static final int SCROLLS = xy(1, 19); //16 slots
|
||||
|
||||
Reference in New Issue
Block a user