Hard Light Productions Forums

Modding, Mission Design, and Coding => The Modding Workshop => Topic started by: Goober5000 on November 28, 2009, 01:42:04 am

Title: A handy beam comparison tool
Post by: Goober5000 on November 28, 2009, 01:42:04 am
This is a short program I cooked up because I needed a good way to compare beam damages for balancing Scroll of Atankharzim.  It's not the cleanest or best written code I've ever released, but it does the job and it produces some useful output.

Code: [Select]
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import javax.swing.JFileChooser;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileFilter;


public class BeamStats
{
private static final Pattern NAME_PATTERN = Pattern.compile("\\s*\\$Name\\:.*");
private static final Pattern BEAM_FLAG_PATTERN = Pattern.compile("\\s*\\$Flags\\:\\s*\\(.*\\\"beam\\\".*\\)\\s*");

private static final double BEAM_TIMES_PER_SECOND = 5.8824;

public static void main(String[] args)
{
setLAF();

JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new FileFilter()
{
@Override
public boolean accept(File f)
{
return (f.getName().equals("weapons.tbl")) || f.isDirectory();
}

@Override
public String getDescription()
{
return "Only weapons.tbl";
}
});
chooser.setDialogTitle("Choose a weapons table");
chooser.setCurrentDirectory(new File("C:\\Games\\FreeSpace2\\"));

int returnVal = chooser.showOpenDialog(null);
if (returnVal != JFileChooser.APPROVE_OPTION)
return;
File file = chooser.getSelectedFile();

List<String> fileLines = readTextFileLines(file);

for (int i = 0; i < fileLines.size(); i++)
{
// find flag
if (!BEAM_FLAG_PATTERN.matcher(fileLines.get(i)).matches())
continue;

// backtrack to name
for (int j = i; j >= 0; j--)
{
// find name
if (NAME_PATTERN.matcher(fileLines.get(j)).matches())
{
processBeam(fileLines, j);
break;
}
}
}
}

private static void processBeam(List<String> fileLines, int lineNumber)
{
// print the name
String name = fileLines.get(lineNumber).trim();
for (int i = 6; i < name.length(); i++)
{
if (!Character.isWhitespace(name.charAt(i)))
{
System.out.println(name.substring(i));
break;
}
}

double fireWait = Double.parseDouble(findValue(fileLines, lineNumber, "$Fire Wait:"));

double damage = Double.parseDouble(findValue(fileLines, lineNumber, "$Damage:"));

double life = Double.parseDouble(findValue(fileLines, lineNumber, "+Life:"));

// for AAA beams
int shots = Integer.parseInt(findValue(fileLines, lineNumber, "+Shots:"));
if (shots <= 0)
shots = 1;

// calculate total damage per shot
double damage_per_shot = damage * life * BEAM_TIMES_PER_SECOND;

// calculate times per minute
double times_per_minute = 60.0 / fireWait;

System.out.println("Damage per shot:   " + (int) (damage_per_shot));
if (shots > 1)
{
System.out.println("Shots:             " + shots);
System.out.println("Cumulative damage: " + (int) (damage_per_shot) * shots);
}
System.out.println("Fire wait:         " + (int) fireWait);
System.out.println("Damage per minute: " + (int) (damage_per_shot * times_per_minute * shots));
System.out.println();
}

private static String findValue(List<String> fileLines, int startLine, String startsWith)
{
for (int i = startLine; i < fileLines.size(); i++)
{
String line = fileLines.get(i).trim();
if (line.startsWith(startsWith))
{
int pos = line.indexOf(';');
if (pos >= 0)
return line.substring(startsWith.length(), pos).trim();
else
return line.substring(startsWith.length()).trim();
}
}

System.err.println("Can't find " + startsWith);
return null;
}

public static List<String> readTextFileLines(File file)
{
List<String> lines = new ArrayList<String>();
try
{
BufferedReader reader = new BufferedReader(new FileReader(file));

String str;
while ((str = reader.readLine()) != null)
lines.add(str);

reader.close();
}
catch (IOException ioe)
{
ioe.printStackTrace();
lines.clear();
}

return lines;
}

private static void setLAF()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (ClassNotFoundException cnfe)
{
cnfe.printStackTrace();
}
catch (InstantiationException ie)
{
ie.printStackTrace();
}
catch (IllegalAccessException iae)
{
iae.printStackTrace();
}
catch (UnsupportedLookAndFeelException ulafe)
{
ulafe.printStackTrace();
}
}
}

It's a standard Java program with no dependencies.  It compiles and runs under Java 1.6; I haven't tried it on anything earlier but you could probably get it to work on an earlier version with little trouble.

Here's the output on the standard FS2 weapons table:

Code: [Select]
@Targeting Laser
Damage per shot:   0
Fire wait:         0
Damage per minute: 0

SRed
Damage per shot:   4470
Fire wait:         25
Damage per minute: 10729

SAAA
Damage per shot:   185
Shots:             3
Cumulative damage: 555
Fire wait:         5
Damage per minute: 6670

LRed
Damage per shot:   24706
Fire wait:         10
Damage per minute: 148236

BFRed
Damage per shot:   86471
Fire wait:         10
Damage per minute: 518827

AAAf
Damage per shot:   205
Shots:             3
Cumulative damage: 615
Fire wait:         5
Damage per minute: 6738

AAAh
Damage per shot:   205
Shots:             3
Cumulative damage: 615
Fire wait:         5
Damage per minute: 6738

S-AAA-Weak
Damage per shot:   88
Shots:             3
Cumulative damage: 264
Fire wait:         5
Damage per minute: 3176

