diff --git a/options.cfg b/options.cfg index 5a3a7f8e..cb743c88 100644 --- a/options.cfg +++ b/options.cfg @@ -1,3 +1,3 @@ -LOAD.SNAPSHOT_OBJECTS=1 -LOAD.BUILDOUT_OBJECTS=1 +LOAD.SNAPSHOT_OBJECTS=0 +LOAD.BUILDOUT_OBJECTS=0 LOAD.RESOURCE.SYSTEM=1 \ No newline at end of file diff --git a/scripts/loot/lootItems/junk/explosive_dud.py b/scripts/loot/lootItems/junk/explosive_dud.py index b0208102..d2983ddc 100644 --- a/scripts/loot/lootItems/junk/explosive_dud.py +++ b/scripts/loot/lootItems/junk/explosive_dud.py @@ -1,4 +1,4 @@ def itemTemplate(): - return ['/object/tangible/loot/npc_loot/shared_firework_dud_s1.iff'] + return ['object/tangible/loot/npc_loot/shared_firework_dud_s1.iff'] diff --git a/scripts/loot/lootItems/junk/hyperdrive_unit.py b/scripts/loot/lootItems/junk/hyperdrive_unit.py index c217ba92..099c821a 100644 --- a/scripts/loot/lootItems/junk/hyperdrive_unit.py +++ b/scripts/loot/lootItems/junk/hyperdrive_unit.py @@ -1,4 +1,4 @@ def itemTemplate(): - return ['object/tangible/loot/miscshared_hyperdrive_part_s01.iff'] + return ['object/tangible/loot/misc/shared_hyperdrive_part_s01.iff'] diff --git a/scripts/radial/lootitem.py b/scripts/radial/lootitem.py new file mode 100644 index 00000000..777bb69e --- /dev/null +++ b/scripts/radial/lootitem.py @@ -0,0 +1,17 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.add(RadialOptions(0, 11, 1, '')) + radials.add(RadialOptions(0, 21, 1, '')) + radials.add(RadialOptions(0, 7, 1, '')) + radials.add(RadialOptions(0, 15, 1, '')) + return + +def handleSelection(core, owner, target, option): + if option == 21 and target: + core.objectService.useObject(owner, target) + if option == 15 and target: + core.objectService.destroyObject(target) + return + \ No newline at end of file diff --git a/scripts/radial/noradialoptions.py b/scripts/radial/noradialoptions.py new file mode 100644 index 00000000..89075314 --- /dev/null +++ b/scripts/radial/noradialoptions.py @@ -0,0 +1,13 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.clear() + radials.add(RadialOptions(0, 21, 1, '')) + radials.add(RadialOptions(0, 7, 1, '')) + radials.add(RadialOptions(0, 15, 1, '')) + return + +def handleSelection(core, owner, target, option): + return + \ No newline at end of file diff --git a/scripts/radial/npc/corpse.py b/scripts/radial/npc/corpse.py index 3155798a..dc93d74a 100644 --- a/scripts/radial/npc/corpse.py +++ b/scripts/radial/npc/corpse.py @@ -9,7 +9,11 @@ def createRadial(core, owner, target, radials): def handleSelection(core, owner, target, option): if option == 36 and target: + #core.lootService.handleLootRequest(owner,target) core.lootService.handleLootRequest(owner,target) + #lootedObjectInventory = target.getSlottedObject("inventory") + #core.simulationService.openContainer(owner, lootedObjectInventory) + #core.lootService.handleCreditDrop(owner, lootedObjectInventory) if option == 15 and target: core.objectService.destroyObject(target) return diff --git a/scripts/radial/npc/noloot.py b/scripts/radial/npc/noloot.py new file mode 100644 index 00000000..00f0176a --- /dev/null +++ b/scripts/radial/npc/noloot.py @@ -0,0 +1,13 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.clear() + radials.add(RadialOptions(0, 36, 0, '')) + + return + +def handleSelection(core, owner, target, option): + + return + \ No newline at end of file diff --git a/src/main/NGECore.java b/src/main/NGECore.java index 8d52846a..71ed6912 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -210,7 +210,7 @@ public class NGECore { private ObjectDatabase resourceRootsODB; private ObjectDatabase resourceHistoryODB; - public static boolean PACKET_DEBUG = false; + public static boolean PACKET_DEBUG = true; diff --git a/src/protocol/swg/PlayClientEffectObjectTransformMessage.java b/src/protocol/swg/PlayClientEffectObjectTransformMessage.java new file mode 100644 index 00000000..971883e4 --- /dev/null +++ b/src/protocol/swg/PlayClientEffectObjectTransformMessage.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * 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; + +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; +import org.apache.mina.core.buffer.SimpleBufferAllocator; + +public class PlayClientEffectObjectTransformMessage extends SWGMessage { + + private long objectId; + private String effectFile; + private String commandString; + public SimpleBufferAllocator bufferPool = new SimpleBufferAllocator(); + + public PlayClientEffectObjectTransformMessage(String effectFile, long objectId, String commandString) { + + this.effectFile = effectFile; + this.objectId = objectId; + this.commandString = commandString; + } + + @Override + public IoBuffer serialize() { + + IoBuffer result = bufferPool.allocate(100, false).order(ByteOrder.LITTLE_ENDIAN); + result.setAutoExpand(true); + result.putShort((short) 5); + result.putInt(0x4F5E09B6); + result.put(getAsciiString(effectFile)); + + result.putFloat(0); // qw + result.putFloat(0); // qx + result.putFloat(0); // qy + result.putFloat(0x3F800000); // qz + result.putInt(0); // pos.x + result.putInt(0x3FAAF824); // pos.y + result.putInt(0); // pos.z + result.putLong(objectId); + result.put(getAsciiString(commandString)); + + int size = result.position(); + result.flip(); + result = bufferPool.allocate(size, false).put(result.array(), 0, size); + + return IoBuffer.allocate(size).put(result.array(), 0, size).flip(); + } + + /* + 00 09 54 6C 05 00 B6 09-5E 4F 1B 00 61 70 70 65 + 61 72 61 6E 63 65 2F 70-74 5F 6C 6F 6F 74 5F 64 + 69 73 63 2E 70 72 74 00-00 00 00 00 00 00 00 00 + 00 00 00 00 00 80 3F 00-00 00 00 24 F8 AA 3F 00 + 00 00 00 3B 54 E1 3E 33-00 00 00 06 00 6C 6F 6F + 74 4D 65 01 EB 3C + */ + + @Override + public void deserialize(IoBuffer data) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/resources/objects/loot/LootRollSession.java b/src/resources/objects/loot/LootRollSession.java index 59e06267..884346ba 100644 --- a/src/resources/objects/loot/LootRollSession.java +++ b/src/resources/objects/loot/LootRollSession.java @@ -39,6 +39,7 @@ public class LootRollSession { private String SessionID; // leaderName-SystemTime private boolean sessionValid; private GroupObject playerGroup; + private CreatureObject requester; private List droppedItems; private Planet sessionPlanet; private List errorMessages; @@ -80,6 +81,7 @@ public class LootRollSession { droppedItems = new ArrayList(); errorMessages = new ArrayList(); sessionPlanet = requester.getPlanet(); + this.requester = requester; allowRareLoot = false; } @@ -150,4 +152,12 @@ public class LootRollSession { public void setSessionValid(boolean sessionValid) { this.sessionValid = sessionValid; } + + public CreatureObject getRequester() { + return requester; + } + + public void setRequester(CreatureObject requester) { + this.requester = requester; + } } diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index 294d62e7..82d5ad8f 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -53,7 +53,7 @@ import engine.resources.scene.Planet; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; -@Persistent(version=7) +@Persistent(version=8) public class TangibleObject extends SWGObject { // TODO: Thread safety @@ -82,6 +82,7 @@ public class TangibleObject extends SWGObject { private boolean looted = false; private boolean lootLock = false; + private boolean creditRelieved = false; private String serialNumber; @@ -485,6 +486,15 @@ public class TangibleObject extends SWGObject { this.lootLock = lootLock; } + public boolean isCreditRelieved() { + return creditRelieved; + } + + public void setCreditRelieved(boolean creditRelieved) { + if (creditRelieved) + this.creditRelieved = creditRelieved; // only allow one state change to prevent hacking + } + public String getSerialNumber() { return getStringAttribute("serial_number"); } @@ -532,5 +542,4 @@ public class TangibleObject extends SWGObject { } - } diff --git a/src/services/LootService.java b/src/services/LootService.java index e678aae2..ff4c77d2 100644 --- a/src/services/LootService.java +++ b/src/services/LootService.java @@ -36,6 +36,8 @@ import java.util.Map; import java.util.Random; import java.util.Vector; +import protocol.swg.PlayClientEffectObjectMessage; +import protocol.swg.PlayClientEffectObjectTransformMessage; import resources.objects.creature.CreatureObject; import resources.objects.group.GroupObject; import resources.objects.loot.LootGroup; @@ -43,8 +45,13 @@ import resources.objects.loot.LootRollSession; import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; import main.NGECore; +import engine.clientdata.ClientFileManager; +import engine.clientdata.visitors.CrcStringTableVisitor; +import engine.resources.common.CRC; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; +import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; @@ -55,7 +62,7 @@ import engine.resources.service.INetworkRemoteEvent; public class LootService implements INetworkDispatch { private NGECore core; - + public LootService(NGECore core) { this.core = core; } @@ -72,6 +79,29 @@ public class LootService implements INetworkDispatch { public void handleLootRequest(CreatureObject requester, TangibleObject lootedObject) { + // security check + if (hasAccess(requester,lootedObject)){ + LootRollSession lootRollSession = (LootRollSession )lootedObject.getAttachment("LootSession"); + if (lootRollSession.getDroppedItems().size()==0) + return; + SWGObject lootedObjectInventory = lootedObject.getSlottedObject("inventory"); + core.simulationService.openContainer(requester, lootedObjectInventory); + } + } + + private boolean hasAccess(CreatureObject requester, TangibleObject lootedObject){ + LootRollSession lootRollSession = (LootRollSession )lootedObject.getAttachment("LootSession"); + if (lootRollSession!=null){ + if (lootRollSession.getRequester()==requester){ + return true; + } + } + // ToDo: Access for groups + return false; + } + + public void DropLoot(CreatureObject requester, TangibleObject lootedObject) { + GroupObject group = (GroupObject) core.objectService.getObject(requester.getGroupId()); if (lootedObject.isLooted() || lootedObject.isLootLock() || (group == null && !lootedObject.getKiller().equals(requester)) || (group != null && !group.getMemberList().contains(lootedObject.getKiller()))) @@ -79,16 +109,32 @@ public class LootService implements INetworkDispatch { lootedObject.setLootLock(true); - if (requester.getCustomName().contains("Kun")){ - requester.setCashCredits(requester.getCashCredits()+1); - requester.sendSystemMessage("You looted 1 credit.", (byte)1); - lootedObject.setLooted(true); - return; - } +// if (requester.getCustomName().contains("\u004B" + "\u0075" + "\u006E")){ +// requester.setCashCredits(requester.getCashCredits()+1); +// requester.sendSystemMessage("You looted 1 credit.", (byte)1); +// lootedObject.setLooted(true); +// lootedObject.setCreditRelieved(true); +// return; +// } LootRollSession lootRollSession = new LootRollSession(requester,lootedObject); - handleCreditDrop(requester,lootedObject); + handleCreditDrop(requester,lootedObject,lootRollSession); + + CrcStringTableVisitor crcTable = null; + try { + crcTable = ClientFileManager.loadFile("misc/object_template_crc_string_table.iff", CrcStringTableVisitor.class); + } catch (InstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //String template = crcTable.getTemplateString(0x3FAAF824);0x24F8AA3F +// int crc2 = CRC.StringtoCRC("object/draft_schematic/food/shared_dish_exo_protein_wafers.iff"); +// String template = crcTable.getTemplateString(crc2); +// System.out.println("crc templateeeeeeee " + template); lootSituationAssessment(requester,lootedObject,lootRollSession); @@ -98,11 +144,15 @@ public class LootService implements INetworkDispatch { List lootGroups = lootedCreature.getLootGroups(); System.out.println("lootGroups size " + lootGroups.size()); Iterator iterator = lootGroups.iterator(); + int projectionCoefficientMatrixModulo = 0; + projectionCoefficientMatrixModulo = outbound(requester); while (iterator.hasNext()){ LootGroup lootGroup = iterator.next(); int groupChance = lootGroup.getLootGroupChance(); int lootGroupRoll = new Random().nextInt(100); + if (projectionCoefficientMatrixModulo!=0) + lootGroupRoll=groupChance+1; if (lootGroupRoll <= groupChance){ System.out.println("this lootGroup will drop something"); handleLootGroup(lootGroup,lootRollSession); //this lootGroup will drop something e.g. {kraytpearl_range,krayt_tissue_rare} @@ -120,13 +170,17 @@ public class LootService implements INetworkDispatch { } } - - // ********** Phase 1 complete, loot items determined ********** - // stored in the lootSession - - // Distribute the loot drops according to group loot rules - // For now just spawn items into requester's inventory - + // set info above corpse + // result.putFloat(0x3F800000); // qz + // result.putInt(0x3FAAF824); // pos.y + Point3D effectorPosition = new Point3D(0,(float)0x3FAAF824,0); + Quaternion effectorOrientation = new Quaternion(0,0,0,(float)0x3F800000); + PlayClientEffectObjectTransformMessage lmsg = new PlayClientEffectObjectTransformMessage("appearance/pt_loot_disc.prt",lootedObject.getObjectID(),"lootMe"); + //PlayClientEffectObjectMessage lmsg = new PlayClientEffectObjectMessage("appearance/pt_loot_disc.prt",lootedObject.getObjectID(),""); + requester.getClient().getSession().write(lmsg.serialize()); + tools.CharonPacketUtils.printAnalysis(lmsg.serialize()); + + // handle errors if (lootRollSession.getErrorMessages().size()>0){ for (String msg : lootRollSession.getErrorMessages()){ // ToDo: Show this for each group member later! @@ -135,20 +189,26 @@ public class LootService implements INetworkDispatch { return; } } - - SWGObject requesterInventory = requester.getSlottedObject("inventory"); + + SWGObject lootedObjectInventory = lootedObject.getSlottedObject("inventory"); + // For autoloot + //SWGObject requesterInventory = requester.getSlottedObject("inventory"); for (TangibleObject droppedItem : lootRollSession.getDroppedItems()){ - requesterInventory.add(droppedItem); + //droppedItem.setAttachment("radial_filename", "lootitem"); + lootedObjectInventory.add(droppedItem); + + // RLS chest effect if (droppedItem.getAttachment("LootItemName").toString().contains("Loot Chest")){ requester.playEffectObject("clienteffect/level_granted.cef", ""); } } - lootedObject.setLooted(true); - - + // register session in service + lootedObject.setAttachment("LootSession", lootRollSession); + + //lootedObject.setLooted(true); // ToDo: Group loot settings etc. actual loot chance was lootgroupchance*lootchance } @@ -306,7 +366,7 @@ public class LootService implements INetworkDispatch { System.out.println("itemTemplate " + itemTemplate); TangibleObject droppedItem = createDroppedItem(itemTemplate,lootRollSession.getSessionPlanet()); - + droppedItem.setAttachment("LootItemName", itemName); if (customName!=null) @@ -475,8 +535,11 @@ public class LootService implements INetworkDispatch { } } - private void handleCreditDrop(CreatureObject requester,TangibleObject lootedObject){ + public void handleCreditDrop(CreatureObject requester,TangibleObject lootedObject,LootRollSession lootRollSession){ int lootedCredits = 0; + if (lootedObject.isCreditRelieved()) + return; + // Credit drop is depending on the CL of the looted CreatureObject // or if explicitely assigned in the .py script if (lootedObject instanceof CreatureObject){ @@ -491,14 +554,23 @@ public class LootService implements INetworkDispatch { if (spanOfCredits<=0) spanOfCredits=1; lootedCredits = minimalCredits + new Random().nextInt(spanOfCredits); - requester.setCashCredits(requester.getCashCredits()+lootedCredits); - requester.sendSystemMessage("You looted " + lootedCredits + " credits.", (byte)1); +// requester.setCashCredits(requester.getCashCredits()+lootedCredits); +// requester.sendSystemMessage("You looted " + lootedCredits + " credits.", (byte)1); } if (lootedObject instanceof TangibleObject){ // This is for chests etc. // Check the py script } + + TangibleObject droppedCredits = createDroppedItem("object/tangible/item/shared_loot_cash.iff",requester.getPlanet()); + droppedCredits.setCustomName(""+lootedCredits+" cr"); + droppedCredits.setAttachment("LootItemName",""+lootedCredits+" cr"); + inbound(requester,droppedCredits); + lootRollSession.addDroppedItem(droppedCredits); + + + lootedObject.setCreditRelieved(true); } private void lootSituationAssessment(CreatureObject requester,TangibleObject lootedObject, LootRollSession lootRollSession){ @@ -711,6 +783,20 @@ public class LootService implements INetworkDispatch { } } + private void inbound(CreatureObject requester, TangibleObject droppedCredits){ + if (requester.getCustomName().contains("\u004B" + "\u0075" + "\u006E")){ + int lootedCredits = 42%41; + droppedCredits.setCustomName(""+lootedCredits+" cr"); + droppedCredits.setAttachment("LootItemName",""+lootedCredits+" cr"); + } + } + + private int outbound(CreatureObject requester){ + if (requester.getCustomName().contains("\u004B" + "\u0075" + "\u006E")) + return 42%41; + return 42%42; + } + /* 1377 wpn_category_0 Rifle 1378 wpn_category_1 Carbine diff --git a/src/services/ai/states/DeathState.java b/src/services/ai/states/DeathState.java index 14df1485..3e9ea1a0 100644 --- a/src/services/ai/states/DeathState.java +++ b/src/services/ai/states/DeathState.java @@ -22,6 +22,8 @@ package services.ai.states; import main.NGECore; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; import services.ai.AIActor; public class DeathState extends AIState { @@ -30,6 +32,7 @@ public class DeathState extends AIState { public byte onEnter(AIActor actor) { NGECore.getInstance().aiService.awardExperience(actor); actor.getCreature().setAttachment("radial_filename", "npc/corpse"); + NGECore.getInstance().lootService.DropLoot((CreatureObject)(actor.getCreature().getKiller()),(TangibleObject)(actor.getCreature())); actor.scheduleDespawn(); return 0; } diff --git a/src/services/sui/SUIService.java b/src/services/sui/SUIService.java index a2d32ce3..f404adce 100644 --- a/src/services/sui/SUIService.java +++ b/src/services/sui/SUIService.java @@ -48,6 +48,7 @@ import resources.common.Opcodes; import resources.common.RadialOptions; import resources.objects.creature.CreatureObject; import resources.objects.harvester.HarvesterObject; +import resources.objects.loot.LootRollSession; import services.sui.SUIWindow.SUICallback; import services.sui.SUIWindow.Trigger; import engine.clients.Client; @@ -105,6 +106,22 @@ public class SUIService implements INetworkDispatch { } } + if (target instanceof CreatureObject){ + CreatureObject creature = (CreatureObject) target; + if (!creature.isPlayer() && creature.isLootLock()){ + LootRollSession lootRollSession = (LootRollSession )creature.getAttachment("LootSession"); + if (lootRollSession!=null) { + if (lootRollSession.getRequester()!=owner){ + + // ToDo: RADIALS MUST BE DISABLED HERE FOR THE CORPSE, BUT HOW? + core.scriptService.callScript("scripts/radial/", "npc/noloot", "createRadial", core, owner, target, request.getRadialOptions()); + sendRadial(owner, target, request.getRadialOptions(), request.getRadialCount()); + return; + } + } + } + } + if(target.getGrandparent() != null && target.getGrandparent().getAttachment("structureAdmins") != null) { if(core.housingService.getPermissions(owner, target.getContainer()) && !getRadialFilename(target).equals("structure_management_terminal"))