Support Team Toggle in Tower & Refactor MonsterTide

This commit is contained in:
Akka
2022-05-09 15:39:49 +08:00
parent ccdce68434
commit 65c93a747c
10 changed files with 320 additions and 115 deletions

View File

@@ -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()));
}
}

View File

@@ -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()));
}
}
}