Пример #1
0
void medic_idle (edict_t *self)
{
	if(!(self->spawnflags & SF_MONSTER_AMBUSH))
		gi.sound (self, CHAN_VOICE, sound_idle1, 1, ATTN_IDLE, 0);

	if(self->monsterinfo.aiflags & AI_MEDIC)
	{
		// Then we must have reached this point after losing sight
		// of our patient.
		abortHeal(self,false);
	}

	if(medic_FindDeadMonster(self))
		return;

	// If the map has hint_paths, AND the medic isn't at a HOLD point_combat,
	// AND the medic has previously called FoundTarget (trail_time set to
	// level.time), then look for hint_path chain and follow it, hopefully
	// to find monsters to resurrect
	if(self->monsterinfo.aiflags & AI_HINT_TEST)
		return;

	if (hint_chains_exist && !(self->monsterinfo.aiflags & AI_STAND_GROUND)
		&& ((self->monsterinfo.trail_time > 0) || medic_test) )
	{
		edict_t	*e;
		edict_t	*hint=NULL;
		float	dist;
		vec3_t	dir;
		int		i;
		float	bestdistance=99999;

		for(i=game.maxclients+1; i<globals.num_edicts; i++)
		{
			e = &g_edicts[i];
			if(!e->inuse)
				continue;
			if(Q_strcasecmp(e->classname,"hint_path"))
				continue;
			if(!visible(self,e))
				continue;
			if(!canReach(self,e))
				continue;
			VectorSubtract(e->s.origin,self->s.origin,dir);
			dist = VectorLength(dir);
			if(dist < bestdistance)
			{
				hint = e;
				bestdistance = dist;
			}
		}
		if(hint)
		{
			self->hint_chain_id = hint->hint_chain_id;
			if(!self->monsterinfo.pathdir)
				self->monsterinfo.pathdir = 1;
			VectorSubtract(hint->s.origin, self->s.origin, dir);
			self->ideal_yaw = vectoyaw(dir);
			self->goalentity = self->movetarget = hint;
			self->monsterinfo.pausetime = 0;
			self->monsterinfo.aiflags |= AI_MEDIC_PATROL;
			self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_PURSUIT_LAST_SEEN | AI_PURSUE_NEXT | AI_PURSUE_TEMP);
			// run for it
			self->monsterinfo.run (self);
		}
	}
}
Пример #2
0
// Argh! - loads id baseq2/player models, "patches" their skin links 
//         for misc_actor (all id skins, and slots for 10 custom 
//         skins), and saves them to the current moddir location
//
int PatchPlayerModels (char *modelname)
{
	cvar_t	*game;
	int		j;
	int		numskins;		// number of skin entries
	char	skins[MAX_MD2SKINS][MAX_SKINNAME];	// skin entries
	char	infilename[MAX_OSPATH];
	char	outfilename[MAX_OSPATH];
	FILE	*infile;
	FILE	*outfile;
	dmdl_t	model;		// model header
	byte	*data;		// model data
	int		datasize;	// model data size (bytes)
	int		newoffset;	// model data offset (after skins)

	// get game (moddir) name
	game = gi.cvar("game", "", 0);
	if (!*game->string)
		return 0;	// we're in baseq2

	sprintf (outfilename, "%s/players/%s/tris.md2", game->string, modelname);
	if ((outfile = fopen (outfilename, "rb")))
	{
		// output file already exists, move along
		fclose (outfile);
//		gi.dprintf ("PatchPlayerModels: Could not save %s, file already exists\n", outfilename);
		return 0;
	}

	// clear skin names (just in case)
	for (j = 0; j < MAX_MD2SKINS; j++)
		memset (skins[j], 0, MAX_SKINNAME);

	// set model-specific data
	if(!Q_strcasecmp(modelname,"male"))
	{
		numskins = 15;
		sprintf (skins[0],	"players/male/cipher.pcx");
		sprintf (skins[1],	"players/male/claymore.pcx");
		sprintf (skins[2],	"players/male/flak.pcx");
		sprintf (skins[3],	"players/male/grunt.pcx");
		sprintf (skins[4],	"players/male/howitzer.pcx");
		sprintf (skins[5],	"players/male/major.pcx");
		sprintf (skins[6],	"players/male/nightops.pcx");
		sprintf (skins[7],	"players/male/pointman.pcx");
		sprintf (skins[8],	"players/male/psycho.pcx");
		sprintf (skins[9],	"players/male/rampage.pcx");
		sprintf (skins[10], "players/male/razor.pcx");
		sprintf (skins[11], "players/male/recon.pcx");
		sprintf (skins[12], "players/male/scout.pcx");
		sprintf (skins[13], "players/male/sniper.pcx");
		sprintf (skins[14], "players/male/viper.pcx");
	}
	else if(!Q_strcasecmp(modelname,"female"))
	{
		numskins = 10;
		sprintf (skins[0],  "players/female/athena.pcx");
		sprintf (skins[1],  "players/female/brianna.pcx");
		sprintf (skins[2],  "players/female/cobalt.pcx");
		sprintf (skins[3],  "players/female/ensign.pcx");
		sprintf (skins[4],  "players/female/jezebel.pcx");
		sprintf (skins[5],  "players/female/jungle.pcx");
		sprintf (skins[6],  "players/female/lotus.pcx");
		sprintf (skins[7],  "players/female/stiletto.pcx");
		sprintf (skins[8],  "players/female/venus.pcx");
		sprintf (skins[9],  "players/female/voodoo.pcx");
	}
	else if(!Q_strcasecmp(modelname,"cyborg"))
	{
		numskins = 3;
		sprintf (skins[0],  "players/cyborg/oni911.pcx");
		sprintf (skins[1],  "players/cyborg/ps9000.pcx");
		sprintf (skins[2],  "players/cyborg/tyr574.pcx");
	}
	else
		return 0;

	// fill in 32 slots with "customXX"
	for(j=numskins; j<32; j++)
		sprintf( skins[j], "players/%s/custom%d.pcx", modelname, j-numskins+1);
	numskins = 32;

	// load original player model
	sprintf (infilename, "baseq2/players/%s/tris.md2", modelname);
	if ( !(infile = fopen (infilename, "rb")) )
		return 0;	// no player model (this shouldn't happen)
	
	fread (&model, sizeof (dmdl_t), 1, infile);
	
	datasize = model.ofs_end - model.ofs_skins;
	if ( !(data = (byte*)G_Malloc (datasize)) )	// make sure freed locally
	{
		gi.dprintf ("PatchPlayerModels: Could not allocate memory for model\n");
		return 0;
	}
	fread (data, sizeof (byte), datasize, infile);
	
	fclose (infile);
	
	// update model info
	model.num_skins = numskins;
	
	newoffset = numskins * MAX_SKINNAME;
	model.ofs_st     += newoffset;
	model.ofs_tris   += newoffset;
	model.ofs_frames += newoffset;
	model.ofs_glcmds += newoffset;
	model.ofs_end    += newoffset;
	
	// save new player model
	sprintf (outfilename, "%s/players", game->string);	// make some dirs if needed
	_mkdir (outfilename);
	sprintf (outfilename, "%s/players/%s", game->string, modelname);
	_mkdir (outfilename);
	sprintf (outfilename, "%s/players/%s/tris.md2", game->string, modelname);
	
	if ( !(outfile = fopen (outfilename, "wb")) )
	{
		// file couldn't be created for some other reason
		gi.dprintf ("PatchPlayerModels: Could not save %s\n", outfilename);
		G_Free(data);
		return 0;
	}
	
	fwrite (&model, sizeof (dmdl_t), 1, outfile);
	fwrite (skins, sizeof (char), newoffset, outfile);
	fwrite (data, sizeof (byte), datasize, outfile);
	
	fclose (outfile);
	gi.dprintf ("PatchPlayerModels: Saved %s\n", outfilename);
	G_Free(data);
	return 1;
}
Пример #3
0
static void CD_f (void)
{
    char	*command;
    int		ret;
    int		n;

    if (Cmd_Argc() < 2)
    {
        Con_Printf("CD parameters:\n on\n off\n reset\n remap\n eject\n close\n play\n loop\n pause\n resume\n stop\n info\n"); // Manoel Kasimier
        return;
    }

    command = Cmd_Argv (1);

    if (Q_strcasecmp(command, "on") == 0)
    {
        Cvar_SetValue("cd_enabled", 1); // Manoel Kasimier - CD player in menu
        return;
    }

    if (Q_strcasecmp(command, "off") == 0)
    {
        if (playing)
            CDAudio_Stop();
        Cvar_SetValue("cd_enabled", 0); // Manoel Kasimier - CD player in menu
        return;
    }

    if (Q_strcasecmp(command, "reset") == 0)
    {
        /* // Manoel Kasimier - Windows XP fix
        if (playing)
        	CDAudio_Stop();
        for (n = 0; n < 100; n++)
        	remap[n] = n;
        CDAudio_GetAudioDiskInfo();
        */ // Manoel Kasimier - Windows XP fix - begin
        CDAudio_Shutdown();
        CDAudio_Init();
        // Manoel Kasimier - Windows XP fix - end
        return;
    }

    if (Q_strcasecmp(command, "remap") == 0)
    {
        ret = Cmd_Argc() - 2;
        if (ret <= 0)
        {
            for (n = 1; n < 100; n++)
                if (remap[n] != n)
                    Con_Printf("  %u -> %u\n", n, remap[n]);
            return;
        }
        for (n = 1; n <= ret; n++)
            remap[n] = Q_atoi(Cmd_Argv (n+1));
        return;
    }

    // Manoel Kasimier - moved the "eject" command here so empty drives can be ejected
    if (Q_strcasecmp(command, "eject") == 0)
    {
        if (playing)
            CDAudio_Stop();
        CDAudio_Eject();
        cdValid = false;
        maxTrack = 0; // Manoel Kasimier - CD player in menu
        return;
    }

    if (Q_strcasecmp(command, "close") == 0)
    {
        CDAudio_CloseDoor();
        Cbuf_AddText ("wait;cd reset\n", "cd reset"); // Manoel Kasimier - CD player in menu - auto-update CD status after closing drive door
        return;
    }

    if (Q_strcasecmp(command, "info") == 0)
    {
        // Manoel Kasimier - begin
        if (!maxTrack)
            Con_Printf("No CD in player.\n");
        else
        {
            Con_Printf("%u tracks\n", maxTrack);
            if (!cdValid)
                Con_Printf("No audio tracks on disc\n");
            else // List valid tracks
            {
                Con_Printf("Audio tracks on disc:\n");
                for (n=1; n<=99; n++)
                    if (audioTrack[n])
                    {
                        if (!audioTrack[n+1]) // end of sequence, or isolated track
                            Con_Printf(" %2i\n", n);
                        else if (!audioTrack[n-1]) // beginning of sequence
                            Con_Printf(" %2i -", n);
                    }
                if (cd_enabled.value)
                {
                    // Manoel Kasimier - end
                    if (playing)
                        Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
                    else if (wasPlaying)
                        Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
                    // Manoel Kasimier - begin
                }
            }
        }
        if (!cd_enabled.value)
            Con_Printf("CD audio is off\n");
        // Manoel Kasimier - end
        Con_Printf("Volume is %.1f\n", cdvolume); // Manoel Kasimier - edited
        return;
    }

    if (!cdValid)
    {
        CDAudio_GetAudioDiskInfo();
        if (!cdValid)
        {
            // Manoel Kasimier - begin
            if (maxTrack)
                Con_Printf("No audio tracks on disc\n");
            else
                // Manoel Kasimier - end
                Con_Printf("No CD in player.\n");
            return;
        }
    }

    if (Q_strcasecmp(command, "play") == 0)
    {
        CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false);
        return;
    }

    if (Q_strcasecmp(command, "loop") == 0)
    {
        CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true);
        return;
    }

    if (Q_strcasecmp(command, "stop") == 0)
    {
        CDAudio_Stop();
        return;
    }

    if (Q_strcasecmp(command, "pause") == 0)
    {
        CDAudio_Pause();
        return;
    }

    if (Q_strcasecmp(command, "resume") == 0)
    {
        CDAudio_Resume();
        return;
    }

    Con_Printf("CD parameters:\n on\n off\n reset\n remap\n eject\n close\n play\n loop\n pause\n resume\n stop\n info\n"); // Manoel Kasimier - absent/unrecognized parameter
}
Пример #4
0
/*
====================
CL_UpdateLevelHunkUsage

  This updates the "hunkusage.dat" file with the current map and it's hunk usage count

  This is used for level loading, so we can show a percentage bar dependant on the amount
  of hunk memory allocated so far

  This will be slightly inaccurate if some settings like sound quality are changed, but these
  things should only account for a small variation (hopefully)
====================
*/
void CL_UpdateLevelHunkUsage( void ) {
	int handle;
	char *memlistfile = "hunkusage.dat";
	char *buf, *outbuf;
	char *buftrav, *outbuftrav;
	char *token;
	char outstr[256];
	int len, memusage;

	memusage = Cvar_VariableIntegerValue( "com_hunkused" ) + Cvar_VariableIntegerValue( "hunk_soundadjust" );

	len = FS_FOpenFileByMode( memlistfile, &handle, FS_READ );
	if ( len >= 0 ) { // the file exists, so read it in, strip out the current entry for this map, and save it out, so we can append the new value

		buf = (char *)Z_Malloc( len + 1 );
		memset( buf, 0, len + 1 );
		outbuf = (char *)Z_Malloc( len + 1 );
		memset( outbuf, 0, len + 1 );

		FS_Read( (void *)buf, len, handle );
		FS_FCloseFile( handle );

		// now parse the file, filtering out the current map
		buftrav = buf;
		outbuftrav = outbuf;
		outbuftrav[0] = '\0';
		while ( ( token = COM_Parse( &buftrav ) ) && token[0] ) {
			if ( !Q_strcasecmp( token, cl.mapname ) ) {
				// found a match
				token = COM_Parse( &buftrav );  // read the size
				if ( token && token[0] ) {
					if ( atoi( token ) == memusage ) {  // if it is the same, abort this process
						Z_Free( buf );
						Z_Free( outbuf );
						return;
					}
				}
			} else {    // send it to the outbuf
				Q_strcat( outbuftrav, len + 1, token );
				Q_strcat( outbuftrav, len + 1, " " );
				token = COM_Parse( &buftrav );  // read the size
				if ( token && token[0] ) {
					Q_strcat( outbuftrav, len + 1, token );
					Q_strcat( outbuftrav, len + 1, "\n" );
				} else {
					Com_Error( ERR_DROP, "hunkusage.dat file is corrupt\n" );
				}
			}
		}

#ifdef __MACOS__    //DAJ MacOS file typing
		{
			extern _MSL_IMP_EXP_C long _fcreator, _ftype;
			_ftype = 'TEXT';
			_fcreator = 'WlfS';
		}
#endif
		handle = FS_FOpenFileWrite( memlistfile );
		if ( handle < 0 ) {
			Com_Error( ERR_DROP, "cannot create %s\n", memlistfile );
		}
		// input file is parsed, now output to the new file
		len = strlen( outbuf );
		if ( FS_Write( (void *)outbuf, len, handle ) != len ) {
			Com_Error( ERR_DROP, "cannot write to %s\n", memlistfile );
		}
		FS_FCloseFile( handle );

		Z_Free( buf );
		Z_Free( outbuf );
	}
	// now append the current map to the current file
	FS_FOpenFileByMode( memlistfile, &handle, FS_APPEND );
	if ( handle < 0 ) {
		Com_Error( ERR_DROP, "cannot write to hunkusage.dat, check disk full\n" );
	}
	Com_sprintf( outstr, sizeof( outstr ), "%s %i\n", cl.mapname, memusage );
	FS_Write( outstr, strlen( outstr ), handle );
	FS_FCloseFile( handle );

	// now just open it and close it, so it gets copied to the pak dir
	len = FS_FOpenFileByMode( memlistfile, &handle, FS_READ );
	if ( len >= 0 ) {
		FS_FCloseFile( handle );
	}
}
Пример #5
0
static void _Datagram_SearchForHosts(qboolean xmit)
{
    int		ret;
    int		n;
    int		i;
    struct qsockaddr readaddr;
    struct qsockaddr myaddr;
    int		control;

    dfunc.GetSocketAddr(dfunc.controlSock, &myaddr);
    if (xmit) {
        SZ_Clear(&net_message);
        // save space for the header, filled in later
        MSG_WriteLong(&net_message, 0);
        MSG_WriteByte(&net_message, CCREQ_SERVER_INFO);
        MSG_WriteString(&net_message, "QUAKE");
        MSG_WriteByte(&net_message, NET_PROTOCOL_VERSION);
        *((int *)net_message.data) = BigLong(NETFLAG_CTL | (net_message.cursize & NETFLAG_LENGTH_MASK));
        dfunc.Broadcast(dfunc.controlSock, net_message.data, net_message.cursize);
        SZ_Clear(&net_message);
    }

    while ((ret = dfunc.Read(dfunc.controlSock, net_message.data, net_message.maxsize, &readaddr)) > 0) {
        if (ret < sizeof(int)) {
            continue;
        }
        net_message.cursize = ret;

        // don't answer our own query
        if (dfunc.AddrCompare(&readaddr, &myaddr) >= 0) {
            continue;
        }

        // is the cache full?
        if (hostCacheCount == HOSTCACHESIZE) {
            continue;
        }

        MSG_BeginReading();
        control = BigLong(*((int *)net_message.data));
        MSG_ReadLong();
        if (control == -1) {
            continue;
        }
        if ((control & (~NETFLAG_LENGTH_MASK)) !=  NETFLAG_CTL) {
            continue;
        }
        if ((control & NETFLAG_LENGTH_MASK) != ret) {
            continue;
        }

        if (MSG_ReadByte() != CCREP_SERVER_INFO) {
            continue;
        }

        dfunc.GetAddrFromName(MSG_ReadString(), &readaddr);
        // search the cache for this server
        for (n = 0; n < hostCacheCount; n++)
            if (dfunc.AddrCompare(&readaddr, &hostcache[n].addr) == 0) {
                break;
            }

        // is it already there?
        if (n < hostCacheCount) {
            continue;
        }

        // add it
        hostCacheCount++;
        Q_strcpy(hostcache[n].name, MSG_ReadString());
        Q_strcpy(hostcache[n].map, MSG_ReadString());
        hostcache[n].users = MSG_ReadByte();
        hostcache[n].maxusers = MSG_ReadByte();
        if (MSG_ReadByte() != NET_PROTOCOL_VERSION) {
            Q_strcpy(hostcache[n].cname, hostcache[n].name);
            hostcache[n].cname[14] = 0;
            Q_strcpy(hostcache[n].name, "*");
            Q_strcat(hostcache[n].name, hostcache[n].cname);
        }
        Q_memcpy(&hostcache[n].addr, &readaddr, sizeof(struct qsockaddr));
        hostcache[n].driver = net_driverlevel;
        hostcache[n].ldriver = net_landriverlevel;
        Q_strcpy(hostcache[n].cname, dfunc.AddrToString(&readaddr));

        // check for a name conflict
        for (i = 0; i < hostCacheCount; i++) {
            if (i == n) {
                continue;
            }
            if (Q_strcasecmp(hostcache[n].name, hostcache[i].name) == 0) {
                i = Q_strlen(hostcache[n].name);
                if (i < 15 && hostcache[n].name[i-1] > '8') {
                    hostcache[n].name[i] = '0';
                    hostcache[n].name[i+1] = 0;
                } else {
                    hostcache[n].name[i-1]++;
                }
                i = -1;
            }
        }
    }
}
Пример #6
0
/*
===============
CG_SoundParseSounds
===============
*/
static void CG_SoundParseSounds ( char *filename, char *buffer ) {
	char *token, **text;
	int s;
	long	hash;
	soundScript_t		sound;			// the current sound being read
	soundScriptSound_t	*scriptSound;
	qboolean	inSound, wantSoundName;

	s = 0;
	inSound = qfalse;
	wantSoundName = qtrue;
	text = &buffer;

	while ( 1 ) {
		token = COM_ParseExt( text, qtrue );
		if ( !token[0] ) {
			if (inSound) {
				CG_Error( "no concluding '}' in sound %s, file %s\n", sound.name, filename );
			}
			return;
		}
		if ( !Q_strcasecmp( token, "{" ) ) {
			if (inSound) {
				CG_Error( "no concluding '}' in sound %s, file %s\n", sound.name, filename );
			}
			if (wantSoundName) {
				CG_Error( "'{' found but not expected, after %s, file %s\n", sound.name, filename );
			}
			inSound = qtrue;
			continue;
		}
		if ( !Q_strcasecmp( token, "}" ) ) {
			if (!inSound) {
				CG_Error( "'}' unexpected after sound %s, file %s\n", sound.name, filename );
			}
		
			// end of a sound, copy it to the global list and stick it in the hashTable
			hash = generateHashValue( sound.name );
			sound.nextHash = hashTable[hash];
			soundScripts[numSoundScripts] = sound;
			hashTable[hash] = &soundScripts[numSoundScripts++];

			if (numSoundScripts == MAX_SOUND_SCRIPTS) {
				CG_Error( "MAX_SOUND_SCRIPTS exceeded.\nReduce number of sound scripts.\n" );
			}

			inSound = qfalse;
			wantSoundName = qtrue;
			continue;
		}
		if ( !inSound ) {
			// this is the identifier for a new sound
			if (!wantSoundName) {
				CG_Error( "'%s' unexpected after sound %s, file %s\n", token, sound.name, filename );
			}
			memset( &sound, 0, sizeof(sound) );
			Q_strncpyz( sound.name, token, sizeof(sound.name) );
			wantSoundName = qfalse;
			sound.index = numSoundScripts;
			// setup the new sound defaults
			sound.channel = CHAN_AUTO;
			sound.attenuation = 1;	// default to fade away with distance (for streaming sounds)
			//
			continue;
		}
		
		// we are inside a sound script

		if ( !Q_strcasecmp( token, "channel" ) ) {
			// ignore this now, just look for the channel identifiers explicitly
			continue;
		}
		if ( !Q_strcasecmp( token, "local" ) ) {
			sound.channel = CHAN_LOCAL;
			continue;
		} else if ( !Q_strcasecmp( token, "announcer" ) ) {
			sound.channel = CHAN_ANNOUNCER;
			continue;
		} else if ( !Q_strcasecmp( token, "body" ) ) {
			sound.channel = CHAN_BODY;
			continue;
		} else if ( !Q_strcasecmp( token, "voice" ) ) {
			sound.channel = CHAN_VOICE;
			continue;
		} else if ( !Q_strcasecmp( token, "weapon" ) ) {
			sound.channel = CHAN_WEAPON;
			continue;
		} else if ( !Q_strcasecmp( token, "item" ) ) {
			sound.channel = CHAN_ITEM;
			continue;
		} else if ( !Q_strcasecmp( token, "auto" ) ) {
			sound.channel = CHAN_AUTO;
			continue;
		}
		if ( !Q_strcasecmp( token, "global" ) ) {
			sound.attenuation = 0;
			continue;
		}
		if ( !Q_strcasecmp( token, "streaming" ) ) {
			sound.streaming = qtrue;
			continue;
		}
		if ( !Q_strcasecmp( token, "looping" ) ) {
			sound.looping = qtrue;
			continue;
		}
		if ( !Q_strcasecmp( token, "sound" ) ) {
			// grab a free scriptSound
			scriptSound = &soundScriptSounds[numSoundScriptSounds++];

			if (numSoundScripts == MAX_SOUND_SCRIPT_SOUNDS) {
				CG_Error( "MAX_SOUND_SCRIPT_SOUNDS exceeded.\nReduce number of sound scripts.\n" );
			}

			token = COM_ParseExt( text, qtrue );
			Q_strncpyz( scriptSound->filename, token, sizeof(scriptSound->filename) );
			scriptSound->lastPlayed = 0;
			scriptSound->sfxHandle = 0;
			scriptSound->next = sound.soundList;
			sound.soundList = scriptSound;
			continue;
		}
	}
}
Пример #7
0
gltexture_t *Material_LoadTexture(Material_t *mMaterial, MaterialSkin_t *mCurrentSkin, char *cArg)
{
	int	iTextureFlags = TEXPREF_ALPHA|TEXPREF_MIPMAP;
	uint8_t *bTextureMap;

	// Check if it's trying to use a built-in texture.
	if (cArg[0] == '@')
	{
		cArg++;

		if (!Q_strcasecmp(cArg, "notexture"))
			return notexture;
		else if (!Q_strcasecmp(cArg, "lightmap"))
		{
			mMaterial->override_lightmap = true;
			mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].mttType = MATERIAL_TEXTURE_LIGHTMAP;
			return notexture;
		}
		else
		{
			Con_Warning("Attempted to set invalid internal texture! (%s)\n", mMaterial->cPath);
			return notexture;
		}
	}

	// Ensure we haven't loaded the texture in already...
	gltexture_t *gTexture = TexMgr_GetTexture(cArg);
	if (gTexture)
