Skip to content

Commit

Permalink
Stub creature possession
Browse files Browse the repository at this point in the history
  • Loading branch information
tonihele committed Jul 21, 2024
1 parent f34f51f commit d6683c5
Show file tree
Hide file tree
Showing 21 changed files with 323 additions and 43 deletions.
44 changes: 44 additions & 0 deletions src/toniarts/openkeeper/game/component/Possessed.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2014-2024 OpenKeeper
*
* OpenKeeper is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenKeeper is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenKeeper. If not, see <http://www.gnu.org/licenses/>.
*/
package toniarts.openkeeper.game.component;

import com.simsilica.es.EntityComponent;

/**
* Simple tagging component for entity being possessed
*
* @author Toni Helenius <[email protected]>
*/
public class Possessed implements EntityComponent {

/**
* We mark the mana drain here so that we can easily get the information.
* Mana component should be used in other calculations
*/
public int manaDrain;
public double manaCheckTime;

public Possessed() {
// For serialization
}

public Possessed(int manaDrain, double manaCheckTime) {
this.manaDrain = manaDrain;
this.manaCheckTime = manaCheckTime;
}

}
7 changes: 7 additions & 0 deletions src/toniarts/openkeeper/game/controller/GameController.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.badlogic.gdx.ai.GdxAI;
import com.jme3.util.SafeArrayList;
import com.simsilica.es.EntityData;
import com.simsilica.es.EntityId;
import java.io.IOException;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
Expand Down Expand Up @@ -650,6 +651,12 @@ public GameResult getGameResult() {
return gameResult;
}

@Override
public void setPossession(EntityId target, short playerId) {
players.get(playerId).setPossession(target != null);
playerService.setPossession(target, playerId);
}

