1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
|
/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#include "debugconsole/console.h"
#include "freespace2/freespace.h" // for Missiontime
#include "io/timer.h"
#include "object/object.h"
#include "ship/ship.h"
#include "weapon/corkscrew.h"
#include "weapon/weapon.h"
// corkscrew structure flags
#define CS_FLAG_USED (1<<0) // this structure is in use
#define CS_FLAG_COUNTER (1<<1) // counterrotate this guy
// corkscrew settings
int Corkscrew_missile_delay = 30; // delay between missile firings
int Corkscrew_num_missiles_fired = 4; // # of missiles fire in one shot
float Corkscrew_radius = 1.25f; // radius of the corkscrew itself
float Corkscrew_twist = 5.0f; // in degrees/second
int Corkscrew_helix = 1; // attempt to point the missile in the right direction
int Corkscrew_counterrotate = 1; // counterrotate every other missile
int Corkscrew_shrink = 0; // shrink the radius of every successive missile
float Corkscrew_shrink_val = 0.3f; // rate at which the radius shrinks
int Corkscrew_down_first = 1; // have the corkscrew go "down" first
// current counterrotation and radius shrink values
float Corkscrew_radius_cur = Corkscrew_radius;
typedef struct cscrew_info {
int flags; // flags for the missile
// info about the corkscrew effect for this missile
vec3d cen_p; // vector pointing to the "center" of the corkscrew
float radius; // radius of the corkscrew
matrix real_orient; // the orientation used when calling physics (bashed before rendering)
vec3d last_corkscrew_pos; // last position along the corkscrew
} cscrew_info;
#define MAX_CORKSCREW_MISSILES 200
cscrew_info Corkscrew_missiles[MAX_CORKSCREW_MISSILES];
// ------------------------------------------------------------------
// cscrew_level_init()
//
// Called at the start of each new mission
//
void cscrew_level_init()
{
memset(Corkscrew_missiles, 0, sizeof(cscrew_info) * MAX_CORKSCREW_MISSILES);
}
// ------------------------------------------------------------------
// cscrew_maybe_fire_missile()
//
// Check if there are any swarm missiles to fire, and if enough time
// has elapsed since last one fired, go ahead and fire it.
//
// This is called once per ship frame in ship_move()
//
void cscrew_maybe_fire_missile(int shipnum)
{
ship *sp;
ship_weapon *swp;
int weapon_info_index;
Assert(shipnum >= 0 && shipnum < MAX_SHIPS );
sp = &Ships[shipnum];
// make sure we're supposed to be firing some missiles
if ( sp->num_corkscrew_to_fire <= 0 ){
sp->corkscrew_missile_bank = -1;
return;
}
// make sure we have a valid weapon bank
swp = &sp->weapons;
if ( sp->corkscrew_missile_bank == -1 ) {
sp->num_corkscrew_to_fire = 0;
return;
}
weapon_info_index = swp->secondary_bank_weapons[sp->corkscrew_missile_bank];
Assert( weapon_info_index >= 0 && weapon_info_index < MAX_WEAPON_TYPES );
// if current secondary bank is not a corkscrew missile, return
if ( !(Weapon_info[weapon_info_index].wi_flags & WIF_CORKSCREW) ) {
sp->num_corkscrew_to_fire = 0;
sp->corkscrew_missile_bank = -1;
return;
}
if ( timestamp_elapsed(sp->next_corkscrew_fire) ) {
sp->next_corkscrew_fire = timestamp(Weapon_info[weapon_info_index].cs_delay);
ship_fire_secondary( &Objects[sp->objnum], 1 );
sp->num_corkscrew_to_fire--;
}
}
// ------------------------------------------------------------------
// cscrew_create()
//
// Get a free corkscrew missile entry, and initialize the struct members
//
int cscrew_create(object *obj)
{
int i;
cscrew_info *cscrewp = NULL;
weapon_info *wip;
wip = &Weapon_info[Weapons[obj->instance].weapon_info_index];
for ( i = 0; i < MAX_CORKSCREW_MISSILES; i++ ) {
cscrewp = &Corkscrew_missiles[i];
if ( !(cscrewp->flags & CS_FLAG_USED) ) {
break;
}
}
if ( i >= MAX_CORKSCREW_MISSILES ) {
nprintf(("Warning","No more corkscrew missiles are available\n"));
return -1;
}
// mark the guy as "used"
cscrewp->flags = CS_FLAG_USED;
// determine if he is counterrotating
if(wip->cs_crotate){
if(frand_range(0.0f, 1.0f) < 0.5f){
cscrewp->flags |= CS_FLAG_COUNTER;
}
}
// get the "center" pointing vector
vec3d neg;
neg = obj->orient.vec.uvec;
if(Corkscrew_down_first){
vm_vec_negate(&neg);
}
vm_vec_scale_add2(&cscrewp->cen_p, &neg, wip->cs_radius);
// move the missile up so that the corkscrew point is at the muzzle of the gun
// vm_vec_scale_add2(&obj->pos, &obj->orient.vec.uvec, Corkscrew_radius);
// store some initial helix params
cscrewp->real_orient = obj->orient;
cscrewp->last_corkscrew_pos = obj->pos;
return i;
}
// ------------------------------------------------------------------
// cscrew_delete()
//
//
void cscrew_delete(int i)
{
if ( !(Corkscrew_missiles[i].flags & CS_FLAG_USED) ) {
Int3();
}
memset(&Corkscrew_missiles[i], 0, sizeof(cscrew_info));
}
// pre process the corkscrew weapon by putting him in the "center" of his corkscrew
void cscrew_process_pre(object *objp)
{
cscrew_info *ci;
// check stuff
Assert(objp->type == OBJ_WEAPON);
Assert(Weapons[objp->instance].cscrew_index >= 0);
Assert(Corkscrew_missiles[Weapons[objp->instance].cscrew_index].flags & CS_FLAG_USED);
ci = &Corkscrew_missiles[Weapons[objp->instance].cscrew_index];
// unrotate the missile itself
if(Corkscrew_helix){
// restore the "real" matrix now
objp->orient = ci->real_orient;
}
// move the missile back to the center of the corkscrew
vm_vec_add2(&objp->pos, &ci->cen_p);
}
// post process the corkscrew weapon by putting him back to the right spot on his corkscrew
void cscrew_process_post(object *objp)
{
vec3d cen, neg;
vec3d new_pt;
weapon *wp;
weapon_info *wip;
cscrew_info *ci;
float twist_val;
// check stuff
Assert(objp->type == OBJ_WEAPON);
Assert(Weapons[objp->instance].cscrew_index >= 0);
Assert(Corkscrew_missiles[Weapons[objp->instance].cscrew_index].flags & CS_FLAG_USED);
// get various useful pointers
wp = &Weapons[objp->instance];
wip = &Weapon_info[wp->weapon_info_index];
ci = &Corkscrew_missiles[wp->cscrew_index];
// move to the outside of the corkscrew
neg = ci->cen_p;
cen = objp->pos;
vm_vec_negate(&neg);
vm_vec_add2(&objp->pos, &neg);
// determine what direction (clockwise or counterclockwise) the missile will spin
twist_val = ci->flags & CS_FLAG_COUNTER ? -wip->cs_twist : wip->cs_twist;
twist_val *= flFrametime;
// rotate the missile position
vm_rot_point_around_line(&new_pt, &objp->pos, twist_val, &cen, &objp->orient.vec.fvec);
objp->pos = new_pt;
// rotate the missile itself
if(Corkscrew_helix){
vec3d dir;
// compute a "fake" orient and store the old one for safekeeping
ci->real_orient = objp->orient;
vm_vec_sub(&dir, &objp->pos, &ci->last_corkscrew_pos);
vm_vec_normalize(&dir);
vm_vector_2_matrix(&objp->orient, &dir, NULL, NULL);
// mark down this position so we can orient nicely _next_ frame
ci->last_corkscrew_pos = objp->pos;
}
// get the new center pointing vector
vm_vec_sub(&ci->cen_p, &cen, &objp->pos);
// do trail stuff here
if ( wp->trail_ptr != NULL ) {
if (trail_stamp_elapsed(wp->trail_ptr)) {
trail_add_segment( wp->trail_ptr, &objp->pos );
trail_set_stamp(wp->trail_ptr);
} else {
trail_set_segment( wp->trail_ptr, &objp->pos );
}
}
}
// debug console functionality
void cscrew_display_dcf()
{
dc_printf("Corkscrew settings\n\n");
dc_printf("Delay (cscrew_delay) : %d\n",Corkscrew_missile_delay);
dc_printf("Count (cscrew_count) : %d\n",Corkscrew_num_missiles_fired);
dc_printf("Radius (cscrew_radius) : %f\n",Corkscrew_radius);
dc_printf("Twist (cscrew_twist) : %f\n",Corkscrew_twist);
if(Corkscrew_helix){
dc_printf("Helix (cscrew_helix): ON\n");
} else {
dc_printf("Helix (cscrew_helix): OFF\n");
}
if(Corkscrew_counterrotate){
dc_printf("Counterrotate (cscrew_counter): ON\n");
} else {
dc_printf("Counterrotate (cscrew_counter): OFF\n");
}
if(Corkscrew_shrink){
dc_printf("Shrink (cscrew_shrink): ON\n");
} else {
dc_printf("Shrink (cscrew_shrink): OFF\n");
}
dc_printf("Corkscrew shrink (cscrew_shrinkval): %f\n", Corkscrew_shrink_val);
if(Corkscrew_down_first){
dc_printf("Corkscrew down first : ON\n");
} else {
dc_printf("Corkscrew down first : OFF\n");
}
}
DCF(cscrew, "Listing of corkscrew missile debug console functions")
{
cscrew_display_dcf();
}
DCF(cscrew_delay, "Change the delay between corkscrew firing")
{
dc_stuff_int(&Corkscrew_missile_delay);
cscrew_display_dcf();
}
DCF(cscrew_count, "Change the # of corkscrew missiles fired")
{
dc_stuff_int(&Corkscrew_num_missiles_fired);
cscrew_display_dcf();
}
DCF(cscrew_radius, "Change the radius of corkscrew missiles")
{
dc_stuff_float(&Corkscrew_radius);
cscrew_display_dcf();
}
DCF(cscrew_twist, "Change the rate of the corkscrew twist")
{
dc_stuff_float(&Corkscrew_twist);
cscrew_display_dcf();
}
DCF(cscrew_helix, "Attempt to orient missile nicely along the corkscrew")
{
Corkscrew_helix = !Corkscrew_helix;
cscrew_display_dcf();
}
DCF(cscrew_counter, "Counterrotate every other missile")
{
Corkscrew_counterrotate = !Corkscrew_counterrotate;
cscrew_display_dcf();
}
DCF(cscrew_shrink, "Shrink the radius of every other missile")
{
Corkscrew_shrink = !Corkscrew_shrink;
cscrew_display_dcf();
}
DCF(cscrew_shrinkval, "Change the rate at which the radii shrink")
{
dc_stuff_float(&Corkscrew_shrink_val);
cscrew_display_dcf();
}
DCF(cscrew_down, "Cause the missile to spiral down first")
{
Corkscrew_down_first = !Corkscrew_down_first;
cscrew_display_dcf();
}
|