Skip to content

Commit

Permalink
Legion the Leader of Interceptors
Browse files Browse the repository at this point in the history
  • Loading branch information
Slotterleet committed Jan 1, 2024
1 parent 4b19e60 commit 7b28e35
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 28 deletions.
6 changes: 5 additions & 1 deletion core/res/bundles/bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ accelerator.campaignonly = This block only works in campaign mode.
accelerator.confirmtitle = Are you sure?
accelerator.confirmtext = This core will be sent towards the nearest planet. Do you really want to launch it?

ability.hackfield = Hack Field ([accent]{0}[] range)
ability.hackfield = Hack Field
ability.unitresistance = Damage Resistance

bar.units = Units: {0}/{1}
bar.detectorreq = Ore Detector Required

stat.hackchance = Hack Chance
stat.attacksbosses = [accent]may hack guardians[]
stat.lifetime = Lifetime
stat.unitdamageres = Resistance per Unit

unittype = [gray]Type: []
unittype.infantry = [accent]Infantry[]
Expand Down Expand Up @@ -288,8 +290,10 @@ status.fos-standard5.name = Rifle Mk. V
status.fos-shotgun1.name = Sawed-off Shotgun Mount
status.fos-shotgun1.description = A shotgun with poor range but decent damage.

unit.fos-legionnaire.name = Legionnaire
unit.fos-legion.name = Legion
unit.fos-legion.description = Does not fight by itself, but summons a bunch of weaker drones on its side. [red]EXPERIMENTAL BOSS ENEMY[]
unit.fos-legion.details = Produces [accent]Legionnaires[] on its side to attack targets while being supported by the Legion. Each Legionnaire currently functioning gives the Legion resistance to all damage. It's advised to deal with the Legionnaires first before attacking the Legion itself.
unit.fos-sergeant.name = Sergeant
unit.fos-sergeant.description = A weak drone capable of turning weak enemies to its team's side. Hacked enemies will die eventually.
unit.fos-lieutenant.name = Lieutenant
Expand Down
6 changes: 5 additions & 1 deletion core/res/bundles/bundle_ru.properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ accelerator.campaignonly = Этот блок работает только в р
accelerator.confirmtitle = Вы уверены?
accelerator.confirmtext = Это ядро будет отправлено в ближайшую планету. Вы точно хотите его запустить?

ability.hackfield = Поле взлома ([accent]{0}[] дальность)
ability.hackfield = Поле взлома
ability.unitresistance = Устойчивость к урону

bar.units = Боевые единицы: {0}/{1}
bar.detectorreq = Требуется детектор руды

stat.hackchance = Шанс взлома
stat.attacksbosses = [accent]может взломать стражей[]
stat.lifetime = Время жизни
stat.unitdamageres = Устойчивость на боевую ед.

unittype = [gray]Тип: []
unittype.infantry = [accent]Пехота[]
Expand Down Expand Up @@ -291,8 +293,10 @@ status.fos-standard5.name = Винтовка Mk. V
status.fos-shotgun1.name = Обрез
status.fos-shotgun1.description = Дробовик с малой дальностью, но неплохим уроном.

unit.fos-legionnaire.name = Легионер
unit.fos-legion.name = Легион
unit.fos-legion.description = Не сражается напрямую, но конструирует множество более слабых дронов на своей стороне. [red]ЭКСПЕРИМЕНТАЛЬНЫЙ БОСС[]
unit.fos-legion.details = Производит [accent]Легионеров[] на своей стороне, которые атакуют цели, будучи под поддержкой Легиона. Каждый функционирующий Легионер дает Легиону устойчивость ко всему урону. Рекомендуется сначала уничтожить Легионеров перед сражением с Легионом.
unit.fos-sergeant.name = Сержант
unit.fos-sergeant.description = Слабый дрон, позволяющий обратить слабых врагов с свою сторону. Взломанные враги рано или поздно будут уничтожены.
unit.fos-lieutenant.name = Лейтенант
Expand Down
Binary file modified core/res/maps/ruins.msav
Binary file not shown.
Binary file added core/res/sprites/units/bosses/legion.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 2 additions & 5 deletions core/src/fos/ai/GroundBossAI.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package fos.ai;

