diff --git a/ngengine_public.jar b/ngengine_public.jar index 96bf44fb..71c19543 100644 Binary files a/ngengine_public.jar and b/ngengine_public.jar differ diff --git a/scripts/commands/pvp.py b/scripts/commands/pvp.py index b8df8ca0..93e9051b 100644 --- a/scripts/commands/pvp.py +++ b/scripts/commands/pvp.py @@ -22,12 +22,18 @@ def run(core, actor, target, commandString): actor.setFaction('neutral') return - #if actorStatus == 0 and actorFaction == "imperial" or "rebel": - #actor.setFactionStatus(1) + if actorStatus == 0 and actorFaction == "imperial": + actor.setFactionStatus(1) #print ("FactionStatus: " + str(actor.getFactionStatus())) - #actor.sendSystemMessage('You are no longer On Leave.', 0) - #return - + actor.sendSystemMessage('You are no longer On Leave.', 0) + return + + if actorStatus == 0 and actorFaction == "rebel": + actor.setFactionStatus(1) + #print ("FactionStatus: " + str(actor.getFactionStatus())) + actor.sendSystemMessage('You are no longer On Leave.', 0) + return + if actorStatus == 1 and actorFaction == "imperial": actor.setFactionStatus(2) pvpStatus.setFaction(UpdatePVPStatusMessage.factionCRC.Imperial) diff --git a/scripts/commands/transferitemweapon.py b/scripts/commands/transferitemweapon.py index bd1efcd3..a480461a 100644 --- a/scripts/commands/transferitemweapon.py +++ b/scripts/commands/transferitemweapon.py @@ -12,6 +12,6 @@ def run(core, actor, target, commandString): print 'Weapon Test' oldContainer = target.getContainer() oldContainer.transferTo(actor, container, target) - + actor.setWeaponId(target.getObjectID()) return \ No newline at end of file diff --git a/scripts/demo.py b/scripts/demo.py index 0176ca1e..011c9670 100644 --- a/scripts/demo.py +++ b/scripts/demo.py @@ -5,6 +5,30 @@ def CreateStartingCharacter(core, object): testObject = core.objectService.createObject('object/weapon/ranged/rifle/shared_rifle_t21.iff', object.getPlanet()) testObject.setCustomName('This is a Jython Rifle') testObject.setStringAttribute('crafter', 'Light') + testObject.setStringAttribute('cat_wpn_damage.wpn_damage_type', '@obj_attr_n:armor_eff_energy') + testObject.setIntAttribute('cat_wpn_damage.wpn_damage_min', 425) + testObject.setIntAttribute('cat_wpn_damage.wpn_damage_max', 1140) + object.addSkillMod('constitution_modified' , 350) + object.addSkillMod('strength_modified' , 350) + object.addSkillMod('precision_modified' , 350) + object.addSkillMod('luck_modified' , 350) + object.addSkillMod('agility_modified' , 350) + object.addSkillMod('stamina_modified' , 350) + object.addSkillMod('kinetic' , 10000) + object.addSkillMod('energy' , 10000) + object.addSkillMod('heat' , 6000) + object.addSkillMod('cold' , 6000) + object.addSkillMod('acid' , 6000) + object.addSkillMod('electricity' , 6000) + object.addSkillMod('combat_strikethrough_value' , 50) + object.addSkillMod('display_only_dodge' , 2000) + object.addSkillMod('display_only_parry' , 1000) + object.addSkillMod('display_only_strikethrough' , 500) + object.addSkillMod('display_only_critical' , 2500) + object.addSkillMod('display_only_evasion' , 1000) + object.addSkillMod('display_only_glancing_blow' , 750) + object.addSkillMod('display_only_block' , 2000) + object.addSkillMod('combat_block_value' , 0) inventory = object.getSlottedObject('inventory') inventory.add(testObject) @@ -16,5 +40,59 @@ def CreateStartingCharacter(core, object): inventory.add(testClothing) inventory.add(testCloak) + profession = object.getSlottedObject('ghost').getProfession() + addProfessionAbilities(core, object, profession) + return + +def addProfessionAbilities(core, object, profession): + if profession == 'force_sensitive_1a': + testObject = core.objectService.createObject('object/weapon/melee/2h_sword/crafted_saber/shared_sword_lightsaber_two_handed_gcw_s01_gen5.iff', object.getPlanet()) + testObject.setCustomName('Lightsaber') + testObject.setStringAttribute('crafter', 'Light') + testObject.setStringAttribute('cat_wpn_damage.wpn_damage_type', '@obj_attr_n:armor_eff_energy') + testObject.setIntAttribute('cat_wpn_damage.wpn_damage_min', 600) + testObject.setIntAttribute('cat_wpn_damage.wpn_damage_max', 1300) + inventory = object.getSlottedObject('inventory') + inventory.add(testObject) + + object.addAbility('fs_sweep_7') + object.addAbility('fs_drain_7') + object.addAbility('forceRun') + object.addAbility('fs_dm_cc_crit_5') + object.addAbility('fs_maelstrom_5') + object.addAbility('fs_ae_dm_cc_6') + object.addAbility('fs_sh_3') + object.addAbility('fs_dm_cc_6') + object.addAbility('fs_dm_7') + elif profession == 'medic_1a': + object.addAbility('me_bacta_bomb_5') + object.addAbility('me_bacta_grenade_5') + object.addAbility('me_bacta_ampule_6') + object.addAbility('me_ae_heal_6') + object.addAbility('me_dm_8') + object.addAbility('me_dm_dot_6') + object.addAbility('me_drag_1') + object.addAbility('me_rv_pvp_single') + object.addAbility('me_rv_area') + object.addAbility('me_rv_pvp_area') + object.addAbility('me_reckless_stimulation_6') + object.addAbility('me_sh_1') + object.addAbility('me_stasis_1') + object.addAbility('me_stasis_self_1') + object.addAbility('me_thyroid_rupture_1') + object.addAbility('me_traumatize_5') + object.addAbility('me_induce_insanity_1') + elif profession == 'bounty_hunter_1a': + object.addAbility('bh_shields_1') + object.addAbility('bh_dm_8') + object.addAbility('bh_sh_3') + object.addAbility('bh_armor_sprint_1') + object.addAbility('bh_prescience') + object.addAbility('bh_dm_crit_8') + object.addAbility('crippleShot') + object.addAbility('bh_fumble_6') + object.addAbility('bh_intimidate_6') + object.addAbility('bh_flawless_strike') + return diff --git a/src/main/NGECore.java b/src/main/NGECore.java index ba8370bf..b0376f0e 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -36,6 +36,7 @@ import services.AttributeService; import services.CharacterService; import services.ConnectionService; import services.LoginService; +import services.PlayerService; import services.ScriptService; import services.SimulationService; import services.TerrainService; @@ -106,6 +107,7 @@ public class NGECore { public GCWService gcwService; public TradeService tradeService; public CombatService combatService; + public PlayerService playerService; // Login Server public NetworkDispatch loginDispatch; @@ -153,6 +155,7 @@ public class NGECore { attributeService = new AttributeService(this); suiService = new SUIService(this); combatService = new CombatService(this); + playerService = new PlayerService(this); // Ping Server try { PingServer pingServer = new PingServer(config.getInt("PING.PORT")); diff --git a/src/protocol/swg/ChatPersistentMessageToClient.java b/src/protocol/swg/ChatPersistentMessageToClient.java index 08f79a3d..249d30e6 100644 --- a/src/protocol/swg/ChatPersistentMessageToClient.java +++ b/src/protocol/swg/ChatPersistentMessageToClient.java @@ -22,9 +22,13 @@ package protocol.swg; import java.nio.ByteOrder; +import java.util.List; +import java.util.Vector; import org.apache.mina.core.buffer.IoBuffer; +import services.chat.WaypointAttachment; + public class ChatPersistentMessageToClient extends SWGMessage { @@ -36,8 +40,9 @@ public class ChatPersistentMessageToClient extends SWGMessage { private String subject; private byte status; private int timestamp; + private List attachments; - public ChatPersistentMessageToClient(String sender, String galaxyName, int mailId, byte requestTypeFlag, String message, String subject, byte status, int timestamp) { + public ChatPersistentMessageToClient(String sender, String galaxyName, int mailId, byte requestTypeFlag, String message, String subject, byte status, int timestamp, List attachments) { this.sender = sender; this.galaxyName = galaxyName; @@ -47,6 +52,7 @@ public class ChatPersistentMessageToClient extends SWGMessage { this.subject = subject; this.status = status; this.timestamp = timestamp; + this.attachments = attachments; } @@ -60,7 +66,7 @@ public class ChatPersistentMessageToClient extends SWGMessage { public IoBuffer serialize() { IoBuffer result = IoBuffer.allocate(41 + sender.length() + galaxyName.length() + message.length() * 2 + subject.length() * 2).order(ByteOrder.LITTLE_ENDIAN); - + result.setAutoExpand(true); result.putShort((short) 2); result.putInt(0x08485E17); result.put(getAsciiString(sender)); @@ -75,12 +81,40 @@ public class ChatPersistentMessageToClient extends SWGMessage { result.put(getUnicodeString(message)); result.put(getUnicodeString(subject)); - result.putInt(0); // attachements doing later when waypoints work + + if(requestTypeFlag == 1 || attachments.size() == 0) + result.putInt(0); + else if(requestTypeFlag == 0 && attachments.size() > 0){ + + int position = result.position(); + result.putInt(0); + + for(WaypointAttachment attachment : attachments) { + + result.putInt(0); + result.putFloat(attachment.positionX); + result.putFloat(attachment.positionY); + result.putFloat(attachment.positionZ); + result.putLong(0); + result.putInt(attachment.planetCRC); + result.put(getUnicodeString(attachment.name)); + result.putLong(attachment.cellID); + result.put(attachment.color); + result.put((byte) (attachment.active ? 1 : 0)); + + } + + result.putInt(position, (result.position() - position - 4) / 2); + + } result.put(status); result.putInt(timestamp); result.putInt(0); + int size = result.position(); + result = IoBuffer.allocate(size).put(result.array(), 0, size); + return result.flip(); } diff --git a/src/protocol/swg/ChatPersistentMessageToServer.java b/src/protocol/swg/ChatPersistentMessageToServer.java index 40b9d142..42d1dfd2 100644 --- a/src/protocol/swg/ChatPersistentMessageToServer.java +++ b/src/protocol/swg/ChatPersistentMessageToServer.java @@ -23,9 +23,16 @@ package protocol.swg; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; import org.apache.mina.core.buffer.IoBuffer; +import services.chat.WaypointAttachment; + +import com.sleepycat.persist.model.Persistent; + public class ChatPersistentMessageToServer extends SWGMessage { @@ -33,6 +40,7 @@ public class ChatPersistentMessageToServer extends SWGMessage { private int counter; private String subject; private String recipient; + private List waypointAttachments = new ArrayList(); @Override public void deserialize(IoBuffer buffer) { @@ -47,11 +55,52 @@ public class ChatPersistentMessageToServer extends SWGMessage { setMessage(new String(ByteBuffer.allocate(size * 2).put(buffer.array(), buffer.position(), size * 2).array(), "UTF-16LE")); buffer.position(buffer.position() + size * 2); - int attachmentsSize = buffer.getInt(); // TODO: Implement when waypoints are done + int attachmentsSize = buffer.getInt() * 2; - while(attachmentsSize > 0) { + /*while(attachmentsSize > 0) { buffer.get(); --attachmentsSize; + }*/ + + if(attachmentsSize > 0) { + + int position = buffer.position(); + + while(buffer.position() < position + attachmentsSize) { + + short appendByte = buffer.getShort(); + buffer.get(); + int type = buffer.getInt(); + + if(type == 0xFFFFFFFD) { + + WaypointAttachment waypoint = new WaypointAttachment(); + + buffer.getInt(); // unk 0 + waypoint.positionX = buffer.getFloat(); + waypoint.positionY = buffer.getFloat(); + waypoint.positionZ = buffer.getFloat(); + buffer.getLong(); // unk + waypoint.planetCRC = buffer.getInt(); + size = buffer.getInt(); + waypoint.name = new String(ByteBuffer.allocate(size * 2).put(buffer.array(), buffer.position(), size * 2).array(), "UTF-16LE"); + buffer.position(buffer.position() + size * 2); + waypoint.cellID = buffer.getLong(); + waypoint.color = buffer.get(); + byte active = buffer.get(); + if(active == 1) + waypoint.active = true; + else + waypoint.active = false; + + waypointAttachments.add(waypoint); + + if(appendByte > 0) + buffer.get(); + + } + } + } setCounter(buffer.getInt()); @@ -110,5 +159,15 @@ public class ChatPersistentMessageToServer extends SWGMessage { public void setCounter(int counter) { this.counter = counter; } + + public List getWaypointAttachments() { + return waypointAttachments; + } + + public void setWaypointAttachments(List waypointAttachments) { + this.waypointAttachments = waypointAttachments; + } + + } diff --git a/src/protocol/swg/ObjControllerMessage.java b/src/protocol/swg/ObjControllerMessage.java index 979a9b5e..e307d7c2 100644 --- a/src/protocol/swg/ObjControllerMessage.java +++ b/src/protocol/swg/ObjControllerMessage.java @@ -51,6 +51,7 @@ public class ObjControllerMessage extends SWGMessage { public static final int SIT_ON_OBJECT = 0x013B; public static final int OBJECT_MENU_RESPONSE = 0x0147; public static final int SHOW_FLY_TEXT = 0x01BD; + public static final int START_TASK = 0x448; public ObjControllerMessage() { diff --git a/src/protocol/swg/UpdateTransformMessage.java b/src/protocol/swg/UpdateTransformMessage.java index 555e2a2b..b5d1b0ee 100644 --- a/src/protocol/swg/UpdateTransformMessage.java +++ b/src/protocol/swg/UpdateTransformMessage.java @@ -38,7 +38,7 @@ public class UpdateTransformMessage extends SWGMessage { private float speed; private byte combatFlag; - public UpdateTransformMessage(long objectId, short x, short y, short z, int movementCounter, byte direction, float speed, byte combatFlag) { + public UpdateTransformMessage(long objectId, short x, short y, short z, int movementCounter, byte direction, float speed) { this.objectId = objectId; this.x = x; this.y = y; @@ -46,7 +46,6 @@ public class UpdateTransformMessage extends SWGMessage { this.movementCounter = movementCounter; this.direction = direction; this.speed = speed; - this.combatFlag = combatFlag; } public void deserialize(IoBuffer data) { @@ -65,8 +64,8 @@ public class UpdateTransformMessage extends SWGMessage { result.putInt(movementCounter+1); result.put((byte) speed); result.put((byte) direction); + result.put((byte) 1); result.put((byte) 0); - result.put(combatFlag); result.flip(); return result; } diff --git a/src/protocol/swg/UpdateTransformWithParentMessage.java b/src/protocol/swg/UpdateTransformWithParentMessage.java index fd3ca8e9..249e26a3 100644 --- a/src/protocol/swg/UpdateTransformWithParentMessage.java +++ b/src/protocol/swg/UpdateTransformWithParentMessage.java @@ -39,7 +39,7 @@ public class UpdateTransformWithParentMessage extends SWGMessage { private float speed; private byte combatFlag; - public UpdateTransformWithParentMessage(long objectId, long cellId, short x, short y, short z, int movementCounter, byte direction, float speed, byte combatFlag) { + public UpdateTransformWithParentMessage(long objectId, long cellId, short x, short y, short z, int movementCounter, byte direction, float speed) { this.objectId = objectId; this.cellId = cellId; this.x = x; @@ -48,7 +48,6 @@ public class UpdateTransformWithParentMessage extends SWGMessage { this.movementCounter = movementCounter; this.direction = direction; this.speed = speed; - this.combatFlag = combatFlag; } public void deserialize(IoBuffer data) { @@ -68,7 +67,8 @@ public class UpdateTransformWithParentMessage extends SWGMessage { result.putInt(movementCounter+1); result.put((byte) speed); result.put(direction); - result.put(combatFlag); + result.put((byte) 1); + result.put((byte) 0); result.flip(); return result; } diff --git a/src/protocol/swg/objectControllerObjects/CombatAction.java b/src/protocol/swg/objectControllerObjects/CombatAction.java index 6a119b38..41087f21 100644 --- a/src/protocol/swg/objectControllerObjects/CombatAction.java +++ b/src/protocol/swg/objectControllerObjects/CombatAction.java @@ -33,12 +33,14 @@ public class CombatAction extends ObjControllerObject{ private long attackerId; private long weaponId; private long defenderId; + private int commandCRC; - public CombatAction(int actionCRC, long attackerId, long weaponId, long defenderId) { + public CombatAction(int actionCRC, long attackerId, long weaponId, long defenderId, int commandCRC) { this.actionCRC = actionCRC; this.attackerId = attackerId; this.weaponId = weaponId; this.defenderId = defenderId; + this.commandCRC = commandCRC; } public void deserialize(IoBuffer data) { @@ -46,7 +48,8 @@ public class CombatAction extends ObjControllerObject{ } public IoBuffer serialize() { - IoBuffer result = IoBuffer.allocate(100).order(ByteOrder.LITTLE_ENDIAN); + + IoBuffer result = IoBuffer.allocate(60).order(ByteOrder.LITTLE_ENDIAN); result.putInt(ObjControllerMessage.COMBAT_ACTION); @@ -56,17 +59,23 @@ public class CombatAction extends ObjControllerObject{ result.putLong(attackerId); result.putLong(weaponId); result.put((byte) 0); + result.put((byte) 0x10); + result.put((byte) 0); + result.putInt(commandCRC); + result.put((byte) 0); + result.putShort((short) 1); + result.putLong(defenderId); + result.put((byte) 0); result.put((byte) 1); result.put((byte) 0); - byte[] unkdata = new byte[] { - 0x2B, (byte) 0x87, 0x64, (byte) 0xA1, 0x01, 0x15, 0x02, (byte) 0x97, (byte) 0xC5, 0x00, 0x00, (byte) 0xD0, 0x40, 0x6F, 0x16, (byte) 0x80, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }; - result.put(unkdata); + byte[] unkdata2 = new byte[] { (byte) 0, 0, 0 }; + result.put(unkdata2); + + return result.flip(); - return result; } public CombatAction clone() { - return new CombatAction(actionCRC, attackerId, weaponId, defenderId); + return new CombatAction(actionCRC, attackerId, weaponId, defenderId, actionCRC); } } diff --git a/src/protocol/swg/objectControllerObjects/StartTask.java b/src/protocol/swg/objectControllerObjects/StartTask.java new file mode 100644 index 00000000..c8cdd408 --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/StartTask.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * 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 protocol.swg.objectControllerObjects; + +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; + +import protocol.swg.ObjControllerMessage; + +public class StartTask extends ObjControllerObject { + + private int actionCounter; + private long objectId; + private int commandCRC; + + public StartTask(int actionCounter, long objectId, int commandCRC) { + this.actionCounter = actionCounter; + this.objectId = objectId; + this.commandCRC = commandCRC; + } + + @Override + public void deserialize(IoBuffer data) { + // TODO Auto-generated method stub + + } + + @Override + public IoBuffer serialize() { + + IoBuffer result = IoBuffer.allocate(33).order(ByteOrder.LITTLE_ENDIAN); + + result.putInt(ObjControllerMessage.START_TASK); + + result.putLong(objectId); + result.putInt(0); + result.put((byte) 0); + result.putInt(actionCounter); + result.putLong(0); + result.putInt(commandCRC); + + return result.flip(); + + } + +} diff --git a/src/resources/objects/creature/CreatureMessageBuilder.java b/src/resources/objects/creature/CreatureMessageBuilder.java index dd21c99d..939496a8 100644 --- a/src/resources/objects/creature/CreatureMessageBuilder.java +++ b/src/resources/objects/creature/CreatureMessageBuilder.java @@ -247,11 +247,11 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putInt(0); buffer.putInt(6); // Current HAM - buffer.putInt(0); + buffer.putInt(creature.getHamListCounter()); - buffer.putInt(20000); + buffer.putInt(creature.getHealth()); buffer.putInt(0); - buffer.putInt(12500); + buffer.putInt(creature.getAction()); buffer.putInt(0); buffer.putInt(0x2C01); buffer.putInt(0); diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index d1a47a43..6a16e987 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -27,6 +27,7 @@ import java.util.List; import org.apache.mina.core.buffer.IoBuffer; +import protocol.Message; import protocol.swg.ChatSystemMessage; import protocol.swg.ObjControllerMessage; import protocol.swg.UpdatePVPStatusMessage; @@ -112,12 +113,12 @@ public class CreatureObject extends TangibleObject implements IPersistent { private byte moodId = 0; private int performanceCounter = 0; private int performanceId = 0; - private int health; - private int action; + private int health = 20000; + private int action = 12500; @NotPersistent private int HAMListCounter = 0; - private int maxHealth; - private int maxAction; + private int maxHealth = 20000; + private int maxAction = 12500; @NotPersistent private int maxHAMListCounter = 0; @@ -352,6 +353,16 @@ public class CreatureObject extends TangibleObject implements IPersistent { } return null; } + + public void addSkillMod(String name, int base) { + synchronized(objectMutex) { + SkillMod skillMod = new SkillMod(); + skillMod.setBase(base); + skillMod.setSkillModString(name); + skillMod.setModifier(0); + skillMods.add(skillMod); + } + } public short getSkillModsUpdateCounter() { synchronized(objectMutex) { @@ -497,6 +508,12 @@ public class CreatureObject extends TangibleObject implements IPersistent { this.abilitiesUpdateCounter = abilitiesUpdateCounter; } } + + public void addAbility(String abilityName) { + synchronized(objectMutex) { + abilities.add(abilityName); + } + } public List getMissionCriticalObjects() { return missionCriticalObjects; @@ -512,6 +529,9 @@ public class CreatureObject extends TangibleObject implements IPersistent { synchronized(objectMutex) { this.combatFlag = combatFlag; } + IoBuffer combatDelta = messageBuilder.buildCombatFlagDelta(combatFlag); + + notifyObservers(combatDelta, true); } public short getLevel() { @@ -796,11 +816,15 @@ public class CreatureObject extends TangibleObject implements IPersistent { } public void setHealth(int health) { + IoBuffer delta; synchronized(objectMutex) { + if(health > maxHealth) + health = maxHealth; this.health = health; - setMaxHAMListCounter(getHamListCounter() + 1); + setHamListCounter(getHamListCounter() + 1); + delta = messageBuilder.buildHealthDelta(health); } - notifyObservers(messageBuilder.buildHealthDelta(health), true); + notifyObservers(delta, true); } public int getAction() { @@ -810,11 +834,15 @@ public class CreatureObject extends TangibleObject implements IPersistent { } public void setAction(int action) { + IoBuffer delta; synchronized(objectMutex) { + if(action > maxAction) + action = maxAction; this.action = action; - setMaxHAMListCounter(getHamListCounter() + 1); + setHamListCounter(getHamListCounter() + 1); + delta = messageBuilder.buildActionDelta(action); } - notifyObservers(messageBuilder.buildActionDelta(action), true); + notifyObservers(delta, true); } public int getHamListCounter() { diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index d39a7dab..e8c231e7 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -54,7 +54,7 @@ public class TangibleObject extends SWGObject { protected int optionsBitmask = 0; private int maxDamage = 0; private boolean staticObject = false; - protected String faction; + protected String faction = ""; @NotPersistent private Vector defendersList = new Vector(); // unused in packets but useful for the server @NotPersistent diff --git a/src/resources/objects/weapon/WeaponMessageBuilder.java b/src/resources/objects/weapon/WeaponMessageBuilder.java index 6e722042..6f3a3a1f 100644 --- a/src/resources/objects/weapon/WeaponMessageBuilder.java +++ b/src/resources/objects/weapon/WeaponMessageBuilder.java @@ -66,9 +66,8 @@ public class WeaponMessageBuilder extends ObjectMessageBuilder { buffer.putFloat(weapon.getAttackSpeed()); buffer.putInt(0); buffer.putInt(0); - buffer.putShort((short) 0); - buffer.putInt(0x014280); // range 64m no idea how this converts to 64 - buffer.putShort((short) 0); + buffer.putFloat(weapon.getMaxRange()); + buffer.putInt(0); buffer.putInt(0); buffer.putInt(0); // those 2 ints have something to do with particle color diff --git a/src/services/PlayerService.java b/src/services/PlayerService.java index 8fbc152f..53980f93 100644 --- a/src/services/PlayerService.java +++ b/src/services/PlayerService.java @@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit; import org.apache.mina.core.buffer.IoBuffer; import protocol.swg.ServerTimeMessage; +import resources.objects.creature.CreatureObject; import main.NGECore; @@ -41,7 +42,7 @@ import engine.resources.service.INetworkRemoteEvent; public class PlayerService implements INetworkDispatch { private NGECore core; - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2); public PlayerService(final NGECore core) { this.core = core; @@ -62,6 +63,34 @@ public class PlayerService implements INetworkDispatch { }, 1, 1, TimeUnit.MINUTES); } + + public void postZoneIn(final CreatureObject creature) { + + scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + + if(creature.getAction() < creature.getMaxAction()) + creature.setAction(creature.getAction() + 200); + + } + + }, 0, 1, TimeUnit.SECONDS); + + scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + + if(creature.getHealth() < creature.getMaxHealth() && creature.getCombatFlag() == 0) + creature.setHealth(creature.getHealth() + 300); + + } + + }, 0, 1, TimeUnit.SECONDS); + + } @Override public void insertOpcodes(Map arg0, diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index e665d258..fe4b3336 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -226,7 +226,7 @@ public class SimulationService implements INetworkDispatch { //object.setParent(null); // System.out.println("Parsed Height: " + core.terrainService.getHeight(object.getPlanetId(), dataTransform.getXPosition(), dataTransform.getZPosition()) // + " should be: " + dataTransform.getYPosition()); - UpdateTransformMessage utm = new UpdateTransformMessage(object.getObjectID(), dataTransform.getTransformedX(), dataTransform.getTransformedY(), dataTransform.getTransformedZ(), dataTransform.getMovementCounter(), (byte) dataTransform.getMovementAngle(), dataTransform.getSpeed(), object.getCombatFlag()); + UpdateTransformMessage utm = new UpdateTransformMessage(object.getObjectID(), dataTransform.getTransformedX(), dataTransform.getTransformedY(), dataTransform.getTransformedZ(), dataTransform.getMovementCounter(), (byte) dataTransform.getMovementAngle(), dataTransform.getSpeed()); List newAwareObjects = get(object.getPlanet(), newPos.x, newPos.z, 200); ArrayList oldAwareObjects = new ArrayList(object.getAwareObjects()); @@ -289,7 +289,7 @@ public class SimulationService implements INetworkDispatch { Point3D oldPos = object.getPosition(); Quaternion newOrientation = new Quaternion(dataTransform.getWOrientation(), dataTransform.getXOrientation(), dataTransform.getYOrientation(), dataTransform.getZOrientation()); - UpdateTransformWithParentMessage utm = new UpdateTransformWithParentMessage(object.getObjectID(), dataTransform.getCellId(), dataTransform.getTransformedX(), dataTransform.getTransformedY(), dataTransform.getTransformedZ(), dataTransform.getMovementCounter(), (byte) dataTransform.getMovementAngle(), dataTransform.getSpeed(), object.getCombatFlag()); + UpdateTransformWithParentMessage utm = new UpdateTransformWithParentMessage(object.getObjectID(), dataTransform.getCellId(), dataTransform.getTransformedX(), dataTransform.getTransformedY(), dataTransform.getTransformedZ(), dataTransform.getMovementCounter(), (byte) dataTransform.getMovementAngle(), dataTransform.getSpeed()); if(object.getContainer() != parent) { @@ -417,7 +417,9 @@ public class SimulationService implements INetworkDispatch { end = new Point3D(endX, endY, endZ); - Vector3D direction = new Vector3D(end.x - origin.x, end.y - origin.y, end.z - origin.z).normalize(); + 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(); return new Ray(origin, direction); diff --git a/src/services/chat/ChatService.java b/src/services/chat/ChatService.java index 52e68333..fecb6110 100644 --- a/src/services/chat/ChatService.java +++ b/src/services/chat/ChatService.java @@ -229,7 +229,7 @@ public class ChatService implements INetworkDispatch { mail.setStatus(Mail.NEW); mail.setSubject(packet.getSubject()); mail.setTimeStamp((int) (date.getTime() / 1000)); - + mail.setAttachments(packet.getWaypointAttachments()); storePersistentMessage(mail); if(recipient.getClient() != null) { @@ -324,7 +324,7 @@ public class ChatService implements INetworkDispatch { //System.out.println(config.getString("GALAXY_NAME")); ChatPersistentMessageToClient msg = new ChatPersistentMessageToClient(mail.getSenderName(), config.getString("GALAXY_NAME"), mail.getMailId() - ,(byte) 1, "", mail.getSubject(), mail.getStatus(), mail.getTimeStamp()); + ,(byte) 1, "", mail.getSubject(), mail.getStatus(), mail.getTimeStamp(), mail.getAttachments()); client.getSession().write(msg.serialize()); } @@ -343,7 +343,7 @@ public class ChatService implements INetworkDispatch { //System.out.println(config.getString("GALAXY_NAME")); ChatPersistentMessageToClient msg = new ChatPersistentMessageToClient(mail.getSenderName(), config.getString("GALAXY_NAME"), mail.getMailId() - ,(byte) 0, mail.getMessage(), mail.getSubject(), mail.getStatus(), mail.getTimeStamp()); + ,(byte) 0, mail.getMessage(), mail.getSubject(), mail.getStatus(), mail.getTimeStamp(), mail.getAttachments()); client.getSession().write(msg.serialize()); } diff --git a/src/services/chat/Mail.java b/src/services/chat/Mail.java index cf811a62..3b6ad439 100644 --- a/src/services/chat/Mail.java +++ b/src/services/chat/Mail.java @@ -21,10 +21,14 @@ ******************************************************************************/ package services.chat; +import java.util.List; +import java.util.Vector; + + import com.sleepycat.persist.model.Entity; import com.sleepycat.persist.model.PrimaryKey; -@Entity +@Entity(version=1) public class Mail { @PrimaryKey @@ -35,6 +39,7 @@ public class Mail { private String message; private byte status; private int timeStamp; + private List attachments; public static final byte NEW = 0x4E; public static final byte READ = 0x52; @@ -114,5 +119,15 @@ public class Mail { public void setTimeStamp(int timeStamp) { this.timeStamp = timeStamp; } + + + public List getAttachments() { + return attachments; + } + + + public void setAttachments(List attachments) { + this.attachments = attachments; + } } diff --git a/src/services/chat/WaypointAttachment.java b/src/services/chat/WaypointAttachment.java new file mode 100644 index 00000000..314cb08f --- /dev/null +++ b/src/services/chat/WaypointAttachment.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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.chat; + +import com.sleepycat.persist.model.Persistent; + +@Persistent +public class WaypointAttachment { + + public WaypointAttachment() { } + + public long cellID; + public int planetCRC; + public float positionX; + public float positionY; + public float positionZ; + public byte color; + public boolean active; + public String name; + +} diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index 1806d769..39cf70d7 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -24,6 +24,13 @@ package services.combat; import java.util.Map; import java.util.Random; +import org.python.modules.math; + +import protocol.swg.ObjControllerMessage; +import protocol.swg.objectControllerObjects.CombatAction; +import protocol.swg.objectControllerObjects.CommandEnqueueRemove; +import protocol.swg.objectControllerObjects.StartTask; + import resources.objects.creature.CreatureObject; import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; @@ -31,6 +38,7 @@ import services.command.CombatCommand; import main.NGECore; +import engine.resources.common.CRC; import engine.resources.objects.SWGObject; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; @@ -41,6 +49,16 @@ public class CombatService implements INetworkDispatch { public CombatService(NGECore core) { this.core = core; + core.commandService.registerCombatCommand("rangedshotrifle"); + core.commandService.registerCombatCommand("rangedshotpistol"); + core.commandService.registerCombatCommand("rangedshotlightrifle"); + core.commandService.registerCombatCommand("rangedshot"); + core.commandService.registerCombatCommand("meleehit"); + core.commandService.registerCombatCommand("saberhit"); + core.commandService.registerCombatCommand("fs_sweep_7"); + core.commandService.registerCombatCommand("fs_dm_7"); + core.commandService.registerCombatCommand("fs_dm_cc_6"); + core.commandService.registerCombatCommand("fs_ae_dm_cc_6"); } @Override @@ -136,13 +154,31 @@ public class CombatService implements INetworkDispatch { damage -= blockValue; } + + if(damage > 0) + applyDamage(attacker, target, (int) damage); - applyDamage(attacker, target, (int) damage); + sendCombatPackets(attacker, target, weapon, command, actionCounter); } + private void sendCombatPackets(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + + String animationStr = command.getRandomAnimation(weapon); + CombatAction combatAction = new CombatAction(CRC.StringtoCRC(animationStr), attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); + ObjControllerMessage objController = new ObjControllerMessage(0x1B, combatAction); + attacker.notifyObserversInRange(objController, true, 125); + StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC()); + ObjControllerMessage objController2 = new ObjControllerMessage(0x0B, startTask); + attacker.getClient().getSession().write(objController2.serialize()); + CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectID(), actionCounter); + ObjControllerMessage objController3 = new ObjControllerMessage(0x0B, commandRemove); + attacker.getClient().getSession().write(objController3.serialize()); + + } + private float getArmorReduction(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, byte hitType) { int elementalType = 1; @@ -441,6 +477,26 @@ public class CombatService implements INetworkDispatch { } + private boolean isInConeAngle(CreatureObject attacker, CreatureObject target, int coneLength, int coneWidth, float directionX, float directionZ) { + + float radius = coneWidth / 2; + float angle = (float) (2 * Math.atan(coneLength / radius)); + + float targetX = target.getWorldPosition().x - attacker.getWorldPosition().x; + float targetZ = target.getWorldPosition().z - attacker.getWorldPosition().z; + + float targetAngle = (float) (Math.atan2(targetZ, targetX) - Math.atan2(directionZ, directionX)); + + float degrees = (float) (targetAngle * 180 / Math.PI); + float coneAngle = angle / 2; + + if(degrees > coneAngle || degrees < -coneAngle) + return false; + + return true; + + } + public enum HitType{; diff --git a/src/services/command/CombatCommand.java b/src/services/command/CombatCommand.java index d708476d..41cbcedb 100644 --- a/src/services/command/CombatCommand.java +++ b/src/services/command/CombatCommand.java @@ -21,6 +21,9 @@ ******************************************************************************/ package services.command; +import java.util.Random; + +import resources.objects.weapon.WeaponObject; import engine.clientdata.ClientFileManager; import engine.clientdata.visitors.DatatableVisitor; @@ -72,7 +75,7 @@ public class CombatCommand extends BaseSWGCommand { for(int i = 0; i < visitor.getRowCount(); i++) { if(visitor.getObject(i, 0) != null) - if(((String) visitor.getObject(i, 0)).equals(commandName)) { + if(((String) visitor.getObject(i, 0)).equalsIgnoreCase(commandName)) { validTargetType = ((Integer) visitor.getObject(i, 5)).byteValue(); hitType = ((Integer) visitor.getObject(i, 6)).byteValue(); @@ -110,7 +113,7 @@ public class CombatCommand extends BaseSWGCommand { coneWidth = (Float) visitor.getObject(i, 42); minRange = (Float) visitor.getObject(i, 43); maxRange = (Float) visitor.getObject(i, 44); - addedDamage = (Integer) visitor.getObject(i, 45); + addedDamage = (Integer) visitor.getObject(i, 45); flatActionDamage = (Integer) visitor.getObject(i, 46); percentFromWeapon = (Float) visitor.getObject(i, 47); bypassArmor = (Float) visitor.getObject(i, 48); @@ -527,6 +530,60 @@ public class CombatCommand extends BaseSWGCommand { public void setHitSpam(byte hitSpam) { this.hitSpam = hitSpam; } + + public String getRandomAnimation(WeaponObject weapon) { + + int weaponType = weapon.getWeaponType(); + String[] animations; + + switch(weaponType) { + + case 0: + animations = rifleAnimations; + break; + case 1: + animations = carbineAnimations; + break; + case 2: + animations = pistolAnimations; + break; + case 3: + animations = heavyWpnAnimations; + break; + case 4: + animations = oneHandedAnimations; + break; + case 5: + animations = twoHandedAnimations; + break; + case 6: + animations = unarmedAnimations; + break; + case 7: + animations = polearmAnimations; + break; + case 8: + animations = thrownAnimations; + break; + case 9: + animations = oneHandedLSAnimations; + break; + case 10: + animations = twoHandedLSAnimations; + break; + case 11: + animations = polearmLSAnimations; + break; + + default: + animations = unarmedAnimations; + break; + + } + + return animations[new Random().nextInt(animations.length)]; + + } diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index 83259806..c9d096ab 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -360,21 +360,23 @@ public class ObjectService implements INetworkDispatch { @Override public void process(SWGObject object) { - if(object.getParentId() != 0 && object.getContainer() == null) - object.setParent(getObject(object.getParentId())); - object.getContainerInfo(object.getTemplate()); - } - - }); - creature.viewChildren(creature, true, true, new Traverser() { - - @Override - public void process(SWGObject object) { - //System.out.println(object.getTemplate()); objectList.add(object); } }); + + creature.viewChildren(creature, true, true, new Traverser() { + + @Override + public void process(SWGObject object) { + if(object.getParentId() != 0 && object.getContainer() == null) + object.setParent(getObject(object.getParentId())); + object.getContainerInfo(object.getTemplate()); + if(getObject(object.getObjectID()) == null) + objectList.add(object); + } + + }); if(creature.getParentId() != 0) { SWGObject parent = getObject(creature.getParentId()); @@ -400,6 +402,8 @@ public class ObjectService implements INetworkDispatch { core.simulationService.handleZoneIn(client); creature.makeAware(creature); + + core.playerService.postZoneIn(creature); //CmdSceneReady cmdSceneReady = new CmdSceneReady(); //session.write(cmdSceneReady.serialize());