@Override
public void close() {
if (steeringCalculatorLoop != null) {
Expand Down
9 changes: 9 additions & 0 deletions src/toniarts/openkeeper/game/controller/IGameController.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package toniarts.openkeeper.game.controller;

import com.simsilica.es.EntityId;
import java.util.Collection;
import toniarts.openkeeper.game.data.GameResult;
import toniarts.openkeeper.game.logic.IEntityPositionLookup;
Expand Down Expand Up @@ -71,4 +72,12 @@ public interface IGameController {

public IGameWorldController getGameWorldController();

/**
* Set player possession mode on/off
*
* @param target possession target, null if possession ends
* @param playerId player ID that posesses
*/
public void setPossession(EntityId target, short playerId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public void createShot(short shotTypeId, int shotData1, int shotData2, short pla
objectsController.loadObject((short) shotData1, playerId, position, 0);
}
case POSSESS_CREATURE -> {

creaturesController.createController(target).setPossession(true);
}
case MODIFY_HEALTH -> {
EntityController.setDamage(entityData, target, -shotData1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import toniarts.openkeeper.game.component.Gold;
import toniarts.openkeeper.game.component.Health;
import toniarts.openkeeper.game.component.InHand;
import toniarts.openkeeper.game.component.Mana;
import toniarts.openkeeper.game.component.Mobile;
import toniarts.openkeeper.game.component.Navigation;
import toniarts.openkeeper.game.component.Objective;
Expand All @@ -55,6 +56,7 @@
import toniarts.openkeeper.game.component.PlayerObjective;
import toniarts.openkeeper.game.component.PortalGem;
import toniarts.openkeeper.game.component.Position;
import toniarts.openkeeper.game.component.Possessed;
import toniarts.openkeeper.game.component.RoomStorage;
import toniarts.openkeeper.game.component.Slapped;
import toniarts.openkeeper.game.component.TaskComponent;
Expand Down Expand Up @@ -1253,4 +1255,37 @@ public boolean isRecuperating() {
return entityData.getComponent(entityId, CreatureRecuperating.class) != null;
}

@Override
public void setPossession(boolean possessed) {
if (possessed) {
startPossession();
} else {
endPossession();
}
}

private void startPossession() {
CreatureComponent creatureComponent = entityData.getComponent(entityId, CreatureComponent.class);
int manaDrain = creatureComponent != null ? creatureComponent.posessionManaCost : 0;
Mana mana = entityData.getComponent(entityId, Mana.class);
entityData.setComponent(entityId, new Mana(mana != null ? -manaDrain - mana.manaGeneration : -manaDrain));
entityData.setComponent(entityId, new Possessed(manaDrain, gameTimer.getGameTime()));
entityData.removeComponent(entityId, CreatureAi.class);
entityData.removeComponent(entityId, Navigation.class);
}

private void endPossession() {
entityData.setComponent(entityId, new CreatureAi(gameTimer.getGameTime(), CreatureState.IDLE, getCreature().getCreatureId()));

// Return the mana flow
Possessed possessed = entityData.getComponent(entityId, Possessed.class);
Mana mana = entityData.getComponent(entityId, Mana.class);
int manaGeneration = mana.manaGeneration + possessed.manaDrain;
if (manaGeneration == 0) {
entityData.removeComponent(entityId, Mana.class);
} else {
entityData.setComponent(entityId, new Mana(manaGeneration));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -247,4 +247,11 @@ public interface ICreatureController extends IGameLogicUpdatable, INavigable, IE
*/
public boolean isRecuperating();

/**
* Sets creature possession on/off
*
* @param possessed should the creature be posessed or AI driven
*/
public void setPossession(boolean possessed);

}
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,8 @@ public void addListener(PlayerManaListener listener) {
public void removeListener(PlayerManaListener listener) {
listeners.remove(listener);
}

public boolean hasEnoughMana(int manaDrain) {
return keeper.getMana() - manaDrain + keeper.getManaGain() - keeper.getManaLoose() > 0;
}
}
9 changes: 9 additions & 0 deletions src/toniarts/openkeeper/game/data/Keeper.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class Keeper implements Comparable<Keeper>, IIndexable, Savable {
private int manaLoose;
private int maxMana;
private Point dungeonHeartLocation;
private boolean possession;
private List<ResearchableEntity> availableRooms = new ArrayList<>();
private List<ResearchableEntity> availableSpells = new ArrayList<>();
private List<Short> availableCreatures = new ArrayList<>();
Expand Down Expand Up @@ -219,6 +220,14 @@ public void setDungeonHeartLocation(Point dungeonHeartLocation) {
this.dungeonHeartLocation = dungeonHeartLocation;
}

public boolean isPossession() {
return possession;
}

public void setPossession(boolean possession) {
this.possession = possession;
}

public List<ResearchableEntity> getAvailableRooms() {
return availableRooms;
}
Expand Down
107 changes: 107 additions & 0 deletions src/toniarts/openkeeper/game/logic/PossessedSystem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (C) 2014-2024 OpenKeeper
*
* OpenKeeper is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenKeeper is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenKeeper. If not, see <http://www.gnu.org/licenses/>.
*/
package toniarts.openkeeper.game.logic;

import com.simsilica.es.Entity;
import com.simsilica.es.EntityData;
import com.simsilica.es.EntitySet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import toniarts.openkeeper.game.component.Owner;
import toniarts.openkeeper.game.component.Possessed;
import toniarts.openkeeper.game.controller.IGameController;
import toniarts.openkeeper.game.controller.IPlayerController;
import toniarts.openkeeper.game.controller.player.PlayerManaControl;

/**
* Maintains possessed state, sees when we need to stop possessing
*
* @author Toni Helenius <[email protected]>
*/
public class PossessedSystem implements IGameLogicUpdatable {

private final EntitySet possessedEntities;
private final Map<Short, PlayerManaControl> manaControls;
private final EntityData entityData;
private final IGameController gameController;

public PossessedSystem(Collection<IPlayerController> playerControllers, EntityData entityData, IGameController gameController) {
this.gameController = gameController;
this.entityData = entityData;
manaControls = HashMap.newHashMap(playerControllers.size());
for (IPlayerController playerController : playerControllers) {
PlayerManaControl manaControl = playerController.getManaControl();
if (manaControl != null) {
manaControls.put(playerController.getKeeper().getId(), manaControl);
}
}

// Listen for posessed entities
possessedEntities = entityData.getEntities(Possessed.class, Owner.class);
processAddedEntities(possessedEntities);
}

@Override
public void processTick(float tpf, double gameTime) {
if (possessedEntities.applyChanges()) {

processAddedEntities(possessedEntities.getAddedEntities());

processDeletedEntities(possessedEntities.getRemovedEntities());
}

for (Entity entity : possessedEntities) {

// See if the player is running out of mana
Possessed possessed = entity.get(Possessed.class);
Owner owner = entity.get(Owner.class);
if (possessed.manaCheckTime + 1 < gameTime) {
continue;
}

if (!manaControls.get(owner.ownerId).hasEnoughMana(possessed.manaDrain)) {
entityData.removeComponent(entity.getId(), Possessed.class);
} else {
entityData.setComponent(entity.getId(), new Possessed(possessed.manaDrain, gameTime));
}
}
}

@Override
public void start() {

}

@Override
public void stop() {
possessedEntities.release();
}

private void processAddedEntities(Set<Entity> entities) {
for (Entity entity : entities) {
gameController.setPossession(entity.getId(), entity.get(Owner.class).ownerId);
}
}

private void processDeletedEntities(Set<Entity> entities) {
for (Entity entity : entities) {
gameController.setPossession(null, entity.get(Owner.class).ownerId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -417,5 +417,12 @@ public void onResearchStatusChanged(short keeperId, ResearchableEntity researcha
l.onResearchStatusChanged(keeperId, researchableEntity);
}
}

@Override
public void setPossession(EntityId target) {
for (GameSessionListener l : listeners.getArray()) {
l.setPossession(target);
}
}
}
}
15 changes: 15 additions & 0 deletions src/toniarts/openkeeper/game/network/game/GameHostedService.java
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,16 @@ public void onResearchStatusChanged(short keeperId, ResearchableEntity researcha
}
}

@Override
public void setPossession(EntityId target, short playerId) {
for (Map.Entry<ClientInfo, GameSessionImpl> gameSession : players.entrySet()) {
if (gameSession.getKey().getKeeper().getId() == playerId) {
gameSession.getValue().setPossession(target);
break;
}
}
}

private class ServerMessageListener implements MessageListener<HostedConnection> {

public ServerMessageListener() {
Expand Down Expand Up @@ -698,5 +708,10 @@ public void onResearchStatusChanged(short keeperId, ResearchableEntity researcha
getCallback().onResearchStatusChanged(keeperId, researchableEntity);
}

@Override
public void setPossession(EntityId target) {
getCallback().setPossession(target);
}

}
}
5 changes: 5 additions & 0 deletions src/toniarts/openkeeper/game/state/GameClientState.java
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,11 @@ private Comparable getResearchableEntityType(KwdFile kwdFile, ResearchableType r

return null;
}

@Override
public void setPossession(EntityId target) {
playerState.setPossession(target);
}
}

public IMapInformation getMapClientService() {
Expand Down
Loading

0 comments on commit d6683c5

Please sign in to comment.