QuakeC from Scratch tutorials - Chapter 4: The golden mirror...
Created By: | Ender |
eMail: | ender@admdev.com |
Difficulty Scale: | Hard |
- Id1 C:\quake |- Scratch - / Weapons / Entities |- Blah \ Source-|----------- |- Blah \ Monsters \ Effects |- Blah - BlahInside this, create a new file. Once again, you will want to add the customary headers. Call this file, 'Chasecam.QC' and place the following code inside it:
/* +--------+ |Chasecam| +--------+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ | Scratch Http://www.admdev.com/scratch | +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ | Simple Chasecam. Follows player for above and back slightly. Impulse 100 | +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ */ .entity camera; // Chasecam Entity void() Chasecam_Update; // From Chasecam.QC void() Chasecam_On = { self.camera = spawn(); // Create a new Camera entity self.camera.classname = "camera"; // This is a Camera self.camera.movetype = MOVETYPE_NONE; // No movetype self.camera.solid = SOLID_NOT; // Not solid. setmodel(self.camera, "progs/s_bubble.spr"); setsize(self.camera, '0 0 0', '0 0 0'); // Has no size. Chasecam_Update(); // Update cam stuffcmd(self, "r_drawviewmodel 0\ncl_bob 0\ncl_rollangle 0\nv_kickpitch 0\nv_kickroll 0\n"); SetViewPoint(self.camera); }; void() Chasecam_Off = { stuffcmd(self, "r_drawviewmodel 1\ncl_bob 0.02\ncl_rollangle 2.0\nv_kickpitch 0.6\nv_kickroll 0.6\n"); SetViewPoint(self); remove(self.camera); }; void() Chasecam_Update = { local vector camera_origin; if (!self.camera) return; makevectors (self.v_angle); traceline (self.origin + self.view_ofs, self.origin + (self.view_ofs * 2) + (v_forward * -64) + (v_up * -6), 0, self); camera_origin_x = trace_endpos_x; camera_origin_y = trace_endpos_y; camera_origin_z = trace_endpos_z - self.view_ofs_z; camera_origin = camera_origin + trace_plane_normal; setorigin (self.camera, camera_origin); }; void() ChaseCam_Toggle = // Toggle Chasecam on/off { if (!self.camera) {Chasecam_On();} else {Chasecam_Off();} };Add this file (Effects/Chasecam.QC) to the bottom of PROGS.SRC.
precache_model("progs/s_bubble.spr");with the other precache.
void(entity ent) SetViewPoint = // Alter the Viewpoint Entity { msg_entity = self; // This message is to myself. WriteByte(1, SVC_SETVIEW); // Network Protocol: Set Viewpoint Entity WriteEntity(1, ent); // Write entity to clients. };This small function act's by using the Quake Network Protocol. SVC number 5, SVC_SETVIEW, is not defined in the usual defs.qc, but is in the one included with Scratch.
void() PlayerPreThink = {CheckImpulses(); Chasecam_Update();};Also at the top of Client.QC, after the header, add the prototype:
void() Chasecam_Update; // From Chasecam.QCRemember from earlier that the Quake Compiler (QCC) doesn't know about this function yet, as Chasecam.QC comes later in the progs.src CheckImpulses? Yes. Now you come to the last point for this tutorial. All Quake players and coders know about impulses. They are those little things you type from the console to call special functions of Quake mod's.. and even.. *gasp* CHEAT!
/* +--------+ |Impulses| +--------+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ | Scratch Http://www.admdev.com/scratch | +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ | Handle and execute "Impulse" commands - as entered from console. | +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+ */ void() CheckImpulses = { if (self.impulse == 100) {ChaseCam_Toggle();} // If Impulse 100, toggle cam self.impulse = 0; // Clear impulse list. };Very simple. Waiting impulses are help in self.impulse. Here we check the value of this. If it equals 100, turn on the chasecam. After the Impulse has been handled, we reset self.impulse to 0 so we can get the next Impulse command.