.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  
func_pushable (Groups : qc : Forum : vault() : func_pushable) Locked
Thread Options
numbersix
numbersix quake-c coder++
Feb 24 2017 Anchor

Found in hip_push.qc. A search of hipnotic map .bsp found none in use.

The QUAKED entry has this:

Hipnotic note: Not quite working, but fun to play around with.

I decided to put one on my test map.
How it works: make a map brush with texture, etc. Select it then make
it a func_pushable. (In radiant the right-click menu brings up entity options.)

Issues I noted:

  • Odd shapes not handled - bounding box is rectalinear. Does not conform to bsp brush shape or rotates.
  • Only touch map brush on bottom - you must use func_illusionary walls for sides and top
    - if sides or top touch a solid map brush, the pushable will fall out of the level when spawned

Then I decided to improve the code:

// allow new ents to pass back pointer to calling fn
entity nspawn;
.vector v__;

/*QUAKED func_pushable (0 .5 .8) ? MDL LOC
-------- HIPN --------
Hipnotic Miscellaneous Geometry
-------------------------------
"MDL" using a custom bps or mdl model on pushable or target
(doesnt work on pushable, makes little sense on target ent)
"LOC" locate pushable proxy to target ent

"view_ofs" - z adust for LOC locate ent that ends up in floor '0 0 1' suggested
"target" - spawn a 'push wall proxy' for this ent and enable it as a pushable
(you can make an explodbox pushable this way - then it wont blow up
unless splash damaged)
"targetname" - allow pushable to be targeted for removal

Pushable walls.
Can NOT be bounded on top or sides by a solid brush.
If you want a pushable hidden in a wall it MUST have a few
units of func_illusionary around it. Suggest 4 qu. brush.

Hipnotic note: Not quite working,
but fun to play around with.
*/

/* Pushable walls QuickC program
	By Jim Dose'  9/16/96
	Copyright (c)1996 Hipnotic Interactive, Inc.
	All rights reserved.
	Distributed (unsupported) on 3.12.97
*/

void() push_use =
{
//	local vector delta;
//	local float x;
//	local float y;

//	walkmove (other.angles_y, 16 * frametime);
/*
	if ( (other.angles_y >= 315) || (other.angles_y < 45))
	{
		walkmove ( 0, 16 * frametime);
	}
	else if ( (other.angles_y >= 45) && (other.angles_y < 135))
	{
		walkmove ( 90, 16 * frametime);
	}
	else if ( (other.angles_y >= 135) && (other.angles_y < 225))
	{
		walkmove ( 180, 16 * frametime);
	}
	else if ( (other.angles_y >= 225) && (other.angles_y < 315))
	{
		walkmove ( 270, 16 * frametime);
	}
	else
	{
		return;
	}
*/
// fallout fix - and fails
	self.movetype = MOVETYPE_STEP;
	self.owner.movetype = MOVETYPE_PUSH;

	makevectors(other.angles);
	
//	x = fabs( v_forward_x );
//	y = fabs( v_forward_y );
	self.v___x = fabs( other.velocity_x );
	self.v___y = fabs( other.velocity_y );

#ifndef nodprint
	dprint( ftos( self.v___x ) );
	dprint( ", " );
	dprint( ftos( self.v___y ) );
#endifdef

	if ( self.v___x > self.v___y )
	{
#ifndef nodprint
		dprint( " x move\n\n\n\n" );
#endifdef
		if ( other.velocity_x > 0 )
		{
			walkmove ( 0, 16 * frametime);
		}
		else
		{
			walkmove( 180, 16 * frametime );
		}
	}
	else
	{
#ifndef nodprint
		dprint( " y move\n\n\n\n" );
#endifdef
		if ( other.velocity_y > 0 )
		{
			walkmove ( 90, 16 * frametime);
		}
		else
		{
			walkmove( 270, 16 * frametime );
		}
	}

// this makes blocks un-pushable
// and some blocks still went thru floor, just slower
//	self.velocity_z = 0;
//	self.owner.velocity_z = 0;

//	delta = self.origin - self.oldorigin;
	setorigin (self.owner, self.owner.oldorigin + (self.origin - self.oldorigin) + self.view_ofs );	//delta );
};

/*QUAKED func_pushable (0 .5 .8) ?
Pushable walls.
*/

// something wrong where these fall from the level
// initial MOVETYPE_NONE fixes this, but still fsck on ops with these
// fall from level is a result of bottom of proxy being embedded in floor

