//========================================== // AITools_DrawPath // Draws the current path (floods as hell also) //========================================== void AITools_DrawPath( edict_t *self, int node_to ) { static unsigned int drawnpath_timeout; int count = 0; int pos = 0; //don't draw it every frame (flood) if( level.time < drawnpath_timeout ) return; drawnpath_timeout = level.time + 4 * game.snapFrameTime; if( self->ai->path.goalNode != node_to ) return; pos = self->ai->path.numNodes; // Now set up and display the path while( self->ai->path.nodes[pos] != node_to && count < 32 && pos > 0 ) { edict_t *event; event = G_SpawnEvent( EV_GREEN_LASER, 0, nodes[self->ai->path.nodes[pos]].origin ); event->r.svflags = SVF_TRANSMITORIGIN2; VectorCopy( nodes[self->ai->path.nodes[pos-1]].origin, event->s.origin2 ); G_SetBoundsForSpanEntity( event, 8 ); GClip_LinkEntity( event ); pos--; count++; } }
//========================================== // AITools_DrawLine // Just so I don't hate to write the event every time //========================================== void AITools_DrawLine( vec3_t origin, vec3_t dest ) { edict_t *event; event = G_SpawnEvent( EV_GREEN_LASER, 0, origin ); event->r.svflags = SVF_TRANSMITORIGIN2; VectorCopy( dest, event->s.origin2 ); G_SetBoundsForSpanEntity( event, 8 ); GClip_LinkEntity( event ); }
//========================================== // AITools_DrawColorLine // Just so I don't hate to write the event every time //========================================== void AITools_DrawColorLine( vec3_t origin, vec3_t dest, int color, int parm ) { edict_t *event; event = G_SpawnEvent( EV_PNODE, parm, origin ); event->s.colorRGBA = color; event->r.svflags = SVF_TRANSMITORIGIN2; VectorCopy( dest, event->s.origin2 ); G_SetBoundsForSpanEntity( event, 8 ); GClip_LinkEntity( event ); }
/* * W_Fire_Lasergun */ edict_t *W_Fire_Lasergun( edict_t *self, vec3_t start, vec3_t angles, float damage, int knockback, int stun, int range, int mod, int timeDelta ) { edict_t *laser; qboolean newLaser; trace_t tr; vec3_t dir; if( GS_Instagib() ) damage = 9999; laser = _FindOrSpawnLaser( self, ET_LASERBEAM, &newLaser ); if( newLaser ) { // the quad start sound is added from the server if( self->r.client && self->r.client->ps.inventory[POWERUP_QUAD] > 0 ) G_Sound( self, CHAN_AUTO, trap_SoundIndex( S_QUAD_FIRE ), ATTN_NORM ); } laser_damage = damage; laser_knockback = knockback; laser_stun = stun; laser_attackerNum = ENTNUM( self ); laser_mod = mod; laser_missed = qtrue; GS_TraceLaserBeam( &tr, start, angles, range, ENTNUM( self ), timeDelta, _LaserImpact ); laser->r.svflags |= SVF_FORCEOWNER; VectorCopy( start, laser->s.origin ); AngleVectors( angles, dir, NULL, NULL ); VectorMA( laser->s.origin, range, dir, laser->s.origin2 ); laser->think = G_Laser_Think; laser->nextThink = level.time + 100; if( laser_missed && self->r.client ) G_AwardPlayerMissedLasergun( self, mod ); // calculate laser's mins and maxs for linkEntity G_SetBoundsForSpanEntity( laser, 8 ); GClip_LinkEntity( laser ); return laser; }
//QUAKED target_laser (0 .5 0) (-8 -8 -8) (8 8 8) START_ON RED GREEN BLUE YELLOW ORANGE FAT //When triggered, fires a laser. You can either set a target or a direction. //-------- KEYS -------- //angles: alternate "pitch, yaw, roll" angles method of aiming laser (default 0 0 0). //target : point this to a target_position entity to set the laser's aiming direction. //targetname : the activating trigger points to this. //notsingle : when set to 1, entity will not spawn in Single Player mode //notfree : when set to 1, entity will not spawn in "Free for all" and "Tournament" modes. //notduel : when set to 1, entity will not spawn in "Teamplay" and "CTF" modes. (jal: todo) //notteam : when set to 1, entity will not spawn in "Teamplay" and "CTF" modes. //notctf : when set to 1, entity will not spawn in "Teamplay" and "CTF" modes. (jal: todo) //-------- SPAWNFLAGS -------- //START_ON : when set, the laser will start on in the game. //RED : //GREEN : BLUE : //YELLOW : //ORANGE : //FAT : static void target_laser_think( edict_t *self ) { edict_t *ignore; vec3_t start; vec3_t end; trace_t tr; vec3_t point; vec3_t last_movedir; int count; // our lifetime has expired if( self->delay && ( self->wait * 1000 < level.time ) ) { if( self->r.owner && self->r.owner->use ) G_CallUse( self->r.owner, self, self->activator ); G_FreeEdict( self ); return; } if( self->spawnflags & 0x80000000 ) count = 8; else count = 4; if( self->enemy ) { VectorCopy( self->moveinfo.movedir, last_movedir ); VectorMA( self->enemy->r.absmin, 0.5, self->enemy->r.size, point ); VectorSubtract( point, self->s.origin, self->moveinfo.movedir ); VectorNormalize( self->moveinfo.movedir ); if( !VectorCompare( self->moveinfo.movedir, last_movedir ) ) self->spawnflags |= 0x80000000; } ignore = self; VectorCopy( self->s.origin, start ); VectorMA( start, 2048, self->moveinfo.movedir, end ); VectorClear( tr.endpos ); // shut up compiler while( 1 ) { G_Trace( &tr, start, NULL, NULL, end, ignore, MASK_SHOT ); if( tr.fraction == 1 ) break; // hurt it if we can if( ( game.edicts[tr.ent].takedamage ) && !( game.edicts[tr.ent].flags & FL_IMMUNE_LASER ) ) { if( game.edicts[tr.ent].r.client && self->activator->r.client ) { if( !GS_TeamBasedGametype() || game.edicts[tr.ent].s.team != self->activator->s.team ) G_Damage( &game.edicts[tr.ent], self, self->activator, self->moveinfo.movedir, self->moveinfo.movedir, tr.endpos, self->dmg, 1, 0, 0, self->count ); } else { G_Damage( &game.edicts[tr.ent], self, self->activator, self->moveinfo.movedir, self->moveinfo.movedir, tr.endpos, self->dmg, 1, 0, 0, self->count ); } } // if we hit something that's not a monster or player or is immune to lasers, we're done if( !game.edicts[tr.ent].r.client ) { if( self->spawnflags & 0x80000000 ) { edict_t *event; self->spawnflags &= ~0x80000000; event = G_SpawnEvent( EV_LASER_SPARKS, DirToByte( tr.plane.normal ), tr.endpos ); event->s.eventCount = count; event->s.colorRGBA = self->s.colorRGBA; } break; } ignore = &game.edicts[tr.ent]; VectorCopy( tr.endpos, start ); } VectorCopy( tr.endpos, self->s.origin2 ); G_SetBoundsForSpanEntity( self, 8 ); GClip_LinkEntity( self ); self->nextThink = level.time + 1; }