Search in sources :

Example 1 with TriggerTrait

use of net.aufdemrand.denizen.npc.traits.TriggerTrait in project Denizen-For-Bukkit by DenizenScript.

the class TriggerCommand method execute.

@Override
public void execute(ScriptEntry scriptEntry) throws CommandExecutionException {
    Element toggle = scriptEntry.getElement("toggle");
    Element trigger = scriptEntry.getElement("trigger");
    Element radius = scriptEntry.getElement("radius");
    Duration cooldown = (Duration) scriptEntry.getObject("cooldown");
    dNPC npc = scriptEntry.hasObject("npc") ? (dNPC) scriptEntry.getObject("npc") : ((BukkitScriptEntryData) scriptEntry.entryData).getNPC();
    dB.report(scriptEntry, getName(), trigger.debug() + toggle.debug() + (radius != null ? radius.debug() : "") + (cooldown != null ? cooldown.debug() : "") + npc.debug());
    // Add trigger trait
    if (!npc.getCitizen().hasTrait(TriggerTrait.class)) {
        npc.getCitizen().addTrait(TriggerTrait.class);
    }
    TriggerTrait trait = npc.getCitizen().getTrait(TriggerTrait.class);
    switch(Toggle.valueOf(toggle.asString().toUpperCase())) {
        case TOGGLE:
            trait.toggleTrigger(trigger.asString());
            break;
        case TRUE:
            trait.toggleTrigger(trigger.asString(), true);
            break;
        case FALSE:
            trait.toggleTrigger(trigger.asString(), false);
            break;
    }
    if (radius != null) {
        trait.setLocalRadius(trigger.asString(), radius.asInt());
    }
    if (cooldown != null) {
        trait.setLocalCooldown(trigger.asString(), cooldown.getSeconds());
    }
}
Also used : net.aufdemrand.denizen.objects.dNPC(net.aufdemrand.denizen.objects.dNPC) TriggerTrait(net.aufdemrand.denizen.npc.traits.TriggerTrait) Element(net.aufdemrand.denizencore.objects.Element) Duration(net.aufdemrand.denizencore.objects.Duration)

Example 2 with TriggerTrait

use of net.aufdemrand.denizen.npc.traits.TriggerTrait in project Denizen-For-Bukkit by DenizenScript.

the class ChatTrigger method process.

