43 public static String
DATA_KEY =
"core_shard_spawner_data_key";
47 public static enum ShardType {
55 public static class ShardTypeVariants {
56 public Map<ShardType, WeightedRandomPicker<String>> variants =
new HashMap<ShardType, WeightedRandomPicker<String>>();
57 public ShardTypeVariants() {
63 variants.put(type, result);
69 public static Map<HullSize, ShardTypeVariants>
variantData =
new HashMap<HullSize, ShardTypeVariants>();
71 ShardTypeVariants fighters =
new ShardTypeVariants();
73 fighters.get(ShardType.GENERAL).add(
"aspect_attack_wing", 10f);
74 fighters.get(ShardType.GENERAL).add(
"aspect_missile_wing", 1f);
76 fighters.get(ShardType.MISSILE).add(
"aspect_missile_wing", 10f);
78 fighters.get(ShardType.ANTI_ARMOR).add(
"aspect_attack_wing", 10f);
80 fighters.get(ShardType.ANTI_SHIELD).add(
"aspect_shieldbreaker_wing", 10f);
82 fighters.get(ShardType.POINT_DEFENSE).add(
"aspect_shock_wing", 10f);
85 ShardTypeVariants small =
new ShardTypeVariants();
88 small.get(ShardType.GENERAL).add(
"shard_left_Attack", 10f);
89 small.get(ShardType.GENERAL).add(
"shard_left_Attack2", 10f);
90 small.get(ShardType.GENERAL).add(
"shard_right_Attack", 10f);
91 small.get(ShardType.GENERAL).add(
"aspect_attack_wing", 10f);
92 small.get(ShardType.GENERAL).add(
"aspect_missile_wing", 1f);
94 small.get(ShardType.ANTI_ARMOR).add(
"shard_left_Armorbreaker", 10f);
96 small.get(ShardType.ANTI_SHIELD).add(
"shard_left_Shieldbreaker", 10f);
97 small.get(ShardType.ANTI_SHIELD).add(
"shard_right_Shieldbreaker", 10f);
100 small.get(ShardType.POINT_DEFENSE).add(
"shard_left_Defense", 10f);
101 small.get(ShardType.POINT_DEFENSE).add(
"shard_right_Shock", 10f);
104 small.get(ShardType.MISSILE).add(
"shard_left_Missile", 10f);
105 small.get(ShardType.MISSILE).add(
"shard_right_Missile", 10f);
109 ShardTypeVariants medium =
new ShardTypeVariants();
112 medium.get(ShardType.GENERAL).add(
"facet_Attack");
113 medium.get(ShardType.GENERAL).add(
"facet_Attack2");
115 medium.get(ShardType.ANTI_ARMOR).add(
"facet_Armorbreaker");
117 medium.get(ShardType.ANTI_SHIELD).add(
"facet_Shieldbreaker");
119 medium.get(ShardType.POINT_DEFENSE).add(
"facet_Defense");
121 medium.get(ShardType.MISSILE).add(
"facet_Missile");
123 ShardTypeVariants large =
new ShardTypeVariants();
126 large.get(ShardType.GENERAL).add(
"tesseract_Attack");
127 large.get(ShardType.GENERAL).add(
"tesseract_Attack2");
128 large.get(ShardType.GENERAL).add(
"tesseract_Strike");
129 large.get(ShardType.GENERAL).add(
"tesseract_Disruptor");
131 large.get(ShardType.ANTI_ARMOR).add(
"tesseract_Disruptor");
132 large.get(ShardType.ANTI_ARMOR).add(
"tesseract_Strike");
134 large.get(ShardType.ANTI_SHIELD).add(
"tesseract_Shieldbreaker");
136 large.get(ShardType.POINT_DEFENSE).add(
"tesseract_Defense");
138 large.get(ShardType.MISSILE).add(
"tesseract_Strike");
141 public static class ShardSpawnerData {
142 boolean done =
false;
143 float delay = 2f + (float) Math.random() * 1f;
160 ShardSpawnerData data = (ShardSpawnerData) engine.
getCustomData().get(key);
162 data =
new ShardSpawnerData();
166 if (data.done)
return;
171 data.delay -= amount;
172 if (data.delay > 0)
return;
179 float splitWeight = 0f;
181 float probNothingAtAll = 0f;
183 float cruiserProb = 0f;
184 float cruiserProbMult = 0f;
185 float maxCruisers = 0f;
186 float destroyerProb = 0f;
187 float destroyerProbMult = 0f;
188 float maxDestroyers = 0f;
189 float frigateProb = 0f;
190 float frigateProbMult = 0f;
191 float maxFrigates = 0f;
197 cruiserProbMult = 0.5f;
200 destroyerProbMult = 1f;
203 frigateProbMult = 1f;
218 destroyerProbMult = 0.5f;
221 frigateProbMult = 1f;
233 frigateProbMult = 1f;
247 if ((
float) Math.random() < probNothingAtAll) {
252 int spawnAnglesIter = 0;
253 float angleOffset = (float) Math.random() * 360f;
255 float addedWeight = 0f;
258 float destroyers = 0f;
260 List<ShardFadeInPlugin> shards =
new ArrayList<ShardFadeInPlugin>();
261 while (addedWeight < splitWeight) {
262 ShardType type = typePicker.
pick();
264 float rem = splitWeight - addedWeight;
265 boolean cruiser = (float) Math.random() < cruiserProb && cruisers < maxCruisers && rem >= 3.5f;
266 boolean destroyer = (float) Math.random() < destroyerProb && destroyers < maxDestroyers && rem >= 1.5f;
267 boolean frigate = (float) Math.random() < frigateProb && frigates < maxFrigates;
269 String variant =
null;
273 ShardTypeVariants variants =
variantData.get(HullSize.CRUISER);
275 variant = variantPicker.
pick();
276 if (variant !=
null) {
279 cruiserProb *= cruiserProbMult;
283 if (destroyer && variant ==
null) {
284 ShardTypeVariants variants =
variantData.get(HullSize.DESTROYER);
286 variant = variantPicker.
pick();
287 if (variant !=
null) {
290 destroyerProb *= destroyerProbMult;
294 if (frigate && variant ==
null) {
295 ShardTypeVariants variants =
variantData.get(HullSize.FRIGATE);
297 variant = variantPicker.
pick();
298 if (variant !=
null) {
301 frigateProb *= frigateProbMult;
305 if (variant ==
null) {
306 ShardTypeVariants variants =
variantData.get(HullSize.FIGHTER);
308 variant = variantPicker.
pick();
309 if (variant !=
null) {
317 if (variant !=
null) {
318 if (spawnAngles ==
null || spawnAngles.
isEmpty()) {
325 addedWeight += weight;
347 }
else if (iter == 2) {
353 for (
float i = start; i < 360f + start; i += incr) {
363 float checkRadius = 5000;
366 float weightFighters = 0f;
367 float weightGoodShields = 0f;
368 float weightGoodArmor = 0f;
369 float weightVulnerable = 0f;
370 float weightCarriers = 0f;
372 float weightEnemies = 0f;
373 float weightFriends = 0f;
375 while (iter.hasNext()) {
376 Object o = iter.next();
384 weightFighters += 0.25f;
385 weightEnemies += 0.25f;
391 weightGoodShields += w;
394 weightGoodArmor += w;
397 weightVulnerable += w;
405 weightFriends += 0.25f;
416 float total = weightFighters + weightGoodShields + weightGoodArmor + weightVulnerable + weightCarriers;
417 if (total <= 1f) total = 1f;
419 float antiFighter = (weightFighters + weightCarriers) / total;
420 float antiShield = weightGoodShields / total;
421 float antiArmor = weightGoodArmor / total;
422 float missile = weightVulnerable / total;
424 float friends = weightFriends / Math.max(1f, weightEnemies + weightFriends);
426 picker.
add(ShardType.GENERAL, 0.0f + (1f - friends) * 0.4f);
432 float unlikelyWeight = 0f;
433 float unlikelyThreshold = 0.2f;
435 if (antiFighter < unlikelyThreshold) antiFighter = unlikelyWeight;
436 picker.
add(ShardType.POINT_DEFENSE, antiFighter);
438 if (antiShield < unlikelyThreshold) antiShield = unlikelyWeight;
439 picker.
add(ShardType.ANTI_SHIELD, antiShield);
441 if (antiArmor < unlikelyThreshold) antiArmor = unlikelyWeight;
442 picker.
add(ShardType.ANTI_ARMOR, antiArmor);
444 if (missile < unlikelyThreshold) missile = unlikelyWeight;
445 picker.
add(ShardType.MISSILE, missile);
454 if (dist > 2000)
return false;
456 float assumedMissileSpeed = 500;
457 float eta = dist / assumedMissileSpeed;
465 float requiredArmor = 1240;
470 return armor >= requiredArmor * 0.8f;
476 if (shield ==
null)
return false;
477 if (shield.
getType() == ShieldType.NONE)
return false;
478 if (shield.
getType() == ShieldType.PHASE)
return false;
480 float requiredCapacity = 10000000f;
483 requiredCapacity = 25000;
484 if (shield.
getType() == ShieldType.FRONT && shield.
getArc() < 250) {
485 requiredCapacity = 1000000;
489 requiredCapacity = 12500;
490 if (shield.
getType() == ShieldType.FRONT && shield.
getArc() < 250) {
491 requiredCapacity = 1000000;
495 requiredCapacity = 8000;
498 requiredCapacity = 4000;
505 capacity /= Math.max(0.1f, e);
507 return capacity >= requiredCapacity && e <= 1f;
513 final List<ShardFadeInPlugin> shards) {
518 protected void pushShipsAway(
float amount) {
519 Vector2f com =
new Vector2f();
521 for (ShardFadeInPlugin shard : shards) {
527 com.scale(1f / Math.max(1f, count));
529 Vector2f comForFighters =
new Vector2f();
531 for (ShardFadeInPlugin shard : shards) {
534 Vector2f.add(comForFighters, ship.
getLocation(), comForFighters);
537 comForFighters.scale(1f / Math.max(1f, count));
539 float progress = elapsed / fadeOutTime;
540 if (progress > 1f) progress = 1f;
541 for (ShardFadeInPlugin shard : shards) {
543 Vector2f currCom = com;
544 if (ship.
isFighter()) currCom = comForFighters;
548 dir.scale(amount * speed * progress);
554 public void advance(
float amount, List<InputEventAPI> events) {
560 float progress = elapsed / fadeOutTime;
561 if (progress > 1f) progress = 1f;
565 pushShipsAway(amount);
568 if (progress > 0.5f) {
572 float jitterLevel = progress;
573 if (jitterLevel < 0.5f) {
576 jitterLevel = (1f - jitterLevel) * 2f;
579 float jitterRange = progress;
581 float maxRangeBonus = 100f;
582 float jitterRangeBonus = jitterRange * maxRangeBonus;
584 int alpha = c.getAlpha();
585 alpha += 100f * progress;
586 if (alpha > 255) alpha = 255;
589 ship.
setJitter(
this, c, jitterLevel, 35, 0f, jitterRangeBonus);
592 if (interval.intervalElapsed() && elapsed < fadeOutTime * 0.75f) {
595 float baseDuration = 2f;
598 for (
int i = 0; i < 3; i++) {
601 float dur = baseDuration + baseDuration * (float) Math.random();
605 v.scale(nSize + nSize * (
float) Math.random() * 0.5f);
607 Vector2f.add(vel, v, v);
609 float maxSpeed = nSize * 1.5f * 0.2f;
610 float minSpeed = nSize * 1f * 0.2f;
611 float overMin = v.length() - minSpeed;
613 float durMult = 1f - overMin / (maxSpeed - minSpeed);
614 if (durMult < 0.1f) durMult = 0.1f;
615 dur *= 0.5f + 0.5f * durMult;
618 0.5f / dur, 0f, dur, c);
622 if (elapsed > fadeOutTime) {
634 final float delay,
final float fadeInTime,
final float angle) {
636 return new ShardFadeInPlugin(variantId, source, delay, fadeInTime, angle);
650 public ShardFadeInPlugin(String variantId,
ShipAPI source,
float delay,
float fadeInTime,
float angle) {
651 this.variantId = variantId;
652 this.source = source;
654 this.fadeInTime = fadeInTime;
661 public void advance(
float amount, List<InputEventAPI> events) {
665 if (elapsed < delay)
return;
670 float facing = source.
getFacing() + 15f * ((float) Math.random() - 0.5f);
678 fleetManager.setSuppressDeploymentMessages(
true);
679 if (variantId.endsWith(
"_wing")) {
688 for (
int i = 0; i < ships.length; i++) {
694 ships =
new ShipAPI[1];
697 for (
int i = 0; i < ships.length; i++) {
701 if (Global.getCombatEngine().isInCampaign() || Global.getCombatEngine().isInCampaignSim()) {
702 FactionAPI faction = Global.getSector().getFaction(Factions.OMEGA);
703 if (faction !=
null) {
704 String name = faction.pickRandomShipName();
709 fleetManager.setSuppressDeploymentMessages(wasSuppressed);
712 DeployedFleetMemberAPI sourceMember = fleetManager.getDeployedFleetMemberFromAllEverDeployed(source);
713 DeployedFleetMemberAPI deployed = fleetManager.getDeployedFleetMemberFromAllEverDeployed(ships[0]);
714 if (sourceMember !=
null && deployed !=
null) {
715 Map<DeployedFleetMemberAPI, DeployedFleetMemberAPI> map = fleetManager.getShardToOriginalShipMap();
716 while (map.containsKey(sourceMember)) {
717 sourceMember = map.get(sourceMember);
719 if (sourceMember !=
null) {
720 map.put(deployed, sourceMember);
727 float progress = (elapsed - delay) / fadeInTime;
728 if (progress > 1f) progress = 1f;
730 for (
int i = 0; i < ships.length; i++) {
731 ShipAPI ship = ships[i];
734 if (progress < 0.5f) {
735 ship.blockCommandForOneFrame(ShipCommand.ACCELERATE);
736 ship.blockCommandForOneFrame(ShipCommand.TURN_LEFT);
737 ship.blockCommandForOneFrame(ShipCommand.TURN_RIGHT);
738 ship.blockCommandForOneFrame(ShipCommand.STRAFE_LEFT);
739 ship.blockCommandForOneFrame(ShipCommand.STRAFE_RIGHT);
742 ship.blockCommandForOneFrame(ShipCommand.USE_SYSTEM);
743 ship.blockCommandForOneFrame(ShipCommand.TOGGLE_SHIELD_OR_PHASE_CLOAK);
744 ship.blockCommandForOneFrame(ShipCommand.FIRE);
745 ship.blockCommandForOneFrame(ShipCommand.PULL_BACK_FIGHTERS);
746 ship.blockCommandForOneFrame(ShipCommand.VENT_FLUX);
747 ship.setHoldFireOneFrame(
true);
748 ship.setHoldFire(
true);
751 ship.setCollisionClass(CollisionClass.NONE);
752 ship.getMutableStats().getHullDamageTakenMult().modifyMult(
"ShardSpawnerInvuln", 0f);
753 if (progress < 0.5f) {
755 }
else if (progress > 0.75f){
756 ship.setCollisionClass(collisionClass);
757 ship.getMutableStats().getHullDamageTakenMult().unmodifyMult(
"ShardSpawnerInvuln");
765 float jitterLevel = progress;
766 if (jitterLevel < 0.5f) {
769 jitterLevel = (1f - jitterLevel) * 2f;
772 float jitterRange = 1f - progress;
773 float maxRangeBonus = 50f;
774 float jitterRangeBonus = jitterRange * maxRangeBonus;
777 ship.setJitter(
this, c, jitterLevel, 25, 0f, jitterRangeBonus);
780 if (elapsed > fadeInTime) {
781 for (
int i = 0; i < ships.length; i++) {
782 ShipAPI ship = ships[i];
784 ship.setHoldFire(
false);
785 ship.setCollisionClass(collisionClass);
786 ship.getMutableStats().getHullDamageTakenMult().unmodifyMult(
"ShardSpawnerInvuln");