mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-19 10:24:47 +01:00
Support Team Toggle in Tower & Refactor MonsterTide
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
package emu.grasscutter.scripts.service;
|
||||
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.def.MonsterData;
|
||||
import emu.grasscutter.data.def.WorldLevelData;
|
||||
import emu.grasscutter.game.entity.EntityMonster;
|
||||
import emu.grasscutter.scripts.SceneScriptManager;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.SceneMonster;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ScriptMonsterSpawnService {
|
||||
|
||||
private final SceneScriptManager sceneScriptManager;
|
||||
private final List<Consumer<EntityMonster>> onMonsterCreatedListener = new ArrayList<>();
|
||||
|
||||
private final List<Consumer<EntityMonster>> onMonsterDeadListener = new ArrayList<>();
|
||||
|
||||
public ScriptMonsterSpawnService(SceneScriptManager sceneScriptManager){
|
||||
this.sceneScriptManager = sceneScriptManager;
|
||||
}
|
||||
|
||||
public void addMonsterCreatedListener(Consumer<EntityMonster> consumer){
|
||||
onMonsterCreatedListener.add(consumer);
|
||||
}
|
||||
public void addMonsterDeadListener(Consumer<EntityMonster> consumer){
|
||||
onMonsterCreatedListener.add(consumer);
|
||||
}
|
||||
|
||||
public void onMonsterDead(EntityMonster entityMonster){
|
||||
onMonsterCreatedListener.stream().forEach(l -> l.accept(entityMonster));
|
||||
}
|
||||
public void spawnMonster(int groupId, SceneMonster monster) {
|
||||
if(monster == null){
|
||||
return;
|
||||
}
|
||||
|
||||
MonsterData data = GameData.getMonsterDataMap().get(monster.monster_id);
|
||||
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate level
|
||||
int level = monster.level;
|
||||
|
||||
if (sceneScriptManager.getScene().getDungeonData() != null) {
|
||||
level = sceneScriptManager.getScene().getDungeonData().getShowLevel();
|
||||
} else if (sceneScriptManager.getScene().getWorld().getWorldLevel() > 0) {
|
||||
WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(sceneScriptManager.getScene().getWorld().getWorldLevel());
|
||||
|
||||
if (worldLevelData != null) {
|
||||
level = worldLevelData.getMonsterLevel();
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn mob
|
||||
EntityMonster entity = new EntityMonster(sceneScriptManager.getScene(), data, monster.pos, level);
|
||||
entity.getRotation().set(monster.rot);
|
||||
entity.setGroupId(groupId);
|
||||
entity.setConfigId(monster.config_id);
|
||||
|
||||
onMonsterCreatedListener.forEach(action -> action.accept(entity));
|
||||
|
||||
sceneScriptManager.getScene().addEntity(entity);
|
||||
|
||||
sceneScriptManager.callEvent(EventType.EVENT_ANY_MONSTER_LIVE, new ScriptArgs(entity.getConfigId()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package emu.grasscutter.scripts.service;
|
||||
|
||||
import emu.grasscutter.game.entity.EntityMonster;
|
||||
import emu.grasscutter.scripts.SceneScriptManager;
|
||||
import emu.grasscutter.scripts.constants.EventType;
|
||||
import emu.grasscutter.scripts.data.SceneGroup;
|
||||
import emu.grasscutter.scripts.data.SceneMonster;
|
||||
import emu.grasscutter.scripts.data.ScriptArgs;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ScriptMonsterTideService {
|
||||
private final SceneScriptManager sceneScriptManager;
|
||||
private final SceneGroup currentGroup;
|
||||
private final AtomicInteger monsterAlive;
|
||||
private final AtomicInteger monsterTideCount;
|
||||
private final AtomicInteger monsterKillCount;
|
||||
private final int monsterSceneLimit;
|
||||
private final ConcurrentLinkedQueue<Integer> monsterConfigOrders;
|
||||
|
||||
public ScriptMonsterTideService(SceneScriptManager sceneScriptManager,
|
||||
SceneGroup group, int tideCount, int monsterSceneLimit, Integer[] ordersConfigId){
|
||||
this.sceneScriptManager = sceneScriptManager;
|
||||
this.currentGroup = group;
|
||||
this.monsterSceneLimit = monsterSceneLimit;
|
||||
this.monsterTideCount = new AtomicInteger(tideCount);
|
||||
this.monsterKillCount = new AtomicInteger(0);
|
||||
this.monsterAlive = new AtomicInteger(0);
|
||||
this.monsterConfigOrders = new ConcurrentLinkedQueue<>(List.of(ordersConfigId));
|
||||
|
||||
this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterCreatedListener(this::onMonsterCreated);
|
||||
this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterDeadListener(this::onMonsterDead);
|
||||
// spawn the first turn
|
||||
for (int i = 0; i < this.monsterSceneLimit; i++) {
|
||||
this.sceneScriptManager.getScriptMonsterSpawnService().spawnMonster(group.id, getNextMonster());
|
||||
}
|
||||
}
|
||||
|
||||
public void onMonsterCreated(EntityMonster entityMonster){
|
||||
if(this.monsterSceneLimit > 0){
|
||||
this.monsterTideCount.decrementAndGet();
|
||||
this.monsterAlive.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
public SceneMonster getNextMonster(){
|
||||
var nextId = this.monsterConfigOrders.poll();
|
||||
if(currentGroup.monsters.containsKey(nextId)){
|
||||
return currentGroup.monsters.get(nextId);
|
||||
}
|
||||
// TODO some monster config_id do not exist in groups, so temporarily set it to the first
|
||||
return currentGroup.monsters.values().stream().findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public void onMonsterDead(EntityMonster entityMonster){
|
||||
if(this.monsterSceneLimit <= 0){
|
||||
return;
|
||||
}
|
||||
if(this.monsterAlive.decrementAndGet() >= this.monsterSceneLimit) {
|
||||
// maybe not happen
|
||||
return;
|
||||
}
|
||||
this.monsterKillCount.incrementAndGet();
|
||||
if(this.monsterTideCount.get() > 0){
|
||||
// add more
|
||||
this.sceneScriptManager.getScriptMonsterSpawnService().spawnMonster(this.currentGroup.id, getNextMonster());
|
||||
}else if(this.monsterAlive.get() == 0){
|
||||
// spawn the last turn of monsters
|
||||
this.sceneScriptManager.callEvent(EventType.EVENT_MONSTER_TIDE_DIE, new ScriptArgs(this.monsterKillCount.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user