Author Topic: fighter beams-code  (Read 7150 times)

0 Members and 1 Guest are viewing this topic.

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
I guess I never put up any code snipets :o

the big change, I bypassed the targeting beam functions by filling out the firing info and firing the beams on a ship by ship basis
I beleve I made coments on all my changes
ship.cpp
Code: [Select]

int ship_fire_primary(object * obj, int stream_weapons, int force)
{
vector gun_point, pnt, firing_pos;
int n = obj->instance;
ship *shipp;
ship_weapon *swp;
ship_info *sip;
ai_info *aip;
int weapon, i, j, weapon_objnum;
int bank_to_fire, num_fired = 0;
int banks_fired, have_timeout; // used for multiplayer to help determine whether or not to send packet
have_timeout = 0; // used to help tell us whether or not we need to send a packet
banks_fired = 0; // used in multiplayer -- bitfield of banks that were fired

int sound_played; // used to track what sound is played.  If the player is firing two banks
// of the same laser, we only want to play one sound
Assert( obj != NULL );

if(obj == NULL){
return 0;
}

// in the case where the server is an observer, he can fire (which) would be bad - unless we do this.
if( obj->type == OBJ_OBSERVER){
return 0;
}

Assert( obj->type == OBJ_SHIP );
Assert( n >= 0 );
Assert( Ships[n].objnum == OBJ_INDEX(obj));
if((obj->type != OBJ_SHIP) || (n < 0) || (n >= MAX_SHIPS) || (Ships[n].objnum != OBJ_INDEX(obj))){
return 0;
}

shipp = &Ships[n];
swp = &shipp->weapons;

//if (shipp->targeting_laser_objnum != -1)
//shipp->targeting_laser_objnum = -1; // erase old laser obj num if it has any -Bobboau

// bogus
if((shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
return 0;
}
if((shipp->ai_index < 0) || (shipp->ai_index >= MAX_AI_INFO)){
return 0;
}
sip = &Ship_info[shipp->ship_info_index];
aip = &Ai_info[shipp->ai_index];

if ( swp->num_primary_banks <= 0 ) {
return 0;
}

if ( swp->current_primary_bank < 0 ){
return 0;
}

sound_played = -1;

// Fire the correct primary bank.  If primaries are linked (SF_PRIMARY_LINKED set), then fire
// both primary banks.
int num_primary_banks;

if ( shipp->flags & SF_PRIMARY_LINKED ) {
num_primary_banks = swp->num_primary_banks;
} else {
num_primary_banks = min(1, swp->num_primary_banks);
}

Assert(num_primary_banks > 0);
if (num_primary_banks < 1){
return 0;
}

// if we're firing stream weapons, but the trigger is not down, do nothing
if(stream_weapons && !(shipp->flags & SF_TRIGGER_DOWN)){
return 0;
}

for ( i = 0; i < num_primary_banks; i++ ) {
bank_to_fire = (swp->current_primary_bank+i)%2; // Max supported banks is 2

weapon = swp->primary_bank_weapons[bank_to_fire];
Assert( weapon >= 0 && weapon < MAX_WEAPONS );
if ( (weapon < 0) || (weapon >= MAX_WEAPON_TYPES) ) {
Int3(); // why would a ship try to fire a weapon that doesn't exist?
continue;
}
weapon_info* winfo_p = &Weapon_info[weapon];

// if this is a targeting laser, start it up   ///- only targeting laser if it is tag-c, otherwise it's a fighter beam -Bobboau
if((winfo_p->wi_flags & WIF_BEAM) && (winfo_p->tag_level == 3) && (shipp->flags & SF_TRIGGER_DOWN) && (winfo_p->b_info.beam_type == BEAM_TYPE_C) ){
ship_start_targeting_laser(shipp);
}

// if we're firing stream weapons and this is a non stream weapon, skip it
if(stream_weapons && !(winfo_p->wi_flags & WIF_STREAM)){
continue;
}
// if we're firing non stream weapons and this is a stream weapon, skip it
if(!stream_weapons && (winfo_p->wi_flags & WIF_STREAM)){
continue;
}

// only non-multiplayer clients (single, multi-host) need to do timestamp checking
if ( !timestamp_elapsed(swp->next_primary_fire_stamp[bank_to_fire]) ) {
if (timestamp_until(swp->next_primary_fire_stamp[bank_to_fire]) > 5000){
swp->next_primary_fire_stamp[bank_to_fire] = timestamp(1000);
}

have_timeout = 1;
continue;
}

//nprintf(("AI", "Time = %7.3f, firing %s\n", f2fl(Missiontime), Weapon_info[weapon].name));

// do timestamp stuff for next firing time
float next_fire_delay = (float) winfo_p->fire_wait * 1000.0f;
if (!(obj->flags & OF_PLAYER_SHIP) ) {
if (shipp->team == Ships[Player_obj->instance].team){
next_fire_delay *= Ship_fire_delay_scale_friendly[Game_skill_level];
} else {
next_fire_delay *= Ship_fire_delay_scale_hostile[Game_skill_level];
}
}

next_fire_delay *= 1.0f + (num_primary_banks - 1) * 0.5f; // 50% time penalty if banks linked

// MK, 2/4/98: Since you probably were allowed to fire earlier, but couldn't fire until your frame interval
// rolled around, subtract out up to half the previous frametime.
// Note, unless we track whether the fire button has been held down, and not tapped, it's hard to
// know how much time to subtract off.  It could be this fire is "late" because the user didn't want to fire.
if ((next_fire_delay > 0.0f)) {
if (obj->flags & OF_PLAYER_SHIP) {
int t = timestamp_until(swp->next_primary_fire_stamp[bank_to_fire]);
if (t < 0) {
float tx;

tx = (float) t/-1000.0f;
if (tx > flFrametime/2.0f){
tx = 1000.0f * flFrametime * 0.7f;
}
next_fire_delay -= tx;
}

if ((int) next_fire_delay < 1){
next_fire_delay = 1.0f;
}
}

swp->next_primary_fire_stamp[bank_to_fire] = timestamp((int)(next_fire_delay));
if ((winfo_p->wi_flags & WIF_BEAM) && (winfo_p->b_info.beam_type == BEAM_TYPE_C))// fighter beams fire constantly, they only stop if they run out of power -Bobboau
swp->next_primary_fire_stamp[bank_to_fire] = timestamp();
}

// Here is where we check if weapons subsystem is capable of firing the weapon.
// Note that we can have partial bank firing, if the weapons subsystem is partially
// functional, which should be cool.  
if ( ship_weapon_maybe_fail(shipp) && !force) {
if ( obj == Player_obj ) {
if ( ship_maybe_play_primary_fail_sound() ) {
}
}
continue;
}

polymodel *po = model_get( Ship_info[shipp->ship_info_index].modelnum );

if ( po->n_guns > 0 ) {
int num_slots = po->gun_banks[bank_to_fire].num_slots;




if(winfo_p->wi_flags & WIF_BEAM){ // the big change I made for fighter beams, if there beams fill out the Fire_Info for a targeting laser then fire it, for each point in the weapon bank -Bobboau

// fail unless we're forcing (energy based primaries)
if ( (shipp->weapon_energy < num_slots*winfo_p->energy_consumed*flFrametime) && !force) {
swp->next_primary_fire_stamp[bank_to_fire] = timestamp(swp->next_primary_fire_stamp[bank_to_fire]);
if ( obj == Player_obj ) {
if ( ship_maybe_play_primary_fail_sound() ) {
}
}
continue;
}


// deplete the weapon reserve energy by the amount of energy used to fire the weapon and the number of points and do it by the time it's been fireing becase this is a beam -Bobboau
shipp->weapon_energy -= num_slots*winfo_p->energy_consumed*flFrametime;

beam_fire_info fbfire_info;
//int j = (timestamp()/100)%num_slots; // fireing point cycleing for TBP
for ( int j = 0; j < num_slots; j++ ){
fbfire_info.accuracy = 0.0f;
fbfire_info.beam_info_index = shipp->weapons.primary_bank_weapons[bank_to_fire];
fbfire_info.beam_info_override = NULL;
fbfire_info.shooter = &Objects[shipp->objnum];
fbfire_info.target = NULL;
fbfire_info.target_subsys = NULL;
fbfire_info.turret = NULL;
fbfire_info.targeting_laser_offset = po->gun_banks[bank_to_fire].pnt[j];

beam_fire_targeting(&fbfire_info);
//shipp->targeting_laser_objnum = beam_fire_targeting(&fire_info);
}
}else{ //if this insn't a fighter beam, do it normaly -Bobboau
//Assert (!(winfo_p->wi_flags & WIF_BEAM))
// fail unless we're forcing (energy based primaries)
if ( (shipp->weapon_energy < num_slots*winfo_p->energy_consumed) && !force) {
swp->next_primary_fire_stamp[bank_to_fire] = timestamp(swp->next_primary_fire_stamp[bank_to_fire]);
if ( obj == Player_obj ) {
if ( ship_maybe_play_primary_fail_sound() ) {
}
}
continue;
}


// deplete the weapon reserve energy by the amount of energy used to fire the weapon
shipp->weapon_energy -= num_slots*winfo_p->energy_consumed;

// Mark all these weapons as in the same group
int new_group_id = weapon_create_group_id();

for ( j = 0; j < num_slots; j++ ) {
pnt = po->gun_banks[bank_to_fire].pnt[j];
vm_vec_unrotate(&gun_point, &pnt, &obj->orient);
vm_vec_add(&firing_pos, &gun_point, &obj->pos);

// create the weapon -- the network signature for multiplayer is created inside
// of weapon_create
weapon_objnum = weapon_create( &firing_pos, &obj->orient, weapon, OBJ_INDEX(obj),0, new_group_id );
weapon_set_tracking_info(weapon_objnum, OBJ_INDEX(obj), aip->target_objnum, aip->current_target_is_locked, aip->targeted_subsys);

// create the muzzle flash effect
shipfx_flash_create( obj, shipp, &pnt, &obj->orient.fvec, 1, weapon );

// maybe shudder the ship - if its me
if((winfo_p->wi_flags & WIF_SHUDDER) && (obj == Player_obj) && !(Game_mode & GM_STANDALONE_SERVER)){
// calculate some arbitrary value between 100
// (mass * velocity) / 10
game_shudder_apply(500, (winfo_p->mass * winfo_p->max_speed) / 10.0f);
}

num_fired++;
}
}

if(shipp->weapon_energy < 0.0f){
shipp->weapon_energy = 0.0f;
}


banks_fired |= (1< // mark this bank as fired.
}

// Only play the weapon fired sound if it hasn't been played yet.  This is to
// avoid playing the same sound multiple times when banks are linked with the
// same weapon.
if ( sound_played != winfo_p->launch_snd ) {
sound_played = winfo_p->launch_snd;
if ( obj == Player_obj ) {
if ( winfo_p->launch_snd != -1 ) {
weapon_info *wip;
ship_weapon *swp;

// HACK
if(winfo_p->launch_snd == SND_AUTOCANNON_SHOT){
snd_play( &Snds[winfo_p->launch_snd], 0.0f, 1.0f, SND_PRIORITY_TRIPLE_INSTANCE );
} else {
snd_play( &Snds[winfo_p->launch_snd], 0.0f, 1.0f, SND_PRIORITY_MUST_PLAY );
}
// snd_play( &Snds[winfo_p->launch_snd] );

swp = &Player_ship->weapons;
if (swp->current_primary_bank >= 0) {
wip = &Weapon_info[swp->primary_bank_weapons[swp->current_primary_bank]];
joy_ff_play_primary_shoot((int) ((wip->armor_factor + wip->shield_factor * 0.2f) * (wip->damage * wip->damage - 7.5f) * 0.45f + 0.6f) * 10 + 2000);
}
}
}
else {
if ( winfo_p->launch_snd != -1 ) {
snd_play_3d( &Snds[winfo_p->launch_snd], &obj->pos, &View_position );
}
}
}
} // end for (go to next primary bank)

// if multiplayer and we're client-side firing, send the packet
// if((Game_mode & GM_MULTIPLAYER) && (Netgame.debug_flags & NETD_FLAG_CLIENT_FIRING)){
if(Game_mode & GM_MULTIPLAYER){
// if i'm a client, and this is not me, don't send
if(!(MULTIPLAYER_CLIENT && (shipp != Player_ship))){
send_NEW_primary_fired_packet( shipp, banks_fired );
}
}

// post a primary fired event
if(Game_mode & GM_DEMO_RECORD){
demo_POST_primary_fired(obj, swp->current_primary_bank, shipp->flags & SF_PRIMARY_LINKED);
}

   // STATS
   if (obj->flags & OF_PLAYER_SHIP) {
// in multiplayer -- only the server needs to keep track of the stats.  Call the cool
// function to find the player given the object *.  It had better return a valid player
// or our internal structure as messed up.
if( Game_mode & GM_MULTIPLAYER ) {
if ( Net_player->flags & NETINFO_FLAG_AM_MASTER ) {
int player_num;

player_num = multi_find_player_by_object ( obj );
Assert ( player_num != -1 );

Net_players[player_num].player->stats.mp_shots_fired += num_fired;
}
} else {
Player->stats.mp_shots_fired += num_fired;
}
}

return num_fired;
}



I made this change to
void beam_handle_collisions(beam *b)
beam.cpp
Code: [Select]

case OBJ_SHIP:
// hit the ship - again, the innards of this code handle multiplayer cases
// maybe vaporize ship.
ship_apply_local_damage(&Objects[target], &Objects[b->objnum], &b->f_collisions[idx].cinfo.hit_point_world, beam_get_ship_damage(b, &Objects[target]), b->f_collisions[idx].quadrant);

// if this is the first hit on the player ship. whack him
if((do_damage) && !(b->f_collisions[idx].quadrant)){ //I didn't want the beam wacking things if it's hitting just sheilds -Bobboau
beam_apply_whack(b, &Objects[target], &b->f_collisions[idx].cinfo.hit_point_world);
}
break;
}




and I added a bit to this
beam.cpp
Code: [Select]

void beam_add_collision(beam *b, object *hit_object, mc_info *cinfo)
{
beam_collision *bc;
int idx;
int quadrant_num = -1;


// if we haven't reached the limit for beam collisions, just add
if(b->f_collision_count < MAX_FRAME_COLLISIONS){
bc = &b->f_collisions[b->f_collision_count++];
bc->c_objnum = OBJ_INDEX(hit_object);
bc->cinfo = *cinfo;

if( (cinfo->flags & MC_CHECK_SHIELD) && cinfo->num_hits ){ //beam sheild hit code -Bobboau
quadrant_num = get_quadrant(&cinfo->hit_point);
// if (!(hit_object->flags & SF_DYING) && ship_is_shield_up(hit_object,quadrant_num) ) {
HUD_printf("you should see sheild hits");
add_shield_point(hit_object->instance, cinfo->shield_hit_tri, &cinfo->hit_point);
bc->quadrant=quadrant_num;
// hud_shield_quadrant_hit(hit_object, quadrant_num);
// gr_printf(10, 50, "shield hit %f", quadrant_num);
// }
}


// done
return;
}

// otherwise, we've got to do some checking, ick.
// I guess we can always just remove the farthest item
bc = NULL;
for(idx=0; idx if((bc == NULL) || (b->f_collisions[idx].cinfo.hit_dist > bc->cinfo.hit_dist)){
bc = &b->f_collisions[idx];
}
}

// copy in
Assert(bc != NULL);
if(bc == NULL){
return;
}
bc->c_objnum = OBJ_INDEX(hit_object);
bc->cinfo = *cinfo;



}




changes made to
int beam_collide_ship(obj_pair *pair)
if you can't figure what I changed I'll post the whole function
beam.cpp
Code: [Select]

bwi = &Weapon_info[b->weapon_info_index];

// maybe do a sphere line
if(widest > pair->b->radius * BEAM_AREA_PERCENT){
test_collide.radius = beam_get_widest(b) * 0.5f;
if ( get_shield_strength(&Objects[shipp->objnum]) && (bwi->b_info.beam_type == BEAM_TYPE_C) ){ //check shields for type c beams -Bobboau
//HUD_printf("BC shpere sheild");
test_collide.flags = MC_CHECK_SHIELD | MC_CHECK_SPHERELINE;
}else{
//HUD_printf("BC shpere hull");
test_collide.flags = MC_CHECK_MODEL | MC_CHECK_SPHERELINE;
}
} else {
if ( get_shield_strength(&Objects[shipp->objnum]) && (bwi->b_info.beam_type == BEAM_TYPE_C) ){ //check shields for type c beams -Bobboau
//HUD_printf("BC ray sheild");
test_collide.flags = MC_CHECK_SHIELD | MC_CHECK_RAY;
}else{
//HUD_printf("BC ray hull");
test_collide.flags = MC_CHECK_MODEL | MC_CHECK_RAY;
}
}




and don't forget this in beam.h

Code: [Select]

// collision info
typedef struct beam_collision {
mc_info cinfo; // collision info
int c_objnum; // objnum of the guy we recently collided with
int c_sig; // object sig
int c_stamp; // when we should next apply damage
int quadrant; // sheild quadrant this beam hits if any -Bobboau
} beam_collision;



I may have found the weak point in fighter beam hit recording (it returns the parent properly, ecsept for player ship)
beam.cpp
Code: [Select]

int beam_get_parent(object *bm)
{
beam *b;

// get a handle to the beam
Assert(bm->type == OBJ_BEAM);
Assert(bm->instance >= 0);
if(bm->type != OBJ_BEAM){
return -1;
}
if(bm->instance < 0){
return -1;
}
b = &Beams[bm->instance];

Assert(b->objp != NULL);
if(b->objp == NULL){
return -1;
}

// if the object handle is invalid
/* if(b->objp->signature != b->sig){
return -1;
}
*/ //comented out to see if this is the weak link in the fighter beam hit recording -Bobboau
// return the handle
return OBJ_INDEX(b->objp);
}


I comented out one line in create_shield_explosion_all in sheild.cpp
   //   Assert(count == 0);   //   Couldn't find all the alleged shield hits.  Bogus! //cometed out becase fighterbeams were tripping this -Bobboau


I think thats all the changes
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline Inquisitor

Figured I would split it, that beam thread was hard as hell to keep track of :)

