Finish the training game for now

This commit is contained in:
Sam 2017-06-23 01:43:11 +01:00
parent f22a091fa0
commit 65ebf41d4f
12 changed files with 289 additions and 99 deletions

View File

@ -6,7 +6,7 @@ import org.bukkit.Color;
public enum MobaRole
{
ASSASSIN("Assassin", Color.GRAY, ChatColor.DARK_GRAY),
ASSASSIN("Assassin", Color.GRAY, ChatColor.GRAY),
HUNTER("Hunter", Color.LIME, ChatColor.GREEN),
MAGE("Mage", Color.PURPLE, ChatColor.DARK_PURPLE),
WARRIOR("Warrior", Color.YELLOW, ChatColor.GOLD),

View File

@ -34,6 +34,11 @@ public class BossManager implements Listener
private void spawnBosses()
{
if (_dummyBosses)
{
return;
}
_host.CreatureAllowOverride = true;
WorldData worldData = _host.WorldData;
@ -41,18 +46,15 @@ public class BossManager implements Listener
// Spawn Team Withers
for (GameTeam team : _host.GetTeamList())
{
WitherBoss boss = new WitherBoss(_host, worldData.GetDataLocs(team.GetName().toUpperCase()).get(0), team, _dummyBosses);
WitherBoss boss = new WitherBoss(_host, worldData.GetDataLocs(team.GetName().toUpperCase()).get(0), team);
boss.setup();
_teamBosses.put(team, boss);
}
// Pumpkin King
if (!_dummyBosses)
{
_pumpkinBoss = new PumpkinBoss(_host, worldData.GetDataLocs("BLACK").get(0));
_pumpkinBoss.setup();
}
_host.CreatureAllowOverride = false;
}

View File

@ -21,7 +21,6 @@ import nautilus.game.arcade.game.games.moba.boss.MobaBoss;
import nautilus.game.arcade.game.games.moba.boss.wither.attack.BossAttackEarthquake;
import nautilus.game.arcade.game.games.moba.structure.tower.Tower;
import nautilus.game.arcade.game.games.moba.structure.tower.TowerDestroyEvent;
import nautilus.game.arcade.game.games.moba.training.MobaTraining;
import nautilus.game.arcade.game.games.moba.util.MobaUtil;
import org.bukkit.EntityEffect;
import org.bukkit.Location;
@ -46,17 +45,15 @@ public class WitherBoss extends MobaBoss
private static final int MIN_INFORM_TIME = (int) TimeUnit.SECONDS.toMillis(30);
private final GameTeam _team;
private final boolean _dummy;
private MobaAI _ai;
private DisguiseWither _disguise;
private boolean _damageable;
private long _lastInform;
public WitherBoss(Moba host, Location location, GameTeam team, boolean dummy)
public WitherBoss(Moba host, Location location, GameTeam team)
{
super(host, location);
_dummy = dummy;
_location.setYaw(UtilAlg.GetYaw(UtilAlg.getTrajectory(location, host.GetSpectatorLocation())));
_team = team;
@ -103,12 +100,6 @@ public class WitherBoss extends MobaBoss
@EventHandler(priority = EventPriority.LOWEST)
public void preDamage(CustomDamageEvent event)
{
if (_dummy)
{
event.SetCancelled("Dummy Boss");
return;
}
if (!event.GetDamageeEntity().equals(_entity) || MobaUtil.isInBoundary(_team, _entity, _location, getAi().getBoundaries(), event.GetDamagerPlayer(true)))
{
return;
@ -195,7 +186,7 @@ public class WitherBoss extends MobaBoss
{
Tower tower = event.getTower();
if (!_team.equals(tower.getOwner()) || _dummy)
if (!_team.equals(tower.getOwner()))
{
return;
}

View File

@ -43,15 +43,8 @@ public class MobaDamageManager implements Listener
return;
}
if (damageeTeam.equals(damagerTeam))
{
event.SetCancelled("Team Damage");
}
else
{
_host.getScoreboardModule().refreshAsSubject(damagee);
}
}
@EventHandler
public void preventTeamFire(ConditionApplyEvent event)

View File

@ -67,20 +67,6 @@ public class GoldManager implements Listener
});
}
@EventHandler
public void prepare(GameStateChangeEvent event)
{
if (event.GetState() != GameState.Prepare)
{
return;
}
for (Player player : _host.GetPlayers(true))
{
_playerGold.put(player, 0);
}
}
@EventHandler
public void playerQuit(PlayerQuitEvent event)
{
@ -146,7 +132,7 @@ public class GoldManager implements Listener
public int getGold(Player player)
{
return _playerGold.get(player);
return _playerGold.getOrDefault(player, 0);
}
public void addGold(Player player, int amount)
@ -156,6 +142,7 @@ public class GoldManager implements Listener
public void addGold(Player player, int amount, String reason)
{
_playerGold.putIfAbsent(player, 0);
_playerGold.put(player, _playerGold.get(player) + amount);
_host.getArcadeManager().GetStatsManager().incrementStat(player, _host.GetName() + ".GoldEarned", amount);
@ -168,12 +155,13 @@ public class GoldManager implements Listener
public void removeGold(Player player, int amount)
{
_playerGold.putIfAbsent(player, 0);
_playerGold.put(player, _playerGold.get(player) - amount);
}
public boolean hasGold(Player player, int amount)
{
return _playerGold.get(player) >= amount;
return _playerGold.getOrDefault(player, 0) >= amount;
}
}

View File

@ -262,6 +262,11 @@ public class HeroKit extends Kit
Manager.GetDisguise().disguise(disguise);
}
public SkinData getSkinData()
{
return _skin;
}
public boolean isVisible()
{
return _visible;

View File

@ -107,13 +107,13 @@ public class HeroSkill extends Perk
_item = new ItemBuilder(_item)
.setTitle((action != null ? C.cYellowB + action + C.cGray + " - " : "") + C.cGreenB + GetName())
.addLore(GetDesc())
.setLore(GetDesc())
.setUnbreakable(true)
.build();
_cooldownItem = new ItemBuilder(Material.INK_SACK, (byte) 8)
.setTitle(C.cRed + GetName())
.addLore(GetDesc())
.setLore(GetDesc())
.setUnbreakable(true)
.build();
}
@ -351,14 +351,19 @@ public class HeroSkill extends Perk
protected boolean isTeamDamage(LivingEntity damagee, LivingEntity damager)
{
if (!(damager instanceof Player))
if (damagee.equals(damager))
{
return true;
}
if (!(damager instanceof Player) || Manager.GetGame().DamageTeamSelf)
{
return false;
}
GameTeam team = Manager.GetGame().GetTeam((Player) damager);
return !Manager.GetGame().DamageTeamSelf && team != null && MobaUtil.isTeamEntity(damagee, team);
return team != null && MobaUtil.isTeamEntity(damagee, team);
}

