/* ================= AimAtTarget Calculate origin2 so the target apogee will be hit ================= */ void AimAtTarget(gentity_t *self) { gentity_t *ent; vec3_t origin; float height, gravity, time, forward; float dist; VectorAdd(self->r.absmin, self->r.absmax, origin); VectorScale(origin, 0.5, origin); ent = G_PickTarget(self->target); if (!ent) { G_FreeEntity(self); return; } height = ent->r.currentOrigin[2] - origin[2]; gravity = g_gravity.value; time = sqrt(height / (0.5 * gravity)); if (!time) { G_FreeEntity(self); return; } // set s.origin2 to the push velocity VectorSubtract(ent->r.currentOrigin, origin, self->s.origin2); self->s.origin2[2] = 0; dist = VectorNormalize(self->s.origin2); forward = dist / time; VectorScale(self->s.origin2, forward, self->s.origin2); self->s.origin2[2] = time * gravity; }
void trigger_elevator_init (edict_t *self) { if (!self->target) { gi.dprintf("trigger_elevator has no target\n"); return; } self->movetarget = G_PickTarget (self->target); if (!self->movetarget) { gi.dprintf("trigger_elevator unable to find target %s\n", self->target); return; } if (strcmp(self->movetarget->classname, "func_train") != 0) { gi.dprintf("trigger_elevator target %s is not a train\n", self->target); return; } self->use = trigger_elevator_use; self->svflags = SVF_NOCLIENT; }
/*QUAKED target_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) RED_ONLY BLUE_ONLY RANDOM This doesn't perform any actions except fire its targets. The activator can be forced to be from a certain team. if RANDOM is checked, only one of the targets will be fired, not all of them */ void target_relay_use( gentity_t *self, gentity_t *other, gentity_t *activator ) { if( ( self->spawnflags & 1 ) && activator && activator->client && activator->client->ps.stats[ STAT_TEAM ] != TEAM_HUMANS ) return; if( ( self->spawnflags & 2 ) && activator && activator->client && activator->client->ps.stats[ STAT_TEAM ] != TEAM_ALIENS ) return; if( self->spawnflags & 4 ) { gentity_t *ent; ent = G_PickTarget( self->target ); if( ent && ent->use ) ent->use( ent, self, activator ); return; } G_UseTargets( self, activator ); }
void turret_breach_finish_init (edict_t *self) { // get and save info for muzzle location if (!self->target) { gi.dprintf("%s at %s needs a target\n", self->classname, vtos(self->s.origin)); } else { self->target_ent = G_PickTarget (self->target); if(self->target_ent) { VectorSubtract (self->target_ent->s.origin, self->s.origin, self->move_origin); G_FreeEdict(self->target_ent); } else gi.dprintf("could not find target entity for %s at %s\n", self->classname, vtos(self->s.origin)); } self->teammaster->dmg = self->dmg; self->think = turret_breach_think; self->think (self); }
void trigger_teleporter_touch(gentity_t * self, gentity_t * other, trace_t * trace) { gentity_t *dest; if(!other->client) { return; } if(other->client->ps.pm_type == PM_DEAD) { return; } // Spectators only? if((self->spawnflags & 1) && other->client->sess.sessionTeam != TEAM_SPECTATOR) { return; } dest = G_PickTarget(self->target); if(!dest) { G_Printf("Couldn't find teleporter destination\n"); return; } #ifdef G_LUA // Lua API callbacks if(self->luaTrigger) { G_LuaHook_EntityTrigger(self->luaTrigger, self->s.number, other->s.number); } #endif TeleportPlayer(other, dest->s.origin, dest->s.angles); }
/*QUAKED target_relay (.5 .5 .5) (-8 -8 -8) (8 8 8) RED_ONLY BLUE_ONLY RANDOM This doesn't perform any actions except fire its targets. The activator can be forced to be from a certain team. if RANDOM is checked, only one of the targets will be fired, not all of them */ void target_relay_use (gentity_t *self, gentity_t *other, gentity_t *activator) { /* LQ3A */ UNREFERENCED_PARAMETER(other); if ( ( self->spawnflags & 1 ) && activator->client && activator->client->sess.sessionTeam != TEAM_RED ) { return; } if ( ( self->spawnflags & 2 ) && activator->client && activator->client->sess.sessionTeam != TEAM_BLUE ) { return; } if ( self->spawnflags & 4 ) { gentity_t *ent; ent = G_PickTarget( self->target ); if ( ent && ent->use ) { ent->use( ent, self, activator ); } return; } G_UseTargets (self, activator); }
void trigger_teleporter_touch( gentity_t *self, gentity_t *other, trace_t *trace ) { gentity_t *dest; if ( self->s.eFlags & EF_NODRAW ) { return; } if ( !other->client ) { return; } if ( other->client->ps.pm_type == PM_DEAD ) { return; } // Spectators only? if ( ( self->spawnflags & 1 ) && other->client->sess.spectatorState == SPECTATOR_NOT ) { return; } dest = G_PickTarget( self->target ); if ( !dest ) { G_Printf( "Couldn't find teleporter destination\n" ); return; } TeleportPlayer( other, dest->s.origin, dest->s.angles, self->speed ); }
void train_spline_next (edict_t *self) { edict_t *ent; vec3_t dest; qboolean first; vec3_t angles,v; first = true; again: if (!self->target) { self->s.sound = 0; return; } ent = G_PickTarget (self->target); if (!ent) { gi.dprintf ("train_spline_next: bad target %s\n", self->target); return; } // spline stuff: self->from = self->to; self->to = ent; VectorSubtract(self->from->s.origin,self->to->s.origin,v); self->moveinfo.distance = VectorLength(v); self->moveinfo.ratio = 0.0; // end spline stuff self->target = ent->target; // check for a teleport path_corner if (ent->spawnflags & 1) { if (!first) { gi.dprintf ("connected teleport path_corners, see %s at %s\n", ent->classname, vtos(ent->s.origin)); return; } first = false; VectorSubtract (ent->s.origin, self->mins, self->s.origin); VectorCopy (self->s.origin, self->s.old_origin); self->s.event = EV_OTHER_TELEPORT; gi.linkentity (self); goto again; } self->moveinfo.wait = ent->wait; self->target_ent = ent; if (!(self->flags & FL_TEAMSLAVE)) { if (self->moveinfo.sound_start) gi.sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self->moveinfo.sound_start, 1, ATTN_STATIC, 0); self->s.sound = self->moveinfo.sound_middle; } VectorSubtract (ent->s.origin, self->mins, dest); self->moveinfo.state = STATE_TOP; VectorCopy (self->s.origin, self->moveinfo.start_origin); VectorCopy (dest, self->moveinfo.end_origin); // Rroff rotating if (self->spawnflags & TRAIN_ROTATE && !(ent->spawnflags & 2)) { // Lazarus: No no no :-). This is measuring from the center // of the func_train to the path_corner. Should // be path_corner to path_corner. //VectorSubtract (ent->s.origin, self->s.origin, v); VectorAdd(self->s.origin,self->mins,v); VectorSubtract(ent->s.origin,v,v); vectoangles(v,angles); self->ideal_yaw = angles[YAW]; self->ideal_pitch = angles[PITCH]; if(self->ideal_pitch < 0) self->ideal_pitch += 360; self->ideal_roll = ent->roll; VectorClear(self->movedir); self->movedir[1] = 1.0; } Move_Calc (self, dest, train_spline_wait); self->spawnflags |= TRAIN_START_ON; }
void target_actor_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t v; if (other->movetarget != self) return; if (other->enemy) return; other->goalentity = other->movetarget = NULL; if (self->message) { int n; edict_t *ent; for (n = 1; n <= game.maxclients; n++) { ent = &g_edicts[n]; if (!ent->inuse) continue; safe_cprintf (ent, PRINT_CHAT, "%s: %s\n", actor_names[(other - g_edicts)%MAX_ACTOR_NAMES], self->message); } } if (self->spawnflags & 1) //jump { other->velocity[0] = self->movedir[0] * self->speed; other->velocity[1] = self->movedir[1] * self->speed; if (other->groundentity) { other->groundentity = NULL; other->velocity[2] = self->movedir[2]; gi.sound(other, CHAN_VOICE, gi.soundindex("player/male/jump1.wav"), 1, ATTN_NORM, 0); } } if (self->spawnflags & 2) //shoot { } else if (self->spawnflags & 4) //attack { other->enemy = G_PickTarget(self->pathtarget); if (other->enemy) { other->goalentity = other->enemy; if (self->spawnflags & 32) other->monsterinfo.aiflags |= AI_BRUTAL; if (self->spawnflags & 16) { other->monsterinfo.aiflags |= AI_STAND_GROUND; actor_stand (other); } else { actor_run (other); } } } if (!(self->spawnflags & 6) && (self->pathtarget)) { char *savetarget; savetarget = self->target; self->target = self->pathtarget; G_UseTargets (self, other); self->target = savetarget; } other->movetarget = G_PickTarget(self->target); if (!other->goalentity) other->goalentity = other->movetarget; if (!other->movetarget && !other->enemy) { other->monsterinfo.pausetime = level.time + 100000000; other->monsterinfo.stand (other); } else if (other->movetarget == other->goalentity) { VectorSubtract (other->movetarget->s.origin, other->s.origin, v); other->ideal_yaw = vectoyaw (v); } }
void trigger_teleporter_touch( gentity_t *self, gentity_t *other, trace_t *trace ) { gentity_t *dest; if ( !other->client ) { return; } if ( other->client->ps.pm_type == PM_DEAD ) { return; } // Spectators only? if ( ( self->spawnflags & 1 ) && ( ( other->client->sess.sessionTeam != TEAM_SPECTATOR ) && !LPSDeadSpec( other->client ) ) ) { return; } // FIXME: Use defines for spawnflags if ( ( self->spawnflags & 0x2 ) && !IsSyc() ) { // No need to check for sprayroom teleporter out return; } if ( ( other->client->sess.sessionTeam != TEAM_SPECTATOR ) && !LPSDeadSpec( other->client ) ) { // sprayroom teleporter in if ( self->spawnflags & 0x2 ) { if ( other->client->ps.ammo[WP_SPRAYPISTOL] <= 0 ) { return; } other->client->logocounter = 0; other->client->sprayroomleavetime = ( ( level.maxsprayroomtime * 1000 ) + level.time ); other->client->sprayroomsoundflags = 0; other->client->ps.stats[STAT_SPRAYROOMSECS] = ( level.maxsprayroomtime + 1 ); if ( other->client->ps.weapon != WP_SPRAYPISTOL ) { other->client->last_nonspray_weapon = other->client->ps.weapon; } if ( other->client->ps.weaponstate == WEAPON_CHARGING ) { other->client->ps.weaponstate = WEAPON_READY; other->client->ps.weaponTime = 0; } trap_SendServerCommand( other->client->ps.clientNum, va( "srwc %i", WP_SPRAYPISTOL ) ); other->client->pers.cmd.weapon = WP_SPRAYPISTOL; other->client->ps.weapon = WP_SPRAYPISTOL; G_BackupPowerups( other->client ); } // sprayroom teleporter out else if ( self->spawnflags & 0x4 ) { other->client->ps.stats[STAT_SPRAYROOMSECS] = 0; trap_SendServerCommand( other->client->ps.clientNum, va( "srwc %i", other->client->last_nonspray_weapon ) ); other->client->pers.cmd.weapon = other->client->last_nonspray_weapon; other->client->ps.weapon = other->client->last_nonspray_weapon; G_RestorePowerups( other->client ); } } dest = G_PickTarget( self->target ); if (!dest) { G_Printf ("Couldn't find teleporter destination\n"); return; } TeleportPlayer( other, dest->s.origin, dest->s.angles ); }
/* ================= AimAtTarget Calculate origin2 so the target apogee will be hit ================= */ void AimAtTarget( gentity_t *self ) { gentity_t *ent; vec3_t origin; float height, gravity, time, forward; float dist; VectorAdd( self->absmin, self->absmax, origin ); VectorScale ( origin, 0.5, origin ); ent = G_PickTarget( self->target ); if ( !ent ) { G_FreeEntity( self ); return; } if ( self->classname && !Q_stricmp( "trigger_push", self->classname ) ) { if ( (self->spawnflags&2) ) {//check once a second to see if we should activate or deactivate ourselves self->e_ThinkFunc = thinkF_trigger_push_checkclear; self->nextthink = level.time + FRAMETIME; } if ( (self->spawnflags&16) ) {//relative, not an arc or linear VectorCopy( ent->currentOrigin, self->s.origin2 ); return; } else if ( (self->spawnflags&4) ) {//linear, not an arc VectorSubtract( ent->currentOrigin, origin, self->s.origin2 ); VectorNormalize( self->s.origin2 ); return; } } if ( self->classname && !Q_stricmp( "target_push", self->classname ) ) { if( self->spawnflags & PUSH_CONSTANT ) { VectorSubtract ( ent->s.origin, self->s.origin, self->s.origin2 ); VectorNormalize( self->s.origin2); VectorScale (self->s.origin2, self->speed, self->s.origin2); return; } } height = ent->s.origin[2] - origin[2]; if ( height < 0 ) {//sqrt of negative is bad! height = 0; } gravity = g_gravity->value; if ( gravity < 0 ) { gravity = 0; } time = sqrt( height / ( .5 * gravity ) ); if ( !time ) { G_FreeEntity( self ); return; } // set s.origin2 to the push velocity VectorSubtract ( ent->s.origin, origin, self->s.origin2 ); self->s.origin2[2] = 0; dist = VectorNormalize( self->s.origin2); forward = dist / time; VectorScale( self->s.origin2, forward, self->s.origin2 ); self->s.origin2[2] = time * gravity; }
void path_corner_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t v; edict_t *next; if (other->movetarget != self) return; if (other->enemy) return; #ifdef IML_Q2_EXTENSIONS if (!ai_movetarget_is_active(other)) return; #endif if (self->pathtarget) { char *savetarget; savetarget = self->target; self->target = self->pathtarget; G_UseTargets (self, other); self->target = savetarget; } if (self->target) next = G_PickTarget(self->target); else next = NULL; if ((next) && (next->spawnflags & PATH_CORNER_TELEPORT)) { VectorCopy (next->s.origin, v); v[2] += next->mins[2]; v[2] -= other->mins[2]; VectorCopy (v, other->s.origin); next = G_PickTarget(next->target); other->s.event = EV_OTHER_TELEPORT; } // 18 Aug 2004 - IML - madhura - path_corner enhancements // was: other->goalentity = other->movetarget = next; other->movetarget = next; other->goalentity = NULL; if (ai_movetarget_is_active(other)) other->goalentity = other->movetarget; if (self->wait) { other->monsterinfo.pausetime = level.time + self->wait; other->monsterinfo.stand (other); return; } // 18 Aug 2004 - IML - madhura - path_corner enhancements // was: if (!other->movetarget) if (!other->goalentity) { other->monsterinfo.pausetime = level.time + 100000000; other->monsterinfo.stand (other); } else { VectorSubtract (other->goalentity->s.origin, other->s.origin, v); other->ideal_yaw = vectoyaw (v); } }
void monster_start_go (edict_t *self) { vec3_t v; if (self->health <= 0) { if (self->max_health <= 0) InitiallyDead(self); return; } // Lazarus: move_origin for func_monitor if(!VectorLength(self->move_origin)) VectorSet(self->move_origin,0,0,self->viewheight); // check for target to point_combat and change to combattarget if (self->target) { qboolean notcombat; qboolean fixup; edict_t *target; target = NULL; notcombat = false; fixup = false; while ((target = G_Find (target, FOFS(targetname), self->target)) != NULL) { if (strcmp(target->classname, "point_combat") == 0) { self->combattarget = self->target; fixup = true; } else { notcombat = true; } } if (notcombat && self->combattarget) gi.dprintf("%s at %s has target with mixed types\n", self->classname, vtos(self->s.origin)); if (fixup) self->target = NULL; } // validate combattarget if (self->combattarget) { edict_t *target; target = NULL; while ((target = G_Find (target, FOFS(targetname), self->combattarget)) != NULL) { if (strcmp(target->classname, "point_combat") != 0) { gi.dprintf("%s at (%i %i %i) has a bad combattarget %s : %s at (%i %i %i)\n", self->classname, (int)self->s.origin[0], (int)self->s.origin[1], (int)self->s.origin[2], self->combattarget, target->classname, (int)target->s.origin[0], (int)target->s.origin[1], (int)target->s.origin[2]); } } } if (self->target) { self->goalentity = self->movetarget = G_PickTarget(self->target); if (!self->movetarget) { gi.dprintf ("%s can't find target %s at %s\n", self->classname, self->target, vtos(self->s.origin)); self->target = NULL; self->monsterinfo.pausetime = 100000000; self->monsterinfo.stand (self); } else if (strcmp (self->movetarget->classname, "path_corner") == 0) { // Lazarus: Don't wipe out target for trigger spawned monsters // that aren't triggered yet if( ! (self->spawnflags & SF_MONSTER_TRIGGER_SPAWN) ) { VectorSubtract (self->goalentity->s.origin, self->s.origin, v); self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v); self->monsterinfo.walk (self); self->target = NULL; } } else { self->goalentity = self->movetarget = NULL; self->monsterinfo.pausetime = 100000000; self->monsterinfo.stand (self); } } else { self->monsterinfo.pausetime = 100000000; self->monsterinfo.stand (self); } self->think = monster_think; self->nextthink = level.time + FRAMETIME; }
void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles ) { gentity_t *tent; // use temp events at source and destination to prevent the effect // from getting dropped by a second player event #ifndef SMOKINGUNS if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) { #else if ( player->client->sess.sessionTeam < TEAM_SPECTATOR ) { #endif tent = G_TempEntity( player->client->ps.origin, EV_PLAYER_TELEPORT_OUT ); tent->s.clientNum = player->s.clientNum; tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN ); tent->s.clientNum = player->s.clientNum; } // unlink to make sure it can't possibly interfere with G_KillBox trap_UnlinkEntity (player); VectorCopy ( origin, player->client->ps.origin ); player->client->ps.origin[2] += 1; // spit the player out AngleVectors( angles, player->client->ps.velocity, NULL, NULL ); VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity ); player->client->ps.pm_time = 160; // hold time player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; // toggle the teleport bit so the client knows to not lerp player->client->ps.eFlags ^= EF_TELEPORT_BIT; #ifdef SMOKINGUNS //unlagged - backward reconciliation #3 // we don't want players being backward-reconciled back through teleporters G_ResetHistory( player ); //unlagged - backward reconciliation #3 #endif // set angles SetClientViewAngle( player, angles ); // kill anything at the destination #ifndef SMOKINGUNS if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) { #else if ( player->client->sess.sessionTeam < TEAM_SPECTATOR ) { #endif G_KillBox (player); #ifdef SMOKINGUNS // Tequila comment: G_KillBox will set dontTelefrag as needed if (player->client->dontTelefrag) { #ifdef DEBUG_TELEFRAG_CASE G_Printf(S_COLOR_MAGENTA "TeleportPlayer: Telefrag case delayed at respawn for %s...\n",player->client->pers.netname); #endif trap_SendServerCommand( player->s.clientNum, va("print \"Go away %s\n\"",player->client->pers.netname) ); // So we will link the player entity later with normal content player->r.contents = 0; } #endif } // save results of pmove BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue ); // use the precise origin for linking VectorCopy( player->client->ps.origin, player->r.currentOrigin ); #ifndef SMOKINGUNS if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) { #else if ( player->client->sess.sessionTeam < TEAM_SPECTATOR ) { #endif trap_LinkEntity (player); } } /*QUAKED misc_teleporter_dest (1 0 0) (-32 -32 -24) (32 32 -16) Point teleporters at these. Now that we don't have teleport destination pads, this is just an info_notnull */ void SP_misc_teleporter_dest( gentity_t *ent ) { } #ifdef SMOKINGUNS // Imported from WoP OpenSource project //=========================================================== /*QUAKED misc_externalmodel (1 0 0) (-16 -16 -16) (16 16 16) "model" arbitrary .md3 file to display "wait" time in seconds before the animation begins */ #define ANIMATION_THINKTIME 50 static void Think_AnimationExternalmodel( gentity_t *ent ) { if(ent->animationEnd>ent->animationStart) { ent->s.frame = (int)((float)level.time*0.001f*ent->animationFPS)%(ent->animationEnd-ent->animationStart); ent->s.frame += ent->animationStart; ent->nextthink = level.time + ANIMATION_THINKTIME; } } void SP_misc_externalmodel( gentity_t *ent ) { ent->s.modelindex = G_ModelIndex( ent->model ); // VectorSet (ent->mins, -16, -16, -16); // VectorSet (ent->maxs, 16, 16, 16); trap_LinkEntity (ent); G_SetOrigin( ent, ent->s.origin ); VectorCopy( ent->s.angles, ent->s.apos.trBase ); if(ent->animationEnd>ent->animationStart && ent->animationFPS>0.0f) { ent->think = Think_AnimationExternalmodel; ent->nextthink = level.time + ANIMATION_THINKTIME; // Tequila: Support for new entity features if (ent->wait>0.0f) ent->nextthink += (int)(ent->wait*1000); } } #endif //=========================================================== /*QUAKED misc_model (1 0 0) (-16 -16 -16) (16 16 16) "model" arbitrary .md3 file to display */ void SP_misc_model( gentity_t *ent ) { #if 0 ent->s.modelindex = G_ModelIndex( ent->model ); VectorSet (ent->mins, -16, -16, -16); VectorSet (ent->maxs, 16, 16, 16); trap_LinkEntity (ent); G_SetOrigin( ent, ent->s.origin ); VectorCopy( ent->s.angles, ent->s.apos.trBase ); #else G_FreeEntity( ent ); #endif } //=========================================================== void locateCamera( gentity_t *ent ) { vec3_t dir; gentity_t *target; gentity_t *owner; owner = G_PickTarget( ent->target ); if ( !owner ) { G_Printf( "Couldn't find target for misc_portal_surface\n" ); G_FreeEntity( ent ); return; } ent->r.ownerNum = owner->s.number; // frame holds the rotate speed if ( owner->spawnflags & 1 ) { ent->s.frame = 25; } else if ( owner->spawnflags & 2 ) { ent->s.frame = 75; } #ifndef SMOKINGUNS // swing camera ? if ( owner->spawnflags & 4 ) { // set to 0 for no rotation at all ent->s.powerups = 0; } else { ent->s.powerups = 1; } #else // set to 0 for no rotation at all ent->s.powerups = 1; #endif // clientNum holds the rotate offset ent->s.clientNum = owner->s.clientNum; VectorCopy( owner->s.origin, ent->s.origin2 ); // see if the portal_camera has a target target = G_PickTarget( owner->target ); if ( target ) { VectorSubtract( target->s.origin, owner->s.origin, dir ); VectorNormalize( dir ); } else { G_SetMovedir( owner->s.angles, dir ); } ent->s.eventParm = DirToByte( dir ); }
static void InitShooter_Finish( gentity_t *ent ) { ent->enemy = G_PickTarget( ent->target ); ent->think = 0; ent->nextthink = 0; }
void path_corner_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { vec3_t v; edict_t *next; if (other->movetarget != self) { return; } if (other->enemy) { return; } if (self->pathtarget) { char *savetarget; savetarget = self->target; self->target = self->pathtarget; G_UseTargets(self, other); self->target = savetarget; } if (self->target) { next = G_PickTarget(self->target); } else { next = NULL; } if ((next) && (next->spawnflags & 1)) { VectorCopy(next->s.origin, v); v[2] += next->mins[2]; v[2] -= other->mins[2]; VectorCopy(v, other->s.origin); next = G_PickTarget(next->target); } other->goalentity = other->movetarget = next; if (self->wait) { other->monsterinfo.pausetime = level.time + self->wait; other->monsterinfo.stand(other); return; } if (!other->movetarget) { other->monsterinfo.pausetime = level.time + 100000000; other->monsterinfo.stand(other); } else { VectorSubtract(other->goalentity->s.origin, other->s.origin, v); other->ideal_yaw = vectoyaw(v); } }
/*QUAKED target_relay (1 1 0) (-8 -8 -8) (8 8 8) RED_ONLY BLUE_ONLY RANDOM NOKEY_ONLY TAKE_KEY NO_LOCKED_NOISE This doesn't perform any actions except fire its targets. The activator can be forced to be from a certain team. if RANDOM is checked, only one of the targets will be fired, not all of them "key" specifies an item you can be carrying that affects the operation of this relay this key is currently an int (1-16) which matches the id of a key entity (key_key1 = 1, etc) NOKEY_ONLY means "fire only if I do /not/ have the specified key" TAKE_KEY removes the key from the players inventory "lockednoise" specifies a .wav file to play if the relay is used and the player doesn't have the necessary key. By default this sound is "sound/movers/doors/default_door_locked.wav" NO_LOCKED_NOISE specifies that it will be silent if activated without proper key */ void target_relay_use (gentity_t *self, gentity_t *other, gentity_t *activator) { if ( ( self->spawnflags & 1 ) && activator && activator->client && activator->client->sess.sessionTeam != TEAM_RED ) { return; } if ( ( self->spawnflags & 2 ) && activator && activator->client && activator->client->sess.sessionTeam != TEAM_BLUE ) { return; } if ( self->spawnflags & 4 ) { gentity_t *ent; ent = G_PickTarget( self->target ); if ( ent && ent->use ) { ent->use( ent, self, activator ); } return; } if(activator) { // activator can be NULL if called from script if(self->key) { gitem_t *item; if(self->key == -1) // relay permanently locked { if (self->soundPos1) G_Sound( self, self->soundPos1); //----(SA) added return; } item = BG_FindItemForKey(self->key, 0); if(item) { if(activator->client->ps.stats[STAT_KEYS] & (1<<item->giTag)) // user has key { if (self->spawnflags & 8 ) { // relay is NOKEY_ONLY and player has key if (self->soundPos1) G_Sound( self, self->soundPos1); //----(SA) added return; } } else // user does not have key { if (!(self->spawnflags & 8) ) { if (self->soundPos1) G_Sound( self, self->soundPos1); //----(SA) added return; } } } if(self->spawnflags & 16) { // (SA) take key activator->client->ps.stats[STAT_KEYS] &= ~(1<<item->giTag); // (SA) TODO: "took inventory item" sound } } } G_UseTargets (self, activator); }
/* * QUAKED point_combat (0.5 0.3 0) (-8 -8 -8) (8 8 8) Hold * Makes this the target of a monster and it will head here * when first activated before going after the activator. If * hold is selected, it will stay here. */ void point_combat_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { edict_t *activator; if (other->movetarget != self) { return; } if (self->target) { other->target = self->target; other->goalentity = other->movetarget = G_PickTarget(other->target); if (!other->goalentity) { gi.dprintf("%s at %s target %s does not exist\n", self->classname, vtos(self->s.origin), self->target); other->movetarget = self; } self->target = NULL; } else if ((self->spawnflags & 1) && !(other->flags & (FL_SWIM | FL_FLY))) { other->monsterinfo.pausetime = level.time + 100000000; other->monsterinfo.aiflags |= AI_STAND_GROUND; other->monsterinfo.stand(other); } if (other->movetarget == self) { other->target = NULL; other->movetarget = NULL; other->goalentity = other->enemy; other->monsterinfo.aiflags &= ~AI_COMBAT_POINT; } if (self->pathtarget) { char *savetarget; savetarget = self->target; self->target = self->pathtarget; if (other->enemy && other->enemy->client) { activator = other->enemy; } else if (other->oldenemy && other->oldenemy->client) { activator = other->oldenemy; } else if (other->activator && other->activator->client) { activator = other->activator; } else { activator = other; } G_UseTargets(self, activator); self->target = savetarget; } }
void monster_start_go(edict_t *self){ vec3_t v; if(self->health <= 0) return; // check for target to combat_point and change to combattarget if(self->target){ qboolean notcombat; qboolean fixup; edict_t *target; target = NULL; notcombat = false; fixup = false; while((target = G_Find(target, FOFS(targetname), self->target)) != NULL){ if(strcmp(target->classname, "point_combat") == 0){ self->combattarget = self->target; fixup = true; } else { notcombat = true; } } if(notcombat && self->combattarget) gi.dprintf("%s at %s has target with mixed types\n", self->classname, vtos(self->s.origin)); if(fixup) self->target = NULL; } // validate combattarget if(self->combattarget){ edict_t *target; target = NULL; while((target = G_Find(target, FOFS(targetname), self->combattarget)) != NULL){ if(strcmp(target->classname, "point_combat") != 0){ gi.dprintf("%s at(%i %i %i) has a bad combattarget %s : %s at(%i %i %i)\n", self->classname,(int)self->s.origin[0],(int)self->s.origin[1],(int)self->s.origin[2], self->combattarget, target->classname,(int)target->s.origin[0],(int)target->s.origin[1], (int)target->s.origin[2]); } } } if(self->target){ self->goalentity = self->movetarget = G_PickTarget(self->target); if(!self->movetarget){ gi.dprintf("%s can't find target %s at %s\n", self->classname, self->target, vtos(self->s.origin)); self->target = NULL; self->monsterinfo.pausetime = 100000000; self->monsterinfo.stand(self); } else if(strcmp(self->movetarget->classname, "path_corner") == 0){ VectorSubtract(self->goalentity->s.origin, self->s.origin, v); self->ideal_yaw = self->s.angles[YAW] = vectoyaw(v); self->monsterinfo.walk(self); self->target = NULL; } else { self->goalentity = self->movetarget = NULL; self->monsterinfo.pausetime = 100000000; self->monsterinfo.stand(self); } } else { self->monsterinfo.pausetime = 100000000; self->monsterinfo.stand(self); } self->think = monster_think; self->nextthink = level.time + FRAMETIME; }
void func_train_spline_find(edict_t *self) { edict_t *ent; if (!self->target) { gi.dprintf("train_spline_find: no target\n"); return; } ent = G_PickTarget(self->target); if (!ent) { gi.dprintf("train_spline_find: target %s not found\n", self->target); return; } // Lazarus: trains can change speed at path_corners if (ent->speed) { self->speed = ent->speed; self->moveinfo.speed = self->speed; self->moveinfo.accel = self->moveinfo.decel = self->moveinfo.speed; } if (ent->pitch_speed) { self->pitch_speed = ent->pitch_speed; } if (ent->yaw_speed) { self->yaw_speed = ent->yaw_speed; } if (ent->roll_speed) { self->roll_speed = ent->roll_speed; } // Lazarus: spline stuff self->from = self->to = ent; self->target = ent->target; ent->think = train_spline_move; ent->enemy = self; ent->nextthink = level.time + FRAMETIME; VectorSubtract(ent->s.origin, self->mins, self->s.origin); gi.linkentity(self); // if not triggered, start immediately if (!self->targetname) { self->spawnflags |= TRAIN_START_ON; } if (self->spawnflags & TRAIN_START_ON) { // Lazarus: animated trains if (self->spawnflags & TRAIN_ANIMATE) { self->s.effects |= EF_ANIM_ALL; } else if (self->spawnflags & TRAIN_ANIMATE_FAST) { self->s.effects |= EF_ANIM_ALLFAST; } self->nextthink = level.time + FRAMETIME; self->think = train_spline_next; self->activator = self; } }