Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feature/issue-335
Browse files Browse the repository at this point in the history
  • Loading branch information
tonihele committed Oct 19, 2024
2 parents f9f96e8 + d7ce545 commit 5dc1c84
Show file tree
Hide file tree
Showing 17 changed files with 406 additions and 59 deletions.
16 changes: 13 additions & 3 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,33 @@ on:
push:
pull_request:
branches: [ master ]
workflow_dispatch:

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- uses: Trass3r/setup-cpp@master
- name: Build with Gradle
run: ./gradlew build
- uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v4
with:
name: distribution
path: build/distributions/OpenKeeper.zip
- uses: marvinpinto/action-automatic-releases@latest
if: github.ref_name == 'master'
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "latest"
prerelease: true
title: "Development Build"
files: |
build/distributions/OpenKeeper.zip
49 changes: 49 additions & 0 deletions src/toniarts/openkeeper/game/component/CreatureSpell.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.EntityId;

/**
* Creature spell. Note that since a creature can have multiple, these are
* supposed to be given to individual entities
*
* @author Toni Helenius <[email protected]>
*/
public class CreatureSpell extends Attack {

public short creatureSpellId;
public EntityId creatureId;

public CreatureSpell() {
// For serialization
}

public CreatureSpell(short creatureSpellId, EntityId creatureId, float rechargeTime, float range) {
super(rechargeTime, range);
this.creatureSpellId = creatureSpellId;
this.creatureId = creatureId;
}

public CreatureSpell(CreatureSpell attack, double attackStartTime) {
super(attack.rechargeTime, attack.range);
this.creatureSpellId = attack.creatureSpellId;
this.creatureId = attack.creatureId;
this.attactStartTime = attackStartTime;
}

}
42 changes: 42 additions & 0 deletions src/toniarts/openkeeper/game/component/CreatureSpells.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* 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;
import com.simsilica.es.EntityId;
import java.util.List;

