[BREAKING] Item Usage Overhaul

-De-hardcode elemental orb values
-De-hardcode exp items
-Change ShopChest format (temporary, drop system overhaul will replace it entirely)
-Food healing actually uses Ability data for real HP amounts
This commit is contained in:
AnimeGitB
2022-10-14 00:00:40 +10:30
parent 5bb43ac074
commit d1d39db56c
66 changed files with 1533 additions and 786 deletions

View File

@@ -0,0 +1,19 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseAcceptQuest extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ACCEPT_QUEST;
}
public ItemUseAcceptQuest(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
return (params.player.getQuestManager().addQuest(this.i) != null);
}
}

View File

@@ -0,0 +1,78 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.data.common.ItemUseData;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseAction {
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_NONE;
}
public static ItemUseAction fromItemUseData(ItemUseData data) {
var useParam = data.getUseParam();
return switch (data.getUseOp()) {
case ITEM_USE_NONE -> null;
// Uprade materials - no direct usage
case ITEM_USE_ADD_EXP -> new ItemUseAddExp(useParam);
case ITEM_USE_ADD_RELIQUARY_EXP -> new ItemUseAddReliquaryExp(useParam);
case ITEM_USE_ADD_WEAPON_EXP -> new ItemUseAddWeaponExp(useParam);
// Energy pickups
case ITEM_USE_ADD_ALL_ENERGY -> new ItemUseAddAllEnergy(useParam);
case ITEM_USE_ADD_ELEM_ENERGY -> new ItemUseAddElemEnergy(useParam);
// Give items
case ITEM_USE_ADD_ITEM -> new ItemUseAddItem(useParam);
case ITEM_USE_GAIN_AVATAR -> new ItemUseGainAvatar(useParam);
case ITEM_USE_GAIN_COSTUME -> new ItemUseGainCostume(useParam); // TODO - real success/fail
case ITEM_USE_GAIN_FLYCLOAK -> new ItemUseGainFlycloak(useParam); // TODO - real success/fail
case ITEM_USE_GAIN_NAME_CARD -> new ItemUseGainNameCard(useParam); // TODO
case ITEM_USE_CHEST_SELECT_ITEM -> new ItemUseChestSelectItem(useParam);
case ITEM_USE_ADD_SELECT_ITEM -> new ItemUseAddSelectItem(useParam);
case ITEM_USE_GRANT_SELECT_REWARD -> new ItemUseGrantSelectReward(useParam);
case ITEM_USE_COMBINE_ITEM -> new ItemUseCombineItem(useParam);
case ITEM_USE_OPEN_RANDOM_CHEST -> new ItemUseOpenRandomChest(useParam);
// Food effects
case ITEM_USE_RELIVE_AVATAR -> new ItemUseReliveAvatar(useParam); // First action for revival food. Should we worry about race conditions in parallel streams?
case ITEM_USE_ADD_CUR_HP -> new ItemUseAddCurHp(useParam);
case ITEM_USE_ADD_CUR_STAMINA -> new ItemUseAddCurStamina(useParam);
case ITEM_USE_ADD_SERVER_BUFF -> new ItemUseAddServerBuff(useParam);
case ITEM_USE_MAKE_GADGET -> new ItemUseMakeGadget(useParam);
// Unlock recipes - TODO: allow scheduling packets for after recipe is removed
case ITEM_USE_UNLOCK_COMBINE -> new ItemUseUnlockCombine(useParam);
case ITEM_USE_UNLOCK_CODEX -> new ItemUseUnlockCodex(useParam); // TODO: No backend for this yet
case ITEM_USE_UNLOCK_COOK_RECIPE -> new ItemUseUnlockCookRecipe(useParam);
case ITEM_USE_UNLOCK_FORGE -> new ItemUseUnlockForge(useParam);
case ITEM_USE_UNLOCK_FURNITURE_FORMULA -> new ItemUseUnlockFurnitureFormula(useParam);
case ITEM_USE_UNLOCK_FURNITURE_SUITE -> new ItemUseUnlockFurnitureSuite(useParam);
case ITEM_USE_UNLOCK_HOME_MODULE -> new ItemUseUnlockHomeModule(useParam); // No backend for this yet
case ITEM_USE_UNLOCK_HOME_BGM -> new ItemUseUnlockHomeBgm(useParam);
// Account things
case ITEM_USE_ACCEPT_QUEST -> new ItemUseAcceptQuest(useParam);
case ITEM_USE_GAIN_CARD_PRODUCT -> new ItemUseGainCardProduct(useParam);
case ITEM_USE_UNLOCK_PAID_BATTLE_PASS_NORMAL -> new ItemUseUnlockPaidBattlePassNormal(useParam); // TODO: add paid BP
// Unused in current resources
case ITEM_USE_DEL_SERVER_BUFF -> null;
case ITEM_USE_ADD_BIG_TALENT_POINT -> null;
case ITEM_USE_GAIN_RESIN_CARD_PRODUCT -> null;
case ITEM_USE_TRIGGER_ABILITY -> null;
case ITEM_USE_ADD_TREASURE_MAP_BONUS_REGION_FRAGMENT -> null;
// Used in current resources but no point yet
case ITEM_USE_ADD_PERSIST_STAMINA -> null; // [int amount] one Test item
case ITEM_USE_ADD_TEMPORARY_STAMINA -> null; // [int amount] one Test item
case ITEM_USE_ADD_DUNGEON_COND_TIME -> null; // [int 1, int 15 or 20] - minigame shards
case ITEM_USE_ADD_CHANNELLER_SLAB_BUFF -> null; // [int] minigame buffs
case ITEM_USE_ADD_REGIONAL_PLAY_VAR -> null; // [String, int] - coral butterfly effect
};
}
public boolean useItem(UseItemParams params) {
// An item must return true on at least one of its actions to count as successfully used.
// If all of the actions return false, the item will not be consumed from inventory.
return false;
}
public boolean postUseItem(UseItemParams params) {
// This is run after the item has been consumed from inventory.
return false;
}
}

