Skip to content

Commit

Permalink
Citadel's Stickybomb Launcher
Browse files Browse the repository at this point in the history
  • Loading branch information
Slotterleet committed Jun 12, 2024
1 parent 500df5c commit 8754fa4
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 26 deletions.
3 changes: 3 additions & 0 deletions res/bundles/bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,9 @@ status.fos-support3.name = EMP Mender Generator
status.fos-support3.description = Repairs allied structures and damages enemies near the bearer.
status.fos-legion-fabricator.name = Legion's Mini-Fabricator Replica
status.fos-legion-fabricator.description = Periodically fabricates Legionnaire replicas that follow the player; each one gives +5% damage resistance to the bearer.
status.fos-citadel-stickybomb-launcher.name = Citadel's Sticky Bomb Launcher
status.fos-citadel-stickybomb-launcher.description = Launches persistent sticky bombs.\n[accent]Middle click[] to blow up all planted sticky bombs.
status.fos-citadel-stickybomb-launcher.description-mobile = Launches persistent sticky bombs.\n[accent]Double tap[] to blow up all planted sticky bombs.

unit.fos-legionnaire.name = Legionnaire
unit.fos-legionnaire-replica.name = Legionnaire Replica
Expand Down
3 changes: 3 additions & 0 deletions res/bundles/bundle_ru.properties
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,9 @@ status.fos-support3.name = Генератор ремонтного ЭМИ
status.fos-support3.description = Чинит союзные постройки и боевые единицы и наносит урон врагам около носителя.
status.fos-legion-fabricator.name = Мини-фабрика Легиона (реплика)
status.fos-legion-fabricator.description = Периодически производит реплики Легионеров, которые следуют за игроком; каждый из них дает +5% устойчивости к урону носителю.
status.fos-citadel-stickybomb-launcher.name = Липучкомет Цитадели
status.fos-citadel-stickybomb-launcher.description = Стреляет постоянными липучими бомбами.\n[accent]Нажмите на колесико мыши[], чтобы взорвать все заложенные липучие бомбы.
status.fos-citadel-stickybomb-launcher.description-mobile = Стреляет постоянными липучими бомбами.\n[accent]Нажмите на экран два раза[], чтобы взорвать все заложенные липучие бомбы.

unit.fos-legionnaire.name = Легионер
unit.fos-legionnaire-replica.name = Легионер (реплика)
Expand Down
39 changes: 36 additions & 3 deletions src/fos/content/FOSWeaponModules.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package fos.content;

import arc.Events;
import arc.*;
import arc.graphics.Color;
import fos.type.abilities.UnitResistanceAbility;
import fos.type.bullets.SmartBulletType;
import fos.type.bullets.*;
import fos.type.content.WeaponSet;
import mindustry.Vars;
import mindustry.content.Fx;
import mindustry.entities.abilities.*;
import mindustry.entities.bullet.*;
Expand All @@ -26,7 +27,7 @@ public class FOSWeaponModules {
standard1, standard2, standard3, standard4, standard5,
shotgun1, shotgun2, shotgun3, shotgun4, shotgun5,
support1, support2, support3, support4, support5,
legionFabricator;
legionFabricator, citadelStickyLauncher;

public static void load() {
// BASIC / ASSAULT RIFLES
Expand Down Expand Up @@ -291,5 +292,37 @@ public static void load() {
);
});
}}.reqs(with(tin, 200, silver, 125, silicon, 150)).produceTime(60 * 20);
citadelStickyLauncher = new WeaponSet("citadel-stickybomb-launcher"){
{
description = Core.bundle.getOrNull(getContentType() + "." + this.name + ".description" + (Vars.mobile ? "-mobile" : ""));

weapons.add(
new Weapon("fos-citadel-stickybomb-launcher"){{
x = 0; y = -2;
mirror = false;
rotate = false;
recoil = 2f;
reload = 60f;
inaccuracy = 6f;
shootSound = Sounds.mud;
bullet = new StickyBulletType(4f, 20f){{
lifetime = 40f;
width = height = 16f;

trailWidth = 3f;
trailLength = 12;
trailColor = Pal.plastaniumBack;
backColor = Pal.plastaniumBack;
frontColor = Pal.plastaniumFront;
ejectEffect = Fx.smokeCloud;

splashDamage = 120f;
splashDamageRadius = 28f;
}};
}}
);
reqs = with(tin, 150, diamond, 75, silicon, 150);
}
};
}
}
5 changes: 3 additions & 2 deletions src/fos/content/LumoniTechTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,9 @@ public static void load() {
);
// BOSS-SPECIFIC WEAPONS
node(legionFabricator, Seq.with(new DefeatBoss(legion)), () -> {
//TODO: citadel shotgun? or stickybomb launcher?
soontm();
node(citadelStickyLauncher, Seq.with(new DefeatBoss(FOSUnitTypes.citadel)), () -> {
soontm();
});
});
});

