/* ------------------------- NPC_Mark1_Precache ------------------------- */ void NPC_Mark1_Precache(void) { G_SoundIndex( "sound/chars/mark1/misc/mark1_wakeup"); G_SoundIndex( "sound/chars/mark1/misc/shutdown"); G_SoundIndex( "sound/chars/mark1/misc/walk"); G_SoundIndex( "sound/chars/mark1/misc/run"); G_SoundIndex( "sound/chars/mark1/misc/death1"); G_SoundIndex( "sound/chars/mark1/misc/death2"); G_SoundIndex( "sound/chars/mark1/misc/anger"); G_SoundIndex( "sound/chars/mark1/misc/mark1_fire"); G_SoundIndex( "sound/chars/mark1/misc/mark1_pain"); G_SoundIndex( "sound/chars/mark1/misc/mark1_explo"); // G_EffectIndex( "small_chunks"); G_EffectIndex( "env/med_explode2"); G_EffectIndex( "explosions/probeexplosion1"); G_EffectIndex( "blaster/smoke_bolton"); G_EffectIndex( "bryar/muzzle_flash"); G_EffectIndex( "explosions/droidexplosion1" ); RegisterItem( FindItemForAmmo( AMMO_METAL_BOLTS)); RegisterItem( FindItemForAmmo( AMMO_BLASTER )); RegisterItem( FindItemForWeapon( WP_BOWCASTER )); RegisterItem( FindItemForWeapon( WP_BRYAR_PISTOL )); }
/* ============== ClearRegisteredItems ============== */ void ClearRegisteredItems( void ) { memset( itemRegistered, '0', bg_numItems ); itemRegistered[ bg_numItems ] = 0; RegisterItem( FindItemForWeapon( WP_BRYAR_PISTOL ) ); //these are given in g_client, ClientSpawn(), but MUST be registered HERE, BEFORE cgame starts. RegisterItem( FindItemForWeapon( WP_STUN_BATON ) ); //these are given in g_client, ClientSpawn(), but MUST be registered HERE, BEFORE cgame starts. RegisterItem( FindItemForInventory( INV_ELECTROBINOCULARS )); // saber or baton is cached in SP_info_player_deathmatch now. extern void Player_CacheFromPrevLevel(void);//g_client.cpp Player_CacheFromPrevLevel(); //reads from transition carry-over; }
//--------------------------------------------- void SP_misc_model_ammo_rack( gentity_t *ent ) { // If BLASTER is checked...or nothing is checked then we'll do blasters if (( ent->spawnflags & RACK_BLASTER ) || !(ent->spawnflags & ( RACK_BLASTER | RACK_METAL_BOLTS | RACK_ROCKETS | RACK_PWR_CELL ))) { if ( ent->spawnflags & RACK_WEAPONS ) { RegisterItem( FindItemForWeapon( WP_BLASTER )); } RegisterItem( FindItemForAmmo( AMMO_BLASTER )); } if (( ent->spawnflags & RACK_METAL_BOLTS )) { if ( ent->spawnflags & RACK_WEAPONS ) { RegisterItem( FindItemForWeapon( WP_REPEATER )); } RegisterItem( FindItemForAmmo( AMMO_METAL_BOLTS )); } if (( ent->spawnflags & RACK_ROCKETS )) { if ( ent->spawnflags & RACK_WEAPONS ) { RegisterItem( FindItemForWeapon( WP_ROCKET_LAUNCHER )); } RegisterItem( FindItemForAmmo( AMMO_ROCKETS )); } if (( ent->spawnflags & RACK_PWR_CELL )) { RegisterItem( FindItemForAmmo( AMMO_POWERCELL )); } if (( ent->spawnflags & RACK_HEALTH )) { RegisterItem( FindItem( "item_medpak_instant" )); } ent->e_ThinkFunc = thinkF_spawn_rack_goods; ent->nextthink = level.time + 100; G_SetOrigin( ent, ent->s.origin ); G_SetAngles( ent, ent->s.angles ); ent->contents = CONTENTS_SHOTCLIP|CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_BOTCLIP;//CONTENTS_SOLID;//so use traces can go through them gi.linkentity( ent ); }
/* ------------------------- NPC_ATST_Precache ------------------------- */ void NPC_ATST_Precache(void) { G_SoundIndex( "sound/chars/atst/atst_damaged1" ); G_SoundIndex( "sound/chars/atst/atst_damaged2" ); RegisterItem( FindItemForWeapon( WP_ATST_MAIN )); //precache the weapon RegisterItem( FindItemForWeapon( WP_BOWCASTER )); //precache the weapon RegisterItem( FindItemForWeapon( WP_ROCKET_LAUNCHER )); //precache the weapon G_EffectIndex( "env/med_explode2" ); // G_EffectIndex( "smaller_chunks" ); G_EffectIndex( "blaster/smoke_bolton" ); G_EffectIndex( "explosions/droidexplosion1" ); }
void NPC_PrecacheWeapons( team_t playerTeam, int spawnflags, char *NPCtype ) { int weapons = NPC_WeaponsForTeam( playerTeam, spawnflags, NPCtype ); gitem_t *item; for ( int curWeap = WP_SABER; curWeap < WP_NUM_WEAPONS; curWeap++ ) { if ( (weapons & ( 1 << curWeap )) ) { item = FindItemForWeapon( ((weapon_t)(curWeap)) ); //precache the weapon CG_RegisterItemSounds( (item-bg_itemlist) ); CG_RegisterItemVisuals( (item-bg_itemlist) ); //precache the in-hand/in-world ghoul2 weapon model char weaponModel[64]; strcpy (weaponModel, weaponData[curWeap].weaponMdl); if (char *spot = strstr(weaponModel, ".md3") ) { *spot = 0; spot = strstr(weaponModel, "_w");//i'm using the in view weapon array instead of scanning the item list, so put the _w back on if (!spot) { strcat (weaponModel, "_w"); } strcat (weaponModel, ".glm"); //and change to ghoul2 } gi.G2API_PrecacheGhoul2Model( weaponModel ); // correct way is item->world_model } } }
void NPC_Mark2_Precache( void ) { G_SoundIndex( "sound/chars/mark2/misc/mark2_explo" );// blows up on death G_SoundIndex( "sound/chars/mark2/misc/mark2_pain" ); G_SoundIndex( "sound/chars/mark2/misc/mark2_fire" ); G_SoundIndex( "sound/chars/mark2/misc/mark2_move_lp" ); G_EffectIndex( "droidexplosion1" ); G_EffectIndex( "env/med_explode2" ); G_EffectIndex( "blaster/smoke_bolton" ); G_EffectIndex( "bryar/muzzle_flash" ); RegisterItem( FindItemForWeapon( WP_BRYAR_PISTOL )); RegisterItem( FindItemForAmmo( AMMO_METAL_BOLTS)); RegisterItem( FindItemForAmmo( AMMO_POWERCELL )); RegisterItem( FindItemForAmmo( AMMO_BLASTER )); }
void NPC_Probe_Precache(void) { for ( int i = 1; i < 4; i++) { G_SoundIndex( va( "sound/chars/probe/misc/probetalk%d", i ) ); } G_SoundIndex( "sound/chars/probe/misc/probedroidloop" ); G_SoundIndex("sound/chars/probe/misc/anger1"); G_SoundIndex("sound/chars/probe/misc/fire"); G_EffectIndex( "chunks/probehead" ); G_EffectIndex( "env/med_explode2" ); G_EffectIndex( "explosions/probeexplosion1"); G_EffectIndex( "bryar/muzzle_flash" ); RegisterItem( FindItemForAmmo( AMMO_BLASTER )); RegisterItem( FindItemForWeapon( WP_BRYAR_PISTOL ) ); }
gentity_t *G_DropSaberItem( const char *saberType, saber_colors_t saberColor, vec3_t saberPos, vec3_t saberVel, vec3_t saberAngles, gentity_t *copySaber ) {//turn it into a pick-uppable item! gentity_t *newItem = NULL; if ( saberType && saberType[0] ) {//have a valid string to use for saberType newItem = G_Spawn(); if ( newItem ) { newItem->classname = G_NewString( "weapon_saber" ); VectorCopy( saberPos, newItem->s.origin ); G_SetOrigin( newItem, newItem->s.origin ); VectorCopy( saberAngles, newItem->s.angles ); G_SetAngles( newItem, newItem->s.angles ); newItem->spawnflags = 128;/*ITMSF_USEPICKUP*/ newItem->spawnflags |= 64;/*ITMSF_NOGLOW*/ newItem->NPC_type = G_NewString( saberType );//saberType //FIXME: transfer per-blade color somehow? newItem->NPC_targetname = (char *)saberColorStringForColor[saberColor]; newItem->count = 1; newItem->flags = FL_DROPPED_ITEM; G_SpawnItem( newItem, FindItemForWeapon( WP_SABER ) ); newItem->s.pos.trType = TR_GRAVITY; newItem->s.pos.trTime = level.time; VectorCopy( saberVel, newItem->s.pos.trDelta ); //newItem->s.eFlags |= EF_BOUNCE_HALF; //copy some values from another saber, if provided: G_CopySaberItemValues( copySaber, newItem ); //don't *think* about calling FinishSpawningItem, just do it! newItem->e_ThinkFunc = thinkF_NULL; newItem->nextthink = -1; FinishSpawningItem( newItem ); newItem->delay = level.time + 500;//so you can't pick it back up right away } } return newItem; }
// AMMO RACK!! void spawn_rack_goods( gentity_t *ent ) { float v_off = 0; gitem_t *blaster = NULL, *metal_bolts = NULL, *rockets = NULL, *it = NULL; gitem_t *am_blaster = NULL, *am_metal_bolts = NULL, *am_rockets = NULL, *am_pwr_cell = NULL; gitem_t *health = NULL; int pos = 0, ct = 0; gitem_t *itemList[4]; // allocating 4, but we only use 3. done so I don't have to validate that the array isn't full before I add another gi.unlinkentity( ent ); // If BLASTER is checked...or nothing is checked then we'll do blasters if (( ent->spawnflags & RACK_BLASTER ) || !(ent->spawnflags & ( RACK_BLASTER | RACK_METAL_BOLTS | RACK_ROCKETS | RACK_PWR_CELL ))) { if ( ent->spawnflags & RACK_WEAPONS ) { blaster = FindItemForWeapon( WP_BLASTER ); } am_blaster = FindItemForAmmo( AMMO_BLASTER ); } if (( ent->spawnflags & RACK_METAL_BOLTS )) { if ( ent->spawnflags & RACK_WEAPONS ) { metal_bolts = FindItemForWeapon( WP_REPEATER ); } am_metal_bolts = FindItemForAmmo( AMMO_METAL_BOLTS ); } if (( ent->spawnflags & RACK_ROCKETS )) { if ( ent->spawnflags & RACK_WEAPONS ) { rockets = FindItemForWeapon( WP_ROCKET_LAUNCHER ); } am_rockets = FindItemForAmmo( AMMO_ROCKETS ); } if (( ent->spawnflags & RACK_PWR_CELL )) { am_pwr_cell = FindItemForAmmo( AMMO_POWERCELL ); } if (( ent->spawnflags & RACK_HEALTH )) { health = FindItem( "item_medpak_instant" ); RegisterItem( health ); } //---------Ammo types if ( am_blaster ) { itemList[ct++] = am_blaster; } if ( am_metal_bolts ) { itemList[ct++] = am_metal_bolts; } if ( am_pwr_cell ) { itemList[ct++] = am_pwr_cell; } if ( am_rockets ) { itemList[ct++] = am_rockets; } if ( !(ent->spawnflags & RACK_NO_FILL) && ct ) //double negative..should always have at least one item on there, but just being safe { for ( ; ct < 3 ; ct++ ) { itemList[ct] = itemList[0]; // first item ALWAYS propagates to fill up the shelf } } // now actually add the items to the shelf...validate that we have a list to add if ( ct ) { for ( int i = 0; i < ct; i++ ) { GunRackAddItem( itemList[i], ent->s.origin, ent->s.angles, crandom() * 0.5f, (i-1)* 8, 7.0f ); } } // -----Weapon option if ( ent->spawnflags & RACK_WEAPONS ) { if ( !(ent->spawnflags & ( RACK_BLASTER | RACK_METAL_BOLTS | RACK_ROCKETS | RACK_PWR_CELL ))) { // nothing was selected, so we assume blaster pack it = blaster; } else { // if weapon is checked...and so are one or more ammo types, then pick a random weapon to display..always give weaker weapons first if ( blaster ) { it = blaster; v_off = 25.5f; } else if ( metal_bolts ) { it = metal_bolts; v_off = 27.0f; } else if ( rockets ) { it = rockets; v_off = 28.0f; } } if ( it ) { // since we may have to put up a health pack on the shelf, we should know where we randomly put // the gun so we don't put the pack on the same spot..so pick either the left or right side pos = ( random() > .5 ) ? -1 : 1; GunRackAddItem( it, ent->s.origin, ent->s.angles, crandom() * 2, ( random() * 6 + 4 ) * pos, v_off ); } } // ------Medpack if (( ent->spawnflags & RACK_HEALTH ) && health ) { if ( !pos ) { // we haven't picked a side already... pos = ( random() > .5 ) ? -1 : 1; } else { // switch to the opposite side pos *= -1; } GunRackAddItem( health, ent->s.origin, ent->s.angles, crandom() * 0.5f, ( random() * 4 + 4 ) * pos, 24 ); } ent->s.modelindex = G_ModelIndex( "models/map_objects/kejim/weaponsrung.md3" ); G_SetOrigin( ent, ent->s.origin ); G_SetAngles( ent, ent->s.angles ); gi.linkentity( ent ); }
//--------------------------------------------- void SP_misc_model_gun_rack( gentity_t *ent ) { gitem_t *blaster = NULL, *repeater = NULL, *rocket = NULL; int ct = 0; float ofz[3]; gitem_t *itemList[3]; // If BLASTER is checked...or nothing is checked then we'll do blasters if (( ent->spawnflags & RACK_BLASTER ) || !(ent->spawnflags & ( RACK_BLASTER | RACK_REPEATER | RACK_ROCKET ))) { blaster = FindItemForWeapon( WP_BLASTER ); } if (( ent->spawnflags & RACK_REPEATER )) { repeater = FindItemForWeapon( WP_REPEATER ); } if (( ent->spawnflags & RACK_ROCKET )) { rocket = FindItemForWeapon( WP_ROCKET_LAUNCHER ); } //---------weapon types if ( blaster ) { ofz[ct] = 23.0f; itemList[ct++] = blaster; } if ( repeater ) { ofz[ct] = 24.5f; itemList[ct++] = repeater; } if ( rocket ) { ofz[ct] = 25.5f; itemList[ct++] = rocket; } if ( ct ) //..should always have at least one item on their, but just being safe { for ( ; ct < 3 ; ct++ ) { ofz[ct] = ofz[0]; itemList[ct] = itemList[0]; // first weapon ALWAYS propagates to fill up the shelf } } // now actually add the items to the shelf...validate that we have a list to add if ( ct ) { for ( int i = 0; i < ct; i++ ) { GunRackAddItem( itemList[i], ent->s.origin, ent->s.angles, crandom() * 2, ( i - 1 ) * 9 + crandom() * 2, ofz[i] ); } } ent->s.modelindex = G_ModelIndex( "models/map_objects/kejim/weaponsrack.md3" ); G_SetOrigin( ent, ent->s.origin ); G_SetAngles( ent, ent->s.angles ); ent->contents = CONTENTS_SOLID; gi.linkentity( ent ); }
//---------------------------------------------------------- void SP_emplaced_gun( gentity_t *ent ) { char name[] = "models/map_objects/imp_mine/turret_chair.glm"; ent->svFlags |= SVF_PLAYER_USABLE; ent->contents = CONTENTS_BODY;//CONTENTS_SHOTCLIP|CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP;//CONTENTS_SOLID; if ( ent->spawnflags & EMPLACED_INACTIVE ) { ent->svFlags |= SVF_INACTIVE; } VectorSet( ent->mins, -30, -30, -5 ); VectorSet( ent->maxs, 30, 30, 60 ); ent->takedamage = qtrue; if ( !( ent->spawnflags & EMPLACED_VULNERABLE )) { ent->flags |= FL_GODMODE; } ent->s.radius = 110; ent->spawnflags |= 4; // deadsolid //ent->e_ThinkFunc = thinkF_NULL; ent->e_PainFunc = painF_emplaced_gun_pain; ent->e_DieFunc = dieF_emplaced_gun_die; G_EffectIndex( "emplaced/explode" ); G_EffectIndex( "emplaced/dead_smoke" ); G_SoundIndex( "sound/weapons/emplaced/emplaced_mount.mp3" ); G_SoundIndex( "sound/weapons/emplaced/emplaced_dismount.mp3" ); G_SoundIndex( "sound/weapons/emplaced/emplaced_move_lp.wav" ); // Set up our defaults and override with custom amounts as necessary G_SpawnInt( "count", "999", &ent->count ); G_SpawnInt( "health", "250", &ent->health ); G_SpawnInt( "splashDamage", "80", &ent->splashDamage ); G_SpawnInt( "splashRadius", "128", &ent->splashRadius ); G_SpawnFloat( "delay", "200", &ent->random ); // NOTE: spawning into a different field!! G_SpawnFloat( "wait", "800", &ent->wait ); ent->max_health = ent->health; ent->dflags |= DAMAGE_CUSTOM_HUD; // dumb, but we draw a custom hud ent->s.modelindex = G_ModelIndex( name ); ent->playerModel = gi.G2API_InitGhoul2Model( ent->ghoul2, name, ent->s.modelindex, NULL, NULL, 0, 0 ); // Activate our tags and bones ent->headBolt = gi.G2API_AddBolt( &ent->ghoul2[ent->playerModel], "*seat" ); ent->handLBolt = gi.G2API_AddBolt( &ent->ghoul2[ent->playerModel], "*flash01" ); ent->handRBolt = gi.G2API_AddBolt( &ent->ghoul2[ent->playerModel], "*flash02" ); ent->rootBone = gi.G2API_GetBoneIndex( &ent->ghoul2[ent->playerModel], "base_bone", qtrue ); ent->lowerLumbarBone = gi.G2API_GetBoneIndex( &ent->ghoul2[ent->playerModel], "swivel_bone", qtrue ); gi.G2API_SetBoneAnglesIndex( &ent->ghoul2[ent->playerModel], ent->lowerLumbarBone, vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_Y, POSITIVE_Z, POSITIVE_X, NULL, 0, 0); RegisterItem( FindItemForWeapon( WP_EMPLACED_GUN )); ent->s.weapon = WP_EMPLACED_GUN; G_SetOrigin( ent, ent->s.origin ); G_SetAngles( ent, ent->s.angles ); VectorCopy( ent->s.angles, ent->lastAngles ); // store base angles for later VectorCopy( ent->s.angles, ent->pos1 ); ent->e_UseFunc = useF_emplaced_gun_use; ent->bounceCount = 0;//to distinguish it from the eweb gi.linkentity (ent); }
//---------------------------------------------------------- void SP_emplaced_eweb( gentity_t *ent ) { char name[] = "models/map_objects/hoth/eweb_model.glm"; ent->svFlags |= SVF_PLAYER_USABLE; ent->contents = CONTENTS_BODY; if ( ent->spawnflags & EMPLACED_INACTIVE ) { ent->svFlags |= SVF_INACTIVE; } VectorSet( ent->mins, -12, -12, -24 ); VectorSet( ent->maxs, 12, 12, 24 ); ent->takedamage = qtrue; if ( ( ent->spawnflags & EWEB_INVULNERABLE )) { ent->flags |= FL_GODMODE; } ent->s.radius = 80; ent->spawnflags |= 4; // deadsolid //ent->e_ThinkFunc = thinkF_NULL; ent->e_PainFunc = painF_eweb_pain; ent->e_DieFunc = dieF_eweb_die; G_EffectIndex( "emplaced/explode" ); G_EffectIndex( "emplaced/dead_smoke" ); G_SoundIndex( "sound/weapons/eweb/eweb_aim.wav" ); G_SoundIndex( "sound/weapons/eweb/eweb_dismount.mp3" ); //G_SoundIndex( "sound/weapons/eweb/eweb_empty.wav" ); G_SoundIndex( "sound/weapons/eweb/eweb_fire.wav" ); G_SoundIndex( "sound/weapons/eweb/eweb_hitplayer.wav" ); G_SoundIndex( "sound/weapons/eweb/eweb_hitsurface.wav" ); //G_SoundIndex( "sound/weapons/eweb/eweb_load.wav" ); G_SoundIndex( "sound/weapons/eweb/eweb_mount.mp3" ); // Set up our defaults and override with custom amounts as necessary G_SpawnInt( "count", "999", &ent->count ); G_SpawnInt( "health", "250", &ent->health ); G_SpawnInt( "splashDamage", "40", &ent->splashDamage ); G_SpawnInt( "splashRadius", "100", &ent->splashRadius ); G_SpawnFloat( "delay", "200", &ent->random ); // NOTE: spawning into a different field!! G_SpawnFloat( "wait", "800", &ent->wait ); ent->max_health = ent->health; ent->dflags |= DAMAGE_CUSTOM_HUD; // dumb, but we draw a custom hud ent->s.modelindex = G_ModelIndex( name ); ent->playerModel = gi.G2API_InitGhoul2Model( ent->ghoul2, name, ent->s.modelindex, NULL, NULL, 0, 0 ); // Activate our tags and bones ent->handLBolt = gi.G2API_AddBolt( &ent->ghoul2[ent->playerModel], "*cannonflash" ); //muzzle bolt ent->headBolt = gi.G2API_AddBolt( &ent->ghoul2[ent->playerModel], "cannon_Xrot" ); //for placing the owner relative to rotation ent->rootBone = gi.G2API_GetBoneIndex( &ent->ghoul2[ent->playerModel], "model_root", qtrue ); ent->lowerLumbarBone = gi.G2API_GetBoneIndex( &ent->ghoul2[ent->playerModel], "cannon_Yrot", qtrue ); ent->upperLumbarBone = gi.G2API_GetBoneIndex( &ent->ghoul2[ent->playerModel], "cannon_Xrot", qtrue ); gi.G2API_SetBoneAnglesIndex( &ent->ghoul2[ent->playerModel], ent->lowerLumbarBone, vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_Z, NEGATIVE_X, NEGATIVE_Y, NULL, 0, 0); gi.G2API_SetBoneAnglesIndex( &ent->ghoul2[ent->playerModel], ent->upperLumbarBone, vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_Z, NEGATIVE_X, NEGATIVE_Y, NULL, 0, 0); //gi.G2API_SetBoneAngles( &ent->ghoul2[0], "cannon_Yrot", vec3_origin, BONE_ANGLES_POSTMULT, POSITIVE_Y, POSITIVE_Z, POSITIVE_X, NULL); //set the constraints for this guy as an emplaced weapon, and his constraint angles //ent->s.origin2[0] = 60.0f; //60 degrees in either direction RegisterItem( FindItemForWeapon( WP_EMPLACED_GUN )); ent->s.weapon = WP_EMPLACED_GUN; G_SetOrigin( ent, ent->s.origin ); G_SetAngles( ent, ent->s.angles ); VectorCopy( ent->s.angles, ent->lastAngles ); // store base angles for later VectorClear( ent->pos1 ); ent->e_UseFunc = useF_eweb_use; ent->bounceCount = 1;//to distinguish it from the emplaced gun gi.linkentity (ent); }
void set_mission_stats_cvars( void ) { char text[1024]={0}; //we'll assume that the activator is the player gclient_t* const client = &level.clients[0]; if (!client) { return; } cg_entities[0].gent->client->sess.missionStats.enemiesKilled; gi.cvar_set("ui_stats_enemieskilled", va("%d",client->sess.missionStats.enemiesKilled)); //pass this on to the menu if (cg_entities[0].gent->client->sess.missionStats.totalSecrets) { cgi_SP_GetStringTextString( "SP_INGAME_SECRETAREAS_OF", text, sizeof(text) ); gi.cvar_set("ui_stats_secretsfound", va("%d %s %d", cg_entities[0].gent->client->sess.missionStats.secretsFound, text, cg_entities[0].gent->client->sess.missionStats.totalSecrets)); } else // Setting ui_stats_secretsfound to 0 will hide the text on screen { gi.cvar_set("ui_stats_secretsfound", "0"); } // Find the favorite weapon int wpn=0,i; int max_wpn = cg_entities[0].gent->client->sess.missionStats.weaponUsed[0]; for (i = 1; i<WP_NUM_WEAPONS; i++) { if (cg_entities[0].gent->client->sess.missionStats.weaponUsed[i] > max_wpn) { max_wpn = cg_entities[0].gent->client->sess.missionStats.weaponUsed[i]; wpn = i; } } if ( wpn ) { gitem_t *wItem= FindItemForWeapon( (weapon_t)wpn); cgi_SP_GetStringTextString( va("SP_INGAME_%s",wItem->classname ), text, sizeof( text )); gi.cvar_set("ui_stats_fave", va("%s",text)); //pass this on to the menu } gi.cvar_set("ui_stats_shots", va("%d",client->sess.missionStats.shotsFired)); //pass this on to the menu gi.cvar_set("ui_stats_hits", va("%d",client->sess.missionStats.hits)); //pass this on to the menu const float percent = cg_entities[0].gent->client->sess.missionStats.shotsFired? 100.0f * (float)cg_entities[0].gent->client->sess.missionStats.hits / cg_entities[0].gent->client->sess.missionStats.shotsFired : 0; gi.cvar_set("ui_stats_accuracy", va("%.2f%%",percent)); //pass this on to the menu gi.cvar_set("ui_stats_thrown", va("%d",client->sess.missionStats.saberThrownCnt)); //pass this on to the menu gi.cvar_set("ui_stats_blocks", va("%d",client->sess.missionStats.saberBlocksCnt)); gi.cvar_set("ui_stats_legattacks", va("%d",client->sess.missionStats.legAttacksCnt)); gi.cvar_set("ui_stats_armattacks", va("%d",client->sess.missionStats.armAttacksCnt)); gi.cvar_set("ui_stats_bodyattacks", va("%d",client->sess.missionStats.torsoAttacksCnt)); gi.cvar_set("ui_stats_absorb", va("%d",client->sess.missionStats.forceUsed[FP_ABSORB])); gi.cvar_set("ui_stats_heal", va("%d",client->sess.missionStats.forceUsed[FP_HEAL])); gi.cvar_set("ui_stats_mindtrick", va("%d",client->sess.missionStats.forceUsed[FP_TELEPATHY])); gi.cvar_set("ui_stats_protect", va("%d",client->sess.missionStats.forceUsed[FP_PROTECT])); gi.cvar_set("ui_stats_jump", va("%d",client->sess.missionStats.forceUsed[FP_LEVITATION])); gi.cvar_set("ui_stats_pull", va("%d",client->sess.missionStats.forceUsed[FP_PULL])); gi.cvar_set("ui_stats_push", va("%d",client->sess.missionStats.forceUsed[FP_PUSH])); gi.cvar_set("ui_stats_sense", va("%d",client->sess.missionStats.forceUsed[FP_SEE])); gi.cvar_set("ui_stats_speed", va("%d",client->sess.missionStats.forceUsed[FP_SPEED])); gi.cvar_set("ui_stats_defense", va("%d",client->sess.missionStats.forceUsed[FP_SABER_DEFENSE])); gi.cvar_set("ui_stats_offense", va("%d",client->sess.missionStats.forceUsed[FP_SABER_OFFENSE])); gi.cvar_set("ui_stats_throw", va("%d",client->sess.missionStats.forceUsed[FP_SABERTHROW])); gi.cvar_set("ui_stats_drain", va("%d",client->sess.missionStats.forceUsed[FP_DRAIN])); gi.cvar_set("ui_stats_grip", va("%d",client->sess.missionStats.forceUsed[FP_GRIP])); gi.cvar_set("ui_stats_lightning", va("%d",client->sess.missionStats.forceUsed[FP_LIGHTNING])); gi.cvar_set("ui_stats_rage", va("%d",client->sess.missionStats.forceUsed[FP_RAGE])); }
/* ================= CG_MissionCompletion ================= */ void CG_MissionCompletion(void) { char text[1024]={0}; int w,x,y; const int pad = 18; cgi_SP_GetStringTextString( "INGAME_MISSIONCOMPLETION", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontMedium, 1.2f); cgi_R_Font_DrawString(320 - w/2, 53, text, colorTable[CT_LTGOLD1], cgs.media.qhFontMedium, -1, 1.2f); x = 75; y =86; cgi_SP_GetStringTextString( "INGAME_SECRETAREAS", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_SP_GetStringTextString( "INGAME_SECRETAREAS_OF", text, sizeof(text) ); cgi_R_Font_DrawString(x+w, y, va("%d %s %d", cg_entities[0].gent->client->sess.missionStats.secretsFound, text, cg_entities[0].gent->client->sess.missionStats.totalSecrets ), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_ENEMIESKILLED", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w,y, va("%d",cg_entities[0].gent->client->sess.missionStats.enemiesKilled), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); /* cgi_SP_GetStringTextString( "INGAME_SECRETAREAS_OF", text, sizeof(text) ); cgi_R_Font_DrawString(x+w,y, va("%d %s %d", cg_entities[0].gent->client->sess.missionStats.enemiesKilled, text, cg_entities[0].gent->client->sess.missionStats.enemiesSpawned ), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); */ y +=pad; y +=pad; cgi_SP_GetStringTextString( "INGAME_FAVORITEWEAPON", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); int wpn=0,i; int max_wpn = cg_entities[0].gent->client->sess.missionStats.weaponUsed[0]; for (i = 1; i<WP_NUM_WEAPONS; i++) { if (cg_entities[0].gent->client->sess.missionStats.weaponUsed[i] > max_wpn) { max_wpn = cg_entities[0].gent->client->sess.missionStats.weaponUsed[i]; wpn = i; } } if ( wpn ) { gitem_t *wItem= FindItemForWeapon( (weapon_t)wpn); cgi_SP_GetStringTextString( va("INGAME_%s",wItem->classname ), text, sizeof( text )); // cgi_R_Font_DrawString(x+w, y, va("%d",wpn), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, text, colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); } x = 334+70; y = 86; cgi_SP_GetStringTextString( "INGAME_SHOTSFIRED", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.shotsFired), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_HITS", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.hits), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_ACCURACY", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); const float percent = cg_entities[0].gent->client->sess.missionStats.shotsFired? 100.0f * (float)cg_entities[0].gent->client->sess.missionStats.hits / cg_entities[0].gent->client->sess.missionStats.shotsFired : 0; cgi_R_Font_DrawString(x+w, y, va("%.2f%%",percent), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); if ( cg_entities[0].gent->client->sess.missionStats.weaponUsed[WP_SABER] <= 0 ) { return; //don't have saber yet, so don't print any stats } //first column, FORCE POWERS y =180; cgi_SP_GetStringTextString( "INGAME_FORCEUSE", text, sizeof(text) ); cgi_R_Font_DrawString(x, y, text, colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_HEAL", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.forceUsed[FP_HEAL]), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_SPEED", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.forceUsed[FP_SPEED]), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_PULL", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.forceUsed[FP_PULL]), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_PUSH", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.forceUsed[FP_PUSH]), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString("INGAME_MINDTRICK", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.forceUsed[FP_TELEPATHY]), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_GRIP", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.forceUsed[FP_GRIP]), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_LIGHTNING", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.forceUsed[FP_LIGHTNING]), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); //second column, LIGHT SABER y = 180; x = 140; cgi_SP_GetStringTextString( "INGAME_LIGHTSABERUSE", text, sizeof(text) ); cgi_R_Font_DrawString(x, y, text, colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_THROWN", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.saberThrownCnt), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_BLOCKS", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.saberBlocksCnt), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_LEGATTACKS", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.legAttacksCnt), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_ARMATTACKS", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.armAttacksCnt), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_BODYATTACKS", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.torsoAttacksCnt), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); y +=pad; cgi_SP_GetStringTextString( "INGAME_OTHERATTACKS", text, sizeof(text) ); w = cgi_R_Font_StrLenPixels(text, cgs.media.qhFontSmall, 0.8f); cgi_R_Font_DrawString(x, y, text, colorTable[CT_LTGOLD1], cgs.media.qhFontSmall, -1, 0.8f); cgi_R_Font_DrawString(x+w, y, va("%d",cg_entities[0].gent->client->sess.missionStats.otherAttacksCnt), colorTable[CT_WHITE], cgs.media.qhFontSmall, -1, 0.8f); }
/*QUAKED misc_model_breakable (1 0 0) (-16 -16 -16) (16 16 16) SOLID AUTOANIMATE DEADSOLID NO_DMODEL NO_SMOKE USE_MODEL USE_NOT_BREAK PLAYER_USE NO_EXPLOSION START_OFF SOLID - Movement is blocked by it, if not set, can still be broken by explosions and shots if it has health AUTOANIMATE - Will cycle it's anim DEADSOLID - Stay solid even when destroyed (in case damage model is rather large). NO_DMODEL - Makes it NOT display a damage model when destroyed, even if one exists USE_MODEL - When used, will toggle to it's usemodel (model + "_u1.md3")... this obviously does nothing if USE_NOT_BREAK is not checked USE_NOT_BREAK - Using it, doesn't make it break, still can be destroyed by damage PLAYER_USE - Player can use it with the use button NO_EXPLOSION - By default, will explode when it dies...this is your override. START_OFF - Will start off and will not appear until used. "model" arbitrary .md3 file to display "modelscale" "x" uniform scale "modelscale_vec" "x y z" scale model in each axis - height, width and length - bbox will scale with it "health" how much health to have - default is zero (not breakable) If you don't set the SOLID flag, but give it health, it can be shot but will not block NPCs or players from moving "targetname" when used, dies and displays damagemodel (model + "_d1.md3"), if any (if not, removes itself) "target" What to use when it dies "target2" What to use when it's repaired "target3" What to use when it's used while it's broken "paintarget" target to fire when hit (but not destroyed) "count" the amount of armor/health/ammo given (default 50) "radius" Chunk code tries to pick a good volume of chunks, but you can alter this to scale the number of spawned chunks. (default 1) (.5) is half as many chunks, (2) is twice as many chunks "NPC_targetname" - Only the NPC with this name can damage this "forcevisible" - When you turn on force sight (any level), you can see these draw through the entire level... "redCrosshair" - crosshair turns red when you look at this "gravity" if set to 1, this will be affected by gravity "throwtarget" if set (along with gravity), this thing, when used, will throw itself at the entity whose targetname matches this string "mass" if gravity is on, this determines how much damage this thing does when it hits someone. Default is the size of the object from one corner to the other, that works very well. Only override if this is an object whose mass should be very high or low for it's size (density) Damage: default is none "splashDamage" - damage to do (will make it explode on death) "splashRadius" - radius for above damage "team" - This cannot take damage from members of this team: "player" "neutral" "enemy" "material" - default is "8 - MAT_NONE" - choose from this list: 0 = MAT_METAL (grey metal) 1 = MAT_GLASS 2 = MAT_ELECTRICAL (sparks only) 3 = MAT_ELEC_METAL (METAL chunks and sparks) 4 = MAT_DRK_STONE (brown stone chunks) 5 = MAT_LT_STONE (tan stone chunks) 6 = MAT_GLASS_METAL (glass and METAL chunks) 7 = MAT_METAL2 (blue/grey metal) 8 = MAT_NONE (no chunks-DEFAULT) 9 = MAT_GREY_STONE (grey colored stone) 10 = MAT_METAL3 (METAL and METAL2 chunk combo) 11 = MAT_CRATE1 (yellow multi-colored crate chunks) 12 = MAT_GRATE1 (grate chunks--looks horrible right now) 13 = MAT_ROPE (for yavin_trial, no chunks, just wispy bits ) 14 = MAT_CRATE2 (red multi-colored crate chunks) 15 = MAT_WHITE_METAL (white angular chunks for Stu, NS_hideout ) */ void SP_misc_model_breakable( gentity_t *ent ) { char damageModel[MAX_QPATH]; char chunkModel[MAX_QPATH]; char useModel[MAX_QPATH]; int len; // Chris F. requested default for misc_model_breakable to be NONE...so don't arbitrarily change this. G_SpawnInt( "material", "8", (int*)&ent->material ); G_SpawnFloat( "radius", "1", &ent->radius ); // used to scale chunk code if desired by a designer qboolean bHasScale = G_SpawnVector("modelscale_vec", "0 0 0", ent->s.modelScale); if (!bHasScale) { float temp; G_SpawnFloat( "modelscale", "0", &temp); if (temp != 0.0f) { ent->s.modelScale[ 0 ] = ent->s.modelScale[ 1 ] = ent->s.modelScale[ 2 ] = temp; bHasScale = qtrue; } } CacheChunkEffects( ent->material ); misc_model_breakable_init( ent ); len = strlen( ent->model ) - 4; assert(ent->model[len]=='.');//we're expecting ".md3" strncpy( damageModel, ent->model, sizeof(damageModel) ); damageModel[len] = 0; //chop extension strncpy( chunkModel, damageModel, sizeof(chunkModel)); strncpy( useModel, damageModel, sizeof(useModel)); if (ent->takedamage) { //Dead/damaged model if( !(ent->spawnflags & 8) ) { //no dmodel strcat( damageModel, "_d1.md3" ); ent->s.modelindex2 = G_ModelIndex( damageModel ); } //Chunk model strcat( chunkModel, "_c1.md3" ); ent->s.modelindex3 = G_ModelIndex( chunkModel ); } //Use model if( ent->spawnflags & 32 ) { //has umodel strcat( useModel, "_u1.md3" ); ent->sound1to2 = G_ModelIndex( useModel ); } if ( !ent->mins[0] && !ent->mins[1] && !ent->mins[2] ) { VectorSet (ent->mins, -16, -16, -16); } if ( !ent->maxs[0] && !ent->maxs[1] && !ent->maxs[2] ) { VectorSet (ent->maxs, 16, 16, 16); } // Scale up the tie-bomber bbox a little. if ( ent->model && Q_stricmp( "models/map_objects/ships/tie_bomber.md3", ent->model ) == 0 ) { VectorSet (ent->mins, -80, -80, -80); VectorSet (ent->maxs, 80, 80, 80); //ent->s.modelScale[ 0 ] = ent->s.modelScale[ 1 ] = ent->s.modelScale[ 2 ] *= 2.0f; //bHasScale = qtrue; } if (bHasScale) { //scale the x axis of the bbox up. ent->maxs[0] *= ent->s.modelScale[0];//*scaleFactor; ent->mins[0] *= ent->s.modelScale[0];//*scaleFactor; //scale the y axis of the bbox up. ent->maxs[1] *= ent->s.modelScale[1];//*scaleFactor; ent->mins[1] *= ent->s.modelScale[1];//*scaleFactor; //scale the z axis of the bbox up and adjust origin accordingly ent->maxs[2] *= ent->s.modelScale[2]; float oldMins2 = ent->mins[2]; ent->mins[2] *= ent->s.modelScale[2]; ent->s.origin[2] += (oldMins2-ent->mins[2]); } if ( ent->spawnflags & 2 ) { ent->s.eFlags |= EF_ANIM_ALLFAST; } G_SetOrigin( ent, ent->s.origin ); G_SetAngles( ent, ent->s.angles ); gi.linkentity (ent); if ( ent->spawnflags & 128 ) {//Can be used by the player's BUTTON_USE ent->svFlags |= SVF_PLAYER_USABLE; } if ( ent->team && ent->team[0] ) { ent->noDamageTeam = (team_t)GetIDForString( TeamTable, ent->team ); if ( ent->noDamageTeam == TEAM_FREE ) { G_Error("team name %s not recognized\n", ent->team); } } ent->team = NULL; //HACK if ( ent->model && Q_stricmp( "models/map_objects/ships/x_wing_nogear.md3", ent->model ) == 0 ) { if( ent->splashDamage > 0 && ent->splashRadius > 0 ) { ent->s.loopSound = G_SoundIndex( "sound/vehicles/x-wing/loop.wav" ); ent->s.eFlags |= EF_LESS_ATTEN; } } else if ( ent->model && Q_stricmp( "models/map_objects/ships/tie_fighter.md3", ent->model ) == 0 ) {//run a think G_EffectIndex( "explosions/fighter_explosion2" ); G_SoundIndex( "sound/weapons/tie_fighter/tiepass1.wav" ); /* G_SoundIndex( "sound/weapons/tie_fighter/tiepass2.wav" ); G_SoundIndex( "sound/weapons/tie_fighter/tiepass3.wav" ); G_SoundIndex( "sound/weapons/tie_fighter/tiepass4.wav" ); G_SoundIndex( "sound/weapons/tie_fighter/tiepass5.wav" );*/ G_SoundIndex( "sound/weapons/tie_fighter/tie_fire.wav" ); /* G_SoundIndex( "sound/weapons/tie_fighter/tie_fire2.wav" ); G_SoundIndex( "sound/weapons/tie_fighter/tie_fire3.wav" );*/ G_SoundIndex( "sound/weapons/tie_fighter/TIEexplode.wav" ); RegisterItem( FindItemForWeapon( WP_TIE_FIGHTER )); ent->s.eFlags |= EF_LESS_ATTEN; if( ent->splashDamage > 0 && ent->splashRadius > 0 ) { ent->s.loopSound = G_SoundIndex( "sound/vehicles/tie-bomber/loop.wav" ); //ent->e_ThinkFunc = thinkF_TieFighterThink; //ent->e_UseFunc = thinkF_TieFighterThink; //ent->nextthink = level.time + FRAMETIME; ent->e_UseFunc = useF_TieFighterUse; // Yeah, I could have just made this value changable from the editor, but I // need it immediately! float light; vec3_t color; qboolean lightSet, colorSet; // if the "color" or "light" keys are set, setup constantLight lightSet = qtrue;//G_SpawnFloat( "light", "100", &light ); light = 255; //colorSet = "1 1 1"//G_SpawnVector( "color", "1 1 1", color ); colorSet = qtrue; color[0] = 1; color[1] = 1; color[2] = 1; if ( lightSet || colorSet ) { int r, g, b, i; r = color[0] * 255; if ( r > 255 ) { r = 255; } g = color[1] * 255; if ( g > 255 ) { g = 255; } b = color[2] * 255; if ( b > 255 ) { b = 255; } i = light / 4; if ( i > 255 ) { i = 255; } ent->s.constantLight = r | ( g << 8 ) | ( b << 16 ) | ( i << 24 ); } } } else if ( ent->model && Q_stricmp( "models/map_objects/ships/tie_bomber.md3", ent->model ) == 0 ) { G_EffectIndex( "ships/tiebomber_bomb_falling" ); G_EffectIndex( "ships/tiebomber_explosion2" ); G_EffectIndex( "explosions/fighter_explosion2" ); G_SoundIndex( "sound/weapons/tie_fighter/TIEexplode.wav" ); ent->e_ThinkFunc = thinkF_TieBomberThink; ent->nextthink = level.time + FRAMETIME; ent->attackDebounceTime = level.time + 1000; // We only take damage from a heavy weapon class missiles. ent->flags |= FL_DMG_BY_HEAVY_WEAP_ONLY; ent->s.loopSound = G_SoundIndex( "sound/vehicles/tie-bomber/loop.wav" ); ent->s.eFlags |= EF_LESS_ATTEN; } float grav = 0; G_SpawnFloat( "gravity", "0", &grav ); if ( grav ) {//affected by gravity G_SetAngles( ent, ent->s.angles ); G_SetOrigin( ent, ent->currentOrigin ); G_SpawnString( "throwtarget", NULL, &ent->target4 ); // used to throw itself at something misc_model_breakable_gravity_init( ent, qtrue ); } // Start off. if ( ent->spawnflags & 4096 ) { ent->spawnContents = ent->contents; // It Navs can temporarly turn it "on" ent->s.solid = 0; ent->contents = 0; ent->clipmask = 0; ent->svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->count = 0; } int forceVisible = 0; G_SpawnInt( "forcevisible", "0", &forceVisible ); if ( forceVisible ) {//can see these through walls with force sight, so must be broadcast //ent->svFlags |= SVF_BROADCAST; ent->s.eFlags |= EF_FORCE_VISIBLE; } int redCrosshair = 0; G_SpawnInt( "redCrosshair", "0", &redCrosshair ); if ( redCrosshair ) {//can see these through walls with force sight, so must be broadcast ent->flags |= FL_RED_CROSSHAIR; } }