Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions src/main/java/ch/njol/skript/expressions/ExprTimeLived.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package ch.njol.skript.expressions;

import ch.njol.skript.classes.Changer.ChangeMode;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Example;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.expressions.base.SimplePropertyExpression;
import ch.njol.skript.util.Timespan;
import ch.njol.skript.util.Timespan.TimePeriod;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.entity.Entity;
import org.bukkit.event.Event;
import org.jetbrains.annotations.Nullable;

@Name("Time Lived of Entity")
@Description("""
Returns the total amount of time the entity has lived.
Note: This does not reset when a player dies.
""")
@Example("""
set {_target} to player's target entity
send "%{_target}% has lived for %time lived of {_target}%"

spawn zombie at player:
set {_boss} to zombie
# start off with 1 tick lived instead of 0 to avoid custom effects running off spawn
add 1 tick to {_boss}'s time lived
while {_boss} is alive:
wait 1 tick
# update display name every tick with hp
set display name of {_boss} to "Boss %{_boss}'s health%/%{_boss}'s max health%"
# heal every second
if mod(ticks of {_boss}'s time lived, 20) is 0:
add 1 to {_boss}'s health
# push forward every 2 seconds
if mod(ticks of {_boss}'s time lived, 40) is 0:
push {_boss} forward at speed 1
# give strength every 10 seconds
if mod(ticks of {_boss}'s time lived, 200) is 0:
add potion effect of strength for 3 seconds to {_boss}'s potion effects
""")
@Since("INSERT VERSION")
public class ExprTimeLived extends SimplePropertyExpression<Entity, Timespan> {

static {
register(ExprTimeLived.class, Timespan.class, "time (alive|lived)", "entities");
}

@Override
@Nullable
public Timespan convert(Entity entity) {
return new Timespan(TimePeriod.TICK, entity.getTicksLived());
}

@Override
@Nullable
public Class<?>[] acceptChange(ChangeMode mode) {
if (mode == ChangeMode.REMOVE_ALL || mode == ChangeMode.DELETE)
return null;
return CollectionUtils.array(Timespan.class);
}

@Override
public void change(Event event, @Nullable Object[] delta, ChangeMode mode) {
Entity entity = getExpr().getSingle(event);
if (entity == null) return;

int newTicks = 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better to store this and valueToSet as longs to account for overflows. That is, if the value is set to high for an int, clamp it down to the max int value.

if (mode != ChangeMode.RESET && delta != null && delta.length > 0 && delta[0] instanceof Timespan timespan) {
newTicks = (int) timespan.get(Timespan.TimePeriod.TICK);
}

int currentTicks = entity.getTicksLived();
int valueToSet = switch (mode) {
case ADD -> currentTicks + newTicks;
case REMOVE -> currentTicks - newTicks;
case SET, RESET -> newTicks;
default -> currentTicks;
};

entity.setTicksLived(Math.max(1, valueToSet));
}

@Override
public Class<? extends Timespan> getReturnType() {
return Timespan.class;
}

@Override
protected String getPropertyName() {
return "time lived";
}
}