.qc (dot qc) - the group for quake c coders of all denominations. If you make quake one mods and write code in quake c, join our group! I'll try to answer any quake c questions - please post your inquiry in the forums...

Forum Thread
  Posts  
Rail trail in qc - continued (Groups : qc : Forum : hard_code() : Rail trail in qc - continued) Locked
Thread Options
Dec 6 2015 Anchor

Was gonna try this code, but chaos_spawn () is not there.

Im curious because in the Quake 1 Arena mod which I am working with, its got a railgun that fires te_lightning2 I believe as the beam , once. Since its based on Q3 Arena, he tried to do the "Rails in a Row" feature I guess Q3 Arena has, but he encountered a runaway loop. He had a failsafe built in, but after looking at it, it seems like its got to be rewritten to really work. It will need to detect a hit, then reform a new start vector about v_forward * 32 (the thickness of a player box) which is the exit side of the player bbox. Or , just continue at the new start vector, ignoring the trace_ent just hit, and repeating that process (x) number of times, I believe the limit was 20 rails in a row. Here is the code he was trying to use which never seemed to work. I guess TomazQuake ad a special TE effect for this kind of weapon. I was trying to use DP's check extension for detecting it, but it does not work. Not sure if you wanna try your hand at either fixing it or rewriting it, but here it is:


.entity nextrailent;
.float continuerail;
.float railcountdown;
.vector hitpoint;

void () C />{
if (TQ_RAILTRAIL)
{
return;
}
self.railcountdown = self.railcountdown - 1;
if (self.railcountdown == 0)
{
remove (self);
}
else
{
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
WriteEntity (MSG_BROADCAST, self);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
WriteCoord (MSG_BROADCAST, self.hitpoint_x);
WriteCoord (MSG_BROADCAST, self.hitpoint_y);
WriteCoord (MSG_BROADCAST, self.hitpoint_z);
}
};

void () W_FireRailgun =
{
local vector drawnvector;
local vector hitloc;
local vector startloc;
local vector tempvec;
local entity startpoint;
local entity currentent;
local entity firstent;
local float ringcount;
local float runawayprotect;
local float hitanent;
local float hitdamagable;
local float foo;

sound (self, CHAN_WEAPON, "weapons/railgf1a.wav", WEAPON_SHOTGUN, ATTN_NORM);
self.ammo_slugs = (self.ammo_slugs - WEAPON_SHOTGUN);
if ((self.ammo_slugs < WEAPON_SHOTGUN))
{
self.weapon = W_BestWeapon ();
W_SetCurrentAmmo ();
return;
}
makevectors (self.v_angle);
drawnvector = v_forward;
startloc = ((self.origin + (v_right * TE_LAVASPLASH)) + (v_up * WEAPON_BIG));
startpoint = spawn ();
setorigin (startpoint, startloc);
setmodel (startpoint, "");
startpoint.movetype = MOVETYPE_NONE;
startpoint.solid = SOLID_NOT;
startpoint.railcountdown = MENU_LINKS;
startpoint.think = ContinueTrail;
startpoint.nextthink = (time + 0.2);
traceline (startloc, ((self.origin + (drawnvector * 2000)) + '0 0 20'), TRUE, self);
hitloc = trace_endpos;
startpoint.hitpoint = hitloc;
foo = Calc_PointDamage (hitloc, 100);
if (TQ_RAILTRAIL)
{
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_RAILTRAIL);
WriteCoord (MSG_BROADCAST, self.origin_x);
WriteCoord (MSG_BROADCAST, self.origin_y);
WriteCoord (MSG_BROADCAST, self.origin_z);
WriteCoord (MSG_BROADCAST, hitloc);
WriteCoord (MSG_BROADCAST, hitloc_y);
WriteCoord (MSG_BROADCAST, hitloc_z);
WriteCoord (MSG_BROADCAST, self.v_angle_x);
WriteCoord (MSG_BROADCAST, self.v_angle_y);
WriteCoord (MSG_BROADCAST, self.v_angle_z);
}
else
{
if (!TQ_RAILTRAIL)
{
WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
WriteEntity (MSG_BROADCAST, startpoint);
WriteCoord (MSG_BROADCAST, startpoint.origin_x);
WriteCoord (MSG_BROADCAST, startpoint.origin_y);
WriteCoord (MSG_BROADCAST, startpoint.origin_z);
WriteCoord (MSG_BROADCAST, hitloc);
WriteCoord (MSG_BROADCAST, hitloc_y);
WriteCoord (MSG_BROADCAST, hitloc_z);
}
}
if (trace_ent)
{
if (trace_ent.takedamage)
{
T_Damage (trace_ent, self, self, 100);
}
}
traceline (startloc, hitloc, FALSE, self);
hitdamagable = FALSE;
runawayprotect = 20;
if ((trace_fraction != WEAPON_SHOTGUN))
{
currentent = trace_ent;
firstent = currentent;
currentent.c /> hitanent = TRUE;
while ((hitanent && runawayprotect))
{
runawayprotect = (runawayprotect - WEAPON_SHOTGUN);
tempvec = trace_endpos;
traceline (tempvec, hitloc, FALSE, currentent);
hitanent = FALSE;
if ((trace_fraction != WEAPON_SHOTGUN))
{
currentent.c /> currentent.nextrailent = trace_ent;
currentent = trace_ent;
hitanent = TRUE;
}
}
currentent = firstent;
runawayprotect = TRUE;
while (runawayprotect)
{
if (currentent.takedamage)
{
hitdamagable = TRUE;
if ((cvar ("deathmatch") == MENU_FLAGS2))
{
T_Damage (currentent, self, self, 999);
}
else
{
T_Damage (currentent, self, self, 100);
}
}
if (currentent.continuerail)
{
currentent = currentent.nextrailent;
}
else
{
runawayprotect = FALSE;
}
}
}
if (hitdamagable)
{
if ((currentent.classname == "player"))
{
self.rails_in_a_row = (self.rails_in_a_row + WEAPON_SHOTGUN);
if ((self.rails_in_a_row == WEAPON_ROCKET))
{
sound2 (self, "feedback/impressive_a");
self.rails_in_a_row =0;
}
}
}
else
{
self.rails_in_a_row = 0;
}
};



