Fractal Softworks Forum

Please login or register.

Login with username, password and session length
Advanced search  

News:

Starsector 0.97a is out! (02/02/24); New blog post: Simulator Enhancements (03/13/24)

Pages: [1] 2 3 ... 10

Author Topic: The Radioactive Code Dump  (Read 80553 times)

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
The Radioactive Code Dump
« on: July 28, 2013, 07:13:02 PM »

Some utility stuff I've been working on and wanted to give to people to do cool stuff with.  

Some of these require LazyLib, because I'm even lazier than LazyWizard, and see no reason to reinvent that wonderful toolkit.

An auto-explosion generator with automatic AOE.  
Projectile hits stuff and then makes neato explosion and blows up nearby things.
Provides examples of particle-effect manipulation and how to build a simple AOE system on this engine.  Requires LazyLib.

Does not require the AOE-ish Behavior defined for the Projectile (which has advantages and disadvantages - no auto-trigger near other projectiles, but no auto-trigger near spacecraft, either).  Can't be used with Vanilla AOE right now (but this should work in 0.6+), as that apparently isn't allowing the code to run.  Can't be used with Missiles currently (ditto).  I expect that most of this will be resolved in 0.6.
It has some accuracy issues; sometimes objects within the AOE will not register a hit, for whatever reasons.  This mainly effects small stuff.  There's a kludge in place atm to take care of that.
Spoiler
Code
///////////////////////GENERIC EXPLOSION GENERATOR AND AOE SIMULATION
///////////////////////REQUIRES LAZYLIB
package data.scripts;

import java.awt.Color;

import org.lwjgl.util.vector.Vector2f;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.DamageType;
import com.fs.starfarer.api.combat.DamagingProjectileAPI;
import com.fs.starfarer.api.combat.OnHitEffectPlugin;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.WeaponAPI;
import java.util.List;
import java.util.Iterator;

import org.lazywizard.lazylib.MathUtils;
import org.lazywizard.lazylib.CollisionUtils;
import org.lazywizard.lazylib.combat.*;

public class ExplosiveOnHitEffectWithAOE implements OnHitEffectPlugin {

public void onHit(DamagingProjectileAPI projectile, CombatEntityAPI target,
 Vector2f point, boolean shieldHit, CombatEngineAPI engine) {

float emp = projectile.getEmpAmount();
float dam = projectile.getDamageAmount();
WeaponAPI weapon = projectile.getWeapon();
DamageType damType = weapon.getDamageType();
float aoeToCheck = Math.max(dam / 10f, 20f);//Checks an area equal to damage / 10, with a floor of 20 (anything lower than that isn't worth doing, imo, but you may want to put an upper cap on really huge-damage weapons); can be adjusted to whatever you want
float aoeMult = 0.5f;//This is our multiplier against damage for distant targets, for balance purposes.
//AOE CODE
//This code searches first for nearby Ships, then for nearby non-ship entities, and applies damage to them over the AOE.
//When it checks for nearby ships, if it finds any it gets a valid collision (or not) by doing a ray-test...
//Which keeps things easy (don't thank me, thank Alex / LazyWizard)
//We don't need that (fairly expensive) check for nearby missiles, so we don't bother.
//If the checks come up with anything, then it gets damaged, in this case by half of the base damage.
List nearbyEnemies = CombatUtils.getShipsWithinRange(point, aoeToCheck, true);
for(Iterator iterMe = nearbyEnemies.iterator(); iterMe.hasNext();)
{
CombatEntityAPI targEnt = (CombatEntityAPI) iterMe.next();
if(targEnt != target && (targEnt.getOwner() != ((CombatEntityAPI) projectile.getSource()).getOwner()))//No double hits or friendly fire.
{

Vector2f targLoc = targEnt.getLocation();
//Try to get a valid collision point between our explosion's point source and the Entity.
Vector2f colPoint = CollisionUtils.getCollisionPoint(point, targLoc, targEnt);
//If we can't get a good collision point, use the center of the target Entity.  This is potentially a balance issue (hits all going to one armor cell are pretty OP lol), but this case mainly covers little teeny drones and suchlike that should be registering hits from giant explosions nearby, but often don't, for whatever reason.  Bigger things rarely fail, so it usually works out.
if(colPoint == null) colPoint = targLoc;
if(colPoint != null)//Must check this, getCollisionPoint returns null fairly frequently and that's a wrap
{
engine.applyDamage(
targEnt, //enemy Entity
colPoint, //Our 2D vector to the exact world-position of the collision
dam * aoeMult, //DPS modified by the damage multiplier
damType, //Using the damage type here, so that Kinetic / Explosive / Fragmentation AOE works.
emp * aoeMult, //EMP
false, //Does not bypass shields.
false, //Does not do Soft Flux damage (unless you want it to for some strange reason)
projectile.getSource()  //Who owns this projectile?
);
//This is just for testing purposes- shows a blue dot if, when and where hits occur.  Handy for testing balance.
/*
for(int i = 0; i < 6; i++)
{
engine.addHitParticle(colPoint, new Vector2f(MathUtils.getRandomNumberInRange(-5,5), MathUtils.getRandomNumberInRange(-5,5)), MathUtils.getRandomNumberInRange(25,50), 1f, 100f, new Color(0,0,255,255));
}*/

}
}
}
//Simpler task for missiles- we don't need an intersection with Hulls to get a valid armor location.
nearbyEnemies = CombatUtils.getMissilesWithinRange(point, aoeToCheck, true);
for(Iterator iterMe = nearbyEnemies.iterator(); iterMe.hasNext();)
{
CombatEntityAPI targEnt = (CombatEntityAPI) iterMe.next();
if(targEnt != target && (targEnt.getOwner() != ((CombatEntityAPI) projectile.getSource()).getOwner()))//No double hits or friendly fire.
{
Vector2f targLoc = targEnt.getLocation();
engine.applyDamage(
targEnt, //enemy Entity
targLoc, //Our 2D vector to the exact world-position of the collision
dam * aoeMult, //DPS modified by the damage multiplier
damType, //Using the damage type here, so that Kinetic / Explosive / Fragmentation AOE works.
emp * aoeMult, //EMP
false, //Does not bypass shields.
false, //Does not do Soft Flux damage (unless you want it to for some strange reason)
projectile.getSource()  //Who owns this projectile?
);
}
}

//EXPLOSION BITZ
//This code auto-magically builds a reasonably-cool generic explosion, based on weapon damage.
//There isn't much code that's expensive here and the game does auto-cull particles, so this can be made more complex if you want.  Just be careful about how many particles you create per event, since that's a linear cost (i.e., if you stick this on a Vulcan-type weapon, keep the total count low, low or re-write that part).  
int repeat = Math.max(5,(int) ((dam / 60f)));
int repeatTwo = repeat / 3;

//This bit makes backdrop glows show up fairly briefly behind our main explosion.
//Just one particle per repeat, but it costs a lot of operations to built it.
for(int i = 0; i < repeatTwo; i++)
{
Vector2f randPoint = MathUtils.getRandomPointInCircle(point,dam/35f);
float randSize = MathUtils.getRandomNumberInRange(dam/25f,Math.max(dam / 20f,15f));
Vector2f randVec = new Vector2f(MathUtils.getRandomNumberInRange(-dam / 50f ,dam / 50f),MathUtils.getRandomNumberInRange(-dam / 50f ,dam / 50f));
float randDur = 0.1f + MathUtils.getRandomNumberInRange(0.0f,0.3f);
int yelVal = (int) (Math.random() * 200f + 32f);
int randTrans = (int) MathUtils.getRandomNumberInRange(64f,128f);

engine.addSmoothParticle(randPoint, randVec, randSize, 1f, randDur, new Color(255,yelVal,0,randTrans));
}

//Main explosion, fast & slow fires and smoke at the end.
//Six particles per repeat, min 30.
for(int i = 0; i < repeat; i++)
{

int yelVal = (int) (Math.random() * 128f + 64f);
Vector2f randPoint = MathUtils.getRandomPointInCircle(point,dam/100f);

//Random Vectors, in order of speed; generally, we need smoke and central poof to be slower than others
Vector2f randVecFast = new Vector2f(MathUtils.getRandomNumberInRange(-30f - dam / 2f ,30f + dam / 2f),MathUtils.getRandomNumberInRange(-30f - dam / 2f ,30f + dam / 2f));
Vector2f randVecFastTwo = new Vector2f(MathUtils.getRandomNumberInRange(-30f - dam / 2f ,30f + dam / 2f),MathUtils.getRandomNumberInRange(-30f - dam / 2f ,30f + dam / 2f));
Vector2f randVec = new Vector2f(MathUtils.getRandomNumberInRange(-dam / 25f ,dam / 25f),MathUtils.getRandomNumberInRange(-dam / 25f ,dam / 25f));
Vector2f randVecTwo = new Vector2f(MathUtils.getRandomNumberInRange(-dam / 35f ,dam / 35f),MathUtils.getRandomNumberInRange(-dam / 35f,dam / 35f));
Vector2f randVecThree = new Vector2f(MathUtils.getRandomNumberInRange(-dam / 40f ,dam / 40f),MathUtils.getRandomNumberInRange(-dam / 40f,dam / 40f));

float randSize = MathUtils.getRandomNumberInRange(10f,Math.max(dam / 50f,15f));
float randSizeTwo = MathUtils.getRandomNumberInRange(5f,10f);
float randDur = 1f + MathUtils.getRandomNumberInRange(-0.5f,3f);
float randDurTwo = MathUtils.getRandomNumberInRange(0.5f,1f);
int randTrans = (int) MathUtils.getRandomNumberInRange(32f,200f);
int randGray = (int) MathUtils.getRandomNumberInRange(32f,64f);

engine.addHitParticle(point, randVecFast, randSizeTwo, 1f, randDurTwo * 0.5f, new Color(255,yelVal + 64,0,randTrans + 55));
engine.addHitParticle(point, randVecFastTwo, randSizeTwo, 1f, randDurTwo * 0.65f, new Color(255,yelVal + 64,0,randTrans + 55));
engine.addHitParticle(point, randVec, randSize, 1f, randDurTwo, new Color(255,yelVal-64,0,randTrans));
engine.addHitParticle(point, randVecTwo, randSize, 1f, randDurTwo * 0.75f, new Color(255,yelVal-32,0,randTrans));
engine.addHitParticle(point, randVecThree, randSize, 1f, randDurTwo * 0.5f, new Color(255,yelVal,0,randTrans));

engine.addSmokeParticle(point, randVecThree, MathUtils.getRandomNumberInRange(dam / 100f,dam / 50f), MathUtils.getRandomNumberInRange(0.5f,1f), randDur, new Color(randGray,randGray,randGray,randTrans));
}
}
}
[close]

