Update: At this point, the latest Antipodes 8 build is the best way to go. Once that's in trunk, it'll probably be the next Antipodes release.
So, I threw together a build and since I'm uploading for FotG to use I figured I'd see if anyone else wanted to give it a shot as well.
fso_3_6_13_INF_SSE2_r6481_HUD_Diff10_voicer.7zOS X Build threadPatchThis includes the latest set of
Swifty's HUD branch, plus trunk through r6478, as well as the below patch. The attached patch file also enables speech and voice recognition in VS2008.
WARNING: USE NEW PILOT FILEOk, I've checked this build for a while, and I haven't seen it break a pilot file yet. If you switch to another build and save a pilot, the key bind should just disappear from the pilot's config, or possibly even just be ignored and still saved, not sure. But since there's a chance it could make your pilot asplode, I'm warning you not to use one you care about with this build.
Index: code/controlconfig/controlsconfig.h
===================================================================
--- code/controlconfig/controlsconfig.h (revision 6350)
+++ code/controlconfig/controlsconfig.h (working copy)
@@ -211,8 +211,11 @@
//Gliding
#define TOGGLE_GLIDING 117
+//Inflight configurable firing sequence
+#define CYCLE_PRIMARY_WEAPON_SEQUENCE 118
+
// this should be the total number of control action defines above (or last define + 1)
-#define CCFG_MAX 118
+#define CCFG_MAX 119
extern int Failed_key_index;
extern int Invert_heading;
Index: code/controlconfig/controlsconfigcommon.cpp
===================================================================
--- code/controlconfig/controlsconfigcommon.cpp (revision 6350)
+++ code/controlconfig/controlsconfigcommon.cpp (working copy)
@@ -183,6 +183,7 @@
{ KEY_ALTED | KEY_A, -1, COMPUTER_TAB, false, "Toggle Auto Pilot"},
{ KEY_ALTED | KEY_N, -1, COMPUTER_TAB, false, "Cycle Nav Points"},
{ KEY_ALTED | KEY_G, -1, SHIP_TAB, false, "Toggle Gliding"},
+ { KEY_O, -1, WEAPON_TAB, false, "Cycle Primary Weapon Firing Rate" },
{ -1, -1, -1, false, "" }
};
Index: code/io/keycontrol.cpp
===================================================================
--- code/io/keycontrol.cpp (revision 6350)
+++ code/io/keycontrol.cpp (working copy)
@@ -60,6 +60,120 @@
#include "autopilot/autopilot.h"
#include "cmdline/cmdline.h"
+#define MAX_NUM_SLOTS 6
+
+struct ftable
+{
+int count;
+int table[ MAX_NUM_SLOTS ];
+};
+
+#define MAX_SLOT_COUNT 25
+
+class factor_table
+ {
+ public:
+ factor_table();
+ ~factor_table(){ delete[] table; };
+ int getNextSlots( int slots_on_ship, int cur_slots );
+
+ private:
+ ftable * table;
+ };
+
+factor_table ftables;
+
+static bool isAPrimeFactor( int factor, int product )
+{
+return ( (float)product / (float)factor ) == (product / factor);
+}
+
+factor_table::factor_table()
+{
+table = new ftable[ MAX_NUM_SLOTS ];
+
+memset( table, 0x00, sizeof( ftable ) * MAX_NUM_SLOTS );
+for( int i = 0 ; i < MAX_NUM_SLOTS; ++i )
+ {
+ table[ i ].count = 0;
+ for( int j = 1; j <= i; ++j )
+ {
+ if( isAPrimeFactor( j, i ) )
+ {
+ table[ i ].table[ table[ i ].count ] = j;
+ table[ i ].count ++;
+ }
+ }
+ }
+}
+
+int factor_table::getNextSlots(int slots_on_ship, int cur_slots)
+{
+Assert( slots_on_ship <= MAX_NUM_SLOTS );
+Assert( slots_on_ship >= 0 );
+
+for( int i = 0; i < table[ slots_on_ship ].count; ++i )
+ {
+ if( table[ slots_on_ship ].table[ i ] == cur_slots )
+ {
+ if( table[ slots_on_ship ].count == i + 1 )
+ {
+ //Overflow back to 1
+ return 1;
+ }
+ else
+ {
+ //Next block in the table
+ return table[ slots_on_ship ].table[ i + 1 ];
+ }
+ }
+ }
+//Did not find cur_slots, try and get back on track
+
+Assert( 0 );
+return 1;
+}
+
+//Dynamic weapon link tables
+/*
+static const ftable ftables[]=
+{
+ { 0, { } }, //Alignment placeholder
+ { 1, { 1 } }, //1 gun
+ { 2, { 1, 2 } }, //2 guns
+ { 2, { 1, 3 } }, //3 guns
+ { 3, { 1, 2, 4} }, //4 guns
+ { 2, { 1, 5 } }, //5 guns
+ { 4, { 1, 2, 3, 6 } } //6 guns
+};*/
+
+/*
+char getNextSlots( char slots_on_ship, char cur_slots )
+{
+Assert( slots_on_ship <= MAX_NUM_SLOTS );
+Assert( slots_on_ship >= 0 );
+
+for( int i = 0; i < ftables[ slots_on_ship ].count; ++i )
+ {
+ if( ftables[ slots_on_ship ].table[ i ] == cur_slots )
+ {
+ if( ftables[ slots_on_ship ].count == i + 1 )
+ {
+ //Overflow back to 0
+ return 0;
+ }
+ else
+ {
+ //Next block in the table
+ return ftables[ slots_on_ship ].table[ i + 1 ];
+ }
+ }
+ }
+//Did not find cur_slots, try and get back on track
+Assert( 0 );
+return 0;
+}*/
+
// --------------------------------------------------------------
// Global to file
// --------------------------------------------------------------
@@ -225,8 +339,9 @@
HUD_TARGETBOX_TOGGLE_WIREFRAME,
AUTO_PILOT_TOGGLE,
NAV_CYCLE,
-
- TOGGLE_GLIDING
+
+ TOGGLE_GLIDING,
+ CYCLE_PRIMARY_WEAPON_SEQUENCE
};
int Dead_key_set[] = {
@@ -360,7 +475,8 @@
HUD_TARGETBOX_TOGGLE_WIREFRAME,
AUTO_PILOT_TOGGLE,
NAV_CYCLE,
- TOGGLE_GLIDING
+ TOGGLE_GLIDING,
+ CYCLE_PRIMARY_WEAPON_SEQUENCE
};
@@ -1793,6 +1909,18 @@
}
switch (n) {
+ // cycle num primaries to fire at once
+ case CYCLE_PRIMARY_WEAPON_SEQUENCE:
+ {
+ ship * shipp = &Ships[objp->instance];
+ ship_weapon *swp = &shipp->weapons;
+ ship_info *sip = &Ship_info[shipp->ship_info_index];
+ polymodel *pm = model_get( sip->model_num );
+ shipp->last_fired_point[ swp->current_primary_bank ] = ( shipp->last_fired_point[ swp->current_primary_bank ] + 1 ) % ftables.getNextSlots( pm->gun_banks[ swp->current_primary_bank ].num_slots, swp->primary_bank_slot_count[ swp->current_primary_bank ] );
+ swp->primary_bank_slot_count[ swp->current_primary_bank ] = ftables.getNextSlots( pm->gun_banks[ swp->current_primary_bank ].num_slots, swp->primary_bank_slot_count[ swp->current_primary_bank ] );
+ }
+ break;
+
// cycle to next primary weapon
case CYCLE_NEXT_PRIMARY:
if (at_self) {
@@ -2299,6 +2427,10 @@
// now handle keys the regular way
switch (n) {
+ case CYCLE_PRIMARY_WEAPON_SEQUENCE:
+ return button_function_critical(CYCLE_PRIMARY_WEAPON_SEQUENCE);
+ break;
+
// cycle to next primary weapon
case CYCLE_NEXT_PRIMARY:
return button_function_critical(CYCLE_NEXT_PRIMARY);
Index: code/ship/ship.cpp
===================================================================
--- code/ship/ship.cpp (revision 6350)
+++ code/ship/ship.cpp (working copy)
@@ -281,6 +281,7 @@
{ "gun convergence", SIF2_GUN_CONVERGENCE, 1 },
{ "no thruster geometry noise", SIF2_NO_THRUSTER_GEO_NOISE, 1 },
{ "intrinsic no shields", SIF2_INTRINSIC_NO_SHIELDS, 1 },
+ { "dynamic primary linking", SIF2_DYN_PRIMARY_LINKING, 1 },
{ "no primary linking", SIF2_NO_PRIMARY_LINKING, 1 },
{ "no pain flash", SIF2_NO_PAIN_FLASH, 1 },
@@ -7686,6 +7687,7 @@
// Later, this will happen in the weapon loadout screen.
for (i=0; i < MAX_SHIP_PRIMARY_BANKS; i++){
swp->primary_bank_weapons[i] = sip->primary_bank_weapons[i];
+ swp->primary_bank_slot_count[i] = 1; // RSAXVC DYN LINK CODE
}
for (i=0; i < MAX_SHIP_SECONDARY_BANKS; i++){
@@ -9071,8 +9073,12 @@
// swp->next_primary_fire_stamp[bank_to_fire] = timestamp();
}
- if (winfo_p->wi_flags2 & WIF2_CYCLE){
+ if (sip->flags2 & SIF2_DYN_PRIMARY_LINKING ) {
Assert(pm->gun_banks[bank_to_fire].num_slots != 0);
+ swp->next_primary_fire_stamp[bank_to_fire] = timestamp((int)(next_fire_delay * ( swp->primary_bank_slot_count[ bank_to_fire ] ) / pm->gun_banks[bank_to_fire].num_slots ) );
+ swp->last_primary_fire_stamp[bank_to_fire] = timestamp();
+ }else if (winfo_p->wi_flags2 & WIF2_CYCLE){
+ Assert(pm->gun_banks[bank_to_fire].num_slots != 0);
swp->next_primary_fire_stamp[bank_to_fire] = timestamp((int)(next_fire_delay / pm->gun_banks[bank_to_fire].num_slots));
swp->last_primary_fire_stamp[bank_to_fire] = timestamp();
//to maintain balance of fighters with more fire points they will fire faster than ships with fewer points
@@ -9193,8 +9199,11 @@
// ok if this is a cycling weapon use shots as the number of points to fire from at a time
// otherwise shots is the number of times all points will be fired (used mostly for the 'shotgun' effect)
- if (winfo_p->wi_flags2 & WIF2_CYCLE) {
+ if ( sip->flags2 & SIF2_DYN_PRIMARY_LINKING ) {
numtimes = 1;
+ points = MIN( num_slots, swp->primary_bank_slot_count[ bank_to_fire ] );
+ } else if ( winfo_p->wi_flags2 & WIF2_CYCLE ) {
+ numtimes = 1;
points = MIN(num_slots, winfo_p->shots);
} else {
numtimes = winfo_p->shots;
@@ -9300,7 +9309,7 @@
for ( j = 0; j < points; j++ ) {
int pt; //point
- if (winfo_p->wi_flags2 & WIF2_CYCLE){
+ if (winfo_p->wi_flags2 & WIF2_CYCLE || sip->flags2 & SIF2_DYN_PRIMARY_LINKING ){
//pnt = pm->gun_banks[bank_to_fire].pnt[shipp->last_fired_point[bank_to_fire]+j%num_slots];
pt = (shipp->last_fired_point[bank_to_fire]+1)%num_slots;
//mprintf(("fireing from %d\n",shipp->last_fired_point[bank_to_fire]+j%num_slots));
@@ -10384,6 +10393,11 @@
Assert((swp->current_primary_bank >= 0) && (swp->current_primary_bank < swp->num_primary_banks));
// first check if linked
+ if ( shipp->flags2 & SF2_SHIP_SELECTIVE_LINKING )
+ {
+ printf("npb:%i\n", swp->num_primary_banks );
+ }
+
if ( shipp->flags & SF_PRIMARY_LINKED )
{
shipp->flags &= ~SF_PRIMARY_LINKED;
Index: code/ship/ship.h
===================================================================
--- code/ship/ship.h (revision 6350)
+++ code/ship/ship.h (working copy)
@@ -115,9 +115,13 @@
int primary_bank_ammo[MAX_SHIP_PRIMARY_BANKS]; // Number of missiles left in primary bank
int primary_bank_start_ammo[MAX_SHIP_PRIMARY_BANKS]; // Number of missiles starting in primary bank
int primary_bank_capacity[MAX_SHIP_PRIMARY_BANKS]; // Max number of projectiles in bank
- int primary_next_slot[MAX_SHIP_PRIMARY_BANKS]; // Next slot to fire in the bank
int primary_bank_rearm_time[MAX_SHIP_PRIMARY_BANKS]; // timestamp which indicates when bank can get new projectile
+ // end ballistic primary support
+ // dynamic weapon linking - by RSAXVC
+ int primary_bank_slot_count[MAX_SHIP_PRIMARY_BANKS]; // Fire this many slots at a time
+ // end dynamic weapon linking
+
int secondary_bank_ammo[MAX_SHIP_SECONDARY_BANKS]; // Number of missiles left in secondary bank
int secondary_bank_start_ammo[MAX_SHIP_SECONDARY_BANKS]; // Number of missiles starting in secondary bank
int secondary_bank_capacity[MAX_SHIP_SECONDARY_BANKS]; // Max number of missiles in bank
@@ -392,6 +396,7 @@
#define SF2_SET_CLASS_DYNAMICALLY (1<<18) // Karajorma - This ship should have its class assigned rather than simply read from the mission file
#define SF2_LOCK_ALL_TURRETS_INITIALLY (1<<19) // Karajorma - Lock all turrets on this ship at mission start or on arrival
#define SF2_FORCE_SHIELDS_ON (1<<20)
+#define SF2_SHIP_SELECTIVE_LINKING (1<<21) // RSAXVC - Allow pilot to pick firing configuration
// If any of these bits in the ship->flags are set, ignore this ship when targetting
extern int TARGET_SHIP_IGNORE_FLAGS;
@@ -816,8 +821,9 @@
#define SIF2_INTRINSIC_NO_SHIELDS (1 << 9) // Chief - disables shields for this ship even without No Shields in mission.
#define SIF2_NO_PRIMARY_LINKING (1 << 10) // Chief - slated for 3.7 originally, but this looks pretty simple to implement.
#define SIF2_NO_PAIN_FLASH (1 << 11) // The E - disable red pain flash
+#define SIF2_DYN_PRIMARY_LINKING (1 << 12) // RSAXVC - Dynamically generate weapon linking options
// !!! IF YOU ADD A FLAG HERE BUMP MAX_SHIP_FLAGS !!!
-#define MAX_SHIP_FLAGS 12 // Number of distinct flags for flags field in ship_info struct
+#define MAX_SHIP_FLAGS 13 // Number of distinct flags for flags field in ship_info struct
#define SIF_DEFAULT_VALUE 0
#define SIF2_DEFAULT_VALUE 0
A sample modular table (*-shp.tbm) that utilizes the cycling feature would look something like this:
#Ship Classes
;; Rebel Fighters
$Name: BTL-A4 Y-Wing
+nocreate
$Flags: ( "dynamic primary linking" )
+noreplace
;; Imperial Fighters
$Name: T.I.E. Fighter
+nocreate
$Flags: ( "dynamic primary linking" )
+noreplace
#End
Without a table change, this build should behave identically to trunk + Swifty's HUD code, so please make sure no primary weapon oddity is noticed with this build when not using the feature. I'd love to hear from anyone using fighter beams, or any other strange primary weapon setups to see how this is working.
I should clarify that by default with this build, the key is bound to 'O', and is selectable in the input configuration menu in game. You can see an example of it in action in
FotG's Cruiser Scuffle video.
It won't be able to be committed to trunk as is, because the pilot code will modify how key binds are handled somewhat. But, it should be easy enough to port over once that hits SVN, and I'm hoping that this can be one of the first new key binds supported.
edit: Aug 17 Updated build with latest Swifty's branch r6373, trunk synced through r6354.
edit: Sept 11 Updated build with latest Swifty's branch r6443, trunk synced through r6444.
edit: Sept 21 Updated build with latest Swifty's branch r6481, trunk synced through r6478.
[attachment deleted by ninja]