#if 0	// Debugging
	{
		Con_Printf("Found already existing sample! (%s) (%s)", gTexture->name, mMaterial->cPath);
		return gTexture;
	}
#else
		return gTexture;
#endif

	bTextureMap = Image_LoadImage(cArg,
		&mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiWidth,
		&mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiHeight);
	if (bTextureMap)
	{
		// Warn about incorrect sizes.
		if ((mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiWidth % 2) || (mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiHeight % 2))
		{

			Con_Warning("Texture size is not multiple of 2! (%s) (%ix%i)\n", cArg,
				mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiWidth,
				mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiHeight);

#if 1
			// Pad the image.
			iTextureFlags |= TEXPREF_PAD;
#endif
		}

		if (mMaterial->iFlags & MATERIAL_FLAG_PRESERVE)
			iTextureFlags |= TEXPREF_PERSIST;

		if (mCurrentSkin->uiFlags & MATERIAL_FLAG_NEAREST)
			iTextureFlags |= TEXPREF_NEAREST;

		return TexMgr_LoadImage(NULL, cArg,
			mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiWidth,
			mCurrentSkin->mtTexture[mCurrentSkin->uiTextures].uiHeight,
			SRC_RGBA, bTextureMap, cArg, 0, iTextureFlags);
	}

	Con_Warning("Failed to load texture! (%s) (%s)\n", cArg, mMaterial->cPath);

	return notexture;
}
Пример #8
0
/*
 * Takes a key/value pair and sets
 * the binary values in an edict
 */