Expand Down
25 changes: 25 additions & 0 deletions src/fos/core/FOSMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import arc.graphics.*;
import arc.graphics.g2d.*;
import arc.graphics.gl.Shader;
import arc.input.*;
import arc.math.Mathf;
import arc.scene.*;
import arc.scene.ui.ImageButton;
Expand All @@ -33,6 +34,7 @@

import static arc.Core.*;
import static arc.discord.DiscordRPC.*;
import static arc.input.GestureDetector.GestureListener;
import static mindustry.Vars.*;

@ModAnnotations.RootDirectoryPath(rootDirectoryPath = "")
Expand Down Expand Up @@ -295,6 +297,29 @@ public void draw() {

// add modded hints
FOSVars.hints.load();

input.addProcessor(new GestureDetector(new GestureListener() {
@Override
public boolean tap(float x, float y, int count, KeyCode button) {
if (((mobile && count == 2) || button == KeyCode.mouseMiddle) && !(
state.isMenu() ||
scene.hasMouse() ||
control.input.isPlacing() ||
control.input.isBreaking() ||
control.input.selectedUnit() != null
) && player.unit() instanceof LumoniPlayerUnitc) {
FOSCall.detonate();
return true;
} else {
return false;
}
}

@Override
public boolean touchDown(float x, float y, int pointer, KeyCode button) {
return GestureListener.super.touchDown(x, y, pointer, button);
}
}));
}

