v3.1.0: implemented score penalties for quests

This commit is contained in:
Evan Debenham
2025-03-31 16:40:20 -04:00
parent b43b470329
commit 7909952ab6
15 changed files with 117 additions and 12 deletions

View File

@@ -180,6 +180,7 @@ public enum Rankings {
Statistics.heldItemValue += i.value();
if (i instanceof CorpseDust && Statistics.deepestFloor >= 10){
// in case player kept the corpse dust, for a necromancer run
//we also override the score here, ignoring penalties
Statistics.questScores[1] = 2000;
}
}

View File

@@ -22,10 +22,13 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.blobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.FetidRat;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
@@ -39,12 +42,24 @@ public class StenchGas extends Blob {
Char ch;
int cell;
boolean fetidRatSpawned = false;
for (Mob m : Dungeon.level.mobs){
if (m instanceof FetidRat){
fetidRatSpawned = true;
break;
}
}
for (int i = area.left; i < area.right; i++){
for (int j = area.top; j < area.bottom; j++){
cell = i + j*Dungeon.level.width();
if (cur[cell] > 0 && (ch = Actor.findChar( cell )) != null) {
if (!ch.isImmune(this.getClass()))
Buff.prolong( ch, Paralysis.class, Paralysis.DURATION/5 );
if (!ch.isImmune(this.getClass())) {
if (ch == Dungeon.hero && ch.buff(Paralysis.class) == null && fetidRatSpawned){
Statistics.questScores[0] -= 100;
}
Buff.prolong(ch, Paralysis.class, Paralysis.DURATION / 5);
}
}
}
}

View File

@@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
@@ -115,6 +116,23 @@ public class CrystalGuardian extends Mob{
return true;
}
@Override
public int attackProc(Char enemy, int damage) {
//if enemy is hero, and they aren't currently fighting the spire, -100 points
if (enemy == Dungeon.hero){
boolean spireNear = false;
for (Mob m : Dungeon.level.mobs.toArray(new Mob[0])){
if (m instanceof CrystalSpire && m.HP != m.HT && Dungeon.level.distance(pos, m.pos) <= 8){
spireNear = true;
}
}
if (!spireNear){
Statistics.questScores[2] -= 100;
}
}
return super.attackProc(enemy, damage);
}
@Override
public int defenseProc(Char enemy, int damage) {
if (recovering){

View File

@@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
@@ -129,6 +130,8 @@ public class CrystalSpire extends Mob {
if (ch instanceof CrystalGuardian) {
dmg += 12; //18-27 damage
Buff.prolong(ch, Cripple.class, 30f);
} else if (ch == Dungeon.hero){
Statistics.questScores[2] -= 100;
}
ch.damage(dmg, new SpireSpike());
@@ -303,7 +306,7 @@ public class CrystalSpire extends Mob {
return false; //immune to all buffs and debuffs
}
int hits = 0;
private int hits = 0;
@Override
public boolean interact(Char c) {

View File

@@ -368,6 +368,9 @@ public abstract class Elemental extends Mob {
Char target = Actor.findChar(targetingPos + i);
if (target != null && target != this) {
Buff.affect(target, Burning.class).reignite(target);
if (target == Dungeon.hero){
Statistics.questScores[1] -= 200;
}
}
}
}
@@ -409,7 +412,8 @@ public abstract class Elemental extends Mob {
super.die(cause);
if (alignment == Alignment.ENEMY) {
Dungeon.level.drop( new Embers(), pos ).sprite.drop();
Statistics.questScores[1] = 2000;
//assign score here as player may choose to keep the embers
Statistics.questScores[1] += 2000;
Game.runOnRenderThread(new Callback() {
@Override
public void call() {

View File

@@ -22,6 +22,7 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.StenchGas;
@@ -65,6 +66,9 @@ public class FetidRat extends Rat {
damage = super.attackProc( enemy, damage );
if (Random.Int(3) == 0) {
Buff.affect(enemy, Ooze.class).set( Ooze.DURATION );
if (enemy == Dungeon.hero && !Dungeon.level.water[enemy.pos]){
Statistics.questScores[0] -= 50;
}
}
return damage;

View File

@@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Badges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
@@ -704,6 +705,10 @@ public class GnollGeomancer extends Mob {
if (ch != null && !(ch instanceof GnollGeomancer)){
ch.damage(Random.NormalIntRange(6, 12), new GnollGeomancer.Boulder());
if (ch == Dungeon.hero){
Statistics.questScores[2] -= 100;
}
if (ch.isAlive()){
Buff.prolong( ch, Paralysis.class, ch instanceof GnollGuard ? 10 : 3 );
} else if (!ch.isAlive() && ch == Dungeon.hero) {
@@ -806,6 +811,9 @@ public class GnollGeomancer extends Mob {
@Override
public void affectChar(Char ch) {
ch.damage(Random.NormalIntRange(6, 12), this);
if (ch == Dungeon.hero){
Statistics.questScores[2] -= 100;
}
if (ch.isAlive()) {
Buff.prolong(ch, Paralysis.class, ch instanceof GnollGuard ? 10 : 3);
} else if (ch == Dungeon.hero){

View File

@@ -22,6 +22,7 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
@@ -75,6 +76,11 @@ public class GnollTrickster extends Gnoll {
@Override
public int attackProc( Char enemy, int damage ) {
damage = super.attackProc( enemy, damage );
if (combo >= 1){
Statistics.questScores[0] -= 50;
}
//The gnoll's attacks get more severe the more the player lets it hit them
combo++;
int effect = Random.Int(4)+combo;
@@ -83,12 +89,14 @@ public class GnollTrickster extends Gnoll {
if (effect >=6 && enemy.buff(Burning.class) == null){
if (Dungeon.level.flamable[enemy.pos])
if (Dungeon.level.flamable[enemy.pos]) {
GameScene.add(Blob.seed(enemy.pos, 4, Fire.class));
}
Buff.affect(enemy, Burning.class).reignite( enemy );
} else
Buff.affect( enemy, Poison.class).set((effect-2) );
} else {
Buff.affect(enemy, Poison.class).set((effect - 2));
}
}
return damage;

View File

@@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.spells.ClericSpell;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Ghost;
@@ -84,6 +85,7 @@ public class GreatCrab extends Crab {
GLog.n( Messages.get(this, "noticed") );
sprite.showStatus( CharSprite.NEUTRAL, Messages.get(this, "def_verb") );
Sample.INSTANCE.play( Assets.Sounds.HIT_PARRY, 1, Random.Float(0.96f, 1.05f));
Statistics.questScores[0] -= 50;
} else {
super.damage( dmg, src );
}
@@ -101,6 +103,9 @@ public class GreatCrab extends Crab {
Sample.INSTANCE.play(Assets.Sounds.HIT_PARRY, 1, Random.Float(0.96f, 1.05f));
GLog.n( Messages.get(this, "noticed") );
}
if (enemy == Dungeon.hero){
Statistics.questScores[0] -= 50;
}
return INFINITE_EVASION;
}
return super.defenseSkill( enemy );

View File

@@ -109,7 +109,8 @@ public class RotHeart extends Mob {
public void die(Object cause) {
super.die(cause);
Dungeon.level.drop( new Rotberry.Seed(), pos ).sprite.drop();
Statistics.questScores[1] = 2000;
//assign score here as player may choose to keep the rotberry seed
Statistics.questScores[1] += 2000;
}
@Override

View File

@@ -22,6 +22,7 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
@@ -76,6 +77,9 @@ public class RotLasher extends Mob {
public int attackProc(Char enemy, int damage) {
damage = super.attackProc( enemy, damage );
Buff.affect( enemy, Cripple.class, 2f );
if (enemy == Dungeon.hero){
Statistics.questScores[1] -= 100;
}
return super.attackProc(enemy, damage);
}

View File

@@ -452,7 +452,7 @@ public class Blacksmith extends NPC {
if (bossBeaten) favor += 1000;
Statistics.questScores[2] = favor;
Statistics.questScores[2] += favor;
}
public static boolean rewardsAvailable(){

View File

@@ -369,7 +369,7 @@ public class Ghost extends NPC {
GLog.n( Messages.get(Ghost.class, "find_me") );
Sample.INSTANCE.play( Assets.Sounds.GHOST );
processed = true;
Statistics.questScores[0] = 1000;
Statistics.questScores[0] += 1000;
Game.runOnRenderThread(new Callback() {
@Override

View File

@@ -446,7 +446,10 @@ public class Wandmaker extends NPC {
wand2 = null;
Notes.remove( Notes.Landmark.WANDMAKER );
Statistics.questScores[1] = 2000;
//other quests award score when their boss is defeated
if (Quest.type == 1) {
Statistics.questScores[1] += 2000;
}
}
}
}

View File

@@ -23,7 +23,9 @@ package com.shatteredpixel.shatteredpixeldungeon.items.quest;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
@@ -180,6 +182,35 @@ public class CorpseDust extends Item {
}
}
public static class DustWraith extends Wraith{};
public static class DustWraith extends Wraith{
private int hitCount = 0;
@Override
public int attackProc(Char enemy, int damage) {
if (enemy == Dungeon.hero){
hitCount++;
//first hit from each wraith is free, max of -200 point penalty per wraith
if (hitCount == 2 || hitCount == 3){
Statistics.questScores[1] -= 100;
}
}
return super.attackProc(enemy, damage);
}
private static final String HIT_COUNT = "hit_count";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put(HIT_COUNT, hitCount);
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
hitCount = bundle.getInt(HIT_COUNT);
}
}
}