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)

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Mongreal

Pages: [1] 2 3 4
1
Modding / Re: [0.9.1a] Star Conquest (WIP)
« on: June 15, 2020, 11:08:50 AM »
I'm bookmarking thoses links for ulterior consultation, thanks.

Already running on IntelliJ since the first attempt at scripting, most of the stuff I try out is made that way, even if, most of the time, I don't really know what I'm doing (even when looking in the API doc). My guess is that most of my mistakes comes from a wrong understanding of the engine or misordered loops and "if".

I joined the Discord, dunno when I'll try to ask around there, probably next time I end up stuck on something for a week.
Yeah, using any graphics rendering with hullmod seems pretty complicated, even from first glance x)

Thanks for the answer, by the way

2
Modding / Re: [0.9.1a] Star Conquest (WIP)
« on: June 15, 2020, 08:06:40 AM »
What help did you need? You can PM me if you have questions or I'll try and check this thread every once in a while.

I've heard discord has a dedicated learning section as well where you can ask questions and get help from experienced modders, but I haven't really checked that out yet myself.

Hmm, actually the mod has some flesh (there is about 65 unique ships in total), the main help I'll need is on both the scripting for non-vanilla weapons, hullmod and systems effects, as well as everything that on the campaign side, adding new star systems, planets, fleets, faction and such, has I mainly focused on ships and weapons since the beginning in 2017. If what you have seen in the main post seems interesting to you, I'll gratefully accept your help when I end up stuck on some scripts

Where can I find the Discord link ? That may help a lot too, since I'm always connected when I'm working on the mod, that'll be helpfull too !

3
Modding / Re: [0.9.1a] Star Conquest (WIP)
« on: June 14, 2020, 01:09:20 PM »
Hi there.

I haven't been working on this since a few months (I'm really just going back and forth with it, depending on how work's going on my side).
While it's slow, it's still progressing, sprite after sprite and script failure after script failure.
On this point, if anyone's interested and kind enough to teach me some tricks, I have to admit that I really need it. Scripting easy stuff seems fine, but anything beside projectile spawning is trully out of my reach.

Edit : I'm well aware of the problem with names in this mod. I'll work on it before any release, which could take a while, since there is some stuff I'd like to ask to other mod authors, and still a long way to go for two of the four planned factions.

4
You could script autofire AI, but not when the weapon is fired by the ship "manually". I have no idea what the AI will do with a PULSE weapon - that's not supported, so it might do as you surmise, might shoot with random charge levels, or might not shoot at all (i.e. it might just hold down the button and keep it at full charge).

The AI only cares about more dangerous projectiles; for other stuff it'll (depending on various factors) just look at the weapon - where it's facing, whether it's firing, etc.

I'll try to make it so that the weapon always fire when reaching the max charge level, so, as long as the AI at least try to fire it, something should happen (hopefully ?)
While I'm busy trying to make this work, another tricky subject : Is there a way to use a station module as a "shield" for it's parent ? As in, making it so that it can't take real damage, but transfer the damage taken as shield damage (hard flux) on the parent ? It look easier with module since they already use collisions and bounds.

5
Hmm, offhand, I'm not quite sure. I mean, you could have the weapon script launch a custom effect/shot and have the normal weapon shot be entirely invisible, so that might be the way to go. Regardless, though, the ship AI won't be aware of it - either using this or defending against it - so it seems... well, it could be alright in some specific circumstances, but you'd want to be very careful it doesn't become something that can easily cheese the AI because it doesn't know about it.

Oh, I see how that could work. I already played a bit with projectile spawning so that wouldn't be too hard to script. Isn't there a way to script special weapon AI ? My guess about this is that the AI will always go for the full charged shot, so, while it won't be able to fire weaker shot at a faster rate, it'll still deal the same average DPS over a complete combat length ?
Hmm, so the AI isn't alawys aware of script spawned projectiles ?

6
Pulse weapons are extremely deprecated so I'd recommend not using them. Unless you just mean adding a chargeup time  to a weapon firing? Or do you mean the (very, very old) "hold button to charge, release to fire" behavior?

