mirror of
https://github.com/ProjectSWGCore/NGECore2.git
synced 2026-08-02 03:15:52 -04:00
Merge pull request #1211 from CharonInferar/LairFixes
Several Fixes for lairs
This commit is contained in:
@@ -389,7 +389,7 @@ public class CreatureObject extends TangibleObject implements IPersistent {
|
||||
}
|
||||
|
||||
public void setHeight(float height) {
|
||||
height = (((height < 0.7) || (height > 1.5)) ? 1 : height);
|
||||
// height = (((height < 0.7) || (height > 1.5)) ? 1 : height); Babies need height values smaller than that
|
||||
notifyObservers(getBaseline(3).set("height", height), true);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,15 +21,24 @@
|
||||
******************************************************************************/
|
||||
package services.ai;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Vector;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import engine.resources.scene.Point3D;
|
||||
import main.NGECore;
|
||||
import net.engio.mbassy.listener.Handler;
|
||||
import resources.common.SpawnPoint;
|
||||
import resources.datatables.Posture;
|
||||
import resources.objects.creature.CreatureObject;
|
||||
import resources.objects.tangible.TangibleObject;
|
||||
import services.ai.states.RetreatState;
|
||||
import services.combat.CombatEvents.DamageTaken;
|
||||
import tools.DevLog;
|
||||
|
||||
@@ -45,11 +54,13 @@ public class LairActor {
|
||||
private short level;
|
||||
private String bossTemplate;
|
||||
private boolean bossSpawned = false;
|
||||
private Map<CreatureObject, Long> attackerMap = new ConcurrentHashMap<CreatureObject, Long>();
|
||||
|
||||
public LairActor(TangibleObject lairObject, String creatureTemplate) {
|
||||
this.lairObject = lairObject;
|
||||
this.creatureTemplate = creatureTemplate;
|
||||
lairObject.getEventBus().subscribe(this);
|
||||
checkAttackerTask();
|
||||
}
|
||||
|
||||
public LairActor(TangibleObject lairObject, String creatureTemplate, int maxSpawns, short level) {
|
||||
@@ -58,6 +69,7 @@ public class LairActor {
|
||||
this.maxSpawns = maxSpawns;
|
||||
this.level = level;
|
||||
lairObject.getEventBus().subscribe(this);
|
||||
checkAttackerTask();
|
||||
}
|
||||
|
||||
public LairActor(TangibleObject lairObject, Vector<String> creatureTemplates, int maxSpawns, short level) {
|
||||
@@ -66,6 +78,7 @@ public class LairActor {
|
||||
this.maxSpawns = maxSpawns;
|
||||
this.level = level;
|
||||
lairObject.getEventBus().subscribe(this);
|
||||
checkAttackerTask();
|
||||
}
|
||||
|
||||
|
||||
@@ -90,40 +103,55 @@ public class LairActor {
|
||||
ai.addDefender((CreatureObject)event.attacker);
|
||||
((CreatureObject)event.attacker).addDefender(ai.getCreature());
|
||||
}
|
||||
|
||||
|
||||
attackerMap.put(((CreatureObject)event.attacker), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public void spawnNewCreatures() {
|
||||
|
||||
// remove dead creatures from collection
|
||||
creatures.removeAll(Collections.singleton(null));
|
||||
Vector<AIActor> removers = new Vector<AIActor>();
|
||||
for (AIActor act : creatures){
|
||||
if (act!=null ){
|
||||
if (act.getCreature().getPosture()==Posture.Dead)
|
||||
removers.add(act);
|
||||
else if (lairObject.getPosition().getDistance2D(act.getCreature().getPosition())>80)
|
||||
removers.add(act);
|
||||
}
|
||||
}
|
||||
creatures.removeAll(removers);
|
||||
|
||||
if(creatures.size() >= maxSpawns)
|
||||
return;
|
||||
|
||||
int currentCondition = lairObject.getConditionDamage();
|
||||
int maxCondition = lairObject.getMaximumCondition();
|
||||
|
||||
//System.out.println("spawnWave " + spawnWave + " currentCondition " + currentCondition + " maxCondition " + maxCondition + "quot " + ((float)currentCondition / (float)maxCondition));
|
||||
switch(spawnWave) {
|
||||
// TODO: play damage effect
|
||||
case 0:
|
||||
spawnWave++;
|
||||
break;
|
||||
case 1:
|
||||
if((currentCondition / maxCondition) < 0.7) {
|
||||
if(((float)currentCondition / (float)maxCondition) < 0.7) {
|
||||
spawnWave++;
|
||||
break;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
case 2:
|
||||
if((currentCondition / maxCondition) < 0.3) {
|
||||
if(((float)currentCondition / (float)maxCondition) < 0.3) {
|
||||
spawnWave++;
|
||||
break;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (bossTemplate!=null && ! bossSpawned){
|
||||
//CreatureObject boss = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(bossTemplate, lairObject.getPlanet().getName(), 0L, lairObject.getPosition().x + 3, lairObject.getPosition().y, lairObject.getPosition().z, lairObject.getOrientation().w, lairObject.getOrientation().x, lairObject.getOrientation().y,lairObject.getOrientation().z,-1);
|
||||
CreatureObject boss = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(bossTemplate, lairObject.getPlanet().getName(), 0L, lairObject.getPosition().x + 3, lairObject.getPosition().y, lairObject.getPosition().z, lairObject.getOrientation().w, lairObject.getOrientation().x, lairObject.getOrientation().y,lairObject.getOrientation().z,-1);
|
||||
bossSpawned = true;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -138,7 +166,9 @@ public class LairActor {
|
||||
creatureAmount = new Random().nextInt(4) + (maxSpawns / 5);
|
||||
tries++;
|
||||
}
|
||||
while(creatureAmount > maxSpawns && tries < 10);
|
||||
while(tries < 10);
|
||||
|
||||
//while(creatureAmount > maxSpawns && tries < 10);
|
||||
|
||||
for(int i = 0; i < creatureAmount; i++) {
|
||||
Point3D position = SpawnPoint.getRandomPosition(lairObject.getPosition(), 5, 30, lairObject.getPlanetId());
|
||||
@@ -211,4 +241,48 @@ public class LairActor {
|
||||
public void setBossTemplate(String bossTemplate) {
|
||||
this.bossTemplate = bossTemplate;
|
||||
}
|
||||
|
||||
private void checkAttackerTask(){
|
||||
final Future<?>[] fut1 = {null};
|
||||
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
fut1[0] = scheduler.scheduleAtFixedRate(new Runnable() {
|
||||
@Override public void run() {
|
||||
try {
|
||||
if (lairObject==null){
|
||||
Thread.yield();
|
||||
fut1[0].cancel(false);
|
||||
} else {
|
||||
int currentCondition = lairObject.getConditionDamage();
|
||||
int maxCondition = lairObject.getMaximumCondition();
|
||||
if (currentCondition>maxCondition){
|
||||
Thread.yield();
|
||||
fut1[0].cancel(false);
|
||||
}
|
||||
}
|
||||
checkAttackers();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Exception in checkAttackerTask->scheduleAtFixedRate->checkAttackers() " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}, 0, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void checkAttackers(){
|
||||
Map<CreatureObject, Long> attackerMapClone = new ConcurrentHashMap<CreatureObject, Long>(attackerMap);
|
||||
for (CreatureObject attacker : attackerMapClone.keySet()) {
|
||||
Long lastAttackTime = attackerMapClone.get(attacker);
|
||||
if (attacker.getWorldPosition().getDistance2D(lairObject.getWorldPosition())>100 || System.currentTimeMillis()-lastAttackTime>10000)
|
||||
removeDefender(attacker);
|
||||
}
|
||||
attackerMapClone = null;
|
||||
}
|
||||
|
||||
private void removeDefender(TangibleObject defender) {
|
||||
if (defender==null){
|
||||
return;
|
||||
}
|
||||
lairObject.removeDefender(defender);
|
||||
if (attackerMap.containsKey(defender)) attackerMap.remove(defender);
|
||||
defender.removeDefender(lairObject);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1533,8 +1533,13 @@ public class CombatService implements INetworkDispatch {
|
||||
|
||||
public boolean areInDuel(CreatureObject creature1, CreatureObject creature2) {
|
||||
|
||||
if(creature1.getDuelList().contains(creature2) && creature2.getDuelList().contains(creature1))
|
||||
return true;
|
||||
// Vehicles are going through this too, but dont have duellists, so null checks must be done or NPE
|
||||
if (creature1.getDuelList()!=null && creature2.getDuelList()!=null) {
|
||||
if(creature1.getDuelList().contains(creature2) && creature2.getDuelList().contains(creature1))
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import resources.common.collidables.AbstractCollidable.ExitEvent;
|
||||
import resources.objects.creature.CreatureObject;
|
||||
import services.TerrainService;
|
||||
import services.SimulationService.MoveEvent;
|
||||
import services.ai.AIActor;
|
||||
import services.ai.LairActor;
|
||||
import engine.resources.config.Config;
|
||||
import engine.resources.objects.SWGObject;
|
||||
@@ -213,13 +214,15 @@ public class MixedSpawnArea extends SpawnArea {
|
||||
}
|
||||
}
|
||||
if (this.spawnGroup instanceof LairGroupTemplate){
|
||||
|
||||
object = event.object;
|
||||
|
||||
//if(object == null || !(object instanceof CreatureObject) || object.getContainer() != null)
|
||||
// return;
|
||||
|
||||
if(object == null || !(object instanceof CreatureObject))
|
||||
if(object == null || !(object instanceof CreatureObject)){
|
||||
return;
|
||||
}
|
||||
|
||||
creature = (CreatureObject) object;
|
||||
|
||||
@@ -386,23 +389,26 @@ public class MixedSpawnArea extends SpawnArea {
|
||||
|
||||
// LairSpawnArea class methods
|
||||
public void spawnLair(CreatureObject object) {
|
||||
|
||||
|
||||
NGECore core = NGECore.getInstance();
|
||||
|
||||
LairGroupTemplate lairGroup = (LairGroupTemplate)this.spawnGroup;
|
||||
|
||||
Vector<LairSpawnTemplate> lairTemplates = lairGroup.getLairSpawnTemplates();
|
||||
|
||||
if(lairGroup == null || lairTemplates.isEmpty())
|
||||
if(lairGroup == null || lairTemplates.isEmpty()){
|
||||
return;
|
||||
}
|
||||
|
||||
if((System.currentTimeMillis() - lastSpawnTime) < 10000)
|
||||
if((System.currentTimeMillis() - lastSpawnTime) < 10000){
|
||||
return;
|
||||
}
|
||||
|
||||
Point3D randomPosition = getRandomPosition(object.getWorldPosition(), 32.f, 200.f);
|
||||
|
||||
if(randomPosition == null)
|
||||
if(randomPosition == null){
|
||||
return;
|
||||
}
|
||||
|
||||
TerrainService terrainSvc = core.terrainService;
|
||||
|
||||
@@ -410,29 +416,38 @@ public class MixedSpawnArea extends SpawnArea {
|
||||
randomPosition.y = height;
|
||||
|
||||
for(LairActor otherLair : lairs) {
|
||||
if(otherLair.getLairObject().getWorldPosition().getDistance(randomPosition) < 30)
|
||||
if(otherLair.getLairObject().getWorldPosition().getDistance(randomPosition) < 30){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(!terrainSvc.canBuildAtPosition(object, randomPosition.x, randomPosition.z))
|
||||
if(!terrainSvc.canBuildAtPosition(object, randomPosition.x, randomPosition.z)){
|
||||
return;
|
||||
}
|
||||
|
||||
Random random = new Random();
|
||||
|
||||
|
||||
LairSpawnTemplate lairSpawn = lairTemplates.get(random.nextInt(lairTemplates.size()));
|
||||
|
||||
|
||||
int level = -1; // If level equals -1 then the mobile template CL will be used!
|
||||
if (lairSpawn.getMinLevel() != -1 && lairSpawn.getMaxLevel()!=-1)
|
||||
level = random.nextInt((int) (lairSpawn.getMaxLevel() - lairSpawn.getMinLevel()) + 1) + lairSpawn.getMinLevel();
|
||||
|
||||
AIActor actor = (AIActor) object.getAttachment("AI");
|
||||
|
||||
if (actor!=null)
|
||||
level = actor.getMobileTemplate().getLevel();
|
||||
|
||||
|
||||
if (level<0)
|
||||
level = 10;
|
||||
|
||||
LairActor lairActor = core.spawnService.spawnLair(lairSpawn.getLairTemplate(), getPlanet(), randomPosition, (short) level);
|
||||
if(lairActor == null)
|
||||
|
||||
if(lairActor == null){
|
||||
return;
|
||||
}
|
||||
lairs.add(lairActor);
|
||||
lastSpawnTime = System.currentTimeMillis();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -459,18 +459,23 @@ public class SpawnService {
|
||||
}
|
||||
|
||||
public LairActor spawnLair(String lairSpawnTemplate, Planet planet, Point3D position, short level) {
|
||||
|
||||
|
||||
LairTemplate lairTemplate = lairTemplates.get(lairSpawnTemplate);
|
||||
if(lairTemplate == null)
|
||||
return null;
|
||||
|
||||
// adapt to terrain
|
||||
float positionY = core.terrainService.getHeight(planet.getID(), position.x, position.z);
|
||||
Point3D adaptedPosition = new Point3D(position.x, positionY, position.z);
|
||||
|
||||
TangibleObject lairObject = null;
|
||||
if (lairTemplate.getLairCRC()==null){
|
||||
String lairCRC = lairTemplate.getLairCRCs().get(new Random().nextInt(lairTemplate.getLairCRCs().size()));
|
||||
System.out.println("Lair CRC " + lairCRC);
|
||||
lairObject = (TangibleObject) core.objectService.createObject(lairCRC, 0, planet, position, new Quaternion(1, 0, 0, 0));
|
||||
//System.out.println("Lair CRC " + lairCRC);
|
||||
|
||||
lairObject = (TangibleObject) core.objectService.createObject(lairCRC, 0, planet, adaptedPosition, new Quaternion(1, 0, 0, 0));
|
||||
} else {
|
||||
lairObject = (TangibleObject) core.objectService.createObject(lairTemplate.getLairCRC().trim(), 0, planet, position, new Quaternion(1, 0, 0, 0));
|
||||
lairObject = (TangibleObject) core.objectService.createObject(lairTemplate.getLairCRC().trim(), 0, planet, adaptedPosition, new Quaternion(1, 0, 0, 0));
|
||||
}
|
||||
|
||||
if(lairObject == null)
|
||||
@@ -478,8 +483,17 @@ public class SpawnService {
|
||||
|
||||
lairObject.setOptionsBitmask(Options.ATTACKABLE);
|
||||
lairObject.setPvpBitmask(PvpStatus.Attackable);
|
||||
lairObject.setMaximumCondition(1000 * level);
|
||||
|
||||
|
||||
|
||||
|
||||
if (lairTemplate.getMobiles()!=null){
|
||||
MobileTemplate mobileTemplate = mobileTemplates.get(lairTemplate.getMobiles().get(0));
|
||||
level = mobileTemplate.getLevel();
|
||||
}
|
||||
|
||||
lairObject.setMaximumCondition(1000 * level);
|
||||
|
||||
LairActor lairActor = new LairActor(lairObject, lairTemplate.getMobileName(), 10, level);
|
||||
|
||||
if (lairTemplate.getMobiles()!=null)
|
||||
|
||||
Reference in New Issue
Block a user