No QuakeC Quake?

Discuss programming topics for the various GPL'd game engine sources.
Stroggos
Posts: 50
Joined: Tue Apr 14, 2009 11:40 am
Location: Australia

No QuakeC Quake?

Post by Stroggos »

I was debating weather or not to create a quake engine in PURE C++. No ASM and NO QuakeC. Instead I will replace the QuakeC game code with regular C++. First the conversion from C to C++ then the game code.
What I wanted to ask is, has anyone done this before?
Error
InsideQC Staff
Posts: 865
Joined: Fri Nov 05, 2004 5:15 am
Location: VA, USA
Contact:

Post by Error »

why would you want to do this? just to do it?
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

ID did a QuakeC to C transition for QII, so it might be worth taking a look at some of the gamex86 code for pointers.

(Yes, according to Carmack's .plan at the time it was a direct port of QuakeC to C rather than a rewrite).
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
dreadlorde
Posts: 268
Joined: Tue Nov 24, 2009 2:20 am
Contact:

Post by dreadlorde »

WHY WOULD YOU DO THAT?! You might as well rewrite Quake in brainfuck, as it is easier to understand than the Tower of Babel that is C++.
Ken Thompson wrote:One of my most productive days was throwing away 1000 lines of code.
Get off my lawn!
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Post by Spike »

'for pointers' was intentional irony, right? :P
My biggest complaint about native code, and Q2 especially... is saved games.
Baker
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Re: No QuakeC Quake?

Post by Baker »

Stroggos wrote:I was debating weather or not to create a quake engine in PURE C++. No ASM and NO QuakeC. Instead I will replace the QuakeC game code with regular C++. First the conversion from C to C++ then the game code.
What I wanted to ask is, has anyone done this before?
Um ...

Why?

It is a serious question. Suddenly a game logic modification becomes --- instead of platform independent ... like runs on Windows, Linux, OS X, PSP, Wii, Flash, whatever else ... the game logic would need compiled for each operating system.

I will say that the KTX Quakeworld mod is apparently built-in to MSDSV instead of being a QuakeC mod, so C based game logic has been done in Quake apparently.

Additionally, Tomaz Miniracer seems to have the game logic built-in to the engine as far as I can tell, although only did a cursory examination of the download.
The night is young. How else can I annoy the world before sunsrise? 8) Inquisitive minds want to know ! And if they don't -- well like that ever has stopped me before ..
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Post by frag.machine »

Its' already done. Kinda. It's name is Source engine.
Ok, that's not a correct statement - Source engine base was HL1 engine which, in turn, was a Quake/Quake2 hybrid ported from C to C++. But still, you got the idea.
dreadlorde wrote: WHY WOULD YOU DO THAT?!
Baker wrote:Um ...

Why?

It is a serious question.
I can see at least one big benefit for this move: game logic development would benefit a lot from OO, mostly inheritance.
That said, I really would like to see a more "OO" version of QuakeC to emerge, allowing some simple inheritance model. You could do things like (sorry for the Java taste in the syntax :) ):

Code: Select all

import walkmonster;

entity monster_ogre extends walkmonster {
  public void monster_ogre () {
    super ();
    precache_model ("progs/ogre.mdl");
    setmodel (self, "progs/ogre.mdl");
  }

  private void th_stand () {
    super ();
  }

  (...)
}
As you may realize, creating new stuff would be really easier. A new monster would required roughly half the code it uses currently.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
Dr. Shadowborg
InsideQC Staff
Posts: 1120
Joined: Sat Oct 16, 2004 3:34 pm

Post by Dr. Shadowborg »

This idea = eeew.

Improved QuakeC Idea = Groovy.

Quake 2 using QuakeC idea = Groovy.
mh
Posts: 2292
Joined: Sat Jan 12, 2008 1:38 am

Post by mh »

dreadlorde wrote:WHY WOULD YOU DO THAT?! You might as well rewrite Quake in brainfuck, as it is easier to understand than the Tower of Babel that is C++.
Depends on how you use your C++ really. Templates with layers of abstraction and multiple inheritance is definitely a Tower of Babel, but it's equally as easy (if one is more interested in producing a working program than showing off one's programming skills and knowledge of OO) to write perfectly legible C++ that takes advantage of 90% of the really useful OO stuff.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
Willem
Posts: 73
Joined: Wed Jan 23, 2008 10:58 am
Contact:

