mirror of
https://github.com/Anime-Game-Servers/Grasscutter-Quests.git
synced 2024-11-23 04:29:42 +00:00
Merge pull request #117 from scooterboo/patch-9
Now with 50% more seelies
This commit is contained in:
commit
bffaf4f956
@ -16,6 +16,7 @@ public class RoutePoint {
|
||||
private float waitTime; //optional
|
||||
private float targetVelocity; //optional
|
||||
private boolean hasReachEvent; //optional
|
||||
private boolean reachStop; //optional
|
||||
// rotRoundReachDir //optional Pos with optional values
|
||||
// rotRoundLeaveDir //optional Pos with optional values
|
||||
|
||||
|
@ -8,6 +8,7 @@ import emu.grasscutter.data.excels.GadgetData;
|
||||
import emu.grasscutter.game.ability.AbilityManager;
|
||||
import emu.grasscutter.game.entity.gadget.*;
|
||||
import emu.grasscutter.game.entity.gadget.platform.BaseRoute;
|
||||
import emu.grasscutter.game.entity.gadget.platform.ConfigRoute;
|
||||
import emu.grasscutter.game.entity.interfaces.ConfigAbilityDataAbilityEntity;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.EntityIdType;
|
||||
@ -187,6 +188,14 @@ public class EntityGadget extends EntityBaseGadget implements ConfigAbilityDataA
|
||||
.setSourceEntityId(this.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCreate(List<Player> players) {
|
||||
if (this.getMetaGadget() != null && !this.getMetaGadget().isStartRoute()) return;
|
||||
if (this.routeConfig == null) return;
|
||||
this.routeConfig.startRoute(this.getScene());
|
||||
players.forEach(p -> p.sendPacket(new PacketPlatformStartRouteNotify(this)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoved() {
|
||||
super.onRemoved();
|
||||
@ -225,9 +234,12 @@ public class EntityGadget extends EntityBaseGadget implements ConfigAbilityDataA
|
||||
return false;
|
||||
}
|
||||
|
||||
if(routeConfig.isStarted()){
|
||||
if (routeConfig.isStarted()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
schedulePlatform();
|
||||
|
||||
getScene().broadcastPacket(new PacketSceneTimeNotify(getScene()));
|
||||
routeConfig.startRoute(getScene());
|
||||
getScene().broadcastPacket(new PacketPlatformStartRouteNotify(this));
|
||||
@ -235,14 +247,42 @@ public class EntityGadget extends EntityBaseGadget implements ConfigAbilityDataA
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean schedulePlatform() {
|
||||
if (!(routeConfig instanceof ConfigRoute configRoute)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var route = this.getScene().getSceneRouteById(configRoute.getRouteId());
|
||||
|
||||
if (route == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var points = route.getPoints();
|
||||
|
||||
//restart platform if at end and told to start
|
||||
if (configRoute.getStartIndex() == points.length - 1) {
|
||||
configRoute.setStartIndex(0);
|
||||
}
|
||||
|
||||
val currIndex = configRoute.getStartIndex();
|
||||
if (currIndex == 0) {
|
||||
this.getScene().callPlatformEvent(this.getId());
|
||||
}
|
||||
|
||||
double distance = points[currIndex].getPos().computeDistance(points[currIndex + 1].getPos());
|
||||
double time = 1000 * distance / points[currIndex].getTargetVelocity();
|
||||
time += this.getScene().getSceneTime();
|
||||
this.getScene().getScheduledPlatforms().put(this.getId(), time);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean stopPlatform(){
|
||||
if(routeConfig == null){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!routeConfig.isStarted()){
|
||||
return true;
|
||||
}
|
||||
this.getScene().getScheduledPlatforms().remove(this.getId());
|
||||
routeConfig.stopRoute(getScene());
|
||||
getScene().broadcastPacket(new PacketPlatformStopRouteNotify(this));
|
||||
|
||||
|
@ -235,6 +235,13 @@ public abstract class GameEntity {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called right after this entity is added to the world
|
||||
*/
|
||||
public void afterCreate(List<Player> players) {
|
||||
|
||||
}
|
||||
|
||||
public void onRemoved() {
|
||||
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public abstract class BaseRoute {
|
||||
@Getter @Setter private Position startRot;
|
||||
@Getter @Setter private int startSceneTime;
|
||||
@Getter @Setter private int stopSceneTime;
|
||||
@Getter @Setter private int startIndex;
|
||||
|
||||
BaseRoute(Position startRot, boolean isStarted, boolean isActive) {
|
||||
this.startRot = startRot;
|
||||
@ -24,8 +25,8 @@ public abstract class BaseRoute {
|
||||
|
||||
BaseRoute(SceneGadget gadget) {
|
||||
this.startRot = new Position(gadget.getRot());
|
||||
this.isStarted = gadget.isStartRoute();
|
||||
this.isActive = gadget.isStartRoute();
|
||||
this.isStarted = false;
|
||||
this.isActive = true;
|
||||
}
|
||||
|
||||
public static BaseRoute fromSceneGadget(SceneGadget sceneGadget) {
|
||||
@ -38,22 +39,15 @@ public abstract class BaseRoute {
|
||||
}
|
||||
|
||||
public boolean startRoute(Scene scene) {
|
||||
if (this.isStarted) {
|
||||
return false;
|
||||
}
|
||||
this.isStarted = true;
|
||||
this.isActive = true;
|
||||
this.startSceneTime = scene.getSceneTime()+300;
|
||||
this.startSceneTime = scene.getSceneTime();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean stopRoute(Scene scene) {
|
||||
if (!this.isStarted) {
|
||||
return false;
|
||||
}
|
||||
this.isStarted = false;
|
||||
this.isActive = false;
|
||||
this.startSceneTime = scene.getSceneTime();
|
||||
this.stopSceneTime = scene.getSceneTime();
|
||||
|
||||
@ -95,6 +89,7 @@ public abstract class BaseRoute {
|
||||
if (!isStarted) {
|
||||
result.setStopSceneTime(stopSceneTime);
|
||||
}
|
||||
result.setStartIndex(startIndex);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.GameDepot;
|
||||
import emu.grasscutter.data.binout.SceneNpcBornEntry;
|
||||
import emu.grasscutter.data.binout.routes.Route;
|
||||
import emu.grasscutter.data.binout.routes.RouteType;
|
||||
import emu.grasscutter.data.excels.*;
|
||||
import emu.grasscutter.database.DatabaseHelper;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
@ -14,6 +15,7 @@ import emu.grasscutter.game.dungeons.challenge.WorldChallenge;
|
||||
import emu.grasscutter.game.dungeons.enums.DungeonPassConditionType;
|
||||
import emu.grasscutter.game.entity.*;
|
||||
import emu.grasscutter.game.entity.gadget.GadgetWorktop;
|
||||
import emu.grasscutter.game.entity.gadget.platform.ConfigRoute;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.player.TeamInfo;
|
||||
import emu.grasscutter.game.props.*;
|
||||
@ -89,6 +91,7 @@ public class Scene {
|
||||
private boolean weatherLoaded = false;
|
||||
|
||||
@Getter private final GameEntity sceneEntity;
|
||||
@Getter @Setter private Map<Integer, Double> scheduledPlatforms = new ConcurrentHashMap<>();
|
||||
|
||||
public Scene(World world, SceneData sceneData) {
|
||||
this.world = world;
|
||||
@ -264,12 +267,13 @@ public class Scene {
|
||||
public synchronized void addEntity(GameEntity entity) {
|
||||
addEntityDirectly(entity);
|
||||
broadcastPacket(new PacketSceneEntityAppearNotify(entity));
|
||||
entity.afterCreate(this.players);
|
||||
}
|
||||
|
||||
public synchronized void addEntityToSingleClient(Player player, GameEntity entity) {
|
||||
addEntityDirectly(entity);
|
||||
player.sendPacket(new PacketSceneEntityAppearNotify(entity));
|
||||
|
||||
entity.afterCreate(List.of(player));
|
||||
}
|
||||
|
||||
public void addEntities(Collection<? extends GameEntity> entities) {
|
||||
@ -295,7 +299,10 @@ public class Scene {
|
||||
|
||||
entities.forEach(this::addEntityDirectly);
|
||||
|
||||
chopped(entities.stream().toList(), 100).forEach(l -> broadcastPacket(new PacketSceneEntityAppearNotify(l, visionType)));
|
||||
chopped(entities.stream().toList(), 100).forEach(l -> {
|
||||
broadcastPacket(new PacketSceneEntityAppearNotify(l, visionType));
|
||||
l.forEach(x -> x.afterCreate(this.players));
|
||||
});
|
||||
}
|
||||
|
||||
private GameEntity removeEntityDirectly(GameEntity entity) {
|
||||
@ -342,6 +349,7 @@ public class Scene {
|
||||
entity != player.getTeamManager().getCurrentAvatarEntity()).toList();
|
||||
|
||||
player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_MEET));
|
||||
entities.forEach(x -> x.afterCreate(List.of(player)));
|
||||
}
|
||||
|
||||
public void handleAttack(AttackResult result) {
|
||||
@ -432,9 +440,11 @@ public class Scene {
|
||||
|
||||
this.entities.values().forEach(e -> e.onTick(getSceneTimeSeconds()));
|
||||
|
||||
checkPlatforms();
|
||||
checkNpcGroup();
|
||||
finishLoading();
|
||||
checkPlayerRespawn();
|
||||
|
||||
if (this.tickCount % 10 == 0) {
|
||||
broadcastPacket(new PacketSceneTimeNotify(this));
|
||||
}
|
||||
@ -600,6 +610,7 @@ public class Scene {
|
||||
if (!toAdd.isEmpty()) {
|
||||
toAdd.forEach(this::addEntityDirectly);
|
||||
broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_BORN));
|
||||
toAdd.forEach(x -> x.afterCreate(this.players));
|
||||
}
|
||||
if (!toRemove.isEmpty()) {
|
||||
toRemove.forEach(this::removeEntityDirectly);
|
||||
@ -945,6 +956,77 @@ public class Scene {
|
||||
return dungeonManager != null ? dungeonManager.getDungeonData().getId() : 0;
|
||||
}
|
||||
|
||||
private void checkPlatforms() {
|
||||
val curTime = this.getSceneTime();
|
||||
var iter = scheduledPlatforms.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
val entry = iter.next();
|
||||
val key = entry.getKey();
|
||||
val value = entry.getValue();
|
||||
if (value < curTime) {
|
||||
scheduledPlatforms.remove(key);
|
||||
val entity = getEntityById(key);
|
||||
// Deleted entity
|
||||
if (entity == null) return;
|
||||
// Not a platform
|
||||
if (!(entity instanceof EntityGadget entityGadget)) return;
|
||||
// No configRoute
|
||||
if (!(entityGadget.getRouteConfig() instanceof ConfigRoute configRoute)) return;
|
||||
// No route in file
|
||||
val route = this.getSceneRouteById(configRoute.getRouteId());
|
||||
if (route == null) return;
|
||||
|
||||
val points = route.getPoints();
|
||||
|
||||
// Increment the index
|
||||
var index = 1 + entityGadget.getRouteConfig().getStartIndex();
|
||||
if (index == points.length) index = 0;
|
||||
entityGadget.getRouteConfig().setStartIndex(index);
|
||||
|
||||
// Update position
|
||||
|
||||
entity.getPosition().set(points[index].getPos());
|
||||
|
||||
// If the point has a Reach Event:
|
||||
if (points[index].isHasReachEvent()) {
|
||||
callPlatformEvent(key);
|
||||
}
|
||||
|
||||
//if there is a Reach Stop, or we have reached the end, call stop
|
||||
if (points[index].isReachStop() || (index == points.length - 1 /*&& route.getType().equals(RouteType.OneWay)*/)) {
|
||||
entityGadget.stopPlatform();
|
||||
//otherwise, schedule the next one.
|
||||
} else {
|
||||
double distance;
|
||||
if (index == points.length - 1 && route.getType().equals(RouteType.Loop)) {
|
||||
distance = points[index].getPos().computeDistance(points[0].getPos());
|
||||
} else {
|
||||
distance = points[index].getPos().computeDistance(points[index + 1].getPos());
|
||||
}
|
||||
double time = 1000 * distance / points[index].getTargetVelocity();
|
||||
scheduledPlatforms.put(key, value + time);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean callPlatformEvent(int entityId) {
|
||||
val entity = getEntityById(entityId);
|
||||
if (entity == null) return false;
|
||||
if (!(entity instanceof EntityGadget entityGadget)) return false;
|
||||
if (!(entityGadget.getRouteConfig() instanceof ConfigRoute configRoute)) return false;
|
||||
|
||||
val groupId = entityGadget.getGroupId();
|
||||
val configId = entityGadget.getConfigId();
|
||||
val routeId = configRoute.getRouteId();
|
||||
val index = configRoute.getStartIndex();
|
||||
|
||||
this.scriptManager.callEvent(new ScriptArgs(groupId, EventType.EVENT_PLATFORM_REACH_POINT, configId, routeId)
|
||||
.setParam3(index)
|
||||
.setEventSource(configId));
|
||||
return true;
|
||||
}
|
||||
|
||||
public WeatherArea getWeatherArea(Position position) {
|
||||
val data = GameData.getWeatherAreaPointData().get(getId());
|
||||
if(data == null) return null;
|
||||
|
@ -1016,7 +1016,7 @@ public class SceneScriptManager {
|
||||
}
|
||||
|
||||
logger.warn("trying to cancel a timer that's not active {} {}", groupID, source);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// todo use killed monsters instead of spawned entites for check?
|
||||
|
@ -1466,7 +1466,8 @@ public class ScriptLibHandler extends BaseHandler implements org.anime_game_serv
|
||||
public int SetPlatformRouteId(GroupEventLuaContext context, int entityConfigId, int routeId) {
|
||||
logger.info("[LUA] Call SetPlatformRouteId {} {}", entityConfigId, routeId);
|
||||
|
||||
val entity = context.getSceneScriptManager().getScene().getEntityByConfigId(entityConfigId, context.getCurrentGroup().getGroupInfo().getId());
|
||||
val scene = context.getSceneScriptManager().getScene();
|
||||
val entity = scene.getEntityByConfigId(entityConfigId, context.getCurrentGroup().getGroupInfo().getId());
|
||||
if(entity == null){
|
||||
return 1;
|
||||
}
|
||||
@ -1486,7 +1487,10 @@ public class ScriptLibHandler extends BaseHandler implements org.anime_game_serv
|
||||
}
|
||||
|
||||
configRoute.setRouteId(routeId);
|
||||
context.getSceneScriptManager().getScene().broadcastPacket(new PacketPlatformChangeRouteNotify(entityGadget));
|
||||
configRoute.setStartSceneTime(scene.getSceneTime());
|
||||
configRoute.setStartIndex(0);
|
||||
entityGadget.schedulePlatform();
|
||||
scene.broadcastPacket(new PacketPlatformChangeRouteNotify(entityGadget));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user