diff --git a/ngengine_public.jar b/ngengine_public.jar index ffa4476f..ddeff30b 100644 Binary files a/ngengine_public.jar and b/ngengine_public.jar differ diff --git a/scripts/commands/giveitem.py b/scripts/commands/giveitem.py index 8279dc05..2d5aba72 100644 --- a/scripts/commands/giveitem.py +++ b/scripts/commands/giveitem.py @@ -13,6 +13,9 @@ def run(core, actor, target, commandString): object = core.objectService.createObject(commandString, actor.getPlanet()) + #object.setCustomizationVariable('/private/index_color_blade', 0x02) + #object.setCustomizationVariable('private/alternate_shader_blade', 0x02) + if not object: return diff --git a/scripts/commands/teleporttarget.py b/scripts/commands/teleporttarget.py new file mode 100644 index 00000000..f497fe25 --- /dev/null +++ b/scripts/commands/teleporttarget.py @@ -0,0 +1,29 @@ +import sys +from engine.resources.scene import Point3D + +def setup(): + return + +def run(core, actor, target, commandString): + + playerObject = actor.getSlottedObject('ghost') + + if not playerObject: + return + + commandArgs = commandString.split(' ') + if len(commandArgs) > 0: + arg1 = commandArgs[0] + if len(commandArgs) > 1: + arg2 = commandArgs[1] + if len(commandArgs) > 2: + arg3 = commandArgs[2] + if len(commandArgs) > 3: + arg4 = commandArgs[3] + + if arg1 and arg2 and arg3 and arg4 target: + position = Point3D(float(arg2), float(arg3), float(arg4)) + core.simulationService.transferToPlanet(target, core.terrainService.getPlanetByName(arg1), position, actor.getOrientation(), None) + + + return diff --git a/scripts/mobiles/canon/jedi_master.py b/scripts/mobiles/canon/jedi_master.py new file mode 100644 index 00000000..9770c507 --- /dev/null +++ b/scripts/mobiles/canon/jedi_master.py @@ -0,0 +1,26 @@ +import sys +from services.spawn import MobileTemplate +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + templates = Vector() + templates.add('object/mobile/shared_dressed_dark_jedi_master_female_twk_01.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_female_twk_02.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_female_zab_01.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_female_zab_02.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_male_human_01.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_male_human_04.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_male_human_05.iff') + templates.add('object/mobile/shared_dressed_dark_jedi_master_male_human_06.iff') + mobileTemplate.setTemplates(templates) + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(2) + mobileTemplate.setCustomWeaponTemplate('object/weapon/melee/2h_sword/crafted_saber/shared_sword_lightsaber_two_handed_gen5.iff') + attacks = Vector() + mobileTemplate.setDefaultAttack('saberHit') + mobileTemplate.setAttacks(attacks) + mobileTemplate.setCreatureName('eow_dark_jedi_sentinel_uber') + mobileTemplate.setAttackRange(6) + core.spawnService.addMobileTemplate('jedi_master', mobileTemplate) + \ No newline at end of file diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index b00537a1..dce95545 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -21,35 +21,40 @@ ******************************************************************************/ package resources.objects.tangible; +import java.io.ByteArrayOutputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.Vector; -import main.NGECore; +import javax.xml.bind.DatatypeConverter; +import main.NGECore; import protocol.swg.ObjControllerMessage; import protocol.swg.PlayClientEffectObjectMessage; import protocol.swg.StopClientEffectObjectByLabel; import protocol.swg.UpdatePVPStatusMessage; import protocol.swg.objectControllerObjects.ShowFlyText; - import resources.common.RGB; import resources.objects.creature.CreatureObject; +import resources.visitors.IDManagerVisitor; import services.ai.AIActor; import com.sleepycat.persist.model.NotPersistent; import com.sleepycat.persist.model.Persistent; +import engine.clientdata.ClientFileManager; import engine.clients.Client; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; -@Persistent(version=0) +@Persistent(version=1) public class TangibleObject extends SWGObject { // TODO: Thread safety @@ -59,6 +64,7 @@ public class TangibleObject extends SWGObject { protected int pvpBitmask = 0; protected byte[] customization; private List componentCustomizations = new ArrayList(); + private Map customizationVariables = new HashMap(); protected int optionsBitmask = 0; private int maxDamage = 1000; private boolean staticObject = true; @@ -241,6 +247,50 @@ public class TangibleObject extends SWGObject { } } + public void setCustomizationVariable(String type, byte value) + { + if(customizationVariables.containsKey(type)) customizationVariables.replace(type, value); + else customizationVariables.put(type, value); + + buildCustomizationBytes(); + } + + public void removeCustomizationVariable(String type) + { + if(customizationVariables.containsKey(type)) + { + customizationVariables.remove(type); + buildCustomizationBytes(); + } + } + + private void buildCustomizationBytes() + { + //if(customizationVariables.size() == 0) customization = { 0x00 }; + + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + try + { + IDManagerVisitor visitor = ClientFileManager.loadFile("customization/customization_id_manager.iff", IDManagerVisitor.class); + + stream.write((byte)0x02); // Unk + stream.write((byte)customizationVariables.size()); // Number of customization attributes + + for(String type : customizationVariables.keySet()) + { + stream.write(visitor.getAttributeIndex(type)); // Index of palette type within "customization/customization_id_manager.iff" + stream.write(customizationVariables.get(type)); // Value/Index within palette + + // Seperator/Footer + stream.write((byte) 0xC3); + stream.write((byte) 0xBF); + stream.write((byte) 0x03); + } + customization = stream.toByteArray(); + } + catch (Exception e) { e.printStackTrace(); } + } + public String getFaction() { synchronized(objectMutex) { return faction; diff --git a/src/resources/visitors/IDManagerVisitor.java b/src/resources/visitors/IDManagerVisitor.java index 2ad1ad46..3c7a1617 100644 --- a/src/resources/visitors/IDManagerVisitor.java +++ b/src/resources/visitors/IDManagerVisitor.java @@ -31,11 +31,11 @@ import engine.clientdata.VisitorInterface; public class IDManagerVisitor implements VisitorInterface { - private ConcurrentHashMap customizationMap; + private ConcurrentHashMap customizationMap; private CharsetDecoder charsetDecoder; public IDManagerVisitor() { - customizationMap = new ConcurrentHashMap(); + customizationMap = new ConcurrentHashMap(); charsetDecoder = Charset.forName("US-ASCII").newDecoder(); } @@ -46,21 +46,28 @@ public class IDManagerVisitor implements VisitorInterface { return; while(data.hasRemaining()) { - short designNumber = data.getShort(); + + byte designNumber = data.get(); + data.get(); String customizationType = data.getString(charsetDecoder); charsetDecoder.reset(); - + customizationMap.put(customizationType, designNumber); //System.out.println(designNumber + ": " + customizationType); } } + + public byte getAttributeIndex(String type) + { + return customizationMap.get(type); + } @Override public void notifyFolder(String node, int depth) throws Exception { } - public ConcurrentHashMap getCustomizationMap() { + public ConcurrentHashMap getCustomizationMap() { return this.customizationMap; } } diff --git a/src/services/DevService.java b/src/services/DevService.java index 9ea45006..f9689348 100644 --- a/src/services/DevService.java +++ b/src/services/DevService.java @@ -232,27 +232,33 @@ public class DevService implements INetworkDispatch { return; // [Items] Weapons case 30: // Jedi Weapons - SWGObject lightsaber1 = core.objectService.createObject("object/weapon/melee/sword/crafted_saber/shared_sword_lightsaber_one_handed_gen5.iff", planet); + TangibleObject lightsaber1 = (TangibleObject) core.objectService.createObject("object/weapon/melee/sword/crafted_saber/shared_sword_lightsaber_one_handed_gen5.iff", planet); lightsaber1.setIntAttribute("required_combat_level", 90); lightsaber1.setFloatAttribute("cat_wpn_damage.wpn_attack_speed", 1); lightsaber1.setStringAttribute("class_required", "Jedi"); lightsaber1.setStringAttribute("cat_wpn_damage.wpn_damage_type", "Energy"); lightsaber1.setStringAttribute("cat_wpn_damage.damage", "689-1379"); - SWGObject lightsaber2 = core.objectService.createObject("object/weapon/melee/2h_sword/crafted_saber/shared_sword_lightsaber_two_handed_gen5.iff", planet); + TangibleObject lightsaber2 = (TangibleObject) core.objectService.createObject("object/weapon/melee/2h_sword/crafted_saber/shared_sword_lightsaber_two_handed_gen5.iff", planet); lightsaber2.setIntAttribute("required_combat_level", 90); lightsaber2.setFloatAttribute("cat_wpn_damage.wpn_attack_speed", 1); lightsaber2.setStringAttribute("class_required", "Jedi"); lightsaber2.setStringAttribute("cat_wpn_damage.wpn_damage_type", "Energy"); lightsaber2.setStringAttribute("cat_wpn_damage.damage", "689-1379"); - SWGObject lightsaber3 = core.objectService.createObject("object/weapon/melee/polearm/crafted_saber/shared_sword_lightsaber_polearm_gen5.iff", planet); + TangibleObject lightsaber3 = (TangibleObject) core.objectService.createObject("object/weapon/melee/polearm/crafted_saber/shared_sword_lightsaber_polearm_gen5.iff", planet); lightsaber3.setIntAttribute("required_combat_level", 90); lightsaber3.setFloatAttribute("cat_wpn_damage.wpn_attack_speed", 1); lightsaber3.setStringAttribute("class_required", "Jedi"); lightsaber3.setStringAttribute("cat_wpn_damage.wpn_damage_type", "Energy"); lightsaber3.setStringAttribute("cat_wpn_damage.damage", "689-1379"); + Random random = new Random(); + + lightsaber1.setCustomizationVariable("/private/index_color_blade", (byte) random.nextInt(47)); + lightsaber2.setCustomizationVariable("/private/index_color_blade", (byte) random.nextInt(47)); + lightsaber3.setCustomizationVariable("/private/index_color_blade", (byte) random.nextInt(47)); + inventory.add(lightsaber1); inventory.add(lightsaber2); inventory.add(lightsaber3); diff --git a/src/services/EntertainmentService.java b/src/services/EntertainmentService.java index 970d6f2d..0457d94a 100644 --- a/src/services/EntertainmentService.java +++ b/src/services/EntertainmentService.java @@ -65,7 +65,7 @@ public class EntertainmentService implements INetworkDispatch { private ConcurrentHashMap performancesByIndex = new ConcurrentHashMap(); private ConcurrentHashMap danceMap = new ConcurrentHashMap(); - private ConcurrentHashMap designMap = new ConcurrentHashMap(); + private ConcurrentHashMap designMap = new ConcurrentHashMap(); //private Random ranWorkshop = new Random(); @@ -932,7 +932,7 @@ public class EntertainmentService implements INetworkDispatch { public String getCustomizationString(int number){ synchronized (designMap) { - for (Entry entry : designMap.entrySet()) { + for (Entry entry : designMap.entrySet()) { if (entry.getValue().intValue() == number) { return entry.getKey(); } @@ -943,7 +943,7 @@ public class EntertainmentService implements INetworkDispatch { public int getCustomizationValue(String customizationString) { synchronized(designMap){ - for(Entry entry : designMap.entrySet()) { + for(Entry entry : designMap.entrySet()) { if (entry.getKey().equals(customizationString)) { return entry.getValue().intValue(); } diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index 15b784d7..80680ae1 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -87,6 +87,7 @@ import toxi.geom.Line3D; import toxi.geom.Ray3D; import toxi.geom.Vec3D; import toxi.geom.mesh.TriangleMesh; +import wblut.geom.WB_AABB; import wblut.geom.WB_AABBNode; import wblut.geom.WB_AABBTree; import wblut.geom.WB_Distance; @@ -166,6 +167,7 @@ public class SimulationService implements INetworkDispatch { core.commandService.registerCommand("requestbiography"); core.commandService.registerCommand("eject"); core.commandService.registerGmCommand("broadcast"); + core.commandService.registerGmCommand("teleporttarget"); } @@ -689,7 +691,6 @@ public class SimulationService implements INetworkDispatch { float endZ = (float) (modelSpace.m31 * end.x + modelSpace.m32 * end.y + modelSpace.m33 * end.z + modelSpace.m34); end = new Point3D(endX, endY, endZ); - Vector3D direction = new Vector3D(end.x - origin.x, end.y - origin.y, end.z - origin.z); if(direction.getX() > 0 && direction.getY() > 0 && direction.getZ() > 0) direction.normalize(); @@ -719,7 +720,6 @@ public class SimulationService implements INetworkDispatch { return new Point3D(x, y, z); } - /* * Moved this to ConnectionService which will disconnect them * from the server if they don't send packets for 5 minutes or more @@ -902,7 +902,7 @@ public class SimulationService implements INetworkDispatch { } public boolean checkLineOfSight(SWGObject obj1, SWGObject obj2) { - + long startTime = System.nanoTime(); if(obj1.getPlanet() != obj2.getPlanet()) return false; @@ -931,7 +931,7 @@ public class SimulationService implements INetworkDispatch { Point3D end = new Point3D(position2.x, position2.y + heightDirection, position2.z); float distance = position1.getDistance2D(position2); - List inRangeObjects = get(obj1.getPlanet(), position1.x, position1.z, 150); + List inRangeObjects = get(obj1.getPlanet(), position1.x, position1.z, (int) (distance + 10)); for(SWGObject object : inRangeObjects) { @@ -959,6 +959,7 @@ public class SimulationService implements INetworkDispatch { for(Mesh3DTriangle tri : tris) { if(ray.intersectsTriangle(tri, distance) != null) { + //System.out.println("Collision took: " + (System.nanoTime() - startTime) + " ns (collided)"); // System.out.println("Collided with " + object.getTemplate() + " X: " + object.getPosition().x + " Y: " + object.getPosition().y + " Z: " + object.getPosition().z); return false; } @@ -981,8 +982,8 @@ public class SimulationService implements INetworkDispatch { return checkLineOfSightWorldToCell(obj1, obj2, cell); } - /*List segments = new ArrayList(); - Line3D.splitIntoSegments(new Vec3D(position1.x, position1.y + 1, position1.z), new Vec3D(position2.x, position2.y + 1, position2.z), (float) 0.5, segments, true); + List segments = new ArrayList(); + Line3D.splitIntoSegments(new Vec3D(position1.x, position1.y + 1, position1.z), new Vec3D(position2.x, position2.y + 1, position2.z), (float) 1, segments, true); for(Vec3D segment : segments) { float y = segment.y; @@ -990,11 +991,12 @@ public class SimulationService implements INetworkDispatch { int height = (int) core.terrainService.getHeight(obj1.getPlanetId(), segment.x, segment.z); // round down to int if(height > y) { - System.out.println("Collision with terrain"); + //System.out.println("Collision took: " + (System.nanoTime() - startTime) + " ns (terrain collision)"); return false; } - }*/ - + } + //System.out.println("Collision took: " + (System.nanoTime() - startTime) + " ns (did not collide)"); + return true; } @@ -1031,6 +1033,7 @@ public class SimulationService implements INetworkDispatch { MeshVisitor meshVisitor; if(!cellMeshes.containsKey(cell.mesh)) { meshVisitor = ClientFileManager.loadFile(cell.mesh, MeshVisitor.class); + meshVisitor.getTriangles(); cellMeshes.put(cell.mesh, meshVisitor); } else { meshVisitor = cellMeshes.get(cell.mesh); diff --git a/src/services/spawn/MobileTemplate.java b/src/services/spawn/MobileTemplate.java index c2c42166..9b1cb401 100644 --- a/src/services/spawn/MobileTemplate.java +++ b/src/services/spawn/MobileTemplate.java @@ -23,6 +23,7 @@ package services.spawn; import java.util.Vector; +import main.NGECore; import resources.datatables.Options; import resources.datatables.PvpStatus; import resources.objects.weapon.WeaponObject; @@ -43,6 +44,7 @@ public class MobileTemplate { private float scale = 1; // this is a custom attack Range setting to use for large mobs like krayts private int attackRange; + private String customWeaponTemplate; public Vector getTemplates() { return templates; @@ -155,5 +157,14 @@ public class MobileTemplate { public void setAttackRange(int attackRange) { this.attackRange = attackRange; } - + + public void setCustomWeaponTemplate(String template) + { + this.customWeaponTemplate = template; + } + + public String getCustomWeaponTemplate() + { + return customWeaponTemplate; + } } diff --git a/src/services/spawn/SpawnService.java b/src/services/spawn/SpawnService.java index eede805a..c26defae 100644 --- a/src/services/spawn/SpawnService.java +++ b/src/services/spawn/SpawnService.java @@ -112,7 +112,7 @@ public class SpawnService { creature.setLevel(level); else creature.setLevel(mobileTemplate.getLevel()); - WeaponObject defaultWeapon = (WeaponObject) core.objectService.createObject("object/weapon/creature/shared_creature_default_weapon.iff", creature.getPlanet()); + WeaponObject defaultWeapon = (mobileTemplate.getCustomWeaponTemplate() != null) ? (WeaponObject) core.objectService.createObject(mobileTemplate.getCustomWeaponTemplate(), creature.getPlanet()) : (WeaponObject) core.objectService.createObject("object/weapon/creature/shared_creature_default_weapon.iff", creature.getPlanet()); defaultWeapon.setAttackSpeed(2); defaultWeapon.setDamageType("@obj_attr_n:armor_eff_kinetic"); defaultWeapon.setStringAttribute("cat_wpn_damage.damage", "0-0");