WMCoolmon has been adding "made by Bobbau" changes to our CVS, think maybe he can do that to this one?

:)

Thanks for posting, I was beginning to think we'd never get the code :)

-edit-
typos suck
« Last Edit: July 21, 2002, 06:30:35 pm by 122 »
No signature.

 

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
"mad by Bobbau"
angery not mad, angery!!! :mad:
:D
that was a joke
laugh now!

hmmm, sticky,
that feels good ;7

well now that I have sucsefully derailed my own topic
I'm gona try and get beam sounds to loop properly
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline WMCoolmon

  • Purveyor of space crack
  • 213
Quote
Originally posted by Inquisitor
WMCoolmon has been adding "made by Bobbau" changes to our CVS, think maybe he can do that to this one?

Sure...just as soon as I get ahold of a good syntax highlighter for Linux, or reboot back into Windows 2000 :D
-C

 

Offline LAM3O

  • 25
Whoohoo, update the tbp FAQ

 

Offline penguin

  • Eudyptes codus
  • 28
  • Still alive.
Quote
Originally posted by WMCoolmon

Sure...just as soon as I get ahold of a good syntax highlighter for Linux, or reboot back into Windows 2000 :D
emacs

M-x c++-mode
M-x font-lock-mode

Gotta do it in X, though; it doesn't do syntax highlighting in terminal mode.
your source code slave

 

