home *** CD-ROM | disk | FTP | other *** search
- /*
- DemoCam QC mod by Harlequin (dtebben@alumni.caltech.edu). See the
- democam.txt file for info on how to use -- it's a bit confusing.
- The intermission and top-dog cams are broken and possibly not fixable.
- If you have any luck, please drop me a line.
- */
-
- float SVC_SETVIEWPORT = 5;
- void() W_SetCurrentAmmo;
-
- //#Harlequin# Turns off the democam (back to first-person in the demo)
- void(entity CamClient) DemoCamStop =
- {
- if (!CamClient.HAS_DEMOCAM)
- return;
-
- msg_entity = CamClient;
- WriteByte(MSG_ONE, SVC_SETVIEWPORT);
- WriteEntity(MSG_ONE, CamClient);
- CamClient.HAS_DEMOCAM = 0;
- CamClient.VIEW_ON_DEMOCAM = 0;
- W_SetCurrentAmmo();
- };
-
-
- //#Harlequin# FindTopDog returns the player with the most frags.
- entity(entity oldtopdog) FindTopDog =
- {
- local entity topdog, searchent;
-
- topdog = oldtopdog;
- searchent = findradius(oldtopdog.origin, 100000);
- while (searchent)
- {
- if (searchent.classname == "player")
- {
- if (searchent.frags > topdog.frags)
- topdog = searchent;
- }
- searchent = searchent.chain;
- }
- return topdog;
- };
-
- //#Harlequin# FindIntermissionCam returns the intermission spot with
- //the most players in view.
- entity() FindIntermissionCam =
- {
- local entity newintercam, searchent, searchent2;
- local float playercount, bestplayercount;
-
- searchent = find(world, classname, "info_intermission");
- while (searchent)
- {
- searchent2 = find(world, classname, "player");
- while (searchent2)
- {
- traceline(searchent.origin, searchent2.origin, TRUE, searchent);
- if (trace_fraction == 1)
- playercount = playercount + 1;
- searchent2 = find(searchent2, classname, "player");
- }
- if (playercount > bestplayercount)
- {
- newintercam = searchent;
- bestplayercount = playercount;
- }
- playercount = 0;
- searchent = find(searchent, classname, "info_intermission");
- }
-
- //#Harlequin# If there are no players within LOS of an intermission
- //camera, switching to it screws everything up. Therefore wait until
- //someone can be seen before switching.
- if (bestplayercount > 0)
- return newintercam;
- else
- return world;
-
-
- //#Harlequin# If no intermission spots, look for player_start
- searchent = find(world, classname, "info_player_start");
- if (searchent)
- return searchent;
-
- //#Harlequin# For funky maps with no player_start
- searchent = find(world, classname, "testplayerstart");
- if (searchent)
- return searchent;
-
- //#Harlequin# This shouldn't ever happen
- objerror ("FindIntermissionCam: no spot");
- };
-
-
- //#Harlequin# The think routine for intermission cams.
- void() IntermissionCamThink =
- {
- local entity newintercam;
-
- //#Harlequin# Finds a new spot every 10 seconds.
- self.nextthink = time + 0.1;
-
- if (self.INTER_TIME < time)
- {
- newintercam = FindIntermissionCam();
-
- if (newintercam != world)
- {
- setorigin(self, newintercam.origin);
- self.INTER_TIME = time + 10;
- self.angles = self.v_angle = newintercam.mangle;
- }
- }
- };
-
-
- //#Harlequin# Chase cam tracking code lifted wholesale from Eli
- //(apathas@mailhost.primenet.com)'s excellent ChaseCam mod in kuaqe2.
- //Only minor changes (except the TopDog stuff).
- void() DemoCamTrack =
- {
- local vector spot2,
- dir;
- local float dist,
- cap;
- local entity topdogtest;
-
- //#Harlequin# Stop recording in intermissions, or else funny things
- //will happen to the demo. Anybody know how to fix this?
- //#Harlequin# Note that self.owner is whoever it's following, but
- //self.DEMOCAM is the person recording the demo. Here, top_dog_time
- //is actually a brief delay so the scores are included in the demo.
- if ((self.owner.movetype == MOVETYPE_NONE) && (self.owner.health > 0))
- {
- if ((self.TOP_DOG_TIME > time + 3) && (self.TOP_DOG_TIME < time + 10))
- {
- stuffcmd(self.DEMOCAM, "stop\n");
- DemoCamStop(self.DEMOCAM);
- }
- else if (self.TOP_DOG_TIME < time + 3)
- self.TOP_DOG_TIME = time + 12;
- }
-
- self.nextthink = time + 0.1;
-
- //#Harlequin# The basic routine for TopDogChaseCams. It only checks
- //every 2 seconds because: 1) it could get confusing otherwise and
- //2) very frequent calls of FindRadius can slow down the server.
- //Note that self.owner is just who it happens to be following.
- if ((self.TOP_DOG_TIME) && (self.TOP_DOG_TIME < time))
- {
- self.TOP_DOG_TIME = time + 2;
- topdogtest = FindTopDog(self.owner);
- if (topdogtest != self.owner)
- {
- self.owner = topdogtest;
- self.origin = self.owner.origin;
- }
- }
-
- makevectors (self.owner.v_angle);
-
- // Set initial spot before clipping, compensating for looking up
- // and down so the player doesn't block the view
- spot2 = self.owner.origin - (v_forward * self.ammo_shells);
- spot2_z = spot2_z + 16;
-
- if (self.owner.v_angle_x < 0)
- spot2 = spot2 - self.owner.v_angle_x * 0.6 * v_up;
- if (self.owner.v_angle_x > 0)
- spot2 = spot2 + self.owner.v_angle_x * 0.6 * v_up;
-
- traceline (self.owner.origin, spot2, TRUE, self.owner);
- self.ammo_shells = vlen (trace_endpos - self.owner.origin);
- spot2 = trace_endpos + (v_forward * 2);
-
- traceline (spot2, spot2 + '0 0 32', TRUE, self.owner );
- if (trace_fraction < 1 )
- spot2 = trace_endpos - '0 0 32';
-
- dir = normalize (spot2 - self.origin);
- dist = vlen (spot2 - self.origin);
-
- traceline (self.origin, spot2, TRUE, self.owner);
- if (trace_fraction == 1)
- {
- self.angles = self.owner.angles;
- cap = dist * 0.2;
-
- if (cap > 5.2)
- self.velocity = dir * dist * 5.2;
- else if (cap > 1)
- self.velocity = dir * dist * cap;
- else
- self.velocity = dir * dist;
-
- if ((vlen(self.owner.origin - self.origin)) < 30)
- {
- self.velocity = self.velocity * 2;
- }
- }
- else
- setorigin (self, spot2);
-
- self.ammo_shells = self.ammo_shells + 4;
-
- if (self.ammo_shells > 72)
- self.ammo_shells = 72;
-
- // respawn if missile ent. get's hung up
- if (self.oldorigin == self.origin)
- {
- if (dist > 30)
- self.ammo_nails = self.ammo_nails + 1;
- }
-
- if (self.ammo_nails > 3)
- {
- self.origin = self.owner.origin;
- return;
- }
-
- self.oldorigin = self.origin;
- };
-
- //#Harlequin# The next function initializes the DemoCam. Also taken
- //mostly from Eli's code. CamClient is the person activating it.
- void(entity CamClient, float camtype) DemoCamStart =
- {
- local entity DemoCam;
-
- msg_entity = CamClient;
-
- //#Harlequin# Get rid of the old democam, if it exists
- if(CamClient.HAS_DEMOCAM)
- {
- WriteByte(MSG_ONE, SVC_SETVIEWPORT);
- WriteEntity(MSG_ONE, CamClient);
- remove(CamClient.DEMOCAM);
- CamClient.HAS_DEMOCAM = 0;
- CamClient.VIEW_ON_DEMOCAM = 0;
- }
- DemoCam = spawn();
- DemoCam.solid = SOLID_NOT;
- DemoCam.movetype = MOVETYPE_FLYMISSILE;
- DemoCam.owner = CamClient;
- DemoCam.angles = DemoCam.owner.angles;
-
- //#Harlequin# This is confusing, but it just gives the camera & client
- //references to one another.
- DemoCam.owner.DEMOCAM = DemoCam;
- DemoCam.DEMOCAM = CamClient;
-
- DemoCam.owner.HAS_DEMOCAM = 1;
- setmodel(DemoCam, "progs/s_bubble.spr");
- //#Harlequin# Uncomment the next line to use the null sprite instead,
- //but remember to uncomment the precaching line in weapons.qc also
- // setmodel(DemoCam, "null.spr");
- setsize(DemoCam, '0 0 0', '0 0 0');
- setorigin(DemoCam, DemoCam.owner.origin);
- DemoCam.nextthink = time;
- if (camtype != 3) //#Harlequin# All except intermission cam
- DemoCam.think = DemoCamTrack;
- else
- DemoCam.think = IntermissionCamThink;
- if (camtype == 2)
- DemoCam.TOP_DOG_TIME = time;
-
- //#Harlequin# Switch the view to cam & back rapidly. The aliases
- //are to mark the demo -- read the readme!
- WriteByte(MSG_ONE, SVC_SETVIEWPORT);
- WriteEntity(MSG_ONE, DemoCam);
- stuffcmd(CamClient, "alias disconnect\n");
- WriteByte(MSG_ONE, SVC_SETVIEWPORT);
- WriteEntity(MSG_ONE, DemoCam.owner);
- stuffcmd(CamClient, "alias disconnect\n");
- if (!CamClient.SHOW_WEAPONMODELS)
- CamClient.weaponmodel = string_null;
- };
-
-
- //#Harlequin# DemoCamViewOn works only if the player is within line-of-
- //sight of his democam. It does not continue to check for LOS after
- //activation, but being unable to see your own character is unlikely to
- //provide any advantage in a deathmatch :-).
- void(entity CamClient) DemoCamViewOn =
- {
- if (!CamClient.HAS_DEMOCAM)
- return;
-
- // traceline(CamClient.origin, CamClient.DEMOCAM.origin, TRUE, CamClient);
- // if (trace_fraction == 1)
- {
- msg_entity = CamClient;
- WriteByte(MSG_ONE, SVC_SETVIEWPORT);
- WriteEntity(MSG_ONE, CamClient.DEMOCAM);
- CamClient.VIEW_ON_DEMOCAM = 1;
- }
- };
-
- //#Harlequin# Similar to the same code in the start function. The
- //aliasing stuff marks the demo.
- void(entity CamClient) DemoCamViewOff =
- {
- msg_entity = CamClient;
- WriteByte(MSG_ONE, SVC_SETVIEWPORT);
- WriteEntity(MSG_ONE, CamClient.DEMOCAM);
- stuffcmd(CamClient, "alias disconnect\n");
- WriteByte(MSG_ONE, SVC_SETVIEWPORT);
- WriteEntity(MSG_ONE, CamClient);
- stuffcmd(CamClient, "alias disconnect\n");
- CamClient.VIEW_ON_DEMOCAM = 0;
- };