void
ED_ParseField(const char *key, const char *value, edict_t *ent)
{
	field_t *f;
	byte *b;
	float v;
	vec3_t vec;

	if (!key || !value)
	{
		return;
	}

	for (f = fields; f->name; f++)
	{
		if (!(f->flags & FFL_NOSPAWN) && !Q_strcasecmp(f->name, (char *)key))
		{
			/* found it */
			if (f->flags & FFL_SPAWNTEMP)
			{
				b = (byte *)&st;
			}
			else
			{
				b = (byte *)ent;
			}

			switch (f->type)
			{
				case F_LSTRING:
					*(char **)(b + f->ofs) = ED_NewString(value);
					break;
				case F_VECTOR:
					sscanf(value, "%f %f %f", &vec[0], &vec[1], &vec[2]);
					((float *)(b + f->ofs))[0] = vec[0];
					((float *)(b + f->ofs))[1] = vec[1];
					((float *)(b + f->ofs))[2] = vec[2];
					break;
				case F_INT:
					*(int *)(b + f->ofs) = (int)strtol(value, (char **)NULL, 10);
					break;
				case F_FLOAT:
					*(float *)(b + f->ofs) = (float)strtod(value, (char **)NULL);
					break;
				case F_ANGLEHACK:
					v = (float)strtod(value, (char **)NULL);
					((float *)(b + f->ofs))[0] = 0;
					((float *)(b + f->ofs))[1] = v;
					((float *)(b + f->ofs))[2] = 0;
					break;
				case F_IGNORE:
					break;
				default:
					break;
			}

			return;
		}
	}

	gi.dprintf("%s is not a field\n", key);
}
Пример #9
0
/*
 * ======================
 * SV_Map
 *
 * the full syntax is:
 *
 * map [*]<map>$<startspot>+<nextserver>
 *
 * command from the console or progs.
 * Map can also be a.cin, .pcx, or .dm2 file
 * Nextserver is used to allow a cinematic to play, then proceed to
 * another level:
 *
 *      map tram.cin+jail_e3
 * ======================
 */