"Heat" special projectile type.  
When it (beam / projectile) hits, it generates multiple sub-hits around the target, potentially bypassing the shields.  Thus it can knock out engines even as the target attempts to retreat and other Fun Things.  
It's insidiously powerful; feel free to combine it with AOE for the ultimate in "crisping" fun.  Space napalm, baby.
Requires LazyLib.
Spoiler
Code
package data.scripts;

import java.awt.Color;

import org.lwjgl.util.vector.Vector2f;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.WeaponAPI;
import com.fs.starfarer.api.combat.DamageType;
import com.fs.starfarer.api.combat.DamagingProjectileAPI;
import com.fs.starfarer.api.combat.OnHitEffectPlugin;
import com.fs.starfarer.api.combat.ShipAPI;

import org.lazywizard.lazylib.CollisionUtils;
import org.lazywizard.lazylib.MathUtils;

public class HellboreOnHitEffect implements OnHitEffectPlugin {

public void onHit(DamagingProjectileAPI projectile, CombatEntityAPI target,
 Vector2f point, boolean shieldHit, CombatEngineAPI engine) {
if (target instanceof ShipAPI) {
float emp = projectile.getEmpAmount() * 0.1f;
float dam = projectile.getDamageAmount() * 0.1f;
WeaponAPI weapon = projectile.getWeapon();
DamageType damType = weapon.getDamageType();
int heatMe = (int) Math.max(6f,dam / 150f);

Vector2f targLoc = target.getLocation();
for(int i = 0; i < heatMe; i++)
{
//Gets a point far, far away and uses it as our ray-test point.  Long distances work better than shorter ones.
Vector2f cloneLoc = MathUtils.getRandomPointOnCircumference(targLoc, 1000000f);

//Try to get a valid collision point between our explosion's point source and the Entity.
Vector2f colPoint = CollisionUtils.getCollisionPoint(cloneLoc, targLoc, target);
//If we can't get a good collision point, use the center of the target Entity.  This is potentially a balance issue (hits all going to one armor cell are pretty OP lol), but this case mainly covers little teeny drones and suchlike that should be registering hits from giant explosions nearby, but often don't, for whatever reason.  Bigger things rarely fail, so it usually works out.
if(colPoint == null) colPoint = targLoc;
if(colPoint != null)//Must check this, getCollisionPoint returns null fairly frequently and that's a wrap
{
engine.applyDamage(
target, //enemy Entity
colPoint, //Our 2D vector to the exact world-position of the collision
dam, //DPS modified by the damage multiplier
damType, //Using the damage type here, so that Kinetic / Explosive / Fragmentation AOE works.
emp, //EMP (if any)
false, //Does not bypass shields.
false, //Does not do Soft Flux damage (unless you want it to for some strange reason)
projectile.getSource()  //Who owns this projectile?
);
}
}  
}
}
}
[close]

Physics fun.  
Car-like driving behaviors with skidding and rolling resistance and stuff.  
Not super-fancy but it gets the job done for sea or land warfare, where we don't want turning to feel like Outer Space, or where we'd like to simulate inertial changes in space a bit more realistically.  

As a bonus, also has code for "inertialess" drive behaviors- change direction without any velocity costs (or adjust as required).
Intended to run within an EveryFrameCombatPlugin.  
Requires some basic vector-math knowledge to do much with, but it has a lot of the basics like adjusting the forward / rightward vectors relative to the Entity's current velocity.

This is as far as my Autoduel-ish mod idea (well, that and a few silly graphics things that might just work in 0.6+) got before I ran out of steam.
Spoiler
Code
		//Gets all ships;
