Skip to content

Commit

Permalink
Initial spell casting
Browse files Browse the repository at this point in the history
  • Loading branch information
tonihele committed Jul 17, 2024
1 parent 86b06f2 commit 9e7a525
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 39 deletions.
42 changes: 29 additions & 13 deletions src/toniarts/openkeeper/game/controller/CreaturesController.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import toniarts.openkeeper.game.component.CreatureComponent;
import toniarts.openkeeper.game.component.CreatureEfficiency;
import toniarts.openkeeper.game.component.CreatureExperience;
import toniarts.openkeeper.game.component.CreatureFall;
import toniarts.openkeeper.game.component.CreatureHunger;
import toniarts.openkeeper.game.component.CreatureImprisoned;
import toniarts.openkeeper.game.component.CreatureMeleeAttack;
Expand Down Expand Up @@ -73,7 +74,6 @@
import toniarts.openkeeper.tools.convert.map.Variable;
import toniarts.openkeeper.utils.Utils;
import toniarts.openkeeper.utils.WorldUtils;
import toniarts.openkeeper.view.map.MapViewController;

/**
* This is a controller that controls all the game objects in the world TODO:
Expand Down Expand Up @@ -214,30 +214,30 @@ public EntityId spawnCreature(Thing.Creature creature, Vector2f position) {
ownerId = deadBody.getPlayerId();
}
return loadCreature(creature.getCreatureId(), ownerId, level, position.getX(), position.getY(), 0f, healthPercentage, creature.getGoldHeld(),
triggerId != null && triggerId != 0 ? triggerId : null, false, objective, objectiveTargetPlayerId, objectiveTargetActionPointId);
triggerId != null && triggerId != 0 ? triggerId : null, SpawnType.PLACE, objective, objectiveTargetPlayerId, objectiveTargetActionPointId);
}

@Override
public EntityId spawnCreature(short creatureId, short playerId, int level, Vector2f position, boolean entrance) {
return loadCreature(creatureId, playerId, level, position.x, position.y, 0, 100, 0, null, entrance, null, (short) 0, 0);
public EntityId spawnCreature(short creatureId, short playerId, int level, Vector2f position, SpawnType spawnType) {
return loadCreature(creatureId, playerId, level, position.x, position.y, 0, 100, 0, null, spawnType, null, (short) 0, 0);
}

private EntityId loadCreature(short creatureId, short ownerId, int level, float x, float y, float rotation, Integer healthPercentage, int money,
Integer triggerId, boolean entrance, Thing.HeroParty.Objective objective, short objectiveTargetPlayerId, int objectiveTargetActionPointId) {
Integer triggerId, SpawnType spawnType, Thing.HeroParty.Objective objective, short objectiveTargetPlayerId, int objectiveTargetActionPointId) {
EntityId entity = entityData.createEntity();
Creature creature = kwdFile.getCreature(creatureId);

return loadCreature(entity, creature, healthPercentage, money, level, entrance, x, y, ownerId, rotation, objective, objectiveTargetPlayerId, objectiveTargetActionPointId, triggerId);
return loadCreature(entity, creature, healthPercentage, money, level, spawnType, x, y, ownerId, rotation, objective, objectiveTargetPlayerId, objectiveTargetActionPointId, triggerId);
}

private EntityId loadCreature(EntityId entity, Creature creature, Integer healthPercentage, int money, int level, boolean entrance, float x, float y, short ownerId, float rotation, Thing.HeroParty.Objective objective, short objectiveTargetPlayerId, int objectiveTargetActionPointId, Integer triggerId) {
private EntityId loadCreature(EntityId entity, Creature creature, Integer healthPercentage, int money, int level, SpawnType spawnType, float x, float y, short ownerId, float rotation, Thing.HeroParty.Objective objective, short objectiveTargetPlayerId, int objectiveTargetActionPointId, Integer triggerId) {
String name = Utils.generateCreatureName();
String bloodType = Utils.generateBloodType();

return loadCreature(entity, creature, name, bloodType, healthPercentage, money, level, entrance, x, y, ownerId, rotation, objective, objectiveTargetPlayerId, objectiveTargetActionPointId, triggerId);
return loadCreature(entity, creature, name, bloodType, healthPercentage, money, level, spawnType, x, y, ownerId, rotation, objective, objectiveTargetPlayerId, objectiveTargetActionPointId, triggerId);
}

private EntityId loadCreature(EntityId entity, Creature creature, String name, String bloodType, Integer healthPercentage, int money, int level, boolean entrance, float x, float y, short ownerId, float rotation, Thing.HeroParty.Objective objective, short objectiveTargetPlayerId, int objectiveTargetActionPointId, Integer triggerId) {
private EntityId loadCreature(EntityId entity, Creature creature, String name, String bloodType, Integer healthPercentage, int money, int level, SpawnType spawnType, float x, float y, short ownerId, float rotation, Thing.HeroParty.Objective objective, short objectiveTargetPlayerId, int objectiveTargetActionPointId, Integer triggerId) {
short creatureId = creature.getId();

// Create health, unless dead body
Expand Down Expand Up @@ -279,8 +279,24 @@ private EntityId loadCreature(EntityId entity, Creature creature, String name, S
entityData.setComponent(entity, new CreatureHunger(gameTimer.getGameTime(), 0));
}

CreatureState creatureState = entrance ? CreatureState.ENTERING_DUNGEON : getCreatureStateByMapLocation(WorldUtils.vectorToPoint(x, y), ownerId, entity);
entityData.setComponent(entity, new CreatureAi(gameTimer.getGameTime(), creatureState, creatureId));
CreatureState creatureState;
switch (spawnType) {
case ENTRANCE -> {
creatureState = CreatureState.ENTERING_DUNGEON;
}
case PLACE -> {
creatureState = getCreatureStateByMapLocation(WorldUtils.vectorToPoint(x, y), ownerId, entity);
}
case CONJURE -> {
creatureState = null;
entityData.setComponent(entity, new CreatureFall());
}
default ->
throw new RuntimeException("SpawnType " + spawnType + " not handled!");
}
if (creatureState != null) {
entityData.setComponent(entity, new CreatureAi(gameTimer.getGameTime(), creatureState, creatureId));
}

// Regeneration
Regeneration regeneration = new Regeneration();
Expand Down Expand Up @@ -320,7 +336,7 @@ private EntityId loadCreature(EntityId entity, Creature creature, String name, S

// Position
// FIXME: no floor height
entityData.setComponent(entity, new Position(rotation, new Vector3f(x, MapViewController.FLOOR_HEIGHT, y)));
entityData.setComponent(entity, new Position(rotation, new Vector3f(x, spawnType == SpawnType.CONJURE ? WorldUtils.DROP_HEIGHT : WorldUtils.FLOOR_HEIGHT, y)));

// Mobility
entityData.setComponent(entity, new Mobile(creature.getFlags().contains(Creature.CreatureFlag.CAN_FLY),
Expand Down Expand Up @@ -568,7 +584,7 @@ public void turnCreatureIntoAnother(EntityId entityId, short playerId, short cre
EntityId newEntityId = entityData.createEntity();

// Load the creature anew
loadCreature(newEntityId, kwdFile.getCreature(creatureId), creatureComponent.name, creatureComponent.bloodType, 100, 0, 1, false, position.position.x, position.position.z, playerId, position.rotation, null, (short) 0, 0, trigger != null ? trigger.triggerId : null);
loadCreature(newEntityId, kwdFile.getCreature(creatureId), creatureComponent.name, creatureComponent.bloodType, 100, 0, 1, SpawnType.PLACE, position.position.x, position.position.z, playerId, position.rotation, null, (short) 0, 0, trigger != null ? trigger.triggerId : null);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ public void createNewGame() {
gameWorldController.createNewGame(this, this);

positionSystem = new PositionSystem(gameWorldController.getMapController(), entityData, gameWorldController.getCreaturesController(), gameWorldController.getDoorsController(), gameWorldController.getObjectsController());
gameWorldController.setEntityPositionLookup(positionSystem);

// Navigation
navigationService = new NavigationService(gameWorldController.getMapController(), positionSystem);
Expand Down
68 changes: 45 additions & 23 deletions src/toniarts/openkeeper/game/controller/GameWorldController.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import toniarts.openkeeper.game.controller.room.storage.IRoomObjectControl;
import toniarts.openkeeper.game.controller.room.storage.RoomGoldControl;
import toniarts.openkeeper.game.data.Keeper;
import toniarts.openkeeper.game.data.ResearchableEntity;
import toniarts.openkeeper.game.listener.PlayerActionListener;
import toniarts.openkeeper.game.logic.IEntityPositionLookup;
import toniarts.openkeeper.game.map.IMapTileController;
Expand All @@ -79,6 +80,7 @@
import toniarts.openkeeper.tools.convert.map.KwdFile;
import toniarts.openkeeper.tools.convert.map.Player;
import toniarts.openkeeper.tools.convert.map.Room;
import toniarts.openkeeper.tools.convert.map.Shot;
import toniarts.openkeeper.tools.convert.map.Terrain;
import toniarts.openkeeper.tools.convert.map.Tile;
import toniarts.openkeeper.tools.convert.map.Trap;
Expand All @@ -92,7 +94,7 @@
*/
public class GameWorldController implements IGameWorldController, IPlayerActions {

private static final Logger LOGGER = Logger.getLogger(GameWorldController.class.getName());
private static final Logger logger = Logger.getLogger(GameWorldController.class.getName());

/**
* When dealing with gold... We currently better lock it. Logic stuff
Expand Down Expand Up @@ -126,7 +128,6 @@ public GameWorldController(KwdFile kwdFile, EntityData entityData, Map<Variable.
}

public void createNewGame(IGameController gameController, ILevelInfo levelInfo) {
entityPositionLookup = gameController.getEntityLookupService();

// Load objects
objectsController = new ObjectsController(kwdFile, entityData, gameSettings, gameTimer, gameController, levelInfo);
Expand Down Expand Up @@ -767,7 +768,7 @@ private void dropCreature(IRoomController roomController, EntityId entity, Point

// Add position
// Maybe in the future the physics deal with this and we just need to detect that we are airborne
Vector3f pos = new Vector3f(coordinates.x, (tortureOrImprisonment ? 1 : 2), coordinates.y);
Vector3f pos = new Vector3f(coordinates.x, (tortureOrImprisonment ? WorldUtils.FLOOR_HEIGHT : WorldUtils.DROP_HEIGHT), coordinates.y);
entityData.setComponent(entity, new Position(0, pos));

// If we got state, add it
Expand Down Expand Up @@ -867,7 +868,7 @@ private static boolean canInteract(EntityId entityId, short playerId, EntityData
return false;
}

// Is it iteractable?
// Is it interactable?
Interaction interaction = entityData.getComponent(entityId, Interaction.class);
if (interaction == null) {
return false;
Expand All @@ -889,7 +890,7 @@ private static boolean isEntityIncapacitated(EntityId entityId, EntityData entit
public void castKeeperSpell(short keeperSpellId, EntityId target, Point tile, Vector2f position, short playerId) {
KeeperSpell keeperSpell = kwdFile.getKeeperSpellById(keeperSpellId);
if (keeperSpell == null) {
LOGGER.log(Level.WARNING, "Invalid spell ID for spell casting received, was: {0}", keeperSpellId);
logger.log(Level.WARNING, "Invalid spell ID for spell casting received, was: {0}", keeperSpellId);
return;
}

Expand All @@ -898,13 +899,19 @@ public void castKeeperSpell(short keeperSpellId, EntityId target, Point tile, Ve
mapTile = entityPositionLookup.getEntityLocation(target);
}
if (mapTile == null) {
LOGGER.log(Level.WARNING, "Invalid map location for spell casting received, was: {0}", tile);
logger.log(Level.WARNING, "Invalid map location for spell casting received, was: {0}", tile);
return;
}

Keeper player = players.get(playerId);
if (player == null) {
LOGGER.log(Level.WARNING, "Invalid player for spell casting received, was: {0}", playerId);
logger.log(Level.WARNING, "Invalid player for spell casting received, was: {0}", playerId);
return;
}

ResearchableEntity researchableEntity = playerControllers.get(playerId).getSpellControl().getTypes().get(keeperSpell);
if (researchableEntity == null || !researchableEntity.isDiscovered()) {
logger.log(Level.WARNING, "Player spell is not available", playerId);
return;
}

Expand Down Expand Up @@ -958,54 +965,65 @@ public void castKeeperSpell(short keeperSpellId, EntityId target, Point tile, Ve
}
}
switch (keeperSpell.getTargetRule()) {
case ALL:
case LAND:
break;
case NONE:
case ALL, LAND -> {
}
case NONE -> {
return;
case ALL_CREATURES: {
}
case ALL_CREATURES -> {
if (creature == null) {
return;
}
break;
}
case ENEMY_CREATURES: {
case ENEMY_CREATURES -> {
if (owner == null) {
return;
}
if (!player.isEnemy(owner)) {
return;
}
break;
}
case OWN_CREATURES:
case POSESSION: {
case OWN_CREATURES, POSESSION -> {
if (creature == null || owner == null || owner != playerId) {
return;
}
}
}


// Cast the spell
Shot shot = kwdFile.getShotById(keeperSpell.getShotTypeId());
int shotData1 = researchableEntity.isUpgraded() ? keeperSpell.getBonusShotData1() : keeperSpell.getShotData1();
int shotData2 = researchableEntity.isUpgraded() ? keeperSpell.getBonusShotData2() : keeperSpell.getShotData2();
switch (shot.getProcessType()) {
case CREATE_CREATURE -> {
creaturesController.spawnCreature((short) shotData1, playerId, shotData2, position, ICreaturesController.SpawnType.CONJURE);
}
case MODIFY_HEALTH -> {

}
default ->
logger.log(Level.WARNING, "Shot type {0} not implemented", shot.getProcessType());
}
}

@Override
public void placeDoor(short doorId, Point tile, short playerId) {
Door door = kwdFile.getDoorById(doorId);
if (door == null) {
LOGGER.log(Level.WARNING, "Invalid door ID for door placement received, was: {0}", door);
logger.log(Level.WARNING, "Invalid door ID for door placement received, was: {0}", door);
return;
}

IMapTileInformation mapTile = mapController.getMapData().getTile(tile);
if (mapTile == null) {
LOGGER.log(Level.WARNING, "Invalid map location for door placement received, was: {0}", tile);
logger.log(Level.WARNING, "Invalid map location for door placement received, was: {0}", tile);
return;
}

Keeper player = players.get(playerId);
if (player == null) {
LOGGER.log(Level.WARNING, "Invalid player for door placement received, was: {0}", playerId);
logger.log(Level.WARNING, "Invalid player for door placement received, was: {0}", playerId);
return;
}

Expand All @@ -1016,19 +1034,19 @@ public void placeDoor(short doorId, Point tile, short playerId) {
public void placeTrap(short trapId, Point tile, short playerId) {
Trap trap = kwdFile.getTrapById(trapId);
if (trap == null) {
LOGGER.log(Level.WARNING, "Invalid trap ID for trap placement received, was: {0}", trap);
logger.log(Level.WARNING, "Invalid trap ID for trap placement received, was: {0}", trap);
return;
}

IMapTileInformation mapTile = mapController.getMapData().getTile(tile);
if (mapTile == null) {
LOGGER.log(Level.WARNING, "Invalid map location for trap placement received, was: {0}", tile);
logger.log(Level.WARNING, "Invalid map location for trap placement received, was: {0}", tile);
return;
}

Keeper player = players.get(playerId);
if (player == null) {
LOGGER.log(Level.WARNING, "Invalid player for trap placement received, was: {0}", playerId);
logger.log(Level.WARNING, "Invalid player for trap placement received, was: {0}", playerId);
return;
}

Expand All @@ -1052,4 +1070,8 @@ public IObjectsController getObjectsController() {
public ITrapsController getTrapsController() {
return trapsController;
}

public void setEntityPositionLookup(IEntityPositionLookup entityPositionLookup) {
this.entityPositionLookup = entityPositionLookup;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
*/
public interface ICreaturesController extends IEntityWrapper<ICreatureController> {

public enum SpawnType {
PLACE,
ENTRANCE,
CONJURE
}

/**
* Spawn a creature
*
Expand All @@ -46,11 +52,10 @@ public interface ICreaturesController extends IEntityWrapper<ICreatureController
* @param playerId the owner
* @param level the creature level
* @param position the position to spawn to, may be {@code null}
* @param entrance whether this an enrance for the creature (coming out of a
* portal)
* @param spawnType what type of entrance the creature is going to make
* @return the actual spawned creature
*/
EntityId spawnCreature(short creatureId, short playerId, int level, Vector2f position, boolean entrance);
EntityId spawnCreature(short creatureId, short playerId, int level, Vector2f position, SpawnType spawnType);

/**
* Spawn a hero party
Expand Down

0 comments on commit 9e7a525

Please sign in to comment.