diff --git a/scripts/commands/pvp.py b/scripts/commands/pvp.py index c313fbc4..34f6c5ff 100644 --- a/scripts/commands/pvp.py +++ b/scripts/commands/pvp.py @@ -14,6 +14,9 @@ def run(core, actor, target, commandString): if actor.getPvpStatus(PvpStatus.GoingOvert) or actor.getPvpStatus(PvpStatus.GoingCovert): actor.sendSystemMessage('@faction_recruiter:pvp_status_changing', 0) return + if core.gcwService.isInPvpZone(actor): + actor.sendSystemMessage('@gcw:pvp_advanced_region_cannot_go_covert', 0) + return if commandString != '' and commandString != faction: if commandString == 'rebel' or commandString == 'imperial' or commandString == 'neutral': @@ -60,6 +63,8 @@ def run(core, actor, target, commandString): actor.sendSystemMessage('@faction_recruiter:covert_to_overt', 0) actor.setPvpStatus(PvpStatus.GoingOvert, True) time.sleep(30) + if core.gcwService.isInPvpZone(actor): + return actor.setFactionStatus(FactionStatus.SpecialForces) actor.setPvpStatus(PvpStatus.GoingOvert, False) actor.sendSystemMessage('@faction_recruiter:overt_complete', 0) @@ -70,6 +75,8 @@ def run(core, actor, target, commandString): actor.sendSystemMessage('@faction_recruiter:overt_to_covert', 0) actor.setPvpStatus(PvpStatus.GoingCovert, True) time.sleep(300) + if core.gcwService.isInPvpZone(actor): + return actor.setFactionStatus(FactionStatus.Combatant) actor.setPvpStatus(PvpStatus.GoingCovert, False) actor.sendSystemMessage('@faction_recruiter:covert_complete', 0) diff --git a/scripts/pvpzones.py b/scripts/pvpzones.py new file mode 100644 index 00000000..91ab32ef --- /dev/null +++ b/scripts/pvpzones.py @@ -0,0 +1,9 @@ +import sys + +def addZones(core): + + gcwService = core.gcwService + + gcwService.addPvPZone('rori', 5318, 5680, 400) + + \ No newline at end of file diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index 432868e4..ecfec005 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -405,6 +405,7 @@ public class SimulationService implements INetworkDispatch { } checkForCollidables(object); + object.setAttachment("lastValidPosition", object.getPosition()); MoveEvent event = new MoveEvent(); event.object = object; object.getEventBus().publish(event); @@ -470,6 +471,7 @@ public class SimulationService implements INetworkDispatch { object.notifyObservers(utm, false); checkForCollidables(object); + object.setAttachment("lastValidPosition", object.getPosition()); } diff --git a/src/services/gcw/GCWService.java b/src/services/gcw/GCWService.java index 73d06d36..dd7bdc14 100644 --- a/src/services/gcw/GCWService.java +++ b/src/services/gcw/GCWService.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -42,20 +43,20 @@ import org.python.google.common.collect.Multimap; import protocol.swg.GcwGroupsRsp; import protocol.swg.GcwRegionsReq; import protocol.swg.GcwRegionsRsp; - import resources.common.Opcodes; +import resources.common.collidables.CollidableCircle; import resources.datatables.FactionStatus; import resources.gcw.CurrentServerGCWZoneHistory; import resources.gcw.CurrentServerGCWZonePercent; import resources.gcw.OtherServerGCWZonePercent; import resources.objects.creature.CreatureObject; import resources.objects.guild.GuildObject; - import main.NGECore; - import engine.clients.Client; import engine.resources.objects.SWGObject; +import engine.resources.scene.Planet; import engine.resources.scene.Point2D; +import engine.resources.scene.Point3D; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; @@ -64,7 +65,7 @@ public class GCWService implements INetworkDispatch { private NGECore core; private GuildObject object; private Map> zoneMap() { return object.getZoneMap(); } - + private Map> pvpZones = new ConcurrentHashMap>(); private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); protected final Object objectMutex = new Object(); @@ -79,6 +80,7 @@ public class GCWService implements INetworkDispatch { private void afterInitialisation() { try { core.scriptService.callScript("scripts/", "gcwzones", "addZones", core); + core.scriptService.callScript("scripts/", "pvpzones", "addZones", core); } catch (Exception e) { e.printStackTrace(); } @@ -421,6 +423,25 @@ public class GCWService implements INetworkDispatch { } + public void addPvPZone(String planetName, float x, float z, float radius) { + Planet planet = core.terrainService.getPlanetByName(planetName); + if(planet == null) + return; + if(pvpZones.get(planet) == null) + pvpZones.put(planet, new ArrayList()); + CollidableCircle area = new CollidableCircle(new Point3D(x, 0, z), radius, planet); + PvPZone zone = new PvPZone(planet, area); + pvpZones.get(planet).add(zone); + core.simulationService.addCollidable(area, x, z); + } + + public boolean isInPvpZone(CreatureObject actor) { + List zones = pvpZones.get(actor.getPlanet()); + if(zones == null) + return false; + return zones.stream().anyMatch(z -> z.getArea().doesCollide(actor)); + } + @Override public void shutdown() { diff --git a/src/services/gcw/PvPZone.java b/src/services/gcw/PvPZone.java index e418327b..8f14000d 100644 --- a/src/services/gcw/PvPZone.java +++ b/src/services/gcw/PvPZone.java @@ -21,16 +21,24 @@ ******************************************************************************/ package services.gcw; +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.datatables.FactionStatus; +import resources.datatables.PvpStatus; +import resources.objects.creature.CreatureObject; +import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; +import engine.resources.scene.Point3D; public class PvPZone { private Planet planet; private AbstractCollidable area; + private NGECore core = NGECore.getInstance(); + public PvPZone(Planet planet, AbstractCollidable area) { this.planet = planet; @@ -54,14 +62,51 @@ public class PvPZone { this.area = area; } + public void warpBack(CreatureObject actor) { + if (core.mountService.isMounted(actor)) { + actor = (CreatureObject) actor.getContainer(); + } + core.simulationService.teleport(actor, (Point3D) actor.getAttachment("lastValidPosition"), actor.getOrientation(), actor.getParentId()); + } + @Handler public void onEnter(EnterEvent event) { + CreatureObject actor = (CreatureObject) event.object; + + if(!actor.getFaction().equals("rebel") && !actor.getFaction().equals("imperial")) { + actor.sendSystemMessage("@gcw:pvp_advanced_region_not_allowed", (byte) 0); + warpBack(actor); + return; + } + + if(actor.getLevel() < 75) { + actor.sendSystemMessage("@gcw:pvp_advanced_region_level_low", (byte) 0); + warpBack(actor); + return; + } + + if(actor.getPvpStatus(PvpStatus.GoingCovert) || actor.getPvpStatus(PvpStatus.GoingOvert)) { + actor.setPvpStatus(PvpStatus.GoingCovert, false); + actor.setPvpStatus(PvpStatus.GoingOvert, false); + actor.sendSystemMessage("@gcw:pvp_advanced_region_faction_type_change_cancel", (byte) 0); + } + + actor.setFactionStatus(FactionStatus.SpecialForces); + actor.updatePvpStatus(); + actor.sendSystemMessage("@gcw:pvp_advanced_region_entered", (byte) 0); + } @Handler public void onExit(ExitEvent event) { + CreatureObject actor = (CreatureObject) event.object; + + actor.setFactionStatus(FactionStatus.OnLeave); + actor.updatePvpStatus(); + actor.sendSystemMessage("@gcw:pvp_advanced_region_exited", (byte) 0); + }