v3.0.0: bare implementation for cleric starter items

This commit is contained in:
Evan Debenham
2024-10-12 11:57:15 -04:00
parent f183e3219f
commit 5e67be46da
10 changed files with 195 additions and 15 deletions

View File

@@ -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.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.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.name=horn of plenty
items.artifacts.hornofplenty.ac_snack=SNACK items.artifacts.hornofplenty.ac_snack=SNACK
items.artifacts.hornofplenty.ac_eat=EAT 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.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.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.name=dagger
items.weapon.melee.dagger.stats_desc=This weapon is stronger against unaware enemies. items.weapon.melee.dagger.stats_desc=This weapon is stronger against unaware enemies.
items.weapon.melee.dagger.ability_name=sneak items.weapon.melee.dagger.ability_name=sneak

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -48,6 +48,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.Waterskin; import com.shatteredpixel.shatteredpixeldungeon.items.Waterskin;
import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClothArmor; import com.shatteredpixel.shatteredpixeldungeon.items.armor.ClothArmor;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CloakOfShadows; 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.bags.VelvetPouch;
import com.shatteredpixel.shatteredpixeldungeon.items.food.Food; import com.shatteredpixel.shatteredpixeldungeon.items.food.Food;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing; 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.scrolls.ScrollOfUpgrade;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.SpiritBow; 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.Dagger;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Gloves; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Gloves;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
@@ -241,11 +243,14 @@ public enum HeroClass {
private static void initCleric( Hero hero ) { private static void initCleric( Hero hero ) {
//TODO Cudgel (hero.belongings.weapon = new Cudgel()).identify();
(hero.belongings.weapon = new Dagger()).identify();
hero.belongings.weapon.activate(hero); 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 PotionOfPurity().identify();
new ScrollOfRemoveCurse().identify(); new ScrollOfRemoveCurse().identify();

View File

@@ -39,6 +39,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.ChaliceOfBlood;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CloakOfShadows; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.CloakOfShadows;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.EtherealChains; 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.HornOfPlenty;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.MasterThievesArmband; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.MasterThievesArmband;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.SandalsOfNature; 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.AssassinsBlade;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.BattleAxe; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.BattleAxe;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Crossbow; 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.Dagger;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dirk; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dirk;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Flail; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Flail;
@@ -414,9 +416,10 @@ public class Generator {
MagesStaff.class, MagesStaff.class,
Dagger.class, Dagger.class,
Gloves.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_T1.probs = WEP_T1.defaultProbs.clone();
WEP_T2.classes = new Class<?>[]{ WEP_T2.classes = new Class<?>[]{
@@ -555,6 +558,7 @@ public class Generator {
CloakOfShadows.class, CloakOfShadows.class,
DriedRose.class, DriedRose.class,
EtherealChains.class, EtherealChains.class,
HolyTome.class,
HornOfPlenty.class, HornOfPlenty.class,
MasterThievesArmband.class, MasterThievesArmband.class,
SandalsOfNature.class, SandalsOfNature.class,
@@ -562,7 +566,7 @@ public class Generator {
TimekeepersHourglass.class, TimekeepersHourglass.class,
UnstableSpellbook.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(); ARTIFACT.probs = ARTIFACT.defaultProbs.clone();
//Trinkets are unique like artifacts, but unlike them you can only have one at once //Trinkets are unique like artifacts, but unlike them you can only have one at once

View File

@@ -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 <http://www.gnu.org/licenses/>
*/
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<String> actions( Hero hero ) {
ArrayList<String> 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
}
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>
*/
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);
}
}

View File

@@ -61,7 +61,7 @@ public class Mace extends MeleeWeapon {
@Override @Override
protected void duelistAbility(Hero hero, Integer target) { 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())); int dmgBoost = augment.damageFactor(5 + Math.round(1.5f*buffedLvl()));
Mace.heavyBlowAbility(hero, target, 1, dmgBoost, this); Mace.heavyBlowAbility(hero, target, 1, dmgBoost, this);
} }

View File

@@ -213,13 +213,14 @@ public class ItemSpriteSheet {
private static final int WEP_TIER1 = xy(1, 7); //8 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 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 GLOVES = WEP_TIER1+2;
public static final int RAPIER = WEP_TIER1+3; public static final int RAPIER = WEP_TIER1+3;
public static final int DAGGER = WEP_TIER1+4; public static final int DAGGER = WEP_TIER1+4;
public static final int MAGES_STAFF = WEP_TIER1+5; public static final int MAGES_STAFF = WEP_TIER1+5;
static{ static{
assignItemRect(WORN_SHORTSWORD, 13, 13); assignItemRect(WORN_SHORTSWORD, 13, 13);
assignItemRect(CUDGEL, 16, 16);
assignItemRect(GLOVES, 12, 16); assignItemRect(GLOVES, 12, 16);
assignItemRect(RAPIER, 13, 14); assignItemRect(RAPIER, 13, 14);
assignItemRect(DAGGER, 12, 13); assignItemRect(DAGGER, 12, 13);
@@ -449,6 +450,7 @@ public class ItemSpriteSheet {
public static final int ARTIFACT_ROSE1 = ARTIFACTS+20; public static final int ARTIFACT_ROSE1 = ARTIFACTS+20;
public static final int ARTIFACT_ROSE2 = ARTIFACTS+21; public static final int ARTIFACT_ROSE2 = ARTIFACTS+21;
public static final int ARTIFACT_ROSE3 = ARTIFACTS+22; public static final int ARTIFACT_ROSE3 = ARTIFACTS+22;
public static final int ARTIFACT_TOME = ARTIFACTS+23; //TODO CLERIC finalize sprite
static{ static{
assignItemRect(ARTIFACT_CLOAK, 9, 15); assignItemRect(ARTIFACT_CLOAK, 9, 15);
assignItemRect(ARTIFACT_ARMBAND, 16, 13); assignItemRect(ARTIFACT_ARMBAND, 16, 13);
@@ -473,6 +475,7 @@ public class ItemSpriteSheet {
assignItemRect(ARTIFACT_ROSE1, 14, 14); assignItemRect(ARTIFACT_ROSE1, 14, 14);
assignItemRect(ARTIFACT_ROSE2, 14, 14); assignItemRect(ARTIFACT_ROSE2, 14, 14);
assignItemRect(ARTIFACT_ROSE3, 14, 14); assignItemRect(ARTIFACT_ROSE3, 14, 14);
assignItemRect(ARTIFACT_TOME, 14, 16);
} }
private static final int TRINKETS = xy(9, 17); //24 slots private static final int TRINKETS = xy(9, 17); //24 slots

View File

@@ -460,8 +460,8 @@ public enum Icons {
return new ItemSprite(ItemSpriteSheet.SPIRIT_BOW); return new ItemSprite(ItemSpriteSheet.SPIRIT_BOW);
case DUELIST: case DUELIST:
return new ItemSprite(ItemSpriteSheet.RAPIER); return new ItemSprite(ItemSpriteSheet.RAPIER);
case CLERIC: //TODO CLERIC class sprite case CLERIC:
return new ItemSprite(ItemSpriteSheet.MASTERY); return new ItemSprite(ItemSpriteSheet.ARTIFACT_TOME);
default: default:
return null; return null;
} }

View File

@@ -73,8 +73,8 @@ public class WndHeroInfo extends WndTabbed {
case DUELIST: case DUELIST:
tabIcon = new ItemSprite(ItemSpriteSheet.RAPIER, null); tabIcon = new ItemSprite(ItemSpriteSheet.RAPIER, null);
break; break;
case CLERIC: //TODO CLERIC case CLERIC:
tabIcon = new ItemSprite(ItemSpriteSheet.MASTERY, null); tabIcon = new ItemSprite(ItemSpriteSheet.ARTIFACT_TOME, null);
break; break;
} }
@@ -201,10 +201,10 @@ public class WndHeroInfo extends WndTabbed {
new ItemSprite(ItemSpriteSheet.THROWING_SPIKE), new ItemSprite(ItemSpriteSheet.THROWING_SPIKE),
new ItemSprite(ItemSpriteSheet.SCROLL_ISAZ)}; new ItemSprite(ItemSpriteSheet.SCROLL_ISAZ)};
break; break;
case CLERIC: //TODO CLERIC case CLERIC:
icons = new Image[]{ new ItemSprite(ItemSpriteSheet.MASTERY), icons = new Image[]{ new ItemSprite(ItemSpriteSheet.ARTIFACT_TOME),
Icons.TALENT.get(), Icons.TALENT.get(),
new ItemSprite(ItemSpriteSheet.MACE), new ItemSprite(ItemSpriteSheet.CUDGEL),
new ItemSprite(ItemSpriteSheet.SCROLL_ISAZ)}; new ItemSprite(ItemSpriteSheet.SCROLL_ISAZ)};
break; break;
} }
@@ -228,6 +228,7 @@ public class WndHeroInfo extends WndTabbed {
icons[i].x = (20-icons[i].width())/2; icons[i].x = (20-icons[i].width())/2;
icons[i].y = info[i].top() + (info[i].height() - icons[i].height())/2; icons[i].y = info[i].top() + (info[i].height() - icons[i].height())/2;
PixelScene.align(icons[i]);
pos = info[i].bottom() + 4*MARGIN; pos = info[i].bottom() + 4*MARGIN;
} }