void turretG2_respawn( gentity_t *self ) { self->use = turretG2_base_use; self->pain = TurretG2Pain; self->die = turretG2_die; self->takedamage = qtrue; self->s.shouldtarget = qtrue; if ( self->s.eFlags & EF_SHADER_ANIM ) { self->s.frame = 0; // normal } self->s.weapon = WP_TURRET; // crosshair code uses this to mark crosshair red turretG2_set_models( self, qfalse ); self->s.health = self->health = self->genericValue6; if (self->maxHealth) { G_ScaleNetHealth(self); } self->genericValue5 = 0;//clear this now }
//------------------------------------------------------------------------------------------------------------ void TurretPain( gentity_t *self, gentity_t *attacker, int damage ) //------------------------------------------------------------------------------------------------------------ { if (self->target_ent) { self->target_ent->health = self->health; if (self->target_ent->maxHealth) { G_ScaleNetHealth(self->target_ent); } } if ( attacker->client && attacker->client->ps.weapon == WP_DEMP2 ) { self->attackDebounceTime = level.time + 800 + random() * 500; self->painDebounceTime = self->attackDebounceTime; } if ( !self->enemy ) {//react to being hit G_SetEnemy( self, attacker ); } }
//----------------------------------------------------- qboolean turret_base_spawn_top( gentity_t *base ) { vec3_t org; int t; gentity_t *top = G_Spawn(); if ( !top ) { return qfalse; } top->s.modelindex = G_ModelIndex( "models/map_objects/hoth/turret_top_new.md3" ); top->s.modelindex2 = G_ModelIndex( "models/map_objects/hoth/turret_top.md3" ); G_SetAngles( top, base->s.angles ); VectorCopy( base->s.origin, org ); org[2] += 128; G_SetOrigin( top, org ); base->r.ownerNum = top->s.number; top->r.ownerNum = base->s.number; if ( base->team && base->team[0] && //g_gametype.integer == GT_SIEGE && !base->teamnodmg) { base->teamnodmg = atoi(base->team); } base->team = NULL; top->teamnodmg = base->teamnodmg; top->alliedTeam = base->alliedTeam; base->s.eType = ET_GENERAL; // Set up our explosion effect for the ExplodeDeath code.... G_EffectIndex( "turret/explode" ); G_EffectIndex( "sparks/spark_exp_nosnd" ); G_EffectIndex( "turret/hoth_muzzle_flash" ); // this is really the pitch angle..... top->speed = 0; // this is a random time offset for the no-enemy-search-around-mode top->count = random() * 9000; if ( !base->health ) { base->health = 3000; } top->health = base->health; G_SpawnInt( "showhealth", "0", &t ); if (t) { //a non-0 maxhealth value will mean we want to show the health on the hud top->maxHealth = base->health; //acts as "maxhealth" G_ScaleNetHealth(top); base->maxHealth = base->health; G_ScaleNetHealth(base); } base->takedamage = qtrue; base->pain = TurretBasePain; base->die = bottom_die; //design specified shot speed G_SpawnFloat( "shotspeed", "1100", &base->mass ); top->mass = base->mass; //even if we don't want to show health, let's at least light the crosshair up properly over ourself if ( !top->s.teamowner ) { top->s.teamowner = top->alliedTeam; } base->alliedTeam = top->alliedTeam; base->s.teamowner = top->s.teamowner; base->s.shouldtarget = qtrue; top->s.shouldtarget = qtrue; //link them to each other base->target_ent = top; top->target_ent = base; //top->s.owner = MAX_CLIENTS; //not owned by any client // search radius if ( !base->radius ) { base->radius = 1024; } top->radius = base->radius; // How quickly to fire if ( !base->wait ) { base->wait = 300 + random() * 55; } top->wait = base->wait; if ( !base->splashDamage ) { base->splashDamage = 300; } top->splashDamage = base->splashDamage; if ( !base->splashRadius ) { base->splashRadius = 128; } top->splashRadius = base->splashRadius; // how much damage each shot does if ( !base->damage ) { base->damage = 100; } top->damage = base->damage; // how fast it turns if ( !base->speed ) { base->speed = 20; } top->speed = base->speed; VectorSet( top->r.maxs, 48.0f, 48.0f, 16.0f ); VectorSet( top->r.mins, -48.0f, -48.0f, 0.0f ); // Precache moving sounds //G_SoundIndex( "sound/chars/turret/startup.wav" ); //G_SoundIndex( "sound/chars/turret/shutdown.wav" ); //G_SoundIndex( "sound/chars/turret/ping.wav" ); G_SoundIndex( "sound/vehicles/weapons/hoth_turret/turn.wav" ); top->genericValue13 = G_EffectIndex( "turret/hoth_muzzle_flash" ); top->genericValue14 = G_EffectIndex( "turret/hoth_shot" ); top->genericValue15 = G_EffectIndex( "turret/hoth_impact" ); top->r.contents = CONTENTS_BODY; //base->max_health = base->health; top->takedamage = qtrue; top->pain = TurretPain; top->die = auto_turret_die; top->material = MAT_METAL; //base->r.svFlags |= SVF_NO_TELEPORT|SVF_NONNPC_ENEMY|SVF_SELF_ANIMATING; // Register this so that we can use it for the missile effect RegisterItem( BG_FindItemForWeapon( WP_EMPLACED_GUN )); // But set us as a turret so that we can be identified as a turret top->s.weapon = WP_EMPLACED_GUN; trap_LinkEntity( top ); return qtrue; }
//----------------------------------------------------- void finish_spawning_turretG2( gentity_t *base ) { vec3_t fwd; int t; if ( (base->spawnflags&2) ) { base->s.angles[ROLL] += 180; base->s.origin[2] -= 22.0f; } G_SetAngles( base, base->s.angles ); AngleVectors( base->r.currentAngles, fwd, NULL, NULL ); G_SetOrigin(base, base->s.origin); base->s.eType = ET_GENERAL; if ( base->team && base->team[0] && //g_gametype.integer == GT_SIEGE && !base->teamnodmg) { base->teamnodmg = atoi(base->team); } base->team = NULL; // Set up our explosion effect for the ExplodeDeath code.... G_EffectIndex( "turret/explode" ); G_EffectIndex( "sparks/spark_exp_nosnd" ); base->use = turretG2_base_use; base->pain = TurretG2Pain; // don't start working right away base->think = turretG2_base_think; base->nextthink = level.time + FRAMETIME * 5; // this is really the pitch angle..... base->speed = 0; // respawn time defaults to 20 seconds if ( (base->spawnflags&SPF_TURRETG2_CANRESPAWN) && !base->count ) { base->count = 20000; } G_SpawnFloat( "shotspeed", "0", &base->mass ); if ( (base->spawnflags&SPF_TURRETG2_TURBO) ) { if ( !base->random ) { //error worked into projectile direction base->random = 2.0f; } if ( !base->mass ) { //misnomer: speed of projectile base->mass = 20000; } if ( !base->health ) { base->health = 2000; } // search radius if ( !base->radius ) { base->radius = 32768; } // How quickly to fire if ( !base->wait ) { base->wait = 1000;// + random() * 500; } if ( !base->splashDamage ) { base->splashDamage = 200; } if ( !base->splashRadius ) { base->splashRadius = 500; } // how much damage each shot does if ( !base->damage ) { base->damage = 500; } if ( (base->spawnflags&SPF_TURRETG2_TURBO) ) { VectorSet( base->r.maxs, 64.0f, 64.0f, 30.0f ); VectorSet( base->r.mins, -64.0f, -64.0f, -30.0f ); } //start in "off" anim TurboLaser_SetBoneAnim( base, 4, 5 ); if ( g_gametype.integer == GT_SIEGE ) { //FIXME: designer-specified? //FIXME: put on other entities, too, particularly siege objectives and bbrushes... base->s.eFlags2 |= EF2_BRACKET_ENTITY; } } else { if ( !base->random ) { //error worked into projectile direction base->random = 2.0f; } if ( !base->mass ) { //misnomer: speed of projectile base->mass = 1100; } if ( !base->health ) { base->health = 100; } // search radius if ( !base->radius ) { base->radius = 512; } // How quickly to fire if ( !base->wait ) { base->wait = 150 + random() * 55; } if ( !base->splashDamage ) { base->splashDamage = 10; } if ( !base->splashRadius ) { base->splashRadius = 25; } // how much damage each shot does if ( !base->damage ) { base->damage = 5; } if ( base->spawnflags & 2 ) { //upside-down, invert r.mins and maxe VectorSet( base->r.maxs, 10.0f, 10.0f, 30.0f ); VectorSet( base->r.mins, -10.0f, -10.0f, 0.0f ); } else { VectorSet( base->r.maxs, 10.0f, 10.0f, 0.0f ); VectorSet( base->r.mins, -10.0f, -10.0f, -30.0f ); } } //stash health off for respawn. NOTE: cannot use maxhealth because that might not be set if not showing the health bar base->genericValue6 = base->health; G_SpawnInt( "showhealth", "0", &t ); if (t) { //a non-0 maxhealth value will mean we want to show the health on the hud base->maxHealth = base->health; G_ScaleNetHealth(base); base->s.shouldtarget = qtrue; //base->s.owner = MAX_CLIENTS; //not owned by any client } if (base->s.iModelScale) { //let's scale the bbox too... float fScale = base->s.iModelScale/100.0f; VectorScale(base->r.mins, fScale, base->r.mins); VectorScale(base->r.maxs, fScale, base->r.maxs); } // Precache special FX and moving sounds if ( (base->spawnflags&SPF_TURRETG2_TURBO) ) { base->genericValue13 = G_EffectIndex( "turret/turb_muzzle_flash" ); base->genericValue14 = G_EffectIndex( "turret/turb_shot" ); base->genericValue15 = G_EffectIndex( "turret/turb_impact" ); //FIXME: Turbo Laser Cannon sounds! G_SoundIndex( "sound/vehicles/weapons/turbolaser/turn.wav" ); } else { G_SoundIndex( "sound/chars/turret/startup.wav" ); G_SoundIndex( "sound/chars/turret/shutdown.wav" ); G_SoundIndex( "sound/chars/turret/ping.wav" ); G_SoundIndex( "sound/chars/turret/move.wav" ); } base->r.contents = CONTENTS_BODY|CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_SHOTCLIP; //base->max_health = base->health; base->takedamage = qtrue; base->die = turretG2_die; base->material = MAT_METAL; //base->r.svFlags |= SVF_NO_TELEPORT|SVF_NONNPC_ENEMY|SVF_SELF_ANIMATING; // Register this so that we can use it for the missile effect RegisterItem( BG_FindItemForWeapon( WP_BLASTER )); // But set us as a turret so that we can be identified as a turret base->s.weapon = WP_TURRET; trap_LinkEntity( base ); }
//initization for misc_model_breakable void misc_model_breakable_init( gentity_t *ent ) { int type; type = MDL_OTHER; if (!ent->model) { G_Error("no model set on %s at (%.1f %.1f %.1f)\n", ent->classname, ent->s.origin[0],ent->s.origin[1],ent->s.origin[2]); } //Main model ent->s.modelindex = ent->sound2to1 = G_ModelIndex( ent->model ); if ( ent->spawnflags & 1 ) {//Blocks movement ent->r.contents = CONTENTS_SOLID|CONTENTS_OPAQUE|CONTENTS_BODY|CONTENTS_MONSTERCLIP|CONTENTS_BOTCLIP;//Was CONTENTS_SOLID, but only architecture should be this ent->s.solid = 2; //SOLID_BBOX ent->clipmask = MASK_PLAYERSOLID; } else if ( ent->health ) {//Can only be shot ent->r.contents = CONTENTS_SHOTCLIP; } if (type == MDL_OTHER) { ent->use = misc_model_use; } else if ( type == MDL_ARMOR_HEALTH ) { // G_SoundIndex("sound/player/suithealth.wav"); ent->use = health_use; if (!ent->count) { ent->count = 100; } ent->health = 60; } else if ( type == MDL_AMMO ) { // G_SoundIndex("sound/player/suitenergy.wav"); //RAFIXME: add this use function ent->use = ammo_use; if (!ent->count) { ent->count = 100; } ent->health = 60; } if ( ent->health ) { G_SoundIndex("sound/weapons/explosions/cargoexplode.wav"); ent->maxHealth = ent->health; G_ScaleNetHealth(ent); ent->takedamage = qtrue; ent->pain = misc_model_breakable_pain; //RACC - I think should be ->die ent->die = misc_model_breakable_die; //ent->think = misc_model_breakable_die; } ent->touch = misc_model_breakable_touch; }
void asteroid_field_think(gentity_t *self) { int numAsteroids = asteroid_count_num_asteroids( self ); self->nextthink = level.time + 500; if ( numAsteroids < self->count ) { //need to spawn a new asteroid gentity_t *newAsteroid = G_Spawn(); if ( newAsteroid ) { vec3_t startSpot, endSpot, startAngles; float dist, speed = flrand( self->speed * 0.25f, self->speed * 2.0f ); int capAxis, axis, time = 0; gentity_t *copyAsteroid = asteroid_pick_random_asteroid( self ); if ( copyAsteroid ) { newAsteroid->model = copyAsteroid->model; newAsteroid->model2 = copyAsteroid->model2; newAsteroid->health = copyAsteroid->health; newAsteroid->spawnflags = copyAsteroid->spawnflags; newAsteroid->mass = copyAsteroid->mass; newAsteroid->damage = copyAsteroid->damage; newAsteroid->speed = copyAsteroid->speed; G_SetOrigin( newAsteroid, copyAsteroid->s.origin ); G_SetAngles( newAsteroid, copyAsteroid->s.angles ); newAsteroid->classname = "func_rotating"; SP_func_rotating( newAsteroid ); newAsteroid->genericValue15 = copyAsteroid->genericValue15; newAsteroid->s.iModelScale = copyAsteroid->s.iModelScale; newAsteroid->maxHealth = newAsteroid->health; G_ScaleNetHealth(newAsteroid); newAsteroid->radius = copyAsteroid->radius; newAsteroid->material = copyAsteroid->material; //CacheChunkEffects( self->material ); //keep track of it newAsteroid->r.ownerNum = self->s.number; //move it capAxis = Q_irand( 0, 2 ); for ( axis = 0; axis < 3; axis++ ) { if ( axis == capAxis ) { if ( Q_irand( 0, 1 ) ) { startSpot[axis] = self->r.mins[axis]; endSpot[axis] = self->r.maxs[axis]; } else { startSpot[axis] = self->r.maxs[axis]; endSpot[axis] = self->r.mins[axis]; } } else { startSpot[axis] = self->r.mins[axis]+(flrand(0,1.0f)*(self->r.maxs[axis]-self->r.mins[axis])); endSpot[axis] = self->r.mins[axis]+(flrand(0,1.0f)*(self->r.maxs[axis]-self->r.mins[axis])); } } //FIXME: maybe trace from start to end to make sure nothing is in the way? How big of a trace? G_SetOrigin( newAsteroid, startSpot ); dist = Distance( endSpot, startSpot ); time = ceil(dist/speed)*1000; Q3_Lerp2Origin( -1, newAsteroid->s.number, endSpot, time ); //spin it startAngles[0] = flrand( -360, 360 ); startAngles[1] = flrand( -360, 360 ); startAngles[2] = flrand( -360, 360 ); G_SetAngles( newAsteroid, startAngles ); newAsteroid->s.apos.trDelta[0] = flrand( -100, 100 ); newAsteroid->s.apos.trDelta[1] = flrand( -100, 100 ); newAsteroid->s.apos.trDelta[2] = flrand( -100, 100 ); newAsteroid->s.apos.trTime = level.time; newAsteroid->s.apos.trType = TR_LINEAR; //remove itself when done newAsteroid->think = G_FreeEntity; newAsteroid->nextthink = level.time+time; //think again sooner if need even more if ( numAsteroids+1 < self->count ) {//still need at least one more //spawn it in 100ms self->nextthink = level.time + 100; } } } } }