ULTRA Anti-Fighter Beam
Damage per shot:   441
Shots:             3
Cumulative damage: 1323
Fire wait:         2
Damage per minute: 36096

TerSlash
Damage per shot:   4117
Fire wait:         10
Damage per minute: 24706

LTerSlash
Damage per shot:   1941
Fire wait:         10
Damage per minute: 11647

BFGreen
Damage per shot:   44706
Fire wait:         35
Damage per minute: 76639

LRBGreen
Damage per shot:   44706
Fire wait:         35
Damage per minute: 76639

BGreen
Damage per shot:   28235
Fire wait:         30
Damage per minute: 56471

SGreen
Damage per shot:   3088
Fire wait:         45
Damage per minute: 4117

SVas
Damage per shot:   5147
Fire wait:         20
Damage per minute: 15441

BVas
Damage per shot:   23941
Fire wait:         24
Damage per minute: 59853

VSlash
Damage per shot:   8823
Fire wait:         10
Damage per minute: 52941

Green Beam
Damage per shot:   2352
Fire wait:         10
Damage per minute: 14117

MjolnirBeam
Damage per shot:   17647
Fire wait:         7
Damage per minute: 151261

MjolnirBeam#home
Damage per shot:   9411
Fire wait:         7
Damage per minute: 80672

One of the things we've changed in Scroll is the massive disparity between SGreen and SVas. :)
Title: Re: A handy beam comparison tool
Post by: Galemp on November 28, 2009, 02:19:30 am
what! You're changing the stats of canonical weapons? That sucks. Reminds me of what CP did with Procyon Insurgency; he edited the Akheton SDG to make it much better and didn't tell anyone about it.

On the other hand :v: did the same things with all kinds of stats, going from FS1 to FS2. So I guess you can if you want to.
Title: Re: A handy beam comparison tool
Post by: Goober5000 on November 28, 2009, 02:38:36 am
Not only is that off-topic, it's inapplicable because the Akheton is a player-chosen weapon and the SGreen is not... :nervous:
Title: Re: A handy beam comparison tool
Post by: Nuke on November 28, 2009, 05:19:05 am
i usually just use spreadsheets for this kinda thing.
Title: Re: A handy beam comparison tool
Post by: Qent on November 28, 2009, 08:38:20 am
I thought that the lifetime of a AAA beam is divided among its shots, so that the number of shots has no effect on damage.

And where did 5.8824 come from? Just wondering.
Title: Re: A handy beam comparison tool
Post by: Goober5000 on November 28, 2009, 11:52:48 am
I thought that the lifetime of a AAA beam is divided among its shots, so that the number of shots has no effect on damage.
Mmmm, you might be right.  Easily fixed in the code, though.

Quote
And where did 5.8824 come from? Just wondering.
Beam damage is applied every 170 milliseconds, thus 5.8824 times a second.
Title: Re: A handy beam comparison tool
Post by: Nuke on November 28, 2009, 08:14:05 pm
^good to know, because my spreadsheets assumed damage was applied 6 times a second, which kinda threw my spreadsheets off.
Title: Re: A handy beam comparison tool
Post by: chief1983 on November 29, 2009, 03:59:25 pm
I was actually thinking about making an app that did something similar for all sorts of weapons, based off of whatever tables you feed it.  Haven't had time though.
Title: Re: A handy beam comparison tool
Post by: Aardwolf on November 29, 2009, 06:09:46 pm
Beam damage is applied every 170 milliseconds, thus 5.8824 times a second.

Is this the sort of thing that maybe should go into ai-profiles.tbl (or whatever that one that has big changes in it is) ?

That is, being able to change the interval. I imagine some mods (particularly ones with fighterbeams) might find that useful.
Title: Re: A handy beam comparison tool
Post by: Goober5000 on November 29, 2009, 08:14:55 pm
Ummm... no.  That's a fundamental game mechanic.  I doubt there'd be any valid reason to change it.
Title: Re: A handy beam comparison tool
Post by: Droid803 on November 29, 2009, 11:23:02 pm
Not completely related, but...Scaling the interval with time compression would probably help reduce issues caused by, well, time compression, though...
Because as it stands right now, beams do different amounts of damage in the same number of full pulses under different levels of time compression.
Title: Re: A handy beam comparison tool
Post by: Goober5000 on November 30, 2009, 02:56:28 am
That makes sense.  If time compression is faster than 5.8824x, then of course some beam damage is going to be skipped.

And incidentally, time compression was originally capped at 4x.  Perhaps this was one of the reasons why.  In any case, there really isn't any reason why players should be fast-forwarding at more than 4x during a battle.
Title: Re: A handy beam comparison tool
Post by: Dragon on November 30, 2009, 08:03:58 am
Unless you want to get killed, thare's absolutely no reason to fast forward during battle at all, at least well written one.
Title: Re: A handy beam comparison tool
Post by: chief1983 on November 30, 2009, 09:41:30 am
I think it was actually used as a hack, since it became known that you could change the damage done by using different time compression levels.
Title: Re: A handy beam comparison tool
Post by: Aardwolf on November 30, 2009, 11:08:51 am
Sometimes you just get bored after hearing the same dialog over and over, or watching the same predefined sequence over and over, etc., and 64x time compression starts to look good.

Although... you could possibly change it so that > 4x is only enabled with cheats or sexps, as it is for < 1x
Title: Re: A handy beam comparison tool
Post by: chief1983 on November 30, 2009, 01:41:19 pm
Really if missions with a long intro had a Press X to Fast Forward option, that'd be awesome.