// Technically defined in TriggerTrait, but placing here instead.
// <--[action]
// @Actions
// chat
//
// @Triggers when a player chats to the NPC.
//
// @Context
// <context.message> returns the triggering message
// <context.keyword> returns the keyword matched by a RegEx trigger
//
// @Determine
// "CANCELLED" to stop the player from chatting.
// Element to change the message.
//
// -->
public ChatContext process(Player player, String message) {
    // Check if there is an NPC within range of a player to chat to.
    dNPC npc = Utilities.getClosestNPC_ChatTrigger(player.getLocation(), 25);
    dPlayer denizenPlayer = dPlayer.mirrorBukkitPlayer(player);
    if (HyperDebug) {
        dB.log("Processing chat trigger: valid npc? " + (npc != null));
    }
    // No NPC? Nothing else to do here.
    if (npc == null) {
        return new ChatContext(false);
    }
    if (HyperDebug) {
        dB.log("Has trait?  " + npc.getCitizen().hasTrait(TriggerTrait.class));
    }
    // just return false.
    if (!npc.getCitizen().hasTrait(TriggerTrait.class)) {
        return new ChatContext(false);
    }
    if (HyperDebug) {
        dB.log("enabled? " + npc.getCitizen().getTrait(TriggerTrait.class).isEnabled(name));
    }
    if (!npc.getCitizen().getTrait(TriggerTrait.class).isEnabled(name)) {
        return new ChatContext(false);
    }
    // Check range
    if (npc.getTriggerTrait().getRadius(name) < npc.getLocation().distance(player.getLocation())) {
        if (HyperDebug) {
            dB.log("Not in range");
        }
        return new ChatContext(false);
    }
    if (Settings.chatMustSeeNPC()) {
        if (!player.hasLineOfSight(npc.getEntity())) {
            if (HyperDebug) {
                dB.log("no LOS");
            }
            return new ChatContext(false);
        }
    }
    if (Settings.chatMustLookAtNPC()) {
        if (!NMSHandler.getInstance().getEntityHelper().isFacingEntity(player, npc.getEntity(), 45)) {
            if (HyperDebug) {
                dB.log("Not facing");
            }
            return new ChatContext(false);
        }
    }
    Boolean ret = false;
    // Denizen should be good to interact with. Let's get the script.
    InteractScriptContainer script = npc.getInteractScript(denizenPlayer, ChatTrigger.class);
    Map<String, dObject> context = new HashMap<String, dObject>();
    context.put("message", new Element(message));
    //
    // Fire the Actions!
    //
    // If engaged or not cool, calls On Unavailable, if cool, calls On Chat
    // If available (not engaged, and cool) sets cool down and returns true.
    TriggerTrait.TriggerContext trigger = npc.getTriggerTrait().trigger(ChatTrigger.this, denizenPlayer, context);
    // Return false if determine cancelled
    if (trigger.hasDetermination()) {
        if (trigger.getDetermination().equalsIgnoreCase("cancelled")) {
            if (HyperDebug) {
                dB.log("Cancelled");
            }
            // Mark as handled, the event will cancel.
            return new ChatContext(true);
        }
    }
    // Return false if trigger was unable to fire
    if (!trigger.wasTriggered()) {
        // through. Check the Settings if this is enabled.
        if (Settings.chatGloballyIfUninteractable()) {
            dB.echoDebug(script, ChatColor.YELLOW + "Resuming. " + ChatColor.WHITE + "The NPC is currently cooling down or engaged.");
            return new ChatContext(false);
        } else {
            ret = true;
        }
    }
    // Debugger
    dB.report(script, name, aH.debugObj("Player", player.getName()) + aH.debugObj("NPC", npc.toString()) + aH.debugObj("Radius(Max)", npc.getLocation().distance(player.getLocation()) + "(" + npc.getTriggerTrait().getRadius(name) + ")") + aH.debugObj("Trigger text", message) + aH.debugObj("LOS", String.valueOf(player.hasLineOfSight(npc.getEntity()))) + aH.debugObj("Facing", String.valueOf(NMSHandler.getInstance().getEntityHelper().isFacingEntity(player, npc.getEntity(), 45))));
    // Change the text if it's in the determination
    if (trigger.hasDetermination()) {
        message = trigger.getDetermination();
    }
    if (script == null) {
        if (HyperDebug) {
            dB.log("null script");
        }
        return new ChatContext(message, false);
    }
    // Check if the NPC has Chat Triggers for this step.
    if (!script.containsTriggerInStep(InteractScriptHelper.getCurrentStep(denizenPlayer, script.getName()), ChatTrigger.class)) {
        // it has no chat triggers for this step
        if (npc.getCitizen().hasTrait(ChatbotTrait.class)) {
            Utilities.talkToNPC(message, denizenPlayer, npc, Settings.chatToNpcOverhearingRange());
            npc.getCitizen().getTrait(ChatbotTrait.class).chatTo(player, message);
            if (HyperDebug) {
                dB.log("chatbot");
            }
            return new ChatContext(false);
        } else // No chat trigger for this step.. do we chat globally, or to the NPC?
        if (!Settings.chatGloballyIfNoChatTriggers()) {
            dB.echoDebug(script, player.getName() + " says to " + npc.getNicknameTrait().getNickname() + ", " + message);
            return new ChatContext(false);
        } else {
            if (HyperDebug) {
                dB.log("No trigger in step, chatting globally");
            }
            return new ChatContext(message, ret);
        }
    }
    // Parse the script and match Triggers.. if found, cancel the text! The
    // parser will take care of everything else.
    String id = null;
    boolean matched = false;
    String replacementText = null;
    String regexId = null;
    String regexMessage = null;
    // Use TreeMap to sort chat triggers alphabetically
    TreeMap<String, String> idMap = new TreeMap<String, String>();
    idMap.putAll(script.getIdMapFor(ChatTrigger.class, denizenPlayer));
    if (!idMap.isEmpty()) {
        // Iterate through the different id entries in the step's chat trigger
        List<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(idMap.entrySet());
        Collections.sort(entries, new Comparator<Map.Entry<String, String>>() {

            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                if (o1 == null || o2 == null) {
                    return 0;
                }
                return o1.getKey().compareToIgnoreCase(o2.getKey());
            }
        });
        for (Map.Entry<String, String> entry : entries) {
            // Check if the chat trigger specified in the specified id's 'trigger:' key
            // matches the text the player has said
            // TODO: script arg?
            String triggerText = TagManager.tag(entry.getValue(), new BukkitTagContext(denizenPlayer, npc, false, null, false, null));
            Matcher matcher = triggerPattern.matcher(triggerText);
            while (matcher.find()) {
                if (!script.checkSpecificTriggerScriptRequirementsFor(ChatTrigger.class, denizenPlayer, npc, entry.getKey())) {
                    continue;
                }
                // TODO: script arg?
                String keyword = TagManager.tag(matcher.group().replace("/", ""), new BukkitTagContext(denizenPlayer, npc, false, null, false, null));
                String[] split = keyword.split("\\\\\\+REPLACE:", 2);
                String replace = null;
                if (split.length == 2) {
                    keyword = split[0];
                    replace = split[1];
                }
                // match already (thus using alphabetical priority for triggers)
                if (regexId == null && isKeywordRegex(keyword)) {
                    Pattern pattern = Pattern.compile(keyword.substring(6));
                    Matcher m = pattern.matcher(message);
                    if (m.find()) {
                        // REGEX matches are left for last, so save it in case non-REGEX
                        // matches don't exist
                        regexId = entry.getKey();
                        regexMessage = triggerText.replace(matcher.group(), m.group());
                        dB.log("entry value: " + triggerText + "  keyword: " + keyword + "  m.group: " + m.group() + "  matcher.group: " + matcher.group());
                        context.put("keyword", new Element(m.group()));
                        if (replace != null) {
                            regexMessage = replace;
                        }
                    }
                } else if (isKeywordStrict(keyword)) {
                    if (message.toUpperCase().equalsIgnoreCase(keyword.toUpperCase())) {
                        // Trigger matches
                        id = entry.getKey();
                        replacementText = triggerText.replace("/", "");
                        matched = true;
                        if (replace != null) {
                            replacementText = replace;
                        }
                    }
                } else if (message.toUpperCase().contains(keyword.toUpperCase())) {
                    // Trigger matches
                    id = entry.getKey();
                    replacementText = triggerText.replace("/", "");
                    matched = true;
                    if (replace != null) {
                        replacementText = replace;
                    }
                }
            }
            if (matched) {
                break;
            }
        }
    }
    if (!matched && regexId != null) {
        id = regexId;
        replacementText = regexMessage;
    }
    // If there was a match, the id of the match should have been returned.
    if (id != null) {
        Utilities.talkToNPC(replacementText, denizenPlayer, npc, Settings.chatToNpcOverhearingRange());
        parse(npc, denizenPlayer, script, id, context);
        if (HyperDebug) {
            dB.log("chat to NPC");
        }
        return new ChatContext(true);
    } else {
        // none of its chat triggers worked
        if (npc.getCitizen().hasTrait(ChatbotTrait.class)) {
            Utilities.talkToNPC(message, denizenPlayer, npc, Settings.chatToNpcOverhearingRange());
            npc.getCitizen().getTrait(ChatbotTrait.class).chatTo(player, message);
            if (HyperDebug) {
                dB.log("Chatbot");
            }
            return new ChatContext(true);
        } else if (!Settings.chatGloballyIfFailedChatTriggers()) {
            Utilities.talkToNPC(message, denizenPlayer, npc, Settings.chatToNpcOverhearingRange());
            if (HyperDebug) {
                dB.log("Chat globally");
            }
            return new ChatContext(true);
        }
    // No matching chat triggers, and the config.yml says we
    // should just ignore the interaction...
    }
    if (HyperDebug) {
        dB.log("Finished calculating");
    }
    return new ChatContext(message, ret);
}
Also used : TriggerTrait(net.aufdemrand.denizen.npc.traits.TriggerTrait) Matcher(java.util.regex.Matcher) Element(net.aufdemrand.denizencore.objects.Element) net.aufdemrand.denizencore.objects.dObject(net.aufdemrand.denizencore.objects.dObject) InteractScriptContainer(net.aufdemrand.denizen.scripts.containers.core.InteractScriptContainer) Pattern(java.util.regex.Pattern) net.aufdemrand.denizen.objects.dNPC(net.aufdemrand.denizen.objects.dNPC) ChatbotTrait(net.aufdemrand.denizen.npc.traits.ChatbotTrait) BukkitTagContext(net.aufdemrand.denizen.tags.BukkitTagContext) net.aufdemrand.denizen.objects.dPlayer(net.aufdemrand.denizen.objects.dPlayer)

