From 1abc0bac2c08f94bcd593cb1155728aa5f7fec1e Mon Sep 17 00:00:00 2001 From: div0 Date: Thu, 28 Aug 2008 09:37:08 +0000 Subject: [PATCH] more laser madness (now: dark lasers, pulsating laser, laser beam interpolation) git-svn-id: svn://svn.icculus.org/nexuiz/trunk@4218 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/particles/laserbeam.tga | Bin 428 -> 24459 bytes data/qcsrc/client/hook.qc | 18 +++--- data/qcsrc/client/laser.qc | 104 ++++++++++++++++++++++++++++++-- data/qcsrc/common/constants.qh | 1 + data/qcsrc/server/cl_client.qc | 1 + data/qcsrc/server/defs.qh | 1 + data/qcsrc/server/g_triggers.qc | 51 ++++++++++++---- data/qcsrc/server/g_world.qc | 2 + data/scripts/entities.def | 4 +- 9 files changed, 154 insertions(+), 28 deletions(-) diff --git a/data/particles/laserbeam.tga b/data/particles/laserbeam.tga index 5d8b0816ea982bbbcd60d0ffb1e952c576c41d4d..88acafaab9682af1ad79e83dc2c31b1b7f27cf3a 100644 GIT binary patch literal 24459 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 diff --git a/data/qcsrc/client/hook.qc b/data/qcsrc/client/hook.qc index d240d1855..a568e612c 100644 --- a/data/qcsrc/client/hook.qc +++ b/data/qcsrc/client/hook.qc @@ -2,18 +2,14 @@ .vector HookEnd; .float HookKillTime; -void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, vector rgb, float drawflag) +void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float alpha, float drawflag) { // I want to draw a quad... // from and to are MIDPOINTS. - float t; vector axis, thickdir, A, B, C, D; float length_tex; - t = -2 * time; - t = random(); - axis = normalize(to - from); length_tex = aspect * vlen(to - from) / thickness; @@ -26,10 +22,10 @@ void Draw_CylindricLine(vector from, vector to, float thickness, string texture, D = to - thickdir * (thickness / 2); R_BeginPolygon(texture, drawflag); - R_PolygonVertex(A, '0 0 0' + t * '1 0 0', rgb, 1); - R_PolygonVertex(B, '0 1 0' + t * '1 0 0', rgb, 1); - R_PolygonVertex(C, '0 1 0' + (t + length_tex) * '1 0 0', rgb, 1); - R_PolygonVertex(D, '0 0 0' + (t + length_tex) * '1 0 0', rgb, 1); + R_PolygonVertex(A, '0 0 0' + shift * '1 0 0', rgb, alpha); + R_PolygonVertex(B, '0 1 0' + shift * '1 0 0', rgb, alpha); + R_PolygonVertex(C, '0 1 0' + (shift + length_tex) * '1 0 0', rgb, alpha); + R_PolygonVertex(D, '0 0 0' + (shift + length_tex) * '1 0 0', rgb, alpha); R_EndPolygon(); } @@ -72,9 +68,9 @@ void Draw_GrapplingHook() rgb = '.3 1 .3'; } if(checkextension("DP_SV_WRITEPICTURE")) - Draw_CylindricLine(b, a, 8, tex, 0.25, '1 1 1', DRAWFLAG_NORMAL); + Draw_CylindricLine(b, a, 8, tex, 0.25, random(), '1 1 1', 1, DRAWFLAG_NORMAL); else - Draw_CylindricLine(b, a, 1, "", 0.25, rgb, DRAWFLAG_NORMAL); + Draw_CylindricLine(b, a, 1, "", 0.25, 0, rgb, 1, DRAWFLAG_NORMAL); } void Net_GrapplingHook() diff --git a/data/qcsrc/client/laser.qc b/data/qcsrc/client/laser.qc index 73c899d1c..07768aabe 100644 --- a/data/qcsrc/client/laser.qc +++ b/data/qcsrc/client/laser.qc @@ -1,17 +1,95 @@ +// FIXME make this generic code, to be used for other entities too? +.vector iorigin1, iorigin2; +.vector ivelocity1, ivelocity2; +.vector iangles1, iangles2; +.float itime1, itime2; +void InterpolateOrigin_Note() +{ + float dt; + + self.iorigin1 = self.iorigin2; + self.iangles1 = self.iangles2; + self.ivelocity1 = self.ivelocity2; + + self.iorigin2 = self.origin; + self.iangles2 = self.angles; + self.ivelocity2 = self.velocity; + + dt = time - self.itime1; + + if(vlen(self.iorigin2 - self.iorigin1) > 1000) + { + self.iorigin1 = self.iorigin2; + self.iangles1 = self.iangles2; + self.ivelocity1 = self.ivelocity2; + } + else if(vlen(self.ivelocity2 - self.ivelocity1) > 1000) + { + self.iangles1 = self.iangles2; + self.ivelocity1 = self.ivelocity2; + } + + if(dt < 0.2) + { + self.itime1 = time; + self.itime2 = time + getstatf(STAT_SYS_TICRATE); + } + else + { + // don't lerp + self.itime1 = self.itime2 = time; + } +} +void InterpolateOrigin_Do() +{ + if(self.itime1 && self.itime2 && self.itime1 != self.itime2) + { + float f; + f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1); + self.origin = (1 - f) * self.iorigin1 + f * self.iorigin2; + self.angles = (1 - f) * self.iangles1 + f * self.iangles2; + self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2; + } +} +void InterpolateOrigin_Undo() +{ + self.origin = self.iorigin2; + self.angles = self.iangles2; + self.velocity = self.ivelocity2; +} + // a laser goes from origin in direction angles // it has color 'colormod' // and stops when something is in the way .float cnt; // end effect .vector colormod; .float state; // on-off +.float count; // flags for the laser +.vector velocity; +.float alpha; void Draw_Laser() { if(!self.state) return; - makevectors(self.angles); - traceline(self.origin, self.origin + v_forward * 32768, 0, self); - Draw_CylindricLine(self.origin, trace_endpos, 2, "particles/laserbeam", 1, self.colormod, DRAWFLAG_ADDITIVE); // TODO make a texture to make the laser look smoother + InterpolateOrigin_Do(); + if(self.count & 0x80) + { + traceline(self.origin, self.velocity, 0, self); + } + else + { + makevectors(self.angles); + traceline(self.origin, self.origin + v_forward * 32768, 0, self); + } + if(self.alpha) + { + Draw_CylindricLine(self.origin, trace_endpos, 2, "particles/laserbeam", 0, time * 3, self.colormod, self.alpha, DRAWFLAG_NORMAL); // TODO make a texture to make the laser look smoother + } + else + { + Draw_CylindricLine(self.origin, trace_endpos, 2, "particles/laserbeam", 0, time * 3, self.colormod, 1, DRAWFLAG_ADDITIVE); // TODO make a texture to make the laser look smoother + } pointparticles(self.cnt, trace_endpos, trace_plane_normal, 256 * drawframetime); } @@ -20,6 +98,8 @@ void Ent_Laser() float f; // 30 bytes, or 13 bytes for just moving f = ReadByte(); + self.count = (f & 0xC0); + InterpolateOrigin_Undo(); if(f & 1) { self.origin_x = ReadCoord(); @@ -31,14 +111,28 @@ void Ent_Laser() self.colormod_x = ReadByte() / 255.0; self.colormod_y = ReadByte() / 255.0; self.colormod_z = ReadByte() / 255.0; + if(f & 0x40) + self.alpha = ReadByte() / 255.0; + else + self.alpha = 0; self.cnt = ReadShort(); // effect number } if(f & 2) { - self.angles_x = ReadCoord(); - self.angles_y = ReadCoord(); + if(f & 0x80) + { + self.velocity_x = ReadCoord(); + self.velocity_y = ReadCoord(); + self.velocity_z = ReadCoord(); + } + else + { + self.angles_x = ReadCoord(); + self.angles_y = ReadCoord(); + } } if(f & 4) self.state = ReadByte(); + InterpolateOrigin_Note(); self.draw = Draw_Laser; } diff --git a/data/qcsrc/common/constants.qh b/data/qcsrc/common/constants.qh index 6f2aebacb..de6c01770 100644 --- a/data/qcsrc/common/constants.qh +++ b/data/qcsrc/common/constants.qh @@ -200,6 +200,7 @@ const float TE_CSQC_SPECTATING = 111; const float STAT_KH_KEYS = 32; const float STAT_CTF_STATE = 33; +const float STAT_SYS_TICRATE = 34; const float CTF_STATE_ATTACK = 1; const float CTF_STATE_DEFEND = 2; const float CTF_STATE_COMMANDER = 3; diff --git a/data/qcsrc/server/cl_client.qc b/data/qcsrc/server/cl_client.qc index 6dc498cc2..ad39b7b3b 100644 --- a/data/qcsrc/server/cl_client.qc +++ b/data/qcsrc/server/cl_client.qc @@ -1922,6 +1922,7 @@ void() ctf_setstatus; .float spectatee_status; void PlayerPreThink (void) { + self.stat_sys_ticrate = cvar("sys_ticrate"); if(blockSpectators) checkSpectatorBlock(); diff --git a/data/qcsrc/server/defs.qh b/data/qcsrc/server/defs.qh index 070c870ff..26b737d6e 100644 --- a/data/qcsrc/server/defs.qh +++ b/data/qcsrc/server/defs.qh @@ -490,3 +490,4 @@ float independent_players; #define MAKE_INDEPENDENT_PLAYER(e) ((e).solid = SOLID_TRIGGER) string clientstuff; +.float stat_sys_ticrate; diff --git a/data/qcsrc/server/g_triggers.qc b/data/qcsrc/server/g_triggers.qc index fd325cb31..ffcb8275b 100644 --- a/data/qcsrc/server/g_triggers.qc +++ b/data/qcsrc/server/g_triggers.qc @@ -710,12 +710,23 @@ void misc_laser_aim() vector a; if(self.enemy) { - a = vectoangles(self.enemy.origin - self.origin); - a_x = -a_x; - if(a != self.mangle) + if(self.spawnflags & 2) { - self.mangle = a; - self.SendFlags |= 2; + if(self.enemy.origin != self.mangle) + { + self.mangle = self.enemy.origin; + self.SendFlags |= 2; + } + } + else + { + a = vectoangles(self.enemy.origin - self.origin); + a_x = -a_x; + if(a != self.mangle) + { + self.mangle = a; + self.SendFlags |= 2; + } } } if(self.origin != self.oldorigin) @@ -741,8 +752,9 @@ void misc_laser_think() misc_laser_aim(); - makevectors(self.mangle); - o = self.origin + 32768 * v_forward; + o = self.enemy.origin; + if not(self.spawnflags & 2) + o = self.origin + normalize(o - self.origin) * 32768; if(self.dmg) { @@ -756,6 +768,11 @@ void misc_laser_think() float laser_SendEntity(entity to, float fl) { WriteByte(MSG_ENTITY, ENT_CLIENT_LASER); + fl = fl - (fl & 0xC0); // use that bit to indicate finite length laser + if(self.spawnflags & 2) + fl |= 0x80; + if(self.alpha) + fl |= 0x40; WriteByte(MSG_ENTITY, fl); if(fl & 1) { @@ -768,19 +785,30 @@ float laser_SendEntity(entity to, float fl) WriteByte(MSG_ENTITY, self.colormod_x * 255.0); WriteByte(MSG_ENTITY, self.colormod_y * 255.0); WriteByte(MSG_ENTITY, self.colormod_z * 255.0); + if(fl & 0x40) + WriteByte(MSG_ENTITY, self.alpha * 255.0); WriteShort(MSG_ENTITY, self.cnt); } if(fl & 2) { - WriteCoord(MSG_ENTITY, self.mangle_x); - WriteCoord(MSG_ENTITY, self.mangle_y); + if(fl & 0x80) + { + WriteCoord(MSG_ENTITY, self.enemy.origin_x); + WriteCoord(MSG_ENTITY, self.enemy.origin_y); + WriteCoord(MSG_ENTITY, self.enemy.origin_z); + } + else + { + WriteCoord(MSG_ENTITY, self.mangle_x); + WriteCoord(MSG_ENTITY, self.mangle_y); + } } if(fl & 4) WriteByte(MSG_ENTITY, self.state); return 1; } -/*QUAKED spawnfunc_misc_laser (.5 .5 .5) ? START_ON +/*QUAKED spawnfunc_misc_laser (.5 .5 .5) ? START_ON DEST_IS_FIXED Any object touching the beam will be hurt Keys: "target" @@ -812,7 +840,8 @@ void spawnfunc_misc_laser() self.cnt = particleeffectnum("misc_laser_beam_end"); } if(self.colormod == '0 0 0') - self.colormod = '1 0 0'; + if(!self.alpha) + self.colormod = '1 0 0'; if(!self.message) self.message = "saw the light"; self.think = misc_laser_think; diff --git a/data/qcsrc/server/g_world.qc b/data/qcsrc/server/g_world.qc index 110ddd4bf..bc9e6891f 100644 --- a/data/qcsrc/server/g_world.qc +++ b/data/qcsrc/server/g_world.qc @@ -365,6 +365,8 @@ void spawnfunc_worldspawn (void) } } + addstat(STAT_SYS_TICRATE, AS_FLOAT, stat_sys_ticrate); + next_pingtime = time + 5; world_initialized = 1; } diff --git a/data/scripts/entities.def b/data/scripts/entities.def index c999718c3..944cf454e 100644 --- a/data/scripts/entities.def +++ b/data/scripts/entities.def @@ -496,7 +496,7 @@ LINEAR: Use a linear falloff. Default is inverse distance squared (more realisti NOANGLE: Ignore angle attenuation. */ -/*QUAKED misc_laser (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON +/*QUAKED misc_laser (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON FINITE Laser beam emitter -------- KEYS -------- target: target_position the laser targets (may be another entity, the laser will then target its origin. Use origin brushes, that is!) @@ -504,8 +504,10 @@ mdl: name of particle effect for the beam end point (see effectinfo.txt; default colormod: color of the laser beam (default: red, that is, 1 0 0) dmg: damage inflicted by the beam per second, or -1 for an instant-death ray targetname: name to target this (then its state is toggled) +alpha: when set, makes a dark laser of the given strength; may be combined with colormod -------- SPAWNFLAGS -------- START_ON: when targeted, the laser will start switched on +FINITE: the laser does not extend over its target like light would do, but stops there (takes more bandwidth) -------- NOTES -------- Use trigger_monoflop if you want the laser to turn off for a while, then turn back on */ -- 2.39.2