Forum

Demos on the map

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

Demos on the map

Postby Max_Salivan » Tue Jan 17, 2012 2:12 pm

Hello,how to do demo(.dem) trigger on the map?

Code: Select all
/* QUAKED trigger_demo
 test cutscene
*/
void() demo_touch =
{
        if (other.classname != "player")
                return;
};

void() trigger_demo=
{
        InitTrigger ();
        self.classname ="demo";
        self.touch = demo_touch;
        if(other.classname != "player") 
      stuffcmd (self, "playdemo qwe\n");
};


please help me=\
Sorry for my english :)
Max_Salivan
 
Posts: 93
Joined: Thu Dec 15, 2011 1:00 pm

Re: Demos on the map

Postby dr_mabuse » Tue Jan 17, 2012 5:44 pm

Is that from the Quake mod "Zerstörer"?
Thats the only mod i know with ingame cutscenes...
User avatar
dr_mabuse
 
Posts: 80
Joined: Sat Sep 03, 2011 6:07 pm

Re: Demos on the map

Postby Max_Salivan » Tue Jan 17, 2012 7:05 pm

no,i dont know this mode=\
Sorry for my english :)
Max_Salivan
 
Posts: 93
Joined: Thu Dec 15, 2011 1:00 pm

Re: Demos on the map

Postby kanyka » Tue Jan 17, 2012 8:26 pm

in hexen 2 was some cutscenes.
kanyka
 
Posts: 1
Joined: Tue Jan 17, 2012 8:11 pm

Re: Demos on the map

Postby leileilol » Wed Jan 18, 2012 12:59 am

Zerstorer's cutscenes were just straight up QC functions I think

YPOD and Malice had demos for cutscenes

Hexen2 only has a video file in the installer, no actual cutscenes other than the QC scripted intro for Portals
i should not be here
leileilol
 
Posts: 2783
Joined: Fri Oct 15, 2004 3:23 am

Re: Demos on the map

Postby Dr. Shadowborg » Wed Jan 18, 2012 5:07 pm

Change your code so it is as below:

Code: Select all
/* QUAKED trigger_demo
 test cutscene
*/
void() demo_touch =
{
        if (other.classname != "player")
                return;

        stuffcmd (other, "playdemo qwe\n");
};

void() trigger_demo=
{
        InitTrigger ();
        self.classname ="demo";
        self.touch = demo_touch;
};


Bear in mind however, that if you play a demo from a map, it won't return you to the map where you triggered the demo when it gets done playing.

If you want ingame cutscenes you'll need to impliment the cutscene code from Zerstorer.
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Re: Demos on the map

Postby dr_mabuse » Wed Jan 18, 2012 5:33 pm

so, lets say i trigger a demo at the end of my E1M1 custom-map and the demo is finished with playing, i will directly go to E1M2 (or any map i assigned to my changelevel trigger)?
User avatar
dr_mabuse
 
Posts: 80
Joined: Sat Sep 03, 2011 6:07 pm

Re: Demos on the map

Postby Max_Salivan » Wed Jan 18, 2012 6:57 pm

Dr. Shadowborg wrote:Change your code so it is as below:

Code: Select all
/* QUAKED trigger_demo
 test cutscene
*/
void() demo_touch =
{
        if (other.classname != "player")
                return;

        stuffcmd (other, "playdemo qwe\n");
};

void() trigger_demo=
{
        InitTrigger ();
        self.classname ="demo";
        self.touch = demo_touch;
};


Bear in mind however, that if you play a demo from a map, it won't return you to the map where you triggered the demo when it gets done playing.

If you want ingame cutscenes you'll need to impliment the cutscene code from Zerstorer.



but Zerstorer cutscene code dont use demos=\
Code: Select all
void() DHM_CalcMoveDone;
void() move_camera;

/* ============================================ */
/* |        Movie camera trigger  - dhm       | */
/* ============================================ */


