Implement GenerateElemBall action

This commit is contained in:
StartForKiller 2023-06-03 20:20:32 -04:00 committed by KingRainbow44
parent 63ccff8755
commit 0167709070
No known key found for this signature in database
GPG Key ID: FC2CB64B00D257BE
4 changed files with 107 additions and 8 deletions

View File

@ -327,6 +327,11 @@ public class AbilityModifier implements Serializable {
public AbilityModifierAction[] successActions; public AbilityModifierAction[] successActions;
public AbilityModifierAction[] failActions; public AbilityModifierAction[] failActions;
public int dropType;
public DynamicFloat baseEnergy;
public DynamicFloat ratio;
public int configID;
public int param1; public int param1;
public int param2; public int param2;
public int param3; public int param3;

View File

@ -1,9 +1,10 @@
package emu.grasscutter.data.binout.config; package emu.grasscutter.data.binout.config;
import emu.grasscutter.data.binout.config.fields.ConfigAbilityData; import emu.grasscutter.data.binout.config.fields.ConfigAbilityData;
import java.util.List;
import lombok.Getter; import lombok.Getter;
import java.util.List;
public class ConfigLevelEntity { public class ConfigLevelEntity {
@Getter private List<ConfigAbilityData> abilities; @Getter private List<ConfigAbilityData> abilities;
@ -11,4 +12,6 @@ public class ConfigLevelEntity {
@Getter private List<ConfigAbilityData> avatarAbilities; @Getter private List<ConfigAbilityData> avatarAbilities;
@Getter private List<ConfigAbilityData> teamAbilities; @Getter private List<ConfigAbilityData> teamAbilities;
@Getter private List<Integer> preloadMonsterEntityIDs; @Getter private List<Integer> preloadMonsterEntityIDs;
@Getter private String dropElemControlType;
} }

View File

@ -0,0 +1,86 @@
package emu.grasscutter.game.ability.actions;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.binout.AbilityModifier.AbilityModifierAction;
import emu.grasscutter.data.binout.config.ConfigLevelEntity;
import emu.grasscutter.game.ability.Ability;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.entity.EntityItem;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.props.ItemUseOp;
import emu.grasscutter.game.props.SceneType;
import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall;
import emu.grasscutter.utils.Position;
@AbilityAction(AbilityModifierAction.Type.GenerateElemBall)
public class ActionGenerateElemBall extends AbilityActionHandler {
@Override
public boolean execute(Ability ability, AbilityModifierAction action, ByteString abilityData, GameEntity target) {
GameEntity owner = ability.getOwner();
AbilityActionGenerateElemBall generateElemBall;
try {
generateElemBall = AbilityActionGenerateElemBall.parseFrom(abilityData);
} catch (InvalidProtocolBufferException e) {
return false;
}
//Check if we should allow elem ball generation
if(action.dropType == 0x0) {
String levelEntityConfig = owner.getScene().getSceneData().getLevelEntityConfig();
ConfigLevelEntity config = GameData.getConfigLevelEntityDataMap().get(levelEntityConfig);
if(config != null && config.getDropElemControlType() != null && config.getDropElemControlType().compareTo("None") == 0) {
Grasscutter.getLogger().warn("This level config don't allow element balls");
return true;
}
} else if(action.dropType == 0x1) {
if(owner.getScene().getSceneData().getSceneType() != SceneType.SCENE_WORLD) {
Grasscutter.getLogger().warn("This level config only allows element balls on big world");
return true;
}
} //Else the drop is forced
var energy = action.baseEnergy.get(ability) * action.ratio.get(ability);
if(energy <= 0.0) return true;
var itemData = GameData.getItemDataMap().get(action.configID);
if(itemData == null) {
Grasscutter.getLogger().warn("configID {} not found", action.configID);
return false;
}
if(itemData.getItemUse() == null || itemData.getItemUse().isEmpty()) {
Grasscutter.getLogger().warn("Item {} has no item use array", action.configID);
return true;
}
var itemUse = itemData.getItemUse().get(0);
double requiredEnergy;
switch(itemUse.getUseOp()) {
case ITEM_USE_ADD_ELEM_ENERGY: requiredEnergy = Integer.parseInt(itemUse.getUseParam()[1]); break;
case ITEM_USE_ADD_ALL_ENERGY: requiredEnergy = Integer.parseInt(itemUse.getUseParam()[0]); break;
default:
Grasscutter.getLogger().warn("UseOp not implemented", itemUse.getUseOp());
return false;
}
var amountGenerated = (int)Math.ceil(energy / requiredEnergy);
if(amountGenerated >= 21) {
Grasscutter.getLogger().warn("Attempt to generate more than 20 element balls {}", amountGenerated);
return false;
}
Grasscutter.getLogger().debug("Generating {} of {} element balls", amountGenerated, action.configID);
for(int i = 0; i < amountGenerated; i++) {
EntityItem energyBall = new EntityItem(owner.getScene(), (owner instanceof EntityAvatar avatar) ? avatar.getPlayer() : null, itemData, new Position(generateElemBall.getPos()), new Position(generateElemBall.getRot()), 1);
owner.getScene().addEntity(energyBall);
}
return true;
}
}

View File

@ -37,14 +37,19 @@ public class EntityItem extends EntityBaseGadget {
this(scene, player, itemData, pos, count, true); this(scene, player, itemData, pos, count, true);
} }
// In official game, some drop items are shared to all players, and some other items are public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, Position rotation, int count) {
// independent to all players this(scene, player, itemData, pos, rotation, count, true);
// For example, if you killed a monster in MP mode, all players could get drops but rarity and }
// number of them are different
public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, int count, boolean share) {
this(scene, player, itemData, pos, null, count, share);
}
// In official game, some drop items are shared to all players, and some other items are independent to all players
// For example, if you killed a monster in MP mode, all players could get drops but rarity and number of them are different
// but if you broke regional mine, when someone picked up the drop then it disappeared // but if you broke regional mine, when someone picked up the drop then it disappeared
public EntityItem( public EntityItem(Scene scene, Player player, ItemData itemData, Position pos, Position rotation, int count, boolean share) {
Scene scene, Player player, ItemData itemData, Position pos, int count, boolean share) { super(scene, pos, rotation);
super(scene, pos, null);
this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET); this.id = getScene().getWorld().getNextEntityId(EntityIdType.GADGET);
this.guid = this.guid =
player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid(); player == null ? scene.getWorld().getHost().getNextGameGuid() : player.getNextGameGuid();