Offline Inquisitor

Unix geek ;)
No signature.

 

Offline WMCoolmon

  • Purveyor of space crack
  • 213
Gnu's not Unix :p

Besides, I have yet to recompile my kernel :nervous:
-C

 

Offline Kazan

  • PCS2 Wizard
  • 212
  • Soul lives in the Mountains
    • http://alliance.sourceforge.net
newest version of vim enhanced
PCS2 2.0.3 | POF CS2 wiki page | Important PCS2 Threads | PCS2 Mantis

"The Mountains are calling, and I must go" - John Muir

 

Offline WMCoolmon

  • Purveyor of space crack
  • 213
Adding...Bobboau, in beam.cpp, you have
Code: [Select]
bwi = &Weapon_info[b->weapon_info_index];
Which will not work; it doesn't get initialized. On the other hand, if I change that to
Code: [Select]
weapon_info * bwi = &Weapon_info[b->weapon_info_index];
Do you have
Code: [Select]
weapon_info * bwi;
anywhere in your code, or is there something I'm missing?

Update: Finished adding code to the CVS repository
« Last Edit: July 24, 2002, 11:38:35 pm by 374 »
-C

 

Offline Bobboau

  • Just a MODern kinda guy
    Just MODerately cool
    And MODest too
  • 213
if that was in int beam_collide_ship(obj_pair *pair) yes I forgot to mention the declaration
Bobboau, bringing you products that work... in theory
learn to use PCS
creator of the ProXimus Procedural Texture and Effect Generator
My latest build of PCS2, get it while it's hot!
PCS 2.0.3


DEUTERONOMY 22:11
Thou shalt not wear a garment of diverse sorts, [as] of woollen and linen together

 

Offline Inquisitor

Added to CVS, unsticking :)
No signature.