void(entity o) spawn_dummy =
{
local entity   s;

   s = spawn ();
   s.origin = o.origin;
   s.velocity = o.velocity;
   s.angles = o.angles;
   s.health = o.health;
   s.weapon = o.weapon;
   s.classname = "dummy";
   s.movetype = MOVETYPE_NONE;
   s.solid = SOLID_NOT;
   s.weaponmodel = o.weaponmodel;
   s.flags = o.flags;
   s.effects = o.effects;
   s.items = o.items;
   s.items2 = o.items2;

   if (o.invincible_finished > time)
      s.invincible_finished = o.invincible_finished - time;
   else o.invincible_finished = 0;
   if (o.invisible_finished > time)
      s.invisible_finished = o.invisible_finished - time;
   else o.invisible_finished = 0;
   if (o.super_damage_finished > time)
      s.super_damage_finished = o.super_damage_finished - time;
   else o.super_damage_finished = 0;
   if (o.radsuit_finished > time)
      s.radsuit_finished = o.radsuit_finished - time;
   else o.radsuit_finished = 0;
   if (o.wing_finished > time)
      s.wing_finished = o.wing_finished - time;
   else o.wing_finished = 0;
   if (o.invincible_time == 1)
      s.invincible_time = 1;
   else if (o.invincible_time > 1)
      s.invincible_time = o.invincible_time - time;
   else o.invincible_time = 0;
   if (o.invisible_time == 1)
      s.invisible_time = 1;
      else if (o.invisible_time > 1)
      s.invisible_time = o.invisible_time - time;
   else o.invisible_time = 0;
   if (o.super_time > time)
      s.super_time = 1;
   else if (o.super_time > 1)
      s.super_time = o.super_time - time;
   else o.super_time = 0;
   if (o.rad_time == 1)
      s.rad_time = 1;
   else if (o.rad_time > 1)
      s.rad_time = o.rad_time - time;
   else o.rad_time = 0;
   if (o.wing_time == 1)
      s.wing_time = 1;
   else if (o.wing_time > 1)
      s.wing_time = o.wing_time - time;
   else o.wing_time = 0;

   setorigin (s, o.origin);
};

void() name_player =
{
local entity play;

   self.owner.classname = "player";
   stuffcmd(self.owner, "-forward\n");
   remove(self);
};

void() go_back =
{
local entity   t,c,d,cvars,old;
local vector   org;
local string   val;

   t = find (world, classname, "dummy");
   if (!t)
      objerror ("couldn't find dummy");

   c = find (world, classname, "camera");
   if (!c)
      objerror ("couldn't find camera");

   setorigin (c, t.origin);
   c.velocity = t.velocity;
   c.view_ofs = '0 0 22';
   c.angles_x = t.angles_x;
   c.angles_y = t.angles_y;
   c.angles_z = 0;
   c.health = t.health;
   c.weapon = t.weapon;
   c.weaponframe = 0;
   c.weaponmodel = t.weaponmodel;
   c.flags = t.flags;
   c.effects = t.effects;
   c.items = t.items;
   c.items2 = t.items2;

   if (t.invincible_finished > 0)
      c.invincible_finished = time + t.invincible_finished;
   if (t.invisible_finished > 0)
      c.invisible_finished = time + t.invisible_finished;
   if (t.super_damage_finished > 0)
      c.super_damage_finished = time + t.super_damage_finished;
   if (t.radsuit_finished > 0)
      c.radsuit_finished = time + t.radsuit_finished;
   if (t.wing_finished > 0)
      c.wing_finished = time + t.wing_finished;
   if (t.invincible_time > 0)
      c.invincible_time = time + t.invincible_time;
   if (t.invisible_time > 0)
      c.invisible_time = time + t.invisible_time;
   if (t.super_time > 0)
      c.super_time = time + t.super_time;
   if (t.rad_time > 0)
      c.rad_time = time + t.rad_time;
   if (t.wing_time > 0)
      c.wing_time = time + t.wing_time;

   c.fixangle = 1;      // turn this way immediately
   c.takedamage = DAMAGE_AIM;
   c.solid = SOLID_SLIDEBOX;
   c.movetype = MOVETYPE_WALK;
   c.think = SUB_Null;
   c.air_finished = time + 12;  // No gasping from you!

/* If you change the classname during this frame, then the
   'find' command ABOVE will fail, so set a timer to change
   the classname back to player.  [grrrrr, I spent way too
   long figuring that out.] */
   d = spawn();
   d.nextthink = time + 0.01;
   d.owner = c;
   d.think = name_player;

/* Look for any CVARSET entities to restore old cvars that
   were changed for the cut-scene */
   if(c.ideal_yaw == -1)
   {
     cvars = find(world, classname, "cvar_done");
     while(cvars != world)
     {
      if(!cvars.message)
         cvars.message = cvars.model;
      cvar_set (cvars.netname, cvars.script);
      old = cvars;
      cvars = find(cvars, classname, "cvar_done");
      remove(old);
     }
     c.ideal_yaw = 0;
   }

   val = ftos (c.cnt);
   cvar_set ("viewsize", val);     //restore old viewsize
   stuffcmd(c, "sizedown\nsizeup\n");    //hack-fix for GLquake

   t.nextthink = time + 0.1;
   t.think = SUB_Remove;
   remove(self);
};

