00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "g_local.h"
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 void SP_info_camp( gentity_t *self ) {
00037 G_SetOrigin( self, self->s.origin );
00038 }
00039
00040
00041
00042
00043
00044 void SP_info_null( gentity_t *self ) {
00045 G_FreeEntity( self );
00046 }
00047
00048
00049
00050
00051
00052
00053 void SP_info_notnull( gentity_t *self ){
00054 G_SetOrigin( self, self->s.origin );
00055 }
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 void SP_light( gentity_t *self ) {
00066 G_FreeEntity( self );
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles ) {
00080 gentity_t *tent;
00081
00082
00083
00084 if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
00085 tent = G_TempEntity( player->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
00086 tent->s.clientNum = player->s.clientNum;
00087
00088 tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN );
00089 tent->s.clientNum = player->s.clientNum;
00090 }
00091
00092
00093 trap_UnlinkEntity (player);
00094
00095 VectorCopy ( origin, player->client->ps.origin );
00096 player->client->ps.origin[2] += 1;
00097
00098
00099 AngleVectors( angles, player->client->ps.velocity, NULL, NULL );
00100 VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity );
00101 player->client->ps.pm_time = 160;
00102 player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
00103
00104
00105 player->client->ps.eFlags ^= EF_TELEPORT_BIT;
00106
00107
00108 SetClientViewAngle( player, angles );
00109
00110
00111 if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
00112 G_KillBox (player);
00113 }
00114
00115
00116 BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue );
00117
00118
00119 VectorCopy( player->client->ps.origin, player->r.currentOrigin );
00120
00121 if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
00122 trap_LinkEntity (player);
00123 }
00124 }
00125
00126
00127
00128
00129
00130
00131
00132 void SP_misc_teleporter_dest( gentity_t *ent ) {
00133 }
00134
00135
00136
00137
00138
00139
00140
00141 void SP_misc_model( gentity_t *ent ) {
00142
00143 #if 0
00144 ent->s.modelindex = G_ModelIndex( ent->model );
00145 VectorSet (ent->mins, -16, -16, -16);
00146 VectorSet (ent->maxs, 16, 16, 16);
00147 trap_LinkEntity (ent);
00148
00149 G_SetOrigin( ent, ent->s.origin );
00150 VectorCopy( ent->s.angles, ent->s.apos.trBase );
00151 #else
00152 G_FreeEntity( ent );
00153 #endif
00154 }
00155
00156
00157
00158 void locateCamera( gentity_t *ent ) {
00159 vec3_t dir;
00160 gentity_t *target;
00161 gentity_t *owner;
00162
00163 owner = G_PickTarget( ent->target );
00164 if ( !owner ) {
00165 G_Printf( "Couldn't find target for misc_partal_surface\n" );
00166 G_FreeEntity( ent );
00167 return;
00168 }
00169 ent->r.ownerNum = owner->s.number;
00170
00171
00172 if ( owner->spawnflags & 1 ) {
00173 ent->s.frame = 25;
00174 } else if ( owner->spawnflags & 2 ) {
00175 ent->s.frame = 75;
00176 }
00177
00178
00179 if ( owner->spawnflags & 4 ) {
00180
00181 ent->s.powerups = 0;
00182 }
00183 else {
00184 ent->s.powerups = 1;
00185 }
00186
00187
00188 ent->s.clientNum = owner->s.clientNum;
00189
00190 VectorCopy( owner->s.origin, ent->s.origin2 );
00191
00192
00193 target = G_PickTarget( owner->target );
00194 if ( target ) {
00195 VectorSubtract( target->s.origin, owner->s.origin, dir );
00196 VectorNormalize( dir );
00197 } else {
00198 G_SetMovedir( owner->s.angles, dir );
00199 }
00200
00201 ent->s.eventParm = DirToByte( dir );
00202 }
00203
00204
00205
00206
00207
00208 void SP_misc_portal_surface(gentity_t *ent) {
00209 VectorClear( ent->r.mins );
00210 VectorClear( ent->r.maxs );
00211 trap_LinkEntity (ent);
00212
00213 ent->r.svFlags = SVF_PORTAL;
00214 ent->s.eType = ET_PORTAL;
00215
00216 if ( !ent->target ) {
00217 VectorCopy( ent->s.origin, ent->s.origin2 );
00218 } else {
00219 ent->think = locateCamera;
00220 ent->nextthink = level.time + 100;
00221 }
00222 }
00223
00224
00225
00226
00227
00228 void SP_misc_portal_camera(gentity_t *ent) {
00229 float roll;
00230
00231 VectorClear( ent->r.mins );
00232 VectorClear( ent->r.maxs );
00233 trap_LinkEntity (ent);
00234
00235 G_SpawnFloat( "roll", "0", &roll );
00236
00237 ent->s.clientNum = roll/360.0 * 256;
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 void Use_Shooter( gentity_t *ent, gentity_t *other, gentity_t *activator ) {
00249 vec3_t dir;
00250 float deg;
00251 vec3_t up, right;
00252
00253
00254 if ( ent->enemy ) {
00255 VectorSubtract( ent->enemy->r.currentOrigin, ent->s.origin, dir );
00256 VectorNormalize( dir );
00257 } else {
00258 VectorCopy( ent->movedir, dir );
00259 }
00260
00261
00262 PerpendicularVector( up, dir );
00263 CrossProduct( up, dir, right );
00264
00265 deg = crandom() * ent->random;
00266 VectorMA( dir, deg, up, dir );
00267
00268 deg = crandom() * ent->random;
00269 VectorMA( dir, deg, right, dir );
00270
00271 VectorNormalize( dir );
00272
00273 switch ( ent->s.weapon ) {
00274 case WP_GRENADE_LAUNCHER:
00275 fire_grenade( ent, ent->s.origin, dir );
00276 break;
00277 case WP_ROCKET_LAUNCHER:
00278 fire_rocket( ent, ent->s.origin, dir );
00279 break;
00280 case WP_PLASMAGUN:
00281 fire_plasma( ent, ent->s.origin, dir );
00282 break;
00283 }
00284
00285 G_AddEvent( ent, EV_FIRE_WEAPON, 0 );
00286 }
00287
00288
00289 static void InitShooter_Finish( gentity_t *ent ) {
00290 ent->enemy = G_PickTarget( ent->target );
00291 ent->think = 0;
00292 ent->nextthink = 0;
00293 }
00294
00295 void InitShooter( gentity_t *ent, int weapon ) {
00296 ent->use = Use_Shooter;
00297 ent->s.weapon = weapon;
00298
00299 RegisterItem( BG_FindItemForWeapon( weapon ) );
00300
00301 G_SetMovedir( ent->s.angles, ent->movedir );
00302
00303 if ( !ent->random ) {
00304 ent->random = 1.0;
00305 }
00306 ent->random = sin( M_PI * ent->random / 180 );
00307
00308 if ( ent->target ) {
00309 ent->think = InitShooter_Finish;
00310 ent->nextthink = level.time + 500;
00311 }
00312 trap_LinkEntity( ent );
00313 }
00314
00315
00316
00317
00318
00319 void SP_shooter_rocket( gentity_t *ent ) {
00320 InitShooter( ent, WP_ROCKET_LAUNCHER );
00321 }
00322
00323
00324
00325
00326
00327 void SP_shooter_plasma( gentity_t *ent ) {
00328 InitShooter( ent, WP_PLASMAGUN);
00329 }
00330
00331
00332
00333
00334
00335 void SP_shooter_grenade( gentity_t *ent ) {
00336 InitShooter( ent, WP_GRENADE_LAUNCHER);
00337 }
00338
00339
00340 #ifdef MISSIONPACK
00341 static void PortalDie (gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int damage, int mod) {
00342 G_FreeEntity( self );
00343
00344 }
00345
00346
00347 void DropPortalDestination( gentity_t *player ) {
00348 gentity_t *ent;
00349 vec3_t snapped;
00350
00351
00352 ent = G_Spawn();
00353 ent->s.modelindex = G_ModelIndex( "models/powerups/teleporter/tele_exit.md3" );
00354
00355 VectorCopy( player->s.pos.trBase, snapped );
00356 SnapVector( snapped );
00357 G_SetOrigin( ent, snapped );
00358 VectorCopy( player->r.mins, ent->r.mins );
00359 VectorCopy( player->r.maxs, ent->r.maxs );
00360
00361 ent->classname = "hi_portal destination";
00362 ent->s.pos.trType = TR_STATIONARY;
00363
00364 ent->r.contents = CONTENTS_CORPSE;
00365 ent->takedamage = qtrue;
00366 ent->health = 200;
00367 ent->die = PortalDie;
00368
00369 VectorCopy( player->s.apos.trBase, ent->s.angles );
00370
00371 ent->think = G_FreeEntity;
00372 ent->nextthink = level.time + 2 * 60 * 1000;
00373
00374 trap_LinkEntity( ent );
00375
00376 player->client->portalID = ++level.portalSequence;
00377 ent->count = player->client->portalID;
00378
00379
00380 player->client->ps.stats[STAT_HOLDABLE_ITEM] = BG_FindItem( "Portal" ) - bg_itemlist;
00381 }
00382
00383
00384 static void PortalTouch( gentity_t *self, gentity_t *other, trace_t *trace) {
00385 gentity_t *destination;
00386
00387
00388 if( other->health <= 0 ) {
00389 return;
00390 }
00391 if( !other->client ) {
00392 return;
00393 }
00394
00395
00396
00397
00398 if ( other->client->ps.powerups[PW_NEUTRALFLAG] ) {
00399 Drop_Item( other, BG_FindItemForPowerup( PW_NEUTRALFLAG ), 0 );
00400 other->client->ps.powerups[PW_NEUTRALFLAG] = 0;
00401 }
00402 else if ( other->client->ps.powerups[PW_REDFLAG] ) {
00403 Drop_Item( other, BG_FindItemForPowerup( PW_REDFLAG ), 0 );
00404 other->client->ps.powerups[PW_REDFLAG] = 0;
00405 }
00406 else if ( other->client->ps.powerups[PW_BLUEFLAG] ) {
00407 Drop_Item( other, BG_FindItemForPowerup( PW_BLUEFLAG ), 0 );
00408 other->client->ps.powerups[PW_BLUEFLAG] = 0;
00409 }
00410
00411
00412 destination = NULL;
00413 while( (destination = G_Find(destination, FOFS(classname), "hi_portal destination")) != NULL ) {
00414 if( destination->count == self->count ) {
00415 break;
00416 }
00417 }
00418
00419
00420 if( !destination ) {
00421 if( self->pos1[0] || self->pos1[1] || self->pos1[2] ) {
00422 TeleportPlayer( other, self->pos1, self->s.angles );
00423 }
00424 G_Damage( other, other, other, NULL, NULL, 100000, DAMAGE_NO_PROTECTION, MOD_TELEFRAG );
00425 return;
00426 }
00427
00428 TeleportPlayer( other, destination->s.pos.trBase, destination->s.angles );
00429 }
00430
00431
00432 static void PortalEnable( gentity_t *self ) {
00433 self->touch = PortalTouch;
00434 self->think = G_FreeEntity;
00435 self->nextthink = level.time + 2 * 60 * 1000;
00436 }
00437
00438
00439 void DropPortalSource( gentity_t *player ) {
00440 gentity_t *ent;
00441 gentity_t *destination;
00442 vec3_t snapped;
00443
00444
00445 ent = G_Spawn();
00446 ent->s.modelindex = G_ModelIndex( "models/powerups/teleporter/tele_enter.md3" );
00447
00448 VectorCopy( player->s.pos.trBase, snapped );
00449 SnapVector( snapped );
00450 G_SetOrigin( ent, snapped );
00451 VectorCopy( player->r.mins, ent->r.mins );
00452 VectorCopy( player->r.maxs, ent->r.maxs );
00453
00454 ent->classname = "hi_portal source";
00455 ent->s.pos.trType = TR_STATIONARY;
00456
00457 ent->r.contents = CONTENTS_CORPSE | CONTENTS_TRIGGER;
00458 ent->takedamage = qtrue;
00459 ent->health = 200;
00460 ent->die = PortalDie;
00461
00462 trap_LinkEntity( ent );
00463
00464 ent->count = player->client->portalID;
00465 player->client->portalID = 0;
00466
00467
00468
00469 ent->nextthink = level.time + 1000;
00470 ent->think = PortalEnable;
00471
00472
00473 destination = NULL;
00474 while( (destination = G_Find(destination, FOFS(classname), "hi_portal destination")) != NULL ) {
00475 if( destination->count == ent->count ) {
00476 VectorCopy( destination->s.pos.trBase, ent->pos1 );
00477 break;
00478 }
00479 }
00480
00481 }
00482 #endif