List ships = engine.getAllShips();
Iterator it = ships.iterator();
while (it.hasNext())
{
ShipAPI ship = (ShipAPI) it.next();

if (ship.isFrigate())
{
ship.setCollisionClass(CollisionClass.FIGHTER);
continue;
}

if (ship.isFighter() || ship.isShuttlePod() || ship.isFrigate() || ship.isDrone()) continue;

//Gets the ship's velocity, expressed as a vector.
Vector2f shipVec = ship.getVelocity();
shipVec = (Vector2f) shipVec.scale(0.999f);
float shipSpeed = (float) Math.sqrt(Math.abs(shipVec.getX() * shipVec.getX()) + Math.abs(shipVec.getY() * shipVec.getY()));
MutableShipStatsAPI stats = ship.getMutableStats();
float maxSpeed = (float) stats.getMaxSpeed().getBaseValue();
float speedPenalty = Math.min(50f,(shipSpeed / maxSpeed) * 100.0f);
String id = ship.getFleetMemberId();
stats.getMaxTurnRate().unmodify(id);
stats.getTurnAcceleration().unmodify(id);
stats.getMaxTurnRate().modifyPercent(id,-speedPenalty);
stats.getTurnAcceleration().modifyPercent(id,-speedPenalty);


//public MutableStat getMaxTurnRate();
//public MutableStat getTurnAcceleration();

//Converts the player's heading (in degrees) back to unit vectors.
Vector2f rotVec = new Vector2f ((float) Math.cos(ship.getFacing() * 3.14159f / 180f), (float) Math.sin(ship.getFacing() * 3.14159f / 180f));
//Gets the "right" vector, i.e. perpendicular to the forward axis
Vector2f rightVec = new Vector2f(rotVec.getY() * -1.0f,rotVec.getX());
//Dot products of the two vectors
float dotForward = Vector2f.dot(shipVec, rotVec);
float dotRight = Vector2f.dot(shipVec, rightVec);
//Gives us the forward and rightward vectors of current velocity
Vector2f forwardVelocity = new Vector2f(rotVec.getX() * dotForward, rotVec.getY() * dotForward);
Vector2f rightVelocity = new Vector2f(rightVec.getX() * dotRight, rightVec.getY() * dotRight);
//Final conversion, drops the rightward component's magnitude while preserving the forward component.
//The multiplier 0.02f is our tuning variable; try different amounts to play with the "friction".
Vector2f.add(shipVec,new Vector2f(rightVelocity.getX() * -0.02f, rightVelocity.getY() * -0.02f),shipVec);

//This is an alternative behavior; it keeps forward velocity (towards the forward vector) constant but lowers...
//"right" velocity, resulting in a ship with an "inertialess" drive.  It might be useful for various behaviors.
//Commented out, because the above behavior is closer to classic land / sea movement.
//shipVec = shipVec.add(forwardVelocity,new Vector2f(rightVelocity.getX() * -0.02f, rightVelocity.getY() * -0.02f),shipVec);
}
[close]

Feel free to dump more useful code here; I'd prefer to see things that solve a specific engineering / gamecode problem or provide a nifty visual effect, since those tend to be the hard things.  Documentation is a must; there's no point in giving out neato stuff that's black-box to all but the 1337 :)

If you're wondering what what license it's released as, it's CC-CR, i.e., please credit me if you use this stuff, otherwise do whatever you want, no permission required or any of that stuff.
« Last Edit: July 28, 2013, 07:32:57 PM by xenoargh »
Logged
Please check out my SS projects :)
Xeno's Mod Pack

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: The Radioactive Code Dump
« Reply #1 on: July 28, 2013, 07:16:46 PM »

Mission example. 
A Mission plugin and Mission that uses it to generate a bunch of dead ships floating around at the start of the Mission.  Used it to generate a "ghost town" during a Mission, but it's a crude example of how to actually make / use the Plugins.  Credit to LazyWizard's half-finished minigame for getting me on the right track.

Mission code.
Spoiler
Code
package data.missions.paragone;

import com.fs.starfarer.api.campaign.CargoAPI.CrewXPLevel;
import com.fs.starfarer.api.mission.FleetSide;
import com.fs.starfarer.api.fleet.FleetGoal;
import com.fs.starfarer.api.fleet.FleetMemberType;
import com.fs.starfarer.api.mission.FleetSide;
import com.fs.starfarer.api.mission.MissionDefinitionAPI;
import com.fs.starfarer.api.mission.MissionDefinitionPlugin;

public class MissionDefinition implements MissionDefinitionPlugin {

public void defineMission(MissionDefinitionAPI api) {

// Set up the fleets
api.initFleet(FleetSide.PLAYER, "TTS", FleetGoal.DEFEND, false, 30);
api.initFleet(FleetSide.ENEMY, "LI", FleetGoal.ATTACK, true, 30);

// Set a blurb for each fleet
api.setFleetTagline(FleetSide.PLAYER, "Emergency Force Delta");
api.setFleetTagline(FleetSide.ENEMY, "The Rogue L.I. / TTS Decisive");

// These show up as items in the bulleted list under
// "Tactical Objectives" on the mission detail screen
api.addBriefingItem("The TTS Decisive must be defeated.  The Rook must survive.");

// Set up the player's fleet
api.addToFleet(FleetSide.PLAYER, "aurora_Balanced", FleetMemberType.SHIP, "TTS Rook", true, CrewXPLevel.ELITE);
api.addToFleet(FleetSide.PLAYER, "silent_raven_Standard", FleetMemberType.SHIP, "TTS Dark Wing", true, CrewXPLevel.ELITE);
api.addToFleet(FleetSide.PLAYER, "silent_raven_Standard", FleetMemberType.SHIP, "TTS Ebon Claw", true, CrewXPLevel.ELITE);
//api.addToFleet(FleetSide.PLAYER, "onslaught_Standard", FleetMemberType.SHIP, "TTS Invincible", true, CrewXPLevel.ELITE);

// Mark player flagship as essential.
api.defeatOnShipLoss("TTS Rook");

// Set up the enemy fleet
api.addToFleet(FleetSide.ENEMY, "paragon_Elite", FleetMemberType.SHIP, "TTS Decisive", true, CrewXPLevel.ELITE);

// Set up the map.
float width = 9000f;
float height = 9000f;
api.initMap((float)-width/2f, (float)width/2f, (float)-height/2f, (float)height/2f);

float minX = -width/2;
float minY = -height/2;

for (int i = 0; i < 15; i++) {
float x = (float) Math.random() * width - width/2;
float y = (float) Math.random() * height - height/2;
float radius = 100f + (float) Math.random() * 900f;
api.addNebula(x, y, radius);
}

// Add an asteroid field going diagonally across the
// battlefield, 2000 pixels wide, with a maximum of
// 100 asteroids in it.
// 20-70 is the range of asteroid speeds.
api.addAsteroidField(0f, 0f, (float) Math.random() * 360f, width,
20f, 70f, 100);
api.addPlugin(new RandomJunkScript(width, height));
}

}
[close]


The plugin that generates the random junk.
Spoiler
Code
package data.missions.paragone;

import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.EveryFrameCombatPlugin;
import com.fs.starfarer.api.combat.MutableShipStatsAPI;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.fleet.FleetMemberAPI;
import com.fs.starfarer.api.mission.FleetSide;
import com.fs.starfarer.api.util.IntervalUtil;
import java.util.List;
import org.lazywizard.lazylib.MathUtils;
import org.lwjgl.util.vector.Vector2f;
import com.fs.starfarer.api.combat.DamageType;
import java.awt.Color;

public class RandomJunkScript implements EveryFrameCombatPlugin
{
private IntervalUtil goInterval = new IntervalUtil(0.1f, 0.1f);

