/* =================== 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; } } }
/* =============== Touch_Item =============== */ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) { int respawn; qboolean predict; if (!other->client) return; if (other->health < 1) return; // dead people can't pickup // the same pickup rules are used for client side and server side if ( !BG_CanItemBeGrabbed( g_gametype.integer, &ent->s, &other->client->ps ) ) { return; } G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname ); predict = other->client->pers.predictItemPickup; // call the item-specific pickup function switch( ent->item->giType ) { case IT_WEAPON: respawn = Pickup_Weapon(ent, other); // predict = qfalse; break; case IT_AMMO: respawn = Pickup_Ammo(ent, other); // predict = qfalse; break; case IT_ARMOR: respawn = Pickup_Armor(ent, other); break; case IT_HEALTH: respawn = Pickup_Health(ent, other); break; case IT_POWERUP: respawn = Pickup_Powerup(ent, other); predict = qfalse; break; #ifdef MISSIONPACK case IT_PERSISTANT_POWERUP: respawn = Pickup_PersistantPowerup(ent, other); break; #endif case IT_TEAM: respawn = Pickup_Team(ent, other); break; case IT_HOLDABLE: respawn = Pickup_Holdable(ent, other); break; default: return; } if ( !respawn ) { return; } // play the normal pickup sound if (predict) { G_AddPredictableEvent( other, EV_ITEM_PICKUP, ent->s.modelindex ); } else { G_AddEvent( other, EV_ITEM_PICKUP, ent->s.modelindex ); } // powerup pickups are global broadcasts if ( ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM) { // if we want the global sound to play if (!ent->speed) { gentity_t *te; te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP ); te->s.eventParm = ent->s.modelindex; te->r.svFlags |= SVF_BROADCAST; } else { gentity_t *te; te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP ); te->s.eventParm = ent->s.modelindex; // only send this temp entity to a single client te->r.svFlags |= SVF_SINGLECLIENT; te->r.singleClient = other->s.number; } } // fire item targets G_UseTargets (ent, other); // wait of -1 will not respawn if ( ent->wait == -1 ) { ent->r.svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; ent->unlinkAfterEvent = qtrue; return; } // non zero wait overrides respawn time if ( ent->wait ) { respawn = ent->wait; } // random can be used to vary the respawn time if ( ent->random ) { respawn += crandom() * ent->random; if ( respawn < 1 ) { respawn = 1; } } // dropped items will not respawn if ( ent->flags & FL_DROPPED_ITEM ) { ent->freeAfterEvent = qtrue; } // picked up items still stay around, they just don't // draw anything. This allows respawnable items // to be placed on movers. ent->r.svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; // ZOID // A negative respawn times means to never respawn this item (but don't // delete it). This is used by items that are respawned by third party // events such as ctf flags if ( respawn <= 0 ) { ent->nextthink = 0; ent->think = 0; } else { ent->nextthink = level.time + respawn * 1000; ent->think = RespawnItem; } trap_LinkEntity( ent ); }
/* =============== Touch_Item =============== */ void Touch_Item( gentity_t *ent, gentity_t *other, trace_t *trace ) { int respawn; int makenoise = EV_ITEM_PICKUP; // only activated items can be picked up if ( !ent->active ) { return; } else { // need to set active to false if player is maxed out ent->active = qfalse; } if ( !other->client ) { return; } if ( other->health < 1 ) { return; // dead people can't pickup } // the same pickup rules are used for client side and server side if ( !BG_CanItemBeGrabbed( &ent->s, &other->client->ps ) ) { return; } G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname ); // call the item-specific pickup function switch ( ent->item->giType ) { case IT_WEAPON: respawn = Pickup_Weapon( ent, other ); break; case IT_AMMO: respawn = Pickup_Ammo( ent, other ); break; case IT_ARMOR: respawn = Pickup_Armor( ent, other ); break; case IT_HEALTH: respawn = Pickup_Health( ent, other ); break; case IT_POWERUP: respawn = Pickup_Powerup( ent, other ); break; case IT_TEAM: respawn = Pickup_Team( ent, other ); break; case IT_HOLDABLE: respawn = Pickup_Holdable( ent, other ); break; case IT_KEY: respawn = Pickup_Key( ent, other ); break; case IT_TREASURE: respawn = Pickup_Treasure( ent, other ); break; case IT_CLIPBOARD: respawn = Pickup_Clipboard( ent, other ); // send the event to the client to request that the UI draw a popup // (specified by the configstring in ent->s.density). //G_AddEvent( other, EV_POPUP, ent->s.density); //if(ent->key) //G_AddEvent( other, EV_GIVEPAGE, ent->key ); break; default: return; } if ( !respawn ) { return; } // play sounds if ( ent->noise_index ) { // (SA) a sound was specified in the entity, so play that sound // (this G_AddEvent) and send the pickup as "EV_ITEM_PICKUP_QUIET" // so it doesn't make the default pickup sound when the pickup event is recieved makenoise = EV_ITEM_PICKUP_QUIET; G_AddEvent( other, EV_GENERAL_SOUND, ent->noise_index ); } // send the pickup event if ( other->client->pers.predictItemPickup ) { G_AddPredictableEvent( other, makenoise, ent->s.modelindex ); } else { G_AddEvent( other, makenoise, ent->s.modelindex ); } // powerup pickups are global broadcasts if ( ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM ) { // (SA) probably need to check for IT_KEY here too... (coop?) gentity_t *te; te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP ); te->s.eventParm = ent->s.modelindex; te->r.svFlags |= SVF_BROADCAST; // (SA) set if we want this to only go to the pickup client // te->r.svFlags |= SVF_SINGLECLIENT; // te->r.singleClient = other->s.number; } // fire item targets G_UseTargets( ent, other ); // wait of -1 will not respawn if ( ent->wait == -1 ) { ent->flags |= FL_NODRAW; //ent->r.svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; ent->unlinkAfterEvent = qtrue; return; } // wait of -2 will respawn but not be available for pickup anymore // (partial use things that leave a spent modle (ex. plate for turkey) if ( respawn == RESPAWN_PARTIAL_DONE ) { ent->s.density = ( 1 << 9 ); // (10 bits of data transmission for density) ent->active = qtrue; // re-activate trap_LinkEntity( ent ); return; } if ( respawn == RESPAWN_PARTIAL ) { // multi-stage health ent->s.density--; if ( ent->s.density ) { // still not completely used up ( (SA) this will change to == 0 and stage 1 will be a destroyable item (plate/etc.) ) ent->active = qtrue; // re-activate trap_LinkEntity( ent ); return; } } // non zero wait overrides respawn time if ( ent->wait ) { respawn = ent->wait; } // random can be used to vary the respawn time if ( ent->random ) { respawn += crandom() * ent->random; if ( respawn < 1 ) { respawn = 1; } } // dropped items will not respawn if ( ent->flags & FL_DROPPED_ITEM ) { ent->freeAfterEvent = qtrue; } // picked up items still stay around, they just don't // draw anything. This allows respawnable items // to be placed on movers. ent->r.svFlags |= SVF_NOCLIENT; ent->flags |= FL_NODRAW; //ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; // ZOID // A negative respawn times means to never respawn this item (but don't // delete it). This is used by items that are respawned by third party // events such as ctf flags if ( respawn <= 0 ) { ent->nextthink = 0; ent->think = 0; } else { ent->nextthink = level.time + respawn * 1000; ent->think = RespawnItem; } trap_LinkEntity( ent ); }
qboolean CanUseInfrontOf(gentity_t *ent) { gentity_t *target; trace_t trace; vec3_t src, dest, vf; if ( ent->s.number && ent->client->NPC_class == CLASS_ATST ) {//a player trying to get out of his ATST // GEntity_UseFunc( ent->activator, ent, ent ); return qfalse; } if (ent->client->ps.viewEntity != ent->s.number) { ent = &g_entities[ent->client->ps.viewEntity]; if ( !Q_stricmp( "misc_camera", ent->classname ) ) { // we are in a camera gentity_t *next = 0; if ( ent->target2 != NULL ) { next = G_Find( NULL, FOFS(targetname), ent->target2 ); } if ( next ) {//found another one if ( !Q_stricmp( "misc_camera", next->classname ) ) {//make sure it's another camera return qtrue; } } else //if ( ent->health > 0 ) {//I was the last (only?) one, clear out the viewentity return qfalse; } } } if ( !ent->client ) { return qfalse; } //FIXME: this does not match where the new accurate crosshair aims... //cg.refdef.vieworg, basically VectorCopy( ent->client->renderInfo.eyePoint, src ); AngleVectors( ent->client->ps.viewangles, vf, NULL, NULL ); //extend to find end of use trace VectorMA( src, USE_DISTANCE, vf, dest ); //Trace ahead to find a valid target gi.trace( &trace, src, vec3_origin, vec3_origin, dest, ent->s.number, MASK_OPAQUE|CONTENTS_SOLID|CONTENTS_TERRAIN|CONTENTS_BODY|CONTENTS_ITEM|CONTENTS_CORPSE , G2_NOCOLLIDE, 10); if ( trace.fraction == 1.0f || trace.entityNum >= ENTITYNUM_WORLD ) { return (CanUseInfrontOfPartOfLevel(ent)); } target = &g_entities[trace.entityNum]; if ( target && target->client && target->client->NPC_class == CLASS_VEHICLE ) { // Attempt to board this vehicle. return qtrue; } //Check for a use command if (ValidUseTarget( target )) { if ( target->s.eType == ET_ITEM ) {//item, see if we could actually pick it up if ( (target->spawnflags&128/*ITMSF_USEPICKUP*/) ) {//player has to be touching me and hit use to pick it up, so don't allow this if ( !G_BoundsOverlap( target->absmin, target->absmax, ent->absmin, ent->absmax ) ) {//not touching return qfalse; } } if ( !BG_CanItemBeGrabbed( &target->s, &ent->client->ps ) ) {//nope, so don't indicate that we can use it return qfalse; } } else if ( target->e_UseFunc == useF_misc_atst_use ) {//drivable AT-ST from JK2 if ( ent->client->ps.groundEntityNum != target->s.number ) {//must be standing on it to use it return qfalse; } } else if ( target->NPC!=NULL && target->health<=0 ) { return qfalse; } else if ( target->e_UseFunc == useF_eweb_use ) { if ( !eweb_can_be_used( target, ent, ent ) ) { return qfalse; } } return qtrue; } if ( target->client && target->client->ps.pm_type < PM_DEAD && target->NPC!=NULL && target->client->playerTeam && (target->client->playerTeam == ent->client->playerTeam || target->client->playerTeam == TEAM_NEUTRAL) && !(target->NPC->scriptFlags&SCF_NO_RESPONSE) && G_ValidActivateBehavior (target, BSET_USE)) { return qtrue; } if (CanUseInfrontOfPartOfLevel(ent)) { return qtrue; } return qfalse; }
void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) { int respawn = 0; if (!other->client) return; if (other->health < 1) return; // dead people can't pickup if ( other->client->ps.pm_time > 0 ) {//cant pick up when out of control return; } // NPCs can pick it up if ((ent->spawnflags & ITMSF_ALLOWNPC) && (!other->s.number)) { return; } // Players cannot pick it up if ( (ent->spawnflags & ITMSF_NOPLAYER) && (other->s.number) ) { return; } if ( ent->noDamageTeam != TEAM_FREE && other->client->playerTeam != ent->noDamageTeam ) {//only one team can pick it up return; } if ( !G_CanPickUpWeapons( other ) ) {//FIXME: some flag would be better //droids can't pick up items/weapons! return; } //FIXME: need to make them run toward a dropped weapon when fleeing without one? //FIXME: need to make them come out of flee mode when pick up their old weapon? if ( CheckItemCanBePickedUpByNPC( ent, other ) ) { if ( other->NPC && other->NPC->goalEntity && other->NPC->goalEntity == ent ) {//they were running to pick me up, they did, so clear goal other->NPC->goalEntity = NULL; other->NPC->squadState = SQUAD_STAND_AND_SHOOT; NPCInfo->tempBehavior = BS_DEFAULT; TIMER_Set(other, "flee", -1); } else { return; } } else if ( !(ent->spawnflags & ITMSF_ALLOWNPC) ) {// NPCs cannot pick it up if ( other->s.number != 0 ) {// Not the player? return; } } // the same pickup rules are used for client side and server side if ( !BG_CanItemBeGrabbed( &ent->s, &other->client->ps ) ) { return; } if ( other->client ) { if ( (other->client->ps.eFlags&EF_FORCE_GRIPPED) || (other->client->ps.eFlags&EF_FORCE_DRAINED) ) {//can't pick up anything while being gripped return; } if ( PM_InKnockDown( &other->client->ps ) && !PM_InGetUp( &other->client->ps ) ) {//can't pick up while in a knockdown return; } } if (!ent->item) { //not an item! gi.Printf( "Touch_Item: %s is not an item!\n", ent->classname); return; } if ( ent->item->giType == IT_WEAPON && ent->item->giTag == WP_SABER ) {//a saber if ( ent->delay > level.time ) {//just picked it up, don't pick up again right away return; } } if ( other->s.number < MAX_CLIENTS && (ent->spawnflags&ITMSF_USEPICKUP) ) {//only if player is holing use button if ( !(other->client->usercmd.buttons&BUTTON_USE) ) {//not holding use? return; } } qboolean bHadWeapon = qfalse; // call the item-specific pickup function switch( ent->item->giType ) { case IT_WEAPON: if ( other->NPC && other->s.weapon == WP_NONE ) {//Make them duck and sit here for a few seconds int pickUpTime = Q_irand( 1000, 3000 ); TIMER_Set( other, "duck", pickUpTime ); TIMER_Set( other, "roamTime", pickUpTime ); TIMER_Set( other, "stick", pickUpTime ); TIMER_Set( other, "verifyCP", pickUpTime ); TIMER_Set( other, "attackDelay", 600 ); respawn = 0; } if ( other->client->ps.stats[STAT_WEAPONS] & ( 1 << ent->item->giTag ) ) { bHadWeapon = qtrue; } respawn = Pickup_Weapon(ent, other); break; case IT_AMMO: respawn = Pickup_Ammo(ent, other); break; case IT_ARMOR: respawn = Pickup_Armor(ent, other); break; case IT_HEALTH: respawn = Pickup_Health(ent, other); break; case IT_HOLDABLE: respawn = Pickup_Holdable(ent, other); break; case IT_BATTERY: respawn = Pickup_Battery( ent, other ); break; case IT_HOLOCRON: respawn = Pickup_Holocron( ent, other ); break; default: return; } if ( !respawn ) { return; } // play the normal pickup sound if ( !other->s.number && g_timescale->value < 1.0f ) {//SIGH... with timescale on, you lose events left and right extern void CG_ItemPickup( int itemNum, qboolean bHadItem ); // but we're SP so we'll cheat cgi_S_StartSound( NULL, other->s.number, CHAN_AUTO, cgi_S_RegisterSound( ent->item->pickup_sound ) ); // show icon and name on status bar CG_ItemPickup( ent->s.modelindex, bHadWeapon ); } else { if ( bHadWeapon ) { G_AddEvent( other, EV_ITEM_PICKUP, -ent->s.modelindex ); } else { G_AddEvent( other, EV_ITEM_PICKUP, ent->s.modelindex ); } } // fire item targets G_UseTargets (ent, other); if ( ent->item->giType == IT_WEAPON && ent->item->giTag == WP_SABER ) {//a saber that was picked up if ( ent->count < 0 ) {//infinite supply ent->delay = level.time + 500; return; } ent->count--; if ( ent->count > 0 ) {//still have more to pick up ent->delay = level.time + 500; return; } } // wait of -1 will not respawn // if ( ent->wait == -1 ) { //why not just remove me? G_FreeEntity( ent ); /* //NOTE: used to do this: (for respawning?) ent->svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->contents = 0; ent->unlinkAfterEvent = qtrue; */ return; } }
/* =============== Touch_Item =============== */ void Touch_Item( gentity_t *ent, gentity_t *other, trace_t *trace ) { int respawn; int makenoise = EV_ITEM_PICKUP; // only activated items can be picked up if( !ent->active ) { return; } else { // need to set active to false if player is maxed out ent->active = qfalse; } if( !other->client ) { return; } if( other->health <= 0 ) { return; // dead people can't pickup } // the same pickup rules are used for client side and server side if ( !BG_CanItemBeGrabbed( &ent->s, &other->client->ps, other->client->sess.skill, other->client->sess.sessionTeam ) ) { return; } if(g_gamestate.integer == GS_PLAYING) { G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname ); } else { // OSP - Don't let them pickup winning stuff in warmup if(ent->item->giType != IT_WEAPON && ent->item->giType != IT_AMMO && ent->item->giType != IT_HEALTH) return; } // G_LogPrintf( "Calling item pickup function for %s\n", ent->item->classname ); // call the item-specific pickup function switch( ent->item->giType ) { case IT_WEAPON: respawn = Pickup_Weapon( ent, other ); break; case IT_HEALTH: respawn = Pickup_Health(ent, other); break; case IT_TEAM: respawn = Pickup_Team(ent, other); break; default: return; } // G_LogPrintf( "Finished pickup function\n" ); if ( !respawn ) { return; } // play sounds if( ent->noise_index ) { // (SA) a sound was specified in the entity, so play that sound // (this G_AddEvent) and send the pickup as "EV_ITEM_PICKUP_QUIET" // so it doesn't make the default pickup sound when the pickup event is recieved makenoise = EV_ITEM_PICKUP_QUIET; G_AddEvent( other, EV_GENERAL_SOUND, ent->noise_index ); } G_AddEvent( other, makenoise, ent->s.modelindex ); // powerup pickups are global broadcasts if ( ent->item->giType == IT_TEAM ) { gentity_t* te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP ); te->s.eventParm = ent->s.modelindex; te->r.svFlags |= SVF_BROADCAST; } // G_LogPrintf( "Firing item targets\n" ); // fire item targets G_UseTargets (ent, other); // dropped items will not respawn if ( ent->flags & FL_DROPPED_ITEM ) { ent->freeAfterEvent = qtrue; } // picked up items still stay around, they just don't // draw anything. This allows respawnable items // to be placed on movers. ent->r.svFlags |= SVF_NOCLIENT; ent->flags |= FL_NODRAW; ent->r.contents = 0; // ZOID // A negative respawn times means to never respawn this item (but don't // delete it). This is used by items that are respawned by third party // events such as ctf flags if ( respawn <= 0 ) { ent->nextthink = 0; ent->think = 0; } else { ent->nextthink = level.time + respawn * 1000; ent->think = RespawnItem; } trap_LinkEntity( ent ); }
void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) { int respawn = 0; if (!other->client) return; if (other->health < 1) return; // dead people can't pickup if ( other->client->ps.pm_time > 0 ) {//cant pick up when out of control return; } // Only monsters can pick it up if ((ent->spawnflags & ITMSF_MONSTER) && (other->client->playerTeam == TEAM_PLAYER)) { return; } // Only starfleet can pick it up if ((ent->spawnflags & ITMSF_TEAM) && (other->client->playerTeam != TEAM_PLAYER)) { return; } if ( other->client->NPC_class == CLASS_ATST || other->client->NPC_class == CLASS_GONK || other->client->NPC_class == CLASS_MARK1 || other->client->NPC_class == CLASS_MARK2 || other->client->NPC_class == CLASS_MOUSE || other->client->NPC_class == CLASS_PROBE || other->client->NPC_class == CLASS_PROTOCOL || other->client->NPC_class == CLASS_R2D2 || other->client->NPC_class == CLASS_R5D2 || other->client->NPC_class == CLASS_SEEKER || other->client->NPC_class == CLASS_REMOTE || other->client->NPC_class == CLASS_SENTRY ) {//FIXME: some flag would be better //droids can't pick up items/weapons! return; } //FIXME: need to make them run toward a dropped weapon when fleeing without one? //FIXME: need to make them come out of flee mode when pick up their old weapon? if ( CheckItemCanBePickedUpByNPC( ent, other ) ) { if ( other->NPC && other->NPC->goalEntity && other->NPC->goalEntity->enemy == ent ) {//they were running to pick me up, they did, so clear goal other->NPC->goalEntity = NULL; other->NPC->squadState = SQUAD_STAND_AND_SHOOT; } } else if (!(ent->spawnflags & ITMSF_TEAM) && !(ent->spawnflags & ITMSF_MONSTER)) {// Only player can pick it up if ( other->s.number != 0 ) // Not the player? { return; } } // the same pickup rules are used for client side and server side if ( !BG_CanItemBeGrabbed( &ent->s, &other->client->ps ) ) { return; } if ( other->client ) { if ( other->client->ps.eFlags&EF_FORCE_GRIPPED ) {//can't pick up anything while being gripped return; } if ( PM_InKnockDown( &other->client->ps ) && !PM_InGetUp( &other->client->ps ) ) {//can't pick up while in a knockdown return; } } if (!ent->item) { //not an item! gi.Printf( "Touch_Item: %s is not an item!\n", ent->classname); return; } qboolean bHadWeapon = qfalse; // call the item-specific pickup function switch( ent->item->giType ) { case IT_WEAPON: if ( other->NPC && other->s.weapon == WP_NONE ) {//Make them duck and sit here for a few seconds int pickUpTime = Q_irand( 1000, 3000 ); TIMER_Set( other, "duck", pickUpTime ); TIMER_Set( other, "roamTime", pickUpTime ); TIMER_Set( other, "stick", pickUpTime ); TIMER_Set( other, "verifyCP", pickUpTime ); TIMER_Set( other, "attackDelay", 600 ); respawn = 0; } if ( other->client->ps.stats[STAT_WEAPONS] & ( 1 << ent->item->giTag ) ) { bHadWeapon = qtrue; } respawn = Pickup_Weapon(ent, other); break; case IT_AMMO: respawn = Pickup_Ammo(ent, other); break; case IT_ARMOR: respawn = Pickup_Armor(ent, other); break; case IT_HEALTH: respawn = Pickup_Health(ent, other); break; case IT_HOLDABLE: respawn = Pickup_Holdable(ent, other); break; case IT_BATTERY: respawn = Pickup_Battery( ent, other ); break; case IT_HOLOCRON: respawn = Pickup_Holocron( ent, other ); break; default: return; } if ( !respawn ) { return; } // play the normal pickup sound if ( !other->s.number && g_timescale->value < 1.0f ) {//SIGH... with timescale on, you lose events left and right extern void CG_ItemPickup( int itemNum, qboolean bHadItem ); // but we're SP so we'll cheat cgi_S_StartSound( NULL, other->s.number, CHAN_AUTO, cgi_S_RegisterSound( ent->item->pickup_sound ) ); // show icon and name on status bar CG_ItemPickup( ent->s.modelindex, bHadWeapon ); } else { if ( bHadWeapon ) { G_AddEvent( other, EV_ITEM_PICKUP, -ent->s.modelindex ); } else { G_AddEvent( other, EV_ITEM_PICKUP, ent->s.modelindex ); } } // fire item targets G_UseTargets (ent, other); // wait of -1 will not respawn // if ( ent->wait == -1 ) { //why not just remove me? G_FreeEntity( ent ); /* //NOTE: used to do this: (for respawning?) ent->svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->contents = 0; ent->unlinkAfterEvent = qtrue; */ return; } }
/* =============== Touch_Item =============== */ void Touch_Item(gentity_t * ent, gentity_t * other, trace_t * trace) { int respawn; qboolean predict; int bandolierFactor; //Makro - some checks if (other == NULL || ent == NULL) return; if (!other->client) return; if (other->health < 1) return; // dead people can't pickup //Makro - even more bot hacks ! //this way, we can remove the item from the bot's library for a few seconds //so bots won't get stuck in a loop between 2 items if ((ent->r.svFlags & MASK_BOTHACK) == MASK_BOTHACK) { if (ent->nextthink < level.time) { ent->nextthink = level.time + 45 * 1000; } return; } // the same pickup rules are used for client side and server side if (!BG_CanItemBeGrabbed(g_gametype.integer, &ent->s, &other->client->ps)) return; predict = other->client->pers.predictItemPickup; if (other->client->ps.stats[STAT_HOLDABLE_ITEM] & (1 << HI_BANDOLIER)) bandolierFactor = 2; else bandolierFactor = 1; //Elder: should check if the item was recently thrown ... if it was, then //don't allow it to be picked up ... or something like that // call the item-specific pickup function switch (ent->item->giType) { case IT_WEAPON: switch (ent->item->giTag) { //Blaze: Check to see if we already have the weapon, //If not so check and see if we have less then full ammo, if so pick up gun //Elder's version: //Accumulators (e.g. knife, grenade): if you have the weap AND the max limit, leave //Pistols: if you have akimbos AND max clips, leave //Akimbos: shouldn't pick them up b/c they shouldn't be dropped //Specials: if you have more than/equal to limit (remember bando later), leave case WP_KNIFE: if (((other->client->ps.stats[STAT_WEAPONS] & (1 << WP_KNIFE)) == (1 << WP_KNIFE)) && (other->client->ps.ammo[ent->item->giTag] >= RQ3_KNIFE_MAXCLIP * bandolierFactor)) return; break; case WP_GRENADE: if (((other->client->ps.stats[STAT_WEAPONS] & (1 << WP_GRENADE)) == (1 << WP_GRENADE)) && (other->client->ps.ammo[ent->item->giTag] >= RQ3_GRENADE_MAXCLIP * bandolierFactor)) return; break; case WP_PISTOL: //Elder: always have pistol - but extra ones give akimbo or clips if (((other->client->ps.stats[STAT_WEAPONS] & (1 << WP_AKIMBO)) == (1 << WP_AKIMBO)) && other->client->numClips[WP_PISTOL] >= RQ3_PISTOL_MAXCLIP * bandolierFactor) { //leave if we have max clips and akimbos return; } break; case WP_M3: case WP_HANDCANNON: case WP_MP5: case WP_M4: case WP_SSG3000: //Elder: check to see if it's in mid-air or over the limit if (other->client->uniqueWeapons >= g_RQ3_maxWeapons.integer + (bandolierFactor - 1) || ent->s.pos.trDelta[2] != 0) return; // Paril: fix/workaround for 4085 // don't pick up dupe special weapons even if we could. if ((other->client->ps.stats[STAT_WEAPONS] & (1 << ent->item->giTag)) == (1 << ent->item->giTag)) return; break; case WP_AKIMBO: default: //Elder: shouldn't be here G_Printf("Touch_Item received invalid IT_WEAPON giTag: %d\n", ent->item->giTag); return; break; } respawn = Pickup_Weapon(ent, other, bandolierFactor); //Elder: added pistol and knife condition if (ent->item->giTag == WP_GRENADE || ent->item->giTag == WP_PISTOL || ent->item->giTag == WP_KNIFE) { respawn = 30; } else { //Elder: moved here respawn = -1; //Dont respawn weapons } // predict = qfalse; break; case IT_AMMO: switch (ent->item->giTag) { //Blaze: dont pick up the clip if we already have all the clips we can have case WP_KNIFE: if (other->client->numClips[ent->item->giTag] >= 0) return; //No clips for knifes break; case WP_PISTOL: if (other->client->numClips[ent->item->giTag] >= RQ3_PISTOL_MAXCLIP * bandolierFactor) return; break; case WP_M3: if (other->client->numClips[ent->item->giTag] >= RQ3_M3_MAXCLIP * bandolierFactor) return; break; case WP_HANDCANNON: if (other->client->numClips[ent->item->giTag] >= RQ3_HANDCANNON_MAXCLIP * bandolierFactor) return; break; case WP_MP5: if (other->client->numClips[ent->item->giTag] >= RQ3_MP5_MAXCLIP * bandolierFactor) return; break; case WP_M4: if (other->client->numClips[ent->item->giTag] >= RQ3_M4_MAXCLIP * bandolierFactor) return; break; case WP_SSG3000: if (other->client->numClips[ent->item->giTag] >= RQ3_SSG3000_MAXCLIP * bandolierFactor) return; break; case WP_AKIMBO: if (other->client->numClips[ent->item->giTag] >= RQ3_AKIMBO_MAXCLIP * bandolierFactor) return; break; case WP_GRENADE: if (other->client->numClips[ent->item->giTag] >= 0) return; //no clips for grenades break; } respawn = Pickup_Ammo(ent, other, bandolierFactor); break; case IT_ARMOR: respawn = Pickup_Armor(ent, other); break; case IT_HEALTH: respawn = Pickup_Health(ent, other); break; case IT_POWERUP: respawn = Pickup_Powerup(ent, other); predict = qfalse; break; case IT_TEAM: // NiceAss: can't pick it up if it's in mid-flight (someone dropped it) if (ent->s.pos.trDelta[2] != 0.0f) return; respawn = Pickup_Team(ent, other); break; case IT_HOLDABLE: //Elder: check to see if it's in mid-air if (other->client->uniqueItems >= g_RQ3_maxItems.integer || ent->s.pos.trDelta[2] != 0) return; respawn = Pickup_Holdable(ent, other); break; default: return; } if (!respawn) { return; } // play the normal pickup sound if (predict) { G_AddPredictableEvent(other, EV_ITEM_PICKUP, ent->s.modelindex); } else { G_AddEvent(other, EV_ITEM_PICKUP, ent->s.modelindex); } // powerup pickups are global broadcasts if (ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM) { // if we want the global sound to play if (!ent->speed) { gentity_t *te; te = G_TempEntity(ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP); te->s.eventParm = ent->s.modelindex; te->r.svFlags |= SVF_BROADCAST; } else { gentity_t *te; te = G_TempEntity(ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP); te->s.eventParm = ent->s.modelindex; // only send this temp entity to a single client te->r.svFlags |= SVF_SINGLECLIENT; te->r.singleClient = other->s.number; } } // fire item targets G_UseTargets(ent, other); // wait of -1 will not respawn if (ent->wait == -1) { ent->r.svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; ent->unlinkAfterEvent = qtrue; return; } // non zero wait overrides respawn time if (ent->wait) { respawn = ent->wait; } // random can be used to vary the respawn time if (ent->random) { respawn += crandom() * ent->random; if (respawn < 1) { respawn = 1; } } // dropped items will not respawn if (ent->flags & FL_DROPPED_ITEM) { ent->freeAfterEvent = qtrue; } // picked up items still stay around, they just don't // draw anything. This allows respawnable items // to be placed on movers. ent->r.svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; // ZOID // A negative respawn times means to never respawn this item (but don't // delete it). This is used by items that are respawned by third party // events such as ctf flags if (respawn <= 0) { ent->nextthink = 0; ent->think = 0; } else { ent->nextthink = level.time + respawn * 1000; ent->think = RespawnItem; } trap_LinkEntity(ent); }
/* =============== Touch_Item =============== */ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) { int respawn; qboolean predict; //instant gib if ((g_instantgib.integer || g_rockets.integer || g_gametype.integer == GT_CTF_ELIMINATION || g_elimination_allgametypes.integer) && ent->item->giType != IT_TEAM) return; //Cannot touch flag before round starts if(g_gametype.integer == GT_CTF_ELIMINATION && level.roundNumber != level.roundNumberStarted) return; //Cannot take ctf elimination oneway if(g_gametype.integer == GT_CTF_ELIMINATION && g_elimination_ctf_oneway.integer!=0 && ( (other->client->sess.sessionTeam==TEAM_BLUE && (level.eliminationSides+level.roundNumber)%2 == 0 ) || (other->client->sess.sessionTeam==TEAM_RED && (level.eliminationSides+level.roundNumber)%2 != 0 ) )) return; if (g_gametype.integer == GT_ELIMINATION || g_gametype.integer == GT_LMS) return; //nothing to pick up in elimination if (!other->client) return; if (other->health < 1) return; // dead people can't pickup // the same pickup rules are used for client side and server side if ( !BG_CanItemBeGrabbed( g_gametype.integer, &ent->s, &other->client->ps ) ) { return; } //In double DD we cannot "pick up" a flag we already got if(g_gametype.integer == GT_DOUBLE_D) { if( strcmp(ent->classname, "team_CTF_redflag") == 0 ) if(other->client->sess.sessionTeam == level.pointStatusA) return; if( strcmp(ent->classname, "team_CTF_blueflag") == 0 ) if(other->client->sess.sessionTeam == level.pointStatusB) return; } G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname ); predict = other->client->pers.predictItemPickup; // call the item-specific pickup function switch( ent->item->giType ) { case IT_WEAPON: respawn = Pickup_Weapon(ent, other); // predict = qfalse; break; case IT_AMMO: respawn = Pickup_Ammo(ent, other); // predict = qfalse; break; case IT_ARMOR: respawn = Pickup_Armor(ent, other); break; case IT_HEALTH: respawn = Pickup_Health(ent, other); break; case IT_POWERUP: respawn = Pickup_Powerup(ent, other); predict = qfalse; break; case IT_PERSISTANT_POWERUP: respawn = Pickup_PersistantPowerup(ent, other); break; case IT_TEAM: respawn = Pickup_Team(ent, other); //If touching a team item remove spawnprotection if(other->client->spawnprotected) other->client->spawnprotected = qfalse; break; case IT_HOLDABLE: respawn = Pickup_Holdable(ent, other); break; default: return; } if ( !respawn ) { return; } // play the normal pickup sound if (predict) { G_AddPredictableEvent( other, EV_ITEM_PICKUP, ent->s.modelindex ); } else { G_AddEvent( other, EV_ITEM_PICKUP, ent->s.modelindex ); } // powerup pickups are global broadcasts if ( ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM) { // if we want the global sound to play if (!ent->speed) { gentity_t *te; te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP ); te->s.eventParm = ent->s.modelindex; te->r.svFlags |= SVF_BROADCAST; } else { gentity_t *te; te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP ); te->s.eventParm = ent->s.modelindex; // only send this temp entity to a single client te->r.svFlags |= SVF_SINGLECLIENT; te->r.singleClient = other->s.number; } } // fire item targets G_UseTargets (ent, other); // wait of -1 will not respawn if ( ent->wait == -1 ) { ent->r.svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; ent->unlinkAfterEvent = qtrue; return; } // non zero wait overrides respawn time if ( ent->wait ) { respawn = ent->wait; } // random can be used to vary the respawn time if ( ent->random ) { respawn += crandom() * ent->random; if ( respawn < 1 ) { respawn = 1; } } // dropped items will not respawn if ( ent->flags & FL_DROPPED_ITEM ) { ent->freeAfterEvent = qtrue; } // picked up items still stay around, they just don't // draw anything. This allows respawnable items // to be placed on movers. ent->r.svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; // ZOID // A negative respawn times means to never respawn this item (but don't // delete it). This is used by items that are respawned by third party // events such as ctf flags if ( respawn <= 0 ) { ent->nextthink = 0; ent->think = 0; } else { ent->nextthink = level.time + respawn * 1000; ent->think = RespawnItem; } trap_LinkEntity( ent ); }
virtual void execute( GameEntity *other, trace_t *trace ) { int respawn; bool predict; GameEntity* self = self_; // Since we may delete our current think() if( !other->client_ ) return; if( other->health_ < 1 ) return; // dead people can't pickup if( other->client_->ps_.pm_type == PM_SPECTATOR ) return; // the same pickup rules are used for client side and server side if ( !BG_CanItemBeGrabbed( g_gametype.integer, &self->s, &other->client_->ps_, other->client_->vehicle_ ) ) return; G_LogPrintf( "Item: %i %s\n", other->s.number, self->item_->classname ); predict = other->client_->pers_.predictItemPickup_; // call the item-specific pickup function switch( self->item_->giType ) { case IT_AMMO: respawn = Pickup_Ammo(self, other); break; case IT_HEALTH: respawn = Pickup_Health(self, other); break; case IT_FUEL: respawn = Pickup_Fuel(self, other); break; case IT_TEAM: respawn = Pickup_Team(self, other); break; default: return; } if ( !respawn ) return; // play the normal pickup sound if( predict ) G_AddPredictableEvent( other, EV_ITEM_PICKUP, self->s.modelindex ); else G_AddEvent( other, EV_ITEM_PICKUP, self->s.modelindex, true ); // powerup pickups are global broadcasts if( self->item_->giType == IT_TEAM) { // if we want the global sound to play if( !self->speed_ ) { GameEntity *te; te = G_TempEntity( self->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP ); te->s.eventParm = self->s.modelindex; te->r.svFlags |= SVF_BROADCAST; } else { GameEntity *te; te = G_TempEntity( self->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP ); te->s.eventParm = self->s.modelindex; // only send this temp entity to a single client te->r.svFlags |= SVF_SINGLECLIENT; te->r.singleClient = other->s.number; } } // fire item targets G_UseTargets (self, other); // wait of -1 will not respawn if( self->wait_ == -1 ) { self->r.svFlags |= SVF_NOCLIENT; self->s.eFlags |= EF_NODRAW; self->r.contents = 0; self->unlinkAfterEvent_ = true; return; } // non zero wait overrides respawn time if( self->wait_ ) respawn = self->wait_; // random can be used to vary the respawn time if( self->random_ ) { respawn += crandom() * self->random_; if ( respawn < 1 ) respawn = 1; } // dropped items will not respawn if( self->flags_ & FL_DROPPED_ITEM ) self->freeAfterEvent_ = true; // picked up items still stay around, they just don't // draw anything. This allows respawnable items // to be placed on movers. self->r.svFlags |= SVF_NOCLIENT; self->s.eFlags |= EF_NODRAW; self->r.contents = 0; // ZOID // A negative respawn times means to never respawn this item (but don't // delete it). This is used by items that are respawned by third party // events such as ctf flags if( respawn <= 0 ) { self->nextthink_ = 0; self->setThink(0); } else { self->nextthink_ = theLevel.time_ + respawn * 1000; self->setThink(new Think_RespawnItem); } SV_LinkEntity( self ); }
/* =============== Touch_Item defcon-X: just keep this for bots! =============== */ void Pick_Item( gentity_t *ent, gentity_t *other, trace_t *trace ) { int respawn; if ( !other->client ) { return; } if ( other->health < 1 ) { return; // dead people can't pickup } if ( !BG_CanItemBeGrabbed( g_gametype.integer, &ent->s, &other->client->ps ) ) { return; } // call the item-specific pickup function switch ( ent->item->giType ) { case IT_WEAPON: respawn = Pickup_Weapon( ent, other ); break; case IT_AMMO: respawn = Pickup_Ammo( ent, other ); break; case IT_ARMOR: respawn = Pickup_Armor( ent, other ); break; case IT_TEAM: respawn = Pickup_Team( ent, other ); break; default: return; } if ( !respawn ) { return; } // play the normal pickup sound if ( ( ent->item->giTag != PW_BRIEFCASE_RETURN ) && ( ent->item->giTag != PW_BRIEFCASE ) ) { if ( ent->item->giType != IT_BOTROAM ) { G_AddEvent( other, EV_ITEM_PICKUP, ent->s.modelindex ); } } // Navy Seals ++ // fire item targets G_UseTargets( ent, other ); // wait of -1 will not respawn if ( ent->wait == -1 ) { ent->r.svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; ent->unlinkAfterEvent = qtrue; return; } // non zero wait overrides respawn time if ( ent->wait ) { respawn = ent->wait; } // random can be used to vary the respawn time if ( ent->random ) { respawn += crandom() * ent->random; if ( respawn < 1 ) { respawn = 1; } } // dropped items will not respawn if ( ent->flags & FL_DROPPED_ITEM ) { ent->freeAfterEvent = qtrue; } // picked up items still stay around, they just don't // draw anything. This allows respawnable items // to be placed on movers. ent->r.svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; // ZOID // A negative respawn times means to never respawn this item (but don't // delete it). This is used by items that are respawned by third party // events such as ctf flags if ( respawn <= 0 ) { ent->nextthink = 0; ent->think = 0; } else { ent->nextthink = level.time + respawn * 1000; ent->think = RespawnItem; } trap_LinkEntity( ent ); }
/* =============== Touch_Item =============== */ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) { int respawn; if (!other->client) return; if (other->health < 1) return; // dead people can't pickup // RPG-X: Marcin: Press USE to pick up items. - 03/12/2008 if ( !(other->client->pers.cmd.buttons & BUTTON_USE) || other->client->pressedUse == qtrue) { return; } else { other->client->pressedUse = qtrue; } // If ghosted, then end the ghost-ness in favor of the pickup. //RPG-X: RedTechie - Keep ghost all the time /*if (other->client->ps.powerups[PW_GHOST] >= level.time) { other->client->ps.powerups[PW_GHOST] = 0; // Unghost the player. This }*/ // the same pickup rules are used for client side and server side if ( !BG_CanItemBeGrabbed( &ent->s, &other->client->ps, Max_Weapon(other->client->ps.weapon) ) && IsAdmin( other ) == qfalse ) { return; } numTotalDropped--; G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname ); // call the item-specific pickup function switch( ent->item->giType ) { case IT_WEAPON: respawn = Pickup_Weapon(ent, other); break; case IT_AMMO: respawn = Pickup_Ammo(ent, other); break; case IT_ARMOR: respawn = Pickup_Armor(ent, other); break; case IT_HEALTH: respawn = Pickup_Health(ent, other); break; case IT_POWERUP: respawn = Pickup_Powerup(ent, other); break; case IT_TEAM: respawn = Pickup_Team(ent, other); break; case IT_HOLDABLE: respawn = Pickup_Holdable(ent, other); break; default: return; } if ( !respawn) { return; } // play the normal pickup sound if ( other->client->pers.predictItemPickup ) { G_AddPredictableEvent( other, EV_ITEM_PICKUP, ent->s.modelindex ); } else { G_AddEvent( other, EV_ITEM_PICKUP, ent->s.modelindex ); } // powerup pickups are global broadcasts if ( ent->item->giType == IT_POWERUP || ent->item->giType == IT_TEAM) { gentity_t *te; te = G_TempEntity( ent->s.pos.trBase, EV_GLOBAL_ITEM_PICKUP ); te->s.eventParm = ent->s.modelindex; // tell us which client fired off this global sound te->s.otherEntityNum = other->s.number; te->r.svFlags |= SVF_BROADCAST; } // fire item targets G_UseTargets (ent, other); if ( rpg_weaponsStay.integer == 1 && IsAdmin( ent->parent ) == qtrue && IsAdmin( other ) == qfalse ) { return; } if ( ent->item->giTag == WP_3 ) { Padd_Remove( ent ); } // wait of -1 will not respawn if ( ent->wait == -1 ) { ent->r.svFlags |= SVF_NOCLIENT; ent->s.eFlags |= EF_NODRAW; ent->r.contents = 0; ent->unlinkAfterEvent = qtrue; return; } // non zero wait overrides respawn time if ( ent->wait ) { respawn = ent->wait; } // random can be used to vary the respawn time if ( ent->random ) { respawn += crandom() * ent->random; if ( respawn < 1 ) { respawn = 1; } } // dropped items will not respawn if ( ent->flags & FL_DROPPED_ITEM ) { ent->freeAfterEvent = qtrue; } // picked up items still stay around, they just don't // draw anything. This allows respawnable items // to be placed on movers. if (ent->item->giType==IT_WEAPON || ent->item->giType==IT_POWERUP) { ent->s.eFlags |= EF_ITEMPLACEHOLDER; } else { // this line used to prevent items that were picked up from being drawn, but we now want to draw the techy grid thing instead ent->s.eFlags |= EF_NODRAW; ent->r.svFlags |= SVF_NOCLIENT; } ent->r.contents = 0; // *************** // ZOID // A negative respawn times means to never respawn this item (but don't // delete it). This is used by items that are respawned by third party // events such as ctf flags if ( respawn <= 0 ) { ent->nextthink = 0; ent->think = 0; } else { ent->nextthink = level.time + respawn * 1000; ent->think = RespawnItem; } trap_LinkEntity( ent ); }