/* =================== CG_TouchItem =================== */ static void CG_TouchItem( centity_t *cent ) { gitem_t *item; if ( !cg_predictItems.integer ) { return; } if ( !BG_PlayerTouchesItem( &cg.cur_lc->predictedPlayerState, ¢->currentState, cg.time ) ) { return; } // never pick an item up twice in a prediction if ( cent->miscTime == cg.time ) { return; } if ( !BG_CanItemBeGrabbed( cgs.gametype, ¢->currentState, &cg.cur_lc->predictedPlayerState ) ) { return; // can't hold it } item = BG_ItemForItemNum( cent->currentState.modelindex ); // Special case for flags. // We don't predict touching our own flag #ifdef MISSIONPACK if( cgs.gametype == GT_1FCTF ) { if( item->giType == IT_TEAM && item->giTag != PW_NEUTRALFLAG ) { return; } } #endif if( cgs.gametype == GT_CTF ) { if (cg.cur_lc->predictedPlayerState.persistant[PERS_TEAM] == TEAM_RED && item->giType == IT_TEAM && item->giTag == PW_REDFLAG) return; if (cg.cur_lc->predictedPlayerState.persistant[PERS_TEAM] == TEAM_BLUE && item->giType == IT_TEAM && item->giTag == PW_BLUEFLAG) return; } // grab it BG_AddPredictableEventToPlayerstate( EV_ITEM_PICKUP, cent->currentState.modelindex , &cg.cur_lc->predictedPlayerState); // remove it from the frame so it won't be drawn cent->currentState.eFlags |= EF_NODRAW; // don't touch it again this prediction cent->miscTime = cg.time; // if it's a weapon, give them some predicted ammo so the autoswitch will work if ( item->giType == IT_WEAPON ) { cg.cur_lc->predictedPlayerState.stats[ STAT_WEAPONS ] |= 1 << item->giTag; if ( !cg.cur_lc->predictedPlayerState.ammo[ item->giTag ] ) { cg.cur_lc->predictedPlayerState.ammo[ item->giTag ] = 1; } } }
/* ============ G_TouchTriggers Find all trigger entities that ent's current position touches. Spectators will only interact with teleporters. ============ */ void G_TouchTriggers(gentity_t *ent) { int i, num, triggerMultiples, pushTriggers; int touch[MAX_GENTITIES]; gentity_t *hit; trace_t trace; vec3_t mins, maxs; static vec3_t range = { 40, 40, 52 }; if (!ent->client) { return; } // Arnout: reset the pointer that keeps track of trigger_objective_info tracking ent->client->touchingTOI = NULL; // dead clients don't activate triggers! if (ent->client->ps.stats[STAT_HEALTH] <= 0) { return; } VectorSubtract(ent->client->ps.origin, range, mins); VectorAdd(ent->client->ps.origin, range, maxs); num = trap_EntitiesInBox(mins, maxs, touch, MAX_GENTITIES); // can't use ent->absmin, because that has a one unit pad VectorAdd(ent->client->ps.origin, ent->r.mins, mins); VectorAdd(ent->client->ps.origin, ent->r.maxs, maxs); triggerMultiples = 0; pushTriggers = 0; for (i = 0 ; i < num ; ++i) { hit = &g_entities[touch[i]]; if (!hit->touch && !ent->touch) { continue; } if (!(hit->r.contents & CONTENTS_TRIGGER)) { continue; } // Arnout: invisible entities can't be touched // Gordon: radiant tabs arnout! ;) if (hit->entstate == STATE_INVISIBLE || hit->entstate == STATE_UNDERCONSTRUCTION) { continue; } // ignore most entities if a spectator if (ent->client->sess.sessionTeam == TEAM_SPECTATOR && hit->s.eType != ET_TELEPORT_TRIGGER) { continue; } // use seperate code for determining if an item is picked up // so you don't have to actually contact its bounding box if (hit->s.eType == ET_ITEM) { if (!BG_PlayerTouchesItem(&ent->client->ps, &hit->s, level.time)) { continue; } } else { // MrE: always use capsule for player if (!trap_EntityContactCapsule(mins, maxs, hit)) { continue; } } // suburb, check which triggers we hit if (hit->s.eType == ET_TRIGGER_MULTIPLE) { triggerMultiples++; } if (hit->s.eType == ET_PUSH_TRIGGER) { pushTriggers++; } memset(&trace, 0, sizeof (trace)); if (hit->touch) { hit->touch(hit, ent, &trace); } } if (triggerMultiples == 0) { ent->client->pers.isTouchingTrigger = qfalse; } else { ent->client->pers.isTouchingTrigger = qtrue; } if (pushTriggers == 0) { ent->client->pers.isTouchingJumppad = qfalse; } else { ent->client->pers.isTouchingJumppad = qtrue; } }
/* ============ G_TouchTriggers Find all trigger entities that ent's current position touches. Spectators will only interact with teleporters (and door triggers for spectators) ============ */ void G_TouchTriggers(gentity_t * ent) { int i, num; int touch[MAX_GENTITIES]; gentity_t *hit; trace_t trace; vec3_t mins, maxs; static vec3_t range = { 40, 40, 52 }; if (!ent->client) { return; } // dead clients don't activate triggers! if (ent->client->ps.stats[STAT_HEALTH] <= 0) { return; } VectorSubtract(ent->client->ps.origin, range, mins); VectorAdd(ent->client->ps.origin, range, maxs); num = trap_EntitiesInBox(mins, maxs, touch, MAX_GENTITIES); // can't use ent->absmin, because that has a one unit pad VectorAdd(ent->client->ps.origin, ent->r.mins, mins); VectorAdd(ent->client->ps.origin, ent->r.maxs, maxs); for (i = 0; i < num; i++) { //Blaze: Print out some debug info if (&g_entities[touch[i]] == NULL) G_Printf("Ln 0429\n"); hit = &g_entities[touch[i]]; if (!hit->touch && !ent->touch) { continue; } if (!(hit->r.contents & CONTENTS_TRIGGER)) { continue; } // ignore most entities if a spectator if (ent->client->sess.sessionTeam == TEAM_SPECTATOR) { if (hit->s.eType != ET_TELEPORT_TRIGGER) { //&& // this is ugly but adding a new ET_? type will // most likely cause network incompatibilities // NiceAss: changed Touch_DoorTrigger to Touch_DoorTriggerSpectator // hit->touch != Touch_DoorTriggerSpectator) { continue; } } // use seperate code for determining if an item is picked up // so you don't have to actually contact its bounding box if (hit->s.eType == ET_ITEM) { if (!BG_PlayerTouchesItem(&ent->client->ps, &hit->s, level.time)) { continue; } } else { if (!trap_EntityContact(mins, maxs, hit)) { continue; } } memset(&trace, 0, sizeof(trace)); if (hit->touch) { hit->touch(hit, ent, &trace); } if ((ent->r.svFlags & SVF_BOT) && (ent->touch)) { ent->touch(ent, hit, &trace); } } // if we didn't touch a jump pad this pmove frame if (ent->client->ps.jumppad_frame != ent->client->ps.pmove_framecount) { ent->client->ps.jumppad_frame = 0; ent->client->ps.jumppad_ent = 0; } if (ent->client->openDoor == 2) { ent->client->openDoor = qfalse; ent->client->openDoorTime = 0; } }
/* ============ G_TouchTriggers Find all trigger entities that ent's current position touches. Spectators will only interact with teleporters. ============ */ void G_TouchTriggers( gentity_t *ent ) { int i, num; int touch[MAX_GENTITIES]; gentity_t *hit; trace_t trace; vec3_t mins, maxs; static vec3_t range = { 40, 40, 52 }; if ( !ent->client ) { return; } // dead clients don't activate triggers! if ( ent->client->ps.stats[STAT_HEALTH] <= 0 ) { return; } VectorSubtract( ent->client->ps.origin, range, mins ); VectorAdd( ent->client->ps.origin, range, maxs ); num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES ); // can't use ent->absmin, because that has a one unit pad VectorAdd( ent->client->ps.origin, ent->r.mins, mins ); VectorAdd( ent->client->ps.origin, ent->r.maxs, maxs ); for ( i = 0 ; i < num ; i++ ) { hit = &g_entities[touch[i]]; if ( !hit->touch && !ent->touch ) { continue; } if ( !( hit->r.contents & CONTENTS_TRIGGER ) ) { continue; } // ignore most entities if a spectator if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) { if ( hit->s.eType != ET_TELEPORT_TRIGGER ) { continue; } } // use seperate code for determining if an item is picked up // so you don't have to actually contact its bounding box if ( hit->s.eType == ET_ITEM ) { if ( !BG_PlayerTouchesItem( &ent->client->ps, &hit->s, level.time ) ) { continue; } } else { // MrE: always use capsule for player //if ( !trap_EntityContactCapsule( mins, maxs, hit ) ) { if ( !trap_EntityContact( mins, maxs, hit ) ) { continue; } } memset( &trace, 0, sizeof( trace ) ); if ( hit->touch ) { hit->touch( hit, ent, &trace ); } if ( ( ent->r.svFlags & SVF_BOT ) && ( ent->touch ) ) { ent->touch( ent, hit, &trace ); } } }
/* ============ G_TouchTriggers Find all trigger entities that ent's current position touches. Spectators will only interact with teleporters. ============ */ void G_TouchTriggers( gentity_t *ent ) { int num; int touch[MAX_GENTITIES]; vec3_t mins; vec3_t maxs; static vec3_t range = { 20, 20, 40 }; if ( !ent->client ) { return; } // dead clients don't activate triggers! if ( G_IsClientDead ( ent->client ) ) { return; } VectorSubtract( ent->client->ps.origin, range, mins ); VectorAdd( ent->client->ps.origin, range, maxs ); num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES ); // can't use ent->r.absmin, because that has a one unit pad VectorAdd( ent->client->ps.origin, ent->r.mins, mins ); VectorAdd( ent->client->ps.origin, ent->r.maxs, maxs ); // Reset the players can use flag ent->client->ps.pm_flags &= ~(PMF_CAN_USE); ent->s.modelindex = 0; for ( int i=0 ; i<num ; i++ ) { gentity_t *hit = &g_entities[touch[i]]; // pmove would have to have detected siamese twins first if ( hit->client && hit != ent && !hit->client->siameseTwin && (ent->client->ps.pm_flags & PMF_SIAMESETWINS) ) { // See if this client has a twin if ( !G_IsClientSiameseTwin ( ent, hit ) ) { continue; } // About time these twins were separated!! ent->client->siameseTwin = hit; hit->client->siameseTwin = ent; } if ( !( hit->r.contents & CONTENTS_TRIGGER ) ) { continue; } if ( !hit->touch && !ent->touch ) { continue; } // ignore most entities if a spectator if ( G_IsClientSpectating ( ent->client ) ) { if ( hit->s.eType != ET_TELEPORT_TRIGGER && // this is ugly but adding a new ET_? type will // most likely cause network incompatibilities hit->touch != Touch_DoorTrigger) { continue; } } // use seperate code for determining if an item is picked up // so you don't have to actually contact its bounding box if ( hit->s.eType == ET_ITEM ) { if ( !BG_PlayerTouchesItem( &ent->client->ps, &hit->s, level.time ) ) { continue; } } else { if ( !trap_EntityContact( mins, maxs, hit ) ) { continue; } } trace_t trace; memset( &trace, 0, sizeof(trace) ); if ( hit->touch ) { hit->touch (hit, ent, &trace); } if ( ( ent->r.svFlags & SVF_BOT ) && ( ent->touch ) ) { ent->touch( ent, hit, &trace ); } } // Dont bother looking for twins again unless pmove says so ent->client->ps.pm_flags &= (~PMF_SIAMESETWINS); }