Post by Willem »

WHY WOULD YOU DO THAT?! You might as well rewrite Quake in brainfuck, as it is easier to understand than the Tower of Babel that is C++.
There's nothing inherently hard to understand about C++. As with any language, it depends on the programmer who writes the code.
dreadlorde
Posts: 268
Joined: Tue Nov 24, 2009 2:20 am
Contact:

Post by dreadlorde »

Willem wrote:
WHY WOULD YOU DO THAT?! You might as well rewrite Quake in brainfuck, as it is easier to understand than the Tower of Babel that is C++.
There's nothing inherently hard to understand about C++. As with any language, it depends on the programmer who writes the code.
The C++ inheritance model is pretty hard to understand. The C++ preprocessor is pretty hard to understand.
Ken Thompson wrote:One of my most productive days was throwing away 1000 lines of code.
Get off my lawn!
Willem
Posts: 73
Joined: Wed Jan 23, 2008 10:58 am
Contact:

Post by Willem »

The C++ inheritance model is pretty hard to understand. The C++ preprocessor is pretty hard to understand.
We'll have to agree to disagree. I find straight up C to often be harder to understand, especially when it's faking object orientation with pointer arithmetic and function pointers. :)
Supa
Posts: 164
Joined: Tue Oct 26, 2004 8:10 am

Post by Supa »

Teiman
Posts: 311
Joined: Sun Jun 03, 2007 9:39 am

Post by Teiman »

There are a few versions of Team Fortress already ported to C.


And about what gain.. perfomance? if you need perfomance. most engines make his gameplay part in a scripting thing, cause often you want flexibility. But.. he!.. maybe you want perfomance for some reason, so C++ o C can be ok-ish.


Some .he... mystery-pseudocode, follows.

Code: Select all

#include "g_local.h"
#define MAX_BODYQUE 4
gedict_t *bodyque[MAX_BODYQUE];
int     bodyque_head;
void InitBodyQue(  )
{
	int     i;

	bodyque[0] = spawn(  );
	bodyque[0]->s.v.classname = "bodyque";
	for ( i = 1; i < MAX_BODYQUE; i++ )
	{
		bodyque[i] = spawn(  );
		bodyque[i]->s.v.classname = "bodyque";
		bodyque[i - 1]->s.v.owner = EDICT_TO_PROG( bodyque[i] );
	}
	bodyque[MAX_BODYQUE - 1]->s.v.owner = EDICT_TO_PROG( bodyque[0] );
	bodyque_head = 0;
}

// make a body que entry for the given ent so the ent can be
// respawned elsewhere
void CopyToBodyQue( gedict_t * ent )
{
	VectorCopy( ent->s.v.angles, bodyque[bodyque_head]->s.v.angles );
	VectorCopy( ent->s.v.velocity, bodyque[bodyque_head]->s.v.velocity );
	bodyque[bodyque_head]->s.v.model = ent->s.v.model;
	bodyque[bodyque_head]->s.v.modelindex = ent->s.v.modelindex;
	bodyque[bodyque_head]->s.v.frame = ent->s.v.frame;
	bodyque[bodyque_head]->s.v.colormap = ent->s.v.colormap;
	bodyque[bodyque_head]->s.v.movetype = ent->s.v.movetype;
	bodyque[bodyque_head]->s.v.flags = 0;

	setorigin( bodyque[bodyque_head], PASSVEC3( ent->s.v.origin ) );
	setsize( bodyque[bodyque_head], PASSVEC3( ent->s.v.mins ), PASSVEC3( ent->s.v.maxs ) );

	if ( ++bodyque_head >= MAX_BODYQUE )
		bodyque_head = 0;
}


extern gedict_t *lastspawn;
int     number_of_teams;

