@@ -0,0 +1,92 @@
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user