public void constructSettings() {
Expand Down
13 changes: 10 additions & 3 deletions src/fos/type/blocks/special/UpgradeCenter.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import mindustry.world.consumers.ConsumeItemDynamic;
import mindustry.world.draw.*;

import static mindustry.Vars.state;

public class UpgradeCenter extends Block {
/** Called when player upgrades their weapon
* @param player player that upgraded weapon
Expand Down Expand Up @@ -184,10 +186,10 @@ public boolean shouldConsume() {
@Override
public void buildConfiguration(Table table) {
if (WeaponSet.sets.size > 0) {
ItemSelection.buildTable(UpgradeCenter.this, table, WeaponSet.sets,
ItemSelection.buildTable(UpgradeCenter.this, table, WeaponSet.sets.select(ws -> !isSetBanned(ws)),
() -> weaponSet == null ? null : weaponSet,
ws -> {
configure(ws == null ? -1 : ws.id);
configure(ws == null || isSetBanned(ws) ? -1 : ws.id);
progress = 0;
},
selectionRows, selectionColumns
Expand All @@ -197,7 +199,7 @@ public void buildConfiguration(Table table) {
if (weaponSet == null || Vars.player == null) return;
FOSCall.upgrade(Vars.player, tile());
deselect();
}).visible(() -> fraction() >= 1f);
}).visible(() -> !isSetBanned(weaponSet) && fraction() >= 1f);
} else {
deselect();
}
Expand All @@ -218,6 +220,11 @@ public boolean acceptItem(Building source, Item item) {
Structs.contains(weaponSet.reqs, stack -> stack.item == item);
}

protected boolean isSetBanned(WeaponSet set) {
Seq<String> banned = new Seq<>(state.rules.tags.get("fos-bannedMountUpgrades", "").split(";"));
return set != null && banned.contains(set.name);
}

@Override
public void write(Writes write) {
super.write(write);
Expand Down
75 changes: 57 additions & 18 deletions src/fos/type/bullets/StickyBulletType.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@

import arc.math.Mathf;
import arc.math.geom.Vec2;
import mindustry.annotations.Annotations;
import mindustry.content.Fx;
import mindustry.entities.bullet.ArtilleryBulletType;
import mindustry.entities.bullet.BasicBulletType;
import mindustry.gen.*;
import mindustry.graphics.Layer;

public class StickyBulletType extends ArtilleryBulletType {
public class StickyBulletType extends BasicBulletType {
/** An interval between the contact with an enemy and the explosion. */
public int explosionDelay;
/** If true, ignores explosion delay and only blows up after double tapping. */
public boolean persistent = false;
/** Persistent sticky bomb limit. */
public int bulletCap = 10;

public StickyBulletType(float speed, float damage) {
this(speed, damage, 10);
persistent = true;
}

public StickyBulletType(float speed, float damage, int explosionDelay) {
super(speed, damage);
Expand All @@ -26,6 +36,18 @@ public StickyBulletType(float speed, float damage, int explosionDelay) {
pierce = true;
collides = true;
collidesGround = true;
collidesAir = false;
}

@Override
public void init(Bullet b) {
super.init(b);

int counter = Groups.bullet.count(bul -> bul.type == this);
if (persistent && counter > bulletCap) {
Groups.bullet.find(bul -> bul.type == this).remove();
}

}

@Override
Expand Down Expand Up @@ -63,27 +85,35 @@ public void update(Bullet b) {

StickyBulletData data = (StickyBulletData) b.data;

if (data != null && data.target == null) {
b.vel.set(Vec2.ZERO);
return;
}
if (data != null) {
if (persistent) {
if (b.owner instanceof Unitc u && u.dead())
b.remove();
b.time = 0f;
}

if (data != null && data.target instanceof Unit u && !u.dead()) {
float bx = b.x(), by = b.y();
float ox = data.target.x(), oy = data.target.y();
if (data.target == null) {
b.vel.set(Vec2.ZERO);
return;
}

if (data.initialAngle == null) data.initialAngle = Mathf.angle(bx - ox, by - oy);
if (data.targetRot == null) data.targetRot = u.rotation;
if (data.target instanceof Unit u && !u.dead()) {
float bx = b.x(), by = b.y();
float ox = data.target.x(), oy = data.target.y();

float angle = data.initialAngle - data.targetRot + u.rotation;
if (data.initialAngle == null) data.initialAngle = Mathf.angle(bx - ox, by - oy);
if (data.targetRot == null) data.targetRot = u.rotation;

var vx = (u.x + Mathf.cos(angle * Mathf.degRad) * u.hitSize / 2) - b.x;
var vy = (u.y + Mathf.sin(angle * Mathf.degRad) * u.hitSize / 2) - b.y;
float angle = data.initialAngle - data.targetRot + u.rotation;

if (vx == 0 && vy == 0) {
b.vel.set(Vec2.ZERO);
} else {
b.vel.set(vx, vy);
var vx = (u.x + Mathf.cos(angle * Mathf.degRad) * u.hitSize / 2) - b.x;
var vy = (u.y + Mathf.sin(angle * Mathf.degRad) * u.hitSize / 2) - b.y;

if (vx == 0 && vy == 0) {
b.vel.set(Vec2.ZERO);
} else {
b.vel.set(vx, vy);
}
}
}
}
Expand All @@ -103,6 +133,15 @@ public void removed(Bullet b) {
}
}

@Annotations.Remote(called = Annotations.Loc.both, targets = Annotations.Loc.client, forward = true)
public static void detonate(Player player) {
Groups.bullet.each(b -> {
if (b == null || !(b.data instanceof StickyBulletData) || b.owner == null) return;

if (b.owner == player.unit()) b.lifetime = 1f;
});
}

public static class StickyBulletData {
public Teamc target;
public Float initialAngle, targetRot;
Expand Down

0 comments on commit 8754fa4

Please sign in to comment.