diff --git a/ngengine_public.jar b/ngengine_public.jar index d776cf77..97f05a6f 100644 Binary files a/ngengine_public.jar and b/ngengine_public.jar differ diff --git a/src/protocol/swg/objectControllerObjects/CombatSpam.java b/src/protocol/swg/objectControllerObjects/CombatSpam.java index e0ba5618..f83d7744 100644 --- a/src/protocol/swg/objectControllerObjects/CombatSpam.java +++ b/src/protocol/swg/objectControllerObjects/CombatSpam.java @@ -26,6 +26,7 @@ import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; import protocol.swg.ObjControllerMessage; +import services.combat.CombatService.HitType; public class CombatSpam extends ObjControllerObject{ @@ -35,17 +36,32 @@ public class CombatSpam extends ObjControllerObject{ private String file; private String text; private byte colorFlag; - private long objectId; + private boolean hit = true; + private boolean critical = false; + private boolean dodge = false; + private boolean parry = false; + private boolean glance = false; + private long weaponId; + private int armorAbsorbed; - public CombatSpam(long attackerId, long defenderId, int damage, String file, String text, byte colorFlag, long objectId) { + public CombatSpam(long attackerId, long defenderId, long weaponId, int damage, int armorAbsorbed, int hitType) { this.attackerId = attackerId; this.defenderId = defenderId; + this.weaponId = weaponId; this.damage = damage; - this.file = file; - this.text = text; - this.colorFlag = colorFlag; - this.objectId = objectId; + this.armorAbsorbed = armorAbsorbed; + + switch(hitType) { + + case HitType.CRITICAL: critical = true; break; + case HitType.DODGE: dodge = true; hit = false; break; + case HitType.GLANCE: glance = true; break; + case HitType.PARRY: parry = true; hit = false; break; + case HitType.MISS: hit = false; break; + + } + } public void deserialize(IoBuffer data) { @@ -53,28 +69,55 @@ public class CombatSpam extends ObjControllerObject{ } public IoBuffer serialize() { + IoBuffer result = IoBuffer.allocate(100).order(ByteOrder.LITTLE_ENDIAN); + result.setAutoExpand(true); result.putInt(ObjControllerMessage.COMBAT_SPAM); - - result.putLong(objectId); - result.putInt(0); - //result.put((byte) 2); //unk result.putLong(attackerId); - result.putLong(defenderId); - result.putLong(0); - result.putInt(damage); - result.putShort((short) file.length()); - result.put(getAsciiString(file)); result.putInt(0); - result.putShort((short) text.length()); - result.put(getAsciiString(text)); - result.put(colorFlag); + result.put((byte) 0); //unk + result.putLong(attackerId); + result.putInt(0); + result.putInt(0); + result.putInt(0); + result.putLong(defenderId); + result.putInt(0); + result.putInt(0); + result.putInt(0); + result.putLong(weaponId); + result.putShort((short) 0); // unk + result.putInt(0xFFFFFFFF); // color? + result.putShort((short) 0); // unk + result.put((byte) ((boolean) hit ? 1 : 0)); // 0 = miss + result.put((byte) ((boolean) dodge ? 1 : 0)); // 1 = dodge + result.put((byte) ((boolean) parry ? 1 : 0)); // 1 = parry + result.put((byte) 0); // unk + result.putInt(0); // unk + result.put((byte) 0); //unk + result.putInt(2000); // unk + result.putInt(0); // type of elemental 1 = heat 2 = cold + result.putInt(0); // elemental damage + result.putInt(0x20); // unk + result.putInt(0); // unk + result.putInt(0); // unk + result.putInt(armorAbsorbed); // damage absorbed by armor + result.putInt(damage); // total damage done after armor without elemental + result.putInt(0); // punishing blow for all values + result.putInt(0); // unk + result.putInt(0); // unk + result.putInt(0); // unk + result.putInt(0); // unk + result.put((byte) ((boolean) critical ? 1 : 0)); //unk + result.put((byte) ((boolean) glance ? 1 : 0)); //unk + result.put((byte) 0); //unk + result.putInt(1); // unk + + int packetSize = result.position(); + result = IoBuffer.allocate(packetSize).put(result.array(), 0, packetSize); + + return result.flip(); - return result; } - public CombatSpam clone() { - return new CombatSpam(attackerId, defenderId, damage, file, text, colorFlag, objectId); - } } diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index 64da30c8..a12f68f6 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -23,8 +23,12 @@ package services.combat; import java.util.Map; import java.util.Random; + +import org.apache.mina.core.buffer.IoBuffer; + import protocol.swg.ObjControllerMessage; import protocol.swg.objectControllerObjects.CombatAction; +import protocol.swg.objectControllerObjects.CombatSpam; import protocol.swg.objectControllerObjects.CommandEnqueueRemove; import protocol.swg.objectControllerObjects.StartTask; import resources.objects.creature.CreatureObject; @@ -140,7 +144,9 @@ public class CombatService implements INetworkDispatch { } } + int damageBeforeArmor = (int) damage; damage *= (1 - getArmorReduction(attacker, target, weapon, command, hitType)); + int armorAbsorbed = (int) (damageBeforeArmor - damage); if(mitigationType == HitType.BLOCK) { float blockValue = (attacker.getSkillMod("strength_modified").getBase() * attacker.getSkillMod("combat_block_value").getBase()) / 2 + 25; @@ -151,24 +157,36 @@ public class CombatService implements INetworkDispatch { if(damage > 0) applyDamage(attacker, target, (int) damage); - sendCombatPackets(attacker, target, weapon, command, actionCounter); + sendCombatPackets(attacker, target, weapon, command, actionCounter, damage, armorAbsorbed, hitType); } - private void sendCombatPackets(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + private void sendCombatPackets(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter, float damage, int armorAbsorbed, int hitType) { 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()); + + CombatSpam combatSpam = new CombatSpam(attacker.getObjectID(), target.getObjectID(), weapon.getObjectID(), (int) damage, armorAbsorbed, hitType); + ObjControllerMessage objController4 = new ObjControllerMessage(0x1B, combatSpam); + IoBuffer spam = objController4.serialize(); + attacker.getClient().getSession().write(spam); + + if(target.getClient() != null) + target.getClient().getSession().write(spam); + }