void SV_Map(qboolean attractloop, char *levelstring, qboolean loadgame)
{
    char level[MAX_QPATH];
    char *ch;
    int  l;
    char spawnpoint[MAX_QPATH];

    sv.loadgame    = loadgame;
    sv.attractloop = attractloop;

    if ((sv.state == ss_dead) && !sv.loadgame)
    {
        SV_InitGame();          // the game is just starting
    }
    // r1ch fix: buffer overflow
//	strcpy (level, levelstring);
    strncpy(level, levelstring, sizeof(level) - 1);

    // if there is a + in the map, set nextserver to the remainder
    ch = strstr(level, "+");
    if (ch)
    {
        *ch = 0;
        Cvar_Set("nextserver", va("gamemap \"%s\"", ch + 1));
    }
    else
    {
        Cvar_Set("nextserver", "");
    }

    //ZOID special hack for end game screen in coop mode
    if (Cvar_VariableValue("coop") && !Q_strcasecmp(level, "victory.pcx"))
    {
        Cvar_Set("nextserver", "gamemap \"*base1\"");
    }

    // if there is a $, use the remainder as a spawnpoint
    ch = strstr(level, "$");
    if (ch)
    {
        *ch = 0;
        strcpy(spawnpoint, ch + 1);
    }
    else
    {
        spawnpoint[0] = 0;
    }

    // skip the end-of-unit flag if necessary
    if (level[0] == '*')
    {
        strcpy(level, level + 1);
    }

    l = strlen(level);
#ifdef  ROQ_SUPPORT
    if ((l > 4) && (!strcmp(level + l - 4, ".cin") || !strcmp(level + l - 4, ".roq")))
#else
    if ((l > 4) && !strcmp(level + l - 4, ".cin"))
#endif // ROQ_SUPPORT
    {
        if (!dedicated->value)
        {
#ifndef DEDICATED_ONLY                 
            SCR_BeginLoadingPlaque();                                   // for local system
#endif            
        }
        SV_BroadcastCommand("changing\n");
        SV_SpawnServer(level, spawnpoint, ss_cinematic, attractloop, loadgame);
    }
    else if ((l > 4) && !strcmp(level + l - 4, ".dm2"))
    {
        if (!dedicated->value)
        {
#ifndef DEDICATED_ONLY                 
            SCR_BeginLoadingPlaque();                                   // for local system
#endif            
        }
        SV_BroadcastCommand("changing\n");
        SV_SpawnServer(level, spawnpoint, ss_demo, attractloop, loadgame);
    }
    else if ((l > 4) && !strcmp(level + l - 4, ".pcx"))
    {
        if (!dedicated->value)
        {
#ifndef DEDICATED_ONLY                 
            SCR_BeginLoadingPlaque();                                   // for local system
#endif            
        }
        SV_BroadcastCommand("changing\n");
        SV_SpawnServer(level, spawnpoint, ss_pic, attractloop, loadgame);
    }
    else
    {
        if (!dedicated->value)
        {
#ifndef DEDICATED_ONLY                 
            SCR_BeginLoadingPlaque();                                   // for local system
#endif            
        }
        SV_BroadcastCommand("changing\n");
        SV_SendClientMessages();
        SV_SpawnServer(level, spawnpoint, ss_game, attractloop, loadgame);
        Cbuf_CopyToDefer();
    }

    SV_BroadcastCommand("reconnect\n");
}
Пример #10
0
void Cmd_Bless(edict_t *ent)
{
	int radius;
	float duration, cooldown;
	edict_t *target = NULL;

	if (debuginfo->value)
		gi.dprintf("DEBUG: %s just called Cmd_Bless()\n", ent->client->pers.netname);

	if(ent->myskills.abilities[BLESS].disable)
		return;

	//if (!G_CanUseAbilities(ent, ent->myskills.abilities[BLESS].current_level, BLESS_COST))
	//	return;

	if (!V_CanUseAbilities(ent, BLESS, BLESS_COST, true))
		return;

	radius = SHAMAN_CURSE_RADIUS_BASE + (SHAMAN_CURSE_RADIUS_BONUS * ent->myskills.abilities[BLESS].current_level);
	duration = BLESS_DURATION_BASE + (BLESS_DURATION_BONUS * ent->myskills.abilities[BLESS].current_level);

	//Blessing self?
	if (Q_strcasecmp(gi.argv(1), "self") == 0)
	{
		if (HasFlag(ent))
		{
			gi.cprintf(ent, PRINT_HIGH, "Can't use this while carrying the flag!\n");
			return;
		}

		if (!curse_add(ent, ent, BLESS, 0, duration))
		{
			gi.cprintf(ent, PRINT_HIGH, "Unable to bless self.\n");
			return;
		}
		target = ent;
	}
	else
	{
		target = curse_Attack(ent, BLESS, radius, duration, false);
	}

	if (target != NULL)
	{
		que_t *slot = NULL;

		//Finish casting the spell
		ent->client->ability_delay = level.time + BLESS_DELAY;
		ent->client->pers.inventory[power_cube_index] -= BLESS_COST;

		cooldown = 2.0 * duration;
		if (cooldown > 10.0)
			cooldown = 10.0;

		ent->myskills.abilities[BLESS].delay = level.time + cooldown;

		//Change the curse think to the bless think
		slot = que_findtype(target->curses, NULL, BLESS);
		if (slot)
		{
			slot->ent->think = Bless_think;
			slot->ent->nextthink = level.time + FRAMETIME;
		}

		//Notify the target
		if (target == ent)
		{
			gi.cprintf(target, PRINT_HIGH, "YOU HAVE BEEN BLESSED FOR %0.1f seconds!!\n", duration);
		}
		else if ((target->client) && !(target->svflags & SVF_MONSTER))
		{
			gi.cprintf(target, PRINT_HIGH, "YOU HAVE BEEN BLESSED FOR %0.1f seconds!!\n", duration);
			gi.cprintf(ent, PRINT_HIGH, "Blessed %s for %0.1f seconds.\n", target->myskills.player_name, duration);
		}
		else
		{
			gi.cprintf(ent, PRINT_HIGH, "Blessed %s for %0.1f seconds.\n", target->classname, duration);
		}
		//Play the spell sound!
		gi.sound(target, CHAN_ITEM, gi.soundindex("curses/bless.wav"), 1, ATTN_NORM, 0);
	}
}
Пример #11
0
Файл: brush.c Проект: kellyrm/Q1
/*
===============
LoadBrush

Converts a mapbrush to a bsp brush
===============
*/
brush_t *LoadBrush (mbrush_t *mb, int hullnum)
{
	brush_t		*b;
	int		contents, NoOfTex = 0, I, TexNo[3], MipTex1, MipTex2, Hull;
	char		*name, Str[512];
	mface_t		*f;

	CurrLine = mb->Line;

//
// check texture name for attributes
//
	name = miptex[MipTex1 = texinfo[mb->faces->texinfo].miptex];

	if (!Q_strcasecmp(name, "clip") && hullnum == 0)
		return NULL;		// "clip" brushes don't show up in the draw hull

	if (name[0] == '*' && worldmodel)		// entities never use water merging
	{
		if (!Q_strncasecmp(name+1,"lava",4))
			contents = CONTENTS_LAVA;
		else if (!Q_strncasecmp(name+1,"slime",5))
			contents = CONTENTS_SLIME;
		else
			contents = CONTENTS_WATER;
	}
	else if (!options.SolidMap && !Q_strncasecmp (name, "sky",3) && worldmodel && hullnum == 0)
		contents = CONTENTS_SKY;
	else
		contents = CONTENTS_SOLID;

	if (hullnum && contents != CONTENTS_SOLID && contents != CONTENTS_SKY)
		return NULL;		// water brushes don't show up in clipping hulls

// no seperate textures on clip hull

//
// create the faces
//
	brush_faces = NULL;

	numbrushfaces = 0;
	for (f=mb->faces ; f ; f=f->next)
	{
		faces[numbrushfaces] = *f;
		if (hullnum)
			faces[numbrushfaces].texinfo = 0;
		numbrushfaces++;

		if (numbrushfaces == MAX_FACES)
			Message (MSGERR, "LoadBrush: numbrushfaces == MAX_FACES (%d) on line %d", MAX_FACES, CurrLine);
	}

	CreateBrushFaces ();

	if (!brush_faces)
	{
		strcpy(Str, name);

		// Find max 3 extra unique texture names
		for (f = mb->faces; f; f = f->next)
		{
			MipTex2 = texinfo[f->texinfo].miptex;

			if (NoOfTex < 3 && MipTex2 != MipTex1)
			{
				for (I = 0; I < NoOfTex; ++I)
				{
					if (MipTex2 == TexNo[I])
						break;
				}

				if (I == NoOfTex)
					TexNo[NoOfTex++] = MipTex2;
			}
		}

		for (I = 0; I < NoOfTex; ++I)
		{
		        strcat(Str, " ");
		        strcat(Str, miptex[TexNo[I]]);
		}

		Message (MSGWARN, "Couldn't create brush on line %d with %d faces, %s", CurrLine, numbrushfaces, Str);
		return NULL;
	}

	Hull = hullnum == 0 ? options.visiblehull : hullnum;

	if (Hull || options.HullExpansion[1] > 0)
	{
		ExpandBrush (Hull);
		FreeBrushFaces(brush_faces);
		CreateBrushFaces ();
	}

//
// create the brush
//
	b = AllocBrush ();

	b->contents = contents;
	b->faces = brush_faces;
	VectorCopy (brush_mins, b->mins);
	VectorCopy (brush_maxs, b->maxs);

	return b;
}
Пример #12
0
void Cmd_Healing(edict_t *ent)
{
	int radius;
	float duration;
	edict_t *target = NULL;

	if (debuginfo->value)
		gi.dprintf("DEBUG: %s just called Cmd_Healing()\n", ent->client->pers.netname);

	if(ent->myskills.abilities[HEALING].disable)
		return;

	if (!G_CanUseAbilities(ent, ent->myskills.abilities[HEALING].current_level, HEALING_COST))
		return;

	radius = SHAMAN_CURSE_RADIUS_BASE + (SHAMAN_CURSE_RADIUS_BONUS * ent->myskills.abilities[HEALING].current_level);
	duration = HEALING_DURATION_BASE + (HEALING_DURATION_BONUS * ent->myskills.abilities[HEALING].current_level);

	//Blessing self?
	if (Q_strcasecmp(gi.argv(1), "self") == 0)
	{
		if (!curse_add(ent, ent, HEALING, 0, duration))
		{
			gi.cprintf(ent, PRINT_HIGH, "Unable to bless self.\n");
			return;
		}
		target = ent;
	}
	else
	{
		target = curse_Attack(ent, HEALING, radius, duration, false);
	}
	if (target != NULL)
	{
		que_t *slot = NULL;
		//Finish casting the spell
		ent->client->ability_delay = level.time + HEALING_DELAY;
		ent->client->pers.inventory[power_cube_index] -= HEALING_COST;

		//Change the curse think to the healing think
		slot = que_findtype(target->curses, NULL, HEALING);
		if (slot)
		{
			slot->ent->think = Healing_think;
			slot->ent->nextthink = level.time + FRAMETIME;
		}

		//Notify the target
		if (target == ent)
		{
			gi.cprintf(target, PRINT_HIGH, "YOU HAVE BEEN BLESSED WITH %0.1f seconds OF HEALING!!\n", duration);
		}
		else if ((target->client) && !(target->svflags & SVF_MONSTER))
		{
			gi.cprintf(target, PRINT_HIGH, "YOU HAVE BEEN BLESSED WITH %0.1f seconds OF HEALING!!\n", duration);
			gi.cprintf(ent, PRINT_HIGH, "Blessed %s with healing for %0.1f seconds.\n", target->myskills.player_name, duration);
		}
		else
		{
			gi.cprintf(ent, PRINT_HIGH, "Blessed %s with healing for %0.1f seconds.\n", target->classname, duration);
		}
		//Play the spell sound!
		gi.sound(target, CHAN_ITEM, gi.soundindex("curses/prayer.wav"), 1, ATTN_NORM, 0);
	}
}
Пример #13
0
void Cmd_Deflect_f(edict_t *ent)
{
	float duration;
	edict_t *target = ent; // default target is self

	if (!V_CanUseAbilities(ent, DEFLECT, DEFLECT_COST, true))
		return;

	duration = DEFLECT_INITIAL_DURATION + DEFLECT_ADDON_DURATION * ent->myskills.abilities[DEFLECT].current_level;

	// bless the tank instead of the noclipped player
	if (PM_PlayerHasMonster(ent))
		target = target->owner;

	//Blessing self?
	if (Q_strcasecmp(gi.argv(1), "self") == 0)
	{
		if (!curse_add(target, ent, DEFLECT, 0, duration))
		{
			gi.cprintf(ent, PRINT_HIGH, "Unable to bless self.\n");
			return;
		}
		//target = ent;
	}
	else
	{
		target = curse_Attack(ent, DEFLECT, 512.0, duration, false);
	}

	if (target != NULL)
	{
		que_t *slot = NULL;

		//Finish casting the spell
		ent->client->ability_delay = level.time + DEFLECT_DELAY;
		ent->client->pers.inventory[power_cube_index] -= DEFLECT_COST;
	//	ent->myskills.abilities[DEFLECT].delay = level.time + duration + DEFLECT_DELAY;

		//Change the curse think to the deflect think
		slot = que_findtype(target->curses, NULL, DEFLECT);
		if (slot)
		{
			slot->ent->think = deflect_think;
			slot->ent->nextthink = level.time + FRAMETIME;
			slot->ent->random = DEFLECT_INITIAL_PROJECTILE_CHANCE+DEFLECT_ADDON_HITSCAN_CHANCE*ent->myskills.abilities[DEFLECT].current_level;
			if (slot->ent->random > DEFLECT_MAX_PROJECTILE_CHANCE)
				slot->ent->random = DEFLECT_MAX_PROJECTILE_CHANCE;
		}

		//Notify the target
		if (target == ent)
		{
			gi.cprintf(target, PRINT_HIGH, "You have been blessed with deflect for %0.1f seconds!\n", duration);
		}
		else if ((target->client) && !(target->svflags & SVF_MONSTER))
		{
			gi.cprintf(target, PRINT_HIGH, "You have been blessed with deflect for %0.1f seconds!\n\n", duration);
			gi.cprintf(ent, PRINT_HIGH, "Blessed %s with deflect for %0.1f seconds.\n", target->myskills.player_name, duration);
		}
		else
		{
			gi.cprintf(ent, PRINT_HIGH, "Blessed %s with deflect for %0.1f seconds.\n", V_GetMonsterName(target), duration);
		}

		//Play the spell sound!
		gi.sound(target, CHAN_ITEM, gi.soundindex("curses/prayer.wav"), 1, ATTN_NORM, 0);
	}
}
Пример #14
0
/*	Converts a mapbrush to a bsp brush
*/
brush_t *LoadBrush (mbrush_t *mb, int brushnum, int hullnum)
{
	brush_t		*b;
	int			contents;
	char		*name;
	mface_t		*f;

	//
	// check texture name for attributes
	//

	for (f = mb->faces;f;f = f->next)
	{
		name = miptex[texinfo[f->texinfo].iMipTex];
		if (hullnum == 0)
			// textures which don't show up in the drawing hull
			if(!Q_strcasecmp(name,"clip"))
				return NULL;
	}

	name = miptex[texinfo[mb->faces->texinfo].iMipTex];
	if (name[0] == '*')		// entities never use water merging
	{
		if(!Q_strncasecmp(name+1,"lava",4))
			contents = BSP_CONTENTS_LAVA;
		else if(!Q_strncasecmp(name+1,"slime",5))
			contents = BSP_CONTENTS_SLIME;
		else
			contents = BSP_CONTENTS_WATER;
	}
	else if (!Q_strncasecmp (name, "sky",3) && hullnum == 0)
		contents = BSP_CONTENTS_SKY;
	else
		contents = BSP_CONTENTS_SOLID;

	if (hullnum && contents != BSP_CONTENTS_SOLID && contents != BSP_CONTENTS_SKY)
		return NULL;		// water brushes don't show up in clipping hulls

	// no seperate textures on clip hull

	//
	// create the faces
	//
	brush_faces = NULL;

	numbrushfaces = 0;
	for(f = mb->faces; f; f = f->next)
	{
		faces[numbrushfaces] = *f;
		if(hullnum)
			faces[numbrushfaces].texinfo = 0;

		numbrushfaces++;
	}

	if(hullnum)
		ExpandBrush (hullnum);

	CreateBrushFaces();

	if (!brush_faces)
	{
		printf ("WARNING: couldn't create faces for brush %i in entity %i (incomplete brush?)\n", brushnum, (int)(CurrentEntity - entities));
		return NULL;
	}

	//
	// create the brush
	//
	b = AllocBrush ();
	b->contents = contents;
	b->faces = brush_faces;
	VectorCopy (brush_mins, b->mins);
	VectorCopy (brush_maxs, b->maxs);
	// debugging code
	//printf("mapbrush\n");
	//for (f=mb->faces ; f ; f=f->next)
	//	printf("face %f %f %f %f \"%s\"\n", f->plane.normal[0], f->plane.normal[1], f->plane.normal[2], f->plane.dist, miptex[texinfo[f->texinfo].miptex]);
	//printf("bspbrush %i\n", numbrushfaces);
	//face_t		*face;
	//for (face=b->faces ; face ; face=face->next)
	//	printf("bspface %f %f %f %f\n", mapplanes[face->planenum].normal[0], mapplanes[face->planenum].normal[1], mapplanes[face->planenum].normal[2], mapplanes[face->planenum].dist);

	return b;
}
Пример #15
0
void
LoadPCX(char *origname, byte **pic, byte **palette, int *width, int *height)
{
	byte *raw;
	pcx_t *pcx;
	int x, y;
	int len, full_size;
	int pcx_width, pcx_height;
	qboolean image_issues = false;
	int dataByte, runLength;
	byte *out, *pix;
	char filename[256];

	Q_strlcpy(filename, origname, sizeof(filename));

	/* Add the extension */
	if (strcmp(COM_FileExtension(filename), "pcx"))
	{
		Q_strlcat(filename, ".pcx", sizeof(filename));
	}

	*pic = NULL;

	if (palette)
	{
		*palette = NULL;
	}

	/* load the file */
	len = ri.FS_LoadFile(filename, (void **)&raw);

	if (!raw || len < sizeof(pcx_t))
	{
		R_Printf(PRINT_DEVELOPER, "Bad pcx file %s\n", filename);
		return;
	}

	/* parse the PCX file */
	pcx = (pcx_t *)raw;

	pcx->xmin = LittleShort(pcx->xmin);
	pcx->ymin = LittleShort(pcx->ymin);
	pcx->xmax = LittleShort(pcx->xmax);
	pcx->ymax = LittleShort(pcx->ymax);
	pcx->hres = LittleShort(pcx->hres);
	pcx->vres = LittleShort(pcx->vres);
	pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
	pcx->palette_type = LittleShort(pcx->palette_type);

	raw = &pcx->data;

	pcx_width = pcx->xmax - pcx->xmin;
	pcx_height = pcx->ymax - pcx->ymin;

	if ((pcx->manufacturer != 0x0a) || (pcx->version != 5) ||
		(pcx->encoding != 1) || (pcx->bits_per_pixel != 8) ||
		(pcx_width >= 4096) || (pcx_height >= 4096))
	{
		R_Printf(PRINT_ALL, "Bad pcx file %s\n", filename);
		ri.FS_FreeFile(pcx);
		return;
	}

	full_size = (pcx_height + 1) * (pcx_width + 1);
	out = malloc(full_size);
	if (!out)
	{
		R_Printf(PRINT_ALL, "Can't allocate\n");
		ri.FS_FreeFile(pcx);
		return;
	}

	*pic = out;

	pix = out;

	if (palette)
	{
		*palette = malloc(768);
		if (!(*palette))
		{
			R_Printf(PRINT_ALL, "Can't allocate\n");
			free(out);
			ri.FS_FreeFile(pcx);
			return;
		}
		if (len > 768)
		{
			memcpy(*palette, (byte *)pcx + len - 768, 768);
		}
		else
		{
			image_issues = true;
		}
	}

	if (width)
	{
		*width = pcx_width + 1;
	}

	if (height)
	{
		*height = pcx_height + 1;
	}

	for (y = 0; y <= pcx_height; y++, pix += pcx_width + 1)
	{
		for (x = 0; x <= pcx_width; )
		{
			if (raw - (byte *)pcx > len)
			{
				// no place for read
				image_issues = true;
				x = pcx_width;
				break;
			}
			dataByte = *raw++;

			if ((dataByte & 0xC0) == 0xC0)
			{
				runLength = dataByte & 0x3F;
				if (raw - (byte *)pcx > len)
				{
					// no place for read
					image_issues = true;
					x = pcx_width;
					break;
				}
				dataByte = *raw++;
			}
			else
			{
				runLength = 1;
			}

			while (runLength-- > 0)
			{
				if ((*pic + full_size) <= (pix + x))
				{
					// no place for write
					image_issues = true;
					x += runLength;
					runLength = 0;
				}
				else
				{
					pix[x++] = dataByte;
				}
			}
		}
	}

	if (raw - (byte *)pcx > len)
	{
		R_Printf(PRINT_DEVELOPER, "PCX file %s was malformed", filename);
		free(*pic);
		*pic = NULL;
	}
	else if(pcx_width == 319 && pcx_height == 239
			&& Q_strcasecmp(origname, "pics/quit.pcx") == 0
			&& Com_BlockChecksum(pcx, len) == 3329419434u)
	{
		// it's the quit screen, and the baseq2 one (identified by checksum)
		// so fix it
		fixQuitScreen(*pic);
	}

	if (image_issues)
	{
		R_Printf(PRINT_ALL, "PCX file %s has possible size issues.\n", filename);
	}

	ri.FS_FreeFile(pcx);
}
Пример #16
0
qsocket_t *NET_Connect (char *host)
{
	qsocket_t		*ret;
	int				n;
	int				numdrivers = net_numdrivers;

	SetNetTime();

	if (host && *host == 0)
		host = NULL;

	if (host)
	{
		if (Q_strcasecmp (host, "local") == 0)
		{
			numdrivers = 1;
			goto JustDoIt;
		}

		if (hostCacheCount)
		{
			for (n = 0; n < hostCacheCount; n++)
				if (Q_strcasecmp (host, hostcache[n].name) == 0)
				{
					host = hostcache[n].cname;
					break;
				}
			if (n < hostCacheCount)
				goto JustDoIt;
		}
	}

	slistSilent = host ? true : false;
	NET_Slist_f ();

	while(slistInProgress)
		NET_Poll();

	if (host == NULL)
	{
		if (hostCacheCount != 1)
			return NULL;
		host = hostcache[0].cname;
		Con_Printf("Connecting to...\n%s @ %s\n\n", hostcache[0].name, host);
	}

	if (hostCacheCount)
		for (n = 0; n < hostCacheCount; n++)
			if (Q_strcasecmp (host, hostcache[n].name) == 0)
			{
				host = hostcache[n].cname;
				break;
			}

JustDoIt:
	for (net_driverlevel=0 ; net_driverlevel<numdrivers; net_driverlevel++)
	{
		if (net_drivers[net_driverlevel].initialized == false)
			continue;
		ret = dfunc.Connect (host);
		if (ret)
			return ret;
	}

	if (host)
	{
		Con_Printf("\n");
		PrintSlistHeader();
		PrintSlist();
		PrintSlistTrailer();
	}
	
	return NULL;
}
Пример #17
0
static void CD_f()
{
	char *command;
	int cdstate;
	if(Cmd_Argc() < 2) return;

	command = Cmd_Argv(1);
	if(!Q_strcasecmp(command,"on"))
	{
		enabled = true;
	}
	if(!Q_strcasecmp(command,"off"))
	{
		if(!cd_id) return;
		cdstate = SDL_CDStatus(cd_id);
		if((cdstate == CD_PLAYING) || (cdstate == CD_PAUSED))
			CDAudio_Stop();
		enabled = false;
		return;
	}
	if(!Q_strcasecmp(command,"play"))
	{
		CDAudio_Play(Q_atoi(Cmd_Argv(2)),false);
		return;
	}
	if(!Q_strcasecmp(command,"loop"))
	{
		CDAudio_Play(Q_atoi(Cmd_Argv(2)),true);
		return;
	}
	if(!Q_strcasecmp(command,"stop"))
	{
		CDAudio_Stop();
		return;
	}
	if(!Q_strcasecmp(command,"pause"))
	{
		CDAudio_Pause();
		return;
	}
	if(!Q_strcasecmp(command,"resume"))
	{
		CDAudio_Resume();
		return;
	}
	if(!Q_strcasecmp(command,"eject"))
	{
		CDAudio_Eject();
		return;
	}
	if(!Q_strcasecmp(command,"info"))
	{
		if(!cd_id) return;
		cdstate = SDL_CDStatus(cd_id);
		Con_Printf("%d tracks\n",cd_id->numtracks);
		if(cdstate == CD_PLAYING)
			Con_Printf("Currently %s track %d\n",
				playLooping ? "looping" : "playing",
				cd_id->cur_track+1);
		else
		if(cdstate == CD_PAUSED)
			Con_Printf("Paused %s track %d\n",
				playLooping ? "looping" : "playing",
				cd_id->cur_track+1);
		return;
	}
}
Пример #18
0
void Master_SetMaster_f() {

   int AreAdding;
   const char * arg_1, * arg_2;
   int port;
   netadr_t netaddress;
   master_server_t * ptr, * ptr2;

   if(Cmd_Argc() < 2 || Cmd_Argc() > 4) {

      Con_Printf("Setmaster <add | remove | enable | disable> <IP:port>\n");
      Con_Printf(" Current master list:\n");

      for(ptr = masterlist; ptr != NULL; ptr = ptr->next) {

         Con_Printf("  %s\n", NET_AdrToString(ptr->address));
      }

      Con_Printf(" End if list\n");
      return;
   }

   arg_1 = Cmd_Argv(1);
   if(arg_1[0] == '\0') { return; }

   if(Q_strcasecmp(arg_1, "disable") == 0) { gfNoMasterServer = 1; return; }
   if(Q_strcasecmp(arg_1, "enable") == 0) { gfNoMasterServer = 0; return; }

   if(Q_strcasecmp(arg_1, "add") == 0) { AreAdding = 1; }
   else if(Q_strcasecmp(arg_1, "remove") == 0) { AreAdding = 0; }
   else {

      Con_Printf("Setmaster:  Unknown command \"%s\".\n", arg_1);
      return;
   }

   arg_2 = Cmd_Argv(2);

   if(Cmd_Argc() == 4) {
      port = Q_atoi(Cmd_Argv(3));
      if(port < 1 || port > 65535) {
         Con_Printf("Setmaster: Invalid port.  Ports can't be larger than 65535.\n");
         return;
      }
   }
   else {
      port = 27010;
   }

   if(NET_StringToAdr(arg_2, &netaddress) == 0) {
      Con_Printf("Setmaster: Passed address could not be processed by StringToAdr.\n");
      return;
   }
   netaddress.port = port;

   if(AreAdding) {

      Master_Init();
      Master_AddServer(&netaddress);
      gfNoMasterServer = 0;
      Con_Printf("Master server %s:%u added.\n", arg_2, port);
   }
   else {

      //case 1: first node.
      if(NET_CompareAdr(masterlist->address, netaddress) != 0) {
         ptr = masterlist;
         masterlist = masterlist->next;
         Q_Free(ptr);
         return;
      }

      //case 2: some node afterwards
      for(ptr = masterlist; ptr->next != NULL; ptr = ptr->next) {
         if(NET_CompareAdr(ptr->next->address, netaddress) != 0) {

            ptr2 = ptr->next;
            ptr->next = ptr->next->next;
            Q_Free(ptr2);
            return;
         }
      }
      //case 3: not here
      Con_Printf("Master %s:%u couldn't be removed.  Couldn't find it.\n", arg_2, port);
   }
}
Пример #19
0
/**
 * @brief Initialize a node behaviour memory, after registration, and before unsing it.
 * @param behaviour Behaviour to initialize
 */