Edited by: Teknoskillz

numbersix
numbersix quake-c coder++
Dec 11 2015 Anchor

Tried the lightning trick. Dont like it - spins the bar model around too much, which was noticeable.

I also tried the multi segment beam by code with something like painkeeps harpoon.

The harpoon creates a convincing cable. Looks bad as a railbeam.

So:

(and I know the weaponmodel skin needs fixed...)

That is in darkplaces, under an as yet unspecified quake 1 mod!

A single beam, no lightning calls.

The code:

if (ew)
{
 e = chaos_spawn(MOVETYPE_FLY, SOLID_NOT, 0, 0, org, v0, v0, vectoangles(v_forward), self.velocity, null_string, 
    "progs/lzrbm_seg.mdl", SUB_Remove, 0.5, SUB_Remove, SUB_Null, self, world);
 e.effects = e.effects | EF_FULLBRIGHT;
 cn = ceil(vl / 32);
 if (cn > 63) cn = 63;
 e.frame = cn;
 if (!XENV) placestain(trace_endpos, "progs/s_rlspg.spr", rlspg_fade, 20);
}

That is it, the rest is damage code.

Engine limitations have forced me to use my imagination...

"progs/lzrbm_seg.mdl" ls a set of frames of the beam, each one 32 units longer than the previous.

Measure the distance - vl, divide by 32, make it int with ceil, and set the frame. Done.

Similar damage code, but I set the limit at 10 damage taking ents.

First cut of that, I had a 1600 unit beam. Till I noticed it poked through walls, and other solids.

That can poke a small bit through thin pieces of wall or bsp model. But it only flashes for a second, so you hardly notice.

Edited by: numbersix

--

\|/
-*- Support free code: Patreon.com
/|\

Dec 25 2015 Anchor

Hrm. Didnt get a chance to try your chaos spawn yet. But I came to realize that according to some of the other code for the railgun, its using TE_LIGHTNING2 for the beam and they seem to belive its 768 Quake units in length. This seems to be the piece they forgot about in the code I previously posted. If you squeezed 24 players side by side, you can fit them in this length, as the players are 16 * 16 wide. However thats if the first contacted entity is flush with the start of the beam.If the first ent you hit is farther down, your beam will travel through but we need to subtract the beam length from the start of the beam to the first ent, then continue it that further with a traceline, and so on , until beamlength left is < 1 for arguements sake.

The other issue is say we shoot through an explobox, do we still continue the beam for example. Probably would be safe to say yes and see how it turns out.