It's the old behavior that I'm referencing, yes. I've been trying different script on some weapon so that their effect varies depending on the charge level before the shot (my mains attempts were : increasing the speed and range for a large kinetic railgun, increasing the explosive power and adding some AoE to a large explosive artillery, and more recently, I tried using the charge level to increase the size of the burst fired by a medium fragmentation weapon, a sort of volleygun which could either fire a few rounds at a time at a quick firerate, or a large batch of projectile if charged for some time).

Is there actually a way to make this work, even with scripting ? I don't really know how, maybe checking the charging rate to spot the frame where its decreasing, meaning that the fire button has been released ? But then, can I make a weapon fire by forcing its charge level to 1 ?

7
Hello,

I'm back on Starsector modding once again, and I was wondering how does pulse weapons works, and if there was a way to use the pulse charging effect on non pulse weapon, like a ballistic artillery. Is there an easy way around ?
Or would that involve scripting a custom behavior for the weapon as en everyframe effect (I guess checking for the charge level until it get back to 0 could work for the percentage of charge, but how can I make a weapon fire with a everyframe plugin ?)
If anyone is familiar with thoses things, feel free to pm me, thanks !

8
Modding Resources / Re: [0.9.1] MagicLib v0.28 (2019/11/09)
« on: January 07, 2020, 11:31:41 AM »
Well, in my case, I'm using this :
Spoiler
Code
            vSize = new Vector2f(sprite.getWidth() * modifier, sprite.getHeight() * modifier);
            vGrowth = new Vector2f(2f * modifier, 2f * modifier);
            vVelocity = new Vector2f(burstSpread / 2f * modifier, burstRange / 2f * modifier);
            //VectorUtils.rotateAroundPivot(vVelocity, barrelLocation, weapon.getCurrAngle());
            MagicRender.battlespace(sprite,
                    barrelLocation,
                    vVelocity,
                    vSize,
                    null,
                    weapon.getCurrAngle() - 90f,
                    0f,
                    flashColor,
                    true,
                    0.15f,
                    0.25f,
                    0.05f
            );