void UI_InitializeNodeBehaviour (uiBehaviour_t* behaviour)
{
	if (behaviour->isInitialized)
		return;

	/* everything inherits 'abstractnode' */
	if (behaviour->extends == NULL && !Q_streq(behaviour->name, "abstractnode")) {
		behaviour->extends = "abstractnode";
	}

	if (behaviour->extends) {
		int i = 0;

		/** TODO Find a way to remove that, if possible */
		behaviour->super = UI_GetNodeBehaviour(behaviour->extends);
		UI_InitializeNodeBehaviour(behaviour->super);

		while (qtrue) {
			const size_t pos = virtualFunctions[i];
			uintptr_t superFunc;
			uintptr_t func;
			if (pos == -1)
				break;

			/* cache super function if we don't overwrite it */
			superFunc = *(uintptr_t*)((byte*)behaviour->super + pos);
			func = *(uintptr_t*)((byte*)behaviour + pos);
			if (func == 0 && superFunc != 0)
				*(uintptr_t*)((byte*)behaviour + pos) = superFunc;

			i++;
		}
	}

	/* sort properties by alphabet */
	if (behaviour->localProperties) {
		int i = 0;
		const value_t* previous;
		const value_t** oldmemory = behaviour->localProperties;
		behaviour->localProperties = UI_AllocHunkMemory(sizeof(value_t*) * (behaviour->propertyCount+1), STRUCT_MEMORY_ALIGN, qfalse);
		if (behaviour->localProperties == NULL) {
			Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: UI memory hunk exceeded - increase the size");
		}

		previous = NULL;
		for (i = 0; i < behaviour->propertyCount; i++) {
			const value_t* better = NULL;
			const value_t** current;
			/* search the next element after previous */
			for (current = oldmemory; *current != NULL; current++) {
				if (previous != NULL && Q_strcasecmp(previous->string, (*current)->string) >= 0) {
					continue;
				}
				if (better == NULL || Q_strcasecmp(better->string, (*current)->string) >= 0) {
					better = *current;
				}
			}
			previous = better;
			behaviour->localProperties[i] = better;
		}
		behaviour->localProperties[behaviour->propertyCount] = NULL;
		Mem_Free(oldmemory);
	}

	/* property must not overwrite another property */
	if (behaviour->super && behaviour->localProperties) {
		const value_t** property = behaviour->localProperties;
		while (*property) {
			const value_t *p = UI_GetPropertyFromBehaviour(behaviour->super, (*property)->string);
#if 0	/**< @todo not possible at the moment, not sure its the right way */
			const uiBehaviour_t *b = UI_GetNodeBehaviour(current->string);
#endif
			if (p != NULL)
				Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: property '%s' from node behaviour '%s' overwrite another property", (*property)->string, behaviour->name);
#if 0	/**< @todo not possible at the moment, not sure its the right way */
			if (b != NULL)
				Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: property '%s' from node behaviour '%s' use the name of an existing node behaviour", (*property)->string, behaviour->name);
#endif
			property++;
		}
	}

	/* Sanity: A property must not be outside the node memory */
	if (behaviour->localProperties) {
		const int size = sizeof(uiNode_t) + behaviour->extraDataSize;
		const value_t** property = behaviour->localProperties;
		while (*property) {
			if ((*property)->type != V_UI_NODEMETHOD && (*property)->ofs + (*property)->size > size)
				Com_Error(ERR_FATAL, "UI_InitializeNodeBehaviour: property '%s' from node behaviour '%s' is outside the node memory. The C code need a fix.", (*property)->string, behaviour->name);
			property++;
		}
	}

	behaviour->isInitialized = qtrue;
}
Пример #20
0
void Master_Init() {

   int i, SkipSection, tempport;
   static int HaveConfigured = 0;
   char * filep;
   const char * curfilep;
   netadr_t tempadr;


   if(HaveConfigured != 0 || gfNoMasterServer != 0) { return; }

   HaveConfigured = 1;

   if(COM_CheckParmCase("-nomaster") != 0 || global_svs.allocated_client_slots <= 1) {

      Con_Printf("%s: Master server comm disabled.\n", __FUNCTION__);
      gfNoMasterServer = 0;
      return; //and don't check again, ever.
   }

   MasterHeartbeatTimeout = 15;

   i = COM_CheckParmCase("-comm");
   if(i != 0 && i+1 < global_com_argc) {

      filep = COM_LoadFileForMe(global_com_argv[i+1], NULL);
   }
   else {

      filep = COM_LoadFileForMe("valvecomm.lst", NULL);
      if(filep == NULL) {
         filep = COM_LoadFileForMe("woncomm.lst", NULL);
      }
   }

   if(filep == NULL) {
      Con_Printf("%s: Couldn't load comm file.  Disabling masters--fix it.\n", __FUNCTION__);
      return;
   }

   curfilep = filep;
   i = 0;
   while(1) {

      curfilep = COM_Parse(curfilep);
      if(global_com_token[0] == '\0') { break; }

      SkipSection = 1;
      if(Q_strcasecmp("master", global_com_token) == 0) {
         SkipSection = 0;
      }

      curfilep = COM_Parse(curfilep);
      if(Q_strcmp("{", global_com_token) != 0) { break; }

      while(1) {

         curfilep = COM_Parse(curfilep);
         if(global_com_token[0] == '\0' || Q_strcmp("}", global_com_token) == 0) { break; }
         if(SkipSection == 0 && NET_StringToAdr(global_com_token, &tempadr) == 0) { break; }

         //We just (maybe) parsed the server name, if you missed it.  Now for the port.
         curfilep = COM_Parse(curfilep);
         if(Q_strcmp(":", global_com_token) != 0) { break; }

         curfilep = COM_Parse(curfilep);
         if(global_com_token[0] == '\0') { break; }

         if(SkipSection == 0) {

            tempport = Q_atoi(global_com_token);
            if(tempport < 1 || tempport > 65535) { tempport = 27010; }
            tempadr.port = tempport;

            Con_Printf("%s: Adding master server %s.\n", __FUNCTION__, NET_AdrToString(tempadr)); //all that work to avoid needless string copying, all gone :)
            Master_AddServer(&tempadr);
            i++;
         }
      }
   }

   COM_FreeFile(filep);

   if(i == 0) {
      Con_Printf("%s: Didn't parse any masters.  Disabling master comm.\n", __FUNCTION__);
      gfNoMasterServer = 0;
   }
}
Пример #21
0
/*
 * Objects need to be moved back on a failed push,
 * otherwise riders would continue to slide.
 */
