001package com.fs.starfarer.api.impl.campaign.terrain; 002 003import java.awt.Color; 004 005import org.lwjgl.opengl.GL11; 006import org.lwjgl.util.vector.Vector2f; 007 008import com.fs.starfarer.api.Global; 009import com.fs.starfarer.api.campaign.SectorEntityToken; 010import com.fs.starfarer.api.graphics.SpriteAPI; 011import com.fs.starfarer.api.impl.campaign.ids.Factions; 012import com.fs.starfarer.api.impl.campaign.ids.Tags; 013import com.fs.starfarer.api.util.FaderUtil; 014import com.fs.starfarer.api.util.Misc; 015 016public class DebrisPiece { 017 018 public static final float CELL_SIZE = 32; 019 020 protected SpriteAPI shadowMask; 021 protected SpriteAPI sprite; 022 protected SpriteAPI glow; 023 024 protected float width; 025 protected float height; 026 protected float radius; 027 028 protected DebrisFieldTerrainPlugin field; 029 030 protected Vector2f loc = new Vector2f(); 031 protected Vector2f vel = new Vector2f(); 032 protected float timeLeft = 0f; 033 protected float facing = 0f; 034 protected float angVel = 0f; 035 protected FaderUtil fader = new FaderUtil(0f, 0.2f, 0.2f); // days 036 037 protected FaderUtil glowBounce; 038 protected FaderUtil glowFader = new FaderUtil(0f, 0.1f, 0.1f); 039 040 //protected IntervalUtil indCheck = new IntervalUtil(0.0f, 0.2f); 041 protected FaderUtil indFader = new FaderUtil(0f, 0.3f, 0.8f, false, true); 042 043 //protected float indProb = 0.05f; 044 045 public DebrisPiece(DebrisFieldTerrainPlugin field) { 046 this.field = field; 047 048 glowBounce = new FaderUtil(0f, 0.1f + (float) Math.random() * 0.1f, 0.1f + (float) Math.random() * 0.1f); // days 049 glowBounce.setBounce(true, true); 050 glowBounce.fadeIn(); 051 052 if ((float) Math.random() < field.getPieceGlowProbability()) { 053 glowFader.fadeIn(); 054 } 055 056 sprite = Global.getSettings().getSprite("terrain", "debrisFieldSheet"); 057 glow = Global.getSettings().getSprite("terrain", "debrisFieldGlowSheet"); 058 059 060 float sizeRangeMult = 0.5f + 0.5f * field.params.density; 061 this.width = field.getParams().minSize + 062 (float) Math.random() * sizeRangeMult * (field.getParams().maxSize - field.getParams().minSize); 063 this.height = width; 064 065 radius = width * 1.41f * 0.5f; 066 067 float w = sprite.getWidth(); 068 float h = sprite.getHeight(); 069 int cols = (int) (w / CELL_SIZE); 070 int rows = (int) (h / CELL_SIZE); 071 072 073 float cellX = (int) (Math.random() * cols); 074 float cellY = (int) (Math.random() * rows); 075 076 float ctw = sprite.getTextureWidth() / (float) cols; 077 float cth = sprite.getTextureHeight() / (float) rows; 078 079 sprite.setTexX(cellX * ctw); 080 sprite.setTexY(cellY * cth); 081 sprite.setTexWidth(ctw); 082 sprite.setTexHeight(cth); 083 084 glow.setTexX(cellX * ctw); 085 glow.setTexY(cellY * cth); 086 glow.setTexWidth(ctw); 087 glow.setTexHeight(cth); 088 089 sprite.setSize(width, height); 090 glow.setSize(width, height); 091 092 //glow.setColor(new Color(255,165,100,255)); 093 glow.setColor(field.getParams().glowColor); 094 095 shadowMask = Global.getSettings().getSprite("graphics/fx/ship_shadow_mask.png"); 096 shadowMask.setSize(width * 1.5f, height * 1.5f); 097 098 fader.fadeIn(); 099 100 facing = (float) Math.random() * 360f; 101 angVel = (float) Math.random() * 360f - 180f; 102 103 float spawnRadius = field.params.bandWidthInEngine * field.getExpander().getBrightness(); 104 //spawnRadius *= 0.75f; 105 106 float r = (float) Math.random(); 107 r = (float) Math.sqrt(r); 108 float dist = r * spawnRadius; 109 110 loc = Misc.getUnitVectorAtDegreeAngle((float)Math.random() * 360f); 111 loc.scale(dist); 112 113 vel = Misc.getUnitVectorAtDegreeAngle((float)Math.random() * 360f); 114 115 vel = Misc.getPerp(loc); 116 float off = 0.25f; 117 vel.x += off - (float) Math.random() * 0.5f * off; 118 vel.y += off - (float) Math.random() * 0.5f * off; 119 if ((float) Math.random() > 0.5f) { 120 vel.negate(); 121 } 122 Misc.normalise(vel); 123 124 float speed = 20f + (float) Math.random() * 100f; 125 vel.scale(speed); 126 127 timeLeft = 1f + (float) Math.random(); 128// if (Math.random() < indProb) { 129// indFader.fadeIn(); 130// } 131 } 132 133 public void render(float alphaMult) { 134 135 //alphaMult *= fader.getBrightness(); 136 if (alphaMult <= 0) return; 137 138 SectorEntityToken entity = field.getEntity(); 139 SectorEntityToken lightSource = entity.getLightSource(); 140 if (lightSource != null && entity.getLightColor() != null) { 141 sprite.setColor(entity.getLightColor()); 142 } else { 143 sprite.setColor(Color.white); 144 } 145 146 sprite.setAngle(facing - 90); 147 sprite.setNormalBlend(); 148 sprite.setAlphaMult(alphaMult * fader.getBrightness()); 149 sprite.renderAtCenter(loc.x, loc.y); 150 151 if (lightSource != null && !entity.getLightSource().hasTag(Tags.AMBIENT_LS)) { 152 float w = shadowMask.getWidth() * 1.41f; 153 float h = w; 154 155 // clear out destination alpha in area we care about 156 GL11.glColorMask(false, false, false, true); 157 GL11.glPushMatrix(); 158 GL11.glTranslatef(loc.x, loc.y, 0); 159 Misc.renderQuadAlpha(0 - w/2f - 1f, 0 - h/2f - 1f, w + 2f, h + 2f, Misc.zeroColor, 0f); 160 GL11.glPopMatrix(); 161 sprite.setBlendFunc(GL11.GL_ONE, GL11.GL_ZERO); 162 sprite.renderAtCenter(loc.x, loc.y); 163 164 float lightDir = Misc.getAngleInDegreesStrict(field.getEntity().getLocation(), lightSource.getLocation()); 165 shadowMask.setAlphaMult(alphaMult); 166 shadowMask.setAngle(lightDir); 167 shadowMask.setBlendFunc(GL11.GL_ZERO, GL11.GL_SRC_ALPHA); 168 shadowMask.renderAtCenter(loc.x, loc.y); 169 170 GL11.glColorMask(true, true, true, false); 171 shadowMask.setBlendFunc(GL11.GL_DST_ALPHA, GL11.GL_ONE_MINUS_DST_ALPHA); 172 shadowMask.renderAtCenter(loc.x, loc.y); 173 } 174 175 176 if (glowFader.getBrightness() > 0) { 177 glow.setAngle(facing - 90); 178 glow.setAdditiveBlend(); 179 glow.setAlphaMult(alphaMult * fader.getBrightness() * 180 (0.5f + 0.5f * glowBounce.getBrightness()) * 181 glowFader.getBrightness()); 182 glow.renderAtCenter(loc.x, loc.y); 183 } 184 185 } 186 187 public void renderIndicator(float alphaMult) { 188 189 if (indFader.isFadedOut()) return; 190 alphaMult *= fader.getBrightness(); 191 192 if (alphaMult <= 0) return; 193 194 195 196 GL11.glPushMatrix(); 197 GL11.glTranslatef(loc.x, loc.y, 0); 198 199 GL11.glDisable(GL11.GL_TEXTURE_2D); 200 GL11.glEnable(GL11.GL_LINE_SMOOTH); 201 GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST); 202 203 float thickness = 1.5f; 204 GL11.glLineWidth(thickness); 205 206 GL11.glEnable(GL11.GL_BLEND); 207 //GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); 208 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); 209 210 //Color color = Global.getSector().getPlayerFaction().getBaseUIColor(); 211 Color color = Global.getSector().getFaction(Factions.NEUTRAL).getBaseUIColor(); 212 if (field.isScavenged()) { 213 //color = Misc.getNegativeHighlightColor(); 214 //color = Global.getSector().getFaction(Factions.PIRATES).getDarkUIColor(); 215 } 216 217 float size = width + 5f; 218 float half = size * 0.5f; 219 float corner = size * 0.25f; 220 float x = 0; 221 float y = 0; 222 223 float b = alphaMult; 224 float f = indFader.getBrightness(); 225 float glow = 0; 226 if (f < 0.1f) { 227 b *= f / 0.1f; 228 } else if (indFader.isFadingIn() && f < 0.4f) { 229 float p = (f - 0.1f) / (0.4f - 0.1f); 230 glow = (float) (Math.sin(p * (float) Math.PI * 6f - (float) Math.PI) + 1f) / 2f; 231 if (glow < 0.5f) { 232 glow = 0f; 233 } else { 234 glow = 1f; 235 } 236 glow *= 0.25f; 237 } 238 239 for (int i = 0; i < 2; i++) { 240 if (i == 1) { 241 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); 242 b = glow; 243 } 244 if (b <= 0) continue; 245 246 GL11.glBegin(GL11.GL_LINE_STRIP); 247 Misc.setColor(color, b); 248 GL11.glVertex2f(x - half, y + half - corner); 249 GL11.glVertex2f(x - half, y + half); 250 GL11.glVertex2f(x - half + corner, y + half); 251 GL11.glEnd(); 252 253 GL11.glBegin(GL11.GL_LINE_STRIP); 254 Misc.setColor(color, b); 255 GL11.glVertex2f(x + half, y + half - corner); 256 GL11.glVertex2f(x + half, y + half); 257 GL11.glVertex2f(x + half - corner, y + half); 258 GL11.glEnd(); 259 260 GL11.glBegin(GL11.GL_LINE_STRIP); 261 Misc.setColor(color, b); 262 GL11.glVertex2f(x - half, y - half + corner); 263 GL11.glVertex2f(x - half, y - half); 264 GL11.glVertex2f(x - half + corner, y - half); 265 GL11.glEnd(); 266 267 GL11.glBegin(GL11.GL_LINE_STRIP); 268 Misc.setColor(color, b); 269 GL11.glVertex2f(x + half, y - half + corner); 270 GL11.glVertex2f(x + half, y - half); 271 GL11.glVertex2f(x + half - corner, y - half); 272 GL11.glEnd(); 273 } 274 275 276 GL11.glPopMatrix(); 277 GL11.glDisable(GL11.GL_LINE_SMOOTH); 278 279 } 280 281 282// public void renderIndicatorOld(float alphaMult) { 283// 284// alphaMult *= fader.getBrightness(); 285// alphaMult *= indFader.getBrightness(); 286// 287// if (alphaMult <= 0) return; 288// 289// 290// float r = Math.max(10f, radius + 5f); 291// float lineLength = 10f; 292// float thickness = 2f; 293// 294// float spanRad = (float) Math.PI * 2f; 295// float arcLength = spanRad * radius; 296// 297// float numSegments = (float) Math.ceil(arcLength/lineLength); 298// if (numSegments < 16) numSegments = 16; 299// if ((int)numSegments % 4 != 0) { 300// numSegments = ((int) numSegments / 4) * 4 + 4; 301// } 302// 303// 304// float anglePerIter = spanRad / numSegments; 305// 306// GL11.glPushMatrix(); 307// GL11.glTranslatef(loc.x, loc.y, 0); 308// 309// GL11.glDisable(GL11.GL_TEXTURE_2D); 310// GL11.glEnable(GL11.GL_LINE_SMOOTH); 311// GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST); 312// GL11.glLineWidth(thickness); 313// 314// GL11.glEnable(GL11.GL_BLEND); 315// //GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE); 316// GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); 317// 318// //Color color = Global.getSector().getPlayerFaction().getBaseUIColor(); 319// Color color = Global.getSector().getFaction(Factions.NEUTRAL).getBaseUIColor(); 320// 321// GL11.glBegin(GL11.GL_LINE_LOOP); 322// for (float i = 0; i < numSegments + 1; i++) { 323// float b = alphaMult; 324// Misc.setColor(color, b); 325// float theta = anglePerIter * i; 326// float cos = (float) Math.cos(theta); 327// float sin = (float) Math.sin(theta); 328// float x1 = cos * (r - thickness / 2f); 329// float y1 = sin * (r - thickness / 2f); 330// GL11.glVertex2f(x1, y1); 331// } 332// GL11.glEnd(); 333// 334// 335// GL11.glPopMatrix(); 336// 337// GL11.glDisable(GL11.GL_LINE_SMOOTH); 338// 339// } 340 341 342 public void advance(float days) { 343 fader.advance(days); 344 glowBounce.advance(days); 345 glowFader.advance(days); 346 347 facing += angVel * days; 348 349 loc.x += vel.x * days; 350 loc.y += vel.y * days; 351 352 timeLeft -= days; 353 if (timeLeft < 0) { 354 fader.fadeOut(); 355 } 356 357// indCheck.advance(days); 358// if (indCheck.intervalElapsed() && Math.random() < indProb) { 359// indFader.fadeIn(); 360// } 361 indFader.advance(days); 362 } 363 364 public void showIndicator() { 365 if (indFader.isIdle()) { 366 float in = 0.3f; 367 float out = 0.3f + 0.7f * (float) Math.random(); 368 indFader.setDuration(in, out); 369 } 370 indFader.fadeIn(); 371 } 372 373 public boolean hasIndicator() { 374 return !indFader.isIdle(); 375 } 376 377 378 public boolean isDone() { 379 return fader.isFadedOut(); 380 } 381 382 public FaderUtil getGlowFader() { 383 return glowFader; 384 } 385 386 387} 388 389 390 391 392 393 394 395 396 397 398 399 400 401