mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-22 15:38:24 +00:00
Updated cost logic and default weights
This commit is contained in:
parent
736ca85300
commit
420801b49e
@ -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]]
|
||||
}
|
||||
]
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user