/* This routine short-circuits player turning and movement while
     in camera mode.  self.oldorigin is used as self.angles, and
     self.mangle is used as self.velocity.  This allows me to
     compute these figures in code, and overwrite what the game
     thinks they should be.  Called from 'client.qc'.
*/
void() look_ahead =
{
local vector    v_ang, looky;

   self.angles = self.oldorigin;
   self.velocity = self.mangle;
   self.fixangle = 1;
   cvar_set ("viewsize", "120");      //keep screen maximized
   if (self.delay == 0)
   {
      looky_x = self.movedir_x - self.origin_x;
      looky_y = self.movedir_y - self.origin_y;
      looky_z = self.origin_z - self.movedir_z;
      self.oldorigin = vectoangles (looky);
   }
};

// This is a modified SUB_CalcMove routine.
void(vector tdest, float tspeed, entity cam) DHM_CalcMove =
{
local vector   vdestdelta;
local float      len, traveltime;

   self.finaldest = tdest;
   self.think = DHM_CalcMoveDone;

   if (tdest == cam.origin)
   {
      cam.velocity = cam.mangle = '0 0 0';
      self.nextthink = time + 0.01;
      return;
   }
      
// set destdelta to the vector needed to move
   vdestdelta = tdest - cam.origin;
   
// calculate length of vector
   len = vlen (vdestdelta);
   
// divide by speed to get time to reach dest
   traveltime = len / tspeed;

   if (traveltime < 0.1)
   {
      cam.velocity = cam.mangle = '0 0 0';
      self.nextthink = time + 0.01;
      return;
   }
   
// set nextthink to trigger a think when dest is reached
   self.nextthink = time + traveltime;

// scale the destdelta vector by the time spent traveling to get velocity
   cam.velocity = cam.mangle = vdestdelta * (1/traveltime);
};

void() wait_camera =
{
   if(!self.wait)
   {
      move_camera();
      return;
   }
   
   self.nextthink = time + self.wait;
   self.think = move_camera;
};

/*
============
After moving, set origin to exact final destination
============
*/
void() DHM_CalcMoveDone =
{
   if(self.enemy.classname != "camera")
   {
      remove(self);
      return;
   }

   setorigin(self.enemy, self.finaldest);
   self.enemy.velocity = self.enemy.mangle = '0 0 0';

   if (self.cnt == -1)
   {
      remove(self);
      return;
   }

   self.nextthink = time + 0.01;
   self.think = wait_camera;

};

