mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-13 01:07:30 +07:00
Lightning shield absorption
This commit is contained in:
@ -27,7 +27,7 @@ allprojects {
|
||||
appName = 'Mindustry'
|
||||
gdxVersion = '1.9.8'
|
||||
roboVMVersion = '2.3.0'
|
||||
uCoreVersion = 'ba0efc413a71192cbede7b4e4bf734860ca764d8'
|
||||
uCoreVersion = '8749ac785424beee126198f5769dc6672587eca1'
|
||||
|
||||
getVersionString = {
|
||||
String buildVersion = getBuildVersion()
|
||||
|
BIN
core/assets-raw/sprites/ui/icons/icon-unlocked.png
Normal file
BIN
core/assets-raw/sprites/ui/icons/icon-unlocked.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 169 B |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 101 KiB |
@ -61,6 +61,11 @@ public class DebugBlocks extends BlockList implements ContentList{
|
||||
hasItems = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outputsItems(){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
SorterEntity entity = tile.entity();
|
||||
@ -81,6 +86,7 @@ public class DebugBlocks extends BlockList implements ContentList{
|
||||
hasLiquids = true;
|
||||
liquidCapacity = 100f;
|
||||
configurable = true;
|
||||
outputsLiquid = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -62,6 +62,7 @@ public class UI extends SceneModule{
|
||||
public ContentInfoDialog content;
|
||||
public SectorsDialog sectors;
|
||||
public MissionDialog missions;
|
||||
public UnlockGraphDialog graph;
|
||||
|
||||
private Locale lastLocale;
|
||||
|
||||
@ -168,6 +169,7 @@ public class UI extends SceneModule{
|
||||
content = new ContentInfoDialog();
|
||||
sectors = new SectorsDialog();
|
||||
missions = new MissionDialog();
|
||||
graph = new UnlockGraphDialog();
|
||||
|
||||
Group group = Core.scene.getRoot();
|
||||
|
||||
|
@ -5,6 +5,7 @@ import com.badlogic.gdx.utils.TimeUtils;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.entities.traits.AbsorbTrait;
|
||||
import io.anuke.mindustry.entities.traits.SyncTrait;
|
||||
import io.anuke.mindustry.entities.traits.TeamTrait;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
@ -26,7 +27,7 @@ import static io.anuke.mindustry.Vars.bulletGroup;
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public class Bullet extends BulletEntity<BulletType> implements TeamTrait, SyncTrait{
|
||||
public class Bullet extends BulletEntity<BulletType> implements TeamTrait, SyncTrait, AbsorbTrait{
|
||||
private static Vector2 vector = new Vector2();
|
||||
public Timer timer = new Timer(3);
|
||||
private Team team;
|
||||
|
@ -9,7 +9,9 @@ import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.content.StatusEffects;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
import io.anuke.mindustry.entities.traits.AbsorbTrait;
|
||||
import io.anuke.mindustry.entities.traits.SyncTrait;
|
||||
import io.anuke.mindustry.entities.traits.TeamTrait;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
@ -17,9 +19,10 @@ import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Effects.Effect;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.entities.impl.TimedEntity;
|
||||
import io.anuke.ucore.entities.impl.SolidEntity;
|
||||
import io.anuke.ucore.entities.trait.DrawTrait;
|
||||
import io.anuke.ucore.entities.trait.SolidTrait;
|
||||
import io.anuke.ucore.entities.trait.TimeTrait;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
@ -34,17 +37,24 @@ import java.io.IOException;
|
||||
import static io.anuke.mindustry.Vars.bulletGroup;
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncTrait{
|
||||
private static Array<SolidTrait> entities = new Array<>();
|
||||
private static Rectangle rect = new Rectangle();
|
||||
private static Rectangle hitrect = new Rectangle();
|
||||
public class Lightning extends SolidEntity implements Poolable, DrawTrait, SyncTrait, AbsorbTrait, TeamTrait, TimeTrait{
|
||||
private static final Array<SolidTrait> entities = new Array<>();
|
||||
private static final Rectangle rect = new Rectangle();
|
||||
private static final Rectangle hitrect = new Rectangle();
|
||||
private static final float wetDamageMultiplier = 2;
|
||||
private static final float step = 4f, range = 6f, attractRange = 20f;
|
||||
|
||||
private static int lastSeed = 0;
|
||||
private static float angle;
|
||||
private static float wetDamageMultiplier = 2;
|
||||
|
||||
private Array<Vector2> lines = new Array<>();
|
||||
private Color color = Palette.lancerLaser;
|
||||
private Lightning parent;
|
||||
private SeedRandom random = new SeedRandom();
|
||||
private float damage, time;
|
||||
private int activeFrame;
|
||||
private Effect effect;
|
||||
private Team team;
|
||||
|
||||
/**For pooling use only. Do not call directly!*/
|
||||
public Lightning(){
|
||||
@ -57,18 +67,17 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
||||
|
||||
/**Do not invoke!*/
|
||||
@Remote(called = Loc.server)
|
||||
public static void createLighting(int seed, Team team, Effect effect, Color color, float damage, float x, float y, float targetAngle, int length){
|
||||
public static Lightning createLighting(int seed, Team team, Effect effect, Color color, float damage, float x, float y, float targetAngle, int length){
|
||||
Lightning l = Pooling.obtain(Lightning.class, Lightning::new);
|
||||
|
||||
l.x = x;
|
||||
l.y = y;
|
||||
l.damage = damage;
|
||||
l.effect = effect;
|
||||
l.team = team;
|
||||
l.random.setSeed(seed);
|
||||
l.color = color;
|
||||
|
||||
float step = 4f;
|
||||
float range = 6f;
|
||||
float attractRange = 20f;
|
||||
|
||||
angle = targetAngle;
|
||||
entities.clear();
|
||||
|
||||
@ -77,10 +86,8 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
||||
for(int i = 0; i < length; i++){
|
||||
l.lines.add(new Vector2(x, y));
|
||||
|
||||
float fx = x, fy = y;
|
||||
float x2 = x + Angles.trnsx(angle, step);
|
||||
float y2 = y + Angles.trnsy(angle, step);
|
||||
float fangle = angle;
|
||||
|
||||
angle += Mathf.range(15f);
|
||||
rect.setSize(attractRange).setCenter(x, y);
|
||||
@ -90,32 +97,11 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
||||
if(dst < attractRange){
|
||||
angle = Mathf.slerp(angle, Angles.angle(x2, y2, entity.x, entity.y), (attractRange - dst) / attractRange / 4f);
|
||||
}
|
||||
|
||||
entity.getHitbox(hitrect);
|
||||
hitrect.x -= range / 2f;
|
||||
hitrect.y -= range / 2f;
|
||||
hitrect.width += range / 2f;
|
||||
hitrect.height += range / 2f;
|
||||
|
||||
if(hitrect.contains(x2, y2) || hitrect.contains(fx, fy)){
|
||||
float result = damage;
|
||||
|
||||
if(entity.hasEffect(StatusEffects.wet))
|
||||
result = (result * wetDamageMultiplier);
|
||||
|
||||
entity.damage(result);
|
||||
Effects.effect(effect, x2, y2, fangle);
|
||||
}
|
||||
});
|
||||
|
||||
if(l.random.chance(0.1f)){
|
||||
createLighting(l.random.nextInt(), team, effect, color, damage, x2, y2, angle + l.random.range(30f), length / 3);
|
||||
}
|
||||
|
||||
Tile tile = world.tileWorld(x, y);
|
||||
if(tile != null && tile.entity != null && tile.getTeamID() != team.ordinal()){
|
||||
Effects.effect(effect, x, y, fangle);
|
||||
tile.entity.damage(damage/4f);
|
||||
createLighting(l.random.nextInt(), team, effect, color, damage, x2, y2, angle + l.random.range(30f), length / 3)
|
||||
.parent = l;
|
||||
}
|
||||
|
||||
x = x2;
|
||||
@ -124,6 +110,41 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
||||
|
||||
l.lines.add(new Vector2(x, y));
|
||||
l.add();
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void absorb(){
|
||||
activeFrame = 99;
|
||||
if(parent != null){
|
||||
parent.absorb();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collides(SolidTrait other){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void time(float time){
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeAbsorbed(){
|
||||
return activeFrame < 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float time(){
|
||||
return time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float fin(){
|
||||
return time/lifetime();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -146,11 +167,45 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Team getTeam(){
|
||||
return team;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
updateTime();
|
||||
|
||||
if(activeFrame == 2){
|
||||
for(Vector2 vec : lines){
|
||||
rect.setSize(range).setCenter(x, y);
|
||||
|
||||
Units.getNearbyEnemies(team, rect, unit -> {
|
||||
unit.getHitbox(hitrect);
|
||||
if(rect.overlaps(hitrect)){
|
||||
unit.damage(damage * (unit.hasEffect(StatusEffects.wet) ? 2f : 1f));
|
||||
Effects.effect(effect, vec.x, vec.y, 0f);
|
||||
}
|
||||
});
|
||||
|
||||
Tile tile = world.tileWorld(vec.x, vec.y);
|
||||
if(tile != null && tile.entity != null && tile.getTeamID() != team.ordinal()){
|
||||
Effects.effect(effect, vec.x, vec.y, 0f);
|
||||
tile.entity.damage(damage/4f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
activeFrame ++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
super.reset();
|
||||
time = 0f;
|
||||
color = Palette.lancerLaser;
|
||||
lines.clear();
|
||||
parent = null;
|
||||
activeFrame = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -159,6 +214,11 @@ public class Lightning extends TimedEntity implements Poolable, DrawTrait, SyncT
|
||||
Pooling.free(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getDamage(){
|
||||
return damage/10f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
float lx = x, ly = y;
|
||||
|
12
core/src/io/anuke/mindustry/entities/traits/AbsorbTrait.java
Normal file
12
core/src/io/anuke/mindustry/entities/traits/AbsorbTrait.java
Normal file
@ -0,0 +1,12 @@
|
||||
package io.anuke.mindustry.entities.traits;
|
||||
|
||||
import io.anuke.ucore.entities.trait.DamageTrait;
|
||||
import io.anuke.ucore.entities.trait.Entity;
|
||||
|
||||
public interface AbsorbTrait extends Entity, TeamTrait, DamageTrait{
|
||||
void absorb();
|
||||
|
||||
default boolean canBeAbsorbed(){
|
||||
return true;
|
||||
}
|
||||
}
|
119
core/src/io/anuke/mindustry/ui/GraphSimulation.java
Normal file
119
core/src/io/anuke/mindustry/ui/GraphSimulation.java
Normal file
@ -0,0 +1,119 @@
|
||||
package io.anuke.mindustry.ui;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.SafeArray;
|
||||
|
||||
public class GraphSimulation<T>{
|
||||
public Array<Vertex<T>> vertices = new SafeArray<>();
|
||||
public Array<Edge<T>> edges = new SafeArray<>();
|
||||
public int frameWidth;
|
||||
public int frameHeight;
|
||||
public boolean equi = false;
|
||||
public float criterion = 1000;
|
||||
public float coolingRate = 0.065f;
|
||||
|
||||
private static final float C = 1f;
|
||||
|
||||
private int iteration = 0;
|
||||
private float k;
|
||||
private float t;
|
||||
private boolean equilibriumReached = false;
|
||||
|
||||
private Vector2 deltaPos = new Vector2();
|
||||
|
||||
public int startSimulation() {
|
||||
|
||||
iteration = 0;
|
||||
equilibriumReached = false;
|
||||
|
||||
int area = Math.min(frameWidth * frameWidth, frameHeight * frameHeight);
|
||||
k = C * Mathf.sqrt(area / vertices.size);
|
||||
t = frameWidth / 10;
|
||||
|
||||
if (equi) {
|
||||
while (!equilibriumReached && iteration < 10000) {
|
||||
simulateStep();
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < criterion; i++) {
|
||||
simulateStep();
|
||||
}
|
||||
}
|
||||
return iteration;
|
||||
}
|
||||
|
||||
private void simulateStep() {
|
||||
for (Vertex<T> v : vertices) {
|
||||
v.disp.set(0, 0);
|
||||
for (Vertex<T> u : vertices) {
|
||||
if (v != u) {
|
||||
deltaPos.set(v.pos).sub(u.pos);
|
||||
float length = deltaPos.len();
|
||||
deltaPos.setLength(forceRepulsive(length, k));
|
||||
v.disp.add(deltaPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Edge<T> e : edges) {
|
||||
deltaPos.set(e.v.pos).sub(e.u.pos);
|
||||
float length = deltaPos.len();
|
||||
deltaPos.setLength(forceAttractive(length, k));
|
||||
|
||||
e.v.disp.sub(deltaPos);
|
||||
e.u.disp.add(deltaPos);
|
||||
}
|
||||
|
||||
equilibriumReached = true;
|
||||
|
||||
for (Vertex<T> v : vertices) {
|
||||
|
||||
deltaPos.set(v.disp);
|
||||
float length = deltaPos.len();
|
||||
|
||||
if (length > criterion) {
|
||||
equilibriumReached = false;
|
||||
}
|
||||
|
||||
deltaPos.setLength(Math.min(length, t));
|
||||
|
||||
v.pos.add(deltaPos);
|
||||
v.pos.x = Mathf.clamp(v.pos.x, 0, frameWidth);
|
||||
v.pos.y = Mathf.clamp(v.pos.y, 0, frameHeight);
|
||||
}
|
||||
|
||||
t = Math.max(t * (1 - coolingRate), 1);
|
||||
iteration++;
|
||||
}
|
||||
|
||||
private float forceAttractive(float d, float k) {
|
||||
return d * d / k;
|
||||
}
|
||||
|
||||
private float forceRepulsive(float d, float k) {
|
||||
return k * k /d;
|
||||
}
|
||||
|
||||
public static class Vertex<T>{
|
||||
public Vector2 pos = new Vector2();
|
||||
public final T value;
|
||||
|
||||
private Vector2 disp = new Vector2();
|
||||
|
||||
public Vertex(T value){
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Edge<T> {
|
||||
public final Vertex<T> v;
|
||||
public final Vertex<T> u;
|
||||
|
||||
public Edge(Vertex<T> v, Vertex<T> u) {
|
||||
this.v = v;
|
||||
this.u = u;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package io.anuke.mindustry.ui.dialogs;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.game.UnlockableContent;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.ItemType;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.ui.GraphSimulation;
|
||||
import io.anuke.mindustry.ui.GraphSimulation.Edge;
|
||||
import io.anuke.mindustry.ui.GraphSimulation.Vertex;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
public class UnlockGraphDialog extends FloatingDialog{
|
||||
int frameSize = 1000;
|
||||
ObjectMap<UnlockableContent, Vertex<UnlockableContent>> map = new ObjectMap<>();
|
||||
Array<Vertex<UnlockableContent>> vertices;
|
||||
Array<Edge<UnlockableContent>> edges;
|
||||
|
||||
public UnlockGraphDialog(){
|
||||
super("$text.unlocks");
|
||||
|
||||
rebuild();
|
||||
}
|
||||
|
||||
public void rebuild(){
|
||||
content().clear();
|
||||
|
||||
GraphSimulation<UnlockableContent> sim = new GraphSimulation<>();
|
||||
sim.frameWidth = frameSize;
|
||||
sim.frameHeight = frameSize;
|
||||
vertices = sim.vertices;
|
||||
edges = sim.edges;
|
||||
|
||||
for(Item item : Vars.content.items()){
|
||||
if(item.type != ItemType.material) continue;
|
||||
put(item);
|
||||
}
|
||||
|
||||
for(Recipe recipe : Vars.content.recipes()){
|
||||
if(recipe.requirements.length == 0) continue;
|
||||
put(recipe);
|
||||
|
||||
for(Item item : Vars.content.items()){
|
||||
for(ItemStack stack : recipe.requirements){
|
||||
if(stack.item == item){
|
||||
link(item, recipe);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sim.startSimulation();
|
||||
|
||||
content().addRect((x, y, w, h) -> {
|
||||
float cx = x + w/2f, cy = y + h/2f;
|
||||
float ox = cx - frameSize/2f, oy = cy - frameSize/2f;
|
||||
|
||||
Draw.color(Color.DARK_GRAY);
|
||||
Lines.stroke(4f);
|
||||
|
||||
for(Edge<UnlockableContent> e : edges){
|
||||
if(e.v.value instanceof Item){
|
||||
Draw.color(((Item) e.v.value).color);
|
||||
}
|
||||
Lines.line(e.u.pos.x + ox, e.u.pos.y + oy, e.v.pos.x + ox, e.v.pos.y + oy);
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
|
||||
for(Vertex<UnlockableContent> v : vertices){
|
||||
Draw.rect(v.value.getContentIcon(), v.pos.x + ox, v.pos.y + oy, 16*2f, 16*2f);
|
||||
}
|
||||
}).grow();
|
||||
}
|
||||
|
||||
private Vertex<UnlockableContent> get(UnlockableContent c){
|
||||
return map.get(c);
|
||||
}
|
||||
|
||||
private void put(UnlockableContent c){
|
||||
Vertex<UnlockableContent> v = new Vertex<>(c);
|
||||
v.pos.set(frameSize/2f + Mathf.range(frameSize/2f), frameSize/2f + Mathf.range(frameSize/2f));
|
||||
map.put(c, v);
|
||||
vertices.add(v);
|
||||
}
|
||||
|
||||
private void link(UnlockableContent a, UnlockableContent b){
|
||||
edges.add(new Edge<>(get(a), get(b)));
|
||||
}
|
||||
}
|
@ -128,7 +128,7 @@ public class MenuFragment extends Fragment{
|
||||
|
||||
out.add(new MenuButton("icon-menu", "$text.changelog.title", ui.changelog::show));
|
||||
|
||||
out.add(new MenuButton("icon-unlocks", "$text.unlocks", ui.unlocks::show));
|
||||
out.add(new MenuButton("icon-unlocks", "$text.unlocks", ui.graph::show));
|
||||
|
||||
out.row();
|
||||
|
||||
|
@ -5,7 +5,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import io.anuke.mindustry.content.fx.BlockFx;
|
||||
import io.anuke.mindustry.content.fx.BulletFx;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.bullet.Bullet;
|
||||
import io.anuke.mindustry.entities.traits.AbsorbTrait;
|
||||
import io.anuke.mindustry.entities.traits.SyncTrait;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
@ -127,13 +127,14 @@ public class ForceProjector extends Block {
|
||||
|
||||
if(!entity.broken){
|
||||
EntityPhysics.getNearby(bulletGroup, tile.drawx(), tile.drawy(), realRadius*2f, bullet -> {
|
||||
if(bullet instanceof Bullet && ((Bullet) bullet).getTeam() != tile.getTeam() && isInsideHexagon(bullet.getX(), bullet.getY(), realRadius * 2f, tile.drawx(), tile.drawy())){
|
||||
((Bullet) bullet).absorb();
|
||||
Effects.effect(BulletFx.absorb, bullet);
|
||||
float hit = ((Bullet) bullet).getDamage()*powerDamage;
|
||||
AbsorbTrait trait = (AbsorbTrait)bullet;
|
||||
if(trait.canBeAbsorbed() && trait.getTeam() != tile.getTeam() && isInsideHexagon(trait.getX(), trait.getY(), realRadius * 2f, tile.drawx(), tile.drawy())){
|
||||
trait.absorb();
|
||||
Effects.effect(BulletFx.absorb, trait);
|
||||
float hit = trait.getDamage()*powerDamage;
|
||||
entity.hit = 1f;
|
||||
entity.power.amount -= Math.min(hit, entity.power.amount);
|
||||
entity.buildup += ((Bullet) bullet).getDamage() * entity.warmup;
|
||||
entity.buildup += trait.getDamage() * entity.warmup;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user