Updated cost logic and default weights

This commit is contained in:
AnimeGitB 2022-05-12 02:23:51 +09:30 committed by Melledy
parent 736ca85300
commit 420801b49e
4 changed files with 40 additions and 22 deletions

View File

@ -6,7 +6,9 @@
"prefabPath": "GachaShowPanel_A022",
"previewPrefabPath": "UI_Tab_GachaShowPanel_A022",
"titlePath": "UI_GACHA_SHOW_PANEL_A022_TITLE",
"costItem": 224,
"costItemId": 224,
"costItemAmount": 1,
"costItemAmount10": 10,
"beginTime": 0,
"endTime": 1924992000,
"sortId": 1000,
@ -21,7 +23,7 @@
"prefabPath": "GachaShowPanel_A079",
"previewPrefabPath": "UI_Tab_GachaShowPanel_A079",
"titlePath": "UI_GACHA_SHOW_PANEL_A048_TITLE",
"costItem": 223,
"costItemId": 223,
"beginTime": 0,
"endTime": 1924992000,
"sortId": 9998,
@ -37,7 +39,7 @@
"prefabPath": "GachaShowPanel_A080",
"previewPrefabPath": "UI_Tab_GachaShowPanel_A080",
"titlePath": "UI_GACHA_SHOW_PANEL_A021_TITLE",
"costItem": 223,
"costItemId": 223,
"beginTime": 0,
"endTime": 1924992000,
"sortId": 9997,
@ -47,6 +49,7 @@
"rateUpItems4": [11401, 12402, 13407, 14401, 15401],
"rateUpItems5": [11509, 12504],
"fallbackItems5Pool1": [],
"weights4": [[1,600], [7,600], [8, 6600], [10,12600]],
"weights5": [[1,100], [62,100], [73, 7800], [80,10000]]
}
]

View File