import fos.type.units.LumoniPlayerUnitType;
import mindustry.ai.Pathfinder;
import mindustry.entities.Units;
import mindustry.entities.units.*;
Expand All @@ -10,7 +9,7 @@ public class GroundBossAI extends AIController implements TargetableAI {
@Override
public void updateMovement() {
Building core = unit.closestEnemyCore();
Unit player = Units.closestEnemy(unit.team, unit.x, unit.y, 999f, u -> u.type instanceof LumoniPlayerUnitType);
Unit player = Units.closestEnemy(unit.team, unit.x, unit.y, unit.range() * 10, Unitc::isPlayer);
Teamc curTarget = player != null ? player : core;

if (curTarget == null) return;
Expand All @@ -22,9 +21,7 @@ public void updateMovement() {
mount.target = curTarget;
}
}
}

if (!unit.within(curTarget, unit.type.range)) {
} else {
if (player == null) {
pathfind(Pathfinder.fieldCore);
} else {
Expand Down
29 changes: 29 additions & 0 deletions core/src/fos/ai/ProtectorAI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package fos.ai;

import fos.content.FOSUnitTypes;
import mindustry.entities.Units;
import mindustry.entities.units.AIController;
import mindustry.gen.Unit;

public class ProtectorAI extends AIController {
public Unit protectTarget;

@Override
public void updateUnit() {
super.updateUnit();

if (protectTarget == null) {
protectTarget = Units.closest(unit.team, unit.x, unit.y, u -> u.isPlayer() || u.type == FOSUnitTypes.legion);
}
}

@Override
public void updateMovement() {
super.updateMovement();

if (protectTarget == null) return;

// Just circle around the unit. That's the entire move set of this AI.
circle(protectTarget, protectTarget.hitSize * 2);
}
}
67 changes: 58 additions & 9 deletions core/src/fos/content/FOSUnitTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import fos.ai.*;
import fos.gen.*;
import fos.graphics.FOSPal;
import fos.type.abilities.HackFieldAbility;
import fos.type.abilities.*;
import fos.type.bullets.*;
import fos.type.units.*;
import fos.type.units.destroyers.DestroyersUnits;
Expand All @@ -21,6 +21,7 @@
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.type.weapons.RepairBeamWeapon;

import static fos.content.FOSStatuses.hacked;

Expand All @@ -29,8 +30,10 @@ public class FOSUnitTypes {

public static @Annotations.EntityDef({Tankc.class}) UnitType warden;

public static @Annotations.EntityDef({Unitc.class}) UnitType sergeant, lieutenant, captain, general, marshal,
smoke, cloud;
public static @Annotations.EntityDef({Unitc.class}) UnitType
sergeant, lieutenant, captain, general, marshal,
smoke, cloud,
legionnaire;

public static @Annotations.EntityDef({ElevationMovec.class, Unitc.class}) UnitType assault;

Expand All @@ -50,22 +53,68 @@ public class FOSUnitTypes {
public static void load(){
DestroyersUnits.load();

legionnaire = new UnitType("legionnaire"){{
health = 150;
hitSize = 8;
speed = 2.5f;
accel = 0.08f;
drag = 0.04f;
isEnemy = false;
omniMovement = false;
outlineColor = Color.valueOf("2b2f36");
weapons.add(
new Weapon(){{
top = false;
rotate = true;
rotateSpeed = 6f;
reload = 30f;
bullet = new BasicBulletType(2.5f, 55){{
width = 7f;
height = 9f;
lifetime = 45f;
shootEffect = Fx.shootSmall;
smokeEffect = Fx.shootSmallSmoke;
ammoMultiplier = 2;
trailWidth = 3;
trailLength = 8;
}};
}}
);
aiController = ProtectorAI::new;
}};
//TODO: campaign boss
legion = new UnitType("legion"){{
health = 25000;
armor = 25;
health = 4500;
armor = 10;
hitSize = 25;
speed = 0.1f;
speed = 0.3f;
flying = false;
canBoost = false;
outlineColor = Color.valueOf("2b2f36");
range = 40f;

weapons.add(
new RepairBeamWeapon("legion-beam"){{
x = 4; y = 0;
mirror = true;
bullet = new BulletType(){{
maxRange = 40f;
}};
}}
);

abilities.add(new UnitResistanceAbility(legionnaire, 0.1f));

float angle = 0f;
for(int i = 0; i < 8; i++){
int units = 1;
for(int i = 0; i < units; i++){
float x = Mathf.cos(angle) * 32;
float y = Mathf.sin(angle) * 32;
abilities.add(new UnitSpawnAbility(UnitTypes.atrax, 600, x, y));
angle += Mathf.PI2 / 8;
abilities.add(new UnitSpawnAbility(legionnaire, 600, x, y));
angle += Mathf.PI2 / units;
}

//aiController = GroundBossAI::new;
}};
//TODO: campaign boss
citadel = new BossUnitType("citadel"){{
Expand Down
26 changes: 15 additions & 11 deletions core/src/fos/type/abilities/HackFieldAbility.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package fos.type.abilities;

import arc.*;
import arc.graphics.*;
import arc.math.*;
import fos.content.*;
import arc.graphics.Color;
import arc.math.Mathf;
import arc.scene.ui.layout.Table;
import fos.content.FOSStatuses;
import mindustry.content.StatusEffects;
import mindustry.entities.*;
import mindustry.entities.abilities.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.entities.Units;
import mindustry.entities.abilities.Ability;
import mindustry.gen.Unit;
import mindustry.graphics.Drawf;
import mindustry.type.StatusEffect;
import mindustry.world.meta.*;

import static mindustry.Vars.tilesize;

public class HackFieldAbility extends Ability {
public StatusEffect status;
Expand All @@ -22,8 +25,9 @@ public HackFieldAbility(StatusEffect status, float range, float chance) {
}

@Override
public String localized() {
return Core.bundle.format("ability.hackfield", range / 8f, FOSStatuses.hacked.emoji());
public void addStats(Table t) {
t.add("[lightgray]" + Stat.range.localized() + ": [white]" + range / tilesize + " " + StatUnit.blocks.localized());
t.row();
}

@Override
Expand Down
49 changes: 49 additions & 0 deletions core/src/fos/type/abilities/UnitResistanceAbility.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package fos.type.abilities;

import arc.graphics.g2d.*;
import arc.scene.ui.layout.Table;
import arc.util.Strings;
import fos.type.draw.FOSStats;
import mindustry.entities.abilities.Ability;
import mindustry.gen.*;
import mindustry.type.UnitType;
import mindustry.world.meta.*;

public class UnitResistanceAbility extends Ability {
public UnitType unitType;
public float resistance;

public UnitResistanceAbility(UnitType type, float resistance) {
this.unitType = type;
this.resistance = resistance;
}

@Override
public void addStats(Table t) {
t.add("[lightgray]" + Stat.unitType.localized() + ": [white]" + unitType.localizedName);
t.row();
t.add("[lightgray]" + FOSStats.unitDamageRes.localized() + ": [white]+" + Strings.autoFixed(resistance * 100, 1000) + StatUnit.percent.localized());
t.row();
}

@Override
public void draw(Unit unit) {
super.draw(unit);

int units = Groups.unit.count(u -> u.type == unitType);
for (int i = 0; i < units; i++) {
Draw.color(unit.team.color);
Draw.alpha(resistance);
Fill.circle(unit.x, unit.y, unit.hitSize);
Lines.stroke(2f);
Lines.circle(unit.x, unit.y, unit.hitSize);
}
}

@Override
public void update(Unit unit) {
// Apply damage resistance based on the amount of given unit type.
int units = Groups.unit.count(u -> u.type == unitType);
unit.healthMultiplier += resistance * units;
}
}
3 changes: 2 additions & 1 deletion core/src/fos/type/draw/FOSStats.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@

public class FOSStats {
public static final Stat
lifetime = new Stat("lifetime");
lifetime = new Stat("lifetime"),
unitDamageRes = new Stat("unitdamageres");
}

0 comments on commit 7b28e35

Please sign in to comment.