package com.flansmod.client.gui.teams; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; import org.lwjgl.opengl.GL11; import com.flansmod.client.ClientProxy; import com.flansmod.client.teams.ClientTeamsData; import com.flansmod.common.FlansMod; import com.flansmod.common.driveables.DriveableType; import com.flansmod.common.guns.AttachmentType; import com.flansmod.common.guns.EnumAttachmentType; import com.flansmod.common.guns.GunType; import com.flansmod.common.guns.ItemGun; import com.flansmod.common.guns.ItemShootable; import com.flansmod.common.guns.Paintjob; import com.flansmod.common.guns.ShootableType; import com.flansmod.common.teams.LoadoutPool; import com.flansmod.common.teams.PlayerLoadout; import com.flansmod.common.teams.TeamsManagerRanked; import com.flansmod.common.teams.LoadoutPool.LoadoutEntry; import com.flansmod.common.teams.LoadoutPool.LoadoutEntryInfoType; import com.flansmod.common.teams.LoadoutPool.LoadoutEntryPaintjob; import com.flansmod.common.teams.PlayerRankData; import com.flansmod.common.types.EnumPaintjobRarity; import com.flansmod.common.types.IFlanItem; import com.flansmod.common.types.IPaintableItem; import com.flansmod.common.types.InfoType; import com.flansmod.common.types.PaintableType; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; public class GuiEditLoadout extends GuiTeamsBase { /** The background image */ private static final ResourceLocation texture = new ResourceLocation("flansmod", "gui/LoadoutEditor.png"); private static final int WIDTH = 326, HEIGHT = 198; protected int selectedLoadout = 0; protected EnumLoadoutSlot selectedSlot = EnumLoadoutSlot.primary; protected int selectedCategory = 0; protected int scroller = 0; private PlayerLoadout previousLoadout = null; protected ArrayList<LoadoutEntry> availableComponents = new ArrayList<LoadoutEntry>(); private static final String[] WEAPON_COMPONENT_NAMES = new String[] { "Weapon", "Paint", "Scope", "Barrel", "Stock", "Grip", "Extra" }; private static final String[] NON_WEAPON_COMPONENT_NAMES = new String[] { "Item", "Paint" }; public GuiEditLoadout(int i) { super(); selectedLoadout = i; previousLoadout = ClientTeamsData.theRankData.loadouts[selectedLoadout].copy(); RecalculateAvailableEntries(); } @Override public void initGui() { super.initGui(); ScaledResolution scaledresolution = new ScaledResolution(mc); int w = scaledresolution.getScaledWidth(); int h = scaledresolution.getScaledHeight(); guiOriginX = w / 2 - WIDTH / 2; guiOriginY = h / 2 - HEIGHT / 2; buttonList.add(new GuiButton(0, width / 2 - WIDTH / 2 + 10, height / 2 - HEIGHT / 2 + 143, 82, 20, "Confirm")); buttonList.add(new GuiButton(1, width / 2 - WIDTH / 2 + 10, height / 2 - HEIGHT / 2 + 165, 82, 20, "Cancel")); } @Override protected void actionPerformed(GuiButton button) { if (button.id == 0) // Confirm { // Send data to server TeamsManagerRanked.ConfirmLoadoutChanges(); ClientTeamsData.OpenLandingPage(); } else if(button.id == 1) // Cancel { ClientTeamsData.theRankData.loadouts[selectedLoadout] = previousLoadout.copy(); ClientTeamsData.OpenLandingPage(); } } @Override public void drawScreen(int i, int j, float f) { ScaledResolution scaledresolution = new ScaledResolution(mc); int w = scaledresolution.getScaledWidth(); int h = scaledresolution.getScaledHeight(); drawDefaultBackground(); GL11.glEnable(3042 /*GL_BLEND*/); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); guiOriginX = w / 2 - WIDTH / 2; guiOriginY = h / 2 - HEIGHT / 2; //Bind the background texture mc.renderEngine.bindTexture(texture); int textureX = 512; int textureY = 256; PlayerRankData data = ClientTeamsData.theRankData; LoadoutPool pool = ClientTeamsData.currentPool; if(data == null || pool == null) { FlansMod.log("Problem in landing page!"); return; } //Draw the background drawModalRectWithCustomSizedTexture(guiOriginX, guiOriginY, 0, 0, WIDTH, HEIGHT, textureX, textureY); // Draw title text drawCenteredString(fontRendererObj, "Edit Loadout " + (selectedLoadout + 1), guiOriginX + WIDTH / 2, guiOriginY + 4, 0xffffff); // Draw loadout slots panel { mc.renderEngine.bindTexture(texture); drawModalRectWithCustomSizedTexture(guiOriginX + 70, guiOriginY + 32 + 22 * selectedSlot.ordinal(), 70, 203, 36, 22, textureX, textureY); drawCenteredString(fontRendererObj, "Loadout", guiOriginX + 51, guiOriginY + 18, 0xffffff); for(int n = 0; n < EnumLoadoutSlot.values().length; n++) { drawCenteredString(fontRendererObj, EnumLoadoutSlot.values()[n].name, guiOriginX + 39, guiOriginY + 38 + 22 * n, 0xffffff); ItemStack stack = data.loadouts[selectedLoadout].slots[n]; drawSlotInventory(stack, guiOriginX + 73, guiOriginY + 35 + 22 * n); } } // Draw slot panel { mc.renderEngine.bindTexture(texture); drawModalRectWithCustomSizedTexture(guiOriginX + 169, guiOriginY + 32 + 22 * selectedCategory, 70, 203, 36, 22, textureX, textureY); drawCenteredString(fontRendererObj, selectedSlot.name, guiOriginX + 150, guiOriginY + 18, 0xffffff); if(selectedSlot.isWeapon) { for(int n = 0; n < WEAPON_COMPONENT_NAMES.length; n++) { ItemStack stack = data.loadouts[selectedLoadout].slots[selectedSlot.ordinal()]; InfoType type = (stack != null && stack.getItem() instanceof IFlanItem) ? ((IFlanItem)stack.getItem()).getInfoType() : null; int numUnlocks = type != null ? data.GetNumUnlocksForType(type) : 0; if(n == 1 && type != null && numUnlocks > 0) { drawCenteredString(fontRendererObj, WEAPON_COMPONENT_NAMES[n] + " (" + numUnlocks + ")", guiOriginX + 138, guiOriginY + 38 + 22 * n, 0xffffff); } else drawCenteredString(fontRendererObj, WEAPON_COMPONENT_NAMES[n], guiOriginX + 138, guiOriginY + 38 + 22 * n, 0xffffff); switch(n) { case 0: // Main item { ItemStack copy = stack == null ? null : stack.copy(); if(copy != null) copy.setItemDamage(0); drawSlotInventory(copy, guiOriginX + 172, guiOriginY + 35 + 22 * n); break; } case 1: // Paint { drawSlotInventory(stack, guiOriginX + 172, guiOriginY + 35 + 22 * n); break; } default: { if(stack != null && stack.getTagCompound() != null) { NBTTagCompound attachmentTags = stack.getTagCompound().getCompoundTag("attachments"); if(attachmentTags != null) { ItemStack attachmentStack = null; switch(n) { case 2: attachmentStack = ItemStack.loadItemStackFromNBT(attachmentTags.getCompoundTag("scope")); break; case 3: attachmentStack = ItemStack.loadItemStackFromNBT(attachmentTags.getCompoundTag("barrel")); break; case 4: attachmentStack = ItemStack.loadItemStackFromNBT(attachmentTags.getCompoundTag("stock")); break; case 5: attachmentStack = ItemStack.loadItemStackFromNBT(attachmentTags.getCompoundTag("grip")); break; case 6: attachmentStack = ItemStack.loadItemStackFromNBT(attachmentTags.getCompoundTag("generic_0")); break; } drawSlotInventory(attachmentStack, guiOriginX + 172, guiOriginY + 35 + 22 * n); } } break; } } } } else { for(int n = 0; n < NON_WEAPON_COMPONENT_NAMES.length; n++) { drawCenteredString(fontRendererObj, NON_WEAPON_COMPONENT_NAMES[n], guiOriginX + 138, guiOriginY + 38 + 22 * n, 0xffffff); ItemStack stack = data.loadouts[selectedLoadout].slots[selectedSlot.ordinal()]; switch(n) { case 0: // Main item { ItemStack copy = stack == null ? null : stack.copy(); if(copy != null) copy.setItemDamage(0); drawSlotInventory(copy, guiOriginX + 172, guiOriginY + 35 + 22 * n); break; } case 1: // Paint { drawSlotInventory(stack, guiOriginX + 172, guiOriginY + 35 + 22 * n); break; } default: { break; } } } } } // Draw stats panel { String name = ""; ItemStack stack = data.loadouts[selectedLoadout].slots[selectedSlot.ordinal()]; if(stack != null) { name = stack.getDisplayName(); } drawCenteredString(fontRendererObj, name, guiOriginX + 262, guiOriginY + 18, 0xffffff); DrawGun(stack, guiOriginX + 254, guiOriginY + 48, 40f); drawCenteredString(fontRendererObj, "Damage", guiOriginX + 234, guiOriginY + 60, 0xffffff); drawCenteredString(fontRendererObj, "Accuracy", guiOriginX + 234, guiOriginY + 70, 0xffffff); drawCenteredString(fontRendererObj, "Ammo", guiOriginX + 234, guiOriginY + 80, 0xffffff); if(stack != null && stack.getItem() instanceof ItemGun) { GunType type = ((ItemGun)stack.getItem()).GetType(); LoadoutEntryInfoType entry = pool.GetLoadoutEntryForInfoType(selectedSlot.ordinal(), type); ShootableType mainAmmo = null; int numClips = 1; for(ItemStack extra : entry.extraItems) { if(extra != null && extra.getItem() instanceof ItemShootable) { mainAmmo = ((ItemShootable)extra.getItem()).type; numClips = extra.stackSize; break; } } if(mainAmmo != null) { drawCenteredString(fontRendererObj, String.format("%.0f", type.damage * mainAmmo.damageVsLiving * mainAmmo.numBullets), guiOriginX + 290, guiOriginY + 60, 0xffffff); drawCenteredString(fontRendererObj, String.format("%.0f", (50.0f - type.bulletSpread) * 2.0f), guiOriginX + 290, guiOriginY + 70, 0xffffff); drawCenteredString(fontRendererObj, String.format("%d", mainAmmo.roundsPerItem * numClips), guiOriginX + 290, guiOriginY + 80, 0xffffff); } } } // Draw selector panel { drawCenteredString(fontRendererObj, "Choose " + WEAPON_COMPONENT_NAMES[selectedCategory].toLowerCase(), guiOriginX + 262, guiOriginY + 95, 0xffffff); for(int row = 0; row < 4; row++) { for(int col = 0; col < 6; col++) { int index = scroller * 24 + row * 6 + col; if(index >= availableComponents.size()) { continue; } LoadoutEntry entry = availableComponents.get(index); if(entry instanceof LoadoutEntryInfoType) { drawSlotInventory(new ItemStack(((LoadoutEntryInfoType) entry).type.getItem()), guiOriginX + 209 + col * 18, guiOriginY + 107 + row * 18); } else if(entry instanceof LoadoutEntryPaintjob) { Paintjob paintjob = ((LoadoutEntryPaintjob)entry).paintjob; DrawRarityBackground(paintjob.rarity, guiOriginX + 209 + col * 18, guiOriginY + 107 + row * 18); drawSlotInventory(new ItemStack(paintjob.parent.getItem(), 1, paintjob.ID), guiOriginX + 209 + col * 18, guiOriginY + 107 + row * 18); } if(!entry.available) { mc.renderEngine.bindTexture(texture); GlStateManager.pushMatrix(); GlStateManager.translate(0.0f, 0.0f, 101.0f); drawModalRectWithCustomSizedTexture(guiOriginX + 209 + col * 18, guiOriginY + 107 + row * 18, 332, 161, 16, 16, textureX, textureY); if(entry.unlockLevel > 0) { drawCenteredString(fontRendererObj, "" + entry.unlockLevel, guiOriginX + 218 + col * 18, guiOriginY + 112 + row * 18, 0xffffff); } GlStateManager.popMatrix(); } } } } // Resets some GL modes to prevent screen going grey sometimes. Quick and easy hack. Thanks, stick. drawSlotInventory(new ItemStack(Items.stick), -50, -50); super.drawScreen(i, j, f); } private boolean IsInSquare(int clickX, int clickY, int x, int y, int w, int h) { return x <= clickX && clickX < x + w && y <= clickY && clickY < y + h; } @Override protected void mouseClicked(int i, int j, int k) throws IOException { super.mouseClicked(i, j, k); int x = i - guiOriginX; int y = j - guiOriginY; if (k == 0 || k == 1) { // Loadout slots panel for(int n = 0; n < EnumLoadoutSlot.values().length; n++) { if(IsInSquare(x, y, 70, 32 + 22 * n, 22, 22)) { selectedSlot = EnumLoadoutSlot.values()[n]; //if(!selectedSlot.isWeapon && selectedCategory > 2) selectedCategory = 0; RecalculateAvailableEntries(); } } // Slot panel if(selectedSlot.isWeapon) { for(int n = 0; n < WEAPON_COMPONENT_NAMES.length; n++) { if(IsInSquare(x, y, 169, 32 + 22 * n, 22, 22)) { selectedCategory = n; RecalculateAvailableEntries(); } } } else { for(int n = 0; n < NON_WEAPON_COMPONENT_NAMES.length; n++) { if(IsInSquare(x, y, 169, 32 + 22 * n, 22, 22)) { selectedCategory = n; RecalculateAvailableEntries(); } } } // Selector panel for(int row = 0; row < 4; row++) { for(int col = 0; col < 6; col++) { int index = scroller * 24 + row * 6 + col; if(index >= availableComponents.size()) continue; if(!availableComponents.get(index).available) continue; if(IsInSquare(x, y, 209 + col * 18, 107 + row * 18, 18, 18)) { LoadoutEntry entry = availableComponents.get(index); SelectItem(entry); } } } if(IsInSquare(x, y, 257, 179, 10, 10)) { SelectItem(null); } } } public void SelectItem(LoadoutEntry entry) { PlayerRankData data = ClientTeamsData.theRankData; LoadoutPool pool = ClientTeamsData.currentPool; switch(selectedCategory) { case 0: // Main item { if(entry instanceof LoadoutEntryInfoType) { data.loadouts[selectedLoadout].slots[selectedSlot.ordinal()] = new ItemStack(((LoadoutEntryInfoType) entry).type.getItem()); } else if(entry != null) { FlansMod.log("Loadout entry doesn't match for slot"); } break; } case 1: // Paint { if(entry instanceof LoadoutEntryPaintjob) { if(data.loadouts[selectedLoadout].slots[selectedSlot.ordinal()] != null) { data.loadouts[selectedLoadout].slots[selectedSlot.ordinal()].setItemDamage(((LoadoutEntryPaintjob) entry).paintjob.ID); } else FlansMod.log("Applying paintjob to null item!"); } else if(entry != null) { FlansMod.log("Loadout entry doesn't match slot"); } } default: // Attachments { if(entry instanceof LoadoutEntryInfoType || entry == null) { ItemStack stack = data.loadouts[selectedLoadout].slots[selectedSlot.ordinal()]; if(stack != null) { if(stack.getTagCompound() == null) { stack.setTagCompound(new NBTTagCompound()); } NBTTagCompound attachmentTags = stack.getTagCompound().getCompoundTag("attachments"); if(attachmentTags == null) { attachmentTags = new NBTTagCompound(); } NBTTagCompound ourTags = new NBTTagCompound(); if(entry != null) { ItemStack attachmentStack = new ItemStack(((LoadoutEntryInfoType) entry).type.getItem()); attachmentStack.writeToNBT(ourTags); } switch(selectedCategory) { case 2: attachmentTags.setTag("scope", ourTags); break; case 3: attachmentTags.setTag("barrel", ourTags); break; case 4: attachmentTags.setTag("stock", ourTags); break; case 5: attachmentTags.setTag("grip", ourTags); break; case 6: attachmentTags.setTag("generic_0", ourTags); break; } stack.getTagCompound().setTag("attachments", attachmentTags); } else FlansMod.log("Applying attachment to null item!"); } else FlansMod.log("Loadout entry doesn't match for slot"); } } } public class LoadoutComparator implements Comparator<LoadoutEntry> { @Override public int compare(LoadoutEntry a, LoadoutEntry b) { if(a.unlockLevel < b.unlockLevel) return -1; if(a.unlockLevel > b.unlockLevel) return 1; if(a instanceof LoadoutEntryPaintjob && b instanceof LoadoutEntryPaintjob) { if(((LoadoutEntryPaintjob)a).paintjob.rarity.ordinal() < ((LoadoutEntryPaintjob)b).paintjob.rarity.ordinal()) return -1; if(((LoadoutEntryPaintjob)a).paintjob.rarity.ordinal() > ((LoadoutEntryPaintjob)b).paintjob.rarity.ordinal()) return 1; } return 0; } } public void RecalculateAvailableEntries() { availableComponents.clear(); PlayerRankData data = ClientTeamsData.theRankData; LoadoutPool pool = ClientTeamsData.currentPool; ArrayList<LoadoutEntry> unlockedEntries = new ArrayList<LoadoutEntry>(); ArrayList<LoadoutEntry> lockedEntries = new ArrayList<LoadoutEntry>(); if(selectedCategory == 1) // Paint { ItemStack stack = data.loadouts[selectedLoadout].slots[selectedSlot.ordinal()]; if(stack != null && stack.getItem() instanceof IPaintableItem) { PaintableType type = ((IPaintableItem)stack.getItem()).GetPaintableType(); for(int i = 0; i < type.paintjobs.size(); i++) { LoadoutEntryPaintjob entry = new LoadoutEntryPaintjob(); entry.unlockLevel = 0; entry.paintjob = type.paintjobs.get(i); if(i == 0) { entry.available = true; } else { entry.available = TeamsManagerRanked.LocalPlayerOwnsUnlock(entry.paintjob.hashCode()); } if(entry.available) unlockedEntries.add(entry); else lockedEntries.add(entry); } } } else { for(LoadoutEntryInfoType entry : pool.unlocks[selectedSlot.ordinal()]) { switch(selectedCategory) { case 0: // Main item { if(entry.type instanceof AttachmentType) continue; break; } case 1: break; // Paint. Shouldn't even get here default: // Attachments. Check sub-type { // Check it is an attachment if(!(entry.type instanceof AttachmentType)) continue; // Check that the gun allows it GunType gunType = ((ItemGun)data.loadouts[selectedLoadout].slots[selectedSlot.ordinal()].getItem()).GetType(); if(!gunType.allowAllAttachments && !gunType.allowedAttachments.contains(entry.type)) continue; // And check that it is right for the slot EnumAttachmentType attachType = ((AttachmentType)entry.type).type; switch(selectedCategory) { case 2: if(attachType != EnumAttachmentType.sights) continue; else break; case 3: if(attachType != EnumAttachmentType.barrel) continue; else break; case 4: if(attachType != EnumAttachmentType.stock) continue; else break; case 5: if(attachType != EnumAttachmentType.grip) continue; else break; case 6: if(attachType != EnumAttachmentType.generic) continue; else break; } break; } } LoadoutEntryInfoType copy = new LoadoutEntryInfoType(); copy.type = entry.type; copy.unlockLevel = entry.unlockLevel; copy.available = data.currentLevel >= copy.unlockLevel; if(copy.available) unlockedEntries.add(copy); else lockedEntries.add(copy); } } unlockedEntries.sort(new LoadoutComparator()); lockedEntries.sort(new LoadoutComparator()); availableComponents.addAll(unlockedEntries); availableComponents.addAll(lockedEntries); } }