    // Whether one-time events have been triggered yet
    private boolean hasSpawned = false;

    // The combat engine object used by this battle
    private CombatEngineAPI engine;

private float height;
private float width;

    public RandomJunkScript(float width, float height)
    {
        // We're just passing the battlefield's height and width in here
        this.height = height;
this.width = width;
    }

private void buildShip(String type)
{
float x = (float) Math.random() * width - width/2;
float y = (float) Math.random() * height - height/2;
Vector2f loc = new Vector2f();
loc.x = x;
loc.y = y;
float facing = (float) Math.random() * 360f;
//String variantID = "brawler_Assault"; //Safety code here


//Give the enemy fleet this ship... temporarily...
ShipAPI target = engine.getFleetManager(FleetSide.ENEMY).spawnShipOrWing(type, loc, facing);
//re-use loc here, use the new position of the ship we've built
loc = target.getLocation();
//move the ship waaaaay off-screen
loc.x += 100000f;
loc.y += 100000f;

//Blow up the new ship.
engine.spawnEmpArc(target, loc, (CombatEntityAPI) target, (CombatEntityAPI) target,
   DamageType.ENERGY,
   1000000f,
   0f, // emp
   10000000f, // max range
   "tachyon_lance_emp_impact",
   0.0001f, // thickness
   new Color(0,0,0,0),
   new Color(0,0,0,0)
   );
//Move the ship back to its spawn position.
loc.x -= 100000f;
loc.y -= 100000f;
}

private void buildFriendlyShip(String type)
{
float x = (float) Math.random() * width - width/2;
float y = (float) (Math.random() * (height / 4)) - height / 8 - 2000f;
Vector2f loc = new Vector2f();
loc.x = x;
loc.y = y;
float facing = (float) Math.random() * 360f;

//Give our fleet the ship.
ShipAPI target = engine.getFleetManager(FleetSide.PLAYER).spawnShipOrWing(type, loc, facing);
}


    @Override
    public void advance(float amount, List events)
    {
        // If the game is paused or we've already done the one-time events, do nothing

        if (engine.isPaused())
        {
            return;
        }
        // One time setup at battle start
goInterval.advance(amount);
       if (goInterval.intervalElapsed() && !hasSpawned)
        {

int randomNum = (int) (Math.random() * 6f + 1f);
    for (int i = 0; i < randomNum; i++) {

   buildShip("afflictor_Strike");
}
randomNum = (int) (Math.random() * 6f + 1f);
    for (int i = 0; i < randomNum; i++) {

   buildShip("aurora_Balanced");
}
randomNum = (int) (Math.random() * 6f + 1f);
    for (int i = 0; i < randomNum; i++) {

   buildShip("buffalo_Standard");
}
randomNum = (int) (Math.random() * 6f + 1f);
    for (int i = 0; i < randomNum; i++) {

   buildShip("odyssey_Balanced");
}
randomNum = (int) (Math.random() * 6f + 1f);
    for (int i = 0; i < randomNum; i++) {

   buildFriendlyShip("aurora_Balanced");
}
hasSpawned = true;
        }
    }

    @Override
    public void init(CombatEngineAPI engine)
    {
        this.engine = engine;
    }
}
[close]
Logged
Please check out my SS projects :)
Xeno's Mod Pack

silentstormpt

  • Admiral
  • *****
  • Posts: 1060
    • View Profile
Re: The Radioactive Code Dump
« Reply #2 on: July 30, 2013, 12:44:49 PM »

No major changes on the main code on your Physics Fun, just made it an actual class that can be used by copy/paste into a file named data/scripts/plugins/PhysicsFun.java:

Code: java
package data.scripts.plugins;

import com.fs.starfarer.api.combat.CollisionClass;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.EveryFrameCombatPlugin;
import com.fs.starfarer.api.combat.MutableShipStatsAPI;
import com.fs.starfarer.api.combat.ShipAPI;

import java.util.List;
import java.util.ListIterator;

import org.lwjgl.util.vector.Vector2f;

/*
* Code by: xenoargh
*/

public class PhysicsFun implements EveryFrameCombatPlugin
{
    private CombatEngineAPI engine;

    @Override
    public void init(CombatEngineAPI engine)
    {
        this.engine = engine;
    }//INIT
    
    @Override
    public void advance(float amount, List events)
    {
        if (engine.isPaused()) return;
        
        ListIterator allships = engine.getShips().listIterator();
        
        if(allships.hasNext())
        {
             while(allships.hasNext())
             {
ShipAPI ship = (ShipAPI) allships.next();

if (ship.isFrigate())
{
ship.setCollisionClass(CollisionClass.FIGHTER);
continue;
}//IF

if (ship.isFighter() || ship.isShuttlePod() || ship.isFrigate() || ship.isDrone())
                            continue;//IF

//Gets the ship's velocity, expressed as a vector.
Vector2f shipVec = ship.getVelocity();
shipVec = (Vector2f) shipVec.scale(0.999f);
float shipSpeed = (float) Math.sqrt(Math.abs(shipVec.getX() * shipVec.getX()) + Math.abs(shipVec.getY() * shipVec.getY()));
MutableShipStatsAPI stats = ship.getMutableStats();
float maxSpeed = (float) stats.getMaxSpeed().getBaseValue();
float speedPenalty = Math.min(50f,(shipSpeed / maxSpeed) * 100.0f);
String id = ship.getFleetMemberId();
stats.getMaxTurnRate().unmodify(id);
stats.getTurnAcceleration().unmodify(id);
stats.getMaxTurnRate().modifyPercent(id,-speedPenalty);
stats.getTurnAcceleration().modifyPercent(id,-speedPenalty);

//public MutableStat getMaxTurnRate();
//public MutableStat getTurnAcceleration();

//Converts the player's heading (in degrees) back to unit vectors.
Vector2f rotVec = new Vector2f ((float) Math.cos(ship.getFacing() * 3.14159f / 180f), (float) Math.sin(ship.getFacing() * 3.14159f / 180f));
//Gets the "right" vector, i.e. perpendicular to the forward axis
Vector2f rightVec = new Vector2f(rotVec.getY() * -1.0f,rotVec.getX());
//Dot products of the two vectors
float dotForward = Vector2f.dot(shipVec, rotVec);
float dotRight = Vector2f.dot(shipVec, rightVec);
//Gives us the forward and rightward vectors of current velocity
Vector2f forwardVelocity = new Vector2f(rotVec.getX() * dotForward, rotVec.getY() * dotForward);
Vector2f rightVelocity = new Vector2f(rightVec.getX() * dotRight, rightVec.getY() * dotRight);
//Final conversion, drops the rightward component's magnitude while preserving the forward component.
//The multiplier 0.02f is our tuning variable; try different amounts to play with the "friction".
Vector2f.add(shipVec,new Vector2f(rightVelocity.getX() * -0.02f, rightVelocity.getY() * -0.02f),shipVec);

//This is an alternative behavior; it keeps forward velocity (towards the forward vector) constant but lowers...
//"right" velocity, resulting in a ship with an "inertialess" drive.  It might be useful for various behaviors.
//Commented out, because the above behavior is closer to classic land / sea movement.
//shipVec = shipVec.add(forwardVelocity,new Vector2f(rightVelocity.getX() * -0.02f, rightVelocity.getY() * -0.02f),shipVec);
}//WHILE
        }//IF
    }//ADVANCE
}//CLASS