/**
* Creature spells. Minor infraction of ECS design having a list here. The idea
* is to link the actual spell entities to a creature. Give this component to a
* creature and you have yourself a search key to the actual spells.
*
* @author Toni Helenius <[email protected]>
*/
public class CreatureSpells implements EntityComponent {

public List<EntityId> creatureSpells;

public CreatureSpells() {
// For serialization
}

public CreatureSpells(List<EntityId> creatureSpells) {
this.creatureSpells = creatureSpells;
}

}
50 changes: 49 additions & 1 deletion src/toniarts/openkeeper/game/controller/CreaturesController.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
import java.lang.System.Logger.Level;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.stream.Collectors;
import toniarts.openkeeper.game.component.CreatureAi;
import toniarts.openkeeper.game.component.CreatureComponent;
import toniarts.openkeeper.game.component.CreatureEfficiency;
Expand All @@ -42,6 +44,8 @@
import toniarts.openkeeper.game.component.CreatureMeleeAttack;
import toniarts.openkeeper.game.component.CreatureMood;
import toniarts.openkeeper.game.component.CreatureSleep;
import toniarts.openkeeper.game.component.CreatureSpell;
import toniarts.openkeeper.game.component.CreatureSpells;
import toniarts.openkeeper.game.component.CreatureTortured;
import toniarts.openkeeper.game.component.CreatureViewState;
import toniarts.openkeeper.game.component.Death;
Expand Down Expand Up @@ -303,6 +307,7 @@ private EntityId loadCreature(EntityId entity, Creature creature, String name, S

// Set every attribute by the level of the created creature
setAttributesByLevel(creatureComponent, creatureExperience, healthComponent, goldComponent, sensesComponent, threatComponent, creatureMeleeAttack, regeneration);
setSpells(entity, creature, level);

entityData.setComponent(entity, creatureComponent);
entityData.setComponent(entity, creatureExperience);
Expand Down Expand Up @@ -445,6 +450,7 @@ public void levelUpCreature(EntityId entityId, int level, int experience) {

// Update stats
setAttributesByLevel(creatureComponent, creatureExperience, health, gold, senses, threat, creatureMeleeAttack, regeneration);
setSpells(entityId, kwdFile.getCreature(creatureComponent.creatureId), level);

// Set the new components to the entity
entityData.setComponents(entityId, creatureComponent, creatureExperience, health, gold, senses, threat, creatureMeleeAttack);
Expand Down Expand Up @@ -558,7 +564,7 @@ public ICreatureController createController(EntityId entityId) {
}

private ICreatureController createCreatureController(EntityId id, CreatureComponent creatureComponent) {
return new CreatureController(id, entityData, kwdFile.getCreature(creatureComponent.creatureId), gameController.getNavigationService(), gameController.getTaskManager(), gameTimer, gameSettings, this, gameController.getEntityLookupService(), mapController, levelInfo, gameController.getGameWorldController().getObjectsController());
return new CreatureController(id, entityData, kwdFile.getCreature(creatureComponent.creatureId), gameController.getNavigationService(), gameController.getTaskManager(), gameTimer, gameSettings, this, gameController.getEntityLookupService(), mapController, levelInfo, gameController.getGameWorldController().getObjectsController(), gameController.getGameWorldController().getShotsController());
}

@Override
Expand Down Expand Up @@ -587,4 +593,46 @@ public void turnCreatureIntoAnother(EntityId entityId, short playerId, short cre
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);
}

private void setSpells(EntityId entityId, Creature creature, int level) {

// Get the spells the creature should have
Map<Short, toniarts.openkeeper.tools.convert.map.CreatureSpell> availableSpells = creature.getSpells()
.stream()
.filter((spell) -> spell.getLevelAvailable() >= level)
.collect(Collectors.toMap((spell) -> spell.getCreatureSpellId(), (spell) -> kwdFile.getCreatureSpellById(spell.getCreatureSpellId())));
List<EntityId> creatureSpellIds = new ArrayList<>(availableSpells.size());
boolean spellsChanged = false;

// ... and compare it to the list we have
CreatureSpells creatureSpells = entityData.getComponent(entityId, CreatureSpells.class);
List<EntityId> ownedSpells = creatureSpells != null ? creatureSpells.creatureSpells : Collections.emptyList();

// Remove all spells we should not have
for (EntityId spellEntityId : ownedSpells) {
CreatureSpell spell = entityData.getComponent(spellEntityId, CreatureSpell.class);
if (availableSpells.containsKey(spell.creatureSpellId)) {
availableSpells.remove(spell.creatureSpellId);
creatureSpellIds.add(spellEntityId);
} else {
entityData.removeEntity(spellEntityId);
spellsChanged = true;
}
}

// All that is left is to add the remaining spells to the creature
for (toniarts.openkeeper.tools.convert.map.CreatureSpell spell : availableSpells.values()) {
EntityId spellEntity = entityData.createEntity();
entityData.setComponent(spellEntity, new CreatureSpell(spell.getCreatureSpellId(), entityId, spell.getRechargeTime(), spell.getRange()));
creatureSpellIds.add(spellEntity);
spellsChanged = true;
}

// Update the creature spell catalog
if (creatureSpellIds.isEmpty()) {
entityData.removeComponent(entityId, CreatureSpells.class);
} else if (spellsChanged) {
entityData.setComponent(entityId, new CreatureSpells(creatureSpellIds));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ public void castKeeperSpell(short keeperSpellId, EntityId target, Point tile, Ve
boolean spellUpgraded = researchableEntity.isUpgraded();
int shotData1 = spellUpgraded ? keeperSpell.getBonusShotData1() : keeperSpell.getShotData1();
int shotData2 = spellUpgraded ? keeperSpell.getBonusShotData2() : keeperSpell.getShotData2();
shotsController.createShot(keeperSpell.getShotTypeId(), shotData1, shotData2, playerId, position, target);
shotsController.createShot(keeperSpell.getShotTypeId(), shotData1, shotData2, playerId, WorldUtils.vector2fToVector3(position), target);
}

@Override
Expand Down Expand Up @@ -995,6 +995,11 @@ public ITrapsController getTrapsController() {
return trapsController;
}

@Override
public IShotsController getShotsController() {
return shotsController;
}

public void setEntityPositionLookup(IEntityPositionLookup entityPositionLookup) {
this.entityPositionLookup = entityPositionLookup;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ public interface IGameWorldController {
*/
public IObjectsController getObjectsController();

/**
* Get the shots controller
*
* @return shots controller
*/
public IShotsController getShotsController();

/**
* Cast a keeper spell on target / location
*
Expand Down
8 changes: 4 additions & 4 deletions src/toniarts/openkeeper/game/controller/IShotsController.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/
package toniarts.openkeeper.game.controller;

import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.simsilica.es.EntityId;

/**
Expand All @@ -33,10 +33,10 @@ public interface IShotsController {
* @param shotTypeId shot type to create
* @param shotData1 arbitrary value, interpreted per shot
* @param shotData2 arbitrary value, interpreted per shot
* @param playerId owher of the shot
* @param position 2D coordinate of the shot origin
* @param playerId owner of the shot
* @param position coordinate of the shot origin
* @param target shot target, can be null
*/
public void createShot(short shotTypeId, int shotData1, int shotData2, short playerId, Vector2f position, EntityId target);
public void createShot(short shotTypeId, int shotData1, int shotData2, short playerId, Vector3f position, EntityId target);

}
7 changes: 4 additions & 3 deletions src/toniarts/openkeeper/game/controller/ShotsController.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/
package toniarts.openkeeper.game.controller;

import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.simsilica.es.EntityData;
import com.simsilica.es.EntityId;
import java.lang.System.Logger;
Expand All @@ -29,6 +29,7 @@
import static toniarts.openkeeper.tools.convert.map.Shot.ProcessType.MODIFY_HEALTH;
import static toniarts.openkeeper.tools.convert.map.Shot.ProcessType.POSSESS_CREATURE;
import toniarts.openkeeper.tools.convert.map.Variable;
import toniarts.openkeeper.utils.WorldUtils;

/**
*
Expand Down Expand Up @@ -62,11 +63,11 @@ public ShotsController(KwdFile kwdFile, EntityData entityData, Map<Variable.Misc
}

@Override
public void createShot(short shotTypeId, int shotData1, int shotData2, short playerId, Vector2f position, EntityId target) {
public void createShot(short shotTypeId, int shotData1, int shotData2, short playerId, Vector3f position, EntityId target) {
Shot shot = kwdFile.getShotById(shotTypeId);
switch (shot.getProcessType()) {
case CREATE_CREATURE -> {
creaturesController.spawnCreature((short) shotData1, playerId, shotData2, position, ICreaturesController.SpawnType.CONJURE);
creaturesController.spawnCreature((short) shotData1, playerId, shotData2, WorldUtils.vector3fToVector2f(position), ICreaturesController.SpawnType.CONJURE);
}
case CREATE_OBJECT -> {
objectsController.loadObject((short) shotData1, playerId, position, 0);
Expand Down
Loading

0 comments on commit 5dc1c84

Please sign in to comment.