qboolean
SV_Push(edict_t *pusher, vec3_t move, vec3_t amove)
{
	int i, e;
	edict_t *check, *block;
	pushed_t *p;
	vec3_t org, org2, move2, forward, right, up;
	vec3_t realmins, realmaxs;

	if (!pusher)
	{
		return false;
	}

	/* clamp the move to 1/8 units, so the position will
       be accurate for client side prediction */
	for (i = 0; i < 3; i++)
	{
		float temp;
		temp = move[i] * 8.0;

		if (temp > 0.0)
		{
			temp += 0.5;
		}
		else
		{
			temp -= 0.5;
		}

		move[i] = 0.125 * (int)temp;
	}

	/* we need this for pushing things later */
	VectorSubtract(vec3_origin, amove, org);
	AngleVectors(org, forward, right, up);

	/* save the pusher's original position */
	pushed_p->ent = pusher;
	VectorCopy(pusher->s.origin, pushed_p->origin);
	VectorCopy(pusher->s.angles, pushed_p->angles);

	if (pusher->client)
	{
		pushed_p->deltayaw = pusher->client->ps.pmove.delta_angles[YAW];
	}

	pushed_p++;

	/* move the pusher to it's final position */
	VectorAdd(pusher->s.origin, move, pusher->s.origin);
	VectorAdd(pusher->s.angles, amove, pusher->s.angles);
	gi.linkentity(pusher);

	/* Create a real bounding box for
	   rotating brush models. */
	RealBoundingBox(pusher, realmins, realmaxs);

	/* see if any solid entities are inside the final position */
	check = g_edicts + 1;

	for (e = 1; e < globals.num_edicts; e++, check++)
	{
		if (!check->inuse)
		{
			continue;
		}

		if ((check->movetype == MOVETYPE_PUSH) ||
			(check->movetype == MOVETYPE_STOP) ||
			(check->movetype == MOVETYPE_NONE) ||
			(check->movetype == MOVETYPE_NOCLIP))
		{
			continue;
		}

		if (!check->area.prev)
		{
			continue; /* not linked in anywhere */
		}

		/* if the entity is standing on the pusher, it will definitely be moved */
		if (check->groundentity != pusher)
		{
			/* see if the ent needs to be tested */
			if ((check->absmin[0] >= realmaxs[0]) ||
				(check->absmin[1] >= realmaxs[1]) ||
				(check->absmin[2] >= realmaxs[2]) ||
				(check->absmax[0] <= realmins[0]) ||
				(check->absmax[1] <= realmins[1]) ||
				(check->absmax[2] <= realmins[2]))
			{
				continue;
			}

			/* see if the ent's bbox is inside the pusher's final position */
			if (!SV_TestEntityPosition(check))
			{
				continue;
			}
		}

		if ((pusher->movetype == MOVETYPE_PUSH) ||
			(check->groundentity == pusher))
		{
			/* move this entity */
			pushed_p->ent = check;
			VectorCopy(check->s.origin, pushed_p->origin);
			VectorCopy(check->s.angles, pushed_p->angles);
			pushed_p++;

			/* try moving the contacted entity */
			VectorAdd(check->s.origin, move, check->s.origin);

			if (check->client)
			{
				check->client->ps.pmove.delta_angles[YAW] += amove[YAW];
			}

			/* figure movement due to the pusher's amove */
			VectorSubtract(check->s.origin, pusher->s.origin, org);
			org2[0] = DotProduct(org, forward);
			org2[1] = -DotProduct(org, right);

			/* Quirk for blocking Elevators when
			   running under amd64. This is most
			   likey  caused by a too high float
			   precision. -_-  */
			if (((pusher->s.number == 285) &&
				 (Q_strcasecmp(level.mapname, "xcompnd2") == 0)) ||
				((pusher->s.number == 520) &&
				 (Q_strcasecmp(level.mapname, "xsewer2") == 0)))
			{
				org2[2] = DotProduct(org, up) + 2;
			}
			else
			{
				org2[2] = DotProduct(org, up);
			}

			VectorSubtract(org2, org, move2);
			VectorAdd(check->s.origin, move2, check->s.origin);

			/* may have pushed them off an edge */
			if (check->groundentity != pusher)
			{
				check->groundentity = NULL;
			}

			block = SV_TestEntityPosition(check);

			if (!block)
			{
				/* pushed ok */
				gi.linkentity(check);

				/* impact? */
				continue;
			}

			/* if it is ok to leave in the old position, do it this
			   is only relevent for riding entities, not pushed */
			VectorSubtract(check->s.origin, move, check->s.origin);
			block = SV_TestEntityPosition(check);

			if (!block)
			{
				pushed_p--;
				continue;
			}
		}

		/* save off the obstacle so we can call the block function */
		obstacle = check;

		/* move back any entities we already moved
		   go backwards, so if the same entity was pushed
		   twice, it goes back to the original position */
		for (p = pushed_p - 1; p >= pushed; p--)
		{
			VectorCopy(p->origin, p->ent->s.origin);
			VectorCopy(p->angles, p->ent->s.angles);

			if (p->ent->client)
			{
				p->ent->client->ps.pmove.delta_angles[YAW] = p->deltayaw;
			}

			gi.linkentity(p->ent);
		}

		return false;
	}

	/* see if anything we moved has touched a trigger */
	for (p = pushed_p - 1; p >= pushed; p--)
	{
		G_TouchTriggers(p->ent);
	}

	return true;
}
Пример #22
0
/**
 * Take a screenshot of the frame buffer
 * @param[in] x
 * @param[in] y
 * @param[in] width
 * @param[in] height
 * @param[in] filename Force to use a filename. Else NULL to autogen a filename
 * @param[in] ext Force to use an image format (tga/png/jpg). Else NULL to use value of r_screenshot_format
 */
