diff --git a/src/main/java/icbm/classic/Settings.java b/src/main/java/icbm/classic/Settings.java
index fc990972c..c9ae7cd09 100644
--- a/src/main/java/icbm/classic/Settings.java
+++ b/src/main/java/icbm/classic/Settings.java
@@ -1,5 +1,6 @@
package icbm.classic;
+import com.builtbroken.mc.core.Engine;
import cpw.mods.fml.common.ModMetadata;
import net.minecraftforge.common.config.Configuration;
@@ -26,6 +27,8 @@ public class Settings
public static boolean POLLUTIVE_NUCLEAR = true;
+ public static boolean FORCE_ENABLE_NIGHTMARE = Engine.runningAsDev;
+
public static void initiate(Configuration configuration)
{
@@ -37,6 +40,8 @@ public static void initiate(Configuration configuration)
MAX_ROCKET_LAUCNHER_TIER = configuration.get(Configuration.CATEGORY_GENERAL, "Limits the max missile tier for rocket launcher item", MAX_ROCKET_LAUCNHER_TIER).getInt(MAX_ROCKET_LAUCNHER_TIER);
POLLUTIVE_NUCLEAR = configuration.get(Configuration.CATEGORY_GENERAL, "Pollutive Nuclear", POLLUTIVE_NUCLEAR).getBoolean(POLLUTIVE_NUCLEAR);
+
+ FORCE_ENABLE_NIGHTMARE = configuration.get(Configuration.CATEGORY_GENERAL, "Force_Enable_Nightmare", false).getBoolean(false);
}
public static void setModMetadata(String id, String name, ModMetadata metadata)
diff --git a/src/main/java/icbm/classic/client/render/RenderMissile.java b/src/main/java/icbm/classic/client/render/RenderMissile.java
index 491aa4e6a..57399d261 100644
--- a/src/main/java/icbm/classic/client/render/RenderMissile.java
+++ b/src/main/java/icbm/classic/client/render/RenderMissile.java
@@ -1,5 +1,6 @@
package icbm.classic.client.render;
+import com.builtbroken.mc.lib.render.RenderUtility;
import com.builtbroken.mc.lib.render.model.loader.EngineModelLoader;
import cpw.mods.fml.client.FMLClientHandler;
import cpw.mods.fml.relauncher.Side;
@@ -8,10 +9,14 @@
import icbm.classic.content.entity.EntityMissile;
import icbm.classic.content.explosive.Explosive;
import icbm.classic.content.explosive.Explosives;
+import icbm.classic.content.explosive.ex.ExNightmare;
import icbm.classic.content.explosive.ex.Explosion;
import net.minecraft.client.renderer.entity.Render;
+import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.Entity;
+import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
+import net.minecraft.util.IIcon;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.IItemRenderer;
import net.minecraftforge.client.model.IModelCustom;
@@ -51,11 +56,11 @@ public void doRender(Entity entity, double x, double y, double z, float f, float
GL11.glRotatef(entityMissile.prevRotationYaw + (entityMissile.rotationYaw - entityMissile.prevRotationYaw) * f1 - 90.0F, 0.0F, 1.0F, 0.0F);
float pitch = entityMissile.prevRotationPitch + (entityMissile.rotationPitch - entityMissile.prevRotationPitch) * f1 - 90;
GL11.glRotatef(pitch, 0.0F, 0.0F, 1.0F);
- if (missile.missileModelPath.contains("missiles"))
+ if (missile.missileModelPath != null && missile.missileModelPath.contains("missiles"))
{
GL11.glScalef(0.00625f, 0.00625f, 0.00625f);
}
- else
+ else if (!(missile instanceof ExNightmare))
{
GL11.glScalef(0.07f, 0.07f, 0.07f);
}
@@ -66,7 +71,26 @@ public void doRender(Entity entity, double x, double y, double z, float f, float
public static void renderMissile(Explosion missile)
{
- if (missile.getMissileModel() != null)
+ if (missile instanceof ExNightmare)
+ {
+ //Render body
+ GL11.glPushMatrix();
+ GL11.glScalef(0.00625f, 0.00625f, 0.00625f);
+ FMLClientHandler.instance().getClient().renderEngine.bindTexture(((Explosion) Explosives.ANVIL.handler).getMissileResource());
+ TIER1_BASE.renderAll();
+ GL11.glPopMatrix();
+
+ //Render head
+ GL11.glPushMatrix();
+ GL11.glScalef(0.5f, 0.5f, 0.5f);
+ GL11.glTranslated(-0.5, 3.8, -0.5);
+
+ FMLClientHandler.instance().getClient().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
+ IIcon side = Blocks.lit_pumpkin.getIcon(1, 2);
+ RenderUtility.renderCubeWithOverrides(0, 0, 0, 1, 1, 1, Blocks.lit_pumpkin, new IIcon[]{side, Blocks.lit_pumpkin.getIcon(2, 2), side, side, side, side}, 0);
+ GL11.glPopMatrix();
+ }
+ else if (missile.getMissileModel() != null)
{
if (missile.missileModelPath.contains("missiles"))
{
@@ -128,16 +152,18 @@ public void renderItem(IItemRenderer.ItemRenderType type, ItemStack item, Object
if (ex.handler instanceof Explosion)
{
Explosion missile = (Explosion) ex.handler;
+ final boolean doMissileSizeFix = missile.missileModelPath != null && missile.missileModelPath.contains("missiles");
+
float yaw = 0;
float pitch = -90;
- float scale = missile.missileModelPath.contains("missiles") ? 0.00625f : 0.7f;
+ float scale = doMissileSizeFix ? 0.00625f : 0.7f;
switch (type)
{
case INVENTORY:
- scale = missile.missileModelPath.contains("missiles") ? 0.0035f : 0.5f;
+ scale = doMissileSizeFix ? 0.0035f : 0.5f;
if (missile.getTier() == 2 || !missile.hasBlockForm())
{
diff --git a/src/main/java/icbm/classic/content/explosive/Explosives.java b/src/main/java/icbm/classic/content/explosive/Explosives.java
index 9deedb8e0..e4b74639b 100644
--- a/src/main/java/icbm/classic/content/explosive/Explosives.java
+++ b/src/main/java/icbm/classic/content/explosive/Explosives.java
@@ -45,7 +45,9 @@ public enum Explosives
MISSILE_HOMING(new MissileHoming()),
MISSILE_ANTI(new MissileAnti()),
MISSILE_CLUSTER(new MissileCluster("cluster", 2)),
- MISSILE_CLUSTER_NUKE(new MissileNuclearCluster());
+ MISSILE_CLUSTER_NUKE(new MissileNuclearCluster()),
+
+ NIGHTMARE(new ExNightmare());
public final Explosive handler;
diff --git a/src/main/java/icbm/classic/content/explosive/blast/BlastNightmare.java b/src/main/java/icbm/classic/content/explosive/blast/BlastNightmare.java
new file mode 100644
index 000000000..3beb8e32d
--- /dev/null
+++ b/src/main/java/icbm/classic/content/explosive/blast/BlastNightmare.java
@@ -0,0 +1,123 @@
+package icbm.classic.content.explosive.blast;
+
+import com.builtbroken.mc.framework.thread.delay.DelayedAction;
+import com.builtbroken.mc.framework.thread.delay.DelayedActionHandler;
+import com.builtbroken.mc.imp.transform.vector.Pos;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.monster.EntityZombie;
+import net.minecraft.entity.passive.EntityBat;
+import net.minecraft.world.World;
+
+/**
+ * @see License for what you can and can't do with the code.
+ * Created by Dark(DarkGuardsman, Robert) on 10/2/2017.
+ */
+public class BlastNightmare extends Blast
+{
+ public BlastNightmare(World world, Entity entity, double x, double y, double z, float size)
+ {
+ super(world, entity, x, y, z, size);
+ }
+
+ @Override
+ protected void doExplode()
+ {
+ final Pos center = new Pos(this);
+ final int size = (int) this.explosionSize;
+
+ //Spawn bats
+ final int batCount = (size / 2) + oldWorld().rand.nextInt(size);
+ for (int i = 0; i < batCount; i++)
+ {
+ //TODO make new bat mob that can attack players and has a pumpkin for a head, have it shoot flames out behind it as well
+ //TODO distribute using missile miss spread code
+ EntityBat bat = new EntityBat(oldWorld());
+ DelayedSpawn delay = new DelayedSpawn(oldWorld(), center, bat, 10, (i + oldWorld().rand.nextInt(size)) * 20); //reduce bats spawning at same time
+ DelayedActionHandler.add(delay);
+ }
+
+ //Spawn monsters
+ final int monsterCount = (size / 2) + oldWorld().rand.nextInt(size);
+ for (int i = 0; i < monsterCount; i++)
+ {
+ //TODO distribute using missile miss spread code
+ //TODO materialize zombies as ghosts so they can walk through walls in order to find an air pocket to spawn
+ EntityZombie zombie = new EntityZombie(oldWorld());
+ DelayedSpawn delay = new DelayedSpawn(oldWorld(), center, zombie, 10, (i + oldWorld().rand.nextInt(size * 2)) * 20); //reduce bats spawning at same time
+ DelayedActionHandler.add(delay);
+ }
+
+ //TODO play deathly scream
+ //TODO replace torches with bone torch set for random halloween colors and low light levels
+ //TODO have monsters move towards players
+ }
+
+ public static class DelayedSpawn extends DelayedAction
+ {
+ Pos center;
+ Entity entity;
+ int range;
+
+ int spawnAttemptLimit = 10;
+ private int spawnAttempts;
+
+ public DelayedSpawn(World world, Pos center, Entity entity, int range, int ticks)
+ {
+ super(world, ticks);
+ this.center = center;
+ this.entity = entity;
+ this.range = range;
+ }
+
+ @Override
+ public boolean trigger()
+ {
+ if (entity != null)
+ {
+ final float width = entity.width;
+ final float height = entity.height;
+
+ //Code can only handle entities roughly 1 block wide
+ if (width <= 1.1)
+ {
+ spawnAttempts++;
+
+ //Get random spawn point
+ Pos spawnPoint = center.addRandom(world.rand, range);
+ if (!spawnPoint.isAirBlock(world))
+ {
+ spawnPoint = spawnPoint.add(0, 1, 0);
+ }
+
+ //Ensure point is in air and is on ground
+ if (spawnPoint.isAirBlock(world) && !spawnPoint.sub(0, 1, 0).isAirBlock(world))
+ {
+ //Do height check
+ if (height > 1)
+ {
+ int heightChecks = (int) Math.ceil(height - 1);
+ for (int i = 0; i < heightChecks; i++)
+ {
+ if (!spawnPoint.add(0, i, 0).isAirBlock(world))
+ {
+ return spawnAttempts >= spawnAttemptLimit;
+ }
+ }
+ }
+ //Set data
+ entity.setPosition(spawnPoint.xi() + 0.5, spawnPoint.yi() + 0.5, spawnPoint.zi() + 0.5);
+ //TODO rotate to face closest player
+
+ //Spawn
+ world.spawnEntityInWorld(entity);
+ return true; //done
+ }
+
+ return spawnAttempts >= spawnAttemptLimit;
+ }
+ }
+
+ return true; //done due to bad data
+ }
+ }
+}
diff --git a/src/main/java/icbm/classic/content/explosive/ex/ExNightmare.java b/src/main/java/icbm/classic/content/explosive/ex/ExNightmare.java
new file mode 100644
index 000000000..7ef58cd55
--- /dev/null
+++ b/src/main/java/icbm/classic/content/explosive/ex/ExNightmare.java
@@ -0,0 +1,40 @@
+package icbm.classic.content.explosive.ex;
+
+import com.builtbroken.mc.api.edit.IWorldChangeAction;
+import com.builtbroken.mc.api.event.TriggerCause;
+import icbm.classic.content.explosive.blast.BlastNightmare;
+import net.minecraft.entity.Entity;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.world.World;
+
+/**
+ * Holiday event missile
+ *
+ * @see License for what you can and can't do with the code.
+ * Created by Dark(DarkGuardsman, Robert) on 10/2/2017.
+ */
+public class ExNightmare extends Explosion
+{
+ public ExNightmare()
+ {
+ super("nightmare", 1);
+ hasGrenade = false;
+ }
+
+ @Override
+ public void init()
+ {
+ }
+
+ @Override
+ public void doCreateExplosion(World world, double x, double y, double z, Entity entity)
+ {
+ new BlastNightmare(world, entity, x, y, z, 50).explode();
+ }
+
+ @Override
+ public IWorldChangeAction createBlastForTrigger(World world, double x, double y, double z, TriggerCause triggerCause, double size, NBTTagCompound tag)
+ {
+ return null;
+ }
+}
diff --git a/src/main/java/icbm/classic/content/explosive/ex/Explosion.java b/src/main/java/icbm/classic/content/explosive/ex/Explosion.java
index 66e3e2890..730c3f8af 100644
--- a/src/main/java/icbm/classic/content/explosive/ex/Explosion.java
+++ b/src/main/java/icbm/classic/content/explosive/ex/Explosion.java
@@ -65,18 +65,22 @@ public ResourceLocation getMissileResource()
@Override
public IModelCustom getMissileModel()
{
- try
+ if(missileModelPath != null)
{
- if (this.model == null)
+ try
{
- model = EngineModelLoader.loadModel(new ResourceLocation(ICBMClassic.DOMAIN, "models/" + this.missileModelPath));
+ if (this.model == null)
+ {
+ model = EngineModelLoader.loadModel(new ResourceLocation(ICBMClassic.DOMAIN, "models/" + this.missileModelPath));
+ }
+ }
+ catch (Exception e)
+ {
+ ICBMClassic.INSTANCE.logger().error("Unexpected error while loading missile Model[ " + this.missileModelPath + "]", e);
}
- }
- catch (Exception e)
- {
- ICBMClassic.INSTANCE.logger().error("Unexpected error while loading missile Model[ " + this.missileModelPath + "]", e);
- }
- return model;
+ return model;
+ }
+ return null;
}
}
diff --git a/src/main/java/icbm/classic/content/items/ItemMissile.java b/src/main/java/icbm/classic/content/items/ItemMissile.java
index f3b8f24ab..bacb9da05 100644
--- a/src/main/java/icbm/classic/content/items/ItemMissile.java
+++ b/src/main/java/icbm/classic/content/items/ItemMissile.java
@@ -1,8 +1,11 @@
package icbm.classic.content.items;
+import com.builtbroken.mc.lib.Holiday;
import com.builtbroken.mc.lib.helper.LanguageUtility;
import icbm.classic.ICBMClassic;
+import icbm.classic.Settings;
import icbm.classic.content.explosive.Explosives;
+import icbm.classic.content.explosive.ex.ExNightmare;
import icbm.classic.content.explosive.tile.ItemBlockExplosive;
import icbm.classic.prefab.item.ItemICBMBase;
import net.minecraft.creativetab.CreativeTabs;
@@ -43,11 +46,11 @@ public String getUnlocalizedName()
@Override
public void getSubItems(Item par1, CreativeTabs par2CreativeTabs, List par3List)
{
- for (Explosives zhaPin : Explosives.values())
+ for (Explosives explosive : Explosives.values())
{
- if (zhaPin.handler.hasMissileForm())
+ if (explosive.handler.hasMissileForm() && (!(explosive.handler instanceof ExNightmare) || Settings.FORCE_ENABLE_NIGHTMARE || Holiday.isHalloween()))
{
- par3List.add(new ItemStack(par1, 1, zhaPin.ordinal()));
+ par3List.add(new ItemStack(par1, 1, explosive.ordinal()));
}
}
}
diff --git a/src/main/java/icbm/classic/content/machines/launcher/base/TileLauncherBaseClient.java b/src/main/java/icbm/classic/content/machines/launcher/base/TileLauncherBaseClient.java
index dfa19ff44..32b17653c 100644
--- a/src/main/java/icbm/classic/content/machines/launcher/base/TileLauncherBaseClient.java
+++ b/src/main/java/icbm/classic/content/machines/launcher/base/TileLauncherBaseClient.java
@@ -101,6 +101,7 @@ else if (getTier() == 2)
}
GL11.glPopMatrix();
+ //TODO move to missile render class
if (cachedMissileStack != null)
{
GL11.glPushMatrix();
@@ -111,11 +112,11 @@ else if (getTier() == 2)
Explosives e = Explosives.get(cachedMissileStack.getItemDamage());
Explosion missile = e == null ? (Explosion) Explosives.CONDENSED.handler : (Explosion) e.handler;
- if (missile.missileModelPath.contains("missiles"))
+ if (missile.missileModelPath != null && missile.missileModelPath.contains("missiles"))
{
GL11.glScalef(0.00625f, 0.00625f, 0.00625f);
}
- else
+ else if(e != Explosives.NIGHTMARE)
{
GL11.glScalef(0.05f, 0.05f, 0.05f);
}