Ejemplo n.º 1
0
// add some jitter to a flak gun's aiming direction, take into account range to target so that we're never _too_ far off
// assumes dir is normalized
void flak_jitter_aim(vec3d* dir, float dist_to_target, float weapon_subsys_strength)
{
	vec3d rand_twist_pre, rand_twist_post;
	matrix temp;
	vec3d final_aim;
	float error_val;

	// get the matrix needed to rotate the base direction to the actual direction		
	vm_vector_2_matrix(&temp, dir, NULL, NULL);

	// error value	
	error_val = Flak_error + (Flak_error * 0.65f * (1.0f - weapon_subsys_strength));

	// scale the rvec by some random value and make it the "pre-twist" value
	float rand_dist = frand_range(0.0f, error_val);
	// no jitter - so do nothing
	if (rand_dist <= 0.0f)
	{
		return;
	}
	vm_vec_copy_scale(&rand_twist_pre, &temp.vec.rvec, rand_dist);

	// now rotate the twist vector around the x axis (the base aim axis) at a random angle
	vm_rot_point_around_line(&rand_twist_post, &rand_twist_pre, fl_radian(359.0f * frand_range(0.0f,
		1.0f)), &vmd_zero_vector, dir);

	// add the resulting vector to the base aim vector and normalize
	final_aim = *dir;
	vm_vec_scale(&final_aim, dist_to_target);
	vm_vec_add(dir, &final_aim, &rand_twist_post);
	vm_vec_normalize(dir);
}
Ejemplo n.º 2
0
// throw some jitter into HUD x and y coords
void emp_hud_jitter(int *x, int *y)
{
	// if the emp effect is not active, don't jitter anything
	if(!emp_active_local()){
		return;
	}

	// some movement
	*x += (int)frand_range(-8.0f * Emp_intensity, 8.0f * Emp_intensity);
	*y += (int)frand_range(-8.0f * Emp_intensity, 8.0f * Emp_intensity);
}
Ejemplo n.º 3
0
// randomize the chars in a string
void emp_randomize_chars(char *str)
{	
	int idx;
	int char_index;
	
	// shuffle chars around
	for(idx=0; idx<(int)(strlen(str)-1); idx++){
		if(frand_range(0.0f, 1.0f) < Emp_intensity){
			char_index = (int)frand_range(0.0f, (float)(NUM_RANDOM_CHARS - 1));
			str[idx] = Emp_random_char[char_index];
		}
	}
}
bool BeamPiercingEffect::processSource(const ParticleSource* source) {
	particle_info info;
	memset(&info, 0, sizeof(info));

	source->getOrigin()->applyToParticleInfo(info);

	if (m_effectBitmap >= 0) {
		info.type = PARTICLE_BITMAP_PERSISTENT;
		info.optional_data = m_effectBitmap;
	}
	else {
		info.type = PARTICLE_SMOKE;
	}

	info.rad = m_radius * frand_range(0.5f, 2.0f);

	vec3d fvec = source->getOrientation()->getDirectionVector();

	float base_v, back_v;
	vec3d rnd_vec;

	vm_vec_rand_vec_quick(&rnd_vec);

	if (m_velocity != 0.0f) {
		base_v = m_velocity;
	} else {
		base_v = m_radius;
	}

	if (m_backVelocity != 0.0f) {
		back_v = m_backVelocity;
	} else {
		back_v = base_v * (-0.2f);
	}

	vm_vec_copy_scale(&info.vel, &fvec, base_v * frand_range(1.0f, 2.0f));
	vm_vec_scale_add2(&info.vel, &rnd_vec, base_v * m_variance);

	// Create the primary piercing particle
	create(&info);

	vm_vec_copy_scale(&info.vel, &fvec, back_v * frand_range(1.0f, 2.0f));
	vm_vec_scale_add2(&info.vel, &rnd_vec, back_v * m_variance);

	// Create the splash particle
	create(&info);

	return false;
}
Ejemplo n.º 5
0
void fishtank_start()
{
	int idx;

	if(Fish_inited){
		return;
	}

	// try and load the fish anim
	Fish_left_anim = anim_load(FISH_LEFT_ANIM_NAME);
	if(Fish_left_anim == NULL){
		return;
	}
	Fish_right_anim = anim_load(FISH_RIGHT_ANIM_NAME);
	if(Fish_right_anim == NULL){
		return;
	}

	// no anim instances
	for(idx=0; idx<MAX_FISH; idx++){
		Fish[idx].a = NULL;
		Fish[idx].swimming = 0;
	}	

	Fish_inited = 1;

	// generate a random # of fish
	int count = (int)frand_range(1.0f, (float)(MAX_FISH - 1));
	for(idx=0; idx<count; idx++){
		fish_generate();
	}		
}
Ejemplo n.º 6
0
// randomly say yes or no to a gauge, if emp is not active, always say yes
int emp_should_blit_gauge()
{
	// if the EMP effect is not active, always blit
	if(!emp_active_local()){
		return 1;
	}

	// otherwise, randomly say no
	return frand_range(0.0f, 1.0f) > Emp_intensity;
}
Ejemplo n.º 7
0
// radar is damaged, so make blips dance around
void HudGaugeRadarOrb::blipDrawDistorted(blip *b, vec3d *pos)
{
    float scale;
    float dist=vm_vec_normalize(pos);
    vec3d out;
    float distortion_angle=20;

    // maybe alter the effect if EMP is active
    if(emp_active_local()) {
        scale = emp_current_intensity();
        distortion_angle *= frand_range(-3.0f,3.0f)*frand_range(0.0f, scale);
        dist *= frand_range(MAX(0.75f, 0.75f*scale), MIN(1.25f, 1.25f*scale));

        if (dist > 1.25f) dist = 1.25f;
        if (dist < 0.75f) dist = 0.75f;
    }

    vm_vec_random_cone(&out,pos,distortion_angle);
    vm_vec_scale(&out,dist);

    drawContactHtl(&out,b->rad);
}
// radar is damaged, so make blips dance around
void HudGaugeRadarDradis::blipDrawDistorted(blip *b, vec3d *pos, float alpha)
{
	float temp_scale;
	float dist = vm_vec_normalize(pos);
	vec3d out;
	float distortion_angle=20;

	// maybe alter the effect if EMP is active
	if (emp_active_local())
	{
		temp_scale = emp_current_intensity();
		dist *= frand_range(MAX(0.75f, 0.75f*temp_scale), MIN(1.25f, 1.25f*temp_scale));
		distortion_angle *= frand_range(-3.0f,3.0f)*frand_range(0.0f, temp_scale);

		if (dist > 1.0f) dist = 1.0f;
		if (dist < 0.1f) dist = 0.1f;
	}

	vm_vec_random_cone(&out, pos, distortion_angle);
	vm_vec_scale(&out, dist);

	drawContact(&out, -1, unknown_contact_icon, b->dist, alpha, 1.0f);
}
Ejemplo n.º 9
0
// blip is for a target immune to sensors, so cause to flicker in/out with mild distortion
void HudGaugeRadarOrb::blipDrawFlicker(blip *b, vec3d *pos)
{
    int flicker_index;

    float dist=vm_vec_normalize(pos);
    vec3d out;
    float distortion_angle=10;

    if ( (b-Blips) & 1 ) {
        flicker_index=0;
    } else {
        flicker_index=1;
    }

    if ( timestamp_elapsed(Radar_flicker_timer[flicker_index]) ) {
        Radar_flicker_timer[flicker_index] = timestamp_rand(50,1000);
        Radar_flicker_on[flicker_index] ^= 1;
    }

    if ( !Radar_flicker_on[flicker_index] ) {
        return;
    }

    if ( rand() & 1 ) {

        distortion_angle *= frand_range(0.1f,2.0f);
        dist *= frand_range(0.75f, 1.25f);

        if (dist > 1.25f) dist = 1.25f;
        if (dist < 0.75f) dist = 0.75f;
    }

    vm_vec_random_cone(&out,pos,distortion_angle);
    vm_vec_scale(&out,dist);

    drawContactHtl(&out,b->rad);
}
Ejemplo n.º 10
0
void ssm_get_random_start_pos(vec3d *out, vec3d *start, matrix *orient, size_t ssm_index)
{
	vec3d temp;
	ssm_info *s = &Ssm_info[ssm_index];
	float radius, offset;

	if (s->max_radius == -1.0f)
		radius = s->radius;
	else
		radius = frand_range(s->radius, s->max_radius);

	if (s->max_offset == -1.0f)
		offset = s->offset;
	else
		offset = frand_range(s->offset, s->max_offset);

	switch (s->shape) {
	case SSM_SHAPE_SPHERE:
		// get a random vector in a sphere around the target
		vm_vec_random_in_sphere(&temp, start, orient, radius, 1);
		break;
	case SSM_SHAPE_CIRCLE:
		// get a random vector in the circle of the firing plane
		vm_vec_random_in_circle(&temp, start, orient, radius, 1);
		break;
	case SSM_SHAPE_POINT:
		// boooring
		vm_vec_scale_add(&temp, start, &orient->vec.fvec, radius);
		break;
	default:
		Assertion(false, "Unknown shape '%d' in SSM type #" SIZE_T_ARG " ('%s'). This should not be possible; get a coder!\n", s->shape, ssm_index, s->name);
		break;
	}

	// offset it a bit
	vm_vec_scale_add(out, &temp, &orient->vec.fvec, offset);
}
Ejemplo n.º 11
0
// blip is for a target immune to sensors, so cause to flicker in/out with mild distortion
void HudGaugeRadarDradis::blipDrawFlicker(blip *b, vec3d *pos, float alpha)
{
	int flicker_index;

	float dist=vm_vec_normalize(pos);
	vec3d out;
	float distortion_angle=10;

	if ((b-Blips) & 1)
		flicker_index=0;
	else
		flicker_index=1;
	

	if (timestamp_elapsed(Radar_flicker_timer[flicker_index])) {
		Radar_flicker_timer[flicker_index] = timestamp_rand(50,1000);
		Radar_flicker_on[flicker_index] ^= 1;
	}

	if (!Radar_flicker_on[flicker_index])
		return;

	if (rand() & 1)
	{
		distortion_angle *= frand_range(0.1f,2.0f);
		dist *= frand_range(0.75f, 1.25f);

		if (dist > 1.0f) dist = 1.0f;
		if (dist < 0.1f) dist = 0.1f;
	}
	
	vm_vec_random_cone(&out,pos,distortion_angle);
	vm_vec_scale(&out,dist);

	drawContact(&out, -1, unknown_contact_icon, b->dist, alpha, 1.0f);
}
Ejemplo n.º 12
0
// process some stuff every frame (before frame is rendered)
void emp_process_local()
{	
	if(!emp_active_local()){
		return;
	}

	// decrement the intensity a bit
	Emp_intensity -= (flFrametime * Emp_decr);	

	// see if we should choose a random target
	if((Emp_wacky_target_timestamp == -1) || timestamp_elapsed(Emp_wacky_target_timestamp)){
		// choose a target (if not the "first" time)
		if(Emp_wacky_target_timestamp != -1){
			hud_target_random_ship();
		}

		// reset the timestamp
		Emp_wacky_target_timestamp = timestamp((int)frand_range(100.0f, 750.0f * (1.0f - Emp_intensity)));
	}			
}
Ejemplo n.º 13
0
/**
 * Checks debris-ship collisions.  
 * @param pair obj_pair pointer to the two objects. pair->a is debris and pair->b is ship.
 * @return 1 if all future collisions between these can be ignored
 */