@ -6,6 +6,7 @@ import emu.grasscutter.utils.Utils;
import static emu.grasscutter.Configuration.*;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.common.ItemParamData;
public class GachaBanner {
@ -145,25 +146,26 @@ public class GachaBanner {
+ "/gacha/details?s=" + sessionKey + "&gachaType=" + gachaType;
// Grasscutter.getLogger().info("record = " + record);
ItemParamData costItem1 = this.getCost(1);
ItemParamData costItem10 = this.getCost(10);
GachaInfo.Builder info = GachaInfo.newBuilder()
.setGachaType(this.getGachaType())
.setScheduleId(this.getScheduleId())
.setBeginTime(this.getBeginTime())
.setEndTime(this.getEndTime())
.setCostItemId(this.getCostItem())
.setCostItemNum(1)
.setCostItemId(costItem1.getId())
.setCostItemNum(costItem1.getCount())
.setTenCostItemId(costItem10.getId())
.setTenCostItemNum(costItem10.getCount())
.setGachaPrefabPath(this.getPrefabPath())
.setGachaPreviewPrefabPath(this.getPreviewPrefabPath())
.setGachaProbUrl(details)
.setGachaProbUrlOversea(details)
.setGachaRecordUrl(record)
.setGachaRecordUrlOversea(record)
.setTenCostItemId(this.getCostItem())
.setTenCostItemNum(10)
.setLeftGachaTimes(Integer.MAX_VALUE)
.setGachaTimesLimit(Integer.MAX_VALUE)
.setGachaSortId(this.getSortId());
if (this.getTitlePath() != null) {
info.setGachaTitlePath(this.getTitlePath());
}

View File

@ -4,6 +4,7 @@ import java.io.File;
import java.io.FileReader;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
@ -46,6 +47,8 @@ public class GachaManager {
private static final int starglitterId = 221;
private static final int stardustId = 222;
private int[] fallbackItems4Pool2Default = {11401, 11402, 11403, 11405, 12401, 12402, 12403, 12405, 13401, 13407, 14401, 14402, 14403, 14409, 15401, 15402, 15403, 15405};
private int[] fallbackItems5Pool2Default = {11501, 11502, 12501, 12502, 13502, 13505, 14501, 14502, 15501, 15502};
public GachaManager(GameServer server) {
this.server = server;
@ -156,16 +159,16 @@ public class GachaManager {
// Simple weighted selection with an upper bound for the roll that cuts off trailing entries
// All weights must be >= 0
int total = 0;
for (int i : weights) {
if (i < 0) {
for (int weight : weights) {
if (weight < 0) {
throw new IllegalArgumentException("Weights must be non-negative!");
}
total += i;
total += weight;
}
int roll = ThreadLocalRandom.current().nextInt((total < cutoff)? total : cutoff);
int subTotal = 0;
for (int i : weights) {
subTotal += i;
for (int i=0; i<weights.length; i++) {
subTotal += weights[i];
if (roll < subTotal) {
return i;
}
@ -176,16 +179,22 @@ public class GachaManager {
private synchronized int doRarePull(int[] featured, int[] fallback1, int[] fallback2, int rarity, GachaBanner banner, PlayerGachaBannerInfo gachaInfo) {
int itemId = 0;
if ( (featured.length > 0)
&& (gachaInfo.getFailedFeaturedItemPulls(rarity) >= 1)
|| (this.randomRange(1, 100) <= banner.getEventChance(rarity))) {
boolean pullFeatured = (gachaInfo.getFailedFeaturedItemPulls(rarity) >= 1) // Lost previous coinflip
|| (this.randomRange(1, 100) <= banner.getEventChance(rarity)); // Won this coinflip
if (pullFeatured && (featured.length > 0)) {
itemId = getRandom(featured);
gachaInfo.setFailedFeaturedItemPulls(rarity, 0);
} else {
gachaInfo.addFailedFeaturedItemPulls(rarity, 1);
if (fallback1.length < 1) {
itemId = getRandom(fallback2); // Don't ever run an empty fallback2 btw
if (fallback2.length < 1) {
itemId = getRandom((rarity==5)? fallbackItems5Pool2Default : fallbackItems4Pool2Default);
} else {
itemId = getRandom(fallback2);
}
} else if (fallback2.length < 1) {
itemId = getRandom(fallback1);
} else { // Both pools are possible, use the pool balancer
int pityPool1 = banner.getPoolBalanceWeight(rarity, gachaInfo.getPityPool(rarity, 1));
int pityPool2 = banner.getPoolBalanceWeight(rarity, gachaInfo.getPityPool(rarity, 2));
int chosenPool = switch ((pityPool1 >= pityPool2)? 1 : 0) { // Larger weight must come first for the hard cutoff to function correctly
@ -245,6 +254,7 @@ public class GachaManager {
// Spend currency
ItemParamData cost = banner.getCost(times);
if (cost.getCount() > 0 && !inventory.payItem(cost)) {
player.sendPacket(new PacketDoGachaRsp());
return;
}

View File

@ -2,6 +2,7 @@ package emu.grasscutter.server.packet.send;
import java.util.List;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.game.gacha.GachaBanner;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes;
@ -14,16 +15,18 @@ public class PacketDoGachaRsp extends BasePacket {
public PacketDoGachaRsp(GachaBanner banner, List<GachaItem> list) {
super(PacketOpcodes.DoGachaRsp);
ItemParamData costItem = banner.getCost(1);
ItemParamData costItem10 = banner.getCost(10);
DoGachaRsp p = DoGachaRsp.newBuilder()
.setGachaType(banner.getGachaType())
.setGachaScheduleId(banner.getScheduleId())
.setGachaTimes(list.size())
.setNewGachaRandom(12345)
.setLeftGachaTimes(Integer.MAX_VALUE)
.setCostItemId(banner.getCostItem())
.setCostItemNum(1)
.setTenCostItemId(banner.getCostItem())
.setTenCostItemNum(10)
.setCostItemId(costItem.getId())
.setCostItemNum(costItem.getCount())
.setTenCostItemId(costItem10.getId())
.setTenCostItemNum(costItem10.getCount())
.addAllGachaItemList(list)
.build();