ShipSystemStatsScript.
Added CombatEntityAPI MutableShipStatsAPI.getEntity(). You can cast it to ShipAPI in that particular case (sometimes, it may be a MissileAPI).
And thank you for putting in so much effort on the modding side of things. I've been modding for 12 years, and Starfarer is (by far!) the most enjoyable of all the games I've ever modded. :)
Thank you, it's my pleasure :)
Oh, and if you're noting things that need attention, ShipAPI's getPhaseCloak() still returns a placeholder Object. ;)
Changed to ShipSystemAPI. That's what it already returned, just hadn't changed the method signature.
Hmm, is the problem with getBaseDamage() due to the MutableStats? If so, would a getDamage() method suffer the same difficulties? Sorry to bother you about this, but I'm trying to write helper classes that calculate the threat generated by nearby enemies, and damage is fairly important to the equation. ;)
Oh and on getDamage(), I'd rather just see the current true damage; that's very complex because of flux bonuses, character bonuses, system bonuses, bonuses for your bonuses, etc.
Yeah, that's part of the problem. But all that doesn't get figured out until a projectile is actually created. Which you can get access to once they're flying, which can be a bit late for certain things.
Added WeaponAPI.isFiring(), btw. That may come in handy for determining how much of a threat something is.
Let me just expose something that's used internally. It's not taking skills or damage bonuses into account, but are the baseline weapon stats, in a more immediately useful form:
public static interface DerivedWeaponStatsAPI {
float getBurstFireDuration();
float getSustainedDps();
float getEmpPerSecond();
float getDamageOver30Sec();
float getDps();
float getBurstDamage();
float getFluxPerDam();
float getRoF();
float getFluxPerSecond();
float getSustainedFluxPerSecond();
}
.
Also added WeaponAPI.getDerivedStats().
I hope that the "can I fire at this" team-check's all in one place; it should be straightforward to do "not my team, but not team 100" to keep AI from shooting NEUTRAL stuff and "team 100 does not fire". Request that team 666 be designated HOSTILE, lol.
It's not, actually. Which could pose a bit of a problem :)
I want to be able to see stuff that's going on in the strategic map a little less clunkily. My diplomatic system, for example, just goes off of changes over time and is potentially exploitable (for example, you can attack X, drop Relations .1, then attack Y and Z before the next update and avoid the "you just attacked an ally" condition I wrote). Having a callback when a battle ends on the strategic map would be a huge benefit there, as well as allowing for a bunch of other stuff to be made possible such as writing some basic strategic-level AI. Right now it's very clunky getting information about what's going on, but it's gotta be there already, because the engine's clearly acting on it.
Yeah, I understand. I just don't want to go expanding the campaign API until a few versions from now.
Now then, I should really go back to working on some design docs - been doing nothing but posting here since this morning. Well, and fixing/adding things in response, so I guess that counts as "real work" :)
Also, could CargoAPI, CargoStackAPI, and FleetDataAPI get hashCode() implementations based on their contents? It would help when checking if they have been modified (right now we need to keep a copy of their prior contents around to diff against).
o1.hashCode() == o2.hashCode() does not imply o1.equals(o2). Am I missing something about how you intended to use it?
A hash should change if the contents change, correct? So instead of iterating through every stack and comparing them against a reference copy to see if they have changed, we could just use if (cargo.hashCode() != lastHash)
{
lastHash = cargo.hashCode();
// Do stuff
}
Could we get a getHullType method? At the moment, we're limited to something like:
private static String getHullType( FleetMemberAPI ship ) {
if (ship.isFighterWing()) {
return ship.getSpecId();
}
int lastIndex = ship.getSpecId().lastIndexOf("_");
if (lastIndex > 0) {
return ship.getSpecId().substring(0, lastIndex);
}
return ship.getSpecId();
}
Which works fine most of the time, but fails if, for example, someone made a default variant with a name like "liao-freighter-standard" instead of "liao-freighter_standard".
one that i really want...
make
spawnProjectile() consistent with spawnEmpArk()
atm you need to make a dummy weapon for spawnProjectile() to work
what i want wish and desire:
spawnProjectile(ShipAPI ship, //same as
WeaponAPI weapon, //same as
DamageType damageType, //from emp arc
float damAmount, //from emp arc
float empDamAmount, //from emp ark
float maxRange, /from emp ark
java.lang.String projectileId, //what projectile wprite will be used
Vector2f point, //same as
float angle, //same as
Vector2f projectileVelocity) //not weliant on what is in weapon.csv
this would make cripting much easier, since you wouldnt need to fiddle around with many files, or write massive workarounds
// New API request, came up while I was writing some mod or other. Damaging Projectile API already has this:
String DamagingProjectileAPI.getProjectileSpecId();
// So it would be nice if it also had this:
ProjectileSpecAPI DamagingProjectileAPI.getProjectileSpec();
// Or this (which it looks like you might have added, or plan to add already, if so, disregard this):
ProjectileSpecAPI DataAPI.getProjectileSpec( String projectileSpecId );
Basically, I'd like a way to get the game context of whatever area of the game a given Object is being displayed in. For example, if a WeaponAPI is being displayed in the Context of the Fleet display and I don't want them to draw their sprite, because they're Decoratives that are supposed to be hidden unless an EveryFrameScript says it's OK to draw, it'd be nice to be able to catch that and kill it.
getContext() would pull that value and return it. This would be so handy for so many things, where we want things to operate here but not there, and right now, determining here and there is either difficult or just plain impossible. IDK whether the game's mature enough to add this feature yet, but I figured I'd request it now, since it's something people are going to want for a lot of situations.
public interface ContextAPI {
public static enum Context {
RADAR_VIEW,
STRATEGIC_VIEW,
BATTLE,
SIMULATOR,
DIALOG,
REFIT,
TRADE,
FLEET,
SKILLS,
START,
START,
OTHER STUFF I FORGOT,
}
Context getContext();
}
Requesting a new API type, ResourceAPI, along with basic functions -- at the moment, getValue() and setValue().
I was conceiving of a way of introducing some civil gameplay instead of combat-oriented gameplay in the form of cargo deliveries accessed on the trade screen, but unfortunately bumped against the problem that we presently have no way of re-pricing resources (such as Fuel, Elite Crew, Supplies, etc.) on space stations.
My original proposal (for my own use as a design document) was:
Spoiler
Perhaps one way of implementing a civilian economy at the moment, prior to any full-on scripted mission system, is simply to have passengers and cargo destined for local trading hubs. More to the point, the game would add the following:
Commuter Passenger to [X]
Travelling Passenger to [X]
Migrant Passenger to [X]
multiplied by the maximum number of trading hubs in the game -- so if there are 50 possible hubs, then there are 150 different new "crew" types added to the game.
Each of the different passenger types would be configured to correspond to one destination hub, and then from 1 to 20 of each passenger type would be scattered at each of a number of hubs within the specified range band. Commuter Passengers would appear on other trading hubs within the same system, Travelling Passengers would appear on trading hubs in adjacent systems, and Migrant Passengers would appear on trading hubs in non-adjacent systems. Periodic update scripts would remove the corresponding passenger types who are in the cargo of the appropriate hub, and would periodically add from 0 to 5 new passengers for that hub to random stations in the corresponding range bands. Periodic scripts would also check to see the number of passengers waiting at every station and would subtract from 0 to 10% of all passengers waiting -- this is to reflect other companies scooping up these passengers, or the passengers getting fed up of waiting and hiring their own shuttle instead of waiting for a liner.
Each passenger is "free" to "buy". When you dock with the designated trading hub, the "selling" price of all corresponding passengers is then set accordingly -- commuter passengers would pay a commuter fee (25 credits), travelling passengers would pay a intersystem hop fee (125 credits), and migrant passengers would pay a hyperflight fee (625 credits). The cost of supplies and hyperfuel combined will make single hops inefficient for bulk transports, but very, very efficient when large numbers of passengers are transported. Shuttles, on the other hand, can turn a profit running commuter service only, since their daily supply costs are low and no fuel is needed for in-system travel.
A similar behaviour would apply to cargo:
Delivery Cargo to [X]
Intersystem Cargo to [X]
Long-Range Cargo to [X]
TODO: Balance "selling" prices subject to testing -- how long does a typical commuter shuttle trip take (and therefore how many daily supplies -- no more than 7 days?), and what personnel capacity is involved (and therefore how many life support supplies -- 0.1/passenger/day?)
TODO: Dropping off passengers at places other than their destination works fine as designed -- they'll just have zero value -- but how to criminalise jettisoning passengers?
Aside from the inability to add new crew types at the moment -- they seem to be fairly hard-coded ;-) -- which in itself makes the idea unfeasible for passengers but still feasible for cargo deliveries, the main lacking feature is the ability to price commodities via the campaign or sector updates.
I could of course go the hard route and implement commodity exchanges and passenger pickups as dialogue plugins and then assign the cargos themselves as zero-value commodities, but that's a brutal path to follow for something that was intended to be ultimately simple.
I would also have to represent passengers as cargo rather than as crew, owing to the aforementioned hard-coding, which would mean I'd have to apply a scripted drain on supplies rather than having it behave emergently as part of the existing personnel capacity system, which would have a number of undesirable side effects, such as not being represented properly on the UI, and creating the unintuitive scenario that a troopship cannot be used as a passenger ferry. However, allowing the creation of new crew types seems like it would be rather difficult to implement on the engine side, so that particular request will have to wait for another day, I suppose.
That's the thing, I actually looked at several missions and I found addPlugin(new EscapeRevealPlugin(context)) so I thought it had to do with some EscapeRevealPlugin which didn't seem relevant to what I was trying to achieve.
However if I'd just had a look at a few more missions, and I'd opened the Bismarck mission it probably would have twigged at about line 94:
api.addPlugin(new EveryFrameCombatPlugin() {
public void init(CombatEngineAPI engine) {
engine.getContext().setStandoffRange(10000f);
}
public void advance(float amount, List events) {
}
});
That makes sense to me.
I have a bit of a concern though with this method of adding a plugin. Normally when I do a plugin, I either clear out lists in the Init or in advance section from the previous engine.
However if the plugin is not run again in another instance of combat, those lists/hashmaps etc. might remain there in memory until the application closes. So if the use case is the user plays the mission with the script X that stores various ship data, they then complete the mission, then go off and play the campaign I'm not certain that the GC would cleanup my lists/hashmaps properly, potentially leading to a crash due to lack of memory on 32-bit systems.
Anyway aside from the GC of mission EveryFrameCombatPlugin scripts lists, I think it seems fairly straight forward after looking at the bismarck mission.
Well, I didn't write it for portability; you need to figure stuff like that out :)
That said... it's pretty straightforward, I think.
File dir = new File("data/world/factions/");
File[] files = dir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".faction");
}
});
...gets you every single .faction file. Read into JSON. Do whatever analysis thing you want once you have the data set. Should be straightforward to push it all to a string table, eliminate all matches, etc.
We're also in need of a way to get the DamagingProjectileAPI objects before the core sends the damage amount to the public O0OO.o notifyDealtDamage(Vector2f paramVector2f, G paramG, com.fs.starfarer.combat.o0OO.H paramH)
This allows to perform changes in these projectiles before any calculation is done. You can only imagine how much magic this would allow us in creating defensive and offensive systems without resorting to very heavy iterations on all projectiles on the game and other highly volatile coding to get said systems done.
I eventually did notice that FleetEncounterContext actually had a LOT more going on than its corresponding Plugin, yes.
reportBattleOccurred (part of the CampaignEventListener system, not the CampaignPlugin? I'm not sure what CampaignEnginePlugin is, is that new?) doesn't seem to have any hooks into the respective cargo of the fleets before it gets discarded after a battle.
At the moment I can get what I want by copy-pasting the entirety of FIDPI and BAPI and changing one line in each, so I'm doing that, but it feels... well, wrong :)
(Specifically, I'm changing them to have FleetEncounterContext context = new PersistantDebrisFleetEncounterContext();
which is a subclass with slightly expanded autoLoot and afterBattleBlah calls.)
That's why I hoped they'd call out to a factory class instead, and why I wanted FleetEncounterContext to be more moddable. I'm aware it is completely moddable right now, but because it's only used as a private instance variable in both cases, you can't change it without also changing FIDPI and BAPI, so I suppose that's my request, I'd like to be able to change it separately without all this copy-pasting. Any ideas?
Edit: It's not that copying FIDPI and BAPI isn't working, it's just going to be bad for inter-mod compatibility unless I provide instructions on how anyone else modifying FIDPI and/or BAPI can selectively use my new FleetEncounterContext subclass, which on second thought is an amazing position to be in, and I commend you on your mod structure that my only REAL complaint is "I'm changing something really deep in the implementation code, could it please be easier for other mods to automatically pick that up". I know I've mentioned it before, but you really deserve praise for your game+engine's moddability, it is the best.
Edit2: Looting doesn't remove stuff from the cargo in question... *bleeeeeerrrrgh*
Edit3!: CargoAPI.getStacksCopy() isn't guaranteed to actually be a -separate- copy of every stack... double*blergh*
That seems fair enough; making the functions in the implementation public so we can extend it, rather than just copying it, would be nice instead?
Hmm, yes, this.
If you make everything in FIDPI and BAPI public, I think the problem mostly goes away - we can override only the functions we need, and even better if we only want to add stuff we can override it to be almost a tail call like:
@override
public SomethingAPI IUsedToBePrivate(FleetContextThing thing)
{
SomethingAPI firstReturn = super.IUsedToBePrivate(thing);
return myNewMethod(thing, firstReturn);
}
That would be great, because then anyone who can see our source can -easily- integrate the mod just by calling that method. Which we should also make public, of course.
Basically I think modders (and you when it comes to Impl classes) shouldn't be too worried about encapsulation given that people might very well want to mess with the internals. Maybe just Protected would be good enough, I haven't given it a huge amount of thought, but either would be a great easing of the difficulty in changing what happens in these Impl classes at the moment!
I would like a method to get FleetMemberAPI from ShipAPI.
You can already do this, though there are a few edge cases you have to work around. If you use LazyLib you can just use CombatUtils.getFleetMember(ShipAPI ship). Otherwise, feel free to borrow the code that method uses:
public static FleetMemberAPI getFleetMember(ShipAPI ship)
{
final CombatFleetManagerAPI fm = Global.getCombatEngine()
.getFleetManager(ship.getOriginalOwner());
final DeployedFleetMemberAPI dfm = fm.getDeployedFleetMemberEvenIfDisabled(ship);
// In almost all cases this method will return here
if (dfm != null && dfm.getMember() != null)
{
return dfm.getMember();
}
// Directly spawned ships won't have a fleet member assigned
final String id = ship.getFleetMemberId();
if (id == null)
{
return null;
}
// Not deployed? Check reserves
for (FleetMemberAPI member : fm.getReservesCopy())
{
if (id.equals(member.getId()))
{
return member;
}
}
// No match was found
return null;
}
Went through this; added some new methods:
CombatFleetManagerAPI:
boolean isSuppressDeploymentMessages();
void setSuppressDeploymentMessages(boolean suppressDeploymentMessages);
WeaponAPI
void setMaxAmmo(int maxAmmo);
CombatEngineAPI
CombatNebulaAPI getNebula();
CombatNebulaAPI
int getTilesWide();
int getTilesHigh();
float getTileSizeInPixels();
boolean tileHasNebula(int cellX, int cellY);
boolean locationHasNebula(float x, float y);
int getLeftOf();
int getBelow();
int getRightOf();
int getAbove();
CombatFleetManagerAPI:
boolean isSuppressDeploymentMessages();
void setSuppressDeploymentMessages(boolean suppressDeploymentMessages);
THANKYOU!!!!!!!!
Went through this; added some new methods:
CombatFleetManagerAPI:
boolean isSuppressDeploymentMessages();
void setSuppressDeploymentMessages(boolean suppressDeploymentMessages);
WeaponAPI
void setMaxAmmo(int maxAmmo);
CombatEngineAPI
CombatNebulaAPI getNebula();
CombatNebulaAPI
int getTilesWide();
int getTilesHigh();
float getTileSizeInPixels();
boolean tileHasNebula(int cellX, int cellY);
boolean locationHasNebula(float x, float y);
int getLeftOf();
int getBelow();
int getRightOf();
int getAbove();
Thank you Alex.
Went through this; added some new methods:
[...]
CombatEngineAPI
CombatNebulaAPI getNebula();
CombatNebulaAPI
int getTilesWide();
int getTilesHigh();
float getTileSizeInPixels();
boolean tileHasNebula(int cellX, int cellY);
boolean locationHasNebula(float x, float y);
int getLeftOf();
int getBelow();
int getRightOf();
int getAbove();
Awesome, thank you!
In MissionDefinitionAPI nebulae are currently added using a location and a radius. Is that converted to tiles under the hood, or is the tile system more along the lines of "there's a nebula somewhere within this square"?
Could ShipAPI extend AssignmentTargetAPI? I might be doing something wrong but it seems like it would be convenient to use ships as assignment targets directly. Especially since the ShipAPI already has all the required method AFAICT (through the CombatEntityAPI interface).
http://fractalsoftworks.com/starfarer.api/com/fs/starfarer/api/combat/ShipAPI.html (http://fractalsoftworks.com/starfarer.api/com/fs/starfarer/api/combat/ShipAPI.html)
http://fractalsoftworks.com/starfarer.api/com/fs/starfarer/api/combat/AssignmentTargetAPI.html (http://fractalsoftworks.com/starfarer.api/com/fs/starfarer/api/combat/AssignmentTargetAPI.html)
You can do this with a DeployedFleetMemberAPI object if you explicit cast it, but I can't remember if it works with ShipAPI or FleetMemberAPI:
// Get combat fleet manager for the deployed ship's fleet side
CombatFleetManagerAPI combatFleetManagerAPI = Global.getCombatEngine().getFleetManager(shipAPI.getOwner());
// Create an escort assignment on the deployed ship
CombatFleetManagerAPI.AssignmentInfo assignmentInfo = combatFleetManagerAPI.getTaskManager(false).createAssignment(CombatAssignmentType.LIGHT_ESCORT, (AssignmentTargetAPI)this.getDeployedFleetMemberAPI(shipAPI), false);
// Give the escort assigned to another ship
combatFleetManagerAPI.getTaskManager(false).giveAssignment(this.getDeployedFleetMemberAPI(otherShipAPI), assignmentInfo, false);
Supporting code (I think a duplicate of this might exist in LazyLib):
private DeployedFleetMemberAPI getDeployedFleetMemberAPI(ShipAPI shipAPI) {
CombatFleetManagerAPI fm = Global.getCombatEngine().getFleetManager(shipAPI.getOriginalOwner());
return fm.getDeployedFleetMember(shipAPI);
}
Honestly surprised its not in there considering there is getAmmoBonus(), but after a double check I could use:
com.fs.starfarer.api.combat.MutableShipStatsAPI.getMissileAmmoRegenBonus();
and
com.fs.starfarer.api.combat.MutableShipStatsAPI.getEnergyAmmoRegenBonus();
Need these for a built-in hullmod for my fighters to lessen the strike capabilities of their weapons.
Just an off-hand suggestion/query regarding the fleet creation API for single missions. Specifically, I discovered today that the only options within
api.addToFleet(FleetSide.[FLEET SIDE], ......)
are "PLAYER" and "ENEMY". Would it be possible to also have "ALLY" be an option?
My thinking behind this would be to match the circumstance in the campaign where you join an existing battle between two fleets, or a friendly fleet supports your forces when you engage in combat. Under these circumstances you still have control over your ships, but the "ally", while fighting on your side, will give their own orders independent to you.
I reckon it would be nice to have "ALLY" be an option for single missions with similar effects, so you can create a mission that matches a storyline where you are assisting/being assisted by another friendly fleet with its own commander. Off the top of my head I can't think of any problems with this (although you could possibly abuse it by creating a mission where all the friendly ships are "allies" and the player has no control of anything).
Thoughts?
Is it possible to change the hullmod API ?
public boolean isApplicableToShip(ShipAPI ship)
I dislike how mods have to just remove the vanilla hullmods for conflicting rather than not showing conflicting vanilla ones in first place.
Maybe add a conflict group tag to hullmod themselves?
when existed any of hullmod in a group, other hullmods in same group return false.
I would like to be able to write an event that can react to reputation change, but only for specific reasons.
Currently the api is:
public void reportPlayerReputationChange(String faction, float delta)
I would like to see something like this:
public void reportPlayerReputationChange(String faction, RepActions action, float delta)
Just been working on a "recon" type hullmod to make scout/espionage ships, and realised that what would be ideal is a ship stat that affected the time it takes to capture an objective.
Something that I'd hope would be easy enough to stick in the MutableShipStatsAPI file:
getObjectiveCaptureTimeMod()
or similar perhaps?
I reckon it would be perfect for a recon ship that can dash out and capture objectives at an increased rate.
Alex hinted me about getting 3 skill choices per officer level but i have no idea how should i write up or compile it into working API.
"officerLevelUp":"com.fs.starfarer.api.impl.campaign.OfficerLevelupPluginImpl"
Been told that this is the one that controlling it but he also hasn't test that if it will work.
http://fractalsoftworks.com/forum/index.php?topic=13222.0
Thread in question.
(Not really sure where to put this, but it's part query, part complaint and part suggestion, so I guess here will do.)
It seems that a shieldless ship returns "null" under ship.getShield(). How come "NONE" is a valid type in the ShieldAPI.ShieldType enum list then? ??? Seemed logical to me that to check if a ship was unshielded, I should just use:
if (ship.getShield().getType() == ShieldType.NONE) {...}
As you may guess, that crashed the game with a NPE upon inserting a shieldless ship into the equation. :-\ What I needed to do was use:
if (ship.getShield()== null) {...}
... which works perfectly fine.
I'm not really sure what to suggest in regard to this, since I don't know what the reasons are for it being the way it is right now, but it was definitely confusing to me, especially since I'm so used to just writing "NONE" under shield type in ship_data.csv for shieldless ships. Just thought it should be noted down that it's a potential pitfall for a newbie modder and it isn't immediately obvious what should be done.
Requesting that the following methods be supported at the time of ModPlugin.onGameLoad
- Global.getSector().getCampaignUI().showConfirmDialog [CTD due to NPE]
- Global.getSector().getCampaignUI().addMessage [silent failure]
NPE stack trace:
Spoiler
848390 [Thread-4] ERROR com.fs.starfarer.combat.CombatMain - java.lang.NullPointerException
java.lang.NullPointerException
at com.fs.starfarer.ui.while.show(Unknown Source)
at com.fs.starfarer.ui.impl.float.show(Unknown Source)
at com.fs.starfarer.campaign.CampaignState.showConfirmDialog(Unknown Source)
at com.fs.starfarer.campaign.CampaignState.showConfirmDialog(Unknown Source)
at starship_legends.ModPlugin.onGameLoad(ModPlugin.java:50)
at com.fs.starfarer.campaign.save.CampaignGameManager.o00000(Unknown Source)
at com.fs.starfarer.campaign.save.CampaignGameManager.o00000(Unknown Source)
at com.fs.starfarer.title.TitleScreenState.menuItemSelected(Unknown Source)
at com.fs.starfarer.title.C.actionPerformed(Unknown Source)
at com.fs.starfarer.ui.OoO0.buttonPressed(Unknown Source)
at com.fs.starfarer.ui.oooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.?0000(Unknown Source)
at com.fs.starfarer.ui.oooOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO.processInput(Unknown Source)
at com.fs.starfarer.ui.V.super(Unknown Source)
at com.fs.starfarer.BaseGameState.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)
Any chance we could get a MutableShipStatsAPI.get<SIZE>WeaponRangeBonus, i.e. MutableShipStatsAPI.getSmallWeaponRangeBonus? :)
There are a couple things where you can only tweak certain weapons by type, and others by size, and some by PD tag or projectile/beam, etc. and I bumped into this one recently.
What if you want to start mixing weapon size and weapon type stat changes though? I feel like this would get clunky very fast. I love the flexibility that stats affecting certain sizes gives, but imagine having all the mutable stats a weapon can take multiplied by three for the different weapon sizes.
I suggest a potential extension of Vayra's request: for weapon-affecting stats that are applied to a whole ship (such as, say, weapon range), the stat change method ".get_WeaponRangeBonus()" could have an optional field before the modifier method that allows you to specify a size - either as an enum "SMALL / MEDIUM / LARGE", or just an integer from 0 to 2. So, to give a range buff to all of a ship's small-sized ballistic weapons, you could do this:
...
stats.getBallisticWeaponRange(WeaponSize.SMALL).modifyPercent(id, someRangeBonus);
...
This could extend to all sorts of ship-wide, weapon-affecting stats - weapon flux cost, weapon damage, weapon rate of fire, etc. - in much the same way, keeping everything nice and tidy without MutableShipStatsAPI becoming a bit of a labyrinth (even if it already is ;) ). Would such a setup be possible, or even sane?
A method, of some sort, to adjust built-in weapons on a ship post-generation. Ideally, it would work in one of two ways: either ShipAPI.getVariant().addWeapon() would allow built-in weapon slots to be modified (which might not be ideal, or even possible), or some similar hook specifically for modifying built-in weapons could be added. This second hook could either be something similar to how built-in fighters can currently be modified (via list reference modification):
java
ShipAPI.getHullSpec().getBuiltInWeapons(); /* Returns a List<Pair<String, String>>, with first element being weapon slot ID and second being weapon spec ID */
This has the added benefit of matching the existing getBuiltInFighters() and getBuiltInHullmods() functions. Or, if it's for some reason preferable, an entirely different endpoint could be used. Something like this:
java
ShipAPI.getVariant().addBuiltinWeaponOverride(String slotID, String newWeaponID) /* Adds an override, making the variant replace the hullspec's built-in weapon */
ShipAPI.getVariant().removeBuiltinWeaponOverride(String slotID) /* Removes an override, giving control back to the hullspec */
Either of these solutions (or an equivalent solution) would allow for some more interesting weapons and hullmods to be coded, without messing with the autofit or fleetmember instantiators (which current attempts at "semi-builtin" weapons do), and several modders have already expressed desire to use the functionality this would allow.
Also, unrelated for the suggestion but related to the thread: the OP seems to be outdated, as several of its entries that now exist in the game are not marked as such.
Also, MIRV'd projectiles get their hitpoint variable from their parents; there's no such thing as an "armored MIRV" with weak, PD-able shots.
Umm. What?
From Hurricane MIRV projectile file:
...
"behaviorSpec":{"behavior":"MIRV",
"splitRange":1000,
"minTimeToSplit":2,
"canSplitEarly":true,
"splitSound":"hurricane_mirv_fire",
"numShots":11,
"damage":500,
"impact":5,
"emp":0,
"damageType":HIGH_EXPLOSIVE,
-->"hitpoints":250,
"arc":180,
"arcOffset":180,
"evenSpread":true,
"spreadSpeed":200,
"spreadSpeedRange":50,
"projectileSpec":"mirv_warhead",
...
"hitpoints":250
Request: a way to get a collection of the FleetMembers selected for deployment in the deployment window. Something like one of these:
Global.getCombatEngine().getSelectedForDeployment()
myCombatFleetManager.getSelectedForDeployment()
Admittedly the use cases are limited, but this information is currently very difficult to obtain.
I'd like to disable the player's ability to construct/upgrade/downgrade/scrap structures/industries in certain circumstances. I think I really just need it to disable the UIs. I guess that would go in MarketAPI?
boolean canBuildUpgrade()
setCanBuildUpgrade(boolean)
boolean canDowngradeShutDown()
setCanDowngradeShutDown(boolean)
EDIT
Realized build/upgrade and downgrade/shut down should be separate toggles.
something like:
stats.getCargoMod().modifyFlat(id, ship.getVariant().getNumFluxCapacitors());
won't work.
Actually, almost every campaign-related MutableShipStatsAPI modifications with dynamic values like:
stats.getFuelMod().modifyFlat(id, dynamicValueA);
stats.getMaxCrewMod().modifyFlat(id, dynamicValueB);
stats.getSensorProfile().modifyFlat(id, dynamicValueC);
stats.getSuppliesPerMonth().modifyFlat(id, dynamicValueD);
won't work.
I hope these issues can be fixed or changed in next updates...
... Until you have to account for the case where a modder tries to modify a mutable stat by itself, and the game crashes with an infinity error of some kind.
Spoiler
If you're trying to adjust stat X based on stat Y (specifically within a hullmod), you can actually get some information by translating ship stats backwards from the applyEffectsAfterShipCreation() method into the applyEffectsBeforeShipCreation() method. Disassemble Reassemble has a hullmod that exploits just that, letting you replace a ship's fighter bays with cargo capacity, and the cargo bonus scales with the number of bays the ship has.
Hi Alex!
I would be interested in a way to set either a wing as builtin or as UI-locked.
Use case is a hull mod to add a dedicated launch bay for a particular wing.
Example usage (in hull mod):
public void applyEffectsBeforeShipCreation(HullSize hullSize, MutableShipStatsAPI stats, String id) {
stats.getNumFighterBays().modifyFlat(id, 1f);
boolean isUILocked_Or_BuiltIn = true;
int wingIndex = stats.getNumFighterBays().getModifiedInt() - 1;
stats.getVariant().setWingId(this.wingIndex, wingId, isUILocked_Or_BuiltIn);
}
I couldn't work out a way to do it in the existing API but someone let me know if it is possible :)
Cheers,
Zaphide
This request is prompted by a weapon I recently scripted with custom projectile velocities and motion.
Demonstration
(https://i.imgur.com/GOSqamz.gif)
As you can see the range indicator as defined by the weapon .csv is misleading due to the range calculation being messed up by the non-linear velocity.
My request is DamagingProjectileAPI.setIsFading(boolean fading) or DamagingProjectileAPI.forceStartFading() to be able to make the projectile fade manually without having to mess around with weapon settings, ultimately creating a range indicator that is misleading to the player and the ai :D
boolean DroneLauncherShipSystemAPI.isInHoldingPattern() would be really useful to avoid a workaround I've been using for the DRONE_LAUNCHER shipsystem type (this is even displayed as a status for player ship on the HUD so it's annoying that it can't be gotten in code...) thanks :)
I think you're looking for something too specific. Look in DroneLauncherShipSystemAPI.java again and you'll see exactly what you need already there.
public static enum DroneOrders {
RECALL,
DEPLOY,
ATTACK,
}
...
DroneLauncherShipSystemAPI.DroneOrders getDroneOrders();
This isn't so much a suggestion and more of a query.
In an unrelated discussion in the Unofficial Discord, it came to my knowledge that the Ion Beam and Tachyon Lance have slightly different on-hit beam effects. Fine, they're different weapon formats, but while playing "spot the difference" I noticed something odd:
float emp = beam.getDamage().getFluxComponent() * 1f;
float dam = beam.getDamage().getDamage() * 1f;
float emp = beam.getWeapon().getDamage().getFluxComponent() * 0.5f;
float dam = beam.getWeapon().getDamage().getDamage() * 0.25f;
These are the bits that choose the damage values for the EMP arcs both weapons can generate (Ion Beam above, Tachyon Lance below). Fine, the multipliers are different, but what is the difference between these?
beam.getWeapon().getDamage()...
beam.getDamage()...
I looked in the API, and both the WeaponAPI and BeamAPI have this "getDamage()" method to the DamageAPI, while BeamAPI also has the "getWeapon()" method to get a WeaponAPI. Here, the Ion Beam goes straight from the BeamAPI to the damage instance, but the Tachyon Lance takes a detour through its WeaponAPI to achieve the same thing.
What is the significance of this? Is there any reason to use one format over the other? All I can think of is that one is a burst beam and one is a sustained beam, does that cause a difference in what is handled by the DamageAPI?
I'd like to request a public method in BaseIndustry that allows for modification of the current build progress via protected float buildProgress
I've just noticed game can render select boxes (e.g. Codex, Weapons, Small/Medium/Large and Energy/Ballistic/Missile) - could we have this exposed in TooltipMakerAPI? Example:
Same description as addButton:
SelectBoxAPI addSelectBox(java.lang.String text, java.lang.Object data, java.awt.Color base, java.awt.Color bg, float width, float height, float pad)
SelectBoxAPI addSelectBox(java.lang.String text, java.lang.Object data, float width, float height, float pad)
For simplicity, SelectBoxAPI extends ButtonAPI plus:
void setSelected(boolean isSelected);
boolean getSelected();
And an event handler function in IntelInfoPlugin:void selectBoxChanged(java.lang.Object selectBoxId, boolean isSelected, IntelUIAPI ui)
I remember seeing something regarding officer/admin skills - I think it was regarding dialog box for recruitment.
Could you add `showSkills(PersonAPI person, ...)` to TooltipMakerAPI?
Possible descriptions:
void showSkills(PersonAPI person);// shows all non-zero skills
void showSkills(PersonAPI person, boolean sorted);// like showCargo, sort based on level
void showSkills(PersonAPI person, int max);// show up to max, then "and X other skills"
It would be nice to have access to more stuff in com.fs.starfarer.api.ui,
I will preface this with: I have no idea what any of the classes/methods are so this will sound super generic.
A way to create tri-pad like menus akin to the intel and command menus. Currently mod authors are utilizing the intel tab to add menu functionality to their mods.
com.fs.starfarer.api.ui.TriPadAPI
The "would be nice" features would include:
- Tab implementation
- Scrollable content functionality
- Maybe even a sidebar (Like intel has a sidebar where specific items are held)
- Tab content could be table based like the intel tab is
For ToolTipMakerAPI:
void addCheckbox(String id, boolean checked)
boolean getChecked(String id)
void addTextInput(String id, String placeholder)
void addTextBox(String id, String placeholder, int height) /* height could be number of lines, or pixel height I guess */
String getTextInput(java.lang.string id)
I'd like to ask for a method to block the availability of buildings on a market-to-market basis.
For example:
com.fs.starfarer.api.campaign.econ.MarketAPI
void blacklistIndustry(industryId)
void whitelistIndustry(industryId)
to disallow building that specific building on a market unless removed from the blacklist via a similar method.
Edit - Apologies for posting in the wrong thread - it's been a while since I read the OP. Feel free to delete it, I'll repost it as new subject sometime if it's gone.
Right after using F8 to reload all the vanilla data files in dev mode. I can add a plugin that track button presses to MagicLib, but I figured the game does it already, so why not have it done the proper way.
Thank you! For some reason I was thinking in terms of the campaign and it wasn't quite clicking.
Added:
/**
* Called after F8 is pressed in combat while in devMode.
* Note: the game becomes potentially unstable after an F8-dev mode reload. That is,
* crashes may occur that would not have occured otherwise and are not indicative of bugs.
*/
void onDevModeF8Reload();
Is it possible to get a
public void setHidden(boolean hidden) method in Industry, the way LionsGuardHQ is hidden if Sindria is not owned by the Diktat?
Did that.
Can I make a request to have the generation of the d-mod and s-mod bars on ship icon (see below) abstracted and made accessible to the modding API?
I mean these:
In Fleet screen: (here the bars even have tooltips)
(https://i.imgur.com/N5rnrpX.png)
In Refit screen:
(https://i.imgur.com/ehyw5p1.png)
The bars are also visible on ships icons in the encounter dialogs, and in fleet tooltips in campaign, no idea if elsewhere.
What I request is some way for a mod to decide how many and what color of bars it wants display on a ship icon, to possibly add extra types for some special hullmods in addition to the default green and red ones.
Right now they are hardcoded in the obfuscated part of the code (sorry to dig there, I wanted to check how hardcoded or moddable it is).
The hardcoded logic gets the number of d-mods and displays correct number of red bars with corresponsing tooltips, and then gets the number of built-in mods and displays green bars with corresponding tooltip, which is exactly what we see. What I request is to have this logic to be abstracted and fully or partially overridable by custom implementation.
Simple way - allow full replacement of default bars:
- overridable method getShipIconHullModBars() -> returns list of objects, each object representing one group of colored bars, with fields like this:
class HullModBarsGroup {
Color barColor;
int numberOfBars;
String tooltipText;
}
More advanced way (not exclusive with simple way) - allow adding of new bars at specified place, without removing exisitng ones (would provide better compatibility between mods that all want to add their own special groups):
- overridable method getShipIconExtraHullModBars() -> returns list of objects, each object representing one group of colored bars, and its ordering, with fields like this:
class HullModBarsGroup {
float order;
Color barColor;
int numberOfBars;
String tooltipText;
}
The default implementation of getShipIconHullModBars() to match the current logic would look like this:
public List<HullModBarsGroup> getShipIconHullModBars(ShipVariantAPI shipVariantAPI) {
HullModBarsGroup dmodBars = new HullModBarsGroup(
Color.red,
DModManager.getNumDMods(shipVariantAPI),
"Number of d-mods this ship has."
);
HullModBarsGroup storyModBars = new HullModBarsGroup(
Misc.getStoryOptionColor(),
Misc.getCurrSpecialMods(shipVariantAPI),
"Number of built in mods this ship has. Only counts mods custom built in after the ship was produced."
);
return Arrays.asList(dmodBars, storyModBars); // assuming they are added right-to-left, which seems to be the case
}
Would you please add a getter for the member DamagingExplosion.damagedAlready ?
Simply:
public List<Ship> getDamagedAlready() {
return this.damagedAlready;
}
Need this in the Detailed Combat Results mod to watch for doom damages.
Thanks!!!
public static boolean isUnboardable(FleetMemberAPI member) {
return isUnboardable(member.getHullSpec());
}
public static boolean isUnboardable(ShipHullSpecAPI hullSpec) {
if (hullSpec.getHints().contains(ShipTypeHints.UNBOARDABLE)) {
for (String tag : getAllowedRecoveryTags()) {
if (hullSpec.hasTag(tag)) return false;
}
if (hullSpec.isDefaultDHull()) {
ShipHullSpecAPI parent = hullSpec.getDParentHull();
for (String tag : getAllowedRecoveryTags()) {
if (parent.hasTag(tag)) return false;
}
}
return true;
}
return false;
}
Would it be possible for the Misc.IsUnboardable to check for the variant's tag of this fleet member as well? It is slightly annoying to duplicate a ship and make it unrecoverable when a variant's tag could do :(
Thank you for the suggestions/requests, everyone! A reminder that this thread is for things that already exist but aren't exposed in the API, not new features. I don't particularly mind if stuff crosses over into that territory, but given that I generally go through this thread late in the release cycle, anything that requires substantial effort is not likely to get done.
With that out of the way, did a bunch of these!
Added SettingsAPI.computeStringWidth(String in, String font)
Added TooltipMakerAPI.computeStringWidth(String in)
Added HullModSpecAPI.setManufacturer()
Added DamagingProjectileAPI.List<CombatEntityAPI> getDamagedAlready()
Returns null for everything other than explosions
Added getters and setters to BoostIndustryInstallableItemEffect
"no_autofit" tag now also works when applied to variants
Added "unboardable" tag to variants
Added TextFieldAPI
Added to TooltipMakerAPI:
TextFieldAPI addTextField(float width, float pad);
TextFieldAPI addTextField(float width, String font, float pad);
TextFieldAPI addTextField(float width, float height, String font, float pad);
ButtonAPI addCheckbox(float width, float height, String text, UICheckboxSize size, float pad);
ButtonAPI addCheckbox(float width, float height, String text, String font, Color checkColor, UICheckboxSize size, float pad);
Added to SettingsAPI:
TextFieldAPI createTextField(String text, String font);
ButtonAPI createCheckbox(String text, UICheckboxSize size);
ButtonAPI createCheckbox(String text, String font, Color checkColor, UICheckboxSize size);
Added to InteractionDialogAPI:
Version of showCargoPickerDialog() that takes a custom dialog size as a parameter
Added to WeaponSpecAPI:
void setOrdnancePointCost(float armamentCapacity);
3. While I am sharing my wishlist... Could we get cargo / fleet member pickers to work outside of dialogs? Might be affected by the one below...
4. ... And finally renewing my ask for the ability to create UI elements (custom panels) on top of an existing screen. Hope this is not a huge change though (functionality exists, but I get it if it's highly coupled with other code). Ideally I'd love to create a smaller (blocking) panel on top of intel UI (or campaign UI), with an X button and custom content (kinda like you can view commodity demand/availability on top of current market screen).
That's unfortunately a bit complicated, yeah. Sorry!
can we get removeSMod and addSMod, the same as add/removeMod and add/removePermaMod?
I'd like it for some faction-specific hullmod replacements, so they override autofitted smods properly (and it just kinda seems weird that it isnt a thing already)
It's a thing - addPermaMod() has a boolean parameter that sets whether it's an s-mod that's being added.
I'd like a ShipHullSpecAPI.getDeploymentPoints() or some equivalent. Currently I think the only way to obtain it is either loading the ship_data.csv or grabbing it from FleetMemberAPI.getStats().getSuppliesToRecover().getBaseValue() or something to that effect.
That already exists - ShipHullSpecAPI.getSuppliesToRecover()
The ship system WEAPON_BOOST AI only activates against fighters for frigates. Could we get a way to trigger this behavior for certain larger ships?
Hmm - Accelerated Ammo Feeder uses that AI, so I suspect this isn't actually the case?
Would it be possible to change the behavior of ShipAPI.getFleetMember() and MutableShipStatsAPI.getFleetMember() to more reliably return real fleet members instead of dummy fleet members?
Currently, the "stats" and "ship" arguments passed to the various BaseHullMod methods will return dummy fleet members if the hullmod is attached to a module, instead of returning the actual fleet member the module is attached to. Furthermore, modules in this context will present as if they're not modules for other reasons, returning false with isStationModule and null with getParentStation. This makes it very difficult to determine what fleet member the module is attached to.
I realize this might not be feasible if vanilla code relies on the existing behavior of getFleetMember, but I figured I might as well ask. Thanks for considering!
Ahh, this is... let's call it "code that's potentially very sensitive/error prone" and I don't want to touch it unless I absolutely have to. My apologies!
Huh, tested Hammerhead and Roider Union's Firestorm and they do use their AAF vs fighters in 0.95a. They did not in 0.9.1a (tested that too) and I don't recall seeing any patch note mentioning a change in behavior.
Ah, that's entirely possible; the patch notes are definitely not 100% inclusive.
4. ... And finally renewing my ask for the ability to create UI elements (custom panels) on top of an existing screen. Hope this is not a huge change though (functionality exists, but I get it if it's highly coupled with other code). Ideally I'd love to create a smaller (blocking) panel on top of intel UI (or campaign UI), with an X button and custom content (kinda like you can view commodity demand/availability on top of current market screen).
What if this was rephrased into the ability to hide more parts of interaction dialog API? Right now you can hide text or visual panels, but I'd like to hide text and option panels (and have visual panel extend to take over freed space), thus have one big visual panel to work with.
I was thinking you needed it in a different context - i.e. the intel screen. For this, actually, there *will* be something in the new release that should cover it:
InteractionDialogAPI.showCustomVisualDialog(float customPanelWidth, float customPanelHeight, CustomVisualDialogDelegate delegate);
public interface CustomVisualDialogDelegate {
public interface DialogCallbacks {
void dismissDialog();
FaderUtil getPanelFader();
}
void init(CustomPanelAPI panel, DialogCallbacks callbacks);
CustomUIPanelPlugin getCustomPanelPlugin();
float getNoiseAlpha();
void advance(float amount);
void reportDismissed(int option);
}
Basically you get a custom dialog that's *entirely* a CustomPanelAPI, aside from the border decorating it. So it needs to handle being dismissed etc, but you get full control over its contents.
Yup, I wasn't expecting any of these for 0.95.1 - either 0.95.2 (if there is any) or later. Lifting the lid off my wish-list jar, there's one more item I would dearly love to see: the ability to manipulate scrollers programmatically.
Currently, if I want to have a button that changes the state of the CustomPanelAPI (either the one it resides in or elsewhere that is displayed as part of the same view) I have to call `ui.updateUIForItem(this)`. This causes the whole thing to recreate the panel (createLargeIntel()), and shows the default state (every scroller that exist in this view is parked at the top). I am happy to do the legwork, e.g. check scroller position for each CustomPanelAPI, store it internally in my structures, and when I create the same panel in the new call - reapply the scroller.
A bare minimum that I would need is thus:
float CustomPanelAPI.getScrollPosition();
void CustomPanelAPI.setScrollPosition(float);
Now, I THINK I could work this around and correct me if I am wrong. I could be keeping references to every CustomPanelAPI that was created as part of my UI (the ones that I allow scrollers at least), and on consecutive calls reusing them instead of creating a new one. Which is ugly, as these will have been created with different CustomPanelAPIs (from previous calls, so things could break). And it would have to be transient, of course, as resolution could have changed between loads affecting element sizes, and thus scroller positions.
Would it be possible to add some method to register programmatically created variants with the methods used by the variant ID lookup so I can call these SettingsAPI methods on some new variant ID that did not exist at startup:
void addDefaultEntryForRole(java.lang.String role, java.lang.String variantId, float weight)
void addEntryForRole(java.lang.String factionId, java.lang.String role, java.lang.String variantId, float weight)
I would like to programmatically create variants, but since they can't be added to the variant id lookup, I can't dynamically create variants, add default roles for them and add them to faction's known ships & doctrines.
InteractionDialogAPI.hideOptionPanel()
InteractionDialogAPI.showOptionPanel()
We can already toggle visual and text panels, but not the option panel. The only way to draw a custom panel or cargo picker is currently to spawn an empty interaction dialog, and call showXXX on it. Unfortunately, you still see "You decide to..." in the background, even if there are no options to select.
Alternative - just autohide if option list is empty?
New here! I was told this was the best place to bring this up.
Currently all ship systems will "reset" the colors of the ship's shields upon deactivation, not just ship systems that alter the color of the shields (like Fortress Shields). This causes unintended behavior with ships with hullmods etc. that change the color of ship's shields. A boolean resetShieldColor()
or something similar would at least allow us to stop that from happening, although given how hard it was to track down I think it'd be best if the behavior was simply isolated to ship systems that change the shield colors. Have them grab the current colors and then go back to that when they're done, maybe?
{"freq":0, "tip":"You can change the frequency of tips by adding a json object instead of a string, like so. For example, this tip has a frequency of 0 and will never show up. The default freq value is 1."},
I'm interested in this type of code... can there be a method in the SettingsAPI that lets modders set frequency of these tips and/or remove tips?
Asking so that tip frequencies can be modified based on mod interactions and compatibility.
Class:
com.fs.starfarer.api.combat.HullModEffect:
Request:
Add method :
/*
* If return true and hullmod is "visible", the hullmod will be displayed normally in the choosing list at the refit screen.
* If return false, it will be hidden from the list.
* No effect on invisible hullmods.
* default implementation in BaseHullMod (default when not overriden) should return true.
*/
public boolean isDisplayedToShip(com.fs.starfarer.api.combat.ShipAPI arg0);
Use case:
When there are many hullmods created which is only applicable for a small number of ship types, they will appear as non-applicable to all other ships.
This one allows the mod developer of those hull mods to set it such that the hullmods will only appear for the applicable ships and will be hidden from other ships, thus avoiding clogging up the hull mod selection list with a large number of totally irrelevant hullmods for the latter case.
We have `beginGrid` and `beginGridFlipped`, but only `beginTable`. Could you add `beginTableFlipped`? The first column is the header row, and each "row" is a new column.
Also, the ability to "skip" header row in regular table would be great (so I can create fake header row using areacheckbox which looks the same and have them interactive :rubs_hands_in_glee: ).
Finally, the ability to add buttons to this special reserved space at the bottom (I'd love to put my "Delete" button next to "Show on map" button).
Spoiler
(https://media.discordapp.net/attachments/908476833736060969/943117654527471626/unknown.png)
I would like a rulecmd implemented in vanilla or an OR operator for Rule Scripting.
It seems rather inconvenient that this never existed in the current rulecmd packages. I see 5 major mods that use a custom rulecmd just use an OR operator for certain conditions.
EitherOr <memkey> <memkey> <memkey> <memkey> ...
return true if any of the memory key return true or something like that really...
Might be really useful for modders when they want a rule check for $player.fuel >= 50 or $player.supplies >= 100
...
:-[
Can we get FluxTrackerAPI's ventflux() method exposed? Use case is currently a "burst vent" system.
Also MissileAPI.setSprite(), if possible. (Or ideally a setSprite() for all projectiles, but I don't know how feasible that is). Use case is missiles that would require animation, and repeated projectile swaps to achieve that is less than ideal.
edit with a third request- is it possible to add a method to manipulate a beam's endpoint? ie, BeamAPI.setTo()? it's for this:
Spoiler
(https://cdn.discordapp.com/attachments/835725831534936104/980767394194653185/Pen.gif)
Asking for MarketConditionSpecAPI to have setters as well, they are really useful.
Strange for it to have setDecivRemove and setIcon, but not
void setDesc(string desc); for MarketConditionSpecAPI
I'd like this private static to be public please, so modded Luddic factions can add their majority presence here. :-[
public class LuddicMajority extends BaseMarketConditionPlugin {
private static String [] luddicFactions = new String [] {
"knights_of_ludd",
"luddic_church",
"luddic_path",
};
public void apply(String id) {
if (Arrays.asList(luddicFactions).contains(market.getFactionId())) {
market.getStability().modifyFlat(id, ConditionData.STABILITY_LUDDIC_MAJORITY_BONUS, "Luddic majority");
} else {
market.getStability().modifyFlat(id, ConditionData.STABILITY_LUDDIC_MAJORITY_PENALTY, "Luddic majority");
}
}
public void unapply(String id) {
market.getStability().unmodify(id);
}
}
1. Replace Indirect Chains of Methods with Instance Methods
Some API object instances lack instance methods to answer questions about their direct relationships to other API object instances, which are returned only by indirect chains of methods that involve repeating the name of the object instance. I propose that such instance methods as would answer these questions be added to the corresponding API object instances and further, for clarity, the indirect chains be deprecated and later removed.
For example, a WeaponAPI cannot tell you the WeaponGroupAPI to which it belongs,
but must instead ask its ship,
weapon.getShip().getWeaponGroupFor(weapon)
Getting the AutofireAIPlugin of a WeaponAPI entails an even more indirect and repetitive chain.
weapon.getAutofireAIPlugin()
weapon.getShip().getWeaponGroupFor(weapon).getAutofireAIPlugin(weapon)
2. Remove the String source argument from the instance methods of MutableStat and add it to the fields and constructor of that class.
Expose setAfterCreate() [and consequently getCol()] to be called after addRow() to allow us to emulate this from CargoTooltipFactory:
var65.setAfterCreate(new Runnable() {
public void run() {
new var1x = new new(var48.getLocationInHyperspace(), false);
var1x.setSize(var65.getHeight(), var65.getHeight());
var65.getCol(4).add(var1x).inRMid(5.0F);
}
This will, if I understood the code right, allow adding images to specific cells in tables.
Edit: disregard this, turns out combined features of TooltipMakerAPI, LabelAPI and PositionAPI are quite enough for re-creating custom tables in pretty much whatever way one wants.
I've been making a list of API requests over the last few months of tinkering. Some of this might require some context, so... I've been working on a mod that adds simple "planetary operations" to surveyed planets. It's important for the player to be able to see where these are at a glance, so I create an intel item for each one. There can be quite a few of them, however, so I made an intel item for filtering them (see screenshot). Each time the filtration criteria are changed the list of op intel is updated.
Screenshot
(https://i.imgur.com/5X1myN6.png)
My requests:
Some way to prevent calls to IntelUIAPI.updateIntelList from deselecting the currently selected intel, as long as it is still part of the list. It would be nice if the scroll position wasn't reset either. My current workaround is an automated click to re-select the filter intel after updateIntelList is called, which brings me much anxiety and shame.- Some way to change the max number of intel icons shown at once. The current limit is 100, which I think is prudent, but overly restrictive for unconventional applications of the intel map. In my case, I'd like to be able to show up to about 500.
- A TooltipMakerAPI method for displaying planets. Not particularly important, but it could be neat even for a few vanilla intel items.
A way to adjust the fuel range indicator. Part of this mod increases fuel consumption under certain dynamic conditions that can make the default range very misleading. My current solution is to adjust fuel consumption only while the map is open in order to manipulate the range indicator, but that results in the "real" range being shown briefly while the map is closing.- Some way to flag ship engines to prevent their flames from being seen in the campaign view. Maneuvering thrusters do this, but have other characteristics that aren't always desired.
Sorry if I've overlooked existing solutions, and please let me know if any clarification is needed. Thanks for considering, as always :)
In SettingsAPI, please change
Collection<Object> getAllSpecs(Class c);
to
<SPEC> Collection<SPEC> getAllSpecs(Class<SPEC> c);
Use case:
final Collection<Object> specs = settings.getAllSpecs(DropGroupRow.class);
for (final Object spec : specs) {
final DropGroupRow dropGroupRow = (DropGroupRow) spec;
is simplified to
final Collection<DropGroupRow> specs = settings.getAllSpecs(DropGroupRow.class);
for (final DropGroupRow dropGroupRow : specs) {
Please add a base interface for SpecAPIs that contains e.g. the tag handling methods #hasTag(String), #addTag(String), etc.
Use case: Currently code to process tags has to be duplicated for each SpecAPI interface. Note that starting from Java 8, Method References could be used to circumvent this issue (create method parameter Predicate<String> hasTags and pass WeaponSpecAPI::hasTags into it, etc.), but even there just having a common ancestor would be the tidiest solution.
Please remove magical implicit "no_drop" / "no_dealer" functionality from ShipTypeHints.STATION (and actually add these tags to the derelict mothership, like on the Merlon) - currently I have to check for this hint to filter the Explorarium mothership from unobtainable ship specs, because it magically does not need these tags and thence does not have them.
Please add constant for "package_bp" to Items, e.g.
public static final String TAG_BLUEPRINT_PACKAGE = "package_bp";
Please add constant for the "tags" field to... unsure, presumably Tags, e.g.
/** If something can have tags, they will be found in a field of this name. */
public static final String FIELD_IDENTIFIER = "tags";
Please add outer braces to drop_groups.csv column "commodity" so it can be readily parsed using org.util.JSONObject.
E.g. change
wpn_:{tags:[omega, !no_drop], weaponSize:SMALL}
to
{wpn_:{tags:[omega, !no_drop], weaponSize:SMALL}}
Use case:
final JSONObject json = new JSONObject("{" + dropGroupRow.getCommodity() + "}");
final JSONObject item = json.getJSONObject(DropGroupRow.ITEM_PREFIX);
final JSONArray tags = item.getJSONArray(DROP_GROUP_COMMODITY_TAGS);
for (int i = 0; i < tags.length(); ++i) {
final String tag = tags.getString(i);
if (BLUEPRINT_PACKAGE_TAG.equals(tag)) {
dropGroupRow.setFreq(dropGroupRow.getFreq() / 2.f);
break;
}
}
is simplified to
final JSONObject json = new JSONObject(dropGroupRow.getCommodity());
final JSONObject item = json.getJSONObject(DropGroupRow.ITEM_PREFIX);
final JSONArray tags = item.getJSONArray(DROP_GROUP_COMMODITY_TAGS);
for (int i = 0; i < tags.length(); ++i) {
final String tag = tags.getString(i);
if (BLUEPRINT_PACKAGE_TAG.equals(tag)) {
dropGroupRow.setFreq(dropGroupRow.getFreq() / 2.f);
break;
}
}
It is currently too easy to fall into the trap of trying to parse the commodity manually (source: I did and just now realised how stupid I was being), when it is almost perfectly good JSON. E.g. finding "item_" without also finding "item_modspec" while correctly handling all whitespaces is a challenge manually, but a trivial task using JSONObject.
can we get a dynamic equivalent of statBonuses?
something like MutableShipStatsAPI.getDynamic.getStatBonus(String id);
would be v helpful for using dynamic stats to create completely custom stats (e.g, the amount of times a system fires a projectile or the range of those projectiles), rn just having dynamic mutableStats is a bit limiting in that regard.
Re-posting what I mentioned on the announcement thread (https://fractalsoftworks.com/forum/index.php?topic=26020.msg394672#msg394672) here so you see it when reading posts for your next API expansion.
Please expose:
BeamWeaponSpec.setDamagePerSecond(float damagePerSecond);
BeamWeaponSpec.setEmpPerSecond(float empPerSecond);
Without equivalent API methods, I must include not only the black magic for them but also the necessary black magic of ReflectionTools and ProxyTools.
It seems com.fs.starfarer.api.campaign.SubmarketPlugin has
boolean isBlackMarket();
boolean isOpenMarket();
but does not have
boolean isMilitaryMarket();
Could it be added?
public MutableStat getBeamSpeedMult();
for MutableShipStatsAPI, thanks
need ShipAPI.getFleetCommander()
in afterShipCreation() method, ship.getFleetMember would be null, if ship.getCaptain.isDefault, I can't get the fleet commander.
I could get the commander like this, but it's not elegant:
PersonAPI commander = null;
FleetMemberAPI member = ship.getFleetMember();
if (member == null && ship instanceof Ship) {
commander = ((Ship) ship).getFleetCommander();
}}