Just a little more "non programmer friendly"
« Last Edit: October 02, 2013, 07:17:19 AM by silentstormpt »
Logged

silentstormpt

  • Admiral
  • *****
  • Posts: 1060
    • View Profile
Re: The Radioactive Code Dump
« Reply #3 on: August 02, 2013, 09:13:09 AM »

Critical Hit System

Requires LazyLib 1.5

What it does is, every projectile/missile (except beams) has a chance to crit depending on 3 Important factors:

  • DamageType must be HighExplosive or Energy;
  • Crew XP counts ALOT, a more experienced crew has a higher chance, a GREEN crew wont even have a chance to crit, this makes higher skilled crew much more desirable;
  • Depending on the weapons RoF, a higher RoF, lower the chance, this prevents mass crit barrages with fast weapons.

Every time a projectile crits, it will show a message on the poor soul who took that crit in a red text, theres also explosions and a smoke coming out of that spot where the projectile crits
Theres some extra code i left since it wont do any changes to the actual scripts intended purpose and its for a possible update on it.

To add this you just need to create a java file in the data/scripts/plugins/[name_of_the_script].java (without the []), dont forget to change on this part of the code as well
Code
public class [name_of_the_script] implements EveryFrameCombatPlugin
:

Code: java
package data.scripts.plugins;

import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.CollisionClass;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.DamageType;
import com.fs.starfarer.api.combat.DamagingProjectileAPI;
import com.fs.starfarer.api.combat.EveryFrameCombatPlugin;
import com.fs.starfarer.api.combat.MutableStat.StatMod;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ShipSystemAPI;
import com.fs.starfarer.api.combat.WeaponAPI;
import com.fs.starfarer.api.combat.WeaponAPI.WeaponSize;
import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Random;
import org.lazywizard.lazylib.CollisionUtils;
import org.lazywizard.lazylib.MathUtils;
import org.lazywizard.lazylib.combat.CombatUtils;
import org.lwjgl.util.vector.Vector2f;

/*
 * Multiple scripts from the following authors:
 * xangle13 for hes: http://fractalsoftworks.com/forum/index.php?topic=5819 and http://fractalsoftworks.com/forum/index.php?topic=6003.0
 * Psiyon for hes Original Crit System Script;
 * LazyWizard for hes IncendiaryAmmoPlugin, ArmorPiercePlugin and LazyLib 1.5;
 * Alex for helping me with a issue;
 * @author eXist3nZ
 */
public class [name_of_the_script] implements EveryFrameCombatPlugin
{
    // Combat Engine ofc
    private CombatEngineAPI engine;
    // Change this value for hull mods for example, original value is 5% Crit Chance
    public float PercCritChance = 0.05f;
    // CritDamage is 2 times the normal damage.
    public float CritDamage = 2f;
    // Sound to play while piercing a target's shield - Depending on size
    private static final Map SOUND_IDS_PENETRATION_SHIELD = new HashMap();
    static
    {
        SOUND_IDS_PENETRATION_SHIELD.put("Small", "explosion_ship");
        SOUND_IDS_PENETRATION_SHIELD.put("Medium", "explosion_ship");
        SOUND_IDS_PENETRATION_SHIELD.put("Large", "explosion_ship");
    }
    // Sound to play while piercing a target's armor - Depending on size (should be loopable!)
    private static final Map SOUND_IDS_PENETRATION_ARMOR = new HashMap();
    static
    {
        SOUND_IDS_PENETRATION_ARMOR.put("Small", "explosion_ship");
        SOUND_IDS_PENETRATION_ARMOR.put("Medium", "explosion_ship");
        SOUND_IDS_PENETRATION_ARMOR.put("Large", "explosion_ship");
    }
    // Sound on High Explosive explosion
    private static final Map SOUND_IDS_HE = new HashMap();
    static
    {
        SOUND_IDS_HE.put("isFrigate", "explosion_ship");
        SOUND_IDS_HE.put("isDestroyer", "explosion_ship");
        SOUND_IDS_HE.put("isCruiser", "explosion_ship");
        SOUND_IDS_HE.put("isCapital", "explosion_ship");
    }
    // Sound on Energy explosion
    private static final Map SOUND_IDS_ENERGY = new HashMap();
    static
    {
        SOUND_IDS_ENERGY.put("isFrigate", "explosion_ship");
        SOUND_IDS_ENERGY.put("isDestroyer", "explosion_ship");
        SOUND_IDS_ENERGY.put("isCruiser", "explosion_ship");
        SOUND_IDS_ENERGY.put("isCapital", "explosion_ship");
    }
    // Projectile ID (String), pierces shields (boolean)
    private static final List PROJ_IDS = new ArrayList();
    static
    {
        //add all the projectile ids that ignore shield
        PROJ_IDS.add("lw_impaler_shot");
    }
  
    @Override
    public void init(CombatEngineAPI engine) {
        this.engine = engine;
    }
  
    @Override
    public void advance(float amount, List events)
    {
        // Obvious exploit is obvious
        if (engine.isPaused())
        {
            return;
        }

        DamagingProjectileAPI proj;
        CombatEntityAPI entity;
        String spec;

        // Scan all shots on the map for armor piercing projectiles
        for (Iterator itproj = engine.getProjectiles().iterator(); itproj.hasNext();)
        {
            //Grab a projectile in the battlefield
            proj = (DamagingProjectileAPI) itproj.next();
            //Get its ID (the one in the *.proj file)
            spec = proj.getProjectileSpecId();
            
            // We'll do collision checks manually
            //proj.setCollisionClass(CollisionClass.NONE);

            // Find nearby ships, missiles and asteroids
            List toCheck = CombatUtils.getShipsWithinRange(proj.getLocation(),
                    proj.getCollisionRadius() + 5f);
            toCheck.addAll(CombatUtils.getMissilesWithinRange(proj.getLocation(),
                    proj.getCollisionRadius() + 5f));
            toCheck.addAll(CombatUtils.getAsteroidsWithinRange(proj.getLocation(),
                    proj.getCollisionRadius() + 5f));
            // Don't include the ship that fired this projectile!
            toCheck.remove(proj.getSource());
            
            if(proj != null)
            {
                for (Iterator iter2 = toCheck.iterator(); iter2.hasNext();)
                {
                    entity = (CombatEntityAPI) iter2.next();

                    // Check for an active phase cloak
                    if (entity instanceof ShipAPI)
                    {
                        ShipSystemAPI cloak = ((ShipAPI) entity).getPhaseCloak();

                        if (cloak != null && cloak.isActive())
                        {
                            continue;
                        }//IF
                    }//IF

                    // Check for a shield hit
                    if ((entity.getShield() != null
                            && entity.getShield().isOn()
                            && entity.getShield().isWithinArc(proj.getLocation())))
                    {
                        ListIterator projlist = PROJ_IDS.listIterator();

                        while(projlist.hasNext())
                        {                                
                            if(projlist.next().equals(spec))
                            {
                                // Save the CollisionClass
                                CollisionClass projCollision = proj.getCollisionClass();
                                // If we hit a shield, disable collision
                                proj.setCollisionClass(CollisionClass.NONE);
                                // Stop the projectile (ensures a hit for fast projectiles)
                                proj.getVelocity().set(entity.getVelocity());
                                // Then move the projectile inside the ship's shield bounds
                                Vector2f.add((Vector2f) MathUtils.getDirectionalVector(proj,entity).scale(5f), proj.getLocation(), proj.getLocation());
                                // Give back its original Collision
                                proj.setCollisionClass(projCollision);
                                // Play piercing sound (depends on the weapon size)
                                Global.getSoundPlayer().playSound(SOUND_IDS_PENETRATION_SHIELD.get(proj.getWeapon().getSize().getDisplayName()).toString(),
                                        1f,
                                        1f,
                                        proj.getLocation(),
                                        proj.getVelocity());
                            }
                        }
                    }
                    // Check if the projectile is inside the entity's bounds
                    else if (CollisionUtils.isPointWithinBounds(proj.getLocation(), entity))
                    {  
                        //Is this a ship or a asteroid (dont forget asteroids can only be a CombatEntity)
                        if(critSucessfull(proj) && entity instanceof ShipAPI)
                        {
                            shipHitEffect ((ShipAPI) entity,  proj);
                        }//IF
                        else
                        {
                            continue;
                        }
                    }//IF
                }//FOR
            }//IF
        }//FOR
    }//advance
    
