-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Handle mob summon and limbo state (#2432)
Mob summon: Something like Monster_Apparatus_Perpetual can summon helper mobs. Ensure these helpers actually get summoned and, on their defeat, possibly change the summoner's mob state. Like, temporarily enter weak state. * Take summon tags from BinOutput/Monster/ConfigMonster_*.json and put them in SceneMonsterInfo * Handle Summon action in ability modifiers from BinOutput/Ability/Temp/MonsterAbilities/ConfigAbility_Monster_*.json * On summoner's kill, also kill the summoned mobs Limbo state: Something like Monster_Invoker_Herald_Water should be invulnerable at a certain HP threshold. Like, shouldn't die when creating their elemental shield. Or, Monster_Apparatus_Perpetual's helper mobs shouldn't die before their summoner. * Look through ConfigAbility (AbilityData in GC) like Invoker_Herald_Water_StateControl. If any AbilityModifier within specifies state Limbo and properties.Actor_HpThresholdRatio, account for this threshold in GameEntity::damage. * Don't let the entity die while in limbo. They will be killed by other events.
- Loading branch information
Showing
9 changed files
with
199 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
src/main/java/emu/grasscutter/data/binout/config/fields/ConfigCombatSummon.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package emu.grasscutter.data.binout.config.fields; | ||
|
||
import lombok.*; | ||
import lombok.experimental.FieldDefaults; | ||
import java.util.List; | ||
|
||
@Data | ||
public class ConfigCombatSummon { | ||
List<SummonTag> summonTags; | ||
|
||
@Getter | ||
public final class SummonTag { | ||
int summonTag; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
src/main/java/emu/grasscutter/game/ability/actions/ActionSummon.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
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.game.ability.Ability; | ||
import emu.grasscutter.game.entity.*; | ||
import emu.grasscutter.game.world.*; | ||
import emu.grasscutter.server.packet.send.PacketMonsterSummonTagNotify; | ||
import emu.grasscutter.net.proto.EPKDEHOJFLIOuterClass.EPKDEHOJFLI; | ||
import emu.grasscutter.utils.*; | ||
|
||
@AbilityAction(AbilityModifierAction.Type.Summon) | ||
public class ActionSummon extends AbilityActionHandler { | ||
@Override | ||
public synchronized boolean execute( | ||
Ability ability, AbilityModifierAction action, ByteString abilityData, GameEntity target) { | ||
EPKDEHOJFLI summonPosRot = null; | ||
try { | ||
// In game version 4.0, summoned entity's | ||
// position and rotation are packed in EPKDEHOJFLI. | ||
// This is packet AbilityActionSummon and has two fields: | ||
// 4: Vector pos | ||
// 13: Vector rot | ||
summonPosRot = EPKDEHOJFLI.parseFrom(abilityData); | ||
} catch (InvalidProtocolBufferException e) { | ||
Grasscutter.getLogger().error("Failed to parse abilityData: {}", Utils.bytesToHex(abilityData.toByteArray())); | ||
return false; | ||
} | ||
|
||
var pos = new Position(summonPosRot.getPos()); | ||
var rot = new Position(summonPosRot.getRot()); | ||
var monsterId = action.monsterID; | ||
|
||
var scene = target.getScene(); | ||
|
||
var monsterData = GameData.getMonsterDataMap().get(monsterId); | ||
if (monsterData == null) { | ||
Grasscutter.getLogger().error("Failed to find monster by ID {}", monsterId); | ||
return false; | ||
} | ||
|
||
if (target instanceof EntityMonster ownerEntity) { | ||
var level = scene.getLevelForMonster(0, ownerEntity.getLevel()); | ||
var entity = new EntityMonster(scene, monsterData, pos, rot, level); | ||
ownerEntity.getSummonTagMap().put(action.summonTag, entity); | ||
entity.setSummonedTag(action.summonTag); | ||
entity.setOwnerEntityId(target.getId()); | ||
scene.addEntity(entity); | ||
scene.getPlayers().get(0).sendPacket(new PacketMonsterSummonTagNotify(ownerEntity)); | ||
|
||
Grasscutter.getLogger().trace("Spawned entityId {} monsterId {} pos {} rot {}, target { {} }, action { {} }", | ||
entity.getId(), monsterId, pos, rot, target, action); | ||
|
||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
src/main/java/emu/grasscutter/server/packet/send/PacketMonsterSummonTagNotify.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package emu.grasscutter.server.packet.send; | ||
|
||
import emu.grasscutter.game.entity.EntityMonster; | ||
import emu.grasscutter.game.player.Player; | ||
import emu.grasscutter.game.world.Scene; | ||
import emu.grasscutter.net.packet.*; | ||
import emu.grasscutter.net.proto.MonsterSummonTagNotifyOuterClass.MonsterSummonTagNotify; | ||
import java.util.*; | ||
import static java.util.Map.entry; | ||
|
||
public class PacketMonsterSummonTagNotify extends BasePacket { | ||
|
||
public PacketMonsterSummonTagNotify(EntityMonster monsterEntity) { | ||
super(PacketOpcodes.MonsterSummonTagNotify); | ||
|
||
var proto = | ||
MonsterSummonTagNotify.newBuilder() | ||
.setMonsterEntityId(monsterEntity.getId()); | ||
monsterEntity.getSummonTagMap().forEach((k, v) -> proto.putSummonTagMap(k, v == null ? 0 : 1)); | ||
|
||
this.setData(proto.build()); | ||
} | ||
} |