Fix cataclysm survivor score calculation

This commit is contained in:
Melledy
2025-11-21 20:36:35 -08:00
parent e8a3576d8b
commit 3059c549d5
6 changed files with 155 additions and 19 deletions

View File

@@ -37,6 +37,12 @@ public class GameConstants {
public static final int MAX_FRIENDSHIPS = 50;
public static final int MAX_PENDING_FRIENDSHIPS = 30;
public static int[][] VAMPIRE_SURVIVOR_BONUS_POWER = new int[][] {
new int[] {100, 120},
new int[] {200, 150},
new int[] {300, 200}
};
// Daily gifts (Custom)
public static final WeightedList<ItemParam> DAILY_GIFTS = new WeightedList<>();

View File

@@ -12,6 +12,18 @@ public class VampireSurvivorDef extends BaseDef {
private int NeedWorldClass;
private int[] FateCardBundle;
private int NormalScore1;
private int EliteScore1;
private int BossScore1;
private int TimeScore1;
private int TimeLimit1;
private int NormalScore2;
private int EliteScore2;
private int BossScore2;
private int TimeScore2;
private int TimeLimit2;
@Override
public int getId() {
return Id;

View File

@@ -0,0 +1,82 @@
package emu.nebula.game.vampire;
import java.util.stream.IntStream;
import emu.nebula.GameConstants;
import emu.nebula.data.resources.VampireSurvivorDef;
import emu.nebula.proto.VampireSurvivorSettle.VampireSurvivorAreaInfo;
import lombok.Getter;
@Getter
public class VampireSurvivorArea {
private final VampireSurvivorGame game;
private int time;
private int score;
private int[] killCount;
private int[] killScore;
public VampireSurvivorArea(VampireSurvivorGame game, int time, int[] killCount) {
this.game = game;
this.time = time;
this.calcScore(killCount);
}
private VampireSurvivorDef getData() {
return this.getGame().getData();
}
private void calcScore(int[] killCount) {
// Set kill count/score
this.killCount = killCount;
this.killScore = new int[killCount.length];
// Check size for kill counter array
int maxSize = 4 + (GameConstants.VAMPIRE_SURVIVOR_BONUS_POWER.length * 2);
if (killCount.length < maxSize) {
return;
}
// Calculate
killScore[0] = killCount[0] * this.getData().getNormalScore1(); // Monster
killScore[1] = killCount[1] * this.getData().getEliteScore1(); // Elite monster
killScore[2] = killCount[2] * this.getData().getEliteScore1(); // Lord
killScore[3] = this.getData().getBossScore1(); // Boss
int offset = 4;
for (int i = 0; i < GameConstants.VAMPIRE_SURVIVOR_BONUS_POWER.length; i++, offset++) {
int bonusKill = killCount[offset];
int bonusPower = GameConstants.VAMPIRE_SURVIVOR_BONUS_POWER[i][1];
double mod = (bonusPower - 100) / 100D;
killScore[offset] = (int) (bonusKill * mod * this.getData().getNormalScore1());
}
for (int i = 0; i < GameConstants.VAMPIRE_SURVIVOR_BONUS_POWER.length; i++, offset++) {
int bonusKill = killCount[offset];
int bonusPower = GameConstants.VAMPIRE_SURVIVOR_BONUS_POWER[i][1];
double mod = (bonusPower - 100) / 100D;
killScore[offset] = (int) (bonusKill * mod * this.getData().getEliteScore1());
}
// Get final score
this.score = IntStream.of(killScore).sum();
}
// Proto
public VampireSurvivorAreaInfo toProto() {
var proto = VampireSurvivorAreaInfo.newInstance()
.setBossTime(this.getTime())
.setScore(this.getScore())
.addAllKillCount(this.getKillCount())
.addAllKillScore(this.getKillScore());
return proto;
}
}

View File

@@ -1,5 +1,6 @@
package emu.nebula.game.vampire;
import java.util.List;
import java.util.Set;
import emu.nebula.data.GameData;
@@ -8,10 +9,12 @@ import emu.nebula.data.resources.VampireSurvivorDef;
import emu.nebula.proto.Public.CardInfo;
import emu.nebula.proto.Public.VampireSurvivorLevelReward;
import emu.nebula.util.WeightedList;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import lombok.Getter;
@@ -27,6 +30,9 @@ public class VampireSurvivorGame {
private int rewardLevel;
private IntList rewards;
// Areas
private List<VampireSurvivorArea> areas;
// Cache
private Set<FateCardDef> randomCards;
@@ -37,6 +43,7 @@ public class VampireSurvivorGame {
this.cards = new IntOpenHashSet();
this.rewards = new IntArrayList();
this.areas = new ObjectArrayList<>();
// Cache fate cards from bundles
this.cacheRandomCards();
@@ -48,6 +55,16 @@ public class VampireSurvivorGame {
public int getId() {
return this.getData().getId();
}
public int getTotalScore() {
int score = 0;
for (var area : this.getAreas()) {
score += area.getScore();
}
return score;
}
public boolean isNewCard(int id) {
return !this.getManager().getProgress().getFateCards().contains(id);
@@ -147,6 +164,17 @@ public class VampireSurvivorGame {
return chest;
}
public VampireSurvivorArea settleArea(int time, int[] killCount) {
// Create area
var area = new VampireSurvivorArea(this, time, killCount);
// Add to areas list
this.getAreas().add(area);
// Success
return area;
}
// Proto
public VampireSurvivorLevelReward getRewardProto() {

View File

@@ -2,6 +2,7 @@ package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.VampireSurvivorAreaChange.VampireSurvivorAreaChangeReq;
import emu.nebula.net.HandlerId;
import emu.nebula.net.GameSession;
@@ -10,6 +11,19 @@ public class HandlerVampireSurvivorAreaChangeReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Parse req
var req = VampireSurvivorAreaChangeReq.parseFrom(message);
// Get vampire survivor game
var game = session.getPlayer().getVampireSurvivorManager().getGame();
if (game == null) {
session.encodeMsg(NetMsgId.vampire_survivor_area_change_failed_ack);
}
// Calculate score for area
game.settleArea(req.getTime(), req.getKillCount().toArray());
// Encode and send
return session.encodeMsg(NetMsgId.vampire_survivor_area_change_succeed_ack);
}

View File

@@ -2,7 +2,6 @@ package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.VampireSurvivorSettle.VampireSurvivorAreaInfo;
import emu.nebula.proto.VampireSurvivorSettle.VampireSurvivorSettleReq;
import emu.nebula.proto.VampireSurvivorSettle.VampireSurvivorSettleResp;
import emu.nebula.net.HandlerId;
@@ -16,40 +15,35 @@ public class HandlerVampireSurvivorSettleReq extends NetHandler {
// Parse request
var req = VampireSurvivorSettleReq.parseFrom(message);
// Sanity check
// Get vampire survivor game
var game = session.getPlayer().getVampireSurvivorManager().getGame();
if (game == null) {
session.encodeMsg(NetMsgId.vampire_survivor_settle_failed_ack);
}
// Calculate victory + score
// Calculate victory
boolean victory = !req.getDefeat();
int score = 1;
// Settle
session.getPlayer().getVampireSurvivorManager().settle(victory, score);
// Settle area
var area = game.settleArea(req.getTime(), req.getKillCount().toArray());
// Settle game
session.getPlayer().getVampireSurvivorManager().settle(victory, area.getScore());
// Build response
var rsp = VampireSurvivorSettleResp.newInstance();
if (victory) {
var areaInfo = VampireSurvivorAreaInfo.newInstance()
.setBossTime(1)
.setScore(score);
// TODO
for (int i : req.getKillCount()) {
areaInfo.addKillCount(i);
areaInfo.addKillScore(0);
}
rsp.getMutableVictory()
.setFinalScore(score)
.addInfos(areaInfo);
.setFinalScore(game.getTotalScore());
for (var a : game.getAreas()) {
rsp.getMutableVictory().addInfos(a.toProto());
}
} else {
rsp.getMutableDefeat()
.setFinalScore(score);
.setFinalScore(game.getTotalScore());
}
// Encode and send