void() move_camera =
{
local entity   cpt,fpt;
local vector   looky;

   if(self.enemy.classname != "camera")
   {
      remove(self);
      return;
   }

   cpt = find (world, targetname, self.target);
   if (!cpt.target)     //if this is the end of the line, stop camera
   {
      self.think = SUB_Null;
      self.enemy.velocity = '0 0 0';
      self.enemy.mangle = '0 0 0';     //mangle == velocity in cut-scene
      DHM_CalcMoveDone();
      self.cnt = -1;   // remove control entity in DHM_CalcMoveDone
      //return;
   }
   if(cpt.focal_point)   //is there a new focal point?
   {
      fpt = find (world, targetname, cpt.focal_point);
      if(!fpt)
         objerror("Couldn't find new focal point!");
      
      self.enemy.movedir = fpt.origin;
      looky_x = self.enemy.movedir_x - self.enemy.origin_x;
      looky_y = self.enemy.movedir_y - self.enemy.origin_y;
      looky_z = self.enemy.origin_z - self.enemy.movedir_z;
      self.enemy.oldorigin = vectoangles (looky);
      self.enemy.angles = self.enemy.oldorigin;    //oldorigin == angles in CS
   }
// Check for auto-focus or still camera angle
   if (cpt.delay)
      self.enemy.delay = cpt.delay;
   else
      self.enemy.delay = 0;

   self.target = cpt.target;
   self.wait = cpt.wait;
   if(cpt.speed)
      self.speed = cpt.speed;
   DHM_CalcMove (cpt.origin, self.speed, self.enemy);   
};

void() go_camera =
{
local entity   control;
local vector   looky;

// Change the player into a camera
   self.classname = "camera";
   self.velocity = '0 0 0';
   self.view_ofs = '0 0 0';

   looky_x = self.movedir_x - self.enemy.origin_x;
   looky_y = self.movedir_y - self.enemy.origin_y;
   looky_z = self.enemy.origin_z - self.movedir_z;
   self.oldorigin = vectoangles (looky);
   self.angles = self.oldorigin;      //oldorigin == angles in CS

// Check if camera is auto-focus or not
   if (self.enemy.delay)
      self.delay = self.enemy.delay;
   else
      self.delay = 0;

   self.velocity = self.mangle = '0 0 0';

   self.dmg = 0;
   self.fixangle = 1;      // turn this way immediately
   self.movetype = MOVETYPE_NOCLIP;
   self.takedamage = DAMAGE_NO;
   //self.solid = SOLID_NOT;
   self.effects = 0;
   self.items = 0;
   self.weaponmodel = "";

// Spawn a control function to handle moving the camera
   if(self.enemy.target)
   {
      control = spawn();
      control.classname = "camcontrol";
      control.enemy = self;
      control.target = self.enemy.target;
      control.speed = self.enemy.speed;
      control.nextthink = time + self.enemy.wait + 0.05;
      control.think = move_camera;
   }
 
//Setting script_count to 0 is what triggers the script to play,
//  It will then play the script number.
   if (!self.script)
      dprint ("trigger_camera needs a script number!");
   self.script_count = 0;

//Save current viewscreen size to return to after camera.
   self.cnt = cvar("viewsize");
   cvar_set ("viewsize", "120");    //Full screen
   stuffcmd(self, "sizedown\nsizeup\n");   //hack-fix for GLquake

   setorigin (self, self.enemy.origin);
};