View File

@@ -0,0 +1,23 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseAddAllEnergy extends ItemUseAddEnergy {
private float energy = 0f;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_ALL_ENERGY;
}
public ItemUseAddAllEnergy(String[] useParam) {
try {
this.energy = Float.parseFloat(useParam[0]);
} catch (Exception ignored) {}
}
public float getAddEnergy(ElementType avatarElement) {
return this.energy;
}
}

View File

@@ -0,0 +1,22 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseAddCurHp extends ItemUseInt {
private String icon;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_CUR_HP;
}
public ItemUseAddCurHp(String[] useParam) {
super(useParam);
this.icon = useParam[1];
}
@Override
public boolean useItem(UseItemParams params) {
return (params.targetAvatar.getAsEntity().heal(params.count * this.i) > 0.01);
}
}

View File

@@ -0,0 +1,19 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseAddCurStamina extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_CUR_STAMINA;
}
public ItemUseAddCurStamina(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
return params.player.getStaminaManager().addCurrentStamina(this.i);
}
}

View File

@@ -0,0 +1,31 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseAddElemEnergy extends ItemUseAddEnergy {
private ElementType element = ElementType.None;
private float elemEnergy = 0f;
private float otherEnergy = 0f;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_ELEM_ENERGY;
}
public ItemUseAddElemEnergy(String[] useParam) {
try {
this.element = ElementType.getTypeByValue(Integer.parseInt(useParam[0]));
} catch (Exception ignored) {}
try {
this.elemEnergy = Float.parseFloat(useParam[1]);
} catch (Exception ignored) {}
try {
this.otherEnergy = Float.parseFloat(useParam[2]);
} catch (Exception ignored) {}
}
public float getAddEnergy(ElementType avatarElement) {
return (avatarElement == this.element) ? this.elemEnergy : this.otherEnergy;
}
}

View File