void() func_pushable =
{
//	local entity new;
//	local vector newsize;

	if (self.target != "")
	{
		if (time < 3)		// cant find target before it spawns
		{
			self.think = func_pushable;
			self.nextthink = time + 2;
			return;
		}
		nspawn = self;
		self = find (world, targetname, nspawn.target);
		if (!self) return;		// reload may correct this asp
		self.solid = SOLID_BSP;
		self.movetype = MOVETYPE_NONE;
		self.oldorigin = self.origin;
		self.targetname = nspawn.targetname;		// in case of a remove target on pushable
//		nspawn.origin = self.origin; // does not relocate pushable
	}
	else
	{
		self.mangle = self.angles;
		self.angles = '0 0 0';

		self.classname = "pushablewall";
		self.solid = SOLID_BSP;
	//	self.movetype = MOVETYPE_PUSH;
		self.movetype = MOVETYPE_NONE;
		setmodel (self, self.model);
		setorigin( self, self.origin );
		setsize (self, self.mins, self.maxs );
		self.oldorigin = self.origin;

		nspawn = spawn();
		nspawn.targetname = self.targetname;		// in case pushable is targeted
	}
	nspawn.owner = self;
	nspawn.mangle = self.mangle;
	nspawn.angles = self.angles;

	nspawn.classname = "pushablewallproxy";
	nspawn.solid = SOLID_BBOX;
//	nspawn.movetype = MOVETYPE_STEP;
	nspawn.movetype = MOVETYPE_NONE;
	nspawn.origin = ( self.mins + self.maxs ) * 0.5 + '0 0 1';
	self.v__ = ( self.maxs - self.mins ) * 0.5;
	nspawn.mins = '-1 -1 0' - self.v__ + nspawn.view_ofs;
	nspawn.maxs = '1 1 -2' + self.v__;
	if (nspawn.spawnflags & 1) setmodel (self, self.mdl);		// _only_ works with target ent! - a pure pushable MUST use the map brush supplied
	if (nspawn.spawnflags & 2)
	{
		nspawn.origin = self.origin;
		nspawn.maxs = self.maxs + '1 1 -2';
		nspawn.mins = '-1 -1 0' + self.mins + nspawn.view_ofs;
	}
	setsize( nspawn, nspawn.mins, nspawn.maxs );
	setorigin( nspawn, nspawn.origin );
	nspawn.oldorigin = nspawn.origin;
 	nspawn.touch = push_use;
};

So, what does the "target" improvement do?

You can push misc_explobox or other miscellaneous model items.

Issues still exist. Some tricks would need to be implemented to pass damage on to a shootable item
like misc_explobox. Likewise for a touchable item.

Other ideas I have:

  • implement the damage pass-through
  • remove players viswep while pushing
  • see if it works with SOLID_BSP for shape conform



Video of pushable in action: Moddb.com

This uses the "LOC" flag and target pointer to a regular misc_explobox.

The misc_explobox has the corresponding targetname:

// entity 1374
{
"view_ofs" "0 0 1"
"spawnflags" "2"
"target" "pushqbomb"
"origin" "1224 -376 0"
"classname" "func_pushable"
// brush 0
{
( -179 -2712 0 ) ( -218 -2672 0 ) ( -264 -2718 0 ) chaos/pipe1c 80 0 0 0.500000 0.500000 0 0 0
( -239 -2735 64 ) ( -193 -2689 64 ) ( -154 -2729 64 ) chaos/pipe1c 80 0 0 0.500000 0.500000 0 0 0
( -232 -2696 0 ) ( -208 -2696 0 ) ( -232 -2696 64 ) chaos/pipe1c 80 0 0 0.500000 0.500000 0 0 0
( -208 -2696 0 ) ( -208 -2712 0 ) ( -208 -2696 64 ) chaos/pipe1c 64 0 0 0.500000 0.500000 0 0 0
( -216 -2728 0 ) ( -224 -2728 0 ) ( -216 -2728 64 ) chaos/pipe1c 80 0 0 0.500000 0.500000 0 0 0
( -240 -2728 0 ) ( -240 -2712 0 ) ( -240 -2728 64 ) chaos/pipe1c 64 0 0 0.500000 0.500000 0 0 0
}
}
// entity 1375
{
"origin" "-256 -2688 0"
"classname" "misc_explobox"
"targetname" "pushqbomb"
}

Addendum - add a push "scraping" sound

Edited by: numbersix

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.