void() camera_touch =
{
local entity   t,fpt;

   if (self.targetname)
   {
      if (self.nextthink < time)
      {
         return;      // not fired yet
      }
   }

// only activate for player, 1st time touched
   if (other.health <= 0 || other.classname != "player" || self.cnt == -1)
      return;

//If player is on ground, take him off ground so no one gets confused
   if (other.flags & FL_ONGROUND)
       other.flags = other.flags - FL_ONGROUND;

// put a dummy where the player was
   spawn_dummy (other);

// find camera
   t = find (world, targetname, self.target);
   while ((t != world) && (t.classname != "info_movie_camera"))
      t = find (t, targetname, self.target);
   if (!t)
      objerror ("couldn't find target");

// find focal point
   fpt = find (world, targetname, self.focal_point);
   if (!fpt)
      objerror ("You must have a focal point!\n");
   else
      other.movedir = fpt.origin;   //movedir used to calc focal dir
         
// Go to the camera - not in this function, because touch functions are
// called while looping through c code, and you don't want to move the
// player, or something like that?
   other.enemy = t;      //save camera position, etc.
   other.script = self.script;   //save script number
   other.script_delay = self.script_delay;  //save delay for page 1

   fpt = self;
   self = other;
   go_camera ();
   self = fpt;   

   activator = self;
   SUB_UseTargets();
   self.cnt = -1;  //used to make sure only one dummy is spawned

//Remove the trigger_camera from level
   self.nextthink = time + 0.1;
   self.think = SUB_Remove;
};

/*QUAKED info_movie_camera (.5 .5 .5) (-8 -8 -8) (8 8 32)
This is the destination marker for a camera.  It should have a "targetname" field with the same value as a camera-trigger's "target" field.
*/
void() imc_touch =
{
local string temps;

   if (other.classname != "camera")
      return;
   temps = self.target;
   self.target = self.message;
   SUB_UseTargets();
   self.target = temps;
   if (self.cnt)
      return;

   self.think = SUB_Remove;
   self.nextthink = time + 10;
   self.solid = SOLID_NOT;
};

void() info_movie_camera =
{
// this does nothing, just serves as a target spot
   //self.use = SUB_Null;
   self.solid = SOLID_TRIGGER;
   setorigin(self, self.origin);
   setsize(self, '-8 -8 -8', '8 8 8');
   self.touch = imc_touch;
};

void() camera_use =
{
   self.nextthink = time + 100000;
   force_retouch = 2;      // make sure even still objects get hit
   self.think = SUB_Null;
};

void() gocam_use =
{
local entity   control, temp;

   control = find(world, classname, "camcontrol");
   if (control == world)
      dprint("Can't find camcontrol!\n");

   temp = self;
   self = control;
   DHM_CalcMoveDone ();
   self = temp;
   self.nextthink = time + 0.1;
   self.think = SUB_Remove;
};

void() trigger_gocamera =
{
   self.use = gocam_use;
};

/*QUAKED info_focal_point (.5 .5 .5) (-8 -8 -8) (8 8 32)
This is the point that the camera will face.  It should have a "targetname"
field with the same value as a camera-trigger's "focal_point" field.
*/
void() info_focal_point =
{
// just holds a spot for the focal point.
};

/*QUAKED trigger_camera (.5 .5 .5) ?
A player touching this will be transported to the corresponding info_movie_camera entity. You must set the "target" field, and put a info_movie_camera with a "targetname" field that matches.  The "script" key gives a starting script number, and the "script_delay" key is the amount of time(seconds) to stay on the first script page.

If the trigger_camera has a targetname, it will only enter camera mode after it has been fired.
*/
void() trigger_camera =
{
   if (deathmatch || coop)
      remove (self);

   InitTrigger ();
   self.touch = camera_touch;
   // find the destination
   if (!self.target)
      objerror ("Camera trigger with no target");
   self.use = camera_use;
};


/* ----------------------------------
        Scripting function - dhm
   ---------------------------------- */
/* The original timing idea for scripts was inspired by
   Zoid.  Study the code for Zoid's CTF, it is an
   excellent example of good Quake-C coding.  Also
   look at all of Quake Command's stuff.  Wedge rules.
*/
// Script_play is called from PlayerPreThink()
// 'self' is the player (camera)