@@ -0,0 +1,61 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.data.excels.AvatarSkillDepotData;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.props.ElementType;
import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason;
public abstract class ItemUseAddEnergy extends ItemUseAction {
public abstract float getAddEnergy(ElementType avatarElement);
public float getAddEnergy(AvatarSkillDepotData depot) {
if (depot == null) return 0f;
var element = depot.getElementType();
if (element == null) return 0f;
return this.getAddEnergy(element);
}
@Override
public boolean useItem(UseItemParams params) {
var teamManager = params.player.getTeamManager();
return switch (params.itemUseTarget) {
case ITEM_USE_TARGET_CUR_AVATAR -> {
this.addEnergy(teamManager.getCurrentAvatarEntity().getAvatar(), params.count);
yield true; // Always consume elem balls
}
case ITEM_USE_TARGET_CUR_TEAM -> {
var activeTeam = teamManager.getActiveTeam();
// On-field vs off-field multiplier.
// The on-field character gets full amount, off-field characters get less depending on the team size.
final float offFieldRatio = switch(activeTeam.size()) {
case 2 -> 0.8f;
case 3 -> 0.7f;
default -> 0.6f;
};
final int currentCharacterIndex = teamManager.getCurrentCharacterIndex();
// Add energy to every team member.
for (int i = 0; i < activeTeam.size(); i++) {
var avatar = activeTeam.get(i).getAvatar();
if (i == currentCharacterIndex)
this.addEnergy(avatar, params.count);
else
this.addEnergy(avatar, params.count * offFieldRatio);
}
yield true; // Always consume elem balls
}
case ITEM_USE_TARGET_SPECIFY_AVATAR, ITEM_USE_TARGET_SPECIFY_ALIVE_AVATAR, ITEM_USE_TARGET_SPECIFY_DEAD_AVATAR ->
this.addEnergy(params.targetAvatar, params.count); // Targeted items might care about this
case ITEM_USE_TARGET_NONE -> false;
};
}
private boolean addEnergy(Avatar avatar, float multiplier) {
float energy = this.getAddEnergy(avatar.getSkillDepot()) * multiplier;
if (energy < 0.01f)
return false;
avatar.getAsEntity().addEnergy(energy, PropChangeReason.PROP_CHANGE_REASON_ENERGY_BALL);
return true;
}
}

View File

@@ -0,0 +1,19 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
import lombok.Getter;
public class ItemUseAddExp extends ItemUseAction {
@Getter private int exp = 0;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_EXP;
}
public ItemUseAddExp(String[] useParam) {
try {
this.exp = Integer.parseInt(useParam[0]);
} catch (NumberFormatException ignored) {}
}
}

View File

@@ -0,0 +1,24 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseAddItem extends ItemUseInt {
private int count = 0;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_ITEM;
}
public ItemUseAddItem(String[] useParam) {
super(useParam);
try {
this.count = Integer.parseInt(useParam[1]);
} catch (NumberFormatException ignored) {}
}
@Override
public boolean useItem(UseItemParams params) {
return params.player.getInventory().addItem(this.i, this.count * params.count);
}
}

View File

@@ -0,0 +1,19 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
import lombok.Getter;
public class ItemUseAddReliquaryExp extends ItemUseAction {
@Getter private int exp = 0;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_RELIQUARY_EXP;
}
public ItemUseAddReliquaryExp(String[] useParam) {
try {
this.exp = Integer.parseInt(useParam[0]);
} catch (NumberFormatException ignored) {}
}
}

View File

@@ -0,0 +1,22 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseAddSelectItem extends ItemUseSelectItems {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_SELECT_ITEM;
}
public ItemUseAddSelectItem(String[] useParam) {
String[] options = useParam[0].split(",");
this.optionItemIds = new int[options.length];
for (int i = 0; i < options.length; i++) {
try {
this.optionItemIds[i] = Integer.parseInt(options[i]);
} catch (NumberFormatException ignored) {
this.optionItemIds[i] = INVALID;
}
};
}
}

View File