Example 3 with TriggerTrait

use of net.aufdemrand.denizen.npc.traits.TriggerTrait in project Denizen-For-Bukkit by DenizenScript.

the class ProximityTrigger method onEnable.

@Override
public void onEnable() {
    Bukkit.getServer().getPluginManager().registerEvents(this, DenizenAPI.getCurrentInstance());
    final ProximityTrigger trigger = this;
    taskID = Bukkit.getScheduler().scheduleSyncRepeatingTask(DenizenAPI.getCurrentInstance(), new Runnable() {

        @Override
        public void run() {
            //
            // Iterate over all of the NPCs
            //
            Iterator<dNPC> it = dNPCRegistry.getSpawnedNPCs().iterator();
            while (it.hasNext()) {
                dNPC npc = it.next();
                if (npc == null) {
                    continue;
                }
                if (npc.getCitizen() == null) {
                    continue;
                }
                //
                if (!npc.getCitizen().hasTrait(TriggerTrait.class)) {
                    continue;
                }
                if (!npc.getCitizen().getTrait(TriggerTrait.class).isEnabled(name)) {
                    continue;
                }
                if (!npc.isSpawned()) {
                    continue;
                }
                // Loop through all players
                for (Player BukkitPlayer : Bukkit.getOnlinePlayers()) {
                    //
                    if (!npc.getWorld().equals(BukkitPlayer.getWorld()) && hasExitedProximityOf(BukkitPlayer, npc)) {
                        continue;
                    }
                    //
                    if (!isCloseEnough(BukkitPlayer, npc) && hasExitedProximityOf(BukkitPlayer, npc)) {
                        continue;
                    }
                    // Get the player
                    dPlayer player = dPlayer.mirrorBukkitPlayer(BukkitPlayer);
                    //
                    // Check to make sure the NPC has an assignment. If no assignment, a script doesn't need to be parsed,
                    // but it does still need to trigger for cooldown and action purposes.
                    //
                    InteractScriptContainer script = npc.getInteractScriptQuietly(player, ProximityTrigger.class);
                    //
                    // Set default ranges with information from the TriggerTrait. This allows per-npc overrides and will
                    // automatically check the config for defaults.
                    //
                    double entryRadius = npc.getTriggerTrait().getRadius(name);
                    double exitRadius = npc.getTriggerTrait().getRadius(name);
                    double moveRadius = npc.getTriggerTrait().getRadius(name);
                    //
                    if (script != null) {
                        try {
                            if (script.hasTriggerOptionFor(ProximityTrigger.class, player, null, "ENTRY RADIUS")) {
                                entryRadius = Integer.valueOf(script.getTriggerOptionFor(ProximityTrigger.class, player, null, "ENTRY RADIUS"));
                            }
                        } catch (NumberFormatException nfe) {
                            dB.echoDebug(script, "Entry Radius was not an integer.  Assuming " + entryRadius + " as the radius.");
                        }
                        try {
                            if (script.hasTriggerOptionFor(ProximityTrigger.class, player, null, "EXIT RADIUS")) {
                                exitRadius = Integer.valueOf(script.getTriggerOptionFor(ProximityTrigger.class, player, null, "EXIT RADIUS"));
                            }
                        } catch (NumberFormatException nfe) {
                            dB.echoDebug(script, "Exit Radius was not an integer.  Assuming " + exitRadius + " as the radius.");
                        }
                        try {
                            if (script.hasTriggerOptionFor(ProximityTrigger.class, player, null, "MOVE RADIUS")) {
                                moveRadius = Integer.valueOf(script.getTriggerOptionFor(ProximityTrigger.class, player, null, "MOVE RADIUS"));
                            }
                        } catch (NumberFormatException nfe) {
                            dB.echoDebug(script, "Move Radius was not an integer.  Assuming " + moveRadius + " as the radius.");
                        }
                    }
                    Location npcLocation = npc.getLocation();
                    //
                    // If the Player switches worlds while in range of an NPC, trigger still needs to
                    // fire since technically they have exited proximity. Let's check that before
                    // trying to calculate a distance between the Player and NPC, which will throw
                    // an exception if worlds do not match.
                    //
                    boolean playerChangedWorlds = false;
                    if (npcLocation.getWorld() != player.getWorld()) {
                        playerChangedWorlds = true;
                    }
                    //
                    // If the user is outside the range, and was previously within the
                    // range, then execute the "Exit" script.
                    //
                    // If the user entered the range and were not previously within the
                    // range, then execute the "Entry" script.
                    //
                    // If the user was previously within the range and moved, then execute
                    // the "Move" script.
                    //
                    boolean exitedProximity = hasExitedProximityOf(BukkitPlayer, npc);
                    double distance = 0;
                    if (!playerChangedWorlds) {
                        distance = npcLocation.distance(player.getLocation());
                    }
                    if (!exitedProximity && (playerChangedWorlds || distance >= exitRadius)) {
                        if (!npc.getTriggerTrait().triggerCooldownOnly(trigger, player)) {
                            continue;
                        }
                        // Remember that NPC has exited proximity.
                        exitProximityOf(BukkitPlayer, npc);
                        // Exit Proximity Action
                        npc.action("exit proximity", player);
                        // Parse Interact Script
                        parse(npc, player, script, "EXIT");
                    } else if (exitedProximity && distance <= entryRadius) {
                        // Cooldown
                        if (!npc.getTriggerTrait().triggerCooldownOnly(trigger, player)) {
                            continue;
                        }
                        // Remember that Player has entered proximity of the NPC
                        enterProximityOf(BukkitPlayer, npc);
                        // Enter Proximity Action
                        npc.action("enter proximity", player);
                        // Parse Interact Script
                        parse(npc, player, script, "ENTRY");
                    } else if (!exitedProximity && distance <= moveRadius) {
                        // TODO: Remove this? Constantly cooling down on move may make
                        // future entry/exit proximities 'lag' behind.  Temporarily removing
                        // cooldown on 'move proximity'.
                        // if (!npc.getTriggerTrait().triggerCooldownOnly(this, event.getPlayer()))
                        //     continue;
                        // Move Proximity Action
                        npc.action("move proximity", player);
                        // Parse Interact Script
                        parse(npc, player, script, "MOVE");
                    }
                }
            }
        }
    }, 5, 5);
}
Also used : net.aufdemrand.denizen.objects.dPlayer(net.aufdemrand.denizen.objects.dPlayer) Player(org.bukkit.entity.Player) net.aufdemrand.denizen.objects.dNPC(net.aufdemrand.denizen.objects.dNPC) TriggerTrait(net.aufdemrand.denizen.npc.traits.TriggerTrait) net.aufdemrand.denizen.objects.dPlayer(net.aufdemrand.denizen.objects.dPlayer) InteractScriptContainer(net.aufdemrand.denizen.scripts.containers.core.InteractScriptContainer) Location(org.bukkit.Location)