int collide_debris_ship( obj_pair * pair )
{
	float dist;
	object *pdebris = pair->a;
	object *pship = pair->b;

	// Don't check collisions for warping out player
	if ( Player->control_mode != PCM_NORMAL )	{
		if ( pship == Player_obj )
			return 0;
	}

	Assert( pdebris->type == OBJ_DEBRIS );
	Assert( pship->type == OBJ_SHIP );

	// don't check collision if it's our own debris and we are dying
	if ( (pdebris->parent == OBJ_INDEX(pship)) && (Ships[pship->instance].flags[Ship::Ship_Flags::Dying]) )
		return 0;

	dist = vm_vec_dist( &pdebris->pos, &pship->pos );
	if ( dist < pdebris->radius + pship->radius )	{
		int hit;
		vec3d	hitpos;
		// create and initialize ship_ship_hit_info struct
		collision_info_struct debris_hit_info;
		init_collision_info_struct(&debris_hit_info);

		if ( pdebris->phys_info.mass > pship->phys_info.mass ) {
			debris_hit_info.heavy = pdebris;
			debris_hit_info.light = pship;
		} else {
			debris_hit_info.heavy = pship;
			debris_hit_info.light = pdebris;
		}

		hit = debris_check_collision(pdebris, pship, &hitpos, &debris_hit_info );
		if ( hit )
		{
			Script_system.SetHookObjects(4, "Ship", pship, "Debris", pdebris, "Self", pship, "Object", pdebris);
			bool ship_override = Script_system.IsConditionOverride(CHA_COLLIDEDEBRIS, pship);

			Script_system.SetHookObjects(2, "Self",pdebris, "Object", pship);
			bool debris_override = Script_system.IsConditionOverride(CHA_COLLIDESHIP, pdebris);
			if(!ship_override && !debris_override)
			{
				float		ship_damage;	
				float		debris_damage;

				// do collision physics
				calculate_ship_ship_collision_physics( &debris_hit_info );

				if ( debris_hit_info.impulse < 0.5f )
					return 0;

				// calculate ship damage
				ship_damage = 0.005f * debris_hit_info.impulse;	//	Cut collision-based damage in half.
				//	Decrease heavy damage by 2x.
				if (ship_damage > 5.0f)
					ship_damage = 5.0f + (ship_damage - 5.0f)/2.0f;

				// calculate debris damage and set debris damage to greater or debris and ship
				// debris damage is needed since we can really whack some small debris with afterburner and not do
				// significant damage to ship but the debris goes off faster than afterburner speed.
				debris_damage = debris_hit_info.impulse/pdebris->phys_info.mass;	// ie, delta velocity of debris
				debris_damage = (debris_damage > ship_damage) ? debris_damage : ship_damage;

				// modify ship damage by debris damage multiplier
				ship_damage *= Debris[pdebris->instance].damage_mult;

				// supercaps cap damage at 10-20% max hull ship damage
				if (Ship_info[Ships[pship->instance].ship_info_index].flags[Ship::Info_Flags::Supercap]) {
					float cap_percent_damage = frand_range(0.1f, 0.2f);
					ship_damage = MIN(ship_damage, cap_percent_damage * Ships[pship->instance].ship_max_hull_strength);
				}

				// apply damage to debris
				debris_hit( pdebris, pship, &hitpos, debris_damage);		// speed => damage
				int quadrant_num, apply_ship_damage;

				// apply damage to ship unless 1) debris is from ship
				apply_ship_damage = !(pship->signature == pdebris->parent_sig);

				if ( debris_hit_info.heavy == pship ) {
					quadrant_num = get_ship_quadrant_from_global(&hitpos, pship);
					if ((pship->flags[Object::Object_Flags::No_shields]) || !ship_is_shield_up(pship, quadrant_num) ) {
						quadrant_num = -1;
					}
					if (apply_ship_damage) {
						ship_apply_local_damage(debris_hit_info.heavy, debris_hit_info.light, &hitpos, ship_damage, quadrant_num, CREATE_SPARKS, debris_hit_info.submodel_num);
					}
				} else {
					// don't draw sparks using sphere hit position
					if (apply_ship_damage) {
						ship_apply_local_damage(debris_hit_info.light, debris_hit_info.heavy, &hitpos, ship_damage, MISS_SHIELDS, NO_SPARKS);
					}
				}

				// maybe print Collision on HUD
				if ( pship == Player_obj ) {					
					hud_start_text_flash(XSTR("Collision", 1431), 2000);
				}

				collide_ship_ship_do_sound(&hitpos, pship, pdebris, pship==Player_obj);
			}

			Script_system.SetHookObjects(2, "Self",pship, "Object", pdebris);
			if(!(debris_override && !ship_override))
				Script_system.RunCondition(CHA_COLLIDEDEBRIS, '\0', NULL, pship);

			Script_system.SetHookObjects(2, "Self",pdebris, "Object", pship);
			if((debris_override && !ship_override) || (!debris_override && !ship_override))
				Script_system.RunCondition(CHA_COLLIDESHIP, '\0', NULL, pdebris);

			Script_system.RemHookVars(4, "Ship", "Debris", "Self", "Object");

			return 0;
		}
	} else {	//	Bounding spheres don't intersect, set timestamp for next collision check.
		float	ship_max_speed, debris_speed;
		float	time;
		ship *shipp;

		shipp = &Ships[pship->instance];

		if (ship_is_beginning_warpout_speedup(pship)) {
			ship_max_speed = MAX(ship_get_max_speed(shipp), ship_get_warpout_speed(pship));
		} else {
			ship_max_speed = ship_get_max_speed(shipp);
		}
		ship_max_speed = MAX(ship_max_speed, 10.0f);
		ship_max_speed = MAX(ship_max_speed, pship->phys_info.vel.xyz.z);

		debris_speed = pdebris->phys_info.speed;

		time = 1000.0f * (dist - pship->radius - pdebris->radius - 10.0f) / (ship_max_speed + debris_speed);		// 10.0f is a safety factor
		time -= 200.0f;		// allow one frame slow frame at ~5 fps

		if (time > 100) {
			pair->next_check_time = timestamp( fl2i(time) );
		} else {
			pair->next_check_time = timestamp(0);	// check next time
		}
	}

	return 0;
}
Ejemplo n.º 14
0
// maybe reformat a string 
void emp_maybe_reformat_text(char *text, int max_len, int gauge_id)
{
	wacky_text *wt;

	// if the EMP effect is not active, never reformat it
	if(!emp_active_local()){
		return;
	}

	// randomly _don't_ apply text craziness
	if(frand_range(0.0f, 1.0f) > Emp_intensity){
		return;
	}

	// if the gauge is EG_NULL, empty the string
	if(gauge_id == EG_NULL){
		strcpy(text, "");
		return;
	}

	// if this gauge has not been wacked out, or if the timestamp has expired, we
	// neeed to wack it out again
	Assert((gauge_id >= EG_NULL) && (gauge_id < NUM_TEXT_STAMPS));
	wt = &Emp_wacky_text[gauge_id];
	if((wt->stamp == -1) || timestamp_elapsed(wt->stamp)){
		// reformat specific gauges differently
		switch(gauge_id){	
		//	weapons
		case EG_WEAPON_TITLE: case EG_WEAPON_P1: case EG_WEAPON_P2: case EG_WEAPON_P3: case EG_WEAPON_S1: case EG_WEAPON_S2:			
			int wep_index;
			wep_index = (int)frand_range(0.0f, (float)(MAX_WEAPON_TYPES - 1));
			strcpy_s(wt->str, Weapon_info[ wep_index >= MAX_WEAPON_TYPES ? 0 : wep_index ].name);			
			break;		

		// escort list
		case EG_ESCORT1: case EG_ESCORT2: case EG_ESCORT3:
			// choose a random ship
			int shipnum;
			shipnum = ship_get_random_targetable_ship();
			if(shipnum >= 0){
				strcpy_s(wt->str, Ships[shipnum].ship_name);
			}
			break;

		// directives title
		case EG_OBJ_TITLE:
			strcpy_s(wt->str, "");
			break;

		// directives themselves
		case EG_OBJ1: case EG_OBJ2: case EG_OBJ3: case EG_OBJ4: case EG_OBJ5:
			strcpy_s(wt->str, text);
			emp_randomize_chars(wt->str);
			break;

		// target box info
		case EG_TBOX_EXTRA1: case EG_TBOX_EXTRA2: case EG_TBOX_EXTRA3: case EG_TBOX_CLASS:
		case EG_TBOX_DIST: case EG_TBOX_CARGO: case EG_TBOX_HULL: case EG_TBOX_NAME: case EG_TBOX_INTEG:
			strcpy_s(wt->str, text);
			emp_randomize_chars(wt->str);
			break;

		// squadmsg menu
		case EG_SQ1: case EG_SQ2: case EG_SQ3: case EG_SQ4: case EG_SQ5: case EG_SQ6: case EG_SQ7:
		case EG_SQ8: case EG_SQ9: case EG_SQ10:
			strcpy_s(wt->str, text);
			emp_randomize_chars(wt->str);
			break;
			
		// default 
		default :
			return;
		}

		// recalculate the timestamp
		wt->stamp = timestamp((int)frand_range(100.0f, 750.0f * (1.0f - Emp_intensity)));

		// copy the text
		strcpy(text, wt->str);
	}
	// otherwise, use what we calculated last time
	else {
		strcpy(text, wt->str);
	}

	// watch out for '#' - Goober5000
	end_string_at_first_hash_symbol(text);
}
Ejemplo n.º 15
0
void multi_respawn_place(object *new_obj, int team)
{
	ship_obj *moveup;
	ship *s_check;
	ship *pri = NULL;
	object *pri_obj = NULL;
	object *hit_check;
	int collided, idx, lookup;

	// first determine if there are any appropriate priority ships to use
	pri = NULL;
	pri_obj = NULL;
	for(idx=0; idx<Multi_respawn_priority_count; idx++){
		// all relevant ships
		if((Multi_respawn_priority_ships[idx].team == team) || !(Netgame.type_flags & NG_TYPE_TEAM)){

			lookup = ship_name_lookup(Multi_respawn_priority_ships[idx].ship_name);
			if( (lookup >= 0) && ((pri == NULL) || (Ships[lookup].respawn_priority > pri->respawn_priority)) && (Ships[lookup].objnum >= 0) && (Ships[lookup].objnum < MAX_OBJECTS)){
				pri = &Ships[lookup];
				pri_obj = &Objects[Ships[lookup].objnum];
			}
		}
	}
	
	// if we have a relevant respawn ship
	if((pri != NULL) && (pri_obj != NULL)){
		// pick a point just outside his bounding box
		polymodel *pm = model_get(pri->modelnum); 

		// hmm, ugly. Pick a point 2000 meters to the y direction
		if(pm == NULL){			
			vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.rvec, 2000.0f);
		} else {
			// pick a random direction
			int d = (int)frand_range(0.0f, 5.9f);
			switch(d){
			case 0:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.rvec, (pm->maxs.xyz.x - pm->mins.xyz.x)); 
				break;

			case 1:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.rvec, -(pm->maxs.xyz.x - pm->mins.xyz.x));
				break;

			case 2:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.uvec, (pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;

			case 3:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.uvec, -(pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;

			case 4:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.fvec, (pm->maxs.xyz.z - pm->mins.xyz.z)); 
				break;

			case 5:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.fvec, -(pm->maxs.xyz.z - pm->mins.xyz.z)); 
				break;

			default:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.uvec, -(pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;
			}
		}
	}
	// otherwise, resort to plain respawn points
	else {
		Assert(Multi_respawn_point_count > 0);
		
		// get the next appropriate respawn point by team
		lookup = 0;		
		int count = 0;
		while(!lookup && (count < 13)){
			if((team == TEAM_TRAITOR) || (team == Multi_respawn_points[Multi_next_respawn_point].team)){
				lookup = 1;
			}			

			// next item
			if(!lookup){
				if(Multi_next_respawn_point >= (Multi_respawn_point_count-1)){
					Multi_next_respawn_point = 0;
				} else {
					Multi_next_respawn_point++;
				}				
			}

			count++;
		}

		// set respawn info
		new_obj->pos = Multi_respawn_points[Multi_next_respawn_point].pos;		
	}

	// now make sure we're not colliding with anyone		
	do {
		collided = 0;
		moveup = GET_FIRST(&Ship_obj_list);
		while(moveup!=END_OF_LIST(&Ship_obj_list)){
			// don't check the new_obj itself!!
			if(Objects[moveup->objnum].net_signature != new_obj->net_signature){
				hit_check = &Objects[moveup->objnum];
				Assert(hit_check->type == OBJ_SHIP);
				Assert(hit_check->instance >= 0);
				if((hit_check->type != OBJ_SHIP) || (hit_check->instance < 0)){
					continue;
				}
				s_check = &Ships[hit_check->instance];
				
				// just to make sure we don't get any strange magnitude errors
				if(vm_vec_same(&hit_check->pos, &new_obj->pos)){
					new_obj->pos.xyz.x += 1.0f;
				}
				
				WITHIN_BBOX();				
				if(collided){						
					MOVE_AWAY_BBOX();
					break;
				} 
				collided = 0;
			}
			moveup = GET_NEXT(moveup);
		}
	} while(collided);   		
}
Ejemplo n.º 16
0
void multi_respawn_place(object *new_obj, int team)
{
	ship *pri = NULL;
	object *pri_obj = NULL;
	int idx, lookup;

	// first determine if there are any appropriate priority ships to use
	pri = NULL;
	pri_obj = NULL;
	for(idx=0; idx<Multi_respawn_priority_count; idx++){
		// all relevant ships
		if((Multi_respawn_priority_ships[idx].team == team) || !(Netgame.type_flags & NG_TYPE_TEAM)){

			lookup = ship_name_lookup(Multi_respawn_priority_ships[idx].ship_name);
			if( (lookup >= 0) && ((pri == NULL) || (Ships[lookup].respawn_priority > pri->respawn_priority)) && (Ships[lookup].objnum >= 0) && (Ships[lookup].objnum < MAX_OBJECTS)){
				pri = &Ships[lookup];
				pri_obj = &Objects[Ships[lookup].objnum];
			}
		}
	}
	
	// if we have a relevant respawn ship
	if((pri != NULL) && (pri_obj != NULL)){
		// pick a point just outside his bounding box
		polymodel *pm = model_get(Ship_info[pri->ship_info_index].model_num); 

		// hmm, ugly. Pick a point 2000 meters to the y direction
		if(pm == NULL){			
			vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.rvec, 2000.0f);
		} else {
			// pick a random direction
			int d = (int)frand_range(0.0f, 5.9f);
			switch(d){
			case 0:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.rvec, (pm->maxs.xyz.x - pm->mins.xyz.x)); 
				break;

			case 1:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.rvec, -(pm->maxs.xyz.x - pm->mins.xyz.x)); 
				break;

			case 2:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.uvec, (pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;

			case 3:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.uvec, -(pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;

			case 4:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.fvec, (pm->maxs.xyz.z - pm->mins.xyz.z)); 
				break;

			case 5:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.fvec, -(pm->maxs.xyz.z - pm->mins.xyz.z)); 
				break;

			default:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.uvec, -(pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;
			}
		}
	}
	// otherwise, resort to plain respawn points
	else {
		Assert(Multi_respawn_point_count > 0);
		
		// get the next appropriate respawn point by team
		lookup = 0;		
		int count = 0;
		while(!lookup && (count < 13)){
			if((team == Iff_traitor) || (team == Multi_respawn_points[Multi_next_respawn_point].team)){
				lookup = 1;
			}			

			// next item
			if(!lookup){
				if(Multi_next_respawn_point >= (Multi_respawn_point_count-1)){
					Multi_next_respawn_point = 0;
				} else {
					Multi_next_respawn_point++;
				}				
			}

			count++;
		}

		// set respawn info
		new_obj->pos = Multi_respawn_points[Multi_next_respawn_point].pos;		
	}

	// now make sure we're not colliding with anyone
	prevent_spawning_collision(new_obj);
}
Ejemplo n.º 17
0
// given a just fired flak shell, pick a detonating distance for it
void flak_pick_range(object* objp, vec3d* firing_pos, vec3d* predicted_target_pos, float weapon_subsys_strength)
{
	float final_range;
	float det_range;
	vec3d temp;

	// make sure this flak object is valid
	Assert(objp->type == OBJ_WEAPON);
	Assert(objp->instance >= 0);
	Assert(Weapons[objp->instance].weapon_info_index >= 0);
	Assert(Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags & WIF_FLAK);

	// if the flak index is invalid, do nothing - if this fails the flak simply becomes a non-rendering bullet
	/*
	if(Weapons[objp->instance].flak_index < 0){
		return;
	}
	*/

	// get the range to the target
	vm_vec_sub(&temp, &objp->pos, predicted_target_pos);
	final_range = vm_vec_mag(&temp);

	//Is it larger than det_range?
	det_range = Weapon_info[Weapons[objp->instance].weapon_info_index].det_range;
	if (det_range != 0.0f && final_range > det_range)
	{
		flak_set_range(objp, det_range);
		return;
	}

	// add in some randomness
	final_range += (Flak_range + (Flak_range * 0.65f * (1.0f - weapon_subsys_strength))) * frand_range(-1.0f, 1.0f);

	// make sure we're firing at least 10 meters away
	if (final_range < 10.0f)
	{
		final_range = 10.0f;
	}

	// set the range
	flak_set_range(objp, final_range);
}
Ejemplo n.º 18
0
void fish_generate()
{
	fish *f;
	int idx;

	if(!Fish_inited){
		return;
	}

	// bogus anims
	if((Fish_left_anim == NULL) || (Fish_right_anim == NULL)){
		return;
	}

	// find a free fish
	f = NULL;
	for(idx=0; idx<MAX_FISH; idx++){
		if(!Fish[idx].swimming){
			f = &Fish[idx];
		}
	}

	// no fish left
	if(f == NULL){
		return;
	}	

	// left or right
	f->left = frand_range(0.0f, 1.0f) < 0.5f ? 0 : 1;

	// start location
	if(f->left){
		f->x = gr_screen.max_w_unscaled_zoomed + frand_range(0.0f, 50.0f);
	} else {
		f->x = frand_range(0.0f, -50.0f) - FISH_ANIM_WIDTH;
	}
	f->y = frand_range(-40.0f, (float)gr_screen.max_h_unscaled_zoomed + 40.0f);

	// speed
	if(f->left){
		f->x_speed = frand_range(-1.0f, -15.0f);
	} else {
		f->x_speed = frand_range(1.0f, 15.0f);
	}
	f->y_speed = frand_range(0.0f, 1.0f) < 0.5f ? frand_range(1.0f, 4.0f) : frand_range(-1.0f, -4.0f);

	// all fish start out offscreen
	f->onscreen = 0;

	// he's swimming
	f->swimming = 1;

	// anim instance
	anim_play_struct aps;

	if(f->left){
		anim_play_init(&aps, Fish_left_anim, (int)f->x, (int)f->y);		
		f->a = anim_play(&aps);

		// doh. cancel him
		if(f->a == NULL){
			f->swimming = 0;
		} else {
			f->a->screen_id = GS_STATE_MAIN_MENU;
			f->a->looped = 1;
			f->a->framerate_independent = 1;
		}
	} else {
		anim_play_init(&aps, Fish_right_anim, (int)f->x, (int)f->y);		
		f->a = anim_play(&aps);

		// doh. cancel him
		if(f->a == NULL){
			f->swimming = 0;
		} else {
			f->a->screen_id = GS_STATE_MAIN_MENU;
			f->a->looped = 1;
			f->a->framerate_independent = 1;
		}
	}
}
Ejemplo n.º 19
0
// Checks debris-ship collisions.  pair->a is debris and pair->b is ship.
// Returns 1 if all future collisions between these can be ignored
int collide_debris_ship( obj_pair * pair )
{
	float dist;
	object *pdebris = pair->a;
	object *pship = pair->b;

		// Don't check collisions for warping out player
	if ( Player->control_mode != PCM_NORMAL )	{
		if ( pship == Player_obj )
			return 0;
	}

	Assert( pdebris->type == OBJ_DEBRIS );
	Assert( pship->type == OBJ_SHIP );

/*	Debris_ship_count++;
	if (Debris_ship_count % 100 == 0)
		nprintf(("AI", "Done %i debris:ship checks in %i frames = %.2f checks/frame\n", Debris_ship_count, Framecount, (float) Debris_ship_count/Framecount));
*/
	dist = vm_vec_dist( &pdebris->pos, &pship->pos );
	if ( dist < pdebris->radius + pship->radius )	{
		int hit;
		vector	hitpos;
		// create and initialize ship_ship_hit_info struct
		collision_info_struct debris_hit_info;
		memset( &debris_hit_info, -1, sizeof(collision_info_struct) );

		if ( pdebris->phys_info.mass > pship->phys_info.mass ) {
			debris_hit_info.heavy = pdebris;
			debris_hit_info.light = pship;
		} else {
			debris_hit_info.heavy = pship;
			debris_hit_info.light = pdebris;
		}

		hit = debris_check_collision(pdebris, pship, &hitpos, &debris_hit_info );
		if ( hit ) {
			float		ship_damage;	
			float		debris_damage;

			// do collision physics
			calculate_ship_ship_collision_physics( &debris_hit_info );

			if ( debris_hit_info.impulse < 0.5f )
				return 0;

			// calculate ship damage
			ship_damage = 0.005f * debris_hit_info.impulse;	//	Cut collision-based damage in half.
			//	Decrease heavy damage by 2x.
			if (ship_damage > 5.0f)
				ship_damage = 5.0f + (ship_damage - 5.0f)/2.0f;

			// calculate debris damage and set debris damage to greater or debris and ship
			// debris damage is needed since we can really whack some small debris with afterburner and not do
			// significant damage to ship but the debris goes off faster than afterburner speed.
			debris_damage = debris_hit_info.impulse/pdebris->phys_info.mass;	// ie, delta velocity of debris
			debris_damage = (debris_damage > ship_damage) ? debris_damage : ship_damage;

			// supercaps cap damage at 10-20% max hull ship damage
			if (Ship_info[Ships[pship->instance].ship_info_index].flags & SIF_SUPERCAP) {
				float cap_percent_damage = frand_range(0.1f, 0.2f);
				ship_damage = min(ship_damage, cap_percent_damage * Ship_info[Ships[pship->instance].ship_info_index].initial_hull_strength);
			}

			// apply damage to debris
			debris_hit( pdebris, pship, &hitpos, debris_damage);		// speed => damage
			int quadrant_num, apply_ship_damage;

			// apply damage to ship unless 1) debris is from ship
			// apply_ship_damage = !((pship->signature == pdebris->parent_sig) && ship_is_beginning_warpout_speedup(pship));
			apply_ship_damage = !(pship->signature == pdebris->parent_sig);

			if ( debris_hit_info.heavy == pship ) {
				quadrant_num = get_ship_quadrant_from_global(&hitpos, pship);
				if ((pship->flags & OF_NO_SHIELDS) || !ship_is_shield_up(pship, quadrant_num) ) {
					quadrant_num = -1;
				}
				if (apply_ship_damage) {
					ship_apply_local_damage(debris_hit_info.heavy, debris_hit_info.light, &hitpos, ship_damage, quadrant_num, CREATE_SPARKS, debris_hit_info.submodel_num);
				}
			} else {
				// don't draw sparks using sphere hit position
				if (apply_ship_damage) {
					ship_apply_local_damage(debris_hit_info.light, debris_hit_info.heavy, &hitpos, ship_damage, MISS_SHIELDS, NO_SPARKS);
				}
			}

			// maybe print Collision on HUD
			if ( pship == Player_obj ) {					
				hud_start_text_flash(XSTR("Collision", 1431), 2000);
			}

			collide_ship_ship_do_sound(&hitpos, pship, pdebris, pship==Player_obj);

			return 0;
		}
	} else {	//	Bounding spheres don't intersect, set timestamp for next collision check.
		float	ship_max_speed, debris_speed;
		float	time;
		ship *shipp;

		shipp = &Ships[pship->instance];

		if (ship_is_beginning_warpout_speedup(pship)) {
			ship_max_speed = max(ship_get_max_speed(shipp), ship_get_warp_speed(pship));
		} else {
			ship_max_speed = ship_get_max_speed(shipp);
		}
		ship_max_speed = max(ship_max_speed, 10.0f);
		ship_max_speed = max(ship_max_speed, pship->phys_info.vel.xyz.z);

		debris_speed = pdebris->phys_info.speed;

		time = 1000.0f * (dist - pship->radius - pdebris->radius - 10.0f) / (ship_max_speed + debris_speed);		// 10.0f is a safety factor
		time -= 200.0f;		// allow one frame slow frame at ~5 fps

		if (time > 100) {
			//nprintf(("AI", "Ship %s debris #%i delay time = %.1f seconds\n", Ships[pship->instance].ship_name, pdebris-Objects, time/1000.0f));
			pair->next_check_time = timestamp( fl2i(time) );
		} else {
			pair->next_check_time = timestamp(0);	// check next time
		}
	}

	return 0;
}