michaelbolland Posted February 23, 2015 Report Posted February 23, 2015 Hey Shooms, I dont want auto learning abilities, i am wanting to have clicky items that grant them So I modified the recipe hook script and made a new one from it to allow items to be consumed to give abilities But for some reason I don't see the ability on my action bar - I do however get a message saying I can't consume the ability if i try to use it a second time (it states i already know it) So it seems like I am getting the ability but it's not showing - any ideas why? Code below package atavism.agis.core; import java.io.Serializable; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import atavism.server.engine.BasicWorldNode; import atavism.server.engine.Engine; import atavism.server.engine.EnginePlugin; import atavism.server.engine.OID; import atavism.server.math.AOVector; import atavism.server.objects.ObjectTypes; import atavism.server.plugins.WorldManagerClient; import atavism.server.plugins.WorldManagerClient.ExtensionMessage; import atavism.server.plugins.WorldManagerClient.TargetedExtensionMessage; import atavism.server.util.*; import atavism.agis.objects.*; import atavism.agis.plugins.AgisInventoryClient; import atavism.agis.plugins.CombatPlugin; import atavism.agis.plugins.CraftingClient; import atavism.agis.plugins.VoxelClient; import atavism.agis.util.ExtendedCombatMessages; /** * An acquire hook for items that turn into an ability * when acquired. */ public class ConsumeAbilityActivateHook implements ActivateHook { public ConsumeAbilityActivateHook() { super(); } public ConsumeAbilityActivateHook(int abilityID) { super(); setAbilityID(abilityID); } public void setAbilityID(int abilityID) { if (abilityID == -1) { throw new RuntimeException("ConsumeAbilityActivateHook.setResource: bad resource"); } this.abilityID = abilityID; } public int getAbilityID() { return abilityID; } protected int abilityID; /** * Adds the item to the Building Resources map for the player and returns true telling the item to be * destroyed. */ public boolean activate(OID activatorOid, AgisItem item, OID targetOid) { if (Log.loggingDebug) Log.debug("ConsumeAbilityActivateHook.activate: activator=" + activatorOid + " item=" + item + " ability=" + abilityID); // Only convert it if it is activated by a player if (WorldManagerClient.getObjectInfo(activatorOid).objType != ObjectTypes.player) { return false; } // Add ability resource LinkedList abilities = (LinkedList)EnginePlugin.getObjectProperty(activatorOid, WorldManagerClient.NAMESPACE, "abilities"); if (abilities == null) { abilities = new LinkedList(); } else if (abilities.contains("" + abilityID)) { ExtendedCombatMessages.sendErrorMessage(activatorOid, "You already know that ability"); return false; } abilities.add("" + abilityID); EnginePlugin.setObjectProperty(activatorOid, WorldManagerClient.NAMESPACE, "abilities", abilities); ExtendedCombatMessages.sendCombatText(activatorOid, "Learned new ability", 16); sendAbilities(activatorOid, abilities); //ExtendedCombatMessages.sendAnouncementMessage(activatorOid, "You have learned a new ability", "Skill"); // Need to remove the item AgisInventoryClient.removeSpecificItem(activatorOid, item.getOid(), true, 1); return true; } /** * Sends down the map of Ability Resources the player has to the client. Static function so can be called from anywhere. * @param oid * @param resources */ public static void sendAbilities(OID oid, LinkedList abilities) { Map props = new HashMap(); props.put("ext_msg_subtype", "abilities"); int numResources = 0; for (String resourceID : abilities) { Log.debug("RESOURCE: got currency to send: " + resourceID); props.put("resource" + numResources + "ID", resourceID); numResources++; } props.put("numAbilities", numResources); TargetedExtensionMessage msg = new TargetedExtensionMessage(WorldManagerClient.MSG_TYPE_EXTENSION, oid, oid, false, props); Engine.getAgent().sendBroadcast(msg); Log.debug("ABILITIES: sending down ability message to: " + oid + " with props: " + props); } public String toString() { return "ConsumeAbilityActivateHook=" + abilityID; } private static final long serialVersionUID = 1L; } Quote
michaelbolland Posted April 30, 2015 Author Report Posted April 30, 2015 Hi Shooms, Sorry to bug you on this but i haven't really been able to make much progress on this over the last few months and wondered if you can help Thanks Quote
sooms Posted May 4, 2015 Report Posted May 4, 2015 Sorry Michael, I had been away for a while and now back in action. Firstly, it's awesome to see some more people trying to dig into the code. This stuff gets quite tricky pretty quick so I will explain how the ability system works first with a bit of core Atavism design explanation. Each part of your characters data is separate, such as the combat, inventory, quest progress etc. Each of these subObjects of your character are referred to as "typeInfo" so for combat it is CombatInfo, and they only exist in the relevant process (so the CombatInfo is only usable within the Combat and ClassAbility Plugins). This means all the characters ability info (along with the actions) are stored in the CombatInfo subObject, and when you want to access the abilities or action list in the server code it needs to be done in the Combat areas. What you have done is just try to directly set a list (of strings) that contains the abilities the player has, and try to save it to the WorldManager subObject. What needs to be done is code needs to exist in the ClassAbilityPlugin.java file that picks up a message saying which ability the player has learned and then it will access the CombatInfo for the player and add the ability and update the action list. You can see an example which just updates the ActionList (from ClassAbilityPlugin.java line 895): class UpdateActionBarHook implements Hook { public boolean processMessage(Message msg, int flags) { CombatClient.updateActionBarMessage UABMsg = (CombatClient.updateActionBarMessage) msg; OID oid = UABMsg.getSubject(); int actionPosition = (Integer) UABMsg.getProperty("actionPosition"); String newAction = (String) UABMsg.getProperty("newAction"); CombatInfo cInfo = CombatPlugin.getCombatInfo(oid); ArrayList actions = cInfo.getCurrentActions(); while (actions.size() <= actionPosition) { actions.add(""); } actions.set(actionPosition, newAction); cInfo.setCurrentActions(actions); ExtendedCombatMessages.sendActions(oid, actions); return true; } } What I recommend is I will add a LearnAbilityMessage and a Hook to catch that message and then add the ability to the players CombatInfo. I will have it in 2.4 as I see it as an important feature and will take me 30 minutes. Quote
michaelbolland Posted May 4, 2015 Author Report Posted May 4, 2015 Hi Sooms, Thank you for the reply, this is really helpful So as for moving this over to the ClassAbility plugin i am wondering how i should handle my current hook At the moment the event will fire based on right clicking the item in my inventory So for example I have added a new effecttype into ItemDatabase.java Here is the code } else if (effectType.equals("BuildingMaterial")) { // Used to turn an item into a Building Resource when acquired //String value = rs.getString("effect" + i + "value"); //int resourceID = Integer.parseInt(value); tmpl.put(InventoryClient.ITEM_NAMESPACE, AgisItem.TEMPL_ACQUIRE_HOOK, new BuildingResourceAcquireHook(rs.getInt("id"))); } else if (effectType.equals("Blueprint")) { // Used to turn an item into a recipe when acquired String value = rs.getString("effect" + i + "value"); int recipeID = Integer.parseInt(value); tmpl.put(InventoryClient.ITEM_NAMESPACE, InventoryClient.TEMPL_ACTIVATE_HOOK, new RecipeItemActivateHook(recipeID)); } else if (effectType.equals("ConsumeAbility")) { // Mixxit - Used to turn an item into an ability when acquired String value = rs.getString("effect" + i + "value"); int abilityID = Integer.parseInt(value); tmpl.put(InventoryClient.ITEM_NAMESPACE, InventoryClient.TEMPL_ACTIVATE_HOOK, new ConsumeAbilityActivateHook(abilityID)); } At the point here, where I am putting the hook into the Item Namespace, are you saying I need to instead put this into the ClassAbility namespace? If so how will the event fire for the right click of the item? Quote
sooms Posted May 5, 2015 Report Posted May 5, 2015 That part of the code is fine as you had it. It is in the actual ConsumeAbilityActivateHook class, the activate function will instead need to send a message (which I have to create) which the ClassAbilityPlugin will catch and then add the ability to the player. The way Atavism works is you have the different processes for each part of the game (combat, mobs, inventory etc) and when you need to pass some information on to another process (such as adding an ability from an item event) you need to send a message which the other process can catch and then work with. Quote
michaelbolland Posted May 5, 2015 Author Report Posted May 5, 2015 is that outside of our control? i'm just thinking that if i have to do other things like this in the future would i be able to add my own messages and if so can you show me where they are defined? thanks! Quote
sooms Posted May 5, 2015 Report Posted May 5, 2015 You can add your own messages. I will need to write up a tutorial to explain it as it isn't easy. Quote
michaelbolland Posted May 5, 2015 Author Report Posted May 5, 2015 thanks that would be really great, can you possibly put it in the wiki for others too? i know you have a lot of work to do for the roadmap and instead of you coding in changes for us to do what we want to achieve if you can go into detail on how it works currently we can do the changes ourselves and then if you are happy we can submit our changes to you for future releases that way the community can work in harmony with you instead of being a burden, sure we will have technical questions but if you believe it is possible for us to make the changes now then all that needs to be addressed is the documentation really thanks again! Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.