/* ------------------------- FX_BryarHitWall ------------------------- */ void FX_BryarHitWall( vec3_t origin, vec3_t normal ) { trap_FX_PlayEffectID( cgs.effects.bryarWallImpactEffect, origin, normal ); //Boot: /*if (Q_irand(0, 4) > 2) {*/ trap_FX_PlayEffectID(trap_FX_RegisterEffect("smoke_alot.efx"), origin, normal); trap_FX_PlayEffectID(trap_FX_RegisterEffect("blaster/intense_sparks.efx"), origin, normal); //} }
/* ------------------------- FX_BlasterWeaponHitPlayer ------------------------- */ void FX_BlasterWeaponHitPlayer( vec3_t origin, vec3_t normal, qboolean humanoid ) { if ( humanoid ) { trap_FX_PlayEffectID( cgs.effects.blasterFleshImpactEffect, origin, normal ); } else { trap_FX_PlayEffectID( cgs.effects.blasterDroidImpactEffect, origin, normal ); } }
/* ------------------------- FX_TurretHitPlayer ------------------------- */ void FX_TurretHitPlayer( vec3_t origin, vec3_t normal, qboolean humanoid ) { if ( humanoid ) { trap_FX_PlayEffectID( cgs.effects.bryarFleshImpactEffect, origin, normal ); } else { trap_FX_PlayEffectID( cgs.effects.bryarDroidImpactEffect, origin, normal ); } }
/* ------------------------- FX_BryarHitPlayer ------------------------- */ void FX_BryarHitPlayer( vec3_t origin, vec3_t normal, qboolean humanoid ) { if ( humanoid ) { trap_FX_PlayEffectID( cgs.effects.bryarFleshImpactEffect, origin, normal ); } else { trap_FX_PlayEffectID( cgs.effects.bryarDroidImpactEffect, origin, normal ); } //trap_FX_PlayEffectID(trap_FX_RegisterEffect("smoke_alot.efx"), origin, normal); //trap_FX_PlayEffectID(trap_FX_RegisterEffect("blaster/intense_sparks.efx"), origin, normal); }
/* ------------------------- FX_BryarAltHitWall ------------------------- */ void FX_BryarAltHitWall( vec3_t origin, vec3_t normal, int power ) { switch( power ) { case 4: case 5: trap_FX_PlayEffectID( cgs.effects.bryarWallImpactEffect3, origin, normal ); break; case 2: case 3: trap_FX_PlayEffectID( cgs.effects.bryarWallImpactEffect2, origin, normal ); break; default: trap_FX_PlayEffectID( cgs.effects.bryarWallImpactEffect, origin, normal ); break; } }
/* ------------------------- FX_FlechetteWeaponHitPlayer ------------------------- */ void FX_FlechetteWeaponHitPlayer( vec3_t origin, vec3_t normal, qboolean humanoid ) { // if ( humanoid ) // { trap_FX_PlayEffectID( cgs.effects.flechetteFleshImpactEffect, origin, normal, -1, -1 ); // } // else // { // trap_FX_PlayEffect( "blaster/droid_impact", origin, normal ); // } }
/* ------------------------- FX_BlasterAltFireThink ------------------------- */ void FX_BlasterAltFireThink( centity_t *cent, const struct weaponInfo_s *weapon ) { vec3_t forward; if ( VectorNormalize2( cent->currentState.pos.trDelta, forward ) == 0.0f ) { forward[2] = 1.0f; } trap_FX_PlayEffectID( cgs.effects.blasterShotEffect, cent->lerpOrigin, forward ); }
void FX_RocketAltProjectileThink( centity_t *cent, const struct weaponInfo_s *weapon ) { vec3_t forward; if ( VectorNormalize2( cent->currentState.pos.trDelta, forward ) == 0.0f ) { forward[2] = 1.0f; } trap_FX_PlayEffectID( cgs.effects.rocketShotEffect, cent->lerpOrigin, forward, -1, -1 ); }
/* ------------------------- ALT FIRE ------------------------- FX_BryarAltProjectileThink ------------------------- */ void FX_BryarAltProjectileThink( centity_t *cent, const struct weaponInfo_s *weapon ) { vec3_t forward; int t; if ( VectorNormalize2( cent->currentState.pos.trDelta, forward ) == 0.0f ) { forward[2] = 1.0f; } // see if we have some sort of extra charge going on for (t = 1; t < cent->currentState.generic1; t++ ) { // just add ourselves over, and over, and over when we are charged trap_FX_PlayEffectID( cgs.effects.bryarPowerupShotEffect, cent->lerpOrigin, forward ); } // for ( int t = 1; t < cent->gent->count; t++ ) // The single player stores the charge in count, which isn't accessible on the client trap_FX_PlayEffectID( cgs.effects.bryarShotEffect, cent->lerpOrigin, forward ); }
/* ------------------------- FX_BryarAltHitWall ------------------------- */ void FX_BryarAltHitWall( vec3_t origin, vec3_t normal, int power ) { switch( power ) { case 4: case 5: trap_FX_PlayEffectID( cgs.effects.bryarWallImpactEffect3, origin, normal ); break; case 2: case 3: trap_FX_PlayEffectID( cgs.effects.bryarWallImpactEffect2, origin, normal ); break; default: trap_FX_PlayEffectID( cgs.effects.bryarWallImpactEffect, origin, normal ); break; } trap_FX_PlayEffectID(trap_FX_RegisterEffect("smoke_alot.efx"), origin, normal); trap_FX_PlayEffectID(trap_FX_RegisterEffect("blaster/intense_sparks.efx"), origin, normal); }
void PM_VehicleImpact(bgEntity_t *pEnt, trace_t *trace) { // See if the vehicle has crashed into the ground. Vehicle_t *pSelfVeh = pEnt->m_pVehicle; float magnitude = VectorLength( pm->ps->velocity ) * pSelfVeh->m_pVehicleInfo->mass / 50.0f; qboolean forceSurfDestruction = qfalse; #ifdef QAGAME gentity_t *hitEnt = trace!=NULL?&g_entities[trace->entityNum]:NULL; if (!hitEnt || //nothing to hit (pSelfVeh && pSelfVeh->m_pPilot &&//I'm a piloted vehicle hitEnt && hitEnt->s.eType == ET_MISSILE && hitEnt->inuse &&//that hit a missile hitEnt->r.ownerNum == pSelfVeh->m_pPilot->s.number)//and the missile is owned by my pilot ) {//don't hit it return; } if ( pSelfVeh//I have a vehicle struct && pSelfVeh->m_iRemovedSurfaces )//vehicle has bits removed {//spiralling to our deaths, explode on any solid impact if ( hitEnt->s.NPC_class == CLASS_VEHICLE ) {//hit another vehicle, explode! //Give credit to whoever got me into this death spiral state G_DamageFromKiller( (gentity_t *)pEnt, (gentity_t *)pSelfVeh->m_pParentEntity, (gentity_t *)hitEnt, pm->ps->origin, 999999, DAMAGE_NO_ARMOR, MOD_COLLISION ); return; } else if ( !VectorCompare( trace->plane.normal, vec3_origin ) && (trace->entityNum == ENTITYNUM_WORLD || hitEnt->r.bmodel ) ) {//have a valid hit plane and we hit a solid brush vec3_t moveDir; float impactDot; VectorCopy( pm->ps->velocity, moveDir ); VectorNormalize( moveDir ); impactDot = DotProduct( moveDir, trace->plane.normal ); if ( impactDot <= -0.7f )//hit rather head-on and hard {// Just DIE now //Give credit to whoever got me into this death spiral state G_DamageFromKiller( (gentity_t *)pEnt, (gentity_t *)pSelfVeh->m_pParentEntity, (gentity_t *)hitEnt, pm->ps->origin, 999999, DAMAGE_NO_ARMOR, MOD_FALLING ); return; } } } if ( trace->entityNum < ENTITYNUM_WORLD && hitEnt->s.eType == ET_MOVER && hitEnt->s.apos.trType != TR_STATIONARY//rotating && (hitEnt->spawnflags&16) //IMPACT && Q_stricmp( "func_rotating", hitEnt->classname ) == 0 ) {//hit a func_rotating that is supposed to destroy anything it touches! //guarantee the hit will happen, thereby taking off a piece of the ship forceSurfDestruction = qtrue; } else if ( (fabs(pm->ps->velocity[0])+fabs(pm->ps->velocity[1])) < 100.0f && pm->ps->velocity[2] > -100.0f ) #else if ( (fabs(pm->ps->velocity[0])+fabs(pm->ps->velocity[1])) < 100.0f && pm->ps->velocity[2] > -100.0f ) #endif /* if ( (pSelfVeh->m_ulFlags&VEH_GEARSOPEN) && trace->plane.normal[2] > 0.7f && fabs(pSelfVeh->m_vOrientation[PITCH]) < 0.2f && fabs(pSelfVeh->m_vOrientation[ROLL]) < 0.2f )*/ {//we're landing, we're cool //FIXME: some sort of landing "thump", not the impactFX /* if ( pSelfVeh->m_pVehicleInfo->iImpactFX ) { vec3_t up = {0,0,1}; #ifdef QAGAME G_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, up ); #else trap_FX_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, up, -1, -1 ); #endif } */ //this was annoying me -rww //FIXME: this shouldn't even be getting called when the vehicle is at rest! #ifdef QAGAME if (hitEnt && (hitEnt->s.eType == ET_PLAYER || hitEnt->s.eType == ET_NPC) && pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER) { //always smack players } else #endif { return; } } if ( pSelfVeh && (pSelfVeh->m_pVehicleInfo->type == VH_SPEEDER || pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER) && //this is kind of weird on tauntauns and atst's.. (magnitude >= 100||forceSurfDestruction) ) { if ( pEnt->m_pVehicle->m_iHitDebounce < pm->cmd.serverTime || forceSurfDestruction ) {//a bit of a hack, may conflict with getting shot, but... //FIXME: impact sound and effect should be gotten from g_vehicleInfo...? //FIXME: should pass in trace.endpos and trace.plane.normal vec3_t vehUp; #ifdef QAGAME qboolean noDamage = qfalse; #else bgEntity_t *hitEnt; #endif if ( trace && !pSelfVeh->m_iRemovedSurfaces && !forceSurfDestruction ) { qboolean turnFromImpact = qfalse, turnHitEnt = qfalse; float l = pm->ps->speed*0.5f; vec3_t bounceDir; #ifndef QAGAME bgEntity_t *hitEnt = PM_BGEntForNum(trace->entityNum); #endif if ( (trace->entityNum == ENTITYNUM_WORLD || hitEnt->s.solid == SOLID_BMODEL)//bounce off any brush && !VectorCompare(trace->plane.normal, vec3_origin) )//have a valid plane to bounce off of { //bounce off in the opposite direction of the impact if (pSelfVeh->m_pVehicleInfo->type == VH_SPEEDER) { pm->ps->speed *= pml.frametime; VectorCopy(trace->plane.normal, bounceDir); } else if ( trace->plane.normal[2] >= MIN_LANDING_SLOPE//flat enough to land on && pSelfVeh->m_LandTrace.fraction < 1.0f //ground present && pm->ps->speed <= MIN_LANDING_SPEED ) {//could land here, don't bounce off, in fact, return altogether! return; } else { if (pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER) { turnFromImpact = qtrue; } VectorCopy(trace->plane.normal, bounceDir); } } else if ( pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER ) {//check for impact with another fighter #ifndef QAGAME bgEntity_t *hitEnt = PM_BGEntForNum(trace->entityNum); #endif if ( hitEnt->s.NPC_class == CLASS_VEHICLE && hitEnt->m_pVehicle && hitEnt->m_pVehicle->m_pVehicleInfo && hitEnt->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER ) {//two vehicles hit each other, turn away from the impact turnFromImpact = qtrue; turnHitEnt = qtrue; #ifndef QAGAME VectorSubtract( pm->ps->origin, hitEnt->s.origin, bounceDir ); #else VectorSubtract( pm->ps->origin, hitEnt->r.currentOrigin, bounceDir ); #endif VectorNormalize( bounceDir ); } } if ( turnFromImpact ) {//bounce off impact surf and turn away vec3_t pushDir={0}, turnAwayAngles, turnDelta; float turnStrength, pitchTurnStrength, yawTurnStrength; vec3_t moveDir; float bounceDot, turnDivider; //bounce if ( !turnHitEnt ) {//hit wall VectorScale(bounceDir, (pm->ps->speed*0.25f/pSelfVeh->m_pVehicleInfo->mass), pushDir); } else {//hit another fighter #ifndef QAGAME VectorScale( bounceDir, (pm->ps->speed+hitEnt->s.speed)*0.5f, bounceDir ); #else if ( hitEnt->client ) { VectorScale( bounceDir, (pm->ps->speed+hitEnt->client->ps.speed)*0.5f, pushDir ); } else { VectorScale( bounceDir, (pm->ps->speed+hitEnt->s.speed)*0.5f, pushDir ); } #endif VectorScale(pushDir, (l/pSelfVeh->m_pVehicleInfo->mass), pushDir); VectorScale(pushDir, 0.1f, pushDir); } VectorNormalize2( pm->ps->velocity, moveDir ); bounceDot = DotProduct( moveDir, bounceDir )*-1; if ( bounceDot < 0.1f ) { bounceDot = 0.1f; } VectorScale( pushDir, bounceDot, pushDir ); VectorAdd(pm->ps->velocity, pushDir, pm->ps->velocity); //turn turnDivider = (pSelfVeh->m_pVehicleInfo->mass/400.0f); if ( turnHitEnt ) {//don't turn as much when hit another ship turnDivider *= 4.0f; } if ( turnDivider < 0.5f ) { turnDivider = 0.5f; } turnStrength = (magnitude/2000.0f); if ( turnStrength < 0.1f ) { turnStrength = 0.1f; } else if ( turnStrength > 2.0f ) { turnStrength = 2.0f; } //get the angles we are going to turn towards vectoangles( bounceDir, turnAwayAngles ); //get the delta from our current angles to those new angles AnglesSubtract( turnAwayAngles, pSelfVeh->m_vOrientation, turnDelta ); //now do pitch if ( !bounceDir[2] ) {//shouldn't be any pitch } else { pitchTurnStrength = turnStrength*turnDelta[PITCH]; if ( pitchTurnStrength > MAX_IMPACT_TURN_ANGLE ) { pitchTurnStrength = MAX_IMPACT_TURN_ANGLE; } else if ( pitchTurnStrength < -MAX_IMPACT_TURN_ANGLE ) { pitchTurnStrength = -MAX_IMPACT_TURN_ANGLE; } //pSelfVeh->m_vOrientation[PITCH] = AngleNormalize180(pSelfVeh->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier); pSelfVeh->m_vFullAngleVelocity[PITCH] = AngleNormalize180(pSelfVeh->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier); } //now do yaw if ( !bounceDir[0] && !bounceDir[1] ) {//shouldn't be any yaw } else { yawTurnStrength = turnStrength*turnDelta[YAW]; if ( yawTurnStrength > MAX_IMPACT_TURN_ANGLE ) { yawTurnStrength = MAX_IMPACT_TURN_ANGLE; } else if ( yawTurnStrength < -MAX_IMPACT_TURN_ANGLE ) { yawTurnStrength = -MAX_IMPACT_TURN_ANGLE; } //pSelfVeh->m_vOrientation[ROLL] = AngleNormalize180(pSelfVeh->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier); pSelfVeh->m_vFullAngleVelocity[ROLL] = AngleNormalize180(pSelfVeh->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier); } /* PM_SetPMViewAngle(pm->ps, pSelfVeh->m_vOrientation, &pSelfVeh->m_ucmd); if ( pm_entVeh ) {//I'm a vehicle, so pm_entVeh is actually my pilot bgEntity_t *pilot = pm_entVeh; if ( !BG_UnrestrainedPitchRoll( pilot->playerState, pSelfVeh ) ) { //set the rider's viewangles to the vehicle's viewangles PM_SetPMViewAngle(pilot->playerState, pSelfVeh->m_vOrientation, &pSelfVeh->m_ucmd); } } */ #ifdef QAGAME//server-side, turn the guy we hit away from us, too if ( turnHitEnt//make the other guy turn and get pushed && hitEnt->client //must be a valid client && !FighterIsLanded( hitEnt->m_pVehicle, &hitEnt->client->ps )//but not if landed && !(hitEnt->spawnflags&2) )//and not if suspended { l = hitEnt->client->ps.speed; //now bounce *them* away and turn them //flip the bounceDir VectorScale( bounceDir, -1, bounceDir ); //do bounce VectorScale( bounceDir, (pm->ps->speed+l)*0.5f, pushDir ); VectorScale(pushDir, (l*0.5f/hitEnt->m_pVehicle->m_pVehicleInfo->mass), pushDir); VectorNormalize2( hitEnt->client->ps.velocity, moveDir ); bounceDot = DotProduct( moveDir, bounceDir )*-1; if ( bounceDot < 0.1f ) { bounceDot = 0.1f; } VectorScale( pushDir, bounceDot, pushDir ); VectorAdd(hitEnt->client->ps.velocity, pushDir, hitEnt->client->ps.velocity); //turn turnDivider = (hitEnt->m_pVehicle->m_pVehicleInfo->mass/400.0f); if ( turnHitEnt ) {//don't turn as much when hit another ship turnDivider *= 4.0f; } if ( turnDivider < 0.5f ) { turnDivider = 0.5f; } //get the angles we are going to turn towards vectoangles( bounceDir, turnAwayAngles ); //get the delta from our current angles to those new angles AnglesSubtract( turnAwayAngles, hitEnt->m_pVehicle->m_vOrientation, turnDelta ); //now do pitch if ( !bounceDir[2] ) {//shouldn't be any pitch } else { pitchTurnStrength = turnStrength*turnDelta[PITCH]; if ( pitchTurnStrength > MAX_IMPACT_TURN_ANGLE ) { pitchTurnStrength = MAX_IMPACT_TURN_ANGLE; } else if ( pitchTurnStrength < -MAX_IMPACT_TURN_ANGLE ) { pitchTurnStrength = -MAX_IMPACT_TURN_ANGLE; } //hitEnt->m_pVehicle->m_vOrientation[PITCH] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier); hitEnt->m_pVehicle->m_vFullAngleVelocity[PITCH] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[PITCH]+pitchTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier); } //now do yaw if ( !bounceDir[0] && !bounceDir[1] ) {//shouldn't be any yaw } else { yawTurnStrength = turnStrength*turnDelta[YAW]; if ( yawTurnStrength > MAX_IMPACT_TURN_ANGLE ) { yawTurnStrength = MAX_IMPACT_TURN_ANGLE; } else if ( yawTurnStrength < -MAX_IMPACT_TURN_ANGLE ) { yawTurnStrength = -MAX_IMPACT_TURN_ANGLE; } //hitEnt->m_pVehicle->m_vOrientation[ROLL] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier); hitEnt->m_pVehicle->m_vFullAngleVelocity[ROLL] = AngleNormalize180(hitEnt->m_pVehicle->m_vOrientation[ROLL]-yawTurnStrength/turnDivider*pSelfVeh->m_fTimeModifier); } //NOTE: will these angle changes stick or will they be stomped // when the vehicle goes through its own update and re-grabs // its angles from its pilot...? Should we do a // SetClientViewAngles on the pilot? /* SetClientViewAngle( hitEnt, hitEnt->m_pVehicle->m_vOrientation ); if ( hitEnt->m_pVehicle->m_pPilot && ((gentity_t *)hitEnt->m_pVehicle->m_pPilot)->client ) { SetClientViewAngle( (gentity_t *)hitEnt->m_pVehicle->m_pPilot, hitEnt->m_pVehicle->m_vOrientation ); } */ } #endif } } #ifdef QAGAME if (!hitEnt) { return; } AngleVectors( pSelfVeh->m_vOrientation, NULL, NULL, vehUp ); if ( pSelfVeh->m_pVehicleInfo->iImpactFX ) { //G_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, vehUp ); //tempent use bad! G_AddEvent((gentity_t *)pEnt, EV_PLAY_EFFECT_ID, pSelfVeh->m_pVehicleInfo->iImpactFX); } pEnt->m_pVehicle->m_iHitDebounce = pm->cmd.serverTime + 200; magnitude /= pSelfVeh->m_pVehicleInfo->toughness * 50.0f; if (hitEnt && (hitEnt->s.eType != ET_TERRAIN || !(hitEnt->spawnflags & 1) || pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER)) { //don't damage the vehicle from terrain that doesn't want to damage vehicles gentity_t *killer = NULL; if (pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER) { //increase the damage... float mult = (pSelfVeh->m_vOrientation[PITCH]*0.1f); if (mult < 1.0f) { mult = 1.0f; } if (hitEnt->inuse && hitEnt->takedamage) { //if the other guy takes damage, don't hurt us a lot for ramming him //unless it's a vehicle, then we get 1.5 times damage if (hitEnt->s.eType == ET_NPC && hitEnt->s.NPC_class == CLASS_VEHICLE && hitEnt->m_pVehicle) { mult = 1.5f; } else { mult = 0.5f; } } magnitude *= mult; } pSelfVeh->m_iLastImpactDmg = magnitude; //FIXME: what about proper death credit to the guy who shot you down? //FIXME: actually damage part of the ship that impacted? if ( hitEnt->s.eType == ET_MISSILE )//missile { //FIX: NEVER do or take impact damage from a missile... noDamage = qtrue; if ( (hitEnt->s.eFlags&EF_JETPACK_ACTIVE)//vehicle missile && ((gentity_t *)hitEnt)->r.ownerNum < MAX_CLIENTS )//valid client owner {//I ran into a missile and died because of the impact, give credit to the missile's owner (PROBLEM: might this ever accidently give improper credit to client 0?) /* if ( ((gentity_t *)hitEnt)->r.ownerNum == pEnt->s.number ) {//hit our own missile? Don't damage ourselves or it... (so we don't kill ourselves!) if it hits *us*, then fine, but not here noDamage = qtrue; } */ killer = &g_entities[((gentity_t *)hitEnt)->r.ownerNum]; } } if ( !noDamage ) { G_Damage( (gentity_t *)pEnt, ((gentity_t*)hitEnt), killer!=NULL?killer:((gentity_t *)hitEnt), NULL, pm->ps->origin, magnitude*5, DAMAGE_NO_ARMOR, (hitEnt->s.NPC_class==CLASS_VEHICLE?MOD_COLLISION:MOD_FALLING) );//FIXME: MOD_IMPACT } if (pSelfVeh->m_pVehicleInfo->surfDestruction) { G_FlyVehicleSurfaceDestruction((gentity_t *)pEnt, trace, magnitude, forceSurfDestruction ); } pSelfVeh->m_ulFlags |= VEH_CRASHING; } if (hitEnt && hitEnt->inuse && hitEnt->takedamage) { //damage this guy because we hit him float pmult = 1.0f; int finalD; gentity_t *attackEnt; if ( (hitEnt->s.eType == ET_PLAYER && hitEnt->s.number < MAX_CLIENTS) || (hitEnt->s.eType == ET_NPC && hitEnt->s.NPC_class != CLASS_VEHICLE) ) { //probably a humanoid, or something if (pSelfVeh->m_pVehicleInfo->type == VH_FIGHTER) { //player die good.. if me fighter pmult = 2000.0f; } else { pmult = 40.0f; } if (hitEnt->client && BG_KnockDownable(&hitEnt->client->ps) && G_CanBeEnemy((gentity_t *)pEnt, hitEnt)) { //smash! if (hitEnt->client->ps.forceHandExtend != HANDEXTEND_KNOCKDOWN) { hitEnt->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN; hitEnt->client->ps.forceHandExtendTime = pm->cmd.serverTime + 1100; hitEnt->client->ps.forceDodgeAnim = 0; //this toggles between 1 and 0, when it's 1 we should play the get up anim } hitEnt->client->ps.otherKiller = pEnt->s.number; hitEnt->client->ps.otherKillerTime = pm->cmd.serverTime + 5000; hitEnt->client->ps.otherKillerDebounceTime = pm->cmd.serverTime + 100; hitEnt->client->otherKillerMOD = MOD_COLLISION; hitEnt->client->otherKillerVehWeapon = 0; hitEnt->client->otherKillerWeaponType = WP_NONE; //add my velocity into his to force him along in the correct direction from impact VectorAdd(hitEnt->client->ps.velocity, pm->ps->velocity, hitEnt->client->ps.velocity); //upward thrust hitEnt->client->ps.velocity[2] += 200.0f; } } if (pSelfVeh->m_pPilot) { attackEnt = (gentity_t *)pSelfVeh->m_pPilot; } else { attackEnt = (gentity_t *)pEnt; } finalD = magnitude*pmult; if (finalD < 1) { finalD = 1; } if ( !noDamage ) { G_Damage( hitEnt, attackEnt, attackEnt, NULL, pm->ps->origin, finalD, 0, (hitEnt->s.NPC_class==CLASS_VEHICLE?MOD_COLLISION:MOD_FALLING/*MOD_MELEE*/) );//FIXME: MOD_IMPACT } } #else //this is gonna result in "double effects" for the client doing the prediction. //it doesn't look bad though. could just use predicted events, but I'm too lazy. hitEnt = PM_BGEntForNum(trace->entityNum); if (!hitEnt || hitEnt->s.owner != pEnt->s.number) { //don't hit your own missiles! AngleVectors( pSelfVeh->m_vOrientation, NULL, NULL, vehUp ); pEnt->m_pVehicle->m_iHitDebounce = pm->cmd.serverTime + 200; trap_FX_PlayEffectID( pSelfVeh->m_pVehicleInfo->iImpactFX, pm->ps->origin, vehUp, -1, -1 ); pSelfVeh->m_ulFlags |= VEH_CRASHING; } #endif } } }
void FX_BowcasterHitPlayer( vec3_t origin, vec3_t normal, qboolean humanoid ) { trap_FX_PlayEffectID( cgs.effects.bowcasterImpactEffect, origin, normal ); }
void CGSyscall_FX_PlayEffectID( int id, vec3_t org, vec3_t fwd, int vol, int rad, qboolean isPortal ) { if ( isPortal ) trap_FX_PlayPortalEffectID( id, org, fwd, vol, rad ); else trap_FX_PlayEffectID( id, org, fwd, vol, rad ); }
void FX_RocketHitWall( vec3_t origin, vec3_t normal ) { trap_FX_PlayEffectID( cgs.effects.rocketExplosionEffect, origin, normal, -1, -1 ); }
void FX_RocketHitPlayer( vec3_t origin, vec3_t normal, qboolean humanoid ) { trap_FX_PlayEffectID( cgs.effects.rocketExplosionEffect, origin, normal, -1, -1 ); }
/* ------------------------- FX_BryarHitWall ------------------------- */ void FX_BryarHitWall( vec3_t origin, vec3_t normal ) { trap_FX_PlayEffectID( cgs.effects.bryarWallImpactEffect, origin, normal ); }
void FX_DEMP2_HitWall( vec3_t origin, vec3_t normal ) { trap_FX_PlayEffectID( cgs.effects.demp2WallImpactEffect, origin, normal ); }
void FX_DEMP2_HitPlayer( vec3_t origin, vec3_t normal, qboolean humanoid ) { trap_FX_PlayEffectID( cgs.effects.demp2FleshImpactEffect, origin, normal ); }
void FX_BowcasterHitWall( vec3_t origin, vec3_t normal ) { trap_FX_PlayEffectID( cgs.effects.bowcasterImpactEffect, origin, normal ); }
/* ------------------------- FX_ConcussionHitWall ------------------------- */ void FX_ConcussionHitWall( vec3_t origin, vec3_t normal ) { trap_FX_PlayEffectID( cgs.effects.concussionImpactEffect, origin, normal, -1, -1 ); }
/* ------------------------- FX_ConcussionHitPlayer ------------------------- */ void FX_ConcussionHitPlayer( vec3_t origin, vec3_t normal, qboolean humanoid ) { trap_FX_PlayEffectID( cgs.effects.concussionImpactEffect, origin, normal, -1, -1 ); }
/* ------------------------- FX_FlechetteWeaponHitWall ------------------------- */ void FX_FlechetteWeaponHitWall( vec3_t origin, vec3_t normal ) { trap_FX_PlayEffectID( cgs.effects.flechetteWallImpactEffect, origin, normal, -1, -1 ); }
/* ------------------------- FX_BlasterWeaponHitWall ------------------------- */ void FX_BlasterWeaponHitWall( vec3_t origin, vec3_t normal ) { trap_FX_PlayEffectID( cgs.effects.blasterWallImpactEffect, origin, normal ); }
void CG_MiscModelExplosion( vector3 *mins, vector3 *maxs, int size, material_t chunkType ) { int ct = 13; float r; vector3 org, mid, dir; char *effect = NULL, *effect2 = NULL; int eID1, eID2 = 0; int i; VectorAdd( mins, maxs, &mid ); VectorScale( &mid, 0.5f, &mid ); switch( chunkType ) { default: break; case MAT_GLASS: effect = "chunks/glassbreak"; ct = 5; break; case MAT_GLASS_METAL: effect = "chunks/glassbreak"; effect2 = "chunks/metalexplode"; ct = 5; break; case MAT_ELECTRICAL: case MAT_ELEC_METAL: effect = "chunks/sparkexplode"; ct = 5; break; case MAT_METAL: case MAT_METAL2: case MAT_METAL3: case MAT_CRATE1: case MAT_CRATE2: effect = "chunks/metalexplode"; ct = 2; break; case MAT_GRATE1: effect = "chunks/grateexplode"; ct = 8; break; case MAT_ROPE: ct = 20; effect = "chunks/ropebreak"; break; case MAT_WHITE_METAL: //not sure what this crap is really supposed to be.. case MAT_DRK_STONE: case MAT_LT_STONE: case MAT_GREY_STONE: case MAT_SNOWY_ROCK: switch( size ) { case 2: effect = "chunks/rockbreaklg"; break; case 1: default: effect = "chunks/rockbreakmed"; break; } } if ( !effect ) { return; } ct += 7 * size; // FIXME: real precache .. VERify that these need to be here...don't think they would because the effects should be registered in g_breakable //rww - No they don't.. indexed effects gameside get precached on load clientside, as server objects are setup before client asset load time. //However, we need to index them, so.. eID1 = trap_FX_RegisterEffect( effect ); if ( effect2 && effect2[0] ) { // FIXME: real precache eID2 = trap_FX_RegisterEffect( effect2 ); } // spawn chunk roughly in the bbox of the thing.. for ( i = 0; i < ct; i++ ) { int j; for( j = 0; j < 3; j++ ) { r = random() * 0.8f + 0.1f; org.data[j] = ( r * mins->data[j] + ( 1 - r ) * maxs->data[j] ); } // shoot effect away from center VectorSubtract( &org, &mid, &dir ); VectorNormalize( &dir ); if ( effect2 && effect2[0] && ( rand() & 1 )) trap_FX_PlayEffectID( eID2, &org, &dir, -1, -1 ); else trap_FX_PlayEffectID( eID1, &org, &dir, -1, -1 ); } }
void TurretClientRun(centity_t *ent) { if (!ent->ghoul2) { weaponInfo_t *weaponInfo; trap_G2API_InitGhoul2Model(&ent->ghoul2, CG_ConfigString( CS_MODELS+ent->currentState.modelindex ), 0, 0, 0, 0, 0); if (!ent->ghoul2) { //bad return; } ent->torsoBolt = trap_G2API_AddBolt( ent->ghoul2, 0, "*flash02" ); trap_G2API_SetBoneAngles( ent->ghoul2, 0, "bone_hinge", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_Y, POSITIVE_Z, POSITIVE_X, NULL, 100, cg.time ); trap_G2API_SetBoneAngles( ent->ghoul2, 0, "bone_gback", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_Y, POSITIVE_Z, POSITIVE_X, NULL, 100, cg.time ); trap_G2API_SetBoneAngles( ent->ghoul2, 0, "bone_barrel", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_Y, POSITIVE_Z, POSITIVE_X, NULL, 100, cg.time ); trap_G2API_SetBoneAnim( ent->ghoul2, 0, "model_root", 0, 11, BONE_ANIM_OVERRIDE_FREEZE, 0.8f, cg.time, 0, 0 ); ent->turAngles[ROLL] = 0; ent->turAngles[PITCH] = 90; ent->turAngles[YAW] = 0; weaponInfo = &cg_weapons[WP_TURRET]; if ( !weaponInfo->registered ) { CG_RegisterWeapon(WP_TURRET); } } if (ent->currentState.fireflag == 2) { //I'm about to blow if (ent->turAngles) { trap_G2API_SetBoneAngles( ent->ghoul2, 0, "bone_hinge", ent->turAngles, BONE_ANGLES_REPLACE, NEGATIVE_Y, NEGATIVE_Z, NEGATIVE_X, NULL, 100, cg.time ); } return; } else if (ent->currentState.fireflag && ent->bolt4 != ent->currentState.fireflag) { vec3_t muzzleOrg, muzzleDir; mdxaBone_t boltMatrix; trap_G2API_GetBoltMatrix(ent->ghoul2, 0, ent->torsoBolt, &boltMatrix, /*ent->lerpAngles*/vec3_origin, ent->lerpOrigin, cg.time, cgs.gameModels, ent->modelScale); BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, muzzleOrg); BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_X, muzzleDir); trap_FX_PlayEffectID(cgs.effects.mTurretMuzzleFlash, muzzleOrg, muzzleDir, -1, -1); ent->bolt4 = ent->currentState.fireflag; } else if (!ent->currentState.fireflag) { ent->bolt4 = 0; } if (ent->currentState.bolt2 != ENTITYNUM_NONE) { //turn toward the enemy centity_t *enemy = &cg_entities[ent->currentState.bolt2]; if (enemy) { vec3_t enAng; vec3_t enPos; VectorCopy(enemy->currentState.pos.trBase, enPos); VectorSubtract(enPos, ent->lerpOrigin, enAng); VectorNormalize(enAng); vectoangles(enAng, enAng); enAng[ROLL] = 0; enAng[PITCH] += 90; CreepToPosition(enAng, ent->turAngles); } } else { vec3_t idleAng; float turnAmount; if (ent->turAngles[YAW] > 360) { ent->turAngles[YAW] -= 361; } if (!ent->dustTrailTime) { ent->dustTrailTime = cg.time; } turnAmount = (cg.time-ent->dustTrailTime)*0.03; if (turnAmount > 360) { turnAmount = 360; } idleAng[PITCH] = 90; idleAng[ROLL] = 0; idleAng[YAW] = ent->turAngles[YAW] + turnAmount; ent->dustTrailTime = cg.time; CreepToPosition(idleAng, ent->turAngles); } if (cg.time < ent->frame_minus1_refreshed) { ent->frame_minus1_refreshed = cg.time; return; } ent->frame_minus1_refreshed = cg.time; trap_G2API_SetBoneAngles( ent->ghoul2, 0, "bone_hinge", ent->turAngles, BONE_ANGLES_REPLACE, NEGATIVE_Y, NEGATIVE_Z, NEGATIVE_X, NULL, 100, cg.time ); }
// This effect is not generic because of possible enhancements void FX_ForceDrained(vec3_t origin, vec3_t dir) { VectorScale(dir, -1.0, dir); trap_FX_PlayEffectID(cgs.effects.forceDrained, origin, dir); }