Example 4 with TriggerTrait

use of net.aufdemrand.denizen.npc.traits.TriggerTrait in project Denizen-For-Bukkit by DenizenScript.

the class ClickTrigger method clickTrigger.

// <--[action]
// @Actions
// no click trigger
//
// @Triggers when the NPC is clicked but no click trigger fires.
//
// @Context
// None
//
// -->
// Technically defined in TriggerTrait, but placing here instead.
// <--[action]
// @Actions
// click
//
// @Triggers when the NPC is clicked by a player.
//
// @Context
// None
//
// @Determine
// "cancelled" to cancel the click event completely.
//
// -->
@EventHandler
public void clickTrigger(NPCRightClickEvent event) {
    // ANY triggers enabled!
    if (!event.getNPC().hasTrait(TriggerTrait.class)) {
        return;
    }
    // The rest of the methods beyond this point require a dNPC object, which can easily be
    // obtained if a valid NPC object is available:
    dNPC npc = DenizenAPI.getDenizenNPC(event.getNPC());
    // super AbstractTrigger and contains the name of the trigger that was use in registration.
    if (!npc.getTriggerTrait().isEnabled(name)) {
        return;
    }
    // We'll get the player too, since it makes reading the next few methods a bit easier:
    dPlayer player = dPlayer.mirrorBukkitPlayer(event.getClicker());
    // Check availability based on the NPC's ENGAGED status and the trigger's COOLDOWN that is
    // provided (and adjustable) by the TriggerTrait. Just use .trigger(...)!
    // If unavailable (engaged or not cool), .trigger calls 'On Unavailable' action and returns false.
    // If available (not engaged, and cool), .trigger sets cool down and returns true.
    TriggerTrait.TriggerContext trigger = npc.getTriggerTrait().trigger(this, player);
    if (!trigger.wasTriggered()) {
        return;
    }
    if (trigger.hasDetermination() && trigger.getDetermination().equalsIgnoreCase("cancelled")) {
        event.setCancelled(true);
        return;
    }
    // Note: In some cases, the automatic actions that .trigger offers may not be
    // desired. In this case, it's recommended to at least use .triggerCooldownOnly which
    // only handles cooling down the trigger with the triggertrait if the 'available' criteria
    // is met. This handles the built-in cooldown that TriggerTrait implements.
    // Okay, now we need to know which interact script will be selected for the Player/NPC
    // based on requirements/npc's assignment script. To get that information, use:
    // InteractScriptHelper.getInteractScript(dNPC, Player, Trigger Class)
    // .getInteractScript will check the Assignment for possible scripts, and automatically
    // check requirements for each of them.
    InteractScriptContainer script = npc.getInteractScript(player, getClass());
    // In an Interact Script, Triggers can have multiple scripts to choose from depending on
    // some kind of 'criteria'. For the 'Click Trigger', that criteria is the item the Player
    // has in hand. Let's get the possible criteria to see which 'Click Trigger script', if any,
    // should trigger. For example:
    //
    // Script Name:
    //   type: interact
    //   steps:
    //     current step:
    //       click trigger:
    String id = null;
    if (script != null) {
        Map<String, String> idMap = script.getIdMapFor(this.getClass(), player);
        if (!idMap.isEmpty()) // Iterate through the different id entries in the step's click trigger
        {
            for (Map.Entry<String, String> entry : idMap.entrySet()) {
                // Tag the entry value to account for replaceables
                // TODO: script arg?
                String entry_value = TagManager.tag(entry.getValue(), new BukkitTagContext(player, npc, false, null, false, null));
                // Check if the item specified in the specified id's 'trigger:' key
                // matches the item that the player is holding.
                dItem item = dItem.valueOf(entry_value);
                if (item == null) {
                    dB.echoError("Invalid click trigger in script '" + script.getName() + "' (null trigger item)!");
                }
                if (item != null && item.comparesTo(player.getPlayerEntity().getItemInHand()) >= 0 && script.checkSpecificTriggerScriptRequirementsFor(this.getClass(), player, npc, entry.getKey())) {
                    id = entry.getKey();
                }
            }
        }
    }
    // we'll call the action 'on no click trigger'.
    if (!parse(npc, player, script, id)) {
        npc.action("no click trigger", player);
    }
}
Also used : TriggerTrait(net.aufdemrand.denizen.npc.traits.TriggerTrait) net.aufdemrand.denizen.objects.dNPC(net.aufdemrand.denizen.objects.dNPC) net.aufdemrand.denizen.objects.dItem(net.aufdemrand.denizen.objects.dItem) BukkitTagContext(net.aufdemrand.denizen.tags.BukkitTagContext) net.aufdemrand.denizen.objects.dPlayer(net.aufdemrand.denizen.objects.dPlayer) InteractScriptContainer(net.aufdemrand.denizen.scripts.containers.core.InteractScriptContainer) Map(java.util.Map) EventHandler(org.bukkit.event.EventHandler)