[close]
as part of a EveryFrameWeaponEffectPlugin.
This particular battlespace is called with each shot of the weapon itself (which may be the problem but I'll wait for your answer).
Each shot fired from the magazine of the gun increase the modifier value, which add an unknown value to the original size, growth speed, and velocity, if I'm not mistaken.
On the next shot, the size of the sprite doesn't goes back to the initial witdh and height set by the vSize variable : The sprite stays bigger until the last round of this magazine, which suddenly pushes the size to extreme values (should multiply it but 1.5 or 1.8, but instead, the sprite fill the entire screen).
Does the battlespace stay "active" between two reading of this section, and thus, doesn't get "reset" anywhere ? From what I tried, I can only assume that the MagicRender.battlespace shouldn't be use this way on everyframe stuff ? Can I achieve something like this with singleframe instead ?
If you don't mind, I can give you my discord on mp. I don't know if you remember me, but I used to chat with you on Skype three years ago. And, I'm french too, by the way.

9
Modding Resources / Re: [0.9.1] MagicLib v0.28 (2019/11/09)
« on: January 06, 2020, 01:17:55 PM »
What does growth affect on MagicRender.battlespace ? When does growth and size get reset ?

10
Hmm - it's kind of hard to tell what the issue actually is.

Does it still happen if you don't assign this AI to the missile and it hits something?

The code that actually spawns this missile could also be useful to see, if it's spawned with code and not fired from a weapon.

Another test would be to fire it from a weapon to see if that makes it work or not; that'd also narrow down the possibilities.

It doesn't happen when this AI isn't used by the projectile, I made some mistakes with some new attempts and in some of them I forgot to remove the AI from the comments of the ModPlugin...

The missile itself is fired from a weapon, and the results (without taking into account the guidance stuff which sometimes come off "weird") are thoses outcomes :
The missile fly like any other missile and aim for the targetLocation ; Nothing crashes here.
The missile is fired by the weapon, the second missile is spawned using the AI, and then, the original missile is removed. The spawned missile flameout before hitting it's target and it doesn't matter if its hit it or not ; Nothing crashes either.
The missile is fired normaly, the second missile spawn in and the original one is removed, but this time, the spawned missile hit before the flameout ; The game crash and dump the log I sent.

I'm wondering if removing the missile that run the new AI doesn't messes with the spawned projectile, as the spawned projectile source si the same as the missile removed, does removing the original missile also make the source of the second invalid ?
I'm going to try "moving" the missile instead of spawning a new one and deleting the older one : Still work like a teleportation if I prevent any colliding while it's moving, right ?

Edit : Well, moving the projectile seems fine, problem solved.

11
Hi everyone,

I'm back again with yet another script error.
I tried to mess a bit with missile IA :
Spoiler
Code
package data.scripts.ai;

import com.fs.starfarer.api.Global;
import com.fs.starfarer.api.combat.*;
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.GuidedMissileAI;
import com.fs.starfarer.api.combat.MissileAIPlugin;
import com.fs.starfarer.api.combat.MissileAPI;
import com.fs.starfarer.api.combat.ShipAPI;
import com.fs.starfarer.api.combat.ShipCommand;
import org.lazywizard.lazylib.MathUtils;
import java.awt.Color;
import java.util.List;

import org.lazywizard.lazylib.VectorUtils;
import org.lazywizard.lazylib.combat.AIUtils;
import org.lwjgl.util.vector.Vector2f;
import com.fs.starfarer.api.util.Misc;
import com.fs.starfarer.api.util.WeightedRandomPicker;
import data.scripts.util.MagicLensFlare;
import org.lazywizard.lazylib.MathUtils;
import org.lazywizard.lazylib.combat.AIUtils;


public class SCQ_LongbowMissileAI implements MissileAIPlugin, GuidedMissileAI {

    private static final Color JITTER_COLOR = new Color(143, 169,255,75);
    private static final Color JITTER_UNDER_COLOR = new Color(123, 144,255,155);
   
    private CombatEngineAPI engine;
    public WeaponAPI weapon;
    private List<MissileAPI> missiles;
    private MissileAPI missile;
    private ShipAPI ship,
            launchingShip;
    private CombatEntityAPI target;
    private Vector2f targetLocation;
    private boolean runOnce = false;
    private String missileId = "LNC_waver_CN_mrm",
            missileTeleporterId = "LNC_longbow_waver_mrm_teleporter",
            teleportedMissileId = "LNC_waver_teleported";
    private float minTeleportRange = 1500.0f,
            jitterMinLevel = 20.0f,
            fluxIncrease = 200.0f,
            missileRange,
            teleportRange,
            targetRange,
            jitterLevel;

    //////////////////////
    //  DATA COLLECTING //
    //////////////////////

    public SCQ_LongbowMissileAI(MissileAPI missile, ShipAPI launchingShip) {
        this.missile = missile;
        this.ship = launchingShip;
        this.weapon = missile.getWeapon();
        missileRange = missile.getMaxFlightTime() * missile.getMaxSpeed();
        missileRange = MathUtils.clamp(missileRange, 2500f, 3000f);
        teleportRange = missile.getWeapon().getRange() - missileRange ;
        teleportRange = MathUtils.clamp(teleportRange, 7000f, 10000f);
        runOnce = false;
        if (engine != Global.getCombatEngine()) {
            engine = Global.getCombatEngine();
        }
    }
   
    //////////////////////
    //   MAIN AI LOOP   //
    //////////////////////
   
    @Override
    public void advance(float amount) {
        //skip the AI if the game is paused, the missile is engine-less or fading
        if (engine == null) { //  || engine.isPaused() || missile.isFading() || missile.isFizzling()
                return;
            }
        if(missile != null && (missile.isFizzling() || missile.isFading() || missile.getFlightTime() > missile.getMaxFlightTime())){
            // Vector2f loc, Vector2f vel, Color color, float size, float duration
            engine.spawnExplosion(missile.getLocation(), missile.getVelocity(), new Color(112, 198, 240,200), 15f, 8f);
            //public void applyDamage(CombatEntityAPI entity, Vector2f point, float damageAmount, DamageType damageType, float empAmount, boolean bypassShields, boolean dealsSoftFlux, Object source)
            engine.applyDamage(missile, missile.getLocation(), missile.getHitpoints() * 2, DamageType.FRAGMENTATION, 0, true, false, missile.getSource());
            engine.removeEntity(missile);
            return;
        }
        //variables
        if (targetLocation == null) {
            if (ship.getMouseTarget() != null || !MathUtils.isWithinRange(missile.getLocation(), ship.getMouseTarget(), minTeleportRange)) {
                targetLocation = ship.getMouseTarget();
            } else if (ship.getShipTarget() != null && ship.getShipTarget().getLocation() != null) {
                targetLocation = ship.getShipTarget().getLocation();
            } else if (missile != null && AIUtils.getNearestEnemy(missile) != null) {
                targetLocation = AIUtils.getNearestEnemy(missile).getLocation();
            }
            targetRange = Misc.getDistance(missile.getLocation(), targetLocation);
            if (targetLocation != null) {
                if (targetRange > teleportRange) {
                    float dir = Misc.getAngleInDegrees(missile.getLocation(), targetLocation);
                    targetLocation = Misc.getUnitVectorAtDegreeAngle(dir);
                    targetLocation.scale(teleportRange);
                    Vector2f.add(targetLocation, missile.getLocation(), targetLocation);
                }
                targetLocation = findClearLocation(missile, targetLocation);
            }
        }
        if (!runOnce) {
            if (ship.getCurrFlux() + fluxIncrease >= ship.getMaxFlux() || targetRange < minTeleportRange) {
                Global.getSoundPlayer().playSound("short_range_lauch", 0.8f, 1.2f, ship.getLocation(), new Vector2f(0, 0));
                runOnce = true;
                return;
            } else if (targetLocation != null) { // && (missileRange + teleportRange >= targetRange)
                Global.getSoundPlayer().playSound("system_phase_skimmer", 0.8f, 1.2f, ship.getLocation(), new Vector2f(0,0));
                ship.getFluxTracker().setCurrFlux(ship.getCurrFlux() + fluxIncrease);
                teleportOnce(amount, missile, targetLocation);
                jitterLevel = jitterMinLevel * 1 + (ship.getCurrFlux() / ship.getMaxFlux());
                missile.setJitter(missile, JITTER_COLOR, jitterLevel, 4, 0f, 0 + (ship).getCurrFlux() / ship.getMaxFlux());
                runOnce = true;
                engine.removeEntity(missile);
                return;
            }
        }
        if (targetLocation == null) {
            missile.giveCommand(ShipCommand.ACCELERATE);
        } else {
            float aimAngle = MathUtils.getShortestRotation(missile.getFacing(), VectorUtils.getAngle(missile.getLocation(), targetLocation));
            if (Math.abs(aimAngle) < 45.0f) {
                missile.giveCommand(ShipCommand.ACCELERATE);
            }
            if (aimAngle < 0f) {
                missile.giveCommand(ShipCommand.TURN_RIGHT);
            }
            if (aimAngle > 0f) {
                missile.giveCommand(ShipCommand.TURN_LEFT);
            }
        }
    }

    void teleportOnce(float amount, MissileAPI missile, Vector2f targetLocation){
        if(targetLocation != null) {
                Global.getSoundPlayer().playSound("system_phase_skimmer", 1.2f, 0.5f, missile.getLocation(), new Vector2f(0,0));
            /**for (int i = 0; i < 12; i++) {
                Vector2f cPoint = MathUtils.getRandomPointInCircle(targetLocation, 25f);
                engine.addHitParticle(cPoint, new Vector2f ((float) Math.random() * 0.5f, (float) Math.random() * 0.5f), jitterLevel, jitterLevel, 0.5f, JITTER_COLOR);
            }*/
            if (ship != null && weapon != null && weapon.getShip() == ship) {
                //engine.spawnProjectile(ShipAPI ship, WeaponAPI weapon, String weaponId, String projSpecId, Vector2f point, float angle, Vector2f shipVelocity)
                engine.spawnProjectile(
                        null,
                        null,
                        missileTeleporterId,
                        teleportedMissileId,
                        targetLocation,
                        missile.getFacing(),
                        new Vector2f (0f, 0f) //new Vector2f(0,0)
                );
            } else return;
        } else return;
    }

    private Vector2f findClearLocation(MissileAPI missile, Vector2f dest) {
        if (isLocationClear(dest)) return dest;
        float incr = 50f;
        WeightedRandomPicker<Vector2f> tested = new WeightedRandomPicker<Vector2f>();
        for (float distIndex = 1; distIndex <= 32f; distIndex *= 2f) {
            float start = (float) Math.random() * 360f;
            for (float angle = start; angle < start + 360; angle += 60f) {
                Vector2f loc = Misc.getUnitVectorAtDegreeAngle(angle);
                loc.scale(incr * distIndex);
                Vector2f.add(dest, loc, loc);
                tested.add(loc);
                if (isLocationClear(loc)) {
                    return loc;
                }
            }
        }
        if (tested.isEmpty()) return dest; // shouldn't happen
        return tested.pick();
    }

    private boolean isLocationClear(Vector2f loc) {
        for (ShipAPI other : Global.getCombatEngine().getShips()) {
            if (other.isShuttlePod()) continue;
            if (other.isFighter()) continue;
            float dist = Misc.getDistance(loc, other.getLocation());
            float r = other.getCollisionRadius();
            //r = Math.min(r, Misc.getTargetingRadius(loc, other, false) + r * 0.25f);
            if (dist < r + minTeleportRange) {
                return false;
            }
        }
        for (CombatEntityAPI other : Global.getCombatEngine().getAsteroids()) {
            float dist = Misc.getDistance(loc, other.getLocation());
            if (dist < other.getCollisionRadius() + minTeleportRange) {
                return false;
            }
        }
        return true;
    }

    @Override
    public CombatEntityAPI getTarget() {
        return target;
    }

    @Override
    public void setTarget(CombatEntityAPI target) {
        this.target = target;
    }
   
    public void init(CombatEngineAPI engine) {}
}
[close]

And everything looks fine until one of the spawned missiles hit anything (ship, asteroid, shield, projectiles, other missiles, fighters, really anything), which give me a nullPointer...
Spoiler
Code
52777 [Thread-4] ERROR com.fs.starfarer.combat.CombatMain  - java.lang.NullPointerException
java.lang.NullPointerException
at com.fs.starfarer.combat.entities.Ship.applyDamageInner(Unknown Source)
at com.fs.starfarer.combat.entities.Ship.applyDamageInner(Unknown Source)
at com.fs.starfarer.combat.entities.Ship.applyDamage(Unknown Source)
at com.fs.starfarer.combat.class.super.O0OO.o00000(Unknown Source)
at com.fs.starfarer.combat.class.super.super(Unknown Source)
at com.fs.starfarer.combat.class.super.super(Unknown Source)
at com.fs.starfarer.combat.CombatEngine.advanceInner(Unknown Source)
at com.fs.starfarer.combat.CombatEngine.advance(Unknown Source)
at com.fs.starfarer.combat.CombatState.traverse(Unknown Source)
at com.fs.state.AppDriver.begin(Unknown Source)
at com.fs.starfarer.combat.CombatMain.main(Unknown Source)
at com.fs.starfarer.StarfarerLauncher$1.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
[close]

My guess is that the engine doesn't know the source of the damage and can't apply it to the object hit. Doesn't work either if I'm using the missile's ship and weapon as source for the ShipAPI and WeaponAPI.
Any easy way to fix this ?

12
Hi there !
I found why my game was crashing last time : Intellij wasn't compiling the jar where I wanted after an update. Strange but resolved.
On the other hand... :
Spoiler
Code
195040 [Thread-4] ERROR com.fs.starfarer.combat.CombatMain  - java.lang.NullPointerException
java.lang.NullPointerException
at data.scripts.weapons.SCQ_NRT_RevolverEffect.advance(SCQ_NRT_RevolverEffect.java:99)
at com.fs.starfarer.combat.entities.ship.oOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.O0oO.advance(Unknown Source)
at com.fs.starfarer.combat.systems.void.advanceLinked(Unknown Source)
at com.fs.starfarer.combat.systems.void.advance(Unknown Source)
at com.fs.starfarer.combat.entities.Ship.fire(Unknown Source)
at com.fs.starfarer.combat.entities.Ship.advance(Unknown Source)
at com.fs.starfarer.combat.CombatEngine.advanceInner(Unknown Source)
at com.fs.starfarer.combat.CombatEngine.advance(Unknown Source)
at com.fs.starfarer.combat.CombatState.traverse(Unknown Source)
at com.fs.state.AppDriver.begin(Unknown Source)
at com.fs.starfarer.combat.CombatMain.main(Unknown Source)
at com.fs.starfarer.StarfarerLauncher$1.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
195195 [Thread-10] INFO  sound.public  - Creating streaming player for music with id [battle_ambience_01.ogg]
195195 [Thread-10] INFO  sound.H  - Playing music with id [battle_ambience_01.ogg]
[close]

This is the error I get, sometimes, when overloading enemy ships in the simulator / destroying enemy fighter wings. Looks right from the IDE perspective and work perfectly on unshielded targets.
The plugin :
Spoiler
Code
package data.scripts.weapons;

import com.fs.starfarer.api.combat.*;
import com.fs.starfarer.api.loading.MuzzleFlashSpec;
import org.lazywizard.lazylib.MathUtils;
import com.fs.starfarer.api.util.IntervalUtil;
import org.lazywizard.lazylib.VectorUtils;
import org.lazywizard.lazylib.combat.CombatUtils;
import org.lwjgl.util.vector.Vector2f;
import data.scripts.util.MagicRender;

import java.awt.*;
import java.util.List;

public class SCQ_NRT_RevolverEffect implements EveryFrameWeaponEffectPlugin {

    //effects
    private Color explosionColor = new Color(160, 105, 17, 100);
    private Color flashColor = new Color(216, 161, 39, 150);
    private final Color SMOKE1_COLOR = new Color(100, 100, 100, 130);
    private final Color SMOKE2_COLOR = new Color(75, 75, 75, 110);
    private final Color SMOKE3_COLOR = new Color(40, 40, 40, 60);

    private boolean runOnce = false,
                applyDamageBonus = false;
    private float burstSpread,
            burstRange,
            damageRange,
            modifier,
            baseBurstDamage,
            originWeaponDamage,
            barrelOffset,
            lastRoundBonusMult;
    private static final float MEDIUM_DAMAGE = 150f,
            LARGE_DAMAGE = 200f;
    private int barrelNumber;
    private Vector2f location,
                barrelLocation;
    private DamagingProjectileAPI proj; //The projectile itself
    private final IntervalUtil timer = new IntervalUtil(0.05f, 0.15f);
    private static WeaponAPI.WeaponSize weaponSize;
    private MuzzleFlashSpec originMuzzleFlash;

    @Override
    public void advance(float amount, CombatEngineAPI engine, WeaponAPI weapon) {
        if (weapon.getShip().getOriginalOwner() == -1 || weapon.getShip().isHulk()) {
            return;
        }
        if (!runOnce) {
            //originWeaponDamage = weapon.getDamage().getDamage();
            weaponSize = weapon.getSize();
            originMuzzleFlash = weapon.getMuzzleFlashSpec().clone();
            weapon.ensureClonedSpec();
            weapon.setMaxAmmo(weapon.getSpec().getMaxAmmo());
            switch (weaponSize) {
                case MEDIUM:
                    originWeaponDamage = MEDIUM_DAMAGE;
                    burstSpread = 30f;
                    burstRange = 90f;
                    damageRange = 80f;
                    baseBurstDamage = 30f;
                    barrelNumber = 1;
                    lastRoundBonusMult = 1.5f;
                    if (weapon.getSlot().isTurret()) {
                        barrelOffset = 24.0f;
                    } else barrelOffset = 30.0f;
                    break;
                case LARGE:
                    originWeaponDamage = LARGE_DAMAGE;
                    burstSpread = 35f;
                    burstRange = 120f;
                    damageRange = 100f;
                    baseBurstDamage = 50f;
                    barrelNumber = 2;
                    lastRoundBonusMult = 1.8f;
                    if (weapon.getSlot().isTurret()) {
                        barrelOffset = 32.0f;
                    } else barrelOffset = 38.0f;
                    break;
                default:
                    return;
            }
            runOnce = true;
        }
        barrelLocation = new Vector2f (weapon.getLocation().getX() + barrelOffset, weapon.getLocation().getY());
        VectorUtils.rotateAroundPivot(barrelLocation, weapon.getLocation(), weapon.getCurrAngle());
        if (weapon.getAmmo() <= barrelNumber && weapon.getCooldownRemaining() <= 0.05f && weapon.getChargeLevel() <= 0.05f) {
            applyDamageBonus = true;
        } else if (weapon.getAmmo() > barrelNumber) {
            applyDamageBonus = false;
        }
        if (applyDamageBonus) {
            modifier = lastRoundBonusMult;
            if (weapon.isFiring()) {
                List<DamagingProjectileAPI> projectiles = engine.getProjectiles();
                int size = projectiles.size();
                for (int i = 0; i < size; i++) {
                    proj = projectiles.get(i);
                    if (proj != null && proj.getWeapon().getId() == weapon.getSpec().getWeaponId() && proj.getElapsed() < 0.05f) {
                        proj.setDamageAmount(originWeaponDamage * modifier);
                    }
                }
            }
            weapon.getMuzzleFlashSpec().setParticleColor(new Color(220, 60, 20, 200));
            timer.advance(amount);
            if(timer.intervalElapsed() && MagicRender.screenCheck(0.1f, weapon.getLocation()) && weapon.getAmmo() > 0){
                engine.addHitParticle(
                        weapon.getLocation(),
                        weapon.getShip().getVelocity(),
                        MathUtils.getRandomNumberInRange(30, 50),
                        0.7f,
                        MathUtils.getRandomNumberInRange(0.2f, 0.35f),
                        new Color(220, 120, 40, 150)
                );
            }
        } else {
            modifier = 1f;
            weapon.getMuzzleFlashSpec().setParticleColor(originMuzzleFlash.getParticleColor());
            //muzzleFlash effects
            weapon.getMuzzleFlashSpec().setLength(originMuzzleFlash.getLength() * modifier);
            weapon.getMuzzleFlashSpec().setSpread(originMuzzleFlash.getSpread() * modifier);
            weapon.getMuzzleFlashSpec().setParticleCount((originMuzzleFlash.getParticleCount() * (int) (modifier * 10)) / 10);
        }
        if (weapon.isFiring()) {
            applyExplosion(amount, engine, weapon);
        }

    }
    private void applyExplosion(float amount, CombatEngineAPI engine, WeaponAPI weapon) {
        if (applyDamageBonus && weapon.isFiring()) {
            explosionColor = new Color(200, 53, 13, 150);
            flashColor = new Color(255, 75, 48, 200);
        } else if (!applyDamageBonus) {
            explosionColor = new Color(160, 105, 17, 100);
            flashColor = new Color(216, 161, 39, 150);
        }
        float random = ((float) barrelNumber + (float) Math.random() * 1 * modifier) / (4 - modifier);
        for (int j = 0; j <= random; j++) {
            location = MathUtils.getRandomPointInCone(barrelLocation, burstRange * modifier, weapon.getCurrAngle() - (burstSpread * modifier), weapon.getCurrAngle() + (burstSpread * modifier));
            //add an explosion effect at that point
            //void spawnExplosion(Vector2f loc, Vector2f vel, Color color, float size, float maxDuration);
            engine.addHitParticle(location,new Vector2f(), MathUtils.getRandomNumberInRange(12f * modifier, 25f * modifier),0.8f, 0.3f * modifier, explosionColor);
            engine.addHitParticle(location,new Vector2f(), MathUtils.getRandomNumberInRange(8f * modifier, 15f * modifier),0.5f, 0.1f * modifier, flashColor);
            //engine.spawnExplosion(location, new Vector2f(), explosionColor, MathUtils.getRandomNumberInRange(9f, 22f), 0.05f);
            //engine.spawnExplosion(location, new Vector2f(), flashColor, MathUtils.getRandomNumberInRange(6f, 15f), 0.05f);
            //public void addSmokeParticle(Vector2f loc, Vector2f vel, float size, float opacity, float duration, Color color);
            engine.addSmokeParticle(location, new Vector2f(), MathUtils.getRandomNumberInRange(7f * modifier, 14f * modifier), 0.1f, 0.50f * modifier, SMOKE3_COLOR);
            engine.addSmokeParticle(location, new Vector2f(), MathUtils.getRandomNumberInRange(6f * modifier, 12f * modifier), 0.1f, 0.25f * modifier, SMOKE2_COLOR);
            engine.addSmokeParticle(location, new Vector2f(), MathUtils.getRandomNumberInRange(5f * modifier, 10f * modifier), 0.1f, 0.12f * modifier, SMOKE1_COLOR);
        }
        List<MissileAPI> nearbyMissiles = CombatUtils.getMissilesWithinRange(location, damageRange * modifier); //damage nearby missiles
        if (!nearbyMissiles.isEmpty()) {
            for (MissileAPI missiles : nearbyMissiles) {
                engine.applyDamage(
                        missiles,
                        location,
                        baseBurstDamage * modifier,
                        DamageType.ENERGY,
                        0f,
                        false,
                        false,
                        weapon.getShip()
                );
            }
        }
        List<ShipAPI> nearbyShips = CombatUtils.getShipsWithinRange(location, damageRange * modifier); //damage nearby ships
        if (!nearbyShips.isEmpty()) {
            if (nearbyShips.contains(weapon.getShip())) {
                nearbyShips.remove(weapon.getShip());
            }
            for (CombatEntityAPI ship : nearbyShips) {
                engine.applyDamage(
                        ship,
                        location,
                        baseBurstDamage * modifier,
                        DamageType.ENERGY,
                        0f,
                        false,
                        false,
                        weapon.getShip()
                );
            }
        }
    }
}
[close]

13
Another small question, while I'm trying to repair the previous script : I made a missile AI but I don't have any idea of the way I'm supposed to use it. How am I supposed to apply it on the missiles I want ?

Edit : I managed to find where I'm supposed to call the missile AI in ModPlugin, but it doesn't seems to work with this :
Code
@Override
    public PluginPick<MissileAIPlugin> pickMissileAI(MissileAPI missile, ShipAPI ship) {
        switch (missile.getProjectileSpecId()) {
            case "NRT_chaos_lrm":
                return new PluginPick (new SCQ_ChaosMissileAI(missile, ship),CampaignPlugin.PickPriority.MOD_SPECIFIC);
            default:
        }
        return null;
    }
The missile just fly straight.

14
Modding Resources / Re: [0.9.1] MagicLib v0.28 (2019/11/09)
« on: December 15, 2019, 04:28:47 AM »
Quote
MagicGuidedProjectileScript (allows projectiles to track their target)
What could prevent this script from working ?

Does this (well, it's not the complete script I'm using but it's the part used with projectile that use the MagicGuidedProjectileScript) should work ? :
Spoiler
Code
List<DamagingProjectileAPI> projectiles = engine.getProjectiles();
            int size = projectiles.size();
            for (int i = 0; i < size; i++) {
                proj = projectiles.get(i);
                String spec = proj.getProjectileSpecId();
                WeaponAPI mainWeapon = proj.getWeapon();

                if (mainWeapon.getShip().getShipTarget() != null) {
                    target = mainWeapon.getShip().getShipTarget();
                } else {
                    target = AIUtils.getNearestEnemy(proj);
                }

                switch (spec) {
                       case LIGHT_PLASMA_DART_PROJECTILE_ID:
                              isGuided = true;
                       break;

             if (isGuided) {
                  engine.addPlugin(MagicGuidedProjectileScript(proj, target));
             }
[close]

15
Quote
compile this into a jar and provide that with your mod instead of having the game try to compile it on startup.

It's actually a .jar file compiled by Intellij IDEA, but I'm pretty sure it's a dumb mistake since even when the plugin is "empty" (i.e nothing actually coded inside), the game crash when loading it.
I need to do some cleanup because the rest of the mod is somewhat of a mess before sending it, I made a lot of copy for the weapons using this plugin, and I tried to achieve the same effect with different methods (using a Beam and a BeamEffect instead of EveryFrameWeaponEffect, forcing the cooldown to arbitrary values after each real fire to change the firerate but without any more success. The only luck I had was at the beginning of the cooldown method, but the firerate was somewhat randomized by the script).

Pages: [1] 2 3 4