void SP_trigger_push( edict_t *self ) { InitTrigger( self ); if( st.noise && Q_stricmp( st.noise, "default" ) ) { if( Q_stricmp( st.noise, "silent" ) ) { self->moveinfo.sound_start = trap_SoundIndex( st.noise ); G_PureSound( st.noise ); } } else self->moveinfo.sound_start = trap_SoundIndex( S_JUMPPAD ); // gameteam field from editor if( st.gameteam >= TEAM_SPECTATOR && st.gameteam < GS_MAX_TEAMS ) self->s.team = st.gameteam; else self->s.team = TEAM_SPECTATOR; self->touch = trigger_push_touch; self->think = trigger_push_setup; self->nextThink = level.time + 1; self->r.svflags &= ~SVF_NOCLIENT; self->s.type = ET_PUSH_TRIGGER; self->r.svflags |= SVF_TRANSMITORIGIN2; GClip_LinkEntity( self ); // ET_PUSH_TRIGGER gets exceptions at linking so it's added for prediction self->timeStamp = level.time; if( !self->wait ) self->wait = MIN_TRIGGER_PUSH_REBOUNCE_TIME * 0.001f; }
void ThrowDebris( edict_t *self, int modelindex, float speed, vec3_t origin ) { edict_t *chunk; vec3_t v; chunk = G_Spawn(); VectorCopy( origin, chunk->s.origin ); chunk->r.svflags &= ~SVF_NOCLIENT; chunk->s.modelindex = modelindex; v[0] = 100 *crandom(); v[1] = 100 *crandom(); v[2] = 100 + 100 *crandom(); VectorMA( self->velocity, speed, v, chunk->velocity ); chunk->movetype = MOVETYPE_BOUNCE; chunk->r.solid = SOLID_NOT; chunk->avelocity[0] = random()*600; chunk->avelocity[1] = random()*600; chunk->avelocity[2] = random()*600; chunk->think = G_FreeEdict; chunk->nextThink = level.time + 5000 + random()*5000; chunk->s.frame = 0; chunk->flags = 0; chunk->classname = "debris"; chunk->takedamage = DAMAGE_YES; chunk->die = debris_die; chunk->r.owner = self; GClip_LinkEntity( chunk ); }
/* * G_TeleportPlayer */ void G_TeleportPlayer( edict_t *player, edict_t *dest ) { int i; vec3_t velocity; mat3_t axis; float speed; gclient_t *client = player->r.client; if( !dest ) { return; } if( !client ) { return; } // draw the teleport entering effect G_TeleportEffect( player, false ); // // teleport the player // // from racesow - use old pmove velocity VectorCopy( client->old_pmove.velocity, velocity ); velocity[2] = 0; // ignore vertical velocity speed = VectorLengthFast( velocity ); AnglesToAxis( dest->s.angles, axis ); VectorScale( &axis[AXIS_FORWARD], speed, client->ps.pmove.velocity ); VectorCopy( dest->s.angles, client->ps.viewangles ); VectorCopy( dest->s.origin, client->ps.pmove.origin ); // set the delta angle for ( i = 0; i < 3; i++ ) client->ps.pmove.delta_angles[i] = ANGLE2SHORT( client->ps.viewangles[i] ) - client->ucmd.angles[i]; client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT; client->ps.pmove.pm_time = 1; // force the minimum no control delay player->s.teleported = true; // update the entity from the pmove VectorCopy( client->ps.viewangles, player->s.angles ); VectorCopy( client->ps.pmove.origin, player->s.origin ); VectorCopy( client->ps.pmove.origin, player->s.old_origin ); VectorCopy( client->ps.pmove.origin, player->olds.origin ); VectorCopy( client->ps.pmove.velocity, player->velocity ); // unlink to make sure it can't possibly interfere with KillBox GClip_UnlinkEntity( player ); // kill anything at the destination KillBox( player ); GClip_LinkEntity( player ); // add the teleport effect at the destination G_TeleportEffect( player, true ); }
//========================================== // AITools_DrawPath // Draws the current path (floods as hell also) //========================================== void AITools_DrawPath( edict_t *self, int node_to ) { static unsigned int drawnpath_timeout; int count = 0; int pos = 0; //don't draw it every frame (flood) if( level.time < drawnpath_timeout ) return; drawnpath_timeout = level.time + 4 * game.snapFrameTime; if( self->ai->path.goalNode != node_to ) return; pos = self->ai->path.numNodes; // Now set up and display the path while( self->ai->path.nodes[pos] != node_to && count < 32 && pos > 0 ) { edict_t *event; event = G_SpawnEvent( EV_GREEN_LASER, 0, nodes[self->ai->path.nodes[pos]].origin ); event->r.svflags = SVF_TRANSMITORIGIN2; VectorCopy( nodes[self->ai->path.nodes[pos-1]].origin, event->s.origin2 ); G_SetBoundsForSpanEntity( event, 8 ); GClip_LinkEntity( event ); pos--; count++; } }
void SetRespawn( edict_t *ent, int delay ) { if( !ent->item ) return; if( delay < 0 ) { G_FreeEdict( ent ); return; } ent->r.svflags |= SVF_NOCLIENT; ent->r.solid = SOLID_NOT; ent->nextThink = level.time + delay; ent->think = DoRespawn; // megahealth is different if( ( ent->style & HEALTH_TIMED ) && ent->r.owner ) { ent->think = MegaHealth_think; ent->nextThink = level.time + 1; } GClip_LinkEntity( ent ); }
/* * G_GhostClient */ void G_GhostClient( edict_t *ent ) { G_DeathAwards( ent ); ent->movetype = MOVETYPE_NONE; ent->r.solid = SOLID_NOT; memset( &ent->snap, 0, sizeof( ent->snap ) ); memset( &ent->r.client->resp.snap, 0, sizeof( ent->r.client->resp.snap ) ); memset( &ent->r.client->resp.chase, 0, sizeof( ent->r.client->resp.chase ) ); memset( &ent->r.client->resp.awardInfo, 0, sizeof( ent->r.client->resp.awardInfo ) ); ent->r.client->resp.next_drown_time = 0; ent->r.client->resp.old_waterlevel = 0; ent->r.client->resp.old_watertype = 0; ent->s.modelindex = ent->s.modelindex2 = ent->s.skinnum = 0; ent->s.effects = 0; ent->s.weapon = 0; ent->s.sound = 0; ent->s.light = 0; ent->viewheight = 0; ent->takedamage = DAMAGE_NO; // clear inventory memset( ent->r.client->ps.inventory, 0, sizeof( ent->r.client->ps.inventory ) ); ent->r.client->ps.stats[STAT_WEAPON] = ent->r.client->ps.stats[STAT_PENDING_WEAPON] = WEAP_NONE; ent->r.client->ps.weaponState = WEAPON_STATE_READY; ent->r.client->ps.stats[STAT_WEAPON_TIME] = 0; G_SetPlayerHelpMessage( ent, 0 ); GClip_LinkEntity( ent ); }
//QUAKED light_mine (0 1 0) (-2 -2 -12) (2 2 12) void SP_light_mine( edict_t *ent ) { ent->movetype = MOVETYPE_NONE; ent->r.solid = SOLID_YES; ent->s.modelindex = trap_ModelIndex( "models/objects/minelite/light1/tris.md2" ); GClip_LinkEntity( ent ); }
//========================================== // BOT_SpawnBot // Used Spawn the bot //========================================== void BOT_SpawnBot( const char *team_name ) { edict_t *spawner; int team; if( level.spawnedTimeStamp + 5000 > game.realtime || !level.canSpawnEntities ) return; if( !nav.loaded ) { Com_Printf( "AI: Can't spawn bots without a valid navigation file\n" ); if( g_numbots->integer ) trap_Cvar_Set( "g_numbots", "0" ); return; } // create a entity which will call the bot spawn spawner = G_Spawn(); spawner->think = BOT_SpawnerThink; team = GS_Teams_TeamFromName( team_name ); if( team != -1 ) spawner->s.team = team; spawner->nextThink = level.time + random() * 3000; spawner->movetype = MOVETYPE_NONE; spawner->r.solid = SOLID_NOT; spawner->r.svflags |= SVF_NOCLIENT; GClip_LinkEntity( spawner ); game.numBots++; }
void SetRespawn( edict_t *ent, int delay ) { if( !ent->item ) return; if( delay < 0 ) { G_FreeEdict( ent ); return; } ent->r.solid = SOLID_NOT; ent->nextThink = level.time + delay; ent->think = DoRespawn; if( GS_MatchState() == MATCH_STATE_WARMUP ) { ent->s.effects |= EF_GHOST; } else { ent->r.svflags |= SVF_NOCLIENT; } // megahealth is different if( ( ent->spawnflags & ITEM_TIMED ) && ent->r.owner ) { if( ent->item->type == IT_HEALTH ) { ent->think = MegaHealth_think; ent->nextThink = level.time + 1; } } GClip_LinkEntity( ent ); }
void ThrowClientHead( edict_t *self, int damage ) { vec3_t vd; self->s.modelindex = 1; self->s.modelindex2 = 0; self->s.skinnum = 0; self->s.origin[2] += 32; self->s.frame = 0; VectorSet( self->r.mins, -16, -16, 0 ); VectorSet( self->r.maxs, 16, 16, 16 ); self->takedamage = DAMAGE_NO; self->r.solid = SOLID_NOT; self->s.type = ET_GIB; self->s.sound = 0; self->s.effects = 0; self->flags |= FL_NO_KNOCKBACK; self->movetype = MOVETYPE_BOUNCE; VelocityForDamage( max( damage, 50 ), vd ); VectorAdd( self->velocity, vd, self->velocity ); G_AddEvent( self, EV_GIB, 0, false ); GClip_LinkEntity( self ); }
/* * W_Fire_Grenade */ edict_t *W_Fire_Grenade( edict_t *self, vec3_t start, vec3_t dir, int speed, float damage, int minKnockback, int maxKnockback, int stun, int minDamage, float radius, int timeout, int mod, int timeDelta ) { edict_t *grenade; if( GS_Instagib() ) { damage = 9999; } grenade = W_Fire_TossProjectile( self, start, dir, speed, damage, minKnockback, maxKnockback, stun, minDamage, radius, timeout, timeDelta ); VectorClear( grenade->s.angles ); grenade->style = mod; grenade->s.type = ET_GRENADE; grenade->movetype = MOVETYPE_BOUNCEGRENADE; grenade->touch = W_Touch_Grenade; grenade->use = NULL; grenade->think = W_Grenade_Explode; grenade->classname = "grenade"; grenade->enemy = NULL; VectorSet( grenade->avelocity, 300, 300, 300 ); if( mod == MOD_GRENADE_S ) { grenade->s.modelindex = trap_ModelIndex( PATH_GRENADE_STRONG_MODEL ); grenade->s.effects |= EF_STRONG_WEAPON; } else { grenade->s.modelindex = trap_ModelIndex( PATH_GRENADE_WEAK_MODEL ); grenade->s.effects &= ~EF_STRONG_WEAPON; } GClip_LinkEntity( grenade ); return grenade; }
void SP_func_object( edict_t *self ) { G_InitMover( self ); self->r.mins[0] += 1; self->r.mins[1] += 1; self->r.mins[2] += 1; self->r.maxs[0] -= 1; self->r.maxs[1] -= 1; self->r.maxs[2] -= 1; if( !self->dmg ) self->dmg = 100; if( self->spawnflags == 0 ) { self->r.solid = SOLID_YES; self->movetype = MOVETYPE_PUSH; self->think = func_object_release; self->nextThink = level.time + self->wait * 1000; self->r.svflags &= ~SVF_NOCLIENT; } else { self->r.solid = SOLID_NOT; self->movetype = MOVETYPE_PUSH; self->use = func_object_use; self->r.svflags |= SVF_NOCLIENT; } self->r.clipmask = MASK_MONSTERSOLID; GClip_LinkEntity( self ); }
void SP_func_static( edict_t *ent ) { G_InitMover( ent ); ent->movetype = MOVETYPE_NONE; ent->r.svflags = SVF_BROADCAST; GClip_LinkEntity( ent ); }
/* * body_ready */ static void body_ready( edict_t *body ) { body->takedamage = DAMAGE_YES; body->r.solid = SOLID_YES; body->think = body_think; // body self destruction countdown body->nextThink = level.time + g_deadbody_autogib_delay->integer + ( crandom() * g_deadbody_autogib_delay->value * 0.25f ) ; GClip_LinkEntity( body ); }
static void func_explosive_spawn( edict_t *self, edict_t *other, edict_t *activator ) { self->r.solid = SOLID_YES; self->r.svflags &= ~SVF_NOCLIENT; self->use = NULL; KillBox( self ); GClip_LinkEntity( self ); }
//========================================== // AITools_DrawLine // Just so I don't hate to write the event every time //========================================== void AITools_DrawLine( vec3_t origin, vec3_t dest ) { edict_t *event; event = G_SpawnEvent( EV_GREEN_LASER, 0, origin ); event->r.svflags = SVF_TRANSMITORIGIN2; VectorCopy( dest, event->s.origin2 ); G_SetBoundsForSpanEntity( event, 8 ); GClip_LinkEntity( event ); }
void SP_func_wall( edict_t *self ) { G_InitMover( self ); self->s.solid = SOLID_NOT; // just a wall if( ( self->spawnflags & 7 ) == 0 ) { self->r.solid = SOLID_YES; GClip_LinkEntity( self ); return; } // it must be TRIGGER_SPAWN if( !( self->spawnflags & 1 ) ) { // G_Printf ("func_wall missing TRIGGER_SPAWN\n"); self->spawnflags |= 1; } // yell if the spawnflags are odd if( self->spawnflags & 4 ) { if( !( self->spawnflags & 2 ) ) { if( developer->integer ) G_Printf( "func_wall START_ON without TOGGLE\n" ); self->spawnflags |= 2; } } self->use = func_wall_use; if( self->spawnflags & 4 ) { self->r.solid = SOLID_YES; } else { self->r.solid = SOLID_NOT; self->r.svflags |= SVF_NOCLIENT; } GClip_LinkEntity( self ); }
/* * W_Fire_LinearProjectile - Spawn a generic linear projectile without a model, touch func, sound nor mod */ static edict_t *W_Fire_LinearProjectile( edict_t *self, vec3_t start, vec3_t angles, int speed, float damage, int minKnockback, int maxKnockback, int stun, int minDamage, int radius, int timeout, int timeDelta ) { edict_t *projectile; vec3_t dir; projectile = G_Spawn(); VectorCopy( start, projectile->s.origin ); VectorCopy( start, projectile->s.old_origin ); VectorCopy( start, projectile->olds.origin ); VectorCopy( angles, projectile->s.angles ); AngleVectors( angles, dir, NULL, NULL ); VectorScale( dir, speed, projectile->velocity ); GS_SnapVelocity( projectile->velocity ); projectile->movetype = MOVETYPE_LINEARPROJECTILE; projectile->s.linearProjectile = qtrue; projectile->r.solid = SOLID_YES; projectile->r.clipmask = ( !GS_RaceGametype() ) ? MASK_SHOT : MASK_SOLID; projectile->r.svflags = SVF_PROJECTILE; // enable me when drawing exception is added to cgame projectile->r.svflags |= SVF_TRANSMITORIGIN2; VectorClear( projectile->r.mins ); VectorClear( projectile->r.maxs ); projectile->s.modelindex = 0; projectile->r.owner = self; projectile->s.ownerNum = ENTNUM( self ); projectile->touch = W_Touch_Projectile; //generic one. Should be replaced after calling this func projectile->nextThink = level.time + timeout; projectile->think = G_FreeEdict; projectile->classname = NULL; // should be replaced after calling this func. projectile->style = 0; projectile->s.sound = 0; projectile->timeStamp = level.time; projectile->s.linearProjectileTimeStamp = game.serverTime; projectile->timeDelta = timeDelta; projectile->projectileInfo.minDamage = min( minDamage, damage ); projectile->projectileInfo.maxDamage = damage; projectile->projectileInfo.minKnockback = min( minKnockback, maxKnockback ); projectile->projectileInfo.maxKnockback = maxKnockback; projectile->projectileInfo.stun = stun; projectile->projectileInfo.radius = radius; GClip_LinkEntity( projectile ); // update some data required for the transmission VectorCopy( projectile->velocity, projectile->s.linearProjectileVelocity ); projectile->s.team = self->s.team; projectile->s.modelindex2 = ( abs( timeDelta ) > 255 ) ? 255 : (unsigned int)abs( timeDelta ); return projectile; }
void SP_misc_portal_camera( edict_t *ent ) { VectorClear( ent->r.mins ); VectorClear( ent->r.maxs ); GClip_LinkEntity( ent ); ent->r.svflags = SVF_NOCLIENT; ent->count = (int)( st.roll / 360.0f * 256.0f ); if( st.noents ) ent->speed = 1; }
//========================================== // AITools_DrawColorLine // Just so I don't hate to write the event every time //========================================== void AITools_DrawColorLine( vec3_t origin, vec3_t dest, int color, int parm ) { edict_t *event; event = G_SpawnEvent( EV_PNODE, parm, origin ); event->s.colorRGBA = color; event->r.svflags = SVF_TRANSMITORIGIN2; VectorCopy( dest, event->s.origin2 ); G_SetBoundsForSpanEntity( event, 8 ); GClip_LinkEntity( event ); }
static void hurt_use( edict_t *self, edict_t *other, edict_t *activator ) { if( self->r.solid == SOLID_NOT ) self->r.solid = SOLID_TRIGGER; else self->r.solid = SOLID_NOT; GClip_LinkEntity( self ); if( !( self->spawnflags & 2 ) ) self->use = NULL; }
/* * SV_PushEntity * * Does not change the entities velocity at all */ static trace_t SV_PushEntity( edict_t *ent, vec3_t push ) { trace_t trace; vec3_t start; vec3_t end; int mask; VectorCopy( ent->s.origin, start ); VectorAdd( start, push, end ); retry: if( ent->r.clipmask ) { mask = ent->r.clipmask; } else { mask = MASK_SOLID; } G_Trace4D( &trace, start, ent->r.mins, ent->r.maxs, end, ent, mask, ent->timeDelta ); if( ent->movetype == MOVETYPE_PUSH || !trace.startsolid ) { VectorCopy( trace.endpos, ent->s.origin ); } GClip_LinkEntity( ent ); if( trace.fraction < 1.0 ) { SV_Impact( ent, &trace ); // if the pushed entity went away and the pusher is still there if( !game.edicts[trace.ent].r.inuse && ent->movetype == MOVETYPE_PUSH && ent->r.inuse ) { // move the pusher back and try again VectorCopy( start, ent->s.origin ); GClip_LinkEntity( ent ); goto retry; } } if( ent->r.inuse ) { GClip_TouchTriggers( ent ); } return trace; }
/* * G_ProjectileDistancePrestep */ static void G_ProjectileDistancePrestep( edict_t *projectile, float distance ) { float speed; vec3_t dir, dest; int mask, i; trace_t trace; #ifdef PLASMAHACK vec3_t plasma_hack_start; #endif if( projectile->movetype != MOVETYPE_TOSS && projectile->movetype != MOVETYPE_LINEARPROJECTILE && projectile->movetype != MOVETYPE_BOUNCE && projectile->movetype != MOVETYPE_BOUNCEGRENADE ) return; if( !distance ) return; if( ( speed = VectorNormalize2( projectile->velocity, dir ) ) == 0.0f ) return; mask = ( projectile->r.clipmask ) ? projectile->r.clipmask : MASK_SHOT; // race trick should come set up inside clipmask if( projectile->movetype == MOVETYPE_LINEARPROJECTILE ) VectorCopy( projectile->s.origin2, projectile->s.origin ); #ifdef PLASMAHACK VectorCopy( projectile->s.origin, plasma_hack_start ); #endif VectorMA( projectile->s.origin, distance, dir, dest ); G_Trace4D( &trace, projectile->s.origin, projectile->r.mins, projectile->r.maxs, dest, projectile->r.owner, mask, projectile->timeDelta ); for( i = 0; i < 3; i++ ) projectile->s.origin[i] = projectile->s.origin2[i] = projectile->olds.origin[i] = projectile->olds.origin2[i] = trace.endpos[i]; GClip_LinkEntity( projectile ); SV_Impact( projectile, &trace ); // set initial water state if( !projectile->r.inuse ) return; projectile->waterlevel = ( G_PointContents4D( projectile->s.origin, projectile->timeDelta ) & MASK_WATER ) ? qtrue : qfalse; // ffs : hack for the plasmagun #ifdef PLASMAHACK if( projectile->s.type == ET_PLASMA ) if (trap_Cvar_Get( "rs_plasma_hack", "1", CVAR_ARCHIVE )->integer==1)//racesow W_Plasma_Backtrace( projectile, plasma_hack_start ); #endif }
/* * W_Fire_TossProjectile - Spawn a generic projectile without a model, touch func, sound nor mod */ static edict_t *W_Fire_TossProjectile( edict_t *self, vec3_t start, vec3_t angles, int speed, float damage, int minKnockback, int maxKnockback, int stun, int minDamage, int radius, int timeout, int timeDelta ) { edict_t *projectile; vec3_t dir; projectile = G_Spawn(); VectorCopy( start, projectile->s.origin ); VectorCopy( start, projectile->s.old_origin ); VectorCopy( start, projectile->olds.origin ); VectorCopy( angles, projectile->s.angles ); AngleVectors( angles, dir, NULL, NULL ); VectorScale( dir, speed, projectile->velocity ); GS_SnapVelocity( projectile->velocity ); projectile->movetype = MOVETYPE_BOUNCEGRENADE; // make missile fly through players in race if( GS_RaceGametype() ) projectile->r.clipmask = MASK_SOLID; else projectile->r.clipmask = MASK_SHOT; projectile->r.solid = SOLID_YES; projectile->r.svflags = SVF_PROJECTILE; VectorClear( projectile->r.mins ); VectorClear( projectile->r.maxs ); //projectile->s.modelindex = trap_ModelIndex ("models/objects/projectile/plasmagun/proj_plasmagun2.md3"); projectile->s.modelindex = 0; projectile->r.owner = self; projectile->touch = W_Touch_Projectile; //generic one. Should be replaced after calling this func projectile->nextThink = level.time + timeout; projectile->think = G_FreeEdict; projectile->classname = NULL; // should be replaced after calling this func. projectile->style = 0; projectile->s.sound = 0; projectile->timeStamp = level.time; projectile->timeDelta = timeDelta; projectile->s.team = self->s.team; projectile->projectileInfo.minDamage = min( minDamage, damage ); projectile->projectileInfo.maxDamage = damage; projectile->projectileInfo.minKnockback = min( minKnockback, maxKnockback ); projectile->projectileInfo.maxKnockback = maxKnockback; projectile->projectileInfo.stun = stun; projectile->projectileInfo.radius = radius; GClip_LinkEntity( projectile ); return projectile; }
/* * W_Fire_Grenade */ edict_t *W_Fire_Grenade( edict_t *self, vec3_t start, vec3_t angles, int speed, float damage, int minKnockback, int maxKnockback, int stun, int minDamage, float radius, int timeout, int mod, int timeDelta, qboolean aim_up ) { edict_t *grenade; static cvar_t *g_grenade_gravity = NULL; if( GS_Instagib() ) damage = 9999; if( !g_grenade_gravity ) g_grenade_gravity = trap_Cvar_Get( "g_grenade_gravity", "1.3", CVAR_DEVELOPER ); if( aim_up ) { angles[PITCH] -= 10; // aim some degrees upwards from view dir // clamp to front side of the player angles[PITCH] += -90; // rotate to make easier the check while( angles[PITCH] < -360 ) angles[PITCH] += 360; clamp( angles[PITCH], -180, 0 ); angles[PITCH] += 90; while( angles[PITCH] > 360 ) angles[PITCH] -= 360; } grenade = W_Fire_TossProjectile( self, start, angles, speed, damage, minKnockback, maxKnockback, stun, minDamage, radius, timeout, timeDelta ); VectorClear( grenade->s.angles ); grenade->style = mod; grenade->s.type = ET_GRENADE; grenade->movetype = MOVETYPE_BOUNCEGRENADE; grenade->touch = W_Touch_Grenade; grenade->use = NULL; grenade->think = W_Grenade_Explode; grenade->classname = "grenade"; grenade->gravity = g_grenade_gravity->value; grenade->enemy = NULL; if( mod == MOD_GRENADE_S ) { grenade->s.modelindex = trap_ModelIndex( PATH_GRENADE_STRONG_MODEL ); grenade->s.effects |= EF_STRONG_WEAPON; } else { grenade->s.modelindex = trap_ModelIndex( PATH_GRENADE_WEAK_MODEL ); grenade->s.effects &= ~EF_STRONG_WEAPON; } GClip_LinkEntity( grenade ); return grenade; }
static void use_target_spawner( edict_t *self, edict_t *other, edict_t *activator ) { edict_t *ent; ent = G_Spawn(); ent->classname = self->target; VectorCopy( self->s.origin, ent->s.origin ); VectorCopy( self->s.angles, ent->s.angles ); G_CallSpawn( ent ); GClip_UnlinkEntity( ent ); KillBox( ent ); GClip_LinkEntity( ent ); if( self->speed ) VectorCopy( self->moveinfo.movedir, ent->velocity ); }
/* * GClip_SetBrushModel * * Also sets mins and maxs for inline bmodels */ void GClip_SetBrushModel( edict_t *ent, char *name ) { struct cmodel_s *cmodel; if( !name ) { //racesow G_Printf( "Warning: GClip_SetBrushModel: NULL model in '%s'", ent->classname ? ent->classname : "no classname\n" ); GClip_UnlinkEntity( ent ); G_FreeEdict( ent ); return; //!racesow } if( !name[0] ) { ent->s.modelindex = 0; return; } if( name[0] != '*' ) { ent->s.modelindex = trap_ModelIndex( name ); return; } // if it is an inline model, get the size information for it // world model is special if( !strcmp( name, "*0" ) ) { ent->s.modelindex = 0; cmodel = trap_CM_InlineModel( 0 ); trap_CM_InlineModelBounds( cmodel, ent->r.mins, ent->r.maxs ); return; } // racesow: THIS IS A VERY DIRTY "FIX": it assigns normally unreachable models (the ones over MAX_MODELS) to unrelated models.. // normally this only affects buggy maps that otherwise wouldn't load (like amt-freestyle3) // brush model //ent->s.modelindex = trap_ModelIndex( name ); // <- This is the unmodified version ent->s.modelindex = atoi( name+1 ); // !racesow assert( ent->s.modelindex == (unsigned int)atoi( name + 1 ) ); cmodel = trap_CM_InlineModel( ent->s.modelindex ); trap_CM_InlineModelBounds( cmodel, ent->r.mins, ent->r.maxs ); GClip_LinkEntity( ent ); }
void SP_path_corner( edict_t *self ) { if( !self->targetname ) { if( developer->integer ) G_Printf( "path_corner with no targetname at %s\n", vtos( self->s.origin ) ); G_FreeEdict( self ); return; } self->r.solid = SOLID_TRIGGER; self->touch = path_corner_touch; VectorSet( self->r.mins, -8, -8, -8 ); VectorSet( self->r.maxs, 8, 8, 8 ); self->r.svflags |= SVF_NOCLIENT; GClip_LinkEntity( self ); }
/* * GClip_SetBrushModel * * Also sets mins and maxs for inline bmodels */ void GClip_SetBrushModel( edict_t *ent, const char *name ) { struct cmodel_s *cmodel; if( !name ) { G_Error( "GClip_SetBrushModel: NULL model in '%s'", ent->classname ? ent->classname : "no classname" ); // racesow GClip_UnlinkEntity( ent ); G_FreeEdict( ent ); return; // !racesow } if( !name[0] ) { ent->s.modelindex = 0; return; } if( name[0] != '*' ) { ent->s.modelindex = trap_ModelIndex( name ); return; } // if it is an inline model, get the size information for it // world model is special if( !strcmp( name, "*0" ) ) { ent->s.modelindex = 0; cmodel = trap_CM_InlineModel( 0 ); trap_CM_InlineModelBounds( cmodel, ent->r.mins, ent->r.maxs ); return; } // brush model ent->s.modelindex = trap_ModelIndex( name ); assert( ent->s.modelindex == (unsigned int)atoi( name + 1 ) ); cmodel = trap_CM_InlineModel( ent->s.modelindex ); trap_CM_InlineModelBounds( cmodel, ent->r.mins, ent->r.maxs ); GClip_LinkEntity( ent ); }
/* * W_Fire_Lasergun */ edict_t *W_Fire_Lasergun( edict_t *self, vec3_t start, vec3_t angles, float damage, int knockback, int stun, int range, int mod, int timeDelta ) { edict_t *laser; qboolean newLaser; trace_t tr; vec3_t dir; if( GS_Instagib() ) damage = 9999; laser = _FindOrSpawnLaser( self, ET_LASERBEAM, &newLaser ); if( newLaser ) { // the quad start sound is added from the server if( self->r.client && self->r.client->ps.inventory[POWERUP_QUAD] > 0 ) G_Sound( self, CHAN_AUTO, trap_SoundIndex( S_QUAD_FIRE ), ATTN_NORM ); } laser_damage = damage; laser_knockback = knockback; laser_stun = stun; laser_attackerNum = ENTNUM( self ); laser_mod = mod; laser_missed = qtrue; GS_TraceLaserBeam( &tr, start, angles, range, ENTNUM( self ), timeDelta, _LaserImpact ); laser->r.svflags |= SVF_FORCEOWNER; VectorCopy( start, laser->s.origin ); AngleVectors( angles, dir, NULL, NULL ); VectorMA( laser->s.origin, range, dir, laser->s.origin2 ); laser->think = G_Laser_Think; laser->nextThink = level.time + 100; if( laser_missed && self->r.client ) G_AwardPlayerMissedLasergun( self, mod ); // calculate laser's mins and maxs for linkEntity G_SetBoundsForSpanEntity( laser, 8 ); GClip_LinkEntity( laser ); return laser; }