void() Script_play =
{
local entity   scrpt, temp;
   
   scrpt = find (world, script_num, self.script); 
   if (!scrpt)
      dprint ("Error: script not found!");

   /** if script has a target, trigger it once. **/
   if (scrpt.target)
   {
      temp = self;
      self = scrpt;
      SUB_UseTargets ();
      self.target = string_null;
      self = temp;
   }

   self.script_delay = scrpt.script_delay;
   self.script_time = time + 1;
   self.script_count = self.script_count + 1;
   centerprint(self, scrpt.message);

   if (self.script_count == self.script_delay)
   {
      self.script = scrpt.next_script;
      if (self.script != "0")
          self.script_count = 0;
      else
        {
       scrpt.nextthink = time + 3;
       scrpt.classname = "going_back";
       scrpt.think = go_back;
        }
   }
   return;
};


/*QUAKED info_script (.5 .5 .5) (-8 -8 -8) (8 8 32)
This is the destination marker for a script. 
It should have a "script_num" field that signifies the script number, and a "next_script" to signal the next script ("0" if this is the last page of the script), a "script_delay" to signify how many seconds to display this page, and of course a "message" field with the text to display.
*/
void() info_script =
{
};


/* ------------------------------ */
/* |      trigger_cvarset     | */
/* ------------------------------ */
/*QUAKED trigger_cvarset (.5 .5 .5) (-8 -8 -8) (8 8 32)
You can set any CVAR on the server with this trigger.  Put the CVAR name
in "netname" and put the value in "message".  Useful CVAR's are sv_gravity,  sv_friction, fov, and v_idlescale.
*/
void() change_cvar =
{
local entity   check;

   cvar_set (self.netname, self.message);
   bprint("\n\n\n\n");

   self.classname = "cvar_done";
   check = find(world, classname, "player");
   if(!check)
      check = find(world, classname, "camera");

   check.ideal_yaw = -1;
   
   self.nextthink = time + 0.02;
   self.think = SUB_UseTargets;
};

void() cvarset_touch =
{
    if (self.cnt > time || other.health <= 0 || other.classname != "player")
      return;

   change_cvar();
};

void() trigger_cvarset =
{
   if (deathmatch || coop)
      remove (self);

   InitTrigger ();
   self.use = change_cvar;
};


/* ------------------------------ */
/* |      trigger_gravity     | */
/* ------------------------------ */
/*QUAKED trigger_gravity (.5 .5 .5) (-8 -8 -8) (8 8 32)
This will change the gravity for objects that are inside it.
Put the value to change gravity to in the "gravity" field.
Ziggurat Vertigo used '100' for its low gravity.
*/
void() gravity_use =
{
   if (self.cnt == -1)
   {
      //dprint("Anti-gravity machine turned ON\n");
      self.cnt = 0;
   }
   else
   {
      //dprint("Anti-gravity machine turned OFF\n");
      self.cnt = -1;
   }
};

void() gravity_touch =
{
   if(self.cnt == -1)
      return;
   if(other.deadflag < 2)
   if(other.velocity_z != 0)
   if(other.movetype != MOVETYPE_FLYMISSILE)
   if(other.classname != "BloodCube")
      other.velocity_z = other.velocity_z + (self.delay * frametime);
};

void() trigger_gravity =
{
local float   worldGravity;

   InitTrigger ();
   worldGravity = cvar("sv_gravity");
   self.delay = worldGravity - self.gravity;
   self.touch = gravity_touch;

   if(self.targetname)
   {
      self.cnt = -1;
      self.use = gravity_use;
   }
};


/* ------------------------------ */
/* |      trigger_quake        | */
/* ------------------------------ */
/*QUAKED trigger_quake (.5 .5 .5) (-8 -8 -8) (8 8 32)
Starts an earthquake.  Players view will shake for amount of time you
put in "wait".  Place the richter scale of the quake in the "dmg" field.
It will also trigger all targets like a 'trigger_once'.
*/

void() q_trig =
{
   SUB_UseTargets();
   remove(self);
};

