00001
00002
00003
00004
00005 #include "g_local.h"
00006 #include "../ghoul2/G2.h"
00007
00008 #include "ai_main.h"
00009
00010 #define HOLOCRON_RESPAWN_TIME 30000
00011 #define MAX_AMMO_GIVE 2
00012 #define STATION_RECHARGE_TIME 100
00013
00014 void HolocronThink(gentity_t *ent);
00015 extern vmCvar_t g_MaxHolocronCarry;
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 void SP_info_camp( gentity_t *self ) {
00026 G_SetOrigin( self, self->s.origin );
00027 }
00028
00029
00030
00031
00032
00033 void SP_info_null( gentity_t *self ) {
00034 G_FreeEntity( self );
00035 }
00036
00037
00038
00039
00040
00041
00042 void SP_info_notnull( gentity_t *self ){
00043 G_SetOrigin( self, self->s.origin );
00044 }
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 static void misc_lightstyle_set ( gentity_t *ent)
00087 {
00088 const int mLightStyle = ent->count;
00089 const int mLightSwitchStyle = ent->bounceCount;
00090 const int mLightOffStyle = ent->fly_sound_debounce_time;
00091 if (!ent->alt_fire)
00092 {
00093 if (mLightOffStyle)
00094 {
00095 char lightstyle[32];
00096 trap_GetConfigstring(CS_LIGHT_STYLES + (mLightOffStyle*3)+0, lightstyle, 32);
00097 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+0, lightstyle);
00098
00099 trap_GetConfigstring(CS_LIGHT_STYLES + (mLightOffStyle*3)+1, lightstyle, 32);
00100 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+1, lightstyle);
00101
00102 trap_GetConfigstring(CS_LIGHT_STYLES + (mLightOffStyle*3)+2, lightstyle, 32);
00103 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+2, lightstyle);
00104 }else
00105 {
00106 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+0, "a");
00107 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+1, "a");
00108 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+2, "a");
00109 }
00110 }
00111 else
00112 {
00113 if (mLightSwitchStyle)
00114 {
00115 char lightstyle[32];
00116 trap_GetConfigstring(CS_LIGHT_STYLES + (mLightSwitchStyle*3)+0, lightstyle, 32);
00117 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+0, lightstyle);
00118
00119 trap_GetConfigstring(CS_LIGHT_STYLES + (mLightSwitchStyle*3)+1, lightstyle, 32);
00120 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+1, lightstyle);
00121
00122 trap_GetConfigstring(CS_LIGHT_STYLES + (mLightSwitchStyle*3)+2, lightstyle, 32);
00123 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+2, lightstyle);
00124 }
00125 else
00126 {
00127 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+0, "z");
00128 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+1, "z");
00129 trap_SetConfigstring(CS_LIGHT_STYLES + (mLightStyle*3)+2, "z");
00130 }
00131 }
00132 }
00133
00134 void misc_dlight_use ( gentity_t *ent, gentity_t *other, gentity_t *activator )
00135 {
00136 G_ActivateBehavior(ent,BSET_USE);
00137
00138 ent->alt_fire = !ent->alt_fire;
00139 misc_lightstyle_set (ent);
00140 }
00141
00142 void SP_light( gentity_t *self ) {
00143 if (!self->targetname )
00144 {
00145 G_FreeEntity( self );
00146 return;
00147 }
00148
00149 G_SpawnInt( "style", "0", &self->count );
00150 G_SpawnInt( "switch_style", "0", &self->bounceCount );
00151 G_SpawnInt( "style_off", "0", &self->fly_sound_debounce_time );
00152 G_SetOrigin( self, self->s.origin );
00153 trap_LinkEntity( self );
00154
00155 self->use = misc_dlight_use;
00156
00157 self->s.eType = ET_GENERAL;
00158 self->alt_fire = qfalse;
00159 self->r.svFlags |= SVF_NOCLIENT;
00160
00161 if ( !(self->spawnflags & 4) )
00162 {
00163 self->alt_fire = qtrue;
00164 }
00165 misc_lightstyle_set (self);
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles ) {
00178 gentity_t *tent;
00179 qboolean isNPC = qfalse;
00180 if (player->s.eType == ET_NPC)
00181 {
00182 isNPC = qtrue;
00183 }
00184
00185
00186
00187 if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
00188 tent = G_TempEntity( player->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
00189 tent->s.clientNum = player->s.clientNum;
00190
00191 tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN );
00192 tent->s.clientNum = player->s.clientNum;
00193 }
00194
00195
00196 trap_UnlinkEntity (player);
00197
00198 VectorCopy ( origin, player->client->ps.origin );
00199 player->client->ps.origin[2] += 1;
00200
00201
00202 AngleVectors( angles, player->client->ps.velocity, NULL, NULL );
00203 VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity );
00204 player->client->ps.pm_time = 160;
00205 player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
00206
00207
00208 player->client->ps.eFlags ^= EF_TELEPORT_BIT;
00209
00210
00211 SetClientViewAngle( player, angles );
00212
00213
00214 if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
00215 G_KillBox (player);
00216 }
00217
00218
00219 BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue );
00220 if (isNPC)
00221 {
00222 player->s.eType = ET_NPC;
00223 }
00224
00225
00226 VectorCopy( player->client->ps.origin, player->r.currentOrigin );
00227
00228 if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
00229 trap_LinkEntity (player);
00230 }
00231 }
00232
00233
00234
00235
00236
00237
00238
00239 void SP_misc_teleporter_dest( gentity_t *ent ) {
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249 void SP_misc_model( gentity_t *ent ) {
00250
00251 #if 0
00252 ent->s.modelindex = G_ModelIndex( ent->model );
00253 VectorSet (ent->r.mins, -16, -16, -16);
00254 VectorSet (ent->r.maxs, 16, 16, 16);
00255 trap_LinkEntity (ent);
00256
00257 G_SetOrigin( ent, ent->s.origin );
00258 VectorCopy( ent->s.angles, ent->s.apos.trBase );
00259 #else
00260 G_FreeEntity( ent );
00261 #endif
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 void SP_misc_model_static(gentity_t *ent)
00278 {
00279 G_FreeEntity( ent );
00280 }
00281
00282
00283
00284
00285 void SP_misc_G2model( gentity_t *ent ) {
00286
00287 #if 0
00288 char name1[200] = "models/players/kyle/modelmp.glm";
00289 trap_G2API_InitGhoul2Model(&ent->s, name1, G_ModelIndex( name1 ), 0, 0, 0, 0);
00290 trap_G2API_SetBoneAnim(ent->s.ghoul2, 0, "model_root", 0, 12, BONE_ANIM_OVERRIDE_LOOP, 1.0f, level.time, -1, -1);
00291 ent->s.radius = 150;
00292
00293
00294 trap_LinkEntity (ent);
00295
00296 G_SetOrigin( ent, ent->s.origin );
00297 VectorCopy( ent->s.angles, ent->s.apos.trBase );
00298 #else
00299 G_FreeEntity( ent );
00300 #endif
00301 }
00302
00303
00304
00305 void locateCamera( gentity_t *ent ) {
00306 vec3_t dir;
00307 gentity_t *target;
00308 gentity_t *owner;
00309
00310 owner = G_PickTarget( ent->target );
00311 if ( !owner ) {
00312 G_Printf( "Couldn't find target for misc_partal_surface\n" );
00313 G_FreeEntity( ent );
00314 return;
00315 }
00316 ent->r.ownerNum = owner->s.number;
00317
00318
00319 if ( owner->spawnflags & 1 ) {
00320 ent->s.frame = 25;
00321 } else if ( owner->spawnflags & 2 ) {
00322 ent->s.frame = 75;
00323 }
00324
00325
00326 if ( owner->spawnflags & 4 ) {
00327
00328 ent->s.powerups = 0;
00329 }
00330 else {
00331 ent->s.powerups = 1;
00332 }
00333
00334
00335 ent->s.clientNum = owner->s.clientNum;
00336
00337 VectorCopy( owner->s.origin, ent->s.origin2 );
00338
00339
00340 target = G_PickTarget( owner->target );
00341 if ( target ) {
00342 VectorSubtract( target->s.origin, owner->s.origin, dir );
00343 VectorNormalize( dir );
00344 } else {
00345 G_SetMovedir( owner->s.angles, dir );
00346 }
00347
00348 ent->s.eventParm = DirToByte( dir );
00349 }
00350
00351
00352
00353
00354
00355 void SP_misc_portal_surface(gentity_t *ent) {
00356 VectorClear( ent->r.mins );
00357 VectorClear( ent->r.maxs );
00358 trap_LinkEntity (ent);
00359
00360 ent->r.svFlags = SVF_PORTAL;
00361 ent->s.eType = ET_PORTAL;
00362
00363 if ( !ent->target ) {
00364 VectorCopy( ent->s.origin, ent->s.origin2 );
00365 } else {
00366 ent->think = locateCamera;
00367 ent->nextthink = level.time + 100;
00368 }
00369 }
00370
00371
00372
00373
00374
00375 void SP_misc_portal_camera(gentity_t *ent) {
00376 float roll;
00377
00378 VectorClear( ent->r.mins );
00379 VectorClear( ent->r.maxs );
00380 trap_LinkEntity (ent);
00381
00382 G_SpawnFloat( "roll", "0", &roll );
00383
00384 ent->s.clientNum = roll/360.0 * 256;
00385 }
00386
00387
00388
00389
00390 void SP_misc_bsp(gentity_t *ent)
00391 {
00392 char temp[MAX_QPATH];
00393 char *out;
00394 float newAngle;
00395 int tempint;
00396
00397 G_SpawnFloat( "angle", "0", &newAngle );
00398 if (newAngle != 0.0)
00399 {
00400 ent->s.angles[1] = newAngle;
00401 }
00402
00403 ent->s.angles[0] = 0.0;
00404 ent->s.angles[2] = 0.0;
00405
00406 G_SpawnString("bspmodel", "", &out);
00407
00408 ent->s.eFlags = EF_PERMANENT;
00409
00410
00411 G_SpawnInt( "spacing", "0", &tempint);
00412 ent->s.time2 = tempint;
00413 G_SpawnInt( "flatten", "0", &tempint);
00414 ent->s.time = tempint;
00415
00416 Com_sprintf(temp, MAX_QPATH, "#%s", out);
00417 trap_SetBrushModel( ent, temp );
00418 G_BSPIndex(temp);
00419
00420 level.mNumBSPInstances++;
00421 Com_sprintf(temp, MAX_QPATH, "%d-", level.mNumBSPInstances);
00422 VectorCopy(ent->s.origin, level.mOriginAdjust);
00423 level.mRotationAdjust = ent->s.angles[1];
00424 level.mTargetAdjust = temp;
00425
00426 level.mBSPInstanceDepth++;
00427
00428
00429
00430
00431 G_SpawnString("teamfilter", "", &out);
00432 strcpy(level.mTeamFilter, out);
00433
00434 VectorCopy( ent->s.origin, ent->s.pos.trBase );
00435 VectorCopy( ent->s.origin, ent->r.currentOrigin );
00436 VectorCopy( ent->s.angles, ent->s.apos.trBase );
00437 VectorCopy( ent->s.angles, ent->r.currentAngles );
00438
00439 ent->s.eType = ET_MOVER;
00440
00441 trap_LinkEntity (ent);
00442
00443 trap_SetActiveSubBSP(ent->s.modelindex);
00444 G_SpawnEntitiesFromString(qtrue);
00445 trap_SetActiveSubBSP(-1);
00446
00447 level.mBSPInstanceDepth--;
00448
00449 level.mTeamFilter[0] = 0;
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 void AddSpawnField(char *field, char *value);
00483 #define MAX_INSTANCE_TYPES 16
00484 void SP_terrain(gentity_t *ent)
00485 {
00486 char temp[MAX_INFO_STRING];
00487 char final[MAX_QPATH];
00488 char seed[MAX_QPATH];
00489 char missionType[MAX_QPATH];
00490
00491 int shaderNum, i;
00492 char *value;
00493 int terrainID;
00494
00495
00496 trap_Cvar_Set("RMG", "1");
00497 g_RMG.integer = 1;
00498
00499 VectorClear (ent->s.angles);
00500 trap_SetBrushModel( ent, ent->model );
00501
00502
00503
00504 shaderNum = 0;
00505
00506 if (g_RMG.integer)
00507 {
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 trap_Cvar_VariableStringBuffer("RMG_seed", seed, MAX_QPATH);
00525 trap_Cvar_VariableStringBuffer("RMG_mission", missionType, MAX_QPATH);
00526
00527
00528
00529
00530 }
00531
00532
00533 temp[0] = 0;
00534 G_SpawnString("heightmap", "", &value);
00535 Info_SetValueForKey(temp, "heightMap", value);
00536
00537 G_SpawnString("numpatches", "400", &value);
00538 Info_SetValueForKey(temp, "numPatches", va("%d", atoi(value)));
00539
00540 G_SpawnString("terxels", "4", &value);
00541 Info_SetValueForKey(temp, "terxels", va("%d", atoi(value)));
00542
00543 Info_SetValueForKey(temp, "seed", seed);
00544 Info_SetValueForKey(temp, "minx", va("%f", ent->r.mins[0]));
00545 Info_SetValueForKey(temp, "miny", va("%f", ent->r.mins[1]));
00546 Info_SetValueForKey(temp, "minz", va("%f", ent->r.mins[2]));
00547 Info_SetValueForKey(temp, "maxx", va("%f", ent->r.maxs[0]));
00548 Info_SetValueForKey(temp, "maxy", va("%f", ent->r.maxs[1]));
00549 Info_SetValueForKey(temp, "maxz", va("%f", ent->r.maxs[2]));
00550
00551 Info_SetValueForKey(temp, "modelIndex", va("%d", ent->s.modelindex));
00552
00553 G_SpawnString("terraindef", "grassyhills", &value);
00554 Info_SetValueForKey(temp, "terrainDef", value);
00555
00556 G_SpawnString("instancedef", "", &value);
00557 Info_SetValueForKey(temp, "instanceDef", value);
00558
00559 G_SpawnString("miscentdef", "", &value);
00560 Info_SetValueForKey(temp, "miscentDef", value);
00561
00562 Info_SetValueForKey(temp, "missionType", missionType);
00563
00564 for(i = 0; i < MAX_INSTANCE_TYPES; i++)
00565 {
00566 trap_Cvar_VariableStringBuffer(va("RMG_instance%d", i), final, MAX_QPATH);
00567 if(strlen(final))
00568 {
00569 Info_SetValueForKey(temp, va("inst%d", i), final);
00570 }
00571 }
00572
00573
00574 G_SpawnString("densitymap", "", &value);
00575 Info_SetValueForKey(temp, "densityMap", value);
00576
00577 Info_SetValueForKey(temp, "shader", va("%d", shaderNum));
00578 G_SpawnString("texturescale", "0.005", &value);
00579 Info_SetValueForKey(temp, "texturescale", va("%f", atof(value)));
00580
00581
00582 terrainID = trap_CM_RegisterTerrain(temp);
00583
00584
00585 Info_SetValueForKey(temp, "terrainId", va("%d", terrainID));
00586
00587
00588
00589
00590
00591
00592
00593
00594 trap_SetConfigstring(CS_TERRAINS + terrainID, temp);
00595
00596
00597 ent->r.contents = CONTENTS_TERRAIN;
00598 ent->r.svFlags = SVF_NOCLIENT;
00599 ent->s.eFlags = EF_PERMANENT;
00600 ent->s.eType = ET_TERRAIN;
00601
00602
00603 trap_LinkEntity(ent);
00604
00605
00606 if ( g_RMG.integer )
00607 {
00608 trap_RMG_Init(terrainID);
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 }
00631 }
00632
00633
00634
00635
00636
00637
00638 void G_PortalifyEntities(gentity_t *ent)
00639 {
00640 int i = 0;
00641 gentity_t *scan = NULL;
00642
00643 while (i < MAX_GENTITIES)
00644 {
00645 scan = &g_entities[i];
00646
00647 if (scan && scan->inuse && scan->s.number != ent->s.number && trap_InPVS(ent->s.origin, scan->r.currentOrigin))
00648 {
00649 trace_t tr;
00650
00651 trap_Trace(&tr, ent->s.origin, vec3_origin, vec3_origin, scan->r.currentOrigin, ent->s.number, CONTENTS_SOLID);
00652
00653 if (tr.fraction == 1.0 || (tr.entityNum == scan->s.number && tr.entityNum != ENTITYNUM_NONE && tr.entityNum != ENTITYNUM_WORLD))
00654 {
00655 if (!scan->client || scan->s.eType == ET_NPC)
00656 {
00657 scan->s.isPortalEnt = qtrue;
00658 }
00659 }
00660 }
00661
00662 i++;
00663 }
00664
00665 ent->think = G_FreeEntity;
00666 ent->nextthink = level.time;
00667 }
00668
00669
00670
00671
00672
00673
00674
00675 void SP_misc_skyportal_orient (gentity_t *ent)
00676 {
00677 G_FreeEntity(ent);
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 void SP_misc_skyportal (gentity_t *ent)
00695 {
00696 char *fov;
00697 vec3_t fogv;
00698 int fogn;
00699 int fogf;
00700 int isfog = 0;
00701
00702 float fov_x;
00703
00704 G_SpawnString ("fov", "80", &fov);
00705 fov_x = atof (fov);
00706
00707 isfog += G_SpawnVector ("fogcolor", "0 0 0", fogv);
00708 isfog += G_SpawnInt ("fognear", "0", &fogn);
00709 isfog += G_SpawnInt ("fogfar", "300", &fogf);
00710
00711 trap_SetConfigstring( CS_SKYBOXORG, va("%.2f %.2f %.2f %.1f %i %.2f %.2f %.2f %i %i", ent->s.origin[0], ent->s.origin[1], ent->s.origin[2], fov_x, (int)isfog, fogv[0], fogv[1], fogv[2], fogn, fogf ) );
00712
00713 ent->think = G_PortalifyEntities;
00714 ent->nextthink = level.time + 1050;
00715 }
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760 void HolocronRespawn(gentity_t *self)
00761 {
00762 self->s.modelindex = (self->count - 128);
00763 }
00764
00765 void HolocronPopOut(gentity_t *self)
00766 {
00767 if (Q_irand(1, 10) < 5)
00768 {
00769 self->s.pos.trDelta[0] = 150 + Q_irand(1, 100);
00770 }
00771 else
00772 {
00773 self->s.pos.trDelta[0] = -150 - Q_irand(1, 100);
00774 }
00775 if (Q_irand(1, 10) < 5)
00776 {
00777 self->s.pos.trDelta[1] = 150 + Q_irand(1, 100);
00778 }
00779 else
00780 {
00781 self->s.pos.trDelta[1] = -150 - Q_irand(1, 100);
00782 }
00783 self->s.pos.trDelta[2] = 150 + Q_irand(1, 100);
00784 }
00785
00786 void HolocronTouch(gentity_t *self, gentity_t *other, trace_t *trace)
00787 {
00788 int i = 0;
00789 int othercarrying = 0;
00790 float time_lowest = 0;
00791 int index_lowest = -1;
00792 int hasall = 1;
00793 int forceReselect = WP_NONE;
00794
00795 if (trace)
00796 {
00797 self->s.groundEntityNum = trace->entityNum;
00798 }
00799
00800 if (!other || !other->client || other->health < 1)
00801 {
00802 return;
00803 }
00804
00805 if (!self->s.modelindex)
00806 {
00807 return;
00808 }
00809
00810 if (self->enemy)
00811 {
00812 return;
00813 }
00814
00815 if (other->client->ps.holocronsCarried[self->count])
00816 {
00817 return;
00818 }
00819
00820 if (other->client->ps.holocronCantTouch == self->s.number && other->client->ps.holocronCantTouchTime > level.time)
00821 {
00822 return;
00823 }
00824
00825 while (i < NUM_FORCE_POWERS)
00826 {
00827 if (other->client->ps.holocronsCarried[i])
00828 {
00829 othercarrying++;
00830
00831 if (index_lowest == -1 || other->client->ps.holocronsCarried[i] < time_lowest)
00832 {
00833 index_lowest = i;
00834 time_lowest = other->client->ps.holocronsCarried[i];
00835 }
00836 }
00837 else if (i != self->count)
00838 {
00839 hasall = 0;
00840 }
00841 i++;
00842 }
00843
00844 if (hasall)
00845 {
00846
00847 }
00848
00849 if (!(other->client->ps.fd.forcePowersActive & (1 << other->client->ps.fd.forcePowerSelected)))
00850 {
00851 if (self->count != FP_SABER_OFFENSE && self->count != FP_SABER_DEFENSE && self->count != FP_SABERTHROW && self->count != FP_LEVITATION)
00852 {
00853 other->client->ps.fd.forcePowerSelected = self->count;
00854 }
00855 }
00856
00857 if (g_MaxHolocronCarry.integer && othercarrying >= g_MaxHolocronCarry.integer)
00858 {
00859 other->client->ps.holocronsCarried[index_lowest] = 0;
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874 }
00875
00876
00877 G_AddEvent( other, EV_ITEM_PICKUP, self->s.number );
00878
00879 other->client->ps.holocronsCarried[self->count] = level.time;
00880 self->s.modelindex = 0;
00881 self->enemy = other;
00882
00883 self->pos2[0] = 1;
00884 self->pos2[1] = level.time + HOLOCRON_RESPAWN_TIME;
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 if (forceReselect != WP_NONE)
00900 {
00901 G_AddEvent(other, EV_NOAMMO, forceReselect);
00902 }
00903
00904
00905 }
00906
00907 void HolocronThink(gentity_t *ent)
00908 {
00909 if (ent->pos2[0] && (!ent->enemy || !ent->enemy->client || ent->enemy->health < 1))
00910 {
00911 if (ent->enemy && ent->enemy->client)
00912 {
00913 HolocronRespawn(ent);
00914 VectorCopy(ent->enemy->client->ps.origin, ent->s.pos.trBase);
00915 VectorCopy(ent->enemy->client->ps.origin, ent->s.origin);
00916 VectorCopy(ent->enemy->client->ps.origin, ent->r.currentOrigin);
00917
00918 HolocronPopOut(ent);
00919 ent->enemy->client->ps.holocronsCarried[ent->count] = 0;
00920 ent->enemy = NULL;
00921
00922 goto justthink;
00923 }
00924 }
00925 else if (ent->pos2[0] && ent->enemy && ent->enemy->client)
00926 {
00927 ent->pos2[1] = level.time + HOLOCRON_RESPAWN_TIME;
00928 }
00929
00930 if (ent->enemy && ent->enemy->client)
00931 {
00932 if (!ent->enemy->client->ps.holocronsCarried[ent->count])
00933 {
00934 ent->enemy->client->ps.holocronCantTouch = ent->s.number;
00935 ent->enemy->client->ps.holocronCantTouchTime = level.time + 5000;
00936
00937 HolocronRespawn(ent);
00938 VectorCopy(ent->enemy->client->ps.origin, ent->s.pos.trBase);
00939 VectorCopy(ent->enemy->client->ps.origin, ent->s.origin);
00940 VectorCopy(ent->enemy->client->ps.origin, ent->r.currentOrigin);
00941
00942 HolocronPopOut(ent);
00943 ent->enemy = NULL;
00944
00945 goto justthink;
00946 }
00947
00948 if (!ent->enemy->inuse || (ent->enemy->client && ent->enemy->client->ps.fallingToDeath))
00949 {
00950 if (ent->enemy->inuse && ent->enemy->client)
00951 {
00952 ent->enemy->client->ps.holocronBits &= ~(1 << ent->count);
00953 ent->enemy->client->ps.holocronsCarried[ent->count] = 0;
00954 }
00955 ent->enemy = NULL;
00956 HolocronRespawn(ent);
00957 VectorCopy(ent->s.origin2, ent->s.pos.trBase);
00958 VectorCopy(ent->s.origin2, ent->s.origin);
00959 VectorCopy(ent->s.origin2, ent->r.currentOrigin);
00960
00961 ent->s.pos.trTime = level.time;
00962
00963 ent->pos2[0] = 0;
00964
00965 trap_LinkEntity(ent);
00966
00967 goto justthink;
00968 }
00969 }
00970
00971 if (ent->pos2[0] && ent->pos2[1] < level.time)
00972 {
00973 VectorCopy(ent->s.origin2, ent->s.pos.trBase);
00974 VectorCopy(ent->s.origin2, ent->s.origin);
00975 VectorCopy(ent->s.origin2, ent->r.currentOrigin);
00976
00977 ent->s.pos.trTime = level.time;
00978
00979 ent->pos2[0] = 0;
00980
00981 trap_LinkEntity(ent);
00982 }
00983
00984 justthink:
00985 ent->nextthink = level.time + 50;
00986
00987 if (ent->s.pos.trDelta[0] || ent->s.pos.trDelta[1] || ent->s.pos.trDelta[2])
00988 {
00989 G_RunObject(ent);
00990 }
00991 }
00992
00993 void SP_misc_holocron(gentity_t *ent)
00994 {
00995 vec3_t dest;
00996 trace_t tr;
00997
00998 if (g_gametype.integer != GT_HOLOCRON)
00999 {
01000 G_FreeEntity(ent);
01001 return;
01002 }
01003
01004 if (HasSetSaberOnly())
01005 {
01006 if (ent->count == FP_SABER_OFFENSE ||
01007 ent->count == FP_SABER_DEFENSE ||
01008 ent->count == FP_SABERTHROW)
01009 {
01010 G_FreeEntity(ent);
01011 return;
01012 }
01013 }
01014
01015 ent->s.isJediMaster = qtrue;
01016
01017 VectorSet( ent->r.maxs, 8, 8, 8 );
01018 VectorSet( ent->r.mins, -8, -8, -8 );
01019
01020 ent->s.origin[2] += 0.1;
01021 ent->r.maxs[2] -= 0.1;
01022
01023 VectorSet( dest, ent->s.origin[0], ent->s.origin[1], ent->s.origin[2] - 4096 );
01024 trap_Trace( &tr, ent->s.origin, ent->r.mins, ent->r.maxs, dest, ent->s.number, MASK_SOLID );
01025 if ( tr.startsolid )
01026 {
01027 G_Printf ("SP_misc_holocron: misc_holocron startsolid at %s\n", vtos(ent->s.origin));
01028 G_FreeEntity( ent );
01029 return;
01030 }
01031
01032
01033 ent->r.maxs[2] += 0.1;
01034
01035
01036
01037
01038 G_SetOrigin( ent, tr.endpos );
01039
01040 if (ent->count < 0)
01041 {
01042 ent->count = 0;
01043 }
01044
01045 if (ent->count >= NUM_FORCE_POWERS)
01046 {
01047 ent->count = NUM_FORCE_POWERS-1;
01048 }
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060 ent->enemy = NULL;
01061
01062 ent->flags = FL_BOUNCE_HALF;
01063
01064 ent->s.modelindex = (ent->count - 128);
01065 ent->s.eType = ET_HOLOCRON;
01066 ent->s.pos.trType = TR_GRAVITY;
01067 ent->s.pos.trTime = level.time;
01068
01069 ent->r.contents = CONTENTS_TRIGGER;
01070 ent->clipmask = MASK_SOLID;
01071
01072 ent->s.trickedentindex4 = ent->count;
01073
01074 if (forcePowerDarkLight[ent->count] == FORCE_DARKSIDE)
01075 {
01076 ent->s.trickedentindex3 = 1;
01077 }
01078 else if (forcePowerDarkLight[ent->count] == FORCE_LIGHTSIDE)
01079 {
01080 ent->s.trickedentindex3 = 2;
01081 }
01082 else
01083 {
01084 ent->s.trickedentindex3 = 3;
01085 }
01086
01087 ent->physicsObject = qtrue;
01088
01089 VectorCopy(ent->s.pos.trBase, ent->s.origin2);
01090
01091 ent->touch = HolocronTouch;
01092
01093 trap_LinkEntity(ent);
01094
01095 ent->think = HolocronThink;
01096 ent->nextthink = level.time + 50;
01097 }
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107 void Use_Shooter( gentity_t *ent, gentity_t *other, gentity_t *activator ) {
01108 vec3_t dir;
01109 float deg;
01110 vec3_t up, right;
01111
01112
01113 if ( ent->enemy ) {
01114 VectorSubtract( ent->enemy->r.currentOrigin, ent->s.origin, dir );
01115 VectorNormalize( dir );
01116 } else {
01117 VectorCopy( ent->movedir, dir );
01118 }
01119
01120
01121 PerpendicularVector( up, dir );
01122 CrossProduct( up, dir, right );
01123
01124 deg = crandom() * ent->random;
01125 VectorMA( dir, deg, up, dir );
01126
01127 deg = crandom() * ent->random;
01128 VectorMA( dir, deg, right, dir );
01129
01130 VectorNormalize( dir );
01131
01132 switch ( ent->s.weapon ) {
01133 case WP_BLASTER:
01134 WP_FireBlasterMissile( ent, ent->s.origin, dir, qfalse );
01135 break;
01136 }
01137
01138 G_AddEvent( ent, EV_FIRE_WEAPON, 0 );
01139 }
01140
01141
01142 static void InitShooter_Finish( gentity_t *ent ) {
01143 ent->enemy = G_PickTarget( ent->target );
01144 ent->think = 0;
01145 ent->nextthink = 0;
01146 }
01147
01148 void InitShooter( gentity_t *ent, int weapon ) {
01149 ent->use = Use_Shooter;
01150 ent->s.weapon = weapon;
01151
01152 RegisterItem( BG_FindItemForWeapon( weapon ) );
01153
01154 G_SetMovedir( ent->s.angles, ent->movedir );
01155
01156 if ( !ent->random ) {
01157 ent->random = 1.0;
01158 }
01159 ent->random = sin( M_PI * ent->random / 180 );
01160
01161 if ( ent->target ) {
01162 ent->think = InitShooter_Finish;
01163 ent->nextthink = level.time + 500;
01164 }
01165 trap_LinkEntity( ent );
01166 }
01167
01168
01169
01170
01171
01172 void SP_shooter_blaster( gentity_t *ent ) {
01173 InitShooter( ent, WP_BLASTER);
01174 }
01175
01176 void check_recharge(gentity_t *ent)
01177 {
01178 if (ent->fly_sound_debounce_time < level.time ||
01179 !ent->activator ||
01180 !ent->activator->client ||
01181 !(ent->activator->client->pers.cmd.buttons & BUTTON_USE))
01182 {
01183 if (ent->activator)
01184 {
01185 G_Sound(ent, CHAN_AUTO, ent->genericValue7);
01186 }
01187 ent->s.loopSound = 0;
01188 ent->s.loopIsSoundset = qfalse;
01189 ent->activator = NULL;
01190 ent->fly_sound_debounce_time = 0;
01191 }
01192
01193 if (!ent->activator)
01194 {
01195 if (ent->genericValue8 < level.time)
01196 {
01197 if (ent->count < ent->genericValue4)
01198 {
01199 ent->count++;
01200 }
01201 ent->genericValue8 = level.time + ent->genericValue5;
01202 }
01203 }
01204 ent->s.