@@ -0,0 +1,24 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseAddServerBuff extends ItemUseInt {
private int duration = 0;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_SERVER_BUFF;
}
public ItemUseAddServerBuff(String[] useParam) {
super(useParam);
try {
this.duration = Integer.parseInt(useParam[1]);
} catch (NumberFormatException ignored) {}
}
@Override
public boolean useItem(UseItemParams params) {
return params.player.getBuffManager().addBuff(this.i, this.duration, params.targetAvatar);
}
}

View File

@@ -0,0 +1,19 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
import lombok.Getter;
public class ItemUseAddWeaponExp extends ItemUseAction {
@Getter private int exp = 0;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_WEAPON_EXP;
}
public ItemUseAddWeaponExp(String[] useParam) {
try {
this.exp = Integer.parseInt(useParam[0]);
} catch (NumberFormatException ignored) {}
}
}

View File

@@ -0,0 +1,37 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseChestSelectItem extends ItemUseSelectItems {
private int[] optionItemCounts;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_CHEST_SELECT_ITEM;
}
public ItemUseChestSelectItem(String[] useParam) {
String[] options = useParam[0].split(",");
this.optionItemIds = new int[options.length];
this.optionItemCounts = new int[options.length];
for (int i = 0; i < options.length; i++) {
String[] optionParts = options[i].split(":");
try {
this.optionItemIds[i] = Integer.parseInt(optionParts[0]);
} catch (NumberFormatException ignored) {
this.optionItemIds[i] = INVALID;
}
try {
this.optionItemCounts[i] = Integer.parseInt(optionParts[1]);
} catch (NumberFormatException ignored) {
this.optionItemCounts[i] = INVALID;
}
};
}
@Override
protected int getItemCount(int index) {
if ((optionItemCounts == null) || (index < 0) || (index > optionItemCounts.length)) return INVALID;
return this.optionItemCounts[index];
}
}

View File

@@ -0,0 +1,29 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseCombineItem extends ItemUseInt {
private int resultId = 0;
private int resultCount = 1;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_COMBINE_ITEM;
}
public ItemUseCombineItem(String[] useParam) {
super(useParam);
try {
this.resultId = Integer.parseInt(useParam[1]);
} catch (NumberFormatException ignored) {}
try {
this.resultCount = Integer.parseInt(useParam[2]);
} catch (NumberFormatException ignored) {}
}
@Override
public boolean useItem(UseItemParams params) {
if (params.count != this.i) return false; // Wrong amount of fragments supplied!
return params.player.getInventory().addItem(this.resultId, this.resultCount);
}
}

View File

@@ -0,0 +1,43 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.props.ItemUseOp;
import emu.grasscutter.game.systems.InventorySystem;
public class ItemUseGainAvatar extends ItemUseInt {
private int level = 1;
private int constellation = 0;
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_GAIN_AVATAR;
}
public ItemUseGainAvatar(String[] useParam) {
super(useParam);
try {
this.level = Integer.parseInt(useParam[1]);
} catch (NumberFormatException ignored) {}
try {
this.constellation = Integer.parseInt(useParam[2]);
} catch (NumberFormatException ignored) {}
}
@Override
public boolean useItem(UseItemParams params) {
int haveConstellation = InventorySystem.checkPlayerAvatarConstellationLevel(params.player, this.i);
if (haveConstellation == -2 || haveConstellation >= 6) {
return false;
} else if (haveConstellation == -1) {
var avatar = new Avatar(this.i);
avatar.setLevel(this.level);
avatar.forceConstellationLevel(this.constellation);
avatar.recalcStats();
params.player.addAvatar(avatar);
return true;
} else {
int itemId = (this.i % 1000) + 100;
return params.player.getInventory().addItem(itemId);
}
}
}

View File

@@ -0,0 +1,18 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseGainCardProduct extends ItemUseAction {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_GAIN_CARD_PRODUCT;
}
public ItemUseGainCardProduct(String[] useParam) {
}
@Override
public boolean useItem(UseItemParams params) {
return params.player.rechargeMoonCard();
}
}

View File