    public boolean critSucessfull(DamagingProjectileAPI damagingproj)
    {
        Random r = new Random();
        WeaponAPI weapon = damagingproj.getWeapon();
        float crewMaxXP = 0f;
        
        if(weapon.getDamageType().equals(DamageType.FRAGMENTATION) ||
                weapon.getDamageType().equals(DamageType.KINETIC) ||
                weapon.getDamageType().equals(DamageType.OTHER))
        {
            return false;
        }
        
        ShipAPI ship = damagingproj.getSource();
        float weaponRoF = weapon.getDerivedStats().getRoF();
          
        StatMod crewBonus = ship.getMutableStats().getAutofireAimAccuracy().getFlatStatMod("crew skill bonus");
        
        // Green crew don't grant a bonus
        if (crewBonus != null)
        {
            //Goes from 0f to 1f - thanks Alex and Lazy for the help
            crewMaxXP = crewBonus.getValue();
        }
        
        //slower shooting weapons should not surpass limit of 5%
        if (weaponRoF < 1f)
        {
            weaponRoF = 1f;
        }
        
        float CritChance = r.nextFloat();
        //This means that, if the crew is elite its (0.05f * 1) \ 1 that means 5%,
        //if the crew is actually lower skilled and the weapon's RoF is higher the chances get lower.
        float MAXCritChance = (PercCritChance * crewMaxXP) / weaponRoF;
        
        if(CritChance <= MAXCritChance)
        {
            return true;
        }
        else
        {
            return false;
        }
    }//critSucessful
    
    public void shipHitEffect (ShipAPI ship, DamagingProjectileAPI proj)
    {
        WeaponAPI weapon = proj.getWeapon();
        float explosionSize = 0f;
        float weaponRoF = weapon.getDerivedStats().getRoF();
        
        //Lets make sure we dont get a REALLY HUGE Crit text
        if (weaponRoF < 1f)
        {
            weaponRoF = 1f;
        }
        
        if(weapon.getSize().equals(WeaponSize.SMALL))
        {
            explosionSize = MathUtils.getRandomNumberInRange(20f, 30f) / weaponRoF;
        }
        else if(weapon.getSize().equals(WeaponSize.MEDIUM))
        {
            explosionSize = MathUtils.getRandomNumberInRange(30f, 40f) / weaponRoF;
        }
        else if(weapon.getSize().equals(WeaponSize.LARGE))
        {
            explosionSize = MathUtils.getRandomNumberInRange(40f, 50f) / weaponRoF;
        }
        
        engine.addFloatingText(proj.getLocation(), "CRITICAL HIT", explosionSize, Color.RED, proj.getDamageTarget(), 0f, 0f);
        
        if(weapon.getDamageType().equals(DamageType.HIGH_EXPLOSIVE))
        {
            if(ship.isFrigate()) {  
                explosionEffects(ship,
                        proj,
                        weapon.getDamageType(),
                        SOUND_IDS_HE.get("isFrigate").toString(),
                        explosionSize);
            }
            else if(ship.isDestroyer()) {
                explosionEffects(ship,
                        proj,
                        weapon.getDamageType(),
                        SOUND_IDS_HE.get("isDestroyer").toString(),
                        explosionSize);
            }
            else if(ship.isCruiser()) {
                explosionEffects(ship,
                        proj,
                        weapon.getDamageType(),
                        SOUND_IDS_HE.get("isCruiser").toString(),
                        explosionSize);
            }
            else if(ship.isCapital()) {
                explosionEffects(ship,
                        proj,
                        weapon.getDamageType(),
                        SOUND_IDS_HE.get("isCapital").toString(),
                        explosionSize);
            }
        }
        else if(weapon.getDamageType().equals(DamageType.ENERGY))
        {
            if(ship.isFrigate()) {  
                explosionEffects(ship,
                        proj,
                        weapon.getDamageType(),
                        SOUND_IDS_ENERGY.get("isFrigate").toString(),
                        explosionSize);
            }
            else if(ship.isDestroyer()) {
                explosionEffects(ship,
                        proj,
                        weapon.getDamageType(),
                        SOUND_IDS_ENERGY.get("isDestroyer").toString(),
                        explosionSize);
            }
            else if(ship.isCruiser()) {
                explosionEffects(ship,
                        proj,
                        weapon.getDamageType(),
                        SOUND_IDS_ENERGY.get("isCruiser").toString(),
                        explosionSize);
            }
            else if(ship.isCapital()) {
                explosionEffects(ship,
                        proj,
                        weapon.getDamageType(),
                        SOUND_IDS_ENERGY.get("isCapital").toString(),
                        explosionSize);
            }
        }
    }//shipHitEffect
    
    public void explosionEffects (ShipAPI ship, DamagingProjectileAPI proj, DamageType dmgtype, String ExplosionSoundID, float explosionSize)
    {
        if(dmgtype.equals(DamageType.HIGH_EXPLOSIVE))
        {
            float damage = proj.getDamageAmount() * CritDamage;
            float emp = proj.getEmpAmount() * CritDamage;

            // Apply damage and slow the projectile
            // Note: BALLISTIC_AS_BEAM projectiles won't be slowed!
            engine.applyDamage(ship,
                    proj.getLocation(), damage, proj.getDamageType(),
                    emp, true, true, proj.getSource());

            proj.getVelocity().scale(1.5f - 1.0f);
            
            engine.spawnExplosion(
                    proj.getLocation(),
                    ship.getVelocity(),
                    Color.ORANGE,
                    1f,
                    1.5f);

            // Play Explosion sound
            Global.getSoundPlayer().playSound(ExplosionSoundID,
                    1f,
                    1f,
                    proj.getLocation(),
                    ship.getVelocity());

            if(!ship.isHulk())
            {
                engine.addSmokeParticle(ship.getLocation(), // Location
                        ship.getVelocity(), // Velocity
                        explosionSize, // Size
                        MathUtils.getRandomNumberInRange(.5f, .75f), // Brightness
                        10f, Color.DARK_GRAY); // Duration, color
            }
        }
        else if(dmgtype.equals(DamageType.ENERGY))
        {
            float damage = proj.getDamageAmount() * CritDamage;
            float emp = proj.getEmpAmount() * CritDamage;

            // Apply damage and slow the projectile
            // Note: BALLISTIC_AS_BEAM projectiles won't be slowed!
            engine.applyDamage(ship,
                    proj.getLocation(),
                    damage,
                    proj.getDamageType(),
                    emp,
                    true,
                    true,
                    proj.getSource());

            proj.getVelocity().scale(1.5f - 1.0f);
            
            engine.spawnExplosion(
                    proj.getLocation(),
                    ship.getVelocity(),
                    Color.blue,
                    1f,
                    1.5f);

            // Play Crit Explosion
            Global.getSoundPlayer().playSound(ExplosionSoundID,
                    1f,
                    1f,
                    proj.getLocation(),
                    ship.getVelocity());

            if(!ship.isHulk())
            {
                engine.addSmokeParticle(ship.getLocation(), // Location
                        ship.getVelocity(), // Velocity
                        explosionSize, // Size
                        MathUtils.getRandomNumberInRange(.5f, .75f), // Brightness
                        10f, Color.DARK_GRAY); // Duration, color
            }
        }
    }//explosionEffects
}//MAIN CLASS

