93 lines
3.4 KiB
Java
93 lines
3.4 KiB
Java
package com.disklexar.mmorpg.combat;
|
|
|
|
import com.disklexar.mmorpg.MmorpgPlugin;
|
|
import com.disklexar.mmorpg.core.service.Service;
|
|
import com.disklexar.mmorpg.player.OnlinePlayer;
|
|
import com.disklexar.mmorpg.player.OnlinePlayerRegistry;
|
|
import com.disklexar.mmorpg.player.PlayerSessionService;
|
|
import com.disklexar.mmorpg.player.model.PlayerProfile;
|
|
import com.disklexar.mmorpg.rpg.power.PowerCatalog;
|
|
import com.hypixel.hytale.component.Ref;
|
|
import com.hypixel.hytale.component.Store;
|
|
import com.hypixel.hytale.protocol.MovementSettings;
|
|
import com.hypixel.hytale.server.core.entity.entities.player.movement.MovementManager;
|
|
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
|
|
|
import javax.annotation.Nonnull;
|
|
import java.util.concurrent.ScheduledFuture;
|
|
|
|
/**
|
|
* Reconciles passive movement effects every couple of seconds.
|
|
* <p>
|
|
* The "Sprinter" power grants {@code +10%} base movement speed while the player is out of combat;
|
|
* the bonus is removed while in combat and restored afterwards.
|
|
*/
|
|
public final class PassiveEffectService implements Service {
|
|
|
|
private static final long RECONCILE_PERIOD = 2_000L;
|
|
|
|
private final MmorpgScheduler scheduler;
|
|
private final OnlinePlayerRegistry online;
|
|
private final PlayerSessionService sessions;
|
|
private final CombatStateService combatState;
|
|
|
|
private ScheduledFuture<?> task;
|
|
|
|
public PassiveEffectService(
|
|
@Nonnull MmorpgPlugin plugin,
|
|
@Nonnull MmorpgScheduler scheduler,
|
|
@Nonnull OnlinePlayerRegistry online,
|
|
@Nonnull PlayerSessionService sessions,
|
|
@Nonnull CombatStateService combatState) {
|
|
this.scheduler = scheduler;
|
|
this.online = online;
|
|
this.sessions = sessions;
|
|
this.combatState = combatState;
|
|
}
|
|
|
|
@Override
|
|
public void start() {
|
|
task = scheduler.runRepeating(this::reconcileAll, RECONCILE_PERIOD, RECONCILE_PERIOD);
|
|
}
|
|
|
|
@Override
|
|
public void shutdown() {
|
|
if (task != null) {
|
|
task.cancel(false);
|
|
task = null;
|
|
}
|
|
}
|
|
|
|
private void reconcileAll() {
|
|
for (OnlinePlayer player : online.all()) {
|
|
PlayerProfile profile = sessions.getSession(player.uuid());
|
|
if (profile == null) {
|
|
continue;
|
|
}
|
|
boolean sprinter = profile.getPowers().contains(PowerCatalog.SPRINTER.id());
|
|
boolean active = sprinter && !combatState.isInCombat(player.uuid());
|
|
player.world().execute(() -> applySpeed(player, active));
|
|
}
|
|
}
|
|
|
|
private void applySpeed(@Nonnull OnlinePlayer player, boolean buffed) {
|
|
Store<EntityStore> store = player.world().getEntityStore().getStore();
|
|
Ref<EntityStore> ref = player.entityRef();
|
|
MovementManager movement = store.getComponent(ref, MovementManager.getComponentType());
|
|
if (movement == null) {
|
|
return;
|
|
}
|
|
MovementSettings defaults = movement.getDefaultSettings();
|
|
MovementSettings current = movement.getSettings();
|
|
if (defaults == null || current == null) {
|
|
return;
|
|
}
|
|
float baseline = defaults.baseSpeed;
|
|
float target = buffed ? baseline * (float) (1.0 + PowerCatalog.SPRINTER_SPEED_BONUS) : baseline;
|
|
if (Math.abs(current.baseSpeed - target) > 0.0001f) {
|
|
current.baseSpeed = target;
|
|
movement.update(player.playerRef().getPacketHandler());
|
|
}
|
|
}
|
|
}
|