diff --git a/data/TowerSchedule.json b/data/TowerSchedule.json index b93100645..e10416a20 100644 --- a/data/TowerSchedule.json +++ b/data/TowerSchedule.json @@ -1,5 +1,5 @@ { - "scheduleId" : 1, + "scheduleId" : 45, "scheduleStartTime" : "2022-05-01T00:00:00+08:00", "nextScheduleChangeTime" : "2022-05-30T00:00:00+08:00" } \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java b/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java index 2e07f0058..a13f1a611 100644 --- a/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java +++ b/src/main/java/emu/grasscutter/game/dungeons/DungeonChallenge.java @@ -28,14 +28,20 @@ public class DungeonChallenge { private int challengeId; private boolean success; private boolean progress; - + /** + * has more challenge + */ + private boolean stage; private int score; private int objective = 0; private IntSet rewardedPlayers; - public DungeonChallenge(Scene scene, SceneGroup group) { + public DungeonChallenge(Scene scene, SceneGroup group, int challengeId, int challengeIndex, int objective) { this.scene = scene; this.group = group; + this.challengeId = challengeId; + this.challengeIndex = challengeIndex; + this.objective = objective; this.setRewardedPlayers(new IntOpenHashSet()); } @@ -86,7 +92,15 @@ public class DungeonChallenge { public int getScore() { return score; } - + + public boolean isStage() { + return stage; + } + + public void setStage(boolean stage) { + this.stage = stage; + } + public int getTimeLimit() { return 600; } @@ -112,7 +126,7 @@ public class DungeonChallenge { if (this.isSuccess()) { // Call success script event this.getScene().getScriptManager().callEvent(EventType.EVENT_CHALLENGE_SUCCESS, null); - + // Settle settle(); } else { @@ -122,8 +136,10 @@ public class DungeonChallenge { private void settle() { getScene().getDungeonSettleObservers().forEach(o -> o.onDungeonSettle(getScene())); - - getScene().getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE, new ScriptArgs(this.isSuccess() ? 1 : 0)); + + if(!stage){ + getScene().getScriptManager().callEvent(EventType.EVENT_DUNGEON_SETTLE, new ScriptArgs(this.isSuccess() ? 1 : 0)); + } } public void onMonsterDie(EntityMonster entity) { diff --git a/src/main/java/emu/grasscutter/game/entity/EntityMonster.java b/src/main/java/emu/grasscutter/game/entity/EntityMonster.java index f8a96a808..491aaa3f4 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityMonster.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityMonster.java @@ -116,14 +116,18 @@ public class EntityMonster extends GameEntity { if (this.getSpawnEntry() != null) { this.getScene().getDeadSpawnedEntities().add(getSpawnEntry()); } + // first set the challenge data + if (getScene().getChallenge() != null && getScene().getChallenge().getGroup().id == this.getGroupId()) { + getScene().getChallenge().onMonsterDie(this); + } if (getScene().getScriptManager().isInit() && this.getGroupId() > 0) { if(getScene().getScriptManager().getScriptMonsterSpawnService() != null){ getScene().getScriptManager().getScriptMonsterSpawnService().onMonsterDead(this); } - getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, null); - } - if (getScene().getChallenge() != null && getScene().getChallenge().getGroup().id == this.getGroupId()) { - getScene().getChallenge().onMonsterDie(this); + // prevent spawn monster after success + if(getScene().getChallenge() != null && getScene().getChallenge().inProgress()){ + getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, null); + } } } diff --git a/src/main/java/emu/grasscutter/game/tower/TowerManager.java b/src/main/java/emu/grasscutter/game/tower/TowerManager.java index cac848ea6..790efc7f6 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerManager.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerManager.java @@ -122,7 +122,7 @@ public class TowerManager { if(!hasNextLevel()){ // set up the next floor - recordMap.put(getNextFloorId(), new TowerLevelRecord(getNextFloorId())); + recordMap.putIfAbsent(getNextFloorId(), new TowerLevelRecord(getNextFloorId())); player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(getNextFloorId(), 1)); }else{ player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, getCurrentLevel())); diff --git a/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java b/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java index bc0e896f5..5b86aa298 100644 --- a/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java +++ b/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java @@ -373,6 +373,12 @@ public class SceneScriptManager { new ScriptMonsterTideService(this, group, tideCount, sceneLimit, ordersConfigId); } + public void unloadCurrentMonsterTide(){ + if(this.getScriptMonsterTideService() == null){ + return; + } + this.getScriptMonsterTideService().unload(); + } public void spawnMonstersByConfigId(int configId, int delayTime) { // TODO delay this.scriptMonsterSpawnService.spawnMonster(this.currentGroup.id, this.currentGroup.monsters.get(configId)); @@ -395,12 +401,15 @@ public class SceneScriptManager { if (params != null) { args = CoerceJavaToLua.coerce(params); } - + + ScriptLib.logger.trace("Call Condition Trigger {}", trigger); ret = safetyCall(trigger.condition, condition, args); } if (ret.isboolean() && ret.checkboolean()) { + ScriptLib.logger.trace("Call Action Trigger {}", trigger); LuaValue action = (LuaValue) this.getBindings().get(trigger.action); + // TODO impl the param of SetGroupVariableValueByGroup var arg = new ScriptArgs(); arg.param2 = 100; var args = CoerceJavaToLua.coerce(arg); diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLib.java b/src/main/java/emu/grasscutter/scripts/ScriptLib.java index 0d686dd5a..b7fb5939f 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLib.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLib.java @@ -147,6 +147,12 @@ public class ScriptLib { return 1; } + // avoid spawn wrong monster + if(getSceneScriptManager().getScene().getChallenge() != null) + if(!getSceneScriptManager().getScene().getChallenge().inProgress() || + getSceneScriptManager().getScene().getChallenge().getGroup().id != groupId){ + return 0; + } this.getSceneScriptManager().spawnMonstersInGroup(group, suite); return 0; @@ -175,13 +181,13 @@ public class ScriptLib { return 0; } - DungeonChallenge challenge = new DungeonChallenge(getSceneScriptManager().getScene(), group); - challenge.setChallengeId(challengeId); - challenge.setChallengeIndex(challengeIndex); - challenge.setObjective(objective); - + DungeonChallenge challenge = new DungeonChallenge(getSceneScriptManager().getScene(), + group, challengeId, challengeIndex, objective); + // set if tower first stage (6-1) + challenge.setStage(getSceneScriptManager().getVariables().getOrDefault("stage", -1) == 0); + getSceneScriptManager().getScene().setChallenge(challenge); - + challenge.start(); return 0; } @@ -336,9 +342,19 @@ public class ScriptLib { logger.debug("[LUA] Call TowerMirrorTeamSetUp with {},{}", team,var1); + getSceneScriptManager().unloadCurrentMonsterTide(); getSceneScriptManager().getScene().getPlayers().get(0).getTowerManager().mirrorTeamSetUp(team-1); return 0; } + public int CreateGadget(LuaTable table){ + logger.debug("[LUA] Call CreateGadget with {}", + printTable(table)); + var configId = table.get("config_id").toint(); + + //TODO + + return 0; + } } diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java b/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java index a627f67c4..301fdb8e0 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneTrigger.java @@ -21,4 +21,15 @@ public class SceneTrigger { return name.hashCode(); } + @Override + public String toString() { + return "SceneTrigger{" + + "name='" + name + '\'' + + ", config_id=" + config_id + + ", event=" + event + + ", source='" + source + '\'' + + ", condition='" + condition + '\'' + + ", action='" + action + '\'' + + '}'; + } } diff --git a/src/main/java/emu/grasscutter/scripts/listener/ScriptMonsterListener.java b/src/main/java/emu/grasscutter/scripts/listener/ScriptMonsterListener.java new file mode 100644 index 000000000..b3b99fd61 --- /dev/null +++ b/src/main/java/emu/grasscutter/scripts/listener/ScriptMonsterListener.java @@ -0,0 +1,8 @@ +package emu.grasscutter.scripts.listener; + +import emu.grasscutter.game.entity.EntityMonster; + +public interface ScriptMonsterListener { + + void onNotify(EntityMonster sceneMonster); +} diff --git a/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java index 0d6baf25d..fdc4941f2 100644 --- a/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java +++ b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterSpawnService.java @@ -8,31 +8,36 @@ import emu.grasscutter.scripts.SceneScriptManager; import emu.grasscutter.scripts.constants.EventType; import emu.grasscutter.scripts.data.SceneMonster; import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.scripts.listener.ScriptMonsterListener; import java.util.ArrayList; import java.util.List; -import java.util.function.Consumer; public class ScriptMonsterSpawnService { private final SceneScriptManager sceneScriptManager; - private final List> onMonsterCreatedListener = new ArrayList<>(); + private final List onMonsterCreatedListener = new ArrayList<>(); - private final List> onMonsterDeadListener = new ArrayList<>(); + private final List onMonsterDeadListener = new ArrayList<>(); public ScriptMonsterSpawnService(SceneScriptManager sceneScriptManager){ this.sceneScriptManager = sceneScriptManager; } - public void addMonsterCreatedListener(Consumer consumer){ - onMonsterCreatedListener.add(consumer); + public void addMonsterCreatedListener(ScriptMonsterListener scriptMonsterListener){ + onMonsterCreatedListener.add(scriptMonsterListener); } - public void addMonsterDeadListener(Consumer consumer){ - onMonsterDeadListener.add(consumer); + public void addMonsterDeadListener(ScriptMonsterListener scriptMonsterListener){ + onMonsterDeadListener.add(scriptMonsterListener); + } + public void removeMonsterCreatedListener(ScriptMonsterListener scriptMonsterListener){ + onMonsterCreatedListener.remove(scriptMonsterListener); + } + public void removeMonsterDeadListener(ScriptMonsterListener scriptMonsterListener){ + onMonsterDeadListener.remove(scriptMonsterListener); } - public void onMonsterDead(EntityMonster entityMonster){ - onMonsterDeadListener.forEach(l -> l.accept(entityMonster)); + onMonsterDeadListener.forEach(l -> l.onNotify(entityMonster)); } public void spawnMonster(int groupId, SceneMonster monster) { if(monster == null){ @@ -64,7 +69,7 @@ public class ScriptMonsterSpawnService { entity.setGroupId(groupId); entity.setConfigId(monster.config_id); - onMonsterCreatedListener.forEach(action -> action.accept(entity)); + onMonsterCreatedListener.forEach(action -> action.onNotify(entity)); sceneScriptManager.getScene().addEntity(entity); diff --git a/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java index 3cf186188..57d4735ba 100644 --- a/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java +++ b/src/main/java/emu/grasscutter/scripts/service/ScriptMonsterTideService.java @@ -6,6 +6,7 @@ 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 emu.grasscutter.scripts.listener.ScriptMonsterListener; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; @@ -19,6 +20,8 @@ public class ScriptMonsterTideService { private final AtomicInteger monsterKillCount; private final int monsterSceneLimit; private final ConcurrentLinkedQueue monsterConfigOrders; + private final OnMonsterCreated onMonsterCreated= new OnMonsterCreated(); + private final OnMonsterDead onMonsterDead= new OnMonsterDead(); public ScriptMonsterTideService(SceneScriptManager sceneScriptManager, SceneGroup group, int tideCount, int monsterSceneLimit, Integer[] ordersConfigId){ @@ -30,18 +33,21 @@ public class ScriptMonsterTideService { this.monsterAlive = new AtomicInteger(0); this.monsterConfigOrders = new ConcurrentLinkedQueue<>(List.of(ordersConfigId)); - this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterCreatedListener(this::onMonsterCreated); - this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterDeadListener(this::onMonsterDead); + this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterCreatedListener(onMonsterCreated); + this.sceneScriptManager.getScriptMonsterSpawnService().addMonsterDeadListener(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 class OnMonsterCreated implements ScriptMonsterListener{ + @Override + public void onNotify(EntityMonster sceneMonster) { + if(monsterSceneLimit > 0){ + monsterAlive.incrementAndGet(); + monsterTideCount.decrementAndGet(); + } } } @@ -54,21 +60,30 @@ public class ScriptMonsterTideService { return currentGroup.monsters.values().stream().findFirst().orElse(null); } - public void onMonsterDead(EntityMonster entityMonster){ - if(this.monsterSceneLimit <= 0){ - return; + public class OnMonsterDead implements ScriptMonsterListener { + @Override + public void onNotify(EntityMonster sceneMonster) { + if (monsterSceneLimit <= 0) { + return; + } + if (monsterAlive.decrementAndGet() >= monsterSceneLimit) { + // maybe not happen + return; + } + monsterKillCount.incrementAndGet(); + if (monsterTideCount.get() > 0) { + // add more + sceneScriptManager.getScriptMonsterSpawnService().spawnMonster(currentGroup.id, getNextMonster()); + } + // spawn the last turn of monsters + // fix the 5-2 + sceneScriptManager.callEvent(EventType.EVENT_MONSTER_TIDE_DIE, new ScriptArgs(monsterKillCount.get())); } - 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()); - } - // spawn the last turn of monsters - // fix the 5-2 - this.sceneScriptManager.callEvent(EventType.EVENT_MONSTER_TIDE_DIE, new ScriptArgs(this.monsterKillCount.get())); + + } + + public void unload(){ + this.sceneScriptManager.getScriptMonsterSpawnService().removeMonsterCreatedListener(onMonsterCreated); + this.sceneScriptManager.getScriptMonsterSpawnService().removeMonsterDeadListener(onMonsterDead); } }