void SP_worldspawn(  )
{
	char   *s;
	char    gamedir[64], cycledir[64];
	char    exec_maps[10];

	G_SpawnString( "classname", "", &s );
	if ( Q_stricmp( s, "worldspawn" ) )
	{
		G_Error( "SP_worldspawn: The first entity isn't 'worldspawn'" );
	}
	world->s.v.classname = "worldspawn";
	lastspawn = world;
	number_of_teams = 0;
	InitBodyQue(  );

	if ( !Q_stricmp( self->s.v.model, "maps/e1m8.bsp" ) )
		trap_cvar_set( "sv_gravity", "100" );
	else
		trap_cvar_set( "sv_gravity", "800" );

	infokey( world, "*sv_gamedir", gamedir, sizeof( gamedir ) );
	if ( gamedir[0] != 0 && strcmp( gamedir, "fortress" ) )
	{
		G_Error( "QW TF must be run with a sv_gamedir of \"fortress\".\n" );
	} else
	{
		if ( gamedir[0] == 0 )
		{
			infokey( world, "*gamedir", gamedir, sizeof( gamedir ) );
			if ( strcmp( gamedir, "fortress" ) )
				G_Error( "QW TF must be run with a sv_gamedir of \"fortress\".\n" );
		}
	}

	infokey( world, "exec_map_cfgs", exec_maps, sizeof( exec_maps ) );

	if ( !strcmp( exec_maps, "on" ) )
	{
		infokey( world, "cycledir", cycledir, sizeof( cycledir ) );
		if ( cycledir[0] )
		{
			localcmd( "exec %s/mapdefault.cfg\n", cycledir );
			localcmd( "exec %s/%s.cfg\n", cycledir, g_globalvars.mapname );
		} else
		{
			localcmd( "exec qwmcycle/mapdefault.cfg\n" );
			localcmd( "exec qwmcycle/%s.cfg\n", g_globalvars.mapname );
		}
	}
// the area based ambient sounds MUST be the first precache_sounds

// player precaches     
	W_Precache(  );		// get weapon precaches

// sounds used from C physics code
	trap_precache_sound( "demon/dland2.wav" );	// landing thud
	trap_precache_sound( "misc/h2ohit1.wav" );	// landing splash

// setup precaches allways needed
	trap_precache_sound( "items/itembk2.wav" );	// item respawn sound
	trap_precache_sound( "player/plyrjmp8.wav" );	// player jump
	trap_precache_sound( "player/land.wav" );	// player landing
	trap_precache_sound( "player/land2.wav" );	// player hurt landing
	trap_precache_sound( "player/drown1.wav" );	// drowning pain
	trap_precache_sound( "player/drown2.wav" );	// drowning pain
	trap_precache_sound( "player/gasp1.wav" );	// gasping for air
	trap_precache_sound( "player/gasp2.wav" );	// taking breath
	trap_precache_sound( "player/h2odeath.wav" );	// drowning death

	trap_precache_sound( "misc/talk.wav" );	// talk
	trap_precache_sound( "player/teledth1.wav" );	// telefrag
	trap_precache_sound( "misc/r_tele1.wav" );	// teleport sounds
	trap_precache_sound( "misc/r_tele2.wav" );
	trap_precache_sound( "misc/r_tele3.wav" );
	trap_precache_sound( "misc/r_tele4.wav" );
	trap_precache_sound( "misc/r_tele5.wav" );
	trap_precache_sound( "weapons/lock4.wav" );	// ammo pick up
	trap_precache_sound( "weapons/pkup.wav" );	// weapon up
	trap_precache_sound( "items/armor1.wav" );	// armor up
	trap_precache_sound( "weapons/lhit.wav" );	//lightning
	trap_precache_sound( "weapons/lstart.wav" );	//lightning start
	trap_precache_sound( "items/damage3.wav" );

	trap_precache_sound( "misc/power.wav" );	//lightning for boss

// player gib sounds
	trap_precache_sound( "player/gib.wav" );	// player gib sound
	trap_precache_sound( "player/udeath.wav" );	// player gib sound
	trap_precache_sound( "player/tornoff2.wav" );	// gib sound

// player pain sounds

	trap_precache_sound( "player/pain1.wav" );
	trap_precache_sound( "player/pain2.wav" );
	trap_precache_sound( "player/pain3.wav" );
	trap_precache_sound( "player/pain4.wav" );
	trap_precache_sound( "player/pain5.wav" );
	trap_precache_sound( "player/pain6.wav" );

// player death sounds
	trap_precache_sound( "player/death1.wav" );
	trap_precache_sound( "player/death2.wav" );
	trap_precache_sound( "player/death3.wav" );
	trap_precache_sound( "player/death4.wav" );
	trap_precache_sound( "player/death5.wav" );

	trap_precache_sound( "boss1/sight1.wav" );

// ax sounds    
	trap_precache_sound( "weapons/ax1.wav" );	// ax swoosh
	trap_precache_sound( "player/axhit1.wav" );	// ax hit meat
	trap_precache_sound( "player/axhit2.wav" );	// ax hit world

	trap_precache_sound( "player/h2ojump.wav" );	// player jumping into water
	trap_precache_sound( "player/slimbrn2.wav" );	// player enter slime
	trap_precache_sound( "player/inh2o.wav" );	// player enter water
	trap_precache_sound( "player/inlava.wav" );	// player enter lava
	trap_precache_sound( "misc/outwater.wav" );	// leaving water sound

	trap_precache_sound( "player/lburn1.wav" );	// lava burn
	trap_precache_sound( "player/lburn2.wav" );	// lava burn

	trap_precache_sound( "misc/water1.wav" );	// swimming
	trap_precache_sound( "misc/water2.wav" );	// swimming

// Invulnerability sounds
	trap_precache_sound( "items/protect.wav" );
	trap_precache_sound( "items/protect2.wav" );
	trap_precache_sound( "items/protect3.wav" );


	trap_precache_model( "progs/player.mdl" );
	trap_precache_model( "progs/eyes.mdl" );
	trap_precache_model( "progs/h_player.mdl" );
	trap_precache_model( "progs/gib1.mdl" );
	trap_precache_model( "progs/gib2.mdl" );
	trap_precache_model( "progs/gib3.mdl" );

	trap_precache_model( "progs/s_bubble.spr" );	// drowning bubbles
	trap_precache_model( "progs/s_explod.spr" );	// sprite explosion

	trap_precache_model( "progs/v_axe.mdl" );
	trap_precache_model( "progs/v_shot.mdl" );
	trap_precache_model( "progs/v_nail.mdl" );
	trap_precache_model( "progs/v_rock.mdl" );
	trap_precache_model( "progs/v_shot2.mdl" );
	trap_precache_model( "progs/v_nail2.mdl" );
	trap_precache_model( "progs/v_rock2.mdl" );

	trap_precache_model( "progs/bolt.mdl" );	// for lightning gun
	trap_precache_model( "progs/bolt2.mdl" );	// for lightning gun
	trap_precache_model( "progs/bolt3.mdl" );	// for boss shock
	trap_precache_model( "progs/lavaball.mdl" );	// for testing

	trap_precache_model( "progs/missile.mdl" );
	trap_precache_model( "progs/grenade.mdl" );
	trap_precache_model( "progs/spike.mdl" );
	trap_precache_model( "progs/s_spike.mdl" );

	trap_precache_model( "progs/backpack.mdl" );

	trap_precache_model( "progs/zom_gib.mdl" );

	trap_precache_model( "progs/v_light.mdl" );

/////////////////////////TF///////////////////
	trap_precache_model( "progs/laser.mdl" );
	trap_precache_sound( "enforcer/enfire.wav" );
	trap_precache_sound( "enforcer/enfstop.wav" );
	trap_precache_sound( "hknight/attack1.wav" );
	trap_precache_model( "progs/sight.spr" );
	trap_precache_model( "progs/caltrop.mdl" );
	trap_precache_model( "progs/cross1.mdl" );
	trap_precache_model( "progs/tf_flag.mdl" );
	trap_precache_model( "progs/tf_stan.mdl" );
	trap_precache_model( "progs/v_medi.mdl" );
	trap_precache_model( "progs/v_bio.mdl" );
	trap_precache_model( "progs/v_pipe.mdl" );
	trap_precache_model( "progs/hgren2.mdl" );
	trap_precache_model( "progs/biggren.mdl" );
	trap_precache_model( "progs/flare.mdl" );
	trap_precache_model( "progs/v_srifle.mdl" );
	trap_precache_model( "progs/v_asscan.mdl" );
	trap_precache_model( "progs/detpack.mdl" );
	trap_precache_model( "progs/ammobox.mdl" );
	trap_precache_model( "progs/v_knife.mdl" );
	trap_precache_model( "progs/v_knife2.mdl" );
	trap_precache_model( "progs/v_span.mdl" );
	trap_precache_model( "progs/e_spike1.mdl" );
	trap_precache_model( "progs/e_spike2.mdl" );
	trap_precache_model( "progs/v_rail.mdl" );
	trap_precache_model( "progs/turrgun.mdl" );
	trap_precache_model( "progs/turrbase.mdl" );
	trap_precache_model( "progs/tgib1.mdl" );
	trap_precache_model( "progs/tgib2.mdl" );
	trap_precache_model( "progs/tgib3.mdl" );
	trap_precache_model( "progs/disp.mdl" );
	trap_precache_model( "progs/dgib1.mdl" );
	trap_precache_model( "progs/dgib2.mdl" );
	trap_precache_model( "progs/dgib3.mdl" );
	trap_precache_model( "progs/grenade2.mdl" );
	trap_precache_model( "progs/v_grap.mdl" );
	trap_precache_model( "progs/hook.mdl" );
	trap_precache_model( "progs/caltrop.mdl" );
	trap_precache_sound( "doors/baseuse.wav" );
	trap_precache_sound( "doors/medtry.wav" );
	trap_precache_sound( "speech/saveme1.wav" );
	trap_precache_sound( "speech/saveme2.wav" );
	trap_precache_model( "progs/detpack2.mdl" );
	trap_precache_model( "progs/grenade3.mdl" );
	trap_precache_sound( "misc/b1.wav" );
	trap_precache_sound( "misc/b2.wav" );
	trap_precache_sound( "misc/b3.wav" );
	trap_precache_sound( "misc/b4.wav" );
	trap_precache_model( "progs/w_s_key.mdl" );
	trap_precache_model( "progs/m_s_key.mdl" );
	trap_precache_model( "progs/b_s_key.mdl" );
	trap_precache_model( "progs/w_g_key.mdl" );
	trap_precache_model( "progs/m_g_key.mdl" );
	trap_precache_model( "progs/b_g_key.mdl" );
//
// Setup light animation tables. 'a' is total darkness, 'z' is maxbright.
//

	// 0 normal
	trap_lightstyle( 0, "m" );

	// 1 FLICKER (first variety)
	trap_lightstyle( 1, "mmnmmommommnonmmonqnmmo" );

	// 2 SLOW STRONG PULSE
	trap_lightstyle( 2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba" );

	// 3 CANDLE (first variety)
	trap_lightstyle( 3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg" );

	// 4 FAST STROBE
	trap_lightstyle( 4, "mamamamamama" );

	// 5 GENTLE PULSE 1
	trap_lightstyle( 5, "jklmnopqrstuvwxyzyxwvutsrqponmlkj" );

	// 6 FLICKER (second variety)
	trap_lightstyle( 6, "nmonqnmomnmomomno" );

	// 7 CANDLE (second variety)
	trap_lightstyle( 7, "mmmaaaabcdefgmmmmaaaammmaamm" );

	// 8 CANDLE (third variety)
	trap_lightstyle( 8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa" );

	// 9 SLOW STROBE (fourth variety)
	trap_lightstyle( 9, "aaaaaaaazzzzzzzz" );

	// 10 FLUORESCENT FLICKER
	trap_lightstyle( 10, "mmamammmmammamamaaamammma" );

	// 11 SLOW PULSE NOT FADE TO BLACK
	trap_lightstyle( 11, "abcdefghijklmnopqrrqponmlkjihgfedcba" );

	// styles 32-62 are assigned by the light program for switchable lights

	// 63 testing
	trap_lightstyle( 63, "a" );

}

int     timelimit, fraglimit, teamplay, deathmatch, framecount, coop;


void StartFrame( int time )
{
	timelimit = trap_cvar( "timelimit" ) * 60;
	fraglimit = trap_cvar( "fraglimit" );
	teamplay  = trap_cvar( "teamplay" );
	deathmatch = trap_cvar( "deathmatch" );

	framecount = framecount + 1;
}

Dr. Shadowborg
InsideQC Staff
Posts: 1120
Joined: Sat Oct 16, 2004 3:34 pm

Post by Dr. Shadowborg »

Post Reply