Author Topic: [Committed] Auto Spread Shields  (Read 6894 times)

0 Members and 1 Guest are viewing this topic.

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
[Committed] Auto Spread Shields
This patch allows shields which extend a given distance away from the ship's hull, without requiring a shield mesh. This is good for capships, ships with odd shapes with which shield meshes tend to not work right, or ships with large moving parts which would require a huge shield mesh to cover. Or simply if you don't feel like making shield meshes. However, the shield impact effects which normally get projected onto the shield mesh itself won't occur.

Since it'd look bad if, for example, you were close to a capship and your fighter lasers would hit its shields as soon as you pressed the trigger, weapons are always guaranteed to travel at least a distance equal to the thickness of the shield before they're allowed to impact it; unless of course the weapon hits the hull, in which case it is treated as a shield hit, just like when surface shields are used.

To enable the shields for a particular ship type, you need to give the ship type the "auto spread shields" flag and then specify the shield thickness underneath the $Shields attribute:

Code: [Select]
...
$SBank Capacity: ( )
$Shields: 500
  +Auto Spread: 50 ;makes the shield 50m thick
  +Spread From LOD: 2 ;OPTIONAL: projects the shield based on LOD2, helps performance a lot
$Shield Color:                100, 100, 100
...

Later on I might make it a ship-specific rather than shiptype-specific attribute and expose it to Lua, but for now it's defined per shiptype only. I could also add an option to make hits closer to the hull deal more damage than hits to the outer boundary of the shield if someone has a particular need for that, or for disabling the above-mentioned exception to the minimum weapon travel distances. You can make other suggestions, but I won't promise anything.

And here's the patch itself (also as an attachment):

Code: [Select]
Index: ship/ship.h
===================================================================
--- ship/ship.h (revision 9629)
+++ ship/ship.h (working copy)
@@ -918,8 +918,9 @@
 #define SIF2_NO_ETS (1 << 13) // The E - No ETS on this ship class
 #define SIF2_NO_LIGHTING (1 << 14) // Valathil - No lighting for this ship
 #define SIF2_DYN_PRIMARY_LINKING (1 << 15) // RSAXVC - Dynamically generate weapon linking options
+#define SIF2_AUTO_SPREAD_SHIELDS (1 << 16) // zookeeper - auto spread shields
 // !!! IF YOU ADD A FLAG HERE BUMP MAX_SHIP_FLAGS !!!
-#define MAX_SHIP_FLAGS 16 // Number of distinct flags for flags field in ship_info struct
+#define MAX_SHIP_FLAGS 17 // Number of distinct flags for flags field in ship_info struct
 #define SIF_DEFAULT_VALUE 0
 #define SIF2_DEFAULT_VALUE 0
 
@@ -1290,6 +1291,8 @@
 
  float max_hull_strength; // Max hull strength of this class of ship.
  float max_shield_strength;
+ float auto_shield_spread;
+ int auto_shield_spread_from_lod;
 
  float hull_repair_rate; //How much of the hull is repaired every second
  float subsys_repair_rate; //How fast
Index: ship/ship.cpp
===================================================================
--- ship/ship.cpp (revision 9629)
+++ ship/ship.cpp (working copy)
@@ -305,6 +305,7 @@
  { "no pain flash", SIF2_NO_PAIN_FLASH, 1 },
  { "no ets", SIF2_NO_ETS, 1 },
  { "no lighting", SIF2_NO_LIGHTING, 1 },
+ { "auto spread shields", SIF2_AUTO_SPREAD_SHIELDS, 1 },
 
  // to keep things clean, obsolete options go last
  { "ballistic primaries", -1, 255 }
@@ -806,6 +807,8 @@
  }
 
  sip->max_shield_strength = 0.0f;
+ sip->auto_shield_spread = 0.0f;
+ sip->auto_shield_spread_from_lod = -1;
  sip->shield_color[0] = 255;
  sip->shield_color[1] = 255;
  sip->shield_color[2] = 255;