Major thanks for alot of ppl, specially Lazy for helping out and release the 1.5 LazyLib.

This script can be "upgraded easily".

EDIT: I've updated the Script, it now takes in account the weapon size, the crit text size depending on how much damage did that Crit do to the ship.
EDIT2: Also fixed a calculation error i hadn't noticed before at the time, some lower RoF weapons had huge crit chance do to being lower then 1
« Last Edit: October 02, 2013, 07:18:56 AM by silentstormpt »
Logged

Thule

  • Admiral
  • *****
  • Posts: 580
    • View Profile
Re: The Radioactive Code Dump
« Reply #4 on: August 02, 2013, 12:24:49 PM »

There a a couple of those code example threads flying around on the forum, could a mod compile them into a single thread?
Otherwise i fear alot of cool stuff gets lost and burried.
Logged

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: The Radioactive Code Dump
« Reply #5 on: August 02, 2013, 01:59:35 PM »

I love the critical hit system idea, can't wait to read through that one :)
Logged
Please check out my SS projects :)
Xeno's Mod Pack

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: The Radioactive Code Dump
« Reply #6 on: August 02, 2013, 09:42:16 PM »

The Freeze Ray.  Slows down Entities that are hit.  With enough of them, you can immobilize anything. 

Never see a pesky Frigate run away again!  Muahahahahaha... er, I mean, it works, and stuff.  Can't wait to release my mod now, these are just a few of the toys ;)

Spoiler
Code
package data.scripts;

import java.awt.Color;

import org.lwjgl.util.vector.Vector2f;

import com.fs.starfarer.api.combat.BeamAPI;
import com.fs.starfarer.api.combat.BeamEffectPlugin;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.ShipAPI;

public class FreezeRayEffect implements BeamEffectPlugin {
public void advance(float amount, CombatEngineAPI engine, BeamAPI beam) {
CombatEntityAPI target = beam.getDamageTarget();
//Do we have a valid Entity to effect?
if (target != null)
{
//Yes!  Is it in range, and the beam's on?
if (beam.getBrightness() >= 1f)
{
//Get the velocity, and drop it- bigger ships drop a lot less than small ones.
//This might not be balanced for your mod.  The accumulative change in velocity per-frame is really huge!
Vector2f targVel = target.getVelocity();
if(target instanceof ShipAPI)
{
ShipAPI ship = (ShipAPI) target;
if(ship.isDrone())
{
targVel.x *= 0.75f;
targVel.y *= 0.75f;
} else if (ship.isFighter())
{
targVel.x *= 0.95f;
targVel.y *= 0.95f;
} else if (ship.isFrigate())
{
targVel.x *= 0.97f;
targVel.y *= 0.97f;
} else if (ship.isDestroyer())
{
targVel.x *= 0.99f;
targVel.y *= 0.99f;
} else if (ship.isCruiser())
{
targVel.x *= 0.995f;
targVel.y *= 0.995f;
} else if (ship.isCapital())
{
targVel.x *= 0.999f;
targVel.y *= 0.999f;
}
} else {
//If not a ship, slow down a lot.  Instant slowdown for bombs, takes just a few frames for most missiles.
targVel.x *= 0.75f;
targVel.y *= 0.75f;
}
}
}
}
}
[close]
Logged
Please check out my SS projects :)
Xeno's Mod Pack

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: The Radioactive Code Dump
« Reply #7 on: August 02, 2013, 10:10:38 PM »

Fixed version of the Critical Hit system; uses larger text if the damage is heavy, loses a few operations it didn't need, uses the correct formula for Rate of Fire.

Spoiler
Code
//Silentstormpt's Critical Hit system, v. 2.0, xenoargh build
//Credits to Silentstormpt, xangle13, Psyion, LazyWizard, xenoargh, eXist3nz, Alex
package data.scripts.plugins;

import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.DamageType;
import com.fs.starfarer.api.combat.DamagingProjectileAPI;
import com.fs.starfarer.api.combat.EveryFrameCombatPlugin;
import com.fs.starfarer.api.combat.MutableStat.StatMod;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ShipSystemAPI;
import com.fs.starfarer.api.combat.WeaponAPI;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Random;
import org.lazywizard.lazylib.CollisionUtils;
import org.lazywizard.lazylib.MathUtils;
import org.lazywizard.lazylib.combat.CombatUtils;
import org.lwjgl.util.vector.Vector2f;


