From 2840eb30f5e42a87ca186a54c6826dfca87f51aa Mon Sep 17 00:00:00 2001 From: CharonInferar Date: Thu, 22 May 2014 19:28:03 +0200 Subject: [PATCH] First ideas --- src/services/spawn/MixedSpawnArea.java | 335 +++++++++++++++++++++++++ src/services/spawn/SpawnGroup.java | 30 +++ 2 files changed, 365 insertions(+) create mode 100644 src/services/spawn/MixedSpawnArea.java create mode 100644 src/services/spawn/SpawnGroup.java diff --git a/src/services/spawn/MixedSpawnArea.java b/src/services/spawn/MixedSpawnArea.java new file mode 100644 index 00000000..4a24c44d --- /dev/null +++ b/src/services/spawn/MixedSpawnArea.java @@ -0,0 +1,335 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.spawn; + +import java.util.Collections; +import java.util.Random; +import java.util.Vector; + +import resources.datatables.Options; +import resources.datatables.Posture; +import main.NGECore; +import net.engio.mbassy.listener.Handler; +import resources.common.collidables.AbstractCollidable; +import resources.common.collidables.AbstractCollidable.EnterEvent; +import resources.common.collidables.AbstractCollidable.ExitEvent; +import resources.objects.creature.CreatureObject; +import services.TerrainService; +import services.SimulationService.MoveEvent; +import engine.resources.objects.SWGObject; +import engine.resources.scene.Planet; +import engine.resources.scene.Point3D; + +public class MixedSpawnArea extends SpawnArea { + + private SpawnGroup spawnGroup; + private Vector spawnGroups; + private Vector mobiles = new Vector(); + + public MixedSpawnArea(Planet planet, AbstractCollidable area, SpawnGroup spawnGroup) { + super(planet, area); + this.spawnGroup = spawnGroup; + } + + public MixedSpawnArea(Planet planet, AbstractCollidable area, Vector spawnGroups) { + super(planet, area); + this.spawnGroups = spawnGroups; + } + + @Override + @Handler + public void onEnter(EnterEvent event) { + + SWGObject object = event.object; + // ToDo: Mounted players must be handled too + //System.out.println("Entering object " + object.getClass().getName()); + if(object == null || !(object instanceof CreatureObject)) + return; + + + CreatureObject creature = (CreatureObject) object; + + if(creature.getSlottedObject("ghost") == null && !creature.getOption(Options.MOUNT)) + return; + + creature.getEventBus().subscribe(this); + // spawn some creatures + if (spawnGroups==null){ + if (spawnGroup.getGroupMembersNumber()==-1){ + for(int i = 0; i < 5; i++) + spawnCreature(creature); + } else { + Vector groupMembers = new Vector(); + Point3D randomGroupPosition = getRandomPosition(creature.getWorldPosition(), 32, 100); + for(int i = 0; i < spawnGroup.getGroupMembersNumber(); i++) {// A group with a specified number of members + CreatureObject spawnedCreature = spawnCreatureMember(creature, groupMembers, randomGroupPosition, i); + if (spawnedCreature!=null) + groupMembers.add(spawnedCreature); + } + } + } else { + // select randomly one of the spawngroups -> minimizes number of collidables for areas with multiple different NPC groups + // One spawnarea -> many NPC groups + int index = new Random().nextInt(spawnGroups.size()); + this.spawnGroup = spawnGroups.get(index); + Vector groupMembers = new Vector(); + Point3D randomGroupPosition = getRandomPosition(creature.getWorldPosition(), 32, 100); + int spawnCount = spawnGroup.getGroupMembersNumber(); + if (spawnCount<0){ + int spawnCount2 = 1; + if (Math.abs(spawnCount) groupMembers = new Vector(); + Point3D randomGroupPosition = getRandomPosition(creature.getWorldPosition(), 32, 100); + for(int i = 0; i < spawnGroup.getGroupMembersNumber(); i++) {// A group with a specified number of members + CreatureObject spawnedCreature = spawnCreatureMember(creature, groupMembers, randomGroupPosition, i); + if (spawnedCreature!=null) + groupMembers.add(spawnedCreature); + } + } + } else { + // select randomly one of the spawngroups -> minimizes number of collidables for areas with multiple different NPC groups + // One spawnarea -> many NPC groups + int index = new Random().nextInt(spawnGroups.size()); + this.spawnGroup = spawnGroups.get(index); + + Vector groupMembers = new Vector(); + //Point3D randomGroupPosition = getRandomPosition(creature.getWorldPosition(), 32, 100); + Point3D randomGroupPosition = getRandomPosition(creature.getWorldPosition(), 32, spawnGroup.getMinSpawnDistance()+10); + int spawnCount = spawnGroup.getGroupMembersNumber(); + if (spawnCount<0){ + int spawnCount2 = 1; + if (Math.abs(spawnCount) it = mobiles.iterator(); // This stops further execution of this method for some reason +// it.forEachRemaining(mobile -> { +// if(mobile.getPosture() == Posture.Dead) +// it.remove(); +// }); + + mobiles.removeAll(Collections.singleton(null)); + Vector removers = new Vector(); + for (CreatureObject ob : mobiles){ + if (ob.getPosture() == Posture.Dead) + removers.add(ob); + } + mobiles.removeAll(removers); + + if(mobiles.size() >= spawnGroup.getMaxSpawns()) + return; + + boolean foundPos = false; + int tries = 0; + Point3D randomPosition = null; + + while(!foundPos && ++tries < 10) { + + randomPosition = getRandomPosition(creature.getWorldPosition(), 32.f, 200.f); + + if(randomPosition == null) + return; + + TerrainService terrainSvc = core.terrainService; + + float height = terrainSvc.getHeight(getPlanet().getID(), randomPosition.x, randomPosition.z); + randomPosition.y = height; + + if (mobiles.size()>0){ // Fix, mobiles must be filled first, before doing this check + for(CreatureObject mobile : mobiles) { + if(mobile.getWorldPosition().getDistance(randomPosition) > spawnGroup.getMinSpawnDistance()) + foundPos = true; + } + } else {foundPos = true;} + + if(!terrainSvc.canBuildAtPosition(creature, randomPosition.x, randomPosition.z)) + foundPos = false; + + } + + if(!foundPos) + return; + + Random random = new Random(); + + String mobileTemplate = spawnGroup.getMobiles().get(random.nextInt(spawnGroup.getMobiles().size())); + CreatureObject spawnedCreature = core.spawnService.spawnCreature(mobileTemplate, getPlanet().getName(), 0, randomPosition.x, randomPosition.y, randomPosition.z); + if(spawnedCreature != null){ + mobiles.add(spawnedCreature); + } + + } + + + private CreatureObject spawnCreatureMember(CreatureObject creature, Vector groupMembers, Point3D randomGroupPosition, int spawnIndex) { + + NGECore core = NGECore.getInstance(); + +// Iterator it = mobiles.iterator(); // This stops further execution of this method for some reason +// it.forEachRemaining(mobile -> { +// if(mobile.getPosture() == Posture.Dead) +// it.remove(); +// }); + + mobiles.removeAll(Collections.singleton(null)); + Vector removers = new Vector(); + for (CreatureObject ob : mobiles){ + if (ob.getPosture() == Posture.Dead) + removers.add(ob); + } + mobiles.removeAll(removers); + +// if(mobiles.size() >= spawnGroup.getMaxSpawns()) +// return; + + boolean foundPos = false; + int tries = 0; + Point3D randomPosition = null; + String template = spawnGroup.getMobiles().get(spawnIndex); + MobileTemplate mobileTemplate = NGECore.getInstance().spawnService.getMobileTemplate(template); + if (mobileTemplate==null){ + System.out.println("mobileTemplate==null for template " + template); + return null; + } + + while(!foundPos && ++tries < 30) { + + randomPosition = getRandomPosition(randomGroupPosition, mobileTemplate.getMinSpawnDistance(), mobileTemplate.getMaxSpawnDistance()); + + if(randomPosition == null){ + //System.out.println("randomPosition == null"); + return null; + } + + TerrainService terrainSvc = core.terrainService; + + float height = terrainSvc.getHeight(getPlanet().getID(), randomPosition.x, randomPosition.z); + randomPosition.y = height; + + if (mobiles.size()>0){ // Fix, mobiles must be filled first, before doing this check + boolean minDistViolated = false; + for(CreatureObject mobile : mobiles) { + if(mobile.getWorldPosition().getDistance(randomPosition) < spawnGroup.getMinSpawnDistance() && ! groupMembers.contains(mobile)){ + minDistViolated = true; // Distance to other nearby groups + //System.out.println("minDistViolated " + mobile.getWorldPosition().getDistance(randomPosition) + "mobile: " + mobile.getTemplate()); + } + } + if (minDistViolated) + foundPos = false; + else + foundPos = true; + } else {foundPos = true;} + + if(!terrainSvc.canBuildAtPosition(creature, randomPosition.x, randomPosition.z)) + foundPos = false; + + } + + if(!foundPos){ + //System.out.println("mobileTemplate pos not found " + mobileTemplate.getCreatureName()); + return null; + } + //System.out.println("mobileTemplate pos found " + mobileTemplate.getCreatureName()); + + CreatureObject spawnedCreature = core.spawnService.spawnCreature(template, getPlanet().getName(), 0, randomPosition.x, randomPosition.y, randomPosition.z); + if(spawnedCreature != null){ + mobiles.add(spawnedCreature); + //System.err.println("Creature ADDED " + spawnedCreature.getTemplate()); + } else + { + //System.out.println("Creature not spawned" + template); + } + + return spawnedCreature; + } +} diff --git a/src/services/spawn/SpawnGroup.java b/src/services/spawn/SpawnGroup.java new file mode 100644 index 00000000..de8abe0f --- /dev/null +++ b/src/services/spawn/SpawnGroup.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.spawn; + + +public abstract class SpawnGroup { + + public SpawnGroup() { + + } +}