void() kick_me =
{
local float      n;
local entity    play;

   if(self.cnt < time)
      remove(self);

   play = find(world, classname, "player");
   if(!play)
      return;

   if (!(play.flags & FL_ONGROUND))
   {
      self.nextthink = time + 0.15;
      if (self.delay < time)
      {
         self.delay = time + 3;
         sound(play, CHAN_AUTO, "ambience/equake.wav", 1, ATTN_NORM);
      }
      return;
   }
   if (self.delay < time)
   {
       self.delay = time + 3;
       sound(play, CHAN_AUTO, "ambience/equake.wav", 1, ATTN_NORM);
   }

   n = self.dmg / 2;
   play.punchangle_x = (random() * self.dmg) - n;
   play.punchangle_y = (random() * self.dmg) - n;
   play.punchangle_z = (random() * self.dmg) - n;
   self.nextthink = time + 0.15;
   self.think = kick_me;
};

void() tq_use =
{
local entity   kicker;

   if (activator.health <= 0 || activator.classname != "player")
      return;

   kicker = spawn();
   kicker.cnt = time + self.wait;    //remove kicker when wait expires.
   kicker.delay = 0;
   kicker.dmg = self.dmg;
   kicker.nextthink = time + 0.2;
   kicker.think = kick_me;

   q_trig();
};

void() tq_touch =
{
local entity   kicker;

   if (other.health <= 0 || other.classname != "player")
      return;

   kicker = spawn();
   kicker.cnt = time + self.wait;    //remove kicker when wait expires.
   kicker.delay = 0;
   kicker.dmg = self.dmg;
   kicker.nextthink = time + 0.2;
   kicker.think = kick_me;

   q_trig();
};

void() trigger_quake =
{
   if (deathmatch || coop)
   {
      self.think = q_trig;
      self.nextthink = time + 0.5;
      return;
   }

   precache_sound2 ("ambience/equake.wav");
   InitTrigger ();

      self.use = tq_use;
   self.touch = tq_touch;
};
Sorry for my english :)
Max_Salivan
 
Posts: 93
Joined: Thu Dec 15, 2011 1:00 pm

Re: Demos on the map

Postby Dr. Shadowborg » Wed Jan 18, 2012 7:59 pm

dr_mabuse wrote:so, lets say i trigger a demo at the end of my E1M1 custom-map and the demo is finished with playing, i will directly go to E1M2 (or any map i assigned to my changelevel trigger)?


No, not unless you've done something special to tell quake to go to the map you want, and I wouldn't count on keeping your items from E1M1 when you get to your new map. (demos are NOT intended to be used for cutscenes, they are only for gameplay recording)

/me looks at max_salivan posting the cutscene.qc of zerstorer while saying that it doesn't play demos and facepalms

It's not supposed to play a demo, what it DOES do is provide the ability to do an ingame cutscene by actually using the engine to do all the work, rather than using a pre-recorded demo.

i.e. trigger_camera touched by player -> make player dummy entity to stand in for the player replete with all his health and items and can be programmed to follow a path_corner / shoot at targets -> shift the player (and hence his view) to the camera entity that follows the path_corner's it's assigned -> cutscene sequence complete, shift player to the player dummy origin (transfer everything back to the player from the dummy, including health), and remove the dummy.

Note that the zerstorer cutscene code first appeared in a separate standalone map titled "Vision of Hatred" and came with the "Cutscene Construction Kit" packaged with it. This same cutscene code has been used for other perhaps lesser known map packs such as e-5. NONE of these mods uses demos to do their cutscenes. Both zerstorer and the Vision of Hatred CCK should come with some relatively simple instructions on how to use them.

http://www.quaddicted.com/reviews/vision.html
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Re: Demos on the map

Postby dr_mabuse » Wed Jan 18, 2012 8:14 pm

thanks, this looks nice...
I will try to use this in my little mod :)

edit: backed the code into my mod and it works, thanks :)
This is just awesome.
User avatar
dr_mabuse
 
Posts: 80
Joined: Sat Sep 03, 2011 6:07 pm


Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest