diff --git a/scripts/commands/flourish.py b/scripts/commands/flourish.py index 0ec20d6b..51835b03 100644 --- a/scripts/commands/flourish.py +++ b/scripts/commands/flourish.py @@ -4,9 +4,9 @@ def setup(): return def run(core, actor, target, commandString): - - if len(commandString) <= 0: - actor.sendSystemMessage('@performance:flourish_not_valid', 0) + + if len(commandString) == 0 or commandString == None or commandString == "": + actor.sendSystemMessage('@performance:flourish_format') return try: diff --git a/scripts/commands/holoemote.py b/scripts/commands/holoemote.py new file mode 100644 index 00000000..1146b0b8 --- /dev/null +++ b/scripts/commands/holoemote.py @@ -0,0 +1,62 @@ +import sys + +def setup(): + return + +def run(core, actor, target, commandString): + player = actor.getSlottedObject('ghost') + + if player is None: + return + + commandString = commandString.lower() + installedEmote = player.getHoloEmote().replace('holoemote_','') + + if installedEmote == None or installedEmote == "": + actor.sendSystemMessage('@image_designer:no_holoemote', 0) + return + + if commandString == 'help': + helpWindow = core.suiService.createMessageBox(1, 'HOLO-EMOTE HELP', holoPrompt(player, installedEmote), actor, actor, 10) + core.suiService.openSUIWindow(helpWindow) + return + + if player.getHoloEmoteUses() < 1: + actor.sendSystemMessage('@image_designer:no_charges_holoemote', 0) + return + + if commandString == "kitty": + commandString = "technokitty" + + if commandString != installedEmote and installedEmote != 'all': + actor.sendSystemMessage('Your installed Holo-Emote generator does not support that emote.', 0) + return + + effectObj = 'clienteffect/holoemote_' + commandString + '.cef' + actor.playEffectObject(effectObj, 'head') + player.setHoloEmoteUses(player.getHoloEmoteUses() - 1) + # TODO: Cooldowns for the holo-emote's + return + +def holoPrompt(player, emote): + emotesToPlay = "Your Holo-Emote generator can only play the " + emote + " Holo-Emote.\n" + if emote == "all": + emotesToPlay = "Your Holo-Emote generator can play all Holo-Emotes available.\n" + + remainingCharges = "You have " + str(player.getHoloEmoteUses()) + " charges remaining.\n" + if player.getHoloEmoteUses() == 1: + remainingCharges = "You have 1 charge remaining.\n" + + body = "To play a Holo-Emote, type /holoemote ." \ +"To delete your Holo-Emote type /holoemote delete.\n" \ +"Purchasing a new Holo-Emote will automatically delete your current Holo-Emote.\n" \ +"\n" \ +"The available Holo-Emote names are:\n\n" \ +"Beehive\t Blossom\tBrainstorm\n" \ +"Bubblehead\t Bullhorns\tButterflies\n" \ +"Champagne\t Haunted\tHearts\n" \ +"Hologlitter\t Holonotes\tImperial\n" \ +"Kitty\t\t Phonytail\tRebel\n" \ +"Sparky" + + return emotesToPlay + remainingCharges + body \ No newline at end of file diff --git a/scripts/commands/imagedesign.py b/scripts/commands/imagedesign.py index 6cbf658d..f304d583 100644 --- a/scripts/commands/imagedesign.py +++ b/scripts/commands/imagedesign.py @@ -6,12 +6,23 @@ def setup(): return def run(core, actor, target, commandString): - print ('Design!') - design = ImageDesignStartMessage(actor.getObjectId(), actor.getObjectId(), target.getObjectId()) - obj = ObjControllerMessage(11, design) - actor.getClient().getSession().write(obj.serialize()) + + if target is None: + design = ImageDesignStartMessage(actor.getObjectId(), actor.getObjectId(), target.getObjectId()) + obj = ObjControllerMessage(11, design) + actor.getClient().getSession().write(obj.serialize()) + return - tDesign = ImageDesignStartMessage(target.getObjectId(), actor.getObjectId(), target.getObjectId()) - tObj = ObjControllerMessage(11, tDesign) - target.getClient().getSession().write(tObj.serialize()) + else: + if target.getGroupId() == actor.getGroupId(): + print ('same group') + tDesign = ImageDesignStartMessage(target.getObjectId(), actor.getObjectId(), target.getObjectId()) + tObj = ObjControllerMessage(11, tDesign) + target.getClient().getSession().write(tObj.serialize()) + + design = ImageDesignStartMessage(actor.getObjectId(), actor.getObjectId(), target.getObjectId()) + obj = ObjControllerMessage(11, design) + actor.getClient().getSession().write(obj.serialize()) + return + return return \ No newline at end of file diff --git a/scripts/commands/stopdance.py b/scripts/commands/stopdance.py index ed2b7a44..e403a179 100644 --- a/scripts/commands/stopdance.py +++ b/scripts/commands/stopdance.py @@ -15,6 +15,6 @@ def run(core, actor, target, commandString): # all packets are triggered in setPosture. # this may not be very consistent, but it prevents # duplicate code. - actor.setPosture(0x00) + actor.stopPerformance() return diff --git a/src/protocol/swg/PlayClientEffectObjectMessage.java b/src/protocol/swg/PlayClientEffectObjectMessage.java index 5e9dead4..498b8ddd 100644 --- a/src/protocol/swg/PlayClientEffectObjectMessage.java +++ b/src/protocol/swg/PlayClientEffectObjectMessage.java @@ -47,10 +47,8 @@ public class PlayClientEffectObjectMessage extends SWGMessage { result.putShort((short) 5); result.putInt(0x8855434A); result.put(getAsciiString(effectFile)); - result.putShort((short) 0); - result.putLong(objectId); result.put(getAsciiString(commandString)); - + result.putLong(objectId); return result.flip(); } diff --git a/src/protocol/swg/objectControllerObjects/ImageDesignMessage.java b/src/protocol/swg/objectControllerObjects/ImageDesignMessage.java index 5dc8a965..8678ec4d 100644 --- a/src/protocol/swg/objectControllerObjects/ImageDesignMessage.java +++ b/src/protocol/swg/objectControllerObjects/ImageDesignMessage.java @@ -69,9 +69,7 @@ public class ImageDesignMessage extends ObjControllerObject { @Override public void deserialize(IoBuffer data) { - System.out.println("===== Recieved Packet ======"); - StringUtilities.printBytes(data.array()); - + setObjectId(data.getLong()); data.getInt(); setDesignerId(data.getLong()); @@ -224,7 +222,6 @@ public class ImageDesignMessage extends ObjControllerObject { } public void setObjectId(long objectId) { - System.out.println("OBJECT ID: " + objectId); this.objectId = objectId; } @@ -233,7 +230,6 @@ public class ImageDesignMessage extends ObjControllerObject { } public void setUnkByte(byte unkByte) { - System.out.println("Set unk byte to " + unkByte); this.unkByte = unkByte; } @@ -250,7 +246,6 @@ public class ImageDesignMessage extends ObjControllerObject { } public void setUnk(String unk) { - System.out.println("Set UNK to " + unk); this.unk = unk; } @@ -307,7 +302,6 @@ public class ImageDesignMessage extends ObjControllerObject { } public void setBodyFormSkill1(int bodyFormSkill1) { - System.out.println("Set body form skill 1 to " + bodyFormSkill1); this.bodyFormSkill1 = bodyFormSkill1; } @@ -316,7 +310,6 @@ public class ImageDesignMessage extends ObjControllerObject { } public void setFaceFormSkill1(int faceFormSkill1) { - System.out.println("Set face form skill 1 to " + faceFormSkill1); this.faceFormSkill1 = faceFormSkill1; } @@ -325,7 +318,6 @@ public class ImageDesignMessage extends ObjControllerObject { } public void setBodyFormSkill2(int bodyFormSkill2) { - System.out.println("Set body form skill 2 to " + bodyFormSkill2); this.bodyFormSkill2 = bodyFormSkill2; } @@ -334,7 +326,6 @@ public class ImageDesignMessage extends ObjControllerObject { } public void setFaceFormSkill2(int faceFormSkill2) { - System.out.println("Set face form skill 2 to " + faceFormSkill2); this.faceFormSkill2 = faceFormSkill2; } @@ -343,7 +334,6 @@ public class ImageDesignMessage extends ObjControllerObject { } public void setHoloEmote(String holoEmote) { - System.out.println("Holoemote set to " + holoEmote); this.holoEmote = holoEmote; } diff --git a/src/protocol/swg/objectControllerObjects/ShowLootBox.java b/src/protocol/swg/objectControllerObjects/ShowLootBox.java index 432ddd14..d4c83d33 100644 --- a/src/protocol/swg/objectControllerObjects/ShowLootBox.java +++ b/src/protocol/swg/objectControllerObjects/ShowLootBox.java @@ -39,7 +39,7 @@ public class ShowLootBox extends ObjControllerObject { public ShowLootBox(long playerId, SWGObject reward) { this.playerId = playerId; - this.rewards = rewards; + this.reward = reward; } public ShowLootBox(long playerId, Vector rewards) { diff --git a/src/resources/common/IDAttribute.java b/src/resources/common/IDAttribute.java index 7b26fc49..6accf7e3 100644 --- a/src/resources/common/IDAttribute.java +++ b/src/resources/common/IDAttribute.java @@ -55,9 +55,4 @@ public class IDAttribute { this.value = value; } - public byte[] getHexValue() { - System.out.println(BigInteger.valueOf(value).toByteArray()); - return BigInteger.valueOf(value).toByteArray(); - } - } \ No newline at end of file diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 2d1844c9..97052abd 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -169,6 +169,9 @@ public class CreatureObject extends TangibleObject implements IPersistent { @NotPersistent private boolean performingEffect; + @NotPersistent + private boolean performingFlourish; + private int coverCharge; public CreatureObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String Template) { @@ -350,26 +353,22 @@ public class CreatureObject extends TangibleObject implements IPersistent { } public void setPosture(byte posture) { - boolean needsStopPerformance = false; + synchronized(objectMutex) { if (this.posture == 0x09) { - needsStopPerformance = true; + stopPerformance(); } if(this.posture == posture) return; this.posture = posture; } - + Posture postureUpdate = new Posture(getObjectID(), posture); ObjControllerMessage objController = new ObjControllerMessage(0x1B, postureUpdate); notifyObservers(messageBuilder.buildPostureDelta(posture), true); notifyObservers(objController, true); - if (needsStopPerformance) { - stopPerformance(); - } - } public void startPerformance() { @@ -379,12 +378,16 @@ public class CreatureObject extends TangibleObject implements IPersistent { } public void stopPerformance() { + System.out.println("Stop Performance called!"); String type = ""; synchronized(objectMutex) { - // TODO: Minimum check to wait for song to finish before stopping... ? - setPerformanceId(0,true); + + // Some reason this prevents the animation for playing an instrument when stopping (unless that's what "" does) + setCurrentAnimation(getCurrentAnimation()); + setPerformanceCounter(0); - setCurrentAnimation(""); + setPerformanceId(0,true); + type = (performanceType) ? "dance" : "music"; if (entertainerExperience != null) { entertainerExperience.cancel(true); @@ -396,12 +399,12 @@ public class CreatureObject extends TangibleObject implements IPersistent { stopAudience(); getClient().getSession().write(messageBuilder.buildStartPerformance(false)); + } public void stopAudience() { - String type = ""; synchronized(objectMutex) { - type = (performanceType) ? "dance" : "music"; + //String type = (performanceType) ? "dance" : "music"; if (performanceAudience == null) { return; } @@ -1703,4 +1706,16 @@ public class CreatureObject extends TangibleObject implements IPersistent { this.coverCharge = coverCharge; } } + + public boolean isPerformingFlourish() { + synchronized(objectMutex){ + return performingFlourish; + } + } + + public void setPerformingFlourish(boolean performingFlourish) { + synchronized(objectMutex) { + this.performingFlourish = performingFlourish; + } + } } diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index 94bb6b4b..73eb9787 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -43,7 +43,7 @@ import engine.resources.scene.Planet; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; -@Persistent(version=5) +@Persistent(version=6) public class PlayerObject extends IntangibleObject { // PLAY 3 @@ -120,6 +120,8 @@ public class PlayerObject extends IntangibleObject { private String biography = ""; private String spouse; + private String holoEmote; + private int holoEmoteUses; @NotPersistent private PlayerMessageBuilder messageBuilder; @@ -740,5 +742,20 @@ public class PlayerObject extends IntangibleObject { return ((flagBitmask & flags) == flags); } } - + + public String getHoloEmote() { + return holoEmote; + } + + public void setHoloEmote(String holoEmote) { + this.holoEmote = holoEmote; + } + + public int getHoloEmoteUses() { + return holoEmoteUses; + } + + public void setHoloEmoteUses(int holoEmoteUses) { + this.holoEmoteUses = holoEmoteUses; + } } diff --git a/src/resources/visitors/IDManagerVisitor.java b/src/resources/visitors/IDManagerVisitor.java new file mode 100644 index 00000000..2ad1ad46 --- /dev/null +++ b/src/resources/visitors/IDManagerVisitor.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 resources.visitors; + +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.mina.core.buffer.IoBuffer; + +import engine.clientdata.VisitorInterface; + +public class IDManagerVisitor implements VisitorInterface { + + private ConcurrentHashMap customizationMap; + private CharsetDecoder charsetDecoder; + + public IDManagerVisitor() { + customizationMap = new ConcurrentHashMap(); + charsetDecoder = Charset.forName("US-ASCII").newDecoder(); + } + + @Override + public void parseData(String node, IoBuffer data, int depth, int size) throws Exception { + + if (!node.equals("0001DATA") || depth != 2) + return; + + while(data.hasRemaining()) { + short designNumber = data.getShort(); + String customizationType = data.getString(charsetDecoder); + charsetDecoder.reset(); + + customizationMap.put(customizationType, designNumber); + + //System.out.println(designNumber + ": " + customizationType); + } + } + + @Override + public void notifyFolder(String node, int depth) throws Exception { + } + + public ConcurrentHashMap getCustomizationMap() { + return this.customizationMap; + } +} diff --git a/src/services/EntertainmentService.java b/src/services/EntertainmentService.java index 587a6b3f..d57aa4c4 100644 --- a/src/services/EntertainmentService.java +++ b/src/services/EntertainmentService.java @@ -4,6 +4,7 @@ import java.nio.ByteOrder; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import java.util.Random; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; @@ -41,6 +42,7 @@ import resources.objects.SkillMod; import resources.objects.creature.CreatureObject; import resources.objects.player.PlayerObject; import resources.objects.tangible.TangibleObject; +import resources.visitors.IDManagerVisitor; import services.sui.SUIService.InputBoxType; import services.sui.SUIWindow; import services.sui.SUIWindow.SUICallback; @@ -63,6 +65,8 @@ public class EntertainmentService implements INetworkDispatch { private ConcurrentHashMap performancesByIndex = new ConcurrentHashMap(); private ConcurrentHashMap danceMap = new ConcurrentHashMap(); + private ConcurrentHashMap designMap = new ConcurrentHashMap(); + private Random ranWorkshop = new Random(); private Map performanceEffects = new ConcurrentHashMap(); @@ -73,6 +77,7 @@ public class EntertainmentService implements INetworkDispatch { populatePerformanceTable(); populatePerformanceEffects(); registerCommands(); + loadCharacterCustomizationData(); } @Override @@ -114,31 +119,30 @@ public class EntertainmentService implements INetworkDispatch { // TODO: Attribute check for colors? if (bodyAttributes != null) { for (IDAttribute atr : bodyAttributes) { - System.out.println("ATTRIBUTE: " + atr.getName()); + System.out.println("ATTRIBUTE: " + atr.getName() + " value of " + atr.getFloatValue()); if (atr.getFloatValue() > 1f || atr.getFloatValue() < 0) { // RIP Height Exploit <3 return; } } } - if (colorAttributes != null) { + /*if (colorAttributes != null) { for (IDAttribute atr : colorAttributes) { - System.out.println("COLOR ATTRIBUTE: " + atr.getName()); + System.out.println("COLOR ATTRIBUTE: " + atr.getName() + " value of " + atr.getValue()); } - } + }*/ if (sentPacket.getTargetId() != sentPacket.getDesignerId()) { if (sentPacket.isCustomerAccepted() && sentPacket.isDesignerCommited()) { System.out.print("Both Accepted!"); - // TODO: Send close packet to target & apply changes + sentPacket.setEndMessage(true); - if (sentPacket.getMoneyDemanded() > 0) { + int fee = sentPacket.getMoneyDemanded() + sentPacket.getMoneyOffered(); + if (fee > 0) { int payersCash = designTarget.getCashCredits(); - int fee = sentPacket.getMoneyDemanded(); - int tip = sentPacket.getMoneyOffered(); - + if (payersCash < fee) { if (designTarget != designer) { @@ -153,30 +157,26 @@ public class EntertainmentService implements INetworkDispatch { designer.sendSystemMessage("Your target did not have the required payment fee", (byte) 0); } - } else if (payersCash < tip) { - designTarget.sendSystemMessage("You tried to offer more credits than you had and the Image Design session has ended.", (byte) 0); + }else { + // TODO: Apply customization + designTarget.setCashCredits(designTarget.getCashCredits() - fee); + designer.setCashCredits(designer.getCashCredits() + fee); + + handleImageDesign(designer, designTarget, colorAttributes, bodyAttributes, sentPacket.getHair(), sentPacket.getHoloEmote()); + + sentPacket.setEndMessage(true); + sentPacket.setObjectId(designTarget.getObjectId()); ObjControllerMessage msg = new ObjControllerMessage(0x0B, sentPacket); designTarget.getClient().getSession().write(msg.serialize()); - } else { - // TODO: Apply customization - for (IDAttribute atr : bodyAttributes) { - if (atr.getName().equals("height")) - designTarget.setHeight(atr.getFloatValue()); - } - - for (IDAttribute atr : colorAttributes) { - if (atr.getName().equals("color_hair")){ - if (sentPacket.getHair() != null) { - designTarget._remove(designTarget.getSlottedObject("hair")); - TangibleObject hair = (TangibleObject) core.objectService.createObject(sentPacket.getHair(), designTarget.getPlanet()); - hair.setCustomization(atr.getHexValue()); - designTarget._add(hair); - System.out.print("Added hair"); - } - } - } } + } else { + handleImageDesign(designer, designTarget, colorAttributes, bodyAttributes, sentPacket.getHair(), sentPacket.getHoloEmote()); + sentPacket.setEndMessage(true); + sentPacket.setObjectId(designTarget.getObjectId()); + + ObjControllerMessage msg = new ObjControllerMessage(0x0B, sentPacket); + designTarget.getClient().getSession().write(msg.serialize()); } } else if (sentPacket.getObjectId() == designTarget.getObjectId()) { @@ -191,6 +191,12 @@ public class EntertainmentService implements INetworkDispatch { ObjControllerMessage msg = new ObjControllerMessage(0x0B, sentPacket); designTarget.getClient().getSession().write(msg.serialize()); } + } else { + // No need to send a close packet message because the client automatically closes the ID window for the Desginer when they commit + if (sentPacket.isDesignerCommited()) + handleImageDesign(designer, designTarget, colorAttributes, bodyAttributes, sentPacket.getHair(), sentPacket.getHoloEmote()); + else + return; } } @@ -487,11 +493,11 @@ public class EntertainmentService implements INetworkDispatch { core.commandService.registerCommand("stopdance"); core.commandService.registerCommand("watch"); //core.commandService.registerCommand("stopwatching"); // SWGList error - //core.commandService.registerCommand("holoEmote"); + core.commandService.registerCommand("holoEmote"); core.commandService.registerCommand("covercharge"); //core.commandService.registerCommand("en_holographic_recall"); //core.commandService.registerCommand("en_holographic_image"); - //core.commandService.registerCommand("imagedesign"); + core.commandService.registerCommand("imagedesign"); // TODO: Add /bandsolo, /bandpause, /changeBandMusic, /changeDance, /changeGroupDance, /changeMusic // Entertainer Effects @@ -705,8 +711,8 @@ public class EntertainmentService implements INetworkDispatch { public void performFlourish(final CreatureObject performer, int flourish) { - if (performer.getFlourishCount() > 0) { - performer.sendSystemMessage("@performance:wait_flourish_self", (byte) 0); + if (performer.getFlourishCount() > 0 || performer.isPerformingFlourish()) { + performer.sendSystemMessage("@performance:flourish_wait_self", (byte) 0); return; } Performance performance = getPerformanceByIndex(performer.getPerformanceId()); @@ -720,14 +726,16 @@ public class EntertainmentService implements INetworkDispatch { anmFlo = "mistake"; performer.setFlourishCount(1); + performer.setPerformingFlourish(true); performer.sendSystemMessage("@performance:flourish_perform", (byte) 0); performer.doSkillAnimation(anmFlo); - + scheduler.schedule(new Runnable() { @Override public void run() { performer.setFlourishCount(0); + performer.setPerformingFlourish(false); } }, (long) performance.getLoopDuration(), TimeUnit.SECONDS); @@ -862,8 +870,85 @@ public class EntertainmentService implements INetworkDispatch { } } - private void doAppearanceChange(CreatureObject designee, ImageDesignMessage msg) { + private void handleImageDesign(CreatureObject designer, CreatureObject designTarget, Vector colorAttributes, Vector bodyAttributes, String hairTemplate, String holoEmote) { + + if (hairTemplate != null && !hairTemplate.equals("")) { + System.out.println(hairTemplate); + String sharedHairTemplate = hairTemplate.replace("/hair_", "/shared_hair_"); + TangibleObject hairObject = (TangibleObject) core.objectService.createObject(sharedHairTemplate, designTarget.getPlanet()); + + if (hairObject == null) + return; + + TangibleObject oldHair = (TangibleObject) designTarget.getSlottedObject("hair"); + if (oldHair == null) + return; + core.objectService.destroyObject(oldHair); + + designTarget.add(hairObject); + + designTarget.addObjectToEquipList(hairObject); + + } + if (bodyAttributes != null) { + for (IDAttribute atr : bodyAttributes) { + if (atr.getName().equals("height")) + designTarget.setHeight(atr.getFloatValue()); + + // TODO: Body Attributes + } + } + + if (colorAttributes != null) { + for (IDAttribute atr : colorAttributes) { + if (atr.getName().equals("color_hair")){ + // TODO: Color Attributes + } + } + } + if (holoEmote != null) { + PlayerObject player = (PlayerObject) designTarget.getSlottedObject("ghost"); + if (player != null) { + player.setHoloEmote(holoEmote); + player.setHoloEmoteUses(20); + designTarget.sendSystemMessage("@image_designer:new_holoemote", (byte) 0); + } + } + + } + + private void loadCharacterCustomizationData() { + try { + IDManagerVisitor visitor = ClientFileManager.loadFile("customization/customization_id_manager.iff", IDManagerVisitor.class); + + designMap = visitor.getCustomizationMap(); + + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + } + + public String getCustomizationString(int number){ + synchronized (designMap) { + for (Entry entry : designMap.entrySet()) { + if (entry.getValue().intValue() == number) { + return entry.getKey(); + } + } + } + return ""; + } + + public int getCustomizationValue(String customizationString) { + synchronized(designMap){ + for(Entry entry : designMap.entrySet()) { + if (entry.getKey().equals(customizationString)) { + return entry.getValue().intValue(); + } + } + } + return 0; } @Override diff --git a/src/services/EquipmentService.java b/src/services/EquipmentService.java index d9df1dc8..c130d46d 100644 --- a/src/services/EquipmentService.java +++ b/src/services/EquipmentService.java @@ -100,6 +100,9 @@ public class EquipmentService implements INetworkDispatch { public boolean canEquip(CreatureObject actor, SWGObject item) { boolean result = true; + if (item == null) + return false; + if (item.getAttributes().toString().contains("cat_armor")) if (actor.getLevel() >= 22) result = true;