View File

@ -4,11 +4,9 @@ import mineplex.core.common.Rank;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilAlg;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTime;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import nautilus.game.arcade.events.GamePrepareCountdownCommence;
import nautilus.game.arcade.game.DebugCommand;
import nautilus.game.arcade.game.GameTeam;
import nautilus.game.arcade.game.games.moba.Moba;
@ -33,7 +31,6 @@ import java.util.concurrent.TimeUnit;
public class MinionManager implements Listener
{
private static final int MINION_SPAWN_DELAY_TICKS = 40;
private static final long MINION_SPAWN_TIME = TimeUnit.SECONDS.toMillis(30);
private final Moba _host;
@ -48,6 +45,7 @@ public class MinionManager implements Listener
{
_host = host;
_waves = new HashSet<>();
_enabled = true;
host.registerDebugCommand(new DebugCommand("removeminions", Rank.DEVELOPER)
{
@ -64,12 +62,6 @@ public class MinionManager implements Listener
});
}
@EventHandler
public void gameCountdownCommence(GamePrepareCountdownCommence event)
{
UtilServer.runSyncLater(() -> setEnabled(!_enabled), MINION_SPAWN_DELAY_TICKS);
}
@EventHandler
public void spawnMinions(UpdateEvent event)
{
@ -80,6 +72,11 @@ public class MinionManager implements Listener
_lastWave = System.currentTimeMillis();
if (_path == null)
{
preparePath();
}
for (GameTeam team : _host.GetTeamList())
{
List<Location> path = new ArrayList<>(_path);
@ -130,18 +127,7 @@ public class MinionManager implements Listener
public void disableMinions()
{
// As when the game starts _enabled is inverted.
_enabled = true;
}
private void setEnabled(boolean enabled)
{
_enabled = enabled;
if (enabled)
{
preparePath();
}
_enabled = false;
}
public void unregisterWave(MinionWave wave)

View File

@ -112,8 +112,6 @@ public class PrepareSelection implements Listener, IPacketHandler
List<HeroKit> heroKits = _host.getKits(mobaPlayer.getRole());
ItemStack head = new ItemBuilder(Material.SKULL_ITEM, (byte) 2).build();
UtilServer.runSyncLater(() ->
{
for (Location location : spawns.values())
@ -126,10 +124,10 @@ public class PrepareSelection implements Listener, IPacketHandler
stand.setCustomNameVisible(true);
stand.setCustomName(C.cGreenB + kit.GetName());
stand.setArms(true);
stand.setHelmet(head);
// stand.setChestplate(buildColouredStack(Material.LEATHER_CHESTPLATE, role));
// stand.setLeggings(buildColouredStack(Material.LEATHER_LEGGINGS, role));
// stand.setBoots(buildColouredStack(Material.LEATHER_BOOTS, role));
stand.setHelmet(kit.getSkinData().getSkull());
stand.setChestplate(buildColouredStack(Material.LEATHER_CHESTPLATE, kit.getRole()));
stand.setLeggings(buildColouredStack(Material.LEATHER_LEGGINGS, kit.getRole()));
stand.setBoots(buildColouredStack(Material.LEATHER_BOOTS, kit.getRole()));
player.playSound(player.getLocation(), Sound.LEVEL_UP, 1, 0.5F);
UtilParticle.PlayParticle(ParticleType.CLOUD, location.clone().add(0, 2, 0), 0.5F, 0.5F, 0.5F, 0.01F, 20, ViewDist.LONG, player);

View File

@ -1,38 +1,45 @@
package nautilus.game.arcade.game.games.moba.training;
import mineplex.core.common.Rank;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilAlg;
import mineplex.core.common.util.UtilEnt;
import mineplex.core.common.util.UtilTime;
import mineplex.core.disguise.disguises.DisguiseWither;
import mineplex.core.hologram.Hologram;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.core.utils.UtilVariant;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import nautilus.game.arcade.ArcadeManager;
import nautilus.game.arcade.GameType;
import nautilus.game.arcade.events.GameStateChangeEvent;
import nautilus.game.arcade.events.PlayerStateChangeEvent;
import nautilus.game.arcade.game.DebugCommand;
import nautilus.game.arcade.game.GameTeam;
import nautilus.game.arcade.game.GameTeam.PlayerState;
import nautilus.game.arcade.game.games.moba.Moba;
import nautilus.game.arcade.game.games.moba.MobaPlayer;
import nautilus.game.arcade.game.games.moba.kit.HeroKit;
import nautilus.game.arcade.game.modules.CustomScoreboardModule;
import nautilus.game.arcade.game.modules.TrainingGameModule;
import nautilus.game.arcade.scoreboard.GameScoreboard;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Skeleton;
import org.bukkit.entity.Villager;
import org.bukkit.entity.Villager.Profession;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
public class MobaTraining extends Moba
@ -45,17 +52,63 @@ public class MobaTraining extends Moba
private static final String[][] HELP_HOLOGRAMS =
{
{
C.cYellow + "Welcome to " + C.cGreen + "Heroes of GWEN",
C.cYellow + "Here you can use learn about the game",
C.cYellow + "and test out the Heroes.",
C.cYellow + "If you know what you are doing you can type",
C.cGreen + "/skip" + C.cYellow + " to skip to the end of the tutorial."
},
{
C.cGreen + "Heroes of GWEN" + C.cYellow + " is a MOBA style game.",
C.cYellow + "There are " + C.cGreen + "4" + C.cYellow + " Roles of Heroes to play",
C.cYellow + "with many different Heroes within each role."
},
{
C.cYellow + "This is a " + C.cGreen + "Tower",
C.cYellow + "You need to destroy these in order to be able",
C.cYellow + "to attack the other team's " + C.cGreen + "Wither" + C.cYellow + " to win the game."
},
{
C.cYellow + "This is a " + C.cGreen + "Beacon",
C.cYellow + "You can capture these for your team.",
C.cYellow + "Capturing and holding these increases the amount",
C.cYellow + "of " + C.cGold + "Gold" + C.cYellow + " your team earns."
},
{
C.cYellow + "The is the " + C.cDRedB + "Pumpkin King",
C.cYellow + "He spawns at " + C.cGreen + "10 minutes" + C.cYellow + " into the game.",
C.cYellow + "The team that kills him will be given increased",
C.cYellow + "regeneration and damage."
},
{
C.cYellow + "Once all of the enemy's towers are destroyed",
C.cYellow + "your team can attack their " + C.cGreen + "Wither",
C.cYellow + "Once the Wither is killed the game is over!"
},
{
C.cGreen + "Minions" + C.cYellow + " spawn for both teams periodically",
C.cYellow + "and make their way to each other's bases.",
C.cYellow + "They will fight each other and help destroy enemy Towers."
},
{
C.cYellow + "With the " + C.cGold + "Gold" + C.cYellow + "you earn you can",
C.cYellow + "spend it on upgrades for your weapons and armor.",
C.cYellow + "You can do this via the gold ingot in your inventory",
C.cYellow + "during the game or by clicking on the Villager."
},
{
C.cYellow + "Now you know the basics",
C.cYellow + "Click on this NPC to select a Hero",
C.cYellow + "to try out!"
}
};
private static final long GAME_TIME = TimeUnit.HOURS.toMillis(3);
private static final int GOLD = 100000;
private Location _borderA;
private Location _borderB;
private Location _selectKit;
private LivingEntity _selectKitEntity;
private Function<Player, Boolean> _safeFunction = player -> UtilAlg.inBoundingBox(player.getLocation(), _borderA, _borderB);
private Function<Player, GameTeam> _teamFunction = player -> GetTeam(ChatColor.YELLOW);
private final Set<LivingEntity> _entities = new HashSet<>();
@ -64,10 +117,13 @@ public class MobaTraining extends Moba
super(manager, GameType.MOBATraining, DESCRIPTION);
DamageTeamSelf = true;
DamageFall = false;
DeathOut = false;
DeathSpectateSecs = 0;
PrepareTime = 500;
GiveClock = false;
HideTeamSheep = true;
HungerSet = 20;
// Prevent the wither from being damaged as well as to not spawn the pumpkin king
_boss.setDummyBosses(true);
@ -75,11 +131,13 @@ public class MobaTraining extends Moba
// Disable minions
_minion.disableMinions();
Function<Player, Boolean> safeFunction = player -> UtilAlg.inBoundingBox(player.getLocation(), _borderA, _borderB);
Function<Player, GameTeam> teamFunction = player -> GetTeam(ChatColor.GRAY);
new TrainingGameModule()
.setGiveReturnToSpawn(false)
.setSkillFunction(_safeFunction)
.setDamageFunction(_safeFunction)
.setTeamFunction(_teamFunction)
.setSkillFunction(safeFunction)
.setDamageFunction(safeFunction)
.setTeamFunction(teamFunction)
.register(this);
new CustomScoreboardModule()
@ -128,6 +186,18 @@ public class MobaTraining extends Moba
.setUnderName((perspective, subject) ->
(int) (Math.ceil(subject.getHealth() / 2D)))
.register(this);
registerDebugCommand(new DebugCommand("skip", Rank.ALL)
{
@Override
public void Execute(Player caller, String[] args)
{
if (!safeFunction.apply(caller))
{
caller.teleport(GetTeam(ChatColor.YELLOW).GetSpawn());
}
}
});
}
private void write(Player player, GameScoreboard scoreboard)
@ -140,7 +210,7 @@ public class MobaTraining extends Moba
scoreboard.writeNewLine();
scoreboard.write(C.cYellowB + "Hero");
scoreboard.write(mobaPlayer.getKit().GetName() + " (" + mobaPlayer.getRole().getChatColor() + mobaPlayer.getRole().getName() + C.cWhite + ")");
scoreboard.write(mobaPlayer.getKit().GetName() + " (" + mobaPlayer.getRole().getName() + C.cWhite + ")");
}
scoreboard.writeNewLine();
@ -162,6 +232,8 @@ public class MobaTraining extends Moba
scoreboard.write(C.cYellowB + "Time");
scoreboard.write(UtilTime.MakeStr(System.currentTimeMillis() - GetStateTime()));
scoreboard.writeNewLine();
}
@Override
@ -175,6 +247,7 @@ public class MobaTraining extends Moba
_borderB = locations.get(1);
_selectKit = WorldData.GetCustomLocs("SELECT_KIT").get(0);
SpectatorSpawn = _selectKit;
}
@EventHandler
@ -195,9 +268,10 @@ public class MobaTraining extends Moba
location.setYaw(UtilAlg.GetYaw(UtilAlg.getTrajectory(location, _selectKit)));
}
Location center = WorldData.GetCustomLocs("CENTER").get(0);
for (Location location : WorldData.GetDataLocs("LIME"))
{
location.setYaw(UtilAlg.GetYaw(UtilAlg.getTrajectory(location, SpectatorSpawn)));
location.setYaw(UtilAlg.GetYaw(UtilAlg.getTrajectory(location, center)));
}
}
@ -208,19 +282,54 @@ public class MobaTraining extends Moba
{
return;
}
GameTeam players = GetTeam(ChatColor.GRAY);
{
GameTeam players = GetTeam(ChatColor.RED);
players.SetColor(ChatColor.GRAY);
players.SetName("Players");
players.setDisplayName(C.cYellow + "Players");
players.setDisplayName(C.cYellowB + "Players");
}
{
GameTeam players = GetTeam(ChatColor.GREEN);
players.SetColor(ChatColor.YELLOW);
players.SetName("Players");
players.setDisplayName(C.cYellowB + "Players");
}
}
@Override
public GameTeam ChooseTeam(Player player)
{
return GetTeam(ChatColor.GRAY);
}
@Override
public void EndCheck()
{
if (!IsLive())
{
return;
}
if (UtilTime.elapsed(GetStateTime(), GAME_TIME))
{
SetState(GameState.Dead);
}
}
@EventHandler
public void giveGold(PlayerStateChangeEvent event)
public void giveGold(UpdateEvent event)
{
if (event.GetState() == PlayerState.IN)
if (event.getType() != UpdateType.SEC)
{
_goldManager.addGold(event.GetPlayer(), GOLD);
return;
}
for (Player player : GetPlayers(true))
{
if (_goldManager.getGold(player) < 100)
{
_goldManager.addGold(player, GOLD);
}
}
}
@ -261,10 +370,44 @@ public class MobaTraining extends Moba
if (_selectKitEntity != null && _selectKitEntity.equals(event.GetDamageeEntity()))
{
teleportIntoArena(event.GetDamagerPlayer(false));
openMenu(event.GetDamagerPlayer(false));
}
}
@EventHandler
public void entityInteract(PlayerInteractAtEntityEvent event)
{
if (_selectKitEntity != null && event.getRightClicked().equals(_selectKitEntity))
{
openMenu(event.getPlayer());
}
}
@EventHandler
public void updateEntityLocation(UpdateEvent event)
{
if (event.getType() != UpdateType.TICK)
{
return;
}
for (LivingEntity entity : _entities)
{
Location location = entity.getLocation();
((CraftEntity) entity).getHandle().setPosition(location.getX(), location.getY(), location.getZ());
}
}
private void openMenu(Player player)
{
if (player == null)
{
return;
}
new SelectKitMenu(Manager).open(player);
}
private void spawnHelpText()
{
Map<String, Location> locationMap = getLocationStartsWith("HELP");
@ -272,9 +415,9 @@ public class MobaTraining extends Moba
for (Entry<String, Location> entry : locationMap.entrySet())
{
String[] split = entry.getKey().split(" ");
String index = split[0];
String index = split[1];
int indexInt = Integer.parseInt(index);
String[] display = HELP_HOLOGRAMS[indexInt];
String[] display = HELP_HOLOGRAMS[indexInt - 1];
new Hologram(Manager.getHologramManager(), entry.getValue(), true, display).start();
}
@ -308,29 +451,32 @@ public class MobaTraining extends Moba
{
Location location = WorldData.GetCustomLocs("DUMMY_SHOP").get(0);
Villager villager = location.getWorld().spawn(location, Villager.class);
villager.setProfession(Profession.LIBRARIAN);
villager.setCustomName(C.cGoldB + "Gold Upgrades");
_entities.add(villager);
}
}
private void spawnNPCs()
{
Villager villager = WorldData.World.spawn(_selectKit, Villager.class);
villager.setCustomName(C.cYellow + "Select A Hero");
UtilEnt.CreatureLook(villager, WorldData.GetDataLocs("LIME").get(0));
villager.setCustomName(C.cYellowB + "Select A Hero");
UtilEnt.CreatureLook(villager, GetTeam(ChatColor.YELLOW).GetSpawns().get(0));
_entities.add(villager);
_selectKitEntity = villager;
}
private void teleportIntoArena(Player player)
public void teleportIntoArena(Player player, HeroKit kit)
{
if (player == null)
if (!kit.equals(GetKit(player)))
{
return;
_shop.clearPurchases(player);
}
player.teleport(UtilAlg.Random(WorldData.GetDataLocs("LIME")));
SetPlayerTeam(player, GetTeam(ChatColor.YELLOW), true);
SetKit(player, kit, true);
}
}