public class CriticalHits implements EveryFrameCombatPlugin
{
private CombatEngineAPI engine;
// Sound to play while piercing a target's armor (should be loopable!)
private static final String PIERCE_SOUND = "explosion_ship"; // TEMPORARY

public void init(CombatEngineAPI engine) {
this.engine = engine;
}

public void advance(float amount, List events)
{
// Obvious exploit is obvious
if (engine.isPaused())
{
return;
}

DamagingProjectileAPI proj;
CombatEntityAPI entity;
String spec;

// Scan all shots on the map for armor piercing projectiles
for (Iterator itproj = engine.getProjectiles().iterator(); itproj.hasNext();)
{
//Grab a projectile in the battlefield
proj = (DamagingProjectileAPI) itproj.next();

//Did this projectile do damage to an Entity?
if(proj.didDamage() && proj.getDamageTarget() != null)
{
//Get the entity hit
entity = (CombatEntityAPI) proj.getDamageTarget();

// Check to make sure we've hit a ship, and if so, for a shield hit; if we hit a ship's shield or a non-ship, stop!
if(entity instanceof ShipAPI && entity.getShield() == null || entity instanceof ShipAPI && !entity.getShield().isOn() || entity instanceof ShipAPI && !entity.getShield().isWithinArc(proj.getLocation()))
{
spec = proj.getProjectileSpecId();
if(critSucessful(proj))
{
//If Shuttle, stop right now!
if(((ShipAPI) entity).isShuttlePod())
{
continue;
}
//Random damage from crits
amount = MathUtils.getRandomNumberInRange(2f,5f);

float damage = (proj.getDamageAmount() * amount);
float emp = (proj.getEmpAmount() * amount);

Vector2f projVel = proj.getVelocity();
Vector2f projPos = proj.getLocation();

engine.applyDamage(entity,
projPos, damage, proj.getDamageType(),
emp, true, true, proj.getSource());


engine.addFloatingText(projPos, "CRIT!", Math.min(Math.max(20f,damage/200f),50f), Color.RED, entity, 0f, 0f);
//Create particle bursts only for big crits
if(damage > 1500f)
{
for(int i = 0; i < 30; i++)
{
//Invert the vector and randomize a little bit
float randX = MathUtils.getRandomNumberInRange(-60f,60f);
float randY = MathUtils.getRandomNumberInRange(-60f,60f);
Vector2f newVel = new Vector2f (randX - projVel.x / 3f, randY - projVel.y / 3f);
int randYel = (int) MathUtils.getRandomNumberInRange(64f,200f);
engine.addHitParticle(projPos, newVel, MathUtils.getRandomNumberInRange(5f,8f), 1f, MathUtils.getRandomNumberInRange(3f,7f), new Color(255,randYel,0,127));
}
}

}//IF    
}//IF
}//FOR
}//FOR
}//advance

public boolean critSucessful(DamagingProjectileAPI damagingproj)
{
Random r = new Random();
WeaponAPI weapon = damagingproj.getWeapon();
float MAXCritChance = 0.05f; // change this value for hull mods for example, original value is 5%
float crewMaxXP = 0f;
//Safety code, catches null pointer exception
if(weapon == null || weapon.getDamageType() == null) return false;
//If the weapon can't crit, it stops here
if(weapon.getDamageType().equals(DamageType.FRAGMENTATION) ||
weapon.getDamageType().equals(DamageType.ENERGY) ||
weapon.getDamageType().equals(DamageType.OTHER))
{
return false;  //No crit for u!
}

//Where did this shot come from?
ShipAPI ship = damagingproj.getSource();
float weaponRoF = weapon.getDerivedStats().getRoF() * 4f;//Balance here; crits should be really rare for high-RoF weapons

StatMod crewBonus = ship.getMutableStats().getAutofireAimAccuracy().getFlatStatMod("crew skill bonus");
// Green crew don't grant a bonus
if (crewBonus != null)
{
crewMaxXP = crewBonus.getValue(); //goes from 0f to 1f - thanks Alex and Lazy for the help
}

//Get our random number
float CritChance = r.nextFloat();

//Crit chance never goes above the max / min values here.
if(CritChance <= Math.min(Math.max((MAXCritChance * crewMaxXP) / weaponRoF,0.001f),0.05f))
{

return true;  //We got a crit, send it back!
} else {
return false;  //Failed...
}
}//critSucessful
}//MAIN CLASS
[close]
« Last Edit: August 22, 2013, 08:49:29 PM by xenoargh »
Logged
Please check out my SS projects :)
Xeno's Mod Pack

Thule

  • Admiral
  • *****
  • Posts: 580
    • View Profile
Re: The Radioactive Code Dump
« Reply #8 on: August 03, 2013, 01:44:07 AM »

The Freeze Ray.  Slows down Entities that are hit.  With enough of them, you can immobilize anything. 

Never see a pesky Frigate run away again!  Muahahahahaha... er, I mean, it works, and stuff.  Can't wait to release my mod now, these are just a few of the toys ;)

Spoiler
Code
package data.scripts;

import java.awt.Color;

import org.lwjgl.util.vector.Vector2f;

import com.fs.starfarer.api.combat.BeamAPI;
import com.fs.starfarer.api.combat.BeamEffectPlugin;
import com.fs.starfarer.api.combat.CombatEngineAPI;
import com.fs.starfarer.api.combat.CombatEntityAPI;
import com.fs.starfarer.api.combat.ShipAPI;

public class FreezeRayEffect implements BeamEffectPlugin {
public void advance(float amount, CombatEngineAPI engine, BeamAPI beam) {
CombatEntityAPI target = beam.getDamageTarget();
//Do we have a valid Entity to effect?
if (target != null)
{
//Yes!  Is it in range, and the beam's on?
if (beam.getBrightness() >= 1f)
{
//Get the velocity, and drop it- bigger ships drop a lot less than small ones.
//This might not be balanced for your mod.  The accumulative change in velocity per-frame is really huge!
Vector2f targVel = target.getVelocity();
if(target instanceof ShipAPI)
{
ShipAPI ship = (ShipAPI) target;
if(ship.isDrone())
{
targVel.x *= 0.75f;
targVel.y *= 0.75f;
} else if (ship.isFighter())
{
targVel.x *= 0.95f;
targVel.y *= 0.95f;
} else if (ship.isFrigate())
{
targVel.x *= 0.97f;
targVel.y *= 0.97f;
} else if (ship.isDestroyer())
{
targVel.x *= 0.99f;
targVel.y *= 0.99f;
} else if (ship.isCruiser())
{
targVel.x *= 0.995f;
targVel.y *= 0.995f;
} else if (ship.isCapital())
{
targVel.x *= 0.999f;
targVel.y *= 0.999f;
}
} else {
//If not a ship, slow down a lot.  Instant slowdown for bombs, takes just a few frames for most missiles.
targVel.x *= 0.75f;
targVel.y *= 0.75f;
}
}
}
}
}
[close]

Xeno, may i use this for tl? modified of course ^^
Logged

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: The Radioactive Code Dump
« Reply #9 on: August 07, 2013, 02:28:25 PM »

Absolutely, that's why it's posted here :)
Logged
Please check out my SS projects :)
Xeno's Mod Pack

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: The Radioactive Code Dump
« Reply #10 on: August 22, 2013, 08:50:11 PM »

Updated the Critical Hit code.  Thanks to Silentstormpt for pointing out some things that could still be improved :)
Logged
Please check out my SS projects :)
Xeno's Mod Pack

Okim

  • Admiral
  • *****
  • Posts: 2161
    • View Profile
    • Okim`s Modelling stuff
Re: The Radioactive Code Dump
« Reply #11 on: August 22, 2013, 09:58:15 PM »

I might use the 'Freese Beam' if it`s author doesn`t mind.

xenoargh

  • Admiral
  • *****
  • Posts: 5078
  • naively breaking things!
    • View Profile
Re: The Radioactive Code Dump
« Reply #12 on: August 22, 2013, 10:03:11 PM »

Haven't had time to clean it up enough for posting here, but I'm pretty sure it's non-buggy and efficient, so feel free :)
Logged
Please check out my SS projects :)
Xeno's Mod Pack

Gotcha!

  • Admiral
  • *****
  • Posts: 1124
    • View Profile
    • Welcome to New Hiigara
Re: The Radioactive Code Dump
« Reply #13 on: August 31, 2013, 09:51:29 AM »

I've got a stupid question. How would one attach the critical hit system to a weapon? :-[
Or does this script enable critical hits for every weapon in the mod?

Edit: After testing I see that this script gives all weapons this ability. Would it be possible to limit it to a specific weapon? :)
« Last Edit: August 31, 2013, 10:39:34 AM by Gotcha! »
Logged
  

silentstormpt

  • Admiral
  • *****
  • Posts: 1060
    • View Profile
Re: The Radioactive Code Dump
« Reply #14 on: August 31, 2013, 10:48:08 AM »

I've got a stupid question. How would one attach the critical hit system to a weapon? :-[
Or does this script enable critical hits for every weapon in the mod?

Edit: After testing I see that this script gives all weapons this ability. Would it be possible to limit it to a specific weapon? :)

Yes and no, it does work on every weapon except for beam weapons, it also only affects High Explosive and Energy damage types. As for the limit for a weapon, might as well make a OnHit script, its alot less CPU intensive.
Logged
Pages: [1] 2 3 ... 10