/
HurtCommand.java
175 lines (158 loc) · 7.54 KB
/
HurtCommand.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
package com.denizenscript.denizen.scripts.commands.entity;
import com.denizenscript.denizen.utilities.Utilities;
import com.denizenscript.denizen.utilities.debugging.Debug;
import com.denizenscript.denizen.objects.EntityTag;
import com.denizenscript.denizencore.exceptions.InvalidArgumentsException;
import com.denizenscript.denizencore.objects.Argument;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.ArgumentHelper;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
import org.bukkit.Bukkit;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import java.util.ArrayList;
import java.util.List;
public class HurtCommand extends AbstractCommand {
public HurtCommand() {
setName("hurt");
setSyntax("hurt (<#.#>) ({player}/<entity>|...) (cause:<cause>)");
setRequiredArguments(0, 3);
}
// <--[command]
// @Name Hurt
// @Syntax hurt (<#.#>) ({player}/<entity>|...) (cause:<cause>)
// @Required 0
// @Maximum 3
// @Short Hurts the player or a list of entities.
// @Group entity
//
// @Description
// Does damage to a list of entities, or to any single entity.
//
// If no entities are specified: if there is a linked player, the command targets that. If there is no linked
// player but there is a linked NPC, the command targets the NPC. If neither is available, the command will error.
//
// Does a specified amount of damage usually, but, if no damage is specified, does precisely 1HP worth of damage
// (half a heart).
// Optionally, specify (source:<entity>) to make the system treat that entity as the attacker,
// be warned this does not always work as intended, and is liable to glitch.
// You may also optionally specify a damage cause to fire a proper damage event with the given cause,
// only doing the damage if the event wasn't cancelled. Calculates the 'final damage' rather
// than using the raw damage input number. See <@link language damage cause> for damage causes.
// To make the source only be included in the initial damage event, and not the application of damage, specify 'source_once'.
//
// @Tags
// <EntityTag.health>
// <EntityTag.last_damage.amount>
// <EntityTag.last_damage.cause>
// <EntityTag.last_damage.duration>
// <EntityTag.last_damage.max_duration>
//
// @Usage
// Use to hurt the player for 1 HP.
// - hurt
//
// @Usage
// Use to hurt the NPC for 5 HP.
// - hurt 5 <npc>
//
// @Usage
// Use to cause the player to hurt the NPC for all its health (if unarmored).
// - hurt <npc.health> <npc> cause:CUSTOM source:<player>
// -->
@Override
public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {
for (Argument arg : scriptEntry.getProcessedArgs()) {
if (!scriptEntry.hasObject("amount")
&& (arg.matchesFloat()
|| arg.matchesInteger())) {
scriptEntry.addObject("amount", arg.asElement());
}
else if (!scriptEntry.hasObject("source")
&& arg.matchesPrefix("source", "s")
&& arg.matchesArgumentType(EntityTag.class)) {
scriptEntry.addObject("source", arg.asType(EntityTag.class));
}
else if (!scriptEntry.hasObject("entities")
&& arg.matchesArgumentList(EntityTag.class)) {
scriptEntry.addObject("entities", arg.asType(ListTag.class).filter(EntityTag.class, scriptEntry));
}
else if (!scriptEntry.hasObject("cause")
&& arg.matchesEnum(EntityDamageEvent.DamageCause.values())) {
scriptEntry.addObject("cause", arg.asElement());
}
else if (!scriptEntry.hasObject("source_once")
&& arg.matches("source_once")) {
scriptEntry.addObject("source_once", new ElementTag(true));
}
else {
arg.reportUnhandled();
}
}
if (!scriptEntry.hasObject("amount")) {
scriptEntry.addObject("amount", new ElementTag(1.0d));
}
if (!scriptEntry.hasObject("entities")) {
List<EntityTag> entities = new ArrayList<>();
if (Utilities.getEntryPlayer(scriptEntry) != null) {
entities.add(Utilities.getEntryPlayer(scriptEntry).getDenizenEntity());
}
else if (Utilities.getEntryNPC(scriptEntry) != null) {
entities.add(Utilities.getEntryNPC(scriptEntry).getDenizenEntity());
}
else {
throw new InvalidArgumentsException("No valid target entities found.");
}
scriptEntry.addObject("entities", entities);
}
}
@SuppressWarnings("unchecked")
@Override
public void execute(ScriptEntry scriptEntry) {
List<EntityTag> entities = (List<EntityTag>) scriptEntry.getObject("entities");
EntityTag source = (EntityTag) scriptEntry.getObject("source");
ElementTag amountElement = scriptEntry.getElement("amount");
ElementTag cause = scriptEntry.getElement("cause");
ElementTag source_once = scriptEntry.getElement("source_once");
if (scriptEntry.dbCallShouldDebug()) {
Debug.report(scriptEntry, getName(), amountElement.debug()
+ ArgumentHelper.debugList("entities", entities)
+ (source_once == null ? "" : source_once.debug())
+ (cause == null ? "" : cause.debug())
+ (source == null ? "" : source.debug()));
}
double amount = amountElement.asDouble();
for (EntityTag entity : entities) {
if (entity.getLivingEntity() == null) {
Debug.echoDebug(scriptEntry, entity + " is not a living entity!");
continue;
}
if (cause == null) {
if (source == null) {
entity.getLivingEntity().damage(amount);
}
else {
entity.getLivingEntity().damage(amount, source.getBukkitEntity());
}
}
else {
EntityDamageEvent.DamageCause causeEnum = EntityDamageEvent.DamageCause.valueOf(cause.asString().toUpperCase());
EntityDamageEvent ede = source == null ? new EntityDamageEvent(entity.getBukkitEntity(), causeEnum, amount) :
new EntityDamageByEntityEvent(source.getBukkitEntity(), entity.getBukkitEntity(), causeEnum, amount);
Bukkit.getPluginManager().callEvent(ede);
if (!ede.isCancelled()) {
entity.getLivingEntity().setLastDamageCause(ede);
if (source == null || (source_once != null && source_once.asBoolean())) {
entity.getLivingEntity().damage(ede.getFinalDamage());
}
else {
entity.getLivingEntity().damage(ede.getFinalDamage(), source.getBukkitEntity());
}
entity.getLivingEntity().setLastDamageCause(ede);
}
}
}
}
}