#include "g_local.h"#include "bg_saga.h"#include "../namespace_begin.h"#include "../namespace_end.h"Go to the source code of this file.
|
|
Definition at line 1097 of file g_active.c. |
|
|
Definition at line 1098 of file g_active.c. |
|
|
Definition at line 1100 of file g_active.c. |
|
|
Definition at line 1101 of file g_active.c. |
|
|
Referenced by ClientThink_real(). |
|
|
Referenced by ClientThink_real(). |
|
|
Definition at line 1653 of file g_active.c.
01654 {
01655 TAUNT_TAUNT = 0,
01656 TAUNT_BOW,
01657 TAUNT_MEDITATE,
01658 TAUNT_FLOURISH,
01659 TAUNT_GLOAT
01660 };
|
|
|
Definition at line 930 of file bg_panimate.c. References BOTH_KNOCKDOWN1, BOTH_KNOCKDOWN2, BOTH_KNOCKDOWN3, BOTH_KNOCKDOWN4, BOTH_KNOCKDOWN5, qboolean, qfalse, and qtrue. Referenced by ClientEvents(), and DoFall().
00931 {
00932 switch ( anim )
00933 {
00934 case BOTH_KNOCKDOWN1:
00935 case BOTH_KNOCKDOWN2:
00936 case BOTH_KNOCKDOWN3:
00937 case BOTH_KNOCKDOWN4:
00938 case BOTH_KNOCKDOWN5:
00939 return qtrue;
00940 }
00941 return qfalse;
00942 }
|
|
||||||||||||
|
Definition at line 407 of file g_active.c. References gentity_s::client, DoImpact(), FL_BBRUSH, gentity_s::flags, gentity_t, gentity_s::health, gentity_s::inuse, level, MAT_GLASS, MAT_GLASS_METAL, MAT_GRATE1, gentity_s::material, qfalse, gentity_s::r, gclient_s::sess, clientSession_t::sessionTeam, gentity_s::spawnflags, SVF_GLASS_BRUSH, entityShared_t::svFlags, TEAM_SPECTATOR, gclient_s::tempSpectate, and level_locals_t::time.
00408 {
00409 if ( !other || !other->inuse )
00410 {
00411 return;
00412 }
00413 if (!self || !self->inuse || !self->client ||
00414 self->client->tempSpectate >= level.time ||
00415 self->client->sess.sessionTeam == TEAM_SPECTATOR)
00416 { //hmm.. let's not let spectators ram into breakables.
00417 return;
00418 }
00419
00420 /*
00421 if (BG_InSpecialJump(self->client->ps.legsAnim))
00422 { //don't do this either, qa says it creates "balance issues"
00423 return;
00424 }
00425 */
00426
00427 if ( other->material == MAT_GLASS
00428 || other->material == MAT_GLASS_METAL
00429 || other->material == MAT_GRATE1
00430 || ((other->flags&FL_BBRUSH)&&(other->spawnflags&8/*THIN*/))
00431 || ((other->flags&FL_BBRUSH)&&(other->health<=10))
00432 || (other->r.svFlags&SVF_GLASS_BRUSH) )
00433 {//clients only do impact damage against easy-break breakables
00434 DoImpact( self, other, qfalse );
00435 }
00436 }
|
|
|
Definition at line 3766 of file g_active.c. References BG_PlayerStateToEntityState(), BG_PlayerStateToEntityStateExtraPolate(), CLASS_VEHICLE, gentity_s::client, playerState_s::commandTime, EF_CONNECTION, entityState_s::eFlags, ET_NPC, entityState_s::eType, G_SetClientSound(), g_smoothClients, g_synchronousClients, gentity_t, gentity_s::health, vmCvar_t::integer, level_locals_t::intermissiontime, gclient_s::lastCmdTime, level, MAX_CLIENTS, MAX_POWERUPS, gclient_s::NPC_class, entityState_s::number, P_DamageFeedback(), P_WorldEffects(), gclient_s::pers, PM_FLOAT, PM_JETPACK, PM_NORMAL, playerState_s::pm_type, playerState_s::powerups, gclient_s::ps, qboolean, qfalse, qtrue, gentity_s::s, SendPendingPredictableEvents(), gclient_s::sess, clientSession_t::sessionTeam, SpectatorClientEndFrame(), STAT_HEALTH, playerState_s::stats, TEAM_SPECTATOR, level_locals_t::time, VectorClear, and playerState_s::viewangles. Referenced by ClientSpawn(), and G_RunFrame().
03766 {
03767 int i;
03768 clientPersistant_t *pers;
03769 qboolean isNPC = qfalse;
03770
03771 if (ent->s.eType == ET_NPC)
03772 {
03773 isNPC = qtrue;
03774 }
03775
03776 if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
03777 SpectatorClientEndFrame( ent );
03778 return;
03779 }
03780
03781 pers = &ent->client->pers;
03782
03783 // turn off any expired powerups
03784 for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
03785 if ( ent->client->ps.powerups[ i ] < level.time ) {
03786 ent->client->ps.powerups[ i ] = 0;
03787 }
03788 }
03789
03790 // save network bandwidth
03791 #if 0
03792 if ( !g_synchronousClients->integer && (ent->client->ps.pm_type == PM_NORMAL || ent->client->ps.pm_type == PM_JETPACK || ent->client->ps.pm_type == PM_FLOAT) ) {
03793 // FIXME: this must change eventually for non-sync demo recording
03794 VectorClear( ent->client->ps.viewangles );
03795 }
03796 #endif
03797
03798 //
03799 // If the end of unit layout is displayed, don't give
03800 // the player any normal movement attributes
03801 //
03802 if ( level.intermissiontime ) {
03803 if ( ent->s.number < MAX_CLIENTS
03804 || ent->client->NPC_class == CLASS_VEHICLE )
03805 {//players and vehicles do nothing in intermissions
03806 return;
03807 }
03808 }
03809
03810 // burn from lava, etc
03811 P_WorldEffects (ent);
03812
03813 // apply all the damage taken this frame
03814 P_DamageFeedback (ent);
03815
03816 // add the EF_CONNECTION flag if we haven't gotten commands recently
03817 if ( level.time - ent->client->lastCmdTime > 1000 ) {
03818 ent->s.eFlags |= EF_CONNECTION;
03819 } else {
03820 ent->s.eFlags &= ~EF_CONNECTION;
03821 }
03822
03823 ent->client->ps.stats[STAT_HEALTH] = ent->health; // FIXME: get rid of ent->health...
03824
03825 G_SetClientSound (ent);
03826
03827 // set the latest infor
03828 if (g_smoothClients.integer) {
03829 BG_PlayerStateToEntityStateExtraPolate( &ent->client->ps, &ent->s, ent->client->ps.commandTime, qfalse );
03830 //rww - 12-03-02 - Don't snap the origin of players! It screws prediction all up.
03831 }
03832 else {
03833 BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qfalse );
03834 }
03835
03836 if (isNPC)
03837 {
03838 ent->s.eType = ET_NPC;
03839 }
03840
03841 SendPendingPredictableEvents( &ent->client->ps );
03842
03843 // set the bit for the reachability area the client is currently in
03844 // i = trap_AAS_PointReachabilityAreaIndex( ent->client->ps.origin );
03845 // ent->client->areabits[i >> 3] |= 1 << (i & 7);
03846 }
|
|
||||||||||||
|
Definition at line 909 of file g_active.c. References BG_InKnockDownOnly(), CHAN_AUTO, gentity_s::client, client, DAMAGE_NO_ARMOR, gclient_s::dangerTime, DF_NO_FALLING, EF_INVULNERABLE, playerState_s::eFlags, ET_PLAYER, entityState_s::eType, EV_ALT_FIRE, EV_FALL, EV_FIRE_WEAPON, EV_ROLL, EV_SABER_ATTACK, EV_USE_ITEM1, EV_USE_ITEM10, EV_USE_ITEM11, EV_USE_ITEM2, EV_USE_ITEM3, EV_USE_ITEM4, EV_USE_ITEM5, EV_USE_ITEM6, EV_USE_ITEM7, EV_USE_ITEM8, EV_USE_ITEM9, playerState_s::eventParms, playerState_s::events, playerState_s::eventSequence, playerState_s::fallingToDeath, FireWeapon(), G_Damage(), g_dmflags, g_gametype, G_Sound(), G_SoundIndex(), gclient_t, gentity_t, GT_SIEGE, gentity_s::health, vmCvar_t::integer, gclient_s::invulnerableTimer, ItemUse_Binoculars(), ItemUse_Jetpack(), ItemUse_MedPack(), ItemUse_MedPack_Big(), ItemUse_Seeker(), ItemUse_Sentry(), ItemUse_Shield(), ItemUse_UseCloak(), ItemUse_UseEWeb(), playerState_s::legsAnim, level, MAX_PS_EVENTS, MOD_FALLING, NULL, gentity_s::pain_debounce_time, gclient_s::ps, qboolean, qfalse, qtrue, gentity_s::s, level_locals_t::time, vec3_t, and VectorSet. Referenced by ClientThink_real().
00909 {
00910 int i;//, j;
00911 int event;
00912 gclient_t *client;
00913 int damage;
00914 vec3_t dir;
00915 // vec3_t origin, angles;
00916 // qboolean fired;
00917 // gitem_t *item;
00918 // gentity_t *drop;
00919
00920 client = ent->client;
00921
00922 if ( oldEventSequence < client->ps.eventSequence - MAX_PS_EVENTS ) {
00923 oldEventSequence = client->ps.eventSequence - MAX_PS_EVENTS;
00924 }
00925 for ( i = oldEventSequence ; i < client->ps.eventSequence ; i++ ) {
00926 event = client->ps.events[ i & (MAX_PS_EVENTS-1) ];
00927
00928 switch ( event ) {
00929 case EV_FALL:
00930 case EV_ROLL:
00931 {
00932 int delta = client->ps.eventParms[ i & (MAX_PS_EVENTS-1) ];
00933 qboolean knockDownage = qfalse;
00934
00935 if (ent->client && ent->client->ps.fallingToDeath)
00936 {
00937 break;
00938 }
00939
00940 if ( ent->s.eType != ET_PLAYER )
00941 {
00942 break; // not in the player model
00943 }
00944
00945 if ( g_dmflags.integer & DF_NO_FALLING )
00946 {
00947 break;
00948 }
00949
00950 if (BG_InKnockDownOnly(ent->client->ps.legsAnim))
00951 {
00952 if (delta <= 14)
00953 {
00954 break;
00955 }
00956 knockDownage = qtrue;
00957 }
00958 else
00959 {
00960 if (delta <= 44)
00961 {
00962 break;
00963 }
00964 }
00965
00966 if (knockDownage)
00967 {
00968 damage = delta*1; //you suffer for falling unprepared. A lot. Makes throws and things useful, and more realistic I suppose.
00969 }
00970 else
00971 {
00972 if (g_gametype.integer == GT_SIEGE &&
00973 delta > 60)
00974 { //longer falls hurt more
00975 damage = delta*1; //good enough for now, I guess
00976 }
00977 else
00978 {
00979 damage = delta*0.16; //good enough for now, I guess
00980 }
00981 }
00982
00983 VectorSet (dir, 0, 0, 1);
00984 ent->pain_debounce_time = level.time + 200; // no normal pain sound
00985 G_Damage (ent, NULL, NULL, NULL, NULL, damage, DAMAGE_NO_ARMOR, MOD_FALLING);
00986
00987 if (ent->health < 1)
00988 {
00989 G_Sound(ent, CHAN_AUTO, G_SoundIndex( "sound/player/fallsplat.wav" ));
00990 }
00991 }
00992 break;
00993 case EV_FIRE_WEAPON:
00994 FireWeapon( ent, qfalse );
00995 ent->client->dangerTime = level.time;
00996 ent->client->ps.eFlags &= ~EF_INVULNERABLE;
00997 ent->client->invulnerableTimer = 0;
00998 break;
00999
01000 case EV_ALT_FIRE:
01001 FireWeapon( ent, qtrue );
01002 ent->client->dangerTime = level.time;
01003 ent->client->ps.eFlags &= ~EF_INVULNERABLE;
01004 ent->client->invulnerableTimer = 0;
01005 break;
01006
01007 case EV_SABER_ATTACK:
01008 ent->client->dangerTime = level.time;
01009 ent->client->ps.eFlags &= ~EF_INVULNERABLE;
01010 ent->client->invulnerableTimer = 0;
01011 break;
01012
01013 //rww - Note that these must be in the same order (ITEM#-wise) as they are in holdable_t
01014 case EV_USE_ITEM1: //seeker droid
01015 ItemUse_Seeker(ent);
01016 break;
01017 case EV_USE_ITEM2: //shield
01018 ItemUse_Shield(ent);
01019 break;
01020 case EV_USE_ITEM3: //medpack
01021 ItemUse_MedPack(ent);
01022 break;
01023 case EV_USE_ITEM4: //big medpack
01024 ItemUse_MedPack_Big(ent);
01025 break;
01026 case EV_USE_ITEM5: //binoculars
01027 ItemUse_Binoculars(ent);
01028 break;
01029 case EV_USE_ITEM6: //sentry gun
01030 ItemUse_Sentry(ent);
01031 break;
01032 case EV_USE_ITEM7: //jetpack
01033 ItemUse_Jetpack(ent);
01034 break;
01035 case EV_USE_ITEM8: //health disp
01036 //ItemUse_UseDisp(ent, HI_HEALTHDISP);
01037 break;
01038 case EV_USE_ITEM9: //ammo disp
01039 //ItemUse_UseDisp(ent, HI_AMMODISP);
01040 break;
01041 case EV_USE_ITEM10: //eweb
01042 ItemUse_UseEWeb(ent);
01043 break;
01044 case EV_USE_ITEM11: //cloak
01045 ItemUse_UseCloak(ent);
01046 break;
01047 default:
01048 break;
01049 }
01050 }
01051
01052 }
|
|
||||||||||||
|
Definition at line 478 of file g_active.c. References g_entities, gentity_t, memset(), pmove_t::numtouch, pm, gentity_s::r, SVF_BOT, entityShared_t::svFlags, gentity_s::touch, and pmove_t::touchents. Referenced by ClientThink_real().
00478 {
00479 int i, j;
00480 trace_t trace;
00481 gentity_t *other;
00482
00483 memset( &trace, 0, sizeof( trace ) );
00484 for (i=0 ; i<pm->numtouch ; i++) {
00485 for (j=0 ; j<i ; j++) {
00486 if (pm->touchents[j] == pm->touchents[i] ) {
00487 break;
00488 }
00489 }
00490 if (j != i) {
00491 continue; // duplicated
00492 }
00493 other = &g_entities[ pm->touchents[i] ];
00494
00495 if ( ( ent->r.svFlags & SVF_BOT ) && ( ent->touch ) ) {
00496 ent->touch( ent, other, &trace );
00497 }
00498
00499 if ( !other->touch ) {
00500 continue;
00501 }
00502
00503 other->touch( other, ent, &trace );
00504 }
00505
00506 }
|
|
|
|
Definition at line 810 of file g_active.c. References BUTTON_ATTACK, BUTTON_USE_HOLDABLE, usercmd_s::buttons, gclient_s::buttons, client, clientPersistant_t::cmd, EF_FIRING, EF_TALK, playerState_s::eFlags, gclient_t, gclient_s::oldbuttons, gclient_s::pers, gclient_s::ps, and gclient_s::readyToExit. Referenced by ClientThink_real().
00810 {
00811 client->ps.eFlags &= ~EF_TALK;
00812 client->ps.eFlags &= ~EF_FIRING;
00813
00814 // the level will exit when everyone wants to or after timeouts
00815
00816 // swap and latch button actions
00817 client->oldbuttons = client->buttons;
00818 client->buttons = client->pers.cmd.buttons;
00819 if ( client->buttons & ( BUTTON_ATTACK | BUTTON_USE_HOLDABLE ) & ( client->oldbuttons ^ client->buttons ) ) {
00820 // this used to be an ^1 but once a player says ready, it should stick
00821 client->readyToExit = 1;
00822 }
00823 }
|
|
||||||||||||
|
Definition at line 3621 of file g_active.c. References gentity_s::client, ClientThink_real(), clientPersistant_t::cmd, g_entities, g_synchronousClients, gentity_t, vmCvar_t::integer, gclient_s::lastCmdTime, level, MAX_CLIENTS, gclient_s::pers, gentity_s::r, SVF_BOT, entityShared_t::svFlags, level_locals_t::time, trap_GetUsercmd(), ucmd, and usercmd_t. Referenced by ClientSpawn(), ClientThink_real(), CorpsePhysics(), NPC_Begin(), NPC_ExecuteBState(), NPC_Think(), and vmMain().
03621 {
03622 gentity_t *ent;
03623
03624 ent = g_entities + clientNum;
03625 if (clientNum < MAX_CLIENTS)
03626 {
03627 trap_GetUsercmd( clientNum, &ent->client->pers.cmd );
03628 }
03629
03630 // mark the time we got info, so we can display the
03631 // phone jack if they don't get any for a while
03632 ent->client->lastCmdTime = level.time;
03633
03634 if (ucmd)
03635 {
03636 ent->client->pers.cmd = *ucmd;
03637 }
03638
03639 /* This was moved to clientthink_real, but since its sort of a risky change i left it here for
03640 now as a more concrete reference - BSD
03641
03642 if ( clientNum < MAX_CLIENTS
03643 && ent->client->ps.m_iVehicleNum )
03644 {//driving a vehicle
03645 if (g_entities[ent->client->ps.m_iVehicleNum].client)
03646 {
03647 gentity_t *veh = &g_entities[ent->client->ps.m_iVehicleNum];
03648
03649 if (veh->m_pVehicle &&
03650 veh->m_pVehicle->m_pPilot == (bgEntity_t *)ent)
03651 { //only take input from the pilot...
03652 veh->client->ps.commandTime = ent->client->ps.commandTime;
03653 memcpy(&veh->m_pVehicle->m_ucmd, &ent->client->pers.cmd, sizeof(usercmd_t));
03654 if ( veh->m_pVehicle->m_ucmd.buttons & BUTTON_TALK )
03655 { //forced input if "chat bubble" is up
03656 veh->m_pVehicle->m_ucmd.buttons = BUTTON_TALK;
03657 veh->m_pVehicle->m_ucmd.forwardmove = 0;
03658 veh->m_pVehicle->m_ucmd.rightmove = 0;
03659 veh->m_pVehicle->m_ucmd.upmove = 0;
03660 }
03661 }
03662 }
03663 }
03664 */
03665 if ( !(ent->r.svFlags & SVF_BOT) && !g_synchronousClients.integer ) {
03666 ClientThink_real( ent );
03667 }
03668 // vehicles are clients and when running synchronous they still need to think here
03669 // so special case them.
03670 else if ( clientNum >= MAX_CLIENTS ) {
03671 ClientThink_real( ent );
03672 }
03673
03674 /* This was moved to clientthink_real, but since its sort of a risky change i left it here for
03675 now as a more concrete reference - BSD
03676
03677 if ( clientNum < MAX_CLIENTS
03678 && ent->client->ps.m_iVehicleNum )
03679 {//driving a vehicle
03680 //run it
03681 if (g_entities[ent->client->ps.m_iVehicleNum].inuse &&
03682 g_entities[ent->client->ps.m_iVehicleNum].client)
03683 {
03684 ClientThink(ent->client->ps.m_iVehicleNum, &g_entities[ent->client->ps.m_iVehicleNum].m_pVehicle->m_ucmd);
03685 }
03686 else
03687 { //vehicle no longer valid?
03688 ent->client->ps.m_iVehicleNum = 0;
03689 }
03690 }
03691 */
03692 }
|
|
|
Definition at line 1939 of file g_active.c. References gNPC_t::aiFlags, AngleDelta(), AngleVectors(), pmove_t::animations, pmove_t::baseEnt, playerState_s::basespeed, gclient_s::beingThrown, BG_KnockDownable(), BG_PlayerStateToEntityState(), BG_PlayerStateToEntityStateExtraPolate(), BG_SaberInAttack(), bgAllAnims, bgEntity_t, bgSiegeClasses, gclient_s::bodyGrabIndex, BUTTON_ALT_ATTACK, BUTTON_ATTACK, BUTTON_GESTURE, BUTTON_TALK, BUTTON_USE, BUTTON_USE_HOLDABLE, BUTTON_WALKING, gclient_s::buttons, usercmd_s::buttons, ceil(), CHAN_AUTO, CHAN_VOICE, pmove_t::checkDuelLoss, CLASS_VEHICLE, gentity_s::client, client, ClientEvents(), ClientImpacts(), ClientInactivityTimer(), ClientIntermissionThink(), ClientThink(), ClientTimerActions(), gentity_s::clipmask, pmove_t::cmd, clientPersistant_t::cmd, Cmd_EngageDuel_f(), Cmd_SaberAttackCycle_f(), Cmd_ToggleSaber_f(), gNPC_t::combatMove, playerState_s::commandTime, CON_CONNECTED, clientPersistant_t::connected, entityShared_t::contents, CONTENTS_BODY, CONTENTS_LADDER, CONTENTS_MONSTERCLIP, CONTENTS_SOLID, entityShared_t::currentAngles, entityShared_t::currentOrigin, gNPC_t::currentSpeed, DAMAGE_NO_ARMOR, DAMAGE_NO_PROTECTION, pmove_t::debugLevel, pmove_t::debugMelee, gNPC_t::desiredSpeed, gNPC_t::desiredYaw, DF_NO_FOOTSTEPS, gNPC_t::distToGoal, gclient_s::doingThrow, playerState_s::duelIndex, playerState_s::duelInProgress, playerState_s::duelTime, EF2_FLYING, EF2_HELD_BY_MONSTER, EF2_SHIP_DEATH, EF_BODYPUSH, EF_DISINTEGRATION, EF_FIRING, EF_INVULNERABLE, EF_JETPACK, EF_JETPACK_ACTIVE, EF_JETPACK_FLAMING, EF_NODRAW, entityState_s::eFlags, playerState_s::eFlags, playerState_s::eFlags2, ENTITYNUM_NONE, pmove_t::entSize, gentity_s::epVelocity, ET_BODY, ET_NPC, entityState_s::eType, EV_PRIVATE_DUEL, EV_USE_ITEM0, playerState_s::eventSequence, gentity_s::eventTime, fabs(), FALL_FADE_TIME, playerState_s::fallingToDeath, playerState_s::fd, gclient_s::fireHeld, FL_FORCE_GESTURE, gentity_s::flags, floor(), FORCE_LEVEL_3, ForceAbsorb(), playerState_s::forceDodgeAnim, playerState_s::forceGripChangeMovetype, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, ForceHeal(), playerState_s::forceKickFlip, forcedata_s::forcePowerLevel, forcedata_s::forcePowersActive, ForceProtect(), ForceRage(), forcedata_s::forceRageRecoveryTime, ForceSeeing(), ForceSpeed(), ForceTeamForceReplenish(), ForceTeamHeal(), ForceTelepathy(), ForceThrow(), usercmd_s::forwardmove, FP_RAGE, trace_t::fraction, pmove_t::g2Bolts_LFoot, pmove_t::g2Bolts_RFoot, G_AddEvent(), G_AddPushVecToUcmd(), G_CheckClientIdle(), G_CheckForDismemberment(), G_CheckMovingLoopingSounds(), G_Damage(), g_debugMelee, g_debugMove, g_dmflags, g_entities, G_EntitySound(), g_forcerespawn, g_friendlyFire, g_gametype, G_GetStringEdString(), g_gravity, G_HeldByMonster(), G_ItemUsable(), G_MuteSound(), g_noSpecMove, G_PreDefSound(), g_saberLockRandomNess, G_SetTauntAnim(), g_siegeRespawn, g_smoothClients, G_Sound(), G_SoundIndex(), g_spawnInvulnerability, g_speed, g_stepSlideFix, G_TouchTriggers(), G_UpdateClientBroadcasts(), pmove_t::gametype, gclient_t, gDoSlowMoDuel, GENCMD_BOW, GENCMD_ENGAGE_DUEL, GENCMD_FLOURISH, GENCMD_FORCE_ABSORB, GENCMD_FORCE_DISTRACT, GENCMD_FORCE_FORCEPOWEROTHER, GENCMD_FORCE_HEAL, GENCMD_FORCE_HEALOTHER, GENCMD_FORCE_PROTECT, GENCMD_FORCE_PULL, GENCMD_FORCE_RAGE, GENCMD_FORCE_SEEING, GENCMD_FORCE_SPEED, GENCMD_FORCE_THROW, GENCMD_GLOAT, GENCMD_MEDITATE, GENCMD_SABERATTACKCYCLE, GENCMD_SABERSWITCH, GENCMD_TAUNT, GENCMD_USE_AMMODISP, GENCMD_USE_BACTA, GENCMD_USE_BACTABIG, GENCMD_USE_CLOAK, GENCMD_USE_ELECTROBINOCULARS, GENCMD_USE_EWEB, GENCMD_USE_FIELD, GENCMD_USE_HEALTHDISP, GENCMD_USE_JETPACK, GENCMD_USE_SEEKER, GENCMD_USE_SENTRY, GENCMD_ZOOM, usercmd_s::generic_cmd, gentity_t, gGAvoidDismember, pmove_t::ghoul2, gentity_s::ghoul2, playerState_s::gravity, vehicleInfo_t::gravity, playerState_s::groundEntityNum, GT_DUEL, GT_POWERDUEL, GT_SIEGE, HANDEXTEND_DRAGGING, HANDEXTEND_KNOCKDOWN, HANDEXTEND_NONE, HANDEXTEND_POSTTHROW, HANDEXTEND_POSTTHROWN, HANDEXTEND_WEAPONREADY, gentity_s::health, playerState_s::heldByClient, HI_AMMODISP, HI_BINOCULARS, HI_CLOAK, HI_EWEB, HI_HEALTHDISP, HI_JETPACK, HI_MEDPAC, HI_MEDPAC_BIG, HI_SEEKER, HI_SENTRY_GUN, HI_SHIELD, gclient_s::inSpaceIndex, vmCvar_t::integer, level_locals_t::intermissiontime, gentity_s::inuse, gclient_s::invulnerableTimer, ItemUse_Binoculars(), ItemUse_Jetpack(), ItemUse_MedPack(), ItemUse_MedPack_Big(), ItemUse_Seeker(), ItemUse_Sentry(), ItemUse_Shield(), ItemUse_UseEWeb(), Jedi_Cloak(), Jedi_Decloak(), gclient_s::jetPackOn, gNPC_t::last_ucmd, gclient_s::lastGenCmd, gclient_s::lastGenCmdTime, gclient_s::latched_buttons, playerState_s::legsAnim, level, gentity_s::localAnimIndex, saberInfo_t::lockBonus, gNPC_t::lockedDesiredYaw, Vehicle_s::m_iRemovedSurfaces, playerState_s::m_iVehicleNum, Vehicle_s::m_pPilot, gentity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, Vehicle_s::m_ucmd, MASK_PLAYERSOLID, mdxaBone_t::matrix, MAX_CLIENTS, MAX_GENTITIES, MAX_SABERS, pmove_t::maxs, entityShared_t::maxs, memcpy(), memset(), MIN_NPC_SPEED, pmove_t::mins, entityShared_t::mins, MOD_CRUSH, MOD_FALLING, MOD_MELEE, MOD_SABER, saberInfo_t::model, pmove_t::modelScale, gentity_s::modelScale, clientPersistant_t::netname, gclient_s::noclip, pmove_t::noFootsteps, pmove_t::nonHumanoid, pmove_t::noSpecMove, gentity_s::NPC, NPC_Accelerate(), entityState_s::NPC_class, gclient_s::NPC_class, NPCAI_CUSTOM_GRAVITY, NPCAI_NO_SLOWDOWN, NULL, entityState_s::number, gclient_s::oldbuttons, gclient_s::oldOrigin, OnSameTeam(), ORIGIN, playerState_s::origin, playerState_s::otherKiller, playerState_s::otherKillerDebounceTime, playerState_s::otherKillerTime, PDSOUND_FORCEJUMP, gclient_s::pers, PITCH, pm, PM_DEAD, playerState_s::pm_flags, PM_JETPACK, PM_NOCLIP, PM_NORMAL, PM_SaberInReturn(), PM_SaberInStart(), PM_SaberInTransition(), playerState_s::pm_type, PMF_FOLLOW, Pmove(), pmove_t::pmove_fixed, pmove_fixed, pmove_t::pmove_msec, pmove_msec, clientPersistant_t::pmoveFixed, pmove_t::pointcontents, entityState_s::pos, playerState_s::powerups, forcedata_s::privateDuelTime, pmove_t::ps, gclient_s::ps, gclient_s::pushEffectTime, PW_CLOAKED, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, entityState_s::ragAttach, respawn(), gclient_s::respawnTime, usercmd_s::rightmove, ROLL, bgEntity_s::s, gentity_s::s, gclient_s::saber, forcedata_s::saberAnimLevel, forcedata_s::saberAnimLevelBase, saberCheckKnockdown_DuelLoss(), forcedata_s::saberDrawAnimLevel, playerState_s::saberEntityNum, playerState_s::saberHolstered, playerState_s::saberLockAdvance, playerState_s::saberLockEnemy, playerState_s::saberLockFrame, playerState_s::saberLockHitCheckTime, playerState_s::saberLockHitIncrementTime, playerState_s::saberLockHits, playerState_s::saberLockTime, playerState_s::saberMove, SendPendingPredictableEvents(), usercmd_s::serverTime, gclient_s::sess, clientSession_t::sessionTeam, SetClientViewAngle(), gclient_s::siegeClass, saberInfo_t::singleBladeStyle, SLOWDOWN_DIST, gclient_s::solidHack, saberInfo_t::soundOn, SPECTATOR_FOLLOW, SPECTATOR_SCOREBOARD, clientSession_t::spectatorState, SpectatorThink(), playerState_s::speed, SS_DESANN, SS_DUAL, SS_FAST, SS_MEDIUM, SS_NONE, SS_NUM_SABER_STYLES, SS_STAFF, SS_STRONG, SS_TAVION, trace_t::startsolid, STAT_HEALTH, STAT_HOLDABLE_ITEMS, STAT_MAX_HEALTH, gNPC_t::stats, playerState_s::stats, pmove_t::stepSlideFix, saberInfo_t::stylesLearned, SVF_BOT, entityShared_t::svFlags, gentity_s::takedamage, TAUNT_BOW, TAUNT_FLOURISH, TAUNT_GLOAT, TAUNT_MEDITATE, TAUNT_TAUNT, TEAM_SPECTATOR, gclient_s::tempSpectate, gclient_s::throwingIndex, level_locals_t::time, pmove_t::trace, pmove_t::tracemask, trap_Cvar_Set(), trap_G2_HaveWeGhoul2Models(), trap_G2API_AddBolt(), trap_G2API_GetBoltMatrix(), trap_LinkEntity(), trap_PointContents(), trap_SendServerCommand(), trap_Trace(), trajectory_t::trBase, TryUse(), vehicleInfo_t::type, ucmd, usercmd_s::upmove, playerState_s::useDelay, pmove_t::useEvent, usercmd_t, va(), vmCvar_t::value, vec3_t, vectoangles(), VectorAdd, VectorClear, VectorCopy, VectorNormalize(), VectorNormalize2(), VectorScale, VectorSet, VectorSubtract, vectoyaw(), playerState_s::velocity, VH_WALKER, playerState_s::viewangles, gNPCstats_e::walkSpeed, pmove_t::waterlevel, gentity_s::waterlevel, pmove_t::watertype, gentity_s::watertype, playerState_s::weapon, WP_SABER, WP_SaberStyleValidForSaber(), YAW, and playerState_s::zoomMode. Referenced by ClientThink(), and G_RunClient().
01939 {
01940 gclient_t *client;
01941 pmove_t pm;
01942 int oldEventSequence;
01943 int msec;
01944 usercmd_t *ucmd;
01945 qboolean isNPC = qfalse;
01946 qboolean controlledByPlayer = qfalse;
01947 qboolean killJetFlags = qtrue;
01948
01949 client = ent->client;
01950
01951 if (ent->s.eType == ET_NPC)
01952 {
01953 isNPC = qtrue;
01954 }
01955
01956 // don't think if the client is not yet connected (and thus not yet spawned in)
01957 if (client->pers.connected != CON_CONNECTED && !isNPC) {
01958 return;
01959 }
01960
01961 // This code was moved here from clientThink to fix a problem with g_synchronousClients
01962 // being set to 1 when in vehicles.
01963 if ( ent->s.number < MAX_CLIENTS && ent->client->ps.m_iVehicleNum )
01964 {//driving a vehicle
01965 if (g_entities[ent->client->ps.m_iVehicleNum].client)
01966 {
01967 gentity_t *veh = &g_entities[ent->client->ps.m_iVehicleNum];
01968
01969 if (veh->m_pVehicle &&
01970 veh->m_pVehicle->m_pPilot == (bgEntity_t *)ent)
01971 { //only take input from the pilot...
01972 veh->client->ps.commandTime = ent->client->ps.commandTime;
01973 memcpy(&veh->m_pVehicle->m_ucmd, &ent->client->pers.cmd, sizeof(usercmd_t));
01974 if ( veh->m_pVehicle->m_ucmd.buttons & BUTTON_TALK )
01975 { //forced input if "chat bubble" is up
01976 veh->m_pVehicle->m_ucmd.buttons = BUTTON_TALK;
01977 veh->m_pVehicle->m_ucmd.forwardmove = 0;
01978 veh->m_pVehicle->m_ucmd.rightmove = 0;
01979 veh->m_pVehicle->m_ucmd.upmove = 0;
01980 }
01981 }
01982 }
01983 }
01984
01985 if (!(client->ps.pm_flags & PMF_FOLLOW))
01986 {
01987 if (g_gametype.integer == GT_SIEGE &&
01988 client->siegeClass != -1 &&
01989 bgSiegeClasses[client->siegeClass].saberStance)
01990 { //the class says we have to use this stance set.
01991 if (!(bgSiegeClasses[client->siegeClass].saberStance & (1 << client->ps.fd.saberAnimLevel)))
01992 { //the current stance is not in the bitmask, so find the first one that is.
01993 int i = SS_FAST;
01994
01995 while (i < SS_NUM_SABER_STYLES)
01996 {
01997 if (bgSiegeClasses[client->siegeClass].saberStance & (1 << i))
01998 {
01999 if (i == SS_DUAL
02000 && client->ps.saberHolstered == 1 )
02001 {//one saber should be off, adjust saberAnimLevel accordinly
02002 client->ps.fd.saberAnimLevelBase = i;
02003 client->ps.fd.saberAnimLevel = SS_FAST;
02004 client->ps.fd.saberDrawAnimLevel = client->ps.fd.saberAnimLevel;
02005 }
02006 else if ( i == SS_STAFF
02007 && client->ps.saberHolstered == 1
02008 && client->saber[0].singleBladeStyle != SS_NONE)
02009 {//one saber or blade should be off, adjust saberAnimLevel accordinly
02010 client->ps.fd.saberAnimLevelBase = i;
02011 client->ps.fd.saberAnimLevel = client->saber[0].singleBladeStyle;
02012 client->ps.fd.saberDrawAnimLevel = client->ps.fd.saberAnimLevel;
02013 }
02014 else
02015 {
02016 client->ps.fd.saberAnimLevelBase = client->ps.fd.saberAnimLevel = i;
02017 client->ps.fd.saberDrawAnimLevel = i;
02018 }
02019 break;
02020 }
02021
02022 i++;
02023 }
02024 }
02025 }
02026 else if (client->saber[0].model[0] && client->saber[1].model[0])
02027 { //with two sabs always use akimbo style
02028 if ( client->ps.saberHolstered == 1 )
02029 {//one saber should be off, adjust saberAnimLevel accordinly
02030 client->ps.fd.saberAnimLevelBase = SS_DUAL;
02031 client->ps.fd.saberAnimLevel = SS_FAST;
02032 client->ps.fd.saberDrawAnimLevel = client->ps.fd.saberAnimLevel;
02033 }
02034 else
02035 {
02036 if ( !WP_SaberStyleValidForSaber( &client->saber[0], &client->saber[1], client->ps.saberHolstered, client->ps.fd.saberAnimLevel ) )
02037 {//only use dual style if the style we're trying to use isn't valid
02038 client->ps.fd.saberAnimLevelBase = client->ps.fd.saberAnimLevel = SS_DUAL;
02039 }
02040 client->ps.fd.saberDrawAnimLevel = client->ps.fd.saberAnimLevel;
02041 }
02042 }
02043 else
02044 {
02045 if (client->saber[0].stylesLearned == (1<<SS_STAFF) )
02046 { //then *always* use the staff style
02047 client->ps.fd.saberAnimLevelBase = SS_STAFF;
02048 }
02049 if ( client->ps.fd.saberAnimLevelBase == SS_STAFF )
02050 {//using staff style
02051 if ( client->ps.saberHolstered == 1
02052 && client->saber[0].singleBladeStyle != SS_NONE)
02053 {//one blade should be off, adjust saberAnimLevel accordinly
02054 client->ps.fd.saberAnimLevel = client->saber[0].singleBladeStyle;
02055 client->ps.fd.saberDrawAnimLevel = client->ps.fd.saberAnimLevel;
02056 }
02057 else
02058 {
02059 client->ps.fd.saberAnimLevel = SS_STAFF;
02060 client->ps.fd.saberDrawAnimLevel = client->ps.fd.saberAnimLevel;
02061 }
02062 }
02063 }
02064 }
02065
02066 // mark the time, so the connection sprite can be removed
02067 ucmd = &ent->client->pers.cmd;
02068
02069 if ( client && (client->ps.eFlags2&EF2_HELD_BY_MONSTER) )
02070 {
02071 G_HeldByMonster( ent, &ucmd );
02072 }
02073
02074 // sanity check the command time to prevent speedup cheating
02075 if ( ucmd->serverTime > level.time + 200 ) {
02076 ucmd->serverTime = level.time + 200;
02077 // G_Printf("serverTime <<<<<\n" );
02078 }
02079 if ( ucmd->serverTime < level.time - 1000 ) {
02080 ucmd->serverTime = level.time - 1000;
02081 // G_Printf("serverTime >>>>>\n" );
02082 }
02083
02084 if (isNPC && (ucmd->serverTime - client->ps.commandTime) < 1)
02085 {
02086 ucmd->serverTime = client->ps.commandTime + 100;
02087 }
02088
02089 msec = ucmd->serverTime - client->ps.commandTime;
02090 // following others may result in bad times, but we still want
02091 // to check for follow toggles
02092 if ( msec < 1 && client->sess.spectatorState != SPECTATOR_FOLLOW ) {
02093 return;
02094 }
02095
02096 if ( msec > 200 ) {
02097 msec = 200;
02098 }
02099
02100 if ( pmove_msec.integer < 8 ) {
02101 trap_Cvar_Set("pmove_msec", "8");
02102 }
02103 else if (pmove_msec.integer > 33) {
02104 trap_Cvar_Set("pmove_msec", "33");
02105 }
02106
02107 if ( pmove_fixed.integer || client->pers.pmoveFixed ) {
02108 ucmd->serverTime = ((ucmd->serverTime + pmove_msec.integer-1) / pmove_msec.integer) * pmove_msec.integer;
02109 //if (ucmd->serverTime - client->ps.commandTime <= 0)
02110 // return;
02111 }
02112
02113 //
02114 // check for exiting intermission
02115 //
02116 if ( level.intermissiontime )
02117 {
02118 if ( ent->s.number < MAX_CLIENTS
02119 || client->NPC_class == CLASS_VEHICLE )
02120 {//players and vehicles do nothing in intermissions
02121 ClientIntermissionThink( client );
02122 return;
02123 }
02124 }
02125
02126 // spectators don't do much
02127 if ( client->sess.sessionTeam == TEAM_SPECTATOR || client->tempSpectate > level.time ) {
02128 if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD ) {
02129 return;
02130 }
02131 SpectatorThink( ent, ucmd );
02132 return;
02133 }
02134
02135 if (ent && ent->client && (ent->client->ps.eFlags & EF_INVULNERABLE))
02136 {
02137 if (ent->client->invulnerableTimer <= level.time)
02138 {
02139 ent->client->ps.eFlags &= ~EF_INVULNERABLE;
02140 }
02141 }
02142
02143 if (ent->s.eType != ET_NPC)
02144 {
02145 // check for inactivity timer, but never drop the local client of a non-dedicated server
02146 if ( !ClientInactivityTimer( client ) ) {
02147 return;
02148 }
02149 }
02150
02151 //Check if we should have a fullbody push effect around the player
02152 if (client->pushEffectTime > level.time)
02153 {
02154 client->ps.eFlags |= EF_BODYPUSH;
02155 }
02156 else if (client->pushEffectTime)
02157 {
02158 client->pushEffectTime = 0;
02159 client->ps.eFlags &= ~EF_BODYPUSH;
02160 }
02161
02162 if (client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_JETPACK))
02163 {
02164 client->ps.eFlags |= EF_JETPACK;
02165 }
02166 else
02167 {
02168 client->ps.eFlags &= ~EF_JETPACK;
02169 }
02170
02171 if ( client->noclip ) {
02172 client->ps.pm_type = PM_NOCLIP;
02173 } else if ( client->ps.eFlags & EF_DISINTEGRATION ) {
02174 client->ps.pm_type = PM_NOCLIP;
02175 } else if ( client->ps.stats[STAT_HEALTH] <= 0 ) {
02176 client->ps.pm_type = PM_DEAD;
02177 } else {
02178 if (client->ps.forceGripChangeMovetype)
02179 {
02180 client->ps.pm_type = client->ps.forceGripChangeMovetype;
02181 }
02182 else
02183 {
02184 if (client->jetPackOn)
02185 {
02186 client->ps.pm_type = PM_JETPACK;
02187 client->ps.eFlags |= EF_JETPACK_ACTIVE;
02188 killJetFlags = qfalse;
02189 }
02190 else
02191 {
02192 client->ps.pm_type = PM_NORMAL;
02193 }
02194 }
02195 }
02196
02197 if (killJetFlags)
02198 {
02199 client->ps.eFlags &= ~EF_JETPACK_ACTIVE;
02200 client->ps.eFlags &= ~EF_JETPACK_FLAMING;
02201 }
02202
02203 #define SLOWDOWN_DIST 128.0f
02204 #define MIN_NPC_SPEED 16.0f
02205
02206 if (client->bodyGrabIndex != ENTITYNUM_NONE)
02207 {
02208 gentity_t *grabbed = &g_entities[client->bodyGrabIndex];
02209
02210 if (!grabbed->inuse || grabbed->s.eType != ET_BODY ||
02211 (grabbed->s.eFlags & EF_DISINTEGRATION) ||
02212 (grabbed->s.eFlags & EF_NODRAW))
02213 {
02214 if (grabbed->inuse && grabbed->s.eType == ET_BODY)
02215 {
02216 grabbed->s.ragAttach = 0;
02217 }
02218 client->bodyGrabIndex = ENTITYNUM_NONE;
02219 }
02220 else
02221 {
02222 mdxaBone_t rhMat;
02223 vec3_t rhOrg, tAng;
02224 vec3_t bodyDir;
02225 float bodyDist;
02226
02227 ent->client->ps.forceHandExtend = HANDEXTEND_DRAGGING;
02228
02229 if (ent->client->ps.forceHandExtendTime < level.time + 500)
02230 {
02231 ent->client->ps.forceHandExtendTime = level.time + 1000;
02232 }
02233
02234 VectorSet(tAng, 0, ent->client->ps.viewangles[YAW], 0);
02235 trap_G2API_GetBoltMatrix(ent->ghoul2, 0, 0, &rhMat, tAng, ent->client->ps.origin, level.time,
02236 NULL, ent->modelScale); //0 is always going to be right hand bolt
02237 BG_GiveMeVectorFromMatrix(&rhMat, ORIGIN, rhOrg);
02238
02239 VectorSubtract(rhOrg, grabbed->r.currentOrigin, bodyDir);
02240 bodyDist = VectorLength(bodyDir);
02241
02242 if (bodyDist > 40.0f)
02243 { //can no longer reach
02244 grabbed->s.ragAttach = 0;
02245 client->bodyGrabIndex = ENTITYNUM_NONE;
02246 }
02247 else if (bodyDist > 24.0f)
02248 {
02249 bodyDir[2] = 0; //don't want it floating
02250 //VectorScale(bodyDir, 0.1f, bodyDir);
02251 VectorAdd(grabbed->epVelocity, bodyDir, grabbed->epVelocity);
02252 G_Sound(grabbed, CHAN_AUTO, G_SoundIndex("sound/player/roll1.wav"));
02253 }
02254 }
02255 }
02256 else if (ent->client->ps.forceHandExtend == HANDEXTEND_DRAGGING)
02257 {
02258 ent->client->ps.forceHandExtend = HANDEXTEND_WEAPONREADY;
02259 }
02260
02261 if (ent->NPC && ent->s.NPC_class != CLASS_VEHICLE) //vehicles manage their own speed
02262 {
02263 //FIXME: swoop should keep turning (and moving forward?) for a little bit?
02264 if ( ent->NPC->combatMove == qfalse )
02265 {
02266 //if ( !(ucmd->buttons & BUTTON_USE) )
02267 if (1)
02268 {//Not leaning
02269 qboolean Flying = (ucmd->upmove && (ent->client->ps.eFlags2&EF2_FLYING));//ent->client->moveType == MT_FLYSWIM);
02270 qboolean Climbing = (ucmd->upmove && ent->watertype&CONTENTS_LADDER );
02271
02272 //client->ps.friction = 6;
02273
02274 if ( ucmd->forwardmove || ucmd->rightmove || Flying )
02275 {
02276 //if ( ent->NPC->behaviorState != BS_FORMATION )
02277 {//In - Formation NPCs set thier desiredSpeed themselves
02278 if ( ucmd->buttons & BUTTON_WALKING )
02279 {
02280 ent->NPC->desiredSpeed = NPC_GetWalkSpeed( ent );//ent->NPC->stats.walkSpeed;
02281 }
02282 else//running
02283 {
02284 ent->NPC->desiredSpeed = NPC_GetRunSpeed( ent );//ent->NPC->stats.runSpeed;
02285 }
02286
02287 if ( ent->NPC->currentSpeed >= 80 && !controlledByPlayer )
02288 {//At higher speeds, need to slow down close to stuff
02289 //Slow down as you approach your goal
02290 // if ( ent->NPC->distToGoal < SLOWDOWN_DIST && client->race != RACE_BORG && !(ent->NPC->aiFlags&NPCAI_NO_SLOWDOWN) )//128
02291 if ( ent->NPC->distToGoal < SLOWDOWN_DIST && !(ent->NPC->aiFlags&NPCAI_NO_SLOWDOWN) )//128
02292 {
02293 if ( ent->NPC->desiredSpeed > MIN_NPC_SPEED )
02294 {
02295 float slowdownSpeed = ((float)ent->NPC->desiredSpeed) * ent->NPC->distToGoal / SLOWDOWN_DIST;
02296
02297 ent->NPC->desiredSpeed = ceil(slowdownSpeed);
02298 if ( ent->NPC->desiredSpeed < MIN_NPC_SPEED )
02299 {//don't slow down too much
02300 ent->NPC->desiredSpeed = MIN_NPC_SPEED;
02301 }
02302 }
02303 }
02304 }
02305 }
02306 }
02307 else if ( Climbing )
02308 {
02309 ent->NPC->desiredSpeed = ent->NPC->stats.walkSpeed;
02310 }
02311 else
02312 {//We want to stop
02313 ent->NPC->desiredSpeed = 0;
02314 }
02315
02316 NPC_Accelerate( ent, qfalse, qfalse );
02317
02318 if ( ent->NPC->currentSpeed <= 24 && ent->NPC->desiredSpeed < ent->NPC->currentSpeed )
02319 {//No-one walks this slow
02320 client->ps.speed = ent->NPC->currentSpeed = 0;//Full stop
02321 ucmd->forwardmove = 0;
02322 ucmd->rightmove = 0;
02323 }
02324 else
02325 {
02326 if ( ent->NPC->currentSpeed <= ent->NPC->stats.walkSpeed )
02327 {//Play the walkanim
02328 ucmd->buttons |= BUTTON_WALKING;
02329 }
02330 else
02331 {
02332 ucmd->buttons &= ~BUTTON_WALKING;
02333 }
02334
02335 if ( ent->NPC->currentSpeed > 0 )
02336 {//We should be moving
02337 if ( Climbing || Flying )
02338 {
02339 if ( !ucmd->upmove )
02340 {//We need to force them to take a couple more steps until stopped
02341 ucmd->upmove = ent->NPC->last_ucmd.upmove;//was last_upmove;
02342 }
02343 }
02344 else if ( !ucmd->forwardmove && !ucmd->rightmove )
02345 {//We need to force them to take a couple more steps until stopped
02346 ucmd->forwardmove = ent->NPC->last_ucmd.forwardmove;//was last_forwardmove;
02347 ucmd->rightmove = ent->NPC->last_ucmd.rightmove;//was last_rightmove;
02348 }
02349 }
02350
02351 client->ps.speed = ent->NPC->currentSpeed;
02352 // if ( player && player->client && player->client->ps.viewEntity == ent->s.number )
02353 // {
02354 // }
02355 // else
02356 //rwwFIXMEFIXME: do this and also check for all real client
02357 if (1)
02358 {
02359 //Slow down on turns - don't orbit!!!
02360 float turndelta = 0;
02361 // if the NPC is locked into a Yaw, we want to check the lockedDesiredYaw...otherwise the NPC can't walk backwards, because it always thinks it trying to turn according to desiredYaw
02362 //if( client->renderInfo.renderFlags & RF_LOCKEDANGLE ) // yeah I know the RF_ flag is a pretty ugly hack...
02363 if (0) //rwwFIXMEFIXME: ...
02364 {
02365 turndelta = (180 - fabs( AngleDelta( ent->r.currentAngles[YAW], ent->NPC->lockedDesiredYaw ) ))/180;
02366 }
02367 else
02368 {
02369 turndelta = (180 - fabs( AngleDelta( ent->r.currentAngles[YAW], ent->NPC->desiredYaw ) ))/180;
02370 }
02371
02372 if ( turndelta < 0.75f )
02373 {
02374 client->ps.speed = 0;
02375 }
02376 else if ( ent->NPC->distToGoal < 100 && turndelta < 1.0 )
02377 {//Turn is greater than 45 degrees or closer than 100 to goal
02378 client->ps.speed = floor(((float)(client->ps.speed))*turndelta);
02379 }
02380 }
02381 }
02382 }
02383 }
02384 else
02385 {
02386 ent->NPC->desiredSpeed = ( ucmd->buttons & BUTTON_WALKING ) ? NPC_GetWalkSpeed( ent ) : NPC_GetRunSpeed( ent );
02387
02388 client->ps.speed = ent->NPC->desiredSpeed;
02389 }
02390
02391 if (ucmd->buttons & BUTTON_WALKING)
02392 { //sort of a hack I guess since MP handles walking differently from SP (has some proxy cheat prevention methods)
02393 /*
02394 if (ent->client->ps.speed > 64)
02395 {
02396 ent->client->ps.speed = 64;
02397 }
02398 */
02399
02400 if (ucmd->forwardmove > 64)
02401 {
02402 ucmd->forwardmove = 64;
02403 }
02404 else if (ucmd->forwardmove < -64)
02405 {
02406 ucmd->forwardmove = -64;
02407 }
02408
02409 if (ucmd->rightmove > 64)
02410 {
02411 ucmd->rightmove = 64;
02412 }
02413 else if ( ucmd->rightmove < -64)
02414 {
02415 ucmd->rightmove = -64;
02416 }
02417
02418 //ent->client->ps.speed = ent->client->ps.basespeed = NPC_GetRunSpeed( ent );
02419 }
02420 client->ps.basespeed = client->ps.speed;
02421 }
02422 else if (!client->ps.m_iVehicleNum &&
02423 (!ent->NPC || ent->s.NPC_class != CLASS_VEHICLE)) //if riding a vehicle it will manage our speed and such
02424 {
02425 // set speed
02426 client->ps.speed = g_speed.value;
02427
02428 //Check for a siege class speed multiplier
02429 if (g_gametype.integer == GT_SIEGE &&
02430 client->siegeClass != -1)
02431 {
02432 client->ps.speed *= bgSiegeClasses[client->siegeClass].speed;
02433 }
02434
02435 if (client->bodyGrabIndex != ENTITYNUM_NONE)
02436 { //can't go nearly as fast when dragging a body around
02437 client->ps.speed *= 0.2f;
02438 }
02439
02440 client->ps.basespeed = client->ps.speed;
02441 }
02442
02443 if ( !ent->NPC || !(ent->NPC->aiFlags&NPCAI_CUSTOM_GRAVITY) )
02444 {//use global gravity
02445 if (ent->NPC && ent->s.NPC_class == CLASS_VEHICLE &&
02446 ent->m_pVehicle && ent->m_pVehicle->m_pVehicleInfo->gravity)
02447 { //use custom veh gravity
02448 client->ps.gravity = ent->m_pVehicle->m_pVehicleInfo->gravity;
02449 }
02450 else
02451 {
02452 if (ent->client->inSpaceIndex && ent->client->inSpaceIndex != ENTITYNUM_NONE)
02453 { //in space, so no gravity...
02454 client->ps.gravity = 1.0f;
02455 if (ent->s.number < MAX_CLIENTS)
02456 {
02457 VectorScale(client->ps.velocity, 0.8f, client->ps.velocity);
02458 }
02459 }
02460 else
02461 {
02462 if (client->ps.eFlags2 & EF2_SHIP_DEATH)
02463 { //float there
02464 VectorClear(client->ps.velocity);
02465 client->ps.gravity = 1.0f;
02466 }
02467 else
02468 {
02469 client->ps.gravity = g_gravity.value;
02470 }
02471 }
02472 }
02473 }
02474
02475 if (ent->client->ps.duelInProgress)
02476 {
02477 gentity_t *duelAgainst = &g_entities[ent->client->ps.duelIndex];
02478
02479 //Keep the time updated, so once this duel ends this player can't engage in a duel for another
02480 //10 seconds. This will give other people a chance to engage in duels in case this player wants
02481 //to engage again right after he's done fighting and someone else is waiting.
02482 ent->client->ps.fd.privateDuelTime = level.time + 10000;
02483
02484 if (ent->client->ps.duelTime < level.time)
02485 {
02486 //Bring out the sabers
02487 if (ent->client->ps.weapon == WP_SABER
02488 && ent->client->ps.saberHolstered
02489 && ent->client->ps.duelTime )
02490 {
02491 ent->client->ps.saberHolstered = 0;
02492
02493 if (ent->client->saber[0].soundOn)
02494 {
02495 G_Sound(ent, CHAN_AUTO, ent->client->saber[0].soundOn);
02496 }
02497 if (ent->client->saber[1].soundOn)
02498 {
02499 G_Sound(ent, CHAN_AUTO, ent->client->saber[1].soundOn);
02500 }
02501
02502 G_AddEvent(ent, EV_PRIVATE_DUEL, 2);
02503
02504 ent->client->ps.duelTime = 0;
02505 }
02506
02507 if (duelAgainst
02508 && duelAgainst->client
02509 && duelAgainst->inuse
02510 && duelAgainst->client->ps.weapon == WP_SABER
02511 && duelAgainst->client->ps.saberHolstered
02512 && duelAgainst->client->ps.duelTime)
02513 {
02514 duelAgainst->client->ps.saberHolstered = 0;
02515
02516 if (duelAgainst->client->saber[0].soundOn)
02517 {
02518 G_Sound(duelAgainst, CHAN_AUTO, duelAgainst->client->saber[0].soundOn);
02519 }
02520 if (duelAgainst->client->saber[1].soundOn)
02521 {
02522 G_Sound(duelAgainst, CHAN_AUTO, duelAgainst->client->saber[1].soundOn);
02523 }
02524
02525 G_AddEvent(duelAgainst, EV_PRIVATE_DUEL, 2);
02526
02527 duelAgainst->client->ps.duelTime = 0;
02528 }
02529 }
02530 else
02531 {
02532 client->ps.speed = 0;
02533 client->ps.basespeed = 0;
02534 ucmd->forwardmove = 0;
02535 ucmd->rightmove = 0;
02536 ucmd->upmove = 0;
02537 }
02538
02539 if (!duelAgainst || !duelAgainst->client || !duelAgainst->inuse ||
02540 duelAgainst->client->ps.duelIndex != ent->s.number)
02541 {
02542 ent->client->ps.duelInProgress = 0;
02543 G_AddEvent(ent, EV_PRIVATE_DUEL, 0);
02544 }
02545 else if (duelAgainst->health < 1 || duelAgainst->client->ps.stats[STAT_HEALTH] < 1)
02546 {
02547 ent->client->ps.duelInProgress = 0;
02548 duelAgainst->client->ps.duelInProgress = 0;
02549
02550 G_AddEvent(ent, EV_PRIVATE_DUEL, 0);
02551 G_AddEvent(duelAgainst, EV_PRIVATE_DUEL, 0);
02552
02553 //Winner gets full health.. providing he's still alive
02554 if (ent->health > 0 && ent->client->ps.stats[STAT_HEALTH] > 0)
02555 {
02556 if (ent->health < ent->client->ps.stats[STAT_MAX_HEALTH])
02557 {
02558 ent->client->ps.stats[STAT_HEALTH] = ent->health = ent->client->ps.stats[STAT_MAX_HEALTH];
02559 }
02560
02561 if (g_spawnInvulnerability.integer)
02562 {
02563 ent->client->ps.eFlags |= EF_INVULNERABLE;
02564 ent->client->invulnerableTimer = level.time + g_spawnInvulnerability.integer;
02565 }
02566 }
02567
02568 /*
02569 trap_SendServerCommand( ent-g_entities, va("print \"%s %s\n\"", ent->client->pers.netname, G_GetStringEdString("MP_SVGAME", "PLDUELWINNER")) );
02570 trap_SendServerCommand( duelAgainst-g_entities, va("print \"%s %s\n\"", ent->client->pers.netname, G_GetStringEdString("MP_SVGAME", "PLDUELWINNER")) );
02571 */
02572 //Private duel announcements are now made globally because we only want one duel at a time.
02573 if (ent->health > 0 && ent->client->ps.stats[STAT_HEALTH] > 0)
02574 {
02575 trap_SendServerCommand( -1, va("cp \"%s %s %s!\n\"", ent->client->pers.netname, G_GetStringEdString("MP_SVGAME", "PLDUELWINNER"), duelAgainst->client->pers.netname) );
02576 }
02577 else
02578 { //it was a draw, because we both managed to die in the same frame
02579 trap_SendServerCommand( -1, va("cp \"%s\n\"", G_GetStringEdString("MP_SVGAME", "PLDUELTIE")) );
02580 }
02581 }
02582 else
02583 {
02584 vec3_t vSub;
02585 float subLen = 0;
02586
02587 VectorSubtract(ent->client->ps.origin, duelAgainst->client->ps.origin, vSub);
02588 subLen = VectorLength(vSub);
02589
02590 if (subLen >= 1024)
02591 {
02592 ent->client->ps.duelInProgress = 0;
02593 duelAgainst->client->ps.duelInProgress = 0;
02594
02595 G_AddEvent(ent, EV_PRIVATE_DUEL, 0);
02596 G_AddEvent(duelAgainst, EV_PRIVATE_DUEL, 0);
02597
02598 trap_SendServerCommand( -1, va("print \"%s\n\"", G_GetStringEdString("MP_SVGAME", "PLDUELSTOP")) );
02599 }
02600 }
02601 }
02602
02603 if (ent->client->doingThrow > level.time)
02604 {
02605 gentity_t *throwee = &g_entities[ent->client->throwingIndex];
02606
02607 if (!throwee->inuse || !throwee->client || throwee->health < 1 ||
02608 throwee->client->sess.sessionTeam == TEAM_SPECTATOR ||
02609 (throwee->client->ps.pm_flags & PMF_FOLLOW) ||
02610 throwee->client->throwingIndex != ent->s.number)
02611 {
02612 ent->client->doingThrow = 0;
02613 ent->client->ps.forceHandExtend = HANDEXTEND_NONE;
02614
02615 if (throwee->inuse && throwee->client)
02616 {
02617 throwee->client->ps.heldByClient = 0;
02618 throwee->client->beingThrown = 0;
02619
02620 if (throwee->client->ps.forceHandExtend != HANDEXTEND_POSTTHROWN)
02621 {
02622 throwee->client->ps.forceHandExtend = HANDEXTEND_NONE;
02623 }
02624 }
02625 }
02626 }
02627
02628 if (ent->client->beingThrown > level.time)
02629 {
02630 gentity_t *thrower = &g_entities[ent->client->throwingIndex];
02631
02632 if (!thrower->inuse || !thrower->client || thrower->health < 1 ||
02633 thrower->client->sess.sessionTeam == TEAM_SPECTATOR ||
02634 (thrower->client->ps.pm_flags & PMF_FOLLOW) ||
02635 thrower->client->throwingIndex != ent->s.number)
02636 {
02637 ent->client->ps.heldByClient = 0;
02638 ent->client->beingThrown = 0;
02639
02640 if (ent->client->ps.forceHandExtend != HANDEXTEND_POSTTHROWN)
02641 {
02642 ent->client->ps.forceHandExtend = HANDEXTEND_NONE;
02643 }
02644
02645 if (thrower->inuse && thrower->client)
02646 {
02647 thrower->client->doingThrow = 0;
02648 thrower->client->ps.forceHandExtend = HANDEXTEND_NONE;
02649 }
02650 }
02651 else if (thrower->inuse && thrower->client && thrower->ghoul2 &&
02652 trap_G2_HaveWeGhoul2Models(thrower->ghoul2))
02653 {
02654 #if 0
02655 int lHandBolt = trap_G2API_AddBolt(thrower->ghoul2, 0, "*l_hand");
02656 int pelBolt = trap_G2API_AddBolt(thrower->ghoul2, 0, "pelvis");
02657
02658
02659 if (lHandBolt != -1 && pelBolt != -1)
02660 #endif
02661 {
02662 float pDif = 40.0f;
02663 vec3_t boltOrg, pBoltOrg;
02664 vec3_t tAngles;
02665 vec3_t vDif;
02666 vec3_t entDir, otherAngles;
02667 vec3_t fwd, right;
02668
02669 //Always look at the thrower.
02670 VectorSubtract( thrower->client->ps.origin, ent->client->ps.origin, entDir );
02671 VectorCopy( ent->client->ps.viewangles, otherAngles );
02672 otherAngles[YAW] = vectoyaw( entDir );
02673 SetClientViewAngle( ent, otherAngles );
02674
02675 VectorCopy(thrower->client->ps.viewangles, tAngles);
02676 tAngles[PITCH] = tAngles[ROLL] = 0;
02677
02678 //Get the direction between the pelvis and position of the hand
02679 #if 0
02680 mdxaBone_t boltMatrix, pBoltMatrix;
02681
02682 trap_G2API_GetBoltMatrix(thrower->ghoul2, 0, lHandBolt, &boltMatrix, tAngles, thrower->client->ps.origin, level.time, 0, thrower->modelScale);
02683 boltOrg[0] = boltMatrix.matrix[0][3];
02684 boltOrg[1] = boltMatrix.matrix[1][3];
02685 boltOrg[2] = boltMatrix.matrix[2][3];
02686
02687 trap_G2API_GetBoltMatrix(thrower->ghoul2, 0, pelBolt, &pBoltMatrix, tAngles, thrower->client->ps.origin, level.time, 0, thrower->modelScale);
02688 pBoltOrg[0] = pBoltMatrix.matrix[0][3];
02689 pBoltOrg[1] = pBoltMatrix.matrix[1][3];
02690 pBoltOrg[2] = pBoltMatrix.matrix[2][3];
02691 #else //above tends to not work once in a while, for various reasons I suppose.
02692 VectorCopy(thrower->client->ps.origin, pBoltOrg);
02693 AngleVectors(tAngles, fwd, right, 0);
02694 boltOrg[0] = pBoltOrg[0] + fwd[0]*8 + right[0]*pDif;
02695 boltOrg[1] = pBoltOrg[1] + fwd[1]*8 + right[1]*pDif;
02696 boltOrg[2] = pBoltOrg[2];
02697 #endif
02698 //G_TestLine(boltOrg, pBoltOrg, 0x0000ff, 50);
02699
02700 VectorSubtract(ent->client->ps.origin, boltOrg, vDif);
02701 if (VectorLength(vDif) > 32.0f && (thrower->client->doingThrow - level.time) < 4500)
02702 { //the hand is too far away, and can no longer hold onto us, so escape.
02703 ent->client->ps.heldByClient = 0;
02704 ent->client->beingThrown = 0;
02705 thrower->client->doingThrow = 0;
02706
02707 thrower->client->ps.forceHandExtend = HANDEXTEND_NONE;
02708 G_EntitySound( thrower, CHAN_VOICE, G_SoundIndex("*pain25.wav") );
02709
02710 ent->client->ps.forceDodgeAnim = 2;
02711 ent->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
02712 ent->client->ps.forceHandExtendTime = level.time + 500;
02713 ent->client->ps.velocity[2] = 400;
02714 G_PreDefSound(ent->client->ps.origin, PDSOUND_FORCEJUMP);
02715 }
02716 else if ((client->beingThrown - level.time) < 4000)
02717 { //step into the next part of the throw, and go flying back
02718 float vScale = 400.0f;
02719 ent->client->ps.forceHandExtend = HANDEXTEND_POSTTHROWN;
02720 ent->client->ps.forceHandExtendTime = level.time + 1200;
02721 ent->client->ps.forceDodgeAnim = 0;
02722
02723 thrower->client->ps.forceHandExtend = HANDEXTEND_POSTTHROW;
02724 thrower->client->ps.forceHandExtendTime = level.time + 200;
02725
02726 ent->client->ps.heldByClient = 0;
02727
02728 ent->client->ps.heldByClient = 0;
02729 ent->client->beingThrown = 0;
02730 thrower->client->doingThrow = 0;
02731
02732 AngleVectors(thrower->client->ps.viewangles, vDif, 0, 0);
02733 ent->client->ps.velocity[0] = vDif[0]*vScale;
02734 ent->client->ps.velocity[1] = vDif[1]*vScale;
02735 ent->client->ps.velocity[2] = 400;
02736
02737 G_EntitySound( ent, CHAN_VOICE, G_SoundIndex("*pain100.wav") );
02738 G_EntitySound( thrower, CHAN_VOICE, G_SoundIndex("*jump1.wav") );
02739
02740 //Set the thrower as the "other killer", so if we die from fall/impact damage he is credited.
02741 ent->client->ps.otherKiller = thrower->s.number;
02742 ent->client->ps.otherKillerTime = level.time + 8000;
02743 ent->client->ps.otherKillerDebounceTime = level.time + 100;
02744 }
02745 else
02746 { //see if we can move to be next to the hand.. if it's not clear, break the throw.
02747 vec3_t intendedOrigin;
02748 trace_t tr;
02749 trace_t tr2;
02750
02751 VectorSubtract(boltOrg, pBoltOrg, vDif);
02752 VectorNormalize(vDif);
02753
02754 VectorClear(ent->client->ps.velocity);
02755 intendedOrigin[0] = pBoltOrg[0] + vDif[0]*pDif;
02756 intendedOrigin[1] = pBoltOrg[1] + vDif[1]*pDif;
02757 intendedOrigin[2] = thrower->client->ps.origin[2];
02758
02759 trap_Trace(&tr, intendedOrigin, ent->r.mins, ent->r.maxs, intendedOrigin, ent->s.number, ent->clipmask);
02760 trap_Trace(&tr2, ent->client->ps.origin, ent->r.mins, ent->r.maxs, intendedOrigin, ent->s.number, CONTENTS_SOLID);
02761
02762 if (tr.fraction == 1.0 && !tr.startsolid && tr2.fraction == 1.0 && !tr2.startsolid)
02763 {
02764 VectorCopy(intendedOrigin, ent->client->ps.origin);
02765
02766 if ((client->beingThrown - level.time) < 4800)
02767 {
02768 ent->client->ps.heldByClient = thrower->s.number+1;
02769 }
02770 }
02771 else
02772 { //if the guy can't be put here then it's time to break the throw off.
02773 ent->client->ps.heldByClient = 0;
02774 ent->client->beingThrown = 0;
02775 thrower->client->doingThrow = 0;
02776
02777 thrower->client->ps.forceHandExtend = HANDEXTEND_NONE;
02778 G_EntitySound( thrower, CHAN_VOICE, G_SoundIndex("*pain25.wav") );
02779
02780 ent->client->ps.forceDodgeAnim = 2;
02781 ent->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
02782 ent->client->ps.forceHandExtendTime = level.time + 500;
02783 ent->client->ps.velocity[2] = 400;
02784 G_PreDefSound(ent->client->ps.origin, PDSOUND_FORCEJUMP);
02785 }
02786 }
02787 }
02788 }
02789 }
02790 else if (ent->client->ps.heldByClient)
02791 {
02792 ent->client->ps.heldByClient = 0;
02793 }
02794
02795 /*
02796 if ( client->ps.powerups[PW_HASTE] ) {
02797 client->ps.speed *= 1.3;
02798 }
02799 */
02800
02801 //Will probably never need this again, since we have g2 properly serverside now.
02802 //But just in case.
02803 /*
02804 if (client->ps.usingATST && ent->health > 0)
02805 { //we have special shot clip boxes as an ATST
02806 ent->r.contents |= CONTENTS_NOSHOT;
02807 ATST_ManageDamageBoxes(ent);
02808 }
02809 else
02810 {
02811 ent->r.contents &= ~CONTENTS_NOSHOT;
02812 client->damageBoxHandle_Head = 0;
02813 client->damageBoxHandle_RLeg = 0;
02814 client->damageBoxHandle_LLeg = 0;
02815 }
02816 */
02817
02818 //rww - moved this stuff into the pmove code so that it's predicted properly
02819 //BG_AdjustClientSpeed(&client->ps, &client->pers.cmd, level.time);
02820
02821 // set up for pmove
02822 oldEventSequence = client->ps.eventSequence;
02823
02824 memset (&pm, 0, sizeof(pm));
02825
02826 if ( ent->flags & FL_FORCE_GESTURE ) {
02827 ent->flags &= ~FL_FORCE_GESTURE;
02828 ent->client->pers.cmd.buttons |= BUTTON_GESTURE;
02829 }
02830
02831 if (ent->client && ent->client->ps.fallingToDeath &&
02832 (level.time - FALL_FADE_TIME) > ent->client->ps.fallingToDeath)
02833 { //die!
02834 if (ent->health > 0)
02835 {
02836 gentity_t *otherKiller = ent;
02837 if (ent->client->ps.otherKillerTime > level.time &&
02838 ent->client->ps.otherKiller != ENTITYNUM_NONE)
02839 {
02840 otherKiller = &g_entities[ent->client->ps.otherKiller];
02841
02842 if (!otherKiller->inuse)
02843 {
02844 otherKiller = ent;
02845 }
02846 }
02847 G_Damage(ent, otherKiller, otherKiller, NULL, ent->client->ps.origin, 9999, DAMAGE_NO_PROTECTION, MOD_FALLING);
02848 //player_die(ent, ent, ent, 100000, MOD_FALLING);
02849 // if (!ent->NPC)
02850 // {
02851 // respawn(ent);
02852 // }
02853 // ent->client->ps.fallingToDeath = 0;
02854
02855 G_MuteSound(ent->s.number, CHAN_VOICE); //stop screaming, because you are dead!
02856 }
02857 }
02858
02859 if (ent->client->ps.otherKillerTime > level.time &&
02860 ent->client->ps.groundEntityNum != ENTITYNUM_NONE &&
02861 ent->client->ps.otherKillerDebounceTime < level.time)
02862 {
02863 ent->client->ps.otherKillerTime = 0;
02864 ent->client->ps.otherKiller = ENTITYNUM_NONE;
02865 }
02866 else if (ent->client->ps.otherKillerTime > level.time &&
02867 ent->client->ps.groundEntityNum == ENTITYNUM_NONE)
02868 {
02869 if (ent->client->ps.otherKillerDebounceTime < (level.time + 100))
02870 {
02871 ent->client->ps.otherKillerDebounceTime = level.time + 100;
02872 }
02873 }
02874
02875 // WP_ForcePowersUpdate( ent, msec, ucmd); //update any active force powers
02876 // WP_SaberPositionUpdate(ent, ucmd); //check the server-side saber point, do apprioriate server-side actions (effects are cs-only)
02877
02878 //NOTE: can't put USE here *before* PMove!!
02879 if ( ent->client->ps.useDelay > level.time
02880 && ent->client->ps.m_iVehicleNum )
02881 {//when in a vehicle, debounce the use...
02882 ucmd->buttons &= ~BUTTON_USE;
02883 }
02884
02885 //FIXME: need to do this before check to avoid walls and cliffs (or just cliffs?)
02886 G_AddPushVecToUcmd( ent, ucmd );
02887
02888 //play/stop any looping sounds tied to controlled movement
02889 G_CheckMovingLoopingSounds( ent, ucmd );
02890
02891 pm.ps = &client->ps;
02892 pm.cmd = *ucmd;
02893 if ( pm.ps->pm_type == PM_DEAD ) {
02894 pm.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY;
02895 }
02896 else if ( ent->r.svFlags & SVF_BOT ) {
02897 pm.tracemask = MASK_PLAYERSOLID | CONTENTS_MONSTERCLIP;
02898 }
02899 else {
02900 pm.tracemask = MASK_PLAYERSOLID;
02901 }
02902 pm.trace = trap_Trace;
02903 pm.pointcontents = trap_PointContents;
02904 pm.debugLevel = g_debugMove.integer;
02905 pm.noFootsteps = ( g_dmflags.integer & DF_NO_FOOTSTEPS ) > 0;
02906
02907 pm.pmove_fixed = pmove_fixed.integer | client->pers.pmoveFixed;
02908 pm.pmove_msec = pmove_msec.integer;
02909
02910 pm.animations = bgAllAnims[ent->localAnimIndex].anims;//NULL;
02911
02912 //rww - bgghoul2
02913 pm.ghoul2 = NULL;
02914
02915 #ifdef _DEBUG
02916 if (g_disableServerG2.integer)
02917 {
02918
02919 }
02920 else
02921 #endif
02922 if (ent->ghoul2)
02923 {
02924 if (ent->localAnimIndex > 1)
02925 { //if it isn't humanoid then we will be having none of this.
02926 pm.ghoul2 = NULL;
02927 }
02928 else
02929 {
02930 pm.ghoul2 = ent->ghoul2;
02931 pm.g2Bolts_LFoot = trap_G2API_AddBolt(ent->ghoul2, 0, "*l_leg_foot");
02932 pm.g2Bolts_RFoot = trap_G2API_AddBolt(ent->ghoul2, 0, "*r_leg_foot");
02933 }
02934 }
02935
02936 //point the saber data to the right place
02937 #if 0
02938 k = 0;
02939 while (k < MAX_SABERS)
02940 {
02941 if (ent->client->saber[k].model[0])
02942 {
02943 pm.saber[k] = &ent->client->saber[k];
02944 }
02945 else
02946 {
02947 pm.saber[k] = NULL;
02948 }
02949 k++;
02950 }
02951 #endif
02952
02953 //I'll just do this every frame in case the scale changes in realtime (don't need to update the g2 inst for that)
02954 VectorCopy(ent->modelScale, pm.modelScale);
02955 //rww end bgghoul2
02956
02957 pm.gametype = g_gametype.integer;
02958 pm.debugMelee = g_debugMelee.integer;
02959 pm.stepSlideFix = g_stepSlideFix.integer;
02960
02961 pm.noSpecMove = g_noSpecMove.integer;
02962
02963 pm.nonHumanoid = (ent->localAnimIndex > 0);
02964
02965 VectorCopy( client->ps.origin, client->oldOrigin );
02966
02967 /*
02968 if (level.intermissionQueued != 0 && g_singlePlayer.integer) {
02969 if ( level.time - level.intermissionQueued >= 1000 ) {
02970 pm.cmd.buttons = 0;
02971 pm.cmd.forwardmove = 0;
02972 pm.cmd.rightmove = 0;
02973 pm.cmd.upmove = 0;
02974 if ( level.time - level.intermissionQueued >= 2000 && level.time - level.intermissionQueued <= 2500 ) {
02975 trap_SendConsoleCommand( EXEC_APPEND, "centerview\n");
02976 }
02977 ent->client->ps.pm_type = PM_SPINTERMISSION;
02978 }
02979 }
02980 */
02981
02982 //Set up bg entity data
02983 pm.baseEnt = (bgEntity_t *)g_entities;
02984 pm.entSize = sizeof(gentity_t);
02985
02986 if (ent->client->ps.saberLockTime > level.time)
02987 {
02988 gentity_t *blockOpp = &g_entities[ent->client->ps.saberLockEnemy];
02989
02990 if (blockOpp && blockOpp->inuse && blockOpp->client)
02991 {
02992 vec3_t lockDir, lockAng;
02993
02994 //VectorClear( ent->client->ps.velocity );
02995 VectorSubtract( blockOpp->r.currentOrigin, ent->r.currentOrigin, lockDir );
02996 //lockAng[YAW] = vectoyaw( defDir );
02997 vectoangles(lockDir, lockAng);
02998 SetClientViewAngle( ent, lockAng );
02999 }
03000
03001 if ( ent->client->ps.saberLockHitCheckTime < level.time )
03002 {//have moved to next frame since last lock push
03003 ent->client->ps.saberLockHitCheckTime = level.time;//so we don't push more than once per server frame
03004 if ( ( ent->client->buttons & BUTTON_ATTACK ) && ! ( ent->client->oldbuttons & BUTTON_ATTACK ) )
03005 {
03006 if ( ent->client->ps.saberLockHitIncrementTime < level.time )
03007 {//have moved to next frame since last saberlock attack button press
03008 int lockHits = 0;
03009 ent->client->ps.saberLockHitIncrementTime = level.time;//so we don't register an attack key press more than once per server frame
03010 //NOTE: FP_SABER_OFFENSE level already taken into account in PM_SaberLocked
03011 if ( (ent->client->ps.fd.forcePowersActive&(1<<FP_RAGE)) )
03012 {//raging: push harder
03013 lockHits = 1+ent->client->ps.fd.forcePowerLevel[FP_RAGE];
03014 }
03015 else
03016 {//normal attack
03017 switch ( ent->client->ps.fd.saberAnimLevel )
03018 {
03019 case SS_FAST:
03020 lockHits = 1;
03021 break;
03022 case SS_MEDIUM:
03023 case SS_TAVION:
03024 case SS_DUAL:
03025 case SS_STAFF:
03026 lockHits = 2;
03027 break;
03028 case SS_STRONG:
03029 case SS_DESANN:
03030 lockHits = 3;
03031 break;
03032 }
03033 }
03034 if ( ent->client->ps.fd.forceRageRecoveryTime > level.time
03035 && Q_irand( 0, 1 ) )
03036 {//finished raging: weak
03037 lockHits -= 1;
03038 }
03039 lockHits += ent->client->saber[0].lockBonus;
03040 if ( ent->client->saber[1].model
03041 && ent->client->saber[1].model[0]
03042 && !ent->client->ps.saberHolstered )
03043 {
03044 lockHits += ent->client->saber[1].lockBonus;
03045 }
03046 ent->client->ps.saberLockHits += lockHits;
03047 if ( g_saberLockRandomNess.integer )
03048 {
03049 ent->client->ps.saberLockHits += Q_irand( 0, g_saberLockRandomNess.integer );
03050 if ( ent->client->ps.saberLockHits < 0 )
03051 {
03052 ent->client->ps.saberLockHits = 0;
03053 }
03054 }
03055 }
03056 }
03057 if ( ent->client->ps.saberLockHits > 0 )
03058 {
03059 if ( !ent->client->ps.saberLockAdvance )
03060 {
03061 ent->client->ps.saberLockHits--;
03062 }
03063 ent->client->ps.saberLockAdvance = qtrue;
03064 }
03065 }
03066 }
03067 else
03068 {
03069 ent->client->ps.saberLockFrame = 0;
03070 //check for taunt
03071 if ( (pm.cmd.generic_cmd == GENCMD_ENGAGE_DUEL) && (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL) )
03072 {//already in a duel, make it a taunt command
03073 pm.cmd.buttons |= BUTTON_GESTURE;
03074 }
03075 }
03076
03077 if (ent->s.number >= MAX_CLIENTS)
03078 {
03079 VectorCopy(ent->r.mins, pm.mins);
03080 VectorCopy(ent->r.maxs, pm.maxs);
03081 #if 1
03082 if (ent->s.NPC_class == CLASS_VEHICLE &&
03083 ent->m_pVehicle )
03084 {
03085 if ( ent->m_pVehicle->m_pPilot)
03086 { //vehicles want to use their last pilot ucmd I guess
03087 if ((level.time - ent->m_pVehicle->m_ucmd.serverTime) > 2000)
03088 { //Previous owner disconnected, maybe
03089 ent->m_pVehicle->m_ucmd.serverTime = level.time;
03090 ent->client->ps.commandTime = level.time-100;
03091 msec = 100;
03092 }
03093
03094 memcpy(&pm.cmd, &ent->m_pVehicle->m_ucmd, sizeof(usercmd_t));
03095
03096 //no veh can strafe
03097 pm.cmd.rightmove = 0;
03098 //no crouching or jumping!
03099 pm.cmd.upmove = 0;
03100
03101 //NOTE: button presses were getting lost!
03102 assert(g_entities[ent->m_pVehicle->m_pPilot->s.number].client);
03103 pm.cmd.buttons = (g_entities[ent->m_pVehicle->m_pPilot->s.number].client->pers.cmd.buttons&(BUTTON_ATTACK|BUTTON_ALT_ATTACK));
03104 }
03105 if ( ent->m_pVehicle->m_pVehicleInfo->type == VH_WALKER )
03106 {
03107 if ( ent->client->ps.groundEntityNum != ENTITYNUM_NONE )
03108 {//ATST crushes anything underneath it
03109 gentity_t *under = &g_entities[ent->client->ps.groundEntityNum];
03110 if ( under && under->health && under->takedamage )
03111 {
03112 vec3_t down = {0,0,-1};
03113 //FIXME: we'll be doing traces down from each foot, so we'll have a real impact origin
03114 G_Damage( under, ent, ent, down, under->r.currentOrigin, 100, 0, MOD_CRUSH );
03115 }
03116 }
03117 }
03118 }
03119 #endif
03120 }
03121
03122 Pmove (&pm);
03123
03124 if (ent->client->solidHack)
03125 {
03126 if (ent->client->solidHack > level.time)
03127 { //whee!
03128 ent->r.contents = 0;
03129 }
03130 else
03131 {
03132 ent->r.contents = CONTENTS_BODY;
03133 ent->client->solidHack = 0;
03134 }
03135 }
03136
03137 if ( ent->NPC )
03138 {
03139 VectorCopy( ent->client->ps.viewangles, ent->r.currentAngles );
03140 }
03141
03142 if (pm.checkDuelLoss)
03143 {
03144 if (pm.checkDuelLoss > 0 && (pm.checkDuelLoss <= MAX_CLIENTS || (pm.checkDuelLoss < (MAX_GENTITIES-1) && g_entities[pm.checkDuelLoss-1].s.eType == ET_NPC) ) )
03145 {
03146 gentity_t *clientLost = &g_entities[pm.checkDuelLoss-1];
03147
03148 if (clientLost && clientLost->inuse && clientLost->client && Q_irand(0, 40) > clientLost->health)
03149 {
03150 vec3_t attDir;
03151 VectorSubtract(ent->client->ps.origin, clientLost->client->ps.origin, attDir);
03152 VectorNormalize(attDir);
03153
03154 VectorClear(clientLost->client->ps.velocity);
03155 clientLost->client->ps.forceHandExtend = HANDEXTEND_NONE;
03156 clientLost->client->ps.forceHandExtendTime = 0;
03157
03158 gGAvoidDismember = 1;
03159 G_Damage(clientLost, ent, ent, attDir, clientLost->client->ps.origin, 9999, DAMAGE_NO_PROTECTION, MOD_SABER);
03160
03161 if (clientLost->health < 1)
03162 {
03163 gGAvoidDismember = 2;
03164 G_CheckForDismemberment(clientLost, ent, clientLost->client->ps.origin, 999, (clientLost->client->ps.legsAnim), qfalse);
03165 }
03166
03167 gGAvoidDismember = 0;
03168 }
03169 else if (clientLost && clientLost->inuse && clientLost->client &&
03170 clientLost->client->ps.forceHandExtend != HANDEXTEND_KNOCKDOWN && clientLost->client->ps.saberEntityNum)
03171 { //if we didn't knock down it was a circle lock. So as punishment, make them lose their saber and go into a proper anim
03172 saberCheckKnockdown_DuelLoss(&g_entities[clientLost->client->ps.saberEntityNum], clientLost, ent);
03173 }
03174 }
03175
03176 pm.checkDuelLoss = 0;
03177 }
03178
03179 if (pm.cmd.generic_cmd &&
03180 (pm.cmd.generic_cmd != ent->client->lastGenCmd || ent->client->lastGenCmdTime < level.time))
03181 {
03182 ent->client->lastGenCmd = pm.cmd.generic_cmd;
03183 if (pm.cmd.generic_cmd != GENCMD_FORCE_THROW &&
03184 pm.cmd.generic_cmd != GENCMD_FORCE_PULL)
03185 { //these are the only two where you wouldn't care about a delay between
03186 ent->client->lastGenCmdTime = level.time + 300; //default 100ms debounce between issuing the same command.
03187 }
03188
03189 switch(pm.cmd.generic_cmd)
03190 {
03191 case 0:
03192 break;
03193 case GENCMD_SABERSWITCH:
03194 Cmd_ToggleSaber_f(ent);
03195 break;
03196 case GENCMD_ENGAGE_DUEL:
03197 if ( g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL )
03198 {//already in a duel, made it a taunt command
03199 }
03200 else
03201 {
03202 Cmd_EngageDuel_f(ent);
03203 }
03204 break;
03205 case GENCMD_FORCE_HEAL:
03206 ForceHeal(ent);
03207 break;
03208 case GENCMD_FORCE_SPEED:
03209 ForceSpeed(ent, 0);
03210 break;
03211 case GENCMD_FORCE_THROW:
03212 ForceThrow(ent, qfalse);
03213 break;
03214 case GENCMD_FORCE_PULL:
03215 ForceThrow(ent, qtrue);
03216 break;
03217 case GENCMD_FORCE_DISTRACT:
03218 ForceTelepathy(ent);
03219 break;
03220 case GENCMD_FORCE_RAGE:
03221 ForceRage(ent);
03222 break;
03223 case GENCMD_FORCE_PROTECT:
03224 ForceProtect(ent);
03225 break;
03226 case GENCMD_FORCE_ABSORB:
03227 ForceAbsorb(ent);
03228 break;
03229 case GENCMD_FORCE_HEALOTHER:
03230 ForceTeamHeal(ent);
03231 break;
03232 case GENCMD_FORCE_FORCEPOWEROTHER:
03233 ForceTeamForceReplenish(ent);
03234 break;
03235 case GENCMD_FORCE_SEEING:
03236 ForceSeeing(ent);
03237 break;
03238 case GENCMD_USE_SEEKER:
03239 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_SEEKER)) &&
03240 G_ItemUsable(&ent->client->ps, HI_SEEKER) )
03241 {
03242 ItemUse_Seeker(ent);
03243 G_AddEvent(ent, EV_USE_ITEM0+HI_SEEKER, 0);
03244 ent->client->ps.stats[STAT_HOLDABLE_ITEMS] &= ~(1 << HI_SEEKER);
03245 }
03246 break;
03247 case GENCMD_USE_FIELD:
03248 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_SHIELD)) &&
03249 G_ItemUsable(&ent->client->ps, HI_SHIELD) )
03250 {
03251 ItemUse_Shield(ent);
03252 G_AddEvent(ent, EV_USE_ITEM0+HI_SHIELD, 0);
03253 ent->client->ps.stats[STAT_HOLDABLE_ITEMS] &= ~(1 << HI_SHIELD);
03254 }
03255 break;
03256 case GENCMD_USE_BACTA:
03257 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_MEDPAC)) &&
03258 G_ItemUsable(&ent->client->ps, HI_MEDPAC) )
03259 {
03260 ItemUse_MedPack(ent);
03261 G_AddEvent(ent, EV_USE_ITEM0+HI_MEDPAC, 0);
03262 ent->client->ps.stats[STAT_HOLDABLE_ITEMS] &= ~(1 << HI_MEDPAC);
03263 }
03264 break;
03265 case GENCMD_USE_BACTABIG:
03266 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_MEDPAC_BIG)) &&
03267 G_ItemUsable(&ent->client->ps, HI_MEDPAC_BIG) )
03268 {
03269 ItemUse_MedPack_Big(ent);
03270 G_AddEvent(ent, EV_USE_ITEM0+HI_MEDPAC_BIG, 0);
03271 ent->client->ps.stats[STAT_HOLDABLE_ITEMS] &= ~(1 << HI_MEDPAC_BIG);
03272 }
03273 break;
03274 case GENCMD_USE_ELECTROBINOCULARS:
03275 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_BINOCULARS)) &&
03276 G_ItemUsable(&ent->client->ps, HI_BINOCULARS) )
03277 {
03278 ItemUse_Binoculars(ent);
03279 if (ent->client->ps.zoomMode == 0)
03280 {
03281 G_AddEvent(ent, EV_USE_ITEM0+HI_BINOCULARS, 1);
03282 }
03283 else
03284 {
03285 G_AddEvent(ent, EV_USE_ITEM0+HI_BINOCULARS, 2);
03286 }
03287 }
03288 break;
03289 case GENCMD_ZOOM:
03290 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_BINOCULARS)) &&
03291 G_ItemUsable(&ent->client->ps, HI_BINOCULARS) )
03292 {
03293 ItemUse_Binoculars(ent);
03294 if (ent->client->ps.zoomMode == 0)
03295 {
03296 G_AddEvent(ent, EV_USE_ITEM0+HI_BINOCULARS, 1);
03297 }
03298 else
03299 {
03300 G_AddEvent(ent, EV_USE_ITEM0+HI_BINOCULARS, 2);
03301 }
03302 }
03303 break;
03304 case GENCMD_USE_SENTRY:
03305 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_SENTRY_GUN)) &&
03306 G_ItemUsable(&ent->client->ps, HI_SENTRY_GUN) )
03307 {
03308 ItemUse_Sentry(ent);
03309 G_AddEvent(ent, EV_USE_ITEM0+HI_SENTRY_GUN, 0);
03310 ent->client->ps.stats[STAT_HOLDABLE_ITEMS] &= ~(1 << HI_SENTRY_GUN);
03311 }
03312 break;
03313 case GENCMD_USE_JETPACK:
03314 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_JETPACK)) &&
03315 G_ItemUsable(&ent->client->ps, HI_JETPACK) )
03316 {
03317 ItemUse_Jetpack(ent);
03318 G_AddEvent(ent, EV_USE_ITEM0+HI_JETPACK, 0);
03319 /*
03320 if (ent->client->ps.zoomMode == 0)
03321 {
03322 G_AddEvent(ent, EV_USE_ITEM0+HI_BINOCULARS, 1);
03323 }
03324 else
03325 {
03326 G_AddEvent(ent, EV_USE_ITEM0+HI_BINOCULARS, 2);
03327 }
03328 */
03329 }
03330 break;
03331 case GENCMD_USE_HEALTHDISP:
03332 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_HEALTHDISP)) &&
03333 G_ItemUsable(&ent->client->ps, HI_HEALTHDISP) )
03334 {
03335 //ItemUse_UseDisp(ent, HI_HEALTHDISP);
03336 G_AddEvent(ent, EV_USE_ITEM0+HI_HEALTHDISP, 0);
03337 }
03338 break;
03339 case GENCMD_USE_AMMODISP:
03340 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_AMMODISP)) &&
03341 G_ItemUsable(&ent->client->ps, HI_AMMODISP) )
03342 {
03343 //ItemUse_UseDisp(ent, HI_AMMODISP);
03344 G_AddEvent(ent, EV_USE_ITEM0+HI_AMMODISP, 0);
03345 }
03346 break;
03347 case GENCMD_USE_EWEB:
03348 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_EWEB)) &&
03349 G_ItemUsable(&ent->client->ps, HI_EWEB) )
03350 {
03351 ItemUse_UseEWeb(ent);
03352 G_AddEvent(ent, EV_USE_ITEM0+HI_EWEB, 0);
03353 }
03354 break;
03355 case GENCMD_USE_CLOAK:
03356 if ( (ent->client->ps.stats[STAT_HOLDABLE_ITEMS] & (1 << HI_CLOAK)) &&
03357 G_ItemUsable(&ent->client->ps, HI_CLOAK) )
03358 {
03359 if ( ent->client->ps.powerups[PW_CLOAKED] )
03360 {//decloak
03361 Jedi_Decloak( ent );
03362 }
03363 else
03364 {//cloak
03365 Jedi_Cloak( ent );
03366 }
03367 }
03368 break;
03369 case GENCMD_SABERATTACKCYCLE:
03370 Cmd_SaberAttackCycle_f(ent);
03371 break;
03372 case GENCMD_TAUNT:
03373 G_SetTauntAnim( ent, TAUNT_TAUNT );
03374 break;
03375 case GENCMD_BOW:
03376 G_SetTauntAnim( ent, TAUNT_BOW );
03377 break;
03378 case GENCMD_MEDITATE:
03379 G_SetTauntAnim( ent, TAUNT_MEDITATE );
03380 break;
03381 case GENCMD_FLOURISH:
03382 G_SetTauntAnim( ent, TAUNT_FLOURISH );
03383 break;
03384 case GENCMD_GLOAT:
03385 G_SetTauntAnim( ent, TAUNT_GLOAT );
03386 break;
03387 default:
03388 break;
03389 }
03390 }
03391
03392 // save results of pmove
03393 if ( ent->client->ps.eventSequence != oldEventSequence ) {
03394 ent->eventTime = level.time;
03395 }
03396 if (g_smoothClients.integer) {
03397 BG_PlayerStateToEntityStateExtraPolate( &ent->client->ps, &ent->s, ent->client->ps.commandTime, qfalse );
03398 //rww - 12-03-02 - Don't snap the origin of players! It screws prediction all up.
03399 }
03400 else {
03401 BG_PlayerStateToEntityState( &ent->client->ps, &ent->s, qfalse );
03402 }
03403
03404 if (isNPC)
03405 {
03406 ent->s.eType = ET_NPC;
03407 }
03408
03409 SendPendingPredictableEvents( &ent->client->ps );
03410
03411 if ( !( ent->client->ps.eFlags & EF_FIRING ) ) {
03412 client->fireHeld = qfalse; // for grapple
03413 }
03414
03415 // use the snapped origin for linking so it matches client predicted versions
03416 VectorCopy( ent->s.pos.trBase, ent->r.currentOrigin );
03417
03418 if (ent->s.eType != ET_NPC ||
03419 ent->s.NPC_class != CLASS_VEHICLE ||
03420 !ent->m_pVehicle ||
03421 !ent->m_pVehicle->m_iRemovedSurfaces)
03422 { //let vehicles that are getting broken apart do their own crazy sizing stuff
03423 VectorCopy (pm.mins, ent->r.mins);
03424 VectorCopy (pm.maxs, ent->r.maxs);
03425 }
03426
03427 ent->waterlevel = pm.waterlevel;
03428 ent->watertype = pm.watertype;
03429
03430 // execute client events
03431 ClientEvents( ent, oldEventSequence );
03432
03433 if ( pm.useEvent )
03434 {
03435 //TODO: Use
03436 // TryUse( ent );
03437 }
03438 if ((ent->client->pers.cmd.buttons & BUTTON_USE) && ent->client->ps.useDelay < level.time)
03439 {
03440 TryUse(ent);
03441 ent->client->ps.useDelay = level.time + 100;
03442 }
03443
03444 // link entity now, after any personal teleporters have been used
03445 trap_LinkEntity (ent);
03446 if ( !ent->client->noclip ) {
03447 G_TouchTriggers( ent );
03448 }
03449
03450 // NOTE: now copy the exact origin over otherwise clients can be snapped into solid
03451 VectorCopy( ent->client->ps.origin, ent->r.currentOrigin );
03452
03453 //test for solid areas in the AAS file
03454 // BotTestAAS(ent->r.currentOrigin);
03455
03456 // touch other objects
03457 ClientImpacts( ent, &pm );
03458
03459 // save results of triggers and client events
03460 if (ent->client->ps.eventSequence != oldEventSequence) {
03461 ent->eventTime = level.time;
03462 }
03463
03464 // swap and latch button actions
03465 client->oldbuttons = client->buttons;
03466 client->buttons = ucmd->buttons;
03467 client->latched_buttons |= client->buttons & ~client->oldbuttons;
03468
03469 // G_VehicleAttachDroidUnit( ent );
03470
03471 // Did we kick someone in our pmove sequence?
03472 if (client->ps.forceKickFlip)
03473 {
03474 gentity_t *faceKicked = &g_entities[client->ps.forceKickFlip-1];
03475
03476 if (faceKicked && faceKicked->client && (!OnSameTeam(ent, faceKicked) || g_friendlyFire.integer) &&
03477 (!faceKicked->client->ps.duelInProgress || faceKicked->client->ps.duelIndex == ent->s.number) &&
03478 (!ent->client->ps.duelInProgress || ent->client->ps.duelIndex == faceKicked->s.number))
03479 {
03480 if ( faceKicked && faceKicked->client && faceKicked->health && faceKicked->takedamage )
03481 {//push them away and do pain
03482 vec3_t oppDir;
03483 int strength = (int)VectorNormalize2( client->ps.velocity, oppDir );
03484
03485 strength *= 0.05;
03486
03487 VectorScale( oppDir, -1, oppDir );
03488
03489 G_Damage( faceKicked, ent, ent, oppDir, client->ps.origin, strength, DAMAGE_NO_ARMOR, MOD_MELEE );
03490
03491 if ( faceKicked->client->ps.weapon != WP_SABER ||
03492 faceKicked->client->ps.fd.saberAnimLevel != FORCE_LEVEL_3 ||
03493 (!BG_SaberInAttack(faceKicked->client->ps.saberMove) && !PM_SaberInStart(faceKicked->client->ps.saberMove) && !PM_SaberInReturn(faceKicked->client->ps.saberMove) && !PM_SaberInTransition(faceKicked->client->ps.saberMove)) )
03494 {
03495 if (faceKicked->health > 0 &&
03496 faceKicked->client->ps.stats[STAT_HEALTH] > 0 &&
03497 faceKicked->client->ps.forceHandExtend != HANDEXTEND_KNOCKDOWN)
03498 {
03499 if (BG_KnockDownable(&faceKicked->client->ps) && Q_irand(1, 10) <= 3)
03500 { //only actually knock over sometimes, but always do velocity hit
03501 faceKicked->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
03502 faceKicked->client->ps.forceHandExtendTime = level.time + 1100;
03503 faceKicked->client->ps.forceDodgeAnim = 0; //this toggles between 1 and 0, when it's 1 we should play the get up anim
03504 }
03505
03506 faceKicked->client->ps.otherKiller = ent->s.number;
03507 faceKicked->client->ps.otherKillerTime = level.time + 5000;
03508 faceKicked->client->ps.otherKillerDebounceTime = level.time + 100;
03509
03510 faceKicked->client->ps.velocity[0] = oppDir[0]*(strength*40);
03511 faceKicked->client->ps.velocity[1] = oppDir[1]*(strength*40);
03512 faceKicked->client->ps.velocity[2] = 200;
03513 }
03514 }
03515
03516 G_Sound( faceKicked, CHAN_AUTO, G_SoundIndex( va("sound/weapons/melee/punch%d", Q_irand(1, 4)) ) );
03517 }
03518 }
03519
03520 client->ps.forceKickFlip = 0;
03521 }
03522
03523 // check for respawning
03524 if ( client->ps.stats[STAT_HEALTH] <= 0
03525 && !(client->ps.eFlags2&EF2_HELD_BY_MONSTER)//can't respawn while being eaten
03526 && ent->s.eType != ET_NPC ) {
03527 // wait for the attack button to be pressed
03528 if ( level.time > client->respawnTime && !gDoSlowMoDuel ) {
03529 // forcerespawn is to prevent users from waiting out powerups
03530 int forceRes = g_forcerespawn.integer;
03531
03532 if (g_gametype.integer == GT_POWERDUEL)
03533 {
03534 forceRes = 1;
03535 }
03536 else if (g_gametype.integer == GT_SIEGE &&
03537 g_siegeRespawn.integer)
03538 { //wave respawning on
03539 forceRes = 1;
03540 }
03541
03542 if ( forceRes > 0 &&
03543 ( level.time - client->respawnTime ) > forceRes * 1000 ) {
03544 respawn( ent );
03545 return;
03546 }
03547
03548 // pressing attack or use is the normal respawn method
03549 if ( ucmd->buttons & ( BUTTON_ATTACK | BUTTON_USE_HOLDABLE ) ) {
03550 respawn( ent );
03551 }
03552 }
03553 else if (gDoSlowMoDuel)
03554 {
03555 client->respawnTime = level.time + 1000;
03556 }
03557 return;
03558 }
03559
03560 // perform once-a-second actions
03561 ClientTimerActions( ent, msec );
03562
03563 G_UpdateClientBroadcasts ( ent );
03564
03565 //try some idle anims on ent if getting no input and not moving for some time
03566 G_CheckClientIdle( ent, ucmd );
03567
03568 // This code was moved here from clientThink to fix a problem with g_synchronousClients
03569 // being set to 1 when in vehicles.
03570 if ( ent->s.number < MAX_CLIENTS && ent->client->ps.m_iVehicleNum )
03571 {//driving a vehicle
03572 //run it
03573 if (g_entities[ent->client->ps.m_iVehicleNum].inuse && g_entities[ent->client->ps.m_iVehicleNum].client)
03574 {
03575 ClientThink(ent->client->ps.m_iVehicleNum, &g_entities[ent->client->ps.m_iVehicleNum].m_pVehicle->m_ucmd);
03576 }
03577 else
03578 { //vehicle no longer valid?
03579 ent->client->ps.m_iVehicleNum = 0;
03580 }
03581 }
03582
03583 }
|
|
||||||||||||
|
Definition at line 783 of file g_active.c. References gentity_s::client, client, gclient_t, gentity_t, gentity_s::health, gclient_s::ps, STAT_ARMOR, STAT_MAX_HEALTH, playerState_s::stats, and gclient_s::timeResidual. Referenced by ClientThink_real().
00783 {
00784 gclient_t *client;
00785
00786 client = ent->client;
00787 client->timeResidual += msec;
00788
00789 while ( client->timeResidual >= 1000 )
00790 {
00791 client->timeResidual -= 1000;
00792
00793 // count down health when over max
00794 if ( ent->health > client->ps.stats[STAT_MAX_HEALTH] ) {
00795 ent->health--;
00796 }
00797
00798 // count down armor when over max
00799 if ( client->ps.stats[STAT_ARMOR] > client->ps.stats[STAT_MAX_HEALTH] ) {
00800 client->ps.stats[STAT_ARMOR]--;
00801 }
00802 }
00803 }
|
|
||||||||||||||||
|
10; Definition at line 213 of file g_active.c. References entityShared_t::absmax, gentity_s::client, CONTENTS_WATER, entityShared_t::currentOrigin, DAMAGE_NO_ARMOR, DotProduct, ENTITYNUM_NONE, ENTITYNUM_WORLD, playerState_s::fd, FL_BBRUSH, gentity_s::flags, forcedata_s::forceJumpZStart, G_ApplyKnockback(), G_Damage(), g_gravity, gentity_t, playerState_s::groundEntityNum, gentity_s::health, playerState_s::lastOnGround, level, gentity_s::mass, MAT_GLASS, MAT_GLASS_METAL, MAT_GRATE1, gentity_s::material, entityShared_t::maxs, entityShared_t::mins, MOD_CRUSH, MOD_FALLING, NULL, entityState_s::number, entityState_s::pos, gclient_s::ps, qboolean, qtrue, gentity_s::r, gentity_s::s, gentity_s::spawnflags, gentity_s::splashRadius, SVF_GLASS_BRUSH, entityShared_t::svFlags, gentity_s::takedamage, level_locals_t::time, TR_GRAVITY, trap_PointContents(), trajectory_t::trDelta, trajectory_t::trType, vmCvar_t::value, vec3_origin, vec3_t, VectorCopy, VectorNormalize(), VectorSubtract, playerState_s::velocity, entityState_s::weapon, and WP_SABER. Referenced by Client_CheckImpactBBrush(), and G_RunObject().
00214 {
00215 float magnitude, my_mass;
00216 vec3_t velocity;
00217 int cont;
00218 qboolean easyBreakBrush = qtrue;
00219
00220 if( self->client )
00221 {
00222 VectorCopy( self->client->ps.velocity, velocity );
00223 if( !self->mass )
00224 {
00225 my_mass = 10;
00226 }
00227 else
00228 {
00229 my_mass = self->mass;
00230 }
00231 }
00232 else
00233 {
00234 VectorCopy( self->s.pos.trDelta, velocity );
00235 if ( self->s.pos.trType == TR_GRAVITY )
00236 {
00237 velocity[2] -= 0.25f * g_gravity.value;
00238 }
00239 if( !self->mass )
00240 {
00241 my_mass = 1;
00242 }
00243 else if ( self->mass <= 10 )
00244 {
00245 my_mass = 10;
00246 }
00247 else
00248 {
00249 my_mass = self->mass;
00250 }
00251 }
00252
00253 magnitude = VectorLength( velocity ) * my_mass / 10;
00254
00255 /*
00256 if(pointcontents(self.absmax)==CONTENT_WATER)//FIXME: or other watertypes
00257 magnitude/=3; //water absorbs 2/3 velocity
00258
00259 if(self.classname=="barrel"&&self.aflag)//rolling barrels are made for impacts!
00260 magnitude*=3;
00261
00262 if(self.frozen>0&&magnitude<300&&self.flags&FL_ONGROUND&&loser==world&&self.velocity_z<-20&&self.last_onground+0.3<time)
00263 magnitude=300;
00264 */
00265 if ( other->material == MAT_GLASS
00266 || other->material == MAT_GLASS_METAL
00267 || other->material == MAT_GRATE1
00268 || ((other->flags&FL_BBRUSH)&&(other->spawnflags&8/*THIN*/))
00269 || (other->r.svFlags&SVF_GLASS_BRUSH) )
00270 {
00271 easyBreakBrush = qtrue;
00272 }
00273
00274 if ( !self->client || self->client->ps.lastOnGround+300<level.time || ( self->client->ps.lastOnGround+100 < level.time && easyBreakBrush ) )
00275 {
00276 vec3_t dir1, dir2;
00277 float force = 0, dot;
00278
00279 if ( easyBreakBrush )
00280 magnitude *= 2;
00281
00282 //damage them
00283 if ( magnitude >= 100 && other->s.number < ENTITYNUM_WORLD )
00284 {
00285 VectorCopy( velocity, dir1 );
00286 VectorNormalize( dir1 );
00287 if( VectorCompare( other->r.currentOrigin, vec3_origin ) )
00288 {//a brush with no origin
00289 VectorCopy ( dir1, dir2 );
00290 }
00291 else
00292 {
00293 VectorSubtract( other->r.currentOrigin, self->r.currentOrigin, dir2 );
00294 VectorNormalize( dir2 );
00295 }
00296
00297 dot = DotProduct( dir1, dir2 );
00298
00299 if ( dot >= 0.2 )
00300 {
00301 force = dot;
00302 }
00303 else
00304 {
00305 force = 0;
00306 }
00307
00308 force *= (magnitude/50);
00309
00310 cont = trap_PointContents( other->r.absmax, other->s.number );
00311 if( (cont&CONTENTS_WATER) )//|| (self.classname=="barrel"&&self.aflag))//FIXME: or other watertypes
00312 {
00313 force /= 3; //water absorbs 2/3 velocity
00314 }
00315
00316 /*
00317 if(self.frozen>0&&force>10)
00318 force=10;
00319 */
00320
00321 if( ( force >= 1 && other->s.number != 0 ) || force >= 10)
00322 {
00323 /*
00324 dprint("Damage other (");
00325 dprint(loser.classname);
00326 dprint("): ");
00327 dprint(ftos(force));
00328 dprint("\n");
00329 */
00330 if ( other->r.svFlags & SVF_GLASS_BRUSH )
00331 {
00332 other->splashRadius = (float)(self->r.maxs[0] - self->r.mins[0])/4.0f;
00333 }
00334 if ( other->takedamage )
00335 {
00336 G_Damage( other, self, self, velocity, self->r.currentOrigin, force, DAMAGE_NO_ARMOR, MOD_CRUSH);//FIXME: MOD_IMPACT
00337 }
00338 else
00339 {
00340 G_ApplyKnockback( other, dir2, force );
00341 }
00342 }
00343 }
00344
00345 if ( damageSelf && self->takedamage )
00346 {
00347 //Now damage me
00348 //FIXME: more lenient falling damage, especially for when driving a vehicle
00349 if ( self->client && self->client->ps.fd.forceJumpZStart )
00350 {//we were force-jumping
00351 if ( self->r.currentOrigin[2] >= self->client->ps.fd.forceJumpZStart )
00352 {//we landed at same height or higher than we landed
00353 magnitude = 0;
00354 }
00355 else
00356 {//FIXME: take off some of it, at least?
00357 magnitude = (self->client->ps.fd.forceJumpZStart-self->r.currentOrigin[2])/3;
00358 }
00359 }
00360 //if(self.classname!="monster_mezzoman"&&self.netname!="spider")//Cats always land on their feet
00361 if( ( magnitude >= 100 + self->health && self->s.number != 0 && self->s.weapon != WP_SABER ) || ( magnitude >= 700 ) )//&& self.safe_time < level.time ))//health here is used to simulate structural integrity
00362 {
00363 if ( (self->s.weapon == WP_SABER || self->s.number == 0) && self->client && self->client->ps.groundEntityNum < ENTITYNUM_NONE && magnitude < 1000 )
00364 {//players and jedi take less impact damage
00365 //allow for some lenience on high falls
00366 magnitude /= 2;
00367 /*
00368 if ( self.absorb_time >= time )//crouching on impact absorbs 1/2 the damage
00369 {
00370 magnitude/=2;
00371 }
00372 */
00373 }
00374 magnitude /= 40;
00375 magnitude = magnitude - force/2;//If damage other, subtract half of that damage off of own injury
00376 if ( magnitude >= 1 )
00377 {
00378 //FIXME: Put in a thingtype impact sound function
00379 /*
00380 dprint("Damage self (");
00381 dprint(self.classname);
00382 dprint("): ");
00383 dprint(ftos(magnitude));
00384 dprint("\n");
00385 */
00386 /*
00387 if ( self.classname=="player_sheep "&& self.flags&FL_ONGROUND && self.velocity_z > -50 )
00388 return;
00389 */
00390 G_Damage( self, NULL, NULL, NULL, self->r.currentOrigin, magnitude/2, DAMAGE_NO_ARMOR, MOD_FALLING );//FIXME: MOD_IMPACT
00391 }
00392 }
00393 }
00394
00395 //FIXME: slow my velocity some?
00396
00397 // NOTENOTE We don't use lastimpact as of yet
00398 // self->lastImpact = level.time;
00399
00400 /*
00401 if(self.flags&FL_ONGROUND)
00402 self.last_onground=time;
00403 */
00404 }
00405 }
|
|
|
Definition at line 46 of file g_nav.c. Referenced by NAV_ClearPathToPoint(), NPC_BSST_Investigate(), NPC_ClearPathToGoal(), and ReachedGoal().
|
|
|
Definition at line 1260 of file g_active.c. References BUTTON_ALT_ATTACK, BUTTON_ATTACK, BUTTON_FORCE_DRAIN, BUTTON_FORCE_LIGHTNING, BUTTON_FORCEGRIP, BUTTON_FORCEPOWER, BUTTON_GESTURE, BUTTON_USE, BUTTON_USE_HOLDABLE, qboolean, qfalse, and qtrue. Referenced by G_CheckClientIdle().
01261 {
01262 if (buttons & BUTTON_ATTACK)
01263 {
01264 return qtrue;
01265 }
01266 else if (buttons & BUTTON_USE_HOLDABLE)
01267 {
01268 return qtrue;
01269 }
01270 else if (buttons & BUTTON_GESTURE)
01271 {
01272 return qtrue;
01273 }
01274 else if (buttons & BUTTON_USE)
01275 {
01276 return qtrue;
01277 }
01278 else if (buttons & BUTTON_FORCEGRIP)
01279 {
01280 return qtrue;
01281 }
01282 else if (buttons & BUTTON_ALT_ATTACK)
01283 {
01284 return qtrue;
01285 }
01286 else if (buttons & BUTTON_FORCEPOWER)
01287 {
01288 return qtrue;
01289 }
01290 else if (buttons & BUTTON_FORCE_LIGHTNING)
01291 {
01292 return qtrue;
01293 }
01294 else if (buttons & BUTTON_FORCE_DRAIN)
01295 {
01296 return qtrue;
01297 }
01298
01299 return qfalse;
01300 }
|
|
||||||||||||
|
Definition at line 1211 of file g_active.c. References AngleVectors(), gentity_s::client, DotProduct, floor(), usercmd_s::forwardmove, gentity_t, level, NULL, gclient_s::ps, gclient_s::pushVec, gclient_s::pushVecTime, usercmd_s::rightmove, playerState_s::speed, level_locals_t::time, ucmd, usercmd_t, vec3_t, VectorAdd, VectorClear, VectorMA, VectorNormalize(), VectorScale, and playerState_s::viewangles. Referenced by ClientThink_real().
01212 {
01213 vec3_t forward, right, moveDir;
01214 float pushSpeed, fMove, rMove;
01215
01216 if ( !self->client )
01217 {
01218 return;
01219 }
01220 pushSpeed = VectorLengthSquared(self->client->pushVec);
01221 if(!pushSpeed)
01222 {//not being pushed
01223 return;
01224 }
01225
01226 AngleVectors(self->client->ps.viewangles, forward, right, NULL);
01227 VectorScale(forward, ucmd->forwardmove/127.0f * self->client->ps.speed, moveDir);
01228 VectorMA(moveDir, ucmd->rightmove/127.0f * self->client->ps.speed, right, moveDir);
01229 //moveDir is now our intended move velocity
01230
01231 VectorAdd(moveDir, self->client->pushVec, moveDir);
01232 self->client->ps.speed = VectorNormalize(moveDir);
01233 //moveDir is now our intended move velocity plus our push Vector
01234
01235 fMove = 127.0 * DotProduct(forward, moveDir);
01236 rMove = 127.0 * DotProduct(right, moveDir);
01237 ucmd->forwardmove = floor(fMove);//If in the same dir , will be positive
01238 ucmd->rightmove = floor(rMove);//If in the same dir , will be positive
01239
01240 if ( self->client->pushVecTime < level.time )
01241 {
01242 VectorClear( self->client->pushVec );
01243 }
01244 }
|
|
||||||||||||||||
|
Definition at line 2949 of file g_combat.c. References gentity_s::client, entityShared_t::currentOrigin, g_gravity, g_knockback, gentity_t, level, gentity_s::physicsBounce, playerState_s::pm_flags, playerState_s::pm_time, PMF_TIME_KNOCKBACK, entityState_s::pos, gclient_s::ps, gentity_s::r, gentity_s::s, level_locals_t::time, TR_LINEAR_STOP, TR_NONLINEAR_STOP, TR_STATIONARY, trajectory_t::trBase, trajectory_t::trDelta, trajectory_t::trTime, trajectory_t::trType, vmCvar_t::value, vec3_t, VectorAdd, VectorCopy, VectorScale, and playerState_s::velocity. Referenced by DoImpact().
02950 {
02951 vec3_t kvel;
02952 float mass;
02953
02954 if ( targ->physicsBounce > 0 ) //overide the mass
02955 mass = targ->physicsBounce;
02956 else
02957 mass = 200;
02958
02959 if ( g_gravity.value > 0 )
02960 {
02961 VectorScale( newDir, g_knockback.value * (float)knockback / mass * 0.8, kvel );
02962 kvel[2] = newDir[2] * g_knockback.value * (float)knockback / mass * 1.5;
02963 }
02964 else
02965 {
02966 VectorScale( newDir, g_knockback.value * (float)knockback / mass, kvel );
02967 }
02968
02969 if ( targ->client )
02970 {
02971 VectorAdd( targ->client->ps.velocity, kvel, targ->client->ps.velocity );
02972 }
02973 else if ( targ->s.pos.trType != TR_STATIONARY && targ->s.pos.trType != TR_LINEAR_STOP && targ->s.pos.trType != TR_NONLINEAR_STOP )
02974 {
02975 VectorAdd( targ->s.pos.trDelta, kvel, targ->s.pos.trDelta );
02976 VectorCopy( targ->r.currentOrigin, targ->s.pos.trBase );
02977 targ->s.pos.trTime = level.time;
02978 }
02979
02980 // set the timer so that the other client can't cancel
02981 // out the movement immediately
02982 if ( targ->client && !targ->client->ps.pm_time )
02983 {
02984 int t;
02985
02986 t = knockback * 2;
02987 if ( t < 50 ) {
02988 t = 50;
02989 }
02990 if ( t > 200 ) {
02991 t = 200;
02992 }
02993 targ->client->ps.pm_time = t;
02994 targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
02995 }
02996 }
|
|
||||||||||||
|
Definition at line 857 of file g_active.c. References gentity_s::client, gclient_s::dangerTime, EF_INVULNERABLE, playerState_s::eFlags, EV_ALT_FIRE, EV_FIRE_WEAPON, FireWeapon(), g_entities, gentity_t, gentity_s::inuse, gclient_s::invulnerableTimer, level, playerState_s::m_iVehicleNum, gentity_s::m_pVehicle, Vehicle_s::m_pVehicleInfo, gclient_s::ps, qfalse, qtrue, playerState_s::saberHolstered, level_locals_t::time, vehicleInfo_t::type, VH_SPEEDER, playerState_s::weapon, WP_MELEE, and WP_SABER.
00858 {
00859 gentity_t *ent = &g_entities[entNum];
00860
00861 if (!ent->inuse || !ent->client)
00862 {
00863 return;
00864 }
00865
00866 switch (ev)
00867 {
00868 case EV_FIRE_WEAPON:
00869 if (ent->m_pVehicle && ent->m_pVehicle->m_pVehicleInfo->type == VH_SPEEDER &&
00870 ent->client && ent->client->ps.m_iVehicleNum)
00871 { //a speeder with a pilot
00872 gentity_t *rider = &g_entities[ent->client->ps.m_iVehicleNum-1];
00873 if (rider->inuse && rider->client)
00874 { //pilot is valid...
00875 if (rider->client->ps.weapon != WP_MELEE &&
00876 (rider->client->ps.weapon != WP_SABER || !rider->client->ps.saberHolstered))
00877 { //can only attack on speeder when using melee or when saber is holstered
00878 break;
00879 }
00880 }
00881 }
00882
00883 FireWeapon( ent, qfalse );
00884 ent->client->dangerTime = level.time;
00885 ent->client->ps.eFlags &= ~EF_INVULNERABLE;
00886 ent->client->invulnerableTimer = 0;
00887 break;
00888 case EV_ALT_FIRE:
00889 FireWeapon( ent, qtrue );
00890 ent->client->dangerTime = level.time;
00891 ent->client->ps.eFlags &= ~EF_INVULNERABLE;
00892 ent->client->invulnerableTimer = 0;
00893 break;
00894 }
00895 }
|
|
||||||||||||
|
|
Definition at line 3592 of file g_active.c. References gentity_s::client, clientPersistant_t::cmd, g_timeouttospec, gentity_t, vmCvar_t::integer, level, gclient_s::pers, usercmd_s::serverTime, gclient_s::sess, clientSession_t::sessionTeam, SetTeam(), TEAM_SPECTATOR, and level_locals_t::time. Referenced by G_RunFrame().
03593 {
03594 // Only timeout supported right now is the timeout to spectator mode
03595 if ( !g_timeouttospec.integer )
03596 {
03597 return;
03598 }
03599
03600 // Already a spectator, no need to boot them to spectator
03601 if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR )
03602 {
03603 return;
03604 }
03605
03606 // See how long its been since a command was received by the client and if its
03607 // longer than the timeout to spectator then force this client into spectator mode
03608 if ( level.time - ent->client->pers.cmd.serverTime > g_timeouttospec.integer * 1000 )
03609 {
03610 SetTeam ( ent, "spectator" );
03611 }
03612 }
|
|
||||||||||||
|
Definition at line 1577 of file g_active.c. References CLASS_MARK2, CLASS_MOUSE, CLASS_PROBE, CLASS_R2D2, CLASS_R5D2, gentity_s::client, FlyingCreature(), usercmd_s::forwardmove, G_SoundIndex(), gentity_t, gentity_s::health, entityState_s::loopSound, playerState_s::moveDir, gentity_s::NPC, gclient_s::NPC_class, gclient_s::ps, usercmd_s::rightmove, gentity_s::s, ucmd, usercmd_s::upmove, usercmd_t, vec3_origin, and playerState_s::velocity. Referenced by ClientThink_real().
01578 {
01579 if ( ent->client )
01580 {
01581 if ( (ent->NPC&&!VectorCompare( vec3_origin, ent->client->ps.moveDir ))//moving using moveDir
01582 || ucmd->forwardmove || ucmd->rightmove//moving using ucmds
01583 || (ucmd->upmove&&FlyingCreature( ent ))//flier using ucmds to move
01584 || (FlyingCreature( ent )&&!VectorCompare( vec3_origin, ent->client->ps.velocity )&&ent->health>0))//flier using velocity to move
01585 {
01586 switch( ent->client->NPC_class )
01587 {
01588 case CLASS_R2D2:
01589 ent->s.loopSound = G_SoundIndex( "sound/chars/r2d2/misc/r2_move_lp.wav" );
01590 break;
01591 case CLASS_R5D2:
01592 ent->s.loopSound = G_SoundIndex( "sound/chars/r2d2/misc/r2_move_lp2.wav" );
01593 break;
01594 case CLASS_MARK2:
01595 ent->s.loopSound = G_SoundIndex( "sound/chars/mark2/misc/mark2_move_lp" );
01596 break;
01597 case CLASS_MOUSE:
01598 ent->s.loopSound = G_SoundIndex( "sound/chars/mouse/misc/mouse_lp" );
01599 break;
01600 case CLASS_PROBE:
01601 ent->s.loopSound = G_SoundIndex( "sound/chars/probe/misc/probedroidloop" );
01602 }
01603 }
01604 else
01605 {//not moving under your own control, stop loopSound
01606 if ( ent->client->NPC_class == CLASS_R2D2 || ent->client->NPC_class == CLASS_R5D2
01607 || ent->client->NPC_class == CLASS_MARK2 || ent->client->NPC_class == CLASS_MOUSE
01608 || ent->client->NPC_class == CLASS_PROBE )
01609 {
01610 ent->s.loopSound = 0;
01611 }
01612 }
01613 }
01614 }
|
|
||||||||||||
|
Definition at line 1616 of file g_active.c. References BG_AttachToRancor(), CLASS_RANCOR, gentity_s::client, entityShared_t::currentAngles, entityShared_t::currentOrigin, EF2_GENERIC_NPC_FLAG, playerState_s::eFlags2, g_entities, G_SetAngles(), G_SetOrigin(), gentity_t, gentity_s::ghoul2, playerState_s::hasLookTarget, level, playerState_s::lookTarget, gentity_s::modelScale, entityState_s::NPC_class, NULL, playerState_s::origin, gclient_s::ps, gentity_s::r, gentity_s::s, SetClientViewAngle(), level_locals_t::time, trap_LinkEntity(), usercmd_t, VectorClear, playerState_s::velocity, playerState_s::viewangles, gentity_s::waypoint, and YAW. Referenced by ClientThink_real().
01617 {
01618 if ( ent
01619 && ent->client
01620 && ent->client->ps.hasLookTarget )//NOTE: lookTarget is an entity number, so this presumes that client 0 is NOT a Rancor...
01621 {
01622 gentity_t *monster = &g_entities[ent->client->ps.lookTarget];
01623 if ( monster && monster->client )
01624 {
01625 //take the monster's waypoint as your own
01626 ent->waypoint = monster->waypoint;
01627 if ( monster->s.NPC_class == CLASS_RANCOR )
01628 {//only possibility right now, may add Wampa and Sand Creature later
01629 BG_AttachToRancor( monster->ghoul2, //ghoul2 info
01630 monster->r.currentAngles[YAW],
01631 monster->r.currentOrigin,
01632 level.time,
01633 NULL,
01634 monster->modelScale,
01635 (monster->client->ps.eFlags2&EF2_GENERIC_NPC_FLAG),
01636 ent->client->ps.origin,
01637 ent->client->ps.viewangles,
01638 NULL );
01639 }
01640 VectorClear( ent->client->ps.velocity );
01641 G_SetOrigin( ent, ent->client->ps.origin );
01642 SetClientViewAngle( ent, ent->client->ps.viewangles );
01643 G_SetAngles( ent, ent->client->ps.viewangles );
01644 trap_LinkEntity( ent );//redundant?
01645 }
01646 }
01647 // don't allow movement, weapon switching, and most kinds of button presses
01648 (*ucmd)->forwardmove = 0;
01649 (*ucmd)->rightmove = 0;
01650 (*ucmd)->upmove = 0;
01651 }
|
|
||||||||||||
|
Definition at line 601 of file g_active.c. References entityShared_t::contents, CONTENTS_TRIGGER, entityShared_t::currentOrigin, ET_PUSH_TRIGGER, entityState_s::eType, g_entities, gentity_t, MAX_GENTITIES, entityShared_t::maxs, memset(), entityShared_t::mins, NULL, entityState_s::pos, gentity_s::r, gentity_s::s, gentity_s::touch, trap_EntitiesInBox(), trap_EntityContact(), trajectory_t::trDelta, vec3_t, VectorAdd, VectorMA, VectorNormalize(), and VectorSubtract. Referenced by G_RunObject().
00602 {
00603 int i, num;
00604 float step, stepSize, dist;
00605 int touch[MAX_GENTITIES];
00606 gentity_t *hit;
00607 trace_t trace;
00608 vec3_t mins, maxs, dir, size, checkSpot;
00609 const vec3_t range = { 40, 40, 52 };
00610
00611 // non-moving movers don't hit triggers!
00612 if ( !VectorLengthSquared( ent->s.pos.trDelta ) )
00613 {
00614 return;
00615 }
00616
00617 VectorSubtract( ent->r.mins, ent->r.maxs, size );
00618 stepSize = VectorLength( size );
00619 if ( stepSize < 1 )
00620 {
00621 stepSize = 1;
00622 }
00623
00624 VectorSubtract( ent->r.currentOrigin, oldOrg, dir );
00625 dist = VectorNormalize( dir );
00626 for ( step = 0; step <= dist; step += stepSize )
00627 {
00628 VectorMA( ent->r.currentOrigin, step, dir, checkSpot );
00629 VectorSubtract( checkSpot, range, mins );
00630 VectorAdd( checkSpot, range, maxs );
00631
00632 num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );
00633
00634 // can't use ent->r.absmin, because that has a one unit pad
00635 VectorAdd( checkSpot, ent->r.mins, mins );
00636 VectorAdd( checkSpot, ent->r.maxs, maxs );
00637
00638 for ( i=0 ; i<num ; i++ )
00639 {
00640 hit = &g_entities[touch[i]];
00641
00642 if ( hit->s.eType != ET_PUSH_TRIGGER )
00643 {
00644 continue;
00645 }
00646
00647 if ( hit->touch == NULL )
00648 {
00649 continue;
00650 }
00651
00652 if ( !( hit->r.contents & CONTENTS_TRIGGER ) )
00653 {
00654 continue;
00655 }
00656
00657
00658 if ( !trap_EntityContact( mins, maxs, hit ) )
00659 {
00660 continue;
00661 }
00662
00663 memset( &trace, 0, sizeof(trace) );
00664
00665 if ( hit->touch != NULL )
00666 {
00667 hit->touch(hit, ent, &trace);
00668 }
00669 }
00670 }
00671 }
|
|
|
Definition at line 3695 of file g_active.c. References gentity_s::client, ClientThink_real(), clientPersistant_t::cmd, g_synchronousClients, gentity_t, vmCvar_t::integer, level, gclient_s::pers, gentity_s::r, usercmd_s::serverTime, SVF_BOT, entityShared_t::svFlags, and level_locals_t::time. Referenced by G_RunFrame().
03695 {
03696 if ( !(ent->r.svFlags & SVF_BOT) && !g_synchronousClients.integer ) {
03697 return;
03698 }
03699 ent->client->pers.cmd.serverTime = level.time;
03700 ClientThink_real( ent );
03701 }
|
|
|
||||||||||||
|
Definition at line 1662 of file g_active.c. References animNumber_t, BG_AnimLength(), BOTH_BOW, BOTH_DUAL_TAUNT, BOTH_ENGAGETAUNT, BOTH_GESTURE1, BOTH_MEDITATE, BOTH_SHOWOFF_DUAL, BOTH_SHOWOFF_FAST, BOTH_SHOWOFF_MEDIUM, BOTH_SHOWOFF_STAFF, BOTH_SHOWOFF_STRONG, BOTH_STAFF_TAUNT, BOTH_VICTORY_DUAL, BOTH_VICTORY_FAST, BOTH_VICTORY_MEDIUM, BOTH_VICTORY_STAFF, BOTH_VICTORY_STRONG, saberInfo_t::bowAnim, CHAN_WEAPON, gentity_s::client, clientPersistant_t::cmd, ENTITYNUM_NONE, EV_TAUNT, playerState_s::fd, saberInfo_t::flourishAnim, playerState_s::forceDodgeAnim, playerState_s::forceHandExtend, playerState_s::forceHandExtendTime, usercmd_s::forwardmove, G_AddEvent(), g_gametype, G_Sound(), gentity_t, saberInfo_t::gloatAnim, playerState_s::groundEntityNum, GT_DUEL, GT_POWERDUEL, HANDEXTEND_NONE, HANDEXTEND_TAUNT, vmCvar_t::integer, playerState_s::legsTimer, level, gentity_s::localAnimIndex, saberInfo_t::meditateAnim, saberInfo_t::model, gclient_s::pers, gclient_s::ps, usercmd_s::rightmove, gclient_s::saber, forcedata_s::saberAnimLevel, playerState_s::saberHolstered, playerState_s::saberLockTime, saberInfo_t::soundOff, saberInfo_t::soundOn, SS_DESANN, SS_DUAL, SS_FAST, SS_MEDIUM, SS_STAFF, SS_STRONG, SS_TAVION, TAUNT_BOW, TAUNT_FLOURISH, TAUNT_GLOAT, TAUNT_MEDITATE, TAUNT_TAUNT, saberInfo_t::tauntAnim, level_locals_t::time, playerState_s::torsoTimer, usercmd_s::upmove, playerState_s::weapon, playerState_s::weaponTime, and WP_SABER. Referenced by ClientThink_real().
01663 {
01664 if (ent->client->pers.cmd.upmove ||
01665 ent->client->pers.cmd.forwardmove ||
01666 ent->client->pers.cmd.rightmove)
01667 { //hack, don't do while moving
01668 return;
01669 }
01670 if ( taunt != TAUNT_TAUNT )
01671 {//normal taunt always allowed
01672 if ( g_gametype.integer != GT_DUEL
01673 && g_gametype.integer != GT_POWERDUEL )
01674 {//no taunts unless in Duel
01675 return;
01676 }
01677 }
01678 if ( ent->client->ps.torsoTimer < 1
01679 && ent->client->ps.forceHandExtend == HANDEXTEND_NONE
01680 && ent->client->ps.legsTimer < 1
01681 && ent->client->ps.weaponTime < 1
01682 && ent->client->ps.saberLockTime < level.time )
01683 {
01684 int anim = -1;
01685 switch ( taunt )
01686 {
01687 case TAUNT_TAUNT:
01688 if ( ent->client->ps.weapon != WP_SABER )
01689 {
01690 anim = BOTH_ENGAGETAUNT;
01691 }
01692 else if ( ent->client->saber[0].tauntAnim != -1 )
01693 {
01694 anim = ent->client->saber[0].tauntAnim;
01695 }
01696 else if ( ent->client->saber[1].model
01697 && ent->client->saber[1].model[0]
01698 && ent->client->saber[1].tauntAnim != -1 )
01699 {
01700 anim = ent->client->saber[1].tauntAnim;
01701 }
01702 else
01703 {
01704 switch ( ent->client->ps.fd.saberAnimLevel )
01705 {
01706 case SS_FAST:
01707 case SS_TAVION:
01708 if ( ent->client->ps.saberHolstered == 1
01709 && ent->client->saber[1].model
01710 && ent->client->saber[1].model[0] )
01711 {//turn off second saber
01712 G_Sound( ent, CHAN_WEAPON, ent->client->saber[1].soundOff );
01713 }
01714 else if ( ent->client->ps.saberHolstered == 0 )
01715 {//turn off first
01716 G_Sound( ent, CHAN_WEAPON, ent->client->saber[0].soundOff );
01717 }
01718 ent->client->ps.saberHolstered = 2;
01719 anim = BOTH_GESTURE1;
01720 break;
01721 case SS_MEDIUM:
01722 case SS_STRONG:
01723 case SS_DESANN:
01724 anim = BOTH_ENGAGETAUNT;
01725 break;
01726 case SS_DUAL:
01727 if ( ent->client->ps.saberHolstered == 1
01728 && ent->client->saber[1].model
01729 && ent->client->saber[1].model[0] )
01730 {//turn on second saber
01731 G_Sound( ent, CHAN_WEAPON, ent->client->saber[1].soundOn );
01732 }
01733 else if ( ent->client->ps.saberHolstered == 2 )
01734 {//turn on first
01735 G_Sound( ent, CHAN_WEAPON, ent->client->saber[0].soundOn );
01736 }
01737 ent->client->ps.saberHolstered = 0;
01738 anim = BOTH_DUAL_TAUNT;
01739 break;
01740 case SS_STAFF:
01741 if ( ent->client->ps.saberHolstered > 0 )
01742 {//turn on all blades
01743 G_Sound( ent, CHAN_WEAPON, ent->client->saber[0].soundOn );
01744 }
01745 ent->client->ps.saberHolstered = 0;
01746 anim = BOTH_STAFF_TAUNT;
01747 break;
01748 }
01749 }
01750 break;
01751 case TAUNT_BOW:
01752 if ( ent->client->saber[0].bowAnim != -1 )
01753 {
01754 anim = ent->client->saber[0].bowAnim;
01755 }
01756 else if ( ent->client->saber[1].model
01757 && ent->client->saber[1].model[0]
01758 && ent->client->saber[1].bowAnim != -1 )
01759 {
01760 anim = ent->client->saber[1].bowAnim;
01761 }
01762 else
01763 {
01764 anim = BOTH_BOW;
01765 }
01766 if ( ent->client->ps.saberHolstered == 1
01767 && ent->client->saber[1].model
01768 && ent->client->saber[1].model[0] )
01769 {//turn off second saber
01770 G_Sound( ent, CHAN_WEAPON, ent->client->saber[1].soundOff );
01771 }
01772 else if ( ent->client->ps.saberHolstered == 0 )
01773 {//turn off first
01774 G_Sound( ent, CHAN_WEAPON, ent->client->saber[0].soundOff );
01775 }
01776 ent->client->ps.saberHolstered = 2;
01777 break;
01778 case TAUNT_MEDITATE:
01779 if ( ent->client->saber[0].meditateAnim != -1 )
01780 {
01781 anim = ent->client->saber[0].meditateAnim;
01782 }
01783 else if ( ent->client->saber[1].model
01784 && ent->client->saber[1].model[0]
01785 && ent->client->saber[1].meditateAnim != -1 )
01786 {
01787 anim = ent->client->saber[1].meditateAnim;
01788 }
01789 else
01790 {
01791 anim = BOTH_MEDITATE;
01792 }
01793 if ( ent->client->ps.saberHolstered == 1
01794 && ent->client->saber[1].model
01795 && ent->client->saber[1].model[0] )
01796 {//turn off second saber
01797 G_Sound( ent, CHAN_WEAPON, ent->client->saber[1].soundOff );
01798 }
01799 else if ( ent->client->ps.saberHolstered == 0 )
01800 {//turn off first
01801 G_Sound( ent, CHAN_WEAPON, ent->client->saber[0].soundOff );
01802 }
01803 ent->client->ps.saberHolstered = 2;
01804 break;
01805 case TAUNT_FLOURISH:
01806 if ( ent->client->ps.weapon == WP_SABER )
01807 {
01808 if ( ent->client->ps.saberHolstered == 1
01809 && ent->client->saber[1].model
01810 && ent->client->saber[1].model[0] )
01811 {//turn on second saber
01812 G_Sound( ent, CHAN_WEAPON, ent->client->saber[1].soundOn );
01813 }
01814 else if ( ent->client->ps.saberHolstered == 2 )
01815 {//turn on first
01816 G_Sound( ent, CHAN_WEAPON, ent->client->saber[0].soundOn );
01817 }
01818 ent->client->ps.saberHolstered = 0;
01819 if ( ent->client->saber[0].flourishAnim != -1 )
01820 {
01821 anim = ent->client->saber[0].flourishAnim;
01822 }
01823 else if ( ent->client->saber[1].model
01824 && ent->client->saber[1].model[0]
01825 && ent->client->saber[1].flourishAnim != -1 )
01826 {
01827 anim = ent->client->saber[1].flourishAnim;
01828 }
01829 else
01830 {
01831 switch ( ent->client->ps.fd.saberAnimLevel )
01832 {
01833 case SS_FAST:
01834 case SS_TAVION:
01835 anim = BOTH_SHOWOFF_FAST;
01836 break;
01837 case SS_MEDIUM:
01838 anim = BOTH_SHOWOFF_MEDIUM;
01839 break;
01840 case SS_STRONG:
01841 case SS_DESANN:
01842 anim = BOTH_SHOWOFF_STRONG;
01843 break;
01844 case SS_DUAL:
01845 anim = BOTH_SHOWOFF_DUAL;
01846 break;
01847 case SS_STAFF:
01848 anim = BOTH_SHOWOFF_STAFF;
01849 break;
01850 }
01851 }
01852 }
01853 break;
01854 case TAUNT_GLOAT:
01855 if ( ent->client->saber[0].gloatAnim != -1 )
01856 {
01857 anim = ent->client->saber[0].gloatAnim;
01858 }
01859 else if ( ent->client->saber[1].model
01860 && ent->client->saber[1].model[0]
01861 && ent->client->saber[1].gloatAnim != -1 )
01862 {
01863 anim = ent->client->saber[1].gloatAnim;
01864 }
01865 else
01866 {
01867 switch ( ent->client->ps.fd.saberAnimLevel )
01868 {
01869 case SS_FAST:
01870 case SS_TAVION:
01871 anim = BOTH_VICTORY_FAST;
01872 break;
01873 case SS_MEDIUM:
01874 anim = BOTH_VICTORY_MEDIUM;
01875 break;
01876 case SS_STRONG:
01877 case SS_DESANN:
01878 if ( ent->client->ps.saberHolstered )
01879 {//turn on first
01880 G_Sound( ent, CHAN_WEAPON, ent->client->saber[0].soundOn );
01881 }
01882 ent->client->ps.saberHolstered = 0;
01883 anim = BOTH_VICTORY_STRONG;
01884 break;
01885 case SS_DUAL:
01886 if ( ent->client->ps.saberHolstered == 1
01887 && ent->client->saber[1].model
01888 && ent->client->saber[1].model[0] )
01889 {//turn on second saber
01890 G_Sound( ent, CHAN_WEAPON, ent->client->saber[1].soundOn );
01891 }
01892 else if ( ent->client->ps.saberHolstered == 2 )
01893 {//turn on first
01894 G_Sound( ent, CHAN_WEAPON, ent->client->saber[0].soundOn );
01895 }
01896 ent->client->ps.saberHolstered = 0;
01897 anim = BOTH_VICTORY_DUAL;
01898 break;
01899 case SS_STAFF:
01900 if ( ent->client->ps.saberHolstered )
01901 {//turn on first
01902 G_Sound( ent, CHAN_WEAPON, ent->client->saber[0].soundOn );
01903 }
01904 ent->client->ps.saberHolstered = 0;
01905 anim = BOTH_VICTORY_STAFF;
01906 break;
01907 }
01908 }
01909 break;
01910 }
01911 if ( anim != -1 )
01912 {
01913 if ( ent->client->ps.groundEntityNum != ENTITYNUM_NONE )
01914 {
01915 ent->client->ps.forceHandExtend = HANDEXTEND_TAUNT;
01916 ent->client->ps.forceDodgeAnim = anim;
01917 ent->client->ps.forceHandExtendTime = level.time + BG_AnimLength(ent->localAnimIndex, (animNumber_t)anim);
01918 }
01919 if ( taunt != TAUNT_MEDITATE
01920 && taunt != TAUNT_BOW )
01921 {//no sound for meditate or bow
01922 G_AddEvent( ent, EV_TAUNT, taunt );
01923 }
01924 }
01925 }
01926 }
|
|
|
Definition at line 1246 of file g_active.c. References BOTH_STAND1, BOTH_STAND2, BOTH_STAND3, BOTH_STAND4, qboolean, qfalse, and qtrue. Referenced by G_CheckClientIdle().
01247 {//NOTE: does not check idles or special (cinematic) stands
01248 switch ( anim )
01249 {
01250 case BOTH_STAND1:
01251 case BOTH_STAND2:
01252 case BOTH_STAND3:
01253 case BOTH_STAND4:
01254 return qtrue;
01255 break;
01256 }
01257 return qfalse;
01258 }
|
|
|
Definition at line 516 of file g_active.c. References BG_PlayerTouchesItem(), gentity_s::client, entityShared_t::contents, CONTENTS_TRIGGER, ET_ITEM, ET_TELEPORT_TRIGGER, entityState_s::eType, g_entities, gentity_t, playerState_s::jumppad_ent, playerState_s::jumppad_frame, level, MAX_GENTITIES, entityShared_t::maxs, memset(), entityShared_t::mins, playerState_s::origin, playerState_s::pmove_framecount, gclient_s::ps, gentity_s::r, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, STAT_HEALTH, playerState_s::stats, SVF_BOT, entityShared_t::svFlags, TEAM_SPECTATOR, level_locals_t::time, gentity_s::touch, Touch_DoorTrigger(), trap_EntitiesInBox(), trap_EntityContact(), vec3_t, VectorAdd, and VectorSubtract. Referenced by ClientThink_real(), and SpectatorThink().
00516 {
00517 int i, num;
00518 int touch[MAX_GENTITIES];
00519 gentity_t *hit;
00520 trace_t trace;
00521 vec3_t mins, maxs;
00522 static vec3_t range = { 40, 40, 52 };
00523
00524 if ( !ent->client ) {
00525 return;
00526 }
00527
00528 // dead clients don't activate triggers!
00529 if ( ent->client->ps.stats[STAT_HEALTH] <= 0 ) {
00530 return;
00531 }
00532
00533 VectorSubtract( ent->client->ps.origin, range, mins );
00534 VectorAdd( ent->client->ps.origin, range, maxs );
00535
00536 num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES );
00537
00538 // can't use ent->r.absmin, because that has a one unit pad
00539 VectorAdd( ent->client->ps.origin, ent->r.mins, mins );
00540 VectorAdd( ent->client->ps.origin, ent->r.maxs, maxs );
00541
00542 for ( i=0 ; i<num ; i++ ) {
00543 hit = &g_entities[touch[i]];
00544
00545 if ( !hit->touch && !ent->touch ) {
00546 continue;
00547 }
00548 if ( !( hit->r.contents & CONTENTS_TRIGGER ) ) {
00549 continue;
00550 }
00551
00552 // ignore most entities if a spectator
00553 if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
00554 if ( hit->s.eType != ET_TELEPORT_TRIGGER &&
00555 // this is ugly but adding a new ET_? type will
00556 // most likely cause network incompatibilities
00557 hit->touch != Touch_DoorTrigger) {
00558 continue;
00559 }
00560 }
00561
00562 // use seperate code for determining if an item is picked up
00563 // so you don't have to actually contact its bounding box
00564 if ( hit->s.eType == ET_ITEM ) {
00565 if ( !BG_PlayerTouchesItem( &ent->client->ps, &hit->s, level.time ) ) {
00566 continue;
00567 }
00568 } else {
00569 if ( !trap_EntityContact( mins, maxs, hit ) ) {
00570 continue;
00571 }
00572 }
00573
00574 memset( &trace, 0, sizeof(trace) );
00575
00576 if ( hit->touch ) {
00577 hit->touch (hit, ent, &trace);
00578 }
00579
00580 if ( ( ent->r.svFlags & SVF_BOT ) && ( ent->touch ) ) {
00581 ent->touch( ent, hit, &trace );
00582 }
00583 }
00584
00585 // if we didn't touch a jump pad this pmove frame
00586 if ( ent->client->ps.jumppad_frame != ent->client->ps.pmove_framecount ) {
00587 ent->client->ps.jumppad_frame = 0;
00588 ent->client->ps.jumppad_ent = 0;
00589 }
00590 }
|
|
|
Definition at line 1199 of file g_active.c. References entityShared_t::broadcastClients, gentity_t, memset(), and gentity_s::r. Referenced by ClientThink_real().
01200 {
01201 // Clear all the broadcast bits for this client
01202 memset ( self->r.broadcastClients, 0, sizeof ( self->r.broadcastClients ) );
01203
01204 // The jedi master is broadcast to everyone in range
01205 G_UpdateJediMasterBroadcasts ( self );
01206
01207 // Anyone with force sight on should see this client
01208 G_UpdateForceSightBroadcasts ( self );
01209 }
|
|
|
|
Definition at line 799 of file NPC_AI_Jedi.c.
00800 {
00801 if ( self )
00802 {
00803 self->flags |= FL_NOTARGET;
00804 if ( self->client )
00805 {
00806 if ( !self->client->ps.powerups[PW_CLOAKED] )
00807 {//cloak
00808 self->client->ps.powerups[PW_CLOAKED] = Q3_INFINITE;
00809
00810 //FIXME: debounce attacks?
00811 //FIXME: temp sound
00812 G_Sound( self, CHAN_ITEM, G_SoundIndex("sound/chars/shadowtrooper/cloak.wav") );
00813 }
00814 }
00815 }
00816 }
|
|
|
Definition at line 818 of file NPC_AI_Jedi.c.
00819 {
00820 if ( self )
00821 {
00822 self->flags &= ~FL_NOTARGET;
00823 if ( self->client )
00824 {
00825 if ( self->client->ps.powerups[PW_CLOAKED] )
00826 {//Uncloak
00827 self->client->ps.powerups[PW_CLOAKED] = 0;
00828
00829 G_Sound( self, CHAN_ITEM, G_SoundIndex("sound/chars/shadowtrooper/decloak.wav") );
00830 }
00831 }
00832 }
00833 }
|
|
||||||||||||||||
|
Definition at line 1432 of file g_active.c. References gNPCstats_e::acceleration, gentity_s::client, gNPC_t::currentSpeed, gNPC_t::desiredSpeed, gentity_t, gentity_s::NPC, gNPC_t::stats, and gNPCstats_e::walkSpeed. Referenced by ClientThink_real().
01433 {
01434 if ( !ent->client || !ent->NPC )
01435 {
01436 return;
01437 }
01438
01439 if ( !ent->NPC->stats.acceleration )
01440 {//No acceleration means just start and stop
01441 ent->NPC->currentSpeed = ent->NPC->desiredSpeed;
01442 }
01443 //FIXME: in cinematics always accel/decel?
01444 else if ( ent->NPC->desiredSpeed <= ent->NPC->stats.walkSpeed )
01445 {//Only accelerate if at walkSpeeds
01446 if ( ent->NPC->desiredSpeed > ent->NPC->currentSpeed + ent->NPC->stats.acceleration )
01447 {
01448 //ent->client->ps.friction = 0;
01449 ent->NPC->currentSpeed += ent->NPC->stats.acceleration;
01450 }
01451 else if ( ent->NPC->desiredSpeed > ent->NPC->currentSpeed )
01452 {
01453 //ent->client->ps.friction = 0;
01454 ent->NPC->currentSpeed = ent->NPC->desiredSpeed;
01455 }
01456 else if ( fullWalkAcc && ent->NPC->desiredSpeed < ent->NPC->currentSpeed - ent->NPC->stats.acceleration )
01457 {//decelerate even when walking
01458 ent->NPC->currentSpeed -= ent->NPC->stats.acceleration;
01459 }
01460 else if ( ent->NPC->desiredSpeed < ent->NPC->currentSpeed )
01461 {//stop on a dime
01462 ent->NPC->currentSpeed = ent->NPC->desiredSpeed;
01463 }
01464 }
01465 else// if ( ent->NPC->desiredSpeed > ent->NPC->stats.walkSpeed )
01466 {//Only decelerate if at runSpeeds
01467 if ( fullRunAcc && ent->NPC->desiredSpeed > ent->NPC->currentSpeed + ent->NPC->stats.acceleration )
01468 {//Accelerate to runspeed
01469 //ent->client->ps.friction = 0;
01470 ent->NPC->currentSpeed += ent->NPC->stats.acceleration;
01471 }
01472 else if ( ent->NPC->desiredSpeed > ent->NPC->currentSpeed )
01473 {//accelerate instantly
01474 //ent->client->ps.friction = 0;
01475 ent->NPC->currentSpeed = ent->NPC->desiredSpeed;
01476 }
01477 else if ( fullRunAcc && ent->NPC->desiredSpeed < ent->NPC->currentSpeed - ent->NPC->stats.acceleration )
01478 {
01479 ent->NPC->currentSpeed -= ent->NPC->stats.acceleration;
01480 }
01481 else if ( ent->NPC->desiredSpeed < ent->NPC->currentSpeed )
01482 {
01483 ent->NPC->currentSpeed = ent->NPC->desiredSpeed;
01484 }
01485 }
01486 }
|
|
||||||||||||||||||||
|
|
|
|
Definition at line 36 of file g_active.c. References gentity_s::client, client, gclient_s::damage_armor, gclient_s::damage_blood, gclient_s::damage_from, gclient_s::damage_fromWorld, gclient_s::damage_knockback, playerState_s::damageCount, playerState_s::damageEvent, playerState_s::damagePitch, playerState_s::damageType, playerState_s::damageYaw, EF_DEAD, entityState_s::eFlags, EV_PAIN, FL_GODMODE, gentity_s::flags, G_AddEvent(), gclient_t, gentity_t, gentity_s::health, level, P_SetTwitchInfo(), gentity_s::pain_debounce_time, playerState_s::painTime, PITCH, PM_DEAD, playerState_s::pm_type, gclient_s::ps, qfalse, gentity_s::s, level_locals_t::time, vec3_t, vectoangles(), and YAW. Referenced by ClientEndFrame().
00036 {
00037 gclient_t *client;
00038 float count;
00039 vec3_t angles;
00040
00041 client = player->client;
00042 if ( client->ps.pm_type == PM_DEAD ) {
00043 return;
00044 }
00045
00046 // total points of damage shot at the player this frame
00047 count = client->damage_blood + client->damage_armor;
00048 if ( count == 0 ) {
00049 return; // didn't take any damage
00050 }
00051
00052 if ( count > 255 ) {
00053 count = 255;
00054 }
00055
00056 // send the information to the client
00057
00058 // world damage (falling, slime, etc) uses a special code
00059 // to make the blend blob centered instead of positional
00060 if ( client->damage_fromWorld ) {
00061 client->ps.damagePitch = 255;
00062 client->ps.damageYaw = 255;
00063
00064 client->damage_fromWorld = qfalse;
00065 } else {
00066 vectoangles( client->damage_from, angles );
00067 client->ps.damagePitch = angles[PITCH]/360.0 * 256;
00068 client->ps.damageYaw = angles[YAW]/360.0 * 256;
00069
00070 //cap them since we can't send negative values in here across the net
00071 if (client->ps.damagePitch < 0)
00072 {
00073 client->ps.damagePitch = 0;
00074 }
00075 if (client->ps.damageYaw < 0)
00076 {
00077 client->ps.damageYaw = 0;
00078 }
00079 }
00080
00081 // play an apropriate pain sound
00082 if ( (level.time > player->pain_debounce_time) && !(player->flags & FL_GODMODE) && !(player->s.eFlags & EF_DEAD) ) {
00083
00084 // don't do more than two pain sounds a second
00085 // nmckenzie: also don't make him loud and whiny if he's only getting nicked.
00086 if ( level.time - client->ps.painTime < 500 || count < 10) {
00087 return;
00088 }
00089 P_SetTwitchInfo(client);
00090 player->pain_debounce_time = level.time + 700;
00091
00092 G_AddEvent( player, EV_PAIN, player->health );
00093 client->ps.damageEvent++;
00094
00095 if (client->damage_armor && !client->damage_blood)
00096 {
00097 client->ps.damageType = 1; //pure shields
00098 }
00099 else if (client->damage_armor)
00100 {
00101 client->ps.damageType = 2; //shields and health
00102 }
00103 else
00104 {
00105 client->ps.damageType = 0; //pure health
00106 }
00107 }
00108
00109
00110 client->ps.damageCount = count;
00111
00112 //
00113 // clear totals
00114 //
00115 client->damage_blood = 0;
00116 client->damage_armor = 0;
00117 client->damage_knockback = 0;
00118 }
|
|
|
Definition at line 20 of file g_active.c. References client, gclient_t, level, playerState_s::painDirection, playerState_s::painTime, gclient_s::ps, and level_locals_t::time. Referenced by P_DamageFeedback().
|
|
|
Definition at line 129 of file g_active.c. References gclient_s::airOutTime, CHAN_VOICE, gentity_s::client, CONTENTS_LAVA, CONTENTS_SLIME, gentity_s::damage, DAMAGE_NO_ARMOR, EV_POWERUP_BATTLESUIT, G_AddEvent(), G_Damage(), G_Sound(), G_SoundIndex(), gentity_t, gentity_s::health, level, MOD_LAVA, MOD_SLIME, MOD_WATER, gclient_s::noclip, NULL, gentity_s::pain_debounce_time, playerState_s::powerups, gclient_s::ps, PW_BATTLESUIT, qboolean, rand(), level_locals_t::time, gentity_s::waterlevel, and gentity_s::watertype. Referenced by ClientEndFrame().
00129 {
00130 qboolean envirosuit;
00131 int waterlevel;
00132
00133 if ( ent->client->noclip ) {
00134 ent->client->airOutTime = level.time + 12000; // don't need air
00135 return;
00136 }
00137
00138 waterlevel = ent->waterlevel;
00139
00140 envirosuit = ent->client->ps.powerups[PW_BATTLESUIT] > level.time;
00141
00142 //
00143 // check for drowning
00144 //
00145 if ( waterlevel == 3 ) {
00146 // envirosuit give air
00147 if ( envirosuit ) {
00148 ent->client->airOutTime = level.time + 10000;
00149 }
00150
00151 // if out of air, start drowning
00152 if ( ent->client->airOutTime < level.time) {
00153 // drown!
00154 ent->client->airOutTime += 1000;
00155 if ( ent->health > 0 ) {
00156 // take more damage the longer underwater
00157 ent->damage += 2;
00158 if (ent->damage > 15)
00159 ent->damage = 15;
00160
00161 // play a gurp sound instead of a normal pain sound
00162 if (ent->health <= ent->damage) {
00163 G_Sound(ent, CHAN_VOICE, G_SoundIndex(/*"*drown.wav"*/"sound/player/gurp1.wav"));
00164 } else if (rand()&1) {
00165 G_Sound(ent, CHAN_VOICE, G_SoundIndex("sound/player/gurp1.wav"));
00166 } else {
00167 G_Sound(ent, CHAN_VOICE, G_SoundIndex("sound/player/gurp2.wav"));
00168 }
00169
00170 // don't play a normal pain sound
00171 ent->pain_debounce_time = level.time + 200;
00172
00173 G_Damage (ent, NULL, NULL, NULL, NULL,
00174 ent->damage, DAMAGE_NO_ARMOR, MOD_WATER);
00175 }
00176 }
00177 } else {
00178 ent->client->airOutTime = level.time + 12000;
00179 ent->damage = 2;
00180 }
00181
00182 //
00183 // check for sizzle damage (move to pmove?)
00184 //
00185 if (waterlevel &&
00186 (ent->watertype&(CONTENTS_LAVA|CONTENTS_SLIME)) ) {
00187 if (ent->health > 0
00188 && ent->pain_debounce_time <= level.time ) {
00189
00190 if ( envirosuit ) {
00191 G_AddEvent( ent, EV_POWERUP_BATTLESUIT, 0 );
00192 } else {
00193 if (ent->watertype & CONTENTS_LAVA) {
00194 G_Damage (ent, NULL, NULL, NULL, NULL,
00195 30*waterlevel, 0, MOD_LAVA);
00196 }
00197
00198 if (ent->watertype & CONTENTS_SLIME) {
00199 G_Damage (ent, NULL, NULL, NULL, NULL,
00200 10*waterlevel, 0, MOD_SLIME);
00201 }
00202 }
00203 }
00204 }
00205 }
|
|
|
Definition at line 1193 of file bg_panimate.c. References LS_R_T2B, LS_R_TL2BR, qboolean, qfalse, and qtrue. Referenced by BG_SaberInReturn(), BG_SaberInTransitionAny(), ClientThink_real(), PM_CheckPullAttack(), and PM_WeaponLightsaber().
01194 {
01195 if ( move >= LS_R_TL2BR && move <= LS_R_T2B )
01196 {
01197 return qtrue;
01198 }
01199 return qfalse;
01200 }
|
|
|
Definition at line 1184 of file bg_panimate.c.
01185 {
01186 if ( move >= LS_S_TL2BR && move <= LS_S_T2B )
01187 {
01188 return qtrue;
01189 }
01190 return qfalse;
01191 }
|
|
|
Definition at line 1610 of file bg_panimate.c.
01611 {
01612 if ( move >= LS_T1_BR__R && move <= LS_T1_BL__L )
01613 {
01614 return qtrue;
01615 }
01616 return qfalse;
01617 }
|
|
||||||||||||||||
|
Definition at line 6679 of file w_saber.c. References BLOCKED_BOUNCE_MOVE, gentity_s::client, saberInfo_t::disarmBonus, gentity_t, gclient_s::lastSaberBase_Always, gclient_s::lastSaberStorageTime, level, LS_V1_BL, saberInfo_t::model, gclient_s::olderIsValid, gclient_s::olderSaberBase, gclient_s::ps, Q_irand(), qboolean, qfalse, qtrue, gclient_s::saber, playerState_s::saberBlocked, playerState_s::saberHolstered, SABERINVALID, saberKnockOutOfHand(), playerState_s::saberMove, level_locals_t::time, vec3_t, VectorClear, VectorNormalize(), VectorScale, and VectorSubtract. Referenced by ClientThink_real().
06680 {
06681 vec3_t dif;
06682 float totalDistance = 1;
06683 float distScale = 6.5f;
06684 qboolean validMomentum = qtrue;
06685 int disarmChance = 1;
06686
06687 if (SABERINVALID)
06688 {
06689 return qfalse;
06690 }
06691
06692 VectorClear(dif);
06693
06694 if (!other->client->olderIsValid || (level.time - other->client->lastSaberStorageTime) >= 200)
06695 { //see if the spots are valid
06696 validMomentum = qfalse;
06697 }
06698
06699 if (validMomentum)
06700 {
06701 //Get the difference
06702 VectorSubtract(other->client->lastSaberBase_Always, other->client->olderSaberBase, dif);
06703 totalDistance = VectorNormalize(dif);
06704
06705 if (!totalDistance)
06706 { //fine, try our own
06707 if (!saberOwner->client->olderIsValid || (level.time - saberOwner->client->lastSaberStorageTime) >= 200)
06708 {
06709 validMomentum = qfalse;
06710 }
06711
06712 if (validMomentum)
06713 {
06714 VectorSubtract(saberOwner->client->lastSaberBase_Always, saberOwner->client->olderSaberBase, dif);
06715 totalDistance = VectorNormalize(dif);
06716 }
06717 }
06718
06719 if (validMomentum)
06720 {
06721 if (!totalDistance)
06722 { //try the difference between the two blades
06723 VectorSubtract(saberOwner->client->lastSaberBase_Always, other->client->lastSaberBase_Always, dif);
06724 totalDistance = VectorNormalize(dif);
06725 }
06726
06727 if (totalDistance)
06728 { //if we still have no difference somehow, just let it fall to the ground when the time comes.
06729 if (totalDistance < 20)
06730 {
06731 totalDistance = 20;
06732 }
06733 VectorScale(dif, totalDistance*distScale, dif);
06734 }
06735 }
06736 }
06737
06738 saberOwner->client->ps.saberMove = LS_V1_BL; //rwwFIXMEFIXME: Ideally check which lock it was exactly and use the proper anim (same goes for the attacker)
06739 saberOwner->client->ps.saberBlocked = BLOCKED_BOUNCE_MOVE;
06740
06741 if ( other && other->client )
06742 {
06743 disarmChance += other->client->saber[0].disarmBonus;
06744 if ( other->client->saber[1].model
06745 && other->client->saber[1].model[0]
06746 && !other->client->ps.saberHolstered )
06747 {
06748 other->client->saber[1].disarmBonus;
06749 }
06750 }
06751 if ( Q_irand( 0, disarmChance ) )
06752 {
06753 return saberKnockOutOfHand(saberent, saberOwner, dif);
06754 }
06755 else
06756 {
06757 return qfalse;
06758 }
06759 }
|
|
|
Definition at line 1059 of file g_active.c. References BG_PlayerStateToEntityState(), playerState_s::clientNum, EF_PLAYER_EVENT, entityState_s::eFlags, playerState_s::entityEventSequence, ET_EVENTS, entityState_s::eType, playerState_s::events, playerState_s::eventSequence, playerState_s::externalEvent, G_TempEntity(), gentity_t, MAX_PS_EVENTS, entityState_s::number, playerState_s::origin, entityState_s::otherEntityNum, playerState_t, qtrue, gentity_s::r, gentity_s::s, entityShared_t::singleClient, SVF_NOTSINGLECLIENT, and entityShared_t::svFlags. Referenced by ClientEndFrame(), and ClientThink_real().
01059 {
01060 gentity_t *t;
01061 int event, seq;
01062 int extEvent, number;
01063
01064 // if there are still events pending
01065 if ( ps->entityEventSequence < ps->eventSequence ) {
01066 // create a temporary entity for this event which is sent to everyone
01067 // except the client who generated the event
01068 seq = ps->entityEventSequence & (MAX_PS_EVENTS-1);
01069 event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 );
01070 // set external event to zero before calling BG_PlayerStateToEntityState
01071 extEvent = ps->externalEvent;
01072 ps->externalEvent = 0;
01073 // create temporary entity for event
01074 t = G_TempEntity( ps->origin, event );
01075 number = t->s.number;
01076 BG_PlayerStateToEntityState( ps, &t->s, qtrue );
01077 t->s.number = number;
01078 t->s.eType = ET_EVENTS + event;
01079 t->s.eFlags |= EF_PLAYER_EVENT;
01080 t->s.otherEntityNum = ps->clientNum;
01081 // send to everyone except the client who generated the event
01082 t->r.svFlags |= SVF_NOTSINGLECLIENT;
01083 t->r.singleClient = ps->clientNum;
01084 // set back external event
01085 ps->externalEvent = extEvent;
01086 }
01087 }
|
|
|
Definition at line 3710 of file g_active.c. References gentity_s::client, ClientBegin(), level_locals_t::clients, CON_CONNECTED, clientPersistant_t::connected, playerState_s::eFlags, ET_NPC, entityState_s::eType, level_locals_t::follow1, level_locals_t::follow2, gclient_t, gentity_t, level, gclient_s::pers, playerState_s::pm_flags, PMF_FOLLOW, PMF_SCOREBOARD, gclient_s::ps, qtrue, gentity_s::s, gclient_s::sess, clientSession_t::sessionTeam, SPECTATOR_FOLLOW, SPECTATOR_FREE, SPECTATOR_SCOREBOARD, clientSession_t::spectatorClient, clientSession_t::spectatorState, and TEAM_SPECTATOR. Referenced by ClientEndFrame().
03710 {
03711 gclient_t *cl;
03712
03713 if (ent->s.eType == ET_NPC)
03714 {
03715 assert(0);
03716 return;
03717 }
03718
03719 // if we are doing a chase cam or a remote view, grab the latest info
03720 if ( ent->client->sess.spectatorState == SPECTATOR_FOLLOW ) {
03721 int clientNum;//, flags;
03722
03723 clientNum = ent->client->sess.spectatorClient;
03724
03725 // team follow1 and team follow2 go to whatever clients are playing
03726 if ( clientNum == -1 ) {
03727 clientNum = level.follow1;
03728 } else if ( clientNum == -2 ) {
03729 clientNum = level.follow2;
03730 }
03731 if ( clientNum >= 0 ) {
03732 cl = &level.clients[ clientNum ];
03733 if ( cl->pers.connected == CON_CONNECTED && cl->sess.sessionTeam != TEAM_SPECTATOR ) {
03734 //flags = (cl->mGameFlags & ~(PSG_VOTED | PSG_TEAMVOTED)) | (ent->client->mGameFlags & (PSG_VOTED | PSG_TEAMVOTED));
03735 //ent->client->mGameFlags = flags;
03736 ent->client->ps.eFlags = cl->ps.eFlags;
03737 ent->client->ps = cl->ps;
03738 ent->client->ps.pm_flags |= PMF_FOLLOW;
03739 return;
03740 } else {
03741 // drop them to free spectators unless they are dedicated camera followers
03742 if ( ent->client->sess.spectatorClient >= 0 ) {
03743 ent->client->sess.spectatorState = SPECTATOR_FREE;
03744 ClientBegin( ent->client - level.clients, qtrue );
03745 }
03746 }
03747 }
03748 }
03749
03750 if ( ent->client->sess.spectatorState == SPECTATOR_SCOREBOARD ) {
03751 ent->client->ps.pm_flags |= PMF_SCOREBOARD;
03752 } else {
03753 ent->client->ps.pm_flags &= ~PMF_SCOREBOARD;
03754 }
03755 }
|
|
||||||||||||
|
||||||||||||||||||||
|
Definition at line 353 of file bg_saberLoad.c.
00354 {
00355 qboolean saber1Active;
00356 qboolean saber2Active;
00357 qboolean dualSabers = qfalse;
00358
00359 if ( saber2 && saber2->model && saber2->model[0] )
00360 {
00361 dualSabers = qtrue;
00362 }
00363
00364 if ( dualSabers )
00365 {//dual
00366 if ( saberHolstered > 1 )
00367 {
00368 saber1Active = saber2Active = qfalse;
00369 }
00370 else if ( saberHolstered > 0 )
00371 {
00372 saber1Active = qtrue;
00373 saber2Active = qfalse;
00374 }
00375 else
00376 {
00377 saber1Active = saber2Active = qtrue;
00378 }
00379 }
00380 else
00381 {
00382 saber2Active = qfalse;
00383 if ( !saber1
00384 || !saber1->model
00385 || !saber1->model[0] )
00386 {
00387 saber1Active = qfalse;
00388 }
00389 else if ( saber1->numBlades > 1 )
00390 {//staff
00391 if ( saberHolstered > 1 )
00392 {
00393 saber1Active = qfalse;
00394 }
00395 else
00396 {
00397 saber1Active = qtrue;
00398 }
00399 }
00400 else
00401 {//single
00402 if ( saberHolstered )
00403 {
00404 saber1Active = qfalse;
00405 }
00406 else
00407 {
00408 saber1Active = qtrue;
00409 }
00410 }
00411 }
00412
00413 if ( saber1Active
00414 && saber1
00415 && saber1->model
00416 && saber1->model[0]
00417 && saber1->stylesForbidden )
00418 {
00419 if ( (saber1->stylesForbidden&(1<<saberAnimLevel)) )
00420 {//not a valid style for first saber!
00421 return qfalse;
00422 }
00423 }
00424 if ( dualSabers
00425 && saber2Active
00426 && saber2
00427 && saber2->model
00428 && saber2->model[0] )
00429 {
00430 if ( saber2->stylesForbidden )
00431 {//check second saber, too
00432 if ( (saber2->stylesForbidden&(1<<saberAnimLevel)) )
00433 {//not a valid style for second saber!
00434 return qfalse;
00435 }
00436 }
00437 //now: if using dual sabers, only dual and tavion (if given with this saber) are allowed
00438 if ( saberAnimLevel != SS_DUAL )
00439 {//dual is okay
00440 if ( saberAnimLevel != SS_TAVION )
00441 {//tavion might be okay, all others are not
00442 return qfalse;
00443 }
00444 else
00445 {//see if "tavion" style is okay
00446 if ( saber1Active
00447 && saber1
00448 && saber1->model
00449 && saber1->model[0]
00450 && (saber1->stylesLearned&(1<<SS_TAVION)) )
00451 {//okay to use tavion style, first saber gave it to us
00452 }
00453 else if ( (saber2->stylesLearned&(1<<SS_TAVION)) )
00454 {//okay to use tavion style, second saber gave it to us
00455 }
00456 else
00457 {//tavion style is not allowed because neither of the sabers we're using gave it to us (I know, doesn't quite make sense, but...)
00458 return qfalse;
00459 }
00460 }
00461 }
00462 }
00463 return qtrue;
00464 }
|
|
|
Definition at line 18 of file g_active.c. Referenced by ClientThink_real(). |