This will be some tricky code to devise...right now its basicly a while loop doing repeat tracelines, but there is no recurrence of the lightning effect which visually makes the beam seem to pass through one ent to the next. That will be the tricky part, sort of like a while loop in a while loop...but I am going to make the temp effects spawned for the beam basicly "think", and reset itself to the end of the traceline, and keep thinking until beamlength < 1. In theory sounds ok, but I guess we will see. Will try to post the code and screenshots later...


Is that basically what your chaos spawn code does?

Edited by: Teknoskillz

numbersix
numbersix quake-c coder++
Dec 25 2015 Anchor

All chaos spawn does is make a new ent and assigned the passed values to their respective fields in the new entity.

>beam and they seem to belive its 768 Quake units in length
Is that an engine limit? I didnt think there was one - you just give the te_lightning the coords and it makes the beam.
I would have to run a test though, there might be some limit like that, the old lightning used a model and threw out a lot of triangles to render.

This is my rail damage code for either beam:

	self.enemy = startent;

	i = 10;
	startent = self;
	destination = trace_endpos + v_forward*8;

	damage = 130 + random()*5;

	while(i > 0)
	{
		traceline (org, destination, FALSE, startent);

		if(trace_fraction >= 1 && !trace_ent.takedamage) // hit solid
			return;

		if(trace_ent == self) // on self
			return;

		j = (trace_ent.takedamage == DAMAGE_AIM);
		impactent = trace_ent;

		trace_endpos = trace_endpos - v_forward*16;
		if(trace_ent.takedamage)
		{
			T_Damage (trace_ent, self, self, damage);
			if(j)
				SpawnExitWound (trace_endpos, v_forward * 1200, 0.2, MOVETYPE_FLY); // something that bleeds
		}
		else
		{
			SpawnSmoke(trace_endpos, '0 0 20');
/* CHECK: blocked, no rubble fn yet - restore later
			k = 2 + random() * 3;
			while(k > 0)
			{
				rubble_debris(trace_endpos, v_forward * -100 + randdir()*50, 2 + random() * 4, 0);
//				SpawnRubble(trace_endpos, v_forward * -100 + randdir()*50);
				k = k - 1;
			}
*/
		}

		if(!j || vlen(org - destination) < 5)
			return; // hit something solid or finished

		org = trace_endpos;
		startent = impactent;
		damage = damage * 0.75;
		i = i - 1;
	}

Looks like I used a segment trace from impact to impact looking for damagable ents, up to 10.
Or stop when hitting a solid and throw some rubble. Reduce he damage by 75% every hit.

Or no rubble...but it could do that.

--

\|/
-*- Support free code: Patreon.com
/|\

Dec 25 2015 Anchor

DP's new shortcut to make lightning2

te_lightning2 (entity,vec_start, vec_end);


So if you do a traceline first, for say 2048 quake units from start, then use trace_endpos as vec_end, you wind up with a beam 2048 units long....as long as the traceline dont hit anything, If it does hit something the engine wont draw the beam further. So Im assigning it default length, in this case the railgun is not a weapon capable of infinite endless power , otherwise it could contine the beam forever. I suppose I could code in an "overload" mode using the alt fire button where it would detonate , kill the owner and do damage a certain radius , like a suicide of glory of sorts, or just have the alt fire extend the size of the beam such as 768 + (768 / 2) or 1.5 times as long, giving it a distance reach, but making the railgun recharge / attack_finished longer...and also expending more of what they call "slugs" which is what it apparently uses for ammo.


But anyhow, yes, looks like you are doing something like I am thinking to do by repeatedly spawning entities at the impact positions of the end of the beam, then tracelining again, ignoring the contacted ent, multiple times to determine multiple hits....reassigning the fields again each time too.

numbersix
numbersix quake-c coder++
Dec 26 2015 Anchor

>contine the beam forever

I sense this might lead to:

>Host error: server runaway loop counter hit limit of 10000000 jumps

But before that, you have the max size of a quake-c float.
Which is all a vector is ... a pointer and 3 qc floats. Yes, vectors take up 4 global slots unless used as an entity parm.That also means they are affected by qc's terrible float round off error at large values.

Be interesting to see what a te_lightning call would do with '0 0 0' to 'max max max'.
I dont think the engine would be happy if it doesnt have bounds checking.

--

\|/
-*- Support free code: Patreon.com
/|\

Reply to thread
click to sign in and post

Only registered members can share their thoughts. So come on! Join the community today (totally free - or sign in with your social account on the right) and join in the conversation.