@@ -0,0 +1,20 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseGainCostume extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_GAIN_COSTUME;
}
public ItemUseGainCostume(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
params.player.getInventory().addItem(this.i); // TODO: Currently this returns false for all virtual items - need to have a proper success/fail
return true;
}
}

View File

@@ -0,0 +1,20 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseGainFlycloak extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_GAIN_FLYCLOAK;
}
public ItemUseGainFlycloak(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
params.player.getInventory().addItem(this.i); // TODO: Currently this returns false for all virtual items - need to have a proper success/fail
return true;
}
}

View File

@@ -0,0 +1,18 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseGainNameCard extends ItemUseAction {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_GAIN_NAME_CARD;
}
public ItemUseGainNameCard(String[] useParam) {
}
@Override
public boolean useItem(UseItemParams params) {
return false; // TODO: work out if this is actually used and how to get the namecard id
}
}

View File

@@ -0,0 +1,22 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseGrantSelectReward extends ItemUseSelectItems {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_ADD_SELECT_ITEM;
}
public ItemUseGrantSelectReward(String[] useParam) {
String[] options = useParam[0].split(",");
this.optionItemIds = new int[options.length];
for (int i = 0; i < options.length; i++) {
try {
this.optionItemIds[i] = Integer.parseInt(options[i]);
} catch (NumberFormatException ignored) {
this.optionItemIds[i] = INVALID;
}
};
}
}

View File

@@ -0,0 +1,13 @@
package emu.grasscutter.game.props.ItemUseAction;
import lombok.Getter;
public abstract class ItemUseInt extends ItemUseAction {
@Getter protected int i = 0;
public ItemUseInt(String[] useParam) {
try {
this.i = Integer.parseInt(useParam[0]);
} catch (NumberFormatException ignored) {}
}
}

View File

@@ -0,0 +1,26 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.entity.EntityVehicle;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseMakeGadget extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_MAKE_GADGET;
}
public ItemUseMakeGadget(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
var player = params.player;
var scene = player.getScene();
var pos = player.getPosition().nearby2d(1f);
var rot = player.getRotation().clone();
var e = new EntityVehicle(scene, player, this.i, 0, pos, rot);
scene.addEntity(e);
return true;
}
}

View File

@@ -0,0 +1,25 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseOpenRandomChest extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_OPEN_RANDOM_CHEST;
}
public ItemUseOpenRandomChest(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) { // cash shop material bundles
var rewardItems = params.player.getServer().getShopSystem().getShopChestData(this.i).stream().map(GameItem::new).toList();
if (!rewardItems.isEmpty()) {
params.player.getInventory().addItems(rewardItems, ActionReason.Shop);
}
return false;
}
}

View File

@@ -0,0 +1,18 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseReliveAvatar extends ItemUseAction {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_RELIVE_AVATAR;
}
public ItemUseReliveAvatar(String[] useParam) {
}
@Override
public boolean useItem(UseItemParams params) {
return params.player.getTeamManager().reviveAvatar(params.targetAvatar);
}
}

View File

@@ -0,0 +1,38 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.data.GameData;
import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.game.props.ActionReason;
public abstract class ItemUseSelectItems extends ItemUseAction {
protected static final int INVALID = -1;
protected int[] optionItemIds;
protected int getItemId(int index) {
if ((optionItemIds == null) || (index < 0) || (index > optionItemIds.length)) return INVALID;
return this.optionItemIds[index];
}
protected int getItemCount(int index) {
return 1;
}
protected GameItem getItemStack(int index, int useCount) {
int id = this.getItemId(index);
int count = this.getItemCount(index);
if (id == INVALID || count == INVALID) return null;
var item = GameData.getItemDataMap().get(id);
if (item == null) return null;
return new GameItem(item, count * useCount);
}
@Override
public boolean useItem(UseItemParams params) {
var itemStack = this.getItemStack(params.optionId - 1, params.count);
if (itemStack == null) return false;
return params.player.getInventory().addItem(itemStack, ActionReason.Shop);
}
}

View File

