
Quake DeveLS - Laser HyperBlaster
Author: Mario[RIP]
Difficulty: Easy
Let's make
quake2 more net-firendly !
This code changes the
hyperblaster from spawning a series of 'bolt' projectiles, to firing a series
of green laser beams. The lasers hit their target instantly like the railgun or
machine gun fire.
Just replace the
'fire_blaster' function in g_weapon.c with this:
void fire_blaster (edict_t *self, vec3_t start, vec3_t dir, int damage,int speed, int effect, qboolean hyper){ edict_t *bolt; trace_t tr; vec3_t from; vec3_t end; VectorNormalize (dir); if(effect & EF_BLASTER)// if blaster, spawn blaster bolt { bolt = G_Spawn(); VectorCopy (start, bolt->s.origin); VectorCopy (start, bolt->s.old_origin); vectoangles (dir, bolt->s.angles); VectorScale (dir, speed, bolt->velocity); bolt->movetype = MOVETYPE_FLYMISSILE; bolt->clipmask = MASK_SHOT; bolt->solid = SOLID_BBOX; bolt->s.effects |= effect; VectorClear (bolt->mins); VectorClear (bolt->maxs); bolt->s.modelindex =gi.modelindex("models/objects/laser/tris.md2"); bolt->s.sound = gi.soundindex("misc/lasfly.wav"); bolt->owner = self; bolt->touch = blaster_touch; bolt->nextthink = level.time + 2; bolt->think = G_FreeEdict; bolt->dmg = damage; bolt->classname = "bolt"; gi.linkentity (bolt); if (self->client) check_dodge (self, bolt->s.origin, dir, speed); tr = gi.trace (self->s.origin, NULL, NULL, bolt->s.origin, bolt,MASK_SHOT); if (tr.fraction < 1.0) { VectorMA (bolt->s.origin, -10, dir, bolt->s.origin); bolt->touch (bolt, tr.ent, NULL, NULL); } } else // laser hyperblaster { // set origin of laser beam at gun barrel. // note that the barrel is rotating, so the beams will // originate from different places each time. VectorMA (start, 8192, dir, end); VectorCopy (start, from); // trace for end point of laser beam. // the laser aim is perfect. // no random aim like the machinegun tr = gi.trace (from, NULL, NULL, end, self, MASK_SHOT); // send laser beam temp entity to clients VectorCopy (tr.endpos, from); gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BFG_LASER); gi.WritePosition (start); gi.WritePosition (tr.endpos); gi.multicast (self->s.origin, MULTICAST_PHS); if ((tr.ent != self) && (tr.ent->takedamage)) T_Damage (tr.ent, self, self, dir, tr.endpos, tr.plane.normal,damage, 0, 0, MOD_HYPERBLASTER); else if (!((tr.surface) && (tr.surface->flags & SURF_SKY))) { // hit a brush, send clients // a light flash and sparks temp entity. gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BLASTER); gi.WritePosition (tr.endpos); gi.WriteDir (tr.plane.normal); gi.multicast (self->s.origin, MULTICAST_PVS); } }}
The code
is simple and strait forward. Since the hyperblaster is fired at a very high
speed, so we don't want to waste any of the server's CPU cycles with a more
complicated effect. We also want to use temp entities instead of spawning full
entities to reduce network traffic.
Here Is a break-down of
what was happening before, compared to the new code: PREVIOUS HYPERBLASTER
FIRING ONE ROUND:
LASER HYPERBLASTER FIRING ONE ROUND:
I wrote
this for more reasons than just for grins. The hyperblaster, as it was, was not
very network friendly. It floods clients with info about position changes for
each 'bolt' entity through time. It is also not good for the server. Remember
The server has to do collision testing for every solid entity you spawn.
I read an article on RUST
about making CTF levels, (http://www.planetquake.com/rust/style/ctfstyle.html)
where they commented that the hyperblaster should be put into CTF levels only
sparingly. It would be a tragedy if we had to start throwing away a good gun
because it was causing trouble for the 'bandwidth challenged'. Like me and my
33.6kb modem.
Here are some netgraph
testing results of two people doing a continuous spray of fire from old version
and new version while in same q2ctf5 flag room. Old Hyperblaster's netgraph:
![]()
New Laser Hyperblaster's
netgraph:
![]()
Tutorial by Mario[RIP]
|
This site, and all
content and graphics displayed on it, |