View File

@ -0,0 +1,70 @@
package nautilus.game.arcade.game.games.moba.training;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilUI;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.menu.Button;
import mineplex.core.menu.Menu;
import nautilus.game.arcade.ArcadeManager;
import nautilus.game.arcade.game.games.moba.kit.HeroKit;
import nautilus.game.arcade.kit.Perk;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class SelectKitMenu extends Menu<ArcadeManager>
{
public SelectKitMenu(ArcadeManager plugin)
{
super("Select A Hero", plugin);
}
@Override
protected Button[] setUp(Player player)
{
MobaTraining moba = (MobaTraining) getPlugin().GetGame();
Button[] buttons = new Button[36];
int[] slots = UtilUI.getIndicesFor(moba.GetKits().length, 1);
int i = 0;
for (int slot : slots)
{
HeroKit kit = (HeroKit) moba.GetKits()[i++];
ItemBuilder builder = new ItemBuilder(kit.getSkinData().getSkull());
builder.setTitle(C.cGreen + kit.GetName());
builder.addLore("", "Skills:");
for (Perk perk : kit.GetPerks())
{
builder.addLore(C.cWhite + " - " + C.cYellow + perk.GetName());
}
builder.addLore("", C.cGreen + "Click to join the arena with this kit!");
buttons[slot] = new SelectKitButton(builder.build(), getPlugin(), kit);
}
return buttons;
}
private class SelectKitButton extends Button<ArcadeManager>
{
private final HeroKit _kit;
private SelectKitButton(ItemStack item, ArcadeManager plugin, HeroKit kit)
{
super(item, plugin);
_kit = kit;
}
@Override
public void onClick(Player player, ClickType clickType)
{
((MobaTraining) getPlugin().GetGame()).teleportIntoArena(player, _kit);
}
}
}

View File

@ -62,6 +62,12 @@ public class TrainingGameModule extends Module
List<Location> locations = getGame().WorldData.GetDataLocs("PURPLE");
int i = 0;
if (locations.isEmpty())
{
return;
}
getGame().CreatureAllowOverride = true;
for (Kit kit : getGame().GetKits())