@@ -0,0 +1,19 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseUnlockCodex extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_UNLOCK_CODEX;
}
public ItemUseUnlockCodex(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
return false;
}
}

View File

@@ -0,0 +1,24 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseUnlockCombine extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_UNLOCK_COMBINE;
}
public ItemUseUnlockCombine(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
return true;
}
@Override
public boolean postUseItem(UseItemParams params) {
return params.player.getServer().getCombineSystem().unlockCombineDiagram(params.player, this.i);
}
}

View File

@@ -0,0 +1,24 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseUnlockCookRecipe extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_UNLOCK_COOK_RECIPE;
}
public ItemUseUnlockCookRecipe(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
return true;
}
@Override
public boolean postUseItem(UseItemParams params) {
return params.player.getCookingManager().unlockRecipe(this.i);
}
}

View File

@@ -0,0 +1,24 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseUnlockForge extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_UNLOCK_FORGE;
}
public ItemUseUnlockForge(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
return true;
}
@Override
public boolean postUseItem(UseItemParams params) {
return params.player.getForgingManager().unlockForgingBlueprint(this.i);
}
}

View File

@@ -0,0 +1,24 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseUnlockFurnitureFormula extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_UNLOCK_FURNITURE_FORMULA;
}
public ItemUseUnlockFurnitureFormula(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
return true;
}
@Override
public boolean postUseItem(UseItemParams params) {
return params.player.getFurnitureManager().unlockFurnitureFormula(this.i);
}
}

View File

@@ -0,0 +1,24 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseUnlockFurnitureSuite extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_UNLOCK_FURNITURE_SUITE;
}
public ItemUseUnlockFurnitureSuite(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
return true;
}
@Override
public boolean postUseItem(UseItemParams params) {
return params.player.getFurnitureManager().unlockFurnitureSuite(this.i);
}
}

View File

@@ -0,0 +1,20 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseUnlockHomeBgm extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_UNLOCK_HOME_BGM;
}
public ItemUseUnlockHomeBgm(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
params.player.getHome().addUnlockedHomeBgm(this.i);
return true; // Probably best to remove the item even if the bgm was already unlocked.
}
}

View File

@@ -0,0 +1,19 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseUnlockHomeModule extends ItemUseInt {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_UNLOCK_HOME_MODULE;
}
public ItemUseUnlockHomeModule(String[] useParam) {
super(useParam);
}
@Override
public boolean useItem(UseItemParams params) {
return false;
}
}

View File

@@ -0,0 +1,20 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.props.ItemUseOp;
public class ItemUseUnlockPaidBattlePassNormal extends ItemUseAction {
@Override
public ItemUseOp getItemUseOp() {
return ItemUseOp.ITEM_USE_UNLOCK_PAID_BATTLE_PASS_NORMAL;
}
public ItemUseUnlockPaidBattlePassNormal(String[] useParam) {
}
@Override
public boolean useItem(UseItemParams params) {
// TODO: add paid BP
//return params.player.getBattlePassManager().setPaid(true);
return false;
}
}

View File

@@ -0,0 +1,29 @@
package emu.grasscutter.game.props.ItemUseAction;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.ItemUseTarget;
public class UseItemParams {
// Don't want to change 40 method signatures when this gets extended!
public Player player;
public ItemUseTarget itemUseTarget;
public Avatar targetAvatar = null;
public int count = 1;
public int optionId = 0;
public boolean isEnterMpDungeonTeam = false;
public UseItemParams(Player player, ItemUseTarget itemUseTarget, Avatar targetAvatar, int count, int optionId, boolean isEnterMpDungeonTeam) {
this.player = player;
this.itemUseTarget = itemUseTarget;
this.targetAvatar = targetAvatar;
this.count = count;
this.optionId = optionId;
this.isEnterMpDungeonTeam = isEnterMpDungeonTeam;
}
public UseItemParams(Player player, ItemUseTarget itemUseTarget) {
this.player = player;
this.itemUseTarget = itemUseTarget;
}
}