00001
00002
00003 #include "g_local.h"
00004 #include "bg_saga.h"
00005
00006 int gTrigFallSound;
00007
00008 void InitTrigger( gentity_t *self ) {
00009 if (!VectorCompare (self->s.angles, vec3_origin))
00010 G_SetMovedir (self->s.angles, self->movedir);
00011
00012 trap_SetBrushModel( self, self->model );
00013 self->r.contents = CONTENTS_TRIGGER;
00014 self->r.svFlags = SVF_NOCLIENT;
00015
00016 if(self->spawnflags & 128)
00017 {
00018 self->flags |= FL_INACTIVE;
00019 }
00020 }
00021
00022
00023 void multi_wait( gentity_t *ent ) {
00024 ent->nextthink = 0;
00025 }
00026
00027 void trigger_cleared_fire (gentity_t *self);
00028
00029
00030
00031
00032 void multi_trigger_run( gentity_t *ent )
00033 {
00034 ent->think = 0;
00035
00036 G_ActivateBehavior( ent, BSET_USE );
00037
00038 if ( ent->soundSet && ent->soundSet[0] )
00039 {
00040 trap_SetConfigstring( CS_GLOBAL_AMBIENT_SET, ent->soundSet );
00041 }
00042
00043 if (ent->genericValue4)
00044 {
00045 if (ent->genericValue4 == SIEGETEAM_TEAM1 &&
00046 ent->target3 && ent->target3[0])
00047 {
00048 G_UseTargets2(ent, ent->activator, ent->target3);
00049 }
00050 else if (ent->genericValue4 == SIEGETEAM_TEAM2 &&
00051 ent->target4 && ent->target4[0])
00052 {
00053 G_UseTargets2(ent, ent->activator, ent->target4);
00054 }
00055
00056 ent->genericValue4 = 0;
00057 }
00058
00059 G_UseTargets (ent, ent->activator);
00060 if ( ent->noise_index )
00061 {
00062 G_Sound( ent->activator, CHAN_AUTO, ent->noise_index );
00063 }
00064
00065 if ( ent->target2 && ent->target2[0] && ent->wait >= 0 )
00066 {
00067 ent->think = trigger_cleared_fire;
00068 ent->nextthink = level.time + ent->speed;
00069 }
00070 else if ( ent->wait > 0 )
00071 {
00072 if ( ent->painDebounceTime != level.time )
00073 {
00074
00075 ent->nextthink = level.time + ( ent->wait + ent->random * crandom() ) * 1000;
00076 ent->painDebounceTime = level.time;
00077 }
00078 }
00079 else if ( ent->wait < 0 )
00080 {
00081
00082
00083 ent->r.contents &= ~CONTENTS_TRIGGER;
00084 ent->think = 0;
00085 ent->use = 0;
00086
00087
00088
00089 }
00090 if( ent->activator && ent->activator->client )
00091 {
00092 ent->aimDebounceTime = level.time;
00093 }
00094 }
00095
00096
00097 qboolean G_NameInTriggerClassList(char *list, char *str)
00098 {
00099 char cmp[MAX_STRING_CHARS];
00100 int i = 0;
00101 int j;
00102
00103 while (list[i])
00104 {
00105 j = 0;
00106 while (list[i] && list[i] != '|')
00107 {
00108 cmp[j] = list[i];
00109 i++;
00110 j++;
00111 }
00112 cmp[j] = 0;
00113
00114 if (!Q_stricmp(str, cmp))
00115 {
00116 return qtrue;
00117 }
00118 if (list[i] != '|')
00119 {
00120 return qfalse;
00121 }
00122 i++;
00123 }
00124
00125 return qfalse;
00126 }
00127
00128 extern qboolean gSiegeRoundBegun;
00129 void SiegeItemRemoveOwner(gentity_t *ent, gentity_t *carrier);
00130 void multi_trigger( gentity_t *ent, gentity_t *activator )
00131 {
00132 qboolean haltTrigger = qfalse;
00133
00134 if ( ent->think == multi_trigger_run )
00135 {
00136 return;
00137 }
00138
00139 if (g_gametype.integer == GT_SIEGE &&
00140 !gSiegeRoundBegun)
00141 {
00142 return;
00143 }
00144
00145 if (g_gametype.integer == GT_SIEGE &&
00146 activator && activator->client &&
00147 ent->alliedTeam &&
00148 activator->client->sess.sessionTeam != ent->alliedTeam)
00149 {
00150 return;
00151 }
00152
00153 if (g_gametype.integer == GT_SIEGE &&
00154 ent->idealclass && ent->idealclass[0])
00155 {
00156 if (!activator ||
00157 !activator->client ||
00158 activator->client->siegeClass < 0)
00159 {
00160 return;
00161 }
00162
00163 if (!G_NameInTriggerClassList(bgSiegeClasses[activator->client->siegeClass].name, ent->idealclass))
00164 {
00165 return;
00166 }
00167 }
00168
00169 if (g_gametype.integer == GT_SIEGE && ent->genericValue1)
00170 {
00171 haltTrigger = qtrue;
00172
00173 if (activator && activator->client &&
00174 activator->client->holdingObjectiveItem &&
00175 ent->targetname && ent->targetname[0])
00176 {
00177 gentity_t *objItem = &g_entities[activator->client->holdingObjectiveItem];
00178
00179 if (objItem && objItem->inuse)
00180 {
00181 if (objItem->goaltarget && objItem->goaltarget[0] &&
00182 !Q_stricmp(ent->targetname, objItem->goaltarget))
00183 {
00184 if (objItem->genericValue7 != activator->client->sess.sessionTeam)
00185 {
00186 if (objItem->target3 && objItem->target3[0])
00187 {
00188 G_UseTargets2(objItem, objItem, objItem->target3);
00189
00190
00191 if (ent->targetname && ent->targetname[0])
00192 {
00193 haltTrigger = qfalse;
00194 }
00195 }
00196 else
00197 {
00198 haltTrigger = qfalse;
00199 }
00200
00201
00202 SiegeItemRemoveOwner(objItem, activator);
00203 objItem->nextthink = 0;
00204 objItem->neverFree = qfalse;
00205 G_FreeEntity(objItem);
00206 }
00207 }
00208 }
00209 }
00210 }
00211 else if (ent->genericValue1)
00212 {
00213 return;
00214 }
00215
00216 if (ent->genericValue2)
00217 {
00218 int i = 0;
00219 int team1ClNum = 0;
00220 int team2ClNum = 0;
00221 int owningTeam = ent->genericValue3;
00222 int newOwningTeam = 0;
00223 int numEnts = 0;
00224 int entityList[MAX_GENTITIES];
00225 gentity_t *cl;
00226
00227 if (g_gametype.integer != GT_SIEGE)
00228 {
00229 return;
00230 }
00231
00232 if (!activator->client ||
00233 (activator->client->sess.sessionTeam != SIEGETEAM_TEAM1 && activator->client->sess.sessionTeam != SIEGETEAM_TEAM2))
00234 {
00235 return;
00236 }
00237
00238
00239 numEnts = trap_EntitiesInBox( ent->r.absmin, ent->r.absmax, entityList, MAX_GENTITIES );
00240 while (i < numEnts)
00241 {
00242 if (entityList[i] < MAX_CLIENTS)
00243 {
00244 cl = &g_entities[entityList[i]];
00245
00246
00247 if (cl->inuse && cl->client &&
00248 (cl->client->sess.sessionTeam == SIEGETEAM_TEAM1 || cl->client->sess.sessionTeam == SIEGETEAM_TEAM2) &&
00249 cl->health > 0 &&
00250 !(cl->client->ps.eFlags & EF_DEAD))
00251 {
00252
00253 if (cl->client->sess.sessionTeam == SIEGETEAM_TEAM1)
00254 {
00255 team1ClNum++;
00256 }
00257 else
00258 {
00259 team2ClNum++;
00260 }
00261 }
00262 }
00263 i++;
00264 }
00265
00266 if (!team1ClNum && !team2ClNum)
00267 {
00268 return;
00269 }
00270
00271 if (team1ClNum == team2ClNum)
00272 {
00273 return;
00274 }
00275
00276
00277 if (team1ClNum > team2ClNum)
00278 {
00279 newOwningTeam = SIEGETEAM_TEAM1;
00280 }
00281 else
00282 {
00283 newOwningTeam = SIEGETEAM_TEAM2;
00284 }
00285
00286 if (owningTeam == newOwningTeam)
00287 {
00288 return;
00289 }
00290
00291
00292 ent->genericValue3 = newOwningTeam;
00293 ent->genericValue4 = newOwningTeam;
00294 }
00295
00296 if (haltTrigger)
00297 {
00298 return;
00299 }
00300
00301 if ( ent->nextthink > level.time )
00302 {
00303 if( ent->spawnflags & 2048 )
00304 {
00305 if ( ent->painDebounceTime && ent->painDebounceTime != level.time )
00306 {
00307 return;
00308 }
00309 }
00310 else
00311 {
00312 return;
00313 }
00314
00315 }
00316
00317
00318 if( activator && !activator->s.number && ent->aimDebounceTime == level.time )
00319 {
00320 return;
00321 }
00322
00323 if ( ent->flags & FL_INACTIVE )
00324 {
00325 return;
00326 }
00327
00328 ent->activator = activator;
00329
00330 if(ent->delay && ent->painDebounceTime < (level.time + ent->delay) )
00331 {
00332 ent->think = multi_trigger_run;
00333 ent->nextthink = level.time + ent->delay;
00334 ent->painDebounceTime = level.time;
00335
00336 }
00337 else
00338 {
00339 multi_trigger_run (ent);
00340 }
00341 }
00342
00343 void Use_Multi( gentity_t *ent, gentity_t *other, gentity_t *activator )
00344 {
00345 multi_trigger( ent, activator );
00346 }
00347
00348 qboolean G_PointInBounds( vec3_t point, vec3_t mins, vec3_t maxs );
00349
00350 void Touch_Multi( gentity_t *self, gentity_t *other, trace_t *trace )
00351 {
00352 if( !other->client )
00353 {
00354 return;
00355 }
00356
00357 if ( self->flags & FL_INACTIVE )
00358 {
00359 return;
00360 }
00361
00362 if( self->alliedTeam )
00363 {
00364 if ( other->client->sess.sessionTeam != self->alliedTeam )
00365 {
00366 return;
00367 }
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 if ( self->spawnflags & 1 )
00379 {
00380 if ( other->s.eType == ET_NPC )
00381 {
00382 return;
00383 }
00384 }
00385 else
00386 {
00387 if ( self->spawnflags & 16 )
00388 {
00389 if ( other->NPC == NULL )
00390 {
00391 return;
00392 }
00393 }
00394
00395 if ( self->NPC_targetname && self->NPC_targetname[0] )
00396 {
00397 if ( other->script_targetname && other->script_targetname[0] )
00398 {
00399 if ( Q_stricmp( self->NPC_targetname, other->script_targetname ) != 0 )
00400 {
00401 return;
00402 }
00403 }
00404 else
00405 {
00406 return;
00407 }
00408 }
00409 }
00410
00411 if ( self->spawnflags & 2 )
00412 {
00413 vec3_t forward;
00414
00415 AngleVectors( other->client->ps.viewangles, forward, NULL, NULL );
00416
00417 if ( DotProduct( self->movedir, forward ) < 0.5 )
00418 {
00419 return;
00420 }
00421 }
00422
00423 if ( self->spawnflags & 4 )
00424 {
00425 if( !( other->client->pers.cmd.buttons & BUTTON_USE ) )
00426 {
00427 return;
00428 }
00429
00430 if ((other->client->ps.weaponTime > 0 && other->client->ps.torsoAnim != BOTH_BUTTON_HOLD && other->client->ps.torsoAnim != BOTH_CONSOLE1) || other->health < 1 ||
00431 (other->client->ps.pm_flags & PMF_FOLLOW) || other->client->sess.sessionTeam == TEAM_SPECTATOR ||
00432 other->client->ps.forceHandExtend != HANDEXTEND_NONE)
00433 {
00434 return;
00435 }
00436
00437 if (self->genericValue7)
00438 {
00439 if (g_gametype.integer == GT_SIEGE &&
00440 self->idealclass && self->idealclass[0])
00441 {
00442 if (!other ||
00443 !other->client ||
00444 other->client->siegeClass < 0)
00445 {
00446 return;
00447 }
00448
00449 if (!G_NameInTriggerClassList(bgSiegeClasses[other->client->siegeClass].name, self->idealclass))
00450 {
00451 return;
00452 }
00453 }
00454
00455 if (!G_PointInBounds( other->client->ps.origin, self->r.absmin, self->r.absmax ))
00456 {
00457 return;
00458 }
00459 else if (other->client->isHacking != self->s.number && other->s.number < MAX_CLIENTS )
00460 {
00461 other->client->isHacking = self->s.number;
00462 VectorCopy(other->client->ps.viewangles, other->client->hackingAngles);
00463 other->client->ps.hackingTime = level.time + self->genericValue7;
00464 other->client->ps.hackingBaseTime = self->genericValue7;
00465 if (other->client->ps.hackingBaseTime > 60000)
00466 {
00467 other->client->ps.hackingTime = level.time + 60000;
00468 other->client->ps.hackingBaseTime = 60000;
00469 }
00470 return;
00471 }
00472 else if (other->client->ps.hackingTime < level.time)
00473 {
00474 other->client->isHacking = 0;
00475 other->client->ps.hackingTime = 0;
00476 }
00477 else
00478 {
00479 return;
00480 }
00481 }
00482 }
00483
00484 if ( self->spawnflags & 8 )
00485 {
00486 if( !( other->client->pers.cmd.buttons & BUTTON_ATTACK ) &&
00487 !( other->client->pers.cmd.buttons & BUTTON_ALT_ATTACK ) )
00488 {
00489 return;
00490 }
00491 }
00492
00493 if ( self->radius )
00494 {
00495 vec3_t eyeSpot;
00496
00497
00498
00499
00500 VectorCopy(other->client->ps.origin, eyeSpot);
00501 eyeSpot[2] += other->client->ps.viewheight;
00502
00503 if ( G_PointInBounds( eyeSpot, self->r.absmin, self->r.absmax ) )
00504 {
00505 if( !( other->client->pers.cmd.buttons & BUTTON_ATTACK ) &&
00506 !( other->client->pers.cmd.buttons & BUTTON_ALT_ATTACK ) )
00507 {
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 }
00523 }
00524 }
00525
00526 if ( self->spawnflags & 4 )
00527 {
00528 if (other->client->ps.torsoAnim != BOTH_BUTTON_HOLD &&
00529 other->client->ps.torsoAnim != BOTH_CONSOLE1)
00530 {
00531 G_SetAnim( other, NULL, SETANIM_TORSO, BOTH_BUTTON_HOLD, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD, 0 );
00532 }
00533 else
00534 {
00535 other->client->ps.torsoTimer = 500;
00536 }
00537 other->client->ps.weaponTime = other->client->ps.torsoTimer;
00538 }
00539
00540 if ( self->think == trigger_cleared_fire )
00541 {
00542 self->nextthink = level.time + self->speed;
00543 return;
00544 }
00545
00546 multi_trigger( self, other );
00547 }
00548
00549 void trigger_cleared_fire (gentity_t *self)
00550 {
00551 G_UseTargets2( self, self->activator, self->target2 );
00552 self->think = 0;
00553
00554 if ( self->wait > 0 )
00555 {
00556 self->nextthink = level.time + ( self->wait + self->random * crandom() ) * 1000;
00557 }
00558 }
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 void SP_trigger_multiple( gentity_t *ent )
00608 {
00609 char *s;
00610 if ( G_SpawnString( "noise", "", &s ) )
00611 {
00612 if (s && s[0])
00613 {
00614 ent->noise_index = G_SoundIndex(s);
00615 }
00616 else
00617 {
00618 ent->noise_index = 0;
00619 }
00620 }
00621
00622 G_SpawnInt("usetime", "0", &ent->genericValue7);
00623
00624
00625 G_SpawnInt("siegetrig", "0", &ent->genericValue1);
00626 G_SpawnInt("teambalance", "0", &ent->genericValue2);
00627
00628 G_SpawnInt("delay", "0", &ent->delay);
00629
00630 if ( (ent->wait > 0) && (ent->random >= ent->wait) ) {
00631 ent->random = ent->wait - FRAMETIME;
00632 Com_Printf(S_COLOR_YELLOW"trigger_multiple has random >= wait\n");
00633 }
00634
00635 ent->delay *= 1000;
00636 if ( !ent->speed && ent->target2 && ent->target2[0] )
00637 {
00638 ent->speed = 1000;
00639 }
00640 else
00641 {
00642 ent->speed *= 1000;
00643 }
00644
00645 ent->touch = Touch_Multi;
00646 ent->use = Use_Multi;
00647
00648 if ( ent->team && ent->team[0] )
00649 {
00650 ent->alliedTeam = atoi(ent->team);
00651 ent->team = NULL;
00652 }
00653
00654 InitTrigger( ent );
00655 trap_LinkEntity (ent);
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 void SP_trigger_once( gentity_t *ent )
00695 {
00696 char *s;
00697 if ( G_SpawnString( "noise", "", &s ) )
00698 {
00699 if (s && s[0])
00700 {
00701 ent->noise_index = G_SoundIndex(s);
00702 }
00703 else
00704 {
00705 ent->noise_index = 0;
00706 }
00707 }
00708
00709 G_SpawnInt("usetime", "0", &ent->genericValue7);
00710
00711
00712 G_SpawnInt("siegetrig", "0", &ent->genericValue1);
00713
00714 G_SpawnInt("delay", "0", &ent->delay);
00715
00716 ent->wait = -1;
00717
00718 ent->touch = Touch_Multi;
00719 ent->use = Use_Multi;
00720
00721 if ( ent->team && ent->team[0] )
00722 {
00723 ent->alliedTeam = atoi(ent->team);
00724 ent->team = NULL;
00725 }
00726
00727 ent->delay *= 1000;
00728
00729 InitTrigger( ent );
00730 trap_LinkEntity (ent);
00731 }
00732
00733
00734
00735
00736
00737
00738
00739 void Do_Strike(gentity_t *ent)
00740 {
00741 trace_t localTrace;
00742 vec3_t strikeFrom;
00743 vec3_t strikePoint;
00744 vec3_t fxAng;
00745
00746
00747 VectorSet(fxAng, 90.0f, 0.0f, 0.0f);
00748
00749
00750 strikePoint[0] = flrand(ent->r.absmin[0], ent->r.absmax[0]);
00751 strikePoint[1] = flrand(ent->r.absmin[1], ent->r.absmax[1]);
00752
00753
00754 strikePoint[2] = ent->r.absmin[2];
00755
00756
00757 strikeFrom[0] = strikePoint[0];
00758 strikeFrom[1] = strikePoint[1];
00759 strikeFrom[2] = ent->r.absmax[2]-4.0f;
00760
00761
00762 trap_Trace(&localTrace, strikeFrom, NULL, NULL, strikePoint, ent->s.number, MASK_PLAYERSOLID);
00763 VectorCopy(localTrace.endpos, strikePoint);
00764
00765 if (localTrace.startsolid || localTrace.allsolid)
00766 {
00767 ent->nextthink = level.time;
00768 return;
00769 }
00770
00771 if (ent->radius)
00772 {
00773 G_RadiusDamage(strikePoint, ent, ent->damage, ent->radius, ent, NULL, MOD_SUICIDE);
00774 }
00775 else
00776 {
00777 gentity_t *trHit = &g_entities[localTrace.entityNum];
00778
00779 if (trHit->inuse && trHit->takedamage)
00780 {
00781 G_Damage(trHit, ent, ent, NULL, trHit->r.currentOrigin, ent->damage, 0, MOD_SUICIDE);
00782 }
00783 }
00784
00785 G_PlayEffectID(ent->genericValue2, strikeFrom, fxAng);
00786 }
00787
00788
00789 void Think_Strike(gentity_t *ent)
00790 {
00791 if (ent->genericValue1)
00792 {
00793 return;
00794 }
00795
00796 ent->nextthink = level.time + ent->wait + Q_irand(0, ent->random);
00797 Do_Strike(ent);
00798 }
00799
00800
00801 void Use_Strike( gentity_t *ent, gentity_t *other, gentity_t *activator )
00802 {
00803 ent->genericValue1 = !ent->genericValue1;
00804
00805 if (!ent->genericValue1)
00806 {
00807 ent->nextthink = level.time;
00808 }
00809 }
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 void SP_trigger_lightningstrike( gentity_t *ent )
00825 {
00826 char *s;
00827
00828 ent->use = Use_Strike;
00829 ent->think = Think_Strike;
00830 ent->nextthink = level.time + 500;
00831
00832 G_SpawnString("lightningfx", "", &s);
00833 if (!s || !s[0])
00834 {
00835 Com_Error(ERR_DROP, "trigger_lightningstrike with no lightningfx");
00836 }
00837
00838
00839 ent->genericValue2 = G_EffectIndex(s);
00840
00841 if (ent->spawnflags & 1)
00842 {
00843 ent->genericValue1 = 1;
00844 }
00845
00846 if (!ent->wait)
00847 {
00848 ent->wait = 1000;
00849 }
00850 if (!ent->random)
00851 {
00852 ent->random = 2000;
00853 }
00854 if (!ent->damage)
00855 {
00856 ent->damage = 50;
00857 }
00858
00859 InitTrigger( ent );
00860 trap_LinkEntity (ent);
00861 }
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 void trigger_always_think( gentity_t *ent ) {
00873 G_UseTargets(ent, ent);
00874 G_FreeEntity( ent );
00875 }
00876
00877
00878
00879
00880 void SP_trigger_always (gentity_t *ent) {
00881
00882 ent->nextthink = level.time + 300;
00883 ent->think = trigger_always_think;
00884 }
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 #define PUSH_LINEAR 4
00896 #define PUSH_RELATIVE 16
00897 #define PUSH_MULTIPLE 2048
00898
00899 #define PUSH_CONSTANT 2
00900
00901 void trigger_push_touch (gentity_t *self, gentity_t *other, trace_t *trace ) {
00902 if ( self->flags & FL_INACTIVE )
00903 {
00904 return;
00905 }
00906
00907 if ( !(self->spawnflags&PUSH_LINEAR) )
00908 {
00909 if ( !other->client ) {
00910 return;
00911 }
00912 BG_TouchJumpPad( &other->client->ps, &self->s );
00913 return;
00914 }
00915
00916
00917 if( level.time < self->painDebounceTime + self->wait )
00918 {
00919 if( self->spawnflags & PUSH_MULTIPLE )
00920 {
00921 if ( self->painDebounceTime && level.time > self->painDebounceTime )
00922 {
00923 return;
00924 }
00925 }
00926 else
00927 {
00928 return;
00929 }
00930 }
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 if ( !other->client ) {
00972 if ( other->s.pos.trType != TR_STATIONARY && other->s.pos.trType != TR_LINEAR_STOP && other->s.pos.trType != TR_NONLINEAR_STOP && VectorLengthSquared( other->s.pos.trDelta ) )
00973 {
00974 VectorCopy( other->r.currentOrigin, other->s.pos.trBase );
00975 VectorCopy( self->s.origin2, other->s.pos.trDelta );
00976 other->s.pos.trTime = level.time;
00977 }
00978 return;
00979 }
00980
00981 if ( other->client->ps.pm_type != PM_NORMAL
00982 && other->client->ps.pm_type != PM_DEAD
00983 && other->client->ps.pm_type != PM_FREEZE )
00984 {
00985 return;
00986 }
00987
00988 if ( (self->spawnflags&PUSH_RELATIVE) )
00989 {
00990 vec3_t dir;
00991 VectorSubtract( self->s.origin2, other->r.currentOrigin, dir );
00992 if ( self->speed )
00993 {
00994 VectorNormalize( dir );
00995 VectorScale( dir, self->speed, dir );
00996 }
00997 VectorCopy( dir, other->client->ps.velocity );
00998 }
00999 else if ( (self->spawnflags&PUSH_LINEAR) )
01000 {
01001 VectorScale( self->s.origin2, self->speed, other->client->ps.velocity );
01002 }
01003 else
01004 {
01005 VectorCopy( self->s.origin2, other->client->ps.velocity );
01006 }
01007
01008
01009
01010
01011
01012
01013
01014 if ( self->wait == -1 )
01015 {
01016 self->touch = NULL;
01017 }
01018 else if ( self->wait > 0 )
01019 {
01020 self->painDebounceTime = level.time;
01021
01022 }
01023
01024
01025
01026
01027
01028
01029 }
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 void AimAtTarget( gentity_t *self ) {
01040 gentity_t *ent;
01041 vec3_t origin;
01042 float height, gravity, time, forward;
01043 float dist;
01044
01045 VectorAdd( self->r.absmin, self->r.absmax, origin );
01046 VectorScale ( origin, 0.5f, origin );
01047
01048 ent = G_PickTarget( self->target );
01049 if ( !ent ) {
01050 G_FreeEntity( self );
01051 return;
01052 }
01053
01054 if ( self->classname && !Q_stricmp( "trigger_push", self->classname ) )
01055 {
01056 if ( (self->spawnflags&PUSH_RELATIVE) )
01057 {
01058 VectorCopy( ent->r.currentOrigin, self->s.origin2 );
01059 return;
01060 }
01061 else if ( (self->spawnflags&PUSH_LINEAR) )
01062 {
01063 VectorSubtract( ent->r.currentOrigin, origin, self->s.origin2 );
01064 VectorNormalize( self->s.origin2 );
01065 return;
01066 }
01067 }
01068
01069 if ( self->classname && !Q_stricmp( "target_push", self->classname ) )
01070 {
01071 if( self->spawnflags & PUSH_CONSTANT )
01072 {
01073 VectorSubtract ( ent->s.origin, self->s.origin, self->s.origin2 );
01074 VectorNormalize( self->s.origin2);
01075 VectorScale (self->s.origin2, self->speed, self->s.origin2);
01076 return;
01077 }
01078 }
01079
01080 height = ent->s.origin[2] - origin[2];
01081 gravity = g_gravity.value;
01082 time = sqrt( height / ( .5 * gravity ) );
01083 if ( !time ) {
01084 G_FreeEntity( self );
01085 return;
01086 }
01087
01088
01089 VectorSubtract ( ent->s.origin, origin, self->s.origin2 );
01090 self->s.origin2[2] = 0;
01091 dist = VectorNormalize( self->s.origin2);
01092
01093 forward = dist / time;
01094 VectorScale( self->s.origin2, forward, self->s.origin2 );
01095
01096 self->s.origin2[2] = time * gravity;
01097 }
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112 void SP_trigger_push( gentity_t *self ) {
01113 InitTrigger (self);
01114
01115
01116 self->r.svFlags &= ~SVF_NOCLIENT;
01117
01118
01119 G_SoundIndex("sound/weapons/force/jump.wav");
01120
01121 self->s.eType = ET_PUSH_TRIGGER;
01122
01123 if ( !(self->spawnflags&2) )
01124 {
01125 self->touch = trigger_push_touch;
01126 }
01127
01128 if ( self->spawnflags & 4 )
01129 {
01130 self->speed = 1000;
01131 }
01132
01133 self->think = AimAtTarget;
01134 self->nextthink = level.time + FRAMETIME;
01135 trap_LinkEntity (self);
01136 }
01137
01138 void Use_target_push( gentity_t *self, gentity_t *other, gentity_t *activator ) {
01139 if ( !activator->client ) {
01140 return;
01141 }
01142
01143 if ( activator->client->ps.pm_type != PM_NORMAL && activator->client->ps.pm_type != PM_FLOAT ) {
01144 return;
01145 }
01146
01147 G_ActivateBehavior(self,BSET_USE);
01148
01149 VectorCopy (self->s.origin2, activator->client->ps.velocity);
01150
01151
01152 if ( activator->fly_sound_debounce_time < level.time ) {
01153 activator->fly_sound_debounce_time = level.time + 1500;
01154 if (self->noise_index)
01155 {
01156 G_Sound( activator, CHAN_AUTO, self->noise_index );
01157 }
01158 }
01159 }
01160
01161
01162
01163
01164
01165
01166
01167
01168 void SP_target_push( gentity_t *self ) {
01169 if (!self->speed) {
01170 self->speed = 1000;
01171 }
01172 G_SetMovedir (self->s.angles, self->s.origin2);
01173 VectorScale (self->s.origin2, self->speed, self->s.origin2);
01174
01175 if ( self->spawnflags & 1 ) {
01176 self->noise_index = G_SoundIndex("sound/weapons/force/jump.wav");
01177 } else {
01178 self->noise_index = 0;
01179 }
01180 if ( self->target ) {
01181 VectorCopy( self->s.origin, self->r.absmin );
01182 VectorCopy( self->s.origin, self->r.absmax );
01183 self->think = AimAtTarget;
01184 self->nextthink = level.time + FRAMETIME;
01185 }
01186 self->use = Use_target_push;
01187 }
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197 void trigger_teleporter_touch (gentity_t *self, gentity_t *other, trace_t *trace ) {
01198 gentity_t *dest;
01199
01200 if ( self->flags & FL_INACTIVE )
01201 {
01202 return;
01203 }
01204
01205 if ( !other->client ) {
01206 return;
01207 }
01208 if ( other->client->ps.pm_type == PM_DEAD ) {
01209 return;
01210 }
01211
01212 if ( ( self->spawnflags & 1 ) &&
01213 other->client->sess.sessionTeam != TEAM_SPECTATOR ) {
01214 return;
01215 }
01216
01217
01218 dest = G_PickTarget( self->target );
01219 if (!dest) {
01220 G_Printf ("Couldn't find teleporter destination\n");
01221 return;
01222 }
01223
01224 TeleportPlayer( other, dest->s.origin, dest->s.angles );
01225 }
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236 void SP_trigger_teleport( gentity_t *self ) {
01237 InitTrigger (self);
01238
01239
01240
01241 if ( self->spawnflags & 1 ) {
01242 self->r.svFlags |= SVF_NOCLIENT;
01243 } else {
01244 self->r.svFlags &= ~SVF_NOCLIENT;
01245 }
01246
01247
01248 G_SoundIndex("sound/weapons/force/speed.wav");
01249
01250 self->s.eType = ET_TELEPORT_TRIGGER;
01251 self->touch = trigger_teleporter_touch;
01252
01253 trap_LinkEntity (self);
01254 }
01255
01256
01257
01258
01259
01260
01261
01262