mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-15 00:15:33 +01:00
Attempt to implement bargaining (untested)
This commit is contained in:
@@ -2,7 +2,7 @@ package emu.grasscutter.game.player;
|
||||
|
||||
import dev.morphia.annotations.*;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.quest.ItemGiveRecord;
|
||||
import emu.grasscutter.game.quest.*;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import lombok.*;
|
||||
@@ -29,12 +29,14 @@ public class PlayerProgress {
|
||||
private Map<String, Integer> questProgressCountMap;
|
||||
|
||||
private Map<Integer, ItemGiveRecord> itemGivings;
|
||||
private Map<Integer, BargainRecord> bargains;
|
||||
|
||||
public PlayerProgress() {
|
||||
this.questProgressCountMap = new ConcurrentHashMap<>();
|
||||
this.completedDungeons = new IntArrayList();
|
||||
this.itemHistory = new Int2ObjectOpenHashMap<>();
|
||||
this.itemGivings = new Int2ObjectOpenHashMap<>();
|
||||
this.bargains = new Int2ObjectOpenHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
109
src/main/java/emu/grasscutter/game/quest/BargainRecord.java
Normal file
109
src/main/java/emu/grasscutter/game/quest/BargainRecord.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package emu.grasscutter.game.quest;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.BargainData;
|
||||
import emu.grasscutter.net.proto.BargainResultTypeOuterClass.BargainResultType;
|
||||
import emu.grasscutter.net.proto.BargainSnapshotOuterClass.BargainSnapshot;
|
||||
import emu.grasscutter.utils.Utils;
|
||||
import lombok.*;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Builder
|
||||
public final class BargainRecord {
|
||||
/**
|
||||
* Provides an instance of a bargain record.
|
||||
* Uses information from game resources.
|
||||
*
|
||||
* @param bargainId The ID of the bargain.
|
||||
* @return An instance of a bargain record.
|
||||
*/
|
||||
public static BargainRecord resolve(int bargainId) {
|
||||
var bargainData = GameData.getBargainDataMap().get(bargainId);
|
||||
if (bargainData == null) throw new RuntimeException("No bargain data found for " + bargainId + ".");
|
||||
|
||||
return BargainRecord.builder()
|
||||
.bargainId(bargainId)
|
||||
.build()
|
||||
.determineBase(bargainData);
|
||||
}
|
||||
|
||||
private int bargainId;
|
||||
private int lowestPrice;
|
||||
private int expectedPrice;
|
||||
|
||||
private int currentMood;
|
||||
|
||||
private boolean finished;
|
||||
private BargainResultType result;
|
||||
|
||||
/**
|
||||
* Determines the price of the bargain.
|
||||
*/
|
||||
public BargainRecord determineBase(BargainData data) {
|
||||
// Set the expected price.
|
||||
var price = data.getExpectedValue();
|
||||
this.setExpectedPrice(Utils.randomRange(
|
||||
price.get(0), price.get(1)));
|
||||
// Set the lowest price.
|
||||
this.setLowestPrice(price.get(0));
|
||||
|
||||
// Set the base mood.
|
||||
var mood = data.getRandomMood();
|
||||
this.setCurrentMood(Utils.randomRange(
|
||||
mood.get(0), mood.get(1)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes an offer's validity.
|
||||
*
|
||||
* @param offer The offer to compute.
|
||||
* @return The result of the offer.
|
||||
*/
|
||||
public BargainResultType applyOffer(int offer) {
|
||||
if (offer < this.getLowestPrice()) {
|
||||
// Decrease the mood.
|
||||
this.currentMood -= Utils.randomRange(1, 3);
|
||||
// Return a failure.
|
||||
return this.result = BargainResultType.BARGAIN_SINGLE_FAIL;
|
||||
}
|
||||
|
||||
if (offer > this.getExpectedPrice()) {
|
||||
// Complete the bargain.
|
||||
this.setFinished(true);
|
||||
// Return a success.
|
||||
return this.result = BargainResultType.BARGAIN_COMPLETE_SUCC;
|
||||
}
|
||||
|
||||
// Compare the offer against the mood & expected price.
|
||||
// The mood is out of 100; 1 mood should decrease the price by 100.
|
||||
var moodAdjustment = (int) Math.floor(this.getCurrentMood() / 100.0);
|
||||
var expectedPrice = this.getExpectedPrice() - moodAdjustment;
|
||||
if (offer < expectedPrice) {
|
||||
// Decrease the mood.
|
||||
this.currentMood -= Utils.randomRange(1, 3);
|
||||
// Return a failure.
|
||||
return this.result = BargainResultType.BARGAIN_SINGLE_FAIL;
|
||||
} else {
|
||||
// Complete the bargain.
|
||||
this.setFinished(true);
|
||||
// Return a success.
|
||||
return this.result = BargainResultType.BARGAIN_COMPLETE_SUCC;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A snapshot of this bargain record.
|
||||
*/
|
||||
public BargainSnapshot toSnapshot() {
|
||||
return BargainSnapshot.newBuilder()
|
||||
.setBargainId(this.getBargainId())
|
||||
.setCurMood(this.getCurrentMood())
|
||||
.setPJHMEHGELGC(this.getExpectedPrice())
|
||||
.setHADMOPEJFIC(this.getLowestPrice())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -170,7 +170,54 @@ public final class QuestManager extends BasePlayerManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to remove the giving action.
|
||||
* Attempts to start the bargain.
|
||||
*
|
||||
* @param bargainId The bargain ID.
|
||||
*/
|
||||
public void startBargain(int bargainId) {
|
||||
var progress = this.player.getPlayerProgress();
|
||||
var bargains = progress.getBargains();
|
||||
|
||||
// Check if the bargain is already present.
|
||||
if (bargains.containsKey(bargainId)) {
|
||||
throw new IllegalStateException("Bargain " + bargainId + " is already active.");
|
||||
}
|
||||
|
||||
// Add the action.
|
||||
var bargain = BargainRecord.resolve(bargainId);
|
||||
bargains.put(bargainId, bargain);
|
||||
// Save the bargains.
|
||||
this.player.save();
|
||||
|
||||
// Send the player the start packet.
|
||||
this.player.sendPacket(new PacketBargainStartNotify(bargain));
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to stop the bargain.
|
||||
*
|
||||
* @param bargainId The bargain ID.
|
||||
*/
|
||||
public void stopBargain(int bargainId) {
|
||||
var progress = this.player.getPlayerProgress();
|
||||
var bargains = progress.getBargains();
|
||||
|
||||
// Check if the bargain is already present.
|
||||
if (!bargains.containsKey(bargainId)) {
|
||||
throw new IllegalStateException("Bargain " + bargainId + " is not active.");
|
||||
}
|
||||
|
||||
// Remove the action.
|
||||
bargains.remove(bargainId);
|
||||
// Save the bargains.
|
||||
this.player.save();
|
||||
|
||||
// Send the player the stop packet.
|
||||
this.player.sendPacket(new PacketBargainTerminateNotify(bargainId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the giving records to the player.
|
||||
*/
|
||||
public void sendGivingRecords() {
|
||||
// Send the record to the player.
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package emu.grasscutter.game.quest.content;
|
||||
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.quest.*;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.net.proto.BargainResultTypeOuterClass.BargainResultType;
|
||||
|
||||
@QuestValueContent(QuestContent.QUEST_CONTENT_BARGAIN_FAIL)
|
||||
public final class ContentBargainFail extends BaseContent {
|
||||
@Override
|
||||
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
|
||||
var bargain = quest.getOwner()
|
||||
.getPlayerProgress()
|
||||
.getBargains()
|
||||
.get(condition.getParam()[0]);
|
||||
if (bargain == null) return false;
|
||||
|
||||
return bargain.getResult() == BargainResultType.BARGAIN_COMPLETE_FAIL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package emu.grasscutter.game.quest.content;
|
||||
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.quest.*;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.net.proto.BargainResultTypeOuterClass.BargainResultType;
|
||||
|
||||
@QuestValueContent(QuestContent.QUEST_CONTENT_ITEM_LESS_THAN_BARGAIN)
|
||||
public final class ContentBargainLessThan extends BaseContent {
|
||||
@Override
|
||||
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
|
||||
var bargain = quest.getOwner()
|
||||
.getPlayerProgress()
|
||||
.getBargains()
|
||||
.get(condition.getParam()[0]);
|
||||
if (bargain == null) return false;
|
||||
|
||||
return bargain.getResult() == BargainResultType.BARGAIN_SINGLE_FAIL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package emu.grasscutter.game.quest.content;
|
||||
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.quest.*;
|
||||
import emu.grasscutter.game.quest.enums.QuestContent;
|
||||
import emu.grasscutter.net.proto.BargainResultTypeOuterClass.BargainResultType;
|
||||
|
||||
@QuestValueContent(QuestContent.QUEST_CONTENT_BARGAIN_SUCC)
|
||||
public final class ContentBargainSuccess extends BaseContent {
|
||||
@Override
|
||||
public boolean execute(GameQuest quest, QuestData.QuestContentCondition condition, String paramStr, int... params) {
|
||||
var bargain = quest.getOwner()
|
||||
.getPlayerProgress()
|
||||
.getBargains()
|
||||
.get(condition.getParam()[0]);
|
||||
if (bargain == null) return false;
|
||||
|
||||
return bargain.getResult() == BargainResultType.BARGAIN_COMPLETE_SUCC;
|
||||
}
|
||||
}
|
||||
@@ -51,9 +51,9 @@ public enum QuestContent implements QuestTrigger {
|
||||
QUEST_CONTENT_QUEST_VAR_LESS(121),
|
||||
QUEST_CONTENT_OBTAIN_VARIOUS_ITEM(122), // missing, finish
|
||||
QUEST_CONTENT_FINISH_TOWER_LEVEL(123), // missing, currently unused
|
||||
QUEST_CONTENT_BARGAIN_SUCC(124), // missing, finish
|
||||
QUEST_CONTENT_BARGAIN_FAIL(125), // missing, fail
|
||||
QUEST_CONTENT_ITEM_LESS_THAN_BARGAIN(126), // missing, fail
|
||||
QUEST_CONTENT_BARGAIN_SUCC(124),
|
||||
QUEST_CONTENT_BARGAIN_FAIL(125),
|
||||
QUEST_CONTENT_ITEM_LESS_THAN_BARGAIN(126),
|
||||
QUEST_CONTENT_ACTIVITY_TRIGGER_FAILED(127), // missing, fail
|
||||
QUEST_CONTENT_MAIN_COOP_ENTER_SAVE_POINT(128), // missing, finish
|
||||
QUEST_CONTENT_ANY_MANUAL_TRANSPORT(129),
|
||||
|
||||
@@ -47,8 +47,8 @@ public enum QuestExec implements QuestTrigger {
|
||||
QUEST_EXEC_ACTIVE_ACTIVITY_COND_STATE(37), // missing
|
||||
QUEST_EXEC_INACTIVE_ACTIVITY_COND_STATE(38), // missing
|
||||
QUEST_EXEC_ADD_CUR_AVATAR_ENERGY(39),
|
||||
QUEST_EXEC_START_BARGAIN(41), // missing
|
||||
QUEST_EXEC_STOP_BARGAIN(42), // missing
|
||||
QUEST_EXEC_START_BARGAIN(41),
|
||||
QUEST_EXEC_STOP_BARGAIN(42),
|
||||
QUEST_EXEC_SET_QUEST_GLOBAL_VAR(43),
|
||||
QUEST_EXEC_INC_QUEST_GLOBAL_VAR(44),
|
||||
QUEST_EXEC_DEC_QUEST_GLOBAL_VAR(45),
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package emu.grasscutter.game.quest.exec;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.quest.*;
|
||||
import emu.grasscutter.game.quest.enums.QuestExec;
|
||||
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
|
||||
|
||||
@QuestValueExec(QuestExec.QUEST_EXEC_START_BARGAIN)
|
||||
public final class ExecStartBargain extends QuestExecHandler {
|
||||
@Override
|
||||
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
|
||||
// Get the bargain data from the quest parameters.
|
||||
var bargainId = Integer.parseInt(condition.getParam()[0]);
|
||||
|
||||
try {
|
||||
// Start the bargain.
|
||||
quest.getOwner().getQuestManager()
|
||||
.startBargain(bargainId);
|
||||
Grasscutter.getLogger().debug("Bargain {} started.", bargainId);
|
||||
return true;
|
||||
} catch (RuntimeException ignored) {
|
||||
Grasscutter.getLogger().debug("Bargain {} does not exist.", bargainId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package emu.grasscutter.game.quest.exec;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.data.excels.quest.QuestData;
|
||||
import emu.grasscutter.game.quest.*;
|
||||
import emu.grasscutter.game.quest.enums.QuestExec;
|
||||
import emu.grasscutter.game.quest.handlers.QuestExecHandler;
|
||||
|
||||
@QuestValueExec(QuestExec.QUEST_EXEC_STOP_BARGAIN)
|
||||
public final class ExecStopBargain extends QuestExecHandler {
|
||||
@Override
|
||||
public boolean execute(GameQuest quest, QuestData.QuestExecParam condition, String... paramStr) {
|
||||
// Get the bargain data from the quest parameters.
|
||||
var bargainId = Integer.parseInt(condition.getParam()[0]);
|
||||
|
||||
try {
|
||||
// Start the bargain.
|
||||
quest.getOwner().getQuestManager()
|
||||
.stopBargain(bargainId);
|
||||
Grasscutter.getLogger().debug("Bargain {} stopped.", bargainId);
|
||||
return true;
|
||||
} catch (RuntimeException ignored) {
|
||||
Grasscutter.getLogger().debug("Bargain {} does not exist.", bargainId);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user