Example 5 with TriggerTrait

use of net.aufdemrand.denizen.npc.traits.TriggerTrait in project Denizen-For-Bukkit by DenizenScript.

the class DamageTrigger method damageTrigger.

// <--[action]
// @Actions
// no damage trigger
//
// @Triggers when the NPC is damaged by a player but no damage trigger fires.
//
// @Context
// None
//
// -->
// Technically defined in TriggerTrait, but placing here instead.
// <--[action]
// @Actions
// damage
//
// @Triggers when the NPC is damaged by a player.
//
// @Context
// <context.damage> returns how much damage was done.
//
// @Determine
// "cancelled" to cancel the damage event.
//
// -->
// <--[action]
// @Actions
// damaged
//
// @Triggers when the NPC is damaged by an entity.
//
// @Context
// <context.damage> returns how much damage was done.
// <context.damager> returns the entity that did the damage.
//
// @Determine
// "cancelled" to cancel the damage event.
//
// -->
@EventHandler
public void damageTrigger(EntityDamageByEntityEvent event) {
    if (event.getEntity() == null) {
        return;
    }
    dEntity damager = new dEntity(event.getDamager());
    if (damager.isProjectile() && damager.hasShooter()) {
        damager = damager.getShooter();
    }
    Map<String, dObject> context = new HashMap<String, dObject>();
    context.put("damage", new Element(event.getDamage()));
    dPlayer dplayer = null;
    if (CitizensAPI.getNPCRegistry().isNPC(event.getEntity())) {
        dNPC npc = DenizenAPI.getDenizenNPC(CitizensAPI.getNPCRegistry().getNPC(event.getEntity()));
        if (npc == null) {
            return;
        }
        if (npc.getCitizen() == null) {
            return;
        }
        context.put("damager", damager);
        npc.action("damaged", null, context);
        if (damager.isPlayer()) {
            dplayer = damager.getDenizenPlayer();
        } else {
            return;
        }
        if (!npc.getCitizen().hasTrait(TriggerTrait.class)) {
            return;
        }
        if (!npc.getTriggerTrait().isEnabled(name)) {
            return;
        }
        // Get the TriggerContext
        TriggerTrait.TriggerContext trigger = npc.getTriggerTrait().trigger(this, dplayer);
        // Return if the trigger wasn't triggered.
        if (!trigger.wasTriggered()) {
            return;
        }
        // ..or if the determination was cancelled.
        if (trigger.hasDetermination() && trigger.getDetermination().equalsIgnoreCase("cancelled")) {
            event.setCancelled(true);
            return;
        }
        // Build the interact script
        InteractScriptContainer script = InteractScriptHelper.getInteractScript(npc, dplayer, getClass());
        String id = null;
        if (script != null) {
            Map<String, String> idMap = script.getIdMapFor(this.getClass(), dplayer);
            if (!idMap.isEmpty()) // Iterate through the different id entries in the step's click trigger
            {
                for (Map.Entry<String, String> entry : idMap.entrySet()) {
                    // Tag the entry value to account for replaceables
                    // TODO: script arg?
                    String entry_value = TagManager.tag(entry.getValue(), new BukkitTagContext(dplayer, npc, false, null, false, null));
                    // matches the item that the player is holding.
                    if (dItem.valueOf(entry_value).comparesTo(dplayer.getPlayerEntity().getItemInHand()) >= 0 && script.checkSpecificTriggerScriptRequirementsFor(this.getClass(), dplayer, npc, entry.getKey())) {
                        id = entry.getKey();
                    }
                }
            }
        }
        if (!parse(npc, dplayer, script, id, context)) {
            npc.action("no damage trigger", dplayer);
        }
    }
}
Also used : TriggerTrait(net.aufdemrand.denizen.npc.traits.TriggerTrait) HashMap(java.util.HashMap) Element(net.aufdemrand.denizencore.objects.Element) net.aufdemrand.denizen.objects.dNPC(net.aufdemrand.denizen.objects.dNPC) BukkitTagContext(net.aufdemrand.denizen.tags.BukkitTagContext) net.aufdemrand.denizen.objects.dEntity(net.aufdemrand.denizen.objects.dEntity) net.aufdemrand.denizencore.objects.dObject(net.aufdemrand.denizencore.objects.dObject) net.aufdemrand.denizen.objects.dPlayer(net.aufdemrand.denizen.objects.dPlayer) InteractScriptContainer(net.aufdemrand.denizen.scripts.containers.core.InteractScriptContainer) HashMap(java.util.HashMap) Map(java.util.Map) EventHandler(org.bukkit.event.EventHandler)

