diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties
index 224246631..53c517e01 100644
--- a/core/src/main/assets/messages/items/items.properties
+++ b/core/src/main/assets/messages/items/items.properties
@@ -337,6 +337,10 @@ items.artifacts.etherealchains.desc_cursed=The cursed chains are locked to your
items.artifacts.etherealchains.desc_equipped=The chains rest around your side, slowly siphoning the spiritual energy of those you defeat. Each charge is a link in the chain, which will extend out exactly one tile.
items.artifacts.etherealchains$chainsrecharge.levelup=Your chains grow stronger!
+items.artifacts.holytome.name=holy tome
+items.artifacts.holytome.ac_cast=CAST
+items.artifacts.holytome.desc=TODO
+
items.artifacts.hornofplenty.name=horn of plenty
items.artifacts.hornofplenty.ac_snack=SNACK
items.artifacts.hornofplenty.ac_eat=EAT
@@ -1741,6 +1745,13 @@ items.weapon.melee.crossbow.upgrade_ability_stat_name=Ability Boost
items.weapon.melee.crossbow$chargedshot.name=charged
items.weapon.melee.crossbow$chargedshot.desc=The Duelist is focusing power into her crossbow. The next attack she makes with it will always hit and apply one of three effects:\n- Melee attacks will knock enemies a few tiles away.\n- Untipped darts will deal bonus damage.\n- Tipped darts will gain extra uses and apply their effect in a 7x7 area. Positive dart effects will only affect allies, and harmful effects will only apply to enemies. The Duelist cannot use this ability to apply positive dart effects to herself.
+items.weapon.melee.cudgel.name=cudgel
+items.weapon.melee.cudgel.stats_desc=This is a rather accurate weapon.
+items.weapon.melee.cudgel.ability_name=heavy blow
+items.weapon.melee.cudgel.typical_ability_desc=The Duelist can perform a _heavy blow_ with a cudgel. This concentrated attack typically deals _%1$d-%2$d damage_ if it surprised the enemy, and dazes them for 5 turns which reduces accuracy and evasion by 50%%. Heavy blow always hits but deals regular damage if it does not surprise the enemy.
+items.weapon.melee.cudgel.ability_desc=The Duelist can perform a _heavy blow_ with a cudgel. This concentrated attack deals _%1$d-%2$d damage_ if it surprised the enemy, and dazes them for 5 turns which reduces accuracy and evasion by 50%%. Heavy blow always hits but deals regular damage if it does not surprise the enemy.
+items.weapon.melee.cudgel.desc=A small brass mace, made more as a self-defense tool for nobles than as an adventuring weapon.
+
items.weapon.melee.dagger.name=dagger
items.weapon.melee.dagger.stats_desc=This weapon is stronger against unaware enemies.
items.weapon.melee.dagger.ability_name=sneak
diff --git a/core/src/main/assets/sprites/items.png b/core/src/main/assets/sprites/items.png
index 2c3e45186..ca8ff9d2b 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/actors/hero/HeroClass.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java
index 332932b1e..f56017397 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/HeroClass.java
@@ -48,6 +48,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.Waterskin;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClothArmor;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CloakOfShadows;
+import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HolyTome;
import com.shatteredpixel.shatteredpixeldungeon.items.bags.VelvetPouch;
import com.shatteredpixel.shatteredpixeldungeon.items.food.Food;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing;
@@ -65,6 +66,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRemoveCurs
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow;
+import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Cudgel;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dagger;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Gloves;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
@@ -241,11 +243,14 @@ public enum HeroClass {
private static void initCleric( Hero hero ) {
- //TODO Cudgel
- (hero.belongings.weapon = new Dagger()).identify();
+ (hero.belongings.weapon = new Cudgel()).identify();
hero.belongings.weapon.activate(hero);
- //TODO Spellbook
+ HolyTome tome = new HolyTome();
+ (hero.belongings.artifact = tome).identify();
+ hero.belongings.artifact.activate( hero );
+
+ Dungeon.quickslot.setSlot(0, tome);
new PotionOfPurity().identify();
new ScrollOfRemoveCurse().identify();
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java
index 4e3c5909d..949329a2c 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java
@@ -39,6 +39,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.ChaliceOfBlood;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CloakOfShadows;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.EtherealChains;
+import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HolyTome;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.HornOfPlenty;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.MasterThievesArmband;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.SandalsOfNature;
@@ -141,6 +142,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.AssassinsBlade;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.BattleAxe;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Crossbow;
+import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Cudgel;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dagger;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dirk;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Flail;
@@ -414,9 +416,10 @@ public class Generator {
MagesStaff.class,
Dagger.class,
Gloves.class,
- Rapier.class
+ Rapier.class,
+ Cudgel.class,
};
- WEP_T1.defaultProbs = new float[]{ 2, 0, 2, 2, 2 };
+ WEP_T1.defaultProbs = new float[]{ 2, 0, 2, 2, 2, 2 };
WEP_T1.probs = WEP_T1.defaultProbs.clone();
WEP_T2.classes = new Class>[]{
@@ -555,6 +558,7 @@ public class Generator {
CloakOfShadows.class,
DriedRose.class,
EtherealChains.class,
+ HolyTome.class,
HornOfPlenty.class,
MasterThievesArmband.class,
SandalsOfNature.class,
@@ -562,7 +566,7 @@ public class Generator {
TimekeepersHourglass.class,
UnstableSpellbook.class
};
- ARTIFACT.defaultProbs = new float[]{ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 };
+ ARTIFACT.defaultProbs = new float[]{ 1, 1, 0, 1, 1, 0, 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
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/HolyTome.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/HolyTome.java
new file mode 100644
index 000000000..bffdea276
--- /dev/null
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/HolyTome.java
@@ -0,0 +1,81 @@
+/*
+ * 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
+ */
+
+package com.shatteredpixel.shatteredpixeldungeon.items.artifacts;
+
+import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MagicImmune;
+import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
+import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
+
+import java.util.ArrayList;
+
+public class HolyTome extends Artifact {
+
+ {
+ image = ItemSpriteSheet.ARTIFACT_TOME;
+
+ exp = 0;
+ levelCap = 10;
+
+ charge = Math.min(level()+3, 10);
+ partialCharge = 0;
+ chargeCap = Math.min(level()+3, 10);
+
+ defaultAction = AC_CAST;
+
+ unique = true;
+ bones = false;
+ }
+
+ public static final String AC_CAST = "CAST";
+
+ @Override
+ public ArrayList actions( Hero hero ) {
+ ArrayList actions = super.actions( hero );
+ if (isEquipped( hero )
+ && !cursed
+ && hero.buff(MagicImmune.class) == null
+ && charge > 0) {
+ actions.add(AC_CAST);
+ }
+ return actions;
+ }
+
+ //levelling:
+ //starts with 3 charges at +0, reaches 10 charges at +7. +8,9,10 slightly increases charge speed
+ //levels up based on use, probably with a very similar target level system to the Cloak
+
+ //how does the UI for actually using it work though?
+
+ @Override
+ protected ArtifactBuff passiveBuff() {
+ return new tomeRecharge();
+ }
+
+ public class tomeRecharge extends ArtifactBuff{
+
+ public void gainCharge(float levelPortion) {
+ //TODO
+ }
+
+ }
+
+}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Cudgel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Cudgel.java
new file mode 100644
index 000000000..801fa7551
--- /dev/null
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Cudgel.java
@@ -0,0 +1,75 @@
+/*
+ * 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
+ */
+
+package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee;
+
+import com.shatteredpixel.shatteredpixeldungeon.Assets;
+import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
+import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
+import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
+
+public class Cudgel extends MeleeWeapon {
+
+ {
+ image = ItemSpriteSheet.CUDGEL;
+ hitSound = Assets.Sounds.HIT_CRUSH;
+ hitSoundPitch = 1.2f;
+
+ tier = 1;
+ ACC = 1.40f; //40% boost to accuracy
+
+ bones = false;
+ }
+
+ @Override
+ public int max(int lvl) {
+ return 4*(tier+1) + //8 base, down from 10
+ lvl*(tier+1); //scaling unchanged
+ }
+
+ @Override
+ public String targetingPrompt() {
+ return Messages.get(this, "prompt");
+ }
+
+ @Override
+ protected void duelistAbility(Hero hero, Integer target) {
+ //+(3+1.5*lvl) damage, roughly +67% base dmg, +100% scaling
+ int dmgBoost = augment.damageFactor(3 + Math.round(1.5f*buffedLvl()));
+ Mace.heavyBlowAbility(hero, target, 1, dmgBoost, this);
+ }
+
+ @Override
+ public String abilityInfo() {
+ int dmgBoost = levelKnown ? 3 + Math.round(1.5f*buffedLvl()) : 3;
+ if (levelKnown){
+ return Messages.get(this, "ability_desc", augment.damageFactor(min()+dmgBoost), augment.damageFactor(max()+dmgBoost));
+ } else {
+ return Messages.get(this, "typical_ability_desc", min(0)+dmgBoost, max(0)+dmgBoost);
+ }
+ }
+
+ public String upgradeAbilityStat(int level){
+ int dmgBoost = 3 + Math.round(1.5f*level);
+ return augment.damageFactor(min(level)+dmgBoost) + "-" + augment.damageFactor(max(level)+dmgBoost);
+ }
+
+}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Mace.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Mace.java
index 08564ba8e..e9aaf72b9 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Mace.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/melee/Mace.java
@@ -61,7 +61,7 @@ public class Mace extends MeleeWeapon {
@Override
protected void duelistAbility(Hero hero, Integer target) {
- //+(4+1.5*lvl) damage, roughly +55% base dmg, +60% scaling
+ //+(5+1.5*lvl) damage, roughly +55% base dmg, +60% scaling
int dmgBoost = augment.damageFactor(5 + Math.round(1.5f*buffedLvl()));
Mace.heavyBlowAbility(hero, target, 1, dmgBoost, this);
}
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 6273ea587..ebb776d54 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java
@@ -213,13 +213,14 @@ public class ItemSpriteSheet {
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;
+ public static final int CUDGEL = WEP_TIER1+1; //TODO CLERIC better sprite
public static final int GLOVES = WEP_TIER1+2;
public static final int RAPIER = WEP_TIER1+3;
public static final int DAGGER = WEP_TIER1+4;
public static final int MAGES_STAFF = WEP_TIER1+5;
static{
assignItemRect(WORN_SHORTSWORD, 13, 13);
+ assignItemRect(CUDGEL, 16, 16);
assignItemRect(GLOVES, 12, 16);
assignItemRect(RAPIER, 13, 14);
assignItemRect(DAGGER, 12, 13);
@@ -449,6 +450,7 @@ public class ItemSpriteSheet {
public static final int ARTIFACT_ROSE1 = ARTIFACTS+20;
public static final int ARTIFACT_ROSE2 = ARTIFACTS+21;
public static final int ARTIFACT_ROSE3 = ARTIFACTS+22;
+ public static final int ARTIFACT_TOME = ARTIFACTS+23; //TODO CLERIC finalize sprite
static{
assignItemRect(ARTIFACT_CLOAK, 9, 15);
assignItemRect(ARTIFACT_ARMBAND, 16, 13);
@@ -473,6 +475,7 @@ public class ItemSpriteSheet {
assignItemRect(ARTIFACT_ROSE1, 14, 14);
assignItemRect(ARTIFACT_ROSE2, 14, 14);
assignItemRect(ARTIFACT_ROSE3, 14, 14);
+ assignItemRect(ARTIFACT_TOME, 14, 16);
}
private static final int TRINKETS = xy(9, 17); //24 slots
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java
index 2e41e49be..4e43accb8 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/Icons.java
@@ -460,8 +460,8 @@ public enum Icons {
return new ItemSprite(ItemSpriteSheet.SPIRIT_BOW);
case DUELIST:
return new ItemSprite(ItemSpriteSheet.RAPIER);
- case CLERIC: //TODO CLERIC class sprite
- return new ItemSprite(ItemSpriteSheet.MASTERY);
+ case CLERIC:
+ return new ItemSprite(ItemSpriteSheet.ARTIFACT_TOME);
default:
return null;
}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java
index afe7097e4..ce90e58ac 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/windows/WndHeroInfo.java
@@ -73,8 +73,8 @@ public class WndHeroInfo extends WndTabbed {
case DUELIST:
tabIcon = new ItemSprite(ItemSpriteSheet.RAPIER, null);
break;
- case CLERIC: //TODO CLERIC
- tabIcon = new ItemSprite(ItemSpriteSheet.MASTERY, null);
+ case CLERIC:
+ tabIcon = new ItemSprite(ItemSpriteSheet.ARTIFACT_TOME, null);
break;
}
@@ -201,10 +201,10 @@ public class WndHeroInfo extends WndTabbed {
new ItemSprite(ItemSpriteSheet.THROWING_SPIKE),
new ItemSprite(ItemSpriteSheet.SCROLL_ISAZ)};
break;
- case CLERIC: //TODO CLERIC
- icons = new Image[]{ new ItemSprite(ItemSpriteSheet.MASTERY),
+ case CLERIC:
+ icons = new Image[]{ new ItemSprite(ItemSpriteSheet.ARTIFACT_TOME),
Icons.TALENT.get(),
- new ItemSprite(ItemSpriteSheet.MACE),
+ new ItemSprite(ItemSpriteSheet.CUDGEL),
new ItemSprite(ItemSpriteSheet.SCROLL_ISAZ)};
break;
}
@@ -228,6 +228,7 @@ public class WndHeroInfo extends WndTabbed {
icons[i].x = (20-icons[i].width())/2;
icons[i].y = info[i].top() + (info[i].height() - icons[i].height())/2;
+ PixelScene.align(icons[i]);
pos = info[i].bottom() + 4*MARGIN;
}