@@ -2428,9 +2431,23 @@
  stuff_bool_list(sip->draw_secondary_models, sip->num_secondary_banks);
  }
 
- if(optional_string("$Shields:"))
+ if(optional_string("$Shields:")) {
  stuff_float(&sip->max_shield_strength);
 
+ if(optional_string("+Auto Spread:")) {
+ stuff_float(&sip->auto_shield_spread);
+ }
+ if(optional_string("+Spread From LOD:")) {
+ int temp;
+ stuff_int(&temp);
+
+ if (temp > sip->num_detail_levels)
+ Warning(LOCATION, "+Spread From LOD for %s was %i whereas ship only has %i detail levels, ignoring...", sip->name, temp, sip->num_detail_levels);
+ else
+ sip->auto_shield_spread_from_lod = temp;
+ }
+ }
+
  // optional shield color
  if(optional_string("$Shield Color:")){
  stuff_ubyte(&sip->shield_color[0]);
@@ -8782,6 +8799,12 @@
  } else
  shipp->shield_integrity = NULL;
 
+ // Bump the object radius to ensure that collision detection works right
+ // even when spread shields extend outside the models natural radius
+ if (sip->flags2 & SIF2_AUTO_SPREAD_SHIELDS) {
+ Objects[objnum].radius += sip->auto_shield_spread;
+ }
+
  // allocate memory for keeping glow point bank status (enabled/disabled)
  {
  bool val = true; // default value, enabled
Index: object/collideshipweapon.cpp
===================================================================
--- object/collideshipweapon.cpp (revision 9629)
+++ object/collideshipweapon.cpp (working copy)
@@ -193,41 +193,136 @@
  // will absorb it when it hits the hull instead.  This has no fancy graphical effect, though.
  // Someone should make one.
 
- // set flags
- mc_shield.flags = MC_CHECK_SHIELD;
- mc_hull.flags = MC_CHECK_MODEL;
-
  // check both kinds of collisions
- int shield_collision = (pm->shield.ntris > 0) ? model_collide(&mc_shield) : 0;
- int hull_collision = model_collide(&mc_hull);
+ int shield_collision = 0;
+ int hull_collision = 0;
 
  // check shields for impact
- if (!(ship_objp->flags & OF_NO_SHIELDS))
- {
- // pick out the shield quadrant
- if (shield_collision)
- quadrant_num = get_quadrant(&mc_shield.hit_point);
- else if (hull_collision && (sip->flags2 & SIF2_SURFACE_SHIELDS)) {
- vec3d local_pos, local_pos_rot;
- vm_vec_sub(&local_pos, &mc_hull.hit_point_world, &ship_objp->pos);
- vm_vec_rotate(&local_pos_rot, &local_pos, &ship_objp->orient);
- quadrant_num = get_quadrant(&local_pos_rot);
+ if (!(ship_objp->flags & OF_NO_SHIELDS)) {
+ if (sip->flags2 & SIF2_AUTO_SPREAD_SHIELDS) {
+ // The weapon is not allowed to impact the shield before it reaches this point
+ vec3d shield_ignored_until = weapon_objp->last_pos;
+
+ float weapon_flown_for = vm_vec_dist(&wp->start_pos, &weapon_objp->last_pos);
+
+ // If weapon hasn't yet flown a distance greater than the maximum ignore
+ // range, then some part of the currently checked range needs to be
+ // ignored
+ if (weapon_flown_for < sip->auto_shield_spread) {
+ vm_vec_sub(&shield_ignored_until, &weapon_end_pos, &wp->start_pos);
+ vm_vec_normalize(&shield_ignored_until);
+ vm_vec_scale(&shield_ignored_until, sip->auto_shield_spread);
+ vm_vec_add2(&shield_ignored_until, &wp->start_pos);
+ }
+
+ float this_range = vm_vec_dist(&weapon_objp->last_pos, &weapon_end_pos);
+
+ // The range during which the weapon is not allowed to collide with the
+ // shield, except if it actually hits the hull
+ float ignored_range;
+
+ // If the weapon has not yet surpassed the ignore range, calculate the
+ // remaining ignore range
+ if (vm_vec_dist(&wp->start_pos, &shield_ignored_until) > weapon_flown_for)
+ ignored_range = vm_vec_dist(&weapon_objp->last_pos, &shield_ignored_until);
+ else
+ ignored_range = 0.0f;
+
+ // The range during which the weapon may impact the shield
+ float active_range = this_range - ignored_range;
+
+ // During the ignored range, we only check for a ray collision with
+ // the model
+ if (ignored_range > 0.0f) {
+ mc_shield.flags = MC_CHECK_MODEL;
+ mc_shield.p1 = &shield_ignored_until;
+
+ shield_collision = model_collide(&mc_shield);
+
+ mc_shield.p1 = &weapon_end_pos;
+ mc_shield.hit_dist = mc_shield.hit_dist * (ignored_range / this_range);
+ }
+
+ // If no collision with the model found in the ignore range, only
+ // then do we check for sphereline collisions with the model during the
+ // non-ignored range
+ if (!shield_collision && weapon_flown_for + this_range > sip->auto_shield_spread) {
+ mc_shield.p0 = &shield_ignored_until;
+
+ mc_shield.p1 = &weapon_end_pos;
+
+ mc_shield.radius = sip->auto_shield_spread;
+
+ mc_shield.flags = MC_CHECK_MODEL | MC_CHECK_SPHERELINE;
+
+ if (sip->auto_shield_spread_from_lod > -1) {
+ polymodel *pm = model_get(sip->model_num);
+ mc_shield.submodel_num = pm->detail[sip->auto_shield_spread_from_lod];
+ }
+
+ shield_collision = model_collide(&mc_shield);
+
+ mc_shield.submodel_num = -1;
+
+ // Because we manipulated p0 and p1 above, hit_dist will be
+ // relative to the values we used, not the values the rest of
+ // the code expects; this fixes that
+ mc_shield.p0 = &weapon_objp->last_pos;
+ mc_shield.p1 = &weapon_end_pos;
+ mc_shield.hit_dist = (ignored_range + (active_range * mc_shield.hit_dist)) / this_range;
+ }
+
+ if (shield_collision) {
+ // If we used a sphereline check, then the collision point will lie
+ // somewhere on the ship's hull; this re-positions it to lie on the
+ // correct point along the weapon's path
+ if (mc_shield.flags & MC_CHECK_SPHERELINE) {
+ vec3d tempv;
+ vm_vec_sub(&tempv, mc_shield.p1, mc_shield.p0);
+ vm_vec_scale(&tempv, mc_shield.hit_dist);
+ vm_vec_add2(&tempv, mc_shield.p0);
+ mc_shield.hit_point_world = tempv;
+ }
+
+ // Re-calculate hit_point because it's likely pointing to the wrong
+ // place
+ vec3d tempv;
+ vm_vec_sub(&tempv, &mc_shield.hit_point_world, &ship_objp->pos);
+ vm_vec_rotate(&mc_shield.hit_point, &tempv, &ship_objp->orient);
+ }
+ } else if (sip->flags2 & SIF2_SURFACE_SHIELDS) {
+ mc_shield.flags = MC_CHECK_MODEL;
+ shield_collision = model_collide(&mc_shield);
+ } else {
+ // Normal collision check against a shield mesh
+ mc_shield.flags = MC_CHECK_SHIELD;
+ shield_collision = (pm->shield.ntris > 0) ? model_collide(&mc_shield) : 0;
  }
+ }
 
+ // If we found a shield collision but were only checking for a simple model
+ // collision, we can re-use the same collision info for the hull as well
+ if (shield_collision && mc_shield.flags == MC_CHECK_MODEL) {
+ memcpy(&mc_hull, &mc_shield, sizeof(mc_info));
+ hull_collision = shield_collision;
+ } else {
+ mc_hull.flags = MC_CHECK_MODEL;
+ hull_collision = model_collide(&mc_hull);
+ }
+
+ if (shield_collision) {
+ // pick out the shield quadrant
+ quadrant_num = get_quadrant(&mc_shield.hit_point);
+
  // make sure that the shield is active in that quadrant
- if ((quadrant_num >= 0) && ((shipp->flags & SF_DYING) || !ship_is_shield_up(ship_objp, quadrant_num)))
+ if (shipp->flags & SF_DYING || !ship_is_shield_up(ship_objp, quadrant_num))
  quadrant_num = -1;
 
  // see if we hit the shield
- if (quadrant_num >= 0)
- {
+ if (quadrant_num >= 0) {
  // do the hit effect
- if (shield_collision)
- add_shield_point(OBJ_INDEX(ship_objp), mc_shield.shield_hit_tri, &mc_shield.hit_point);
- else {
- /* TODO */
-            }
-           
+ add_shield_point(OBJ_INDEX(ship_objp), mc_shield.shield_hit_tri, &mc_shield.hit_point);
+
  // if this weapon pierces the shield, then do the hit effect, but act like a shield collision never occurred;
  // otherwise, we have a valid hit on this shield
  if (wip->wi_flags2 & WIF2_PIERCE_SHIELDS)
@@ -339,6 +434,8 @@
  Assert( ship->type == OBJ_SHIP );
  Assert( weapon->type == OBJ_WEAPON );
 
+ ship_info *sip = &Ship_info[Ships[ship->instance].ship_info_index];
+
  // Don't check collisions for player if past first warpout stage.
  if ( Player->control_mode > PCM_WARPOUT_STAGE1) {
  if ( ship == Player_obj )
@@ -352,11 +449,13 @@
  // If it does hit, don't check the pair until about 200 ms before collision. 
  // If it does not hit and is within error tolerance, cull the pair.
 
- if ( (Ship_info[Ships[ship->instance].ship_info_index].flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) && (Weapon_info[Weapons[weapon->instance].weapon_info_index].subtype == WP_LASER) ) {
+ if ( (sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) && (Weapon_info[Weapons[weapon->instance].weapon_info_index].subtype == WP_LASER) ) {
  // Check when within ~1.1 radii. 
  // This allows good transition between sphere checking (leaving the laser about 200 ms from radius) and checking
  // within the sphere with little time between.  There may be some time for "small" big ships
- if ( vm_vec_dist_squared(&ship->pos, &weapon->pos) < (1.2f*ship->radius*ship->radius) ) {
+ // Note: culling ships with auto spread shields seems to waste more performance than it saves,
+ // so we're not doing that here
+ if ( !(sip->flags2 & SIF2_AUTO_SPREAD_SHIELDS) && vm_vec_dist_squared(&ship->pos, &weapon->pos) < (1.2f*ship->radius*ship->radius) ) {
  return check_inside_radius_for_big_ships( ship, weapon, pair );
  }
  }

P.S. Feel free to suggest a better name.

[attachment deleted by ninja]
« Last Edit: September 17, 2013, 07:35:17 am by zookeeper »

 

Offline General Battuta

  • Poe's Law In Action
  • 214
  • i wonder when my postcount will exceed my iq
holy **** aaa

  

Offline Nohiki

  • 28
  • Graf von Kaffeetrinken
    • Minecraft
    • Skype
    • Steam
At first I thought this just automatically pressed "Q" all the time, but now that I see it... It's infinitely better than surface shields :)
:::ALSO PROUD VASUDAN RIGHTS SUPPORTER:::

 
Ooh.  I don't suppose there's a way to do some auto-topology magic so that shield impacts could be projected?

(What does $Shield Color: in your example do if no effects happen?)

 

Offline MatthTheGeek

  • Captain Obvious
  • 212
  • Frenchie McFrenchface
Nothing more than it does on shieldless ships would be my guess. It was probably only put there to show between what and what and the new table arguments are supposed to be.
People are stupid, therefore anything popular is at best suspicious.

Mod management tools     -     Wiki stuff!     -     Help us help you

666maslo666: Releasing a finished product is not a good thing! It is a modern fad.

SpardaSon21: it seems like you exist in a permanent state of half-joking misanthropy

Axem: when you put it like that, i sound like an insane person

bigchunk1: it's not retarded it's american!
bigchunk1: ...

batwota: steele's maneuvering for the coup de gras
MatthTheGeek: you mispelled grâce
Awaesaar: grace
batwota: oh right :P
Darius: ah!
Darius: yes, i like that
MatthTheGeek: the way you just spelled it it means fat
Awaesaar: +accent I forgot how to keyboard
MatthTheGeek: or grease
Darius: the killing fat!
Axem: jabba does the coup de gras
MatthTheGeek: XD
Axem: bring me solo and a cookie

 

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
Ooh.  I don't suppose there's a way to do some auto-topology magic so that shield impacts could be projected?

Actually I don't think it would be terribly hard to do by just playing the impact animation on a flat quad, positioned on the point of impact and oriented along the hull. Simulating fancier geometry than that would be much harder.

(What does $Shield Color: in your example do if no effects happen?)

Nothing, I guess. It was just there in the table I copypasted the example from.

 
That would actually be awesome, and avoid issues with animation distortion. 

Come to think of it, don't the WCS builds have some sort of particle system for shield impacts?

 

Offline The E

  • He's Ebeneezer Goode
  • Moderator
  • 213
  • Nothing personal, just tech support.
    • Steam
    • Twitter
Even if they do, since there's no code available for WCS, it's useless to us.
If I'm just aching this can't go on
I came from chasing dreams to feel alone
There must be changes, miss to feel strong
I really need lifе to touch me
--Evergrey, Where August Mourns

 

Offline Spoon

  • 212
  • ヾ(´︶`♡)ノ
Even if they do, since there's no code available for WCS, it's useless to us.
I totally remember them saying that the code would be released eventually.
WCS team is too bitter.

Regardless, the shield impacts WCS has looks a fair bit better than the ancient poo poo effect we have in freespace still.
Urutorahappī!!

[02:42] <@Axem> spoon somethings wrong
[02:42] <@Axem> critically wrong
[02:42] <@Axem> im happy with these missions now
[02:44] <@Axem> well
[02:44] <@Axem> with 2 of them

 

Offline MatthTheGeek

  • Captain Obvious
  • 212
  • Frenchie McFrenchface
Yet ancient poo poo effect is better than no effect at all, at least in a FS setting. This patch, intended for FotG, works fine enough for them I suppose, since they don't need any shield impact effect, but it would be cool if someone could set up something to enable a broader use.
People are stupid, therefore anything popular is at best suspicious.

Mod management tools     -     Wiki stuff!     -     Help us help you

666maslo666: Releasing a finished product is not a good thing! It is a modern fad.

SpardaSon21: it seems like you exist in a permanent state of half-joking misanthropy

Axem: when you put it like that, i sound like an insane person

bigchunk1: it's not retarded it's american!
bigchunk1: ...

batwota: steele's maneuvering for the coup de gras
MatthTheGeek: you mispelled grâce
Awaesaar: grace
batwota: oh right :P
Darius: ah!
Darius: yes, i like that
MatthTheGeek: the way you just spelled it it means fat
Awaesaar: +accent I forgot how to keyboard
MatthTheGeek: or grease
Darius: the killing fat!
Axem: jabba does the coup de gras
MatthTheGeek: XD
Axem: bring me solo and a cookie

 

Offline karajorma

  • King Louie - Jungle VIP
  • Administrator
  • 214
    • Karajorma's Freespace FAQ
I totally remember them saying that the code would be released eventually.
WCS team is too bitter.

Actually, whatever is preventing them from releasing the code is whatever is preventing them from releasing the Mac OS X version. I have no idea what that is but they've basically said they're willing to release the code. It's a pity because it only hurts them really. If the code was out, someone would have ported the game already.
Karajorma's Freespace FAQ. It's almost like asking me yourself.

[ Diaspora ] - [ Seeds Of Rebellion ] - [ Mind Games ]

 

Offline jr2

  • The Mail Man
  • 212
  • It's prounounced jayartoo 0x6A7232
    • Steam
Re: Auto Spread Shields
Hmm, can this be modded to allow you to fly under a capship's shields and make attack runs?  Sort of like (IIRC) you could do with the Death Star?

 

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
Re: Auto Spread Shields
Hmm, can this be modded to allow you to fly under a capship's shields and make attack runs?  Sort of like (IIRC) you could do with the Death Star?

I don't see why not, but there's at least two different possibilities how that could work:

1) Any shot which impacts on the hull bypasses shields.

2) Any shot which has travelled less than the shield thickness when it hits the hull, bypasses shields.

I guess the latter would make more sense.

 

Offline redsniper

  • 211
  • Aim for the Top!
Re: Auto Spread Shields
What if you were below the shields, but you fired at a shallow angle, so the shot ends up traveling farther than the shield thickness?
"Think about nice things not unhappy things.
The future makes happy, if you make it yourself.
No war; think about happy things."   -WouterSmitssm

Hard Light Productions:
"...this conversation is pointlessly confrontational."

 

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
Re: Auto Spread Shields
What if you were below the shields, but you fired at a shallow angle, so the shot ends up traveling farther than the shield thickness?

Then it'd impact the shield as soon as the distance travelled exceeds that threshold.

 

Offline Dragon

  • Citation needed
  • 212
  • The sky is the limit.
Re: Auto Spread Shields
Well, that also means that if you're just below the shield, the shot would hit the shield anyway unless fired straight "down" at the ship's hull. I think that the angle should be taken into account as well.

 

Offline Trivial Psychic

  • 212
  • Snoop Junkie
Re: Auto Spread Shields
Might it be possible to add shield collision into the game engine?  This would prevent an enemy from flying within the shield perimeter.
The Trivial Psychic Strikes Again!

 

Offline Dragon

  • Citation needed
  • 212
  • The sky is the limit.
Re: Auto Spread Shields
That would be a nice feature, but sometimes (like with Star Wars ray shielding) you want strikecraft to pass. So it's not a solution to this particular problem.

 

Offline jr2

  • The Mail Man
  • 212
  • It's prounounced jayartoo 0x6A7232
    • Steam
Re: Auto Spread Shields
Set it as a flag in the mod.ini or whatnot?  OFC then certain people could cheat, but they can cheat anyways if they want.  So you could have shield collisions in certain universes, and not in others.  I'm not sure, though, Star Wars has ray shielding, but don't they have shields for mass, too?  Otherwise all you'd need to take them out would be a Mass Driver, unless they have some pretty nice armor, as well...

 

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
Committed!

In added in this additional optional feature:
2) Any shot which has travelled less than the shield thickness when it hits the hull, bypasses shields.

Taking angles into account would be too complicated so it works the simple way described a few posts ago.

So, an updated usage example:

Code: [Select]
$Shields:                     1000
  +Auto Spread:                 50
  +Allow Bypass:                YES ;defaults to NO
  +Spread From LOD:             2

You'll also need to add the "auto spread shields" ship type flag.
« Last Edit: September 17, 2013, 07:44:45 am by zookeeper »