void G_GetBoltPosition( gentity_t *self, int boltIndex, vec3_t pos, int modelIndex ) { mdxaBone_t boltMatrix; vec3_t result, angles; if (!self || !self->inuse) { return; } if (self->client) { //clients don't actually even keep r.currentAngles maintained VectorSet(angles, 0, self->client->ps.viewangles[YAW], 0); } else { VectorSet(angles, 0, self->r.currentAngles[YAW], 0); } if ( /*!self || ...haha (sorry, i'm tired)*/ !self->ghoul2 ) { return; } trap_G2API_GetBoltMatrix( self->ghoul2, modelIndex, boltIndex, &boltMatrix, angles, self->r.currentOrigin, level.time, NULL, self->modelScale ); if ( pos ) { BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, result ); VectorCopy( result, pos ); } }
//----------------------------------------------------------------- static void GM_CreateExplosion( gentity_t *self, const int boltID, qboolean doSmall ) //doSmall = qfalse { if ( boltID >=0 ) { mdxaBone_t boltMatrix; vec3_t org, dir; trap_G2API_GetBoltMatrix( self->ghoul2, 0, boltID, &boltMatrix, self->r.currentAngles, self->r.currentOrigin, level.time, NULL, self->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, org ); BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_Y, dir ); if ( doSmall ) { G_PlayEffectID( G_EffectIndex("env/small_explode2"), org, dir ); } else { G_PlayEffectID( G_EffectIndex("env/med_explode2"), org, dir ); } } }
/* ------------------------- Mark1Dead_FireBlaster - Shoot the left weapon, the multi-blaster ------------------------- */ void Mark1Dead_FireBlaster (void) { vec3_t muzzle1,muzzle_dir; gentity_t *missile; mdxaBone_t boltMatrix; int bolt; bolt = trap_G2API_AddBolt(NPC->ghoul2, 0, "*flash1"); trap_G2API_GetBoltMatrix( NPC->ghoul2, 0, bolt, &boltMatrix, NPC->r.currentAngles, NPC->r.currentOrigin, level.time, NULL, NPC->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, muzzle1 ); BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_Y, muzzle_dir ); G_PlayEffectID( G_EffectIndex("bryar/muzzle_flash"), muzzle1, muzzle_dir ); missile = CreateMissile( muzzle1, muzzle_dir, 1600, 10000, NPC, qfalse ); G_Sound( NPC, CHAN_AUTO, G_SoundIndex("sound/chars/mark1/misc/mark1_fire")); missile->classname = "bryar_proj"; missile->s.weapon = WP_BRYAR_PISTOL; missile->damage = 1; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_BRYAR_PISTOL; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; }
/* ------------------------- ImperialProbe_FireBlaster ------------------------- */ void ImperialProbe_FireBlaster(void) { vec3_t muzzle1,enemy_org1,delta1,angleToEnemy1; static vec3_t forward, vright, up; // static vec3_t muzzle; int genBolt1; gentity_t *missile; mdxaBone_t boltMatrix; genBolt1 = trap_G2API_AddBolt(NPC->ghoul2, 0, "*flash"); //FIXME: use {0, NPC->client->ps.legsYaw, 0} trap_G2API_GetBoltMatrix( NPC->ghoul2, 0, genBolt1, &boltMatrix, NPC->r.currentAngles, NPC->r.currentOrigin, level.time, NULL, NPC->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, muzzle1 ); G_PlayEffectID( G_EffectIndex("bryar/muzzle_flash"), muzzle1, vec3_origin ); G_Sound( NPC, CHAN_AUTO, G_SoundIndex( "sound/chars/probe/misc/fire" )); if (NPC->health) { CalcEntitySpot( NPC->enemy, SPOT_CHEST, enemy_org1 ); enemy_org1[0]+= Q_irand(0,10); enemy_org1[1]+= Q_irand(0,10); VectorSubtract (enemy_org1, muzzle1, delta1); vectoangles ( delta1, angleToEnemy1 ); AngleVectors (angleToEnemy1, forward, vright, up); } else { AngleVectors (NPC->r.currentAngles, forward, vright, up); } missile = CreateMissile( muzzle1, forward, 1600, 10000, NPC, qfalse ); missile->classname = "bryar_proj"; missile->s.weapon = WP_BRYAR_PISTOL; if ( g_spskill.integer <= 1 ) { missile->damage = 5; } else { missile->damage = 10; } missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_UNKNOWN; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; }
//----------------------------------------------------- void turretG2_head_think( gentity_t *self ) //----------------------------------------------------- { // if it's time to fire and we have an enemy, then gun 'em down! pushDebounce time controls next fire time if ( self->enemy && self->setTime < level.time && self->attackDebounceTime < level.time ) { vec3_t fwd, org; mdxaBone_t boltMatrix; // set up our next fire time self->setTime = level.time + self->wait; // Getting the flash bolt here trap_G2API_GetBoltMatrix( self->ghoul2, 0, (self->alt_fire?self->genericValue12:self->genericValue11), &boltMatrix, self->r.currentAngles, self->r.currentOrigin, level.time, NULL, self->modelScale ); if ( (self->spawnflags&SPF_TURRETG2_TURBO) ) { self->alt_fire = !self->alt_fire; } BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, org ); //BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_Y, fwd ); if ( (self->spawnflags&SPF_TURRETG2_TURBO) ) { BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_X, fwd ); } else { BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_X, fwd ); } VectorMA( org, START_DIS, fwd, org ); turretG2_fire( self, org, fwd ); self->fly_sound_debounce_time = level.time;//used as lastShotTime } }
qboolean CG_SnapRefEntToBone(centity_t *cent, refEntity_t *refEnt, const char *bone_name) { centity_t *cl = cent; mdxaBone_t matrix; vec3_t boltOrg, holsterAngles, boltAng; //vec3_t out_axis[3]; int getBolt = -1; if (!cl->ghoul2) { assert(0); return qfalse; } if (cent->currentState.clientNum == cg.predictedPlayerState.clientNum && !cg.renderingThirdPerson) { //If in first person and you have it then render the thing spinning around on your hud. return qfalse; } getBolt = trap_G2API_AddBolt(cl->ghoul2, 0, bone_name); VectorCopy(cl->lerpAngles, holsterAngles); holsterAngles[PITCH] = 0; holsterAngles[ROLL] = 0; trap_G2API_GetBoltMatrix(cl->ghoul2, 0, getBolt, &matrix, holsterAngles /*cl->lerpAngles*/, cl->lerpOrigin, cg.time, cgs.gameModels, cl->modelScale); BG_GiveMeVectorFromMatrix(&matrix, ORIGIN, boltOrg); BG_GiveMeVectorFromMatrix(&matrix, NEGATIVE_Y, boltAng); vectoangles(boltAng, boltAng); //boltAng[PITCH] = boltAng[ROLL] = 0; //BG_GiveMeVectorFromMatrix(&matrix, ORIGIN, boltOrg); //BG_GiveMeVectorFromMatrix( &matrix, NEGATIVE_Y, refEnt->axis[0] );//out_axis[0] ); //BG_GiveMeVectorFromMatrix( &matrix, POSITIVE_X, refEnt->axis[1] );//out_axis[1] ); //BG_GiveMeVectorFromMatrix( &matrix, POSITIVE_Z, refEnt->axis[2] );//out_axis[2] ); VectorCopy(boltOrg, refEnt->origin); //VectorCopy(cl->lerpAngles, refEnt->angles); VectorCopy(boltAng, refEnt->angles); return qtrue; }
/* ------------------------- Mark1_FireRocket ------------------------- */ void Mark1_FireRocket(void) { mdxaBone_t boltMatrix; vec3_t muzzle1,enemy_org1,delta1,angleToEnemy1; static vec3_t forward, vright, up; int bolt = trap_G2API_AddBolt(NPC->ghoul2, 0, "*flash5"); gentity_t *missile; int damage = 50; trap_G2API_GetBoltMatrix( NPC->ghoul2, 0, bolt, &boltMatrix, NPC->r.currentAngles, NPC->r.currentOrigin, level.time, NULL, NPC->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, muzzle1 ); // G_PlayEffect( "blaster/muzzle_flash", muzzle1 ); CalcEntitySpot( NPC->enemy, SPOT_HEAD, enemy_org1 ); VectorSubtract (enemy_org1, muzzle1, delta1); vectoangles ( delta1, angleToEnemy1 ); AngleVectors (angleToEnemy1, forward, vright, up); G_Sound( NPC, CHAN_AUTO, G_SoundIndex("sound/chars/mark1/misc/mark1_fire" )); missile = CreateMissile( muzzle1, forward, BOWCASTER_VELOCITY, 10000, NPC, qfalse ); missile->classname = "bowcaster_proj"; missile->s.weapon = WP_BOWCASTER; VectorSet( missile->r.maxs, BOWCASTER_SIZE, BOWCASTER_SIZE, BOWCASTER_SIZE ); VectorScale( missile->r.maxs, -1, missile->r.mins ); missile->damage = damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_ROCKET; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missile->splashDamage = BOWCASTER_SPLASH_DAMAGE; missile->splashRadius = BOWCASTER_SPLASH_RADIUS; // we don't want it to bounce missile->bounceCount = 0; }
static void ATST_PlayEffect( gentity_t *self, const int boltID, const char *fx ) { if ( boltID >=0 && fx && fx[0] ) { mdxaBone_t boltMatrix; vec3_t org, dir; trap_G2API_GetBoltMatrix( self->ghoul2, 0, boltID, &boltMatrix, self->r.currentAngles, self->r.currentOrigin, level.time, NULL, self->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, org ); BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_Y, dir ); G_PlayEffectID( G_EffectIndex((char *)fx), org, dir ); } }
/* ------------------------- Mark2_FireBlaster ------------------------- */ void Mark2_FireBlaster(qboolean advance) { vec3_t muzzle1,enemy_org1,delta1,angleToEnemy1; static vec3_t forward, vright, up; static vec3_t muzzle; gentity_t *missile; mdxaBone_t boltMatrix; int bolt = trap_G2API_AddBolt(NPC->ghoul2, 0, "*flash"); trap_G2API_GetBoltMatrix( NPC->ghoul2, 0, bolt, &boltMatrix, NPC->r.currentAngles, NPC->r.currentOrigin, level.time, NULL, NPC->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, muzzle1 ); if (NPC->health) { CalcEntitySpot( NPC->enemy, SPOT_HEAD, enemy_org1 ); VectorSubtract (enemy_org1, muzzle1, delta1); vectoangles ( delta1, angleToEnemy1 ); AngleVectors (angleToEnemy1, forward, vright, up); } else { AngleVectors (NPC->r.currentAngles, forward, vright, up); } G_PlayEffectID( G_EffectIndex("bryar/muzzle_flash"), muzzle1, forward ); G_Sound( NPC, CHAN_AUTO, G_SoundIndex("sound/chars/mark2/misc/mark2_fire")); missile = CreateMissile( muzzle1, forward, 1600, 10000, NPC, qfalse ); missile->classname = "bryar_proj"; missile->s.weapon = WP_BRYAR_PISTOL; missile->damage = 1; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_BRYAR_PISTOL; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; }
/* ------------------------- Mark1Dead_FireRocket - Shoot the left weapon, the multi-blaster ------------------------- */ void Mark1Dead_FireRocket (void) { mdxaBone_t boltMatrix; vec3_t muzzle1,muzzle_dir; gentity_t *missile; int damage = 50; int bolt = trap_G2API_AddBolt(NPC->ghoul2, 0, "*flash5"); trap_G2API_GetBoltMatrix( NPC->ghoul2, 0, bolt, &boltMatrix, NPC->r.currentAngles, NPC->r.currentOrigin, level.time, NULL, NPC->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, muzzle1 ); BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_Y, muzzle_dir ); G_PlayEffectID( G_EffectIndex("bryar/muzzle_flash"), muzzle1, muzzle_dir ); G_Sound( NPC, CHAN_AUTO, G_SoundIndex("sound/chars/mark1/misc/mark1_fire")); missile = CreateMissile( muzzle1, muzzle_dir, BOWCASTER_VELOCITY, 10000, NPC, qfalse ); missile->classname = "bowcaster_proj"; missile->s.weapon = WP_BOWCASTER; VectorSet( missile->r.maxs, BOWCASTER_SIZE, BOWCASTER_SIZE, BOWCASTER_SIZE ); VectorScale( missile->r.maxs, -1, missile->r.mins ); missile->damage = damage; missile->dflags = DAMAGE_DEATH_KNOCKBACK; //missile->methodOfDeath = MOD_ENERGY; missile->methodOfDeath = MOD_ROCKET; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; missile->splashDamage = BOWCASTER_SPLASH_DAMAGE; missile->splashRadius = BOWCASTER_SPLASH_RADIUS; // we don't want it to bounce missile->bounceCount = 0; }
/* ------------------------- NPC_Mark1_Part_Explode ------------------------- */ void NPC_Mark1_Part_Explode( gentity_t *self, int bolt ) { if ( bolt >=0 ) { mdxaBone_t boltMatrix; vec3_t org, dir; trap_G2API_GetBoltMatrix( self->ghoul2, 0, bolt, &boltMatrix, self->r.currentAngles, self->r.currentOrigin, level.time, NULL, self->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, org ); BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_Y, dir ); G_PlayEffectID( G_EffectIndex("env/med_explode2"), org, dir ); G_PlayEffectID( G_EffectIndex("blaster/smoke_bolton"), org, dir ); } }
qboolean strap_G2API_GetBoltMatrix(void *ghoul2, const int modelIndex, const int boltIndex, mdxaBone_t *matrix, const vec3_t angles, const vec3_t position, const int frameNum, qhandle_t *modelList, vec3_t scale) { return trap_G2API_GetBoltMatrix(ghoul2, modelIndex, boltIndex, matrix, angles, position, frameNum, modelList, scale); }
//MP RULE - ALL PROCESSMOVECOMMANDS FUNCTIONS MUST BE BG-COMPATIBLE!!! //If you really need to violate this rule for SP, then use ifdefs. //By BG-compatible, I mean no use of game-specific data - ONLY use //stuff available in the MP bgEntity (in SP, the bgEntity is #defined //as a gentity, but the MP-compatible access restrictions are based //on the bgEntity structure in the MP codebase) -rww // ProcessMoveCommands the Vehicle. static void ProcessMoveCommands( Vehicle_t *pVeh ) { /************************************************************************************/ /* BEGIN Here is where we move the vehicle (forward or back or whatever). BEGIN */ /************************************************************************************/ //Client sets ucmds and such for speed alterations float speedInc, speedIdleDec, speedIdle, speedIdleAccel, speedMin, speedMax; playerState_t *parentPS; playerState_t *pilotPS = NULL; int curTime; #ifdef _JK2MP parentPS = pVeh->m_pParentEntity->playerState; if (pVeh->m_pPilot) { pilotPS = pVeh->m_pPilot->playerState; } #else parentPS = &pVeh->m_pParentEntity->client->ps; if (pVeh->m_pPilot) { pilotPS = &pVeh->m_pPilot->client->ps; } #endif // If we're flying, make us accelerate at 40% (about half) acceleration rate, and restore the pitch // to origin (straight) position (at 5% increments). if ( pVeh->m_ulFlags & VEH_FLYING ) { speedInc = pVeh->m_pVehicleInfo->acceleration * pVeh->m_fTimeModifier * 0.4f; } #ifdef _JK2MP else if ( !parentPS->m_iVehicleNum ) #else else if ( !pVeh->m_pVehicleInfo->Inhabited( pVeh ) ) #endif {//drifts to a stop speedInc = 0; //pVeh->m_ucmd.forwardmove = 127; } else { speedInc = pVeh->m_pVehicleInfo->acceleration * pVeh->m_fTimeModifier; } speedIdleDec = pVeh->m_pVehicleInfo->decelIdle * pVeh->m_fTimeModifier; #ifndef _JK2MP//SP curTime = level.time; #elif QAGAME//MP GAME curTime = level.time; #elif CGAME//MP CGAME //FIXME: pass in ucmd? Not sure if this is reliable... curTime = pm->cmd.serverTime; #endif if ( (pVeh->m_pPilot /*&& (pilotPS->weapon == WP_NONE || pilotPS->weapon == WP_MELEE )*/ && (pVeh->m_ucmd.buttons & BUTTON_ALT_ATTACK) && pVeh->m_pVehicleInfo->turboSpeed) /*|| (parentPS && parentPS->electrifyTime > curTime && pVeh->m_pVehicleInfo->turboSpeed)*/ //make them go! ) { if ( (parentPS && parentPS->electrifyTime > curTime) || (pVeh->m_pPilot->playerState && (pVeh->m_pPilot->playerState->weapon == WP_MELEE || (pVeh->m_pPilot->playerState->weapon == WP_SABER && BG_SabersOff( pVeh->m_pPilot->playerState ) ))) ) { if ((curTime - pVeh->m_iTurboTime)>pVeh->m_pVehicleInfo->turboRecharge) { pVeh->m_iTurboTime = (curTime + pVeh->m_pVehicleInfo->turboDuration); if (pVeh->m_pVehicleInfo->iTurboStartFX) { int i; for (i=0; (i<MAX_VEHICLE_EXHAUSTS && pVeh->m_iExhaustTag[i]!=-1); i++) { #ifdef QAGAME if (pVeh->m_pParentEntity && pVeh->m_pParentEntity->ghoul2 && pVeh->m_pParentEntity->playerState) { //fine, I'll use a tempent for this, but only because it's played only once at the start of a turbo. vec3_t boltOrg, boltDir; mdxaBone_t boltMatrix; VectorSet(boltDir, 0.0f, pVeh->m_pParentEntity->playerState->viewangles[YAW], 0.0f); trap_G2API_GetBoltMatrix(pVeh->m_pParentEntity->ghoul2, 0, pVeh->m_iExhaustTag[i], &boltMatrix, boltDir, pVeh->m_pParentEntity->playerState->origin, level.time, NULL, pVeh->m_pParentEntity->modelScale); BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, boltOrg); BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, boltDir); G_PlayEffectID(pVeh->m_pVehicleInfo->iTurboStartFX, boltOrg, boltDir); } #endif } } parentPS->speed = pVeh->m_pVehicleInfo->turboSpeed; // Instantly Jump To Turbo Speed } } } // Slide Breaking if (pVeh->m_ulFlags&VEH_SLIDEBREAKING) { if (pVeh->m_ucmd.forwardmove>=0 #ifndef _JK2MP || ((level.time - pVeh->m_pParentEntity->lastMoveTime)>500) #endif ) { pVeh->m_ulFlags &= ~VEH_SLIDEBREAKING; } parentPS->speed = 0; } else if ( (curTime > pVeh->m_iTurboTime) && !(pVeh->m_ulFlags&VEH_FLYING) && pVeh->m_ucmd.forwardmove<0 && fabs(pVeh->m_vOrientation[ROLL])>25.0f) { pVeh->m_ulFlags |= VEH_SLIDEBREAKING; } if ( curTime < pVeh->m_iTurboTime ) { speedMax = pVeh->m_pVehicleInfo->turboSpeed; if (parentPS) { parentPS->eFlags |= EF_JETPACK_ACTIVE; } } else { speedMax = pVeh->m_pVehicleInfo->speedMax; if (parentPS) { parentPS->eFlags &= ~EF_JETPACK_ACTIVE; } } speedIdle = pVeh->m_pVehicleInfo->speedIdle; speedIdleAccel = pVeh->m_pVehicleInfo->accelIdle * pVeh->m_fTimeModifier; speedMin = pVeh->m_pVehicleInfo->speedMin; if ( parentPS->speed || parentPS->groundEntityNum == ENTITYNUM_NONE || pVeh->m_ucmd.forwardmove || pVeh->m_ucmd.upmove > 0 ) { if ( pVeh->m_ucmd.forwardmove > 0 && speedInc ) { parentPS->speed += speedInc; } else if ( pVeh->m_ucmd.forwardmove < 0 ) { if ( parentPS->speed > speedIdle ) { parentPS->speed -= speedInc; } else if ( parentPS->speed > speedMin ) { parentPS->speed -= speedIdleDec; } } // No input, so coast to stop. else if ( parentPS->speed > 0.0f ) { parentPS->speed -= speedIdleDec; if ( parentPS->speed < 0.0f ) { parentPS->speed = 0.0f; } } else if ( parentPS->speed < 0.0f ) { parentPS->speed += speedIdleDec; if ( parentPS->speed > 0.0f ) { parentPS->speed = 0.0f; } } } else { if ( !pVeh->m_pVehicleInfo->strafePerc #ifdef _JK2MP || (0 && pVeh->m_pParentEntity->s.number < MAX_CLIENTS) ) #else || (!g_speederControlScheme->value && !pVeh->m_pParentEntity->s.number) ) #endif {//if in a strafe-capable vehicle, clear strafing unless using alternate control scheme //pVeh->m_ucmd.rightmove = 0; } } if ( parentPS->speed > speedMax ) { parentPS->speed = speedMax; } else if ( parentPS->speed < speedMin ) { parentPS->speed = speedMin; } if (parentPS && parentPS->electrifyTime > curTime) { parentPS->speed *= (pVeh->m_fTimeModifier/60.0f); } /********************************************************************************/ /* END Here is where we move the vehicle (forward or back or whatever). END */ /********************************************************************************/ }
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 ); }
void GCam_FollowUpdate ( void ) { vec3_t center, dir, cameraAngles, vec, focus[MAX_CAMERA_GROUP_SUBJECTS];//No more than 16 subjects in a cameraGroup gentity_t *from = NULL; //centity_t *fromCent = NULL; int num_subjects = 0, i; qboolean focused = qfalse; if ( client_camera.cameraGroup[0] == -1 ) {//follow disabled return; } for( i = 0; i < MAX_CAMERA_GROUP_SUBJECTS; i++ ) { //fromCent = &cg_entities[client_camera.cameraGroup[i]]; from = &g_entities[client_camera.cameraGroup[i]]; if ( !from ) { continue; } focused = qfalse; if ( (from->s.eType == ET_PLAYER || from->s.eType == ET_NPC || from->s.number < MAX_CLIENTS) && client_camera.cameraGroupTag && client_camera.cameraGroupTag[0] ) { int newBolt = trap_G2API_AddBolt( &from->ghoul2, 0, client_camera.cameraGroupTag ); if ( newBolt != -1 ) { mdxaBone_t boltMatrix; vec3_t angle; VectorSet(angle, 0, from->client->ps.viewangles[YAW], 0); trap_G2API_GetBoltMatrix( &from->ghoul2, 0, newBolt, &boltMatrix, angle, from->client->ps.origin, level.time, NULL, from->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, focus[num_subjects] ); focused = qtrue; } } if ( !focused ) { VectorCopy(from->r.currentOrigin, focus[num_subjects]); if ( from->s.eType == ET_PLAYER || from->s.eType == ET_NPC || from->s.number < MAX_CLIENTS ) {//Track to their eyes - FIXME: maybe go off a tag? focus[num_subjects][2] += from->client->ps.viewheight; } } if ( client_camera.cameraGroupZOfs ) { focus[num_subjects][2] += client_camera.cameraGroupZOfs; } num_subjects++; } if ( !num_subjects ) // Bad cameragroup { #ifndef FINAL_BUILD G_Printf(S_COLOR_RED"ERROR: Camera Focus unable to locate cameragroup: %s\n", client_camera.cameraGroup); #endif return; } //Now average all points VectorCopy( focus[0], center ); for( i = 1; i < num_subjects; i++ ) { VectorAdd( focus[i], center, center ); } VectorScale( center, 1.0f/((float)num_subjects), center ); //Need to set a speed to keep a distance from //the subject- fixme: only do this if have a distance //set VectorSubtract( client_camera.subjectPos, center, vec ); client_camera.subjectSpeed = VectorLengthSquared( vec ) * 100.0f / g_TimeSinceLastFrame; VectorCopy( center, client_camera.subjectPos ); VectorSubtract( center, camerapos, dir );//can't use client_camera.origin because it's not updated until the end of the move. //Get desired angle vectoangles(dir, cameraAngles); if ( client_camera.followInitLerp ) {//Lerping float frac = g_TimeSinceLastFrame/100.0f * client_camera.followSpeed/100.f; for( i = 0; i < 3; i++ ) { cameraAngles[i] = AngleNormalize180( cameraAngles[i] ); cameraAngles[i] = AngleNormalize180( client_camera.angles[i] + frac * AngleNormalize180(cameraAngles[i] - client_camera.angles[i]) ); cameraAngles[i] = AngleNormalize180( cameraAngles[i] ); } } else {//Snapping, should do this first time if follow_lerp_to_start_duration is zero //will lerp from this point on client_camera.followInitLerp = qtrue; for( i = 0; i < 3; i++ ) {//normalize so that when we start lerping, it doesn't freak out cameraAngles[i] = AngleNormalize180( cameraAngles[i] ); } //So tracker doesn't move right away thinking the first angle change //is the subject moving... FIXME: shouldn't set this until lerp done OR snapped? client_camera.subjectSpeed = 0; } VectorCopy( cameraAngles, client_camera.angles ); }
void UI_SaberDrawBlade( itemDef_t *item, char *saberName, int saberModel, saberType_t saberType, vec3_t origin, vec3_t angles, int bladeNum ) { char bladeColorString[MAX_QPATH]; saber_colors_t bladeColor; float bladeLength,bladeRadius; vec3_t bladeOrigin={0}; vec3_t axis[3]={0}; // vec3_t angles={0}; mdxaBone_t boltMatrix; qboolean tagHack = qfalse; char *tagName; int bolt; float scale; //[RGBSabers] int snum; //[/RGBSabers] if ( (item->flags&ITF_ISSABER) && saberModel < 2 ) { //[RGBSabers] snum = 0; trap_Cvar_VariableStringBuffer("ui_saber_color", bladeColorString, sizeof(bladeColorString) ); } else//if ( item->flags&ITF_ISSABER2 ) - presumed { snum = 1; //[/RGBSabers] trap_Cvar_VariableStringBuffer("ui_saber2_color", bladeColorString, sizeof(bladeColorString) ); } if ( !trap_G2API_HasGhoul2ModelOnIndex(&(item->ghoul2),saberModel) ) {//invalid index! return; } bladeColor = TranslateSaberColor( bladeColorString ); bladeLength = UI_SaberBladeLengthForSaber( saberName, bladeNum ); bladeRadius = UI_SaberBladeRadiusForSaber( saberName, bladeNum ); tagName = va( "*blade%d", bladeNum+1 ); bolt = trap_G2API_AddBolt( item->ghoul2,saberModel, tagName ); if ( bolt == -1 ) { tagHack = qtrue; //hmm, just fall back to the most basic tag (this will also make it work with pre-JKA saber models bolt = trap_G2API_AddBolt( item->ghoul2,saberModel, "*flash" ); if ( bolt == -1 ) {//no tag_flash either?!! bolt = 0; } } // angles[PITCH] = curYaw; // angles[ROLL] = 0; trap_G2API_GetBoltMatrix( item->ghoul2, saberModel, bolt, &boltMatrix, angles, origin, uiInfo.uiDC.realTime, NULL, vec3_origin );//NULL was cgs.model_draw // work the matrix axis stuff into the original axis and origins used. BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, bladeOrigin); BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_Y, axis[0]);//front (was NEGATIVE_Y, but the md3->glm exporter screws up this tag somethin' awful) // ...changed this back to NEGATIVE_Y BG_GiveMeVectorFromMatrix(&boltMatrix, NEGATIVE_X, axis[1]);//right ... and changed this to NEGATIVE_X BG_GiveMeVectorFromMatrix(&boltMatrix, POSITIVE_Z, axis[2]);//up // Where do I get scale from? // scale = DC->xscale; scale = 1.0f; if ( tagHack ) { switch ( saberType ) { case SABER_SINGLE: VectorMA( bladeOrigin, scale, axis[0], bladeOrigin ); break; case SABER_DAGGER: case SABER_LANCE: break; case SABER_STAFF: if ( bladeNum == 0 ) { VectorMA( bladeOrigin, 12*scale, axis[0], bladeOrigin ); } if ( bladeNum == 1 ) { VectorScale( axis[0], -1, axis[0] ); VectorMA( bladeOrigin, 12*scale, axis[0], bladeOrigin ); } break; case SABER_BROAD: if ( bladeNum == 0 ) { VectorMA( bladeOrigin, -1*scale, axis[1], bladeOrigin ); } else if ( bladeNum == 1 ) { VectorMA( bladeOrigin, 1*scale, axis[1], bladeOrigin ); } break; case SABER_PRONG: if ( bladeNum == 0 ) { VectorMA( bladeOrigin, -3*scale, axis[1], bladeOrigin ); } else if ( bladeNum == 1 ) { VectorMA( bladeOrigin, 3*scale, axis[1], bladeOrigin ); } break; case SABER_ARC: VectorSubtract( axis[1], axis[2], axis[1] ); VectorNormalize( axis[1] ); switch ( bladeNum ) { case 0: VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin ); VectorScale( axis[0], 0.75f, axis[0] ); VectorScale( axis[1], 0.25f, axis[1] ); VectorAdd( axis[0], axis[1], axis[0] ); break; case 1: VectorScale( axis[0], 0.25f, axis[0] ); VectorScale( axis[1], 0.75f, axis[1] ); VectorAdd( axis[0], axis[1], axis[0] ); break; case 2: VectorMA( bladeOrigin, -8*scale, axis[0], bladeOrigin ); VectorScale( axis[0], -0.25f, axis[0] ); VectorScale( axis[1], 0.75f, axis[1] ); VectorAdd( axis[0], axis[1], axis[0] ); break; case 3: VectorMA( bladeOrigin, -16*scale, axis[0], bladeOrigin ); VectorScale( axis[0], -0.75f, axis[0] ); VectorScale( axis[1], 0.25f, axis[1] ); VectorAdd( axis[0], axis[1], axis[0] ); break; } break; case SABER_SAI: if ( bladeNum == 1 ) { VectorMA( bladeOrigin, -3*scale, axis[1], bladeOrigin ); } else if ( bladeNum == 2 ) { VectorMA( bladeOrigin, 3*scale, axis[1], bladeOrigin ); } break; case SABER_CLAW: switch ( bladeNum ) { case 0: VectorMA( bladeOrigin, 2*scale, axis[0], bladeOrigin ); VectorMA( bladeOrigin, 2*scale, axis[2], bladeOrigin ); break; case 1: VectorMA( bladeOrigin, 2*scale, axis[0], bladeOrigin ); VectorMA( bladeOrigin, 2*scale, axis[2], bladeOrigin ); VectorMA( bladeOrigin, 2*scale, axis[1], bladeOrigin ); break; case 2: VectorMA( bladeOrigin, 2*scale, axis[0], bladeOrigin ); VectorMA( bladeOrigin, 2*scale, axis[2], bladeOrigin ); VectorMA( bladeOrigin, -2*scale, axis[1], bladeOrigin ); break; } break; case SABER_STAR: switch ( bladeNum ) { case 0: VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin ); break; case 1: VectorScale( axis[0], 0.33f, axis[0] ); VectorScale( axis[2], 0.67f, axis[2] ); VectorAdd( axis[0], axis[2], axis[0] ); VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin ); break; case 2: VectorScale( axis[0], -0.33f, axis[0] ); VectorScale( axis[2], 0.67f, axis[2] ); VectorAdd( axis[0], axis[2], axis[0] ); VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin ); break; case 3: VectorScale( axis[0], -1, axis[0] ); VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin ); break; case 4: VectorScale( axis[0], -0.33f, axis[0] ); VectorScale( axis[2], -0.67f, axis[2] ); VectorAdd( axis[0], axis[2], axis[0] ); VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin ); break; case 5: VectorScale( axis[0], 0.33f, axis[0] ); VectorScale( axis[2], -0.67f, axis[2] ); VectorAdd( axis[0], axis[2], axis[0] ); VectorMA( bladeOrigin, 8*scale, axis[0], bladeOrigin ); break; } break; case SABER_TRIDENT: switch ( bladeNum ) { case 0: VectorMA( bladeOrigin, 24*scale, axis[0], bladeOrigin ); break; case 1: VectorMA( bladeOrigin, -6*scale, axis[1], bladeOrigin ); VectorMA( bladeOrigin, 24*scale, axis[0], bladeOrigin ); break; case 2: VectorMA( bladeOrigin, 6*scale, axis[1], bladeOrigin ); VectorMA( bladeOrigin, 24*scale, axis[0], bladeOrigin ); break; case 3: VectorMA( bladeOrigin, -32*scale, axis[0], bladeOrigin ); VectorScale( axis[0], -1, axis[0] ); break; } break; case SABER_SITH_SWORD: //no blade break; } } if ( saberType == SABER_SITH_SWORD ) {//draw no blade return; } //[RGBSabers] UI_DoSaber( bladeOrigin, axis[0], bladeLength, bladeLength, bladeRadius, bladeColor, snum ); //[/RGBSabers] }
void G_GrabSomeMofos(gentity_t *self) { renderInfo_t *ri = &self->client->renderInfo; mdxaBone_t boltMatrix; vec3_t flatAng; vec3_t pos; vec3_t grabMins, grabMaxs; trace_t trace; if (!self->ghoul2 || ri->handRBolt == -1) { //no good return; } VectorSet(flatAng, 0.0f, self->client->ps.viewangles[1], 0.0f); trap_G2API_GetBoltMatrix(self->ghoul2, 0, ri->handRBolt, &boltMatrix, flatAng, self->client->ps.origin, level.time, NULL, self->modelScale); BG_GiveMeVectorFromMatrix(&boltMatrix, ORIGIN, pos); VectorSet(grabMins, -4.0f, -4.0f, -4.0f); VectorSet(grabMaxs, 4.0f, 4.0f, 4.0f); //trace from my origin to my hand, if we hit anyone then get 'em trap_G2Trace( &trace, self->client->ps.origin, grabMins, grabMaxs, pos, self->s.number, MASK_SHOT, G2TRFLAG_DOGHOULTRACE|G2TRFLAG_GETSURFINDEX|G2TRFLAG_THICK|G2TRFLAG_HITCORPSES, g_g2TraceLod.integer ); if (trace.fraction != 1.0f && trace.entityNum < ENTITYNUM_WORLD) { gentity_t *grabbed = &g_entities[trace.entityNum]; if (grabbed->inuse && (grabbed->s.eType == ET_PLAYER || grabbed->s.eType == ET_NPC) && grabbed->client && grabbed->health > 0 && G_CanBeEnemy(self, grabbed) && G_PrettyCloseIGuess(grabbed->client->ps.origin[2], self->client->ps.origin[2], 4.0f) && (!BG_InGrappleMove(grabbed->client->ps.torsoAnim) || grabbed->client->ps.torsoAnim == BOTH_KYLE_GRAB) && (!BG_InGrappleMove(grabbed->client->ps.legsAnim) || grabbed->client->ps.legsAnim == BOTH_KYLE_GRAB)) { //grabbed an active player/npc int tortureAnim = -1; int correspondingAnim = -1; if (self->client->pers.cmd.forwardmove > 0) { //punch grab tortureAnim = BOTH_KYLE_PA_1; correspondingAnim = BOTH_PLAYER_PA_1; } else if (self->client->pers.cmd.forwardmove < 0) { //knee-throw tortureAnim = BOTH_KYLE_PA_2; correspondingAnim = BOTH_PLAYER_PA_2; } if (tortureAnim == -1 || correspondingAnim == -1) { if (self->client->ps.torsoTimer < 300 && !self->client->grappleState) { //you failed to grab anyone, play the "failed to grab" anim G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, BOTH_KYLE_MISS, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0); if (self->client->ps.torsoAnim == BOTH_KYLE_MISS) { //providing the anim set succeeded.. self->client->ps.weaponTime = self->client->ps.torsoTimer; } } return; } self->client->grappleIndex = grabbed->s.number; self->client->grappleState = 1; grabbed->client->grappleIndex = self->s.number; grabbed->client->grappleState = 20; //time to crack some heads G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, tortureAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0); if (self->client->ps.torsoAnim == tortureAnim) { //providing the anim set succeeded.. self->client->ps.weaponTime = self->client->ps.torsoTimer; } G_SetAnim(grabbed, &grabbed->client->pers.cmd, SETANIM_BOTH, correspondingAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0); if (grabbed->client->ps.torsoAnim == correspondingAnim) { //providing the anim set succeeded.. if (grabbed->client->ps.weapon == WP_SABER) { //turn it off if (!grabbed->client->ps.saberHolstered) { grabbed->client->ps.saberHolstered = 2; if (grabbed->client->saber[0].soundOff) { G_Sound(grabbed, CHAN_AUTO, grabbed->client->saber[0].soundOff); } if (grabbed->client->saber[1].soundOff && grabbed->client->saber[1].model[0]) { G_Sound(grabbed, CHAN_AUTO, grabbed->client->saber[1].soundOff); } } } if (grabbed->client->ps.torsoTimer < self->client->ps.torsoTimer) { //make sure they stay in the anim at least as long as the grabber grabbed->client->ps.torsoTimer = self->client->ps.torsoTimer; } grabbed->client->ps.weaponTime = grabbed->client->ps.torsoTimer; } } } if (self->client->ps.torsoTimer < 300 && !self->client->grappleState) { //you failed to grab anyone, play the "failed to grab" anim G_SetAnim(self, &self->client->pers.cmd, SETANIM_BOTH, BOTH_KYLE_MISS, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0); if (self->client->ps.torsoAnim == BOTH_KYLE_MISS) { //providing the anim set succeeded.. self->client->ps.weaponTime = self->client->ps.torsoTimer; } } }
void BG_AttachToRancor( void *ghoul2, float rancYaw, vec3_t rancOrigin, int time, qhandle_t *modelList, vec3_t modelScale, qboolean inMouth, vec3_t out_origin, vec3_t out_angles, vec3_t out_axis[3] ) { mdxaBone_t boltMatrix; int boltIndex; vec3_t rancAngles; vec3_t temp_angles; // Getting the bolt here if ( inMouth ) {//in mouth boltIndex = trap_G2API_AddBolt(ghoul2, 0, "jaw_bone"); } else {//in right hand boltIndex = trap_G2API_AddBolt(ghoul2, 0, "*r_hand"); } VectorSet( rancAngles, 0, rancYaw, 0 ); trap_G2API_GetBoltMatrix( ghoul2, 0, boltIndex, &boltMatrix, rancAngles, rancOrigin, time, modelList, modelScale ); // Storing ent position, bolt position, and bolt axis if ( out_origin ) { BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, out_origin ); } if ( out_axis ) { if ( inMouth ) {//in mouth BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_Z, out_axis[0] ); BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_Y, out_axis[1] ); BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_X, out_axis[2] ); } else {//in hand BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_Y, out_axis[0] ); BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_X, out_axis[1] ); BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_Z, out_axis[2] ); } //FIXME: this is messing up our axis and turning us inside-out? if ( out_angles ) { vectoangles( out_axis[0], out_angles ); vectoangles( out_axis[2], temp_angles ); out_angles[ROLL] = -temp_angles[PITCH]; } } else if ( out_angles ) { vec3_t temp_axis[3]; if ( inMouth ) {//in mouth BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_Z, temp_axis[0] ); BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_X, temp_axis[2] ); } else {//in hand BG_GiveMeVectorFromMatrix( &boltMatrix, NEGATIVE_Y, temp_axis[0] ); BG_GiveMeVectorFromMatrix( &boltMatrix, POSITIVE_Z, temp_axis[2] ); } //FIXME: this is messing up our axis and turning us inside-out? vectoangles( temp_axis[0], out_angles ); vectoangles( temp_axis[2], temp_angles ); out_angles[ROLL] = -temp_angles[PITCH]; } }
//----------------------------------------------------- static void turretG2_aim( gentity_t *self ) //----------------------------------------------------- { vec3_t enemyDir, org, org2; vec3_t desiredAngles, setAngle; float diffYaw = 0.0f, diffPitch = 0.0f; float maxYawSpeed = (self->spawnflags&SPF_TURRETG2_TURBO)?30.0f:14.0f; float maxPitchSpeed = (self->spawnflags&SPF_TURRETG2_TURBO)?15.0f:3.0f; // move our gun base yaw to where we should be at this time.... BG_EvaluateTrajectory( &self->s.apos, level.time, self->r.currentAngles ); self->r.currentAngles[YAW] = AngleNormalize360( self->r.currentAngles[YAW] ); self->speed = AngleNormalize360( self->speed ); if ( self->enemy ) { mdxaBone_t boltMatrix; // ...then we'll calculate what new aim adjustments we should attempt to make this frame // Aim at enemy if ( self->enemy->client ) { VectorCopy( self->enemy->client->renderInfo.eyePoint, org ); } else { VectorCopy( self->enemy->r.currentOrigin, org ); } if ( self->spawnflags & 2 ) { org[2] -= 15; } else { org[2] -= 5; } if ( (self->spawnflags&SPF_TURRETG2_LEAD_ENEMY) ) { //we want to lead them a bit vec3_t diff, velocity; float dist; VectorSubtract( org, self->s.origin, diff ); dist = VectorNormalize( diff ); if ( self->enemy->client ) { VectorCopy( self->enemy->client->ps.velocity, velocity ); } else { VectorCopy( self->enemy->s.pos.trDelta, velocity ); } VectorMA( org, (dist/self->mass), velocity, org ); } // Getting the "eye" here trap_G2API_GetBoltMatrix( self->ghoul2, 0, (self->alt_fire?self->genericValue12:self->genericValue11), &boltMatrix, self->r.currentAngles, self->s.origin, level.time, NULL, self->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, org2 ); VectorSubtract( org, org2, enemyDir ); vectoangles( enemyDir, desiredAngles ); diffYaw = AngleSubtract( self->r.currentAngles[YAW], desiredAngles[YAW] ); diffPitch = AngleSubtract( self->speed, desiredAngles[PITCH] ); } else { // no enemy, so make us slowly sweep back and forth as if searching for a new one // diffYaw = sin( level.time * 0.0001f + self->count ) * 5.0f; // don't do this for now since it can make it go into walls. } if ( diffYaw ) { // cap max speed.... if ( fabs(diffYaw) > maxYawSpeed ) { diffYaw = ( diffYaw >= 0 ? maxYawSpeed : -maxYawSpeed ); } // ...then set up our desired yaw VectorSet( setAngle, 0.0f, diffYaw, 0.0f ); VectorCopy( self->r.currentAngles, self->s.apos.trBase ); VectorScale( setAngle,- 5, self->s.apos.trDelta ); self->s.apos.trTime = level.time; self->s.apos.trType = TR_LINEAR; } if ( diffPitch ) { if ( fabs(diffPitch) > maxPitchSpeed ) { // cap max speed self->speed += (diffPitch > 0.0f) ? -maxPitchSpeed : maxPitchSpeed; } else { // small enough, so just add half the diff so we smooth out the stopping self->speed -= ( diffPitch );//desiredAngles[PITCH]; } // Note that this is NOT interpolated, so it will be less smooth...On the other hand, it does use Ghoul2 to blend, so it may smooth it out a bit? if ( (self->spawnflags&SPF_TURRETG2_TURBO) ) { if ( self->spawnflags & 2 ) { VectorSet( desiredAngles, 0.0f, 0.0f, -self->speed ); } else { VectorSet( desiredAngles, 0.0f, 0.0f, self->speed ); } G2Tur_SetBoneAngles(self, "pitch", desiredAngles); } else { if ( self->spawnflags & 2 ) { VectorSet( desiredAngles, self->speed, 0.0f, 0.0f ); } else { VectorSet( desiredAngles, -self->speed, 0.0f, 0.0f ); } G2Tur_SetBoneAngles(self, "Bone_body", desiredAngles); } /* trap_G2API_SetBoneAngles( self->ghoul2, 0, "Bone_body", desiredAngles, BONE_ANGLES_POSTMULT, POSITIVE_Y, POSITIVE_Z, POSITIVE_X, NULL, 100, level.time ); */ } if ( diffYaw || diffPitch ) { //FIXME: turbolaser sounds if ( (self->spawnflags&SPF_TURRETG2_TURBO) ) { self->s.loopSound = G_SoundIndex( "sound/vehicles/weapons/turbolaser/turn.wav" ); } else { self->s.loopSound = G_SoundIndex( "sound/chars/turret/move.wav" ); } } else { self->s.loopSound = 0; } }
/* ------------------------- Sentry_Fire ------------------------- */ void Sentry_Fire (void) { vec3_t muzzle; static vec3_t forward, vright, up; gentity_t *missile; mdxaBone_t boltMatrix; int bolt, which; NPCS.NPC->flags &= ~FL_SHIELDED; if ( NPCS.NPCInfo->localState == LSTATE_POWERING_UP ) { if ( TIMER_Done( NPCS.NPC, "powerup" )) { NPCS.NPCInfo->localState = LSTATE_ATTACKING; NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_ATTACK1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); } else { // can't do anything right now return; } } else if ( NPCS.NPCInfo->localState == LSTATE_ACTIVE ) { NPCS.NPCInfo->localState = LSTATE_POWERING_UP; G_Sound( NPCS.NPC, CHAN_AUTO, G_SoundIndex("sound/chars/sentry/misc/sentry_shield_open") ); NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, BOTH_POWERUP1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD ); TIMER_Set( NPCS.NPC, "powerup", 250 ); return; } else if ( NPCS.NPCInfo->localState != LSTATE_ATTACKING ) { // bad because we are uninitialized NPCS.NPCInfo->localState = LSTATE_ACTIVE; return; } // Which muzzle to fire from? which = NPCS.NPCInfo->burstCount % 3; switch( which ) { case 0: bolt = trap_G2API_AddBolt(NPCS.NPC->ghoul2, 0, "*flash1"); break; case 1: bolt = trap_G2API_AddBolt(NPCS.NPC->ghoul2, 0, "*flash2"); break; case 2: default: bolt = trap_G2API_AddBolt(NPCS.NPC->ghoul2, 0, "*flash03"); } trap_G2API_GetBoltMatrix( NPCS.NPC->ghoul2, 0, bolt, &boltMatrix, NPCS.NPC->r.currentAngles, NPCS.NPC->r.currentOrigin, level.time, NULL, NPCS.NPC->modelScale ); BG_GiveMeVectorFromMatrix( &boltMatrix, ORIGIN, muzzle ); AngleVectors( NPCS.NPC->r.currentAngles, forward, vright, up ); // G_Sound( NPC, G_SoundIndex("sound/chars/sentry/misc/shoot.wav")); G_PlayEffectID( G_EffectIndex("bryar/muzzle_flash"), muzzle, forward ); missile = CreateMissile( muzzle, forward, 1600, 10000, NPCS.NPC, qfalse ); missile->classname = "bryar_proj"; missile->s.weapon = WP_BRYAR_PISTOL; missile->dflags = DAMAGE_DEATH_KNOCKBACK; missile->methodOfDeath = MOD_BRYAR_PISTOL; missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER; NPCS.NPCInfo->burstCount++; NPCS.NPC->attackDebounceTime = level.time + 50; missile->damage = 5; // now scale for difficulty if ( g_npcspskill.integer == 0 ) { NPCS.NPC->attackDebounceTime += 200; missile->damage = 1; } else if ( g_npcspskill.integer == 1 ) { NPCS.NPC->attackDebounceTime += 100; missile->damage = 3; } }
//Run physics on the object (purely origin-related) using custom epVelocity entity //state value. Origin smoothing on the client is expected to compensate for choppy //movement. void G_RunExPhys(gentity_t *ent, float gravity, float mass, float bounce, qboolean autoKill, int *g2Bolts, int numG2Bolts) { trace_t tr; vec3_t projectedOrigin; vec3_t vNorm; vec3_t ground; float velScaling = 0.1f; float vTotal = 0.0f; assert(mass <= 1.0f && mass >= 0.01f); if (gravity) { //factor it in before we do anything. VectorCopy(ent->r.currentOrigin, ground); ground[2] -= 0.1f; trap_Trace(&tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ground, ent->s.number, ent->clipmask); if (tr.fraction == 1.0f) { ent->s.groundEntityNum = ENTITYNUM_NONE; } else { ent->s.groundEntityNum = tr.entityNum; } if (ent->s.groundEntityNum == ENTITYNUM_NONE) { ent->epGravFactor += gravity; if (ent->epGravFactor > MAX_GRAVITY_PULL) { //cap it off if needed ent->epGravFactor = MAX_GRAVITY_PULL; } ent->epVelocity[2] -= ent->epGravFactor; } else { //if we're sitting on something then reset the gravity factor. ent->epGravFactor = 0; } } if (!ent->epVelocity[0] && !ent->epVelocity[1] && !ent->epVelocity[2]) { //nothing to do if we have no velocity even after gravity. if (ent->touch) { //call touch if we're in something trap_Trace(&tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, ent->s.number, ent->clipmask); if (tr.startsolid || tr.allsolid) { ent->touch(ent, &g_entities[tr.entityNum], &tr); } } return; } //get the projected origin based on velocity. VectorMA(ent->r.currentOrigin, velScaling, ent->epVelocity, projectedOrigin); VectorScale(ent->epVelocity, 1.0f-mass, ent->epVelocity); //scale it down based on mass VectorCopy(ent->epVelocity, vNorm); vTotal = VectorNormalize(vNorm); if (vTotal < 1 && ent->s.groundEntityNum != ENTITYNUM_NONE) { //we've pretty much stopped moving anyway, just clear it out then. VectorClear(ent->epVelocity); ent->epGravFactor = 0; trap_LinkEntity(ent); return; } if (ent->ghoul2 && g2Bolts) { //Have we been passed a bolt index array to clip against points on the skeleton? vec3_t tMins, tMaxs; vec3_t trajDif; vec3_t gbmAngles; vec3_t boneOrg; vec3_t projectedBoneOrg; vec3_t collisionRootPos; mdxaBone_t matrix; trace_t bestCollision; qboolean hasFirstCollision = qfalse; int i = 0; //Maybe we could use a trap call and get the default radius for the bone specified, //but this will do at least for now. VectorSet(tMins, -3, -3, -3); VectorSet(tMaxs, 3, 3, 3); gbmAngles[PITCH] = gbmAngles[ROLL] = 0; gbmAngles[YAW] = ent->s.apos.trBase[YAW]; //Get the difference relative to the entity origin and projected origin, to add to each bolt position. VectorSubtract(ent->r.currentOrigin, projectedOrigin, trajDif); while (i < numG2Bolts) { //Get the position of the actual bolt for this frame trap_G2API_GetBoltMatrix(ent->ghoul2, 0, g2Bolts[i], &matrix, gbmAngles, ent->r.currentOrigin, level.time, NULL, ent->modelScale); BG_GiveMeVectorFromMatrix(&matrix, ORIGIN, boneOrg); //Now add the projected positional difference into the result VectorAdd(boneOrg, trajDif, projectedBoneOrg); trap_Trace(&tr, boneOrg, tMins, tMaxs, projectedBoneOrg, ent->s.number, ent->clipmask); if (tr.fraction != 1.0 || tr.startsolid || tr.allsolid) { //we've hit something //Store the "deepest" collision we have if (!hasFirstCollision) { //don't have one yet so just use this one bestCollision = tr; VectorCopy(boneOrg, collisionRootPos); hasFirstCollision = qtrue; } else { if (tr.allsolid && !bestCollision.allsolid) { //If the whole trace is solid then this one is deeper bestCollision = tr; VectorCopy(boneOrg, collisionRootPos); } else if (tr.startsolid && !bestCollision.startsolid && !bestCollision.allsolid) { //Next deepest is if it's startsolid bestCollision = tr; VectorCopy(boneOrg, collisionRootPos); } else if (!bestCollision.startsolid && !bestCollision.allsolid && tr.fraction < bestCollision.fraction) { //and finally, if neither is startsolid/allsolid, but the new one has a smaller fraction, then it's closer to an impact point so we will use it bestCollision = tr; VectorCopy(boneOrg, collisionRootPos); } } } i++; } if (hasFirstCollision) { //at least one bolt collided //We'll get the offset between the collided bolt and endpos, then trace there //from the origin so that our desired position becomes that point. VectorSubtract(collisionRootPos, bestCollision.endpos, trajDif); VectorAdd(ent->r.currentOrigin, trajDif, projectedOrigin); } } //If we didn't collide with any bolts projectedOrigin will still be the original desired //projected position so all is well. If we did then projectedOrigin will be modified //to provide us with a relative position which does not place the bolt in a solid. trap_Trace(&tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, projectedOrigin, ent->s.number, ent->clipmask); if (tr.startsolid || tr.allsolid) { //can't go anywhere from here //[MiscCodeTweaks] if(g_developer.integer) { Com_Printf("ExPhys object in solid (%i)\n", ent->s.number); } /* #ifdef _DEBUG Com_Printf("ExPhys object in solid (%i)\n", ent->s.number); #endif */ //[/MiscCodeTweaks] if (autoKill) { ent->think = G_FreeEntity; ent->nextthink = level.time; } return; } //Go ahead and set it to the trace endpoint regardless of what it hit G_SetOrigin(ent, tr.endpos); trap_LinkEntity(ent); if (tr.fraction == 1.0f) { //Nothing was in the way. return; } if (bounce) { vTotal *= bounce; //scale it by bounce VectorScale(tr.plane.normal, vTotal, vNorm); //scale the trace plane normal by the bounce factor if (vNorm[2] > 0) { ent->epGravFactor -= vNorm[2]*(1.0f-mass); //The lighter it is the more gravity will be reduced by bouncing vertically. if (ent->epGravFactor < 0) { ent->epGravFactor = 0; } } //call touch first so we can check velocity upon impact if we want if (tr.entityNum != ENTITYNUM_NONE && ent->touch) { //then call the touch function ent->touch(ent, &g_entities[tr.entityNum], &tr); } VectorAdd(ent->epVelocity, vNorm, ent->epVelocity); //add it into the existing velocity. } else { //if no bounce, kill when it hits something. ent->epVelocity[0] = 0; ent->epVelocity[1] = 0; if (!gravity) { ent->epVelocity[2] = 0; } } }