void R_ScreenShot (int x, int y, int width, int height, const char *filename, const char *ext)
{
	char	checkName[MAX_OSPATH];
	int		type, shotNum, quality = 100;
	byte	*buffer;
	qFILE	f;
	int rowPack;

	glGetIntegerv(GL_PACK_ALIGNMENT, &rowPack);
	glPixelStorei(GL_PACK_ALIGNMENT, 1);

	/* Find out what format to save in */
	if (ext == NULL)
		ext = r_screenshot_format->string;

	if (!Q_strcasecmp(ext, "png"))
		type = SSHOTTYPE_PNG;
	else if (!Q_strcasecmp(ext, "jpg"))
		type = SSHOTTYPE_JPG;
	else
		type = SSHOTTYPE_TGA_COMP;

	/* Set necessary values */
	switch (type) {
	case SSHOTTYPE_TGA_COMP:
		Com_Printf("Taking TGA screenshot...\n");
		ext = "tga";
		break;

	case SSHOTTYPE_PNG:
		Com_Printf("Taking PNG screenshot...\n");
		ext = "png";
		break;

	case SSHOTTYPE_JPG:
		if (Cmd_Argc() == 3)
			quality = atoi(Cmd_Argv(2));
		else
			quality = r_screenshot_jpeg_quality->integer;
		if (quality > 100 || quality <= 0)
			quality = 100;

		Com_Printf("Taking JPG screenshot (at %i%% quality)...\n", quality);
		ext = "jpg";
		break;
	}

	/* Find a file name to save it to */
	if (filename) {
		Com_sprintf(checkName, sizeof(checkName), "scrnshot/%s.%s", filename, ext);
	} else {
		for (shotNum = 0; shotNum < 1000; shotNum++) {
			Com_sprintf(checkName, sizeof(checkName), "scrnshot/ufo%i%i.%s", shotNum / 10, shotNum % 10, ext);
			if (FS_CheckFile("%s", checkName) == -1)
				break;
		}
		if (shotNum == 1000) {
			Com_Printf("R_ScreenShot_f: screenshot limit (of 1000) exceeded!\n");
			return;
		}
	}

	/* Open it */
	FS_OpenFile(checkName, &f, FILE_WRITE);
	if (!f.f) {
		Com_Printf("R_ScreenShot_f: Couldn't create file: %s\n", checkName);
		return;
	}

	/* Allocate room for a copy of the framebuffer */
	buffer = (byte *)Mem_PoolAlloc(width * height * 3, vid_imagePool, 0);
	if (!buffer) {
		Com_Printf("R_ScreenShot_f: Could not allocate %i bytes for screenshot!\n", width * height * 3);
		FS_CloseFile(&f);
		return;
	}

	/* Read the framebuffer into our storage */
	glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
	R_CheckError();

	/* Write */
	switch (type) {
	case SSHOTTYPE_TGA_COMP:
		R_WriteCompressedTGA(&f, buffer, width, height);
		break;

	case SSHOTTYPE_PNG:
		R_WritePNG(&f, buffer, width, height);
		break;

	case SSHOTTYPE_JPG:
		R_WriteJPG(&f, buffer, width, height, quality);
		break;
	}

	/* Finish */
	FS_CloseFile(&f);
	Mem_Free(buffer);

	Com_Printf("Wrote %s to %s\n", checkName, FS_Gamedir());
	glPixelStorei(GL_PACK_ALIGNMENT, rowPack);
}
Пример #23
0
/*
==================
SV_GameMap_f

Saves the state of the map just being exited and goes to a new map.

If the initial character of the map string is '*', the next map is
in a new unit, so the current savegame directory is cleared of
map files.

Example:

*inter.cin+jail

Clears the archived maps, plays the inter.cin cinematic, then
goes to map jail.bsp.
==================
*/
void SV_GameMap_f (void)
{
	char		*map;
	int			i, l;
	client_t	*cl;
	qboolean	*savedInuse;

	if (Cmd_Argc() != 2)
	{
		Com_Printf ("USAGE: gamemap <map>\n");
		return;
	}

	Com_DPrintf("SV_GameMap(%s)\n", Cmd_Argv(1));

	FS_CreatePath (va("%s/save/current/", FS_Gamedir()));

	// check for clearing the current savegame
	map = Cmd_Argv(1);
	if (map[0] == '*')
	{
		// wipe all the *.sav files
		SV_WipeSavegame ("current");
	}
	else
	{
		// save the map just exited
		if (sv.state == ss_game)
		{
			// clear all the client inuse flags before saving so that
			// when the level is re-entered, the clients will spawn
			// at spawn points instead of occupying body shells
			savedInuse = malloc(maxclients->value * sizeof(qboolean));
			for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++)
			{
				savedInuse[i] = cl->edict->inuse;
				cl->edict->inuse = false;
			}

			SV_WriteLevelFile ();

			// we must restore these for clients to transfer over correctly
			for (i=0,cl=svs.clients ; i<maxclients->value; i++,cl++)
				cl->edict->inuse = savedInuse[i];
			free (savedInuse);
		}
	}

	// start up the next map
	SV_Map (false, Cmd_Argv(1), false );

	// archive server state
	strncpy (svs.mapcmd, Cmd_Argv(1), sizeof(svs.mapcmd)-1);

	// copy off the level to the autosave slot
	// Knightmare- don't do this in deathmatch or for cinematics
	l = strlen(map);
	//l = strcspn(map, "+");
	if (!dedicated->value && !Cvar_VariableValue("deathmatch")
		&& Q_strcasecmp (map+l-4, ".cin") && Q_strcasecmp (map+l-4, ".roq")
		&& Q_strcasecmp (map+l-4, ".pcx"))
	{
		SV_WriteServerFile (true);
		SV_CopySaveGame ("current", "kmq2save0");
	}
}
Пример #24
0
/*
=================
G_ScriptAction_PlayAnim

  syntax: playanim <startframe> <endframe> [looping <FOREVER/duration>] [rate <FPS>]

  NOTE: all source animations must be at 20fps
=================
*/
qboolean G_ScriptAction_PlayAnim( gentity_t *ent, const char* params ) {
    const char* pString;
    char* token;
    char tokens[2][MAX_QPATH];
	int i, endtime = 0; // TTimo: init
	qboolean looping = qfalse, forever = qfalse;
	int startframe, endframe, idealframe;
	int rate = 20;

	if ( ( ent->scriptStatus.scriptFlags & SCFL_ANIMATING ) && ( ent->scriptStatus.scriptStackChangeTime == level.time ) ) {
		// this is a new call, so cancel the previous animation
		ent->scriptStatus.scriptFlags &= ~SCFL_ANIMATING;
	}

	pString = params;

	for ( i = 0; i < 2; i++ ) {
		token = COM_ParseExt( &pString, qfalse );
		if ( !token || !token[0] ) {
			G_Printf( "G_Scripting: syntax error\n\nplayanim <startframe> <endframe> [LOOPING <duration>]\n" );
			return qtrue;
		} else {
			Q_strncpyz( tokens[i], token, sizeof( tokens[i] ) );
		}
	}

	startframe = atoi( tokens[0] );
	endframe = atoi( tokens[1] );

	// check for optional parameters
	token = COM_ParseExt( &pString, qfalse );
	if ( token[0] ) {
		if ( !Q_strcasecmp( token, "looping" ) ) {
			looping = qtrue;

			token = COM_ParseExt( &pString, qfalse );
			if ( !token || !token[0] ) {
				G_Printf( "G_Scripting: syntax error\n\nplayanim <startframe> <endframe> [LOOPING <duration>]\n" );
				return qtrue;
			}
			if ( !Q_strcasecmp( token, "untilreachmarker" ) ) {
				if ( level.time < ent->s.pos.trTime + ent->s.pos.trDuration ) {
					endtime = level.time + 100;
				} else {
					endtime = 0;
				}
			} else if ( !Q_strcasecmp( token, "forever" ) ) {
				ent->scriptStatus.animatingParams = params;
				ent->scriptStatus.scriptFlags |= SCFL_ANIMATING;
				endtime = level.time + 100;     // we don't care when it ends, since we are going forever!
				forever = qtrue;
			} else {
				endtime = ent->scriptStatus.scriptStackChangeTime + atoi( token );
			}

			token = COM_ParseExt( &pString, qfalse );
		}

		if ( token[0] && !Q_strcasecmp( token, "rate" ) ) {
			token = COM_ParseExt( &pString, qfalse );
			if ( !token[0] ) {
				G_Error( "G_Scripting: playanim has RATE parameter without an actual rate specified" );
			}
			rate = atoi( token );
		}

		if ( !looping ) {
			endtime = ent->scriptStatus.scriptStackChangeTime + ( ( endframe - startframe ) * ( 1000 / 20 ) );
		}
	}

	idealframe = startframe + (int)c::floor( (float)( level.time - ent->scriptStatus.scriptStackChangeTime ) / ( 1000.0 / (float)rate ) );
	if ( looping ) {
		ent->s.frame = startframe + ( idealframe - startframe ) % ( endframe - startframe );
		ent->s.eFlags |= EF_MOVER_ANIMATE;
	} else {
		if ( idealframe > endframe ) {
			ent->s.frame = endframe;
			ent->s.eFlags &= ~EF_MOVER_ANIMATE; // stop interpolation, since we have gone passed the endframe
		} else {
			ent->s.frame = idealframe;
			ent->s.eFlags |= EF_MOVER_ANIMATE;
		}
	}

	if ( forever ) {
		ent->s.eFlags |= EF_MOVER_ANIMATE;
		return qtrue;   // continue to the next command
	}

	if ( endtime <= level.time ) {
		ent->s.eFlags &= ~EF_MOVER_ANIMATE; // stop animating
		return qtrue;
	} else {
		return qfalse;
	}
}
Пример #25
0
static void Test_f(void)
{
    char	*host;
    int		n;
    int		max = MAX_SCOREBOARD;
    struct qsockaddr sendaddr;

    if (testInProgress) {
        return;
    }

    host = Cmd_Argv(1);

    if (host && hostCacheCount) {
        for (n = 0; n < hostCacheCount; n++)
            if (Q_strcasecmp(host, hostcache[n].name) == 0) {
                if (hostcache[n].driver != myDriverLevel) {
                    continue;
                }
                net_landriverlevel = hostcache[n].ldriver;
                max = hostcache[n].maxusers;
                Q_memcpy(&sendaddr, &hostcache[n].addr, sizeof(struct qsockaddr));
                break;
            }
        if (n < hostCacheCount) {
            goto JustDoIt;
        }
    }

    for (net_landriverlevel = 0; net_landriverlevel < net_numlandrivers; net_landriverlevel++) {
        if (!net_landrivers[net_landriverlevel].initialized) {
            continue;
        }

        // see if we can resolve the host name
        if (dfunc.GetAddrFromName(host, &sendaddr) != -1) {
            break;
        }
    }
    if (net_landriverlevel == net_numlandrivers) {
        return;
    }

JustDoIt:
    testSocket = dfunc.OpenSocket(0);
    if (testSocket == -1) {
        return;
    }

    testInProgress = true;
    testPollCount = 20;
    testDriver = net_landriverlevel;

    for (n = 0; n < max; n++) {
        SZ_Clear(&net_message);
        // save space for the header, filled in later
        MSG_WriteLong(&net_message, 0);
        MSG_WriteByte(&net_message, CCREQ_PLAYER_INFO);
        MSG_WriteByte(&net_message, n);
        *((int *)net_message.data) = BigLong(NETFLAG_CTL |	(net_message.cursize & NETFLAG_LENGTH_MASK));
        dfunc.Write(testSocket, net_message.data, net_message.cursize, &sendaddr);
    }
    SZ_Clear(&net_message);
    SchedulePollProcedure(&testPollProcedure, 0.1);
}
Пример #26
0
/*
=================
G_ScriptAction_FaceAngles

  syntax: faceangles <pitch> <yaw> <roll> <duration/GOTOTIME> [ACCEL/DECCEL]

  The entity will face the given angles, taking <duration> to get there. If the
  GOTOTIME is given instead of a timed duration, the duration calculated from the
  last gotomarker command will be used instead.
=================
*/
qboolean G_ScriptAction_FaceAngles( gentity_t *ent, const char* params ) {
    const char* pString;
    char* token;
	int duration, i;
	vec3_t diff;
	vec3_t angles;
	int trType = TR_LINEAR_STOP;

	if ( !params || !params[0] ) {
		G_Error( "G_Scripting: syntax: faceangles <pitch> <yaw> <roll> <duration/GOTOTIME>\n" );
	}

	if ( ent->scriptStatus.scriptStackChangeTime == level.time ) {
		pString = params;
		for ( i = 0; i < 3; i++ ) {
			token = COM_Parse( &pString );
			if ( !token || !token[0] ) {
				G_Error( "G_Scripting: syntax: faceangles <pitch> <yaw> <roll> <duration/GOTOTIME>\n" );
			}
			angles[i] = atoi( token );
		}

		token = COM_Parse( &pString );
		if ( !token || !token[0] ) {
			G_Error( "G_Scripting: faceangles requires a <pitch> <yaw> <roll> <duration/GOTOTIME>\n" );
		}
		if ( !Q_strcasecmp( token, "gototime" ) ) {
			duration = ent->s.pos.trDuration;
		} else {
			duration = atoi( token );
		}

		token = COM_Parse( &pString );
		if ( token && token[0] ) {
			if ( !Q_strcasecmp( token, "accel" ) ) {
				trType = TR_ACCELERATE;
			}
			if ( !Q_strcasecmp( token, "deccel" ) ) {
				trType = TR_DECCELERATE;
			}
		}

		for ( i = 0; i < 3; i++ ) {
			diff[i] = AngleDifference( angles[i], ent->s.angles[i] );
			while ( diff[i] > 180 )
				diff[i] -= 360;
			while ( diff[i] < -180 )
				diff[i] += 360;
		}

		VectorCopy( ent->s.angles, ent->s.apos.trBase );
		if ( duration ) {
			VectorScale( diff, 1000.0 / (float)duration, ent->s.apos.trDelta );
		} else {
			VectorClear( ent->s.apos.trDelta );
		}
		ent->s.apos.trDuration = duration;
		ent->s.apos.trTime = level.time;
		ent->s.apos.trType = TR_LINEAR_STOP;

		if ( trType != TR_LINEAR_STOP ) { // accel / deccel logic
			// calc the speed from duration and start/end delta
			for ( i = 0; i < 3; i++ ) {
				ent->s.apos.trDelta[i] = 2.0 * 1000.0 * diff[i] / (float)duration;
			}
			ent->s.apos.trType = trType_t (trType);
		}

	} else if ( ent->s.apos.trTime + ent->s.apos.trDuration <= level.time ) {
		// finished turning
		BG_EvaluateTrajectory( &ent->s.apos, ent->s.apos.trTime + ent->s.apos.trDuration, ent->s.angles );
		VectorCopy( ent->s.angles, ent->s.apos.trBase );
		VectorCopy( ent->s.angles, ent->r.currentAngles );
		ent->s.apos.trTime = level.time;
		ent->s.apos.trDuration = 0;
		ent->s.apos.trType = TR_STATIONARY;
		VectorClear( ent->s.apos.trDelta );

		script_linkentity( ent );

		return qtrue;
	}

	BG_EvaluateTrajectory( &ent->s.apos, level.time, ent->r.currentAngles );
	script_linkentity( ent );

	return qfalse;
}
Пример #27
0
static void CD_f (void)
{
	char	*command;
	int		ret;
	int		n;

	if (Cmd_Argc() < 2)
		return;

	command = Cmd_Argv (1);

	if (Q_strcasecmp(command, "on") == 0)
	{
		enabled = true;
		return;
	}

	if (Q_strcasecmp(command, "off") == 0)
	{
		if (playing)
			CDAudio_Stop();
		enabled = false;
		return;
	}

	if (Q_strcasecmp(command, "reset") == 0)
	{
		enabled = true;
		if (playing)
			CDAudio_Stop();
		for (n = 0; n < 100; n++)
			remap[n] = n;
		CDAudio_GetAudioDiskInfo();
		return;
	}

	if (Q_strcasecmp(command, "remap") == 0)
	{
		ret = Cmd_Argc() - 2;
		if (ret <= 0)
		{
			for (n = 1; n < 100; n++)
				if (remap[n] != n)
					Con_Printf("  %u -> %u\n", n, remap[n]);
			return;
		}
		for (n = 1; n <= ret; n++)
			remap[n] = Q_atoi(Cmd_Argv (n+1));
		return;
	}

	if (Q_strcasecmp(command, "close") == 0)
	{
		CDAudio_CloseDoor();
		return;
	}

	if (!cdValid)
	{
		CDAudio_GetAudioDiskInfo();
		if (!cdValid)
		{
			Con_Printf("No CD in player.\n");
			return;
		}
	}

	if (Q_strcasecmp(command, "play") == 0)
	{
		CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), false);
		return;
	}

	if (Q_strcasecmp(command, "loop") == 0)
	{
		CDAudio_Play((byte)Q_atoi(Cmd_Argv (2)), true);
		return;
	}

	if (Q_strcasecmp(command, "stop") == 0)
	{
		CDAudio_Stop();
		return;
	}

	if (Q_strcasecmp(command, "pause") == 0)
	{
		CDAudio_Pause();
		return;
	}

	if (Q_strcasecmp(command, "resume") == 0)
	{
		CDAudio_Resume();
		return;
	}

	if (Q_strcasecmp(command, "eject") == 0)
	{
		if (playing)
			CDAudio_Stop();
		CDAudio_Eject();
		cdValid = false;
		return;
	}

	if (Q_strcasecmp(command, "info") == 0)
	{
		Con_Printf("%u tracks\n", maxTrack);
		if (playing)
			Con_Printf("Currently %s track %u\n", playLooping ? "looping" : "playing", playTrack);
		else if (wasPlaying)
			Con_Printf("Paused %s track %u\n", playLooping ? "looping" : "playing", playTrack);
		Con_Printf("Volume is %f\n", cdvolume);
		return;
	}
}
Пример #28
0
/* DESCRIPTION: COM_InitArgv
// LOCATION: common.c
// PATH: Sys_Init->COM_InitArgv
//
// Rather than describe what this does, should do, etc.  I'll point you to
// sys_initargv instead.  Our mission is simply to tokenize the (non-permenant?)
// string given to us and assign its entries to host_pams.argv and global_com_argv.
*/
void COM_InitArgv(char *argvs) {

   //These static variables are referred to through pointers in global_com_argv a lot.
   //Todo: remove limits by dynamically allocating this memory.

   static char com_cmdline[0x101] = "";
   static char *largv[MAX_NUM_ARGVS + NUM_SAFE_ARGVS + 1];
   static char *safeargvs[NUM_SAFE_ARGVS] =    {"-dibonly", "-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse"
                                   };

   char *startofstring;
   char *argvposition;
   unsigned int NumParsedArgs = 1;
   unsigned int lengthcounter = 0;
   unsigned int com_cmdlinecounter = 0;



   startofstring = argvposition = argvs;
   largv[0] = ""; //dunno why, it just does, probably to ease off by one errors

   while((*argvposition) != '\0' && NumParsedArgs < MAX_NUM_ARGVS) {

      if(isgraph(*argvposition) == 0) {
         if (lengthcounter == 0) { //start and position are at the same place
            startofstring++;
            argvposition++;
         } else {
            lengthcounter++;
            if (com_cmdlinecounter+lengthcounter < 0x100) {

               *argvposition = '\0'; //cap that string
               Q_memcpy(com_cmdline+com_cmdlinecounter, startofstring, lengthcounter);

               largv[NumParsedArgs] = com_cmdlinecounter + com_cmdline;

               com_cmdlinecounter += lengthcounter;
               lengthcounter = 0;
               NumParsedArgs++;
            }
            argvposition++; //next token, whether we copied the old one or not
            startofstring = argvposition;
         }
      } else {
         lengthcounter++;
         argvposition++;
      }
   }

   //and the last one if applicable (likely true)
   if((*argvposition) == '\0' && lengthcounter > 0 && com_cmdlinecounter+lengthcounter < 0x100) {

      Q_memcpy(com_cmdline+com_cmdlinecounter, startofstring, lengthcounter);
      largv[NumParsedArgs] = com_cmdlinecounter + com_cmdline;
      NumParsedArgs++;
   }

   //That was fun.  We parsed our string (as much as we could at least) and
   //assigned its values to largv.

   //NumParsedArgs is still useful.  Other vars are free
   //for generic counter usage

   for(lengthcounter = 0; (lengthcounter < MAX_NUM_ARGVS) && (lengthcounter < NumParsedArgs); lengthcounter++)   {
      if(Q_strcasecmp("-safe", largv[lengthcounter]) == 0) {
         com_cmdlinecounter = 1;
         break;
      }
   }

   if(com_cmdlinecounter == 1) {

      com_cmdlinecounter = 0;

      while(com_cmdlinecounter < NUM_SAFE_ARGVS) {
         largv[NumParsedArgs] = safeargvs[com_cmdlinecounter];
         com_cmdlinecounter++;
         NumParsedArgs++;
      }
   }

   largv[NumParsedArgs] = " ";
   NumParsedArgs++;
   host_parms.argc = global_com_argc = NumParsedArgs;
   host_parms.argv = global_com_argv = largv;
}
Пример #29
0
//--------------------------------------------------------------------------------------------------------------
void DownloadManager::Queue( const char *baseURL, const char *gamePath )
{
	bool bAsHTTP = false;
	if ( !gamePath )
	{
		return;
	}

#ifndef _DEBUG
	if ( sv.IsActive() )
	{
		return;	// don't try to download things for the local server (in case a map is missing sounds etc that
				// aren't needed to play.
	}
#endif

	// only http downloads
	if ( baseURL && (!Q_strnicmp( baseURL, "http://", 7 ) || !Q_strnicmp( baseURL, "https://", 8 )) )
	{
		bAsHTTP = true;
	}

	if ( g_pFileSystem->FileExists( gamePath ) )
	{
		return; // don't download existing files
	}

	if ( Q_strstr( gamePath, "//" ) )
	{
		return;
	}

	if ( Q_strstr( gamePath, "\\\\" ) )
	{
		return;
	}

	if ( Q_strstr( gamePath, ":" ) )
	{
		return;
	}

	if ( Q_strstr( gamePath, "lua/" ) )
		return; // don't download into lua/ folder

	if ( Q_strstr( gamePath, "gamemodes/" ) ) 
		return; // don't download into gamemodes/ folder 

	if ( Q_strstr( gamePath, "addons/" ) ) 
		return; // don't download into addons/ folder 


	// Disallow .. in paths, but allow multiple periods otherwise.  This way we can download blah.dx80.vtx etc.
	const char *backup = strstr( gamePath, ".." );
	const char *extension = strrchr( gamePath, '.' );

	if ( backup || !extension )
		return;

	int baseLen = strlen( extension );
	if ( baseLen > 4 || baseLen < 3 )
		return;

	if ( !Q_strcasecmp( extension, ".cfg" ) )
		return;

	if ( !Q_strcasecmp( extension, ".lst" ) )
		return;

	if ( !Q_strcasecmp( extension, ".exe" ) )
		return;

	if ( !Q_strcasecmp( extension, ".vbs" ) )
		return;

	if ( !Q_strcasecmp( extension, ".com" ) )
		return;

	if ( !Q_strcasecmp( extension, ".bat" ) )
		return;

	if ( !Q_strcasecmp( extension, ".dll" ) )
		return;

	if ( !Q_strcasecmp( extension, ".ini" ) )
		return;

	if ( !Q_strcasecmp( extension, ".log" ) )
		return;

	if ( !Q_strcasecmp( extension, ".lua" ) )
		return;

	if ( bAsHTTP && !g_pFileSystem->FileExists( va( "%s.bz2", gamePath ) ) )
	{
		// Queue up an HTTP download of the bzipped asset, in case it exists.
		// When a bzipped download finishes, we'll uncompress the file to it's
		// original destination, and the queued download of the uncompressed
		// file will abort.

		++m_totalRequests;
		if ( !TheDownloadCache )
		{
			TheDownloadCache = new DownloadCache;
			TheDownloadCache->Init();
		}

		RequestContext *rc = new RequestContext;
		m_queuedRequests.AddToTail( rc );

		memset( rc, 0, sizeof(RequestContext) );

		rc->status = HTTP_CONNECTING;

		Q_strncpy( rc->basePath, com_gamedir, BufferSize );
		Q_strncpy( rc->gamePath, gamePath, BufferSize );
		Q_strncat( rc->gamePath, ".bz2", BufferSize, COPY_ALL_CHARACTERS );
		Q_FixSlashes( rc->gamePath, '/' ); // only matters for debug prints, which are full URLS, so we want forward slashes
		Q_strncpy( rc->serverURL, cl.m_NetChannel->GetRemoteAddress().ToString(), BufferSize );

		rc->bIsBZ2 = true;
		rc->bAsHTTP = true;
		Q_strncpy( rc->baseURL, baseURL, BufferSize );
		Q_strncat( rc->baseURL, "/", BufferSize, COPY_ALL_CHARACTERS );

		//ConDColorMsg( DownloadColor, "Queueing %s%s.\n", rc->baseURL, gamePath );
	}

	++m_totalRequests;
	if ( !TheDownloadCache )
	{
		TheDownloadCache = new DownloadCache;
		TheDownloadCache->Init();
	}

	RequestContext *rc = new RequestContext;
	m_queuedRequests.AddToTail( rc );

	memset( rc, 0, sizeof(RequestContext) );

	rc->status = HTTP_CONNECTING;

	Q_strncpy( rc->basePath, com_gamedir, BufferSize );
	Q_strncpy( rc->gamePath, gamePath, BufferSize );
	Q_FixSlashes( rc->gamePath, '/' ); // only matters for debug prints, which are full URLS, so we want forward slashes
	Q_strncpy( rc->serverURL, cl.m_NetChannel->GetRemoteAddress().ToString(), BufferSize );

	if ( bAsHTTP )
	{
		rc->bAsHTTP = true;
		Q_strncpy( rc->baseURL, baseURL, BufferSize );
		Q_strncat( rc->baseURL, "/", BufferSize, COPY_ALL_CHARACTERS );
	}
	else
	{
		rc->bAsHTTP = false;
	}

	//ConDColorMsg( DownloadColor, "Queueing %s%s.\n", rc->baseURL, gamePath );
}
Пример #30
0
void medic_NextPatrolPoint (edict_t *self, edict_t *hint)
{
	edict_t		*next=NULL;
	edict_t		*e;
	vec3_t		dir;
	qboolean	switch_paths=false;

	self->monsterinfo.aiflags &= ~AI_MEDIC_PATROL;

//	if(self->monsterinfo.aiflags & AI_MEDIC)
//		return;

	if(self->goalentity == hint)
		self->goalentity = NULL;
	if(self->movetarget == hint)
		self->movetarget = NULL;
	if (!(self->monsterinfo.aiflags & AI_MEDIC))
	{
		if(medic_FindDeadMonster(self))
			return;
	}
	if(self->monsterinfo.pathdir == 1)
	{
		if(hint->hint_chain)
			next = hint->hint_chain;
		else
		{
			self->monsterinfo.pathdir = -1;
			switch_paths = true;
		}
	}
	if(self->monsterinfo.pathdir == -1)
	{
		e = hint_chain_starts[hint->hint_chain_id];
		while(e)
		{
			if(e->hint_chain == hint)
			{
				next = e;
				break;
			}
			e = e->hint_chain;
		}
	}
	if(!next)
	{
		self->monsterinfo.pathdir = 1;
		next = hint->hint_chain;
		switch_paths = true;
	}
	// If switch_paths is true, we reached the end of a hint_chain. Just for grins,
	// search for *another* visible hint_path chain and use it if it's reasonably close
	if(switch_paths && hint_chain_count > 1)
	{
		edict_t	*e;
		edict_t	*alternate=NULL;
		float	dist;
		vec3_t	dir;
		int		i;
		float	bestdistance=512;

		for(i=game.maxclients+1; i<globals.num_edicts; i++)
		{
			e = &g_edicts[i];
			if(!e->inuse)
				continue;
			if(Q_strcasecmp(e->classname,"hint_path"))
				continue;
			if(next && (e->hint_chain_id == next->hint_chain_id))
				continue;
			if(!visible(self,e))
				continue;
			if(!canReach(self,e))
				continue;
			VectorSubtract(e->s.origin,self->s.origin,dir);
			dist = VectorLength(dir);
			if(dist < bestdistance)
			{
				alternate = e;
				bestdistance = dist;
			}
		}
		if(alternate)
			next = alternate;
	}
	if(next)
	{
		self->hint_chain_id = next->hint_chain_id;
		VectorSubtract(next->s.origin, self->s.origin, dir);
		self->ideal_yaw = vectoyaw(dir);
		self->goalentity = self->movetarget = next;
		self->monsterinfo.pausetime = 0;
		self->monsterinfo.aiflags |= AI_MEDIC_PATROL;
		self->monsterinfo.aiflags &= ~(AI_SOUND_TARGET | AI_PURSUIT_LAST_SEEN | AI_PURSUE_NEXT | AI_PURSUE_TEMP);
		// run for it
		self->monsterinfo.run (self);
	}
	else
	{
		self->monsterinfo.pausetime = level.time + 100000000;
		self->monsterinfo.stand (self);
	}
}