Aggregations

TriggerTrait (net.aufdemrand.denizen.npc.traits.TriggerTrait)5 net.aufdemrand.denizen.objects.dNPC (net.aufdemrand.denizen.objects.dNPC)5 net.aufdemrand.denizen.objects.dPlayer (net.aufdemrand.denizen.objects.dPlayer)4 InteractScriptContainer (net.aufdemrand.denizen.scripts.containers.core.InteractScriptContainer)4 BukkitTagContext (net.aufdemrand.denizen.tags.BukkitTagContext)3 Element (net.aufdemrand.denizencore.objects.Element)3 Map (java.util.Map)2 net.aufdemrand.denizencore.objects.dObject (net.aufdemrand.denizencore.objects.dObject)2 EventHandler (org.bukkit.event.EventHandler)2 HashMap (java.util.HashMap)1 Matcher (java.util.regex.Matcher)1 Pattern (java.util.regex.Pattern)1 ChatbotTrait (net.aufdemrand.denizen.npc.traits.ChatbotTrait)1 net.aufdemrand.denizen.objects.dEntity (net.aufdemrand.denizen.objects.dEntity)1 net.aufdemrand.denizen.objects.dItem (net.aufdemrand.denizen.objects.dItem)1 Duration (net.aufdemrand.denizencore.objects.Duration)1 Location (org.bukkit.Location)1 Player (org.bukkit.entity.Player)1